mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
更新国际化支持:调整多个组件中的文本引入,优化语言切换和翻译功能,删除不再使用的类型文件。
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SUPPORTED_LOCALES, SupportedLocale } from '@/locales/types'
|
import { SUPPORTED_LOCALES, SupportedLocale } from '@/types/i18n'
|
||||||
import { setI18nLanguage, getCurrentLocale } from '@/plugins/i18n'
|
import { setI18nLanguage, getCurrentLocale } from '@/plugins/i18n'
|
||||||
|
|
||||||
// 当前语言
|
// 当前语言
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import { SubscribeShare } from '@/api/types'
|
|||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import { VBtn } from 'vuetify/lib/components/index.mjs'
|
import { VBtn } from 'vuetify/lib/components/index.mjs'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -116,11 +120,11 @@ async function doFork() {
|
|||||||
const result: { [key: string]: any } = await api.post('subscribe/fork', props.media)
|
const result: { [key: string]: any } = await api.post('subscribe/fork', props.media)
|
||||||
// 订阅状态
|
// 订阅状态
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
$toast.success(`${props.media?.share_title} 添加订阅成功!`)
|
$toast.success(t('subscribe.addSuccess', { name: props.media?.share_title }))
|
||||||
// 完成
|
// 完成
|
||||||
emit('fork', result.data.id)
|
emit('fork', result.data.id)
|
||||||
} else {
|
} else {
|
||||||
$toast.error(`${props.media?.share_title} 添加订阅失败:${result.message}!`)
|
$toast.error(t('subscribe.addFailed', { name: props.media?.share_title, message: result.message }))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
@@ -144,11 +148,11 @@ async function doDelete() {
|
|||||||
})
|
})
|
||||||
// 订阅状态
|
// 订阅状态
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
$toast.success(`${props.media?.share_title} 取消分享成功!`)
|
$toast.success(t('subscribe.cancelSuccess'))
|
||||||
// 完成
|
// 完成
|
||||||
emit('delete', result.data.id)
|
emit('delete', result.data.id)
|
||||||
} else {
|
} else {
|
||||||
$toast.error(`${props.media?.share_title} 取消分享失败:${result.message}!`)
|
$toast.error(t('subscribe.cancelFailed', { message: result.message }))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
@@ -200,13 +204,13 @@ onMounted(() => {
|
|||||||
<VList lines="one">
|
<VList lines="one">
|
||||||
<VListItem class="ps-0">
|
<VListItem class="ps-0">
|
||||||
<VListItemTitle class="text-center text-md-left">
|
<VListItemTitle class="text-center text-md-left">
|
||||||
<span class="font-weight-medium">分享人:</span>
|
<span class="font-weight-medium">{{ t('subscribe.sharer') }}:</span>
|
||||||
<span class="text-body-1"> {{ media?.share_user }}</span>
|
<span class="text-body-1"> {{ media?.share_user }}</span>
|
||||||
</VListItemTitle>
|
</VListItemTitle>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
<VListItem class="ps-0" v-if="media?.keyword">
|
<VListItem class="ps-0" v-if="media?.keyword">
|
||||||
<VListItemTitle class="text-center text-md-left">
|
<VListItemTitle class="text-center text-md-left">
|
||||||
<span class="font-weight-medium">搜索词:</span>
|
<span class="font-weight-medium">{{ t('subscribe.keyword') }}:</span>
|
||||||
<span class="text-body-1"> {{ media?.keyword }}</span>
|
<span class="text-body-1"> {{ media?.keyword }}</span>
|
||||||
</VListItemTitle>
|
</VListItemTitle>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
@@ -217,7 +221,7 @@ onMounted(() => {
|
|||||||
'line-clamp-4 overflow-hidden text-ellipsis': !isExpanded,
|
'line-clamp-4 overflow-hidden text-ellipsis': !isExpanded,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<span class="font-weight-medium">识别词:</span>
|
<span class="font-weight-medium">{{ t('subscribe.recognitionWords') }}:</span>
|
||||||
<span class="text-body-1"> {{ media?.custom_words }}</span>
|
<span class="text-body-1"> {{ media?.custom_words }}</span>
|
||||||
</VListItemTitle>
|
</VListItemTitle>
|
||||||
</VListItem>
|
</VListItem>
|
||||||
@@ -232,7 +236,7 @@ onMounted(() => {
|
|||||||
:loading="processing"
|
:loading="processing"
|
||||||
class="mb-2 me-2"
|
class="mb-2 me-2"
|
||||||
>
|
>
|
||||||
订阅
|
{{ t('subscribe.normalSub') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<VBtn
|
<VBtn
|
||||||
v-if="isFollowed && props.media?.share_uid"
|
v-if="isFollowed && props.media?.share_uid"
|
||||||
@@ -241,7 +245,7 @@ onMounted(() => {
|
|||||||
prepend-icon="mdi-account-remove"
|
prepend-icon="mdi-account-remove"
|
||||||
class="mb-2 me-2"
|
class="mb-2 me-2"
|
||||||
>
|
>
|
||||||
取消关注
|
{{ t('subscribe.unfollow') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<VBtn
|
<VBtn
|
||||||
v-else-if="props.media?.share_uid"
|
v-else-if="props.media?.share_uid"
|
||||||
@@ -250,7 +254,7 @@ onMounted(() => {
|
|||||||
prepend-icon="mdi-account-plus"
|
prepend-icon="mdi-account-plus"
|
||||||
class="mb-2 me-2"
|
class="mb-2 me-2"
|
||||||
>
|
>
|
||||||
关注
|
{{ t('subscribe.follow') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<VBtn
|
<VBtn
|
||||||
v-if="
|
v-if="
|
||||||
@@ -264,11 +268,13 @@ onMounted(() => {
|
|||||||
:loading="deleting"
|
:loading="deleting"
|
||||||
class="mb-2 me-2"
|
class="mb-2 me-2"
|
||||||
>
|
>
|
||||||
取消分享
|
{{ t('subscribe.cancelShare') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs mt-2" v-if="props.media?.count">
|
<div class="text-xs mt-2" v-if="props.media?.count">
|
||||||
<VIcon icon="mdi-fire" />共 {{ props.media?.count?.toLocaleString() }} 次复用
|
<VIcon icon="mdi-fire" />{{
|
||||||
|
t('subscribe.usageCount', { count: props.media?.count?.toLocaleString() })
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
|
|||||||
@@ -232,6 +232,18 @@ export default {
|
|||||||
name: 'Name',
|
name: 'Name',
|
||||||
searchShares: 'Search Subscription Shares',
|
searchShares: 'Search Subscription Shares',
|
||||||
keyword: 'Keyword',
|
keyword: 'Keyword',
|
||||||
|
noShareData:
|
||||||
|
'No shared subscription data available, data sharing is not enabled or the server cannot be connected.',
|
||||||
|
noPopularData:
|
||||||
|
'No popular subscription data available, data sharing is not enabled or the server cannot be connected.',
|
||||||
|
noFilterData: 'No matching content found. Please change the filter criteria.',
|
||||||
|
noSubscribeData: 'Please search to add movie or TV show subscriptions.',
|
||||||
|
sharer: 'Shared by',
|
||||||
|
follow: 'Follow',
|
||||||
|
unfollow: 'Unfollow',
|
||||||
|
recognitionWords: 'Recognition Words',
|
||||||
|
cancelShare: 'Cancel Share',
|
||||||
|
usageCount: 'Used {count} times',
|
||||||
},
|
},
|
||||||
recommend: {
|
recommend: {
|
||||||
all: 'All',
|
all: 'All',
|
||||||
@@ -307,4 +319,52 @@ export default {
|
|||||||
loadMore: 'Load More',
|
loadMore: 'Load More',
|
||||||
noMatchingResults: 'No matching results',
|
noMatchingResults: 'No matching results',
|
||||||
},
|
},
|
||||||
|
calendar: {
|
||||||
|
episode: 'Episode {number}',
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
usedPercent: 'Used {percent}%',
|
||||||
|
},
|
||||||
|
site: {
|
||||||
|
noSites: 'No Sites',
|
||||||
|
sitesWillBeShownHere: 'Added and supported sites will be displayed here.',
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
loadMore: 'Load More',
|
||||||
|
noMoreData: 'No More Data',
|
||||||
|
},
|
||||||
|
logging: {
|
||||||
|
level: 'Level',
|
||||||
|
time: 'Time',
|
||||||
|
program: 'Program',
|
||||||
|
content: 'Content',
|
||||||
|
refreshing: 'Refreshing',
|
||||||
|
},
|
||||||
|
moduleTest: {
|
||||||
|
normal: 'Normal',
|
||||||
|
disabled: 'Disabled',
|
||||||
|
error: 'Error',
|
||||||
|
},
|
||||||
|
nameTest: {
|
||||||
|
recognize: 'Recognize',
|
||||||
|
recognizing: 'Recognizing...',
|
||||||
|
recognizeAgain: 'Recognize Again',
|
||||||
|
title: 'Title',
|
||||||
|
subtitle: 'Subtitle',
|
||||||
|
},
|
||||||
|
netTest: {
|
||||||
|
notTested: 'Not Tested',
|
||||||
|
testing: 'Testing...',
|
||||||
|
normal: 'Normal',
|
||||||
|
},
|
||||||
|
ruleTest: {
|
||||||
|
test: 'Test',
|
||||||
|
testing: 'Testing...',
|
||||||
|
testAgain: 'Test Again',
|
||||||
|
title: 'Title',
|
||||||
|
subtitle: 'Subtitle',
|
||||||
|
ruleGroup: 'Rule Group',
|
||||||
|
priority: 'Priority: {value}',
|
||||||
|
noPriorityRule: 'No priority rule matched!',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,16 @@ export default {
|
|||||||
name: '名称',
|
name: '名称',
|
||||||
searchShares: '搜索订阅分享',
|
searchShares: '搜索订阅分享',
|
||||||
keyword: '关键词',
|
keyword: '关键词',
|
||||||
|
noShareData: '未获取到分享订阅数据,未开启数据分享或服务器无法连接。',
|
||||||
|
noPopularData: '未获取到热门订阅数据,未开启数据分享或服务器无法连接。',
|
||||||
|
noFilterData: '没有筛选到相关内容,请更换筛选条件。',
|
||||||
|
noSubscribeData: '请通过搜索添加电影、电视剧订阅。',
|
||||||
|
sharer: '分享人',
|
||||||
|
follow: '关注',
|
||||||
|
unfollow: '取消关注',
|
||||||
|
recognitionWords: '识别词',
|
||||||
|
cancelShare: '取消分享',
|
||||||
|
usageCount: '共 {count} 次复用',
|
||||||
},
|
},
|
||||||
recommend: {
|
recommend: {
|
||||||
all: '全部',
|
all: '全部',
|
||||||
@@ -307,4 +317,52 @@ export default {
|
|||||||
loadMore: '加载更多',
|
loadMore: '加载更多',
|
||||||
noMatchingResults: '没有匹配的结果',
|
noMatchingResults: '没有匹配的结果',
|
||||||
},
|
},
|
||||||
|
calendar: {
|
||||||
|
episode: '第{number}集',
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
usedPercent: '已使用 {percent}%',
|
||||||
|
},
|
||||||
|
site: {
|
||||||
|
noSites: '没有站点',
|
||||||
|
sitesWillBeShownHere: '已添加并支持的站点将会在这里显示。',
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
loadMore: '加载更多',
|
||||||
|
noMoreData: '没有更多数据',
|
||||||
|
},
|
||||||
|
logging: {
|
||||||
|
level: '级别',
|
||||||
|
time: '时间',
|
||||||
|
program: '程序',
|
||||||
|
content: '内容',
|
||||||
|
refreshing: '正在刷新',
|
||||||
|
},
|
||||||
|
moduleTest: {
|
||||||
|
normal: '正常',
|
||||||
|
disabled: '未启用',
|
||||||
|
error: '错误',
|
||||||
|
},
|
||||||
|
nameTest: {
|
||||||
|
recognize: '识别',
|
||||||
|
recognizing: '识别中...',
|
||||||
|
recognizeAgain: '重新识别',
|
||||||
|
title: '标题',
|
||||||
|
subtitle: '副标题',
|
||||||
|
},
|
||||||
|
netTest: {
|
||||||
|
notTested: '未测试',
|
||||||
|
testing: '测试中...',
|
||||||
|
normal: '正常',
|
||||||
|
},
|
||||||
|
ruleTest: {
|
||||||
|
test: '测试',
|
||||||
|
testing: '正在测试...',
|
||||||
|
testAgain: '重新测试',
|
||||||
|
title: '标题',
|
||||||
|
subtitle: '副标题',
|
||||||
|
ruleGroup: '规则组',
|
||||||
|
priority: '优先级:{value}',
|
||||||
|
noPriorityRule: '未命中任何优先级规则!',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import logo from '@images/logo.png'
|
|||||||
import { useTheme } from 'vuetify'
|
import { useTheme } from 'vuetify'
|
||||||
import { urlBase64ToUint8Array } from '@/@core/utils/navigator'
|
import { urlBase64ToUint8Array } from '@/@core/utils/navigator'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { SUPPORTED_LOCALES, SupportedLocale } from '@/locales/types'
|
import { SUPPORTED_LOCALES, SupportedLocale } from '@/types/i18n'
|
||||||
import { getCurrentLocale, setI18nLanguage } from '@/plugins/i18n'
|
import { getCurrentLocale, setI18nLanguage } from '@/plugins/i18n'
|
||||||
|
|
||||||
// 主题
|
// 主题
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
import { nextTick } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
import { SUPPORTED_LOCALES, SupportedLocale } from '@/locales/types'
|
import { SUPPORTED_LOCALES, SupportedLocale } from '@/types/i18n'
|
||||||
|
|
||||||
// 导入语言文件
|
// 导入语言文件
|
||||||
import zhCN from '@/locales/zh-CN'
|
import zhCN from '@/locales/zh-CN'
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import zhCN from './zh-CN'
|
import zhCN from '@/locales/zh-CN'
|
||||||
|
|
||||||
|
// 导出类型和常量,而不是作为语言消息文件
|
||||||
export type MessageSchema = typeof zhCN
|
export type MessageSchema = typeof zhCN
|
||||||
export type LocaleKey = keyof typeof zhCN
|
export type LocaleKey = keyof typeof zhCN
|
||||||
|
|
||||||
@@ -5,6 +5,10 @@ import api from '@/api'
|
|||||||
import trophy from '@images/misc/storage.png'
|
import trophy from '@images/misc/storage.png'
|
||||||
import triangleDark from '@images/misc/triangle-dark.png'
|
import triangleDark from '@images/misc/triangle-dark.png'
|
||||||
import triangleLight from '@images/misc/triangle-light.png'
|
import triangleLight from '@images/misc/triangle-light.png'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const { global } = useTheme()
|
const { global } = useTheme()
|
||||||
|
|
||||||
@@ -52,13 +56,13 @@ onActivated(() => {
|
|||||||
<template #append>
|
<template #append>
|
||||||
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
|
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
|
||||||
</template>
|
</template>
|
||||||
<VCardTitle>存储空间</VCardTitle>
|
<VCardTitle>{{ t('dashboard.storage') }}</VCardTitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<h5 class="text-2xl font-weight-medium text-primary">
|
<h5 class="text-2xl font-weight-medium text-primary">
|
||||||
{{ formatFileSize(storage) }}
|
{{ formatFileSize(storage) }}
|
||||||
</h5>
|
</h5>
|
||||||
<p class="mt-2">已使用 {{ usedPercent }}% 🚀</p>
|
<p class="mt-2">{{ t('storage.usedPercent', { percent: usedPercent }) }} 🚀</p>
|
||||||
<p class="mt-1">
|
<p class="mt-1">
|
||||||
<VProgressLinear :model-value="usedPercent" color="primary" />
|
<VProgressLinear :model-value="usedPercent" color="primary" />
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type { MediaServerConf, MediaServerLibrary } from '@/api/types'
|
import type { MediaServerConf, MediaServerLibrary } from '@/api/types'
|
||||||
import LibraryCard from '@/components/cards/LibraryCard.vue'
|
import LibraryCard from '@/components/cards/LibraryCard.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 媒体库列表
|
// 媒体库列表
|
||||||
const libraryList = ref<MediaServerLibrary[]>([])
|
const libraryList = ref<MediaServerLibrary[]>([])
|
||||||
@@ -63,7 +67,7 @@ onActivated(() => {
|
|||||||
<template #append>
|
<template #append>
|
||||||
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
|
<VIcon class="cursor-move" v-if="hover.isHovering">mdi-drag</VIcon>
|
||||||
</template>
|
</template>
|
||||||
<VCardTitle>我的媒体库</VCardTitle>
|
<VCardTitle>{{ t('dashboard.library') }}</VCardTitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<div class="grid gap-4 grid-backdrop-card mx-3" tabindex="0">
|
<div class="grid gap-4 grid-backdrop-card mx-3" tabindex="0">
|
||||||
<LibraryCard v-for="item in libraryList" :key="item.id" :media="item" height="10rem" />
|
<LibraryCard v-for="item in libraryList" :key="item.id" :media="item" height="10rem" />
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import NoDataFound from '@/components/NoDataFound.vue'
|
|||||||
import SiteAddEditDialog from '@/components/dialog/SiteAddEditDialog.vue'
|
import SiteAddEditDialog from '@/components/dialog/SiteAddEditDialog.vue'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import { useDynamicButton } from '@/composables/useDynamicButton'
|
import { useDynamicButton } from '@/composables/useDynamicButton'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// APP
|
// APP
|
||||||
const display = useDisplay()
|
const display = useDisplay()
|
||||||
@@ -98,7 +102,7 @@ useDynamicButton({
|
|||||||
<template>
|
<template>
|
||||||
<div class="card-list-container">
|
<div class="card-list-container">
|
||||||
<!-- 页面标题 -->
|
<!-- 页面标题 -->
|
||||||
<VPageContentTitle title="站点管理" />
|
<VPageContentTitle :title="t('navItems.siteManager')" />
|
||||||
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
||||||
<draggable
|
<draggable
|
||||||
v-if="siteList.length > 0"
|
v-if="siteList.length > 0"
|
||||||
@@ -117,8 +121,8 @@ useDynamicButton({
|
|||||||
<NoDataFound
|
<NoDataFound
|
||||||
v-if="siteList.length === 0 && isRefreshed"
|
v-if="siteList.length === 0 && isRefreshed"
|
||||||
error-code="404"
|
error-code="404"
|
||||||
error-title="没有站点"
|
:error-title="t('site.noSites')"
|
||||||
error-description="已添加并支持的站点将会在这里显示。"
|
:error-description="t('site.sitesWillBeShownHere')"
|
||||||
/>
|
/>
|
||||||
<!-- 新增站点按钮 -->
|
<!-- 新增站点按钮 -->
|
||||||
<VFab
|
<VFab
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ import type { MediaInfo, Subscribe, TmdbEpisode } from '@/api/types'
|
|||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { formatEp, parseDate } from '@/@core/utils/formatters'
|
import { formatEp, parseDate } from '@/@core/utils/formatters'
|
||||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { getCurrentLocale } from '@/plugins/i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 进度框
|
// 进度框
|
||||||
const progressDialog = ref(false)
|
const progressDialog = ref(false)
|
||||||
@@ -19,10 +24,13 @@ const loading = ref(false)
|
|||||||
// 已加载过
|
// 已加载过
|
||||||
const isLoaded = ref(false)
|
const isLoaded = ref(false)
|
||||||
|
|
||||||
|
// 获取当前语言
|
||||||
|
const currentLocale = getCurrentLocale().split('-')[0]
|
||||||
|
|
||||||
// 日历属性
|
// 日历属性
|
||||||
const calendarOptions: Ref<CalendarOptions> = ref({
|
const calendarOptions: Ref<CalendarOptions> = ref({
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
locale: 'zh-cn',
|
locale: currentLocale,
|
||||||
plugins: [
|
plugins: [
|
||||||
dayGridPlugin,
|
dayGridPlugin,
|
||||||
timeGridPlugin,
|
timeGridPlugin,
|
||||||
@@ -46,7 +54,7 @@ const calendarOptions: Ref<CalendarOptions> = ref({
|
|||||||
|
|
||||||
async function eventsHander(subscribe: Subscribe) {
|
async function eventsHander(subscribe: Subscribe) {
|
||||||
// 如果是电影直接返回
|
// 如果是电影直接返回
|
||||||
if (subscribe.type === '电影') {
|
if (subscribe.type === t('media.movie')) {
|
||||||
// 调用API查询TMDB详情
|
// 调用API查询TMDB详情
|
||||||
const movie: MediaInfo = await api.get(`media/tmdb:${subscribe.tmdbid}`, {
|
const movie: MediaInfo = await api.get(`media/tmdb:${subscribe.tmdbid}`, {
|
||||||
params: { type_name: subscribe.type },
|
params: { type_name: subscribe.type },
|
||||||
@@ -160,14 +168,14 @@ onActivated(() => {
|
|||||||
{{ arg.event.title }}
|
{{ arg.event.title }}
|
||||||
</VCardSubtitle>
|
</VCardSubtitle>
|
||||||
<VCardText v-if="arg.event.extendedProps.subtitle" class="pa-0 px-2 break-words">
|
<VCardText v-if="arg.event.extendedProps.subtitle" class="pa-0 px-2 break-words">
|
||||||
第{{ arg.event.extendedProps.subtitle }}集
|
{{ t('calendar.episode', { number: arg.event.extendedProps.subtitle }) }}
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:hidden">
|
<div class="md:hidden">
|
||||||
<VTooltip :text="`${arg.event.title} 第 ${arg.event.extendedProps.subtitle} 集`">
|
<VTooltip :text="`${arg.event.title} ${t('calendar.episode', { number: arg.event.extendedProps.subtitle })}`">
|
||||||
<template #activator="{ props }">
|
<template #activator="{ props }">
|
||||||
<VImg
|
<VImg
|
||||||
height="60"
|
height="60"
|
||||||
@@ -198,7 +206,7 @@ onActivated(() => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</FullCalendar>
|
</FullCalendar>
|
||||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" text="正在加载 ..." />
|
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="t('common.loading') + ' ...'" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import SubscribeHistoryDialog from '@/components/dialog/SubscribeHistoryDialog.v
|
|||||||
import { useUserStore } from '@/stores'
|
import { useUserStore } from '@/stores'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import { useDynamicButton } from '@/composables/useDynamicButton'
|
import { useDynamicButton } from '@/composables/useDynamicButton'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// APP
|
// APP
|
||||||
const display = useDisplay()
|
const display = useDisplay()
|
||||||
@@ -31,8 +35,8 @@ const props = defineProps({
|
|||||||
let isRefreshed = ref(false)
|
let isRefreshed = ref(false)
|
||||||
|
|
||||||
// 顺序存储键值
|
// 顺序存储键值
|
||||||
const localOrderKey = props.type === '电影' ? 'MP_SUBSCRIBE_MOVIE_ORDER' : 'MP_SUBSCRIBE_TV_ORDER'
|
const localOrderKey = props.type === t('media.movie') ? 'MP_SUBSCRIBE_MOVIE_ORDER' : 'MP_SUBSCRIBE_TV_ORDER'
|
||||||
const orderRequestKey = props.type === '电影' ? 'SubscribeMovieOrder' : 'SubscribeTvOrder'
|
const orderRequestKey = props.type === t('media.movie') ? 'SubscribeMovieOrder' : 'SubscribeTvOrder'
|
||||||
|
|
||||||
// 刷新状态
|
// 刷新状态
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@@ -160,7 +164,7 @@ useDynamicButton({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VPageContentTitle v-if="keyword" :title="`筛选:${keyword}`" />
|
<VPageContentTitle v-if="keyword" :title="`${t('subscribe.filterSubscriptions')}:${keyword}`" />
|
||||||
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
||||||
<draggable
|
<draggable
|
||||||
v-if="displayList.length > 0"
|
v-if="displayList.length > 0"
|
||||||
@@ -178,8 +182,8 @@ useDynamicButton({
|
|||||||
<NoDataFound
|
<NoDataFound
|
||||||
v-if="displayList.length === 0 && isRefreshed"
|
v-if="displayList.length === 0 && isRefreshed"
|
||||||
error-code="404"
|
error-code="404"
|
||||||
error-title="没有数据"
|
:error-title="t('common.noData')"
|
||||||
:error-description="keyword ? '没有筛选到相关内容,请更换筛选条件。' : '请通过搜索添加电影、电视剧订阅。'"
|
:error-description="keyword ? t('subscribe.noFilterData') : t('subscribe.noSubscribeData')"
|
||||||
/>
|
/>
|
||||||
<!-- 底部操作按钮 -->
|
<!-- 底部操作按钮 -->
|
||||||
<div v-if="isRefreshed">
|
<div v-if="isRefreshed">
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import api from '@/api'
|
|||||||
import type { MediaInfo } from '@/api/types'
|
import type { MediaInfo } from '@/api/types'
|
||||||
import MediaCard from '@/components/cards/MediaCard.vue'
|
import MediaCard from '@/components/cards/MediaCard.vue'
|
||||||
import NoDataFound from '@/components/NoDataFound.vue'
|
import NoDataFound from '@/components/NoDataFound.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -122,8 +126,8 @@ async function fetchData({ done }: { done: any }) {
|
|||||||
<NoDataFound
|
<NoDataFound
|
||||||
v-if="dataList.length === 0 && isRefreshed"
|
v-if="dataList.length === 0 && isRefreshed"
|
||||||
error-code="404"
|
error-code="404"
|
||||||
error-title="没有数据"
|
:error-title="t('common.noData')"
|
||||||
error-description="未获取到热门订阅数据,未开启数据分享或服务器无法连接。"
|
:error-description="t('subscribe.noPopularData')"
|
||||||
/>
|
/>
|
||||||
</VInfiniteScroll>
|
</VInfiniteScroll>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import api from '@/api'
|
|||||||
import type { SubscribeShare } from '@/api/types'
|
import type { SubscribeShare } from '@/api/types'
|
||||||
import NoDataFound from '@/components/NoDataFound.vue'
|
import NoDataFound from '@/components/NoDataFound.vue'
|
||||||
import SubscribeShareCard from '@/components/cards/SubscribeShareCard.vue'
|
import SubscribeShareCard from '@/components/cards/SubscribeShareCard.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 定义输入参数
|
// 定义输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -115,7 +119,7 @@ function removeData(id: number) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VPageContentTitle v-if="keyword" :title="`搜索:${keyword}`" />
|
<VPageContentTitle v-if="keyword" :title="`${t('common.search')}:${keyword}`" />
|
||||||
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
||||||
<VInfiniteScroll mode="intersect" side="end" :items="dataList" class="overflow-visible" @load="fetchData">
|
<VInfiniteScroll mode="intersect" side="end" :items="dataList" class="overflow-visible" @load="fetchData">
|
||||||
<template #loading />
|
<template #loading />
|
||||||
@@ -128,10 +132,8 @@ function removeData(id: number) {
|
|||||||
<NoDataFound
|
<NoDataFound
|
||||||
v-if="dataList.length === 0 && isRefreshed"
|
v-if="dataList.length === 0 && isRefreshed"
|
||||||
error-code="404"
|
error-code="404"
|
||||||
error-title="没有数据"
|
:error-title="t('common.noData')"
|
||||||
:error-description="
|
:error-description="keyword ? t('common.noContent') : t('subscribe.noShareData')"
|
||||||
keyword ? '没有搜索到相关内容,请更换搜索关键词。' : '未获取到分享订阅数据,未开启数据分享或服务器无法连接。'
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</VInfiniteScroll>
|
</VInfiniteScroll>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 已解析的日志列表
|
// 已解析的日志列表
|
||||||
const parsedLogs = ref<{ level: string; time: string; program: string; content: string }[]>([])
|
const parsedLogs = ref<{ level: string; time: string; program: string; content: string }[]>([])
|
||||||
|
|
||||||
// 表头
|
// 表头
|
||||||
const headers = [
|
const headers = [
|
||||||
{ title: '级别', value: 'level' },
|
{ title: t('logging.level'), value: 'level' },
|
||||||
{ title: '时间', value: 'time' },
|
{ title: t('logging.time'), value: 'time' },
|
||||||
{ title: '程序', value: 'program' },
|
{ title: t('logging.program'), value: 'program' },
|
||||||
{ title: '内容', value: 'content' },
|
{ title: t('logging.content'), value: 'content' },
|
||||||
]
|
]
|
||||||
|
|
||||||
// SSE消息对象
|
// SSE消息对象
|
||||||
@@ -73,7 +78,7 @@ onBeforeUnmount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LoadingBanner v-if="parsedLogs.length === 0" class="mt-12" text="正在刷新 ..." />
|
<LoadingBanner v-if="parsedLogs.length === 0" class="mt-12" :text="t('logging.refreshing') + ' ...'" />
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<VTable class="table-rounded" hide-default-footer disable-sort>
|
<VTable class="table-rounded" hide-default-footer disable-sort>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
import type { Message } from '@/api/types'
|
import type { Message } from '@/api/types'
|
||||||
import MessageCard from '@/components/cards/MessageCard.vue'
|
import MessageCard from '@/components/cards/MessageCard.vue'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 定义事件
|
// 定义事件
|
||||||
const emit = defineEmits(['scroll'])
|
const emit = defineEmits(['scroll'])
|
||||||
@@ -103,12 +107,12 @@ onBeforeUnmount(() => {
|
|||||||
:items="messages"
|
:items="messages"
|
||||||
class="overflow-visible"
|
class="overflow-visible"
|
||||||
@load="loadMessages"
|
@load="loadMessages"
|
||||||
load-more-text="加载更多 ..."
|
:load-more-text="t('message.loadMore') + ' ...'"
|
||||||
>
|
>
|
||||||
<template #loading>
|
<template #loading>
|
||||||
<LoadingBanner />
|
<LoadingBanner />
|
||||||
</template>
|
</template>
|
||||||
<template #empty> 没有更多数据 </template>
|
<template #empty> {{ t('message.noMoreData') }} </template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
v-for="(msg, index) in messages"
|
v-for="(msg, index) in messages"
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 定义所有的模块ID、名称列表
|
// 定义所有的模块ID、名称列表
|
||||||
const modules = ref<
|
const modules = ref<
|
||||||
@@ -41,13 +45,13 @@ async function moduleTest(index: number) {
|
|||||||
target.loading = false
|
target.loading = false
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
target.state = 'success'
|
target.state = 'success'
|
||||||
target.name = `${target.name} - 正常`
|
target.name = `${target.name} - ${t('moduleTest.normal')}`
|
||||||
} else if (!result.message) {
|
} else if (!result.message) {
|
||||||
target.state = undefined
|
target.state = undefined
|
||||||
target.name = `${target.name} - 未启用`
|
target.name = `${target.name} - ${t('moduleTest.disabled')}`
|
||||||
} else {
|
} else {
|
||||||
target.state = 'error'
|
target.state = 'error'
|
||||||
target.name = `${target.name} - 错误!`
|
target.name = `${target.name} - ${t('moduleTest.error')}!`
|
||||||
target.errmsg = result.message
|
target.errmsg = result.message
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import { requiredValidator } from '@/@validators'
|
|||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type { Context } from '@/api/types'
|
import type { Context } from '@/api/types'
|
||||||
import MediaInfoCard from '@/components/cards/MediaInfoCard.vue'
|
import MediaInfoCard from '@/components/cards/MediaInfoCard.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 识别结果
|
// 识别结果
|
||||||
const nameTestResult = ref<Context>()
|
const nameTestResult = ref<Context>()
|
||||||
@@ -18,19 +22,18 @@ const nameTestForm = reactive({
|
|||||||
const nameTestLoading = ref(false)
|
const nameTestLoading = ref(false)
|
||||||
|
|
||||||
// 识别按钮文本
|
// 识别按钮文本
|
||||||
const nameTestText = ref('识别')
|
const nameTestText = ref(t('nameTest.recognize'))
|
||||||
|
|
||||||
// 是否显示结果
|
// 是否显示结果
|
||||||
const showResult = ref(false)
|
const showResult = ref(false)
|
||||||
|
|
||||||
// 调用API识别
|
// 调用API识别
|
||||||
async function nameTest() {
|
async function nameTest() {
|
||||||
if (!nameTestForm.title)
|
if (!nameTestForm.title) return
|
||||||
return
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nameTestLoading.value = true
|
nameTestLoading.value = true
|
||||||
nameTestText.value = '识别中...'
|
nameTestText.value = t('nameTest.recognizing')
|
||||||
showResult.value = false
|
showResult.value = false
|
||||||
nameTestResult.value = await api.get('media/recognize', {
|
nameTestResult.value = await api.get('media/recognize', {
|
||||||
params: {
|
params: {
|
||||||
@@ -39,10 +42,9 @@ async function nameTest() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
nameTestLoading.value = false
|
nameTestLoading.value = false
|
||||||
nameTestText.value = '重新识别'
|
nameTestText.value = t('nameTest.recognizeAgain')
|
||||||
showResult.value = true
|
showResult.value = true
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,30 +54,15 @@ async function nameTest() {
|
|||||||
<VForm @submit.prevent="() => {}">
|
<VForm @submit.prevent="() => {}">
|
||||||
<VRow class="pt-2">
|
<VRow class="pt-2">
|
||||||
<VCol cols="12">
|
<VCol cols="12">
|
||||||
<VTextField
|
<VTextField v-model="nameTestForm.title" :label="t('nameTest.title')" :rules="[requiredValidator]" />
|
||||||
v-model="nameTestForm.title"
|
|
||||||
label="标题"
|
|
||||||
:rules="[requiredValidator]"
|
|
||||||
/>
|
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol cols="12">
|
<VCol cols="12">
|
||||||
<VTextarea
|
<VTextarea v-model="nameTestForm.subtitle" :label="t('nameTest.subtitle')" rows="2" auto-grow />
|
||||||
v-model="nameTestForm.subtitle"
|
|
||||||
label="副标题"
|
|
||||||
rows="2"
|
|
||||||
auto-grow
|
|
||||||
/>
|
|
||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
<VRow>
|
<VRow>
|
||||||
<VCol
|
<VCol cols="12" class="text-center">
|
||||||
cols="12"
|
<VBtn :disabled="nameTestLoading" @click="nameTest">
|
||||||
class="text-center"
|
|
||||||
>
|
|
||||||
<VBtn
|
|
||||||
:disabled="nameTestLoading"
|
|
||||||
@click="nameTest"
|
|
||||||
>
|
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<VIcon icon="mdi-text-recognition" />
|
<VIcon icon="mdi-text-recognition" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import tmdb from '@images/logos/tmdb.png'
|
|||||||
import wechat from '@images/logos/wechat.png'
|
import wechat from '@images/logos/wechat.png'
|
||||||
import fanart from '@images/logos/fanart.webp'
|
import fanart from '@images/logos/fanart.webp'
|
||||||
import tvdb from '@images/logos/thetvdb.jpeg'
|
import tvdb from '@images/logos/thetvdb.jpeg'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
interface Status {
|
interface Status {
|
||||||
OK: string
|
OK: string
|
||||||
@@ -46,7 +50,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -56,7 +60,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -66,7 +70,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -76,7 +80,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -86,7 +90,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -96,7 +100,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: false,
|
proxy: false,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -106,7 +110,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: false,
|
proxy: false,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -116,7 +120,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: false,
|
proxy: false,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -126,7 +130,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -136,7 +140,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -146,7 +150,7 @@ const targets = ref<Address[]>([
|
|||||||
proxy: true,
|
proxy: true,
|
||||||
status: 'Normal',
|
status: 'Normal',
|
||||||
time: '',
|
time: '',
|
||||||
message: '未测试',
|
message: t('netTest.notTested'),
|
||||||
btndisable: false,
|
btndisable: false,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -165,7 +169,7 @@ async function netTest(index: number) {
|
|||||||
|
|
||||||
target.btndisable = true
|
target.btndisable = true
|
||||||
target.status = 'Doing'
|
target.status = 'Doing'
|
||||||
target.message = '测试中...'
|
target.message = t('netTest.testing')
|
||||||
|
|
||||||
const result: { [key: string]: any } = await api.get('system/nettest', {
|
const result: { [key: string]: any } = await api.get('system/nettest', {
|
||||||
params: {
|
params: {
|
||||||
@@ -176,7 +180,7 @@ async function netTest(index: number) {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
target.status = 'OK'
|
target.status = 'OK'
|
||||||
target.message = '正常'
|
target.message = t('netTest.normal')
|
||||||
} else {
|
} else {
|
||||||
target.status = 'Fail'
|
target.status = 'Fail'
|
||||||
target.message = result.message
|
target.message = result.message
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import { reactive, ref } from 'vue'
|
|||||||
import { requiredValidator } from '@/@validators'
|
import { requiredValidator } from '@/@validators'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { FilterRuleGroup } from '@/api/types'
|
import { FilterRuleGroup } from '@/api/types'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
// 国际化
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 识别结果
|
// 识别结果
|
||||||
const ruleTestResult = ref('')
|
const ruleTestResult = ref('')
|
||||||
@@ -18,7 +22,7 @@ const ruleTestForm = reactive({
|
|||||||
const ruleTestLoading = ref(false)
|
const ruleTestLoading = ref(false)
|
||||||
|
|
||||||
// 识别按钮文本
|
// 识别按钮文本
|
||||||
const ruleTestText = ref('测试')
|
const ruleTestText = ref(t('ruleTest.test'))
|
||||||
|
|
||||||
// 是否显示结果
|
// 是否显示结果
|
||||||
const showResult = ref(false)
|
const showResult = ref(false)
|
||||||
@@ -47,7 +51,7 @@ async function ruleTest() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
ruleTestLoading.value = true
|
ruleTestLoading.value = true
|
||||||
ruleTestText.value = '正在测试...'
|
ruleTestText.value = t('ruleTest.testing')
|
||||||
showResult.value = false
|
showResult.value = false
|
||||||
const result: { [key: string]: any } = await api.get('system/ruletest', {
|
const result: { [key: string]: any } = await api.get('system/ruletest', {
|
||||||
params: {
|
params: {
|
||||||
@@ -56,11 +60,11 @@ async function ruleTest() {
|
|||||||
rulegroup_name: ruleTestForm.rulegroup,
|
rulegroup_name: ruleTestForm.rulegroup,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if (result.success) ruleTestResult.value = `优先级:${result.data.priority}`
|
if (result.success) ruleTestResult.value = t('ruleTest.priority', { value: result.data.priority })
|
||||||
else ruleTestResult.value = '未命中任何优先级规则!'
|
else ruleTestResult.value = t('ruleTest.noPriorityRule')
|
||||||
|
|
||||||
ruleTestLoading.value = false
|
ruleTestLoading.value = false
|
||||||
ruleTestText.value = '重新测试'
|
ruleTestText.value = t('ruleTest.testAgain')
|
||||||
showResult.value = true
|
showResult.value = true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
@@ -76,13 +80,13 @@ onMounted(() => {
|
|||||||
<VForm @submit.prevent="() => {}">
|
<VForm @submit.prevent="() => {}">
|
||||||
<VRow class="pt-2">
|
<VRow class="pt-2">
|
||||||
<VCol cols="12" md="8">
|
<VCol cols="12" md="8">
|
||||||
<VTextField v-model="ruleTestForm.title" label="标题" :rules="[requiredValidator]" />
|
<VTextField v-model="ruleTestForm.title" :label="t('ruleTest.title')" :rules="[requiredValidator]" />
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol cols="12" md="4">
|
<VCol cols="12" md="4">
|
||||||
<VSelect v-model="ruleTestForm.rulegroup" label="规则组" :items="filterRuleGroupItems" />
|
<VSelect v-model="ruleTestForm.rulegroup" :label="t('ruleTest.ruleGroup')" :items="filterRuleGroupItems" />
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol cols="12">
|
<VCol cols="12">
|
||||||
<VTextarea v-model="ruleTestForm.subtitle" label="副标题" rows="2" auto-grow />
|
<VTextarea v-model="ruleTestForm.subtitle" :label="t('ruleTest.subtitle')" rows="2" auto-grow />
|
||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
<VRow>
|
<VRow>
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ export default defineConfig({
|
|||||||
vueTemplate: true,
|
vueTemplate: true,
|
||||||
}),
|
}),
|
||||||
VueI18n({
|
VueI18n({
|
||||||
include: [resolve(__dirname, 'src/locales/**')],
|
include: [resolve(__dirname, 'src/locales/*.ts')],
|
||||||
}),
|
}),
|
||||||
VitePWA({
|
VitePWA({
|
||||||
injectRegister: 'script',
|
injectRegister: 'script',
|
||||||
|
|||||||
Reference in New Issue
Block a user