Commit 007aaf4a879bf5287845d2eb8f6fb9147368f71b

Authored by fengtao
1 parent 064683d6

feat:新增定时任务页面

@@ -67,7 +67,7 @@ export const SchedueLog: AppRouteRecordRaw = { @@ -67,7 +67,7 @@ export const SchedueLog: AppRouteRecordRaw = {
67 { 67 {
68 path: 'schedue_log/:id', 68 path: 'schedue_log/:id',
69 name: 'Schedue_Log', 69 name: 'Schedue_Log',
70 - component: () => import('/@/views/report/config/SchedueLog.vue'), 70 + component: () => import('../../views/system/scheduled/SchedueLog.vue'),
71 meta: { 71 meta: {
72 title: '调度日志', 72 title: '调度日志',
73 }, 73 },
@@ -16,13 +16,14 @@ @@ -16,13 +16,14 @@
16 :options="selectOptions" 16 :options="selectOptions"
17 @change="handleDeviceChange" 17 @change="handleDeviceChange"
18 mode="multiple" 18 mode="multiple"
  19 + labelInValue
19 /> 20 />
20 <div style="margin-top: 1.5vh"></div> 21 <div style="margin-top: 1.5vh"></div>
21 <DeviceAttrCpns 22 <DeviceAttrCpns
22 ref="deviceAttrRef" 23 ref="deviceAttrRef"
23 @change="handleChange" 24 @change="handleChange"
24 :value="deviceList" 25 :value="deviceList"
25 - :orgId="organizationId" 26 + :orgId="organizationId || orgId"
26 /> 27 />
27 </template> 28 </template>
28 </BasicForm> 29 </BasicForm>
@@ -64,7 +65,6 @@ @@ -64,7 +65,6 @@
64 }); 65 });
65 }); 66 });
66 const handleDeviceChange = (e) => { 67 const handleDeviceChange = (e) => {
67 - console.log('e', e);  
68 deviceList.value = e; 68 deviceList.value = e;
69 }; 69 };
70 const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({ 70 const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
@@ -101,10 +101,22 @@ @@ -101,10 +101,22 @@
101 }); 101 });
102 //TODO 模拟的数据 待服务端返回 102 //TODO 模拟的数据 待服务端返回
103 const deviceIds: any = [ 103 const deviceIds: any = [
104 - '8943f0b0-f1f7-11ec-98ad-a9680487d1e0',  
105 - '8f5b4280-f29e-11ec-98ad-a9680487d1e0',  
106 - '54e199d0-f1f7-11ec-98ad-a9680487d1e0',  
107 - '6d9043f0-f1f7-11ec-98ad-a9680487d1e0', 104 + {
  105 + label: '奥迪网关子设备',
  106 + key: '8a4cc9a0-f201-11ec-98ad-a9680487d1e0',
  107 + },
  108 + {
  109 + label: '宝马默认设备',
  110 + key: '8943f0b0-f1f7-11ec-98ad-a9680487d1e0',
  111 + },
  112 + {
  113 + label: '奔驰默认设备',
  114 + key: '6d9043f0-f1f7-11ec-98ad-a9680487d1e0',
  115 + },
  116 + {
  117 + label: '新增奥迪测试设备',
  118 + key: '8f5b4280-f29e-11ec-98ad-a9680487d1e0',
  119 + },
108 ]; 120 ];
109 selectDevice.value = deviceIds; 121 selectDevice.value = deviceIds;
110 //回显设备属性 TODO 模拟的数据 待服务端返回 122 //回显设备属性 TODO 模拟的数据 待服务端返回
@@ -133,6 +145,7 @@ @@ -133,6 +145,7 @@
133 deviceAttrRef.value?.echoDynamicInputFunc(deviceAttrData.value); 145 deviceAttrRef.value?.echoDynamicInputFunc(deviceAttrData.value);
134 } else { 146 } else {
135 editId.value = ''; 147 editId.value = '';
  148 + orgId.value = '';
136 selectDevice.value = []; 149 selectDevice.value = [];
137 selectOptions.value = []; 150 selectOptions.value = [];
138 deviceList.value = []; 151 deviceList.value = [];
@@ -20,7 +20,6 @@ import { @@ -20,7 +20,6 @@ import {
20 isCountAll, 20 isCountAll,
21 } from './timeConfig'; 21 } from './timeConfig';
22 import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config'; 22 import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config';
23 -import { JCronValidator } from '/@/components/Form';  
24 23
25 export enum SchemaFiled { 24 export enum SchemaFiled {
26 WAY = 'way', 25 WAY = 'way',
@@ -210,13 +209,6 @@ export const formSchema: QFormSchema[] = [ @@ -210,13 +209,6 @@ export const formSchema: QFormSchema[] = [
210 }, 209 },
211 }, 210 },
212 { 211 {
213 - field: 'cronExpression',  
214 - label: 'Cron表达式',  
215 - component: 'JEasyCron',  
216 - defaultValue: '* * * * * ? *',  
217 - rules: [{ required: true, message: '请输入Cron表达式' }, { validator: JCronValidator }],  
218 - },  
219 - {  
220 field: 'timeWeek', 212 field: 'timeWeek',
221 component: 'Select', 213 component: 'Select',
222 label: '周期', 214 label: '周期',
@@ -29,9 +29,7 @@ @@ -29,9 +29,7 @@
29 import { propTypes } from '/@/utils/propTypes'; 29 import { propTypes } from '/@/utils/propTypes';
30 import { SelectTypes } from 'ant-design-vue/es/select'; 30 import { SelectTypes } from 'ant-design-vue/es/select';
31 import { Select } from 'ant-design-vue'; 31 import { Select } from 'ant-design-vue';
32 - import { screenLinkPageByDeptIdGetDevice } from '/@/api/ruleengine/ruleengineApi';  
33 import { getAttribute } from '/@/api/ruleengine/ruleengineApi'; 32 import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
34 - // import { getDeviceAttribute } from '/@/api/alarm/position';  
35 33
36 interface Params { 34 interface Params {
37 [x: string]: string; 35 [x: string]: string;
@@ -44,15 +42,9 @@ @@ -44,15 +42,9 @@
44 }); 42 });
45 const emits = defineEmits(['change', 'update:value', 'dynamicReduceHeight', 'dynamicAddHeight']); 43 const emits = defineEmits(['change', 'update:value', 'dynamicReduceHeight', 'dynamicAddHeight']);
46 const selectOptions = ref<SelectTypes['options']>([]); 44 const selectOptions = ref<SelectTypes['options']>([]);
47 - //动态数据  
48 - const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] });  
49 - //监听传入数据value  
50 - watchEffect(() => {  
51 - initVal();  
52 - });  
53 //获取属性 45 //获取属性
54 - const getAttr = async (orgId, value) => {  
55 - const res = await getAttribute(orgId, value.join(',')); 46 + const getAttr = async (orgId, deviceId) => {
  47 + const res = await getAttribute(orgId, deviceId.join(','));
56 selectOptions.value = res.map((o) => { 48 selectOptions.value = res.map((o) => {
57 return { 49 return {
58 label: o, 50 label: o,
@@ -60,43 +52,25 @@ @@ -60,43 +52,25 @@
60 }; 52 };
61 }); 53 });
62 }; 54 };
63 - //获取设备  
64 - const deviceOptions: any = ref([]);  
65 - const getDevice = async (orgId) => {  
66 - const { items } = await screenLinkPageByDeptIdGetDevice({  
67 - organizationId: orgId,  
68 - });  
69 - deviceOptions.value = items.map((item) => {  
70 - return {  
71 - label: item.name,  
72 - value: item.tbDeviceId,  
73 - };  
74 - });  
75 - }; 55 + //动态数据
  56 + const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] });
  57 + //监听传入数据value
  58 + watchEffect(() => {
  59 + initVal();
  60 + });
