|
@@ -1,4 +1,4 @@
|
|
|
-'use strict';
|
|
|
+'use strict';
|
|
|
|
|
|
/**
|
|
|
*
|
|
@@ -483,71 +483,216 @@ function isOptionNode(node) {
|
|
|
return node && node.depth() % 2 === 1 && node.data.type === 0
|
|
|
}
|
|
|
|
|
|
+ // 判断蓝色子项和孙子项是否打勾了必填
|
|
|
+ function hasRequireData(node, hasRequire = false) {
|
|
|
+ if (node.children
|
|
|
+ && node.children.length
|
|
|
+ && node.children[0].children
|
|
|
+ && node.children[0].children.length
|
|
|
+ && isProcessNode(node.children[0].children[0])
|
|
|
+ ) {
|
|
|
+ node.children.forEach(subNode => {
|
|
|
+ if (subNode.children && subNode.children.length) {
|
|
|
+ subNode.children.forEach(subSubNode => {
|
|
|
+ if (subSubNode.data.required) {
|
|
|
+ hasRequire = true;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ subNode.children.forEach(subSubNode => {
|
|
|
+ hasRequire = hasRequireData(subSubNode.children);
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return hasRequire;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 这里判断有无无定额的情况,有的就返回true,没有就返回false
|
|
|
+ function isRequireData(node) {
|
|
|
+ let isRequired = true;
|
|
|
+ if (node.children && node.children.length) {
|
|
|
+ node.children.forEach(subNode => {
|
|
|
+ if (!subNode.children || !subNode.children.length) {
|
|
|
+ isRequired = false;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return isRequired;
|
|
|
+ }
|
|
|
+ // 获取选套定额
|
|
|
+ function getOptionalData(node, list = []) {
|
|
|
+ node.children.forEach(element => {
|
|
|
+ if (element.children && element.children.length) {
|
|
|
+ element.children.forEach(item => {
|
|
|
+ if (item.data.rationID) {
|
|
|
+ list.push(item.data.rationID);
|
|
|
+ } else if (isProcessNode(item)) {
|
|
|
+ getOptionalData(item, list)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取最底层的定额
|
|
|
+ // 只判断必套的和最简单的情况,选套的还没加
|
|
|
+ function getSubData(nodes, requireRation = [], optionalRation = []) {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ // node为白色,儿子为蓝色
|
|
|
+ if (isProcessNode(node.children[0])) {
|
|
|
+ getSubData(node.children, requireRation, optionalRation);
|
|
|
+ } else {
|
|
|
+ // node为蓝色
|
|
|
+ const nodeRation = [];
|
|
|
+ // 判断当前蓝色节点有没有打勾必填,有就再走一次遍历,没有就下一步判断
|
|
|
+ if (hasRequireData(node)) {
|
|
|
+ // 获取必套的逻辑
|
|
|
+ getSubData(node.children, requireRation, optionalRation);
|
|
|
+ } else {
|
|
|
+ // 判断当前蓝色节点下有没有无定额的情况,存在无定额的就下面全是选套,无无定额的情况就下面全是必套
|
|
|
+ if (isRequireData(node)) {
|
|
|
+ node.children.forEach((subNode) => {
|
|
|
+ if (subNode.children && subNode.children[0] && subNode.children[0].data.rationID) {
|
|
|
+ nodeRation.push(subNode.children[0].data.rationID);
|
|
|
+ } else {
|
|
|
+ getSubData(subNode.children, requireRation, optionalRation);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 这里是选套的逻辑
|
|
|
+ optionalRation.push(...getOptionalData(node));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nodeRation.length) requireRation.push(nodeRation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return { requireRation, optionalRation };
|
|
|
+ }
|
|
|
// 从指引节点,获取分类特征、必套定额数据
|
|
|
function getItemClassData(nodes, prefix) {
|
|
|
- const processNodes = nodes.filter(node => isProcessNode(node));
|
|
|
- const classGroups = []; // 同层必填选项的数组(二维数组)
|
|
|
- processNodes.forEach(processNode => {
|
|
|
- const classItems = [];
|
|
|
- const optionNodes = processNode.children.filter(node => isOptionNode(node));
|
|
|
- optionNodes.forEach(optionNode => {
|
|
|
- if (optionNode.parent && optionNode.parent.data.required && (!optionNode.children
|
|
|
- || !optionNode.children.length
|
|
|
- || (optionNode.children[0].data && optionNode.children[0].data.rationID)
|
|
|
- || !optionNode.children.some(node => isProcessNode(node)))) {
|
|
|
- // 必套定额
|
|
|
- const requiredRationIDs = optionNode.children && optionNode.children.length ?
|
|
|
- optionNode.children.filter(node => !!node.data.rationID).map(node => node.data.rationID) : [];
|
|
|
- classItems.push({ name: optionNode.data.name, requiredRationIDs });
|
|
|
- } else {
|
|
|
- const childrenClassItem = getItemClassData(optionNode.children, optionNode.parent && optionNode.parent.data.required ? optionNode.data.name : '');
|
|
|
- //如果返回的子项为空,但是父项又勾选了必填,则要把本身存入数组
|
|
|
- if(optionNode.parent && optionNode.parent.data.required && childrenClassItem.length === 0){
|
|
|
- classItems.push({ name: optionNode.data.name, requiredRationIDs:[] });
|
|
|
- }else{
|
|
|
- classItems.push(...childrenClassItem);
|
|
|
- }
|
|
|
+ let nodeRequireRation = [];
|
|
|
+ let optionalRationList = [];
|
|
|
+ const processNodes = nodes.filter(node => isProcessNode(node));
|
|
|
+ const classGroups = []; // 同层必填选项的数组(二维数组)
|
|
|
+ processNodes.forEach(processNode => {
|
|
|
+ const classItems = [];
|
|
|
+ const optionNodes = processNode.children.filter(node => isOptionNode(node));
|
|
|
+ optionNodes.forEach(optionNode => {
|
|
|
+ // const name = prefix ? `${prefix}@${optionNode.data.name}` : optionNode.data.name;
|
|
|
+ if (optionNode.parent && optionNode.parent.data.required && (!optionNode.children
|
|
|
+ || !optionNode.children.length
|
|
|
+ || (optionNode.children[0].data && optionNode.children[0].data.rationID)
|
|
|
+ || !optionNode.children.some(node => isProcessNode(node)))) {
|
|
|
+
|
|
|
+ // 必套定额
|
|
|
+ const requiredRationIDs = optionNode.children && optionNode.children.length ?
|
|
|
+ optionNode.children.filter(node => !!node.data.rationID).map(node => node.data.rationID) : [];
|
|
|
+ classItems.push({ name: optionNode.data.name, requiredRationIDs: [requiredRationIDs], optionalRationIDs: [] });
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if (optionNode.parent&& optionNode.parent.data.required) {
|
|
|
+ //这里就开始遍历必填项下面的节点
|
|
|
+ const { requireRation, optionalRation } = getSubData([optionNode]);
|
|
|
+ nodeRequireRation = requireRation;
|
|
|
+ optionalRationList = optionalRation;
|
|
|
+ }else {
|
|
|
+ // 非必填的蓝色节点
|
|
|
+ // 子项是否有勾中必填
|
|
|
+ if( hasRequireData(optionNode.parent)){
|
|
|
+ // 获取必套的逻辑
|
|
|
+ const { requireRation, optionalRation }= getSubData([optionNode.parent]);
|
|
|
+ nodeRequireRation = requireRation;
|
|
|
+ optionalRationList = optionalRation;
|
|
|
+ }else{
|
|
|
+ // 子项没有勾中必填
|
|
|
+ // 判断当前蓝色节点下有没有无定额的情况,存在无定额的就下面全是选套,无无定额的情况就下面全是必套
|
|
|
+ if (isRequireData(optionNode.parent)) {
|
|
|
+ optionNode.children.forEach((subNode) => {
|
|
|
+ if (subNode.children && subNode.children[0] && subNode.children[0].data.rationID) {
|
|
|
+ nodeRation.push(subNode.children[0].data.rationID);
|
|
|
+ } else {
|
|
|
+ getSubData(subNode.children);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+
|
|
|
+ // 这里是选套的逻辑
|
|
|
+ if(optionNode.children&&optionNode.children.length){
|
|
|
+ optionalRationList.push(...getOptionalData(optionNode.parent));
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // classItems.push(...getItemCharacterData(optionNode.children, optionNode.parent && optionNode.parent.data.required ? optionNode.data.name : ''));
|
|
|
+ const childrenClassItem = getItemCharacterData(optionNode.children, optionNode.parent && optionNode.parent.data.required ? optionNode.data.name : '');
|
|
|
+
|
|
|
+ //如果返回的子项为空,但是父项又勾选了必填,则要把本身存入数组
|
|
|
+ if (optionNode.parent
|
|
|
+ && optionNode.parent.data.required
|
|
|
+ && childrenClassItem.length === 0
|
|
|
+ ) {
|
|
|
+ classItems.push({ name: optionNode.data.name, requiredRationIDs: nodeRequireRation, optionalRationIDs: optionalRationList });
|
|
|
+ } else {
|
|
|
+ if (childrenClassItem.length > 0) {
|
|
|
+
|
|
|
+ childrenClassItem.map(item => {
|
|
|
+ item.requiredRationIDs =nodeRequireRation;
|
|
|
+ item.optionalRationIDs = optionalRationList;
|
|
|
+ })
|
|
|
+ }
|
|
|
+ classItems.push(...childrenClassItem);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (classItems.length) {
|
|
|
+ classGroups.push(classItems);
|
|
|
+
|
|
|
}
|
|
|
});
|
|
|
- if (classItems.length) {
|
|
|
- classGroups.push(classItems);
|
|
|
+ // 拼接上一文本
|
|
|
+ if (classGroups[0] && classGroups[0].length) {
|
|
|
+ // classGroups[0] = classGroups[0].map(name => prefix ? `${prefix}@${name}` : name);
|
|
|
+ classGroups[0] = classGroups[0].map(item => {
|
|
|
+ item.name = prefix ? `${prefix}@${item.name}` : item.name
|
|
|
+ return item;
|
|
|
+ });
|
|
|
}
|
|
|
- });
|
|
|
- // 拼接上一文本
|
|
|
- if (classGroups[0] && classGroups[0].length) {
|
|
|
-
|
|
|
- classGroups[0] = classGroups[0].map(item => {
|
|
|
- item.name = prefix ? `${prefix}@${item.name}` : item.name
|
|
|
- return item;
|
|
|
- });
|
|
|
- }
|
|
|
- // 二维数组内容排列组合
|
|
|
- while (classGroups.length > 1) {
|
|
|
- const prevClassItems = classGroups[0];
|
|
|
- const nextClassItems = classGroups[1];
|
|
|
- const mergedClassItems = [];
|
|
|
- for (let i = 0; i < prevClassItems.length; i++) {
|
|
|
- for (let j = 0; j < nextClassItems.length; j++) {
|
|
|
- // 拼接文本
|
|
|
- const mergedName = `${prevClassItems[i].name}@${nextClassItems[j].name}`;
|
|
|
- // 拼接必套定额
|
|
|
- const mergedRationIDs = [...prevClassItems[i].requiredRationIDs, ...nextClassItems[j].requiredRationIDs];
|
|
|
- mergedClassItems.push({name: mergedName, requiredRationIDs: mergedRationIDs});
|
|
|
+ // 二维数组内容排列组合
|
|
|
+ while (classGroups.length > 1) {
|
|
|
+ const prevClassItems = classGroups[0];
|
|
|
+ const nextClassItems = classGroups[1];
|
|
|
+ const mergedClassItems = [];
|
|
|
+ for (let i = 0; i < prevClassItems.length; i++) {
|
|
|
+ for (let j = 0; j < nextClassItems.length; j++) {
|
|
|
+ // 拼接文本
|
|
|
+ const mergedName = `${prevClassItems[i].name}@${nextClassItems[j].name}`;
|
|
|
+ // 拼接必套定额
|
|
|
+ const mergedRationIDs = [...prevClassItems[i].requiredRationIDs, ...nextClassItems[j].requiredRationIDs];
|
|
|
+ const mergedOptionalRationIDs = [...prevClassItems[i].optionalRationIDs, ...nextClassItems[j].optionalRationIDs]
|
|
|
+
|
|
|
+ mergedClassItems.push({ name: mergedName, requiredRationIDs: mergedRationIDs, optionalRationIDs: mergedOptionalRationIDs });
|
|
|
+ }
|
|
|
}
|
|
|
+ classGroups.splice(0, 2, mergedClassItems);
|
|
|
}
|
|
|
- classGroups.splice(0, 2, mergedClassItems);
|
|
|
- }
|
|
|
- // 去重(类别别名要唯一)
|
|
|
- const items = classGroups[0] || [];
|
|
|
- const nameMap = {};
|
|
|
- const rst = [];
|
|
|
- items.forEach(item => {
|
|
|
- if (!nameMap[item.name]) {
|
|
|
- rst.push(item);
|
|
|
- }
|
|
|
- nameMap[item.name] = true;
|
|
|
- });
|
|
|
- return rst;
|
|
|
+ // 去重(类别别名要唯一)
|
|
|
+ const items = classGroups[0] || [];
|
|
|
+ const nameMap = {};
|
|
|
+ const rst = [];
|
|
|
+ items.forEach(item => {
|
|
|
+ if (!nameMap[item.name]) {
|
|
|
+ rst.push(item);
|
|
|
+ }
|
|
|
+ nameMap[item.name] = true;
|
|
|
+ });
|
|
|
+ return rst;
|
|
|
}
|
|
|
|
|
|
// 获取选套定额:把所有分类数据的必套定额确定好了先。选套定额就是清单下所有定额除了必套的
|
|
@@ -613,7 +758,7 @@ async function generateClassData(libID) {
|
|
|
const itemClassData = getItemClassData(guidanceTree.roots); // 必套定额在这个方法内就获取了,避免重复执行递归方法
|
|
|
const allRationIDs = guidanceTree.items.filter(node => !!node.data.rationID).map(node => node.data.rationID);
|
|
|
// 选套定额ID
|
|
|
- const optionalRationIDs = getOptionalRationIDs(itemClassData, allRationIDs);
|
|
|
+ // const optionalRationIDs = getOptionalRationIDs(itemClassData, allRationIDs);
|
|
|
//if(itemClassData.length > 1000) console.log('getItemClassData end',billNode.data.name,billNode.data.code,billNode.data.ID,itemClassData.length)
|
|
|
itemClassData.forEach(item => {
|
|
|
// 错套定额
|
|
@@ -627,7 +772,7 @@ async function generateClassData(libID) {
|
|
|
name: billNode.data.name,
|
|
|
code: billNode.data.code,
|
|
|
requiredRationIDs: item.requiredRationIDs || [],
|
|
|
- optionalRationIDs,
|
|
|
+ optionalRationIDs:item.optionalRationIDs || [],
|
|
|
errorRationIDs,
|
|
|
});
|
|
|
});
|