Commit 53475cba108e121ee7e2a274be9a32d83c6f0c9a
Merge branch 'feat/linkedage' into 'main_dev'
feat: 场景联动新增事件触发 See merge request yunteng/thingskit-front!1036
Showing
8 changed files
with
160 additions
and
23 deletions
... | ... | @@ -99,10 +99,12 @@ export enum TriggerTypeNameEnum { |
99 | 99 | |
100 | 100 | export enum DeviceTriggerTypeEum { |
101 | 101 | TIME_SERIES = 'TIME_SERIES', |
102 | + DEVICE_EVENT = 'DEVICE_EVENT', | |
102 | 103 | } |
103 | 104 | |
104 | 105 | export enum DeviceTriggerTypeNameEum { |
105 | 106 | TIME_SERIES = '属性触发', |
107 | + DEVICE_EVENT = '事件触发', | |
106 | 108 | } |
107 | 109 | |
108 | 110 | export enum TriggerEntityTypeEnum { | ... | ... |
... | ... | @@ -7,7 +7,7 @@ import { |
7 | 7 | DeviceTriggerTypeEum, |
8 | 8 | FlipFlopTypeEnum, |
9 | 9 | NumberOperationEnum, |
10 | - StringOperationNameEnum, | |
10 | + StringOperationEnum, | |
11 | 11 | TriggerTypeEnum, |
12 | 12 | TriggerValueTypeEnum, |
13 | 13 | } from '/@/enums/linkedgeEnum'; |
... | ... | @@ -37,7 +37,7 @@ export interface ConditionType { |
37 | 37 | spec: { type: FlipFlopTypeEnum; unit?: string; predicate?: { defaultValue: any } }; |
38 | 38 | } |
39 | 39 | |
40 | -export type OperationType = NumberOperationEnum | StringOperationNameEnum | BooleanOperationEnum; | |
40 | +export type OperationType = NumberOperationEnum | StringOperationEnum | BooleanOperationEnum; | |
41 | 41 | |
42 | 42 | export interface ConditionItemType { |
43 | 43 | key: { type: DeviceTriggerTypeEum; key: string }; | ... | ... |
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | import { useExecutionActionData } from './useExecutionActionData'; |
11 | 11 | import { createNewExecutionActionItem } from '.'; |
12 | 12 | import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; |
13 | + import { FlipFlopComponentTypeEnum } from '../FlipFlop/types'; | |
13 | 14 | |
14 | 15 | const { disabledDrawer } = useSceneLinkageDrawerContext(); |
15 | 16 | |
... | ... | @@ -103,6 +104,7 @@ |
103 | 104 | :disabled="disabledDrawer" |
104 | 105 | addButtonName="新增清除告警" |
105 | 106 | @delete="handleClearRuleDelete(executionActionItem)" |
107 | + :type="FlipFlopComponentTypeEnum.ALARM_CLEAR" | |
106 | 108 | /> |
107 | 109 | </template> |
108 | 110 | ... | ... |
... | ... | @@ -23,9 +23,15 @@ import { |
23 | 23 | TriggerUnitEnum, |
24 | 24 | TriggerUnitNameEnum, |
25 | 25 | } from '/@/enums/linkedgeEnum'; |
26 | -import { DeviceModelOfMatterAttrs } from '/@/api/device/model/deviceModel'; | |
26 | +import { DeviceModelOfMatterAttrs, DeviceProfileModel } from '/@/api/device/model/deviceModel'; | |
27 | 27 | import TriggerDurationInput from './TriggerDurationInput.vue'; |
28 | 28 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
29 | +import { getModelTsl } from '/@/api/device/modelOfMatter'; | |
30 | +import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | |
31 | +import { GetModelTslParams } from '/@/api/device/model/modelOfMatterModel'; | |
32 | +import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | |
33 | +import { FlipFlopComponentTypeEnum } from './types'; | |
34 | +import { OptionsType } from 'ant-design-vue/es/vc-select/interface'; | |
29 | 35 | |
30 | 36 | export enum FormFieldEnum { |
31 | 37 | FLIP_FLOP_TYPE = 'flipFlopType', |
... | ... | @@ -42,6 +48,8 @@ export enum FormFieldEnum { |
42 | 48 | TRIGGER_REPEAT_COUNT = 'triggerRepeatCount', |
43 | 49 | |
44 | 50 | CONDITION_KEY_DETAIL = 'conditionKeyDetail', |
51 | + TRANSPORT_TYPE = 'transportType', | |
52 | + DEVICE_EVENT_TRIGGER_KEY = 'deviceEventTriggerKey', | |
45 | 53 | } |
46 | 54 | |
47 | 55 | export enum FormFieldNameEnum { |
... | ... | @@ -56,6 +64,8 @@ export enum FormFieldNameEnum { |
56 | 64 | CONDITION_VALUE_TYPE = '比较类型', |
57 | 65 | TRIGGER_DURATION_VALUE = '持续时长', |
58 | 66 | TRIGGER_REPEAT_COUNT = '重复次数', |
67 | + | |
68 | + DEVICE_EVENT_TRIGGER_KEY = '事件', | |
59 | 69 | } |
60 | 70 | |
61 | 71 | useComponentRegister('TriggerDurationInput', TriggerDurationInput); |
... | ... | @@ -72,7 +82,9 @@ function getTriggerValueTypeByThingsModelType(type: DataTypeEnum) { |
72 | 82 | return map[type]; |
73 | 83 | } |
74 | 84 | |
75 | -export const getFormSchemas = (): FormSchema[] => { | |
85 | +export const getFormSchemas = ( | |
86 | + flipFlopComponentType: FlipFlopComponentTypeEnum = FlipFlopComponentTypeEnum.FLIP_FLOP | |
87 | +): FormSchema[] => { | |
76 | 88 | const { organizationId } = useSceneLinkageDrawerContext(); |
77 | 89 | |
78 | 90 | return [ |
... | ... | @@ -119,6 +131,12 @@ export const getFormSchemas = (): FormSchema[] => { |
119 | 131 | }, |
120 | 132 | }, |
121 | 133 | { |
134 | + field: FormFieldEnum.TRANSPORT_TYPE, | |
135 | + label: '传输协议', | |
136 | + component: 'Input', | |
137 | + ifShow: false, | |
138 | + }, | |
139 | + { | |
122 | 140 | field: FormFieldEnum.DEVICE_PROFILE_ID, |
123 | 141 | label: '', |
124 | 142 | component: 'ApiSelect', |
... | ... | @@ -134,11 +152,29 @@ export const getFormSchemas = (): FormSchema[] => { |
134 | 152 | valueField: 'id', |
135 | 153 | placeholder: `请选择${FormFieldNameEnum.DEVICE_PROFILE_ID}`, |
136 | 154 | ...createPickerSearch(), |
137 | - onChange() { | |
138 | - setFieldsValue({ | |
155 | + onChange(value: string, option: DeviceProfileModel) { | |
156 | + const conditionType = formModel[FormFieldEnum.CONDITION_TYPE]; | |
157 | + const deviceTyp = formModel[FormFieldEnum.DEVICE_TYPE]; | |
158 | + const record = { | |
139 | 159 | [FormFieldEnum.ENTITY_ID]: [], |
140 | 160 | [FormFieldEnum.CONDITION_KEY]: null, |
141 | - }); | |
161 | + [FormFieldEnum.TRANSPORT_TYPE]: value ? option.transportType : null, | |
162 | + }; | |
163 | + // TCP网关子设备无物模型事件 | |
164 | + if ( | |
165 | + conditionType === DeviceTriggerTypeEum.DEVICE_EVENT && | |
166 | + option.transportType === TransportTypeEnum.TCP && | |
167 | + deviceTyp === DeviceTypeEnum.SENSOR | |
168 | + ) { | |
169 | + record[FormFieldEnum.CONDITION_TYPE] = null; | |
170 | + } | |
171 | + setFieldsValue(record); | |
172 | + }, | |
173 | + onOptionsChange(options: (DeviceProfileModel & Record<'label' | 'value', string>)[]) { | |
174 | + const res = options.find( | |
175 | + (item) => item.value === formModel[FormFieldEnum.DEVICE_PROFILE_ID] | |
176 | + ); | |
177 | + res && setFieldsValue({ [FormFieldEnum.TRANSPORT_TYPE]: res.transportType }); | |
142 | 178 | }, |
143 | 179 | }; |
144 | 180 | }, |
... | ... | @@ -256,14 +292,25 @@ export const getFormSchemas = (): FormSchema[] => { |
256 | 292 | component: 'Select', |
257 | 293 | rules: [{ required: true, message: `请选择${FormFieldNameEnum.CONDITION_TYPE}` }], |
258 | 294 | defaultValue: DeviceTriggerTypeEum.TIME_SERIES, |
259 | - componentProps: () => { | |
295 | + componentProps: ({ formModel }) => { | |
296 | + const options: OptionsType = [ | |
297 | + { | |
298 | + label: DeviceTriggerTypeNameEum.TIME_SERIES, | |
299 | + value: DeviceTriggerTypeEum.TIME_SERIES, | |
300 | + }, | |
301 | + ]; | |
302 | + | |
303 | + if (flipFlopComponentType === FlipFlopComponentTypeEnum.FLIP_FLOP) { | |
304 | + options.push({ | |
305 | + label: DeviceTriggerTypeNameEum.DEVICE_EVENT, | |
306 | + value: DeviceTriggerTypeEum.DEVICE_EVENT, | |
307 | + disabled: | |
308 | + TransportTypeEnum.TCP === formModel[FormFieldEnum.TRANSPORT_TYPE] && | |
309 | + formModel[FormFieldEnum.DEVICE_TYPE] === DeviceTypeEnum.SENSOR, | |
310 | + }); | |
311 | + } | |
260 | 312 | return { |
261 | - options: [ | |
262 | - { | |
263 | - label: DeviceTriggerTypeNameEum.TIME_SERIES, | |
264 | - value: DeviceTriggerTypeEum.TIME_SERIES, | |
265 | - }, | |
266 | - ], | |
313 | + options, | |
267 | 314 | }; |
268 | 315 | }, |
269 | 316 | }, |
... | ... | @@ -278,6 +325,8 @@ export const getFormSchemas = (): FormSchema[] => { |
278 | 325 | label: '', |
279 | 326 | component: 'ApiSelect', |
280 | 327 | rules: [{ required: true, message: `请选择${FormFieldNameEnum.CONDITION_KEY}` }], |
328 | + ifShow: ({ model }) => | |
329 | + model[FormFieldEnum.CONDITION_TYPE] === DeviceTriggerTypeEum.TIME_SERIES, | |
281 | 330 | componentProps: ({ formModel, formActionType }) => { |
282 | 331 | const { setFieldsValue } = formActionType; |
283 | 332 | return { |
... | ... | @@ -329,6 +378,8 @@ export const getFormSchemas = (): FormSchema[] => { |
329 | 378 | label: '', |
330 | 379 | component: 'Select', |
331 | 380 | rules: [{ required: true, message: `请选择${FormFieldNameEnum.CONDITION_VALUE_TYPE}` }], |
381 | + ifShow: ({ model }) => | |
382 | + model[FormFieldEnum.CONDITION_TYPE] === DeviceTriggerTypeEum.TIME_SERIES, | |
332 | 383 | componentProps: () => { |
333 | 384 | return { |
334 | 385 | options: Object.keys(TriggerValueTypeEnum).map((value) => ({ |
... | ... | @@ -340,12 +391,36 @@ export const getFormSchemas = (): FormSchema[] => { |
340 | 391 | }, |
341 | 392 | }, |
342 | 393 | { |
394 | + field: FormFieldEnum.DEVICE_EVENT_TRIGGER_KEY, | |
395 | + label: '', | |
396 | + component: 'ApiSelect', | |
397 | + ifShow: ({ model }) => | |
398 | + model[FormFieldEnum.CONDITION_TYPE] === DeviceTriggerTypeEum.DEVICE_EVENT, | |
399 | + componentProps: ({ formModel }) => { | |
400 | + return { | |
401 | + api: async (params: GetModelTslParams) => { | |
402 | + if (!params.deviceProfileId) return []; | |
403 | + return await getModelTsl(params); | |
404 | + }, | |
405 | + labelField: 'functionName', | |
406 | + valueField: 'identifier', | |
407 | + params: { | |
408 | + functionType: FunctionType.EVENTS, | |
409 | + deviceProfileId: formModel[FormFieldEnum.DEVICE_PROFILE_ID], | |
410 | + }, | |
411 | + placeholder: `请选择${FormFieldNameEnum.DEVICE_EVENT_TRIGGER_KEY}`, | |
412 | + }; | |
413 | + }, | |
414 | + }, | |
415 | + { | |
343 | 416 | field: 'conditionFilter', |
344 | 417 | label: '', |
345 | 418 | component: 'Input', |
346 | 419 | colProps: { span: 24, xxl: 24, xl: 24, lg: 24, md: 24, sm: 24, xs: 24 }, |
347 | 420 | ifShow: ({ model }) => |
348 | - model[FormFieldEnum.CONDITION_KEY] && model[FormFieldEnum.CONDITION_VALUE_TYPE], | |
421 | + model[FormFieldEnum.CONDITION_TYPE] === DeviceTriggerTypeEum.TIME_SERIES && | |
422 | + model[FormFieldEnum.CONDITION_KEY] && | |
423 | + model[FormFieldEnum.CONDITION_VALUE_TYPE], | |
349 | 424 | colSlot: 'conditionFilter', |
350 | 425 | }, |
351 | 426 | ]; | ... | ... |
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | import { Tooltip, Button } from 'ant-design-vue'; |
4 | 4 | import { CollapseContainer } from '/@/components/Container'; |
5 | 5 | import { Icon } from '/@/components/Icon'; |
6 | - import { FlipFlopItemType, ScheduleOptionItemType } from './types'; | |
6 | + import { FlipFlopItemType, FlipFlopComponentTypeEnum, ScheduleOptionItemType } from './types'; | |
7 | 7 | import { BasicForm, FormActionType } from '/@/components/Form'; |
8 | 8 | import { getFormSchemas, FormFieldEnum } from './config'; |
9 | 9 | import { useSceneLinkageDrawerContext } from '../SceneLinkageDrawer/sceneLinkageDrawerContext'; |
... | ... | @@ -27,6 +27,7 @@ |
27 | 27 | panelTitle?: (index: number) => string; |
28 | 28 | showAddButton?: boolean; |
29 | 29 | disabled?: boolean; |
30 | + type?: FlipFlopComponentTypeEnum; | |
30 | 31 | }>(), |
31 | 32 | { |
32 | 33 | addButtonName: '触发器 (OR)', |
... | ... | @@ -34,10 +35,11 @@ |
34 | 35 | panelTitle: (index: number) => `触发器${index}`, |
35 | 36 | showAddButton: true, |
36 | 37 | disabled: false, |
38 | + type: FlipFlopComponentTypeEnum.FLIP_FLOP, | |
37 | 39 | } |
38 | 40 | ); |
39 | 41 | |
40 | - const formSchemas = getFormSchemas(); | |
42 | + const formSchemas = getFormSchemas(props.type); | |
41 | 43 | |
42 | 44 | const [registerModal, { openModal }] = useModal(); |
43 | 45 | ... | ... |
... | ... | @@ -14,6 +14,12 @@ import { |
14 | 14 | TriggerValueTypeNameEnum, |
15 | 15 | } from '/@/enums/linkedgeEnum'; |
16 | 16 | |
17 | +export enum FlipFlopComponentTypeEnum { | |
18 | + FLIP_FLOP, | |
19 | + EXECUTION_CONDITION, | |
20 | + ALARM_CLEAR, | |
21 | +} | |
22 | + | |
17 | 23 | export interface ScheduleOptionItemType { |
18 | 24 | label: string; |
19 | 25 | value: ScheduleTypeEnum; |
... | ... | @@ -48,4 +54,5 @@ export interface FlipFlopFormRecordType { |
48 | 54 | [FormFieldEnum.TRIGGER_DURATION_VALUE]: number; |
49 | 55 | [FormFieldEnum.TRIGGER_REPEAT_COUNT]: number; |
50 | 56 | [FormFieldEnum.TRIGGER_DURATION_UNIT]: TriggerUnitEnum; |
57 | + [FormFieldEnum.DEVICE_EVENT_TRIGGER_KEY]: string; | |
51 | 58 | } | ... | ... |
... | ... | @@ -2,13 +2,50 @@ import { Ref, nextTick, toRaw, unref } from 'vue'; |
2 | 2 | import { FlipFlopConditionType, FlipFlopFormRecordType, FlipFlopItemType } from './types'; |
3 | 3 | import { DefineComponentsBasicExpose } from '/#/utils'; |
4 | 4 | import { FormFieldEnum } from './config'; |
5 | -import { FlipFlopTypeEnum } from '/@/enums/linkedgeEnum'; | |
5 | +import { | |
6 | + DeviceTriggerTypeEum, | |
7 | + FlipFlopTypeEnum, | |
8 | + StringOperationEnum, | |
9 | + TriggerValueTypeEnum, | |
10 | +} from '/@/enums/linkedgeEnum'; | |
6 | 11 | import { createNewFlipFlopItem } from '.'; |
12 | +import { ConditionItemType } from '../ConditionFilter/type'; | |
7 | 13 | |
8 | 14 | export function useFlipFlopData( |
9 | 15 | flipFlopListRef: Ref<FlipFlopItemType[]> |
10 | 16 | ): DefineComponentsBasicExpose<FlipFlopConditionType[]> { |
17 | + const getEventTriggerCOndition = ( | |
18 | + basicRecord: FlipFlopFormRecordType, | |
19 | + _flipFlopItem: FlipFlopItemType | |
20 | + ): ConditionItemType[] => { | |
21 | + const { deviceEventTriggerKey } = basicRecord; | |
22 | + return [ | |
23 | + { | |
24 | + key: { | |
25 | + type: DeviceTriggerTypeEum.DEVICE_EVENT, | |
26 | + key: deviceEventTriggerKey, | |
27 | + }, | |
28 | + valueType: TriggerValueTypeEnum.STRING, | |
29 | + predicate: { | |
30 | + type: TriggerValueTypeEnum.STRING, | |
31 | + operation: StringOperationEnum.EQUAL, | |
32 | + value: { | |
33 | + defaultValue: deviceEventTriggerKey, | |
34 | + }, | |
35 | + }, | |
36 | + }, | |
37 | + ]; | |
38 | + }; | |
39 | + | |
40 | + const getCondition = (basicRecord: FlipFlopFormRecordType, flipFlopItem: FlipFlopItemType) => { | |
41 | + const { conditionType } = basicRecord; | |
42 | + return conditionType === DeviceTriggerTypeEum.TIME_SERIES | |
43 | + ? flipFlopItem.conditionRef?.getFieldsValue() || [] | |
44 | + : getEventTriggerCOndition(basicRecord, flipFlopItem); | |
45 | + }; | |
46 | + | |
11 | 47 | const crateFlipFlopCondition = (flipFlopItem: FlipFlopItemType): FlipFlopConditionType => { |
48 | + const basicRecord = flipFlopItem.ref?.getFieldsValue() as FlipFlopFormRecordType; | |
12 | 49 | const { |
13 | 50 | deviceProfileId, |
14 | 51 | deviceType, |
... | ... | @@ -19,9 +56,9 @@ export function useFlipFlopData( |
19 | 56 | triggerDurationUnit, |
20 | 57 | triggerRepeatCount, |
21 | 58 | triggerDurationValue, |
22 | - } = flipFlopItem.ref?.getFieldsValue() as FlipFlopFormRecordType; | |
59 | + } = basicRecord; | |
23 | 60 | |
24 | - const condition = flipFlopItem.conditionRef?.getFieldsValue() || []; | |
61 | + const condition = getCondition(basicRecord, flipFlopItem); | |
25 | 62 | |
26 | 63 | return { |
27 | 64 | deviceProfileId, |
... | ... | @@ -70,17 +107,27 @@ export function useFlipFlopData( |
70 | 107 | const { type, unit, predicate } = condition.spec; |
71 | 108 | const { defaultValue } = predicate || {}; |
72 | 109 | |
73 | - item.ref?.setFieldsValue({ | |
110 | + const record = { | |
74 | 111 | ...data, |
75 | 112 | [FormFieldEnum.FLIP_FLOP_TYPE]: type, |
76 | 113 | [FormFieldEnum.CONDITION_KEY]: key.key, |
114 | + [FormFieldEnum.CONDITION_TYPE]: key.type, | |
77 | 115 | [FormFieldEnum.CONDITION_VALUE_TYPE]: valueType, |
78 | 116 | [FormFieldEnum.TRIGGER_DURATION_UNIT]: unit, |
79 | 117 | [FormFieldEnum.TRIGGER_DURATION_VALUE]: |
80 | 118 | type === FlipFlopTypeEnum.DURATION ? defaultValue : null, |
81 | 119 | [FormFieldEnum.TRIGGER_REPEAT_COUNT]: |
82 | 120 | type === FlipFlopTypeEnum.REPEATING ? defaultValue : null, |
83 | - }); | |
121 | + }; | |
122 | + | |
123 | + if (key.type === DeviceTriggerTypeEum.DEVICE_EVENT) { | |
124 | + Object.assign(record, { | |
125 | + [FormFieldEnum.DEVICE_EVENT_TRIGGER_KEY]: key.key, | |
126 | + [FormFieldEnum.CONDITION_KEY]: null, | |
127 | + }); | |
128 | + } | |
129 | + | |
130 | + item.ref?.setFieldsValue(record); | |
84 | 131 | |
85 | 132 | const { |
86 | 133 | daysOfWeek, | ... | ... |
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | import { screenLinkPageAddApi } from '/@/api/ruleengine/ruleengineApi'; |
15 | 15 | import { useMessage } from '/@/hooks/web/useMessage'; |
16 | 16 | import { OrganizationListItem } from '/@/api/system/model/systemModel'; |
17 | + import { FlipFlopComponentTypeEnum } from '../FlipFlop/types'; | |
17 | 18 | |
18 | 19 | const emit = defineEmits(['success', 'register']); |
19 | 20 | |
... | ... | @@ -127,7 +128,7 @@ |
127 | 128 | <Icon icon="ant-design:question-circle-outlined" class="ml-2" /> |
128 | 129 | </Tooltip> |
129 | 130 | </Divider> |
130 | - <FlipFlop ref="flipFlopElRef" /> | |
131 | + <FlipFlop ref="flipFlopElRef" :type="FlipFlopComponentTypeEnum.FLIP_FLOP" /> | |
131 | 132 | </template> |
132 | 133 | <template #executionCondition> |
133 | 134 | <Divider orientation="left"> |
... | ... | @@ -142,6 +143,7 @@ |
142 | 143 | addButtonName="执行条件 (AND)" |
143 | 144 | default-null |
144 | 145 | :panel-title="(index) => `执行条件${index}`" |
146 | + :type="FlipFlopComponentTypeEnum.EXECUTION_CONDITION" | |
145 | 147 | /> |
146 | 148 | </template> |
147 | 149 | <template #executionAction> | ... | ... |