Commit 47d21013bd3f9aa063b20d4067538afe6cd40e19

Authored by fengtao
1 parent ec329e6a

feat:新增定时任务功能

  1 +import { BasicPageParams } from '/@/api/model/baseModel';
  2 +export type ReportQueryParam = BasicPageParams & SchedueParam;
  3 +
  4 +export type SchedueParam = {
  5 + status: true;
  6 + jobName: string;
  7 + jobGroup: string;
  8 + orderFiled: string;
  9 + orderType: string;
  10 + data?: any;
  11 + code?: number;
  12 +};
  13 +
  14 +export interface ReportModel {
  15 + code?: number;
  16 + concurrent: number;
  17 + createTime: string;
  18 + creator: string;
  19 + cronExpression: string;
  20 + defaultConfig: string;
  21 + description: string;
  22 + enabled: true;
  23 + icon: string;
  24 + id: string;
  25 + invokeTarget: string;
  26 + jobGroup: string;
  27 + jobName: string;
  28 + misfirePolicy: number;
  29 + name: string;
  30 + roleIds: [string];
  31 + status: number;
  32 + tenantExpireTime: string;
  33 + tenantId: string;
  34 + tenantProfileId: string;
  35 + tenantStatus: string;
  36 + updateTime: string;
  37 + updater: string;
  38 +}
... ...
  1 +import { defHttp } from '/@/utils/http/axios';
  2 +import { ReportModel, ReportQueryParam } from './model/schedueModel';
  3 +
  4 +enum ReportManagerApi {
  5 + GET_REPORT_API = '/monitor/job/page',
  6 + POST_REPORT_API = '/monitor/job/add',
  7 + DELETE_REPORT_API = '/monitor/job',
  8 + PUT_REPORT_API = '/monitor/job/update',
  9 + PUTID_REPORT_API = '/monitor/job',
  10 + RUN_REPORT_API = '/monitor/job/run',
  11 + JOB_LOG_DETAIL_API = '/monitor/jobLog/get/',
  12 + JOB_LOG_PAGE_API = '/monitor/jobLog/page',
  13 + DELETE_LOG_API = '/monitor/jobLog',
  14 + POST_LOG_CLEAN_API = '/monitor/jobLog/clean',
  15 +}
  16 +
  17 +//分页
  18 +export const scheduePage = (params: ReportQueryParam) => {
  19 + return defHttp.get<ReportQueryParam>({
  20 + url: ReportManagerApi.GET_REPORT_API,
  21 + params,
  22 + });
  23 +};
  24 +
  25 +//删除
  26 +export const deleteSchedueManage = (ids: string[]) => {
  27 + return defHttp.delete({
  28 + url: ReportManagerApi.DELETE_REPORT_API,
  29 + data: {
  30 + ids: ids,
  31 + },
  32 + });
  33 +};
  34 +
  35 +// 创建
  36 +export const createOrEditSchedueManage = (data) => {
  37 + return defHttp.post<ReportModel>({
  38 + url: ReportManagerApi.POST_REPORT_API,
  39 + data,
  40 + });
  41 +};
  42 +
  43 +// 编辑
  44 +export const putSchedueConfigManage = (data) => {
  45 + return defHttp.post<ReportModel>({
  46 + url: ReportManagerApi.PUT_REPORT_API,
  47 + data,
  48 + });
  49 +};
  50 +
  51 +// 修改状态 id status
  52 +export const putSchedueByidAndStatusManage = (id, status) => {
  53 + return defHttp.put<ReportModel>({
  54 + url: ReportManagerApi.PUTID_REPORT_API + '/changeStatus/' + id + '/' + status,
  55 + });
  56 +};
  57 +//执行一次
  58 +export const postRunSchedueConfigManage = (id) => {
  59 + return defHttp.post<ReportModel>({
  60 + url: ReportManagerApi.RUN_REPORT_API+'/'+id,
  61 + });
  62 +};
  63 +
  64 +/**
  65 + * 调度日志
  66 + */
  67 +
  68 +//分页
  69 +export const schedueLogPage = (params: ReportQueryParam) => {
  70 + return defHttp.get<ReportQueryParam>({
  71 + url: ReportManagerApi.JOB_LOG_PAGE_API,
  72 + params,
  73 + });
  74 +};
  75 +
  76 +//删除
  77 +export const deleteSchedueLogManage = (ids: string[]) => {
  78 + return defHttp.delete({
  79 + url: ReportManagerApi.DELETE_LOG_API,
  80 + data: {
  81 + ids: ids,
  82 + },
  83 + });
  84 +};
  85 +
  86 +// 清空
  87 +export const schedueLogCleanPage = () => {
  88 + return defHttp.post<ReportModel>({
  89 + url: ReportManagerApi.POST_LOG_CLEAN_API,
  90 + });
  91 +};
  92 +
  93 +//详情
  94 +export const schedueLogDetailPage = (jobId, id) => {
  95 + return defHttp.get<ReportQueryParam>({
  96 + url: ReportManagerApi.JOB_LOG_DETAIL_API + '/' + jobId + '/' + id,
  97 + });
  98 +};
