index.vue
3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<script setup lang="ts">
import { Card } from 'ant-design-vue'
import { computed, nextTick, reactive, ref, unref, watch } from 'vue'
import { getFormSchemas } from './config'
import { ThingsModelForm } from '.'
import type { StructJSON } from '@/api/device/model'
import { BasicForm, useForm } from '@/components/Form'
import { FormLabelAlignEnum, FormLayoutEnum } from '@/components/Form/src/enum'
import { deepMerge } from '@/utils'
import { DataTypeEnum } from '@/enums/objectModelEnum'
interface ThingsModelFormPropsType {
value?: Recordable
inputData?: StructJSON[]
required?: boolean
title?: string
transportType?: string
}
const props = withDefaults(defineProps<ThingsModelFormPropsType>(), {
inputData: () => [],
required: true,
})
const propsRef = ref<Partial<ThingsModelFormPropsType>>({})
const getProps = computed<ThingsModelFormPropsType>(() => ({ ...props, ...unref(propsRef) }))
const thingsModelFormListElMap = reactive<Record<string, { el: InstanceType<typeof ThingsModelForm>; structJSON: StructJSON }>>({})
const [register, formActionType] = useForm({
schemas: getFormSchemasByProps(),
showActionButtonGroup: false,
name: Math.random().toString(16).substring(2),
labelWidth: 100,
labelAlign: FormLabelAlignEnum.RIGHT,
layout: FormLayoutEnum.HORIZONTAL,
})
const getStructFormItem = computed(() => {
const { inputData } = unref(getProps)
return (inputData || []).filter(item => item.dataType?.type === DataTypeEnum.STRUCT)
})
const setFormElRef = (el: InstanceType<typeof ThingsModelForm>, structJSON: StructJSON) => {
const _structJSON = unref(getStructFormItem).find(item => item.identifier === structJSON.identifier)
if (_structJSON)
thingsModelFormListElMap[structJSON.identifier] = { el, structJSON }
}
const getFieldsValue = () => {
const basicValue = formActionType.getFieldsValue()
const structValue: Recordable = {}
for (const key of Object.keys(thingsModelFormListElMap)) {
const item = thingsModelFormListElMap[key]
const { el } = item
structValue[key] = el.getFieldsValue() || {}
}
return {
...basicValue,
...structValue,
}
}
const setFieldsValue = (value: Recordable) => {
return formActionType.setFieldsValue(value)
}
const validate = async () => {
await formActionType.validate()
for (const key of Object.keys(thingsModelFormListElMap))
await thingsModelFormListElMap[key].el.validate()
}
watch(() => unref(getProps).value,
async (value) => {
await nextTick()
formActionType.setFieldsValue(value || {})
},
{ immediate: true },
)
function getFormSchemasByProps() {
return getFormSchemas({ structJSON: unref(getProps).inputData || [], required: unref(getProps).required, transportType: unref(getProps).transportType })
}
watch(
() => unref(getProps).inputData,
(value) => {
if (value && value.length)
formActionType.setProps({ schemas: getFormSchemasByProps() })
})
function setProps(props: Partial<ThingsModelFormPropsType>) {
propsRef.value = deepMerge(unref(propsRef) || {}, props) as any
}
defineExpose({
getFieldsValue,
setFieldsValue,
validate,
setProps,
})
</script>
<template>
<Card class="!border-2 !border-dashed" :title="getProps.title">
<BasicForm class="things-model-form" @register="register">
<template v-for="item in getStructFormItem" #[item.identifier]="{ model, field }" :key="item.identifier">
<ThingsModelForm
:ref="(el) => setFormElRef(el as InstanceType<typeof ThingsModelForm>, item)"
v-model:value="model[field]" :input-data="(item.dataType?.specs as StructJSON[]) || []"
:title="item.functionName"
/>
</template>
</BasicForm>
</Card>
</template>
<style lang="less" scoped>
.things-model-form {
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-form-item-label) {
>label {
display: block;
text-align: right;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
}
:deep(.ant-form-item-control) {
margin-left: 6px;
}
</style>