| 
					
				 | 
			
			
				@@ -12,6 +12,18 @@ const colDefineType = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     match: 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     pos: 2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const mainReg = /^(GD*)?G?(\d\d)*\d$/i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const subReg = /^(GD*)?G?[A-Z]{2}(\d\d)+$/i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const gdXmjPartReg = /^(GD*)?G?/; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const specCode106 = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    code: ['102', '103', '104'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    reg: /^(GD*)?G?106/i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const specCode109 = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    code: ['102', '103', '104', '105', '106', '107', '108'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    reg: /^(GD*)?G?109/i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const aeUtils = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     toNumber: function (value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let num = _.toNumber(value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -42,21 +54,19 @@ const aeUtils = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return colsDef; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    isMatch11(tempData) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return _.find(tempData, x => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return x.code.indexOf('-') > 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    isMatch18(tempData) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return _.every(tempData, x => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return !x.code || !!x.code.match(mainReg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const mainReg = /^(GD*)?G?(\d\d)*\d$/i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const subReg = /^(GD*)?G?[A-Z]{2}(\d\d)+$/i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const gdXmjPartReg = /^(GD*)?G?/; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const specCode106 = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    code: ['102', '103', '104'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    reg: /^(GD*)?G?106/i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const specCode109 = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    code: ['102', '103', '104', '105', '106', '107', '108'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    reg: /^(GD*)?G?109/i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class ImportBaseTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * 构造函数 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -362,11 +372,9 @@ class ImportStd18Tree extends ImportBaseTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      * @private 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     _checkParent(parent, code) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (code === 'LJ0703') console.log(parent.code, code); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const codeNumberPart = code.replace(gdXmjPartReg, ''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!parent.code) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const numberPart = parent.code.replace(gdXmjPartReg, ''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (code === 'LJ0703') console.log(numberPart, codeNumberPart); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!numberPart || !codeNumberPart || numberPart.length >= codeNumberPart.length) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return code.indexOf(numberPart) === 0 || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             code.indexOf('G' + numberPart) === 0 || 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -515,24 +523,12 @@ class AnalysisExcelTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.needCols = needCols || ['code', 'b_code', 'pos']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    _isMatch11(tempData) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return _.find(tempData, x => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return x.code.indexOf('-') > 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    _isMatch18(tempData) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return _.every(tempData, x => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return !x.code || !!x.code.match(mainReg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     _getNewCacheTree(tempData) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // 模板符合11编办规则,使用11编办树 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (this._isMatch18(tempData)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (aeUtils.isMatch18(tempData)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return new ImportStd18Tree(tempData, this.ctx, this.setting); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // 反之使用11编办(未校验模板是否符合,替换注释部分即可实现) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // } else if (this._isMatch11(tempData)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // } else if (aeUtils.isMatch11(tempData)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return new ImportBaseTree(tempData, this.ctx, this.setting); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -552,12 +548,12 @@ class AnalysisExcelTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             node.dgn_qty1 = aeUtils.toNumber(row[this.colsDef.dgn_qty1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             node.dgn_qty2 = aeUtils.toNumber(row[this.colsDef.dgn_qty2]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            node.total_price = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.total_price]), this.decimal.tp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 2022-6-9 曾沛文要求不导入金额 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //node.total_price = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.total_price]), this.decimal.tp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             node.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             node.memo = this.ctx.helper.replaceReturn(row[this.colsDef.memo]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return this.cacheTree.addXmjNode(node); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            console.log(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (error.stack) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 this.ctx.logger.error(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -676,9 +672,6 @@ class AnalysisExcelTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 this.checkColHeader(row); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.cacheTree.resortFirstPartChildren(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!this.filter.filterCalc) this.cacheTree.calculateLeafWithPos(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return this.cacheTree; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -883,4 +876,95 @@ class AnalysisGclExcelTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-module.exports = { AnalysisExcelTree, AnalysisGclExcelTree }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class ImportStageBaseTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class AnalysisStageTree { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 构造函数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    constructor(ctx, setting) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.ctx = ctx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.setting = setting; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.mid = ctx.tender.id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.decimal = ctx.tender.info.decimal; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.precision = ctx.tender.info.precision; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.colsDef = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.colHeaderMatch = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            code: {value: ['项目节编号', '预算项目节'], type: colDefineType.match}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            b_code: {value: ['清单子目号', '清单编号', '子目号'], type: colDefineType.match}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            pos: {value: ['计量单元'], type: colDefineType.match}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            name: {value: ['名称'], type: colDefineType.match}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            unit: {value: ['单位'], type: colDefineType.match}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            contract_qty: {value: ['本期合同计量|数量'], type: colDefineType.match}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            contract_tp: {value: ['本期合同计量|金额'], type: colDefineType.match}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.needCols = ['code', 'b_code', 'pos', 'name', 'unit', 'contract_qty', 'contract_tp']; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 读取表头并检查 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param {Number} row - Excel数据行 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    checkColHeader(row) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const colsDef = aeUtils.checkColHeader(row, this.colHeaderMatch); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let check = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (const col of this.needCols) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!colsDef[col]) check = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (check) this.colsDef = colsDef; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mergeHeaderRow(iRow, row, subRow, merge) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const result = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (let iCol = 0, iLen = row.length; iCol < iLen; iCol++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const colMerge = merge.find(x => { return x.s.c === iCol && x.s.r === iRow}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (colMerge && colMerge.s.c !== colMerge.e.c) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let iSubCol = iCol; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                while (iSubCol <= colMerge.e.c) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    result.push(row[iCol] + '|' + subRow[iSubCol]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    iSubCol++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                iCol = colMerge.e.c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                result.push(row[iCol]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    loadRowData(row, iRow) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 将excel清单 平面数据 解析为 树结构数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param {object} sheet - excel清单数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param {Array} tempData - 新建项目使用的清单模板 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @returns {ImportBaseTree} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    analysisData(ledger, pos, sheet) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.filter = filter ? filter : {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.colsDef = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.cacheTree = this._getNewLedger(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.errorData = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.loadEnd = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.loadBegin = sheet.rows.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (const iRow in sheet.rows) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (this.colsDef && !this.loadEnd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (iRow < this.loadBegin) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                this.loadRowData(sheet.rows[iRow], iRow); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const mergeRow = this.mergeHeaderRow(iRow, sheet.rows[iRow], sheet.rows[iRow + 1], sheet.merge); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                this.checkColHeader(mergeRow); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (this.colsDef) this.loadBegin = iRow + 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return this.cacheTree; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+module.exports = { AnalysisExcelTree, AnalysisGclExcelTree, AnalysisStageTree }; 
			 |