-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Expand file tree
/
Copy pathindex.vue
More file actions
222 lines (207 loc) · 5.72 KB
/
index.vue
File metadata and controls
222 lines (207 loc) · 5.72 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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
<template>
<el-form
@submit.prevent
ref="ruleFormRef"
label-width="130px"
label-suffix=":"
v-loading="loading"
v-bind="$attrs"
>
<slot :form_value="formValue"></slot>
<template v-for="item in formFieldList" :key="item.field">
<FormItem
ref="formFieldRef"
:key="item.field"
v-if="show(item)"
@change="change(item, $event)"
v-bind:modelValue="formValue[item.field]"
:formfield="item"
:trigger="trigger"
:view="view"
:initDefaultData="initDefaultData"
:defaultItemWidth="defaultItemWidth"
:other-params="otherParams"
:form-value="formValue"
:formfield-list="formFieldList"
:parent_field="parent_field"
>
</FormItem>
</template>
</el-form>
</template>
<script lang="ts" setup>
import type { Dict } from '@/api/type/common'
import FormItem from '@/components/dynamics-form/FormItem.vue'
import type { FormField } from '@/components/dynamics-form/type'
import { ref, onBeforeMount, watch, type Ref } from 'vue'
import type { FormInstance } from 'element-plus'
import triggerApi from '@/api/provider'
import type Result from '@/request/Result'
import _ from 'lodash'
defineOptions({ name: 'dynamicsForm' })
const props = withDefaults(
defineProps<{
// 页面渲染数据
render_data: Promise<Result<Array<FormField>>> | string | Array<FormField>
// 调用接口所需要的其他参数
otherParams?: any
// 是否只读
view?: boolean
// 默认每个宽度
defaultItemWidth?: string
parent_field?: string
modelValue?: Dict<any>
}>(),
{ view: false, defaultItemWidth: '75%', otherParams: () => {} }
)
const formValue = ref<Dict<any>>({})
const loading = ref<boolean>(false)
const formFieldList = ref<Array<FormField>>([])
const ruleFormRef = ref<FormInstance>()
const formFieldRef = ref<Array<InstanceType<typeof FormItem>>>([])
/**
* 当前 field是否展示
* @param field
*/
const show = (field: FormField) => {
if (field.relation_show_field_dict) {
let keys = Object.keys(field.relation_show_field_dict)
for (const index in keys) {
const key = keys[index]
let v = _.get(formValue.value, key)
if (v && v !== undefined && v !== null) {
let values = field.relation_show_field_dict[key]
if (values && values.length > 0) {
return values.includes(v)
} else {
return true
}
} else {
return false
}
}
}
return true
}
const emit = defineEmits(['update:modelValue'])
/**
* 表单字段修改
* @param field
* @param value
*/
const change = (field: FormField, value: any) => {
formValue.value[field.field] = value
}
watch(
formValue,
() => {
emit('update:modelValue', formValue.value)
},
{ deep: true }
)
/**
* 触发器,用户获取子表单 或者 下拉选项
* @param field
* @param loading
*/
const trigger = (field: FormField, loading: Ref<boolean>) => {
if (field.provider && field.method) {
return triggerApi
.trigger(
field.provider,
field.method,
{
...props.otherParams,
...formValue.value
},
loading
)
.then((ok) => {
if (field.trigger_type === 'CHILD_FORMS') {
field.children = ok.data as Array<FormField>
} else {
field.option_list = ok.data as Array<any>
}
})
}
return Promise.resolve([])
}
/**
* 初始化默认数据
*/
const initDefaultData = (formField: FormField) => {
if (
formField.default_value &&
(formValue.value[formField.field] === undefined ||
formValue.value[formField.field] === null ||
!formValue.value[formField.field]) &&
formValue.value[formField.field] != false
) {
if (formField.show_default_value === true) {
formValue.value[formField.field] = formField.default_value
}
}
}
onBeforeMount(() => {
render(props.render_data, props.modelValue)
})
const render = (
render_data: string | Array<FormField> | Promise<Result<Array<FormField>>>,
data?: Dict<any>
) => {
if (typeof render_data == 'string') {
triggerApi.get(render_data, {}, loading).then((ok) => {
formFieldList.value = ok.data
})
} else if (render_data instanceof Array) {
formFieldList.value = render_data
} else {
render_data.then((ok) => {
formFieldList.value = ok.data
})
}
const form_data = data ? data : {}
if (form_data) {
const value = formFieldList.value
.map((item) => {
if (form_data[item.field] !== undefined) {
if (item.value_field && item.option_list && item.option_list.length > 0) {
const value_field = item.value_field
const find = item.option_list?.find((i) => i[value_field] === form_data[item.field])
if (find) {
return { [item.field]: form_data[item.field] }
}
if (item.show_default_value === true || item.show_default_value === undefined) {
return { [item.field]: item.default_value }
}
} else {
return { [item.field]: form_data[item.field] }
}
}
if (item.show_default_value === true || item.show_default_value === undefined) {
return { [item.field]: item.default_value }
}
return {}
})
.reduce((x, y) => ({ ...x, ...y }), {})
formValue.value = _.cloneDeep(value)
}
}
/**
* 校验函数
*/
const validate = () => {
return Promise.all([
...formFieldRef.value.map((item) => item.validate()),
ruleFormRef.value ? ruleFormRef.value.validate() : Promise.resolve()
])
}
// 暴露获取当前表单数据函数
defineExpose({
initDefaultData,
validate,
render,
ruleFormRef
})
</script>
<style lang="scss" scope></style>