Showing
7 changed files
with
384 additions
and
26 deletions
| @@ -174,6 +174,9 @@ export default { | @@ -174,6 +174,9 @@ export default { | ||
| 174 | menu: 'Menu management', | 174 | menu: 'Menu management', |
| 175 | role: 'Role management', | 175 | role: 'Role management', |
| 176 | }, | 176 | }, |
| 177 | + report: { | ||
| 178 | + schedue_log: 'Schedue Log', | ||
| 179 | + }, | ||
| 177 | table: { | 180 | table: { |
| 178 | table: 'Table', | 181 | table: 'Table', |
| 179 | 182 |
| @@ -166,6 +166,9 @@ export default { | @@ -166,6 +166,9 @@ export default { | ||
| 166 | menu: '菜单管理', | 166 | menu: '菜单管理', |
| 167 | role: '角色管理', | 167 | role: '角色管理', |
| 168 | }, | 168 | }, |
| 169 | + report: { | ||
| 170 | + schedue_log: '调度日志', | ||
| 171 | + }, | ||
| 169 | table: { | 172 | table: { |
| 170 | table: 'Table', | 173 | table: 'Table', |
| 171 | basic: '基础表格', | 174 | basic: '基础表格', |
| @@ -53,12 +53,34 @@ export const AccountDetail: AppRouteRecordRaw = { | @@ -53,12 +53,34 @@ export const AccountDetail: AppRouteRecordRaw = { | ||
| 53 | }, | 53 | }, |
| 54 | ], | 54 | ], |
| 55 | }; | 55 | }; |
| 56 | +// 调度日志静态路由 | ||
| 57 | +export const SchedueLog: AppRouteRecordRaw = { | ||
| 58 | + path: '/report', | ||
| 59 | + name: '报表管理', | ||
| 60 | + component: LAYOUT, | ||
| 61 | + meta: { | ||
| 62 | + title: '报表管理', | ||
| 63 | + hideBreadcrumb: true, | ||
| 64 | + hideChildrenInMenu: true, | ||
| 65 | + }, | ||
| 66 | + children: [ | ||
| 67 | + { | ||
| 68 | + path: 'schedue_log/:id', | ||
| 69 | + name: 'Schedue_Log', | ||
| 70 | + component: () => import('/@/views/report/config/SchedueLog.vue'), | ||
| 71 | + meta: { | ||
| 72 | + title: '调度日志', | ||
| 73 | + }, | ||
| 74 | + }, | ||
| 75 | + ], | ||
| 76 | +}; | ||
| 56 | 77 | ||
| 57 | // Basic routing without permission | 78 | // Basic routing without permission |
| 58 | export const basicRoutes = [ | 79 | export const basicRoutes = [ |
| 59 | LoginRoute, | 80 | LoginRoute, |
| 60 | RootRoute, | 81 | RootRoute, |
| 61 | AccountDetail, | 82 | AccountDetail, |
| 83 | + SchedueLog, | ||
| 62 | ...mainOutRoutes, | 84 | ...mainOutRoutes, |
| 63 | REDIRECT_ROUTE, | 85 | REDIRECT_ROUTE, |
| 64 | PAGE_NOT_FOUND_ROUTE, | 86 | PAGE_NOT_FOUND_ROUTE, |
src/views/report/config/SchedueLog.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div> | ||
| 3 | + <BasicModal | ||
| 4 | + v-bind="$attrs" | ||
| 5 | + width="110rem" | ||
| 6 | + :height="heightNum" | ||
| 7 | + @register="register" | ||
| 8 | + title="调度日志" | ||
| 9 | + @cancel="handleCancel" | ||
| 10 | + :showOkBtn="false" | ||
| 11 | + > | ||
| 12 | + <div> | ||
| 13 | + <BasicTable @register="registerTable" :dataSource="tableData"> | ||
| 14 | + <template #toolbar> | ||
| 15 | + <a-button type="primary"> 清空 </a-button> | ||
| 16 | + <a-button type="primary"> 导出 </a-button> | ||
| 17 | + <a-button type="primary"> 关闭 </a-button> | ||
| 18 | + <Popconfirm title="您确定要批量删除数据" ok-text="确定" cancel-text="取消"> | ||
| 19 | + <a-button type="primary" color="error" :disabled="hasBatchDelete"> | ||
| 20 | + 批量删除 | ||
| 21 | + </a-button> | ||
| 22 | + </Popconfirm> | ||
| 23 | + </template> | ||
| 24 | + <template #action="{ record }"> | ||
| 25 | + <TableAction | ||
| 26 | + :actions="[ | ||
| 27 | + { | ||
| 28 | + label: '查看', | ||
| 29 | + icon: 'clarity:note-edit-line', | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + label: '删除', | ||
| 33 | + icon: 'ant-design:delete-outlined', | ||
| 34 | + color: 'error', | ||
| 35 | + popConfirm: { | ||
| 36 | + title: '是否确认删除', | ||
| 37 | + confirm: handleDeleteOrBatchDelete.bind(null, record), | ||
| 38 | + }, | ||
| 39 | + }, | ||
| 40 | + ]" | ||
| 41 | + /> | ||
| 42 | + </template> | ||
| 43 | + </BasicTable> | ||
| 44 | + </div> | ||
| 45 | + </BasicModal> | ||
| 46 | + </div> | ||
| 47 | +</template> | ||
| 48 | +<script setup lang="ts"> | ||
| 49 | + import { ref, nextTick } from 'vue'; | ||
| 50 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 51 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
| 52 | + import { columnSchedue, searchSchedueFormSchema } from './config.data'; | ||
| 53 | + import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; | ||
| 54 | + import { deleteReportManage, reportPage } from '/@/api/report/reportManager'; | ||
| 55 | + import { Popconfirm } from 'ant-design-vue'; | ||
| 56 | + | ||
| 57 | + const heightNum = ref(800); | ||
| 58 | + const tableData: any = ref([]); | ||
| 59 | + const [registerTable, { setProps, reload }] = useTable({ | ||
| 60 | + title: '调度日志表格列表', | ||
| 61 | + api: reportPage, | ||
| 62 | + columns: columnSchedue, | ||
| 63 | + showIndexColumn: false, | ||
| 64 | + clickToRowSelect: false, | ||
| 65 | + useSearchForm: true, | ||
| 66 | + ellipsis: true, | ||
| 67 | + showTableSetting: true, | ||
| 68 | + bordered: true, | ||
| 69 | + formConfig: { | ||
| 70 | + labelWidth: 120, | ||
| 71 | + schemas: searchSchedueFormSchema, | ||
| 72 | + fieldMapToTime: [['sendTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']], | ||
| 73 | + }, | ||
| 74 | + actionColumn: { | ||
| 75 | + width: 200, | ||
| 76 | + title: '操作', | ||
| 77 | + dataIndex: 'action', | ||
| 78 | + slots: { customRender: 'action' }, | ||
| 79 | + fixed: 'right', | ||
| 80 | + }, | ||
| 81 | + }); | ||
| 82 | + // 刷新 | ||
| 83 | + const handleSuccess = () => { | ||
| 84 | + reload(); | ||
| 85 | + }; | ||
| 86 | + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( | ||
| 87 | + deleteReportManage, | ||
| 88 | + handleSuccess, | ||
| 89 | + setProps | ||
| 90 | + ); | ||
| 91 | + | ||
| 92 | + const [register] = useModalInner((data) => { | ||
| 93 | + 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(() => { | ||
| 108 | + setProps(selectionOptions); | ||
| 109 | + getTableData(); | ||
| 110 | + }); | ||
| 111 | + }); | ||
| 112 | + const handleCancel = () => {}; | ||
| 113 | +</script> | ||
| 114 | +<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 | + > | ||
| 12 | + <div> | ||
| 13 | + <Description :column="3" size="middle" @register="registeDesc" /> | ||
| 14 | + </div> | ||
| 15 | + </BasicModal> | ||
| 16 | + </div> | ||
| 17 | +</template> | ||
| 18 | +<script setup lang="ts"> | ||
| 19 | + import { ref, nextTick, reactive } from 'vue'; | ||
| 20 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 21 | + import { personSchema } from './config.data'; | ||
| 22 | + import { Description } from '/@/components/Description/index'; | ||
| 23 | + import { useDescription } from '/@/components/Description'; | ||
| 24 | + | ||
| 25 | + const heightNum = ref(800); | ||
| 26 | + let personData = reactive({}); | ||
| 27 | + const [registeDesc, { setDescProps }] = useDescription({ | ||
| 28 | + title: '任务详细信息', | ||
| 29 | + data: personData, | ||
| 30 | + schema: personSchema, | ||
| 31 | + column: 3, | ||
| 32 | + }); | ||
| 33 | + const [register] = useModalInner((data) => { | ||
| 34 | + console.log(data); | ||
| 35 | + nextTick(() => { | ||
| 36 | + Reflect.set(personData, 'b1', '1'); | ||
| 37 | + Reflect.set(personData, 'b2', '默认'); | ||
| 38 | + Reflect.set(personData, 'b3', '系统默认(无参)'); | ||
| 39 | + Reflect.set(personData, 'b4', '2022-08-01 12:01:58'); | ||
| 40 | + Reflect.set(personData, 'b5', '0/10 * * * * ?'); | ||
| 41 | + Reflect.set(personData, 'b6', '2022-08-08 10:25:00'); | ||
| 42 | + Reflect.set(personData, 'b7', 'ryTask.ryNoParams'); | ||
| 43 | + Reflect.set(personData, 'b8', '失败'); | ||
| 44 | + Reflect.set(personData, 'b9', '禁止'); | ||
| 45 | + Reflect.set(personData, 'b10', '禁止'); | ||
| 46 | + setDescProps(personData); | ||
| 47 | + }); | ||
| 48 | + }); | ||
| 49 | + const handleCancel = () => {}; | ||
| 50 | +</script> | ||
| 51 | +<style></style> |
| 1 | import { ref } from 'vue'; | 1 | import { ref } from 'vue'; |
| 2 | +import { DescItem } from '/@/components/Description/index'; | ||
| 2 | import { BasicColumn, FormSchema } from '/@/components/Table'; | 3 | import { BasicColumn, FormSchema } from '/@/components/Table'; |
| 3 | import type { FormSchema as QFormSchema } from '/@/components/Form/index'; | 4 | import type { FormSchema as QFormSchema } from '/@/components/Form/index'; |
| 4 | import moment from 'moment'; | 5 | import moment from 'moment'; |
| @@ -19,7 +20,7 @@ import { | @@ -19,7 +20,7 @@ import { | ||
| 19 | isCountAll, | 20 | isCountAll, |
| 20 | } from './timeConfig'; | 21 | } from './timeConfig'; |
| 21 | import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config'; | 22 | import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config'; |
| 22 | -// import { JCronValidator } from '/@/components/Form'; | 23 | +import { JCronValidator } from '/@/components/Form'; |
| 23 | 24 | ||
| 24 | export enum SchemaFiled { | 25 | export enum SchemaFiled { |
| 25 | WAY = 'way', | 26 | WAY = 'way', |
| @@ -208,13 +209,13 @@ export const formSchema: QFormSchema[] = [ | @@ -208,13 +209,13 @@ export const formSchema: QFormSchema[] = [ | ||
| 208 | ], | 209 | ], |
| 209 | }, | 210 | }, |
| 210 | }, | 211 | }, |
| 211 | - // { | ||
| 212 | - // field: 'cronExpression', | ||
| 213 | - // label: 'Cron表达式', | ||
| 214 | - // component: 'JEasyCron', | ||
| 215 | - // defaultValue: '* * * * * ? *', | ||
| 216 | - // rules: [{ required: true, message: '请输入Cron表达式' }, { validator: JCronValidator }], | ||
| 217 | - // }, | 212 | + { |
| 213 | + field: 'cronExpression', | ||
| 214 | + label: 'Cron表达式', | ||
| 215 | + component: 'JEasyCron', | ||
| 216 | + defaultValue: '* * * * * ? *', | ||
| 217 | + rules: [{ required: true, message: '请输入Cron表达式' }, { validator: JCronValidator }], | ||
| 218 | + }, | ||
| 218 | { | 219 | { |
| 219 | field: 'timeWeek', | 220 | field: 'timeWeek', |
| 220 | component: 'Select', | 221 | component: 'Select', |
| @@ -609,3 +610,148 @@ export const formSchema: QFormSchema[] = [ | @@ -609,3 +610,148 @@ export const formSchema: QFormSchema[] = [ | ||
| 609 | isCountAll(values.agg), | 610 | isCountAll(values.agg), |
| 610 | }, | 611 | }, |
| 611 | ]; | 612 | ]; |
| 613 | + | ||
| 614 | +export const personSchema: DescItem[] = [ | ||
| 615 | + { | ||
| 616 | + field: 'b1', | ||
| 617 | + label: '任务编号:', | ||
| 618 | + }, | ||
| 619 | + { | ||
| 620 | + field: 'b2', | ||
| 621 | + label: '任务分组:', | ||
| 622 | + }, | ||
| 623 | + { | ||
| 624 | + field: 'b3', | ||
| 625 | + label: '任务名称:', | ||
| 626 | + }, | ||
| 627 | + { | ||
| 628 | + field: 'b4', | ||
| 629 | + label: '创建时间:', | ||
| 630 | + }, | ||
| 631 | + { | ||
| 632 | + field: 'b5', | ||
| 633 | + label: 'cron表达式:', | ||
| 634 | + }, | ||
| 635 | + { | ||
| 636 | + field: 'b6', | ||
| 637 | + label: '下次执行时间:', | ||
| 638 | + }, | ||
| 639 | + { | ||
| 640 | + field: 'b7', | ||
| 641 | + label: '调用目标方法:', | ||
| 642 | + }, | ||
| 643 | + { | ||
| 644 | + field: 'b8', | ||
| 645 | + label: '任务状态:', | ||
| 646 | + }, | ||
| 647 | + { | ||
| 648 | + field: 'b9', | ||
| 649 | + label: '是否并发:', | ||
| 650 | + }, | ||
| 651 | + { | ||
| 652 | + field: 'b10', | ||
| 653 | + label: '执行策略:', | ||
| 654 | + }, | ||
| 655 | +]; | ||
| 656 | + | ||
| 657 | +// 调度日志表格配置 | ||
| 658 | +export const columnSchedue: BasicColumn[] = [ | ||
| 659 | + { | ||
| 660 | + title: '日志编号', | ||
| 661 | + dataIndex: 'name', | ||
| 662 | + width: 80, | ||
| 663 | + }, | ||
| 664 | + { | ||
| 665 | + title: '任务名称', | ||
| 666 | + dataIndex: 'organizationId', | ||
| 667 | + width: 120, | ||
| 668 | + }, | ||
| 669 | + { | ||
| 670 | + title: '任务组名', | ||
| 671 | + dataIndex: 'dataCompare', | ||
| 672 | + width: 120, | ||
| 673 | + }, | ||
| 674 | + { | ||
| 675 | + title: '调用目标字符串', | ||
| 676 | + dataIndex: 'status', | ||
| 677 | + width: 120, | ||
| 678 | + }, | ||
| 679 | + { | ||
| 680 | + title: '日志信息', | ||
| 681 | + dataIndex: 'executeWay', | ||
| 682 | + width: 160, | ||
| 683 | + }, | ||
| 684 | + { | ||
| 685 | + title: '执行状态', | ||
| 686 | + dataIndex: 'devices', | ||
| 687 | + width: 160, | ||
| 688 | + }, | ||
| 689 | + { | ||
| 690 | + title: '执行时间', | ||
| 691 | + dataIndex: 'creator', | ||
| 692 | + width: 180, | ||
| 693 | + }, | ||
| 694 | +]; | ||
| 695 | + | ||
| 696 | +// 调度日志表格查询配置 | ||
| 697 | +export const searchSchedueFormSchema: FormSchema[] = [ | ||
| 698 | + { | ||
| 699 | + field: 'name', | ||
| 700 | + label: '任务名称', | ||
| 701 | + component: 'Input', | ||
| 702 | + colProps: { span: 4 }, | ||
| 703 | + componentProps: { | ||
| 704 | + maxLength: 36, | ||
| 705 | + placeholder: '请输入任务名称', | ||
| 706 | + }, | ||
| 707 | + }, | ||
| 708 | + { | ||
| 709 | + field: 'status', | ||
| 710 | + label: '任务组名', | ||
| 711 | + component: 'Select', | ||
| 712 | + colProps: { span: 4 }, | ||
| 713 | + componentProps: { | ||
| 714 | + options: [ | ||
| 715 | + { | ||
| 716 | + label: '默认', | ||
| 717 | + value: 1, | ||
| 718 | + }, | ||
| 719 | + { | ||
| 720 | + label: '系统', | ||
| 721 | + value: 0, | ||
| 722 | + }, | ||
| 723 | + ], | ||
| 724 | + placeholder: '请选择任务组名', | ||
| 725 | + }, | ||
| 726 | + }, | ||
| 727 | + { | ||
| 728 | + field: 'status1', | ||
| 729 | + label: '执行状态', | ||
| 730 | + component: 'Select', | ||
| 731 | + colProps: { span: 4 }, | ||
| 732 | + componentProps: { | ||
| 733 | + options: [ | ||
| 734 | + { | ||
| 735 | + label: '成功', | ||
| 736 | + value: 1, | ||
| 737 | + }, | ||
| 738 | + { | ||
| 739 | + label: '失败', | ||
| 740 | + value: 0, | ||
| 741 | + }, | ||
| 742 | + ], | ||
| 743 | + placeholder: '请选择执行状态', | ||
| 744 | + }, | ||
| 745 | + }, | ||
| 746 | + { | ||
| 747 | + field: 'sendTime', | ||
| 748 | + label: '执行时间', | ||
| 749 | + component: 'RangePicker', | ||
| 750 | + componentProps: { | ||
| 751 | + showTime: { | ||
| 752 | + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], | ||
| 753 | + }, | ||
| 754 | + }, | ||
| 755 | + colProps: { span: 4 }, | ||
| 756 | + }, | ||
| 757 | +]; |
| @@ -45,25 +45,25 @@ | @@ -45,25 +45,25 @@ | ||
| 45 | }, | 45 | }, |
| 46 | ]" | 46 | ]" |
| 47 | :dropDownActions="[ | 47 | :dropDownActions="[ |
| 48 | - { | ||
| 49 | - label: '执行一次', | ||
| 50 | - popConfirm: { | ||
| 51 | - title: '是否执行一次?', | ||
| 52 | - }, | ||
| 53 | - }, | ||
| 54 | - { | ||
| 55 | - label: '任务详细', | ||
| 56 | - popConfirm: { | ||
| 57 | - title: '任务详细', | ||
| 58 | - }, | ||
| 59 | - }, | ||
| 60 | - { | ||
| 61 | - label: '调度日志', | ||
| 62 | - popConfirm: { | ||
| 63 | - title: '调度日志', | ||
| 64 | - }, | 48 | + { |
| 49 | + label: '执行一次', | ||
| 50 | + icon: 'ant-design:caret-right-filled', | ||
| 51 | + popConfirm: { | ||
| 52 | + title: '确认要立即执行一次' + '“' + record.name + '”' + '任务吗?', | ||
| 53 | + confirm: handleDeleteOrBatchDelete.bind(null, record), | ||
| 65 | }, | 54 | }, |
| 66 | - ]" | 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 | /> | 67 | /> |
| 68 | </template> | 68 | </template> |
| 69 | <template #status="{ record }"> | 69 | <template #status="{ record }"> |
| @@ -79,6 +79,8 @@ | @@ -79,6 +79,8 @@ | ||
| 79 | </BasicTable> | 79 | </BasicTable> |
| 80 | <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" /> | 80 | <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" /> |
| 81 | <DevicePreviewModal @register="registerModal" /> | 81 | <DevicePreviewModal @register="registerModal" /> |
| 82 | + <TaskDetailPreviewModal @register="registerModalTaskDetail" /> | ||
| 83 | + <SchedueLog @register="registerModalSchedueLog" /> | ||
| 82 | </div> | 84 | </div> |
| 83 | </template> | 85 | </template> |
| 84 | 86 | ||
| @@ -88,6 +90,8 @@ | @@ -88,6 +90,8 @@ | ||
| 88 | import { useDrawer } from '/@/components/Drawer'; | 90 | import { useDrawer } from '/@/components/Drawer'; |
| 89 | import ReportConfigDrawer from './ReportConfigDrawer.vue'; | 91 | import ReportConfigDrawer from './ReportConfigDrawer.vue'; |
| 90 | import DevicePreviewModal from './DevicePreviewModal.vue'; | 92 | import DevicePreviewModal from './DevicePreviewModal.vue'; |
| 93 | + import TaskDetailPreviewModal from './TaskDetailPreviewModal.vue'; | ||
| 94 | + import SchedueLog from './SchedueLog.vue'; | ||
| 91 | import { | 95 | import { |
| 92 | reportPage, | 96 | reportPage, |
| 93 | deleteReportManage, | 97 | deleteReportManage, |
| @@ -162,6 +166,8 @@ | @@ -162,6 +166,8 @@ | ||
| 162 | 166 | ||
| 163 | //查看设备 | 167 | //查看设备 |
| 164 | const [registerModal, { openModal }] = useModal(); | 168 | const [registerModal, { openModal }] = useModal(); |
| 169 | + const [registerModalTaskDetail, { openModal: openModalTaskDetail }] = useModal(); | ||
| 170 | + const [registerModalSchedueLog, { openModal: openModalSchedueLog }] = useModal(); | ||
| 165 | const handleDeviceView = (record) => { | 171 | const handleDeviceView = (record) => { |
| 166 | openModal(true, { | 172 | openModal(true, { |
| 167 | isUpdate: true, | 173 | isUpdate: true, |
| @@ -192,4 +198,17 @@ | @@ -192,4 +198,17 @@ | ||
| 192 | } | 198 | } |
| 193 | }; | 199 | }; |
| 194 | const go = useGo(); | 200 | 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 | + }; | ||
| 195 | </script> | 214 | </script> |