|
@@ -2597,32 +2597,16 @@ const billsGuidance = (function () {
|
|
|
}
|
|
|
|
|
|
// 判断蓝色子项和孙子项是否打勾了必填
|
|
|
- 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;
|
|
|
+ function hasRequireData(node) {
|
|
|
+ const requiredList = node.getPosterity().filter(subNode =>
|
|
|
+ subNode.data.required === true
|
|
|
+ );
|
|
|
+ if (requiredList.length) { return true }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
// 这里判断有无无定额的情况,有的就返回true,没有就返回false
|
|
|
- function isRequireData(node) {
|
|
|
+ function isAllRationData(node) {
|
|
|
let isRequired = true;
|
|
|
if (node.children && node.children.length) {
|
|
|
node.children.forEach(subNode => {
|
|
@@ -2631,83 +2615,146 @@ const billsGuidance = (function () {
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
+ //这里是兼容第一层直接是定额的白色节点
|
|
|
+ if (node.children && node.children.length) {
|
|
|
+ node.children.forEach(subNode => {
|
|
|
+ if (subNode.data.rationID) {
|
|
|
+ isRequired = true;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
return isRequired;
|
|
|
}
|
|
|
// 获取选套定额
|
|
|
function getOptionalData(node, list = []) {
|
|
|
- if(isProcessNode(node)){
|
|
|
+ if (isProcessNode(node)) {
|
|
|
node.children.forEach(element => {
|
|
|
if (element.children && element.children.length) {
|
|
|
element.children.forEach(item => {
|
|
|
if (item.data.rationID) {
|
|
|
- list.push(item.data.name);
|
|
|
+ list.push(item.data.rationID);
|
|
|
} else if (isProcessNode(item)) {
|
|
|
getOptionalData(item, list)
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
});
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
node.children.forEach(element => {
|
|
|
if (element.data.rationID) {
|
|
|
- list.push(element.data.name);
|
|
|
- }
|
|
|
+ list.push(element.data.rationID);
|
|
|
+ }
|
|
|
});
|
|
|
}
|
|
|
-
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
- // 获取最底层的定额
|
|
|
- // 只判断必套的和最简单的情况,选套的还没加
|
|
|
- function getSubData(nodes, requireRation = [], optionalRation = [],hasRequire=false) {
|
|
|
- if(hasRequire){
|
|
|
- debugger;
|
|
|
- }
|
|
|
- nodes.forEach(node => {
|
|
|
- if (node.children && node.children.length > 0) {
|
|
|
- // node为白色,儿子为蓝色
|
|
|
- if (isProcessNode(node.children[0])) {
|
|
|
- getSubData(node.children, requireRation, optionalRation,hasRequire);
|
|
|
- } else {
|
|
|
- // node为蓝色
|
|
|
- const nodeRation = [];
|
|
|
- // 判断当前蓝色节点有没有打勾必填,有就再走一次遍历,没有就下一步判断
|
|
|
- if (hasRequireData(node)) {
|
|
|
- // 获取必套的逻辑
|
|
|
- getSubData(node.children, requireRation, optionalRation,true);
|
|
|
+
|
|
|
+ //获取定额数据
|
|
|
+ // requireRationData必套定额对象
|
|
|
+ // optionalRationData 选逃定额对象
|
|
|
+ // classGroups classCode文字和id键值对
|
|
|
+ // classCodeList 各个classCode的pID和ID的关系
|
|
|
+ function getItemData(nodes, requireRationData={}, optionalRationData={}, classGroups={}, prefixID = '', prefixSonID = '',IDData={}) {
|
|
|
+ const processNodes = nodes.filter(node => isProcessNode(node));
|
|
|
+ // const classGroups = []; // 同层必填选项的数组(二维数组)
|
|
|
+ processNodes.forEach(processNode => {
|
|
|
+ // 蓝色节点,必填
|
|
|
+ if (processNode.data.required) {
|
|
|
+ // 白色节点
|
|
|
+ const optionNodes = processNode.children.filter(node => isOptionNode(node));
|
|
|
+ optionNodes.forEach(optionNode => {
|
|
|
+ if (!requireRationData[optionNode.data.ID]) requireRationData[optionNode.data.ID] = [];
|
|
|
+ if (!optionalRationData[optionNode.data.ID]) optionalRationData[optionNode.data.ID] = [];
|
|
|
+ //白色节点下没有蓝色节点,就是到底了
|
|
|
+ if (!optionNode.children.some(subOptionNode => isProcessNode(subOptionNode))) {
|
|
|
+ // 是否必套定额
|
|
|
+ if (isAllRationData(optionNode)) {
|
|
|
+ optionNode.children.forEach(subOptionNode => {
|
|
|
+ requireRationData[optionNode.data.ID].push([subOptionNode.data.rationID]);
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ optionalRationData[optionNode.data.ID] = getOptionalData(optionNode);
|
|
|
+ }
|
|
|
+ const kV = {};
|
|
|
+ kV[optionNode.data.ID] = optionNode.data.name;
|
|
|
+ Object.assign(classGroups, kV);
|
|
|
} 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.name);
|
|
|
+ const kV = {};
|
|
|
+ kV[optionNode.data.ID] = optionNode.data.name;
|
|
|
+ Object.assign(classGroups, kV);
|
|
|
+ // 后代项是否有必填
|
|
|
+ if (hasRequireData(optionNode)) {
|
|
|
+ //后代项有必填
|
|
|
+ prefixSonID='';
|
|
|
+ getItemData(optionNode.children, requireRationData, optionalRationData, classGroups, optionNode.data.ID,prefixSonID,IDData);
|
|
|
+ } else {
|
|
|
+ //后代项无必填
|
|
|
+ optionNode.children.forEach(subOptionNode => {
|
|
|
+ // 是否必套定额
|
|
|
+ if (isAllRationData(optionNode)) {
|
|
|
+ if (!requireRationData[subOptionNode.parent.data.ID]) requireRationData[subOptionNode.parent.data.ID] = [];
|
|
|
+ requireRationData[subOptionNode.parent.data.ID].push(getOptionalData(subOptionNode));
|
|
|
} else {
|
|
|
- getSubData(subNode.children, requireRation, optionalRation,hasRequire);
|
|
|
+ if (!optionalRationData[subOptionNode.parent.data.ID]) optionalRationData[subOptionNode.data.ID] = [];
|
|
|
+ optionalRationData[subOptionNode.parent.data.ID].push(...getOptionalData(subOptionNode));
|
|
|
}
|
|
|
})
|
|
|
- } else {
|
|
|
- // 这里是选套的逻辑
|
|
|
- optionalRation.push(...getOptionalData(node));
|
|
|
}
|
|
|
}
|
|
|
- if (nodeRation.length) requireRation.push(nodeRation);
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 蓝色节点,非必填
|
|
|
+ if (hasRequireData(processNode)) {
|
|
|
+ //后代项有必填
|
|
|
+ if(isProcessNode(processNode)){
|
|
|
+ //蓝色
|
|
|
+ processNode.children.forEach((subProcessNode)=>{
|
|
|
+ subProcessNode.children.forEach((sSubProcessNode)=>{
|
|
|
+ //这里是特殊处理,因为原来的逻辑是直接把定额绑到必填白色选项中下面的,每个蓝色的一组,但是这样是不对的,需要绑定在必填白色选项下的蓝色节点,所以这里就需要传入蓝色节点的id
|
|
|
+ const requireChildrenID=sSubProcessNode.parent.data.required?prefixSonID:sSubProcessNode.data.ID;
|
|
|
+ IDData[sSubProcessNode.data.ID]=prefixID;
|
|
|
+ getItemData(
|
|
|
+ [sSubProcessNode],
|
|
|
+ requireRationData,
|
|
|
+ optionalRationData,
|
|
|
+ classGroups,
|
|
|
+ prefixID,
|
|
|
+ requireChildrenID,
|
|
|
+ IDData
|
|
|
+
|
|
|
+ )
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let key = processNode.data.ID;
|
|
|
+ if (prefixID) key = prefixID;
|
|
|
+ if (prefixSonID) key = prefixSonID;
|
|
|
+ // 是否必套定额
|
|
|
+ if (isAllRationData(processNode)) {
|
|
|
+ if (!requireRationData[key]) requireRationData[key] = [];
|
|
|
+ requireRationData[key].push(getOptionalData(processNode));
|
|
|
+ } else {
|
|
|
+ if (!optionalRationData[key]) optionalRationData[key] = [];
|
|
|
+ optionalRationData[key].push(...getOptionalData(processNode));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
- return { requireRation, optionalRation };
|
|
|
+ return { requireRationData, optionalRationData, classGroups,IDData}
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
/* 生成特征分类: 前端测试使用,想要前端测试,需要在zhiyin.html中,将id=generate-classa的按钮放开 */
|
|
|
- function getItemCharacterData(nodes, prefix) {
|
|
|
+ function getItemCharacterData(nodes, prefix ,prefixID) {
|
|
|
const processNodes = nodes.filter(node => isProcessNode(node));
|
|
|
const classGroups = []; // 同层必填选项的数组(二维数组)
|
|
|
processNodes.forEach(processNode => {
|
|
|
const classItems = [];
|
|
|
const optionNodes = processNode.children.filter(node => isOptionNode(node));
|
|
|
- let nodeRequireRation = [];
|
|
|
- let optionalRationList = [];
|
|
|
optionNodes.forEach(optionNode => {
|
|
|
// const name = prefix ? `${prefix}@${optionNode.data.name}` : optionNode.data.name;
|
|
|
if (optionNode.parent && optionNode.parent.data.required && (!optionNode.children
|
|
@@ -2716,78 +2763,44 @@ const billsGuidance = (function () {
|
|
|
|| !optionNode.children.some(node => isProcessNode(node)))) {
|
|
|
|
|
|
// 必套定额
|
|
|
- const requiredRationIDs = optionNode.children && optionNode.children.length ?
|
|
|
- optionNode.children.filter(node => !!node.data.rationID).map(node => node.data.name) : [];
|
|
|
- classItems.push({ name: optionNode.data.name, requiredRationIDs: [requiredRationIDs], optionalRationIDs: [] });
|
|
|
+ classItems.push({ name: optionNode.data.name, ID: optionNode.data.ID });
|
|
|
|
|
|
} 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 {
|
|
|
- // 这里是选套的逻辑
|
|
|
- optionalRationList.push(...getOptionalData(optionNode));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
// 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 : '');
|
|
|
- console.log(childrenClassItem);
|
|
|
- console.log({optionNode:optionNode.data.name,nodeRequireRation, optionalRationList});
|
|
|
- // debugger
|
|
|
+ const childrenClassItem = getItemCharacterData(
|
|
|
+ optionNode.children,
|
|
|
+ optionNode.parent && optionNode.parent.data.required ? optionNode.data.name : '' ,
|
|
|
+ optionNode.parent && optionNode.parent.data.required ? optionNode.data.ID : ''
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
//如果返回的子项为空,但是父项又勾选了必填,则要把本身存入数组
|
|
|
if (optionNode.parent
|
|
|
&& optionNode.parent.data.required
|
|
|
&& childrenClassItem.length === 0
|
|
|
) {
|
|
|
- classItems.push({ name: optionNode.data.name, requiredRationIDs: nodeRequireRation, optionalRationIDs: optionalRationList });
|
|
|
+ classItems.push({ name: optionNode.data.name,ID: optionNode.data.ID });
|
|
|
} else {
|
|
|
- if (childrenClassItem.length > 0) {
|
|
|
- childrenClassItem.map(item => {
|
|
|
- item.requiredRationIDs =nodeRequireRation;
|
|
|
- item.optionalRationIDs = optionalRationList;
|
|
|
- })
|
|
|
- }
|
|
|
+
|
|
|
classItems.push(...childrenClassItem);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
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
|
|
|
+ item.ID = prefixID ? `${prefixID}@${item.ID}` : item.ID
|
|
|
return item;
|
|
|
});
|
|
|
}
|
|
|
- // debugger
|
|
|
// 二维数组内容排列组合
|
|
|
while (classGroups.length > 1) {
|
|
|
const prevClassItems = classGroups[0];
|
|
@@ -2797,11 +2810,8 @@ const billsGuidance = (function () {
|
|
|
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 });
|
|
|
+ const mergedID = `${prevClassItems[i].ID}@${nextClassItems[j].ID}`;
|
|
|
+ mergedClassItems.push({ name: mergedName,ID:mergedID});
|
|
|
}
|
|
|
}
|
|
|
classGroups.splice(0, 2, mergedClassItems);
|
|
@@ -2820,44 +2830,94 @@ const billsGuidance = (function () {
|
|
|
}
|
|
|
|
|
|
// 获取选套定额:把所有分类数据的必套定额确定好了先。选套定额就是清单下所有定额除了必套的
|
|
|
- function getOptionalRationIDs(itemClassData, guideNodes) {
|
|
|
- // 所有必套定额
|
|
|
- let requiredRationIDs = [];
|
|
|
- itemClassData.forEach(item => {
|
|
|
- if (item.requiredRationIDs) {
|
|
|
- requiredRationIDs.push(...item.requiredRationIDs);
|
|
|
- }
|
|
|
- });
|
|
|
- requiredRationIDs = [...new Set(requiredRationIDs)];
|
|
|
- // 选套定额就是清单下所有定额除了必套的
|
|
|
- const optionalRationIDs = [];
|
|
|
- guideNodes.forEach(node => {
|
|
|
- if (node.data.rationID && !requiredRationIDs.includes(node.data.rationID)) {
|
|
|
- optionalRationIDs.push(node.data.rationID);
|
|
|
- }
|
|
|
- });
|
|
|
+ function getOptionalRationIDs(optionalRationData) {
|
|
|
+ const optionalRationIDs=[];
|
|
|
+ Object.values(optionalRationData).forEach(optionalRation=>{
|
|
|
+ if(optionalRation.length) optionalRationIDs.push(...optionalRation);
|
|
|
+ })
|
|
|
return [...new Set(optionalRationIDs)];
|
|
|
}
|
|
|
|
|
|
// 获取错套定额:清单下所有定额,除了分类对应的必套、选套定额
|
|
|
- function getErrorRationIDs(requiredRationIDs, optionalRationIDs, guideNodes) {
|
|
|
+ function getErrorRationIDs(requiredRationIDList, optionalRationIDs, guideNodes) {
|
|
|
+ const finRequireData=[];
|
|
|
+ requiredRationIDList.forEach(requiredRationIDs=>{
|
|
|
+ finRequireData.push(...requiredRationIDs);
|
|
|
+ })
|
|
|
const errorRationIDs = [];
|
|
|
guideNodes.forEach(node => {
|
|
|
- if (node.data.rationID && !requiredRationIDs.includes(node.data.rationID) && !optionalRationIDs.includes(node.data.rationID)) {
|
|
|
+ if (node.data.rationID && !finRequireData.includes(node.data.rationID) && !optionalRationIDs.includes(node.data.rationID)) {
|
|
|
errorRationIDs.push(node.data.rationID);
|
|
|
}
|
|
|
});
|
|
|
return [...new Set(errorRationIDs)];
|
|
|
}
|
|
|
|
|
|
+ //把classcode和必套选套定额结合在一起
|
|
|
+ function combineData(codeData,requireRationData,classGroups,IDData){
|
|
|
+ //这里需要把绑定在子节点的定额更新到必填的白色选项中(classcode的值)
|
|
|
+ const requireCombineData={};
|
|
|
+ Object.keys(IDData).forEach(key=>{
|
|
|
+ if(!requireCombineData[IDData[key]])requireCombineData[IDData[key]]=new Set();
|
|
|
+ if(requireRationData[key]){
|
|
|
+ requireRationData[key].forEach(subData=>{
|
|
|
+ subData.forEach(subItem=>{
|
|
|
+ requireCombineData[IDData[key]].add(subItem);
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return codeData.map(classCodeData=>{
|
|
|
+ const errorRationIDs=[];
|
|
|
+ const optionalRationIDs=[];
|
|
|
+ const requiredRationIDs=[];
|
|
|
+ let name='';
|
|
|
+ const classCodeIDs=classCodeData.ID;
|
|
|
+ if(/@/.test(classCodeIDs)){
|
|
|
+ classCodeIDs.split('@').forEach((classCodeID)=>{
|
|
|
+ if(name){
|
|
|
+ name=name+'@'+classGroups[classCodeID]
|
|
|
+ }else{
|
|
|
+ name=classGroups[classCodeID]
|
|
|
+ };
|
|
|
+ const unitRation=[];
|
|
|
+ requireRationData[classCodeID].forEach(subItem=>{
|
|
|
+ unitRation.push(...new Set(subItem));
|
|
|
+ })
|
|
|
+ if(requireRationData[classCodeID]&&requireRationData[classCodeID].length) {
|
|
|
+ requiredRationIDs.push(unitRation);
|
|
|
+ }
|
|
|
+ if(requireCombineData[classCodeID]&&requireCombineData[classCodeID].size){
|
|
|
+ requiredRationIDs.push([...requireCombineData[classCodeID]]);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return {name,requiredRationIDs,optionalRationIDs,errorRationIDs}
|
|
|
+ }else{
|
|
|
+ const unitRation=[];
|
|
|
+ requireRationData[classCodeIDs].forEach(subItem=>{
|
|
|
+ unitRation.push(...new Set(subItem));
|
|
|
+ })
|
|
|
+ name=classGroups[classCodeIDs];
|
|
|
+ if(requireRationData[classCodeIDs]&&requireRationData[classCodeIDs].length) requiredRationIDs.push(unitRation);
|
|
|
+ if(requireCombineData[classCodeIDs]&&requireCombineData[classCodeIDs].size) requiredRationIDs.push([...requireCombineData[classCodeIDs]]);
|
|
|
+ return {name,requiredRationIDs,optionalRationIDs,errorRationIDs}
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
$('#generate-class').click(() => {
|
|
|
if (bills.tree.selected && bills.tree.selected.guidance.tree) {
|
|
|
- const classData = getItemCharacterData(bills.tree.selected.guidance.tree.roots);
|
|
|
- const optionalRationIDs = getOptionalRationIDs(classData, bills.tree.selected.guidance.tree.items);
|
|
|
+ const classCodeData = getItemCharacterData(bills.tree.selected.guidance.tree.roots);
|
|
|
+ const {requireRationData,optionalRationData,classGroups,IDData} = getItemData(bills.tree.selected.guidance.tree.roots);
|
|
|
+ const classData= combineData(classCodeData,requireRationData,classGroups,IDData);
|
|
|
+ //因为所有的选套都是一样的,所以这里就直接赋值了
|
|
|
+ const optionalRationIDs = getOptionalRationIDs(optionalRationData);
|
|
|
classData.forEach(item => {
|
|
|
+ item.optionalRationIDs=optionalRationIDs
|
|
|
item.errorRationIDs = getErrorRationIDs(item.requiredRationIDs, optionalRationIDs, bills.tree.selected.guidance.tree.items);
|
|
|
})
|
|
|
- console.log(optionalRationIDs);
|
|
|
+ // console.log(optionalRationIDs);
|
|
|
console.log(classData);
|
|
|
}
|
|
|
});
|