From aabe2d9c0d656f6dbd0273a711c9765acbf51444 Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期六, 05 七月 2025 11:25:58 +0800
Subject: [PATCH] add:corn 和任务管理
---
components/cron-generator.vue | 221 ++++++++++++++++++++
pages/regular/content-config.vue | 177 ++++++++++++++++
pages/regular/task-config.vue | 206 ++++++++++++++++++
3 files changed, 604 insertions(+), 0 deletions(-)
diff --git a/components/cron-generator.vue b/components/cron-generator.vue
new file mode 100644
index 0000000..0fe680a
--- /dev/null
+++ b/components/cron-generator.vue
@@ -0,0 +1,221 @@
+<template>
+ <div class="cron-generator">
+ <el-form :inline="true" label-width="100px">
+ <el-form-item label="定时类型" prop="type">
+ <el-select v-model="type" @change="handleTypeChange" style="width: 200px">
+ <el-option label="每月" value="monthly"/>
+ <el-option label="每周" value="weekly"/>
+ <el-option label="每天" value="daily"/>
+ <el-option label="每小时" value="hourly"/>
+ <el-option label="每隔N分钟" value="interval"/>
+ </el-select>
+ </el-form-item>
+
+ <el-form-item v-if="type==='monthly'" label="日期" prop="day">
+ <el-input-number
+ v-model="day"
+ :min="1"
+ :max="31"
+ controls-position="right"
+ style="width: 120px"
+ />
+ <span style="margin-left: 10px">日</span>
+ </el-form-item>
+
+ <el-form-item v-if="type==='weekly'" label="星期" prop="weekDay">
+ <el-select v-model="weekDay" style="width: 120px">
+ <el-option
+ v-for="(w, i) in weekList"
+ :key="i"
+ :label="w.label"
+ :value="w.value"
+ />
+ </el-select>
+ </el-form-item>
+
+ <el-form-item
+ v-if="['monthly','weekly','daily'].includes(type)"
+ label="时间"
+ prop="time"
+ >
+ <el-time-picker
+ v-model="time"
+ format="HH:mm"
+ value-format="HH:mm"
+ placeholder="选择时间"
+ style="width: 120px"
+ />
+ </el-form-item>
+
+ <el-form-item v-if="type==='interval'" label="间隔" prop="interval">
+ <el-input-number
+ v-model="interval"
+ :min="1"
+ :max="59"
+ controls-position="right"
+ style="width: 120px"
+ />
+ <span style="margin-left: 10px">分钟</span>
+ </el-form-item>
+ </el-form>
+
+ <el-alert
+ :title="'生成的 cron 表达式: ' + cronValue"
+ type="info"
+ show-icon
+ style="margin-top: 15px"
+ />
+ </div>
+</template>
+
+<script>
+export default {
+ props: {
+ value: {
+ type: String,
+ default: ''
+ }
+ },
+ data() {
+ return {
+ type: 'daily',
+ day: 1,
+ weekDay: 1,
+ time: '00:00',
+ interval: 5,
+ weekList: [
+ {label: '周日', value: 0},
+ {label: '周一', value: 1},
+ {label: '周二', value: 2},
+ {label: '周三', value: 3},
+ {label: '周四', value: 4},
+ {label: '周五', value: 5},
+ {label: '周六', value: 6},
+ ]
+ };
+ },
+ computed: {
+ cronValue: {
+ get() {
+ return this.value;
+ },
+ set(val) {
+ this.$emit('input', val);
+ }
+ }
+ },
+ watch: {
+ type() { this.generateCron(); },
+ day() { this.generateCron(); },
+ weekDay() { this.generateCron(); },
+ time() { this.generateCron(); },
+ interval() { this.generateCron(); },
+ value(newVal) {
+ // 外部 value 变化时,自动解析
+ this.setCron(newVal);
+ },
+ },
+ methods: {
+ setCron(cron) {
+ console.log("接收到 cron 值:", cron);
+ if (!cron || typeof cron !== 'string') {
+ return;
+ }
+
+ const parts = cron.split(' ');
+ if (parts.length < 6) return;
+
+ const second = parts[0];
+ const minute = parts[1];
+ const hour = parts[2];
+ const day = parts[3];
+ const weekday = parts[5];
+
+ if (minute.startsWith('*/')) {
+ this.type = 'interval';
+ this.interval = parseInt(minute.split('/')[1]);
+ } else if (day !== '*' && day !== '?') {
+ this.type = 'monthly';
+ this.day = parseInt(day);
+ this.time = `${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`;
+ } else if (weekday !== '*' && weekday !== '?') {
+ this.type = 'weekly';
+ this.weekDay = parseInt(weekday);
+ this.time = `${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`;
+ } else if (hour !== '*') {
+ this.type = 'daily';
+ this.time = `${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`;
+ } else {
+ this.type = 'hourly';
+ }
+ this.generateCron();
+ },
+
+
+ resetToDefault() {
+ this.type = 'daily';
+ this.day = 1;
+ this.weekDay = 1;
+ this.time = '00:00';
+ this.interval = 5;
+ this.generateCron();
+ },
+
+ handleTypeChange() {
+ if (this.type === 'monthly' && (this.day < 1 || this.day > 31)) {
+ this.day = 1;
+ }
+ if (this.type === 'interval' && (this.interval < 1 || this.interval > 59)) {
+ this.interval = 5;
+ }
+ this.generateCron();
+ },
+
+ generateCron() {
+ console.log("生成 cron 表达式,类型:", this.type);
+ let hour = 0;
+ let minute = 0;
+
+ if (this.time) {
+ [hour, minute] = this.time.split(':').map(Number);
+ } else {
+ this.time = '00:00';
+ }
+
+ switch(this.type) {
+ case 'monthly':
+ this.cronValue = `0 ${minute} ${hour} ${this.day} * ?`; // 添加秒位和?号
+ break;
+ case 'weekly':
+ this.cronValue = `0 ${minute} ${hour} ? * ${this.weekDay}`; // 添加秒位和?号
+ break;
+ case 'daily':
+ this.cronValue = `0 ${minute} ${hour} * * ?`; // 添加秒位和?号
+ break;
+ case 'hourly':
+ this.cronValue = `0 ${minute} * * * ?`; // 添加秒位和?号
+ break;
+ case 'interval':
+ // 间隔分钟需要特殊处理,转换为秒级间隔
+ this.cronValue = `0 */${this.interval} * * * ?`;
+ break;
+ default:
+ this.cronValue = '0 * * * * ?';
+ }
+ console.log("生成结果:", this.cronValue);
+ }
+ },
+ mounted() {
+ this.generateCron();
+ }
+}
+</script>
+
+<style scoped>
+.cron-generator {
+ padding: 15px;
+ border: 1px solid #ebeef5;
+ border-radius: 4px;
+ background-color: #f8f9fa;
+}
+</style>
diff --git a/pages/regular/content-config.vue b/pages/regular/content-config.vue
new file mode 100644
index 0000000..760a228
--- /dev/null
+++ b/pages/regular/content-config.vue
@@ -0,0 +1,177 @@
+:task-config.vue
+<template>
+ <el-bus-crud ref="crud" v-bind="tableConfig">
+ <!-- 不再需要自定义插槽 -->
+ </el-bus-crud>
+</template>
+
+<script>
+// 不再需要导入 CronGenerator,因为现在通过全局注册使用
+
+export default {
+ data() {
+ return {
+ tableConfig: {
+ defaultForm: {
+ taskName: '',
+ aiParams: '',
+ cron: '',
+ isEnabled: false
+ },
+ url: 'flower/api/aiTaskConfig/list',
+ newUrl: 'flower/api/aiTaskConfig/new',
+ editUrl: 'flower/api/aiTaskConfig/edit',
+ deleteUrl: 'flower/api/aiTaskConfig/delete',
+ dialogNeedRequest: false,
+ persistSelection: true,
+ columns: [
+ { type: 'selection' },
+ { label: '任务名称', prop: 'taskName' },
+ { label: 'AI参数', prop: 'aiParams' },
+ { label: 'cron表达式', prop: 'cron' },
+ {
+ label: '启用/禁用',
+ formatter: (row) => (
+ <el-switch
+ value={row.isEnabled}
+ onChange={(val) => this.onEnabledChange(row, val)}
+ ></el-switch>
+ ),
+ minWidth: 120,
+ fixed: 'right',
+ },
+ ],
+ searchForm: [
+ {
+ type: 'row',
+ items: [
+ { label: '任务名称', id: 'taskName', type: 'input' },
+ {
+ label: '启用/禁用',
+ id: 'isEnabled',
+ type: 'bus-select-dict',
+ default: '1',
+ el: {
+ code: 'USER_ENABLED_OR_DISABLED',
+ clearable: true,
+ style: 'width:100%',
+ },
+ },
+ ]
+ }
+ ],
+ form: [
+ { label: '任务名称', id: 'taskName', type: 'input', rules: { required: true, message: '请输入任务名称', trigger: 'blur' } },
+ { label: 'AI参数', id: 'aiParams', type: 'input', rules: { required: true, message: '请输入AI参数', trigger: 'blur' } },
+ {
+ label: '定时配置',
+ id: 'cron',
+ type: 'input',
+ // hidden: () => true, // 改为函数形式
+ rules: { required: true }
+ },
+ { label: '是否启用', id: 'isEnabled', type: 'switch' }
+ ],
+ extraButtons: [],
+ headerButtons: [
+ {
+ text: '批量删除',
+ type: 'danger',
+ disabled: selected => selected.length === 0,
+ atClick: async (selected) => {
+ if (!selected.length) return
+
+ try {
+ await this.$elBusUtil.confirm(`确定要批量删除这${selected.length}个任务吗?`)
+ const ids = selected.map(item => item.id)
+ await this.$elBusHttp.request('flower/api/filmTaskConfig/delete', {
+ method: 'post',
+ data: { ids }
+ })
+ this.$refs.crud.getList()
+ this.$message.success('删除成功')
+ } catch (error) {
+ if (error !== 'cancel') {
+ this.$message.error('删除失败')
+ }
+ }
+ }
+ }
+ ],
+ extraDialogs: [
+ {
+ title: '任务配置',
+ form: [
+ { label: '任务名称', id: 'taskName', type: 'input', rules: { required: true, message: '请输入任务名称', trigger: 'blur' } },
+ { label: 'AI参数', id: 'aiParams', type: 'input', rules: { required: true, message: '请输入AI参数', trigger: 'blur' } },
+ {
+ label: '定时配置',
+ id: 'cron',
+ component: 'cron-generator', // 使用组件名称字符串
+ rules: { required: true, message: '请配置定时规则', trigger: 'change' },
+ // hidden: () => false, // 明确显示
+ props: {
+ value: '{{cron}}'
+ },
+ on: {
+ input: (value, form) => {
+ form.cron = value;
+ }
+ }
+ },
+ { label: '是否启用', id: 'isEnabled', type: 'switch' }
+ ],
+ atConfirm: async (form) => {
+ const url = form.id ? this.tableConfig.editUrl : this.tableConfig.newUrl;
+ const { code } = await this.$elBusHttp.request(url, {
+ method: 'post',
+ data: form
+ });
+ if (code === 0) {
+ this.$message.success('保存成功');
+ this.$refs.crud.getList();
+ return true;
+ }
+ return false;
+ }
+ }
+ ]
+ }
+ }
+ },
+ head() {
+ return {
+ title: '模型任务管理',
+ }
+ },
+ methods: {
+ onEnabledChange(row, newValue) {
+ const url = 'flower/api/aiTaskConfig/isEnable'
+ const text = newValue ? '启用' : '禁用'
+ this.$elBusUtil
+ .confirm(`确定要${text}这个模型任务吗?`)
+ .then(async () => {
+ const { code } = await this.$elBusHttp.request(url, {
+ method: 'post',
+ data: {
+ id: row.id,
+ isEnabled: newValue
+ }
+ })
+
+ if (code === 0) {
+ this.$message.success(`${text}成功`)
+ this.$refs.crud.getList()
+ }
+ })
+ .catch(() => {
+ row.isEnabled = !newValue
+ })
+ }
+ }
+}
+</script>
+
+<style scoped>
+/* 可以添加一些样式调整 */
+</style>
diff --git a/pages/regular/task-config.vue b/pages/regular/task-config.vue
new file mode 100644
index 0000000..ffc4e4a
--- /dev/null
+++ b/pages/regular/task-config.vue
@@ -0,0 +1,206 @@
+:task-config.vue
+<template>
+ <el-bus-crud ref="crud" v-bind="tableConfig">
+ <!-- 不再需要自定义插槽 -->
+ </el-bus-crud>
+</template>
+
+<script>
+// 不再需要导入 CronGenerator,因为现在通过全局注册使用
+
+export default {
+ data() {
+ return {
+ tableConfig: {
+ defaultForm: {
+ taskName: '',
+ aiParams: '',
+ cron: '',
+ isEnabled: false
+ },
+ url: 'flower/api/filmTaskConfig/list',
+ newUrl: 'flower/api/filmTaskConfig/new',
+ editUrl: 'flower/api/filmTaskConfig/edit',
+ deleteUrl: 'flower/api/filmTaskConfig/delete',
+ dialogNeedRequest: false,
+ persistSelection: true,
+ hasNew:false,
+ hasEdit:false,
+ hasOperation:false,
+ columns: [
+ { type: 'selection' },
+ { label: '任务名称', prop: 'taskName' },
+ { label: 'AI参数', prop: 'aiParams' },
+ { label: 'cron表达式', prop: 'cron' },
+ {
+ label: '启用/禁用',
+ formatter: (row) => (
+ <el-switch
+ value={row.isEnabled}
+ onChange={(val) => this.onEnabledChange(row, val)}
+ ></el-switch>
+ ),
+ minWidth: 120,
+ fixed: 'right',
+ },
+ ],
+ searchForm: [
+ {
+ type: 'row',
+ items: [
+ { label: '任务名称', id: 'taskName', type: 'input' },
+ {
+ label: '启用/禁用',
+ id: 'isEnabled',
+ type: 'bus-select-dict',
+ default: '1',
+ el: {
+ code: 'USER_ENABLED_OR_DISABLED',
+ clearable: true,
+ style: 'width:100%',
+ },
+ },
+ ]
+ }
+ ],
+ form: [
+ // { label: '任务名称', id: 'taskName', type: 'input', rules: { required: true, message: '请输入任务名称', trigger: 'blur' } },
+ // { label: 'AI参数', id: 'aiParams', type: 'input', rules: { required: true, message: '请输入AI参数', trigger: 'blur' } },
+ // {
+ // label: '定时配置',
+ // id: 'cron',
+ // type: 'input',
+ // // hidden: () => true, // 改为函数形式
+ // rules: { required: true }
+ // },
+ // { label: '是否启用', id: 'isEnabled', type: 'switch' }
+ ],
+ extraButtons: [],
+ headerButtons: [
+ {
+ text: '批量删除',
+ type: 'danger',
+ disabled: selected => selected.length === 0,
+ atClick: async (selected) => {
+ if (!selected.length) return
+
+ try {
+ await this.$elBusUtil.confirm(`确定要批量删除这${selected.length}个任务吗?`)
+ const ids = selected.map(item => item.id)
+ await this.$elBusHttp.request('flower/api/filmTaskConfig/delete/batch', {
+ method: 'post',
+ data: { ids }
+ })
+ this.$refs.crud.getList()
+ this.$message.success('删除成功')
+ } catch (error) {
+ if (error !== 'cancel') {
+ this.$message.error('删除失败')
+ }
+ }
+ }
+ }
+ ],
+ extraDialogs: [
+ {
+ title: '任务配置',
+ form: [
+ { label: '任务名称', id: 'taskName', type: 'input', rules: { required: true, message: '请输入任务名称', trigger: 'blur' } },
+ { label: 'AI参数', id: 'aiParams', type: 'input', rules: { required: true, message: '请输入AI参数', trigger: 'blur' } },
+ {
+ label: '定时配置',
+ id: 'cron',
+ component: 'cron-generator', // 使用组件名称字符串
+ rules: { required: true, message: '请配置定时规则', trigger: 'change' },
+ // hidden: () => false, // 明确显示
+ props: {
+ value: '{{cron}}'
+ },
+ on: {
+ input: (value, form) => {
+ form.cron = value;
+ }
+ }
+ },
+ { label: '是否启用', id: 'isEnabled', type: 'switch' }
+ ],
+ atConfirm: async (form) => {
+ const url = form.id ? this.tableConfig.editUrl : this.tableConfig.newUrl;
+ const { code } = await this.$elBusHttp.request(url, {
+ method: 'post',
+ data: form
+ });
+ if (code === 0) {
+ this.$message.success('保存成功');
+ this.$refs.crud.getList();
+ return true;
+ }
+ return false;
+ }
+ }
+ ]
+ }
+ }
+ },
+ head() {
+ return {
+ title: '模型任务管理',
+ }
+ },
+ methods: {
+ onEnabledChange(row, newValue) {
+ const url = 'flower/api/aiTaskConfig/isEnable'
+ const text = newValue ? '启用' : '禁用'
+ this.$elBusUtil
+ .confirm(`确定要${text}这个模型任务吗?`)
+ .then(async () => {
+ const { code } = await this.$elBusHttp.request(url, {
+ method: 'post',
+ data: {
+ id: row.id,
+ isEnabled: newValue
+ }
+ })
+
+ if (code === 0) {
+ this.$message.success(`${text}成功`)
+ this.$refs.crud.getList()
+ }
+ })
+ .catch(() => {
+ row.isEnabled = !newValue
+ })
+ },
+ onEdit(row) {
+ this.$refs.crud.$refs.extraDialog[0].show(row);
+ },
+ onNew() {
+ this.$refs.crud.$refs.extraDialog[0].show(this.tableConfig.defaultForm);
+ }
+ },
+ mounted() {
+ // 配置按钮触发
+ this.tableConfig.headerButtons.push(
+ {
+ text: '新增',
+ type: 'primary',
+ atClick: () => this.onNew()
+ }
+ );
+
+ // 修改列配置添加操作按钮
+ this.tableConfig.columns.push({
+ label: '操作',
+ fixed: 'right',
+ width: 120,
+ formatter: (row) => (
+ <el-button type="text" onClick={() => this.onEdit(row)}>编辑</el-button>
+ )
+ });
+ }
+}
+</script>
+
+<style scoped>
+/* 可以添加一些样式调整 */
+</style>
--
Gitblit v1.9.3