76 /** 61 /**
77 * 初始化数值 62 * 初始化数值
78 */ 63 */
79 async function initVal() { 64 async function initVal() {
80 dynamicInput.params = []; 65 dynamicInput.params = [];
81 if (props.value && props.orgId) { 66 if (props.value && props.orgId) {
82 - const getPropsDevice = props.value;  
83 - const getPropsOrgId = props.orgId;  
84 - await getAttr(getPropsOrgId, getPropsDevice);  
85 - await getDevice(getPropsOrgId);  
86 - const temp: any = [];  
87 - deviceOptions.value.forEach((f) => {  
88 - getPropsDevice.forEach((f1) => {  
89 - if (f1 == f.value) {  
90 - temp.push({  
91 - label: f.label,  
92 - value: f.value,  
93 - });  
94 - }  
95 - });  
96 - });  
97 - temp.forEach((item: Params) => { 67 + let jsonObj = props.value;
  68 + const deviceId = jsonObj.map((m: any) => m.value);
  69 + await getAttr(props.orgId, deviceId);
  70 + console.log(jsonObj);
  71 + jsonObj.forEach((item: any) => {
98 dynamicInput.params.push({ 72 dynamicInput.params.push({
99 - attribute: item.attribute, 73 + attribute: '',
100 device: item.label, 74 device: item.label,
101 value: item.value, 75 value: item.value,
102 }); 76 });
@@ -116,6 +90,7 @@ @@ -116,6 +90,7 @@
116 }); 90 });
117 }); 91 });
118 } 92 }
  93 + console.log('emitChange', obj);
