uview-plus 3.4.77 → 3.4.79

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/changelog.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 3.4.79(2025-08-09)
2
+ feat: table2组件支持左侧固定列功能
3
+
4
+ ## 3.4.78(2025-08-09)
5
+ fix: 修复table2在popup弹窗中无法横向滚动
6
+
1
7
  ## 3.4.77(2025-08-08)
2
8
  feat: 优化waterfall瀑布流组件逻辑
3
9
 
@@ -1,99 +1,159 @@
1
1
  <template>
2
- <view scroll-x class="u-table2" :style="{ height: height ? height + 'px' : 'auto' }">
3
- <!-- 表头 -->
4
- <view v-if="showHeader" class="u-table-header" :class="{ 'u-table-sticky': fixedHeader }" :style="{minWidth: scrollWidth}">
5
- <view class="u-table-row">
6
- <view v-for="(col, colIndex) in columns" :key="col.key" class="u-table-cell"
7
- :style="headerColStyle(col)"
8
- :class="[
9
- col.align ? 'u-text-' + col.align : '',
10
- headerCellClassName ? headerCellClassName(col) : '',
11
- col.fixed === 'left' ? 'u-table-fixed-left' : '',
12
- col.fixed === 'right' ? 'u-table-fixed-right' : ''
13
- ]" @click="handleHeaderClick(col)">
14
- <slot name="header" :column="col" :columnIndex="colIndex" :level="1">
15
- </slot>
16
- <text v-if="!$slots['header']">{{ col.title }}</text>
17
- <template v-if="col.sortable">
18
- <slot name="headerSort" :sortStatus="getSortValue(col.key)" :column="col"
19
- :columnIndex="colIndex" :level="1">
2
+ <view class="u-table2">
3
+ <scroll-view scroll-x class="u-table2-content" :style="{ height: height ? height + 'px' : 'auto' }" @scroll="onScroll">
4
+ <!-- 表头 -->
5
+ <view v-if="showHeader" class="u-table-header" :class="{ 'u-table-sticky': fixedHeader }" :style="{minWidth: scrollWidth}">
6
+ <view class="u-table-row">
7
+ <view v-for="(col, colIndex) in columns" :key="col.key" class="u-table-cell"
8
+ :style="headerColStyle(col)"
9
+ :class="[col.align ? 'u-text-' + col.align : '',
10
+ headerCellClassName ? headerCellClassName(col) : '',
11
+ getFixedClass(col)
12
+ ]" @click="handleHeaderClick(col)">
13
+ <slot name="header" :column="col" :columnIndex="colIndex" :level="1">
20
14
  </slot>
21
- <view v-if="!$slots['headerSort']">
22
- {{ getSortIcon(col.key) }}
23
- </view>
24
- </template>
15
+ <text v-if="!$slots['header']">{{ col.title }}</text>
16
+ <template v-if="col.sortable">
17
+ <slot name="headerSort" :sortStatus="getSortValue(col.key)" :column="col"
18
+ :columnIndex="colIndex" :level="1">
19
+ </slot>
20
+ <view v-if="!$slots['headerSort']">
21
+ {{ getSortIcon(col.key) }}
22
+ </view>
23
+ </template>
24
+ </view>
25
25
  </view>
26
26
  </view>
27
- </view>
28
27
 
