重构 DirectoryCard 组件,替换 VPathField 为 PathInput;删除不再使用的 PathField 组件;更新 CronInput 组件以支持 v-model 绑定;添加 CronField 组件以简化 CRON 表达式输入

This commit is contained in:
jxxghp
2025-01-11 20:20:05 +08:00
parent 3023214072
commit 88c86f49bf
6 changed files with 77 additions and 21 deletions
+5 -5
View File
@@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { TransferDirectoryConf } from '@/api/types' import type { TransferDirectoryConf } from '@/api/types'
import { VDivider, VSpacer, VTextField } from 'vuetify/lib/components/index.mjs' import PathInput from '@/components/input/PathInput.vue'
import api from '@/api' import api from '@/api'
import { nextTick } from 'vue' import { nextTick } from 'vue'
import { storageOptions } from '@/api/constants' import { storageOptions } from '@/api/constants'
@@ -210,7 +210,7 @@ watch(
/> />
</VCol> </VCol>
<VCol cols="8"> <VCol cols="8">
<VPathField v-model="props.directory.download_path" :storage="props.directory.storage"> <PathInput v-model="props.directory.download_path" :storage="props.directory.storage">
<template #activator="{ menuprops }"> <template #activator="{ menuprops }">
<VTextField <VTextField
:model-value="props.directory.download_path" :model-value="props.directory.download_path"
@@ -219,7 +219,7 @@ watch(
label="下载目录/源目录" label="下载目录/源目录"
/> />
</template> </template>
</VPathField> </PathInput>
</VCol> </VCol>
<VCol cols="6" v-if="!props.directory.media_type || props.directory.media_type === ''"> <VCol cols="6" v-if="!props.directory.media_type || props.directory.media_type === ''">
<VSwitch v-model="props.directory.download_type_folder" label="按类型分类"></VSwitch> <VSwitch v-model="props.directory.download_type_folder" label="按类型分类"></VSwitch>
@@ -257,7 +257,7 @@ watch(
/> />
</VCol> </VCol>
<VCol cols="8"> <VCol cols="8">
<VPathField v-model="props.directory.library_path" :storage="props.directory.library_storage"> <PathInput v-model="props.directory.library_path" :storage="props.directory.library_storage">
<template #activator="{ menuprops }"> <template #activator="{ menuprops }">
<VTextField <VTextField
:modelValue="props.directory.library_path" :modelValue="props.directory.library_path"
@@ -266,7 +266,7 @@ watch(
label="媒体库目录" label="媒体库目录"
/> />
</template> </template>
</VPathField> </PathInput>
</VCol> </VCol>
<VCol cols="4"> <VCol cols="4">
<VSelect <VSelect
+46
View File
@@ -0,0 +1,46 @@
<script setup lang="ts">
import CronInput from '@/components/input/CronInput.vue'
const attrs = useAttrs()
const props = defineProps({
modelValue: {
type: String,
default: '* * * * *',
},
})
const emit = defineEmits(['update:modelValue'])
const innerValue = ref(props.modelValue)
watch(
() => props.modelValue,
value => {
innerValue.value = value
},
)
const propsWithoutModelValue = computed(() => {
const { modelValue, ...rest } = props
return { ...rest, ...attrs }
})
function updateModelValue(value: string) {
innerValue.value = value
emit('update:modelValue', value)
}
</script>
<template>
<CronInput v-model="innerValue" @update:modelValue="updateModelValue">
<template #activator="{ menuprops }">
<VTextField
:modelValue="innerValue"
@update:modelValue="updateModelValue"
v-bind="{ ...menuprops, ...propsWithoutModelValue }"
clearable
/>
</template>
</CronInput>
</template>
+14 -3
View File
@@ -3,7 +3,7 @@ import api from '@/api'
import { FileItem } from '@/api/types' import { FileItem } from '@/api/types'
const props = defineProps({ const props = defineProps({
cron: { modelValue: {
type: String, type: String,
default: '* * * * *', default: '* * * * *',
}, },
@@ -14,8 +14,15 @@ const emit = defineEmits(['update:modelValue'])
const currentCron = ref(props.cron) const currentCron = ref(props.cron)
watch(currentCron, newVal => { watch(currentCron, newVal => {
emit('update:modelValue', currentCron.value) emit('update:modelValue', newVal)
}) })
watch(
() => props.modelValue,
value => {
currentCron.value = value
},
)
</script> </script>
<template> <template>
@@ -24,7 +31,11 @@ watch(currentCron, newVal => {
<template v-slot:activator="{ props }"> <template v-slot:activator="{ props }">
<slot name="activator" :menuprops="props" /> <slot name="activator" :menuprops="props" />
</template> </template>
<VCronVuetify v-model="currentCron" locale="zh-CN" :chip-props="{ color: 'success' }" class="mt-1" /> <VList>
<VListItem>
<VCronVuetify v-model="currentCron" locale="zh-CN" :chip-props="{ color: 'success' }" class="mt-1" />
</VListItem>
</VList>
</VMenu> </VMenu>
</div> </div>
</template> </template>
+2 -1
View File
@@ -93,6 +93,7 @@ const renderComponent = (config: any, model: any, slotScope: any = {}) => {
<template> <template>
<!-- 调用递归渲染函数 --> <!-- 调用递归渲染函数 -->
<div> <div>
<component :is="renderComponent(config, model)" /> <Component v-if="config.html" :is="config.component" v-bind="config.props" v-html="config.html" />
<Component v-else :is="renderComponent(config, model)" />
</div> </div>
</template> </template>
+10 -12
View File
@@ -3,6 +3,14 @@ import '@/@core/utils/compatibility'
import '@/@iconify/icons-bundle' import '@/@iconify/icons-bundle'
import '@/plugins/webfontloader' import '@/plugins/webfontloader'
import { createApp } from 'vue'
import { VAceEditor } from 'vue3-ace-editor'
import { PerfectScrollbarPlugin } from 'vue3-perfect-scrollbar'
import { CronVuetify } from '@vue-js-cron/vuetify'
import { removeEl } from './@core/utils/dom'
import { fetchGlobalSettings } from './api'
import { isPWA } from './@core/utils/navigator'
import App from '@/App.vue' import App from '@/App.vue'
import vuetify from '@/plugins/vuetify' import vuetify from '@/plugins/vuetify'
import router from '@/router' import router from '@/router'
@@ -18,16 +26,7 @@ import PersonCard from './components/cards/PersonCard.vue'
import MediaInfoCard from './components/cards/MediaInfoCard.vue' import MediaInfoCard from './components/cards/MediaInfoCard.vue'
import TorrentCard from './components/cards/TorrentCard.vue' import TorrentCard from './components/cards/TorrentCard.vue'
import MediaIdSelector from './components/misc/MediaIdSelector.vue' import MediaIdSelector from './components/misc/MediaIdSelector.vue'
import PathField from './components/input/PathField.vue' import CronField from './components/field/CronField.vue'
import CronInput from './components/input/CronInput.vue'
import { createApp } from 'vue'
import { VAceEditor } from 'vue3-ace-editor'
import { PerfectScrollbarPlugin } from 'vue3-perfect-scrollbar'
import { CronVuetify } from '@vue-js-cron/vuetify'
import { removeEl } from './@core/utils/dom'
import { fetchGlobalSettings } from './api'
import { isPWA } from './@core/utils/navigator'
import '@core/scss/template/index.scss' import '@core/scss/template/index.scss'
import '@layouts/styles/index.scss' import '@layouts/styles/index.scss'
@@ -70,8 +69,7 @@ initializeApp().then(() => {
.component('VMediaInfoCard', MediaInfoCard) .component('VMediaInfoCard', MediaInfoCard)
.component('VTorrentCard', TorrentCard) .component('VTorrentCard', TorrentCard)
.component('VMediaIdSelector', MediaIdSelector) .component('VMediaIdSelector', MediaIdSelector)
.component('VPathField', PathField) .component('VCronField', CronField)
.component('VCronInput', CronInput)
// 注册插件 // 注册插件
app app