|  | @@ -8,9 +8,8 @@
 | 
	
		
			
				|  |  |   * 1.一个请求中
 | 
	
		
			
				|  |  |   *   {删除}所有超高子目
 | 
	
		
			
				|  |  |   *   {更新}清单、定额下拉列文本
 | 
	
		
			
				|  |  | - *   {新增}清单、定额
 | 
	
		
			
				|  |  | - * 2.一个请求{刷新}项目人材机(计算需要)
 | 
	
		
			
				|  |  | - * 3.一个请求{重算被删除的定额清单节点、新增的定额节点
 | 
	
		
			
				|  |  | + *   {新增}清单、定额、定额人材机、项目人材机
 | 
	
		
			
				|  |  | + * 2.一个请求{重算被删除的定额清单节点、新增的定额节点
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |      // 选项类型,生成的超高子目所在位置
 | 
	
	
		
			
				|  | @@ -66,8 +65,8 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |      const fixedCodeReg = new RegExp(`^${fixedCode}`);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 取费专业名称
 | 
	
		
			
				|  |  | -    // const programName = '超高降效';
 | 
	
		
			
				|  |  | -    const programName = '公共建筑工程';
 | 
	
		
			
				|  |  | +     const programName = '超高降效';
 | 
	
		
			
				|  |  | +    //const programName = '公共建筑工程'; // for Test
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 指定清单表格
 | 
	
		
			
				|  |  |      let specificSpread = null;
 | 
	
	
		
			
				|  | @@ -165,7 +164,7 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |          sourceData = source || [];
 | 
	
		
			
				|  |  |          comboData = sourceData
 | 
	
		
			
				|  |  |              ? sourceData
 | 
	
		
			
				|  |  | -                .filter(item => !item.extra)
 | 
	
		
			
				|  |  | +                .filter(item => !item.extra || !JSON.parse(item.extra))
 | 
	
		
			
				|  |  |                  .map(item => item.name)
 | 
	
		
			
				|  |  |              : [];
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -173,6 +172,10 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |      function getComboData() {
 | 
	
		
			
				|  |  |          return comboData;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    // 根据名称获取下拉项索引
 | 
	
		
			
				|  |  | +    function getIndex(name) {
 | 
	
		
			
				|  |  | +        return comboData.findIndex(item => item === name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      function getOverHeightItem(value) {
 | 
	
		
			
				|  |  |          return sourceData.find(item => item.name === value);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -607,7 +610,7 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |          return nodes[nodes.length - 1]
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 将需要生成超高子目的定额数据按照挂载清单和超高名称进行分组
 | 
	
		
			
				|  |  | +    // 将需要生成超高子目的定额数据按照挂载清单和超高名称进行分组,其下数组为关联的主定额
 | 
	
		
			
				|  |  |      // @return {Object} {'billsID@overHeight': [node: rationNode]}
 | 
	
		
			
				|  |  |      function getGroupData(rationItems, mountedBillsID) {
 | 
	
		
			
				|  |  |          // mapping: billsID-overHeightName
 | 
	
	
		
			
				|  | @@ -672,23 +675,32 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |                  contain,
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        // 根据分组的keys获取定额serialNo值映射表
 | 
	
		
			
				|  |  | +        // 根据分组的keys获取定额serialNo值映射表 billsID@overHeight
 | 
	
		
			
				|  |  |          function getSerialNoMappig(groupKeys) {
 | 
	
		
			
				|  |  |              // 清单ID - serialNo映射
 | 
	
		
			
				|  |  |              const billsIDMap = {};
 | 
	
		
			
				|  |  |              // 完整的key - serialNo映射
 | 
	
		
			
				|  |  |              const keyMap = {};
 | 
	
		
			
				|  |  |              const nodes = projectObj.project.mainTree.nodes;
 | 
	
		
			
				|  |  | +            // 先给根据清单ID设置上第一个serialNo值(基准值),和超高项数据
 | 
	
		
			
				|  |  |              groupKeys.forEach(key => {
 | 
	
		
			
				|  |  | -                const [billsID] = key.split('@');
 | 
	
		
			
				|  |  | +                const [billsID, overHeight] = key.split('@');
 | 
	
		
			
				|  |  |                  if (billsIDMap[billsID]) {
 | 
	
		
			
				|  |  | -                    billsIDMap[billsID] = keyMap[key] += 1;
 | 
	
		
			
				|  |  | +                    billsIDMap[billsID].items.push(overHeight);
 | 
	
		
			
				|  |  |                      return;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  const billsNode = nodes[`id_${billsID}`];
 | 
	
		
			
				|  |  |                  const lastNormalRationNode = billsNode ? getLastNormalRationNode(billsNode) : null;
 | 
	
		
			
				|  |  |                  const serialNo = lastNormalRationNode ? lastNormalRationNode.data.serialNo + 1 : 1;
 | 
	
		
			
				|  |  | -                billsIDMap[billsID] = keyMap[key] = serialNo;
 | 
	
		
			
				|  |  | +                billsIDMap[billsID] = { serialNo, items: [overHeight] };
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +            // 将同一清单下的超高项按照下拉项位置排序
 | 
	
		
			
				|  |  | +            Object.entries(billsIDMap).forEach(([billsID, { serialNo, items }]) => {
 | 
	
		
			
				|  |  | +                items.sort((a, b) => getIndex(a) - getIndex(b));
 | 
	
		
			
				|  |  | +                items.forEach((overHeight, index) => {
 | 
	
		
			
				|  |  | +                    const key = `${billsID}@${overHeight}`;
 | 
	
		
			
				|  |  | +                    keyMap[key] = serialNo + index;
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  |              });
 | 
	
		
			
				|  |  |              return keyMap;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -841,7 +853,7 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |              const postData = generatePostData(isCancelCalc, action);
 | 
	
		
			
				|  |  |              const { addData, updateData, deleteData } = postData;
 | 
	
		
			
				|  |  |              // 更新、删除、新增数据
 | 
	
		
			
				|  |  | -            // 返回的是新增的清单、定额人材机 rst = {bills: [], rationGLJ: []}
 | 
	
		
			
				|  |  | +            // 返回的是新增的清单、定额人材机、项目人材机 rst = {bills: [], rationGLJ: [], projectGLJ: []}
 | 
	
		
			
				|  |  |              const rst = await ajaxPost('/project/calcOverHeightFee', postData);
 | 
	
		
			
				|  |  |              // 后续获取重算节点相关:
 | 
	
		
			
				|  |  |              // 新增的定额节点要在同步数据后才有,删除的定额节点在同步前找不到,因此同步前先获取被删除定额节点的清单ID列表
 | 
	
	
		
			
				|  | @@ -860,7 +872,6 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |                  return;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              // 获取项目人材机数据,更新缓存
 | 
	
		
			
				|  |  | -            await projectObj.project.projectGLJ.loadDataSync();
 | 
	
		
			
				|  |  |              $.bootstrapLoading.end(); // 重算节点相关方法里有loading,防止提前结束了loading
 | 
	
		
			
				|  |  |              // 重算相关节点
 | 
	
		
			
				|  |  |              projectObj.project.calcProgram.calcNodesAndSave(reCalcNodes);
 | 
	
	
		
			
				|  | @@ -893,6 +904,28 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |       * @return {void} 
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      function syncData(delData, updateData, addData) {
 | 
	
		
			
				|  |  | +        // 被删除数据的清单ID@定额serialNo - 价格字段映射
 | 
	
		
			
				|  |  | +        // 在新增节点时,给上原本该行的feesIndex字段,不然会出现新增节点价格为空,重算后价格有值,造成价格字段闪烁的情况
 | 
	
		
			
				|  |  | +        // 新增节点赋上原本该行的feesIndex字段只是为了避免闪烁的情况。
 | 
	
		
			
				|  |  | +        // 新节点fees数组没有赋值,后续计算的时候节点的价格字段会被初始化(calcTools.initFees中),因此这个操作不会对计算结果有影响
 | 
	
		
			
				|  |  | +        function getSerialNoFeesIndexMapping({ ration }) {
 | 
	
		
			
				|  |  | +            const mapping = {};
 | 
	
		
			
				|  |  | +            const rationIDList = ration.map(item => item.ID);
 | 
	
		
			
				|  |  | +            projectObj.project.Ration.datas
 | 
	
		
			
				|  |  | +                .filter(item => rationIDList.includes(item.ID))
 | 
	
		
			
				|  |  | +                .forEach(item => mapping[`${item.billsItemID}@${item.serialNo}`] = item.feesIndex);
 | 
	
		
			
				|  |  | +            return mapping;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 新增定额设置上暂时显示的价格字段
 | 
	
		
			
				|  |  | +        function setTemporaryFeesIndex({ ration }, feesIndexMapping) {
 | 
	
		
			
				|  |  | +            ration.forEach(item => {
 | 
	
		
			
				|  |  | +                const key = `${item.billsItemID}@${item.serialNo}`;
 | 
	
		
			
				|  |  | +                const oldFeesIndex = feesIndexMapping[key];
 | 
	
		
			
				|  |  | +                if (oldFeesIndex) {
 | 
	
		
			
				|  |  | +                    item.feesIndex = oldFeesIndex;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          // 删除数据
 | 
	
		
			
				|  |  |          function del({ ration }) {
 | 
	
		
			
				|  |  |              const sheet = projectObj.mainController.sheet;
 | 
	
	
		
			
				|  | @@ -925,7 +958,7 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |              });
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          // 插入数据
 | 
	
		
			
				|  |  | -        function add({ bills, ration, rationGLJ }) {
 | 
	
		
			
				|  |  | +        function add({ bills, ration, rationGLJ, projectGLJ }) {
 | 
	
		
			
				|  |  |              const sheet = projectObj.mainController.sheet;
 | 
	
		
			
				|  |  |              const func = () => {
 | 
	
		
			
				|  |  |                  // 插入清单数据和清单节点主树节点
 | 
	
	
		
			
				|  | @@ -934,16 +967,26 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  // 插入定额数据和定额节点
 | 
	
		
			
				|  |  |                  if (ration.length) {
 | 
	
		
			
				|  |  | +                    // 按照serialNo排序
 | 
	
		
			
				|  |  | +                    ration.sort((a, b) => a.serialNo - b.serialNo);
 | 
	
		
			
				|  |  |                      projectObj.project.Ration.addNewDataSimply(ration);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  // 插入定额人材机数据
 | 
	
		
			
				|  |  |                  if (rationGLJ.length) {
 | 
	
		
			
				|  |  |                      projectObj.project.ration_glj.addDatasToList(rationGLJ);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | +                // 插入项目人材机数据
 | 
	
		
			
				|  |  | +                if (projectGLJ.length) {
 | 
	
		
			
				|  |  | +                    projectObj.project.projectGLJ.loadNewProjectGLJToCaches(projectGLJ);
 | 
	
		
			
				|  |  | +                    // 重算消耗量
 | 
	
		
			
				|  |  | +                    projectObj.project.projectGLJ.calcQuantity();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |              TREE_SHEET_HELPER.massOperationSheet(sheet, func);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        const feesIndexMapping = getSerialNoFeesIndexMapping(delData);
 | 
	
		
			
				|  |  | +        setTemporaryFeesIndex(addData, feesIndexMapping);
 | 
	
		
			
				|  |  |          del(delData);
 | 
	
		
			
				|  |  |          update(updateData);
 | 
	
		
			
				|  |  |          add(addData);
 | 
	
	
		
			
				|  | @@ -978,76 +1021,76 @@ const OVER_HEIGHT = (() => {
 | 
	
		
			
				|  |  |          $.bootstrapLoading.end();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 返回清单与超高子目和其定额人材机映射
 | 
	
		
			
				|  |  | - * @param {Array} rations - 全部超高子目数据 
 | 
	
		
			
				|  |  | - * @param {Array} rationGLJs - 全部超高子目定额人材机数据 
 | 
	
		
			
				|  |  | - * @return {Object} - {billsItemID@超高子目编码@定额人材机编码: {quanqity, rationItemQuantity}} 
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -function getRationGLJMap(rations, rationGLJs) {
 | 
	
		
			
				|  |  | -    const mapping = {};
 | 
	
		
			
				|  |  | -    rationGLJs.forEach(rGLJ => {
 | 
	
		
			
				|  |  | -        const ration = rations.find(ration => ration.ID === rGLJ.rationID);
 | 
	
		
			
				|  |  | -        const rationCode = ration ? ration.code : '';
 | 
	
		
			
				|  |  | -        // 由于一个清单下不会存在两个相同编号的超高子目(相同编号会被自动汇总),因此这个key能确定唯一一条定额人材机
 | 
	
		
			
				|  |  | -        const key = `${rGLJ.billsItemID}@${rationCode}@${rGLJ.original_code}`;
 | 
	
		
			
				|  |  | -        mapping[key] = { quantity: rGLJ.quantity, rationItemQuantity: rGLJ.rationItemQuantity };
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    return mapping;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 比较两个清单与超高子目和其定额人材机映射表,看是否相同
 | 
	
		
			
				|  |  | -function isMappingEqual(oldMapping, newMapping) {
 | 
	
		
			
				|  |  | -    const oldKeys = Object.keys(oldMapping);
 | 
	
		
			
				|  |  | -    const newKeys = Object.keys(newMapping);
 | 
	
		
			
				|  |  | -    if (oldKeys.length !== newKeys.length) {
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 返回清单与超高子目和其定额人材机映射
 | 
	
		
			
				|  |  | +     * @param {Array} rations - 全部超高子目数据 
 | 
	
		
			
				|  |  | +     * @param {Array} rationGLJs - 全部超高子目定额人材机数据 
 | 
	
		
			
				|  |  | +     * @return {Object} - {billsItemID@超高子目编码@定额人材机编码: {quanqity, rationItemQuantity}} 
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    function getRationGLJMap(rations, rationGLJs) {
 | 
	
		
			
				|  |  | +        const mapping = {};
 | 
	
		
			
				|  |  | +        rationGLJs.forEach(rGLJ => {
 | 
	
		
			
				|  |  | +            const ration = rations.find(ration => ration.ID === rGLJ.rationID);
 | 
	
		
			
				|  |  | +            const rationCode = ration ? ration.code : '';
 | 
	
		
			
				|  |  | +            // 由于一个清单下不会存在两个相同编号的超高子目(相同编号会被自动汇总),因此这个key能确定唯一一条定额人材机
 | 
	
		
			
				|  |  | +            const key = `${rGLJ.billsItemID}@${rationCode}@${rGLJ.original_code}`;
 | 
	
		
			
				|  |  | +            mapping[key] = { quantity: rGLJ.quantity, rationItemQuantity: rGLJ.rationItemQuantity };
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return mapping;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    const isEveryKeySame = oldKeys.every(key => {
 | 
	
		
			
				|  |  | -        const oldData = oldMapping[key];
 | 
	
		
			
				|  |  | -        const newData = newMapping[key];
 | 
	
		
			
				|  |  | -        if (!newData) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 比较两个清单与超高子目和其定额人材机映射表,看是否相同
 | 
	
		
			
				|  |  | +    function isMappingEqual(oldMapping, newMapping) {
 | 
	
		
			
				|  |  | +        const oldKeys = Object.keys(oldMapping);
 | 
	
		
			
				|  |  | +        const newKeys = Object.keys(newMapping);
 | 
	
		
			
				|  |  | +        if (oldKeys.length !== newKeys.length) {
 | 
	
		
			
				|  |  |              return false;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        const quantitySame = commonUtil.similarEqual(oldData.quantity, newData.quantity);
 | 
	
		
			
				|  |  | -        const rationQuantitySame = commonUtil.similarEqual(oldData.rationItemQuantity, newData.rationItemQuantity);
 | 
	
		
			
				|  |  | -        return quantitySame && rationQuantitySame;
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    return isEveryKeySame;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 重新计取项目超高子目,超高子目的值与关联定额相关
 | 
	
		
			
				|  |  | - * 因此各种操作下改变了相关定额,都要重新计算超高子目
 | 
	
		
			
				|  |  | - * 为了降低复杂度和保证逻辑统一性,重新计取为重新走(删除新增逻辑)
 | 
	
		
			
				|  |  | - * 需要尽可能地降低操作的触发率
 | 
	
		
			
				|  |  | - * @param {type}  - 
 | 
	
		
			
				|  |  | - * @return: {type} - 
 | 
	
		
			
				|  |  | - */ 
 | 
	
		
			
				|  |  | -function reCalcOverHeightFee() {
 | 
	
		
			
				|  |  | -    const project = projectObj.project;
 | 
	
		
			
				|  |  | -    // 如果项目没有超高降效数据,项目不可用超高降效,返回
 | 
	
		
			
				|  |  | -    if (!project.isOverHeightProject()) {
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // 如果没有超高定额,返回(因此删除了选项二三、指定的清单不会触发)
 | 
	
		
			
				|  |  | -    const overHeightRations = project.Ration.datas.filter(ration => ration.type === rationType.overHeight);
 | 
	
		
			
				|  |  | -    if (!overHeightRations.length) {
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | +        const isEveryKeySame = oldKeys.every(key => {
 | 
	
		
			
				|  |  | +            const oldData = oldMapping[key];
 | 
	
		
			
				|  |  | +            const newData = newMapping[key];
 | 
	
		
			
				|  |  | +            if (!newData) {
 | 
	
		
			
				|  |  | +                return false;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            const quantitySame = commonUtil.similarEqual(oldData.quantity, newData.quantity);
 | 
	
		
			
				|  |  | +            const rationQuantitySame = commonUtil.similarEqual(oldData.rationItemQuantity, newData.rationItemQuantity);
 | 
	
		
			
				|  |  | +            return quantitySame && rationQuantitySame;
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return isEveryKeySame;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    // 获取新旧超高数据映射表,不同才需要计算
 | 
	
		
			
				|  |  | -    const overHeightRationIDs = overHeightRations.map(ration => ration.ID);
 | 
	
		
			
				|  |  | -    const overHeigtRationGLJs = project.ration_glj.datas.filter(rGLJ => overHeightRationIDs.includes(rGLJ.rationID));
 | 
	
		
			
				|  |  | -    const action = getAction();
 | 
	
		
			
				|  |  | -    const { ration, rationGLJ } = getAddData(action);
 | 
	
		
			
				|  |  | -    const oldMapping = getRationGLJMap(overHeightRations, overHeigtRationGLJs);
 | 
	
		
			
				|  |  | -    const newMapping = getRationGLJMap(ration, rationGLJ);
 | 
	
		
			
				|  |  | -    if (isMappingEqual(oldMapping, newMapping)) {
 | 
	
		
			
				|  |  | -        return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 重新计取项目超高子目,超高子目的值与关联定额相关
 | 
	
		
			
				|  |  | +     * 因此各种操作下改变了相关定额,都要重新计算超高子目
 | 
	
		
			
				|  |  | +     * 为了降低复杂度和保证逻辑统一性,重新计取为重新走(删除新增逻辑)
 | 
	
		
			
				|  |  | +     * 需要尽可能地降低操作的触发率
 | 
	
		
			
				|  |  | +     * @param {type}  - 
 | 
	
		
			
				|  |  | +     * @return: {type} - 
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    function reCalcOverHeightFee() {
 | 
	
		
			
				|  |  | +        const project = projectObj.project;
 | 
	
		
			
				|  |  | +        // 如果项目没有超高降效数据,项目不可用超高降效,返回
 | 
	
		
			
				|  |  | +        if (!project.isOverHeightProject()) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 如果没有超高定额,返回(因此删除了选项二三、指定的清单不会触发)
 | 
	
		
			
				|  |  | +        const overHeightRations = project.Ration.datas.filter(ration => ration.type === rationType.overHeight);
 | 
	
		
			
				|  |  | +        if (!overHeightRations.length) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 获取新旧超高数据映射表,不同才需要计算
 | 
	
		
			
				|  |  | +        const overHeightRationIDs = overHeightRations.map(ration => ration.ID);
 | 
	
		
			
				|  |  | +        const overHeigtRationGLJs = project.ration_glj.datas.filter(rGLJ => overHeightRationIDs.includes(rGLJ.rationID));
 | 
	
		
			
				|  |  | +        const action = getAction();
 | 
	
		
			
				|  |  | +        const { ration, rationGLJ } = getAddData(action);
 | 
	
		
			
				|  |  | +        const oldMapping = getRationGLJMap(overHeightRations, overHeigtRationGLJs);
 | 
	
		
			
				|  |  | +        const newMapping = getRationGLJMap(ration, rationGLJ);
 | 
	
		
			
				|  |  | +        if (isMappingEqual(oldMapping, newMapping)) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 存在不同,重算
 | 
	
		
			
				|  |  | +        handleConfirmed();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    // 存在不同,重算
 | 
	
		
			
				|  |  | -    handleConfirmed();
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 事件监听
 | 
	
		
			
				|  |  |      $(document).ready(() => {
 |