xt-element-ui 2.1.4 → 2.1.6

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.
Files changed (33) hide show
  1. package/docs/components/base/xt-date-picker.md +127 -37
  2. package/docs/components/base/xt-form-schema.md +358 -0
  3. package/docs/components/base/xt-grid-box.md +4 -4
  4. package/docs/components/base/xt-input.md +204 -42
  5. package/docs/components/base/xt-list.md +458 -458
  6. package/docs/components/base/xt-text.md +1 -0
  7. package/docs/components/base/xt-transfer-tree.md +272 -0
  8. package/docs/components/utils/config.md +285 -0
  9. package/docs/components/utils/format.md +445 -0
  10. package/lib/index.common.js +93128 -112769
  11. package/lib/index.css +1 -1
  12. package/lib/index.umd.js +93128 -112769
  13. package/lib/index.umd.min.js +1 -34
  14. package/package.json +4 -2
  15. package/src/components/xt-date-picker/component/Picker.vue +196 -0
  16. package/src/components/xt-date-picker/component/RangeDate.vue +136 -0
  17. package/src/components/xt-date-picker/index.vue +164 -144
  18. package/src/components/xt-flex-box/index.vue +1 -1
  19. package/src/components/xt-form-schema/index.js +8 -0
  20. package/src/components/xt-form-schema/index.vue +328 -0
  21. package/src/components/xt-grid-item/index.vue +2 -2
  22. package/src/components/xt-input/index.vue +224 -28
  23. package/src/components/xt-input/style/index.scss +10 -0
  24. package/src/components/xt-list/index.js +7 -7
  25. package/src/components/xt-list/index.vue +885 -885
  26. package/src/components/xt-text/index.vue +16 -4
  27. package/src/components/xt-transfer-tree/index.js +8 -0
  28. package/src/components/xt-transfer-tree/index.vue +494 -0
  29. package/src/index.js +8 -2
  30. package/src/utils/index.js +278 -1
  31. package/src/components/xt-date-picker/SearchDate.vue +0 -45
  32. package/src/components/xt-date-picker/quarter.vue +0 -154
  33. package/src/components/xt-table/index copy.vue +0 -663
@@ -20,11 +20,17 @@
20
20
  :style="customStyle"
21
21
  @mouseenter="handleMouseEnter"
22
22
  >
23
- <slot name="prefix">{{ prefix }}</slot>
23
+ <template v-if="$slots.prefix">
24
+ <slot name="prefix"></slot>
25
+ </template>
26
+ <template v-else-if="prefix">{{ prefix }}</template>
24
27
  <slot>
25
28
  <template v-if="formattedValue !== undefined">{{ formattedValue }}</template>
26
29
  </slot>
27
- <slot name="suffix">{{ suffix }}</slot>
30
+ <template v-if="$slots.suffix">
31
+ <slot name="suffix"></slot>
32
+ </template>
33
+ <template v-else-if="suffix">{{ suffix }}</template>
28
34
  </span>
29
35
  </el-tooltip>
30
36
  <span
@@ -41,11 +47,17 @@
41
47
  ]"
42
48
  :style="customStyle"
43
49
  >
44
- <slot name="prefix">{{ prefix }}</slot>
50
+ <template v-if="$slots.prefix">
51
+ <slot name="prefix"></slot>
52
+ </template>
53
+ <template v-else-if="prefix">{{ prefix }}</template>
45
54
  <slot>
46
55
  <template v-if="formattedValue !== undefined">{{ formattedValue }}</template>
47
56
  </slot>
48
- <slot name="suffix">{{ suffix }}</slot>
57
+ <template v-if="$slots.suffix">
58
+ <slot name="suffix"></slot>
59
+ </template>
60
+ <template v-else-if="suffix">{{ suffix }}</template>
49
61
  </span>
50
62
  </template>
51
63
 
