xt-element-ui 1.2.0 → 1.2.2
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/README.md +1 -0
- package/lib/index.common.js +210 -341
- package/lib/index.css +1 -1
- package/lib/index.umd.js +215 -346
- package/lib/index.umd.min.js +5 -5
- package/package.json +4 -7
- package/src/components/ex-button/index.vue +7 -1
- package/src/components/ex-button/style/index.scss +32 -2
- package/src/components/ex-card/index.vue +0 -82
- package/src/components/ex-card/style/index.scss +7 -3
- package/src/components/ex-table/index.vue +110 -276
- package/src/components/ex-table/virtualScrollData.js +35 -0
- package/src/components/xt-config-provider/index.vue +10 -10
- package/src/components/xt-text/style/index.scss +4 -4
- package/src/index.js +13 -9
- package/src/styles/css-variables.scss +0 -1
- package/src/styles/element-theme.scss +11 -3
|
@@ -8,32 +8,40 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
|
-
<!--
|
|
11
|
+
<!-- 虚拟滚动固定表头:复用 el-table 列布局,与 body 表头对齐 -->
|
|
12
12
|
<div
|
|
13
|
-
v-if="virtualScroll &&
|
|
13
|
+
v-if="virtualScroll && computedHeight"
|
|
14
14
|
ref="fixedHeader"
|
|
15
15
|
class="ex-table-fixed-header"
|
|
16
|
-
:style="{ marginLeft: -scrollLeft + 'px' }"
|
|
17
16
|
>
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
<el-table
|
|
18
|
+
ref="headerTable"
|
|
19
|
+
:data="headerTableData"
|
|
20
|
+
class="ex-table ex-table-header-only"
|
|
21
|
+
>
|
|
22
|
+
<el-table-column v-if="selection" type="selection" width="55" :fixed="selectionFixed" />
|
|
23
|
+
<el-table-column
|
|
24
|
+
v-if="showIndex"
|
|
25
|
+
type="index"
|
|
26
|
+
width="60"
|
|
27
|
+
label="#"
|
|
28
|
+
:fixed="indexFixed"
|
|
29
|
+
/>
|
|
30
|
+
<template v-for="col in flattenedColumns">
|
|
31
|
+
<el-table-column
|
|
32
|
+
v-if="col.children && col.children.length"
|
|
33
|
+
:key="col._key"
|
|
34
|
+
v-bind="getColumnProps(col)"
|
|
35
|
+
>
|
|
36
|
+
<el-table-column
|
|
37
|
+
v-for="child in col.children"
|
|
38
|
+
:key="child._key || child.prop"
|
|
39
|
+
v-bind="getColumnProps(child)"
|
|
40
|
+
/>
|
|
41
|
+
</el-table-column>
|
|
42
|
+
<el-table-column v-else :key="col._key" v-bind="getColumnProps(col)" />
|
|
43
|
+
</template>
|
|
44
|
+
</el-table>
|
|
37
45
|
</div>
|
|
38
46
|
|
|
39
47
|
<!-- 表格主体 -->
|
|
@@ -106,6 +114,7 @@
|
|
|
106
114
|
ref="table"
|
|
107
115
|
:data="visibleData"
|
|
108
116
|
:height="computedHeight"
|
|
117
|
+
:max-height="computedMaxHeight"
|
|
109
118
|
:span-method="groupColumns.length ? handleSpanMethod : undefined"
|
|
110
119
|
:row-class-name="getRowClassName"
|
|
111
120
|
v-bind="$attrs"
|
|
@@ -171,11 +180,13 @@
|
|
|
171
180
|
|
|
172
181
|
<script>
|
|
173
182
|
import ExTableCell from './ExTableCell.vue'
|
|
183
|
+
// 内部导入 element-ui 组件,避免与外部 element-ui 冲突
|
|
184
|
+
import { Table as ElTable, TableColumn as ElTableColumn } from 'element-ui'
|
|
174
185
|
|
|
175
186
|
export default {
|
|
176
187
|
name: 'ExTable',
|
|
177
188
|
inheritAttrs: false,
|
|
178
|
-
components: { ExTableCell },
|
|
189
|
+
components: { ExTableCell, ElTable, ElTableColumn },
|
|
179
190
|
props: {
|
|
180
191
|
// 表格数据
|
|
181
192
|
tableData: { type: Array, default: () => [] },
|
|
@@ -187,6 +198,8 @@ export default {
|
|
|
187
198
|
title: { type: String, default: '' },
|
|
188
199
|
// 高度
|
|
189
200
|
height: { type: [Number, String], default: null },
|
|
201
|
+
// 最大高度(非虚拟滚动时与 height 二选一,均支持固定表头)
|
|
202
|
+
maxHeight: { type: [Number, String], default: null },
|
|
190
203
|
// 虚拟滚动
|
|
191
204
|
virtualScroll: { type: Boolean, default: false },
|
|
192
205
|
// 预估行高
|
|
@@ -224,8 +237,6 @@ export default {
|
|
|
224
237
|
visibleStartIndex: 0,
|
|
225
238
|
visibleEndIndex: 0,
|
|
226
239
|
visibleCount: 0,
|
|
227
|
-
// 表格宽度(用于自适应列宽计算)
|
|
228
|
-
tableWidth: 0,
|
|
229
240
|
// 分组合并缓存
|
|
230
241
|
spanCache: {},
|
|
231
242
|
// 列扁平化缓存
|
|
@@ -242,203 +253,19 @@ export default {
|
|
|
242
253
|
|
|
243
254
|
computedHeight() {
|
|
244
255
|
if (this.virtualScroll) {
|
|
245
|
-
return this.height || 400
|
|
256
|
+
return this.height || this.maxHeight || 400
|
|
246
257
|
}
|
|
247
258
|
return this.height || undefined
|
|
248
259
|
},
|
|
249
260
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
// 选择列
|
|
254
|
-
if (this.selection) width += 55
|
|
255
|
-
// 序号列
|
|
256
|
-
if (this.showIndex) width += 60
|
|
257
|
-
// fixed 列
|
|
258
|
-
const sumFixedWidth = (cols) => {
|
|
259
|
-
cols.forEach(c => {
|
|
260
|
-
if (c.fixed && (c.width || c.minWidth)) {
|
|
261
|
-
width += typeof c.width === 'number' ? c.width : (typeof c.minWidth === 'number' ? c.minWidth : 100)
|
|
262
|
-
}
|
|
263
|
-
if (c.children && c.children.length) sumFixedWidth(c.children)
|
|
264
|
-
})
|
|
265
|
-
}
|
|
266
|
-
sumFixedWidth(this.columns)
|
|
267
|
-
return width
|
|
261
|
+
computedMaxHeight() {
|
|
262
|
+
if (this.virtualScroll || this.height) return undefined
|
|
263
|
+
return this.maxHeight || undefined
|
|
268
264
|
},
|
|
269
265
|
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const sumWidth = (cols) => {
|
|
274
|
-
cols.forEach(c => {
|
|
275
|
-
if (!c.fixed && c.width) {
|
|
276
|
-
width += typeof c.width === 'number' ? c.width : parseInt(c.width) || 0
|
|
277
|
-
}
|
|
278
|
-
if (c.children && c.children.length) sumWidth(c.children)
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
sumWidth(this.columns)
|
|
282
|
-
return width
|
|
283
|
-
},
|
|
284
|
-
|
|
285
|
-
// 计算需要自适应的列数(非固定列且未设置width)
|
|
286
|
-
autoColumnCount() {
|
|
287
|
-
let count = 0
|
|
288
|
-
const countCols = (cols) => {
|
|
289
|
-
cols.forEach(c => {
|
|
290
|
-
if (!c.fixed) {
|
|
291
|
-
if (c.children && c.children.length) {
|
|
292
|
-
countCols(c.children)
|
|
293
|
-
} else if (!c.width) {
|
|
294
|
-
// 只有未设置width的非固定列才参与自适应
|
|
295
|
-
count++
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
})
|
|
299
|
-
}
|
|
300
|
-
countCols(this.columns)
|
|
301
|
-
return count
|
|
302
|
-
},
|
|
303
|
-
|
|
304
|
-
// 自适应列宽(未设置width的非固定列均分剩余宽度)
|
|
305
|
-
autoColumnWidth() {
|
|
306
|
-
const totalWidth = this.tableWidth || 1000
|
|
307
|
-
const gutter = 12 // el-table 默认 gutter
|
|
308
|
-
const fixedWidth = this.fixedColumnWidth
|
|
309
|
-
const nonFixedWithWidth = this.nonFixedColumnWidthWithWidth
|
|
310
|
-
const autoCount = this.autoColumnCount
|
|
311
|
-
|
|
312
|
-
if (autoCount <= 0) return 100 // 默认宽度
|
|
313
|
-
|
|
314
|
-
// 自适应宽度 = (总宽度 - gutter - 固定列宽度 - 非固定列中已设置的width)/ 需要自适应的列数
|
|
315
|
-
const availableWidth = totalWidth - gutter - fixedWidth - nonFixedWithWidth
|
|
316
|
-
return Math.max(80, Math.floor(availableWidth / autoCount)) // 最小80px
|
|
317
|
-
},
|
|
318
|
-
|
|
319
|
-
// 表头列定义(用于 colgroup,与 headerRows 列数保持一致)
|
|
320
|
-
headerCols() {
|
|
321
|
-
const cols = []
|
|
322
|
-
|
|
323
|
-
// 选择列
|
|
324
|
-
if (this.selection) {
|
|
325
|
-
cols.push({ _key: 'prepend_selection', _width: 55, _minWidth: 55 })
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// 序号列
|
|
329
|
-
if (this.showIndex) {
|
|
330
|
-
cols.push({ _key: 'prepend_index', _width: 60, _minWidth: 60 })
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// 数据列(只取叶子节点,使用一致的key生成)
|
|
334
|
-
const addLeafCols = (columns, parentPath = '') => {
|
|
335
|
-
columns.forEach((col, index) => {
|
|
336
|
-
const path = parentPath ? `${parentPath}_${index}` : String(index)
|
|
337
|
-
const key = this.generateColKey(col, path)
|
|
338
|
-
|
|
339
|
-
if (col.children && col.children.length) {
|
|
340
|
-
addLeafCols(col.children, path)
|
|
341
|
-
} else {
|
|
342
|
-
cols.push({
|
|
343
|
-
_key: key,
|
|
344
|
-
_width: this.getColumnWidth(col),
|
|
345
|
-
_minWidth: col.minWidth
|
|
346
|
-
})
|
|
347
|
-
}
|
|
348
|
-
})
|
|
349
|
-
}
|
|
350
|
-
addLeafCols(this.columns)
|
|
351
|
-
|
|
352
|
-
return cols
|
|
353
|
-
},
|
|
354
|
-
|
|
355
|
-
// 表头层级结构(用于自定义固定表头渲染)
|
|
356
|
-
headerRows() {
|
|
357
|
-
const rows = []
|
|
358
|
-
let maxDepth = 1
|
|
359
|
-
|
|
360
|
-
// 计算最大深度
|
|
361
|
-
const calcDepth = (cols, depth) => {
|
|
362
|
-
maxDepth = Math.max(maxDepth, depth)
|
|
363
|
-
cols.forEach(c => { if (c.children && c.children.length) calcDepth(c.children, depth + 1) })
|
|
364
|
-
}
|
|
365
|
-
if (this.columns.length) calcDepth(this.columns, 1)
|
|
366
|
-
|
|
367
|
-
// 初始化行
|
|
368
|
-
for (let i = 0; i < maxDepth; i++) rows.push([])
|
|
369
|
-
|
|
370
|
-
// 计算叶子数量
|
|
371
|
-
const countLeaves = (cols) => {
|
|
372
|
-
let n = 0
|
|
373
|
-
cols.forEach(c => {
|
|
374
|
-
if (c.children && c.children.length) n += countLeaves(c.children)
|
|
375
|
-
else n++
|
|
376
|
-
})
|
|
377
|
-
return n
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// 选择列 / 序号列占位(仅第一行,rowspan 跨所有行)
|
|
381
|
-
if (this.selection) {
|
|
382
|
-
rows[0].push({
|
|
383
|
-
_key: 'prepend_selection',
|
|
384
|
-
_rowspan: maxDepth,
|
|
385
|
-
_colspan: 1,
|
|
386
|
-
_style: { width: '55px' },
|
|
387
|
-
_hidden: false,
|
|
388
|
-
label: ''
|
|
389
|
-
})
|
|
390
|
-
for (let i = 1; i < maxDepth; i++) {
|
|
391
|
-
rows[i].push({ _key: 'prepend_selection_' + i, _rowspan: 0, _colspan: 1, _hidden: true, label: '' })
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
if (this.showIndex) {
|
|
395
|
-
rows[0].push({
|
|
396
|
-
_key: 'prepend_index',
|
|
397
|
-
_rowspan: maxDepth,
|
|
398
|
-
_colspan: 1,
|
|
399
|
-
_style: { width: '60px' },
|
|
400
|
-
_hidden: false,
|
|
401
|
-
label: '#'
|
|
402
|
-
})
|
|
403
|
-
for (let i = 1; i < maxDepth; i++) {
|
|
404
|
-
rows[i].push({ _key: 'prepend_index_' + i, _rowspan: 0, _colspan: 1, _hidden: true, label: '' })
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// 填充列
|
|
409
|
-
if (this.columns.length) {
|
|
410
|
-
const fill = (cols, depth, parentPath = '') => {
|
|
411
|
-
cols.forEach((c, index) => {
|
|
412
|
-
const path = parentPath ? `${parentPath}_${index}` : String(index)
|
|
413
|
-
const key = this.generateColKey(c, path)
|
|
414
|
-
const hasKids = c.children && c.children.length
|
|
415
|
-
const style = {}
|
|
416
|
-
|
|
417
|
-
// 如果有固定宽度,使用固定宽度;否则使用自适应宽度
|
|
418
|
-
if (c.width) {
|
|
419
|
-
style.width = typeof c.width === 'number' ? c.width + 'px' : c.width
|
|
420
|
-
} else if (!c.fixed && this.virtualScroll) {
|
|
421
|
-
// 非固定列且虚拟滚动时使用自适应宽度
|
|
422
|
-
style.width = this.autoColumnWidth + 'px'
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
if (c.minWidth) style.minWidth = typeof c.minWidth === 'number' ? c.minWidth + 'px' : c.minWidth
|
|
426
|
-
|
|
427
|
-
rows[depth].push({
|
|
428
|
-
_key: key,
|
|
429
|
-
_rowspan: hasKids ? 1 : maxDepth - depth,
|
|
430
|
-
_colspan: hasKids ? countLeaves(c.children) : 1,
|
|
431
|
-
_style: style,
|
|
432
|
-
_hidden: !c.label && !c.prop,
|
|
433
|
-
label: c.label || ''
|
|
434
|
-
})
|
|
435
|
-
if (hasKids) fill(c.children, depth + 1, path)
|
|
436
|
-
})
|
|
437
|
-
}
|
|
438
|
-
fill(this.columns, 0)
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
return rows
|
|
266
|
+
// 虚拟滚动固定表头占位数据(仅渲染表头,不渲染 body 行)
|
|
267
|
+
headerTableData() {
|
|
268
|
+
return []
|
|
442
269
|
},
|
|
443
270
|
|
|
444
271
|
// 处理后的数据(注入小计/总计行)
|
|
@@ -491,22 +318,25 @@ export default {
|
|
|
491
318
|
return start * this.rowHeight
|
|
492
319
|
},
|
|
493
320
|
|
|
494
|
-
//
|
|
321
|
+
// 扁平化列配置(为每级列补充 _key)
|
|
495
322
|
flattenedColumns() {
|
|
496
323
|
if (this.flattenedColumnsCache.length) return this.flattenedColumnsCache
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
const key = col.prop || col.label ||
|
|
501
|
-
|
|
324
|
+
const assignKeys = (cols, parentPath = '') => {
|
|
325
|
+
return cols.map((col, index) => {
|
|
326
|
+
const path = parentPath ? `${parentPath}_${index}` : String(index)
|
|
327
|
+
const key = col.prop || col.slot || col.label || path
|
|
328
|
+
const item = { ...col, _key: key }
|
|
329
|
+
if (col.children && col.children.length) {
|
|
330
|
+
item.children = assignKeys(col.children, path)
|
|
331
|
+
}
|
|
332
|
+
return item
|
|
502
333
|
})
|
|
503
334
|
}
|
|
504
|
-
|
|
505
|
-
this.flattenedColumnsCache
|
|
506
|
-
return result
|
|
335
|
+
this.flattenedColumnsCache = assignKeys(this.columns)
|
|
336
|
+
return this.flattenedColumnsCache
|
|
507
337
|
},
|
|
508
338
|
|
|
509
|
-
//
|
|
339
|
+
// 虚拟滚动时的可见数据(附带 _realIndex 供序号列使用)
|
|
510
340
|
visibleData() {
|
|
511
341
|
const data = this.processedTableData
|
|
512
342
|
if (!this.virtualScroll || data.length === 0) {
|
|
@@ -514,7 +344,10 @@ export default {
|
|
|
514
344
|
}
|
|
515
345
|
const start = Math.max(0, this.visibleStartIndex - this.bufferSize)
|
|
516
346
|
const end = Math.min(data.length, this.visibleEndIndex + this.bufferSize)
|
|
517
|
-
return data.slice(start, end)
|
|
347
|
+
return data.slice(start, end).map((row, i) => ({
|
|
348
|
+
...row,
|
|
349
|
+
_realIndex: start + i
|
|
350
|
+
}))
|
|
518
351
|
}
|
|
519
352
|
},
|
|
520
353
|
|
|
@@ -527,6 +360,7 @@ export default {
|
|
|
527
360
|
this.$nextTick(() => {
|
|
528
361
|
this.measureRowHeight()
|
|
529
362
|
this.updateVisibleRange()
|
|
363
|
+
this.syncTableLayout()
|
|
530
364
|
})
|
|
531
365
|
}
|
|
532
366
|
},
|
|
@@ -536,10 +370,25 @@ export default {
|
|
|
536
370
|
columns: {
|
|
537
371
|
handler() {
|
|
538
372
|
this.flattenedColumnsCache = []
|
|
373
|
+
if (this.virtualScroll) {
|
|
374
|
+
this.$nextTick(() => this.syncTableLayout())
|
|
375
|
+
}
|
|
539
376
|
},
|
|
540
377
|
deep: true
|
|
541
378
|
},
|
|
542
379
|
|
|
380
|
+
height() {
|
|
381
|
+
if (this.virtualScroll) {
|
|
382
|
+
this.$nextTick(() => this.syncTableLayout())
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
|
|
386
|
+
maxHeight() {
|
|
387
|
+
if (this.virtualScroll) {
|
|
388
|
+
this.$nextTick(() => this.syncTableLayout())
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
|
|
543
392
|
virtualScroll(val) {
|
|
544
393
|
if (val) {
|
|
545
394
|
this.$nextTick(() => this.initVirtualScroll())
|
|
@@ -556,7 +405,7 @@ export default {
|
|
|
556
405
|
// 监听窗口resize,更新表格宽度
|
|
557
406
|
this.resizeHandler = () => {
|
|
558
407
|
if (this.virtualScroll) {
|
|
559
|
-
this.$nextTick(() => this.
|
|
408
|
+
this.$nextTick(() => this.syncTableLayout())
|
|
560
409
|
}
|
|
561
410
|
}
|
|
562
411
|
window.addEventListener('resize', this.resizeHandler)
|
|
@@ -795,41 +644,35 @@ export default {
|
|
|
795
644
|
},
|
|
796
645
|
|
|
797
646
|
doLayout() {
|
|
798
|
-
this
|
|
647
|
+
this.syncTableLayout()
|
|
799
648
|
},
|
|
800
649
|
|
|
801
|
-
//
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
if (!col.fixed && this.virtualScroll) {
|
|
809
|
-
return this.autoColumnWidth
|
|
810
|
-
}
|
|
811
|
-
// 默认宽度
|
|
812
|
-
if (col.minWidth) {
|
|
813
|
-
return typeof col.minWidth === 'number' ? col.minWidth : col.minWidth.replace('px', '')
|
|
814
|
-
}
|
|
815
|
-
return 100
|
|
650
|
+
// ==================== 虚拟滚动固定表头 ====================
|
|
651
|
+
syncTableLayout() {
|
|
652
|
+
const bodyTable = this.$refs.table
|
|
653
|
+
const headerTable = this.$refs.headerTable
|
|
654
|
+
if (bodyTable) bodyTable.doLayout()
|
|
655
|
+
if (headerTable) headerTable.doLayout()
|
|
656
|
+
this.syncHeaderScroll(this.scrollLeft)
|
|
816
657
|
},
|
|
817
658
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
659
|
+
syncHeaderScroll(scrollLeft) {
|
|
660
|
+
const headerTable = this.$refs.headerTable
|
|
661
|
+
if (!headerTable) return
|
|
662
|
+
const headerWrapper = headerTable.$el.querySelector('.el-table__header-wrapper')
|
|
663
|
+
if (headerWrapper) {
|
|
664
|
+
headerWrapper.scrollLeft = scrollLeft
|
|
823
665
|
}
|
|
824
666
|
},
|
|
825
667
|
|
|
826
668
|
// ==================== 虚拟滚动 ====================
|
|
827
669
|
initVirtualScroll() {
|
|
828
|
-
this.
|
|
670
|
+
this.rowHeight = this.rowInitHeight
|
|
829
671
|
this.measureRowHeight()
|
|
830
672
|
if (this.processedTableData.length > 0) {
|
|
831
673
|
this.updateVisibleRange()
|
|
832
674
|
}
|
|
675
|
+
this.syncTableLayout()
|
|
833
676
|
},
|
|
834
677
|
|
|
835
678
|
measureRowHeight() {
|
|
@@ -847,6 +690,7 @@ export default {
|
|
|
847
690
|
if (this.virtualScroll) {
|
|
848
691
|
this.scrollTop = target.scrollTop
|
|
849
692
|
this.updateVisibleRange()
|
|
693
|
+
this.syncHeaderScroll(target.scrollLeft)
|
|
850
694
|
}
|
|
851
695
|
},
|
|
852
696
|
|
|
@@ -945,8 +789,12 @@ export default {
|
|
|
945
789
|
|
|
946
790
|
/* 虚拟滚动容器 */
|
|
947
791
|
.ex-table-virtual {
|
|
948
|
-
overflow:
|
|
792
|
+
overflow: overlay;
|
|
949
793
|
position: relative;
|
|
794
|
+
/* Firefox 隐藏滚动条 */
|
|
795
|
+
scrollbar-width: none;
|
|
796
|
+
/* IE/旧 Edge 隐藏滚动条 */
|
|
797
|
+
-ms-overflow-style: none;
|
|
950
798
|
}
|
|
951
799
|
|
|
952
800
|
.ex-table-virtual-inner {
|
|
@@ -964,39 +812,25 @@ export default {
|
|
|
964
812
|
padding: 16px 0;
|
|
965
813
|
}
|
|
966
814
|
|
|
967
|
-
/*
|
|
815
|
+
/* 虚拟滚动固定表头(header-only el-table) */
|
|
968
816
|
.ex-table-fixed-header {
|
|
969
817
|
overflow: hidden;
|
|
970
|
-
|
|
971
|
-
background: #fafafa;
|
|
818
|
+
flex-shrink: 0;
|
|
972
819
|
}
|
|
973
820
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
821
|
+
/* 虚拟滚动表头强制补上 gutter 占位 */
|
|
822
|
+
.ex-table-fixed-header >>> .el-table__header-wrapper thead tr .el-table__cell.gutter {
|
|
823
|
+
display: table-cell;
|
|
824
|
+
width: 8px; /* 和滚动条宽度一致 */
|
|
978
825
|
}
|
|
979
826
|
|
|
980
|
-
.ex-table-fixed-header-table th {
|
|
981
|
-
padding: 12px 8px;
|
|
982
|
-
text-align: left;
|
|
983
|
-
font-weight: 500;
|
|
984
|
-
font-size: 14px;
|
|
985
|
-
color: #606266;
|
|
986
|
-
border-bottom: 1px solid #ebeef5;
|
|
987
|
-
border-right: 1px solid #ebeef5;
|
|
988
|
-
white-space: nowrap;
|
|
989
|
-
overflow: hidden;
|
|
990
|
-
text-overflow: ellipsis;
|
|
991
|
-
background: #fafafa;
|
|
992
|
-
box-sizing: border-box;
|
|
993
|
-
}
|
|
994
827
|
|
|
995
|
-
.ex-table-
|
|
996
|
-
|
|
828
|
+
.ex-table-header-only >>> .el-table__body-wrapper,
|
|
829
|
+
.ex-table-header-only >>> .el-table__empty-block {
|
|
830
|
+
display: none;
|
|
997
831
|
}
|
|
998
832
|
|
|
999
|
-
.ex-table-
|
|
1000
|
-
|
|
833
|
+
.ex-table-header-only >>> .el-table__header-wrapper {
|
|
834
|
+
overflow: hidden;
|
|
1001
835
|
}
|
|
1002
836
|
</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 生成虚拟滚动演示数据
|
|
3
|
+
* @param {number} count 数据条数,默认 10000
|
|
4
|
+
* @returns {Array}
|
|
5
|
+
*/
|
|
6
|
+
export function createVirtualScrollData(count = 10000) {
|
|
7
|
+
const departments = ['研发部', '产品部', '运营部', '财务部', '市场部']
|
|
8
|
+
const positions = ['工程师', '产品经理', '运营专员', '财务主管', '市场经理']
|
|
9
|
+
const statuses = ['在职', '休假', '离职']
|
|
10
|
+
|
|
11
|
+
return Array.from({ length: count }, (_, i) => ({
|
|
12
|
+
id: i + 1,
|
|
13
|
+
name: `用户${i + 1}`,
|
|
14
|
+
department: departments[i % departments.length],
|
|
15
|
+
position: positions[i % positions.length],
|
|
16
|
+
email: `user${i + 1}@example.com`,
|
|
17
|
+
phone: `13800138${String(i).padStart(4, '0')}`,
|
|
18
|
+
address: `北京市朝阳区第${i + 1}号街道`,
|
|
19
|
+
salary: 5000 + Math.floor(Math.random() * 10000),
|
|
20
|
+
status: statuses[i % statuses.length]
|
|
21
|
+
}))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** 虚拟滚动演示列配置 */
|
|
25
|
+
export const virtualScrollColumns = [
|
|
26
|
+
{ prop: 'id', label: 'ID', fixed: 'left', width: 80 },
|
|
27
|
+
{ prop: 'name', label: '姓名', fixed: 'left', width: 120 },
|
|
28
|
+
{ prop: 'department', label: '部门', width: 150 },
|
|
29
|
+
{ prop: 'position', label: '职位', width: 150 },
|
|
30
|
+
{ prop: 'email', label: '邮箱', width: 200 },
|
|
31
|
+
{ prop: 'phone', label: '电话', width: 130 },
|
|
32
|
+
{ prop: 'address', label: '地址', width: 200 },
|
|
33
|
+
{ prop: 'salary', label: '薪资', width: 120 },
|
|
34
|
+
{ prop: 'status', label: '状态', fixed: 'right', width: 100 }
|
|
35
|
+
]
|
|
@@ -13,25 +13,25 @@ export default {
|
|
|
13
13
|
},
|
|
14
14
|
watch: {
|
|
15
15
|
theme(newVal) {
|
|
16
|
-
this
|
|
16
|
+
this.xtConfig ={
|
|
17
17
|
theme: newVal,
|
|
18
18
|
size: this.size,
|
|
19
19
|
primaryColor: this.primaryColor
|
|
20
|
-
}
|
|
20
|
+
}
|
|
21
21
|
},
|
|
22
22
|
size(newVal) {
|
|
23
|
-
this
|
|
24
|
-
theme:
|
|
25
|
-
size:
|
|
23
|
+
this.xtConfig ={
|
|
24
|
+
theme: newVal,
|
|
25
|
+
size: this.size,
|
|
26
26
|
primaryColor: this.primaryColor
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
28
|
},
|
|
29
29
|
primaryColor(newVal) {
|
|
30
|
-
this
|
|
31
|
-
theme:
|
|
30
|
+
this.xtConfig ={
|
|
31
|
+
theme: newVal,
|
|
32
32
|
size: this.size,
|
|
33
|
-
primaryColor:
|
|
34
|
-
}
|
|
33
|
+
primaryColor: this.primaryColor
|
|
34
|
+
}
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
render(h) {
|
|
@@ -76,17 +76,17 @@
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// 暗色主题
|
|
79
|
-
|
|
79
|
+
[data-theme='dark'] .xt-text--primary {
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
[data-theme='dark'] .xt-text--success {
|
|
83
83
|
color: $xt-dark-color-success;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
[data-theme='dark'] .xt-text--warning {
|
|
87
87
|
color: $xt-dark-color-warning;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
[data-theme='dark'] .xt-text--danger {
|
|
91
91
|
color: $xt-dark-color-danger;
|
|
92
92
|
}
|
package/src/index.js
CHANGED
|
@@ -96,15 +96,16 @@ const install = function (Vue, options = {}) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
if (process.env.NODE_ENV === 'development') {
|
|
100
|
+
// 导入内部 element-ui 依赖(作为内部依赖,不与外部冲突)
|
|
101
|
+
const ElementUI = require('element-ui')
|
|
102
|
+
|
|
103
|
+
// 注册 ElementUI 的基础组件(用于 ExTable 等封装组件内部使用)
|
|
104
|
+
// 不调用 Vue.use(ElementUI),避免全局污染
|
|
105
|
+
// ex-table 等组件内部会直接使用 element-ui 的组件
|
|
106
|
+
|
|
107
|
+
// 在开发环境下注册 ElementUI 组件为 Ex 开头(方便文档和示例使用)
|
|
108
|
+
registerElementExComponents(Vue, ElementUI)
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
// 调用统一的注册函数
|
|
@@ -139,6 +140,9 @@ export default {
|
|
|
139
140
|
// ExChart 组件按需导出(使用时需自行安装 echarts 依赖)
|
|
140
141
|
export { default as ExChart } from './components/ex-chart'
|
|
141
142
|
|
|
143
|
+
// ExTable 虚拟滚动演示数据工具
|
|
144
|
+
export { createVirtualScrollData, virtualScrollColumns } from './components/ex-table/virtualScrollData'
|
|
145
|
+
|
|
142
146
|
// 导出工具函数和变量
|
|
143
147
|
export {
|
|
144
148
|
utils,
|