mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-06-29 03:21:39 +08:00
更新国际化支持:在多个组件中引入 vue-i18n,优化文本翻译和结构
This commit is contained in:
@@ -387,6 +387,7 @@ export default {
|
||||
currentVersion: 'Current Version',
|
||||
viewChangelog: 'View Changelog',
|
||||
changelog: 'Changelog',
|
||||
dataDirectory: '/moviepilot',
|
||||
},
|
||||
system: {
|
||||
basicSettings: 'Basic Settings',
|
||||
@@ -439,6 +440,11 @@ export default {
|
||||
copyFailed: 'Copy failed: browser may not support or user blocked!',
|
||||
copyError: 'Copy failed!',
|
||||
reloading: 'Applying configuration...',
|
||||
qbittorrent: 'Qbittorrent',
|
||||
transmission: 'Transmission',
|
||||
emby: 'Emby',
|
||||
jellyfin: 'Jellyfin',
|
||||
plex: 'Plex',
|
||||
},
|
||||
site: {
|
||||
siteSync: 'Site Synchronization',
|
||||
@@ -517,6 +523,11 @@ export default {
|
||||
manualProcess: 'Manual Process',
|
||||
plugin: 'Plugin',
|
||||
other: 'Other',
|
||||
telegram: 'Telegram',
|
||||
slack: 'Slack',
|
||||
synologyChat: 'SynologyChat',
|
||||
voceChat: 'VoceChat',
|
||||
webPush: 'WebPush',
|
||||
},
|
||||
words: {
|
||||
customIdentifiers: 'Custom Identifiers',
|
||||
@@ -586,11 +597,16 @@ export default {
|
||||
downloadUser: 'Remote Search Auto Download User List',
|
||||
downloadUserHint:
|
||||
'Whether to automatically download when searching with Telegram, WeChat, etc., comma separated, set to all to represent all users auto-download',
|
||||
downloadUserPlaceholder: 'UserID1,UserID2',
|
||||
multipleNameSearch: 'Multiple Name Resource Search',
|
||||
multipleNameSearchHint:
|
||||
'Search site resources using multiple names (Chinese, English, etc.) and merge search results, will increase site access frequency',
|
||||
downloadSubtitle: 'Download Site Subtitles',
|
||||
downloadSubtitleHint: 'Check if site resources have separate subtitle files and download them automatically',
|
||||
mediaSource: 'Media Search Data Source',
|
||||
mediaSourceHint: 'Data sources and sorting used when searching for media information',
|
||||
filterRuleGroupHint: 'Filter results by selected filter rule groups when searching for media information',
|
||||
downloadLabelPlaceholder: 'MOVIEPILOT',
|
||||
},
|
||||
directory: {
|
||||
storage: 'Storage',
|
||||
@@ -620,24 +636,29 @@ export default {
|
||||
priorityRuleGroups: 'Priority Rule Groups',
|
||||
priorityRuleGroupsDesc: 'Preset priority rule groups for use in search and subscription.',
|
||||
downloadRules: 'Download Rules',
|
||||
downloadRulesDesc: 'Prioritize downloads when multiple resources match.',
|
||||
downloadRulesDesc: 'Choose the best option when multiple resources are matched.',
|
||||
resourcePriority: 'Resource Priority',
|
||||
sitePriority: 'Site Priority',
|
||||
siteUpload: 'Site Upload',
|
||||
resourceSeeder: 'Resource Seeders',
|
||||
emptyIdError: 'A rule has an empty ID, cannot save. Please modify!',
|
||||
emptyNameError: 'A rule has an empty name, cannot save. Please modify!',
|
||||
duplicateIdError: 'Duplicate rule IDs exist! Cannot save, please modify!',
|
||||
duplicateNameError: 'Duplicate rule names exist! Cannot save, please modify!',
|
||||
customRuleSaveSuccess: 'Custom rules saved successfully',
|
||||
customRuleSaveFailed: 'Failed to save custom rules!',
|
||||
emptyGroupNameError: 'A rule group has an empty name! Cannot save, please modify!',
|
||||
duplicateGroupNameError: 'Duplicate rule group names exist! Cannot save, please modify!',
|
||||
ruleGroupSaveSuccess: 'Priority rule groups saved successfully',
|
||||
ruleGroupSaveFailed: 'Failed to save priority rule groups!',
|
||||
customRuleCopySuccess: 'Custom rules copied to clipboard!',
|
||||
customRuleCopyFailed: 'Failed to copy custom rules: browser may not support or user blocked!',
|
||||
customRuleCopyError: 'Failed to copy custom rules!',
|
||||
ruleGroupCopySuccess: 'Priority rule groups copied to clipboard!',
|
||||
ruleGroupCopyFailed: 'Failed to copy priority rule groups: browser may not support or user blocked!',
|
||||
ruleGroupCopyError: 'Failed to copy priority rule groups!',
|
||||
currentPriorityRules: 'Current Download Priority Rules',
|
||||
currentPriorityRulesHint: 'Higher priority for items at the front, unselected items are not included in sorting',
|
||||
saveSuccess: 'Custom rules saved successfully',
|
||||
saveFailed: 'Failed to save custom rules!',
|
||||
groupSaveSuccess: 'Priority rule groups saved successfully',
|
||||
groupSaveFailed: 'Failed to save priority rule groups!',
|
||||
prioritySaveSuccess: 'Priority rules saved successfully',
|
||||
prioritySaveFailed: 'Failed to save priority rules!',
|
||||
emptyRuleId: 'Rules with empty IDs exist! Cannot save, please modify!',
|
||||
emptyRuleName: 'Rules with empty names exist! Cannot save, please modify!',
|
||||
duplicateRuleId: 'Duplicate rule IDs exist! Cannot save, please modify!',
|
||||
duplicateRuleName: 'Duplicate rule names exist! Cannot save, please modify!',
|
||||
emptyGroupName: 'Rule groups with empty names exist! Cannot save, please modify!',
|
||||
duplicateGroupName: 'Duplicate rule group names exist! Cannot save, please modify!',
|
||||
copySuccess: 'Copied to clipboard!',
|
||||
copyFailed: 'Copy failed: browser may not support or user blocked!',
|
||||
copyError: 'Copy failed!',
|
||||
importCustomRules: 'Import Custom Rules',
|
||||
importRuleGroups: 'Import Priority Rule Groups',
|
||||
importFailed: 'Failed to import rules! Cannot parse input data!',
|
||||
@@ -645,33 +666,27 @@ export default {
|
||||
duplicateValue: 'Duplicate values exist',
|
||||
importNoId: 'Import failed! Found rules without IDs, may belong to priority rule groups!',
|
||||
importHasId: 'Import failed! Found rules with IDs, may belong to custom rules!',
|
||||
torrentPriority: {
|
||||
torrent: 'Resource Priority',
|
||||
site: 'Site Priority',
|
||||
upload: 'Site Upload Amount',
|
||||
seeder: 'Resource Seeders',
|
||||
},
|
||||
},
|
||||
scheduler: {
|
||||
scheduledTasks: 'Scheduled Tasks',
|
||||
scheduledTasksDesc:
|
||||
'Includes system built-in services and plugin-provided services. Manual execution will not affect the normal schedule of tasks.',
|
||||
title: 'Scheduled Jobs',
|
||||
subtitle:
|
||||
"Includes built-in system services and plugin services. Manual execution will not affect the job's normal schedule.",
|
||||
provider: 'Provider',
|
||||
taskName: 'Task Name',
|
||||
taskStatus: 'Task Status',
|
||||
nextRunTime: 'Next Run Time',
|
||||
execute: 'Execute',
|
||||
noServices: 'No background services',
|
||||
submitSuccess: 'Task execution request submitted successfully!',
|
||||
status: {
|
||||
running: 'Running',
|
||||
stopped: 'Stopped',
|
||||
waiting: 'Waiting',
|
||||
},
|
||||
noService: 'No background services',
|
||||
running: 'Running',
|
||||
stopped: 'Stopped',
|
||||
waiting: 'Waiting',
|
||||
executeSuccess: 'Scheduled job execution request submitted successfully!',
|
||||
},
|
||||
subscribe: {
|
||||
basicSettings: 'Basic Settings',
|
||||
basicSettingsDesc: 'Set subscription mode, cycle and other basic settings',
|
||||
subscribeSites: 'Subscribe Sites',
|
||||
subscribeSitesDesc: 'Only selected sites will be used in subscriptions.',
|
||||
mode: 'Subscription Mode',
|
||||
modeHint: 'Auto: automatically crawl site homepage, Site RSS: subscribe via site RSS link',
|
||||
rssInterval: 'Site RSS Interval',
|
||||
@@ -684,12 +699,6 @@ export default {
|
||||
timedSearchHint: 'Search all sites every 24 hours to supplement resources that may be missed by subscription',
|
||||
checkLocalMedia: 'Check Local Media Library',
|
||||
checkLocalMediaHint: 'Check if resources exist on storage disk to avoid duplicate downloads',
|
||||
subscribeSites: 'Subscription Sites',
|
||||
subscribeSitesDesc: 'Only selected sites will be used in subscription.',
|
||||
saveSuccess: 'Subscription sites saved successfully',
|
||||
saveFailed: 'Failed to save subscription sites!',
|
||||
settingsSaveSuccess: 'Subscription basic settings saved successfully',
|
||||
settingsSaveFailed: 'Failed to save subscription basic settings!',
|
||||
modes: {
|
||||
auto: 'Auto',
|
||||
rss: 'Site RSS',
|
||||
@@ -703,6 +712,10 @@ export default {
|
||||
hour12: '12 hours',
|
||||
day1: '1 day',
|
||||
},
|
||||
saveSuccess: 'Subscription sites saved successfully',
|
||||
saveFailed: 'Failed to save subscription sites!',
|
||||
settingsSaveSuccess: 'Subscription basic settings saved successfully',
|
||||
settingsSaveFailed: 'Failed to save subscription basic settings!',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -326,47 +326,6 @@ export default {
|
||||
site: {
|
||||
noSites: '没有站点',
|
||||
sitesWillBeShownHere: '已添加并支持的站点将会在这里显示。',
|
||||
siteSync: '站点同步',
|
||||
siteSyncDesc: '从CookieCloud快速同步站点数据。',
|
||||
enableLocalCookieCloud: '启用本地CookieCloud服务器',
|
||||
enableLocalCookieCloudHint: '使用内建CookieCloud服务同步站点数据,服务地址为:http://localhost:3000/cookiecloud',
|
||||
serviceAddress: '服务地址',
|
||||
serviceAddressPlaceholder: 'https://movie-pilot.org/cookiecloud',
|
||||
serviceAddressHint: '远端CookieCloud服务地址,格式:https://movie-pilot.org/cookiecloud',
|
||||
userKey: '用户KEY',
|
||||
userKeyHint: 'CookieCloud浏览器插件生成的用户KEY',
|
||||
e2ePassword: '端对端加密密码',
|
||||
e2ePasswordHint: 'CookieCloud浏览器插件生成的端对端加密密码',
|
||||
autoSyncInterval: '自动同步间隔',
|
||||
autoSyncIntervalHint: '从CookieCloud服务器自动同步站点Cookie到MoviePilot的时间间隔',
|
||||
syncBlacklist: '同步域名黑名单',
|
||||
syncBlacklistPlaceholder: '多个域名,分割',
|
||||
syncBlacklistHint: 'CookieCloud同步域名黑名单,多个域名,分割',
|
||||
userAgent: '浏览器User-Agent',
|
||||
userAgentHint: 'CookieCloud插件所在的浏览器的User-Agent',
|
||||
siteDataRefresh: '站点数据刷新',
|
||||
siteDataRefreshInterval: '站点数据刷新间隔',
|
||||
siteDataRefreshIntervalHint: '刷新站点用户上传下载等数据的时间间隔',
|
||||
readSiteMessage: '阅读站点消息',
|
||||
readSiteMessageHint: '刷新数据时读取站点消息并发送通知',
|
||||
siteReset: '站点重置',
|
||||
confirmReset: '确认删除所有站点数据并重新同步。',
|
||||
confirmResetHint: '删除所有站点数据并重新从CookieCloud同步,操作请先清空涉及站点的相关设置。',
|
||||
resetSites: '重置站点数据',
|
||||
resettingSites: '正在重置...',
|
||||
syncInterval: {
|
||||
hourly: '每小时',
|
||||
every6Hours: '每6小时',
|
||||
every12Hours: '每12小时',
|
||||
daily: '每天',
|
||||
weekly: '每周',
|
||||
monthly: '每月',
|
||||
never: '永不',
|
||||
},
|
||||
saveSuccess: '保存站点设置成功',
|
||||
saveFailed: '站点设置保存失败!',
|
||||
resetSuccess: '站点重置成功,请等待CookieCloud同步完成!',
|
||||
resetFailed: '站点重置失败!',
|
||||
},
|
||||
message: {
|
||||
loadMore: '加载更多',
|
||||
@@ -426,6 +385,7 @@ export default {
|
||||
currentVersion: '当前版本',
|
||||
viewChangelog: '查看变更日志',
|
||||
changelog: '变更日志',
|
||||
dataDirectory: '/moviepilot',
|
||||
},
|
||||
system: {
|
||||
basicSettings: '基础设置',
|
||||
@@ -478,6 +438,54 @@ export default {
|
||||
copyFailed: '复制失败:可能是浏览器不支持或被用户阻止!',
|
||||
copyError: '复制失败!',
|
||||
reloading: '正在应用配置...',
|
||||
qbittorrent: 'Qbittorrent',
|
||||
transmission: 'Transmission',
|
||||
emby: 'Emby',
|
||||
jellyfin: 'Jellyfin',
|
||||
plex: 'Plex',
|
||||
},
|
||||
site: {
|
||||
siteSync: '站点同步',
|
||||
siteSyncDesc: '从CookieCloud快速同步站点数据。',
|
||||
enableLocalCookieCloud: '启用本地CookieCloud服务器',
|
||||
enableLocalCookieCloudHint: '使用内建CookieCloud服务同步站点数据,服务地址为:http://localhost:3000/cookiecloud',
|
||||
serviceAddress: '服务地址',
|
||||
serviceAddressPlaceholder: 'https://movie-pilot.org/cookiecloud',
|
||||
serviceAddressHint: '远端CookieCloud服务地址,格式:https://movie-pilot.org/cookiecloud',
|
||||
userKey: '用户KEY',
|
||||
userKeyHint: 'CookieCloud浏览器插件生成的用户KEY',
|
||||
e2ePassword: '端对端加密密码',
|
||||
e2ePasswordHint: 'CookieCloud浏览器插件生成的端对端加密密码',
|
||||
autoSyncInterval: '自动同步间隔',
|
||||
autoSyncIntervalHint: '从CookieCloud服务器自动同步站点Cookie到MoviePilot的时间间隔',
|
||||
syncBlacklist: '同步域名黑名单',
|
||||
syncBlacklistPlaceholder: '多个域名,分割',
|
||||
syncBlacklistHint: 'CookieCloud同步域名黑名单,多个域名,分割',
|
||||
userAgent: '浏览器User-Agent',
|
||||
userAgentHint: 'CookieCloud插件所在的浏览器的User-Agent',
|
||||
siteDataRefresh: '站点数据刷新',
|
||||
siteDataRefreshInterval: '站点数据刷新间隔',
|
||||
siteDataRefreshIntervalHint: '刷新站点用户上传下载等数据的时间间隔',
|
||||
readSiteMessage: '阅读站点消息',
|
||||
readSiteMessageHint: '刷新数据时读取站点消息并发送通知',
|
||||
siteReset: '站点重置',
|
||||
confirmReset: '确认删除所有站点数据并重新同步。',
|
||||
confirmResetHint: '删除所有站点数据并重新从CookieCloud同步,操作请先清空涉及站点的相关设置。',
|
||||
resetSites: '重置站点数据',
|
||||
resettingSites: '正在重置...',
|
||||
syncInterval: {
|
||||
hourly: '每小时',
|
||||
every6Hours: '每6小时',
|
||||
every12Hours: '每12小时',
|
||||
daily: '每天',
|
||||
weekly: '每周',
|
||||
monthly: '每月',
|
||||
never: '永不',
|
||||
},
|
||||
saveSuccess: '保存站点设置成功',
|
||||
saveFailed: '站点设置保存失败!',
|
||||
resetSuccess: '站点重置成功,请等待CookieCloud同步完成!',
|
||||
resetFailed: '站点重置失败!',
|
||||
},
|
||||
notification: {
|
||||
channels: '通知渠道',
|
||||
@@ -510,6 +518,11 @@ export default {
|
||||
manualProcess: '手动处理',
|
||||
plugin: '插件',
|
||||
other: '其它',
|
||||
telegram: 'Telegram',
|
||||
slack: 'Slack',
|
||||
synologyChat: 'SynologyChat',
|
||||
voceChat: 'VoceChat',
|
||||
webPush: 'WebPush',
|
||||
},
|
||||
words: {
|
||||
customIdentifiers: '自定义识别词',
|
||||
@@ -572,12 +585,16 @@ export default {
|
||||
tvCategory: '电视剧',
|
||||
animeCategory: '动漫',
|
||||
downloadUser: '远程搜索自动下载用户',
|
||||
downloadUserHint:
|
||||
'使用Telegram、微信等远程搜索时是否自动下载,多个用户使用英文逗号分隔,设置为all代表所有用户自动下载',
|
||||
multipleNameSearch: '多名称资源搜索',
|
||||
multipleNameSearchHint: '使用多个名称(中文、英文等)搜索站点资源并合并搜索结果,会增加站点访问频率',
|
||||
downloadSubtitle: '下载站点字幕',
|
||||
downloadSubtitleHint: '检查站点资源是否有单独的字幕文件并自动下载',
|
||||
mediaSource: '媒体搜索数据源',
|
||||
mediaSourceHint: '搜索媒体信息时使用的数据源以及排序',
|
||||
filterRuleGroupHint: '搜索媒体信息时按选定的过滤规则组对结果进行过滤',
|
||||
downloadUserPlaceholder: '用户ID1,用户ID2',
|
||||
downloadUserHint: '使用Telegram、微信等搜索时是否自动下载,使用逗号分割,设置为 all 代表所有用户自动择优下载',
|
||||
downloadLabelPlaceholder: 'MOVIEPILOT',
|
||||
},
|
||||
directory: {
|
||||
storage: '存储',
|
||||
@@ -607,23 +624,28 @@ export default {
|
||||
priorityRuleGroupsDesc: '预设优先级规则组,以便在搜索和订阅中使用。',
|
||||
downloadRules: '下载规则',
|
||||
downloadRulesDesc: '同时命中多个资源时择优下载。',
|
||||
resourcePriority: '资源优先级',
|
||||
sitePriority: '站点优先级',
|
||||
siteUpload: '站点上传量',
|
||||
resourceSeeder: '资源做种数',
|
||||
emptyIdError: '存在空ID的规则,无法保存,请修改!',
|
||||
emptyNameError: '存在空名字的规则,无法保存,请修改!',
|
||||
duplicateIdError: '存在重复规则ID!无法保存,请修改!',
|
||||
duplicateNameError: '存在重复规则名称!无法保存,请修改!',
|
||||
customRuleSaveSuccess: '自定义规则保存成功',
|
||||
customRuleSaveFailed: '自定义规则保存失败!',
|
||||
emptyGroupNameError: '存在空名字的规则组!无法保存,请修改!',
|
||||
duplicateGroupNameError: '存在重复规则组名称!无法保存,请修改!',
|
||||
ruleGroupSaveSuccess: '优先级规则组保存成功',
|
||||
ruleGroupSaveFailed: '优先级规则组保存失败!',
|
||||
customRuleCopySuccess: '自定义规则已复制到剪贴板!',
|
||||
customRuleCopyFailed: '自定义规则复制失败:可能是浏览器不支持或被用户阻止!',
|
||||
customRuleCopyError: '自定义规则复制失败!',
|
||||
ruleGroupCopySuccess: '优先级规则组已复制到剪贴板!',
|
||||
ruleGroupCopyFailed: '优先级规则组复制失败:可能是浏览器不支持或被用户阻止!',
|
||||
ruleGroupCopyError: '优先级规则组复制失败!',
|
||||
currentPriorityRules: '当前使用下载优先规则',
|
||||
currentPriorityRulesHint: '排在前面的优先级越高,未选择的项不纳入排序',
|
||||
saveSuccess: '自定义规则保存成功',
|
||||
saveFailed: '自定义规则保存失败!',
|
||||
groupSaveSuccess: '优先级规则组保存成功',
|
||||
groupSaveFailed: '优先级规则组保存失败!',
|
||||
prioritySaveSuccess: '优先规则保存成功',
|
||||
prioritySaveFailed: '优先规则保存失败!',
|
||||
emptyRuleId: '存在空ID的规则,无法保存,请修改!',
|
||||
emptyRuleName: '存在空名字的规则,无法保存,请修改!',
|
||||
duplicateRuleId: '存在重复规则ID!无法保存,请修改!',
|
||||
duplicateRuleName: '存在重复规则名称!无法保存,请修改!',
|
||||
emptyGroupName: '存在空名字的规则组!无法保存,请修改!',
|
||||
duplicateGroupName: '存在重复规则组名称!无法保存,请修改!',
|
||||
copySuccess: '已复制到剪贴板!',
|
||||
copyFailed: '复制失败:可能是浏览器不支持或被用户阻止!',
|
||||
copyError: '复制失败!',
|
||||
importCustomRules: '导入自定义规则',
|
||||
importRuleGroups: '导入优先级规则组',
|
||||
importFailed: '导入规则失败!无法解析输入的数据!',
|
||||
@@ -631,12 +653,6 @@ export default {
|
||||
duplicateValue: '存在重名值',
|
||||
importNoId: '导入失败!发现有规则不存在ID,可能属于优先级规则组!',
|
||||
importHasId: '导入失败!发现有规则存在相同ID,可能属于自定义规则!',
|
||||
torrentPriority: {
|
||||
torrent: '资源优先级',
|
||||
site: '站点优先级',
|
||||
upload: '站点上传量',
|
||||
seeder: '资源做种数',
|
||||
},
|
||||
},
|
||||
scheduler: {
|
||||
scheduledTasks: '定时作业',
|
||||
@@ -646,17 +662,17 @@ export default {
|
||||
taskStatus: '任务状态',
|
||||
nextRunTime: '下一次执行时间',
|
||||
execute: '执行',
|
||||
noServices: '没有后台服务',
|
||||
submitSuccess: '定时作业执行请求提交成功!',
|
||||
status: {
|
||||
running: '正在运行',
|
||||
stopped: '已停止',
|
||||
waiting: '等待',
|
||||
},
|
||||
noService: '没有后台服务',
|
||||
running: '正在运行',
|
||||
stopped: '已停止',
|
||||
waiting: '等待',
|
||||
executeSuccess: '定时作业执行请求提交成功!',
|
||||
},
|
||||
subscribe: {
|
||||
basicSettings: '基础设置',
|
||||
basicSettingsDesc: '设定订阅模式、周期等基础设置',
|
||||
subscribeSites: '订阅站点',
|
||||
subscribeSitesDesc: '只有选中的站点才会在订阅中使用。',
|
||||
mode: '订阅模式',
|
||||
modeHint: '自动:自动爬取站点首页,站点RSS:通过站点RSS链接订阅',
|
||||
rssInterval: '站点RSS周期',
|
||||
@@ -669,12 +685,6 @@ export default {
|
||||
timedSearchHint: '每隔24小时全站搜索,以补全订阅可能漏掉的资源',
|
||||
checkLocalMedia: '检查本地媒体库资源',
|
||||
checkLocalMediaHint: '检查存储盘是否存在资源,以避免重复下载',
|
||||
subscribeSites: '订阅站点',
|
||||
subscribeSitesDesc: '只有选中的站点才会在订阅中使用。',
|
||||
saveSuccess: '订阅站点保存成功',
|
||||
saveFailed: '订阅站点保存失败!',
|
||||
settingsSaveSuccess: '订阅基础设置保存成功',
|
||||
settingsSaveFailed: '订阅基础设置保存失败!',
|
||||
modes: {
|
||||
auto: '自动',
|
||||
rss: '站点RSS',
|
||||
@@ -688,6 +698,10 @@ export default {
|
||||
hour12: '12小时',
|
||||
day1: '1天',
|
||||
},
|
||||
saveSuccess: '订阅站点保存成功',
|
||||
saveFailed: '订阅站点保存失败!',
|
||||
settingsSaveSuccess: '订阅基础设置保存成功',
|
||||
settingsSaveFailed: '订阅基础设置保存失败!',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -140,7 +140,9 @@ onMounted(() => {
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.dataDir') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow undefined"><code>/moviepilot</code></span>
|
||||
<span class="flex-grow undefined"
|
||||
><code>{{ t('setting.about.dataDirectory') }}</code></span
|
||||
>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,9 @@ import { TransferDirectoryConf, StorageConf } from '@/api/types'
|
||||
import DirectoryCard from '@/components/cards/DirectoryCard.vue'
|
||||
import StorageCard from '@/components/cards/StorageCard.vue'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// 所有下载目录
|
||||
const directories = ref<TransferDirectoryConf[]>([])
|
||||
@@ -195,8 +198,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>存储</VCardTitle>
|
||||
<VCardSubtitle>设置本地或网盘存储。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.directory.storage') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.directory.storageDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
@@ -214,7 +217,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" class="me-2" @click="saveStorages"> 保存 </VBtn>
|
||||
<VBtn type="submit" class="me-2" @click="saveStorages"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -225,8 +228,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>目录</VCardTitle>
|
||||
<VCardSubtitle>设置媒体文件整理目录结构,按先后顺序依次匹配。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.directory.directory') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.directory.directoryDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
@@ -250,7 +253,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveDirectories"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveDirectories"> {{ t('common.save') }} </VBtn>
|
||||
<VBtn color="success" variant="tonal" @click="addDirectory">
|
||||
<VIcon icon="mdi-plus" />
|
||||
</VBtn>
|
||||
@@ -264,8 +267,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>整理 & 刮削</VCardTitle>
|
||||
<VCardSubtitle>设置重命名格式、刮削选项等。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.directory.organizeAndScrap') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.directory.organizeAndScrapDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VRow>
|
||||
@@ -273,16 +276,16 @@ onMounted(() => {
|
||||
<VSelect
|
||||
v-model="SystemSettings.Basic.SCRAP_SOURCE"
|
||||
:items="sourceItems"
|
||||
label="刮削数据源"
|
||||
hint="刮削时的元数据来源"
|
||||
:label="t('setting.directory.scrapSource')"
|
||||
:hint="t('setting.directory.scrapSourceHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<VTextarea
|
||||
v-model="SystemSettings.Basic.MOVIE_RENAME_FORMAT"
|
||||
label="电影重命名格式"
|
||||
hint="使用Jinja2语法,格式参考:https://jinja.palletsprojects.com/en/3.0.x/templates"
|
||||
:label="t('setting.directory.movieRenameFormat')"
|
||||
:hint="t('setting.directory.movieRenameFormatHint')"
|
||||
persistent-hint
|
||||
clearable
|
||||
active
|
||||
@@ -291,8 +294,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VTextarea
|
||||
v-model="SystemSettings.Basic.TV_RENAME_FORMAT"
|
||||
label="电视剧重命名格式"
|
||||
hint="使用Jinja2语法,格式参考:https://jinja.palletsprojects.com/en/3.0.x/templates"
|
||||
:label="t('setting.directory.tvRenameFormat')"
|
||||
:hint="t('setting.directory.tvRenameFormatHint')"
|
||||
persistent-hint
|
||||
clearable
|
||||
active
|
||||
@@ -303,7 +306,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveSystemSettings(SystemSettings.Basic)"> 保存</VBtn>
|
||||
<VBtn type="submit" @click="saveSystemSettings(SystemSettings.Basic)"> {{ t('common.save') }}</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -311,5 +314,5 @@ onMounted(() => {
|
||||
</VCol>
|
||||
</VRow>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" text="正在应用配置..." />
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="t('setting.system.reloading')" />
|
||||
</template>
|
||||
|
||||
@@ -216,19 +216,19 @@ onMounted(() => {
|
||||
<VListItemTitle>{{ t('setting.notification.wechat') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addNotification('telegram')">
|
||||
<VListItemTitle>Telegram</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.notification.telegram') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addNotification('slack')">
|
||||
<VListItemTitle>Slack</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.notification.slack') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addNotification('synologychat')">
|
||||
<VListItemTitle>SynologyChat</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.notification.synologyChat') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addNotification('vocechat')">
|
||||
<VListItemTitle>VoceChat</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.notification.voceChat') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addNotification('webpush')">
|
||||
<VListItemTitle>WebPush</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.notification.webPush') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
|
||||
@@ -8,6 +8,10 @@ import { CustomRule, FilterRuleGroup } from '@/api/types'
|
||||
import CustomerRuleCard from '@/components/cards/CustomRuleCard.vue'
|
||||
import FilterRuleGroupCard from '@/components/cards/FilterRuleGroupCard.vue'
|
||||
import ImportCodeDialog from '@/components/dialog/ImportCodeDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 自定义规则列表
|
||||
const customRules = ref<CustomRule[]>([])
|
||||
@@ -32,10 +36,10 @@ const $toast = useToast()
|
||||
|
||||
// 种子优先规则下拉框
|
||||
const TorrentPriorityItems = [
|
||||
{ title: '资源优先级', value: 'torrent' },
|
||||
{ title: '站点优先级', value: 'site' },
|
||||
{ title: '站点上传量', value: 'upload' },
|
||||
{ title: '资源做种数', value: 'seeder' },
|
||||
{ title: t('setting.rule.resourcePriority'), value: 'torrent' },
|
||||
{ title: t('setting.rule.sitePriority'), value: 'site' },
|
||||
{ title: t('setting.rule.siteUpload'), value: 'upload' },
|
||||
{ title: t('setting.rule.resourceSeeder'), value: 'seeder' },
|
||||
]
|
||||
|
||||
// 调用API查询自动分类配置
|
||||
@@ -51,12 +55,12 @@ async function loadMediaCategories() {
|
||||
async function saveCustomRules() {
|
||||
// 检查是否存在空id规则
|
||||
if (customRules.value.some(item => !item.id)) {
|
||||
$toast.error('存在空ID的规则,无法保存,请修改!')
|
||||
$toast.error(t('setting.rule.emptyIdError'))
|
||||
return
|
||||
}
|
||||
// 检查是否存在空的规则名称
|
||||
if (customRules.value.some(item => !item.name)) {
|
||||
$toast.error('存在空名字的规则,无法保存,请修改!')
|
||||
$toast.error(t('setting.rule.emptyNameError'))
|
||||
return
|
||||
}
|
||||
// 获取所有规则ID和名称
|
||||
@@ -64,18 +68,18 @@ async function saveCustomRules() {
|
||||
const names = customRules.value.map(item => item.name)
|
||||
// 检查是否存在重名的规则ID
|
||||
if (new Set(ids).size !== ids.length) {
|
||||
$toast.error('存在重复规则ID!无法保存,请修改!')
|
||||
$toast.error(t('setting.rule.duplicateIdError'))
|
||||
return
|
||||
}
|
||||
// 检查是否存在重名规则名称
|
||||
if (new Set(names).size !== names.length) {
|
||||
$toast.error('存在重复规则名称!无法保存,请修改!')
|
||||
$toast.error(t('setting.rule.duplicateNameError'))
|
||||
return
|
||||
}
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('system/setting/CustomFilterRules', customRules.value)
|
||||
if (result.success) $toast.success('自定义规则保存成功')
|
||||
else $toast.error('自定义规则保存失败!')
|
||||
if (result.success) $toast.success(t('setting.rule.customRuleSaveSuccess'))
|
||||
else $toast.error(t('setting.rule.customRuleSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -117,19 +121,19 @@ async function queryFilterRuleGroups() {
|
||||
async function saveFilterRuleGroups() {
|
||||
// 检查是否存在空的规则组名称
|
||||
if (filterRuleGroups.value.some(item => !item.name)) {
|
||||
$toast.error('存在空名字的规则组!无法保存,请修改!')
|
||||
$toast.error(t('setting.rule.emptyGroupNameError'))
|
||||
return
|
||||
}
|
||||
// 检查是否存在重名规则组
|
||||
const names = filterRuleGroups.value.map(item => item.name)
|
||||
if (new Set(names).size !== names.length) {
|
||||
$toast.error('存在重复规则组名称!无法保存,请修改!')
|
||||
$toast.error(t('setting.rule.duplicateGroupNameError'))
|
||||
return
|
||||
}
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('system/setting/UserFilterRuleGroups', filterRuleGroups.value)
|
||||
if (result.success) $toast.success('优先级规则组保存成功')
|
||||
else $toast.error('优先级规则组保存失败!')
|
||||
if (result.success) $toast.success(t('setting.rule.ruleGroupSaveSuccess'))
|
||||
else $toast.error(t('setting.rule.ruleGroupSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -157,10 +161,14 @@ async function shareRules(rules: CustomRule[] | FilterRuleGroup[], type: string)
|
||||
try {
|
||||
let success
|
||||
success = copyToClipboard(value)
|
||||
if (await success) $toast.success(`${type === 'custom' ? '自定义规则' : '优先级规则组'}已复制到剪贴板!`)
|
||||
else $toast.error(`${type === 'custom' ? '自定义规则' : '优先级规则组'}复制失败:可能是浏览器不支持或被用户阻止!`)
|
||||
if (await success)
|
||||
$toast.success(
|
||||
type === 'custom' ? t('setting.rule.customRuleCopySuccess') : t('setting.rule.ruleGroupCopySuccess'),
|
||||
)
|
||||
else
|
||||
$toast.error(type === 'custom' ? t('setting.rule.customRuleCopyFailed') : t('setting.rule.ruleGroupCopyFailed'))
|
||||
} catch (e) {
|
||||
$toast.error(`${type === 'custom' ? '自定义规则' : '优先级规则组'}复制失败!`)
|
||||
$toast.error(type === 'custom' ? t('setting.rule.customRuleCopyError') : t('setting.rule.ruleGroupCopyError'))
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
@@ -178,7 +186,7 @@ function saveCodeString(type: string, codeString: any) {
|
||||
try {
|
||||
parsedCode = JSON.parse(codeString.value)
|
||||
} catch (e) {
|
||||
$toast.error('导入规则失败!无法解析输入的数据!')
|
||||
$toast.error(t('setting.rule.importFailed'))
|
||||
console.error(e)
|
||||
return
|
||||
}
|
||||
@@ -194,10 +202,10 @@ function saveCodeString(type: string, codeString: any) {
|
||||
const newFilterRuleGroups = extractFilterRuleGroups(parsedCode) || []
|
||||
filterRuleGroups.value = [...filterRuleGroups.value, ...newFilterRuleGroups]
|
||||
} else {
|
||||
$toast.error('导入规则失败!未知的数据类型!')
|
||||
$toast.error(t('setting.rule.importUnknownType'))
|
||||
}
|
||||
} catch (e) {
|
||||
$toast.error('导入规则失败!')
|
||||
$toast.error(t('setting.rule.importFailed'))
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
@@ -272,8 +280,8 @@ function isValidValue(value: any, type: string): boolean {
|
||||
|
||||
function validateCustomRule(hasName: boolean, hasId: boolean, noDuplicates: boolean): boolean {
|
||||
if (!hasName || !hasId || !noDuplicates) {
|
||||
if (!noDuplicates) $toast.warning(`存在重名值`)
|
||||
if (!hasId) $toast.error(`导入失败!发现有规则不存在ID,可能属于优先级规则组!`)
|
||||
if (!noDuplicates) $toast.warning(t('setting.rule.duplicateValue'))
|
||||
if (!hasId) $toast.error(t('setting.rule.importNoId'))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -281,8 +289,8 @@ function validateCustomRule(hasName: boolean, hasId: boolean, noDuplicates: bool
|
||||
|
||||
function validateGroupRule(hasName: boolean, hasId: boolean, noDuplicates: boolean): boolean {
|
||||
if (!hasName || hasId || !noDuplicates) {
|
||||
if (!noDuplicates) $toast.warning(`存在重名值`)
|
||||
if (hasId) $toast.error(`导入失败!发现有规则存在相同ID,可能属于自定义规则!`)
|
||||
if (!noDuplicates) $toast.warning(t('setting.rule.duplicateValue'))
|
||||
if (hasId) $toast.error(t('setting.rule.importHasId'))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -367,8 +375,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>自定义规则</VCardTitle>
|
||||
<VCardSubtitle>自定义优先级规则项</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.rule.customRules') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.rule.customRulesDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
@@ -391,7 +399,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" class="me-2" @click="saveCustomRules"> 保存 </VBtn>
|
||||
<VBtn type="submit" class="me-2" @click="saveCustomRules"> {{ t('common.save') }} </VBtn>
|
||||
<VBtnGroup density="comfortable">
|
||||
<VBtn color="success" variant="tonal" @click="addCustomRule">
|
||||
<VIcon icon="mdi-plus" />
|
||||
@@ -416,8 +424,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>优先级规则组</VCardTitle>
|
||||
<VCardSubtitle>预设优先级规则组,以便在搜索和订阅中使用。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.rule.priorityRuleGroups') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.rule.priorityRuleGroupsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
@@ -442,7 +450,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" class="me-2" @click="saveFilterRuleGroups"> 保存 </VBtn>
|
||||
<VBtn type="submit" class="me-2" @click="saveFilterRuleGroups"> {{ t('common.save') }} </VBtn>
|
||||
<VBtnGroup density="comfortable">
|
||||
<VBtn color="success" variant="tonal" @click="addFilterRuleGroup">
|
||||
<VIcon icon="mdi-plus" />
|
||||
@@ -466,7 +474,7 @@ onMounted(() => {
|
||||
<ImportCodeDialog
|
||||
v-if="importCodeDialog"
|
||||
v-model="importCodeDialog"
|
||||
:title="`导入${importCodeType === 'custom' ? '自定义规则' : '优先级规则组'}`"
|
||||
:title="importCodeType === 'custom' ? t('setting.rule.importCustomRules') : t('setting.rule.importRuleGroups')"
|
||||
:dataType="importCodeType"
|
||||
@close="importCodeDialog = false"
|
||||
@save="saveCodeString"
|
||||
@@ -475,8 +483,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>下载规则</VCardTitle>
|
||||
<VCardSubtitle>同时命中多个资源时择优下载。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.rule.downloadRules') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.rule.downloadRulesDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VForm>
|
||||
@@ -488,8 +496,8 @@ onMounted(() => {
|
||||
multiple
|
||||
clearable
|
||||
chips
|
||||
label="当前使用下载优先规则"
|
||||
hint="排在前面的优先级越高,未选择的项不纳入排序"
|
||||
:label="t('setting.rule.currentPriorityRules')"
|
||||
:hint="t('setting.rule.currentPriorityRulesHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -499,7 +507,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveTorrentPriority"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveTorrentPriority"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import api from '@/api'
|
||||
import type { ScheduleInfo } from '@/api/types'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
@@ -26,11 +30,11 @@ async function loadSchedulerList() {
|
||||
// 任务状态颜色
|
||||
function getSchedulerColor(status: string) {
|
||||
switch (status) {
|
||||
case '正在运行':
|
||||
case t('setting.scheduler.running'):
|
||||
return 'success'
|
||||
case '已停止':
|
||||
case t('setting.scheduler.stopped'):
|
||||
return 'error'
|
||||
case '等待':
|
||||
case t('setting.scheduler.waiting'):
|
||||
return ''
|
||||
default:
|
||||
return ''
|
||||
@@ -46,7 +50,7 @@ function runCommand(id: string) {
|
||||
jobid: id,
|
||||
},
|
||||
})
|
||||
$toast.success('定时作业执行请求提交成功!')
|
||||
$toast.success(t('setting.scheduler.executeSuccess'))
|
||||
// 1秒后刷新数据
|
||||
setTimeout(() => {
|
||||
loadSchedulerList()
|
||||
@@ -77,16 +81,16 @@ onUnmounted(() => {
|
||||
<template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>定时作业</VCardTitle>
|
||||
<VCardSubtitle>包含系统内置服务以及插件提供的服务,手动执行不会影响作业正常的时间表。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.scheduler.title') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.scheduler.subtitle') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VTable class="text-no-wrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">提供者</th>
|
||||
<th scope="col">任务名称</th>
|
||||
<th scope="col">任务状态</th>
|
||||
<th scope="col">下一次执行时间</th>
|
||||
<th scope="col">{{ t('setting.scheduler.provider') }}</th>
|
||||
<th scope="col">{{ t('setting.scheduler.taskName') }}</th>
|
||||
<th scope="col">{{ t('setting.scheduler.taskStatus') }}</th>
|
||||
<th scope="col">{{ t('setting.scheduler.nextRunTime') }}</th>
|
||||
<th scope="col" />
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -107,16 +111,20 @@ onUnmounted(() => {
|
||||
{{ scheduler.next_run }}
|
||||
</td>
|
||||
<td>
|
||||
<VBtn size="small" :disabled="scheduler.status === '正在运行'" @click="runCommand(scheduler.id)">
|
||||
<VBtn
|
||||
size="small"
|
||||
:disabled="scheduler.status === t('setting.scheduler.running')"
|
||||
@click="runCommand(scheduler.id)"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon>mdi-play</VIcon>
|
||||
</template>
|
||||
执行
|
||||
{{ t('setting.scheduler.execute') }}
|
||||
</VBtn>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="schedulerList.length === 0">
|
||||
<td colspan="4" class="text-center">没有后台服务</td>
|
||||
<td colspan="4" class="text-center">{{ t('setting.scheduler.noService') }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</VTable>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import api from '@/api'
|
||||
import type { FilterRuleGroup, Site } from '@/api/types'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
@@ -172,6 +173,8 @@ async function loadSystemSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
querySites()
|
||||
queryFilterRuleGroups()
|
||||
@@ -186,8 +189,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>基础设置</VCardTitle>
|
||||
<VCardSubtitle>设定数据源、规则组等基础信息。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.search.basicSettings') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.search.basicSettingsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VRow>
|
||||
@@ -198,8 +201,8 @@ onMounted(() => {
|
||||
clearable
|
||||
chips
|
||||
:items="mediaSourcesDict"
|
||||
label="媒体搜索数据源"
|
||||
hint="搜索媒体信息时使用的数据源以及排序"
|
||||
:label="t('setting.search.mediaSource')"
|
||||
:hint="t('setting.search.mediaSourceHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -210,8 +213,8 @@ onMounted(() => {
|
||||
clearable
|
||||
chips
|
||||
:items="filterRuleGroupOptions"
|
||||
label="优先级规则组"
|
||||
hint="搜索媒体信息时按选定的过滤规则组对结果进行过滤"
|
||||
:label="t('setting.search.filterRuleGroup')"
|
||||
:hint="t('setting.search.filterRuleGroupHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -220,34 +223,34 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="SystemSettings.Basic.TORRENT_TAG"
|
||||
label="下载任务标签"
|
||||
:label="t('setting.search.downloadLabel')"
|
||||
placeholder="MOVIEPILOT"
|
||||
hint="MoviePilot添加的下载任务标签"
|
||||
:hint="t('setting.search.downloadLabelHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VCombobox
|
||||
v-model="SystemSettings.Basic.AUTO_DOWNLOAD_USER"
|
||||
label="远程搜索自动下载用户名单"
|
||||
placeholder="用户ID1,用户ID2"
|
||||
hint="使用Telegram、微信等搜索时是否自动下载,使用逗号分割,设置为 all 代表所有用户自动择优下载"
|
||||
:label="t('setting.search.downloadUser')"
|
||||
:placeholder="t('setting.search.downloadUserPlaceholder')"
|
||||
:hint="t('setting.search.downloadUserHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VSwitch
|
||||
v-model="SystemSettings.Basic.SEARCH_MULTIPLE_NAME"
|
||||
label="多名称资源搜索"
|
||||
hint="使用中英文等多个名称搜索站点资源并合并搜索结果,将会增加站点访问频率"
|
||||
:label="t('setting.search.multipleNameSearch')"
|
||||
:hint="t('setting.search.multipleNameSearchHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VSwitch
|
||||
v-model="SystemSettings.Basic.DOWNLOAD_SUBTITLE"
|
||||
label="下载站点字幕"
|
||||
hint="检查站点资源是否有独立的字幕文件,有则自动下载"
|
||||
:label="t('setting.search.downloadSubtitle')"
|
||||
:hint="t('setting.search.downloadSubtitleHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -256,7 +259,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveSearchSetting"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveSearchSetting"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -267,8 +270,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>搜索站点</VCardTitle>
|
||||
<VCardSubtitle> 只有选中的站点才会在搜索中使用。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.search.downloadSite') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.search.downloadSiteDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VChipGroup v-model="selectedSites" column multiple>
|
||||
@@ -287,7 +290,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveSelectedSites"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveSelectedSites"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useToast } from 'vue-toast-notification'
|
||||
import api from '@/api'
|
||||
import type { FilterRuleGroup, Site } from '@/api/types'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
@@ -24,8 +25,8 @@ const selectedBestVersionRuleGroup = ref([])
|
||||
|
||||
// 订阅模式选择项
|
||||
const subscribeModeItems = [
|
||||
{ title: '自动', value: 'spider' },
|
||||
{ title: '站点RSS', value: 'rss' },
|
||||
{ title: t('setting.subscribe.modes.auto'), value: 'spider' },
|
||||
{ title: t('setting.subscribe.modes.rss'), value: 'rss' },
|
||||
]
|
||||
|
||||
// 所有规则组列表
|
||||
@@ -41,13 +42,13 @@ const filterRuleGroupOptions = computed(() => {
|
||||
|
||||
// RSS运行周期选择项
|
||||
const rssIntervalItems = [
|
||||
{ title: '5分钟', value: 5 },
|
||||
{ title: '10分钟', value: 10 },
|
||||
{ title: '20分钟', value: 20 },
|
||||
{ title: '半小时', value: 30 },
|
||||
{ title: '1小时', value: 60 },
|
||||
{ title: '12小时', value: 720 },
|
||||
{ title: '1天', value: 1440 },
|
||||
{ title: t('setting.subscribe.intervals.min5'), value: 5 },
|
||||
{ title: t('setting.subscribe.intervals.min10'), value: 10 },
|
||||
{ title: t('setting.subscribe.intervals.min20'), value: 20 },
|
||||
{ title: t('setting.subscribe.intervals.min30'), value: 30 },
|
||||
{ title: t('setting.subscribe.intervals.hour1'), value: 60 },
|
||||
{ title: t('setting.subscribe.intervals.hour12'), value: 720 },
|
||||
{ title: t('setting.subscribe.intervals.day1'), value: 1440 },
|
||||
]
|
||||
|
||||
// 系统设置项
|
||||
@@ -99,8 +100,8 @@ async function saveSelectedRssSites() {
|
||||
try {
|
||||
const result1: { [key: string]: any } = await api.post('system/setting/RssSites', selectedRssSites.value)
|
||||
|
||||
if (result1.success) $toast.success('订阅站点保存成功')
|
||||
else $toast.error('订阅站点保存失败!')
|
||||
if (result1.success) $toast.success(t('setting.subscribe.saveSuccess'))
|
||||
else $toast.error(t('setting.subscribe.saveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -154,8 +155,8 @@ async function reloadSystem() {
|
||||
progressDialog.value = true
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.get('system/reload')
|
||||
if (result.success) $toast.success('系统配置已生效')
|
||||
else $toast.error('重载系统失败!')
|
||||
if (result.success) $toast.success(t('setting.system.reloadSuccess'))
|
||||
else $toast.error(t('setting.system.reloadFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -178,14 +179,16 @@ async function saveSubscribeSetting() {
|
||||
const result3 = await saveSystemSetting(SystemSettings.value.Basic)
|
||||
|
||||
if (result1.success && result2.success && result3) {
|
||||
$toast.success('订阅基础设置保存成功')
|
||||
$toast.success(t('setting.subscribe.settingsSaveSuccess'))
|
||||
await reloadSystem()
|
||||
} else $toast.error('订阅基础设置保存失败!')
|
||||
} else $toast.error(t('setting.subscribe.settingsSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
querySites()
|
||||
queryFilterRuleGroups()
|
||||
@@ -200,8 +203,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>基础设置</VCardTitle>
|
||||
<VCardSubtitle>设定订阅模式、周期等基础设置</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.subscribe.basicSettings') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.subscribe.basicSettingsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VForm>
|
||||
@@ -210,8 +213,8 @@ onMounted(() => {
|
||||
<VSelect
|
||||
v-model="SystemSettings.Basic.SUBSCRIBE_MODE"
|
||||
:items="subscribeModeItems"
|
||||
label="订阅模式"
|
||||
hint="自动:自动爬取站点首页,站点RSS:通过站点RSS链接订阅"
|
||||
:label="t('setting.subscribe.mode')"
|
||||
:hint="t('setting.subscribe.modeHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -219,8 +222,8 @@ onMounted(() => {
|
||||
<VSelect
|
||||
v-model="SystemSettings.Basic.SUBSCRIBE_RSS_INTERVAL"
|
||||
:items="rssIntervalItems"
|
||||
label="站点RSS周期"
|
||||
hint="设置站点RSS运行周期,在订阅模式为`站点RSS`时生效"
|
||||
:label="t('setting.subscribe.rssInterval')"
|
||||
:hint="t('setting.subscribe.rssIntervalHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -231,8 +234,8 @@ onMounted(() => {
|
||||
chips
|
||||
multiple
|
||||
clearable
|
||||
label="订阅优先级规则组"
|
||||
hint="按选定的过滤规则组对订阅进行过滤"
|
||||
:label="t('setting.subscribe.filterRuleGroup')"
|
||||
:hint="t('setting.subscribe.filterRuleGroupHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -243,8 +246,8 @@ onMounted(() => {
|
||||
chips
|
||||
multiple
|
||||
clearable
|
||||
label="洗版优先级规则组"
|
||||
hint="按选定的过滤规则组对洗版订阅进行过滤"
|
||||
:label="t('setting.subscribe.bestVersionRuleGroup')"
|
||||
:hint="t('setting.subscribe.bestVersionRuleGroupHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -253,16 +256,16 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VSwitch
|
||||
v-model="SystemSettings.Basic.SUBSCRIBE_SEARCH"
|
||||
label="订阅定时搜索"
|
||||
hint="每隔24小时全站搜索,以补全订阅可能漏掉的资源"
|
||||
:label="t('setting.subscribe.timedSearch')"
|
||||
:hint="t('setting.subscribe.timedSearchHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VSwitch
|
||||
v-model="SystemSettings.Basic.LOCAL_EXISTS_SEARCH"
|
||||
label="检查本地媒体库资源"
|
||||
hint="检查存储盘是否存在资源,以避免重复下载"
|
||||
:label="t('setting.subscribe.checkLocalMedia')"
|
||||
:hint="t('setting.subscribe.checkLocalMediaHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -272,7 +275,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveSubscribeSetting"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveSubscribeSetting"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -283,8 +286,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>订阅站点</VCardTitle>
|
||||
<VCardSubtitle>只有选中的站点才会在订阅中使用。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.subscribe.subscribeSites') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.subscribe.subscribeSitesDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VChipGroup v-model="selectedRssSites" column multiple>
|
||||
@@ -303,7 +306,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveSelectedRssSites"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveSelectedRssSites"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -311,5 +314,5 @@ onMounted(() => {
|
||||
</VCol>
|
||||
</VRow>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" text="正在应用配置..." />
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="t('setting.system.reloading')" />
|
||||
</template>
|
||||
|
||||
@@ -532,10 +532,10 @@ onDeactivated(() => {
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<VListItem @click="addDownloader('qbittorrent')">
|
||||
<VListItemTitle>Qbittorrent</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.system.qbittorrent') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addDownloader('transmission')">
|
||||
<VListItemTitle>Transmission</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.system.transmission') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
@@ -580,13 +580,13 @@ onDeactivated(() => {
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<VListItem @click="addMediaServer('emby')">
|
||||
<VListItemTitle>Emby</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.system.emby') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addMediaServer('jellyfin')">
|
||||
<VListItemTitle>Jellyfin</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.system.jellyfin') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addMediaServer('plex')">
|
||||
<VListItemTitle>Plex</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.system.plex') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addMediaServer('trimemedia')">
|
||||
<VListItemTitle>{{ t('setting.system.trimeMedia') }}</VListItemTitle>
|
||||
|
||||
Reference in New Issue
Block a user