重构 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

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup>
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 { nextTick } from 'vue'
import { storageOptions } from '@/api/constants'
@@ -210,7 +210,7 @@ watch(
/>
</VCol>
<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 }">
<VTextField
:model-value="props.directory.download_path"
@@ -219,7 +219,7 @@ watch(
label="下载目录/源目录"
/>
</template>
</VPathField>
</PathInput>
</VCol>
<VCol cols="6" v-if="!props.directory.media_type || props.directory.media_type === ''">
<VSwitch v-model="props.directory.download_type_folder" label="按类型分类"></VSwitch>
@@ -257,7 +257,7 @@ watch(
/>
</VCol>
<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 }">
<VTextField
:modelValue="props.directory.library_path"
@@ -266,7 +266,7 @@ watch(
label="媒体库目录"
/>
</template>
</VPathField>
</PathInput>
</VCol>
<VCol cols="4">
<VSelect

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>

View File

@@ -3,7 +3,7 @@ import api from '@/api'
import { FileItem } from '@/api/types'
const props = defineProps({
cron: {
modelValue: {
type: String,
default: '* * * * *',
},
@@ -14,8 +14,15 @@ const emit = defineEmits(['update:modelValue'])
const currentCron = ref(props.cron)
watch(currentCron, newVal => {
emit('update:modelValue', currentCron.value)
emit('update:modelValue', newVal)
})
watch(
() => props.modelValue,
value => {
currentCron.value = value
},
)
</script>
<template>
@@ -24,7 +31,11 @@ watch(currentCron, newVal => {
<template v-slot:activator="{ props }">
<slot name="activator" :menuprops="props" />
</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>
</div>
</template>

View File

@@ -93,6 +93,7 @@ const renderComponent = (config: any, model: any, slotScope: any = {}) => {
<template>
<!-- 调用递归渲染函数 -->
<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>
</template>

View File

@@ -3,6 +3,14 @@ import '@/@core/utils/compatibility'
import '@/@iconify/icons-bundle'
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 vuetify from '@/plugins/vuetify'
import router from '@/router'
@@ -18,16 +26,7 @@ import PersonCard from './components/cards/PersonCard.vue'
import MediaInfoCard from './components/cards/MediaInfoCard.vue'
import TorrentCard from './components/cards/TorrentCard.vue'
import MediaIdSelector from './components/misc/MediaIdSelector.vue'
import PathField from './components/input/PathField.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 CronField from './components/field/CronField.vue'
import '@core/scss/template/index.scss'
import '@layouts/styles/index.scss'
@@ -70,8 +69,7 @@ initializeApp().then(() => {
.component('VMediaInfoCard', MediaInfoCard)
.component('VTorrentCard', TorrentCard)
.component('VMediaIdSelector', MediaIdSelector)
.component('VPathField', PathField)
.component('VCronInput', CronInput)
.component('VCronField', CronField)
// 注册插件
app