mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
重构存储选项,更新为存储属性,优化存储字典和图标字典的生成逻辑,提升组件对存储配置的支持
This commit is contained in:
+15
-16
@@ -1,49 +1,48 @@
|
|||||||
import i18n from '@/plugins/i18n'
|
import i18n from '@/plugins/i18n'
|
||||||
|
|
||||||
export const storageOptions = [
|
export const storageAttributes = [
|
||||||
{
|
{
|
||||||
title: i18n.global.t('storage.local'),
|
type: 'local',
|
||||||
value: 'local',
|
|
||||||
icon: 'mdi-folder-multiple-outline',
|
icon: 'mdi-folder-multiple-outline',
|
||||||
remote: false,
|
remote: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.global.t('storage.alipan'),
|
type: 'alipan',
|
||||||
value: 'alipan',
|
|
||||||
icon: 'mdi-cloud-outline',
|
icon: 'mdi-cloud-outline',
|
||||||
remote: true,
|
remote: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.global.t('storage.u115'),
|
type: 'u115',
|
||||||
value: 'u115',
|
|
||||||
icon: 'mdi-cloud-outline',
|
icon: 'mdi-cloud-outline',
|
||||||
remote: true,
|
remote: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.global.t('storage.rclone'),
|
type: 'rclone',
|
||||||
value: 'rclone',
|
|
||||||
icon: 'mdi-server-network-outline',
|
icon: 'mdi-server-network-outline',
|
||||||
remote: true,
|
remote: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.global.t('storage.alist'),
|
type: 'alist',
|
||||||
value: 'alist',
|
|
||||||
icon: 'mdi-server-network-outline',
|
icon: 'mdi-server-network-outline',
|
||||||
remote: true,
|
remote: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.global.t('storage.custom'),
|
type: 'custom',
|
||||||
value: 'custom',
|
icon: 'mdi-database',
|
||||||
icon: 'mdi-cog-outline',
|
|
||||||
remote: true,
|
remote: true,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export const storageDict = storageOptions.reduce((dict, item) => {
|
export const storageIconDict = storageAttributes.reduce((dict, item) => {
|
||||||
dict[item.value] = item.title
|
dict[item.type] = item.icon
|
||||||
return dict
|
return dict
|
||||||
}, {} as Record<string, string>)
|
}, {} as Record<string, string>)
|
||||||
|
|
||||||
|
export const storageRemoteDict = storageAttributes.reduce((dict, item) => {
|
||||||
|
dict[item.type] = item.remote
|
||||||
|
return dict
|
||||||
|
}, {} as Record<string, boolean>)
|
||||||
|
|
||||||
export const innerFilterRules = [
|
export const innerFilterRules = [
|
||||||
{ title: i18n.global.t('filterRules.specSub'), value: ' SPECSUB ' },
|
{ title: i18n.global.t('filterRules.specSub'), value: ' SPECSUB ' },
|
||||||
{ title: i18n.global.t('filterRules.cnSub'), value: ' CNSUB ' },
|
{ title: i18n.global.t('filterRules.cnSub'), value: ' CNSUB ' },
|
||||||
|
|||||||
@@ -3,12 +3,8 @@ import FileList from './filebrowser/FileList.vue'
|
|||||||
import FileToolbar from './filebrowser/FileToolbar.vue'
|
import FileToolbar from './filebrowser/FileToolbar.vue'
|
||||||
import FileNavigator from './filebrowser/FileNavigator.vue'
|
import FileNavigator from './filebrowser/FileNavigator.vue'
|
||||||
import type { EndPoints, FileItem, StorageConf } from '@/api/types'
|
import type { EndPoints, FileItem, StorageConf } from '@/api/types'
|
||||||
import { storageOptions } from '@/api/constants'
|
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { storageIconDict } from '@/api/constants'
|
||||||
|
|
||||||
// 国际化
|
|
||||||
const { t } = useI18n()
|
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -142,8 +138,11 @@ const showDirTree = ref(false)
|
|||||||
|
|
||||||
// 计算属性
|
// 计算属性
|
||||||
const storagesArray = computed(() => {
|
const storagesArray = computed(() => {
|
||||||
const storageCodes = props.storages?.map(item => item.type)
|
return props.storages?.map(item => ({
|
||||||
return storageOptions.filter(item => storageCodes?.includes(item.value))
|
title: item.name,
|
||||||
|
value: item.type,
|
||||||
|
icon: storageIconDict[item.type],
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { TransferDirectoryConf } from '@/api/types'
|
import type { StorageConf, TransferDirectoryConf } from '@/api/types'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { nextTick } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
import { storageOptions } from '@/api/constants'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { storageRemoteDict } from '@/api/constants'
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -19,6 +19,10 @@ const props = defineProps({
|
|||||||
type: Object as PropType<{ [key: string]: any }>,
|
type: Object as PropType<{ [key: string]: any }>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
storages: {
|
||||||
|
type: Array as PropType<StorageConf[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
width: String,
|
width: String,
|
||||||
height: String,
|
height: String,
|
||||||
})
|
})
|
||||||
@@ -35,7 +39,20 @@ const typeItems = computed(() => [
|
|||||||
|
|
||||||
// 计算资源存储字典(整理方式为下载器时不能为远程存储)
|
// 计算资源存储字典(整理方式为下载器时不能为远程存储)
|
||||||
const resourceStorageOptions = computed(() => {
|
const resourceStorageOptions = computed(() => {
|
||||||
return storageOptions.filter(item => !item.remote || props.directory.monitor_type !== 'downloader')
|
return props.storages
|
||||||
|
.filter(item => !storageRemoteDict[item.type] || props.directory.monitor_type !== 'downloader')
|
||||||
|
.map(item => ({
|
||||||
|
title: item.name,
|
||||||
|
value: item.type,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
// 存储字典
|
||||||
|
const libraryStorageOptions = computed(() => {
|
||||||
|
return props.storages.map(item => ({
|
||||||
|
title: item.name,
|
||||||
|
value: item.type,
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
// 自动整理方式下拉字典
|
// 自动整理方式下拉字典
|
||||||
@@ -263,7 +280,7 @@ watch(
|
|||||||
<VSelect
|
<VSelect
|
||||||
v-model="props.directory.library_storage"
|
v-model="props.directory.library_storage"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
:items="storageOptions"
|
:items="libraryStorageOptions"
|
||||||
:label="t('directory.libraryStorage')"
|
:label="t('directory.libraryStorage')"
|
||||||
/>
|
/>
|
||||||
</VCol>
|
</VCol>
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import MediaIdSelector from '../misc/MediaIdSelector.vue'
|
import MediaIdSelector from '../misc/MediaIdSelector.vue'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { storageOptions, transferTypeOptions } from '@/api/constants'
|
import { transferTypeOptions } from '@/api/constants'
|
||||||
import { numberValidator } from '@/@validators'
|
import { numberValidator } from '@/@validators'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import ProgressDialog from './ProgressDialog.vue'
|
import ProgressDialog from './ProgressDialog.vue'
|
||||||
import { FileItem, TransferDirectoryConf, TransferForm } from '@/api/types'
|
import { FileItem, StorageConf, TransferDirectoryConf, TransferForm } from '@/api/types'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
@@ -58,6 +58,28 @@ const progressText = ref(t('dialog.reorganize.processing'))
|
|||||||
// 整理进度
|
// 整理进度
|
||||||
const progressValue = ref(0)
|
const progressValue = ref(0)
|
||||||
|
|
||||||
|
// 所有存储
|
||||||
|
const storages = ref<StorageConf[]>([])
|
||||||
|
|
||||||
|
// 查询存储
|
||||||
|
async function loadStorages() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/Storages')
|
||||||
|
|
||||||
|
storages.value = result.data?.value ?? []
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存储字典
|
||||||
|
const storageOptions = computed(() => {
|
||||||
|
return storages.value.map(item => ({
|
||||||
|
title: item.name,
|
||||||
|
value: item.type,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
// 标题
|
// 标题
|
||||||
const dialogTitle = computed(() => {
|
const dialogTitle = computed(() => {
|
||||||
if (props.items) {
|
if (props.items) {
|
||||||
@@ -218,6 +240,7 @@ async function transfer(background: boolean = false) {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadDirectories()
|
loadDirectories()
|
||||||
|
loadStorages()
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import api from '@/api'
|
||||||
|
import { StorageConf } from '@/api/types'
|
||||||
import { Handle, Position } from '@vue-flow/core'
|
import { Handle, Position } from '@vue-flow/core'
|
||||||
import { storageOptions } from '@/api/constants'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -15,6 +16,27 @@ defineProps({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 所有存储
|
||||||
|
const storages = ref<StorageConf[]>([])
|
||||||
|
|
||||||
|
// 查询存储
|
||||||
|
async function loadStorages() {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/Storages')
|
||||||
|
storages.value = result.data?.value ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存储字典
|
||||||
|
const storageOptions = computed(() => {
|
||||||
|
return storages.value.map(item => ({
|
||||||
|
title: item.name,
|
||||||
|
value: item.type,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadStorages()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
import { debounce } from 'lodash-es'
|
import { debounce } from 'lodash-es'
|
||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type { TransferHistory } from '@/api/types'
|
import type { StorageConf, TransferHistory } from '@/api/types'
|
||||||
import ReorganizeDialog from '@/components/dialog/ReorganizeDialog.vue'
|
import ReorganizeDialog from '@/components/dialog/ReorganizeDialog.vue'
|
||||||
import TransferQueueDialog from '@/components/dialog/TransferQueueDialog.vue'
|
import TransferQueueDialog from '@/components/dialog/TransferQueueDialog.vue'
|
||||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import { storageDict } from '@/api/constants'
|
|
||||||
import { formatFileSize } from '@/@core/utils/formatters'
|
import { formatFileSize } from '@/@core/utils/formatters'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { storageAttributes } from '@/api/constants'
|
||||||
|
|
||||||
// i18n
|
// i18n
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -181,6 +181,28 @@ const deleteConfirmDialog = ref(false)
|
|||||||
// 确认框标题
|
// 确认框标题
|
||||||
const confirmTitle = ref('')
|
const confirmTitle = ref('')
|
||||||
|
|
||||||
|
// 所有存储
|
||||||
|
const storages = ref<StorageConf[]>([])
|
||||||
|
|
||||||
|
// 查询存储
|
||||||
|
async function loadStorages() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/Storages')
|
||||||
|
|
||||||
|
storages.value = result.data?.value ?? []
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存储字典
|
||||||
|
const storageDict = computed(() => {
|
||||||
|
return storages.value.reduce((dict, item) => {
|
||||||
|
dict[item.type] = item.name
|
||||||
|
return dict
|
||||||
|
}, {} as Record<string, string>)
|
||||||
|
})
|
||||||
|
|
||||||
// 转移方式字典
|
// 转移方式字典
|
||||||
const TransferDict: { [key: string]: string } = {
|
const TransferDict: { [key: string]: string } = {
|
||||||
copy: t('transferHistory.transferMode.copy'),
|
copy: t('transferHistory.transferMode.copy'),
|
||||||
@@ -432,7 +454,10 @@ function ensureNumber(value: any, defaultValue: number = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始加载数据
|
// 初始加载数据
|
||||||
onMounted(fetchData)
|
onMounted(() => {
|
||||||
|
loadStorages()
|
||||||
|
fetchData()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ onMounted(() => {
|
|||||||
<DirectoryCard
|
<DirectoryCard
|
||||||
:directory="element"
|
:directory="element"
|
||||||
:categories="mediaCategories"
|
:categories="mediaCategories"
|
||||||
|
:storages="storages"
|
||||||
@update:modelValue="(value: any) => {element.download_path = value?.download; element.library_path = value?.library}"
|
@update:modelValue="(value: any) => {element.download_path = value?.download; element.library_path = value?.library}"
|
||||||
@close="removeDirectory(element)"
|
@close="removeDirectory(element)"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user