mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 23:56:42 +08:00
fix key index issue
This commit is contained in:
@@ -85,22 +85,16 @@ function parseStoragePath(path: string): [prefix: string, suffix: string] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新存储路径前缀
|
// 更新存储路径前缀
|
||||||
function updateStoragePrefix(index: number, storage: string) {
|
function updateStoragePrefix(row: PathMappingRow, storage: string) {
|
||||||
if (!downloaderInfo.value.path_mapping) return
|
const [, currentSuffix] = parseStoragePath(row.storage)
|
||||||
const currentMapping = downloaderInfo.value.path_mapping[index]
|
|
||||||
const currentPath = currentMapping[0] || ''
|
|
||||||
const [, currentSuffix] = parseStoragePath(currentPath)
|
|
||||||
const prefix = storage2Prefix(storage)
|
const prefix = storage2Prefix(storage)
|
||||||
currentMapping[0] = prefix + currentSuffix
|
row.storage = prefix + currentSuffix
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新存储路径后缀
|
// 更新存储路径后缀
|
||||||
function updateStorageSuffix(index: number, suffix: string) {
|
function updateStorageSuffix(row: PathMappingRow, suffix: string) {
|
||||||
if (!downloaderInfo.value.path_mapping) return
|
const [currentPrefix] = parseStoragePath(row.storage)
|
||||||
const currentMapping = downloaderInfo.value.path_mapping[index]
|
row.storage = currentPrefix + suffix
|
||||||
const currentPath = currentMapping[0] || ''
|
|
||||||
const [currentPrefix] = parseStoragePath(currentPath)
|
|
||||||
currentMapping[0] = currentPrefix + suffix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathValidationRules = [
|
const pathValidationRules = [
|
||||||
@@ -115,8 +109,24 @@ const downloaderInfo = ref<DownloaderConf>({
|
|||||||
default: false,
|
default: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
config: {},
|
config: {},
|
||||||
|
path_mapping: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 路径映射行定义
|
||||||
|
interface PathMappingRow {
|
||||||
|
id: string
|
||||||
|
storage: string
|
||||||
|
download: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路径映射行数据
|
||||||
|
const pathMappingRows = ref<PathMappingRow[]>([])
|
||||||
|
|
||||||
|
// 生成随机ID
|
||||||
|
function generateId() {
|
||||||
|
return Math.random().toString(36).substring(2, 9)
|
||||||
|
}
|
||||||
|
|
||||||
// 下载器是否应该刷新数据的计算属性
|
// 下载器是否应该刷新数据的计算属性
|
||||||
const shouldRefresh = computed(() => props.allowRefresh && props.downloader.enabled)
|
const shouldRefresh = computed(() => props.allowRefresh && props.downloader.enabled)
|
||||||
|
|
||||||
@@ -148,6 +158,12 @@ async function loadDownloaderInfo() {
|
|||||||
function openDownloaderInfoDialog() {
|
function openDownloaderInfoDialog() {
|
||||||
// 深复制
|
// 深复制
|
||||||
downloaderInfo.value = cloneDeep(props.downloader)
|
downloaderInfo.value = cloneDeep(props.downloader)
|
||||||
|
// 初始化路径映射行数据
|
||||||
|
pathMappingRows.value = (downloaderInfo.value.path_mapping || []).map(item => ({
|
||||||
|
id: generateId(),
|
||||||
|
storage: item[0],
|
||||||
|
download: item[1],
|
||||||
|
}))
|
||||||
downloaderInfoDialog.value = true
|
downloaderInfoDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +173,9 @@ async function saveDownloaderInfo() {
|
|||||||
const { valid } = await downloaderForm.value?.validate()
|
const { valid } = await downloaderForm.value?.validate()
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
|
|
||||||
|
// 同步路径映射数据
|
||||||
|
downloaderInfo.value.path_mapping = pathMappingRows.value.map(row => [row.storage, row.download])
|
||||||
|
|
||||||
// 为空不保存,跳出警告框
|
// 为空不保存,跳出警告框
|
||||||
if (!downloaderInfo.value.name) {
|
if (!downloaderInfo.value.name) {
|
||||||
$toast.error(t('downloader.nameRequired'))
|
$toast.error(t('downloader.nameRequired'))
|
||||||
@@ -196,15 +215,16 @@ const getIcon = computed(() => {
|
|||||||
|
|
||||||
// 添加路径映射
|
// 添加路径映射
|
||||||
function addPathMapping() {
|
function addPathMapping() {
|
||||||
if (!downloaderInfo.value.path_mapping) {
|
pathMappingRows.value.push({
|
||||||
downloaderInfo.value.path_mapping = []
|
id: generateId(),
|
||||||
}
|
storage: '',
|
||||||
downloaderInfo.value.path_mapping.push(['', ''])
|
download: ''
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除路径映射
|
// 移除路径映射
|
||||||
function removePathMapping(index: number) {
|
function removePathMapping(index: number) {
|
||||||
downloaderInfo.value.path_mapping?.splice(index, 1)
|
pathMappingRows.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按钮点击
|
// 按钮点击
|
||||||
@@ -482,30 +502,30 @@ onUnmounted(() => {
|
|||||||
<VCol cols="12">
|
<VCol cols="12">
|
||||||
<VLabel class="mb-2">{{ t('downloader.pathMapping') }}</VLabel>
|
<VLabel class="mb-2">{{ t('downloader.pathMapping') }}</VLabel>
|
||||||
<VRow
|
<VRow
|
||||||
v-for="(mapping, index) in downloaderInfo.path_mapping"
|
v-for="(row, index) in pathMappingRows"
|
||||||
:key="mapping[0] + '-' + mapping[1]"
|
:key="row.id"
|
||||||
class="align-start flex-wrap pm-row"
|
class="align-start flex-wrap pm-row"
|
||||||
>
|
>
|
||||||
<VCol cols="12" md="6" class="pl-0 pr-0">
|
<VCol cols="12" md="6" class="pl-0 pr-0">
|
||||||
<div class="d-flex flex-nowrap align-start">
|
<div class="d-flex flex-nowrap align-start">
|
||||||
<VTextField
|
<VTextField
|
||||||
class="rp-input"
|
class="rp-input"
|
||||||
:model-value="parseStoragePath(mapping[0])[1]"
|
:model-value="parseStoragePath(row.storage)[1]"
|
||||||
:placeholder="t('downloader.storagePath')"
|
:placeholder="t('downloader.storagePath')"
|
||||||
density="compact"
|
density="compact"
|
||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
:rules="pathValidationRules"
|
:rules="pathValidationRules"
|
||||||
@update:model-value="v => updateStorageSuffix(index, v)"
|
@update:model-value="v => updateStorageSuffix(row, v)"
|
||||||
append-icon="mdi-arrow-right"
|
append-icon="mdi-arrow-right"
|
||||||
>
|
>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<VSelect
|
<VSelect
|
||||||
class="rp-select"
|
class="rp-select"
|
||||||
:model-value="getStorageType(mapping[0])"
|
:model-value="getStorageType(row.storage)"
|
||||||
:items="prefixOptions"
|
:items="prefixOptions"
|
||||||
density="compact"
|
density="compact"
|
||||||
hide-details
|
hide-details
|
||||||
@update:model-value="v => updateStoragePrefix(index, v)"
|
@update:model-value="v => updateStoragePrefix(row, v)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VTextField>
|
</VTextField>
|
||||||
@@ -513,7 +533,7 @@ onUnmounted(() => {
|
|||||||
</VCol>
|
</VCol>
|
||||||
<VCol cols="12" md="6" class="pl-0 pr-0">
|
<VCol cols="12" md="6" class="pl-0 pr-0">
|
||||||
<VTextField
|
<VTextField
|
||||||
v-model="mapping[1]"
|
v-model="row.download"
|
||||||
:placeholder="t('downloader.downloadPath')"
|
:placeholder="t('downloader.downloadPath')"
|
||||||
density="compact"
|
density="compact"
|
||||||
hide-details="auto"
|
hide-details="auto"
|
||||||
|
|||||||
Reference in New Issue
Block a user