Showing
6 changed files
with
266 additions
and
7 deletions
@@ -40,6 +40,7 @@ import StructForm from './externalCompns/components/StructForm/StructForm.vue'; | @@ -40,6 +40,7 @@ import StructForm from './externalCompns/components/StructForm/StructForm.vue'; | ||
40 | import ApiSelectScrollLoad from './components/ApiSelectScrollLoad.vue'; | 40 | import ApiSelectScrollLoad from './components/ApiSelectScrollLoad.vue'; |
41 | import TransferModal from './components/TransferModal.vue'; | 41 | import TransferModal from './components/TransferModal.vue'; |
42 | import TransferTableModal from './components/TransferTableModal.vue'; | 42 | import TransferTableModal from './components/TransferTableModal.vue'; |
43 | +import ObjectModelValidateForm from './externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue'; | ||
43 | 44 | ||
44 | const componentMap = new Map<ComponentType, Component>(); | 45 | const componentMap = new Map<ComponentType, Component>(); |
45 | 46 | ||
@@ -87,6 +88,7 @@ componentMap.set('StructForm', StructForm); | @@ -87,6 +88,7 @@ componentMap.set('StructForm', StructForm); | ||
87 | componentMap.set('ApiSelectScrollLoad', ApiSelectScrollLoad); | 88 | componentMap.set('ApiSelectScrollLoad', ApiSelectScrollLoad); |
88 | componentMap.set('TransferModal', TransferModal); | 89 | componentMap.set('TransferModal', TransferModal); |
89 | componentMap.set('TransferTableModal', TransferTableModal); | 90 | componentMap.set('TransferTableModal', TransferTableModal); |
91 | +componentMap.set('ObjectModelValidateForm', ObjectModelValidateForm); | ||
90 | 92 | ||
91 | export function add(compName: ComponentType, component: Component) { | 93 | export function add(compName: ComponentType, component: Component) { |
92 | componentMap.set(compName, component); | 94 | componentMap.set(compName, component); |
1 | +<script lang="ts" setup> | ||
2 | + import { Card } from 'ant-design-vue'; | ||
3 | + import { nextTick, onBeforeUpdate, onUpdated } from 'vue'; | ||
4 | + import { DataTypeEnum } from '../StructForm/config'; | ||
5 | + import { BasicCreateFormParams } from './type'; | ||
6 | + import { DynamicProps } from '/#/utils'; | ||
7 | + import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ||
8 | + import { BasicForm, FormProps, FormSchema, useForm } from '/@/components/Form'; | ||
9 | + | ||
10 | + const props = withDefaults( | ||
11 | + defineProps<{ | ||
12 | + inputData?: StructJSON[]; | ||
13 | + formProps?: FormProps; | ||
14 | + value?: Recordable; | ||
15 | + }>(), | ||
16 | + { | ||
17 | + inputData: () => [] as StructJSON[], | ||
18 | + formProps: () => ({}), | ||
19 | + value: () => ({}), | ||
20 | + } | ||
21 | + ); | ||
22 | + | ||
23 | + const emit = defineEmits(['update:value']); | ||
24 | + | ||
25 | + const [register, { setProps, getFieldsValue, setFieldsValue }] = useForm({ | ||
26 | + schemas: [], | ||
27 | + showActionButtonGroup: false, | ||
28 | + layout: 'inline', | ||
29 | + labelWidth: 80, | ||
30 | + wrapperCol: { span: 12 }, | ||
31 | + ...(props.formProps || ({} as unknown as Partial<DynamicProps<FormProps>>)), | ||
32 | + }); | ||
33 | + | ||
34 | + const syncValue = (key: string, value: any) => { | ||
35 | + const record = getFieldsValue(); | ||
36 | + emit('update:value', { ...record, [key]: value }); | ||
37 | + }; | ||
38 | + | ||
39 | + const createInputNumber = ({ | ||
40 | + identifier, | ||
41 | + functionName, | ||
42 | + specs, | ||
43 | + }: BasicCreateFormParams): FormSchema => { | ||
44 | + const { valueRange } = specs! as Partial<Specs>; | ||
45 | + const { max = 2147483647, min = -2147483648 } = valueRange || {}; | ||
46 | + return { | ||
47 | + field: identifier, | ||
48 | + label: functionName, | ||
49 | + component: 'InputNumber', | ||
50 | + rules: [ | ||
51 | + { | ||
52 | + type: 'number', | ||
53 | + trigger: 'change', | ||
54 | + validator: (_rule, value) => { | ||
55 | + if (value < min || value > max) { | ||
56 | + return Promise.reject(`${functionName}取值范围在${min}~${max}之间`); | ||
57 | + } | ||
58 | + return Promise.resolve(value); | ||
59 | + }, | ||
60 | + }, | ||
61 | + ], | ||
62 | + componentProps: { | ||
63 | + max, | ||
64 | + min, | ||
65 | + // step: step, | ||
66 | + // formatter: (value: string) => value, | ||
67 | + // parser: (string: string) => { | ||
68 | + // if (dataType === DataTypeEnum.IS_NUMBER_INT) { | ||
69 | + // return Number(Number(string).toFixed()); | ||
70 | + // } | ||
71 | + // return Number(string); | ||
72 | + // }, | ||
73 | + onChange: (value: string) => { | ||
74 | + syncValue(identifier, value); | ||
75 | + }, | ||
76 | + }, | ||
77 | + } as FormSchema; | ||
78 | + }; | ||
79 | + | ||
80 | + const createInput = ({ identifier, functionName, specs }: BasicCreateFormParams): FormSchema => { | ||
81 | + const { length = 10240 } = specs! as Partial<Specs>; | ||
82 | + return { | ||
83 | + field: identifier, | ||
84 | + label: functionName, | ||
85 | + component: 'Input', | ||
86 | + rules: [ | ||
87 | + { | ||
88 | + type: 'string', | ||
89 | + trigger: 'change', | ||
90 | + validator: (_rule, value) => { | ||
91 | + if (value.length > length) { | ||
92 | + return Promise.reject(`${functionName}数据长度应该小于${length}`); | ||
93 | + } | ||
94 | + return Promise.resolve(value); | ||
95 | + }, | ||
96 | + }, | ||
97 | + ], | ||
98 | + componentProps: { | ||
99 | + maxLength: length, | ||
100 | + onChange: (value: InputEvent) => { | ||
101 | + syncValue(identifier, (value.target as HTMLInputElement).value); | ||
102 | + }, | ||
103 | + }, | ||
104 | + } as FormSchema; | ||
105 | + }; | ||
106 | + | ||
107 | + const createSelect = ({ identifier, functionName, specs }: BasicCreateFormParams): FormSchema => { | ||
108 | + const { boolClose, boolOpen } = specs! as Partial<Specs>; | ||
109 | + return { | ||
110 | + field: identifier, | ||
111 | + label: functionName, | ||
112 | + component: 'Select', | ||
113 | + componentProps: { | ||
114 | + options: [ | ||
115 | + { label: `${boolClose}-0`, value: 0 }, | ||
116 | + { label: `${boolOpen}-0`, value: 1 }, | ||
117 | + ], | ||
118 | + onChange: (value: string) => { | ||
119 | + syncValue(identifier, value); | ||
120 | + }, | ||
121 | + }, | ||
122 | + }; | ||
123 | + }; | ||
124 | + | ||
125 | + const createInputJson = ({ identifier, functionName }: BasicCreateFormParams): FormSchema => { | ||
126 | + return { | ||
127 | + field: identifier, | ||
128 | + label: functionName, | ||
129 | + component: 'InputTextArea', | ||
130 | + componentProps: { | ||
131 | + onChange: (value: InputEvent) => { | ||
132 | + syncValue(identifier, (value.target as HTMLInputElement).value); | ||
133 | + }, | ||
134 | + }, | ||
135 | + }; | ||
136 | + }; | ||
137 | + | ||
138 | + const transformToFormSchema = (inputData: StructJSON[]) => { | ||
139 | + const schemas: FormSchema[] = []; | ||
140 | + for (const item of inputData) { | ||
141 | + const { dataType, identifier, functionName } = item; | ||
142 | + const { type, specs } = dataType! || {}; | ||
143 | + | ||
144 | + const params: BasicCreateFormParams = { | ||
145 | + identifier: identifier!, | ||
146 | + functionName: functionName!, | ||
147 | + dataType: dataType! as unknown as DataTypeEnum, | ||
148 | + specs: specs as Partial<Specs>, | ||
149 | + }; | ||
150 | + if (type === DataTypeEnum.IS_NUMBER_INT || type === DataTypeEnum.IS_NUMBER_DOUBLE) { | ||
151 | + schemas.push(createInputNumber(params)); | ||
152 | + } | ||
153 | + | ||
154 | + if (type === DataTypeEnum.IS_BOOL) { | ||
155 | + schemas.push(createSelect(params)); | ||
156 | + } | ||
157 | + | ||
158 | + if (type === DataTypeEnum.IS_STRING) { | ||
159 | + schemas.push(createInput(params)); | ||
160 | + } | ||
161 | + | ||
162 | + if (type === DataTypeEnum.IS_STRUCT) { | ||
163 | + schemas.push(createInputJson(params)); | ||
164 | + } | ||
165 | + } | ||
166 | + | ||
167 | + return schemas; | ||
168 | + }; | ||
169 | + | ||
170 | + onBeforeUpdate(() => { | ||
171 | + if (props.inputData && props.inputData.length) { | ||
172 | + const schemas = transformToFormSchema(props.inputData); | ||
173 | + setProps({ schemas }); | ||
174 | + } | ||
175 | + }); | ||
176 | + | ||
177 | + onUpdated(async () => { | ||
178 | + if (props.inputData && props.inputData.length) { | ||
179 | + await nextTick(); | ||
180 | + setFieldsValue(props.value); | ||
181 | + } | ||
182 | + }); | ||
183 | +</script> | ||
184 | + | ||
185 | +<template> | ||
186 | + <Card bordered class="!border-dashed !rounded-lg !border-2px"> | ||
187 | + <!-- <Alert class="!mb-4 w-32" message="服务参数配置" type="info" /> --> | ||
188 | + <BasicForm class="object-model-validate-form" @register="register" /> | ||
189 | + </Card> | ||
190 | +</template> | ||
191 | + | ||
192 | +<style lang="less"> | ||
193 | + .object-model-validate-form { | ||
194 | + .ant-input-number { | ||
195 | + width: 100% !important; | ||
196 | + } | ||
197 | + } | ||
198 | +</style> |
@@ -121,4 +121,5 @@ export type ComponentType = | @@ -121,4 +121,5 @@ export type ComponentType = | ||
121 | | 'StructForm' | 121 | | 'StructForm' |
122 | | 'ApiSelectScrollLoad' | 122 | | 'ApiSelectScrollLoad' |
123 | | 'TransferModal' | 123 | | 'TransferModal' |
124 | - | 'TransferTableModal'; | 124 | + | 'TransferTableModal' |
125 | + | 'ObjectModelValidateForm'; |
@@ -20,6 +20,11 @@ export type TOption = { | @@ -20,6 +20,11 @@ export type TOption = { | ||
20 | value: string; | 20 | value: string; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | +export enum CommandTypeEnum { | ||
24 | + CUSTOM = 0, | ||
25 | + SERVICE = 1, | ||
26 | +} | ||
27 | + | ||
23 | /** | 28 | /** |
24 | * 所使用的枚举值 | 29 | * 所使用的枚举值 |
25 | */ | 30 | */ |
@@ -575,11 +580,28 @@ export const actionSchema: FormSchema[] = [ | @@ -575,11 +580,28 @@ export const actionSchema: FormSchema[] = [ | ||
575 | span: 6, | 580 | span: 6, |
576 | }, | 581 | }, |
577 | componentProps: ({ formModel, formActionType }) => { | 582 | componentProps: ({ formModel, formActionType }) => { |
578 | - const { setFieldsValue } = formActionType; | ||
579 | - const deviceProfileId = formModel['deviceProfileId']; | 583 | + const { updateSchema } = formActionType; |
584 | + const deviceProfileId = Reflect.get(formModel, 'deviceProfileId'); | ||
585 | + const thingsModelId = Reflect.get(formModel, 'thingsModelId'); | ||
580 | return { | 586 | return { |
581 | placeholder: '请选择服务', | 587 | placeholder: '请选择服务', |
582 | - api: getModelServices, | 588 | + api: async (params: Recordable) => { |
589 | + try { | ||
590 | + const record = await getModelServices(params as Record<'deviceProfileId', string>); | ||
591 | + const selected = record.find((item) => item.id === thingsModelId); | ||
592 | + selected && | ||
593 | + updateSchema({ | ||
594 | + field: 'serviceInputValue', | ||
595 | + componentProps: { | ||
596 | + inputData: selected?.functionJson.inputData, | ||
597 | + }, | ||
598 | + }); | ||
599 | + return record; | ||
600 | + } catch (error) { | ||
601 | + console.error(error); | ||
602 | + return []; | ||
603 | + } | ||
604 | + }, | ||
583 | params: { | 605 | params: { |
584 | deviceProfileId, | 606 | deviceProfileId, |
585 | }, | 607 | }, |
@@ -587,7 +609,15 @@ export const actionSchema: FormSchema[] = [ | @@ -587,7 +609,15 @@ export const actionSchema: FormSchema[] = [ | ||
587 | valueField: 'id', | 609 | valueField: 'id', |
588 | getPopupContainer: () => document.body, | 610 | getPopupContainer: () => document.body, |
589 | onChange: (_, options: ModelOfMatterParams) => { | 611 | onChange: (_, options: ModelOfMatterParams) => { |
590 | - setFieldsValue({ doContext: { ...options.functionJson, callType: options.callType } }); | 612 | + if (options) { |
613 | + // setFieldsValue({ doContext: { ...options.functionJson, callType: options.callType } }); | ||
614 | + updateSchema({ | ||
615 | + field: 'serviceInputValue', | ||
616 | + componentProps: { | ||
617 | + inputData: options.functionJson.inputData, | ||
618 | + }, | ||
619 | + }); | ||
620 | + } | ||
591 | }, | 621 | }, |
592 | }; | 622 | }; |
593 | }, | 623 | }, |
@@ -665,6 +695,18 @@ export const actionSchema: FormSchema[] = [ | @@ -665,6 +695,18 @@ export const actionSchema: FormSchema[] = [ | ||
665 | }, | 695 | }, |
666 | slot: 'clearAlarm', | 696 | slot: 'clearAlarm', |
667 | }, | 697 | }, |
698 | + { | ||
699 | + field: 'serviceInputValue', | ||
700 | + component: 'ObjectModelValidateForm', | ||
701 | + label: '', | ||
702 | + changeEvent: 'update:value', | ||
703 | + valueField: 'value', | ||
704 | + show: ({ values }) => values['thingsModelId'], | ||
705 | + colProps: { | ||
706 | + span: 24, | ||
707 | + }, | ||
708 | + componentProps: {}, | ||
709 | + }, | ||
668 | ]; | 710 | ]; |
669 | 711 | ||
670 | export const alarmScheduleSchemas: FormSchema[] = [ | 712 | export const alarmScheduleSchemas: FormSchema[] = [ |
@@ -103,7 +103,7 @@ | @@ -103,7 +103,7 @@ | ||
103 | import { BasicForm, useForm } from '/@/components/Form/index'; | 103 | import { BasicForm, useForm } from '/@/components/Form/index'; |
104 | import { Tooltip, Select, Checkbox, Card } from 'ant-design-vue'; | 104 | import { Tooltip, Select, Checkbox, Card } from 'ant-design-vue'; |
105 | import { Icon } from '/@/components/Icon'; | 105 | import { Icon } from '/@/components/Icon'; |
106 | - import { actionSchema } from '../config/config.data'; | 106 | + import { actionSchema, CommandTypeEnum } from '../config/config.data'; |
107 | import jsoneditor from 'jsoneditor'; | 107 | import jsoneditor from 'jsoneditor'; |
108 | import 'jsoneditor/dist/jsoneditor.min.css'; | 108 | import 'jsoneditor/dist/jsoneditor.min.css'; |
109 | import { QuestionCircleOutlined, PlusOutlined } from '@ant-design/icons-vue'; | 109 | import { QuestionCircleOutlined, PlusOutlined } from '@ant-design/icons-vue'; |
@@ -261,19 +261,26 @@ | @@ -261,19 +261,26 @@ | ||
261 | //TODO-fengtao-设备验证 | 261 | //TODO-fengtao-设备验证 |
262 | const value = getFieldsValue(); | 262 | const value = getFieldsValue(); |
263 | const doContext = unref(jsonInstance)?.get() || {}; | 263 | const doContext = unref(jsonInstance)?.get() || {}; |
264 | + const serviceInputValue = Reflect.get(value, 'serviceInputValue'); | ||
265 | + | ||
264 | return { | 266 | return { |
265 | ...value, | 267 | ...value, |
266 | - ...(Number(value.commandType) === 0 ? { doContext } : {}), | 268 | + ...(Number(value.commandType) === CommandTypeEnum.CUSTOM |
269 | + ? { doContext } | ||
270 | + : { doContext: serviceInputValue }), | ||
267 | clearRule, | 271 | clearRule, |
268 | }; | 272 | }; |
269 | }; | 273 | }; |
270 | 274 | ||
271 | const setFieldsFormValueFun = (fieldsValue) => { | 275 | const setFieldsFormValueFun = (fieldsValue) => { |
276 | + const doContext = Reflect.get(fieldsValue, 'doContext'); | ||
277 | + const commandType = Reflect.get(fieldsValue, 'commandType'); | ||
272 | setFieldsValue({ | 278 | setFieldsValue({ |
273 | ...fieldsValue, | 279 | ...fieldsValue, |
274 | ...(isNumber(fieldsValue.commandType) | 280 | ...(isNumber(fieldsValue.commandType) |
275 | ? { commandType: String(fieldsValue.commandType) } | 281 | ? { commandType: String(fieldsValue.commandType) } |
276 | : {}), | 282 | : {}), |
283 | + serviceInputValue: commandType === CommandTypeEnum.SERVICE ? doContext.params || {} : {}, | ||
277 | }); | 284 | }); |
278 | }; | 285 | }; |
279 | //ft-add | 286 | //ft-add |