ocpview-plus 1.2.7 → 1.2.8
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 +0 -18
- package/dist/ocpviewplus.min.esm.js +337 -50
- package/dist/ocpviewplus.min.js +14 -14
- package/package.json +1 -1
- package/src/components/masterplate/billdetailform.vue +153 -0
- package/src/components/masterplate/lefttreerightdetails.vue +1 -1
- package/src/components/tree/CompatTree.vue +267 -22
- package/src/components/tree/basetree.vue +162 -46
|
@@ -300,81 +300,140 @@ export default {
|
|
|
300
300
|
})
|
|
301
301
|
]);
|
|
302
302
|
},
|
|
303
|
-
toTreeData
|
|
303
|
+
toTreeData(expandMap = new Set(), selectedId = null) {
|
|
304
304
|
let pos = {};
|
|
305
305
|
let tree = [];
|
|
306
306
|
let i = 0;
|
|
307
|
-
|
|
307
|
+
|
|
308
|
+
const idField = this.myConfig.idField;
|
|
309
|
+
const parentField = this.myConfig.parentField;
|
|
310
|
+
const rootId = this.rootNode[idField];
|
|
311
|
+
|
|
312
|
+
const focusId = (selectedId !== null && selectedId !== undefined)
|
|
313
|
+
? selectedId
|
|
314
|
+
: this._autoExpandId;
|
|
315
|
+
|
|
308
316
|
let autoExpandParents = new Set();
|
|
309
317
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
);
|
|
318
|
+
// 根据 focusId 反查父链(并防环)
|
|
319
|
+
if (focusId !== null && focusId !== undefined) {
|
|
320
|
+
let current = this.data.find(item => item[idField] === focusId);
|
|
321
|
+
const visited = new Set();
|
|
314
322
|
|
|
315
323
|
while (current) {
|
|
316
|
-
|
|
324
|
+
const cid = current[idField];
|
|
325
|
+
if (visited.has(cid)) {
|
|
326
|
+
console.warn('[toTreeData] parent chain cycle detected:', cid);
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
visited.add(cid);
|
|
317
330
|
|
|
318
|
-
|
|
319
|
-
if (!parentId) break;
|
|
331
|
+
autoExpandParents.add(cid); // 选中节点本身 + 全部祖先都加入展开集合
|
|
320
332
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
333
|
+
const pid = current[parentField];
|
|
334
|
+
if (pid == null) break; // 注意:不要写 !pid,避免 0 被误判
|
|
335
|
+
|
|
336
|
+
current = this.data.find(item => item[idField] === pid);
|
|
324
337
|
}
|
|
325
338
|
}
|
|
326
339
|
|
|
340
|
+
|
|
327
341
|
let data = this.$Method.copy(this.data);
|
|
328
342
|
data.forEach(el => {
|
|
329
|
-
this.setSelected(el);
|
|
343
|
+
this.setSelected(el); // 保留你原逻辑
|
|
330
344
|
});
|
|
331
345
|
let tempData = this.$Method.copy(data);
|
|
346
|
+
|
|
347
|
+
// 统一状态赋值(避免到处重复写漏)
|
|
348
|
+
const applyNodeState = (node) => {
|
|
349
|
+
const nid = node[idField];
|
|
350
|
+
|
|
351
|
+
// 展开:外部传入 expandMap 或者 focusId 的祖先链
|
|
352
|
+
if (expandMap.has(nid) || autoExpandParents.has(nid)) {
|
|
353
|
+
node.expand = true;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 选中:focusId 命中
|
|
357
|
+
node.selected = (focusId !== null && focusId !== undefined && nid === focusId);
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
// 防死循环控制
|
|
361
|
+
let guard = 0;
|
|
362
|
+
const maxGuard = data.length * 5 + 20;
|
|
363
|
+
let movedInRound = 0;
|
|
364
|
+
|
|
332
365
|
while (data.length !== 0) {
|
|
333
|
-
|
|
334
|
-
const
|
|
366
|
+
const current = data[i];
|
|
367
|
+
const currentId = current[idField];
|
|
368
|
+
const parentId = current[parentField];
|
|
335
369
|
|
|
336
|
-
|
|
337
|
-
|
|
370
|
+
// 父是否存在于原始数据(判断孤儿)
|
|
371
|
+
const index = tempData.findIndex(item => item[idField] === parentId);
|
|
338
372
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
373
|
+
if (parentId === rootId || index < 0) {
|
|
374
|
+
applyNodeState(current);
|
|
342
375
|
|
|
343
|
-
|
|
344
|
-
tree.
|
|
345
|
-
pos[data[i][this.myConfig.idField]] = [tree.length - 1];
|
|
376
|
+
tree.push(current);
|
|
377
|
+
pos[currentId] = [tree.length - 1];
|
|
346
378
|
data.splice(i, 1);
|
|
347
379
|
i--;
|
|
380
|
+
movedInRound++;
|
|
348
381
|
} else {
|
|
349
|
-
|
|
382
|
+
const posArr = pos[parentId];
|
|
350
383
|
if (posArr) {
|
|
351
384
|
let obj = tree[posArr[0]];
|
|
352
|
-
for (
|
|
385
|
+
for (let j = 1; j < posArr.length; j++) {
|
|
353
386
|
obj = obj.children[posArr[j]];
|
|
354
387
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
obj.children.
|
|
360
|
-
pos[data[i][this.myConfig.idField]] = posArr.concat([obj.children.length - 1]);
|
|
388
|
+
|
|
389
|
+
applyNodeState(current);
|
|
390
|
+
|
|
391
|
+
obj.children.push(current);
|
|
392
|
+
pos[currentId] = posArr.concat([obj.children.length - 1]);
|
|
361
393
|
data.splice(i, 1);
|
|
362
394
|
i--;
|
|
395
|
+
movedInRound++;
|
|
363
396
|
}
|
|
364
397
|
}
|
|
398
|
+
|
|
365
399
|
i++;
|
|
366
400
|
if (i > data.length - 1) {
|
|
401
|
+
// 一轮下来没挂上任何节点 -> 环/坏链路,兜底退出
|
|
402
|
+
if (movedInRound === 0 && data.length > 0) {
|
|
403
|
+
console.warn('[toTreeData] unresolved/cyclic nodes, force attach to root level:', data);
|
|
404
|
+
|
|
405
|
+
data.forEach(node => {
|
|
406
|
+
applyNodeState(node);
|
|
407
|
+
const nid = node[idField];
|
|
408
|
+
tree.push(node);
|
|
409
|
+
pos[nid] = [tree.length - 1];
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
data = [];
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
movedInRound = 0;
|
|
367
417
|
i = 0;
|
|
418
|
+
|
|
419
|
+
guard++;
|
|
420
|
+
if (guard > maxGuard) {
|
|
421
|
+
console.warn('[toTreeData] safety break triggered');
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
368
424
|
}
|
|
369
425
|
}
|
|
426
|
+
|
|
427
|
+
|
|
370
428
|
if (this.myConfig.showRootNode) {
|
|
371
|
-
let root =
|
|
372
|
-
title:
|
|
429
|
+
let root = {
|
|
430
|
+
title: ' ' + this.myConfig.rootNode.name,
|
|
373
431
|
expand: true,
|
|
374
|
-
disabled
|
|
432
|
+
disabled: this.myConfig.readOnly,
|
|
375
433
|
children: tree,
|
|
376
|
-
selected:false
|
|
434
|
+
selected: false
|
|
377
435
|
};
|
|
436
|
+
|
|
378
437
|
if (this.myConfig.rootNode.disabled !== undefined) {
|
|
379
438
|
root.disabled = this.myConfig.rootNode.disabled;
|
|
380
439
|
}
|
|
@@ -386,18 +445,15 @@ export default {
|
|
|
386
445
|
root = this.setIcon(root);
|
|
387
446
|
}
|
|
388
447
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
root.render = this.iconRender;
|
|
393
|
-
}
|
|
448
|
+
|
|
449
|
+
root.render = this.myConfig.nodeRender ? this.myConfig.nodeRender : this.iconRender;
|
|
450
|
+
|
|
394
451
|
this._autoExpandId = null;
|
|
395
452
|
return [root];
|
|
396
453
|
} else {
|
|
397
454
|
this._autoExpandId = null;
|
|
398
455
|
return tree;
|
|
399
456
|
}
|
|
400
|
-
|
|
401
457
|
},
|
|
402
458
|
setSelected (reTemp) {
|
|
403
459
|
if (this.myConfig.expand) {
|
|
@@ -742,7 +798,70 @@ export default {
|
|
|
742
798
|
updateNode(this.data)
|
|
743
799
|
|
|
744
800
|
},
|
|
745
|
-
|
|
801
|
+
|
|
802
|
+
setNodes(data = [], name, value) {
|
|
803
|
+
let tempName = name;
|
|
804
|
+
if (name === 'readOnly') {
|
|
805
|
+
tempName = 'disabled';
|
|
806
|
+
} else if (name === 'selected') {
|
|
807
|
+
tempName = (this.myConfig.multiSelect && this.myConfig.showCheckBox) ? 'checked' : 'selected';
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const responseId = this.myConfig.idField || this.myConfig.responseId;
|
|
811
|
+
|
|
812
|
+
// 统一字符串,避免 1 / "1" 不匹配
|
|
813
|
+
const idSet = new Set(
|
|
814
|
+
(data || []).map(item => String(item?.[responseId]))
|
|
815
|
+
);
|
|
816
|
+
|
|
817
|
+
// 确认真实渲染源
|
|
818
|
+
const source = Array.isArray(this.data)
|
|
819
|
+
? this.data
|
|
820
|
+
: (Array.isArray(this.treeData) ? this.treeData : []);
|
|
821
|
+
|
|
822
|
+
let hitCount = 0;
|
|
823
|
+
|
|
824
|
+
const updateNode = (nodes) => {
|
|
825
|
+
if (!Array.isArray(nodes)) return;
|
|
826
|
+
|
|
827
|
+
nodes.forEach(node => {
|
|
828
|
+
const exists = idSet.has(String(node?.[responseId]));
|
|
829
|
+
if (exists) hitCount++;
|
|
830
|
+
|
|
831
|
+
let newValue;
|
|
832
|
+
|
|
833
|
+
// 只有“选中=true”时,才清空其他节点(单选常见需求)
|
|
834
|
+
if (name === 'selected' && value === true) {
|
|
835
|
+
newValue = exists;
|
|
836
|
+
} else if (exists) {
|
|
837
|
+
// 其他场景只改命中节点
|
|
838
|
+
newValue = value;
|
|
839
|
+
} else {
|
|
840
|
+
newValue = node[tempName];
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
if (node[tempName] !== newValue) {
|
|
844
|
+
// Vue2: 动态键必须用 $set 才响应
|
|
845
|
+
// this.$set(node, tempName, newValue);
|
|
846
|
+
node[tempName] = newValue;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
if (node.children && node.children.length > 0) {
|
|
850
|
+
updateNode(node.children);
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
};
|
|
854
|
+
|
|
855
|
+
updateNode(source);
|
|
856
|
+
|
|
857
|
+
// 兜底触发视图更新
|
|
858
|
+
if (source === this.data) this.data = [...source];
|
|
859
|
+
if (source === this.treeData) this.treeData = [...source];
|
|
860
|
+
|
|
861
|
+
console.log('[setNodes]', { tempName, responseId, targetIds: [...idSet], hitCount });
|
|
862
|
+
return hitCount;
|
|
863
|
+
},
|
|
864
|
+
setNodes2(data, name, value) {
|
|
746
865
|
let tempName = name;
|
|
747
866
|
if (name === 'readOnly') {
|
|
748
867
|
tempName = 'disabled';
|
|
@@ -753,7 +872,7 @@ export default {
|
|
|
753
872
|
tempName = 'selected';
|
|
754
873
|
}
|
|
755
874
|
}
|
|
756
|
-
let responseId = this.myConfig.responseId;
|
|
875
|
+
let responseId = this.myConfig.idField || this.myConfig.responseId;
|
|
757
876
|
// 把目标列表变成 Set,提高查找效率
|
|
758
877
|
const idSet = new Set(
|
|
759
878
|
data.map(item => item[responseId])
|
|
@@ -802,14 +921,12 @@ export default {
|
|
|
802
921
|
return expandSet;
|
|
803
922
|
},
|
|
804
923
|
updateNode(data, flag) {
|
|
805
|
-
|
|
806
924
|
const idField = this.myConfig.idField
|
|
807
925
|
const parentField = this.myConfig.parentField
|
|
808
926
|
const targetId = data[idField]
|
|
809
927
|
|
|
810
928
|
// ① 保存当前展开状态
|
|
811
929
|
const expandSet = this.saveExpandState()
|
|
812
|
-
|
|
813
930
|
// ② 数据更新
|
|
814
931
|
const index = this.data.findIndex(
|
|
815
932
|
el => el[idField] === targetId
|
|
@@ -843,7 +960,6 @@ export default {
|
|
|
843
960
|
this.data.splice(index, 1)
|
|
844
961
|
}
|
|
845
962
|
}
|
|
846
|
-
|
|
847
963
|
// ③ 重建树(带展开状态)
|
|
848
964
|
this.treeData = this.toTreeData(expandSet, targetId)
|
|
849
965
|
},
|