@sy-common/organize-select-help 1.0.0-beta.11 → 1.0.0-beta.14

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.
@@ -35,9 +35,46 @@ export default {
35
35
  this.loading = false
36
36
  this.data = data;
37
37
  },
38
- handleChange(data){
39
- this.$emit('handleChange',data)
38
+ handleChange(data) {
39
+ // 过滤出当前所有选中的节点(排除未选中的)
40
+ const checkedData = Array.isArray(data)
41
+ ? data.filter(item => item.checked)
42
+ : (data.checked ? [data] : []);
43
+ console.log(data,'checkedData')
44
+ // 同步更新子组件内部所有节点的checked状态(防止状态不一致)
45
+ this.syncAllNodeCheckedState(checkedData);
46
+
47
+ // 关键:无论选中/取消,都将最新选中列表传给父组件
48
+ this.$emit('handleChange', checkedData);
40
49
  },
50
+
51
+ // 2. 新增:同步子组件所有节点的checked状态(核心方法)
52
+ syncAllNodeCheckedState(checkedData) {
53
+ if (!Array.isArray(this.data)) return;
54
+
55
+ // 提取所有选中节点的ID,方便快速匹配
56
+ const checkedIds = checkedData.map(item => item.orgUnitId);
57
+
58
+ // 递归遍历所有节点,更新checked状态
59
+ const updateNodeState = (nodeList) => {
60
+ nodeList.forEach(node => {
61
+ // 对比选中ID列表,更新当前节点状态
62
+ const shouldBeChecked = checkedIds.includes(node.orgUnitId);
63
+ if (node.checked !== shouldBeChecked) {
64
+ this.$set(node, 'checked', shouldBeChecked); // 用$set确保响应式
65
+ }
66
+
67
+ // 递归处理子节点
68
+ const childNodes = node.children || node.orgChildrenList || [];
69
+ if (childNodes.length) {
70
+ updateNodeState(childNodes);
71
+ }
72
+ });
73
+ };
74
+
75
+ updateNodeState(this.data);
76
+ },
77
+
41
78
  async loadData(item, callback){
42
79
  // 模拟异步获取数据
43
80
  let children = await this.getOrgChildren(item.orgUnitId)
@@ -65,6 +102,137 @@ export default {
65
102
  })
66
103
  })
67
104
  },
105
+ /**
106
+ * 手动设置树节点选中状态(供父组件调用)
107
+ * @param {Array} nodes - 需要选中的节点数组(单个节点时传数组包裹)
108
+ */
109
+ setCheckedNodes(targets) {
110
+ if (!this.$refs.tree || !Array.isArray(targets)) {
111
+ this.clearAllChecked(this.data);
112
+ this.$emit('handleChange', []); // 取消时通知父组件清空
113
+ this.$nextTick(() => this.$refs.tree.$forceUpdate());
114
+ return;
115
+ }
116
+
117
+ this.clearAllChecked(this.data);
118
+ const targetIds = targets.map(item =>
119
+ typeof item === 'string' ? item : (item.orgUnitId || '')
120
+ ).filter(Boolean);
121
+
122
+ // 递归选中目标节点
123
+ const findAndCheckNode = (treeData, targetId) => {
124
+ for (const node of treeData) {
125
+ if (node.orgUnitId === targetId) {
126
+ this.$set(node, 'selected', true);
127
+ this.expandToNode(node);
128
+ return true;
129
+ }
130
+ const childNodes = node.children || node.orgChildrenList || [];
131
+ if (childNodes.length && findAndCheckNode(childNodes, targetId)) {
132
+ return true;
133
+ }
134
+ }
135
+ return false;
136
+ };
137
+
138
+ targetIds.forEach(id => findAndCheckNode(this.data, id));
139
+
140
+ // 关键:选中后主动收集选中节点,通知父组件
141
+ const checkedNodes = this.collectAllCheckedNodes(this.data);
142
+ this.$nextTick(() => {
143
+ this.$refs.tree.$forceUpdate();
144
+ this.$emit('handleChange', checkedNodes); // 同步父组件暂存数据
145
+ });
146
+ },
147
+ /**
148
+ * 【新增】递归展开到目标节点的所有父节点(确保选中节点可见)
149
+ * @param {Object} node - 目标节点
150
+ */
151
+ expandToNode(node) {
152
+ let current = node;
153
+ while (current && current.parent) {
154
+ // 修复:确保父节点是对象而非数组
155
+ if (typeof current.parent === 'object' && !Array.isArray(current.parent)) {
156
+ this.$set(current.parent, 'expand', true);
157
+ }
158
+ // 修复:正确获取上层父节点
159
+ current = current.parent.orgUnitId
160
+ ? this.findNodeInTree(this.data, current.parent.orgUnitId)
161
+ : null;
162
+ }
163
+ },
164
+ // 4. 新增:收集子组件内所有选中的节点(供同步给父组件)
165
+ collectAllCheckedNodes(nodeList) {
166
+ let checkedNodes = [];
167
+ nodeList.forEach(node => {
168
+ if (node.checked) {
169
+ checkedNodes.push(node);
170
+ }
171
+ // 递归收集子节点
172
+ const childNodes = node.children || node.orgChildrenList || [];
173
+ if (childNodes.length) {
174
+ checkedNodes = [...checkedNodes, ...this.collectAllCheckedNodes(childNodes)];
175
+ }
176
+ });
177
+ return checkedNodes;
178
+ },
179
+ /**
180
+ * 递归清空所有节点的选中状态(辅助方法)
181
+ * @param {Array} treeData - 树形数据
182
+ */
183
+ clearAllChecked(treeData) {
184
+ if (!Array.isArray(treeData)) return;
185
+ treeData.forEach(node => {
186
+ if (node.checked) {
187
+ this.$set(node, 'checked', false); // 响应式更新选中状态
188
+ }
189
+ // 同时处理两种子节点字段
190
+ const childNodes = node.children || node.orgChildrenList || [];
191
+ if (childNodes.length) {
192
+ this.clearAllChecked(childNodes);
193
+ }
194
+ });
195
+ },
196
+ /**
197
+ * 【新增】供父组件调用,手动更新子组件数据(解决数据同步问题)
198
+ * @param {Array} newTreeData - 父组件传递的新树形数据
199
+ */
200
+ updateTreeData(newTreeData) {
201
+ if (!Array.isArray(newTreeData)) return;
202
+ const tree = deepCopy(newTreeData);
203
+ this.initTree(tree); // 确保新数据经过格式转换(添加children、checked等字段)
204
+ this.data = tree; // 更新子组件内部数据
205
+ this.$nextTick(() => {
206
+ this.$refs.tree.$forceUpdate(); // 触发UI刷新
207
+ });
208
+ },
209
+ /**
210
+ * 递归查找树中的节点(辅助方法,与父组件逻辑一致,可复用)
211
+ * @param {Array} treeData - 树形数据
212
+ * @param {string} targetOrgUnitId - 目标节点ID
213
+ * @returns {Object|null} 找到的节点
214
+ */
215
+ findNodeInTree(treeData, targetOrgUnitId) {
216
+ if (!treeData || !targetOrgUnitId) return null;
217
+
218
+ for (const node of treeData) {
219
+ // 记录父节点引用(用于展开节点)
220
+ if (!node.parent && treeData !== this.data) {
221
+ node.parent = treeData; // 标记父节点,方便后续展开
222
+ }
223
+
224
+ // 找到目标节点,直接返回
225
+ if (node.orgUnitId === targetOrgUnitId) return node;
226
+
227
+ // 【关键】先遍历转换后的children,再遍历原始orgChildrenList(防止遗漏)
228
+ const childNodes = node.children || node.orgChildrenList || [];
229
+ if (childNodes.length) {
230
+ const childNode = this.findNodeInTree(childNodes, targetOrgUnitId);
231
+ if (childNode) return childNode;
232
+ }
233
+ }
234
+ return null;
235
+ },
68
236
  initTree(treeList){
69
237
  const defineTree = function(list){
70
238
  if(!list)return
@@ -104,40 +272,59 @@ export default {
104
272
  }
105
273
  })
