lw-cdp-ui 1.3.21 → 1.3.23
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.
- package/dist/components/lwFormMini/FormItem.vue +44 -31
- package/dist/components/lwFormMini/index.vue +95 -80
- package/dist/components/lwTableForm/index.vue +1 -0
- package/dist/components/lwTableSelect/index.vue +59 -60
- package/dist/lw-cdp-ui.esm.js +3112 -3080
- package/dist/lw-cdp-ui.umd.js +12 -12
- package/dist/style.css +1 -1
- package/package.json +1 -1
|
@@ -253,7 +253,7 @@ export default {
|
|
|
253
253
|
props: {
|
|
254
254
|
item: {
|
|
255
255
|
type: Object,
|
|
256
|
-
default: () => {
|
|
256
|
+
default: () => {}
|
|
257
257
|
},
|
|
258
258
|
index: {
|
|
259
259
|
type: Number,
|
|
@@ -261,13 +261,13 @@ export default {
|
|
|
261
261
|
},
|
|
262
262
|
form: {
|
|
263
263
|
type: Object,
|
|
264
|
-
default: () => {
|
|
264
|
+
default: () => {}
|
|
265
265
|
}
|
|
266
266
|
},
|
|
267
267
|
watch: {
|
|
268
268
|
item: {
|
|
269
269
|
handler(val, oldVal) {
|
|
270
|
-
this.objItem = {
|
|
270
|
+
this.objItem = {...val, ...this.objItem}
|
|
271
271
|
},
|
|
272
272
|
immediate: true,
|
|
273
273
|
deep: true
|
|
@@ -275,13 +275,12 @@ export default {
|
|
|
275
275
|
form: {
|
|
276
276
|
handler(val) {
|
|
277
277
|
if (this.item.component === 'checkbox' || this.item.component === 'upload') {
|
|
278
|
-
this.objItem.options?.items?.forEach(
|
|
278
|
+
this.objItem.options?.items?.forEach(option => {
|
|
279
279
|
option.value = this.flattenObject(this.form, option.name, option.value)
|
|
280
|
-
})
|
|
280
|
+
})
|
|
281
281
|
} else {
|
|
282
282
|
this.objItem.value = this.flattenObject(this.form, this.item.name, this.objItem.value)
|
|
283
283
|
}
|
|
284
|
-
|
|
285
284
|
},
|
|
286
285
|
immediate: true,
|
|
287
286
|
deep: true
|
|
@@ -289,9 +288,9 @@ export default {
|
|
|
289
288
|
objItem: {
|
|
290
289
|
handler(val) {
|
|
291
290
|
if (val.component === 'checkbox' || val.component === 'upload') {
|
|
292
|
-
val.options?.items?.forEach(
|
|
291
|
+
val.options?.items?.forEach(option => {
|
|
293
292
|
this.unflattenObject(this.form, option.name, option.value)
|
|
294
|
-
})
|
|
293
|
+
})
|
|
295
294
|
} else {
|
|
296
295
|
this.unflattenObject(this.form, val.name, val.value)
|
|
297
296
|
}
|
|
@@ -302,42 +301,45 @@ export default {
|
|
|
302
301
|
}
|
|
303
302
|
},
|
|
304
303
|
deep: true
|
|
305
|
-
}
|
|
304
|
+
}
|
|
306
305
|
},
|
|
307
306
|
methods: {
|
|
308
307
|
flattenObject(obj, key, defaultValue = '') {
|
|
309
|
-
if (!key || !obj) {
|
|
310
|
-
|
|
308
|
+
if (!key || !obj) {
|
|
309
|
+
return false
|
|
310
|
+
}
|
|
311
|
+
const keys = key.split('.') // 将路径拆分成数组
|
|
311
312
|
|
|
312
|
-
let current = obj
|
|
313
|
+
let current = obj
|
|
313
314
|
// 遍历路径并逐层查找
|
|
314
315
|
for (let i = 0; i < keys.length; i++) {
|
|
315
316
|
// 如果当前层级不存在,则创建该层级对象
|
|
316
317
|
if (current[keys[i]] === undefined) {
|
|
317
|
-
current[keys[i]] =
|
|
318
|
+
current[keys[i]] = i === keys.length - 1 ? defaultValue : {} // 如果是最后一个层级,设为默认值,否则创建空对象
|
|
318
319
|
}
|
|
319
320
|
// 否则,继续向下查找
|
|
320
|
-
current = current[keys[i]]
|
|
321
|
+
current = current[keys[i]]
|
|
321
322
|
}
|
|
322
|
-
return current
|
|
323
|
+
return current
|
|
323
324
|
},
|
|
324
325
|
unflattenObject(obj, path, value) {
|
|
325
|
-
if (!path || !obj) {
|
|
326
|
-
|
|
326
|
+
if (!path || !obj) {
|
|
327
|
+
return false
|
|
328
|
+
}
|
|
329
|
+
const keys = path.split('.') // 按点分隔路径
|
|
327
330
|
|
|
328
331
|
keys.forEach((key, index) => {
|
|
329
332
|
if (index === keys.length - 1) {
|
|
330
333
|
// 最后一级,直接赋值
|
|
331
|
-
obj[key] = value
|
|
334
|
+
obj[key] = value
|
|
332
335
|
} else {
|
|
333
336
|
// 如果不存在该层级,创建空对象
|
|
334
337
|
if (!obj[key] || typeof obj[key] !== 'object') {
|
|
335
|
-
obj[key] = {}
|
|
338
|
+
obj[key] = {}
|
|
336
339
|
}
|
|
337
|
-
obj = obj[key]
|
|
340
|
+
obj = obj[key] // 进入下一层
|
|
338
341
|
}
|
|
339
|
-
})
|
|
340
|
-
|
|
342
|
+
})
|
|
341
343
|
},
|
|
342
344
|
// 删除tag
|
|
343
345
|
tagClose(tag, item) {
|
|
@@ -364,20 +366,19 @@ export default {
|
|
|
364
366
|
rulesHandle(item) {
|
|
365
367
|
if (item.requiredHandle) {
|
|
366
368
|
try {
|
|
367
|
-
const requiredHandleFunc = new Function(
|
|
368
|
-
const exp = requiredHandleFunc(this.form)
|
|
369
|
+
const requiredHandleFunc = new Function('form', `return ${item.requiredHandle.replace(/\$/g, 'form')}`)
|
|
370
|
+
const exp = requiredHandleFunc(this.form)
|
|
369
371
|
|
|
370
|
-
const requiredRule = item.rules.find(t => 'required' in t)
|
|
372
|
+
const requiredRule = item.rules.find(t => 'required' in t)
|
|
371
373
|
if (requiredRule) {
|
|
372
|
-
requiredRule.required = exp
|
|
374
|
+
requiredRule.required = exp
|
|
373
375
|
}
|
|
374
376
|
} catch (error) {
|
|
375
|
-
console.error(
|
|
377
|
+
console.error('Error requiredHandle function:', error)
|
|
376
378
|
}
|
|
377
379
|
}
|
|
378
|
-
return item.rules
|
|
379
|
-
}
|
|
380
|
-
|
|
380
|
+
return item.rules
|
|
381
|
+
}
|
|
381
382
|
}
|
|
382
383
|
}
|
|
383
384
|
</script>
|
|
@@ -394,7 +395,6 @@ export default {
|
|
|
394
395
|
}
|
|
395
396
|
}
|
|
396
397
|
|
|
397
|
-
|
|
398
398
|
:deep(.el-tag) {
|
|
399
399
|
& + .button-new-tag {
|
|
400
400
|
margin-left: 10px;
|
|
@@ -403,4 +403,17 @@ export default {
|
|
|
403
403
|
margin-left: 10px;
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
|
+
.el-form-item-msg {
|
|
407
|
+
width: 100%;
|
|
408
|
+
font-size: 12px;
|
|
409
|
+
color: var(--el-text-color-placeholder);
|
|
410
|
+
line-height: 16px;
|
|
411
|
+
}
|
|
412
|
+
:deep(.el-form-item__label){
|
|
413
|
+
position: relative;
|
|
414
|
+
.el-tooltip__trigger{
|
|
415
|
+
position: absolute;
|
|
416
|
+
right: 0;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
406
419
|
</style>
|
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
</ul>
|
|
16
16
|
</el-affix>
|
|
17
17
|
|
|
18
|
+
<el-tabs v-if="blackType === 'tabs'"
|
|
19
|
+
v-model="activeIndex">
|
|
20
|
+
<el-tab-pane :label="card[0].label"
|
|
21
|
+
v-for="(card, index) in formItems"
|
|
22
|
+
:name="index"></el-tab-pane>
|
|
23
|
+
</el-tabs>
|
|
24
|
+
|
|
18
25
|
<el-skeleton v-if="renderLoading || Object.keys(form).length == 0"
|
|
19
26
|
animated />
|
|
20
27
|
|
|
@@ -28,11 +35,12 @@
|
|
|
28
35
|
:size="config?.size || 'default'"
|
|
29
36
|
element-loading-text="Loading...">
|
|
30
37
|
<div class="lw-form-mini-card"
|
|
31
|
-
v-for="card in formItems">
|
|
32
|
-
<el-row
|
|
38
|
+
v-for="(card, index) in formItems">
|
|
39
|
+
<el-row v-show="activeIndex == index || blackType === 'card'"
|
|
40
|
+
:gutter="15">
|
|
33
41
|
<template v-for="(item, index) in card">
|
|
34
42
|
<el-col :span="item.span || 24"
|
|
35
|
-
v-if="!hideHandle(item)">
|
|
43
|
+
v-if="!hideHandle(item) && !(blackType == 'tabs' && item.component == 'divider')">
|
|
36
44
|
<ViewItem v-if="isView && !item?.options?.isInput"
|
|
37
45
|
:item="item"
|
|
38
46
|
:form="form"
|
|
@@ -94,7 +102,7 @@ export default {
|
|
|
94
102
|
ViewItem
|
|
95
103
|
},
|
|
96
104
|
props: {
|
|
97
|
-
modelValue: {
|
|
105
|
+
modelValue: {type: Object, default: () => {}},
|
|
98
106
|
/**
|
|
99
107
|
* 配置项
|
|
100
108
|
* {
|
|
@@ -120,25 +128,28 @@ export default {
|
|
|
120
128
|
* label: '选项2'
|
|
121
129
|
* }]
|
|
122
130
|
* }
|
|
123
|
-
* ...
|
|
131
|
+
* ...
|
|
124
132
|
* }]
|
|
125
133
|
* labelWidth: '100px', // 表单域标签的宽度
|
|
126
134
|
* labelPosition: 'top', // 表单域标签的位置,如果值为 left 或者 right 时,则需要设置 label-width
|
|
127
135
|
* ...
|
|
128
136
|
* }
|
|
129
137
|
* **/
|
|
130
|
-
config: {
|
|
138
|
+
config: {type: Object, default: () => {}},
|
|
131
139
|
// 是否显示加载中
|
|
132
|
-
loading: {
|
|
140
|
+
loading: {type: Boolean, default: false},
|
|
133
141
|
// 是否是查看模式
|
|
134
|
-
isView: {
|
|
142
|
+
isView: {type: Boolean, default: false},
|
|
135
143
|
// 显示导航
|
|
136
|
-
showMenu: {
|
|
144
|
+
showMenu: {type: Boolean, default: false},
|
|
145
|
+
// 模块显示方式 // tabs, card
|
|
146
|
+
blackType: {type: String, default: 'card'}
|
|
137
147
|
},
|
|
138
148
|
data() {
|
|
139
149
|
return {
|
|
140
150
|
form: {},
|
|
141
151
|
affixIndex: '',
|
|
152
|
+
activeIndex: 0,
|
|
142
153
|
isChange: true,
|
|
143
154
|
scrollObserverEnabled: true,
|
|
144
155
|
renderLoading: false
|
|
@@ -161,7 +172,7 @@ export default {
|
|
|
161
172
|
this.handleScroll()
|
|
162
173
|
})
|
|
163
174
|
}
|
|
164
|
-
this.$emit(
|
|
175
|
+
this.$emit('update:config', val)
|
|
165
176
|
},
|
|
166
177
|
immediate: true,
|
|
167
178
|
deep: true
|
|
@@ -175,30 +186,30 @@ export default {
|
|
|
175
186
|
return Object.keys(this.modelValue).length > 0
|
|
176
187
|
},
|
|
177
188
|
formItems() {
|
|
178
|
-
const result = []
|
|
179
|
-
let currentGroup = []
|
|
189
|
+
const result = []
|
|
190
|
+
let currentGroup = []
|
|
180
191
|
|
|
181
192
|
this.config.formItems.forEach(item => {
|
|
182
|
-
if (item.component ===
|
|
193
|
+
if (item.component === 'divider') {
|
|
183
194
|
if (!this.affixIndex) {
|
|
184
195
|
this.affixIndex = item.label
|
|
185
196
|
}
|
|
186
197
|
|
|
187
198
|
if (currentGroup.length) {
|
|
188
|
-
result.push(currentGroup)
|
|
189
|
-
currentGroup = []
|
|
199
|
+
result.push(currentGroup)
|
|
200
|
+
currentGroup = []
|
|
190
201
|
}
|
|
191
|
-
currentGroup.push(item)
|
|
202
|
+
currentGroup.push(item)
|
|
192
203
|
} else {
|
|
193
|
-
currentGroup.push(item)
|
|
204
|
+
currentGroup.push(item)
|
|
194
205
|
}
|
|
195
|
-
})
|
|
206
|
+
})
|
|
196
207
|
|
|
197
208
|
if (currentGroup.length) {
|
|
198
|
-
result.push(currentGroup)
|
|
209
|
+
result.push(currentGroup)
|
|
199
210
|
}
|
|
200
211
|
|
|
201
|
-
return result
|
|
212
|
+
return result
|
|
202
213
|
}
|
|
203
214
|
},
|
|
204
215
|
mounted() {
|
|
@@ -216,67 +227,71 @@ export default {
|
|
|
216
227
|
*/
|
|
217
228
|
render(config = this.config) {
|
|
218
229
|
function parse(formItems, form) {
|
|
219
|
-
const result = {}
|
|
220
|
-
formItems.forEach(
|
|
230
|
+
const result = {}
|
|
231
|
+
formItems.forEach(item => {
|
|
221
232
|
if (item.component === 'checkbox' || item.component === 'upload') {
|
|
222
|
-
item.options?.items?.forEach(
|
|
223
|
-
if (!option?.name) {
|
|
224
|
-
|
|
225
|
-
|
|
233
|
+
item.options?.items?.forEach(option => {
|
|
234
|
+
if (!option?.name) {
|
|
235
|
+
return false
|
|
236
|
+
}
|
|
237
|
+
result[option.name] = form?.[option.name] ?? option.value
|
|
238
|
+
})
|
|
226
239
|
}
|
|
227
|
-
if (!item?.name) {
|
|
228
|
-
|
|
240
|
+
if (!item?.name) {
|
|
241
|
+
return false
|
|
242
|
+
}
|
|
243
|
+
let existingValue = form?.[item.name] // 检查 form 对象中是否已有值
|
|
229
244
|
|
|
230
245
|
if (item.component === 'list') {
|
|
231
|
-
result[item.name] =
|
|
232
|
-
|
|
233
|
-
existingValue
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
246
|
+
result[item.name] =
|
|
247
|
+
item.value?.map((list, listIndex) => {
|
|
248
|
+
if (!existingValue) {
|
|
249
|
+
existingValue = []
|
|
250
|
+
} else {
|
|
251
|
+
existingValue = form?.[item.name][listIndex] || {}
|
|
252
|
+
}
|
|
253
|
+
return parse(list, existingValue)
|
|
254
|
+
}) || []
|
|
239
255
|
} else if (item.component === 'object') {
|
|
240
|
-
result[item.name] = parse(item.value, existingValue || {})
|
|
256
|
+
result[item.name] = parse(item.value, existingValue || {})
|
|
241
257
|
} else {
|
|
242
258
|
if (item.component === 'number') {
|
|
243
|
-
result[item.name] =
|
|
259
|
+
result[item.name] =
|
|
260
|
+
existingValue ?? (item.value !== undefined ? Number(item.value) : item.options?.min || 0)
|
|
244
261
|
} else {
|
|
245
|
-
result[item.name] = existingValue ?? item.value
|
|
246
|
-
|
|
262
|
+
result[item.name] = existingValue ?? item.value
|
|
247
263
|
}
|
|
248
264
|
}
|
|
249
|
-
})
|
|
265
|
+
})
|
|
250
266
|
|
|
251
|
-
return result
|
|
267
|
+
return result
|
|
252
268
|
}
|
|
253
269
|
|
|
254
|
-
let form = parse(config.formItems, this.modelValue)
|
|
270
|
+
let form = parse(config.formItems, this.modelValue)
|
|
255
271
|
form = {
|
|
256
272
|
...this.modelValue,
|
|
257
273
|
...form
|
|
258
274
|
}
|
|
259
275
|
this.form = this.parseNestedObject(form)
|
|
260
|
-
this.$emit(
|
|
276
|
+
this.$emit('update:modelValue', this.form)
|
|
261
277
|
},
|
|
262
278
|
|
|
263
279
|
parseNestedObject(obj) {
|
|
264
|
-
const result = {}
|
|
280
|
+
const result = {}
|
|
265
281
|
for (const [key, value] of Object.entries(obj)) {
|
|
266
|
-
const keys = key.split('.')
|
|
267
|
-
let current = result
|
|
282
|
+
const keys = key.split('.')
|
|
283
|
+
let current = result
|
|
268
284
|
|
|
269
285
|
keys.forEach((k, index) => {
|
|
270
286
|
if (!current[k]) {
|
|
271
|
-
current[k] = index === keys.length - 1 ? value : {}
|
|
287
|
+
current[k] = index === keys.length - 1 ? value : {}
|
|
272
288
|
}
|
|
273
|
-
current = current[k]
|
|
274
|
-
})
|
|
289
|
+
current = current[k]
|
|
290
|
+
})
|
|
275
291
|
|
|
276
292
|
delete obj[key]
|
|
277
|
-
|
|
278
293
|
}
|
|
279
|
-
return result
|
|
294
|
+
return result
|
|
280
295
|
},
|
|
281
296
|
|
|
282
297
|
//处理动态隐藏
|
|
@@ -284,10 +299,10 @@ export default {
|
|
|
284
299
|
if (typeof item?.hideHandle === 'string') {
|
|
285
300
|
try {
|
|
286
301
|
// 构造一个函数并执行,同时捕获潜在的异常
|
|
287
|
-
const func = new Function('form', `return ${item?.hideHandle.replace(/\$/g,
|
|
288
|
-
return func(this.form)
|
|
302
|
+
const func = new Function('form', `return ${item?.hideHandle.replace(/\$/g, 'form')}`)
|
|
303
|
+
return func(this.form)
|
|
289
304
|
} catch (error) {
|
|
290
|
-
return false
|
|
305
|
+
return false // 或根据需求返回默认值
|
|
291
306
|
}
|
|
292
307
|
} else if (typeof item?.hideHandle === 'boolean') {
|
|
293
308
|
return item.hideHandle
|
|
@@ -310,67 +325,67 @@ export default {
|
|
|
310
325
|
},
|
|
311
326
|
//提交
|
|
312
327
|
submit() {
|
|
313
|
-
this.$emit(
|
|
328
|
+
this.$emit('submit', this.form)
|
|
314
329
|
},
|
|
315
330
|
clickAffix(index) {
|
|
316
|
-
this.affixIndex = index
|
|
317
|
-
const targetElement = document.getElementById('divider-' + index)
|
|
318
|
-
const scrollContainer = document.querySelector('.el-container > .el-main')
|
|
331
|
+
this.affixIndex = index
|
|
332
|
+
const targetElement = document.getElementById('divider-' + index)
|
|
333
|
+
const scrollContainer = document.querySelector('.el-container > .el-main')
|
|
319
334
|
|
|
320
335
|
if (targetElement && scrollContainer) {
|
|
321
|
-
const offset = 85
|
|
322
|
-
const targetRect = targetElement.getBoundingClientRect()
|
|
323
|
-
const containerRect = scrollContainer.getBoundingClientRect()
|
|
336
|
+
const offset = 85 // 目标元素与顶部的偏移量
|
|
337
|
+
const targetRect = targetElement.getBoundingClientRect()
|
|
338
|
+
const containerRect = scrollContainer.getBoundingClientRect()
|
|
324
339
|
|
|
325
340
|
// 计算目标元素相对于滚动容器内部的真实偏移量
|
|
326
|
-
const elementPosition = targetRect.top - containerRect.top + scrollContainer.scrollTop
|
|
341
|
+
const elementPosition = targetRect.top - containerRect.top + scrollContainer.scrollTop
|
|
327
342
|
|
|
328
343
|
// 让 el-main 滚动到目标元素,保证它距离顶部 30px
|
|
329
344
|
scrollContainer.scrollTo({
|
|
330
345
|
top: elementPosition - offset,
|
|
331
346
|
behavior: 'smooth'
|
|
332
|
-
})
|
|
347
|
+
})
|
|
333
348
|
}
|
|
334
349
|
|
|
335
|
-
this.scrollObserverEnabled = false
|
|
350
|
+
this.scrollObserverEnabled = false
|
|
336
351
|
setTimeout(() => {
|
|
337
|
-
this.scrollObserverEnabled = true
|
|
338
|
-
}, 500)
|
|
352
|
+
this.scrollObserverEnabled = true
|
|
353
|
+
}, 500)
|
|
339
354
|
},
|
|
340
355
|
// 监听滚动
|
|
341
356
|
handleScroll() {
|
|
342
|
-
const titleNameDividers = document.querySelectorAll('.title-name-divider')
|
|
343
|
-
const elMain = document.querySelector('.el-main')
|
|
357
|
+
const titleNameDividers = document.querySelectorAll('.title-name-divider')
|
|
358
|
+
const elMain = document.querySelector('.el-main')
|
|
344
359
|
|
|
345
|
-
if (!elMain || titleNameDividers.length === 0) return
|
|
360
|
+
if (!elMain || titleNameDividers.length === 0) return
|
|
346
361
|
|
|
347
|
-
let _this = this
|
|
362
|
+
let _this = this
|
|
348
363
|
|
|
349
364
|
// 创建 IntersectionObserver 观察滚动元素
|
|
350
365
|
const observer = new IntersectionObserver(
|
|
351
|
-
|
|
352
|
-
entries.forEach(
|
|
366
|
+
entries => {
|
|
367
|
+
entries.forEach(entry => {
|
|
353
368
|
if (entry.isIntersecting && _this.scrollObserverEnabled) {
|
|
354
|
-
const dataIndex = entry.target.getAttribute('data-index')
|
|
355
|
-
_this.affixIndex = dataIndex
|
|
369
|
+
const dataIndex = entry.target.getAttribute('data-index')
|
|
370
|
+
_this.affixIndex = dataIndex // 更新 affixIndex
|
|
356
371
|
}
|
|
357
|
-
})
|
|
372
|
+
})
|
|
358
373
|
},
|
|
359
374
|
{
|
|
360
375
|
root: elMain, // 设置 el-main 为滚动容器
|
|
361
376
|
rootMargin: '30px 0px -70% 0px', // 确保元素在滚动到 30px 位置时触发
|
|
362
377
|
threshold: 0.1 // 交叉比例,确保元素部分可见时触发
|
|
363
378
|
}
|
|
364
|
-
)
|
|
379
|
+
)
|
|
365
380
|
|
|
366
381
|
// 观察每个 title-name-divider 元素
|
|
367
|
-
titleNameDividers.forEach(
|
|
382
|
+
titleNameDividers.forEach(divider => observer.observe(divider))
|
|
368
383
|
|
|
369
384
|
// 解绑旧的观察者(防止重复监听)
|
|
370
385
|
if (this.scrollObserver) {
|
|
371
|
-
this.scrollObserver.disconnect()
|
|
386
|
+
this.scrollObserver.disconnect()
|
|
372
387
|
}
|
|
373
|
-
this.scrollObserver = observer
|
|
388
|
+
this.scrollObserver = observer
|
|
374
389
|
}
|
|
375
390
|
}
|
|
376
391
|
}
|