uview-plus 3.4.81 → 3.4.82

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,8 @@
1
+ ## 3.4.82(2025-08-11)
2
+ improvment: 优化table2递归组件逻辑
3
+
4
+ feat: 支持树状列表复选框
5
+
1
6
  ## 3.4.81(2025-08-10)
2
7
  feat: table2新增树状结构递归支持
3
8
 
@@ -61,16 +61,24 @@
61
61
  }
62
62
  </style>
63
63
  <template>
64
- <view v-for="(row, index) in rows" :key="row[rowKey]" class="u-table-row u-table-row-child u-flex-y"
65
- style="border-bottom: 0px;">
66
- <view class="u-table-row u-table-child-first" >
67
- <view v-for="(col, colIndex) in columns" :key="col.key"
68
- class="u-table-cell"
69
- :class="[col.align ? 'u-text-' + col.align : '',
70
- cellClassName ? cellClassName(row, col) : '',
71
- getFixedClass(col)
72
- ]"
73
- :style="cellStyleInner({row: row, column: col, rowIndex: index, columnIndex: colIndex, level: level})">
64
+ <view class="u-table-row u-table-row-child"
65
+ :class="[highlightCurrentRow && currentRow === row ? 'u-table-row-highlight' : '',
66
+ rowClassName ? rowClassName(row, rowIndex) : '',
67
+ stripe && rowIndex % 2 === 1 ? 'u-table-row-zebra' : ''
68
+ ]" :style="{height: rowHeight}" @click="handleRowClick(row)">
69
+ <view v-for="(col, colIndex) in columns" :key="col.key"
70
+ class="u-table-cell"
71
+ :class="[col.align ? 'u-text-' + col.align : '',
72
+ cellClassName ? cellClassName(row, col) : '',
73
+ getFixedClass(col)
74
+ ]"
75
+ :style="cellStyleInner({row: row, column: col, rowIndex: rowIndex, columnIndex: colIndex, level: level})">
76
+ <!-- 复选框列 -->
77
+ <view v-if="col.type === 'selection'">
78
+ <checkbox :checked="isSelected(row)"
79
+ @click.stop="$emit('toggleSelect', row)" />
80
+ </view>
81
+ <template v-else>
74
82
  <!-- 在mainCol列显示展开图标 -->
75
83
  <view v-if="col.key === computedMainCol && hasTree"
76
84
  @click.stop="toggleExpand(row)" :style="{width: expandWidth}">
@@ -78,55 +86,71 @@
78
86
  {{ isExpanded(row) ? '▼' : '▶' }}
79
87
  </view>
80
88
  </view>
81
- <slot name="cell" :row="row" :column="col" :prow="parentRow" :rowIndex="index" :columnIndex="colIndex" :level="level">
89
+ <slot name="cellChild" :row="row" :column="col" :prow="parentRow"
90
+ :rowIndex="rowIndex" :columnIndex="colIndex" :level="level">
82
91
  <view class="u-table-cell_content">
83
92
  {{ row[col.key] }}
84
93
  </view>
85
94
  </slot>
86
- </view>
95
+ </template>
87
96
  </view>
88
-
89
- <!-- 递归渲染更深层的子级 -->
97
+ </view>
98
+ <!-- 递归渲染更深层的子级 -->
90
99
  <template v-if="isExpanded(row) && row[treeProps.children] && row[treeProps.children].length">