... ...
... ... @@ -135,7 +135,17 @@
135 135 });
136 136 const preTimeList = ref('执行预览,会忽略年份参数。');
137 137
138   - // cron表达式
  138 + //fix 去除字符串里的'W' 当选择工作日 会自动在后面加上W 比如1W 2W corn解析会报错
  139 + function Letter(str) {
  140 + let result;
  141 + let reg = /[W]+/;
  142 + while ((result = str.match(reg))) {
  143 + //判断str.match(reg)是否没有字母了
  144 + str = str.replace(result[0], ''); //替换掉字母 result[0] 是 str.match(reg)匹配到的字母
  145 + }
  146 + return str;
  147 + }
  148 + // 最终生成的cron表达式
139 149 const cronValueInner = computed(() => {
140 150 let result: string[] = [];
141 151 if (!props.hideSecond) {
... ... @@ -143,7 +153,7 @@
143 153 }
144 154 result.push(minute.value ? minute.value : '*');
145 155 result.push(hour.value ? hour.value : '*');
146   - result.push(day.value ? day.value : '*');
  156 + result.push(day.value ? Letter(day.value) : '*');
147 157 result.push(month.value ? month.value : '*');
148 158 result.push(week.value ? week.value : '?');
149 159 if (!props.hideYear && !props.hideSecond) result.push(year.value ? year.value : '*');
... ... @@ -177,40 +187,6 @@
177 187 emitValue(newValue);
178 188 assignInput();
179 189 });
180   -
181   - // watch(minute, () => {
182   - // if (second.value === '*') {
183   - // second.value = '0'
184   - // }
185   - // })
186   - // watch(hour, () => {
187   - // if (minute.value === '*') {
188   - // minute.value = '0'
189   - // }
190   - // })
191   - // watch(day, () => {
192   - // if (day.value !== '?' && hour.value === '*') {
193   - // hour.value = '0'
194   - // }
195   - // })
196   - // watch(week, () => {
197   - // if (week.value !== '?' && hour.value === '*') {
198   - // hour.value = '0'
199   - // }
200   - // })
201   - // watch(month, () => {
202   - // if (day.value === '?' && week.value === '*') {
203   - // week.value = '1'
204   - // } else if (week.value === '?' && day.value === '*') {
205   - // day.value = '1'
206   - // }
207   - // })
208   - // watch(year, () => {
209   - // if (month.value === '*') {
210   - // month.value = '1'
211   - // }
212   - // })
213   -
214 190 assignInput();
215 191 formatValue();
216 192 calTriggerListInner();
... ... @@ -219,7 +195,7 @@
219 195 inputValues.second = second.value;
220 196 inputValues.minute = minute.value;
221 197 inputValues.hour = hour.value;
222   - inputValues.day = day.value;
  198 + inputValues.day = Letter(day.value);
223 199 inputValues.month = month.value;
224 200 inputValues.week = week.value;
225 201 inputValues.year = year.value;
... ...
1 1 <template>
2   - <BasicModal @register="registerModal" title="Cron表达式" width="800px" @ok="onOk">
  2 + <BasicModal
  3 + @register="registerModal"
  4 + title="Cron表达式"
  5 + width="800px"
  6 + @cancel="onCancel"
  7 + :footer="null"
  8 + >
3 9 <EasyCron v-bind="attrs" />
  10 + <div style="float: right; margin-top: 2vh">
  11 + <Button type="default" @click="onCancel" class="mr-2">取消</Button>
  12 + <Button type="primary" @click="onOk" class="mr-2">确认</Button>
  13 + </div>
4 14 </BasicModal>
5 15 </template>
6 16
... ... @@ -8,21 +18,29 @@
8 18 import { defineComponent } from 'vue';
9 19 import { useAttrs } from '/@/hooks/core/useAttrs';
10 20 import { BasicModal, useModalInner } from '/@/components/Modal';
11   - import EasyCron from './EasyCronInner.vue'
  21 + import EasyCron from './EasyCronInner.vue';
  22 + import { Button } from '/@/components/Button';
12 23
13 24 export default defineComponent({
14 25 name: 'EasyCronModal',
15 26 inheritAttrs: false,
16   - components: { BasicModal, EasyCron },
  27 + components: { BasicModal, EasyCron, Button },
17 28 setup() {
18 29 const attrs = useAttrs();
19 30 const [registerModal, { closeModal }] = useModalInner();
20 31
21 32 function onOk() {
22   - closeModal();
  33 + setTimeout(() => {
  34 + closeModal();
  35 + }, 500);
  36 + }
  37 + function onCancel() {
  38 + setTimeout(() => {
  39 + closeModal();
  40 + }, 500);
23 41 }
24 42
25   - return { attrs, registerModal, onOk };
  43 + return { attrs, registerModal, onOk, onCancel };
26 44 },
27 45 });
28 46 </script>
... ...
... ... @@ -36,7 +36,7 @@
36 36 <a-radio :value="TypeEnum.specify" v-bind="beforeRadioAttrs">指定</a-radio>
37 37 <div class="list list-cn">
38 38 <a-checkbox-group v-model:value="valueList">
39   - <template v-for="opt in weekOptions" :key="i">
  39 + <template v-for="opt in weekOptions" :key="opt.label">