29
- <!-- 表体 -->
30
- <view class="u-table-body" :style="{ minWidth: scrollWidth, maxHeight: maxHeight ? maxHeight + 'px' : 'none' }">
31
- <template v-if="data && data.length > 0">
32
- <template v-for="(row, index) in sortedData" :key="row[rowKey] || index">
33
- <view class="u-table-row" :class="[
34
- highlightCurrentRow && currentRow === row ? 'u-table-row-highlight' : '',
35
- rowClassName ? rowClassName(row, index) : '',
36
- stripe && index % 2 === 1 ? 'u-table-row-zebra' : ''
37
- ]" @click="handleRowClick(row)">
38
- <view v-for="(col, colIndex) in columns" :key="col.key"
39
- class="u-table-cell" :class="[
40
- col.align ? 'u-text-' + col.align : '',
41
- cellClassName ? cellClassName(row, col) : '',
42
- col.fixed === 'left' ? 'u-table-fixed-left' : '',
43
- col.fixed === 'right' ? 'u-table-fixed-right' : ''
44
- ]" :style="cellStyleInner({row: row, column: col,
45
- rowIndex: index, columnIndex: colIndex, level: 0})">
46
- <!-- 复选框列 -->
47
- <view v-if="col.type === 'selection'">
48
- <checkbox :checked="isSelected(row)"
49
- @click.stop="toggleSelect(row)" />
50
- </view>
28
+ <!-- 表体 -->
29
+ <view class="u-table-body" :style="{ minWidth: scrollWidth, maxHeight: maxHeight ? maxHeight + 'px' : 'none' }">
30
+ <template v-if="data && data.length > 0">
31
+ <template v-for="(row, index) in sortedData" :key="row[rowKey] || index">
32
+ <view class="u-table-row" :class="[highlightCurrentRow && currentRow === row ? 'u-table-row-highlight' : '',
33
+ rowClassName ? rowClassName(row, index) : '',
34
+ stripe && index % 2 === 1 ? 'u-table-row-zebra' : ''
35
+ ]" @click="handleRowClick(row)">
36
+ <view v-for="(col, colIndex) in columns" :key="col.key"
37
+ class="u-table-cell" :class="[col.align ? 'u-text-' + col.align : '',
38
+ cellClassName ? cellClassName(row, col) : '',
39
+ getFixedClass(col)
40
+ ]" :style="cellStyleInner({row: row, column: col,
41
+ rowIndex: index, columnIndex: colIndex, level: 0})">
42
+ <!-- 复选框列 -->
43
+ <view v-if="col.type === 'selection'">
44
+ <checkbox :checked="isSelected(row)"
45
+ @click.stop="toggleSelect(row)" />
46
+ </view>
47
+
48
+ <!-- 树形结构展开图标 -->
49
+ <view v-else-if="col.type === 'expand'" @click.stop="toggleExpand(row)">
50
+ {{ isExpanded(row) ? '▼' : '▶' }}
51
+ </view>
51
52
 
52
- <!-- 树形结构展开图标 -->
53
- <view v-else-if="col.type === 'expand'"
54
- @click.stop="toggleExpand(row)">
55
- {{ isExpanded(row) ? '▼' : '▶' }}
53
+ <!-- 默认插槽或文本 -->
54
+ <slot name="cell" :row="row" :column="col"
55
+ :rowIndex="index" :columnIndex="colIndex">
56
+ <view class="u-table-cell_content">
57
+ {{ row[col.key] }}
58
+ </view>
59
+ </slot>
56
60
  </view>
61
+ </view>
57
62
 
58
- <!-- 默认插槽或文本 -->
59
- <slot name="cell" :row="row" :column="col"
60
- :rowIndex="index" :columnIndex="colIndex">
61
- <view class="u-table-cell_content">
62
- {{ row[col.key] }}
63
+ <!-- 子级渲染 -->
64
+ <template v-if="isExpanded(row) && row[treeProps.children] && row[treeProps.children].length">
65
+ <view v-for="childRow in row[treeProps.children]" :key="childRow[rowKey]"
66
+ class="u-table-row u-table-row-child">
67
+ <view v-for="(col2, col2Index) in columns" :key="col2.key" class="u-table-cell"
68
+ :style="cellStyleInner({row: childRow, column: col2,
69
+ rowIndex: index, columnIndex: col2Index, level: 1})">
70
+ <slot name="cell" :row="childRow" :column="col2" :prow="row"
71
+ :rowIndex="index" :columnIndex="col2Index" :level="1">
72
+ <view class="u-table-cell_content">
73
+ {{ childRow[col2.key] }}
74
+ </view>
75
+ </slot>
63
76
  </view>