91
- <table-row
92
- :rows="row[treeProps.children]"
93
- :parent-row="row"
94
- :columns="columns"
95
- :tree-props="treeProps"
96
- :row-key="rowKey"
97
- :expanded-keys="expandedKeys"
98
- :cell-style-inner="cellStyleInner"
99
- :is-expanded="isExpanded"
100
- :row-class-name="rowClassName"
101
- :stripe="stripe"
102
- :cell-class-name="cellClassName"
103
- :get-fixed-class="getFixedClass"
104
- :highlight-current-row="highlightCurrentRow"
105
- :current-row="currentRow"
106
- :handle-row-click="handleRowClick"
107
- :toggle-expand="toggleExpand"
108
- :level="level + 1"
109
- :hasTree="hasTree"
110
- :expandWidth="expandWidth"
111
- :computed-main-col="computedMainCol"
112
- @row-click="$emit('rowClick', $event)"
113
- @toggle-expand="$emit('toggleExpand', $event)"
114
- />
100
+ <template v-for="(rowChild, childIndex) in row[treeProps.children]" :key="rowChild[rowKey] || childIndex">
101
+ <table-row
102
+ :row="rowChild"
103
+ :rowIndex="childIndex"
104
+ :parent-row="row"
105
+ :columns="columns"
106
+ :tree-props="treeProps"
107
+ :row-key="rowKey"
108
+ :expanded-keys="expandedKeys"
109
+ :cell-style-inner="cellStyleInner"
110
+ :is-expanded="isExpanded"
111
+ :row-class-name="rowClassName"
112
+ :stripe="stripe"
113
+ :cell-class-name="cellClassName"
114
+ :get-fixed-class="getFixedClass"
115
+ :highlight-current-row="highlightCurrentRow"
116
+ :current-row="currentRow"
117
+ :handle-row-click="handleRowClick"
118
+ :toggle-expand="toggleExpand"
119
+ :level="level + 1"
120
+ :rowHeight="rowHeight"
121
+ :hasTree="hasTree"
122
+ :selectedRows="selectedRows"
123
+ :expandWidth="expandWidth"
124
+ :computed-main-col="computedMainCol"
125
+ @toggle-select="$emit('toggleSelect', $event)"
126
+ @row-click="$emit('rowClick', $event)"
127
+ @toggle-expand="$emit('toggleExpand', $event)"
128
+ >
129
+ <template v-slot:cellChild="scope">
130
+ <slot name="cellChild" :row="scope.row" :column="scope.column" :prow="scope.prow"
131
+ :rowIndex="scope.rowIndex" :columnIndex="scope.columnIndex" :level="level">
132
+ </slot>
133
+ </template>
134
+ </table-row>
135
+ </template>
115
136
  </template>
116
- </view>
117
137
  </template>
118
138
 
119
139
  <script>
