Showing
13 changed files
with
342 additions
and
51 deletions
1 | +import { DeviceRecord } from '../device/model/deviceModel'; | |
1 | 2 | import { |
2 | 3 | AddDataBoardParams, |
3 | 4 | AddDataComponentParams, |
... | ... | @@ -183,7 +184,7 @@ export const getAllDeviceByOrg = (organizationId: string, deviceProfileId?: stri |
183 | 184 | * @returns |
184 | 185 | */ |
185 | 186 | export const getMeetTheConditionsDevice = (params: GetMeetTheConditionsDeviceParams) => { |
186 | - return defHttp.get({ | |
187 | + return defHttp.get<DeviceRecord[]>({ | |
187 | 188 | url: DeviceUrl.GET_DEVICE, |
188 | 189 | params, |
189 | 190 | }); | ... | ... |
... | ... | @@ -40,6 +40,11 @@ enum DeviceManagerApi { |
40 | 40 | DEVICE_PUBLIC = '/customer/public/device', |
41 | 41 | |
42 | 42 | DEVICE_PRIVATE = '/customer/device', |
43 | + | |
44 | + /** | |
45 | + * @description 通过设备列表获取设备信息 | |
46 | + */ | |
47 | + QUERY_DEVICES = '/device/get/devices', | |
43 | 48 | } |
44 | 49 | |
45 | 50 | export const devicePage = (params: DeviceQueryParam) => { |
... | ... | @@ -330,3 +335,10 @@ export const privateDevice = (tbDeviceId: string) => { |
330 | 335 | { joinPrefix: false } |
331 | 336 | ); |
332 | 337 | }; |
338 | + | |
339 | +export const getDevicesByDeviceIds = (ids: string[]) => { | |
340 | + return defHttp.post<Record<'data', DeviceModel[]>>({ | |
341 | + url: DeviceManagerApi.QUERY_DEVICES, | |
342 | + data: ids, | |
343 | + }); | |
344 | +}; | ... | ... |
... | ... | @@ -2,6 +2,7 @@ import { |
2 | 2 | CreateTaskRecordType, |
3 | 3 | GenModbusCommandType, |
4 | 4 | GetTaskListParamsType, |
5 | + ImmediateExecuteTaskType, | |
5 | 6 | TaskRecordType, |
6 | 7 | } from './model'; |
7 | 8 | import { PaginationResult } from '/#/axios'; |
... | ... | @@ -16,6 +17,8 @@ enum Api { |
16 | 17 | CANCEL_TASK = '/task_center', |
17 | 18 | |
18 | 19 | GEN_MODBUS_COMMAND = '/js/modbus', |
20 | + | |
21 | + IMMEDIATE_EXECUTE = '/task_center/immediate/execute', | |
19 | 22 | } |
20 | 23 | |
21 | 24 | export const getTaskCenterList = (params: GetTaskListParamsType) => { |
... | ... | @@ -76,3 +79,13 @@ export const genModbusCommand = (data: GenModbusCommandType) => { |
76 | 79 | data, |
77 | 80 | }); |
78 | 81 | }; |
82 | + | |
83 | +export const immediateExecute = (data: ImmediateExecuteTaskType) => { | |
84 | + return defHttp.post<Record<'data', boolean>>( | |
85 | + { | |
86 | + url: Api.IMMEDIATE_EXECUTE, | |
87 | + params: data, | |
88 | + }, | |
89 | + { joinParamsToUrl: true } | |
90 | + ); | |
91 | +}; | ... | ... |
... | ... | @@ -62,3 +62,11 @@ export interface GenModbusCommandType { |
62 | 62 | registerNum?: number; |
63 | 63 | registerValues?: number[]; |
64 | 64 | } |
65 | + | |
66 | +export interface ImmediateExecuteTaskType { | |
67 | + executeTarget: TaskTargetEnum; | |
68 | + id: string; | |
69 | + cronExpression: string; | |
70 | + targetIds: string[]; | |
71 | + name: string; | |
72 | +} | ... | ... |
... | ... | @@ -9,13 +9,13 @@ import { |
9 | 9 | import { PollCommandInput, ModeEnum } from '../PollCommandInput'; |
10 | 10 | import { DeviceProfileModel } from '/@/api/device/model/deviceModel'; |
11 | 11 | import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; |
12 | -import { getDeviceProfile } from '/@/api/alarm/position'; | |
13 | 12 | import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor'; |
14 | 13 | import { TimeUnitEnum, TimeUnitNameEnum } from '/@/enums/toolEnum'; |
15 | -import { createPickerSearch } from '/@/utils/pickerSearch'; | |
16 | 14 | import { dateUtil } from '/@/utils/dateUtil'; |
15 | +import { ProductPicker, validateProductPicker } from '../ProductPicker'; | |
17 | 16 | |
18 | 17 | useComponentRegister('DevicePicker', DevicePicker); |
18 | +useComponentRegister('ProductPicker', ProductPicker); | |
19 | 19 | useComponentRegister('PollCommandInput', PollCommandInput); |
20 | 20 | |
21 | 21 | export enum FormFieldsEnum { |
... | ... | @@ -108,27 +108,26 @@ export const formSchemas: FormSchema[] = [ |
108 | 108 | }, |
109 | 109 | { |
110 | 110 | field: FormFieldsEnum.DEVICE_PROFILE, |
111 | - component: 'ApiSelect', | |
111 | + component: 'ProductPicker', | |
112 | 112 | label: '产品', |
113 | 113 | ifShow: ({ model }) => model[FormFieldsEnum.TARGET_TYPE] === TaskTargetEnum.PRODUCTS, |
114 | + valueField: 'value', | |
115 | + changeEvent: 'update:value', | |
116 | + rules: [validateProductPicker()], | |
117 | + helpMessage: ['任务可以对目标产品按预设的时间策略执行任务。'], | |
114 | 118 | componentProps: ({ formActionType }) => { |
115 | 119 | const { setFieldsValue } = formActionType; |
116 | 120 | return { |
117 | - api: getDeviceProfile, | |
118 | - placeholder: '请选择产品', | |
119 | - labelField: 'name', | |
120 | - valueField: 'id', | |
121 | - onChange(value: string, option: DeviceProfileModel) { | |
122 | - if (value) { | |
123 | - const isTCP = option.transportType === TransportTypeEnum.TCP; | |
121 | + onChange(key: string, _value: string | string[], option: DeviceProfileModel) { | |
122 | + if (key === DeviceCascadePickerFieldsEnum.DEVICE_PROFILE) { | |
123 | + const isTCP = (option || {}).transportType === TransportTypeEnum.TCP; | |
124 | 124 | setFieldsValue({ |
125 | - [FormFieldsEnum.TRANSPORT_TYPE]: isTCP ? PushWayEnum.TCP : PushWayEnum.MQTT, | |
125 | + [FormFieldsEnum.TRANSPORT_TYPE]: _value ? option.transportType : null, | |
126 | 126 | [FormFieldsEnum.PUSH_WAY]: isTCP ? PushWayEnum.TCP : PushWayEnum.MQTT, |
127 | 127 | ...(isTCP ? {} : { [FormFieldsEnum.EXECUTE_CONTENT_TYPE]: TaskTypeEnum.CUSTOM }), |
128 | 128 | }); |
129 | 129 | } |
130 | 130 | }, |
131 | - ...createPickerSearch(), | |
132 | 131 | getPopupContainer: () => document.body, |
133 | 132 | }; |
134 | 133 | }, | ... | ... |
... | ... | @@ -5,9 +5,11 @@ import { CreateTaskRecordType, TaskRecordType } from '/@/api/task/model'; |
5 | 5 | import { DeviceCascadePickerValueType } from '../DevicePicker'; |
6 | 6 | import { TaskTargetEnum } from '../../config'; |
7 | 7 | import { TimeUnitEnum } from '/@/enums/toolEnum'; |
8 | +import { ProductCascadePickerValueType } from '../ProductPicker'; | |
8 | 9 | |
9 | 10 | export interface FormValueType extends Partial<Record<FormFieldsEnum, any>> { |
10 | 11 | [FormFieldsEnum.EXECUTE_TARGET_DATA]: DeviceCascadePickerValueType; |
12 | + [FormFieldsEnum.DEVICE_PROFILE]: ProductCascadePickerValueType; | |
11 | 13 | } |
12 | 14 | |
13 | 15 | type CanWrite<T> = { |
... | ... | @@ -95,6 +97,12 @@ export const composeData = (result: Required<FormValueType>): CreateTaskRecordTy |
95 | 97 | |
96 | 98 | const { organizationId, deviceType, deviceId, deviceProfileId } = executeTargetData || {}; |
97 | 99 | |
100 | + const { | |
101 | + organizationId: productOrg, | |
102 | + deviceProfileId: productId, | |
103 | + deviceType: productDeviceType, | |
104 | + } = deviceProfile || {}; | |
105 | + | |
98 | 106 | const { expression } = genCronExpression(time, period); |
99 | 107 | |
100 | 108 | const cron = |
... | ... | @@ -111,10 +119,10 @@ export const composeData = (result: Required<FormValueType>): CreateTaskRecordTy |
111 | 119 | type: executeContentType, |
112 | 120 | }, |
113 | 121 | executeTarget: { |
114 | - data: targetType === TaskTargetEnum.PRODUCTS ? [deviceProfile] : (deviceId as string[]), | |
115 | - deviceType, | |
116 | - organizationId, | |
117 | - deviceProfileId: targetType === TaskTargetEnum.PRODUCTS ? deviceProfile : deviceProfileId, | |
122 | + data: targetType === TaskTargetEnum.PRODUCTS ? [productId] : (deviceId as string[]), | |
123 | + deviceType: targetType === TaskTargetEnum.PRODUCTS ? productDeviceType : deviceType, | |
124 | + organizationId: targetType === TaskTargetEnum.PRODUCTS ? productOrg : organizationId, | |
125 | + deviceProfileId: targetType === TaskTargetEnum.PRODUCTS ? productId : deviceProfileId, | |
118 | 126 | }, |
119 | 127 | executeTime: { |
120 | 128 | type: executeTimeType, |
... | ... | @@ -147,7 +155,14 @@ export const parseData = (result: TaskRecordType): Required<FormValueType> => { |
147 | 155 | deviceType, |
148 | 156 | organizationId, |
149 | 157 | }, |
150 | - deviceProfile: targetType === TaskTargetEnum.PRODUCTS ? data : null, | |
158 | + deviceProfile: | |
159 | + targetType === TaskTargetEnum.PRODUCTS | |
160 | + ? { | |
161 | + deviceProfileId: data[0], | |
162 | + deviceType, | |
163 | + organizationId, | |
164 | + } | |
165 | + : ({} as unknown as ProductCascadePickerValueType), | |
151 | 166 | executeTimeType, |
152 | 167 | period, |
153 | 168 | periodType: executeTimeType === ExecuteTimeTypeEnum.CUSTOM ? periodType : null, | ... | ... |
1 | +export { default as ProductPicker } from './index.vue'; | |
2 | + | |
3 | +export enum FormFieldsEnum { | |
4 | + DEVICE_TYPE = 'deviceType', | |
5 | + DEVICE_PROFILE = 'deviceProfileId', | |
6 | + ORGANIZATION = 'organizationId', | |
7 | +} | |
8 | + | |
9 | +export type ProductCascadePickerValueType = Record<FormFieldsEnum, string>; | |
10 | + | |
11 | +export { validateProductPicker } from './utils'; | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { getOrganizationList } from '/@/api/system/system'; | |
3 | + import { BasicForm, useForm } from '/@/components/Form'; | |
4 | + import { copyTransFun } from '/@/utils/fnUtils'; | |
5 | + import { watch } from 'vue'; | |
6 | + import { nextTick } from 'vue'; | |
7 | + import { getDeviceProfile } from '/@/api/alarm/position'; | |
8 | + import { findDictItemByCode } from '/@/api/system/dict'; | |
9 | + import { DictEnum } from '/@/enums/dictEnum'; | |
10 | + import { FormFieldsEnum } from '.'; | |
11 | + import { isObject } from '/@/utils/is'; | |
12 | + import { createPickerSearch } from '/@/utils/pickerSearch'; | |
13 | + | |
14 | + const props = withDefaults( | |
15 | + defineProps<{ | |
16 | + value?: Recordable; | |
17 | + }>(), | |
18 | + { | |
19 | + value: () => ({}), | |
20 | + } | |
21 | + ); | |
22 | + | |
23 | + const emit = defineEmits(['update:value', 'change']); | |
24 | + | |
25 | + const handleChange = (key: string, value: string | string[], option: Recordable) => { | |
26 | + emit('change', key, value, option); | |
27 | + }; | |
28 | + | |
29 | + const handleEmit = async (key: string, value: string | string[], option: Recordable) => { | |
30 | + await nextTick(); | |
31 | + let _value = getFieldsValue(); | |
32 | + _value = { | |
33 | + ..._value, | |
34 | + | |
35 | + ...(key === FormFieldsEnum.DEVICE_TYPE | |
36 | + ? { | |
37 | + [FormFieldsEnum.DEVICE_PROFILE]: null, | |
38 | + } | |
39 | + : {}), | |
40 | + }; | |
41 | + handleChange(key, value, option); | |
42 | + emit('update:value', { ..._value }); | |
43 | + }; | |
44 | + | |
45 | + const [register, { setFieldsValue, getFieldsValue, resetFields }] = useForm({ | |
46 | + schemas: [ | |
47 | + { | |
48 | + field: FormFieldsEnum.DEVICE_TYPE, | |
49 | + component: 'ApiSelect', | |
50 | + label: '', | |
51 | + componentProps: () => { | |
52 | + return { | |
53 | + api: findDictItemByCode, | |
54 | + params: { | |
55 | + dictCode: DictEnum.DEVICE_TYPE, | |
56 | + }, | |
57 | + labelField: 'itemText', | |
58 | + valueField: 'itemValue', | |
59 | + placeholder: '请选择设备类型', | |
60 | + onChange(value: string, option: Recordable) { | |
61 | + handleEmit(FormFieldsEnum.DEVICE_TYPE, value, option); | |
62 | + }, | |
63 | + getPopupContainer: () => document.body, | |
64 | + ...createPickerSearch(), | |
65 | + }; | |
66 | + }, | |
67 | + }, | |
68 | + { | |
69 | + field: FormFieldsEnum.ORGANIZATION, | |
70 | + component: 'ApiTreeSelect', | |
71 | + label: '', | |
72 | + componentProps: () => { | |
73 | + return { | |
74 | + api: async () => { | |
75 | + try { | |
76 | + const data = await getOrganizationList(); | |
77 | + copyTransFun(data as any); | |
78 | + return data; | |
79 | + } catch (error) { | |
80 | + console.log(error); | |
81 | + return []; | |
82 | + } | |
83 | + }, | |
84 | + placeholder: '请选择组织', | |
85 | + labelField: 'name', | |
86 | + valueField: 'id', | |
87 | + childField: 'children', | |
88 | + onChange(value: string, option: Recordable) { | |
89 | + handleEmit(FormFieldsEnum.ORGANIZATION, value, option); | |
90 | + }, | |
91 | + getPopupContainer: () => document.body, | |
92 | + }; | |
93 | + }, | |
94 | + }, | |
95 | + { | |
96 | + field: FormFieldsEnum.DEVICE_PROFILE, | |
97 | + component: 'ApiSelect', | |
98 | + label: '', | |
99 | + componentProps: ({ formModel }) => { | |
100 | + const deviceType = Reflect.get(formModel, FormFieldsEnum.DEVICE_TYPE); | |
101 | + return { | |
102 | + api: async () => { | |
103 | + try { | |
104 | + return await getDeviceProfile(deviceType); | |
105 | + } catch (error) { | |
106 | + return []; | |
107 | + } | |
108 | + }, | |
109 | + placeholder: '请选择产品', | |
110 | + labelField: 'name', | |
111 | + valueField: 'id', | |
112 | + onChange(value: string, options: Recordable) { | |
113 | + handleEmit(FormFieldsEnum.DEVICE_PROFILE, value, options); | |
114 | + }, | |
115 | + getPopupContainer: () => document.body, | |
116 | + ...createPickerSearch(), | |
117 | + }; | |
118 | + }, | |
119 | + }, | |
120 | + ], | |
121 | + showActionButtonGroup: false, | |
122 | + layout: 'inline', | |
123 | + baseColProps: { span: 8 }, | |
124 | + }); | |
125 | + | |
126 | + const setValue = async () => { | |
127 | + await nextTick(); | |
128 | + if (!props.value || (isObject(props.value) && !Object.values(props.value).length)) { | |
129 | + resetFields(); | |
130 | + return; | |
131 | + } | |
132 | + setFieldsValue(props.value); | |
133 | + }; | |
134 | + | |
135 | + watch( | |
136 | + () => props.value, | |
137 | + () => { | |
138 | + setValue(); | |
139 | + }, | |
140 | + { | |
141 | + immediate: true, | |
142 | + } | |
143 | + ); | |
144 | +</script> | |
145 | + | |
146 | +<template> | |
147 | + <BasicForm @register="register" class="device-picker" /> | |
148 | +</template> | |
149 | + | |
150 | +<style lang="less" scoped> | |
151 | + .device-picker { | |
152 | + :deep(.ant-row) { | |
153 | + width: 100%; | |
154 | + } | |
155 | + | |
156 | + :deep(.ant-form-item-control-input-content) { | |
157 | + div > div { | |
158 | + width: 100%; | |
159 | + } | |
160 | + } | |
161 | + } | |
162 | +</style> | ... | ... |
1 | +import { FormFieldsEnum } from '.'; | |
2 | +import { Rule } from '/@/components/Form'; | |
3 | + | |
4 | +export const validateProductPicker = () => { | |
5 | + return { | |
6 | + required: true, | |
7 | + validateTrigger: 'blur', | |
8 | + validator(_rule: Recordable, value: Recordable, _callback: Fn) { | |
9 | + const product = Reflect.get(value || {}, FormFieldsEnum.DEVICE_PROFILE); | |
10 | + const org = Reflect.get(value || {}, FormFieldsEnum.ORGANIZATION); | |
11 | + if (!product) return Promise.reject('请选择产品'); | |
12 | + if (!org) return Promise.reject('请选择组织'); | |
13 | + return Promise.resolve(); | |
14 | + }, | |
15 | + } as Rule; | |
16 | +}; | ... | ... |
1 | 1 | import { TaskTargetEnum } from '../../config'; |
2 | +import { getMeetTheConditionsDevice } from '/@/api/dataBoard'; | |
3 | +import { getDevicesByDeviceIds } from '/@/api/device/deviceManager'; | |
4 | +import { TaskRecordType } from '/@/api/task/model'; | |
2 | 5 | import { FormSchema } from '/@/components/Form'; |
6 | +import { createPickerSearch } from '/@/utils/pickerSearch'; | |
7 | + | |
8 | +export interface FormValue extends Record<FormFieldsEnum, any> { | |
9 | + [FormFieldsEnum.TASK_RECORD]: string; | |
10 | +} | |
3 | 11 | |
4 | 12 | export enum FormFieldsEnum { |
5 | - RUN_TARGET_TYPE = 'runTargetType', | |
13 | + EXECUTE_TARGET_TYPE = 'executeTarget', | |
6 | 14 | TASK_TYPE = 'taskType', |
7 | - ASSIGN_TARGET = 'assignTarget', | |
8 | - TASK_TARGET_TYPE = 'taskTargetType', | |
9 | - TASK_TARGET_VALUE = 'taskTargetValue', | |
15 | + TARGET_IDS = 'targetIds', | |
16 | + TASK_RECORD = 'taskRecord', | |
10 | 17 | } |
11 | 18 | |
12 | 19 | export enum TargetType { |
... | ... | @@ -33,26 +40,13 @@ export const formSchemas: FormSchema[] = [ |
33 | 40 | slot: 'taskType', |
34 | 41 | }, |
35 | 42 | { |
36 | - field: FormFieldsEnum.TASK_TARGET_TYPE, | |
37 | - component: 'Input', | |
38 | - label: '目标类型', | |
39 | - show: false, | |
40 | - }, | |
41 | - { | |
42 | - field: FormFieldsEnum.TASK_TARGET_VALUE, | |
43 | + field: FormFieldsEnum.TASK_RECORD, | |
43 | 44 | component: 'Input', |
44 | - label: '目标值', | |
45 | - show: false, | |
46 | - }, | |
47 | - { | |
48 | - field: FormFieldsEnum.TASK_TYPE, | |
49 | - component: 'Input', | |
50 | - label: '任务类型', | |
51 | - renderComponentContent: 'taskType', | |
45 | + label: '任务详情', | |
52 | 46 | show: false, |
53 | 47 | }, |
54 | 48 | { |
55 | - field: FormFieldsEnum.RUN_TARGET_TYPE, | |
49 | + field: FormFieldsEnum.EXECUTE_TARGET_TYPE, | |
56 | 50 | component: 'RadioGroup', |
57 | 51 | label: '选择目标类型', |
58 | 52 | helpMessage: [ |
... | ... | @@ -67,23 +61,36 @@ export const formSchemas: FormSchema[] = [ |
67 | 61 | }, |
68 | 62 | }, |
69 | 63 | { |
70 | - field: FormFieldsEnum.ASSIGN_TARGET, | |
64 | + field: FormFieldsEnum.TARGET_IDS, | |
71 | 65 | component: 'ApiSelect', |
72 | 66 | label: '制定目标设备', |
73 | - ifShow: ({ model }) => model[FormFieldsEnum.RUN_TARGET_TYPE] === TargetType.ASSIGN, | |
67 | + ifShow: ({ model }) => model[FormFieldsEnum.EXECUTE_TARGET_TYPE] === TargetType.ASSIGN, | |
74 | 68 | componentProps: ({ formModel }) => { |
75 | - const taskTargetType = formModel[FormFieldsEnum.TASK_TARGET_TYPE]; | |
76 | - const isDevices = taskTargetType === TaskTargetEnum.DEVICES; | |
69 | + const record = JSON.parse(formModel[FormFieldsEnum.TASK_RECORD]) as TaskRecordType; | |
70 | + const isDevices = record.targetType === TaskTargetEnum.DEVICES; | |
71 | + const { executeTarget } = record; | |
72 | + const { organizationId, data } = executeTarget; | |
77 | 73 | return { |
78 | 74 | api: async () => { |
79 | 75 | try { |
80 | 76 | if (isDevices) { |
77 | + const result = await getDevicesByDeviceIds(data!); | |
78 | + return result.data; | |
81 | 79 | } else { |
80 | + return await getMeetTheConditionsDevice({ | |
81 | + organizationId, | |
82 | + deviceProfileId: data![0], | |
83 | + }); | |
82 | 84 | } |
83 | 85 | } catch (error) { |
84 | 86 | return []; |
85 | 87 | } |
86 | 88 | }, |
89 | + mode: 'multiple', | |
90 | + labelField: 'name', | |
91 | + valueField: 'tbDeviceId', | |
92 | + ...createPickerSearch(), | |
93 | + placeholder: '请选择设备', | |
87 | 94 | getPopupContainer: () => document.body, |
88 | 95 | }; |
89 | 96 | }, | ... | ... |
1 | 1 | <script lang="ts" setup> |
2 | 2 | import { ref } from 'vue'; |
3 | - import { TaskRecordType } from '/@/api/task/model'; | |
3 | + import { ImmediateExecuteTaskType, TaskRecordType } from '/@/api/task/model'; | |
4 | 4 | import { BasicForm, useForm } from '/@/components/Form'; |
5 | 5 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
6 | - import { TaskTypeNameEnum } from '../../config'; | |
7 | - import { formSchemas } from './config'; | |
6 | + import { TaskTargetEnum, TaskTypeNameEnum } from '../../config'; | |
7 | + import { FormValue, TargetType, formSchemas } from './config'; | |
8 | + import { unref } from 'vue'; | |
9 | + import { immediateExecute } from '/@/api/task'; | |
10 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
11 | + const props = defineProps<{ | |
12 | + reload: Fn; | |
13 | + }>(); | |
8 | 14 | |
9 | 15 | defineEmits(['register']); |
10 | 16 | |
11 | 17 | const dataSource = ref<TaskRecordType>(); |
12 | 18 | |
13 | - const [registerModal] = useModalInner((record: TaskRecordType) => { | |
19 | + const [registerModal, { closeModal }] = useModalInner((record: TaskRecordType) => { | |
20 | + resetFields(); | |
14 | 21 | dataSource.value = record; |
15 | 22 | if (record) { |
16 | - setFieldsValue(record); | |
23 | + setFieldsValue({ taskRecord: JSON.stringify(record) } as FormValue); | |
17 | 24 | } |
18 | 25 | }); |
19 | 26 | |
20 | - const [registerForm, { setFieldsValue }] = useForm({ | |
27 | + const [registerForm, { setFieldsValue, getFieldsValue, resetFields }] = useForm({ | |
21 | 28 | schemas: formSchemas, |
22 | 29 | showActionButtonGroup: false, |
23 | 30 | }); |
31 | + | |
32 | + const composeData = (record: FormValue): ImmediateExecuteTaskType => { | |
33 | + const { executeTarget, targetIds } = record; | |
34 | + return { | |
35 | + executeTarget: | |
36 | + executeTarget === TargetType.ASSIGN | |
37 | + ? TaskTargetEnum.DEVICES | |
38 | + : unref(dataSource)!.targetType, | |
39 | + id: unref(dataSource)!.id, | |
40 | + targetIds, | |
41 | + cronExpression: unref(dataSource)!.executeTime.cron, | |
42 | + name: unref(dataSource)!.name, | |
43 | + }; | |
44 | + }; | |
45 | + | |
46 | + const loading = ref(false); | |
47 | + const { createMessage } = useMessage(); | |
48 | + const handleOk = async () => { | |
49 | + const record = getFieldsValue() as FormValue; | |
50 | + const value = composeData(record); | |
51 | + try { | |
52 | + loading.value = true; | |
53 | + const { data } = await immediateExecute(value); | |
54 | + data ? createMessage.success('运行成功') : createMessage.error('运行失败'); | |
55 | + if (data) { | |
56 | + closeModal(); | |
57 | + props.reload?.(); | |
58 | + } | |
59 | + } catch (error) { | |
60 | + throw error; | |
61 | + } finally { | |
62 | + loading.value = false; | |
63 | + } | |
64 | + }; | |
24 | 65 | </script> |
25 | 66 | |
26 | 67 | <template> |
27 | - <BasicModal @register="registerModal" title="运行任务"> | |
68 | + <BasicModal | |
69 | + @register="registerModal" | |
70 | + title="运行任务" | |
71 | + :okButtonProps="{ loading }" | |
72 | + @ok="handleOk" | |
73 | + > | |
28 | 74 | <BasicForm @register="registerForm"> |
29 | 75 | <template #taskName> |
30 | 76 | <div class="font-semibold"> | ... | ... |
... | ... | @@ -100,7 +100,7 @@ |
100 | 100 | <section |
101 | 101 | class="bg-light-50 flex p-4 justify-between items-center x dark:text-gray-300 dark:bg-dark-900" |
102 | 102 | > |
103 | - <div class="text-2xl">任务</div> | |
103 | + <div class="text-2xl">任务中心</div> | |
104 | 104 | <Authority :value="PermissionEnum.CREATE"> |
105 | 105 | <Button |
106 | 106 | type="primary" |
... | ... | @@ -143,7 +143,7 @@ |
143 | 143 | </List> |
144 | 144 | </section> |
145 | 145 | <DetailModal @register="registerModal" :reload="reload" /> |
146 | - <RunTaskModal @register="registerRunTaskModal" /> | |
146 | + <RunTaskModal :reload="reload" @register="registerRunTaskModal" /> | |
147 | 147 | </PageWrapper> |
148 | 148 | </template> |
149 | 149 | ... | ... |