40 40 <a-checkbox :value="opt.value" v-bind="typeSpecifyAttrs">{{ opt.label }}</a-checkbox>
41 41 </template>
42 42 </a-checkbox-group>
... ...
... ... @@ -107,7 +107,7 @@ const setting: ProjectConfig = {
107 107 // Fold trigger position
108 108 trigger: TriggerEnum.HEADER,
109 109 // Turn on accordion mode, only show a menu
110   - accordion: false,
  110 + accordion: true,
111 111 // Switch page to close menu
112 112 closeMixSidebarOnChange: false,
113 113 // Module opening method ‘click’ |'hover'
... ...
1 1 import { ref } from 'vue';
2   -import { DescItem } from '/@/components/Description/index';
3 2 import { BasicColumn, FormSchema } from '/@/components/Table';
4 3 import type { FormSchema as QFormSchema } from '/@/components/Form/index';
5 4 import moment from 'moment';
... ... @@ -13,11 +12,7 @@ import {
13 12 isMonth,
14 13 isEmpty,
15 14 isDefultWeek,
16   - isMin,
17   - isMax,
18   - isAvg,
19   - isSum,
20   - isCountAll,
  15 + isFixedWeek,
21 16 } from './timeConfig';
22 17 import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config';
23 18
... ... @@ -347,16 +342,6 @@ export const formSchema: QFormSchema[] = [
347 342 };
348 343 },
349 344 },
350   - // {
351   - // field: 'deviceAttr',
352   - // label: '设备属性',
353   - // component: 'Select',
354   - // componentProps: {
355   - // placeholder: '请选择设备属性',
356   - // },
357   - // colProps: { span: 24 },
358   - // slot: 'deviceAttr',
359   - // },
360 345 {
361 346 field: 'dataCompare',
362 347 label: '数据类型',
... ... @@ -569,13 +554,7 @@ export const formSchema: QFormSchema[] = [
569 554 };
570 555 },
571 556 colProps: { span: 24 },
572   - ifShow: ({ values }) =>
573   - (!isEmpty(values.agg) && !isDefultWeek(values.defaultWeek)) ||
574   - isMin(values.agg) ||
575   - isMax(values.agg) ||
576   - isAvg(values.agg) ||
577   - isSum(values.agg) ||
578   - isCountAll(values.agg),
  557 + ifShow: ({ values }) => isFixedWeek(values.defaultWeek) && !isEmpty(values.agg),
579 558 },
580 559 {
581 560 field: 'interval',
... ... @@ -593,157 +572,6 @@ export const formSchema: QFormSchema[] = [
593 572 },
594 573 ],
595 574 },
596   - ifShow: ({ values }) =>
597   - (!isEmpty(values.agg) && !isDefultWeek(values.defaultWeek)) ||
598   - isMin(values.agg) ||
599   - isMax(values.agg) ||
600   - isAvg(values.agg) ||
601   - isSum(values.agg) ||
602   - isCountAll(values.agg),
603   - },
604   -];
605   -
606   -export const personSchema: DescItem[] = [
607   - {
608   - field: 'b1',
609   - label: '任务编号:',
610   - },
611   - {
612   - field: 'b2',
613   - label: '任务分组:',
614   - },
615   - {
616   - field: 'b3',
617   - label: '任务名称:',
618   - },
619   - {
620   - field: 'b4',
621   - label: '创建时间:',
622   - },
623   - {
624   - field: 'b5',
625   - label: 'cron表达式:',
626   - },
627   - {
628   - field: 'b6',
629   - label: '下次执行时间:',
630   - },
631   - {
632   - field: 'b7',
633   - label: '调用目标方法:',
634   - },
635   - {
636   - field: 'b8',
637   - label: '任务状态:',
638   - },
639   - {
640   - field: 'b9',
641   - label: '是否并发:',
642   - },
643   - {
644   - field: 'b10',
645   - label: '执行策略:',
646   - },
647   -];
648   -
649   -// 调度日志表格配置
650   -export const columnSchedue: BasicColumn[] = [
651   - {
652   - title: '日志编号',
653   - dataIndex: 'name',
654   - width: 80,
655   - },
656   - {
657   - title: '任务名称',
658   - dataIndex: 'organizationId',
659   - width: 120,
660   - },
661   - {
662   - title: '任务组名',
663   - dataIndex: 'dataCompare',
664   - width: 120,
665   - },
666   - {
667   - title: '调用目标字符串',
668   - dataIndex: 'status',
669   - width: 120,
670   - },
671   - {
672   - title: '日志信息',
673   - dataIndex: 'executeWay',
674   - width: 160,
675   - },
676   - {
677   - title: '执行状态',
678   - dataIndex: 'devices',
679   - width: 160,
680   - },
681   - {
682   - title: '执行时间',
683   - dataIndex: 'creator',
684   - width: 180,
685   - },
686   -];
687   -
688   -// 调度日志表格查询配置
689   -export const searchSchedueFormSchema: FormSchema[] = [
690   - {
691   - field: 'name',
692   - label: '任务名称',
693   - component: 'Input',
694   - colProps: { span: 4 },
695   - componentProps: {
696   - maxLength: 36,
697   - placeholder: '请输入任务名称',
698   - },
699   - },
700   - {
701   - field: 'status',
702   - label: '任务组名',
703   - component: 'Select',
704   - colProps: { span: 4 },
705   - componentProps: {
706   - options: [
707   - {
708   - label: '默认',
709   - value: 1,
710   - },
711   - {
712   - label: '系统',
713   - value: 0,
714   - },
715   - ],
716   - placeholder: '请选择任务组名',
717   - },
718   - },
719   - {
720   - field: 'status1',
721   - label: '执行状态',
722   - component: 'Select',
723   - colProps: { span: 4 },
724   - componentProps: {
725   - options: [
726   - {
727   - label: '成功',
728   - value: 1,
729   - },
730   - {
731   - label: '失败',
732   - value: 0,
733   - },
734   - ],
735   - placeholder: '请选择执行状态',
736   - },
737   - },
738   - {
739   - field: 'sendTime',
740   - label: '执行时间',
741   - component: 'RangePicker',
742   - componentProps: {
743   - showTime: {
744   - defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
745   - },
746   - },
747   - colProps: { span: 4 },
  575 + ifShow: ({ values }) => isFixedWeek(values.defaultWeek) && !isEmpty(values.agg),
748 576 },
749 577 ];
... ...
... ... @@ -8,11 +8,19 @@
8 8 title="调度日志"
9 9 @cancel="handleCancel"
10 10 :showOkBtn="false"
  11 + destroyOnClose