120
140
  export default {
121
141
  name: 'tableRow',
122
142
  props: {
123
- rows: {
124
- type: Array,
143
+ row: {
144
+ type: Object,
145
+ required: true
146
+ },
147
+ rowIndex: {
148
+ type: Number,
125
149
  required: true
126
150
  },
127
151
  parentRow: {
128
152
  type: Object,
129
- required: true
153
+ default: null
130
154
  },
131
155
  columns: {
132
156
  type: Array,
@@ -201,7 +225,20 @@ export default {
201
225
  type: Boolean,
202
226
  required: false
203
227
  },
228
+ selectedRows: {
229
+ type: Array,
230
+ required: false
231
+ },
232
+ rowHeight: {
233
+ type: String,
234
+ required: true
235
+ }
204
236
  },
205
- emits: ['rowClick', 'toggleExpand']
237
+ emits: ['rowClick', 'toggleExpand', 'toggleSelect'],
238
+ methods: {
239
+ isSelected(row) {
240
+ return this.selectedRows.some(r => r[this.rowKey] === row[this.rowKey]);
241
+ }
242
+ }
206
243
  }
207
244
  </script>
@@ -28,66 +28,42 @@
28
28
  <!-- 表体 -->
29
29
  <view class="u-table-body" :style="{ minWidth: scrollWidth, maxHeight: maxHeight ? maxHeight + 'px' : 'none' }">
30
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
- <view v-if="col.key === computedMainCol && hasTree"
49
- @click.stop="toggleExpand(row)" :style="{width: expandWidth}">
50
- <view v-if="row.children && row.children.length > 0">
51
- {{ isExpanded(row) ? '▼' : '▶' }}
52
- </view>
53
- </view>
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>
60
- </view>
61
- </view>
62
-
63
- <!-- 子级渲染 (递归组件) -->
64
- <template v-if="isExpanded(row) && row[treeProps.children] && row[treeProps.children].length">
65
- <table-row
66
- :rows="row[treeProps.children]"
67
- :parent-row="row"
68
- :columns="columns"
69
- :tree-props="treeProps"
70
- :row-key="rowKey"
71
- :expanded-keys="expandedKeys"
72
- :cell-style-inner="cellStyleInner"
73
- :is-expanded="isExpanded"
74
- :row-class-name="rowClassName"
75
- :stripe="stripe"
76
- :cell-class-name="cellClassName"
77
- :get-fixed-class="getFixedClass"
78
- :highlight-current-row="highlightCurrentRow"
79
- :current-row="currentRow"
80
- :handle-row-click="handleRowClick"
81
- :toggle-expand="toggleExpand"
82
- :level="1"
83
- :hasTree="hasTree"
84
- :expandWidth="expandWidth"
85
- :computedMainCol="computedMainCol"
86
- @row-click="handleRowClick"
87
- @toggle-expand="toggleExpand"
88
- />
31
+ <table-row
32
+ v-for="(row, rowIndex) in sortedData"
33
+ :key="row[rowKey] || rowIndex"
34
+ :row="row"
35
+ :rowIndex="rowIndex"
36
+ :parent-row="null"
37
+ :columns="columns"
38
+ :tree-props="treeProps"
39
+ :row-key="rowKey"
40
+ :expanded-keys="expandedKeys"
41
+ :cell-style-inner="cellStyleInner"
42
+ :is-expanded="isExpanded"
43
+ :row-class-name="rowClassName"
44
+ :stripe="stripe"
45
+ :cell-class-name="cellClassName"
46
+ :get-fixed-class="getFixedClass"
47
+ :highlight-current-row="highlightCurrentRow"
48
+ :current-row="currentRow"
49
+ :handle-row-click="handleRowClick"
50
+ :toggle-expand="toggleExpand"
51
+ :level="1"
52
+ :rowHeight="rowHeight"
53
+ :hasTree="hasTree"
54
+ :selectedRows="selectedRows"
55
+ :expandWidth="expandWidth"
56
+ :computedMainCol="computedMainCol"
57
+ @toggle-select="toggleSelect"
58
+ @row-click="handleRowClick"
59
+ @toggle-expand="toggleExpand"
60
+ >
61
+ <template v-slot:cellChild="scope">
62
+ <slot name="cell" :row="scope.row" :column="scope.column" :prow="scope.prow"
63
+ :rowIndex="scope.rowIndex" :columnIndex="scope.columnIndex" :level="scope.level">
64
+ </slot>
89
65
  </template>
90
- </template>
66
+ </table-row>
91
67
  </template>
92
68
  <template v-else>
93
69
  <slot name="empty">
@@ -126,65 +102,42 @@
126
102
  <!-- 表体 -->
127
103
  <view class="u-table-body" :style="{ minWidth: scrollWidth, maxHeight: maxHeight ? maxHeight + 'px' : 'none' }">
128
104
  <template v-if="data && data.length > 0">
129
- <template v-for="(row, index) in sortedData" :key="row[rowKey] || index">
130
- <view class="u-table-row" :class="[highlightCurrentRow && currentRow === row ? 'u-table-row-highlight' : '',
131
- rowClassName ? rowClassName(row, index) : '',
132
- stripe && index % 2 === 1 ? 'u-table-row-zebra' : ''
133
- ]" @click="handleRowClick(row)">
134
- <view v-for="(col, colIndex) in visibleFixedLeftColumns" :key="col.key"
135
- class="u-table-cell" :class="[col.align ? 'u-text-' + col.align : '',
136
- cellClassName ? cellClassName(row, col) : '',
137
- getFixedClass(col)
138
- ]" :style="cellStyleInner({row: row, column: col,
139
- rowIndex: index, columnIndex: colIndex, level: 0})">
140
- <!-- 复选框列 -->
141
- <view v-if="col.type === 'selection'">
142
- <checkbox :checked="isSelected(row)"
143
- @click.stop="toggleSelect(row)" />
144
- </view>
145
-
146
- <!-- 默认插槽或文本 -->
147
- <slot name="cell" :row="row" :column="col"
148
- :rowIndex="index" :columnIndex="colIndex">
149
- <!-- 树形结构展开图标 -->
150
- <view v-if="col.key === computedMainCol"
151
- @click.stop="toggleExpand(row)" :style="{width: expandWidth}">
152
- <view v-if="row.children && row.children.length > 0">
153
- {{ isExpanded(row) ? '▼' : '▶' }}
154
- </view>
155
- </view>
156
- <view class="u-table-cell_content">
157
- {{ row[col.key] }}
158
- </view>
159
- </slot>
160
- </view>
161
- </view>
105
+ <template v-for="(row, rowIndex) in sortedData" :key="row[rowKey] || rowIndex">
162
106
  <!-- 子级渲染 (递归组件) -->
