@neatui/vue 1.2.22 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,425 @@
1
+ <template>
2
+ <div class="form-loader n-sm-sub" :data-level="level" ui-row="">
3
+ <div v-for="(node, i1) in $form" v-if="!node.clear" :key="i1" class="form-loader-item" :id="node._fid" :ui-col="node.media">
4
+ <div :id="`form${index + '' ? '-' + index : ''}-field-${node.field}`" v-bind="node.attrs" :data-level="level" data-node="child">
5
+ <slot :name="node.field" v-model:node="node" v-model:data="data">
6
+ <div v-if="node.label[0] !== '*'" :class="`form-loader-label ${node.vertical ? 'flex-block' : 'flex-fixed nr-sm'} o-ls`" :style="labelcss(node)" ui-flex="row xm">
7
+ <slot v-if="slots.includes(`${node.field}-label`)" :name="`${node.field}-label`"></slot>
8
+ <slot v-else name="every-label" v-bind:node="node" v-bind="data">
9
+ <template v-if="node.label[0]">
10
+ <h6 class="flex-block pr" v-if="node.vertical" v-bind="node.label[1]">
11
+ <template v-if="node.label[0] === '*'"></template>
12
+ <template v-else>
13
+ <b v-if="node.rules.some((v) => v.required)" class="co-risk">﹡</b><span>{{ node.label[0] }}</span>
14
+ </template>
15
+ </h6>
16
+ <h6 v-else class="flex-block ar pr" v-bind="node.label[1]">
17
+ <template v-if="node.label[0] === '*'"></template>
18
+ <template v-else>
19
+ <b v-if="node.rules.some((v) => v.required)" class="co-risk">﹡</b><span>{{ node.label[0] }}</span>
20
+ </template>
21
+ </h6>
22
+ </template>
23
+ </slot>
24
+ <div v-if="node.array">
25
+ <el-button size="s" @click="fAdd(node, data[node.field])">
26
+ <span>+</span>
27
+ </el-button>
28
+ </div>
29
+ </div>
30
+ <template v-if="node.array">
31
+ <template v-if="isArray(node.array)">
32
+ <div class="form-loader-group-array">
33
+ <div v-for="(item, i2) in data[node.field]" :key="i2" class="form-loader-array-item" ui-flex="row xm">
34
+ <div class="flex-block">
35
+ <FormLoader
36
+ v-model:form="node.array"
37
+ v-model:data="item"
38
+ v-model:fulldata="data"
39
+ :rows="rows"
40
+ :level="level + 1"
41
+ :index="i2"
42
+ :debug="debug"
43
+ :interacted="interacted"
44
+ :slots="slots"
45
+ >
46
+ <!-- 通用插槽 -->
47
+ <template v-slot:every-label="slotprops"><slot name="every-label" v-bind="slotprops"></slot></template>
48
+ <template v-slot:array-label="slotprops"><slot name="array-label" v-bind="slotprops"></slot></template>
49
+ <template v-slot:child-label="slotprops"><slot name="child-label" v-bind="slotprops"></slot></template>
50
+
51
+ <!-- 拉圾VUE2不能直接遍历 -->
52
+ <template v-if="slots[0]" v-slot:[slots[0]]="slotprops"><slot :name="slots[0]" v-bind="slotprops"></slot></template>
53
+ <template v-if="slots[1]" v-slot:[slots[1]]="slotprops"><slot :name="slots[1]" v-bind="slotprops"></slot></template>
54
+ <template v-if="slots[2]" v-slot:[slots[2]]="slotprops"><slot :name="slots[2]" v-bind="slotprops"></slot></template>
55
+ <template v-if="slots[3]" v-slot:[slots[3]]="slotprops"><slot :name="slots[3]" v-bind="slotprops"></slot></template>
56
+ <template v-if="slots[4]" v-slot:[slots[4]]="slotprops"><slot :name="slots[4]" v-bind="slotprops"></slot></template>
57
+ <template v-if="slots[5]" v-slot:[slots[5]]="slotprops"><slot :name="slots[5]" v-bind="slotprops"></slot></template>
58
+ <template v-if="slots[6]" v-slot:[slots[6]]="slotprops"><slot :name="slots[6]" v-bind="slotprops"></slot></template>
59
+ <template v-if="slots[7]" v-slot:[slots[7]]="slotprops"><slot :name="slots[7]" v-bind="slotprops"></slot></template>
60
+ <template v-if="slots[8]" v-slot:[slots[8]]="slotprops"><slot :name="slots[8]" v-bind="slotprops"></slot></template>
61
+ <template v-if="slots[9]" v-slot:[slots[9]]="slotprops"><slot :name="slots[9]" v-bind="slotprops"></slot></template>
62
+
63
+ <template v-if="slots[10]" v-slot:[slots[10]]="slotprops"><slot :name="slots[10]" v-bind="slotprops"></slot></template>
64
+ <template v-if="slots[11]" v-slot:[slots[11]]="slotprops"><slot :name="slots[11]" v-bind="slotprops"></slot></template>
65
+ <template v-if="slots[12]" v-slot:[slots[12]]="slotprops"><slot :name="slots[12]" v-bind="slotprops"></slot></template>
66
+ <template v-if="slots[13]" v-slot:[slots[13]]="slotprops"><slot :name="slots[13]" v-bind="slotprops"></slot></template>
67
+ <template v-if="slots[14]" v-slot:[slots[14]]="slotprops"><slot :name="slots[14]" v-bind="slotprops"></slot></template>
68
+ <template v-if="slots[15]" v-slot:[slots[15]]="slotprops"><slot :name="slots[15]" v-bind="slotprops"></slot></template>
69
+ <template v-if="slots[16]" v-slot:[slots[16]]="slotprops"><slot :name="slots[16]" v-bind="slotprops"></slot></template>
70
+ <template v-if="slots[17]" v-slot:[slots[17]]="slotprops"><slot :name="slots[17]" v-bind="slotprops"></slot></template>
71
+ <template v-if="slots[18]" v-slot:[slots[18]]="slotprops"><slot :name="slots[18]" v-bind="slotprops"></slot></template>
72
+ <template v-if="slots[19]" v-slot:[slots[19]]="slotprops"><slot :name="slots[19]" v-bind="slotprops"></slot></template>
73
+
74
+ <template v-if="slots[20]" v-slot:[slots[20]]="slotprops"><slot :name="slots[20]" v-bind="slotprops"></slot></template>
75
+ <template v-if="slots[21]" v-slot:[slots[21]]="slotprops"><slot :name="slots[21]" v-bind="slotprops"></slot></template>
76
+ <template v-if="slots[22]" v-slot:[slots[22]]="slotprops"><slot :name="slots[22]" v-bind="slotprops"></slot></template>
77
+ <template v-if="slots[23]" v-slot:[slots[23]]="slotprops"><slot :name="slots[23]" v-bind="slotprops"></slot></template>
78
+ <template v-if="slots[24]" v-slot:[slots[24]]="slotprops"><slot :name="slots[24]" v-bind="slotprops"></slot></template>
79
+ <template v-if="slots[25]" v-slot:[slots[25]]="slotprops"><slot :name="slots[25]" v-bind="slotprops"></slot></template>
80
+ <template v-if="slots[26]" v-slot:[slots[26]]="slotprops"><slot :name="slots[26]" v-bind="slotprops"></slot></template>
81
+ <template v-if="slots[27]" v-slot:[slots[27]]="slotprops"><slot :name="slots[27]" v-bind="slotprops"></slot></template>
82
+ <template v-if="slots[28]" v-slot:[slots[28]]="slotprops"><slot :name="slots[28]" v-bind="slotprops"></slot></template>
83
+ <template v-if="slots[29]" v-slot:[slots[29]]="slotprops"><slot :name="slots[29]" v-bind="slotprops"></slot></template>
84
+ </FormLoader>
85
+ </div>
86
+ <div class="flex-fixed" @click="fDel(data[node.field], i2)">-</div>
87
+ </div>
88
+ </div>
89
+ </template>
90
+ <div v-else v-html="err(`配置错误:Field: ${node.field} 配置了属性值 [array] 必须是一个数组`)"></div>
91
+ </template>
92
+ <template v-else-if="node.child">
93
+ <template v-if="isArray(node.child)">
94
+ <FormLoader
95
+ class="form-loader-group-child"
96
+ v-model:form="node.child"
97
+ v-model:data="data[node.field]"
98
+ v-model:fulldata="data"
99
+ :rows="rows"
100
+ :level="level + 1"
101
+ :debug="debug"
102
+ :interacted="interacted"
103
+ :slots="slots"
104
+ >
105
+ <!-- 通用插槽 -->
106
+ <template v-slot:every-label="slotprops"><slot name="every-label" v-bind="slotprops"></slot></template>
107
+ <template v-slot:array-label="slotprops"><slot name="array-label" v-bind="slotprops"></slot></template>
108
+ <template v-slot:child-label="slotprops"><slot name="child-label" v-bind="slotprops"></slot></template>
109
+
110
+ <!-- 拉圾VUE2不能直接遍历 -->
111
+ <template v-if="slots[0]" v-slot:[slots[0]]="slotprops"><slot :name="slots[0]" v-bind="slotprops"></slot></template>
112
+ <template v-if="slots[1]" v-slot:[slots[1]]="slotprops"><slot :name="slots[1]" v-bind="slotprops"></slot></template>
113
+ <template v-if="slots[2]" v-slot:[slots[2]]="slotprops"><slot :name="slots[2]" v-bind="slotprops"></slot></template>
114
+ <template v-if="slots[3]" v-slot:[slots[3]]="slotprops"><slot :name="slots[3]" v-bind="slotprops"></slot></template>
115
+ <template v-if="slots[4]" v-slot:[slots[4]]="slotprops"><slot :name="slots[4]" v-bind="slotprops"></slot></template>
116
+ <template v-if="slots[5]" v-slot:[slots[5]]="slotprops"><slot :name="slots[5]" v-bind="slotprops"></slot></template>
117
+ <template v-if="slots[6]" v-slot:[slots[6]]="slotprops"><slot :name="slots[6]" v-bind="slotprops"></slot></template>
118
+ <template v-if="slots[7]" v-slot:[slots[7]]="slotprops"><slot :name="slots[7]" v-bind="slotprops"></slot></template>
119
+ <template v-if="slots[8]" v-slot:[slots[8]]="slotprops"><slot :name="slots[8]" v-bind="slotprops"></slot></template>
120
+ <template v-if="slots[9]" v-slot:[slots[9]]="slotprops"><slot :name="slots[9]" v-bind="slotprops"></slot></template>
121
+
122
+ <template v-if="slots[10]" v-slot:[slots[10]]="slotprops"><slot :name="slots[10]" v-bind="slotprops"></slot></template>
123
+ <template v-if="slots[11]" v-slot:[slots[11]]="slotprops"><slot :name="slots[11]" v-bind="slotprops"></slot></template>
124
+ <template v-if="slots[12]" v-slot:[slots[12]]="slotprops"><slot :name="slots[12]" v-bind="slotprops"></slot></template>
125
+ <template v-if="slots[13]" v-slot:[slots[13]]="slotprops"><slot :name="slots[13]" v-bind="slotprops"></slot></template>
126
+ <template v-if="slots[14]" v-slot:[slots[14]]="slotprops"><slot :name="slots[14]" v-bind="slotprops"></slot></template>
127
+ <template v-if="slots[15]" v-slot:[slots[15]]="slotprops"><slot :name="slots[15]" v-bind="slotprops"></slot></template>
128
+ <template v-if="slots[16]" v-slot:[slots[16]]="slotprops"><slot :name="slots[16]" v-bind="slotprops"></slot></template>
129
+ <template v-if="slots[17]" v-slot:[slots[17]]="slotprops"><slot :name="slots[17]" v-bind="slotprops"></slot></template>
130
+ <template v-if="slots[18]" v-slot:[slots[18]]="slotprops"><slot :name="slots[18]" v-bind="slotprops"></slot></template>
131
+ <template v-if="slots[19]" v-slot:[slots[19]]="slotprops"><slot :name="slots[19]" v-bind="slotprops"></slot></template>
132
+
133
+ <template v-if="slots[20]" v-slot:[slots[20]]="slotprops"><slot :name="slots[20]" v-bind="slotprops"></slot></template>
134
+ <template v-if="slots[21]" v-slot:[slots[21]]="slotprops"><slot :name="slots[21]" v-bind="slotprops"></slot></template>
135
+ <template v-if="slots[22]" v-slot:[slots[22]]="slotprops"><slot :name="slots[22]" v-bind="slotprops"></slot></template>
136
+ <template v-if="slots[23]" v-slot:[slots[23]]="slotprops"><slot :name="slots[23]" v-bind="slotprops"></slot></template>
137
+ <template v-if="slots[24]" v-slot:[slots[24]]="slotprops"><slot :name="slots[24]" v-bind="slotprops"></slot></template>
138
+ <template v-if="slots[25]" v-slot:[slots[25]]="slotprops"><slot :name="slots[25]" v-bind="slotprops"></slot></template>
139
+ <template v-if="slots[26]" v-slot:[slots[26]]="slotprops"><slot :name="slots[26]" v-bind="slotprops"></slot></template>
140
+ <template v-if="slots[27]" v-slot:[slots[27]]="slotprops"><slot :name="slots[27]" v-bind="slotprops"></slot></template>
141
+ <template v-if="slots[28]" v-slot:[slots[28]]="slotprops"><slot :name="slots[28]" v-bind="slotprops"></slot></template>
142
+ <template v-if="slots[29]" v-slot:[slots[29]]="slotprops"><slot :name="slots[29]" v-bind="slotprops"></slot></template>
143
+ </FormLoader>
144
+ </template>
145
+ <div v-else v-html="err(`配置错误:Field: ${node.field} 配置了属性值 [child] 必须是一个数组`)"></div>
146
+ </template>
147
+ <template v-else>
148
+ <FormRender v-model:node="node" v-model:data="data" :interacted="interacted" :data-field="node.field">
149
+ <template v-slot:[`${node.field}-value`]="slotprops">
150
+ <slot :name="`${node.field}-value`" v-bind="slotprops"></slot>
151
+ </template>
152
+ </FormRender>
153
+ </template>
154
+ </slot>
155
+ </div>
156
+ </div>
157
+ <div class="full-x" ui-flex="row lm">
158
+ <div class="flex-fixed" :style="labelcss(node)">&nbsp;</div>
159
+ <div class="flex-block"><slot name="submit"></slot></div>
160
+ </div>
161
+ </div>
162
+ </template>
163
+
164
+ <script>
165
+ import { deepcopy, isArray, isFunction, isString } from '@fekit/utils';
166
+
167
+ // 根据表单结构生成数据结构
168
+ const _rows = (arr) => {
169
+ const data = {};
170
+ for (const node of arr) {
171
+ data[node.field] = node.child ? _rows(node.child) : node.array ? [] : '';
172
+ }
173
+ return data;
174
+ };
175
+
176
+ export default {
177
+ name: 'FormLoader',
178
+ components: {
179
+ FormRender: () => import('./FormRender.vue'),
180
+ FormLoader: () => import('./FormLoader.vue')
181
+ },
182
+ props: {
183
+ debug: {
184
+ type: Boolean,
185
+ default: false
186
+ },
187
+ form: {
188
+ type: Array,
189
+ default: () => []
190
+ },
191
+ data: {
192
+ type: Object,
193
+ default: () => ({})
194
+ },
195
+ fulldata: {
196
+ type: Object,
197
+ default: () => null
198
+ },
199
+ rows: {
200
+ type: String,
201
+ default: 'mob-24 pad-12 dpc-8'
202
+ },
203
+ interacted: {
204
+ type: Boolean,
205
+ default: false
206
+ },
207
+ array: {
208
+ type: Boolean,
209
+ default: false
210
+ },
211
+ level: {
212
+ type: Number,
213
+ default: 0
214
+ },
215
+ index: {
216
+ type: String,
217
+ default: ''
218
+ },
219
+ vertical: {
220
+ type: Boolean,
221
+ default: false
222
+ },
223
+ slots: {
224
+ type: Array,
225
+ default: () => []
226
+ }
227
+ },
228
+ data() {
229
+ return {
230
+ node: [],
231
+ lw: 0
232
+ };
233
+ },
234
+ computed: {
235
+ $form() {
236
+ const form = this.form;
237
+ const data = this.fulldata || this.data;
238
+ return deepcopy(form)?.map((node = {}) => {
239
+ // 清除字段
240
+ if (isFunction(node.clear)) {
241
+ node.clear = node.clear(data, node);
242
+ if (node.clear && data[node.field] !== '') {
243
+ this.$set(data, node.field, '');
244
+ }
245
+ }
246
+
247
+ // 水平垂直
248
+ if (isFunction(node.vertical)) {
249
+ node.vertical = node.vertical(data, node);
250
+ }
251
+ if (!node.vertical) {
252
+ node.vertical = this.vertical;
253
+ }
254
+
255
+ // 模型处理
256
+ if (isFunction(node.model)) {
257
+ node.model = node.model(data, node);
258
+ }
259
+ if (node.model) {
260
+ if (isString(node.model)) {
261
+ node.model = [node.model, { verify: false }];
262
+ }
263
+ } else {
264
+ node.model = ['', { verify: false }];
265
+ }
266
+ if (!node.model[1]) {
267
+ node.model[1] = {};
268
+ }
269
+ if (node.model[1]) {
270
+ node.model[1] = {
271
+ verify: false,
272
+ clearable: true,
273
+ ...node.model[1]
274
+ };
275
+ }
276
+
277
+ // 枚举处理
278
+ if (isFunction(node.enums)) {
279
+ node.enums = node.enums(data, node);
280
+ }
281
+
282
+ // 规则处理
283
+ if (isFunction(node.rules)) {
284
+ node.rules = node.rules(data, node);
285
+ }
286
+ if (!node.rules) {
287
+ node.rules = [];
288
+ }
289
+
290
+ // 媒体查询
291
+ if (isFunction(node.media)) {
292
+ node.media = node.media(data, node);
293
+ }
294
+ if (!node.media) {
295
+ node.media = this.rows;
296
+ }
297
+
298
+ // 属性处理
299
+ if (isFunction(node.attrs)) {
300
+ node.attrs = node.attrs(data, node);
301
+ }
302
+ if (!node.attrs) {
303
+ node.attrs = {};
304
+ }
305
+ if (node.attrs) {
306
+ node.attrs = {
307
+ 'ui-flex': node.vertical ? 'col xt' : 'row xt',
308
+ ...node.attrs
309
+ };
310
+ }
311
+
312
+ // 名称处理
313
+ if (isFunction(node.label)) {
314
+ node.label = node.label(data, node);
315
+ }
316
+ if (node.label) {
317
+ if (isString(node.label)) {
318
+ node.label = [node.label, { class: '', style: '' }];
319
+ }
320
+ } else {
321
+ node.label = ['*', { class: '', style: '' }];
322
+ }
323
+ if (!node.label[1]) {
324
+ node.label[1] = { class: '', style: '' };
325
+ }
326
+ node.label[0] = node.label[0] && node.label[0] !== '*' && !((node.array || node.child) && node.vertical) ? node.label[0] + ':' : node.label[0] || '';
327
+ this.clw(node.label[0]);
328
+ // 默认样式处理
329
+ if (node.label[1]) {
330
+ node.label[1].style = `${node.vertical && node?.rules?.some((v) => v.required) ? 'text-indent: -1em;' : ''} ${node.label[1] || ''}`;
331
+ }
332
+
333
+ return node;
334
+ });
335
+ }
336
+ },
337
+ methods: {
338
+ // 错误提示
339
+ err(text) {
340
+ return `<p class="co-risk" ui-flex="row lm"><svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" style="width: 1.2em; height: 1.2em;"><path d="M906.666667 759.466667L578.133333 187.733333C565.333333 164.266667 539.733333 149.333333 512 149.333333s-53.333333 14.933333-66.133333 38.4L117.333333 759.466667c-12.8 23.466667-12.8 53.333333 0 76.8 14.933333 23.466667 38.4 38.4 66.133334 38.4h657.066666c27.733333 0 53.333333-14.933333 66.133334-38.4 14.933333-23.466667 14.933333-53.333333 0-76.8z m-426.666667-366.933334c0-19.2 14.933333-32 32-32s32 14.933333 32 32v189.866667c0 19.2-14.933333 32-32 32s-32-14.933333-32-32v-189.866667zM512 744.533333c-23.466667 0-44.8-19.2-44.8-44.8 0-23.466667 19.2-44.8 44.8-44.8s44.8 19.2 44.8 44.8c0 25.6-19.2 44.8-44.8 44.8z"></path></svg>${text}</p>`;
341
+ },
342
+ clw(label = '') {
343
+ let _lw = 0;
344
+ if (isString(label)) {
345
+ for (let i = 0; i < label.length; i++) {
346
+ const char = label[i];
347
+ if (/^[\u4e00-\u9fa5]+$/.test(char)) {
348
+ _lw += 1;
349
+ } else {
350
+ _lw += 0.5;
351
+ }
352
+ }
353
+ }
354
+ _lw += 3;
355
+ if (_lw > this.lw) {
356
+ this.lw = _lw;
357
+ }
358
+ },
359
+ // label样式
360
+ labelcss(node) {
361
+ if (node.vertical) {
362
+ // 竖向
363
+ return ``;
364
+ } else {
365
+ // 横向
366
+ return `width:${this.lw}em; max-width:50%;`;
367
+ }
368
+ },
369
+ // 数据预处理
370
+ predata() {
371
+ const fields = [];
372
+ // 补全数据字段
373
+ this.$form.forEach((item) => {
374
+ if (!fields.includes(item.field)) {
375
+ fields.push(item.field);
376
+ } else {
377
+ console.error(`表单字段重复:${item.field}`);
378
+ }
379
+ if (!this.data.hasOwnProperty(item.field)) {
380
+ if (item.array) {
381
+ this.$set(this.data, item.field, []);
382
+ } else if (item.child) {
383
+ this.$set(this.data, item.field, {});
384
+ } else if ((item.model[0] === 'Checkbox' && item.enums) || item.model[1]?.multiple) {
385
+ this.$set(this.data, item.field, []);
386
+ } else {
387
+ this.$set(this.data, item.field, '');
388
+ }
389
+ }
390
+ });
391
+ },
392
+ // 添加数组项
393
+ fAdd(node, data) {
394
+ const rows = _rows(node.array);
395
+ data?.push(rows);
396
+ },
397
+ // 删除数组项
398
+ fDel(data, idx) {
399
+ data?.splice(idx, 1);
400
+ },
401
+ isArray
402
+ },
403
+ watch: {
404
+ $form: {
405
+ handler() {
406
+ this.predata();
407
+ },
408
+ deep: true,
409
+ immediate: true
410
+ }
411
+ }
412
+ };
413
+ </script>
414
+ <style>
415
+ .form-loader {
416
+ position: relative;
417
+ width: 100%;
418
+ font-size: 13px;
419
+ }
420
+
421
+ .form-loader-label {
422
+ padding-top: 4px;
423
+ line-height: 18px;
424
+ }
425
+ </style>