11 12 >
12 13 <div>
13 14 <BasicTable @register="registerTable">
14 15 <template #toolbar>
15   - <a-button type="primary"> 导出 </a-button>
  16 + <Popconfirm
  17 + title="您确定要清空全部数据"
  18 + ok-text="确定"
  19 + cancel-text="取消"
  20 + @confirm="handleClear"
  21 + >
  22 + <a-button type="primary"> 清空 </a-button>
  23 + </Popconfirm>
16 24 <Popconfirm title="您确定要批量删除数据" ok-text="确定" cancel-text="取消">
17 25 <a-button type="primary" color="error" :disabled="hasBatchDelete">
18 26 批量删除
... ... @@ -25,6 +33,7 @@
25 33 {
26 34 label: '查看',
27 35 icon: 'clarity:note-edit-line',
  36 + onClick: handleView.bind(null, record),
28 37 },
29 38 {
30 39 label: '删除',
... ... @@ -38,17 +47,8 @@
38 47 ]"
39 48 />
40 49 </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>
51 50 </BasicTable>
  51 + <ScheduleLogViewModal @register="registerModalScheduleLogView" />
52 52 </div>
53 53 </BasicModal>
54 54 </div>
... ... @@ -57,16 +57,23 @@
57 57 import { ref, nextTick } from 'vue';
58 58 import { BasicModal, useModalInner } from '/@/components/Modal';
59 59 import { BasicTable, useTable, TableAction } from '/@/components/Table';
60   - import { columnSchedue, searchSchedueFormSchema } from '../../report/config/config.data';
  60 + import { columnSchedue, searchSchedueFormSchema } from './config.data';
61 61 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
62   - import { deleteReportManage, reportPage } from '/@/api/report/reportManager';
63   - import { Popconfirm, Switch } from 'ant-design-vue';
  62 + import {
  63 + deleteSchedueLogManage,
  64 + schedueLogPage,
  65 + schedueLogCleanPage,
  66 + } from '/@/api/schedue/schedueManager';
  67 + import { Popconfirm } from 'ant-design-vue';
  68 + import { useMessage } from '/@/hooks/web/useMessage';
  69 + import ScheduleLogViewModal from './ScheduleLogViewModal.vue';
  70 + import { useModal } from '/@/components/Modal';
64 71
65   - const disabledSwitch = ref(false);
  72 + const { createMessage } = useMessage();