77
+ </view>
78
+ </template>
79
+ </template>
80
+ </template>
81
+ <template v-else>
82
+ <slot name="empty">
83
+ </slot>
84
+ <view v-if="!$slots['empty']" class="u-table-empty">{{ emptyText }}</view>
85
+ </template>
86
+ </view>
87
+ </scroll-view>
88
+
89
+ <!-- 固定列浮动视图 -->
90
+ <view v-if="showFixedColumnShadow" class="u-table-fixed-shadow" :style="{ height: tableHeight }">
91
+ <!-- 表头 -->
92
+ <view v-if="showHeader" class="u-table-header" :class="{ 'u-table-sticky': fixedHeader }" :style="{minWidth: scrollWidth}">
93
+ <view class="u-table-row">
94
+ <view v-for="(col, colIndex) in visibleFixedLeftColumns" :key="col.key" class="u-table-cell"
95
+ :style="headerColStyle(col)"
96
+ :class="[col.align ? 'u-text-' + col.align : '',
97
+ headerCellClassName ? headerCellClassName(col) : '',
98
+ getFixedClass(col)
99
+ ]" @click="handleHeaderClick(col)">
100
+ <slot name="header" :column="col" :columnIndex="colIndex" :level="1">
101
+ </slot>
102
+ <text v-if="!$slots['header']">{{ col.title }}</text>
103
+ <template v-if="col.sortable">
104
+ <slot name="headerSort" :sortStatus="getSortValue(col.key)" :column="col"
105
+ :columnIndex="colIndex" :level="1">
64
106
  </slot>
65
- </view>
107
+ <view v-if="!$slots['headerSort']">
108
+ {{ getSortIcon(col.key) }}
109
+ </view>
110
+ </template>
66
111
  </view>
112
+ </view>
113
+ </view>
67
114
 
68
- <!-- 子级渲染 -->
69
- <template v-if="isExpanded(row) && row[treeProps.children] && row[treeProps.children].length">
70
- <view v-for="childRow in row[treeProps.children]" :key="childRow[rowKey]"
71
- class="u-table-row u-table-row-child">
72
- <view v-for="(col2, col2Index) in columns" :key="col2.key" class="u-table-cell"
73
- :style="cellStyleInner({row: childRow, column: col2,
74
- rowIndex: index, columnIndex: col2Index, level: 1})">
75
- <slot name="cell" :row="childRow" :column="col2" :prow="row"
76
- :rowIndex="index" :columnIndex="col2Index" :level="1">
115
+ <!-- 表体 -->
116
+ <view class="u-table-body" :style="{ minWidth: scrollWidth, maxHeight: maxHeight ? maxHeight + 'px' : 'none' }">
117
+ <template v-if="data && data.length > 0">
118
+ <template v-for="(row, index) in sortedData" :key="row[rowKey] || index">
119
+ <view class="u-table-row" :class="[highlightCurrentRow && currentRow === row ? 'u-table-row-highlight' : '',
120
+ rowClassName ? rowClassName(row, index) : '',
121
+ stripe && index % 2 === 1 ? 'u-table-row-zebra' : ''
122
+ ]" @click="handleRowClick(row)">
123
+ <view v-for="(col, colIndex) in visibleFixedLeftColumns" :key="col.key"
124
+ class="u-table-cell" :class="[col.align ? 'u-text-' + col.align : '',
125
+ cellClassName ? cellClassName(row, col) : '',
126
+ getFixedClass(col)
127
+ ]" :style="cellStyleInner({row: row, column: col,
128
+ rowIndex: index, columnIndex: colIndex, level: 0})">
129
+ <!-- 复选框列 -->
130
+ <view v-if="col.type === 'selection'">
131
+ <checkbox :checked="isSelected(row)"
132
+ @click.stop="toggleSelect(row)" />
133
+ </view>
134
+
135
+ <!-- 树形结构展开图标 -->
136
+ <view v-else-if="col.type === 'expand'" @click.stop="toggleExpand(row)">
137
+ {{ isExpanded(row) ? '▼' : '▶' }}
138
+ </view>
139
+
140
+ <!-- 默认插槽或文本 -->
141
+ <slot name="cell" :row="row" :column="col"
142
+ :rowIndex="index" :columnIndex="colIndex">
77
143
  <view class="u-table-cell_content">
78
- {{ childRow[col2.key] }}
144
+ {{ row[col.key] }}
79
145
  </view>
80
146
  </slot>
81
147
  </view>
82
148
  </view>
83
149
  </template>
84
150
  </template>
85
- </template>
86
- <template v-else>
87
- <slot name="empty">
88
- </slot>
89
- <view v-if="!$slots['empty']" class="u-table-empty">{{ emptyText }}</view>
90
- </template>
151
+ </view>
91
152
  </view>