106
274
  },
107
- renderContent(h, { root, node, data }){
275
+ // 子组件 methods 中的 renderContent 方法(修复点击节点选中逻辑)
276
+ renderContent(h, { root, node, data }) {
108
277
  return h('div', {
109
278
  style: {
110
279
  width: '100%',
111
- overflow:'hidden',
112
- display:'flex',
280
+ overflow: 'hidden',
281
+ display: 'flex',
113
282
  alignItems: 'center',
114
283
  }
115
284
  }, [
116
- h('img', {
117
- attrs: {
118
- src: require('./assets/icon.png'),
119
- },
120
- style: {
121
- marginRight: '8px',
122
- width:'14px',
123
- height:'14px',
124
- }
125
- }),
126
- h('span',{
127
- style: {
128
- overflow: 'hidden',
129
- textOverflow:'ellipsis',
130
- flex:1
131
- },
132
- on:{
133
- click:()=>{
134
- this.checkNode(data)
135
- }
285
+ h('img', {
286
+ attrs: {
287
+ src: require('./assets/icon.png'),
288
+ },
289
+ style: {
290
+ marginRight: '8px',
291
+ width: '14px',
292
+ height: '14px',
293
+ }
294
+ }),
295
+ h('span', {
296
+ style: {
297
+ overflow: 'hidden',
298
+ textOverflow: 'ellipsis',
299
+ flex: 1,
300
+ // 新增:添加选中状态样式(与直接选择保持一致)
301
+ color: data.checked ? 'var(--primary-color)' : 'inherit',
302
+ fontWeight: data.checked ? 'bold' : 'normal'
303
+ },
304
+ on: {
305
+ click: () => {
306
+ // 修复:点击节点时同步更新checked状态
307
+ this.$set(data, 'checked', !data.checked);
308
+ this.checkNode(data);
309
+ // 触发Tree组件内置选中事件
310
+ this.handleChange([data]);
136
311
  }
137
- }, data.title)
312
+ }
313
+ }, data.title),
314
+ // 新增:显示选中勾选图标(与直接选择保持视觉一致)
315
+ h('Icon', {
316
+ attrs: {
317
+ type: 'md-checkmark',
318
+ },
319
+ style: {
320
+ color: 'var(--primary-color)',
321
+ display: data.checked ? 'inline-block' : 'none',
322
+ }
323
+ })
138
324
  ]);
139
325
  },
140
326
  upDataTree(){
327
+
141
328
  const unCheck = (list)=>{
142
329
  list.forEach((item)=>{
143
330
  this.$set(item, 'selected', false);