From 8add4e6b46a195636a15a8f6da52b195f08ee008 Mon Sep 17 00:00:00 2001 From: stkevintan Date: Mon, 8 Dec 2025 14:01:42 +0800 Subject: [PATCH] implement path mapping UI --- src/components/cards/DownloaderCard.vue | 155 ++++++++++++++++-------- src/locales/en-US.ts | 3 +- src/locales/zh-CN.ts | 3 +- src/locales/zh-TW.ts | 3 +- 4 files changed, 110 insertions(+), 54 deletions(-) diff --git a/src/components/cards/DownloaderCard.vue b/src/components/cards/DownloaderCard.vue index df07b83a..17704512 100644 --- a/src/components/cards/DownloaderCard.vue +++ b/src/components/cards/DownloaderCard.vue @@ -55,19 +55,50 @@ const downloaderInfoDialog = ref(false) // 表单 const downloaderForm = ref() -// 路径校验规则 -const remotePathRules = [ - (v: string) => !!v || t('downloader.pathMappingRequired'), - (v: string) => { - const prefixes = storageAttributes.map(s => (s.type === 'local' ? '/' : `${s.type}:/`)) - const pattern = new RegExp(`^(${prefixes.join('|')})`) - return pattern.test(v) || t('downloader.pathMappingFormatError') - }, -] +// 路径前缀选项 +const prefixOptions = computed(() => { + return storageAttributes.map(item => ({ + title: t(`storage.${item.type}`), + value: `${item.type}:`, + })) +}) -const localPathRules = [ +// 获取远程路径前缀 +function getRemotePrefix(path: string) { + if (!path) return 'local:' + const match = prefixOptions.value + .find(p => path.startsWith(p.value)) + return match ? match.value : 'local:' +} + +// 获取远程路径后缀 +function getRemotePath(path: string) { + if (!path) return '' + const prefix = getRemotePrefix(path) + return path.replace(new RegExp(`^${prefix}`), '') +} + +// 更新远程路径前缀 +function updateRemotePrefix(index: number, prefix: string) { + if (!downloaderInfo.value.path_mapping) return + const currentPath = downloaderInfo.value.path_mapping[index][0] || '' + const currentSuffix = getRemotePath(currentPath) + prefix = prefix === 'local:' ? '' : prefix // 本地路径前缀为空 + downloaderInfo.value.path_mapping[index][0] = prefix + currentSuffix +} + +// 更新远程路径后缀 +function updateRemotePath(index: number, suffix: string) { + if (!downloaderInfo.value.path_mapping) return + const currentPath = downloaderInfo.value.path_mapping[index][0] || '' + let currentPrefix = getRemotePrefix(currentPath) + currentPrefix = currentPrefix === 'local:' ? '' : currentPrefix // 本地路径前缀为空 + downloaderInfo.value.path_mapping[index][0] = currentPrefix + suffix +} + +const downloadPathRules = [ (v: string) => !!v || t('downloader.pathMappingRequired'), - (v: string) => v.startsWith('/') || t('downloader.pathMappingLocalError'), + (v: string) => v.startsWith('/') || t('downloader.pathMappingError'), ] // 下载器详情 @@ -189,19 +220,32 @@ onUnmounted(() => {