119 emits('change', obj); 94 emits('change', obj);
120 emits('update:value', obj); 95 emits('update:value', obj);
121 } 96 }
@@ -44,26 +44,6 @@ @@ -44,26 +44,6 @@
44 }, 44 },
45 }, 45 },
46 ]" 46 ]"
47 - :dropDownActions="[  
48 - {  
49 - label: '执行一次',  
50 - icon: 'ant-design:caret-right-filled',  
51 - popConfirm: {  
52 - title: '确认要立即执行一次' + '“' + record.name + '”' + '任务吗?',  
53 - confirm: handleDeleteOrBatchDelete.bind(null, record),  
54 - },  
55 - },  
56 - {  
57 - label: '任务详细',  
58 - icon: 'ant-design:eye-outlined',  
59 - onClick: handleTaskDetailModal.bind(null, record),  
60 - },  
61 - {  
62 - label: '调度日志',  
63 - icon: 'ant-design:insert-row-below-outlined',  
64 - onClick: handleSchedulingLogFunc.bind(null, record),  
65 - },  
66 - ]"  
67 /> 47 />
68 </template> 48 </template>
69 <template #status="{ record }"> 49 <template #status="{ record }">
@@ -79,8 +59,6 @@ @@ -79,8 +59,6 @@
79 </BasicTable> 59 </BasicTable>
80 <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" /> 60 <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" />
81 <DevicePreviewModal @register="registerModal" /> 61 <DevicePreviewModal @register="registerModal" />
82 - <TaskDetailPreviewModal @register="registerModalTaskDetail" />  
83 - <SchedueLog @register="registerModalSchedueLog" />  
84 </div> 62 </div>
85 </template> 63 </template>
86 64
@@ -90,8 +68,6 @@ @@ -90,8 +68,6 @@
90 import { useDrawer } from '/@/components/Drawer'; 68 import { useDrawer } from '/@/components/Drawer';
91 import ReportConfigDrawer from './ReportConfigDrawer.vue'; 69 import ReportConfigDrawer from './ReportConfigDrawer.vue';
92 import DevicePreviewModal from './DevicePreviewModal.vue'; 70 import DevicePreviewModal from './DevicePreviewModal.vue';
93 - import TaskDetailPreviewModal from './TaskDetailPreviewModal.vue';  
94 - import SchedueLog from './SchedueLog.vue';  
95 import { 71 import {
96 reportPage, 72 reportPage,
97 deleteReportManage, 73 deleteReportManage,
@@ -166,8 +142,6 @@ @@ -166,8 +142,6 @@
166 142
167 //查看设备 143 //查看设备
168 const [registerModal, { openModal }] = useModal(); 144 const [registerModal, { openModal }] = useModal();
169 - const [registerModalTaskDetail, { openModal: openModalTaskDetail }] = useModal();  
170 - const [registerModalSchedueLog, { openModal: openModalSchedueLog }] = useModal();  
171 const handleDeviceView = (record) => { 145 const handleDeviceView = (record) => {
172 openModal(true, { 146 openModal(true, {
173 isUpdate: true, 147 isUpdate: true,
@@ -198,17 +172,4 @@ @@ -198,17 +172,4 @@
198 } 172 }
199 }; 173 };
200 const go = useGo(); 174 const go = useGo();
201 - const handleSchedulingLogFunc = (record: Recordable) => {  
202 - // go('/report/schedue_log/' + record.id);  
203 - openModalSchedueLog(true, {  
204 - isUpdate: 2,  
205 - record,  
206 - });  
207 - };  
208 - const handleTaskDetailModal = (record: Recordable) => {  
209 - openModalTaskDetail(true, {  
210 - isUpdate: true,  
211 - record,  
212 - });  
213 - };  
214 </script> 175 </script>
src/views/system/scheduled/SchedueLog.vue renamed from src/views/report/config/SchedueLog.vue
@@ -10,11 +10,9 @@ @@ -10,11 +10,9 @@
10 :showOkBtn="false" 10 :showOkBtn="false"
11 > 11 >
12 <div> 12 <div>
13 - <BasicTable @register="registerTable" :dataSource="tableData"> 13 + <BasicTable @register="registerTable">
14 <template #toolbar> 14 <template #toolbar>
15 - <a-button type="primary"> 清空 </a-button>  
16 <a-button type="primary"> 导出 </a-button> 15 <a-button type="primary"> 导出 </a-button>
17 - <a-button type="primary"> 关闭 </a-button>  
18 <Popconfirm title="您确定要批量删除数据" ok-text="确定" cancel-text="取消"> 16 <Popconfirm title="您确定要批量删除数据" ok-text="确定" cancel-text="取消">
19 <a-button type="primary" color="error" :disabled="hasBatchDelete"> 17 <a-button type="primary" color="error" :disabled="hasBatchDelete">
20 批量删除 18 批量删除
@@ -40,6 +38,16 @@ @@ -40,6 +38,16 @@
40 ]" 38 ]"
41 /> 39 />
42 </template> 40 </template>
  41 + <template #doStatus="{ record }">
  42 + <Switch
  43 + :disabled="disabledSwitch"
  44 + :checked="record.status === 1"
  45 + :loading="record.pendingStatus"
  46 + checkedChildren="启用"
  47 + unCheckedChildren="禁用"
  48 + @change="(checked:boolean)=>statusChange(checked,record)"
  49 + />
  50 + </template>
43 </BasicTable> 51 </BasicTable>
44 </div> 52 </div>
45 </BasicModal> 53 </BasicModal>
@@ -49,15 +57,15 @@ @@ -49,15 +57,15 @@
49 import { ref, nextTick } from 'vue'; 57 import { ref, nextTick } from 'vue';
50 import { BasicModal, useModalInner } from '/@/components/Modal'; 58 import { BasicModal, useModalInner } from '/@/components/Modal';
51 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 59 import { BasicTable, useTable, TableAction } from '/@/components/Table';
52 - import { columnSchedue, searchSchedueFormSchema } from './config.data'; 60 + import { columnSchedue, searchSchedueFormSchema } from '../../report/config/config.data';
53 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 61 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
54 import { deleteReportManage, reportPage } from '/@/api/report/reportManager'; 62 import { deleteReportManage, reportPage } from '/@/api/report/reportManager';
55 - import { Popconfirm } from 'ant-design-vue'; 63 + import { Popconfirm, Switch } from 'ant-design-vue';
56 64
  65 + const disabledSwitch = ref(false);
57 const heightNum = ref(800); 66 const heightNum = ref(800);
58 - const tableData: any = ref([]);  
59 const [registerTable, { setProps, reload }] = useTable({ 67 const [registerTable, { setProps, reload }] = useTable({
60 - title: '调度日志表格列表', 68 + title: '调度日志列表',
61 api: reportPage, 69 api: reportPage,
62 columns: columnSchedue, 70 columns: columnSchedue,
63 showIndexColumn: false, 71 showIndexColumn: false,
@@ -71,6 +79,7 @@ @@ -71,6 +79,7 @@
71 schemas: searchSchedueFormSchema, 79 schemas: searchSchedueFormSchema,
72 fieldMapToTime: [['sendTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']], 80 fieldMapToTime: [['sendTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']],
73 }, 81 },
  82 + rowKey: 'id',
74 actionColumn: { 83 actionColumn: {
75 width: 200, 84 width: 200,
76 title: '操作', 85 title: '操作',
@@ -91,24 +100,37 @@ @@ -91,24 +100,37 @@
91 100
92 const [register] = useModalInner((data) => { 101 const [register] = useModalInner((data) => {
93 console.log(data); 102 console.log(data);
94 - const getTableData = () => {  
95 - for (let i = 0; i < 100; i++) {  
96 - tableData.value.push({  
97 - name: `${i}`,  
98 - organizationId: `${i}`,  
99 - dataCompare: `${i}`,  
100 - status: `${i}`,  
101 - executeWay: `${i}`,  
102 - devices: `${i}`,  
103 - creator: `${i}`,  
104 - });  
105 - }  
106 - };  
107 nextTick(() => { 103 nextTick(() => {
108 setProps(selectionOptions); 104 setProps(selectionOptions);
109 - getTableData(); 105 + setProps({
  106 + rowKey: 'id',
  107 + });
110 }); 108 });
111 }); 109 });
112 const handleCancel = () => {}; 110 const handleCancel = () => {};
  111 + const statusChange = async (checked, record) => {
  112 + try {
  113 + setProps({
  114 + loading: true,
  115 + });
  116 + disabledSwitch.value = true;
  117 + const newStatus = checked ? 1 : 0;
  118 + console.log(checked, record, newStatus);
  119 + // const res = await putReportByidAndStatusManage(record.id, newStatus);
  120 + // if (res && newStatus) {
  121 + // createMessage.success(`启用成功`);
  122 + // } else {
  123 + // createMessage.success('禁用成功');
  124 + // }
  125 + } finally {
  126 + setTimeout(() => {
  127 + setProps({
  128 + loading: false,
  129 + });
  130 + disabledSwitch.value = false;
  131 + }, 500);
  132 + reload();
  133 + }
  134 + };
113 </script> 135 </script>
114 <style lang="less" scoped></style> 136 <style lang="less" scoped></style>
  1 +<template>
  2 + <BasicDrawer
  3 + v-bind="$attrs"
  4 + @register="registerDrawer"
  5 + showFooter
  6 + :title="getTitle"
  7 + width="30%"
  8 + @ok="handleSubmit"
  9 + >
  10 + <BasicForm @register="registerForm" />
  11 + </BasicDrawer>
  12 +</template>
  13 +<script lang="ts" setup>
  14 + import { ref, computed, unref, reactive } from 'vue';
  15 + import { BasicForm, useForm } from '/@/components/Form';
  16 + import { formSchema } from './config.form.data';
  17 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  18 + // import { createOrEditReportManage, putReportConfigManage } from '/@/api/report/reportManager';
  19 + import { useMessage } from '/@/hooks/web/useMessage';
  20 +
  21 + const emit = defineEmits(['success', 'register']);
  22 + const isUpdate = ref(true);
  23 + const editId = ref('');
  24 + const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
  25 + labelWidth: 120,
  26 + schemas: formSchema,
  27 + showActionButtonGroup: false,
  28 + fieldMapToTime: [['timeZone', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']],
  29 + });
  30 + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  31 + await resetFields();
  32 + setDrawerProps({ confirmLoading: false });
  33 + isUpdate.value = !!data?.isUpdate;
  34 + if (unref(isUpdate)) {
  35 + //回显基础数据
  36 + await setFieldsValue(data.record);
  37 + } else {
  38 + editId.value = '';
  39 + }
  40 + });
  41 + const getTitle = computed(() => (!unref(isUpdate) ? '新增定时任务' : '编辑定时任务'));
  42 + let postObj: any = reactive({});
  43 + async function handleSubmit() {
  44 + setDrawerProps({ confirmLoading: true });
  45 + try {
  46 + const { createMessage } = useMessage();
  47 + const values = await validate();
  48 + if (!values) return;
  49 + postObj = {};
  50 + let saveMessage = '添加成功';
  51 + let updateMessage = '修改成功';
  52 + // editId.value !== ''
  53 + // ? await putReportConfigManage(postObj)
  54 + // : await createOrEditReportManage(postObj);
  55 +
  56 + closeDrawer();
  57 + emit('success');
  58 + createMessage.success(unref(isUpdate) ? updateMessage : saveMessage);
  59 + } finally {
  60 + setTimeout(() => {
  61 + setDrawerProps({ confirmLoading: false });
  62 + }, 300);
  63 + }
  64 + }
  65 +</script>
src/views/system/scheduled/TaskDetailPreviewModal.vue renamed from src/views/report/config/TaskDetailPreviewModal.vue
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 <script setup lang="ts"> 18 <script setup lang="ts">
19 import { ref, nextTick, reactive } from 'vue'; 19 import { ref, nextTick, reactive } from 'vue';
20 import { BasicModal, useModalInner } from '/@/components/Modal'; 20 import { BasicModal, useModalInner } from '/@/components/Modal';
21 - import { personSchema } from './config.data'; 21 + import { personSchema } from '../../report/config/config.data';
22 import { Description } from '/@/components/Description/index'; 22 import { Description } from '/@/components/Description/index';
23 import { useDescription } from '/@/components/Description'; 23 import { useDescription } from '/@/components/Description';
24 24
  1 +import { DescItem } from '/@/components/Description/index';
  2 +import { BasicColumn, FormSchema } from '/@/components/Table';
  3 +import moment from 'moment';
  4 +
  5 +export const personSchema: DescItem[] = [
  6 + {
  7 + field: 'b1',
  8 + label: '任务编号:',
  9 + },
  10 + {
  11 + field: 'b2',
  12 + label: '任务分组:',
  13 + },
  14 + {
  15 + field: 'b3',
  16 + label: '任务名称:',
  17 + },
  18 + {
  19 + field: 'b4',
  20 + label: '创建时间:',
  21 + },
  22 + {
  23 + field: 'b5',
  24 + label: 'cron表达式:',
  25 + },
  26 + {
  27 + field: 'b6',
  28 + label: '下次执行时间:',
  29 + },
  30 + {
  31 + field: 'b7',
  32 + label: '调用目标方法:',
  33 + },
  34 + {
  35 + field: 'b8',
  36 + label: '任务状态:',
  37 + },
  38 + {
  39 + field: 'b9',
  40 + label: '是否并发:',
  41 + },
  42 + {
  43 + field: 'b10',
  44 + label: '执行策略:',
  45 + },
  46 +];
  47 +
  48 +// 调度日志表格配置
  49 +export const columnSchedue: BasicColumn[] = [
  50 + {
  51 + title: '日志编号',
  52 + dataIndex: 'name',
  53 + width: 80,
  54 + },
  55 + {
  56 + title: '任务名称',
  57 + dataIndex: 'organizationId',
  58 + width: 120,
  59 + },
  60 + {
  61 + title: '任务组名',
  62 + dataIndex: 'dataCompare',
  63 + width: 120,
  64 + },
  65 + {
  66 + title: '调用目标字符串',
  67 + dataIndex: 'status',
  68 + width: 120,
  69 + },
  70 + {
  71 + title: '日志信息',
  72 + dataIndex: 'executeWay',
  73 + width: 160,
  74 + },
  75 + {
  76 + title: '执行状态',
  77 + dataIndex: 'devices',
  78 + width: 160,
  79 + slots: { customRender: 'doStatus' },
  80 + },
  81 + {
  82 + title: '执行时间',
  83 + dataIndex: 'creator',
  84 + width: 180,
  85 + },
  86 +];
  87 +
  88 +// 调度日志表格查询配置
  89 +export const searchSchedueFormSchema: FormSchema[] = [
  90 + {
  91 + field: 'name',
  92 + label: '任务名称',
  93 + component: 'Input',
  94 + colProps: { span: 4 },
  95 + componentProps: {
  96 + maxLength: 36,
  97 + placeholder: '请输入任务名称',
  98 + },
  99 + },
  100 + {
  101 + field: 'status',
  102 + label: '任务组名',
  103 + component: 'Select',
  104 + colProps: { span: 4 },
  105 + componentProps: {
  106 + options: [
  107 + {
  108 + label: '默认',
  109 + value: 1,
  110 + },
  111 + {
  112 + label: '系统',
  113 + value: 0,
  114 + },
  115 + ],
  116 + placeholder: '请选择任务组名',
  117 + },
  118 + },
  119 + {
  120 + field: 'status1',
  121 + label: '执行状态',
  122 + component: 'Select',
  123 + colProps: { span: 4 },
  124 + componentProps: {
  125 + options: [
  126 + {
  127 + label: '成功',
  128 + value: 1,
  129 + },
  130 + {
  131 + label: '失败',
  132 + value: 0,
  133 + },
  134 + ],
  135 + placeholder: '请选择执行状态',
  136 + },
  137 + },
  138 + {
  139 + field: 'sendTime',
  140 + label: '执行时间',
  141 + component: 'RangePicker',
  142 + componentProps: {
  143 + showTime: {
  144 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  145 + },
  146 + },
  147 + colProps: { span: 4 },
  148 + },
  149 +];
  1 +import { BasicColumn, FormSchema } from '/@/components/Table';
  2 +import type { FormSchema as QFormSchema } from '/@/components/Form/index';
  3 +import { JCronValidator } from '/@/components/Form';
  4 +
  5 +// 调度日志表格配置
  6 +export const columnSchedue: BasicColumn[] = [
  7 + {
  8 + title: '任务编号',
  9 + dataIndex: 'name',
  10 + width: 80,
  11 + },
  12 + {
  13 + title: '任务组名',
  14 + dataIndex: 'organizationId',
  15 + width: 120,
  16 + },
  17 + {
  18 + title: '调用目标字符串',
  19 + dataIndex: 'status',
  20 + width: 120,
  21 + },
  22 + {
  23 + title: 'cron执行表达式',
  24 + dataIndex: 'executeWay',
  25 + width: 160,
  26 + },
  27 + {
  28 + title: '状态',
  29 + dataIndex: 'devices',
  30 + width: 160,
  31 + slots: { customRender: 'status' },
  32 + },
  33 +];
  34 +
  35 +// 调度日志表格查询配置
  36 +export const searchSchedueFormSchema: FormSchema[] = [
  37 + {
  38 + field: 'name',
  39 + label: '任务名称',
  40 + component: 'Input',
  41 + colProps: { span: 6 },
  42 + componentProps: {
  43 + maxLength: 36,
  44 + placeholder: '请输入任务名称',
  45 + },
  46 + },
  47 + {
  48 + field: 'status',
  49 + label: '任务组名',
  50 + component: 'Select',
  51 + colProps: { span: 6 },
  52 + componentProps: {
  53 + options: [
  54 + {
  55 + label: '默认',
  56 + value: 1,
  57 + },
  58 + {
  59 + label: '系统',
  60 + value: 0,
  61 + },
  62 + ],
  63 + placeholder: '请选择任务组名',
  64 + },
  65 + },
  66 + {
  67 + field: 'status1',
  68 + label: '任务状态',
  69 + component: 'Select',
  70 + colProps: { span: 6 },
  71 + componentProps: {
  72 + options: [
  73 + {
  74 + label: '正常',
  75 + value: 1,
  76 + },
  77 + {
  78 + label: '暂停',
  79 + value: 0,
  80 + },
  81 + ],
  82 + placeholder: '请选择任务状态',
  83 + },
  84 + },
  85 +];
  86 +
  87 +// 新增编辑配置
  88 +export const formSchema: QFormSchema[] = [
  89 + {
  90 + field: 'name',
  91 + label: '任务名称',
  92 + colProps: { span: 24 },
  93 + required: true,
  94 + component: 'Input',
  95 + componentProps: {
  96 + maxLength: 255,
  97 + placeholder: '请输入任务名称',
  98 + },
  99 + },
  100 + {
  101 + field: 'executeWay',
  102 + component: 'Select',
  103 + label: '任务分组',
  104 + colProps: {
  105 + span: 24,
  106 + },
  107 + componentProps: {
  108 + placeholder: '请选择任务分组',
  109 + options: [
  110 + {
  111 + label: '默认',
  112 + value: 0,
  113 + },
  114 + {
  115 + label: '系统',
  116 + value: 1,
  117 + },
  118 + ],
  119 + },
  120 + },
  121 + {
  122 + field: 'name1',
  123 + label: ' 调用方法',
  124 + helpMessage: [
  125 + "Bean调用示例:ryTask.ryParams('ry')Class类调用示例:com.ruoyi.quartz.task.RyTask.ryParams('ry')参数说明:支持字符串,布尔类型,长整型,浮点型,整型",
  126 + ],
  127 + colProps: { span: 24 },
  128 + required: true,
  129 + component: 'Input',
  130 + componentProps: {
  131 + maxLength: 255,
  132 + placeholder: '请输入调用方法',
  133 + },
  134 + },
  135 + {
  136 + field: 'cronExpression',
  137 + label: 'Cron表达式',
  138 + component: 'JEasyCron',
  139 + defaultValue: '* * * * * ? *',
  140 + colProps: {
  141 + span: 24,
  142 + },
  143 + rules: [{ required: true, message: '请输入Cron表达式' }, { validator: JCronValidator }],
  144 + },
  145 + {
  146 + field: 'field10',
  147 + component: 'RadioButtonGroup',
  148 + label: '执行策略',
  149 + colProps: {
  150 + span: 24,
  151 + },
  152 + defaultValue: '1',
  153 + componentProps: {
  154 + options: [
  155 + {
  156 + label: '立即执行',
  157 + value: '1',
  158 + },
  159 + {
  160 + label: '执行一次',
  161 + value: '2',
  162 + },
  163 + {
  164 + label: '放弃执行',
  165 + value: '3',
  166 + },
  167 + ],
  168 + },
  169 + },
  170 + {
  171 + field: 'field11',
  172 + component: 'RadioButtonGroup',
  173 + label: '是否并发',
  174 + colProps: {
  175 + span: 24,
  176 + },
  177 + defaultValue: '2',
  178 + componentProps: {
  179 + options: [
  180 + {
  181 + label: '允许',
  182 + value: '1',
  183 + },
  184 + {
  185 + label: '禁止',
  186 + value: '2',
  187 + },
  188 + ],
  189 + },
  190 + },
  191 + {
  192 + field: 'field7',
  193 + component: 'RadioGroup',
  194 + label: '状态',
  195 + colProps: {
  196 + span: 24,
  197 + },
  198 + defaultValue: '1',
  199 + componentProps: {
  200 + options: [
  201 + {
  202 + label: '正常',
  203 + value: '1',
  204 + },
  205 + {
  206 + label: '暂停',
  207 + value: '2',
  208 + },
  209 + ],
  210 + },
  211 + },
  212 +];
  1 +<template>
  2 + <div>
  3 + <BasicTable @register="registerTable">
  4 + <template #toolbar>
  5 + <Authority value="api:yt:schedule:post">
  6 + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增 </a-button>
  7 + </Authority>
  8 + <Authority value="api:yt:schedule:get">
  9 + <a-button type="primary"> 导出 </a-button>
  10 + </Authority>
  11 + <Authority value="api:yt:schedule:delete">
  12 + <Popconfirm title="您确定要批量删除数据" ok-text="确定" cancel-text="取消">
  13 + <a-button type="primary" color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>
  14 + </Popconfirm>
  15 + </Authority>
  16 + </template>
  17 + <template #action="{ record }">
  18 + <TableAction
  19 + :actions="[
  20 + {
  21 + label: '编辑',
  22 + icon: 'clarity:note-edit-line',
  23 + auth: 'api:yt:schedule:update',
  24 + onClick: handleCreateOrEdit.bind(null, record),
  25 + },
  26 + {
  27 + label: '删除',
  28 + icon: 'ant-design:delete-outlined',
  29 + color: 'error',
  30 + auth: 'api:yt:schedule:delete',
  31 + popConfirm: {
  32 + title: '是否确认删除',
  33 + confirm: handleDeleteOrBatchDelete.bind(null, record),
  34 + },
  35 + },
  36 + ]"
  37 + :dropDownActions="[
  38 + {
  39 + label: '执行一次',
  40 + icon: 'ant-design:caret-right-filled',
  41 + popConfirm: {
  42 + title: '确认要立即执行一次' + '“' + record.name + '”' + '任务吗?',
  43 + confirm: handleDeleteOrBatchDelete.bind(null, record),
  44 + },
  45 + },
  46 + {
  47 + label: '任务详细',
  48 + icon: 'ant-design:eye-outlined',
  49 + onClick: handleTaskDetailModal.bind(null, record),
  50 + },
  51 + {
  52 + label: '调度日志',
  53 + icon: 'ant-design:insert-row-below-outlined',
  54 + onClick: handleSchedulingLogFunc.bind(null, record),
  55 + },
  56 + ]"
  57 + />
  58 + </template>
  59 + <template #status="{ record }">
  60 + <Switch
  61 + :disabled="disabledSwitch"
  62 + :checked="record.status === 1"
  63 + :loading="record.pendingStatus"
  64 + checkedChildren="启用"
  65 + unCheckedChildren="禁用"
  66 + @change="(checked:boolean)=>statusChange(checked,record)"
  67 + />
  68 + </template>
  69 + </BasicTable>
  70 + <ScheduledDrawer @register="registerDrawer" @success="handleSuccess" />
  71 + <TaskDetailPreviewModal @register="registerModalTaskDetail" />
  72 + <SchedueLog @register="registerModalSchedueLog" />
  73 + </div>
  74 +</template>
  75 +<script setup lang="ts">
  76 + import { nextTick, ref } from 'vue';
  77 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  78 + import { columnSchedue, searchSchedueFormSchema } from './config.form.data';
  79 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
  80 + import { deleteReportManage, reportPage } from '/@/api/report/reportManager';
  81 + import { Popconfirm, Switch } from 'ant-design-vue';
  82 + import { useModal } from '/@/components/Modal';
  83 + import TaskDetailPreviewModal from './TaskDetailPreviewModal.vue';
  84 + import SchedueLog from './SchedueLog.vue';
  85 + import ScheduledDrawer from './ScheduledDrawer.vue';
  86 + import { useDrawer } from '/@/components/Drawer';
  87 + import { Authority } from '/@/components/Authority';
  88 +
  89 + const disabledSwitch = ref(false);
  90 + const [registerTable, { setProps, reload }] = useTable({
  91 + title: '定时任务列表',
  92 + api: reportPage,
  93 + columns: columnSchedue,
  94 + showIndexColumn: false,
  95 + clickToRowSelect: false,
  96 + useSearchForm: true,
  97 + ellipsis: true,
  98 + showTableSetting: true,
  99 + bordered: true,
  100 + formConfig: {
  101 + labelWidth: 120,
  102 + schemas: searchSchedueFormSchema,
  103 + fieldMapToTime: [['sendTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']],
  104 + },
  105 + actionColumn: {
  106 + width: 200,
  107 + title: '操作',
  108 + dataIndex: 'action',
  109 + slots: { customRender: 'action' },
  110 + fixed: 'right',
  111 + },
  112 + });
  113 + // 刷新
  114 + const handleSuccess = () => {
  115 + reload();
  116 + };
  117 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  118 + deleteReportManage,
  119 + handleSuccess,
  120 + setProps
  121 + );
  122 +
  123 + nextTick(() => {
  124 + setProps(selectionOptions);
  125 + });
  126 + const [registerDrawer, { openDrawer }] = useDrawer();
  127 + const [registerModalTaskDetail, { openModal: openModalTaskDetail }] = useModal();
  128 + const [registerModalSchedueLog, { openModal: openModalSchedueLog }] = useModal();
  129 + const handleSchedulingLogFunc = (record: Recordable) => {
  130 + // go('/report/schedue_log/' + record.id);
  131 + openModalSchedueLog(true, {
  132 + isUpdate: 2,
  133 + record,
  134 + });
  135 + };
  136 + const handleTaskDetailModal = (record: Recordable) => {
  137 + openModalTaskDetail(true, {
  138 + isUpdate: true,
  139 + record,
  140 + });
  141 + };
  142 + // 新增或编辑
  143 + const handleCreateOrEdit = (record: Recordable | null) => {
  144 + if (record) {
  145 + openDrawer(true, {
  146 + isUpdate: true,
  147 + record,
  148 + });
  149 + } else {
  150 + openDrawer(true, {
  151 + isUpdate: false,
  152 + });
  153 + }
  154 + };
  155 +
  156 + const statusChange = async (checked, record) => {
  157 + try {
  158 + setProps({
  159 + loading: true,
  160 + });
  161 + disabledSwitch.value = true;
  162 + const newStatus = checked ? 1 : 0;
  163 + console.log(checked, record, newStatus);
  164 + // const res = await putReportByidAndStatusManage(record.id, newStatus);
  165 + // if (res && newStatus) {
  166 + // createMessage.success(`启用成功`);
  167 + // } else {
  168 + // createMessage.success('禁用成功');
  169 + // }
  170 + } finally {
  171 + setTimeout(() => {
  172 + setProps({
  173 + loading: false,
  174 + });
  175 + disabledSwitch.value = false;
  176 + }, 500);
  177 + reload();
  178 + }
  179 + };
  180 +</script>
  181 +<style lang="less" scoped></style>