Showing
6 changed files
with
186 additions
and
12 deletions
@@ -67,7 +67,7 @@ | @@ -67,7 +67,7 @@ | ||
67 | // margin-top 24 height 24 | 67 | // margin-top 24 height 24 |
68 | const paginationHeight = 24 + 24 + 8; | 68 | const paginationHeight = 24 + 24 + 8; |
69 | // list pading top 8 maring-top 8 extra slot 56 | 69 | // list pading top 8 maring-top 8 extra slot 56 |
70 | - const listContainerMarginBottom = 8 + 8 + 56; | 70 | + const listContainerMarginBottom = 8 + 8 + 72; |
71 | const listContainerHeight = | 71 | const listContainerHeight = |
72 | clientHeight - rect.top - paginationHeight - listContainerMarginBottom; | 72 | clientHeight - rect.top - paginationHeight - listContainerMarginBottom; |
73 | const listContainerEl = (unref(listElRef)!.$el as HTMLElement).querySelector( | 73 | const listContainerEl = (unref(listElRef)!.$el as HTMLElement).querySelector( |
@@ -86,7 +86,7 @@ | @@ -86,7 +86,7 @@ | ||
86 | </script> | 86 | </script> |
87 | 87 | ||
88 | <template> | 88 | <template> |
89 | - <PageWrapper class="bg-gray-100"> | 89 | + <PageWrapper class="bg-gray-100 device-task-list-container"> |
90 | <section | 90 | <section |
91 | class="form-container bg-light-50 px-4 pt-4 mt-4 x dark:text-gray-300 dark:bg-dark-900" | 91 | class="form-container bg-light-50 px-4 pt-4 mt-4 x dark:text-gray-300 dark:bg-dark-900" |
92 | > | 92 | > |
@@ -101,7 +101,10 @@ | @@ -101,7 +101,10 @@ | ||
101 | :loading="loading" | 101 | :loading="loading" |
102 | > | 102 | > |
103 | <template #header> | 103 | <template #header> |
104 | - <section class="flex justify-end gap-4"> | 104 | + <section class="flex justify-between gap-4 min-h-12 items-center"> |
105 | + <div class="text-lg font-semibold"> | ||
106 | + <span>任务列表</span> | ||
107 | + </div> | ||
105 | <Tooltip title="刷新"> | 108 | <Tooltip title="刷新"> |
106 | <Button type="primary" @click="getDataSource"> | 109 | <Button type="primary" @click="getDataSource"> |
107 | <ReloadOutlined :spin="loading" /> | 110 | <ReloadOutlined :spin="loading" /> |
@@ -123,3 +126,15 @@ | @@ -123,3 +126,15 @@ | ||
123 | </section> | 126 | </section> |
124 | </PageWrapper> | 127 | </PageWrapper> |
125 | </template> | 128 | </template> |
129 | + | ||
130 | +<style lang="less" scoped> | ||
131 | + .device-task-list-container { | ||
132 | + :deep(.ant-list-header) { | ||
133 | + border: none; | ||
134 | + } | ||
135 | + | ||
136 | + :deep(.ant-card-body) { | ||
137 | + padding: 16px 24px; | ||
138 | + } | ||
139 | + } | ||
140 | +</style> |
1 | +import { TaskTargetEnum } from '../../config'; | ||
2 | +import { FormSchema } from '/@/components/Form'; | ||
3 | + | ||
4 | +export enum FormFieldsEnum { | ||
5 | + RUN_TARGET_TYPE = 'runTargetType', | ||
6 | + TASK_TYPE = 'taskType', | ||
7 | + ASSIGN_TARGET = 'assignTarget', | ||
8 | + TASK_TARGET_TYPE = 'taskTargetType', | ||
9 | + TASK_TARGET_VALUE = 'taskTargetValue', | ||
10 | +} | ||
11 | + | ||
12 | +export enum TargetType { | ||
13 | + ALL = 'ALL', | ||
14 | + ASSIGN = 'ASSIGN', | ||
15 | +} | ||
16 | + | ||
17 | +export enum TargetNameType { | ||
18 | + ALL = '所有目标设备', | ||
19 | + ASSIGN = '指定目标设备', | ||
20 | +} | ||
21 | + | ||
22 | +export const formSchemas: FormSchema[] = [ | ||
23 | + { | ||
24 | + field: 'taskName', | ||
25 | + component: 'Input', | ||
26 | + label: '任务名称', | ||
27 | + slot: 'taskName', | ||
28 | + }, | ||
29 | + { | ||
30 | + field: FormFieldsEnum.TASK_TYPE, | ||
31 | + component: 'Input', | ||
32 | + label: '任务类型', | ||
33 | + slot: 'taskType', | ||
34 | + }, | ||
35 | + { | ||
36 | + field: FormFieldsEnum.TASK_TARGET_TYPE, | ||
37 | + component: 'Input', | ||
38 | + label: '目标类型', | ||
39 | + show: false, | ||
40 | + }, | ||
41 | + { | ||
42 | + field: FormFieldsEnum.TASK_TARGET_VALUE, | ||
43 | + component: 'Input', | ||
44 | + label: '目标值', | ||
45 | + show: false, | ||
46 | + }, | ||
47 | + { | ||
48 | + field: FormFieldsEnum.TASK_TYPE, | ||
49 | + component: 'Input', | ||
50 | + label: '任务类型', | ||
51 | + renderComponentContent: 'taskType', | ||
52 | + show: false, | ||
53 | + }, | ||
54 | + { | ||
55 | + field: FormFieldsEnum.RUN_TARGET_TYPE, | ||
56 | + component: 'RadioGroup', | ||
57 | + label: '选择目标类型', | ||
58 | + helpMessage: [ | ||
59 | + '您可以对该任务关联的所有设备批量执行任务,也可以指定其中的一个或多个关联的设备来执行任务。', | ||
60 | + ], | ||
61 | + defaultValue: TargetType.ALL, | ||
62 | + componentProps: { | ||
63 | + options: [ | ||
64 | + { label: TargetNameType.ALL, value: TargetType.ALL }, | ||
65 | + { label: TargetNameType.ASSIGN, value: TargetType.ASSIGN }, | ||
66 | + ], | ||
67 | + }, | ||
68 | + }, | ||
69 | + { | ||
70 | + field: FormFieldsEnum.ASSIGN_TARGET, | ||
71 | + component: 'ApiSelect', | ||
72 | + label: '制定目标设备', | ||
73 | + ifShow: ({ model }) => model[FormFieldsEnum.RUN_TARGET_TYPE] === TargetType.ASSIGN, | ||
74 | + componentProps: ({ formModel }) => { | ||
75 | + const taskTargetType = formModel[FormFieldsEnum.TASK_TARGET_TYPE]; | ||
76 | + const isDevices = taskTargetType === TaskTargetEnum.DEVICES; | ||
77 | + return { | ||
78 | + api: async () => { | ||
79 | + try { | ||
80 | + if (isDevices) { | ||
81 | + } else { | ||
82 | + } | ||
83 | + } catch (error) { | ||
84 | + return []; | ||
85 | + } | ||
86 | + }, | ||
87 | + getPopupContainer: () => document.body, | ||
88 | + }; | ||
89 | + }, | ||
90 | + }, | ||
91 | +]; |
1 | +export { default as RunTaskModal } from './index.vue'; |
1 | +<script lang="ts" setup> | ||
2 | + import { ref } from 'vue'; | ||
3 | + import { TaskRecordType } from '/@/api/task/model'; | ||
4 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
5 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
6 | + import { TaskTypeNameEnum } from '../../config'; | ||
7 | + import { formSchemas } from './config'; | ||
8 | + | ||
9 | + defineEmits(['register']); | ||
10 | + | ||
11 | + const dataSource = ref<TaskRecordType>(); | ||
12 | + | ||
13 | + const [registerModal] = useModalInner((record: TaskRecordType) => { | ||
14 | + dataSource.value = record; | ||
15 | + if (record) { | ||
16 | + setFieldsValue(record); | ||
17 | + } | ||
18 | + }); | ||
19 | + | ||
20 | + const [registerForm, { setFieldsValue }] = useForm({ | ||
21 | + schemas: formSchemas, | ||
22 | + showActionButtonGroup: false, | ||
23 | + }); | ||
24 | +</script> | ||
25 | + | ||
26 | +<template> | ||
27 | + <BasicModal @register="registerModal" title="运行任务"> | ||
28 | + <BasicForm @register="registerForm"> | ||
29 | + <template #taskName> | ||
30 | + <div class="font-semibold"> | ||
31 | + {{ dataSource?.name }} | ||
32 | + </div> | ||
33 | + </template> | ||
34 | + <template #taskType> | ||
35 | + <div class="font-semibold"> | ||
36 | + {{ | ||
37 | + dataSource ? TaskTypeNameEnum[dataSource.executeContent.type] : TaskTypeNameEnum.CUSTOM | ||
38 | + }} | ||
39 | + </div> | ||
40 | + </template> | ||
41 | + </BasicForm> | ||
42 | + </BasicModal> | ||
43 | +</template> |
@@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
35 | } | 35 | } |
36 | ); | 36 | ); |
37 | 37 | ||
38 | - const emit = defineEmits(['edit']); | 38 | + const emit = defineEmits(['edit', 'runTask']); |
39 | 39 | ||
40 | const loading = ref(false); | 40 | const loading = ref(false); |
41 | 41 | ||
@@ -117,6 +117,10 @@ | @@ -117,6 +117,10 @@ | ||
117 | if (!unref(getRecord).lastExecuteTime) return; | 117 | if (!unref(getRecord).lastExecuteTime) return; |
118 | return getTwoDateDiff(unref(getRecord).lastExecuteTime!); | 118 | return getTwoDateDiff(unref(getRecord).lastExecuteTime!); |
119 | }); | 119 | }); |
120 | + | ||
121 | + const handleRunTask = () => { | ||
122 | + emit('runTask', unref(getRecord)); | ||
123 | + }; | ||
120 | </script> | 124 | </script> |
121 | 125 | ||
122 | <template> | 126 | <template> |
@@ -186,7 +190,7 @@ | @@ -186,7 +190,7 @@ | ||
186 | </div> | 190 | </div> |
187 | </div> | 191 | </div> |
188 | <div class="mt-4 flex justify-between items-center gap-3"> | 192 | <div class="mt-4 flex justify-between items-center gap-3"> |
189 | - <Button size="small"> | 193 | + <Button size="small" @click="handleRunTask"> |
190 | <div class="text-xs px-1"> | 194 | <div class="text-xs px-1"> |
191 | <PlayCircleOutlined class="mr-1" /> | 195 | <PlayCircleOutlined class="mr-1" /> |
192 | <span>运行任务</span> | 196 | <span>运行任务</span> |
@@ -16,8 +16,10 @@ | @@ -16,8 +16,10 @@ | ||
16 | import { ModalParamsType } from '/#/utils'; | 16 | import { ModalParamsType } from '/#/utils'; |
17 | import { Authority } from '/@/components/Authority'; | 17 | import { Authority } from '/@/components/Authority'; |
18 | import { getBoundingClientRect } from '/@/utils/domUtils'; | 18 | import { getBoundingClientRect } from '/@/utils/domUtils'; |
19 | + import { RunTaskModal } from './components/RunTaskModal'; | ||
19 | 20 | ||
20 | const [registerModal, { openModal }] = useModal(); | 21 | const [registerModal, { openModal }] = useModal(); |
22 | + const [registerRunTaskModal, { openModal: openRunTaskModal }] = useModal(); | ||
21 | 23 | ||
22 | const [registerForm, { getFieldsValue }] = useForm({ | 24 | const [registerForm, { getFieldsValue }] = useForm({ |
23 | schemas: formSchemas, | 25 | schemas: formSchemas, |
@@ -61,6 +63,10 @@ | @@ -61,6 +63,10 @@ | ||
61 | } as ModalParamsType); | 63 | } as ModalParamsType); |
62 | }; | 64 | }; |
63 | 65 | ||
66 | + const handleRunTask = (record: TaskRecordType) => { | ||
67 | + openRunTaskModal(true, record); | ||
68 | + }; | ||
69 | + | ||
64 | const reload = () => getDataSource(); | 70 | const reload = () => getDataSource(); |
65 | 71 | ||
66 | const listElRef = ref<Nullable<ComponentElRef>>(null); | 72 | const listElRef = ref<Nullable<ComponentElRef>>(null); |
@@ -71,7 +77,7 @@ | @@ -71,7 +77,7 @@ | ||
71 | // margin-top 24 height 24 | 77 | // margin-top 24 height 24 |
72 | const paginationHeight = 24 + 24 + 8; | 78 | const paginationHeight = 24 + 24 + 8; |
73 | // list pading top 8 maring-top 8 extra slot 56 | 79 | // list pading top 8 maring-top 8 extra slot 56 |
74 | - const listContainerMarginBottom = 8 + 8 + 56; | 80 | + const listContainerMarginBottom = 8 + 8 + 72; |
75 | const listContainerHeight = | 81 | const listContainerHeight = |
76 | clientHeight - rect.top - paginationHeight - listContainerMarginBottom; | 82 | clientHeight - rect.top - paginationHeight - listContainerMarginBottom; |
77 | const listContainerEl = (unref(listElRef)!.$el as HTMLElement).querySelector( | 83 | const listContainerEl = (unref(listElRef)!.$el as HTMLElement).querySelector( |
@@ -90,7 +96,7 @@ | @@ -90,7 +96,7 @@ | ||
90 | </script> | 96 | </script> |
91 | 97 | ||
92 | <template> | 98 | <template> |
93 | - <PageWrapper class="container"> | 99 | + <PageWrapper class="task-center-container"> |
94 | <section | 100 | <section |
95 | class="bg-light-50 flex p-4 justify-between items-center x dark:text-gray-300 dark:bg-dark-900" | 101 | class="bg-light-50 flex p-4 justify-between items-center x dark:text-gray-300 dark:bg-dark-900" |
96 | > | 102 | > |
@@ -109,7 +115,7 @@ | @@ -109,7 +115,7 @@ | ||
109 | > | 115 | > |
110 | <BasicForm @register="registerForm" /> | 116 | <BasicForm @register="registerForm" /> |
111 | </section> | 117 | </section> |
112 | - <section class="bg-light-50 mt-4 p-4 x dark:text-gray-300 dark:bg-dark-900"> | 118 | + <section class="bg-light-50 mt-4 p-4 dark:text-gray-300 dark:bg-dark-900"> |
113 | <List | 119 | <List |
114 | ref="listElRef" | 120 | ref="listElRef" |
115 | :dataSource="dataSource" | 121 | :dataSource="dataSource" |
@@ -118,8 +124,11 @@ | @@ -118,8 +124,11 @@ | ||
118 | :loading="loading" | 124 | :loading="loading" |
119 | > | 125 | > |
120 | <template #header> | 126 | <template #header> |
121 | - <section class="flex justify-end gap-4"> | ||
122 | - <Tooltip title="刷新"> | 127 | + <section class="flex justify-between gap-4 min-h-12 items-center"> |
128 | + <div> | ||
129 | + <span class="text-lg font-medium">任务列表</span> | ||
130 | + </div> | ||
131 | + <Tooltip v-if="dataSource.length" title="刷新"> | ||
123 | <Button type="primary" @click="getDataSource"> | 132 | <Button type="primary" @click="getDataSource"> |
124 | <ReloadOutlined :spin="loading" /> | 133 | <ReloadOutlined :spin="loading" /> |
125 | </Button> | 134 | </Button> |
@@ -128,13 +137,24 @@ | @@ -128,13 +137,24 @@ | ||
128 | </template> | 137 | </template> |
129 | <template #renderItem="{ item }"> | 138 | <template #renderItem="{ item }"> |
130 | <List.Item :key="item.id"> | 139 | <List.Item :key="item.id"> |
131 | - <TaskCard :record="item" :reload="reload" @edit="handleEdit" /> | 140 | + <TaskCard :record="item" :reload="reload" @runTask="handleRunTask" @edit="handleEdit" /> |
132 | </List.Item> | 141 | </List.Item> |
133 | </template> | 142 | </template> |
134 | </List> | 143 | </List> |
135 | </section> | 144 | </section> |
136 | <DetailModal @register="registerModal" :reload="reload" /> | 145 | <DetailModal @register="registerModal" :reload="reload" /> |
146 | + <RunTaskModal @register="registerRunTaskModal" /> | ||
137 | </PageWrapper> | 147 | </PageWrapper> |
138 | </template> | 148 | </template> |
139 | 149 | ||
140 | -<style lang="less" scoped></style> | 150 | +<style lang="less" scoped> |
151 | + .task-center-container { | ||
152 | + :deep(.ant-list-header) { | ||
153 | + border: none; | ||
154 | + } | ||
155 | + | ||
156 | + :deep(.ant-card-body) { | ||
157 | + padding: 16px 24px; | ||
158 | + } | ||
159 | + } | ||
160 | +</style> |