|
@@ -45,6 +45,18 @@ const aeUtils = {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+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 {
|
|
|
/**
|
|
|
* 构造函数
|
|
@@ -61,6 +73,8 @@ class ImportBaseTree {
|
|
|
this.roots = [];
|
|
|
this.pos = [];
|
|
|
this.tempData = [];
|
|
|
+ // 以id为索引
|
|
|
+ this.nodes = {};
|
|
|
|
|
|
// 缓存
|
|
|
this.finalNode = null;
|
|
@@ -97,6 +111,7 @@ class ImportBaseTree {
|
|
|
this.keyNodeId = node.ledger_id + 1;
|
|
|
}
|
|
|
this.tempData.push(node);
|
|
|
+ this.nodes[node.ledger_id] = node;
|
|
|
}
|
|
|
for (const node of this.items) {
|
|
|
node.tender_id = this.ctx.tender.id;
|
|
@@ -182,6 +197,7 @@ class ImportBaseTree {
|
|
|
* @param {Object} node - 当前添加的节点
|
|
|
*/
|
|
|
defineCacheData(node) {
|
|
|
+ this.nodes[node.ledger_id] = node;
|
|
|
this.finalNode = node;
|
|
|
this.finalPrecision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, node.unit);
|
|
|
if (node.code) {
|
|
@@ -297,6 +313,128 @@ class ImportBaseTree {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+class ImportStd18Tree extends ImportBaseTree {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否是父项
|
|
|
+ * @param parent
|
|
|
+ * @param code
|
|
|
+ * @returns {boolean}
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ _checkParent(parent, code) {
|
|
|
+ if (!parent.code) return false;
|
|
|
+ const numberPart = parent.code.replace(gdXmjPartReg, '');
|
|
|
+ if (!numberPart) return false;
|
|
|
+ return code.indexOf(numberPart) === 0 ||
|
|
|
+ code.indexOf('G' + numberPart) === 0 ||
|
|
|
+ code.indexOf('GD' + numberPart) === 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查找主表项目节父项
|
|
|
+ * @param code
|
|
|
+ * @returns {*}
|
|
|
+ */
|
|
|
+ findMainXmjParent(code) {
|
|
|
+ const numberPart = code.replace(gdXmjPartReg, '');
|
|
|
+ if (numberPart.length <= 1) throw '首层项目节模板中未定义,不支持导入';
|
|
|
+
|
|
|
+ let parent = this.cacheMainXmjNode;
|
|
|
+ while (parent) {
|
|
|
+ if (this._checkParent(parent, code)) return parent;
|
|
|
+ parent = this.nodes[parent.ledger_pid];
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查找分表项目节父项
|
|
|
+ * @param code
|
|
|
+ * @returns {*}
|
|
|
+ */
|
|
|
+ findSubXmjParent(code) {
|
|
|
+ let parent = this.cacheSubXmjNode;
|
|
|
+ while (parent && parent.code.match(subReg)) {
|
|
|
+ if (this._checkParent(parent, code)) return parent;
|
|
|
+ parent = this.nodes[parent.ledger_pid];
|
|
|
+ }
|
|
|
+ return this.cacheMainXmjNode;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据 编号 查找 父项项目节
|
|
|
+ * @param {String} code - 子项编号
|
|
|
+ * @returns {*}
|
|
|
+ */
|
|
|
+ findXmjParent(code) {
|
|
|
+ if (code.match(mainReg)) {
|
|
|
+ if (!this.cacheMainXmjNode) throw '主表项目节找不到父项';
|
|
|
+ return this.findMainXmjParent(code);
|
|
|
+ } else if (code.match(subReg)) {
|
|
|
+ if (!this.cacheMainXmjNode) throw '分表项目节找不到所属主表项目节';
|
|
|
+ return this.findSubXmjParent(code);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 定义缓存节点(添加工程量清单、部位明细需使用缓存定位)
|
|
|
+ * @param {Object} node - 当前添加的节点
|
|
|
+ */
|
|
|
+ defineCacheData(node) {
|
|
|
+ super.defineCacheData(node);
|
|
|
+ if (node.code) {
|
|
|
+ if (node.code.match(mainReg)) {
|
|
|
+ this.cacheMainXmjNode = node;
|
|
|
+ this.cacheSubXmjNode = null;
|
|
|
+ } else if (node.code.match(subReg)) {
|
|
|
+ this.cacheSubXmjNode = node;
|
|
|
+ }
|
|
|
+ if (node.code.match(specCode106.reg)) {
|
|
|
+ if (this.cacheSpecMainXmj1 && this.cacheSpecMainXmj1.code.match(specCode109.reg)) {
|
|
|
+ this.cacheSpecMainXmj2 = node;
|
|
|
+ } else {
|
|
|
+ this.cacheSpecMainXmj1 = node;
|
|
|
+ }
|
|
|
+ } else if (node.code.match(specCode109.reg)) {
|
|
|
+ this.cacheSpecMainXmj1 = node;
|
|
|
+ this.cacheSpecMainXmj2 = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加 项目节
|
|
|
+ * @param {Object} node - 项目节
|
|
|
+ * @returns {*}
|
|
|
+ */
|
|
|
+ addXmjNode(node) {
|
|
|
+ if (!node.code || (!node.code.match(mainReg) && !node.code.match(subReg))) return null;
|
|
|
+
|
|
|
+ node.id = this.ctx.app.uuid.v4();
|
|
|
+ node.tender_id = this.ctx.tender.id;
|
|
|
+ node.children = [];
|
|
|
+ if ((specCode106.code.indexOf(node.code) >= 0)) {
|
|
|
+ if (this.cacheSpecMainXmj2 && this.cacheSpecMainXmj2.code.match(specCode106.reg))
|
|
|
+ return this.addNodeWithParent(node, this.cacheSpecMainXmj2);
|
|
|
+ if (this.cacheSpecMainXmj1 && this.cacheSpecMainXmj1.code.match(specCode106.reg))
|
|
|
+ return this.addNodeWithParent(node, this.cacheSpecMainXmj1);
|
|
|
+ }
|
|
|
+ if ((specCode109.code.indexOf(node.code) >= 0) &&
|
|
|
+ (this.cacheSpecMainXmj1 && this.cacheSpecMainXmj1.code.match(specCode109.reg))) {
|
|
|
+ return this.addNodeWithParent(node, this.cacheSpecMainXmj1)
|
|
|
+ }
|
|
|
+ const temp = this.findTempData(node);
|
|
|
+ if (temp) {
|
|
|
+ this.defineCacheData(temp);
|
|
|
+ return temp;
|
|
|
+ } else {
|
|
|
+ const parent = this.findXmjParent(node.code);
|
|
|
+ return this.addNodeWithParent(node, parent);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
class AnalysisExcelTree {
|
|
|
/**
|
|
|
* 构造函数
|
|
@@ -319,6 +457,29 @@ class AnalysisExcelTree {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+ _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)) {
|
|
|
+ return new ImportStd18Tree(tempData, this.ctx);
|
|
|
+ // 反之使用11编办(未校验模板是否符合,替换注释部分即可实现)
|
|
|
+ // } else if (this._isMatch11(tempData)){
|
|
|
+ } else {
|
|
|
+ return new ImportBaseTree(tempData, this.ctx);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 读取项目节节点
|
|
|
* @param {Array} row - excel行数据
|
|
@@ -326,23 +487,38 @@ class AnalysisExcelTree {
|
|
|
* @private
|
|
|
*/
|
|
|
_loadXmjNode(row) {
|
|
|
- const node = {};
|
|
|
- node.code = this.ctx.helper.replaceReturn(row[this.colsDef.code]);
|
|
|
- node.name = this.ctx.helper.replaceReturn(row[this.colsDef.name]);
|
|
|
- node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]);
|
|
|
- const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, node.unit);
|
|
|
- node.quantity = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.quantity]), precision.value);
|
|
|
- node.dgn_qty1 = aeUtils.toNumber(row[this.colsDef.dgn_qty1]);
|
|
|
- node.dgn_qty2 = aeUtils.toNumber(row[this.colsDef.dgn_qty2]);
|
|
|
- node.unit_price = aeUtils.toNumber(row[this.colsDef.unit_price]);
|
|
|
- node.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]);
|
|
|
- node.memo = this.ctx.helper.replaceReturn(row[this.colsDef.memo]);
|
|
|
- if (node.quantity && node.unit_price) {
|
|
|
- node.total_price = this.ctx.helper.mul(node.quantity, node.unit_price, this.ctx.tender.info.decimal.tp);
|
|
|
- } else {
|
|
|
- node.total_price = null;
|
|
|
+ try {
|
|
|
+ const node = {};
|
|
|
+ node.code = this.ctx.helper.replaceReturn(row[this.colsDef.code]);
|
|
|
+ node.name = this.ctx.helper.replaceReturn(row[this.colsDef.name]);
|
|
|
+ node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]);
|
|
|
+ const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, node.unit);
|
|
|
+ node.quantity = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.quantity]), precision.value);
|
|
|
+ node.dgn_qty1 = aeUtils.toNumber(row[this.colsDef.dgn_qty1]);
|
|
|
+ node.dgn_qty2 = aeUtils.toNumber(row[this.colsDef.dgn_qty2]);
|
|
|
+ node.unit_price = aeUtils.toNumber(row[this.colsDef.unit_price]);
|
|
|
+ node.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]);
|
|
|
+ node.memo = this.ctx.helper.replaceReturn(row[this.colsDef.memo]);
|
|
|
+ if (node.quantity && node.unit_price) {
|
|
|
+ node.total_price = this.ctx.helper.mul(node.quantity, node.unit_price, this.ctx.tender.info.decimal.tp);
|
|
|
+ } else {
|
|
|
+ node.total_price = null;
|
|
|
+ }
|
|
|
+ return this.cacheTree.addXmjNode(node);
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error);
|
|
|
+ if (error.stack) {
|
|
|
+ this.ctx.logger.error(error);
|
|
|
+ } else {
|
|
|
+ this.ctx.getLogger('fail').info(JSON.stringify({
|
|
|
+ error,
|
|
|
+ project: this.ctx.session.sessionProject,
|
|
|
+ user: this.ctx.session.sessionUser,
|
|
|
+ body: row,
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
- return this.cacheTree.addXmjNode(node);
|
|
|
}
|
|
|
/**
|
|
|
* 读取工程量清单数据
|
|
@@ -431,7 +607,7 @@ class AnalysisExcelTree {
|
|
|
*/
|
|
|
analysisData(sheet, tempData) {
|
|
|
this.colsDef = null;
|
|
|
- this.cacheTree = new ImportBaseTree(tempData, this.ctx);
|
|
|
+ this.cacheTree = this._getNewCacheTree(tempData);
|
|
|
this.errorData = [];
|
|
|
this.loadEnd = false;
|
|
|
|