|  | @@ -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);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      });
 |