mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-27 19:29:52 +08:00
添加国际化支持:在多个页面和组件中引入 vue-i18n
This commit is contained in:
@@ -14,7 +14,7 @@ export default {
|
||||
inputMessage: 'Enter message or command',
|
||||
send: 'Send',
|
||||
noData: 'No Data',
|
||||
noContent: 'No content found',
|
||||
noContent: 'No Content Found',
|
||||
},
|
||||
theme: {
|
||||
light: 'Light',
|
||||
@@ -22,7 +22,7 @@ export default {
|
||||
auto: 'Auto',
|
||||
transparent: 'Transparent',
|
||||
purple: 'Purple',
|
||||
custom: 'Custom',
|
||||
custom: 'Custom Theme',
|
||||
},
|
||||
app: {
|
||||
moviepilot: 'MoviePilot',
|
||||
@@ -228,5 +228,83 @@ export default {
|
||||
addFailed: 'Failed to add {name}: {message}!',
|
||||
cancelSuccess: 'Subscription cancelled!',
|
||||
cancelFailed: 'Failed to cancel subscription: {message}!',
|
||||
filterSubscriptions: 'Filter Subscriptions',
|
||||
name: 'Name',
|
||||
searchShares: 'Search Subscription Shares',
|
||||
keyword: 'Keyword',
|
||||
},
|
||||
recommend: {
|
||||
all: 'All',
|
||||
categoryMovie: 'Movies',
|
||||
categoryTV: 'TV Shows',
|
||||
categoryAnime: 'Anime',
|
||||
categoryRankings: 'Rankings',
|
||||
trendingNow: 'Trending Now',
|
||||
nowShowing: 'Now Showing',
|
||||
bangumiDaily: 'Bangumi Daily',
|
||||
tmdbHotMovies: 'TMDB Hot Movies',
|
||||
tmdbHotTVShows: 'TMDB Hot TV Shows',
|
||||
doubanHotMovies: 'Douban Hot Movies',
|
||||
doubanHotTVShows: 'Douban Hot TV Shows',
|
||||
doubanHotAnime: 'Douban Hot Anime',
|
||||
doubanNewMovies: 'Douban New Movies',
|
||||
doubanNewTVShows: 'Douban New TV Shows',
|
||||
doubanTop250: 'Douban Movie TOP250',
|
||||
doubanChineseTVRankings: 'Douban Chinese TV Rankings',
|
||||
doubanGlobalTVRankings: 'Douban Global TV Rankings',
|
||||
noCategoryContent: 'No content to display in this category',
|
||||
configureContent: 'Configure Content',
|
||||
customizeContent: 'Customize Content',
|
||||
selectContentToDisplay: 'Select the content you want to display',
|
||||
selectAll: 'Select All',
|
||||
selectNone: 'Select None',
|
||||
},
|
||||
discover: {
|
||||
setTabOrder: 'Set Tab Order',
|
||||
dragToReorder: 'Drag to reorder tabs',
|
||||
},
|
||||
downloading: {
|
||||
noDownloader: 'No Downloaders',
|
||||
configureDownloader: 'Please configure and enable downloaders in settings first.',
|
||||
},
|
||||
resource: {
|
||||
searchResults: 'Resource Search Results',
|
||||
keyword: 'Keyword',
|
||||
title: 'Title',
|
||||
year: 'Year',
|
||||
season: 'Season',
|
||||
switchingView: 'Switching View',
|
||||
backToHome: 'Back to Home',
|
||||
searching: 'Searching, please wait...',
|
||||
noData: 'No Data',
|
||||
noResourceFound: 'No resources found',
|
||||
},
|
||||
browse: {
|
||||
actor: 'Actor',
|
||||
},
|
||||
appcenter: {
|
||||
others: 'Others',
|
||||
},
|
||||
notFound: {
|
||||
title: 'Page Not Found ⚠️',
|
||||
description: 'The page you are trying to access does not exist. Please check the URL.',
|
||||
backButton: 'Back',
|
||||
},
|
||||
torrent: {
|
||||
sortDefault: 'Default',
|
||||
sortSite: 'Site',
|
||||
sortSize: 'Size',
|
||||
sortSeeder: 'Seeders',
|
||||
filterSite: 'Site',
|
||||
filterSeason: 'Season',
|
||||
filterFreeState: 'Promotion',
|
||||
filterVideoCode: 'Video Code',
|
||||
filterEdition: 'Quality',
|
||||
filterResolution: 'Resolution',
|
||||
filterReleaseGroup: 'Release Group',
|
||||
clearFilters: 'Clear',
|
||||
selectAll: 'Select All',
|
||||
loadMore: 'Load More',
|
||||
noMatchingResults: 'No matching results',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -228,5 +228,83 @@ export default {
|
||||
addFailed: '添加{name}失败:{message}!',
|
||||
cancelSuccess: '已取消订阅!',
|
||||
cancelFailed: '取消订阅失败:{message}!',
|
||||
filterSubscriptions: '筛选订阅',
|
||||
name: '名称',
|
||||
searchShares: '搜索订阅分享',
|
||||
keyword: '关键词',
|
||||
},
|
||||
recommend: {
|
||||
all: '全部',
|
||||
categoryMovie: '电影',
|
||||
categoryTV: '电视剧',
|
||||
categoryAnime: '动漫',
|
||||
categoryRankings: '榜单',
|
||||
trendingNow: '流行趋势',
|
||||
nowShowing: '正在热映',
|
||||
bangumiDaily: 'Bangumi每日放送',
|
||||
tmdbHotMovies: 'TMDB热门电影',
|
||||
tmdbHotTVShows: 'TMDB热门电视剧',
|
||||
doubanHotMovies: '豆瓣热门电影',
|
||||
doubanHotTVShows: '豆瓣热门电视剧',
|
||||
doubanHotAnime: '豆瓣热门动漫',
|
||||
doubanNewMovies: '豆瓣最新电影',
|
||||
doubanNewTVShows: '豆瓣最新电视剧',
|
||||
doubanTop250: '豆瓣电影TOP250',
|
||||
doubanChineseTVRankings: '豆瓣国产剧集榜',
|
||||
doubanGlobalTVRankings: '豆瓣全球剧集榜',
|
||||
noCategoryContent: '当前分类下没有可显示的内容',
|
||||
configureContent: '设置显示内容',
|
||||
customizeContent: '自定义内容',
|
||||
selectContentToDisplay: '选择您想在页面显示的内容',
|
||||
selectAll: '全选',
|
||||
selectNone: '全不选',
|
||||
},
|
||||
discover: {
|
||||
setTabOrder: '设置标签顺序',
|
||||
dragToReorder: '拖动对标签页进行排序',
|
||||
},
|
||||
downloading: {
|
||||
noDownloader: '没有下载器',
|
||||
configureDownloader: '请先在设置中正确配置并启用下载器。',
|
||||
},
|
||||
resource: {
|
||||
searchResults: '资源搜索结果',
|
||||
keyword: '关键词',
|
||||
title: '标题',
|
||||
year: '年份',
|
||||
season: '季',
|
||||
switchingView: '切换视图',
|
||||
backToHome: '返回首页',
|
||||
searching: '正在搜索,请稍候...',
|
||||
noData: '没有数据',
|
||||
noResourceFound: '未搜索到任何资源',
|
||||
},
|
||||
browse: {
|
||||
actor: '演员',
|
||||
},
|
||||
appcenter: {
|
||||
others: '其他',
|
||||
},
|
||||
notFound: {
|
||||
title: '页面不存在 ⚠️',
|
||||
description: '您想要访问的页面不存在,请检查地址是否正确。',
|
||||
backButton: '返回',
|
||||
},
|
||||
torrent: {
|
||||
sortDefault: '默认',
|
||||
sortSite: '站点',
|
||||
sortSize: '大小',
|
||||
sortSeeder: '做种数',
|
||||
filterSite: '站点',
|
||||
filterSeason: '季集',
|
||||
filterFreeState: '促销状态',
|
||||
filterVideoCode: '视频编码',
|
||||
filterEdition: '质量',
|
||||
filterResolution: '分辨率',
|
||||
filterReleaseGroup: '制作组',
|
||||
clearFilters: '清除',
|
||||
selectAll: '全选',
|
||||
loadMore: '加载更多',
|
||||
noMatchingResults: '没有匹配的结果',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import NoDataFound from '@/components/NoDataFound.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NoDataFound
|
||||
error-code="404"
|
||||
error-title="页面不存在 ⚠️"
|
||||
error-description="您想要访问的页面不存在,请检查地址是否正确。"
|
||||
>
|
||||
<NoDataFound error-code="404" :error-title="t('notFound.title')" :error-description="t('notFound.description')">
|
||||
<template #button>
|
||||
<VBtn
|
||||
to="/"
|
||||
class="mt-10"
|
||||
>
|
||||
返回
|
||||
<VBtn to="/" class="mt-10">
|
||||
{{ t('notFound.backButton') }}
|
||||
</VBtn>
|
||||
</template>
|
||||
</NoDataFound>
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
import { NavMenu } from '@/@layouts/types'
|
||||
import { getNavMenus } from '@/router/i18n-menu'
|
||||
import { useUserStore } from '@/stores'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 从 Store 中获取superuser信息
|
||||
const superUser = useUserStore().superUser
|
||||
@@ -18,7 +22,7 @@ function categorizeApps() {
|
||||
const groupedMenus: Record<string, NavMenu[]> = {}
|
||||
|
||||
menus.forEach(menu => {
|
||||
const header = menu.header || '其他'
|
||||
const header = menu.header || t('appcenter.others')
|
||||
if (!groupedMenus[header]) {
|
||||
groupedMenus[header] = []
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import MediaCardListView from '@/views/discover/MediaCardListView.vue'
|
||||
import PersonCardListView from '@/views/discover/PersonCardListView.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
@@ -16,7 +20,7 @@ let title = route.query?.title?.toString()
|
||||
|
||||
// 类型
|
||||
const type = route.query?.type?.toString()
|
||||
if (type === 'person') title = '演员:' + title
|
||||
if (type === 'person') title = t('browse.actor') + ': ' + title
|
||||
|
||||
// 计算API路径
|
||||
function getApiPath(paths: string[] | string) {
|
||||
|
||||
@@ -7,6 +7,10 @@ import BangumiView from '@/views/discover/BangumiView.vue'
|
||||
import ExtraSourceView from '@/views/discover/ExtraSourceView.vue'
|
||||
import { DiscoverSource } from '@/api/types'
|
||||
import api from '@/api'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
const activeTab = ref('')
|
||||
|
||||
@@ -180,13 +184,13 @@ onActivated(async () => {
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-order-alphabetical-ascending" size="small" class="me-2" />
|
||||
设置标签顺序
|
||||
{{ t('discover.setTabOrder') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="orderConfigDialog = false" />
|
||||
</VCardItem>
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<p class="settings-hint">拖动对标签页进行排序</p>
|
||||
<p class="settings-hint">{{ t('discover.dragToReorder') }}</p>
|
||||
<draggable
|
||||
v-model="discoverTabs"
|
||||
handle=".cursor-move"
|
||||
@@ -210,7 +214,7 @@ onActivated(async () => {
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-content-save" />
|
||||
</template>
|
||||
保存
|
||||
{{ t('common.save') }}
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
@@ -3,6 +3,10 @@ import api from '@/api'
|
||||
import { DownloaderConf } from '@/api/types'
|
||||
import DownloadingListView from '@/views/reorganize/DownloadingListView.vue'
|
||||
import NoDataFound from '@/components/NoDataFound.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
const route = useRoute()
|
||||
const activeTab = ref(route.query.tab)
|
||||
@@ -54,7 +58,7 @@ onActivated(async () => {
|
||||
<NoDataFound
|
||||
v-else
|
||||
error-code="404"
|
||||
error-title="没有下载器"
|
||||
error-description="请先在设置中正确配置并启用下载器。"
|
||||
:error-title="t('downloading.noDownloader')"
|
||||
:error-description="t('downloading.configureDownloader')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -2,94 +2,98 @@
|
||||
import api from '@/api'
|
||||
import { RecommendSource } from '@/api/types'
|
||||
import MediaCardSlideView from '@/views/discover/MediaCardSlideView.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 当前选择的分类
|
||||
const currentCategory = ref('全部')
|
||||
const currentCategory = ref(t('recommend.all'))
|
||||
|
||||
const viewList = reactive<{ apipath: string; linkurl: string; title: string; type: string }[]>([
|
||||
{
|
||||
apipath: 'recommend/tmdb_trending',
|
||||
linkurl: '/browse/recommend/tmdb_trending?title=流行趋势',
|
||||
title: '流行趋势',
|
||||
type: '榜单',
|
||||
linkurl: '/browse/recommend/tmdb_trending?title=' + t('recommend.trendingNow'),
|
||||
title: t('recommend.trendingNow'),
|
||||
type: t('recommend.categoryRankings'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_showing',
|
||||
linkurl: '/browse/recommend/douban_showing?title=正在热映',
|
||||
title: '正在热映',
|
||||
type: '电影',
|
||||
linkurl: '/browse/recommend/douban_showing?title=' + t('recommend.nowShowing'),
|
||||
title: t('recommend.nowShowing'),
|
||||
type: t('recommend.categoryMovie'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/bangumi_calendar',
|
||||
linkurl: '/browse/recommend/bangumi_calendar?title=Bangumi每日放送',
|
||||
title: 'Bangumi每日放送',
|
||||
type: '动漫',
|
||||
linkurl: '/browse/recommend/bangumi_calendar?title=' + t('recommend.bangumiDaily'),
|
||||
title: t('recommend.bangumiDaily'),
|
||||
type: t('recommend.categoryAnime'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/tmdb_movies',
|
||||
linkurl: '/browse/recommend/tmdb_movies?title=TMDB热门电影',
|
||||
title: 'TMDB热门电影',
|
||||
type: '电影',
|
||||
linkurl: '/browse/recommend/tmdb_movies?title=' + t('recommend.tmdbHotMovies'),
|
||||
title: t('recommend.tmdbHotMovies'),
|
||||
type: t('recommend.categoryMovie'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/tmdb_tvs?with_original_language=zh|en|ja|ko',
|
||||
linkurl: '/browse/recommend/tmdb_tvs??with_original_language=zh|en|ja|ko&title=TMDB热门电视剧',
|
||||
title: 'TMDB热门电视剧',
|
||||
type: '电视剧',
|
||||
linkurl: '/browse/recommend/tmdb_tvs??with_original_language=zh|en|ja|ko&title=' + t('recommend.tmdbHotTVShows'),
|
||||
title: t('recommend.tmdbHotTVShows'),
|
||||
type: t('recommend.categoryTV'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_movie_hot',
|
||||
linkurl: '/browse/recommend/douban_movie_hot?title=豆瓣热门电影',
|
||||
title: '豆瓣热门电影',
|
||||
type: '电影',
|
||||
linkurl: '/browse/recommend/douban_movie_hot?title=' + t('recommend.doubanHotMovies'),
|
||||
title: t('recommend.doubanHotMovies'),
|
||||
type: t('recommend.categoryMovie'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_tv_hot',
|
||||
linkurl: '/browse/recommend/douban_tv_hot?title=豆瓣热门电视剧',
|
||||
title: '豆瓣热门电视剧',
|
||||
type: '电视剧',
|
||||
linkurl: '/browse/recommend/douban_tv_hot?title=' + t('recommend.doubanHotTVShows'),
|
||||
title: t('recommend.doubanHotTVShows'),
|
||||
type: t('recommend.categoryTV'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_tv_animation',
|
||||
linkurl: '/browse/recommend/douban_tv_animation?title=豆瓣热门动漫',
|
||||
title: '豆瓣热门动漫',
|
||||
type: '动漫',
|
||||
linkurl: '/browse/recommend/douban_tv_animation?title=' + t('recommend.doubanHotAnime'),
|
||||
title: t('recommend.doubanHotAnime'),
|
||||
type: t('recommend.categoryAnime'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_movies',
|
||||
linkurl: '/browse/recommend/douban_movies?title=豆瓣最新电影',
|
||||
title: '豆瓣最新电影',
|
||||
type: '电影',
|
||||
linkurl: '/browse/recommend/douban_movies?title=' + t('recommend.doubanNewMovies'),
|
||||
title: t('recommend.doubanNewMovies'),
|
||||
type: t('recommend.categoryMovie'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_tvs',
|
||||
linkurl: '/browse/recommend/douban_tvs?title=豆瓣最新电视剧',
|
||||
title: '豆瓣最新电视剧',
|
||||
type: '电视剧',
|
||||
linkurl: '/browse/recommend/douban_tvs?title=' + t('recommend.doubanNewTVShows'),
|
||||
title: t('recommend.doubanNewTVShows'),
|
||||
type: t('recommend.categoryTV'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_movie_top250',
|
||||
linkurl: '/browse/recommend/douban_movie_top250?title=电影TOP250',
|
||||
title: '豆瓣电影TOP250',
|
||||
type: '榜单',
|
||||
linkurl: '/browse/recommend/douban_movie_top250?title=' + t('recommend.doubanTop250'),
|
||||
title: t('recommend.doubanTop250'),
|
||||
type: t('recommend.categoryRankings'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_tv_weekly_chinese',
|
||||
linkurl: '/browse/recommend/douban_tv_weekly_chinese?title=豆瓣国产剧集榜',
|
||||
title: '豆瓣国产剧集榜',
|
||||
type: '榜单',
|
||||
linkurl: '/browse/recommend/douban_tv_weekly_chinese?title=' + t('recommend.doubanChineseTVRankings'),
|
||||
title: t('recommend.doubanChineseTVRankings'),
|
||||
type: t('recommend.categoryRankings'),
|
||||
},
|
||||
{
|
||||
apipath: 'recommend/douban_tv_weekly_global',
|
||||
linkurl: '/browse/recommend/douban_tv_weekly_global?title=豆瓣全球剧集榜',
|
||||
title: '豆瓣全球剧集榜',
|
||||
type: '榜单',
|
||||
linkurl: '/browse/recommend/douban_tv_weekly_global?title=' + t('recommend.doubanGlobalTVRankings'),
|
||||
title: t('recommend.doubanGlobalTVRankings'),
|
||||
type: t('recommend.categoryRankings'),
|
||||
},
|
||||
])
|
||||
|
||||
// 计算当前分类下显示的视图
|
||||
const filteredViews = computed(() => {
|
||||
if (currentCategory.value === '全部') {
|
||||
if (currentCategory.value === t('recommend.all')) {
|
||||
return viewList.filter(item => enableConfig.value[item.title])
|
||||
}
|
||||
return viewList.filter(item => enableConfig.value[item.title] && item.type === currentCategory.value)
|
||||
@@ -158,29 +162,29 @@ async function saveConfig() {
|
||||
// 标签图标映射
|
||||
const categoryItems: Record<string, string>[] = [
|
||||
{
|
||||
title: '全部',
|
||||
title: t('recommend.all'),
|
||||
icon: 'mdi-filmstrip-box-multiple',
|
||||
tab: '全部',
|
||||
tab: t('recommend.all'),
|
||||
},
|
||||
{
|
||||
title: '电影',
|
||||
title: t('recommend.categoryMovie'),
|
||||
icon: 'mdi-movie',
|
||||
tab: '电影',
|
||||
tab: t('recommend.categoryMovie'),
|
||||
},
|
||||
{
|
||||
title: '电视剧',
|
||||
title: t('recommend.categoryTV'),
|
||||
icon: 'mdi-television-classic',
|
||||
tab: '电视剧',
|
||||
tab: t('recommend.categoryTV'),
|
||||
},
|
||||
{
|
||||
title: '动漫',
|
||||
title: t('recommend.categoryAnime'),
|
||||
icon: 'mdi-animation',
|
||||
tab: '动漫',
|
||||
tab: t('recommend.categoryAnime'),
|
||||
},
|
||||
{
|
||||
title: '榜单',
|
||||
title: t('recommend.categoryRankings'),
|
||||
icon: 'mdi-trophy',
|
||||
tab: '榜单',
|
||||
tab: t('recommend.categoryRankings'),
|
||||
},
|
||||
]
|
||||
|
||||
@@ -221,8 +225,10 @@ onActivated(async () => {
|
||||
|
||||
<div v-if="filteredViews.length === 0" class="empty-category">
|
||||
<VIcon icon="mdi-alert-circle-outline" size="large" class="empty-icon" />
|
||||
<p class="empty-text">当前分类下没有可显示的内容</p>
|
||||
<VBtn color="primary" variant="tonal" size="small" @click="dialog = true"> 设置显示内容 </VBtn>
|
||||
<p class="empty-text">{{ t('recommend.noCategoryContent') }}</p>
|
||||
<VBtn color="primary" variant="tonal" size="small" @click="dialog = true">
|
||||
{{ t('recommend.configureContent') }}
|
||||
</VBtn>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -232,13 +238,13 @@ onActivated(async () => {
|
||||
<VCardItem class="settings-card-header">
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-tune" size="small" class="me-2" />
|
||||
自定义内容
|
||||
{{ t('recommend.customizeContent') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="dialog = false" />
|
||||
</VCardItem>
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<p class="settings-hint">选择您想在页面显示的内容</p>
|
||||
<p class="settings-hint">{{ t('recommend.selectContentToDisplay') }}</p>
|
||||
<div class="settings-grid">
|
||||
<div
|
||||
v-for="(item, index) in viewList"
|
||||
@@ -266,17 +272,17 @@ onActivated(async () => {
|
||||
<VDivider />
|
||||
<VCardActions class="pt-5">
|
||||
<VBtn variant="text" @click="Object.keys(enableConfig).forEach(key => (enableConfig[key] = true))">
|
||||
全选
|
||||
{{ t('recommend.selectAll') }}
|
||||
</VBtn>
|
||||
<VBtn variant="text" @click="Object.keys(enableConfig).forEach(key => (enableConfig[key] = false))">
|
||||
全不选
|
||||
{{ t('recommend.selectNone') }}
|
||||
</VBtn>
|
||||
<VSpacer />
|
||||
<VBtn @click="saveConfig" variant="elevated" color="primary" class="px-5">
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-content-save" />
|
||||
</template>
|
||||
保存
|
||||
{{ t('common.save') }}
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
|
||||
@@ -4,6 +4,10 @@ import api from '@/api'
|
||||
import type { Context } from '@/api/types'
|
||||
import TorrentCardListView from '@/views/torrent/TorrentCardListView.vue'
|
||||
import TorrentRowListView from '@/views/torrent/TorrentRowListView.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 路由参数
|
||||
const route = useRoute()
|
||||
@@ -51,14 +55,14 @@ const progressValue = ref(0)
|
||||
const progressEventSource = ref<EventSource>()
|
||||
|
||||
// 错误标题
|
||||
const errorTitle = ref('没有数据')
|
||||
const errorTitle = ref(t('resource.noData'))
|
||||
|
||||
// 错误描述
|
||||
const errorDescription = ref('未搜索到任何资源')
|
||||
const errorDescription = ref(t('resource.noResourceFound'))
|
||||
|
||||
// 使用SSE监听加载进度
|
||||
function startLoadingProgress() {
|
||||
progressText.value = '正在搜索,请稍候...'
|
||||
progressText.value = t('resource.searching')
|
||||
progressValue.value = 10 // 初始进度设为10%,确保进度条显示
|
||||
progressEventSource.value = new EventSource(`${import.meta.env.VITE_API_BASE_URL}system/progress/search`)
|
||||
progressEventSource.value.onmessage = event => {
|
||||
@@ -199,14 +203,20 @@ onUnmounted(() => {
|
||||
<!-- 精简标题栏 -->
|
||||
<VCard v-if="isRefreshed" class="search-header d-flex align-center mb-3">
|
||||
<div class="search-info-container d-flex align-center flex-wrap">
|
||||
<div class="search-title text-primary">资源搜索结果</div>
|
||||
<div class="search-title text-primary">{{ t('resource.searchResults') }}</div>
|
||||
<div class="search-tags d-flex flex-wrap">
|
||||
<VChip v-if="keyword" class="search-tag" color="primary" size="small" variant="flat">
|
||||
关键词: {{ keyword }}
|
||||
{{ t('resource.keyword') }}: {{ keyword }}
|
||||
</VChip>
|
||||
<VChip v-if="title" class="search-tag" color="primary" size="small" variant="flat">
|
||||
{{ t('resource.title') }}: {{ title }}
|
||||
</VChip>
|
||||
<VChip v-if="year" class="search-tag" color="primary" size="small" variant="flat">
|
||||
{{ t('resource.year') }}: {{ year }}
|
||||
</VChip>
|
||||
<VChip v-if="season" class="search-tag" color="primary" size="small" variant="flat">
|
||||
{{ t('resource.season') }}: {{ season }}
|
||||
</VChip>
|
||||
<VChip v-if="title" class="search-tag" color="primary" size="small" variant="flat"> 标题: {{ title }} </VChip>
|
||||
<VChip v-if="year" class="search-tag" color="primary" size="small" variant="flat"> 年份: {{ year }} </VChip>
|
||||
<VChip v-if="season" class="search-tag" color="primary" size="small" variant="flat"> 季: {{ season }} </VChip>
|
||||
</div>
|
||||
</div>
|
||||
<VSpacer />
|
||||
@@ -232,7 +242,7 @@ onUnmounted(() => {
|
||||
<div class="pulse-circle"></div>
|
||||
<div class="pulse-circle"></div>
|
||||
</div>
|
||||
<div class="view-changing-text">切换视图</div>
|
||||
<div class="view-changing-text">{{ t('resource.switchingView') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</VFadeTransition>
|
||||
@@ -257,7 +267,7 @@ onUnmounted(() => {
|
||||
<!-- 无数据显示 -->
|
||||
<div v-else-if="isRefreshed && !isViewChanging" class="d-flex flex-column align-center justify-center py-8">
|
||||
<NoDataFound :errorTitle="errorTitle" :errorDescription="errorDescription" />
|
||||
<VBtn class="mt-4" color="primary" prepend-icon="mdi-magnify" to="/"> 返回首页 </VBtn>
|
||||
<VBtn class="mt-4" color="primary" prepend-icon="mdi-magnify" to="/">{{ t('resource.backToHome') }}</VBtn>
|
||||
</div>
|
||||
|
||||
<!-- 初始加载状态 -->
|
||||
@@ -269,7 +279,7 @@ onUnmounted(() => {
|
||||
<div class="wave-dot"></div>
|
||||
<div class="wave-dot"></div>
|
||||
</div>
|
||||
<div class="initial-loading-text">搜索中</div>
|
||||
<div class="initial-loading-text">{{ t('resource.searching') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 滚动到顶部按钮 -->
|
||||
|
||||
@@ -3,9 +3,13 @@ import SubscribeListView from '@/views/subscribe/SubscribeListView.vue'
|
||||
import SubscribePopularView from '@/views/subscribe/SubscribePopularView.vue'
|
||||
import SubscribeShareView from '@/views/subscribe/SubscribeShareView.vue'
|
||||
import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { getSubscribeMovieTabs, getSubscribeTvTabs } from '@/router/i18n-menu'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const subType = route.meta.subType?.toString()
|
||||
@@ -69,12 +73,12 @@ const searchShares = () => {
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-filter-multiple-outline" class="mr-2" />
|
||||
筛选订阅
|
||||
{{ t('subscribe.filterSubscriptions') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="filterSubscribeDialog = false" />
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VTextField v-model="subscribeFilter" label="名称" clearable density="comfortable" />
|
||||
<VTextField v-model="subscribeFilter" :label="t('subscribe.name')" clearable density="comfortable" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VMenu>
|
||||
@@ -99,14 +103,14 @@ const searchShares = () => {
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-movie-search-outline" class="mr-2" />
|
||||
搜索订阅分享
|
||||
{{ t('subscribe.searchShares') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="searchShareDialog = false" />
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VTextField v-model="shareKeyword" label="关键词" clearable density="comfortable">
|
||||
<VTextField v-model="shareKeyword" :label="t('subscribe.keyword')" clearable density="comfortable">
|
||||
<template #append>
|
||||
<VBtn prepend-icon="mdi-magnify" color="primary" @click="searchShares">搜索</VBtn>
|
||||
<VBtn prepend-icon="mdi-magnify" color="primary" @click="searchShares">{{ t('common.search') }}</VBtn>
|
||||
</template>
|
||||
</VTextField>
|
||||
</VCardText>
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
import { cloneDeepWith } from 'lodash-es'
|
||||
import type { Context } from '@/api/types'
|
||||
import TorrentCard from '@/components/cards/TorrentCard.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
interface SearchTorrent extends Context {
|
||||
more?: Array<Context>
|
||||
@@ -34,21 +38,21 @@ const filterForm: Record<string, string[]> = reactive({
|
||||
// 排序选项
|
||||
const sortField = ref('default')
|
||||
const sortTitles: Record<string, string> = {
|
||||
default: '默认',
|
||||
site: '站点',
|
||||
size: '大小',
|
||||
seeder: '做种数',
|
||||
default: t('torrent.sortDefault'),
|
||||
site: t('torrent.sortSite'),
|
||||
size: t('torrent.sortSize'),
|
||||
seeder: t('torrent.sortSeeder'),
|
||||
}
|
||||
|
||||
// 过滤项映射(保持中文标题)
|
||||
// 过滤项映射
|
||||
const filterTitles: Record<string, string> = {
|
||||
site: '站点',
|
||||
season: '季集',
|
||||
freeState: '促销状态',
|
||||
videoCode: '视频编码',
|
||||
edition: '质量',
|
||||
resolution: '分辨率',
|
||||
releaseGroup: '制作组',
|
||||
site: t('torrent.filterSite'),
|
||||
season: t('torrent.filterSeason'),
|
||||
freeState: t('torrent.filterFreeState'),
|
||||
videoCode: t('torrent.filterVideoCode'),
|
||||
edition: t('torrent.filterEdition'),
|
||||
resolution: t('torrent.filterResolution'),
|
||||
releaseGroup: t('torrent.filterReleaseGroup'),
|
||||
}
|
||||
|
||||
// 统一存储过滤选项
|
||||
|
||||
Reference in New Issue
Block a user