92
153
  </view>
93
154
  </template>
94
155
 
95
156
  <script>
96
- import { ref, watch, computed } from 'vue'
97
157
  import { addUnit, sleep } from '../../libs/function/index';
98
158
 
99
159
  export default {
@@ -241,26 +301,155 @@ export default {
241
301
  ],
242
302
  data() {
243
303
  return {
244
- scrollWidth: 'auto'
304
+ scrollWidth: 'auto',
305
+ // 将setup中的ref转换为data属性
306
+ expandedKeys: [...this.expandRowKeys],
307
+ selectedRows: [],
308
+ sortConditions: [],
309
+ currentRow: null,
310
+ scrollLeft: 0, // 新增滚动位置数据
311
+ showFixedColumnShadow: false, // 是否显示固定列阴影
312
+ fixedLeftColumns: [], // 左侧固定列
313
+ tableHeight: 'auto', // 表格高度
314
+ rowHeight: 40 // 行高
245
315
  }
246
316
  },
247
317
  mounted() {
248
318
  this.getComponentWidth()
319
+ // 处理currentRowKey初始化
320
+ if (this.currentRowKey !== null) {
321
+ const found = this.data.find(item => item[this.rowKey] === this.currentRowKey);
322
+ if (found) {
323
+ this.currentRow = found;
324
+ }
325
+ }
326
+ // 获取固定列
327
+ this.fixedLeftColumns = this.columns.filter(col => col.fixed === 'left');
328
+ },
329
+ computed: {
330
+ // 将setup中的computed转换为computed属性
331
+ filteredData() {
332
+ return this.data.filter(row => {
333
+ return Object.keys(this.filters).every(key => {
334
+ const filter = this.filters[key];
335
+ if (!filter) return true;
336
+ return row[key]?.toString().includes(filter.toString());
337
+ });
338
+ });
339
+ },
340
+ sortedData() {
341
+ if (!this.sortConditions.length) return this.filteredData;
342
+
343
+ const data = [...this.filteredData];
344
+
345
+ return data.sort((a, b) => {
346
+ for (const condition of this.sortConditions) {
347
+ const { field, order } = condition;
348
+ let valA = a[field];
349
+ let valB = b[field];
350
+
351
+ if (this.sortMethod) {
352
+ const result = this.sortMethod(a, b, field);
353
+ if (result !== 0) return result * (order === 'ascending' ? 1 : -1);
354
+ }
355
+
356
+ if (valA < valB) return order === 'ascending' ? -1 : 1;
357
+ if (valA > valB) return order === 'ascending' ? 1 : -1;
358
+ }
359
+ return 0;
360
+ });
361
+ },
362
+ // 计算当前应该显示的固定左侧列
363
+ visibleFixedLeftColumns() {
364
+ if (this.scrollLeft <= 0) {
365
+ return [];
366
+ }
367
+
368
+ let totalWidth = 0;
369
+ let fixedWidth = 0;
370
+ const visibleColumns = [];
371
+
372
+ // 遍历所有列,不仅仅是固定列
373
+ for (let i = 0; i < this.columns.length; i++) {
374
+ const col = this.columns[i];
375
+ const colWidth = col.width ? parseInt(col.width) : 100; // 默认宽度100px
376
+
377
+ // 如果是固定列且滚动位置足够显示该列
378
+ if (col.fixed === 'left' && this.scrollLeft > totalWidth - fixedWidth) {
379
+ visibleColumns.push(col);
380
+ fixedWidth += colWidth;
381
+ }
382
+
383
+ totalWidth += colWidth;
384
+ }
385
+
386
+ return visibleColumns;
387
+ }
388
+ },
389
+ watch: {
390
+ // 将setup中的watch转换为watch属性
391
+ expandRowKeys: {
392
+ handler(newVal) {
393
+ this.expandedKeys = [...newVal];
394
+ },
395
+ immediate: true
396
+ },
397
+ currentRowKey: {
398
+ handler(newVal) {
399
+ const found = this.data.find(item => item[this.rowKey] === newVal);
400
+ if (found) {
401
+ this.currentRow = found;
402
+ }
403
+ },
404
+ immediate: true
405
+ },
406
+ columns: {
407
+ handler() {
408
+ // this.fixedLeftColumns = this.columns.filter(col => col.fixed === 'left');
409
+ },
410
+ deep: true,
411
+ immediate: false
412
+ }
249
413
  },
250
- computed: {
251
- },
252
414
  methods: {
253
415
  addUnit,
254
- headerColStyle(col) {
255
- let style = {
256
- width: col.width ? addUnit(col.width) : 'auto',
257
- flex: col.width ? 'none' : 1
258
- };
259
- if (col?.style) {
260
- style = {...style, ...col?.style};
261
- }
262
- return style;
263
- },
416
+ onScroll(e) {
417
+ this.scrollLeft = e.detail.scrollLeft;
418
+ // 获取所有左侧固定列
419
+ this.fixedLeftColumns = this.columns.filter(col => col.fixed === 'left');
420
+ // 计算是否需要显示固定列阴影
421
+ if (this.fixedLeftColumns.length > 0) {
422
+ this.showFixedColumnShadow = this.scrollLeft > 0;
423
+ }
424
+ },
425
+
426
+ getFixedShadowStyle(col, index) {
427
+ let style = {
428
+ width: col.width ? addUnit(col.width) : 'auto',
429
+ };
430
+
431
+ if (col?.style) {
432
+ style = {...style, ...col?.style};
433
+ }
434
+
435
+ return style;
436
+ },
437
+
438
+ getFixedClass(col) {
439
+ return ''; // 不再使用原来的固定列样式类
440
+ },
441
+
442
+ headerColStyle(col) {
443
+ let style = {
444
+ width: col.width ? addUnit(col.width) : 'auto',
445
+ flex: col.width ? 'none' : 1
446
+ };
447
+ if (col?.style) {
448
+ style = {...style, ...col?.style};
449
+ }
450
+ return style;
451
+ },
452
+
264
453
  setCellStyle(e) {
265
454
  this.cellStyle = e
266
455
  },
@@ -285,172 +474,99 @@ export default {
285
474
  this.$uGetRect('.u-table-row').then(size => {
286
475
  this.scrollWidth = size.width + 'px'
287
476
  })
477
+
478
+ // 获取表格高度
479
+ this.$uGetRect('.u-table2').then(size => {
480
+ this.tableHeight = size.height + 'px';
481
+ })
288
482
  },
289
- },
290
- setup(props, { emit }) {
291
- const expandedKeys = ref([...props.expandRowKeys]);
292
- const selectedRows = ref([]);
293
- const sortConditions = ref([]);
294
-
295
- // 当前高亮行
296
- const currentRow = ref(null);
297
-
298
- watch(
299
- () => props.expandRowKeys,
300
- newVal => {
301
- expandedKeys.value = [...newVal];
483
+ // 将setup中的函数转换为methods
484
+ handleRowClick(row) {
485
+ if (this.highlightCurrentRow) {
486
+ const oldRow = this.currentRow;
487
+ this.currentRow = row;
488
+ this.$emit('current-change', row, oldRow);
302
489
  }
303
- );
304
-
305
- watch(
306
- () => props.currentRowKey,
307
- newVal => {
308
- const found = props.data.find(item => item[props.rowKey] === newVal);
309
- if (found) {
310
- currentRow.value = found;
311
- }
312
- }
313
- );
314
-
315
- // 过滤后的数据
316
- const filteredData = computed(() => {
317
- return props.data.filter(row => {
318
- return Object.keys(props.filters).every(key => {
319
- const filter = props.filters[key];
320
- if (!filter) return true;
321
- return row[key]?.toString().includes(filter.toString());
322
- });
323
- });
324
- });
325
-
326
- // 排序后的数据
327
- const sortedData = computed(() => {
328
- if (!sortConditions.value.length) return filteredData.value;
329
-
330
- const data = [...filteredData.value];
331
-
332
- return data.sort((a, b) => {
333
- for (const condition of sortConditions.value) {
334
- const { field, order } = condition;
335
- let valA = a[field];
336
- let valB = b[field];
337
-
338
- if (props.sortMethod) {
339
- const result = props.sortMethod(a, b, field);
340
- if (result !== 0) return result * (order === 'ascending' ? 1 : -1);
341
- }
342
-
343
- if (valA < valB) return order === 'ascending' ? -1 : 1;
344
- if (valA > valB) return order === 'ascending' ? 1 : -1;
345
- }
346
- return 0;
347
- });
348
- });
349
-
350
- function handleRowClick(row) {
351
- if (props.highlightCurrentRow) {
352
- const oldRow = currentRow.value;
353
- currentRow.value = row;
354
- emit('current-change', row, oldRow);
355
- }
356
- emit('row-click', row);
357
- }
358
-
359
- function handleHeaderClick(column) {
490
+ this.$emit('row-click', row);
491
+ },
492
+ handleHeaderClick(column) {
360
493
  if (!column.sortable) return;
361
494
 
362
- const index = sortConditions.value.findIndex(c => c.field === column.key);
495
+ const index = this.sortConditions.findIndex(c => c.field === column.key);
363
496
  let newOrder = 'ascending';
364
497
 
365
498
  if (index >= 0) {
366
- if (sortConditions.value[index].order === 'ascending') {
499
+ if (this.sortConditions[index].order === 'ascending') {
367
500
  newOrder = 'descending';
368
501
  } else {
369
- sortConditions.value.splice(index, 1);
370
- emit('sort-change', sortConditions.value);
502
+ this.sortConditions.splice(index, 1);
503
+ this.$emit('sort-change', this.sortConditions);
371
504
  return;
372
505
  }
373
506
  }
374
507
 
375
- if (!props.multiSort) {
376
- sortConditions.value = [{ field: column.key, order: newOrder }];
508
+ if (!this.multiSort) {
509
+ this.sortConditions = [{ field: column.key, order: newOrder }];
377
510
  } else {
378
511
  if (index >= 0) {
379
- sortConditions.value[index].order = newOrder;
512
+ this.sortConditions[index].order = newOrder;
380
513
  } else {
381
- sortConditions.value.push({ field: column.key, order: newOrder });
514
+ this.sortConditions.push({ field: column.key, order: newOrder });
382
515
  }
383
516
  }
384
517
 
385
- emit('sort-change', sortConditions.value);
386
- }
387
-
388
- function getSortIcon(field) {
389
- const cond = sortConditions.value.find(c => c.field === field);
518
+ this.$emit('sort-change', this.sortConditions);
519
+ },
520
+ getSortIcon(field) {
521
+ const cond = this.sortConditions.find(c => c.field === field);
390
522
  if (!cond) return '';
391
523
  return cond.order === 'ascending' ? '↑' : '↓';
392
- }
393
-
394
- function getSortValue(field) {
395
- const cond = sortConditions.value.find(c => c.field === field);
524
+ },
525
+ getSortValue(field) {
526
+ const cond = this.sortConditions.find(c => c.field === field);
396
527
  if (!cond) return '';
397
528
  return cond.order === 'ascending';
398
- }
399
-
400
- function toggleSelect(row) {
401
- const index = selectedRows.value.findIndex(r => r[props.rowKey] === row[props.rowKey]);
529
+ },
530
+ toggleSelect(row) {
531
+ const index = this.selectedRows.findIndex(r => r[this.rowKey] === row[this.rowKey]);
402
532
  if (index >= 0) {
403
- selectedRows.value.splice(index, 1);
533
+ this.selectedRows.splice(index, 1);
404
534
  } else {
405
- selectedRows.value.push(row);
535
+ this.selectedRows.push(row);
406
536
  }
407
- emit('selection-change', selectedRows.value);
408
- emit('select', row);
409
- }
410
-
411
- function isSelected(row) {
412
- return selectedRows.value.some(r => r[props.rowKey] === row[props.rowKey]);
413
- }
414
-
415
- function toggleExpand(row) {
416
- const key = row[props.rowKey];
417
- const index = expandedKeys.value.indexOf(key);
537
+ this.$emit('selection-change', this.selectedRows);
538
+ this.$emit('select', row);
539
+ },
540
+ isSelected(row) {
541
+ return this.selectedRows.some(r => r[this.rowKey] === row[this.rowKey]);
542
+ },
543
+ toggleExpand(row) {
544
+ const key = row[this.rowKey];
545
+ const index = this.expandedKeys.indexOf(key);
418
546
  if (index === -1) {
419
- expandedKeys.value.push(key);
547
+ this.expandedKeys.push(key);
420
548
  } else {
421
- expandedKeys.value.splice(index, 1);
549
+ this.expandedKeys.splice(index, 1);
422
550
  }
423
- emit('expand-change', expandedKeys.value);
424
- }
425
-
426
- function isExpanded(row) {
427
- return expandedKeys.value.includes(row[props.rowKey]);
551
+ this.$emit('expand-change', this.expandedKeys);
552
+ },
553
+ isExpanded(row) {
554
+ return this.expandedKeys.includes(row[this.rowKey]);
428
555
  }
429
-
430
- return {
431
- currentRow,
432
- sortedData,
433
- expandedKeys,
434
- selectedRows,
435
- sortConditions,
436
- handleRowClick,
437
- handleHeaderClick,
438
- getSortValue,
439
- getSortIcon,
440
- toggleSelect,
441
- isSelected,
442
- toggleExpand,
443
- isExpanded
444
- };
445
556
  }
446
557
  };
447
558
  </script>
448
559
 
449
560
  <style lang="scss" scoped>
561
+ .u-table2-wrapper {
562
+ position: relative;
563
+ }
564
+
450
565
  .u-table2 {
451
566
  width: auto;
452
567
  overflow: auto;
453
568
  white-space: nowrap;
569
+ position: relative;
454
570
 
455
571
  .u-table-header {
456
572
  min-width: 100% !important;
@@ -461,6 +577,7 @@ export default {
461
577
  .u-table-body {
462
578
  min-width: 100% !important;
463
579
  width: fit-content;
580
+ position: relative;
464
581
  }
465
582
 
466
583
  .u-table-sticky {
@@ -475,6 +592,8 @@ export default {
475
592
  align-items: center;
476
593
  border-bottom: 1rpx solid #ebeef5;
477
594
  overflow: hidden;
595
+ position: relative;
596
+ min-height: 40px;
478
597
  }
479
598
 
480
599
  .u-table-cell {
@@ -488,18 +607,6 @@ export default {
488
607
  text-overflow: ellipsis;
489
608
  }
490
609
 
491
- .u-table-fixed-left {
492
- position: sticky;
493
- left: 0;
494
- z-index: 9;
495
- }
496
-
497
- .u-table-fixed-right {
498
- position: sticky;
499
- right: 0;
500
- z-index: 9;
501
- }
502
-
503
610
  .u-table-row-zebra {
504
611
  background-color: #fafafa;
505
612
  }
@@ -526,4 +633,36 @@ export default {
526
633
  text-align: right;
527
634
  }
528
635
  }
529
- </style>
636
+
637
+ // 固定列浮动视图
638
+ .u-table-fixed-shadow {
639
+ position: absolute;
640
+ top: 0;
641
+ left: 0;
642
+ width: auto;
643
+ z-index: 20;
644
+ box-shadow: 2px 0 5px rgba(0, 0, 0, 0.15);
645
+ overflow: hidden;
646
+ background-color: #ffffff;
647
+ }
648
+
649
+ .u-table-fixed-row {
650
+ display: flex;
651
+ flex-direction: row;
652
+ align-items: center;
653
+ border-bottom: 1rpx solid #ebeef5;
654
+ position: relative;
655
+ }
656
+
657
+ .u-table-fixed-cell {
658
+ flex: 1;
659
+ display: flex;
660
+ flex-direction: row;
661
+ padding: 5px 4px;
662
+ font-size: 14px;
663
+ white-space: nowrap;
664
+ overflow: hidden;
665
+ text-overflow: ellipsis;
666
+ background-color: #fff;
667
+ }
668
+ </style>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "uview-plus",
3
3
  "name": "uview-plus",
4
4
  "displayName": "零云®uview-plus3.0重磅发布,全面的Vue3鸿蒙跨端移动组件库,组件丰富维护更新稳定。",
5
- "version": "3.4.77",
5
+ "version": "3.4.79",
6
6
  "description": "零云®uview-plus已兼容vue3,100+全面的组件和便捷的工具会让您信手拈来,如鱼得水。",
7
7
  "keywords": [
8
8
  "uview",