163
- <template v-if="isExpanded(row) && row[treeProps.children] && row[treeProps.children].length">
164
- <table-row
165
- :rows="row[treeProps.children]"
166
- :parent-row="row"
167
- :columns="visibleFixedLeftColumns"
168
- :tree-props="treeProps"
169
- :row-key="rowKey"
170
- :expanded-keys="expandedKeys"
171
- :cell-style-inner="cellStyleInner"
172
- :is-expanded="isExpanded"
173
- :row-class-name="rowClassName"
174
- :stripe="stripe"
175
- :cell-class-name="cellClassName"
176
- :get-fixed-class="getFixedClass"
177
- :highlight-current-row="highlightCurrentRow"
178
- :current-row="currentRow"
179
- :handle-row-click="handleRowClick"
180
- :toggle-expand="toggleExpand"
181
- :level="1"
182
- :expandWidth="expandWidth"
183
- :computedMainCol="computedMainCol"
184
- @row-click="handleRowClick"
185
- @toggle-expand="toggleExpand"
186
- />
187
- </template>
107
+ <table-row
108
+ :row="row"
109
+ :rowIndex="rowIndex"
110
+ :parent-row="null"
111
+ :columns="visibleFixedLeftColumns"
112
+ :tree-props="treeProps"
113
+ :row-key="rowKey"
114
+ :expanded-keys="expandedKeys"
115
+ :cell-style-inner="cellStyleInner"
116
+ :is-expanded="isExpanded"
117
+ :row-class-name="rowClassName"
118
+ :stripe="stripe"
119
+ :cell-class-name="cellClassName"
120
+ :get-fixed-class="getFixedClass"
121
+ :highlight-current-row="highlightCurrentRow"
122
+ :current-row="currentRow"
123
+ :handle-row-click="handleRowClick"
124
+ :toggle-expand="toggleExpand"
125
+ :level="1"
126
+ :rowHeight="rowHeight"
127
+ :hasTree="hasTree"
128
+ :selectedRows="selectedRows"
129
+ :expandWidth="expandWidth"
130
+ :computedMainCol="computedMainCol"
131
+ @toggle-select="toggleSelect"
132
+ @row-click="handleRowClick"
133
+ @toggle-expand="toggleExpand"
134
+ >
135
+ <template v-slot:cellChild="scope">
136
+ <slot name="cell" :row="scope.row" :column="scope.column" :prow="scope.prow"
137
+ :rowIndex="scope.rowIndex" :columnIndex="scope.columnIndex" :level="scope.level">
138
+ </slot>
139
+ </template>
140
+ </table-row>
188
141
  </template>
189
142
  </template>
190
143
  </view>
@@ -343,6 +296,10 @@ export default {
343
296
  expandWidth: {
344
297
  type: String,
345
298
  default: '25px'
299
+ },
300
+ rowHeight: {
301
+ String,
302
+ default: '40px'
346
303
  }
347
304
  },
348
305
  emits: [
@@ -363,7 +320,6 @@ export default {
363
320
  showFixedColumnShadow: false, // 是否显示固定列阴影
364
321
  fixedLeftColumns: [], // 左侧固定列
365
322
  tableHeight: 'auto', // 表格高度
366
- rowHeight: 40, // 行高
367
323
  headerHeight: 'auto', // 新增表头高度属性
368
324
  hasTree: false // 新增属性,用于判断是否存在树形结构
369
325
  }
@@ -447,7 +403,7 @@ export default {
447
403
  // 修改为排除有type值的列
448
404
  const validColumns = this.columns.filter(col => !col.type);
449
405
  let mainCol = validColumns && validColumns.length > 0 ? validColumns[0].key : '';
450
- console.log('mainCol', mainCol)
406
+ // console.log('mainCol', mainCol)
451
407
  return mainCol;
452
408
  }
453
409
  },
