mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-28 03:39:46 +08:00
更新国际化支持:在多个组件中引入 vue-i18n
This commit is contained in:
@@ -78,12 +78,12 @@ onMounted(() => {
|
||||
<SearchBar />
|
||||
<!-- 👉 Spacer -->
|
||||
<VSpacer />
|
||||
<!-- 👉 Theme & Language -->
|
||||
<NavbarActions />
|
||||
<!-- 👉 Shortcuts -->
|
||||
<ShortcutBar v-if="superUser" />
|
||||
<!-- 👉 Notification -->
|
||||
<UserNofification />
|
||||
<!-- 👉 Theme & Language -->
|
||||
<NavbarActions />
|
||||
<!-- 👉 UserProfile -->
|
||||
<UserProfile />
|
||||
</div>
|
||||
|
||||
@@ -36,10 +36,9 @@ const themes: ThemeSwitcherTheme[] = [
|
||||
|
||||
<template>
|
||||
<div class="d-flex align-center">
|
||||
<!-- 语言切换 -->
|
||||
<LocaleSwitcher class="me-2" />
|
||||
|
||||
<!-- 主题切换 -->
|
||||
<ThemeSwitcher :themes="themes" />
|
||||
<!-- 语言切换 -->
|
||||
<LocaleSwitcher class="me-2" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -176,8 +176,7 @@ onMounted(() => {
|
||||
<div v-for="(item, index) in shortcuts" :key="index">
|
||||
<VCard
|
||||
flat
|
||||
variant="tonal"
|
||||
class="pa-2 d-flex align-center rounded-lg cursor-pointer transition-transform duration-300 hover:-translate-y-1 border"
|
||||
class="pa-2 d-flex align-center cursor-pointer transition-transform duration-300 hover:-translate-y-1 border h-full"
|
||||
hover
|
||||
@click="openDialog(item.dialogRef)"
|
||||
>
|
||||
|
||||
@@ -244,6 +244,39 @@ export default {
|
||||
recognitionWords: 'Recognition Words',
|
||||
cancelShare: 'Cancel Share',
|
||||
usageCount: 'Used {count} times',
|
||||
basicSettings: 'Basic Settings',
|
||||
basicSettingsDesc: 'Set subscription mode, cycle and other basic settings',
|
||||
mode: 'Subscription Mode',
|
||||
modeHint: 'Auto: automatically crawl site homepage, Site RSS: subscribe via site RSS link',
|
||||
rssInterval: 'Site RSS Interval',
|
||||
rssIntervalHint: 'Set the site RSS running cycle, effective when subscription mode is `Site RSS`',
|
||||
filterRuleGroup: 'Subscription Priority Rule Group',
|
||||
filterRuleGroupHint: 'Filter subscriptions based on selected filter rule groups',
|
||||
bestVersionRuleGroup: 'Version Upgrade Priority Rule Group',
|
||||
bestVersionRuleGroupHint: 'Filter version upgrade subscriptions based on selected filter rule groups',
|
||||
timedSearch: 'Subscription Scheduled Search',
|
||||
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',
|
||||
},
|
||||
intervals: {
|
||||
min5: '5 minutes',
|
||||
min10: '10 minutes',
|
||||
min20: '20 minutes',
|
||||
min30: '30 minutes',
|
||||
hour1: '1 hour',
|
||||
hour12: '12 hours',
|
||||
day1: '1 day',
|
||||
},
|
||||
},
|
||||
recommend: {
|
||||
all: 'All',
|
||||
@@ -328,6 +361,49 @@ export default {
|
||||
site: {
|
||||
noSites: 'No Sites',
|
||||
sitesWillBeShownHere: 'Added and supported sites will be displayed here.',
|
||||
siteSync: 'Site Synchronization',
|
||||
siteSyncDesc: 'Quickly sync site data from CookieCloud.',
|
||||
enableLocalCookieCloud: 'Enable Local CookieCloud Server',
|
||||
enableLocalCookieCloudHint:
|
||||
'Use built-in CookieCloud service to sync site data, service address: http://localhost:3000/cookiecloud',
|
||||
serviceAddress: 'Service Address',
|
||||
serviceAddressPlaceholder: 'https://movie-pilot.org/cookiecloud',
|
||||
serviceAddressHint: 'Remote CookieCloud service address, format: https://movie-pilot.org/cookiecloud',
|
||||
userKey: 'User KEY',
|
||||
userKeyHint: 'User KEY generated by CookieCloud browser plugin',
|
||||
e2ePassword: 'End-to-End Encryption Password',
|
||||
e2ePasswordHint: 'End-to-end encryption password generated by CookieCloud browser plugin',
|
||||
autoSyncInterval: 'Auto Sync Interval',
|
||||
autoSyncIntervalHint: 'Time interval for automatically syncing site cookies from CookieCloud server to MoviePilot',
|
||||
syncBlacklist: 'Sync Domain Blacklist',
|
||||
syncBlacklistPlaceholder: 'Multiple domains, separated by commas',
|
||||
syncBlacklistHint: 'CookieCloud sync domain blacklist, multiple domains separated by commas',
|
||||
userAgent: 'Browser User-Agent',
|
||||
userAgentHint: 'User-Agent of the browser with CookieCloud plugin',
|
||||
siteDataRefresh: 'Site Data Refresh',
|
||||
siteDataRefreshInterval: 'Site Data Refresh Interval',
|
||||
siteDataRefreshIntervalHint: 'Time interval for refreshing site user upload/download data',
|
||||
readSiteMessage: 'Read Site Messages',
|
||||
readSiteMessageHint: 'Read site messages and send notifications when refreshing data',
|
||||
siteReset: 'Site Reset',
|
||||
confirmReset: 'Confirm to delete all site data and resync.',
|
||||
confirmResetHint:
|
||||
'Delete all site data and resync from CookieCloud. Please clear all related site settings before this operation.',
|
||||
resetSites: 'Reset Site Data',
|
||||
resettingSites: 'Resetting...',
|
||||
syncInterval: {
|
||||
hourly: 'Hourly',
|
||||
every6Hours: 'Every 6 Hours',
|
||||
every12Hours: 'Every 12 Hours',
|
||||
daily: 'Daily',
|
||||
weekly: 'Weekly',
|
||||
monthly: 'Monthly',
|
||||
never: 'Never',
|
||||
},
|
||||
saveSuccess: 'Site settings saved successfully',
|
||||
saveFailed: 'Failed to save site settings!',
|
||||
resetSuccess: 'Sites reset successfully, please wait for CookieCloud sync to complete!',
|
||||
resetFailed: 'Failed to reset sites!',
|
||||
},
|
||||
message: {
|
||||
loadMore: 'Load More',
|
||||
@@ -367,4 +443,261 @@ export default {
|
||||
priority: 'Priority: {value}',
|
||||
noPriorityRule: 'No priority rule matched!',
|
||||
},
|
||||
setting: {
|
||||
about: {
|
||||
title: 'About MoviePilot',
|
||||
softwareVersion: 'Software Version',
|
||||
frontendVersion: 'Frontend Version',
|
||||
authVersion: 'Auth Resource Version',
|
||||
indexerVersion: 'Indexer Resource Version',
|
||||
configDir: 'Config Directory',
|
||||
dataDir: 'Data Directory',
|
||||
timezone: 'Timezone',
|
||||
latest: 'Latest',
|
||||
support: 'Support',
|
||||
documentation: 'Documentation',
|
||||
feedback: 'Feedback',
|
||||
channel: 'Release Channel',
|
||||
versions: 'Software Versions',
|
||||
latestVersion: 'Latest Version',
|
||||
currentVersion: 'Current Version',
|
||||
viewChangelog: 'View Changelog',
|
||||
changelog: 'Changelog',
|
||||
},
|
||||
system: {
|
||||
basicSettings: 'Basic Settings',
|
||||
basicSettingsDesc: 'Configure server global functions.',
|
||||
appDomain: 'Access Domain',
|
||||
appDomainHint: 'Used to add quick jump links when sending notifications',
|
||||
wallpaper: 'Background Wallpaper',
|
||||
wallpaperHint: 'Choose the source of the login page background',
|
||||
recognizeSource: 'Recognition Data Source',
|
||||
recognizeSourceHint: 'Set the default media info recognition data source',
|
||||
mediaServerSyncInterval: 'Media Server Sync Interval',
|
||||
mediaServerSyncIntervalHint: 'Time interval for syncing media server data to local',
|
||||
hours: 'hours',
|
||||
required: 'Required field, please fill in',
|
||||
numbersOnly: 'Only numbers are supported, please do not enter other characters',
|
||||
minInterval: 'Interval cannot be less than 1 hour',
|
||||
apiToken: 'API Token',
|
||||
apiTokenHint: 'Set the token value used when external requests access MoviePilot API',
|
||||
apiTokenMinChars: 'Cannot be less than 16 characters',
|
||||
apiTokenRequired: 'Required field; please enter API Token',
|
||||
apiTokenLength: 'API Token must be at least 16 characters',
|
||||
githubToken: 'Github Token',
|
||||
githubTokenFormat: 'ghp_**** or github_pat_****',
|
||||
githubTokenHint: 'Used to increase the rate limit threshold when plugins access Github API',
|
||||
ocrHost: 'OCR Server',
|
||||
ocrHostHint: 'Used for site check-in, updating site cookies and other captcha recognition',
|
||||
advancedSettings: 'Advanced Settings',
|
||||
advancedSettingsDesc: 'System advanced settings, only need to be adjusted in special cases',
|
||||
downloaders: 'Downloaders',
|
||||
downloadersDesc: 'Only the default downloader will be used by default.',
|
||||
mediaServers: 'Media Servers',
|
||||
mediaServersDesc: 'All enabled media servers will be used.',
|
||||
trimeMedia: 'TrimeMedia',
|
||||
system: 'System',
|
||||
media: 'Media',
|
||||
network: 'Network',
|
||||
log: 'Log',
|
||||
lab: 'Lab',
|
||||
reloadSuccess: 'System configuration has taken effect',
|
||||
reloadFailed: 'Failed to reload system!',
|
||||
downloaderSaveSuccess: 'Downloader settings saved successfully',
|
||||
downloaderSaveFailed: 'Failed to save downloader settings!',
|
||||
defaultDownloaderNotice: 'No default downloader set, [{name}] has been set as the default downloader',
|
||||
mediaServerSaveSuccess: 'Media server settings saved successfully',
|
||||
mediaServerSaveFailed: 'Failed to save media server settings!',
|
||||
saveFailed: 'Failed to save settings: {message}!',
|
||||
basicSaveSuccess: 'Basic settings saved successfully',
|
||||
advancedSaveSuccess: 'Advanced settings saved successfully',
|
||||
copySuccess: 'Copied to clipboard!',
|
||||
copyFailed: 'Copy failed: browser may not support or user blocked!',
|
||||
copyError: 'Copy failed!',
|
||||
reloading: 'Applying configuration...',
|
||||
},
|
||||
notification: {
|
||||
channels: 'Notification Channels',
|
||||
channelsDesc: 'Set message sending channel parameters.',
|
||||
scope: 'Notification Scope',
|
||||
scopeDesc: 'Corresponding message types will only be sent to specified users.',
|
||||
messageType: 'Message Type',
|
||||
scopeRange: 'Scope',
|
||||
operationUserOnly: 'Operation User Only',
|
||||
adminOnly: 'Admin Only',
|
||||
userAndAdmin: 'Operation User and Admin',
|
||||
allUsers: 'All Users',
|
||||
sendTime: 'Notification Send Time',
|
||||
sendTimeDesc: 'Set the time range for sending messages.',
|
||||
startTime: 'Start Time',
|
||||
endTime: 'End Time',
|
||||
saveSuccess: 'Notification settings saved successfully',
|
||||
saveFailed: 'Failed to save notification settings!',
|
||||
switchSaveSuccess: 'Message type switches saved successfully',
|
||||
switchSaveFailed: 'Failed to save message type switches!',
|
||||
timeSaveSuccess: 'Notification send time saved successfully',
|
||||
timeSaveFailed: 'Failed to save notification send time!',
|
||||
channel: 'Notification',
|
||||
wechat: 'WeChat',
|
||||
resourceDownload: 'Resource Download',
|
||||
mediaImport: 'Media Import',
|
||||
subscription: 'Subscription',
|
||||
site: 'Site',
|
||||
mediaServer: 'Media Server',
|
||||
manualProcess: 'Manual Process',
|
||||
plugin: 'Plugin',
|
||||
other: 'Other',
|
||||
},
|
||||
words: {
|
||||
customIdentifiers: 'Custom Identifiers',
|
||||
identifiersDesc: 'Add rules to preprocess torrent names or file names to correct identification.',
|
||||
identifiersPlaceholder: 'Support regular expressions, special characters need \\ escape, one line for each rule',
|
||||
identifiersHint: 'Support regular expressions, special characters need \\ escape, one line for each rule',
|
||||
formatTitle: 'Supported configuration formats (mind the spaces):',
|
||||
formatContent:
|
||||
'Block words\n' +
|
||||
'Word to replace => Replacement\n' +
|
||||
'Front word <> Back word >> Episode offset (EP)\n' +
|
||||
'Word to replace => Replacement && Front word <> Back word >> Episode offset (EP)\n' +
|
||||
'Replacement format supports: [[tmdbid/doubanid=xxx;type=movie/tv;s=xxx;e=xxx]] to directly specify TMDBID/Douban ID, where s and e are season and episode numbers (optional)',
|
||||
identifierSaveSuccess: 'Custom identifiers saved successfully',
|
||||
identifierSaveFailed: 'Failed to save custom identifiers!',
|
||||
|
||||
customReleaseGroups: 'Custom Release/Subtitle Groups',
|
||||
releaseGroupsDesc: 'Add release/subtitle groups that cannot be identified.',
|
||||
releaseGroupsPlaceholder:
|
||||
'Support regular expressions, special characters need \\ escape, one line for each group',
|
||||
releaseGroupsHint: 'Support regular expressions, special characters need \\ escape, one line for each group',
|
||||
releaseGroupSaveSuccess: 'Custom release/subtitle groups saved successfully',
|
||||
releaseGroupSaveFailed: 'Failed to save custom release/subtitle groups!',
|
||||
|
||||
customization: 'Custom Placeholders',
|
||||
customizationDesc: 'Add custom placeholder regex patterns, use {customization} in rename format.',
|
||||
customizationPlaceholder:
|
||||
'Support regular expressions, special characters need \\ escape, separate multiple matches with new lines',
|
||||
customizationHint:
|
||||
'Support regular expressions, special characters need \\ escape, separate multiple matches with new lines',
|
||||
customizationSaveSuccess: 'Custom placeholders saved successfully',
|
||||
customizationSaveFailed: 'Failed to save custom placeholders!',
|
||||
|
||||
transferExcludeWords: 'File Organization Block Words',
|
||||
excludeWordsDesc: 'Files or directories containing block words will not be organized.',
|
||||
excludeWordsPlaceholder:
|
||||
'Support regular expressions, special characters need \\ escape, one line for each block word',
|
||||
excludeWordsHint: 'Support regular expressions, special characters need \\ escape, one line for each block word',
|
||||
excludeWordsSaveSuccess: 'File organization block words saved successfully',
|
||||
excludeWordsSaveFailed: 'Failed to save file organization block words!',
|
||||
},
|
||||
search: {
|
||||
basicSettings: 'Basic Settings',
|
||||
basicSettingsDesc: 'Set data sources, rule groups and other basic information.',
|
||||
recognizeSource: 'Recognition Data Source',
|
||||
recognizeSourceDesc:
|
||||
'Default is TMDB. Douban is usually more friendly for Chinese works, but some foreign works have incomplete information.',
|
||||
themoviedb: 'TheMovieDb',
|
||||
douban: 'Douban',
|
||||
filterRuleGroup: 'Filter Rule Group',
|
||||
filterRuleGroupDesc: 'Set filter rule groups used during download process.',
|
||||
downloadLabel: 'Download Task Label',
|
||||
downloadLabelDesc: 'Download labels in downloader, used for filtering queries.',
|
||||
downloadLabelHint: 'Support multiple labels, separated by commas',
|
||||
downloadSite: 'Search Sites',
|
||||
downloadSiteDesc: 'Set site scope for specific category searches.',
|
||||
movieSites: 'Movie Sites',
|
||||
tvSites: 'TV Show Sites',
|
||||
animeSites: 'Anime Sites',
|
||||
saveSites: 'Save Sites',
|
||||
saveSuccess: 'Search settings saved successfully',
|
||||
saveFailed: 'Failed to save search settings!',
|
||||
saveRuleFailed: 'Failed to save rules!',
|
||||
movieCategory: 'Movies',
|
||||
tvCategory: 'TV Shows',
|
||||
animeCategory: 'Anime',
|
||||
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',
|
||||
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',
|
||||
},
|
||||
directory: {
|
||||
storage: 'Storage',
|
||||
storageDesc: 'Set up local or cloud storage.',
|
||||
directory: 'Directory',
|
||||
directoryDesc: 'Set up media file organization directory structure, matching in sequence.',
|
||||
organizeAndScrap: 'Organization & Scraping',
|
||||
organizeAndScrapDesc: 'Set rename format, scraping options, etc.',
|
||||
scrapSource: 'Scraping Data Source',
|
||||
scrapSourceHint: 'Metadata source for scraping',
|
||||
movieRenameFormat: 'Movie Rename Format',
|
||||
movieRenameFormatHint:
|
||||
'Using Jinja2 syntax, format reference: https://jinja.palletsprojects.com/en/3.0.x/templates',
|
||||
tvRenameFormat: 'TV Show Rename Format',
|
||||
tvRenameFormatHint: 'Using Jinja2 syntax, format reference: https://jinja.palletsprojects.com/en/3.0.x/templates',
|
||||
saveSuccess: 'Storage settings saved successfully',
|
||||
saveFailed: 'Failed to save storage settings!',
|
||||
directorySaveSuccess: 'Directory settings saved successfully',
|
||||
directorySaveFailed: 'Failed to save directory settings!',
|
||||
organizeSaveSuccess: 'Organization options saved successfully',
|
||||
organizeSaveFailed: 'Failed to save organization options!',
|
||||
duplicateDirectoryName: 'Duplicate directory names exist! Cannot save, please modify!',
|
||||
},
|
||||
},
|
||||
rule: {
|
||||
customRules: 'Custom Rules',
|
||||
customRulesDesc: 'Custom priority rule items',
|
||||
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.',
|
||||
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!',
|
||||
importUnknownType: 'Failed to import rules! Unknown data type!',
|
||||
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.',
|
||||
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',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -242,6 +242,39 @@ export default {
|
||||
recognitionWords: '识别词',
|
||||
cancelShare: '取消分享',
|
||||
usageCount: '共 {count} 次复用',
|
||||
basicSettings: '基础设置',
|
||||
basicSettingsDesc: '设定订阅模式、周期等基础设置',
|
||||
mode: '订阅模式',
|
||||
modeHint: '自动:自动爬取站点首页,站点RSS:通过站点RSS链接订阅',
|
||||
rssInterval: '站点RSS周期',
|
||||
rssIntervalHint: '设置站点RSS运行周期,在订阅模式为`站点RSS`时生效',
|
||||
filterRuleGroup: '订阅优先级规则组',
|
||||
filterRuleGroupHint: '按选定的过滤规则组对订阅进行过滤',
|
||||
bestVersionRuleGroup: '洗版优先级规则组',
|
||||
bestVersionRuleGroupHint: '按选定的过滤规则组对洗版订阅进行过滤',
|
||||
timedSearch: '订阅定时搜索',
|
||||
timedSearchHint: '每隔24小时全站搜索,以补全订阅可能漏掉的资源',
|
||||
checkLocalMedia: '检查本地媒体库资源',
|
||||
checkLocalMediaHint: '检查存储盘是否存在资源,以避免重复下载',
|
||||
subscribeSites: '订阅站点',
|
||||
subscribeSitesDesc: '只有选中的站点才会在订阅中使用。',
|
||||
saveSuccess: '订阅站点保存成功',
|
||||
saveFailed: '订阅站点保存失败!',
|
||||
settingsSaveSuccess: '订阅基础设置保存成功',
|
||||
settingsSaveFailed: '订阅基础设置保存失败!',
|
||||
modes: {
|
||||
auto: '自动',
|
||||
rss: '站点RSS',
|
||||
},
|
||||
intervals: {
|
||||
min5: '5分钟',
|
||||
min10: '10分钟',
|
||||
min20: '20分钟',
|
||||
min30: '半小时',
|
||||
hour1: '1小时',
|
||||
hour12: '12小时',
|
||||
day1: '1天',
|
||||
},
|
||||
},
|
||||
recommend: {
|
||||
all: '全部',
|
||||
@@ -326,6 +359,79 @@ 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: '站点重置失败!',
|
||||
search: {
|
||||
basicSettings: '基础设置',
|
||||
basicSettingsDesc: '设定数据源、规则组等基础信息。',
|
||||
recognizeSource: '识别数据源',
|
||||
recognizeSourceDesc: '默认使用TMDB。豆瓣识别中文作品通常更友好,但有些国外作品信息不完整。',
|
||||
themoviedb: 'TheMovieDb',
|
||||
douban: '豆瓣',
|
||||
filterRuleGroup: '过滤规则组',
|
||||
filterRuleGroupDesc: '设置下载过程中使用的过滤规则组。',
|
||||
downloadLabel: '下载任务标签',
|
||||
downloadLabelDesc: '下载器中的下载标签,用于过滤查询。',
|
||||
downloadLabelHint: '支持增加多个标签,英文逗号分隔',
|
||||
downloadSite: '搜索站点',
|
||||
downloadSiteDesc: '设置指定分类搜索的站点范围。',
|
||||
movieSites: '电影站点',
|
||||
tvSites: '电视剧站点',
|
||||
animeSites: '动漫站点',
|
||||
saveSites: '保存站点',
|
||||
saveSuccess: '保存搜索设置成功',
|
||||
saveFailed: '搜索设置保存失败!',
|
||||
saveRuleFailed: '规则保存失败!',
|
||||
movieCategory: '电影',
|
||||
tvCategory: '电视剧',
|
||||
animeCategory: '动漫',
|
||||
downloadUser: '远程搜索自动下载用户',
|
||||
downloadUserHint:
|
||||
'使用Telegram、微信等远程搜索时是否自动下载,多个用户使用英文逗号分隔,设置为all代表所有用户自动下载',
|
||||
multipleNameSearch: '多名称资源搜索',
|
||||
multipleNameSearchHint: '使用多个名称(中文、英文等)搜索站点资源并合并搜索结果,会增加站点访问频率',
|
||||
downloadSubtitle: '下载站点字幕',
|
||||
downloadSubtitleHint: '检查站点资源是否有单独的字幕文件并自动下载',
|
||||
},
|
||||
},
|
||||
message: {
|
||||
loadMore: '加载更多',
|
||||
@@ -365,4 +471,221 @@ export default {
|
||||
priority: '优先级:{value}',
|
||||
noPriorityRule: '未命中任何优先级规则!',
|
||||
},
|
||||
setting: {
|
||||
about: {
|
||||
title: '关于 MoviePilot',
|
||||
softwareVersion: '软件版本',
|
||||
frontendVersion: '前端版本',
|
||||
authVersion: '认证资源版本',
|
||||
indexerVersion: '站点资源版本',
|
||||
configDir: '配置目录',
|
||||
dataDir: '数据目录',
|
||||
timezone: '时区',
|
||||
latest: '最新',
|
||||
support: '支援',
|
||||
documentation: '文档',
|
||||
feedback: '问题反馈',
|
||||
channel: '发布频道',
|
||||
versions: '软件版本',
|
||||
latestVersion: '最新软件版本',
|
||||
currentVersion: '当前版本',
|
||||
viewChangelog: '查看变更日志',
|
||||
changelog: '变更日志',
|
||||
},
|
||||
system: {
|
||||
basicSettings: '基础设置',
|
||||
basicSettingsDesc: '设置服务器的全局功能。',
|
||||
appDomain: '访问域名',
|
||||
appDomainHint: '用于发送通知时,添加快捷跳转地址',
|
||||
wallpaper: '背景壁纸',
|
||||
wallpaperHint: '选择登陆页面背景来源',
|
||||
recognizeSource: '识别数据源',
|
||||
recognizeSourceHint: '设置默认媒体信息识别数据源',
|
||||
mediaServerSyncInterval: '媒体服务器同步间隔',
|
||||
mediaServerSyncIntervalHint: '定时同步媒体服务器数据到本地的时间间隔',
|
||||
hours: '小时',
|
||||
required: '必选项,请勿留空',
|
||||
numbersOnly: '仅支持输入数字,请勿输入其他字符',
|
||||
minInterval: '间隔不能小于1个小时',
|
||||
apiToken: 'API令牌',
|
||||
apiTokenHint: '设置外部请求MoviePilot API时使用的token值',
|
||||
apiTokenMinChars: '不能小于16位字符',
|
||||
apiTokenRequired: '必填项;请输入API Token',
|
||||
apiTokenLength: 'API Token不得低于16位',
|
||||
githubToken: 'Github Token',
|
||||
githubTokenFormat: 'ghp_**** 或 github_pat_****',
|
||||
githubTokenHint: '用于提高插件等访问Github API时的限流阈值',
|
||||
ocrHost: '验证码识别服务器',
|
||||
ocrHostHint: '用于站点签到、更新站点Cookie等识别验证码',
|
||||
advancedSettings: '高级设置',
|
||||
advancedSettingsDesc: '系统进阶设置,特殊情况下才需要调整',
|
||||
downloaders: '下载器',
|
||||
downloadersDesc: '只有默认下载器才会被默认使用。',
|
||||
mediaServers: '媒体服务器',
|
||||
mediaServersDesc: '所有启用的媒体服务器都会被使用。',
|
||||
trimeMedia: '飞牛影视',
|
||||
system: '系统',
|
||||
media: '媒体',
|
||||
network: '网络',
|
||||
log: '日志',
|
||||
lab: '实验室',
|
||||
reloadSuccess: '系统配置已生效',
|
||||
reloadFailed: '重载系统失败!',
|
||||
downloaderSaveSuccess: '下载器设置保存成功',
|
||||
downloaderSaveFailed: '下载器设置保存失败!',
|
||||
defaultDownloaderNotice: '未设置默认下载器,已将【{name}】作为默认下载器',
|
||||
mediaServerSaveSuccess: '媒体服务器设置保存成功',
|
||||
mediaServerSaveFailed: '媒体服务器设置保存失败!',
|
||||
saveFailed: '设置保存失败:{message}!',
|
||||
basicSaveSuccess: '基础设置保存成功',
|
||||
advancedSaveSuccess: '高级设置保存成功',
|
||||
copySuccess: '已复制到剪贴板!',
|
||||
copyFailed: '复制失败:可能是浏览器不支持或被用户阻止!',
|
||||
copyError: '复制失败!',
|
||||
reloading: '正在应用配置...',
|
||||
},
|
||||
notification: {
|
||||
channels: '通知渠道',
|
||||
channelsDesc: '设置消息发送渠道参数。',
|
||||
scope: '通知发送范围',
|
||||
scopeDesc: '对应消息类型只会发送给设定的用户。',
|
||||
messageType: '消息类型',
|
||||
scopeRange: '范围',
|
||||
operationUserOnly: '仅操作用户',
|
||||
adminOnly: '仅管理员',
|
||||
userAndAdmin: '操作用户和管理员',
|
||||
allUsers: '所有用户',
|
||||
sendTime: '通知发送时间',
|
||||
sendTimeDesc: '设定消息发送的时间范围。',
|
||||
startTime: '开始时间',
|
||||
endTime: '结束时间',
|
||||
saveSuccess: '通知设置保存成功',
|
||||
saveFailed: '通知设置保存失败!',
|
||||
switchSaveSuccess: '消息类型开关保存成功',
|
||||
switchSaveFailed: '消息类型开关保存失败!',
|
||||
timeSaveSuccess: '通知发送时间保存成功',
|
||||
timeSaveFailed: '通知发送时间保存失败!',
|
||||
channel: '通知',
|
||||
wechat: '微信',
|
||||
resourceDownload: '资源下载',
|
||||
mediaImport: '整理入库',
|
||||
subscription: '订阅',
|
||||
site: '站点',
|
||||
mediaServer: '媒体服务器',
|
||||
manualProcess: '手动处理',
|
||||
plugin: '插件',
|
||||
other: '其它',
|
||||
},
|
||||
words: {
|
||||
customIdentifiers: '自定义识别词',
|
||||
identifiersDesc: '添加规则对种子名或者文件名进行预处理以校正识别。',
|
||||
identifiersPlaceholder: '支持正则表达式,特殊字符需要\\转义,一行为一组',
|
||||
identifiersHint: '支持正则表达式,特殊字符需要\\转义,一行为一组',
|
||||
formatTitle: '支持的配置格式(注意空格):',
|
||||
formatContent:
|
||||
'屏蔽词\n' +
|
||||
'被替换词 => 替换词\n' +
|
||||
'前定位词 <> 后定位词 >> 集偏移量(EP)\n' +
|
||||
'被替换词 => 替换词 && 前定位词 <> 后定位词 >> 集偏移量(EP)\n' +
|
||||
'其中替换词支持格式:[[tmdbid/doubanid=xxx;type=movie/tv;s=xxx;e=xxx]] 直接指定TMDBID/豆瓣ID识别,其中s、e为季数和集数(可选)',
|
||||
identifierSaveSuccess: '自定义识别词保存成功',
|
||||
identifierSaveFailed: '自定义识别词保存失败!',
|
||||
|
||||
customReleaseGroups: '自定义制作组/字幕组',
|
||||
releaseGroupsDesc: '添加无法识别的制作组/字幕组。',
|
||||
releaseGroupsPlaceholder: '支持正则表达式,特殊字符需要\\转义,一行代表一个制作组/字幕组',
|
||||
releaseGroupsHint: '支持正则表达式,特殊字符需要\\转义,一行代表一个制作组/字幕组',
|
||||
releaseGroupSaveSuccess: '自定义制作组/字幕组保存成功',
|
||||
releaseGroupSaveFailed: '自定义制作组/字幕组保存失败!',
|
||||
|
||||
customization: '自定义占位符',
|
||||
customizationDesc: '添加自定义占位符识别正则,重命名格式中添加{customization}使用。',
|
||||
customizationPlaceholder: '支持正则表达式,特殊字符需要\\转义,多个匹配对象请换行分隔',
|
||||
customizationHint: '支持正则表达式,特殊字符需要\\转义,多个匹配对象请换行分隔',
|
||||
customizationSaveSuccess: '自定义占位符保存成功',
|
||||
customizationSaveFailed: '自定义占位符保存失败!',
|
||||
|
||||
transferExcludeWords: '文件整理屏蔽词',
|
||||
excludeWordsDesc: '目录名或文件名中包含屏蔽词时不进行整理。',
|
||||
excludeWordsPlaceholder: '支持正则表达式,特殊字符需要\\转义,一行代表一个屏蔽词',
|
||||
excludeWordsHint: '支持正则表达式,特殊字符需要\\转义,一行代表一个屏蔽词',
|
||||
excludeWordsSaveSuccess: '文件整理屏蔽词保存成功',
|
||||
excludeWordsSaveFailed: '文件整理屏蔽词保存失败!',
|
||||
},
|
||||
},
|
||||
directory: {
|
||||
storage: '存储',
|
||||
storageDesc: '设置本地或网盘存储。',
|
||||
directory: '目录',
|
||||
directoryDesc: '设置媒体文件整理目录结构,按先后顺序依次匹配。',
|
||||
organizeAndScrap: '整理 & 刮削',
|
||||
organizeAndScrapDesc: '设置重命名格式、刮削选项等。',
|
||||
scrapSource: '刮削数据源',
|
||||
scrapSourceHint: '刮削时的元数据来源',
|
||||
movieRenameFormat: '电影重命名格式',
|
||||
movieRenameFormatHint: '使用Jinja2语法,格式参考:https://jinja.palletsprojects.com/en/3.0.x/templates',
|
||||
tvRenameFormat: '电视剧重命名格式',
|
||||
tvRenameFormatHint: '使用Jinja2语法,格式参考:https://jinja.palletsprojects.com/en/3.0.x/templates',
|
||||
saveSuccess: '存储设置保存成功',
|
||||
saveFailed: '存储设置保存失败!',
|
||||
directorySaveSuccess: '目录设置保存成功',
|
||||
directorySaveFailed: '目录设置保存失败!',
|
||||
organizeSaveSuccess: '整理选项设置保存成功',
|
||||
organizeSaveFailed: '整理选项设置保存失败!',
|
||||
duplicateDirectoryName: '存在重复目录名称!无法保存,请修改!',
|
||||
},
|
||||
rule: {
|
||||
customRules: '自定义规则',
|
||||
customRulesDesc: '自定义优先级规则项',
|
||||
priorityRuleGroups: '优先级规则组',
|
||||
priorityRuleGroupsDesc: '预设优先级规则组,以便在搜索和订阅中使用。',
|
||||
downloadRules: '下载规则',
|
||||
downloadRulesDesc: '同时命中多个资源时择优下载。',
|
||||
currentPriorityRules: '当前使用下载优先规则',
|
||||
currentPriorityRulesHint: '排在前面的优先级越高,未选择的项不纳入排序',
|
||||
saveSuccess: '自定义规则保存成功',
|
||||
saveFailed: '自定义规则保存失败!',
|
||||
groupSaveSuccess: '优先级规则组保存成功',
|
||||
groupSaveFailed: '优先级规则组保存失败!',
|
||||
prioritySaveSuccess: '优先规则保存成功',
|
||||
prioritySaveFailed: '优先规则保存失败!',
|
||||
emptyRuleId: '存在空ID的规则,无法保存,请修改!',
|
||||
emptyRuleName: '存在空名字的规则,无法保存,请修改!',
|
||||
duplicateRuleId: '存在重复规则ID!无法保存,请修改!',
|
||||
duplicateRuleName: '存在重复规则名称!无法保存,请修改!',
|
||||
emptyGroupName: '存在空名字的规则组!无法保存,请修改!',
|
||||
duplicateGroupName: '存在重复规则组名称!无法保存,请修改!',
|
||||
copySuccess: '已复制到剪贴板!',
|
||||
copyFailed: '复制失败:可能是浏览器不支持或被用户阻止!',
|
||||
copyError: '复制失败!',
|
||||
importCustomRules: '导入自定义规则',
|
||||
importRuleGroups: '导入优先级规则组',
|
||||
importFailed: '导入规则失败!无法解析输入的数据!',
|
||||
importUnknownType: '导入规则失败!未知的数据类型!',
|
||||
duplicateValue: '存在重名值',
|
||||
importNoId: '导入失败!发现有规则不存在ID,可能属于优先级规则组!',
|
||||
importHasId: '导入失败!发现有规则存在相同ID,可能属于自定义规则!',
|
||||
torrentPriority: {
|
||||
torrent: '资源优先级',
|
||||
site: '站点优先级',
|
||||
upload: '站点上传量',
|
||||
seeder: '资源做种数',
|
||||
},
|
||||
},
|
||||
scheduler: {
|
||||
scheduledTasks: '定时作业',
|
||||
scheduledTasksDesc: '包含系统内置服务以及插件提供的服务,手动执行不会影响作业正常的时间表。',
|
||||
provider: '提供者',
|
||||
taskName: '任务名称',
|
||||
taskStatus: '任务状态',
|
||||
nextRunTime: '下一次执行时间',
|
||||
execute: '执行',
|
||||
noServices: '没有后台服务',
|
||||
submitSuccess: '定时作业执行请求提交成功!',
|
||||
status: {
|
||||
running: '正在运行',
|
||||
stopped: '已停止',
|
||||
waiting: '等待',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { formatDateDifference } from '@/@core/utils/formatters'
|
||||
import api from '@/api'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 系统环境变量
|
||||
const systemEnv = ref<any>({})
|
||||
@@ -68,13 +72,13 @@ onMounted(() => {
|
||||
<div class="px-3">
|
||||
<div class="section">
|
||||
<div>
|
||||
<h3 class="heading">关于 MoviePilot</h3>
|
||||
<h3 class="heading">{{ t('setting.about.title') }}</h3>
|
||||
</div>
|
||||
<div class="section border-t border-gray-800">
|
||||
<dl>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">软件版本</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.softwareVersion') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow flex flex-row items-center truncate">
|
||||
<code class="truncate">{{ systemEnv.VERSION }}</code>
|
||||
@@ -87,7 +91,7 @@ onMounted(() => {
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full whitespace-nowrap bg-green-500 bg-opacity-80 border border-green-500 !text-green-100 ml-2 !cursor-pointer transition hover:bg-green-400"
|
||||
>
|
||||
最新
|
||||
{{ t('setting.about.latest') }}
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
@@ -96,7 +100,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div v-if="systemEnv.FRONTEND_VERSION">
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">前端版本</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.frontendVersion') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow flex flex-row items-center truncate">
|
||||
<code class="truncate">{{ systemEnv.FRONTEND_VERSION }}</code>
|
||||
@@ -106,7 +110,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">认证资源版本</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.authVersion') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow flex flex-row items-center truncate">
|
||||
<code class="truncate">{{ systemEnv.AUTH_VERSION }}</code>
|
||||
@@ -116,7 +120,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">站点资源版本</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.indexerVersion') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow flex flex-row items-center truncate">
|
||||
<code class="truncate">{{ systemEnv.INDEXER_VERSION }}</code>
|
||||
@@ -126,7 +130,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">配置目录</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.configDir') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow undefined">
|
||||
<code>{{ systemEnv.CONFIG_DIR }}</code>
|
||||
@@ -134,7 +138,7 @@ onMounted(() => {
|
||||
</dd>
|
||||
</div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">数据目录</dt>
|
||||
<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>
|
||||
</dd>
|
||||
@@ -142,7 +146,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">时区</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.timezone') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow undefined">
|
||||
<code>{{ systemEnv.TZ }}</code>
|
||||
@@ -155,13 +159,13 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="section">
|
||||
<div>
|
||||
<h3 class="heading">支援</h3>
|
||||
<h3 class="heading">{{ t('setting.about.support') }}</h3>
|
||||
</div>
|
||||
<div class="section border-t border-gray-800">
|
||||
<dl>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">文档</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.documentation') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow undefined">
|
||||
<a
|
||||
@@ -178,7 +182,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">问题反馈</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.feedback') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow undefined">
|
||||
<a
|
||||
@@ -195,7 +199,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div>
|
||||
<div class="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||
<dt class="block text-sm font-bold">发布频道</dt>
|
||||
<dt class="block text-sm font-bold">{{ t('setting.about.channel') }}</dt>
|
||||
<dd class="flex text-sm sm:col-span-2 sm:mt-0">
|
||||
<span class="flex-grow undefined">
|
||||
<a
|
||||
@@ -215,7 +219,7 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="section">
|
||||
<div>
|
||||
<h3 class="heading">软件版本</h3>
|
||||
<h3 class="heading">{{ t('setting.about.versions') }}</h3>
|
||||
<div class="section space-y-3">
|
||||
<div>
|
||||
<div
|
||||
@@ -234,20 +238,20 @@ onMounted(() => {
|
||||
v-if="release.tag_name === latestRelease"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full whitespace-nowrap cursor-default bg-green-500 bg-opacity-80 border border-green-500 !text-green-100"
|
||||
>
|
||||
最新软件版本
|
||||
{{ t('setting.about.latestVersion') }}
|
||||
</span>
|
||||
<span
|
||||
v-if="release.tag_name === systemEnv.VERSION"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full whitespace-nowrap cursor-default bg-indigo-500 bg-opacity-80 border border-indigo-500 !text-indigo-100"
|
||||
>
|
||||
当前版本
|
||||
{{ t('setting.about.currentVersion') }}
|
||||
</span>
|
||||
</div>
|
||||
<VBtn @click.stop="showReleaseDialog(release.tag_name, release.body)">
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-text-box-outline" />
|
||||
</template>
|
||||
查看变更日志
|
||||
{{ t('setting.about.viewChangelog') }}
|
||||
</VBtn>
|
||||
</div>
|
||||
</div>
|
||||
@@ -259,7 +263,7 @@ onMounted(() => {
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VDialogCloseBtn @click="releaseDialog = false" />
|
||||
<VCardTitle>{{ releaseDialogTitle }} 变更日志</VCardTitle>
|
||||
<VCardTitle>{{ releaseDialogTitle }} {{ t('setting.about.changelog') }}</VCardTitle>
|
||||
</VCardItem>
|
||||
<VCardText v-html="releaseDialogBody" />
|
||||
</VCard>
|
||||
|
||||
@@ -5,6 +5,10 @@ import draggable from 'vuedraggable'
|
||||
import type { NotificationConf, NotificationSwitchConf } from '@/api/types'
|
||||
import NotificationChannelCard from '@/components/cards/NotificationChannelCard.vue'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 所有消息渠道
|
||||
const notifications = ref<NotificationConf[]>([])
|
||||
@@ -18,35 +22,35 @@ const progressDialog = ref(false)
|
||||
// 消息类型开关
|
||||
const notificationSwitchs = ref<NotificationSwitchConf[]>([
|
||||
{
|
||||
type: '资源下载',
|
||||
type: t('setting.notification.resourceDownload'),
|
||||
action: 'all',
|
||||
},
|
||||
{
|
||||
type: '整理入库',
|
||||
type: t('setting.notification.mediaImport'),
|
||||
action: 'all',
|
||||
},
|
||||
{
|
||||
type: '订阅',
|
||||
type: t('setting.notification.subscription'),
|
||||
action: 'all',
|
||||
},
|
||||
{
|
||||
type: '站点',
|
||||
type: t('setting.notification.site'),
|
||||
action: 'admin',
|
||||
},
|
||||
{
|
||||
type: '媒体服务器',
|
||||
type: t('setting.notification.mediaServer'),
|
||||
action: 'admin',
|
||||
},
|
||||
{
|
||||
type: '手动处理',
|
||||
type: t('setting.notification.manualProcess'),
|
||||
action: 'admin',
|
||||
},
|
||||
{
|
||||
type: '插件',
|
||||
type: t('setting.notification.plugin'),
|
||||
action: 'admin',
|
||||
},
|
||||
{
|
||||
type: '其它',
|
||||
type: t('setting.notification.other'),
|
||||
action: 'admin',
|
||||
},
|
||||
])
|
||||
@@ -62,8 +66,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)
|
||||
}
|
||||
@@ -72,9 +76,9 @@ async function reloadSystem() {
|
||||
|
||||
// 添加通知渠道
|
||||
function addNotification(notification: string) {
|
||||
let name = `通知${notifications.value.length + 1}`
|
||||
let name = `${t('setting.notification.channel')}${notifications.value.length + 1}`
|
||||
while (notifications.value.some(item => item.name === name)) {
|
||||
name = `通知${parseInt(name.split('通知')[1]) + 1}`
|
||||
name = `${t('setting.notification.channel')}${parseInt(name.split(t('setting.notification.channel'))[1]) + 1}`
|
||||
}
|
||||
notifications.value.push({
|
||||
name: name,
|
||||
@@ -115,9 +119,9 @@ async function saveNotificationSetting() {
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('system/setting/Notifications', notifications.value)
|
||||
if (result.success) {
|
||||
$toast.success('通知设置保存成功')
|
||||
$toast.success(t('setting.notification.saveSuccess'))
|
||||
await reloadSystem()
|
||||
} else $toast.error('通知设置保存失败!')
|
||||
} else $toast.error(t('setting.notification.saveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -128,9 +132,9 @@ async function saveNotificationTime() {
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('system/setting/NotificationSendTime', notificationTime.value)
|
||||
if (result.success) {
|
||||
$toast.success('通知发送时间保存成功')
|
||||
$toast.success(t('setting.notification.timeSaveSuccess'))
|
||||
await reloadSystem()
|
||||
} else $toast.error('通知发送时间保存失败!')
|
||||
} else $toast.error(t('setting.notification.timeSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -159,8 +163,8 @@ async function saveNotificationSwitchs() {
|
||||
'system/setting/NotificationSwitchs',
|
||||
notificationSwitchs.value,
|
||||
)
|
||||
if (result.success) $toast.success('消息类型开关保存成功')
|
||||
else $toast.error('消息类型开关保存失败!')
|
||||
if (result.success) $toast.success(t('setting.notification.switchSaveSuccess'))
|
||||
else $toast.error(t('setting.notification.switchSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -179,8 +183,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>通知渠道</VCardTitle>
|
||||
<VCardSubtitle>设置消息发送渠道参数。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.notification.channels') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.notification.channelsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
@@ -203,13 +207,13 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn mtype="submit" @click="saveNotificationSetting"> 保存 </VBtn>
|
||||
<VBtn mtype="submit" @click="saveNotificationSetting"> {{ t('common.save') }} </VBtn>
|
||||
<VBtn color="success" variant="tonal">
|
||||
<VIcon icon="mdi-plus" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<VListItem @click="addNotification('wechat')">
|
||||
<VListItemTitle>微信</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.notification.wechat') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addNotification('telegram')">
|
||||
<VListItemTitle>Telegram</VListItemTitle>
|
||||
@@ -239,14 +243,14 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>通知发送范围</VCardTitle>
|
||||
<VCardSubtitle>对应消息类型只会发送给设定的用户。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.notification.scope') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.notification.scopeDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VTable class="text-no-wrap">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">消息类型</th>
|
||||
<th scope="col">范围</th>
|
||||
<th scope="col">{{ t('setting.notification.messageType') }}</th>
|
||||
<th scope="col">{{ t('setting.notification.scopeRange') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -256,10 +260,10 @@ onMounted(() => {
|
||||
</td>
|
||||
<td>
|
||||
<VRadioGroup v-model="item.action" inline>
|
||||
<VRadio value="user" label="仅操作用户" />
|
||||
<VRadio value="admin" label="仅管理员" />
|
||||
<VRadio value="user,admin" label="操作用户和管理员" />
|
||||
<VRadio value="all" label="所有用户" />
|
||||
<VRadio value="user" :label="t('setting.notification.operationUserOnly')" />
|
||||
<VRadio value="admin" :label="t('setting.notification.adminOnly')" />
|
||||
<VRadio value="user,admin" :label="t('setting.notification.userAndAdmin')" />
|
||||
<VRadio value="all" :label="t('setting.notification.allUsers')" />
|
||||
</VRadioGroup>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -269,7 +273,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveNotificationSwitchs"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveNotificationSwitchs"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -280,23 +284,23 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>通知发送时间</VCardTitle>
|
||||
<VCardSubtitle>设定消息发送的时间范围。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.notification.sendTime') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.notification.sendTimeDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol cols="6">
|
||||
<VTextField v-model="notificationTime.start" label="开始时间" type="time" />
|
||||
<VTextField v-model="notificationTime.start" :label="t('setting.notification.startTime')" type="time" />
|
||||
</VCol>
|
||||
<VCol cols="6">
|
||||
<VTextField v-model="notificationTime.end" label="结束时间" type="time" />
|
||||
<VTextField v-model="notificationTime.end" :label="t('setting.notification.endTime')" type="time" />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveNotificationTime"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveNotificationTime"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -304,5 +308,10 @@ onMounted(() => {
|
||||
</VCol>
|
||||
</VRow>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" text="正在应用配置..." />
|
||||
<ProgressDialog
|
||||
v-if="progressDialog"
|
||||
v-model="progressDialog"
|
||||
:text="t('setting.system.reloading')"
|
||||
:indeterminate="true"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import api from '@/api'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
@@ -13,7 +17,7 @@ const progressDialog = ref(false)
|
||||
const isConfirmResetSites = ref(false)
|
||||
|
||||
// 站点重置按钮文本
|
||||
const resetSitesText = ref('重置站点数据')
|
||||
const resetSitesText = ref(t('site.resetSites'))
|
||||
|
||||
// 站点重置按钮可用状态
|
||||
const resetSitesDisabled = ref(false)
|
||||
@@ -39,37 +43,37 @@ const siteSetting = ref<any>({
|
||||
|
||||
// 同步间隔下拉框
|
||||
const CookieCloudIntervalItems = [
|
||||
{ title: '每小时', value: 60 },
|
||||
{ title: '每6小时', value: 360 },
|
||||
{ title: '每12小时', value: 720 },
|
||||
{ title: '每天', value: 1440 },
|
||||
{ title: '每周', value: 10080 },
|
||||
{ title: '每月', value: 43200 },
|
||||
{ title: '永不', value: 0 },
|
||||
{ title: t('site.syncInterval.hourly'), value: 60 },
|
||||
{ title: t('site.syncInterval.every6Hours'), value: 360 },
|
||||
{ title: t('site.syncInterval.every12Hours'), value: 720 },
|
||||
{ title: t('site.syncInterval.daily'), value: 1440 },
|
||||
{ title: t('site.syncInterval.weekly'), value: 10080 },
|
||||
{ title: t('site.syncInterval.monthly'), value: 43200 },
|
||||
{ title: t('site.syncInterval.never'), value: 0 },
|
||||
]
|
||||
|
||||
// 站点数据刷新间隔
|
||||
const SiteDataRefreshIntervalItems = [
|
||||
{ title: '每小时', value: 1 },
|
||||
{ title: '每6小时', value: 6 },
|
||||
{ title: '每12小时', value: 12 },
|
||||
{ title: '每天', value: 24 },
|
||||
{ title: '每周', value: 168 },
|
||||
{ title: '永不', value: 0 },
|
||||
{ title: t('site.syncInterval.hourly'), value: 1 },
|
||||
{ title: t('site.syncInterval.every6Hours'), value: 6 },
|
||||
{ title: t('site.syncInterval.every12Hours'), value: 12 },
|
||||
{ title: t('site.syncInterval.daily'), value: 24 },
|
||||
{ title: t('site.syncInterval.weekly'), value: 168 },
|
||||
{ title: t('site.syncInterval.never'), value: 0 },
|
||||
]
|
||||
|
||||
// 重置站点
|
||||
async function resetSites() {
|
||||
try {
|
||||
resetSitesDisabled.value = true
|
||||
resetSitesText.value = '正在重置...'
|
||||
resetSitesText.value = t('site.resettingSites')
|
||||
|
||||
const result: { [key: string]: any } = await api.get('site/reset')
|
||||
if (result.success) $toast.success('站点重置成功,请等待CookieCloud同步完成!')
|
||||
else $toast.error('站点重置失败!')
|
||||
if (result.success) $toast.success(t('site.resetSuccess'))
|
||||
else $toast.error(t('site.resetFailed'))
|
||||
|
||||
resetSitesDisabled.value = false
|
||||
resetSitesText.value = '重置站点数据'
|
||||
resetSitesText.value = t('site.resetSites')
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -97,8 +101,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)
|
||||
}
|
||||
@@ -111,14 +115,14 @@ async function saveSiteSetting(value: { [key: string]: any }) {
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('system/env', value)
|
||||
if (result.success) {
|
||||
$toast.success('保存站点设置成功')
|
||||
$toast.success(t('site.saveSuccess'))
|
||||
await reloadSystem()
|
||||
} else {
|
||||
$toast.error('站点设置保存失败!')
|
||||
$toast.error(t('site.saveFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
$toast.error('保存设置失败!')
|
||||
$toast.error(t('setting.system.saveFailed', { message: error }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +137,8 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>站点同步</VCardTitle>
|
||||
<VCardSubtitle>从CookieCloud快速同步站点数据。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('site.siteSync') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('site.siteSyncDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VForm>
|
||||
@@ -142,8 +146,8 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VCheckbox
|
||||
v-model="siteSetting.CookieCloud.COOKIECLOUD_ENABLE_LOCAL"
|
||||
label="启用本地CookieCloud服务器"
|
||||
hint="使用内建CookieCloud服务同步站点数据,服务地址为:http://localhost:3000/cookiecloud"
|
||||
:label="t('site.enableLocalCookieCloud')"
|
||||
:hint="t('site.enableLocalCookieCloudHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -152,18 +156,18 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="siteSetting.CookieCloud.COOKIECLOUD_HOST"
|
||||
label="服务地址"
|
||||
placeholder="https://movie-pilot.org/cookiecloud"
|
||||
:label="t('site.serviceAddress')"
|
||||
:placeholder="t('site.serviceAddressPlaceholder')"
|
||||
:disabled="siteSetting.CookieCloud.COOKIECLOUD_ENABLE_LOCAL"
|
||||
hint="远端CookieCloud服务地址,格式:https://movie-pilot.org/cookiecloud"
|
||||
:hint="t('site.serviceAddressHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="siteSetting.CookieCloud.COOKIECLOUD_KEY"
|
||||
label="用户KEY"
|
||||
hint="CookieCloud浏览器插件生成的用户KEY"
|
||||
:label="t('site.userKey')"
|
||||
:hint="t('site.userKeyHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -173,34 +177,34 @@ onMounted(() => {
|
||||
:type="isPasswordVisible ? 'text' : 'password'"
|
||||
:append-inner-icon="isPasswordVisible ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
|
||||
@click:append-inner="isPasswordVisible = !isPasswordVisible"
|
||||
label="端对端加密密码"
|
||||
hint="CookieCloud浏览器插件生成的端对端加密密码"
|
||||
:label="t('site.e2ePassword')"
|
||||
:hint="t('site.e2ePasswordHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VSelect
|
||||
v-model="siteSetting.CookieCloud.COOKIECLOUD_INTERVAL"
|
||||
label="自动同步间隔"
|
||||
:label="t('site.autoSyncInterval')"
|
||||
:items="CookieCloudIntervalItems"
|
||||
hint="从CookieCloud服务器自动同步站点Cookie到MoviePilot的时间间隔"
|
||||
:hint="t('site.autoSyncIntervalHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="siteSetting.CookieCloud.COOKIECLOUD_BLACKLIST"
|
||||
label="同步域名黑名单"
|
||||
placeholder="多个域名,分割"
|
||||
hint="CookieCloud同步域名黑名单,多个域名,分割"
|
||||
:label="t('site.syncBlacklist')"
|
||||
:placeholder="t('site.syncBlacklistPlaceholder')"
|
||||
:hint="t('site.syncBlacklistHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="siteSetting.CookieCloud.USER_AGENT"
|
||||
label="浏览器User-Agent"
|
||||
hint="CookieCloud插件所在的浏览器的User-Agent"
|
||||
:label="t('site.userAgent')"
|
||||
:hint="t('site.userAgentHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -210,7 +214,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveSiteSetting(siteSetting.CookieCloud)"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveSiteSetting(siteSetting.CookieCloud)"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -219,16 +223,16 @@ onMounted(() => {
|
||||
</VRow>
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VCard title="站点数据刷新">
|
||||
<VCard :title="t('site.siteDataRefresh')">
|
||||
<VCardText>
|
||||
<VForm>
|
||||
<VRow>
|
||||
<VCol cols="12" md="6">
|
||||
<VSelect
|
||||
v-model="siteSetting.Site.SITEDATA_REFRESH_INTERVAL"
|
||||
label="站点数据刷新间隔"
|
||||
:label="t('site.siteDataRefreshInterval')"
|
||||
:items="SiteDataRefreshIntervalItems"
|
||||
hint="刷新站点用户上传下载等数据的时间间隔"
|
||||
:hint="t('site.siteDataRefreshIntervalHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -237,8 +241,8 @@ onMounted(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VSwitch
|
||||
v-model="siteSetting.Site.SITE_MESSAGE"
|
||||
label="阅读站点消息"
|
||||
hint="刷新数据时读取站点消息并发送通知"
|
||||
:label="t('site.readSiteMessage')"
|
||||
:hint="t('site.readSiteMessageHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -248,7 +252,7 @@ onMounted(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveSiteSetting(siteSetting.Site)"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveSiteSetting(siteSetting.Site)"> {{ t('common.save') }} </VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -257,13 +261,13 @@ onMounted(() => {
|
||||
</VRow>
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VCard title="站点重置">
|
||||
<VCard :title="t('site.siteReset')">
|
||||
<VCardText>
|
||||
<div>
|
||||
<VCheckbox
|
||||
v-model="isConfirmResetSites"
|
||||
label="确认删除所有站点数据并重新同步。"
|
||||
hint="删除所有站点数据并重新从CookieCloud同步,操作请先清空涉及站点的相关设置。"
|
||||
:label="t('site.confirmReset')"
|
||||
:hint="t('site.confirmResetHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</div>
|
||||
@@ -276,5 +280,10 @@ onMounted(() => {
|
||||
</VCol>
|
||||
</VRow>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" text="正在应用配置..." />
|
||||
<ProgressDialog
|
||||
v-if="progressDialog"
|
||||
v-model="progressDialog"
|
||||
:text="t('setting.system.reloading')"
|
||||
:indeterminate="true"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -9,6 +9,10 @@ import DownloaderCard from '@/components/cards/DownloaderCard.vue'
|
||||
import MediaServerCard from '@/components/cards/MediaServerCard.vue'
|
||||
import { copyToClipboard } from '@/@core/utils/navigator'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 系统设置项
|
||||
const SystemSettings = ref<any>({
|
||||
@@ -92,8 +96,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)
|
||||
}
|
||||
@@ -110,8 +114,8 @@ async function saveDownloaderSetting() {
|
||||
downloaders.value = handleDefaultDownloaders(enabledDownloaders, downloaders.value)
|
||||
}
|
||||
const result: { [key: string]: any } = await api.post('system/setting/Downloaders', downloaders.value)
|
||||
if (result.success) $toast.success('下载器设置保存成功')
|
||||
else $toast.error('下载器设置保存失败!')
|
||||
if (result.success) $toast.success(t('setting.system.downloaderSaveSuccess'))
|
||||
else $toast.error(t('setting.system.downloaderSaveFailed'))
|
||||
|
||||
await loadDownloaderSetting()
|
||||
await reloadSystem()
|
||||
@@ -126,7 +130,7 @@ function handleDefaultDownloaders(enabledDownloaders: any[], downloaders: any[])
|
||||
if (enabledDownloaders.length > 0 && !enabledDefaultDownloader) {
|
||||
downloaders = downloaders.map(item => {
|
||||
if (item === enabledDownloaders[0]) {
|
||||
$toast.info(`未设置默认下载器,已将【${item.name}】作为默认下载器`)
|
||||
$toast.info(t('setting.system.defaultDownloaderNotice', { name: item.name }))
|
||||
return { ...item, default: true }
|
||||
}
|
||||
// 清除其他下载器的默认下载器状态
|
||||
@@ -150,8 +154,8 @@ async function loadMediaServerSetting() {
|
||||
async function saveMediaServerSetting() {
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('system/setting/MediaServers', mediaServers.value)
|
||||
if (result.success) $toast.success('媒体服务器设置保存成功')
|
||||
else $toast.error('媒体服务器设置保存失败!')
|
||||
if (result.success) $toast.success(t('setting.system.mediaServerSaveSuccess'))
|
||||
else $toast.error(t('setting.system.mediaServerSaveFailed'))
|
||||
|
||||
await loadMediaServerSetting()
|
||||
await reloadSystem()
|
||||
@@ -184,7 +188,7 @@ async function saveSystemSetting(value: { [key: string]: any }) {
|
||||
if (result.success) {
|
||||
return true
|
||||
} else {
|
||||
$toast.error(`设置保存失败:${result?.message}!`)
|
||||
$toast.error(t('setting.system.saveFailed', { message: result?.message }))
|
||||
return false
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -196,7 +200,7 @@ async function saveSystemSetting(value: { [key: string]: any }) {
|
||||
// 保存基础设置
|
||||
async function saveBasicSettings() {
|
||||
if (await saveSystemSetting(SystemSettings.value.Basic)) {
|
||||
$toast.success('基础设置保存成功')
|
||||
$toast.success(t('setting.system.basicSaveSuccess'))
|
||||
await reloadSystem()
|
||||
}
|
||||
}
|
||||
@@ -207,7 +211,7 @@ async function saveAdvancedSettings() {
|
||||
|
||||
if (await saveSystemSetting(SystemSettings.value.Advanced)) {
|
||||
advancedDialog.value = false
|
||||
$toast.success('高级设置保存成功')
|
||||
$toast.success(t('setting.system.advancedSaveSuccess'))
|
||||
await reloadSystem()
|
||||
}
|
||||
}
|
||||
@@ -226,10 +230,10 @@ async function copyValue(value: string) {
|
||||
try {
|
||||
let success
|
||||
success = copyToClipboard(value)
|
||||
if (await success) $toast.success('已复制到剪贴板!')
|
||||
else $toast.error(`复制失败:可能是浏览器不支持或被用户阻止!`)
|
||||
if (await success) $toast.success(t('setting.system.copySuccess'))
|
||||
else $toast.error(t('setting.system.copyFailed'))
|
||||
} catch (error) {
|
||||
$toast.error('复制失败!')
|
||||
$toast.error(t('setting.system.copyError'))
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
@@ -367,71 +371,97 @@ onDeactivated(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProgressDialog
|
||||
v-if="progressDialog"
|
||||
v-model="progressDialog"
|
||||
:text="t('setting.system.reloading')"
|
||||
:indeterminate="true"
|
||||
/>
|
||||
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>基础设置</VCardTitle>
|
||||
<VCardSubtitle>设置服务器的全局功能。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.system.basicSettings') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.system.basicSettingsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VForm>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<VRow>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="SystemSettings.Basic.APP_DOMAIN"
|
||||
label="访问域名"
|
||||
placeholder="格式:http(s)://domain:port"
|
||||
hint="用于发送通知时,添加快捷跳转地址"
|
||||
:label="t('setting.system.appDomain')"
|
||||
:hint="t('setting.system.appDomainHint')"
|
||||
placeholder="http://localhost:3000"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="3">
|
||||
<VCol cols="12" md="6">
|
||||
<VSelect
|
||||
v-model="SystemSettings.Basic.WALLPAPER"
|
||||
label="背景壁纸"
|
||||
hint="选择登陆页面背景来源"
|
||||
:label="t('setting.system.wallpaper')"
|
||||
:hint="t('setting.system.wallpaperHint')"
|
||||
persistent-hint
|
||||
:items="wallpaperItems"
|
||||
:items="[
|
||||
{ title: 'TMDB', value: 'tmdb' },
|
||||
{ title: 'Bing', value: 'bing' },
|
||||
{ title: 'Bing每日图片', value: 'bing-daily' },
|
||||
{ title: '无壁纸', value: 'none' },
|
||||
]"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<VCol cols="12" md="3">
|
||||
<VCol cols="12" md="6">
|
||||
<VSelect
|
||||
v-model="SystemSettings.Basic.RECOGNIZE_SOURCE"
|
||||
:label="t('setting.system.recognizeSource')"
|
||||
:hint="t('setting.system.recognizeSourceHint')"
|
||||
persistent-hint
|
||||
:items="[
|
||||
{ title: 'TheMovieDb', value: 'themoviedb' },
|
||||
{ title: '豆瓣', value: 'douban' },
|
||||
]"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="SystemSettings.Basic.MEDIASERVER_SYNC_INTERVAL"
|
||||
label="媒体服务器同步间隔"
|
||||
hint="定时同步媒体服务器数据到本地的时间间隔"
|
||||
:label="t('setting.system.mediaServerSyncInterval')"
|
||||
:hint="t('setting.system.mediaServerSyncIntervalHint')"
|
||||
persistent-hint
|
||||
suffix="小时"
|
||||
:suffix="t('setting.system.hours')"
|
||||
type="number"
|
||||
min="1"
|
||||
:rules="[
|
||||
(v: any) => !!v || '必选项,请勿留空',
|
||||
(v: any) => !isNaN(v) || '仅支持输入数字,请勿输入其他字符',
|
||||
(v: any) => v >= 1 || '间隔不能小于1个小时',
|
||||
(v: any) => !!v || t('setting.system.required'),
|
||||
(v: any) => !isNaN(v) || t('setting.system.numbersOnly'),
|
||||
(v: any) => v >= 1 || t('setting.system.minInterval'),
|
||||
]"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="SystemSettings.Basic.API_TOKEN"
|
||||
label="API令牌"
|
||||
hint="设置外部请求MoviePilot API时使用的token值"
|
||||
placeholder="不能小于16位字符"
|
||||
:label="t('setting.system.apiToken')"
|
||||
:hint="t('setting.system.apiTokenHint')"
|
||||
:placeholder="t('setting.system.apiTokenMinChars')"
|
||||
persistent-hint
|
||||
prependInnerIcon="mdi-reload"
|
||||
:appendInnerIcon="SystemSettings.Basic.API_TOKEN ? 'mdi-content-copy' : ''"
|
||||
@click:prependInner="createRandomString"
|
||||
@click:appendInner="copyValue(SystemSettings.Basic.API_TOKEN)"
|
||||
:rules="[(v: string) => !!v || '必填项;请输入API Token', (v: string) => v.length >= 16 || 'API Token不得低于16位']"
|
||||
:rules="[
|
||||
(v: string) => !!v || t('setting.system.apiTokenRequired'),
|
||||
(v: string) => v.length >= 16 || t('setting.system.apiTokenLength'),
|
||||
]"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="SystemSettings.Basic.GITHUB_TOKEN"
|
||||
label="Github Token"
|
||||
placeholder="ghp_**** 或 github_pat_****"
|
||||
hint="用于提高插件等访问Github API时的限流阈值"
|
||||
:label="t('setting.system.githubToken')"
|
||||
:placeholder="t('setting.system.githubTokenFormat')"
|
||||
:hint="t('setting.system.githubTokenHint')"
|
||||
persistent-hint
|
||||
>
|
||||
</VTextField>
|
||||
@@ -439,9 +469,9 @@ onDeactivated(() => {
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
v-model="SystemSettings.Basic.OCR_HOST"
|
||||
label="验证码识别服务器"
|
||||
:label="t('setting.system.ocrHost')"
|
||||
placeholder="https://movie-pilot.org"
|
||||
hint="用于站点签到、更新站点Cookie等识别验证码"
|
||||
:hint="t('setting.system.ocrHostHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCol>
|
||||
@@ -451,7 +481,7 @@ onDeactivated(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveBasicSettings"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveBasicSettings"> {{ t('common.save') }} </VBtn>
|
||||
<VSpacer />
|
||||
<VBtn
|
||||
color="error"
|
||||
@@ -459,7 +489,7 @@ onDeactivated(() => {
|
||||
prepend-icon="mdi-cog"
|
||||
append-icon="mdi-dots-horizontal"
|
||||
>
|
||||
高级设置
|
||||
{{ t('setting.system.advancedSettings') }}
|
||||
</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
@@ -471,8 +501,8 @@ onDeactivated(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>下载器</VCardTitle>
|
||||
<VCardSubtitle>只有默认下载器才会被默认使用。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.system.downloaders') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.system.downloadersDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
@@ -496,7 +526,7 @@ onDeactivated(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveDownloaderSetting"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveDownloaderSetting"> {{ t('common.save') }} </VBtn>
|
||||
<VBtn color="success" variant="tonal">
|
||||
<VIcon icon="mdi-plus" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
@@ -520,8 +550,8 @@ onDeactivated(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>媒体服务器</VCardTitle>
|
||||
<VCardSubtitle>所有启用的媒体服务器都会被使用。</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.system.mediaServers') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.system.mediaServersDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
@@ -544,7 +574,7 @@ onDeactivated(() => {
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveMediaServerSetting"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveMediaServerSetting"> {{ t('common.save') }} </VBtn>
|
||||
<VBtn color="success" variant="tonal">
|
||||
<VIcon icon="mdi-plus" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
@@ -559,7 +589,7 @@ onDeactivated(() => {
|
||||
<VListItemTitle>Plex</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="addMediaServer('trimemedia')">
|
||||
<VListItemTitle>飞牛影视</VListItemTitle>
|
||||
<VListItemTitle>{{ t('setting.system.trimeMedia') }}</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
@@ -575,25 +605,25 @@ onDeactivated(() => {
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VDialogCloseBtn @click="advancedDialog = false" />
|
||||
<VCardTitle>高级设置</VCardTitle>
|
||||
<VCardSubtitle>系统进阶设置,特殊情况下才需要调整</VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.system.advancedSettings') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.system.advancedSettingsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VTabs v-model="activeTab" show-arrows>
|
||||
<VTab value="system">
|
||||
<div>系统</div>
|
||||
<div>{{ t('setting.system.system') }}</div>
|
||||
</VTab>
|
||||
<VTab value="media">
|
||||
<div>媒体</div>
|
||||
<div>{{ t('setting.system.media') }}</div>
|
||||
</VTab>
|
||||
<VTab value="network">
|
||||
<div>网络</div>
|
||||
<div>{{ t('setting.system.network') }}</div>
|
||||
</VTab>
|
||||
<VTab value="log">
|
||||
<div>日志</div>
|
||||
<div>{{ t('setting.system.log') }}</div>
|
||||
</VTab>
|
||||
<VTab value="dev">
|
||||
<div>实验室</div>
|
||||
<div>{{ t('setting.system.lab') }}</div>
|
||||
</VTab>
|
||||
</VTabs>
|
||||
<VWindow v-model="activeTab" class="mt-5 disable-tab-transition" :touch="false">
|
||||
@@ -862,13 +892,11 @@ onDeactivated(() => {
|
||||
@click="saveAdvancedSettings"
|
||||
class="px-5"
|
||||
>
|
||||
保存
|
||||
{{ t('common.save') }}
|
||||
</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" text="正在应用配置..." />
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import api from '@/api'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
@@ -60,14 +64,13 @@ async function queryTransferExcludeWords() {
|
||||
// 保存用户设置的识别词
|
||||
async function saveCustomIdentifiers() {
|
||||
try {
|
||||
// 用户名密码
|
||||
const result: { [key: string]: any } = await api.post(
|
||||
'system/setting/CustomIdentifiers',
|
||||
customIdentifiers.value.split('\n'),
|
||||
)
|
||||
|
||||
if (result.success) $toast.success('自定义识别词保存成功')
|
||||
else $toast.error('自定义识别词保存失败!')
|
||||
if (result.success) $toast.success(t('setting.words.identifierSaveSuccess'))
|
||||
else $toast.error(t('setting.words.identifierSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -76,14 +79,13 @@ async function saveCustomIdentifiers() {
|
||||
// 保存自定义制作组
|
||||
async function saveCustomReleaseGroups() {
|
||||
try {
|
||||
// 用户名密码
|
||||
const result: { [key: string]: any } = await api.post(
|
||||
'system/setting/CustomReleaseGroups',
|
||||
customReleaseGroups.value.split('\n'),
|
||||
)
|
||||
|
||||
if (result.success) $toast.success('自定义制作组/字幕组保存成功')
|
||||
else $toast.error('自定义制作组/字幕组保存失败!')
|
||||
if (result.success) $toast.success(t('setting.words.releaseGroupSaveSuccess'))
|
||||
else $toast.error(t('setting.words.releaseGroupSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -92,14 +94,13 @@ async function saveCustomReleaseGroups() {
|
||||
// 保存自定义占位符
|
||||
async function saveCustomization() {
|
||||
try {
|
||||
// 用户名密码
|
||||
const result: { [key: string]: any } = await api.post(
|
||||
'system/setting/Customization',
|
||||
customization.value.split('\n'),
|
||||
)
|
||||
|
||||
if (result.success) $toast.success('自定义占位符保存成功')
|
||||
else $toast.error('自定义占位符保存失败!')
|
||||
if (result.success) $toast.success(t('setting.words.customizationSaveSuccess'))
|
||||
else $toast.error(t('setting.words.customizationSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -108,14 +109,13 @@ async function saveCustomization() {
|
||||
// 保存文件整理屏蔽词
|
||||
async function saveTransferExcludeWords() {
|
||||
try {
|
||||
// 用户名密码
|
||||
const result: { [key: string]: any } = await api.post(
|
||||
'system/setting/TransferExcludeWords',
|
||||
transferExcludeWords.value.split('\n'),
|
||||
)
|
||||
|
||||
if (result.success) $toast.success('文件整理屏蔽词保存成功')
|
||||
else $toast.error('文件整理屏蔽词保存失败!')
|
||||
if (result.success) $toast.success(t('setting.words.excludeWordsSaveSuccess'))
|
||||
else $toast.error(t('setting.words.excludeWordsSaveFailed'))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
@@ -134,36 +134,26 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>自定义识别词</VCardTitle>
|
||||
<VCardSubtitle> 添加规则对种子名或者文件名进行预处理以校正识别。 </VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.words.customIdentifiers') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.words.identifiersDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VTextarea
|
||||
v-model="customIdentifiers"
|
||||
placeholder="支持正则表达式,特殊字符需要\转义,一行为一组"
|
||||
hint="支持正则表达式,特殊字符需要\转义,一行为一组"
|
||||
:placeholder="t('setting.words.identifiersPlaceholder')"
|
||||
:hint="t('setting.words.identifiersHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VAlert type="info" variant="tonal" title="支持的配置格式(注意空格):">
|
||||
<span
|
||||
v-html="
|
||||
`
|
||||
屏蔽词<br>
|
||||
被替换词 => 替换词<br>
|
||||
前定位词 <> 后定位词 >> 集偏移量(EP)<br>
|
||||
被替换词 => 替换词 && 前定位词 <> 后定位词 >> 集偏移量(EP)<br>
|
||||
其中替换词支持格式:{[tmdbid/doubanid=xxx;type=movie/tv;s=xxx;e=xxx]} 直接指定TMDBID/豆瓣ID识别,其中s、e为季数和集数(可选)<br>
|
||||
`
|
||||
"
|
||||
/>
|
||||
<VAlert type="info" variant="tonal" :title="t('setting.words.formatTitle')">
|
||||
<div style="white-space: pre-line" v-html="t('setting.words.formatContent').split('\n').join('<br>')"></div>
|
||||
</VAlert>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveCustomIdentifiers"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveCustomIdentifiers">{{ t('common.save') }}</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -174,21 +164,21 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>自定义制作组/字幕组</VCardTitle>
|
||||
<VCardSubtitle> 添加无法识别的制作组/字幕组。 </VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.words.customReleaseGroups') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.words.releaseGroupsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VTextarea
|
||||
v-model="customReleaseGroups"
|
||||
placeholder="支持正则表达式,特殊字符需要\转义,一行代表一个制作组/字幕组"
|
||||
hint="支持正则表达式,特殊字符需要\转义,一行代表一个制作组/字幕组"
|
||||
:placeholder="t('setting.words.releaseGroupsPlaceholder')"
|
||||
:hint="t('setting.words.releaseGroupsHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveCustomReleaseGroups"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveCustomReleaseGroups">{{ t('common.save') }}</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -199,21 +189,21 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>自定义占位符</VCardTitle>
|
||||
<VCardSubtitle> 添加自定义占位符识别正则,重命名格式中添加{customization}使用。 </VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.words.customization') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.words.customizationDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VTextarea
|
||||
v-model="customization"
|
||||
placeholder="支持正则表达式,特殊字符需要\转义,多个匹配对象请换行分隔"
|
||||
hint="支持正则表达式,特殊字符需要\转义,多个匹配对象请换行分隔"
|
||||
:placeholder="t('setting.words.customizationPlaceholder')"
|
||||
:hint="t('setting.words.customizationHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveCustomization"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveCustomization">{{ t('common.save') }}</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
@@ -224,21 +214,21 @@ onMounted(() => {
|
||||
<VCol cols="12">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>文件整理屏蔽词</VCardTitle>
|
||||
<VCardSubtitle> 目录名或文件名中包含屏蔽词时不进行整理。 </VCardSubtitle>
|
||||
<VCardTitle>{{ t('setting.words.transferExcludeWords') }}</VCardTitle>
|
||||
<VCardSubtitle>{{ t('setting.words.excludeWordsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VTextarea
|
||||
v-model="transferExcludeWords"
|
||||
placeholder="支持正则表达式,特殊字符需要\转义,一行代表一个屏蔽词"
|
||||
hint="支持正则表达式,特殊字符需要\转义,一行代表一个屏蔽词"
|
||||
:placeholder="t('setting.words.excludeWordsPlaceholder')"
|
||||
:hint="t('setting.words.excludeWordsHint')"
|
||||
persistent-hint
|
||||
/>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
||||
<VBtn type="submit" @click="saveTransferExcludeWords"> 保存 </VBtn>
|
||||
<VBtn type="submit" @click="saveTransferExcludeWords">{{ t('common.save') }}</VBtn>
|
||||
</div>
|
||||
</VForm>
|
||||
</VCardText>
|
||||
|
||||
Reference in New Issue
Block a user