xt-element-ui 2.0.4 → 2.1.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.
- package/docs/components/base/xt-card-item.md +1 -1
- package/docs/components/base/xt-list.md +459 -0
- package/docs/components/base/xt-table.md +120 -0
- package/docs/components/base/xt-upload.md +1 -1
- package/lib/index.common.js +808 -154
- package/lib/index.css +1 -1
- package/lib/index.umd.js +808 -154
- package/lib/index.umd.min.js +4 -4
- package/package.json +3 -3
- package/src/components/xt-badge/index.vue +19 -9
- package/src/components/xt-button/index.vue +3 -3
- package/src/components/xt-button/style/index.scss +5 -5
- package/src/components/xt-card/index.vue +4 -4
- package/src/components/xt-card/style/index.scss +11 -11
- package/src/components/xt-chart/XtLine.vue +2 -8
- package/src/components/xt-chart/theme/dark.js +35 -12
- package/src/components/xt-chart/theme/white.js +5 -0
- package/src/components/xt-chart/utils.js +28 -0
- package/src/components/xt-config-provider/index.vue +5 -1
- package/src/components/xt-list/index.js +8 -0
- package/src/components/xt-list/index.vue +886 -0
- package/src/components/xt-table/index copy.vue +663 -0
- package/src/components/xt-table/index.vue +120 -24
- package/src/index.js +3 -0
- package/src/components/xt-card-item/style/index copy.scss +0 -72
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
2
|
+
<div class="xt-table-wrapper">
|
|
3
3
|
<!-- 标题栏 / 工具栏 -->
|
|
4
|
-
<div class="
|
|
5
|
-
<span class="
|
|
6
|
-
<div class="
|
|
4
|
+
<div class="xt-table-header" v-if="title || $slots.toolbar">
|
|
5
|
+
<span class="xt-table-title" v-if="title">{{ title }}</span>
|
|
6
|
+
<div class="xt-table-toolbar">
|
|
7
7
|
<slot name="toolbar"></slot>
|
|
8
8
|
</div>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<!-- 主体表格:单 Table + 内置虚拟滚动(核心改造) -->
|
|
12
|
-
<div class="
|
|
12
|
+
<div class="xt-table-body">
|
|
13
13
|
<VirtualElTable
|
|
14
14
|
ref="table"
|
|
15
15
|
:data="processedTableData"
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
v-on="$listeners"
|
|
25
25
|
@selection-change="handleSelectionChange"
|
|
26
26
|
@sort-change="handleSortChange"
|
|
27
|
-
class="
|
|
27
|
+
class="xt-table"
|
|
28
28
|
>
|
|
29
29
|
<!-- 选择列 -->
|
|
30
30
|
<el-table-column
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
</div>
|
|
96
96
|
|
|
97
97
|
<!-- 分页 -->
|
|
98
|
-
<div class="
|
|
98
|
+
<div class="xt-table-footer" v-if="showPagination">
|
|
99
99
|
<el-pagination
|
|
100
100
|
:current-page="pagination.pageNum"
|
|
101
101
|
:page-size="pagination.pageSize"
|
|
@@ -122,6 +122,9 @@ export default {
|
|
|
122
122
|
tableData: { type: Array, default: () => [] },
|
|
123
123
|
columns: { type: Array, default: () => [] },
|
|
124
124
|
groupColumns: { type: Array, default: () => [] },
|
|
125
|
+
// 排序配置
|
|
126
|
+
sortGroup: { type: Boolean, default: false },
|
|
127
|
+
defaultSort: { type: Object, default: null },
|
|
125
128
|
title: { type: String, default: '' },
|
|
126
129
|
height: { type: [Number, String], default: null },
|
|
127
130
|
maxHeight: { type: [Number, String], default: null },
|
|
@@ -144,7 +147,10 @@ export default {
|
|
|
144
147
|
return {
|
|
145
148
|
spanCache: {},
|
|
146
149
|
flattenedColumnsCache: [],
|
|
147
|
-
selectedRows: []
|
|
150
|
+
selectedRows: [],
|
|
151
|
+
// 排序状态
|
|
152
|
+
sortProp: null,
|
|
153
|
+
sortOrder: null
|
|
148
154
|
}
|
|
149
155
|
},
|
|
150
156
|
|
|
@@ -159,10 +165,24 @@ export default {
|
|
|
159
165
|
return this.height ? undefined : this.maxHeight || undefined
|
|
160
166
|
},
|
|
161
167
|
|
|
168
|
+
// 排序后的数据
|
|
169
|
+
sortedTableData() {
|
|
170
|
+
if (!this.tableData.length) return []
|
|
171
|
+
if (!this.sortProp || !this.sortOrder) return [...this.tableData]
|
|
172
|
+
|
|
173
|
+
const order = this.sortOrder === 'ascending' ? 1 : -1
|
|
174
|
+
const sortFn = this.resolveSortMethod(this.sortProp)
|
|
175
|
+
|
|
176
|
+
if (this.sortGroup && this.groupColumns.length) {
|
|
177
|
+
return this.groupSort([...this.tableData], sortFn, order)
|
|
178
|
+
}
|
|
179
|
+
return [...this.tableData].sort((a, b) => sortFn(a, b) * order)
|
|
180
|
+
},
|
|
181
|
+
|
|
162
182
|
// 处理小计、总计后的最终数据
|
|
163
183
|
processedTableData() {
|
|
164
|
-
if (!this.
|
|
165
|
-
let data = [...this.
|
|
184
|
+
if (!this.sortedTableData.length) return []
|
|
185
|
+
let data = [...this.sortedTableData]
|
|
166
186
|
const hasSubtotal = this.subtotalConfig && this.subtotalConfig.enabled
|
|
167
187
|
const hasTotal = this.totalConfig && this.totalConfig.enabled
|
|
168
188
|
|
|
@@ -225,6 +245,25 @@ export default {
|
|
|
225
245
|
this.spanCache = {}
|
|
226
246
|
},
|
|
227
247
|
deep: true
|
|
248
|
+
},
|
|
249
|
+
defaultSort: {
|
|
250
|
+
handler(val) {
|
|
251
|
+
if (val && val.prop) {
|
|
252
|
+
this.sortProp = val.prop
|
|
253
|
+
this.sortOrder = val.order || 'ascending'
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
immediate: false
|
|
257
|
+
},
|
|
258
|
+
sortProp() {
|
|
259
|
+
this.spanCache = {}
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
created() {
|
|
264
|
+
if (this.defaultSort && this.defaultSort.prop) {
|
|
265
|
+
this.sortProp = this.defaultSort.prop
|
|
266
|
+
this.sortOrder = this.defaultSort.order || 'ascending'
|
|
228
267
|
}
|
|
229
268
|
},
|
|
230
269
|
|
|
@@ -239,6 +278,52 @@ export default {
|
|
|
239
278
|
},
|
|
240
279
|
|
|
241
280
|
methods: {
|
|
281
|
+
// ========== 排序逻辑 ==========
|
|
282
|
+
resolveSortMethod(prop) {
|
|
283
|
+
const col = this.findColumnByProp(prop)
|
|
284
|
+
if (col && typeof col.sortMethod === 'function') {
|
|
285
|
+
return col.sortMethod
|
|
286
|
+
}
|
|
287
|
+
return (a, b) => {
|
|
288
|
+
const va = a[prop]
|
|
289
|
+
const vb = b[prop]
|
|
290
|
+
if (va == null && vb == null) return 0
|
|
291
|
+
if (va == null) return -1
|
|
292
|
+
if (vb == null) return 1
|
|
293
|
+
if (typeof va === 'number' && typeof vb === 'number') return va - vb
|
|
294
|
+
return String(va).localeCompare(String(vb), undefined, { numeric: true })
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
findColumnByProp(prop) {
|
|
299
|
+
for (const col of this.columns) {
|
|
300
|
+
if (col.children && col.children.length) {
|
|
301
|
+
for (const child of col.children) {
|
|
302
|
+
if (child.prop === prop) return child
|
|
303
|
+
}
|
|
304
|
+
} else if (col.prop === prop) {
|
|
305
|
+
return col
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return null
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
groupSort(data, sortFn, order) {
|
|
312
|
+
const groups = {}
|
|
313
|
+
data.forEach(row => {
|
|
314
|
+
const key = this.groupColumns.map(f => row[f] == null ? '' : String(row[f])).join('|||')
|
|
315
|
+
if (!groups[key]) groups[key] = []
|
|
316
|
+
groups[key].push(row)
|
|
317
|
+
})
|
|
318
|
+
const result = []
|
|
319
|
+
Object.keys(groups).sort().forEach(key => {
|
|
320
|
+
const groupRows = groups[key]
|
|
321
|
+
groupRows.sort((a, b) => sortFn(a, b) * order)
|
|
322
|
+
result.push(...groupRows)
|
|
323
|
+
})
|
|
324
|
+
return result
|
|
325
|
+
},
|
|
326
|
+
|
|
242
327
|
handleResize() {
|
|
243
328
|
this.$nextTick(() => {
|
|
244
329
|
this.$refs.table && this.$refs.table.doLayout()
|
|
@@ -326,14 +411,14 @@ export default {
|
|
|
326
411
|
},
|
|
327
412
|
|
|
328
413
|
getRowClassName({ row }) {
|
|
329
|
-
if (row._rowType === 'subtotal') return '
|
|
330
|
-
if (row._rowType === 'total') return '
|
|
414
|
+
if (row._rowType === 'subtotal') return 'xt-table-row-subtotal'
|
|
415
|
+
if (row._rowType === 'total') return 'xt-table-row-total'
|
|
331
416
|
return ''
|
|
332
417
|
},
|
|
333
418
|
|
|
334
419
|
// ========== 列处理 ==========
|
|
335
420
|
getColumnProps(col) {
|
|
336
|
-
const { _key, children, render, formatter, slot, ...props } = col
|
|
421
|
+
const { _key, children, render, formatter, slot, sortMethod, ...props } = col
|
|
337
422
|
return props
|
|
338
423
|
},
|
|
339
424
|
|
|
@@ -399,6 +484,8 @@ export default {
|
|
|
399
484
|
this.$emit('selection-change', this.selectedRows)
|
|
400
485
|
},
|
|
401
486
|
handleSortChange(info) {
|
|
487
|
+
this.sortProp = info.prop
|
|
488
|
+
this.sortOrder = info.order
|
|
402
489
|
this.$emit('sort-change', info)
|
|
403
490
|
},
|
|
404
491
|
handleSizeChange(size) {
|
|
@@ -416,6 +503,15 @@ export default {
|
|
|
416
503
|
this.$refs.table && this.$refs.table.clearSelection()
|
|
417
504
|
this.selectedRows = []
|
|
418
505
|
},
|
|
506
|
+
clearSort() {
|
|
507
|
+
this.sortProp = null
|
|
508
|
+
this.sortOrder = null
|
|
509
|
+
this.$nextTick(() => {
|
|
510
|
+
if (this.$refs.table && this.$refs.table.$refs.innerTable) {
|
|
511
|
+
this.$refs.table.$refs.innerTable.clearSort()
|
|
512
|
+
}
|
|
513
|
+
})
|
|
514
|
+
},
|
|
419
515
|
toggleRowSelection(row, selected) {
|
|
420
516
|
this.$refs.table && this.$refs.table.toggleRowSelection(row, selected)
|
|
421
517
|
},
|
|
@@ -432,26 +528,26 @@ export default {
|
|
|
432
528
|
}
|
|
433
529
|
</script>
|
|
434
530
|
<style scoped>
|
|
435
|
-
.
|
|
531
|
+
.xt-table-wrapper {
|
|
436
532
|
width: 100%;
|
|
437
533
|
}
|
|
438
534
|
|
|
439
535
|
/* 表头栏 */
|
|
440
|
-
.
|
|
536
|
+
.xt-table-header {
|
|
441
537
|
display: flex;
|
|
442
538
|
align-items: center;
|
|
443
539
|
justify-content: space-between;
|
|
444
540
|
padding: 12px 0;
|
|
445
541
|
margin-bottom: 8px;
|
|
446
542
|
}
|
|
447
|
-
.
|
|
543
|
+
.xt-table-title {
|
|
448
544
|
font-size: 16px;
|
|
449
545
|
font-weight: 600;
|
|
450
546
|
color: #303133;
|
|
451
547
|
position: relative;
|
|
452
548
|
padding-left: 12px;
|
|
453
549
|
}
|
|
454
|
-
.
|
|
550
|
+
.xt-table-title::before {
|
|
455
551
|
content: '';
|
|
456
552
|
position: absolute;
|
|
457
553
|
left: 0;
|
|
@@ -462,40 +558,40 @@ export default {
|
|
|
462
558
|
background: #409eff;
|
|
463
559
|
border-radius: 2px;
|
|
464
560
|
}
|
|
465
|
-
.
|
|
561
|
+
.xt-table-toolbar {
|
|
466
562
|
display: flex;
|
|
467
563
|
align-items: center;
|
|
468
564
|
gap: 8px;
|
|
469
565
|
}
|
|
470
566
|
|
|
471
|
-
.
|
|
567
|
+
.xt-table-body {
|
|
472
568
|
position: relative;
|
|
473
569
|
z-index: 1;
|
|
474
570
|
}
|
|
475
571
|
|
|
476
572
|
/* 分页区域 */
|
|
477
|
-
.
|
|
573
|
+
.xt-table-footer {
|
|
478
574
|
display: flex;
|
|
479
575
|
justify-content: flex-end;
|
|
480
576
|
padding: 16px 0;
|
|
481
577
|
}
|
|
482
578
|
|
|
483
579
|
/* ========== 小计/合计行样式 ========== */
|
|
484
|
-
::v-deep .
|
|
580
|
+
::v-deep .xt-table-row-subtotal {
|
|
485
581
|
background-color: #f5f7fa;
|
|
486
582
|
font-weight: 600;
|
|
487
583
|
color: #303133;
|
|
488
584
|
}
|
|
489
|
-
::v-deep .
|
|
585
|
+
::v-deep .xt-table-row-total {
|
|
490
586
|
background-color: #e8eaed;
|
|
491
587
|
font-weight: 700;
|
|
492
588
|
color: #303133;
|
|
493
589
|
border-top: 2px solid #c0c4cc;
|
|
494
590
|
}
|
|
495
|
-
::v-deep .
|
|
591
|
+
::v-deep .xt-table-row-subtotal:hover > td {
|
|
496
592
|
background-color: #ebeef5 !important;
|
|
497
593
|
}
|
|
498
|
-
::v-deep .
|
|
594
|
+
::v-deep .xt-table-row-total:hover > td {
|
|
499
595
|
background-color: #dcdfe6 !important;
|
|
500
596
|
}
|
|
501
597
|
|
package/src/index.js
CHANGED
|
@@ -37,6 +37,7 @@ import XtDatePicker from './components/xt-date-picker'
|
|
|
37
37
|
import XtChart from './components/xt-chart' // XtChart 组件(基于 ECharts 封装)
|
|
38
38
|
import XtIcon from './components/xt-icon' // XtIcon 组件(支持 el-icon / svg / 自定义字体)
|
|
39
39
|
import XtTable from './components/xt-table' // XtTable 组件(基于 ElementUI Table 封装)
|
|
40
|
+
import XtList from './components/xt-list' // XtList 组件(卡片列表)
|
|
40
41
|
import XtScrollArrow from './components/xt-scroll-arrow'
|
|
41
42
|
import XtBar from './components/xt-chart/XtBar.vue'
|
|
42
43
|
import XtLine from './components/xt-chart/XtLine.vue'
|
|
@@ -69,6 +70,7 @@ const components = [
|
|
|
69
70
|
XtChart,
|
|
70
71
|
XtIcon,
|
|
71
72
|
XtTable,
|
|
73
|
+
XtList,
|
|
72
74
|
XtScrollArrow,
|
|
73
75
|
XtBar,
|
|
74
76
|
XtLine,
|
|
@@ -146,6 +148,7 @@ export default {
|
|
|
146
148
|
XtDatePicker,
|
|
147
149
|
XtIcon,
|
|
148
150
|
XtTable,
|
|
151
|
+
XtList,
|
|
149
152
|
XtScrollArrow,
|
|
150
153
|
XtBar,
|
|
151
154
|
XtLine,
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
@import '../../../styles/variables.scss';
|
|
2
|
-
|
|
3
|
-
.xt-card-item {
|
|
4
|
-
--xt-card-item-color: var(--xt-color-primary, #1890ff);
|
|
5
|
-
|
|
6
|
-
min-height: var(--xt-card-item-min-height, 40px);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.xt-card-item + .xt-card-item {
|
|
10
|
-
margin-top: var(--xt-card-item-gap, 10px);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.xt-card-item.is-border {
|
|
14
|
-
border-right: var(--xt-card-item-border-width, 3px) solid transparent;
|
|
15
|
-
background-color: var(--xt-color-bg-secondary, #f5f7fa);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.xt-card-item.is-border.is-primary {
|
|
19
|
-
border-right-color: var(--xt-card-item-color);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.xt-card-item.is-border.is-primary .item__value .value {
|
|
23
|
-
color: var(--xt-card-item-color);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.xt-card-item.is-border.is-success {
|
|
27
|
-
border-right-color: var(--xt-color-success, #67C23A);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.xt-card-item.is-border.is-success .item__value .value {
|
|
31
|
-
color: var(--xt-color-success, #67C23A);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.xt-card-item.is-border.is-warning {
|
|
35
|
-
border-right-color: var(--xt-color-warning, #E6A23C);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.xt-card-item.is-border.is-warning .item__value .value {
|
|
39
|
-
color: var(--xt-color-warning, #E6A23C);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.xt-card-item.is-border.is-danger {
|
|
43
|
-
border-right-color: var(--xt-color-danger, #F56C6C);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.xt-card-item.is-border.is-danger .item__value .value {
|
|
47
|
-
color: var(--xt-color-danger, #F56C6C);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.xt-card-item .item__value {
|
|
51
|
-
padding-right: 10px;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.xt-card-item .item__value .value {
|
|
55
|
-
font-weight: 600;
|
|
56
|
-
font-size: var(--xt-font-size-base, 14px);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.xt-card-item .item__value .unit {
|
|
60
|
-
font-size: var(--xt-font-size-small, 13px);
|
|
61
|
-
color: var(--xt-color-text-secondary, #909399);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.xt-card-item .item__label {
|
|
65
|
-
padding-left: 10px;
|
|
66
|
-
color: var(--xt-color-text-secondary, #909399);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.xt-card-item .item__unit {
|
|
70
|
-
padding-left: 5px;
|
|
71
|
-
color: var(--xt-color-text-secondary, #909399);
|
|
72
|
-
}
|