@@ -525,7 +481,7 @@ export default {
525
481
  };
526
482
  // 只有展开列设置padding
527
483
  if (scope.column.key == this.computedMainCol) {
528
- style.paddingLeft = (16 * (scope.level || 0)) + 2 + 'px'
484
+ style.paddingLeft = (16 * (scope.level -1 )) + 2 + 'px'
529
485
  }
530
486
  if (this.cellStyle != null) {
531
487
  let styleCalc = this.cellStyle(scope)
@@ -551,7 +507,7 @@ export default {
551
507
  })
552
508
 
553
509
  // 遍历数据列表第一层判断是否存在树形结构
554
- this.hasTree = this.data.some(item => {
510
+ this.hasTree = this.sortedData.some(item => {
555
511
  return item[this.treeProps.children] && item[this.treeProps.children].length > 0;
556
512
  });
557
513
  },
@@ -605,18 +561,22 @@ export default {
605
561
  toggleSelect(row) {
606
562
  const index = this.selectedRows.findIndex(r => r[this.rowKey] === row[this.rowKey]);
607
563
  if (index >= 0) {
564
+ // 取消选中当前行及其所有子节点
608
565
  this.selectedRows.splice(index, 1);
566
+ // 递归取消所有子节点
567
+ this.unselectChildren(row);
609
568
  } else {
569
+ // 选中当前行及其所有子节点
610
570
  this.selectedRows.push(row);
571
+ // 递归选中所有子节点
572
+ this.selectChildren(row);
611
573
  }
574
+ console.log(this.selectedRows)
612
575
  this.$emit('selection-change', this.selectedRows);
613
576
  this.$emit('select', row);
614
577
  },
615
- isSelected(row) {
616
- return this.selectedRows.some(r => r[this.rowKey] === row[this.rowKey]);
617
- },
618
578
  toggleExpand(row) {
619
- console.log(row)
579
+ // console.log(row)
620
580
  const key = row[this.rowKey];
621
581
  const index = this.expandedKeys.indexOf(key);
622
582
  if (index === -1) {
@@ -627,8 +587,40 @@ export default {
627
587
  this.$emit('expand-change', this.expandedKeys);
628
588
  },
629
589
  isExpanded(row) {
590
+ if (!row) {
591
+ return false;
592
+ }
630
593
  return this.expandedKeys.includes(row[this.rowKey]);
631
- }
594
+ },
595
+ // 新增方法:递归选中所有子节点
596
+ selectChildren(row) {
597
+ const children = row[this.treeProps.children];
598
+ if (children && children.length > 0) {
599
+ children.forEach(child => {
600
+ // 检查是否已选中,避免重复添加
601
+ const childIndex = this.selectedRows.findIndex(r => r[this.rowKey] === child[this.rowKey]);
602
+ if (childIndex === -1) {
603
+ this.selectedRows.push(child);
604
+ }
605
+ // 递归处理子节点的子节点
606
+ this.selectChildren(child);
607
+ });
608
+ }
609
+ },
610
+ // 新增方法:递归取消选中所有子节点
611
+ unselectChildren(row) {
612
+ const children = row[this.treeProps.children];
613
+ if (children && children.length > 0) {
614
+ children.forEach(child => {
615
+ const childIndex = this.selectedRows.findIndex(r => r[this.rowKey] === child[this.rowKey]);
616
+ if (childIndex >= 0) {
617
+ this.selectedRows.splice(childIndex, 1);
618
+ }
619
+ // 递归处理子节点的子节点
620
+ this.unselectChildren(child);
621
+ });
622
+ }
623
+ },
632
624
  }
633
625
  };
634
626
  </script>
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.81",
5
+ "version": "3.4.82",
6
6
  "description": "零云®uview-plus已兼容vue3,100+全面的组件和便捷的工具会让您信手拈来,如鱼得水。",
7
7
  "keywords": [
8
8
  "uview",