mirror of
https://github.com/keven1024/015.git
synced 2026-05-26 15:13:30 +00:00
feat: implement internationalization for share views and update UI text for better user experience
This commit is contained in:
@@ -4,6 +4,7 @@ import FormButton from '@/components/Field/FormButton.vue'
|
||||
import InputField from '@/components/Field/InputField.vue'
|
||||
import type { FormContext, GenericObject } from 'vee-validate'
|
||||
import { toast } from 'vue-sonner'
|
||||
const { t } = useI18n()
|
||||
const props = defineProps<{
|
||||
share_id: string
|
||||
hide: any
|
||||
@@ -15,14 +16,14 @@ const handleSubmit = async (form: FormContext<GenericObject, GenericObject>) =>
|
||||
const password = form.values.password
|
||||
const token = await getShareToken(props.share_id, { password })
|
||||
if (!token) {
|
||||
toast.error('密码错误')
|
||||
toast.error(t('page.shareView.passwall.passwordError'))
|
||||
form.resetForm()
|
||||
return
|
||||
}
|
||||
props?.hide(token)
|
||||
return
|
||||
} catch (error) {
|
||||
toast.error('密码错误')
|
||||
toast.error(t('page.shareView.passwall.passwordError'))
|
||||
form.resetForm()
|
||||
}
|
||||
}
|
||||
@@ -31,9 +32,9 @@ const handleSubmit = async (form: FormContext<GenericObject, GenericObject>) =>
|
||||
<template>
|
||||
<VeeForm>
|
||||
<div class="flex flex-col gap-5">
|
||||
<div class="text-xl font-bold">输入密码</div>
|
||||
<InputField name="password" type="password" rules="required" placeholder="请输入密码" />
|
||||
<FormButton @click="handleSubmit">提交</FormButton>
|
||||
<div class="text-xl font-bold">{{ t('page.shareView.passwall.title') }}</div>
|
||||
<InputField name="password" type="password" rules="required" :placeholder="t('page.shareView.passwall.passwordPlaceholder')" />
|
||||
<FormButton @click="handleSubmit">{{ t('btn.submit') }}</FormButton>
|
||||
</div>
|
||||
</VeeForm>
|
||||
</template>
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import QRCode from "qrcode";
|
||||
import QRCode from 'qrcode'
|
||||
const { t } = useI18n()
|
||||
const props = defineProps<{
|
||||
hide: () => void;
|
||||
data: any;
|
||||
}>();
|
||||
hide: () => void
|
||||
data: any
|
||||
}>()
|
||||
const { state } = useAsyncState(async () => {
|
||||
return await QRCode.toDataURL(props.data);
|
||||
}, null);
|
||||
return await QRCode.toDataURL(props.data)
|
||||
}, null)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-5">
|
||||
<div class="text-xl font-bold">分享二维码</div>
|
||||
<div class="flex flex-row justify-center">
|
||||
<img :src="state" v-if="!!state" />
|
||||
<Skeleton class="size-20" v-else />
|
||||
<div class="flex flex-col gap-5">
|
||||
<div class="text-xl font-bold">{{ t('page.result.qrCode.title') }}</div>
|
||||
<div class="flex flex-row justify-center">
|
||||
<img :src="state" v-if="!!state" />
|
||||
<Skeleton class="size-20" v-else />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -12,6 +12,7 @@ import PasswallShareDrawer from '~/components/Drawer/PasswallShareDrawer.vue'
|
||||
dayjs.extend(duration)
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const { t } = useI18n()
|
||||
const props = defineProps<{
|
||||
data: any
|
||||
}>()
|
||||
@@ -31,7 +32,7 @@ const handleDownload = async () => {
|
||||
token = await getShareToken(id)
|
||||
}
|
||||
if (!token) {
|
||||
throw new Error('获取token失败')
|
||||
throw new Error(t('page.shareView.fileShare.getTokenFailed'))
|
||||
}
|
||||
downloadFile(token)
|
||||
} catch (error: any) {
|
||||
@@ -53,19 +54,19 @@ onMounted(() => {
|
||||
|
||||
const fileShareInfo = computed(() => {
|
||||
return [
|
||||
{ label: '需要密码', value: props?.data?.has_password ?? false },
|
||||
{ label: t('page.shareView.fileShare.needPassword'), value: props?.data?.has_password ?? false },
|
||||
{
|
||||
label: '过期时间',
|
||||
value: dayjs.duration(remaining.value, 'seconds').format(`D天 HH:mm:ss`),
|
||||
label: t('page.shareView.fileShare.expireTime'),
|
||||
value: dayjs.duration(remaining.value, 'seconds').format(t('page.shareView.fileShare.durationFormat')),
|
||||
},
|
||||
{ label: '剩余下载次数', value: props?.data?.download_nums ?? 0 },
|
||||
{ label: t('page.shareView.fileShare.remainingDownloads'), value: props?.data?.download_nums ?? 0 },
|
||||
]
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-5 items-center">
|
||||
<h1 class="text-xl font-bold">下载文件</h1>
|
||||
<h1 class="text-xl font-bold">{{ t('page.shareView.fileShare.title') }}</h1>
|
||||
<FilePreviewView :value="props?.data" />
|
||||
<div class="flex flex-col gap-2 md:flex-row w-full">
|
||||
<div class="flex flex-row md:flex-col md:gap-1 justify-between items-center md:flex-1" v-for="item in fileShareInfo">
|
||||
@@ -75,7 +76,7 @@ const fileShareInfo = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<AsyncButton @click="handleDownload" class="w-full">下载</AsyncButton>
|
||||
<AsyncButton @click="handleDownload" class="w-full">{{ t('page.shareView.fileShare.downloadBtn') }}</AsyncButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -17,6 +17,7 @@ import PasswallShareDrawer from '~/components/Drawer/PasswallShareDrawer.vue'
|
||||
dayjs.extend(duration)
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const { t } = useI18n()
|
||||
const props = defineProps<{
|
||||
data: any
|
||||
}>()
|
||||
@@ -37,12 +38,12 @@ onMounted(() => {
|
||||
|
||||
const fileShareInfo = computed(() => {
|
||||
return [
|
||||
{ label: '需要密码', value: props?.data?.has_password ?? false },
|
||||
{ label: t('page.shareView.textShare.needPassword'), value: props?.data?.has_password ?? false },
|
||||
{
|
||||
label: '过期时间',
|
||||
value: dayjs.duration(remaining.value, 'seconds').format(`D天 HH:mm:ss`),
|
||||
label: t('page.shareView.textShare.expireTime'),
|
||||
value: dayjs.duration(remaining.value, 'seconds').format(t('page.shareView.textShare.durationFormat')),
|
||||
},
|
||||
{ label: '剩余浏览次数', value: props?.data?.download_nums ?? 0 },
|
||||
{ label: t('page.shareView.textShare.remainingViews'), value: props?.data?.download_nums ?? 0 },
|
||||
]
|
||||
})
|
||||
const previewText = ref<string | null>(null)
|
||||
@@ -72,7 +73,7 @@ const handlePreview = async () => {
|
||||
<template>
|
||||
<div :class="cx('flex flex-col max-h-full', !!previewText ? 'gap-3' : 'gap-16 items-center')">
|
||||
<div :class="cx('flex flex-row w-full', !!previewText ? 'justify-between' : 'justify-center')">
|
||||
<h1 class="text-xl">查看文本</h1>
|
||||
<h1 class="text-xl">{{ t('page.shareView.textShare.title') }}</h1>
|
||||
<Button
|
||||
v-if="!!previewText"
|
||||
variant="outline"
|
||||
@@ -80,7 +81,7 @@ const handlePreview = async () => {
|
||||
@click="
|
||||
() => {
|
||||
copy(previewText as string)
|
||||
toast.success('复制成功')
|
||||
toast.success(t('page.result.text.copySuccess'))
|
||||
}
|
||||
"
|
||||
>
|
||||
@@ -96,7 +97,7 @@ const handlePreview = async () => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<AsyncButton @click="handlePreview" class="w-full">浏览</AsyncButton>
|
||||
<AsyncButton @click="handlePreview" class="w-full">{{ t('page.shareView.textShare.viewBtn') }}</AsyncButton>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
||||
@@ -160,6 +160,34 @@
|
||||
"link": "Link",
|
||||
"content": "Content",
|
||||
"copySuccess": "Copy Success"
|
||||
},
|
||||
"qrCode": {
|
||||
"title": "Share QR code"
|
||||
}
|
||||
},
|
||||
"shareView": {
|
||||
"linkExpired": "This link has expired.",
|
||||
"passwall": {
|
||||
"title": "Enter password",
|
||||
"passwordError": "Wrong password",
|
||||
"passwordPlaceholder": "Enter password"
|
||||
},
|
||||
"fileShare": {
|
||||
"title": "Download file",
|
||||
"downloadBtn": "Download",
|
||||
"needPassword": "Password required",
|
||||
"expireTime": "Expire time",
|
||||
"remainingDownloads": "Remaining downloads",
|
||||
"getTokenFailed": "Failed to get token",
|
||||
"durationFormat": "D [days] HH:mm:ss"
|
||||
},
|
||||
"textShare": {
|
||||
"title": "View text",
|
||||
"viewBtn": "View",
|
||||
"needPassword": "Password required",
|
||||
"expireTime": "Expire time",
|
||||
"remainingViews": "Remaining views",
|
||||
"durationFormat": "D [days] HH:mm:ss"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
||||
@@ -160,6 +160,34 @@
|
||||
"link": "链接",
|
||||
"content": "内容",
|
||||
"copySuccess": "复制成功"
|
||||
},
|
||||
"qrCode": {
|
||||
"title": "分享二维码"
|
||||
}
|
||||
},
|
||||
"shareView": {
|
||||
"linkExpired": "此链接已过期。",
|
||||
"passwall": {
|
||||
"title": "输入密码",
|
||||
"passwordError": "密码错误",
|
||||
"passwordPlaceholder": "请输入密码"
|
||||
},
|
||||
"fileShare": {
|
||||
"title": "下载文件",
|
||||
"downloadBtn": "下载",
|
||||
"needPassword": "需要密码",
|
||||
"expireTime": "过期时间",
|
||||
"remainingDownloads": "剩余下载次数",
|
||||
"getTokenFailed": "获取token失败",
|
||||
"durationFormat": "D天 HH:mm:ss"
|
||||
},
|
||||
"textShare": {
|
||||
"title": "查看文本",
|
||||
"viewBtn": "浏览",
|
||||
"needPassword": "需要密码",
|
||||
"expireTime": "过期时间",
|
||||
"remainingViews": "剩余浏览次数",
|
||||
"durationFormat": "D天 HH:mm:ss"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
||||
@@ -8,6 +8,7 @@ import TextShareView from '@/components/Share/TextShareView.vue'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { t } = useI18n()
|
||||
const id = computed(() => route.params.id)
|
||||
|
||||
const { data, isLoading, error } = useQuery({
|
||||
@@ -51,14 +52,14 @@ const componentMap = {
|
||||
<template v-else>
|
||||
<div v-if="isExpired || !data" class="flex flex-col gap-5 items-center">
|
||||
<LucideAlertCircle :size="48" class="text-orange-500 rounded-full bg-orange-500/30 p-2" />
|
||||
<div class="text-xl">此链接已过期。</div>
|
||||
<div class="text-xl">{{ t('page.shareView.linkExpired') }}</div>
|
||||
<Button
|
||||
@click="
|
||||
() => {
|
||||
router.push('/')
|
||||
}
|
||||
"
|
||||
>返回首页</Button
|
||||
>{{ t('btn.backToHome') }}</Button
|
||||
>
|
||||
</div>
|
||||
<template v-else>
|
||||
|
||||
Reference in New Issue
Block a user