66 73 const heightNum = ref(800);
67   - const [registerTable, { setProps, reload }] = useTable({
  74 + const [registerTable, { setProps, reload, getForm }] = useTable({
68 75 title: '调度日志列表',
69   - api: reportPage,
  76 + api: schedueLogPage,
70 77 columns: columnSchedue,
71 78 showIndexColumn: false,
72 79 clickToRowSelect: false,
... ... @@ -93,44 +100,34 @@
93 100 reload();
94 101 };
95 102 const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
96   - deleteReportManage,
  103 + deleteSchedueLogManage,
97 104 handleSuccess,
98 105 setProps
99 106 );
100 107
101   - const [register] = useModalInner((data) => {
102   - console.log(data);
  108 + const [register] = useModalInner(() => {
103 109 nextTick(() => {
104 110 setProps(selectionOptions);
105 111 setProps({
106 112 rowKey: 'id',
107 113 });
  114 + //重置清空搜索表单
  115 + const { resetFields } = getForm();
  116 + resetFields();
108 117 });
109 118 });
110 119 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   - }
  120 + const handleClear = async () => {
  121 + await schedueLogCleanPage();
  122 + createMessage.success(`清空成功`);
  123 + handleSuccess();
  124 + };
  125 + const [registerModalScheduleLogView, { openModal: openModalLogView }] = useModal();
  126 + const handleView = (record: Recordable) => {
  127 + openModalLogView(true, {
  128 + isUpdate: true,
  129 + record,
  130 + });
134 131 };
135 132 </script>
136 133 <style lang="less" scoped></style>
... ...
  1 +<template>
  2 + <div>
  3 + <BasicModal
  4 + v-bind="$attrs"
  5 + width="62rem"
  6 + :height="heightNum"
  7 + @register="register"
  8 + title="调度日志详细信息"
  9 + @cancel="handleCancel"
  10 + :showOkBtn="false"
  11 + style="font-size: 12px"
  12 + >
  13 + <div>
  14 + <Description :column="3" size="middle" @register="registeDesc" />
  15 + </div>
  16 + </BasicModal>
  17 + </div>
  18 +</template>
  19 +<script setup lang="ts">
  20 + import { ref, nextTick, reactive } from 'vue';
  21 + import { BasicModal, useModalInner } from '/@/components/Modal';
  22 + import { scheduleLogDetailSchema } from './config.data';
  23 + import { Description } from '/@/components/Description/index';
  24 + import { useDescription } from '/@/components/Description';
  25 + import { schedueLogDetailPage } from '/@/api/schedue/schedueManager';
  26 +
  27 + const heightNum = ref(800);
  28 + let personData = reactive({});
  29 + const [registeDesc, { setDescProps }] = useDescription({
  30 + title: '调度日志详细信息',
  31 + data: personData,
  32 + schema: scheduleLogDetailSchema,
  33 + column: 3,
  34 + });
  35 + const [register] = useModalInner(async (data) => {
  36 + const res = await schedueLogDetailPage(data.record.jobId, data.record.id);
  37 + if (res.code === 200) {
  38 + nextTick(() => {
  39 + for (let i in res.data) {
  40 + Reflect.set(personData, i, res.data[i]);
  41 + }
  42 + setDescProps(personData);
  43 + });
  44 + }
  45 + });
  46 + const handleCancel = () => {};
  47 +</script>
  48 +<style lang="less" scoped>
  49 + :deep(.vben-basic-title-normal) {
  50 + font-size: 16px;
  51 + font-weight: 500;
  52 + }
  53 + :deep(.vben-collapse-container__header) {
  54 + border-bottom: none;
  55 + }
  56 +</style>
... ...
... ... @@ -15,7 +15,7 @@
15 15 import { BasicForm, useForm } from '/@/components/Form';
16 16 import { formSchema } from './config.form.data';
17 17 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
18   - // import { createOrEditReportManage, putReportConfigManage } from '/@/api/report/reportManager';
  18 + import { createOrEditSchedueManage, putSchedueConfigManage } from '/@/api/schedue/schedueManager';
19 19 import { useMessage } from '/@/hooks/web/useMessage';
20 20
21 21 const emit = defineEmits(['success', 'register']);
... ... @@ -33,6 +33,7 @@
33 33 isUpdate.value = !!data?.isUpdate;
34 34 if (unref(isUpdate)) {
35 35 //回显基础数据
  36 + editId.value = data.record.id;
36 37 await setFieldsValue(data.record);
37 38 } else {
38 39 editId.value = '';
... ... @@ -46,12 +47,15 @@
46 47 const { createMessage } = useMessage();
47 48 const values = await validate();
48 49 if (!values) return;
49   - postObj = {};
  50 + postObj = {
  51 + ...values,
  52 + ...{ id: editId.value !== '' ? editId.value : '' },
  53 + };
50 54 let saveMessage = '添加成功';
51 55 let updateMessage = '修改成功';
52   - // editId.value !== ''
53   - // ? await putReportConfigManage(postObj)
54   - // : await createOrEditReportManage(postObj);
  56 + editId.value !== ''
  57 + ? await putSchedueConfigManage(postObj)
  58 + : await createOrEditSchedueManage(postObj);
55 59
56 60 closeDrawer();
57 61 emit('success');
... ...
... ... @@ -19,7 +19,7 @@
19 19 <script setup lang="ts">
20 20 import { ref, nextTick, reactive } from 'vue';
21 21 import { BasicModal, useModalInner } from '/@/components/Modal';
22   - import { personSchema } from '../../report/config/config.data';
  22 + import { personSchema } from './config.data';
23 23 import { Description } from '/@/components/Description/index';
24 24 import { useDescription } from '/@/components/Description';
25 25
... ... @@ -32,18 +32,11 @@
32 32 column: 3,
33 33 });
34 34 const [register] = useModalInner((data) => {
35   - console.log(data);
36 35 nextTick(() => {
37   - Reflect.set(personData, 'b1', '1');
38   - Reflect.set(personData, 'b2', '默认');
39   - Reflect.set(personData, 'b3', '系统默认(无参)');
40   - Reflect.set(personData, 'b4', '2022-08-01 12:01:58');
41   - Reflect.set(personData, 'b5', '0/10 * * * * ?');
42   - Reflect.set(personData, 'b6', '2022-08-08 10:25:00');
43   - Reflect.set(personData, 'b7', 'ryTask.ryNoParams');
44   - Reflect.set(personData, 'b8', '失败');
45   - Reflect.set(personData, 'b9', '禁止');
46   - Reflect.set(personData, 'b10', '禁止');
  36 + //回显
  37 + for (let i in data.record) {
  38 + Reflect.set(personData, i, data.record[i]);
  39 + }
47 40 setDescProps(personData);
48 41 });
49 42 });
... ...
1 1 import { DescItem } from '/@/components/Description/index';
2 2 import { BasicColumn, FormSchema } from '/@/components/Table';
3 3 import moment from 'moment';
  4 +import { h } from 'vue';
  5 +import { Tag } from 'ant-design-vue';
4 6
  7 +//任务详细配置
5 8 export const personSchema: DescItem[] = [
6 9 {
7   - field: 'b1',
8   - label: '任务编号:',
9   - },
10   - {
11   - field: 'b2',
  10 + field: 'jobGroup',
12 11 label: '任务分组:',
  12 + render: (_, data) => {
  13 + return data.jobGroup == 'Default' ? '默认' : data.jobGroup == 'System' ? '系统' : '报表';
  14 + },
13 15 },
14 16 {
15   - field: 'b3',
  17 + field: 'jobName',
16 18 label: '任务名称:',
17 19 },
18 20 {
19   - field: 'b4',
  21 + field: 'createTime',
20 22 label: '创建时间:',
21 23 },
22 24 {
23   - field: 'b5',
  25 + field: 'cronExpression',
24 26 label: 'cron表达式:',
25 27 },
26 28 {
... ... @@ -28,12 +30,15 @@ export const personSchema: DescItem[] = [
28 30 label: '下次执行时间:',
29 31 },
30 32 {
31   - field: 'b7',
  33 + field: 'invokeTarget',
32 34 label: '调用目标方法:',
33 35 },
34 36 {
35   - field: 'b8',
  37 + field: 'status',
36 38 label: '任务状态:',
  39 + render: (_, data) => {
  40 + return data.status == 1 ? '启用' : '禁用';
  41 + },
37 42 },
38 43 {
39 44 field: 'b9',
... ... @@ -48,39 +53,49 @@ export const personSchema: DescItem[] = [
48 53 // 调度日志表格配置
49 54 export const columnSchedue: BasicColumn[] = [
50 55 {
51   - title: '日志编号',
52   - dataIndex: 'name',
53   - width: 80,
54   - },
55   - {
56 56 title: '任务名称',
57   - dataIndex: 'organizationId',
  57 + dataIndex: 'jobName',
58 58 width: 120,
59 59 },
60 60 {
61 61 title: '任务组名',
62   - dataIndex: 'dataCompare',
  62 + dataIndex: 'jobGroup',
63 63 width: 120,
  64 + format: (_text: string, record: Recordable) => {
  65 + return record.jobGroup === 'Default'
  66 + ? '默认'
  67 + : record.jobGroup === 'System'
  68 + ? '系统'
  69 + : '报表';
  70 + },
64 71 },
65 72 {
66 73 title: '调用目标字符串',
67   - dataIndex: 'status',
  74 + dataIndex: 'invokeTarget',
68 75 width: 120,
69 76 },
70 77 {
71 78 title: '日志信息',
72   - dataIndex: 'executeWay',
  79 + dataIndex: 'jobMessage',
73 80 width: 160,
74 81 },
75 82 {
76 83 title: '执行状态',
77   - dataIndex: 'devices',
  84 + dataIndex: 'status',
78 85 width: 160,
79   - slots: { customRender: 'doStatus' },
  86 + customRender: ({ record }) => {
  87 + const status = record.status;
  88 + const success = status === 1;
  89 + const color = success ? 'green' : 'red';
  90 + const successText: string = '成功';
  91 + const failedText: string = '失败';
  92 + const text = success ? successText : failedText;
  93 + return h(Tag, { color: color }, () => text);
  94 + },
80 95 },
81 96 {
82 97 title: '执行时间',
83   - dataIndex: 'creator',
  98 + dataIndex: 'startTime',
84 99 width: 180,
85 100 },
86 101 ];
... ... @@ -88,7 +103,7 @@ export const columnSchedue: BasicColumn[] = [
88 103 // 调度日志表格查询配置
89 104 export const searchSchedueFormSchema: FormSchema[] = [
90 105 {
91   - field: 'name',
  106 + field: 'jobName',
92 107 label: '任务名称',
93 108 component: 'Input',
94 109 colProps: { span: 4 },
... ... @@ -98,7 +113,7 @@ export const searchSchedueFormSchema: FormSchema[] = [
98 113 },
99 114 },
100 115 {
101   - field: 'status',
  116 + field: 'jobGroup',
102 117 label: '任务组名',
103 118 component: 'Select',
104 119 colProps: { span: 4 },
... ... @@ -106,18 +121,22 @@ export const searchSchedueFormSchema: FormSchema[] = [
106 121 options: [
107 122 {
108 123 label: '默认',
109   - value: 1,
  124 + value: 'Default',
110 125 },
111 126 {
112 127 label: '系统',
113   - value: 0,
  128 + value: 'System',
  129 + },
  130 + {
  131 + label: '报表',
  132 + value: 'Report',
114 133 },
115 134 ],
116 135 placeholder: '请选择任务组名',
117 136 },
118 137 },
119 138 {
120   - field: 'status1',
  139 + field: 'status',
121 140 label: '执行状态',
122 141 component: 'Select',
123 142 colProps: { span: 4 },
... ... @@ -147,3 +166,36 @@ export const searchSchedueFormSchema: FormSchema[] = [
147 166 colProps: { span: 4 },
148 167 },
149 168 ];
  169 +// 调度日志详情
  170 +export const scheduleLogDetailSchema: DescItem[] = [
  171 + {
  172 + field: 'jobName',
  173 + label: '任务名称:',
  174 + },
  175 + {
  176 + field: 'jobGroup',
  177 + label: '任务组名:',
  178 + render: (_, data) => {
  179 + return data.jobGroup == 'Default' ? '默认' : data.jobGroup == 'System' ? '系统' : '报表';
  180 + },
  181 + },
  182 + {
  183 + field: 'invokeTarget',
  184 + label: '调用目标字符串:',
  185 + },
  186 + {
  187 + field: 'jobMessage',
  188 + label: '日志信息:',
  189 + },
  190 + {
  191 + field: 'status',
  192 + label: '执行状态:',
  193 + render: (_, data) => {
  194 + return data.status == 1 ? '成功' : '失败';
  195 + },
  196 + },
  197 + {
  198 + field: 'startTime',
  199 + label: '执行时间:',
  200 + },
  201 +];
... ...
... ... @@ -2,40 +2,47 @@ import { BasicColumn, FormSchema } from '/@/components/Table';
2 2 import type { FormSchema as QFormSchema } from '/@/components/Form/index';
3 3 import { JCronValidator } from '/@/components/Form';
4 4
5   -// 调度日志表格配置
  5 +// 定时任务表格配置
6 6 export const columnSchedue: BasicColumn[] = [
7 7 {
8   - title: '任务编号',
9   - dataIndex: 'name',
10   - width: 80,
  8 + title: '任务名称',
  9 + dataIndex: 'jobName',
  10 + width: 120,
11 11 },
12 12 {
13 13 title: '任务组名',
14   - dataIndex: 'organizationId',
  14 + dataIndex: 'jobGroup',
15 15 width: 120,
  16 + format: (_text: string, record: Recordable) => {
  17 + return record.jobGroup === 'Default'
  18 + ? '默认'
  19 + : record.jobGroup === 'System'
  20 + ? '系统'
  21 + : '报表';
  22 + },
16 23 },
17 24 {
18 25 title: '调用目标字符串',
19   - dataIndex: 'status',
  26 + dataIndex: 'invokeTarget',
20 27 width: 120,
21 28 },
22 29 {
23 30 title: 'cron执行表达式',
24   - dataIndex: 'executeWay',
  31 + dataIndex: 'cronExpression',
25 32 width: 160,
26 33 },
27 34 {
28 35 title: '状态',
29   - dataIndex: 'devices',
  36 + dataIndex: 'status',
30 37 width: 160,
31 38 slots: { customRender: 'status' },
32 39 },
33 40 ];
34 41
35   -// 调度日志表格查询配置
  42 +// 定时任务格查询配置
36 43 export const searchSchedueFormSchema: FormSchema[] = [
37 44 {
38   - field: 'name',
  45 + field: 'jobName',
39 46 label: '任务名称',
40 47 component: 'Input',
41 48 colProps: { span: 6 },
... ... @@ -45,7 +52,7 @@ export const searchSchedueFormSchema: FormSchema[] = [
45 52 },
46 53 },
47 54 {
48   - field: 'status',
  55 + field: 'jobGroup',
49 56 label: '任务组名',
50 57 component: 'Select',
51 58 colProps: { span: 6 },
... ... @@ -53,18 +60,22 @@ export const searchSchedueFormSchema: FormSchema[] = [
53 60 options: [
54 61 {
55 62 label: '默认',
56   - value: 1,
  63 + value: 'Default',
57 64 },
58 65 {
59 66 label: '系统',
60   - value: 0,
  67 + value: 'System',
  68 + },
  69 + {
  70 + label: '报表',
  71 + value: 'Report',
61 72 },
62 73 ],
63 74 placeholder: '请选择任务组名',
64 75 },
65 76 },
66 77 {
67   - field: 'status1',
  78 + field: 'status',
68 79 label: '任务状态',
69 80 component: 'Select',
70 81 colProps: { span: 6 },
... ... @@ -87,7 +98,7 @@ export const searchSchedueFormSchema: FormSchema[] = [
87 98 // 新增编辑配置
88 99 export const formSchema: QFormSchema[] = [
89 100 {
90   - field: 'name',
  101 + field: 'jobName',
91 102 label: '任务名称',
92 103 colProps: { span: 24 },
93 104 required: true,
... ... @@ -98,7 +109,7 @@ export const formSchema: QFormSchema[] = [
98 109 },
99 110 },
100 111 {
101   - field: 'executeWay',
  112 + field: 'jobGroup',
102 113 component: 'Select',
103 114 label: '任务分组',
104 115 colProps: {
... ... @@ -109,20 +120,24 @@ export const formSchema: QFormSchema[] = [
109 120 options: [
110 121 {
111 122 label: '默认',
112   - value: 0,
  123 + value: 'Default',
113 124 },
114 125 {
115 126 label: '系统',
116   - value: 1,
  127 + value: 'System',
  128 + },
  129 + {
  130 + label: '报表',
  131 + value: 'Report',
117 132 },
118 133 ],
119 134 },
120 135 },
121 136 {
122   - field: 'name1',
  137 + field: 'invokeTarget',
123 138 label: ' 调用方法',
124 139 helpMessage: [
125   - "Bean调用示例:ryTask.ryParams('ry')Class类调用示例:com.ruoyi.quartz.task.RyTask.ryParams('ry')参数说明:支持字符串,布尔类型,长整型,浮点型,整型",
  140 + 'Bean调用示例:reportTask.noParams()Class类调用示例:reportTask.noParams()参数说明:支持字符串,布尔类型,长整型,浮点型,整型',
126 141 ],
127 142 colProps: { span: 24 },
128 143 required: true,
... ... @@ -189,22 +204,22 @@ export const formSchema: QFormSchema[] = [
189 204 },
190 205 },
191 206 {
192   - field: 'field7',
  207 + field: 'status',
193 208 component: 'RadioGroup',
194 209 label: '状态',
195 210 colProps: {
196 211 span: 24,
197 212 },
198   - defaultValue: '1',
  213 + defaultValue: 1,
199 214 componentProps: {
200 215 options: [
201 216 {
202 217 label: '正常',
203   - value: '1',
  218 + value: 1,
204 219 },
205 220 {
206 221 label: '暂停',
207   - value: '2',
  222 + value: 0,
208 223 },
209 224 ],
210 225 },
... ...
... ... @@ -39,8 +39,8 @@
39 39 label: '执行一次',
40 40 icon: 'ant-design:caret-right-filled',
41 41 popConfirm: {
42   - title: '确认要立即执行一次' + '“' + record.name + '”' + '任务吗?',
43   - confirm: handleDeleteOrBatchDelete.bind(null, record),
  42 + title: '确认要立即执行一次' + '“' + record.jobName + '”' + '任务吗?',
  43 + confirm: handleRunOne.bind(null, record),
44 44 },
45 45 },
46 46 {
... ... @@ -77,7 +77,12 @@
77 77 import { BasicTable, useTable, TableAction } from '/@/components/Table';
78 78 import { columnSchedue, searchSchedueFormSchema } from './config.form.data';
79 79 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
80   - import { deleteReportManage, reportPage } from '/@/api/report/reportManager';
  80 + import {
  81 + deleteSchedueManage,
  82 + scheduePage,
  83 + putSchedueByidAndStatusManage,
  84 + postRunSchedueConfigManage,
  85 + } from '/@/api/schedue/schedueManager';
81 86 import { Popconfirm, Switch } from 'ant-design-vue';
82 87 import { useModal } from '/@/components/Modal';
83 88 import TaskDetailPreviewModal from './TaskDetailPreviewModal.vue';
... ... @@ -85,11 +90,13 @@
85 90 import ScheduledDrawer from './ScheduledDrawer.vue';
86 91 import { useDrawer } from '/@/components/Drawer';
87 92 import { Authority } from '/@/components/Authority';
  93 + import { useMessage } from '/@/hooks/web/useMessage';
88 94
89 95 const disabledSwitch = ref(false);
  96 + const { createMessage } = useMessage();
90 97 const [registerTable, { setProps, reload }] = useTable({
91 98 title: '定时任务列表',
92   - api: reportPage,
  99 + api: scheduePage,
93 100 columns: columnSchedue,
94 101 showIndexColumn: false,
95 102 clickToRowSelect: false,
... ... @@ -115,7 +122,7 @@
115 122 reload();
116 123 };
117 124 const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
118   - deleteReportManage,
  125 + deleteSchedueManage,
119 126 handleSuccess,
120 127 setProps
121 128 );
... ... @@ -127,7 +134,6 @@
127 134 const [registerModalTaskDetail, { openModal: openModalTaskDetail }] = useModal();
128 135 const [registerModalSchedueLog, { openModal: openModalSchedueLog }] = useModal();
129 136 const handleSchedulingLogFunc = (record: Recordable) => {
130   - // go('/report/schedue_log/' + record.id);
131 137 openModalSchedueLog(true, {
132 138 isUpdate: 2,
133 139 record,
... ... @@ -160,13 +166,12 @@
160 166 });
161 167 disabledSwitch.value = true;
162 168 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   - // }
  169 + const res = await putSchedueByidAndStatusManage(record.id, newStatus);
  170 + if (res && newStatus) {
  171 + createMessage.success(`启用成功`);
  172 + } else {
  173 + createMessage.success('禁用成功');
  174 + }
170 175 } finally {
171 176 setTimeout(() => {
172 177 setProps({
... ... @@ -177,5 +182,11 @@
177 182 reload();
178 183 }
179 184 };
  185 + const handleRunOne = async (record: Recordable) => {
  186 + const res = await postRunSchedueConfigManage(record.id);
  187 + if (res?.code === 200) {
  188 + createMessage.success(`执行一次任务"${record.jobName}"成功`);
  189 + }
  190 + };
180 191 </script>
181 192 <style lang="less" scoped></style>
... ...