@@ -0,0 +1,8 @@
1
+ import XtTransferTree from './index.vue'
2
+
3
+ XtTransferTree.install = function (Vue) {
4
+ Vue.component(XtTransferTree.name, XtTransferTree)
5
+ }
6
+
7
+ export default XtTransferTree
8
+ export { XtTransferTree }
@@ -0,0 +1,494 @@
1
+ <template>
2
+ <div class="xt-transfer-tree">
3
+ <div class="xt-transfer-tree__panel xt-transfer-tree__source">
4
+ <div class="xt-transfer-tree__header">
5
+ <span class="xt-transfer-tree__title">{{ leftTitle }}</span>
6
+ <span class="xt-transfer-tree__count">{{ leftCheckedCount }}/{{ leftTotalCount }}</span>
7
+ </div>
8
+ <div class="xt-transfer-tree__search" v-if="filterable">
9
+ <el-input
10
+ v-model="leftFilterText"
11
+ placeholder="搜索"
12
+ prefix-icon="el-icon-search"
13
+ size="small"
14
+ />
15
+ </div>
16
+ <div class="xt-transfer-tree__body">
17
+ <el-tree
18
+ ref="leftTree"
19
+ :data="sourceData"
20
+ :props="treeProps"
21
+ :default-expand-all="defaultExpandAll"
22
+ :filter-node-method="filterLeftNode"
23
+ :show-checkbox="showCheckbox"
24
+ :check-strictly="!cascade"
25
+ :default-checked-keys="leftCheckedKeys"
26
+ @check-change="handleLeftCheckChange"
27
+ @node-click="handleLeftNodeClick"
28
+ >
29
+ <span class="xt-transfer-tree__node" slot-scope="{ node, data }">
30
+ <span>{{ node.label }}</span>
31
+ <span v-if="data.children && data.children.length" class="xt-transfer-tree__node-count">
32
+ ({{ data.children.length }})
33
+ </span>
34
+ </span>
35
+ </el-tree>
36
+ </div>
37
+ </div>
38
+
39
+ <div class="xt-transfer-tree__buttons">
40
+ <el-button
41
+ type="primary"
42
+ :disabled="!leftCheckedCount"
43
+ @click="transferToRight"
44
+ :size="buttonSize"
45
+ >
46
+ <i class="el-icon-arrow-right"></i>
47
+ </el-button>
48
+ <el-button
49
+ type="primary"
50
+ :disabled="!rightCheckedCount"
51
+ @click="transferToLeft"
52
+ :size="buttonSize"
53
+ >
54
+ <i class="el-icon-arrow-left"></i>
55
+ </el-button>
56
+ </div>
57
+
58
+ <div class="xt-transfer-tree__panel xt-transfer-tree__target">
59
+ <div class="xt-transfer-tree__header">
60
+ <span class="xt-transfer-tree__title">{{ rightTitle }}</span>
61
+ <span class="xt-transfer-tree__count">{{ rightCheckedCount }}/{{ rightTotalCount }}</span>
62
+ </div>
63
+ <div class="xt-transfer-tree__search" v-if="filterable">
64
+ <el-input
65
+ v-model="rightFilterText"
66
+ placeholder="搜索"
67
+ prefix-icon="el-icon-search"
68
+ size="small"
69
+ />
70
+ </div>
71
+ <div class="xt-transfer-tree__body">
72
+ <el-tree
73
+ ref="rightTree"
74
+ :data="targetData"
75
+ :props="treeProps"
76
+ :default-expand-all="defaultExpandAll"
77
+ :filter-node-method="filterRightNode"
78
+ :show-checkbox="showCheckbox"
79
+ :check-strictly="!cascade"
80
+ :default-checked-keys="rightCheckedKeys"
81
+ @check-change="handleRightCheckChange"
82
+ @node-click="handleRightNodeClick"
83
+ >
84
+ <span class="xt-transfer-tree__node" slot-scope="{ node, data }">
85
+ <span>{{ node.label }}</span>
86
+ <span v-if="data.children && data.children.length" class="xt-transfer-tree__node-count">
87
+ ({{ data.children.length }})
88
+ </span>
89
+ </span>
90
+ </el-tree>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </template>
95
+
96
+ <script>
97
+ export default {
98
+ name: 'XtTransferTree',
99
+
100
+ props: {
101
+ data: {
102
+ type: Array,
103
+ default: () => []
104
+ },
105
+ value: {
106
+ type: Array,
107
+ default: () => []
108
+ },
109
+ leftTitle: {
110
+ type: String,
111
+ default: '待选择'
112
+ },
113
+ rightTitle: {
114
+ type: String,
115
+ default: '已选择'
116
+ },
117
+ treeProps: {
118
+ type: Object,
119
+ default: () => ({
120
+ label: 'label',
121
+ children: 'children',
122
+ value: 'id'
123
+ })
124
+ },
125
+ defaultExpandAll: {
126
+ type: Boolean,
127
+ default: true
128
+ },
129
+ filterable: {
130
+ type: Boolean,
131
+ default: false
132
+ },
133
+ showCheckbox: {
134
+ type: Boolean,
135
+ default: true
136
+ },
137
+ cascade: {
138
+ type: Boolean,
139
+ default: true
140
+ },
141
+ transferMode: {
142
+ type: String,
143
+ default: 'single',
144
+ validator: (val) => ['single', 'multiple', 'parent-child'].includes(val)
145
+ },
146
+ buttonSize: {
147
+ type: String,
148
+ default: 'small'
149
+ }
150
+ },
151
+
152
+ data() {
153
+ return {
154
+ leftFilterText: '',
155
+ rightFilterText: '',
156
+ leftCheckedKeys: [],
157
+ rightCheckedKeys: []
158
+ }
159
+ },
160
+
161
+ computed: {
162
+ sourceData() {
163
+ const valueSet = new Set(this.value)
164
+ return this.filterTreeData(this.data, valueSet, true)
165
+ },
166
+
167
+ targetData() {
168
+ const valueSet = new Set(this.value)
169
+ return this.filterTreeData(this.data, valueSet, false)
170
+ },
171
+
172
+ leftTotalCount() {
173
+ return this.countTreeNodes(this.sourceData)
174
+ },
175
+
176
+ rightTotalCount() {
177
+ return this.countTreeNodes(this.targetData)
178
+ },
179
+
180
+ leftCheckedCount() {
181
+ return this.leftCheckedKeys.length
182
+ },
183
+
184
+ rightCheckedCount() {
185
+ return this.rightCheckedKeys.length
186
+ }
187
+ },
188
+
189
+ watch: {
190
+ leftFilterText(val) {
191
+ this.$refs.leftTree && this.$refs.leftTree.filter(val)
192
+ },
193
+ rightFilterText(val) {
194
+ this.$refs.rightTree && this.$refs.rightTree.filter(val)
195
+ }
196
+ },
197
+
198
+ methods: {
199
+ filterTreeData(data, valueSet, exclude) {
200
+ return data
201
+ .map(node => {
202
+ const isTarget = valueSet.has(node[this.treeProps.value])
203
+ if (exclude && isTarget) return null
204
+ if (!exclude && !isTarget) return null
205
+
206
+ const result = { ...node }
207
+ if (node.children && node.children.length) {
208
+ const filteredChildren = this.filterTreeData(node.children, valueSet, exclude)
209
+ if (filteredChildren.length) {
210
+ result.children = filteredChildren
211
+ } else {
212
+ delete result.children
213
+ }
214
+ }
215
+ return result
216
+ })
217
+ .filter(Boolean)
218
+ },
219
+
220
+ countTreeNodes(data) {
221
+ let count = 0
222
+ data.forEach(node => {
223
+ count++
224
+ if (node.children) {
225
+ count += this.countTreeNodes(node.children)
226
+ }
227
+ })
228
+ return count
229
+ },
230
+
231
+ getAllKeys(node, keys = []) {
232
+ keys.push(node[this.treeProps.value])
233
+ if (node.children) {
234
+ node.children.forEach(child => this.getAllKeys(child, keys))
235
+ }
236
+ return keys
237
+ },
238
+
239
+ getParentKeys(data, key, parentKeys = []) {
240
+ for (const node of data) {
241
+ if (node[this.treeProps.value] === key) {
242
+ return parentKeys
243
+ }
244
+ if (node.children) {
245
+ const result = this.getParentKeys(node.children, key, [...parentKeys, node[this.treeProps.value]])
246
+ if (result.length > 0) return result
247
+ }
248
+ }
249
+ return []
250
+ },
251
+
252
+ filterLeftNode(value, data) {
253
+ if (!value) return true
254
+ return String(data[this.treeProps.label]).toLowerCase().indexOf(value.toLowerCase()) !== -1
255
+ },
256
+
257
+ filterRightNode(value, data) {
258
+ if (!value) return true
259
+ return String(data[this.treeProps.label]).toLowerCase().indexOf(value.toLowerCase()) !== -1
260
+ },
261
+
262
+ handleLeftCheckChange(data, checked) {
263
+ const key = data[this.treeProps.value]
264
+ if (checked) {
265
+ if (!this.leftCheckedKeys.includes(key)) {
266
+ this.leftCheckedKeys.push(key)
267
+ }
268
+ if (this.cascade && data.children) {
269
+ data.children.forEach(child => {
270
+ const childKey = child[this.treeProps.value]
271
+ if (!this.leftCheckedKeys.includes(childKey)) {
272
+ this.leftCheckedKeys.push(childKey)
273
+ }
274
+ })
275
+ }
276
+ } else {
277
+ this.leftCheckedKeys = this.leftCheckedKeys.filter(k => k !== key)
278
+ if (this.cascade && data.children) {
279
+ data.children.forEach(child => {
280
+ this.leftCheckedKeys = this.leftCheckedKeys.filter(k => k !== child[this.treeProps.value])
281
+ })
282
+ }
283
+ }
284
+ },
285
+
286
+ handleRightCheckChange(data, checked) {
287
+ const key = data[this.treeProps.value]
288
+ if (checked) {
289
+ if (!this.rightCheckedKeys.includes(key)) {
290
+ this.rightCheckedKeys.push(key)
291
+ }
292
+ if (this.cascade && data.children) {
293
+ data.children.forEach(child => {
294
+ const childKey = child[this.treeProps.value]
295
+ if (!this.rightCheckedKeys.includes(childKey)) {
296
+ this.rightCheckedKeys.push(childKey)
297
+ }
298
+ })
299
+ }
300
+ } else {
301
+ this.rightCheckedKeys = this.rightCheckedKeys.filter(k => k !== key)
302
+ if (this.cascade && data.children) {
303
+ data.children.forEach(child => {
304
+ this.rightCheckedKeys = this.rightCheckedKeys.filter(k => k !== child[this.treeProps.value])
305
+ })
306
+ }
307
+ }
308
+ },
309
+
310
+ handleLeftNodeClick(data) {
311
+ if (!this.showCheckbox) {
312
+ const key = data[this.treeProps.value]
313
+ const keysToTransfer = this.getTransferKeys(data)
314
+ this.transferKeys(keysToTransfer, true)
315
+ }
316
+ },
317
+
318
+ handleRightNodeClick(data) {
319
+ if (!this.showCheckbox) {
320
+ const key = data[this.treeProps.value]
321
+ const keysToTransfer = this.getTransferKeys(data)
322
+ this.transferKeys(keysToTransfer, false)
323
+ }
324
+ },
325
+
326
+ getTransferKeys(data) {
327
+ const key = data[this.treeProps.value]
328
+ switch (this.transferMode) {
329
+ case 'parent-child':
330
+ return this.getAllKeys(data)
331
+ case 'multiple':
332
+ return [key]
333
+ default:
334
+ return [key]
335
+ }
336
+ },
337
+
338
+ transferToRight() {
339
+ const keys = [...this.leftCheckedKeys]
340
+ this.transferKeys(keys, true)
341
+ this.leftCheckedKeys = []
342
+ },
343
+
344
+ transferToLeft() {
345
+ const keys = [...this.rightCheckedKeys]
346
+ this.transferKeys(keys, false)
347
+ this.rightCheckedKeys = []
348
+ },
349
+
350
+ transferKeys(keys, toRight) {
351
+ const currentValue = [...this.value]
352
+ const newKeys = new Set(currentValue)
353
+
354
+ if (toRight) {
355
+ keys.forEach(k => newKeys.add(k))
356
+ if (this.cascade) {
357
+ keys.forEach(k => {
358
+ const parentKeys = this.getParentKeys(this.data, k)
359
+ parentKeys.forEach(pk => newKeys.add(pk))
360
+ })
361
+ }
362
+ } else {
363
+ keys.forEach(k => newKeys.delete(k))
364
+ if (this.cascade) {
365
+ keys.forEach(k => {
366
+ const allChildKeys = []
367
+ this.findAllChildKeys(this.data, k, allChildKeys)
368
+ allChildKeys.forEach(ck => newKeys.delete(ck))
369
+ })
370
+ }
371
+ }
372
+
373
+ const newValue = Array.from(newKeys)
374
+ this.$emit('update:value', newValue)
375
+ this.$emit('change', {
376
+ value: newValue,
377
+ addedKeys: toRight ? keys : [],
378
+ removedKeys: toRight ? [] : keys
379
+ })
380
+ },
381
+
382
+ findAllChildKeys(data, parentKey, childKeys) {
383
+ for (const node of data) {
384
+ if (node[this.treeProps.value] === parentKey && node.children) {
385
+ node.children.forEach(child => {
386
+ childKeys.push(child[this.treeProps.value])
387
+ if (child.children) {
388
+ this.findAllChildKeys([child], child[this.treeProps.value], childKeys)
389
+ }
390
+ })
391
+ }
392
+ if (node.children) {
393
+ this.findAllChildKeys(node.children, parentKey, childKeys)
394
+ }
395
+ }
396
+ },
397
+
398
+ clearSelection() {
399
+ this.leftCheckedKeys = []
400
+ this.rightCheckedKeys = []
401
+ }
402
+ }
403
+ }
404
+ </script>
405
+
406
+ <style lang="scss" scoped>
407
+ .xt-transfer-tree {
408
+ display: flex;
409
+ align-items: stretch;
410
+ width: 100%;
411
+ height: 100%;
412
+ }
413
+
414
+ .xt-transfer-tree__panel {
415
+ flex: 1;
416
+ display: flex;
417
+ flex-direction: column;
418
+ border: 1px solid #ebeef5;
419
+ border-radius: 4px;
420
+ overflow: hidden;
421
+ }
422
+
423
+ .xt-transfer-tree__source {
424
+ margin-right: 8px;
425
+ }
426
+
427
+ .xt-transfer-tree__target {
428
+ margin-left: 8px;
429
+ }
430
+
431
+ .xt-transfer-tree__header {
432
+ display: flex;
433
+ align-items: center;
434
+ justify-content: space-between;
435
+ padding: 12px;
436
+ background: #f5f7fa;
437
+ border-bottom: 1px solid #ebeef5;
438
+ }
439
+
440
+ .xt-transfer-tree__title {
441
+ font-size: 14px;
442
+ font-weight: 600;
443
+ color: #303133;
444
+ }
445
+
446
+ .xt-transfer-tree__count {
447
+ font-size: 12px;
448
+ color: #909399;
449
+ }
450
+
451
+ .xt-transfer-tree__search {
452
+ padding: 8px 12px;
453
+ border-bottom: 1px solid #ebeef5;
454
+ }
455
+
456
+ .xt-transfer-tree__body {
457
+ flex: 1;
458
+ overflow-y: auto;
459
+ padding: 8px;
460
+ }
461
+
462
+ .xt-transfer-tree__buttons {
463
+ display: flex;
464
+ flex-direction: column;
465
+ justify-content: center;
466
+ align-items: center;
467
+ padding: 8px;
468
+ gap: 8px;
469
+ }
470
+
471
+ .xt-transfer-tree__node {
472
+ display: flex;
473
+ align-items: center;
474
+ gap: 4px;
475
+ }
476
+
477
+ .xt-transfer-tree__node-count {
478
+ font-size: 12px;
479
+ color: #909399;
480
+ }
481
+
482
+ .xt-transfer-tree__body::-webkit-scrollbar {
483
+ width: 6px;
484
+ }
485
+
486
+ .xt-transfer-tree__body::-webkit-scrollbar-thumb {
487
+ background: #c1c1c1;
488
+ border-radius: 3px;
489
+ }
490
+
491
+ .xt-transfer-tree__body::-webkit-scrollbar-track {
492
+ background: transparent;
493
+ }
494
+ </style>
package/src/index.js CHANGED
@@ -46,6 +46,8 @@ import XtMulti from './components/xt-chart/XtMulti.vue'
46
46
  import XtPage from './components/xt-page'
47
47
  import XtSelectTree from './components/xt-select-tree'
48
48
  import XtUpload from './components/xt-upload'
49
+ import XtTransferTree from './components/xt-transfer-tree' // XtTransferTree 组件(树形穿梭框)
50
+ import XtFormSchema from './components/xt-form-schema' // XtFormSchema 组件(表单配置化搜索)
49
51
 
50
52
 
51
53
  const components = [
@@ -78,7 +80,9 @@ const components = [
78
80
  XtMulti,
79
81
  XtPage,
80
82
  XtSelectTree,
81
- XtUpload
83
+ XtUpload,
84
+ XtTransferTree,
85
+ XtFormSchema
82
86
  ]
83
87
 
84
88
  const install = function (Vue, options = {}) {
@@ -156,7 +160,9 @@ export default {
156
160
  XtMulti,
157
161
  XtPage,
158
162
  XtSelectTree,
159
- XtUpload
163
+ XtUpload,
164
+ XtTransferTree,
165
+ XtFormSchema
160
166
  }
161
167
 
162
168
  // XtChart 组件按需导出(使用时需自行安装 echarts 依赖)