|
|
@@ -1,4 +1,4 @@
|
|
|
-'use strict';
|
|
|
+"use strict";
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
@@ -9,387 +9,397 @@
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
-* 清单导入模块,前端导入excel,进行数据提取,用lz-string进行压缩上传处理
|
|
|
-* */
|
|
|
+ * 清单导入模块,前端导入excel,进行数据提取,用lz-string进行压缩上传处理
|
|
|
+ * */
|
|
|
|
|
|
const importBills = (function () {
|
|
|
- //单元格数据是否存在
|
|
|
- function _isDef(data) {
|
|
|
- return typeof data !== 'undefined' && data !== null && data !== '';
|
|
|
- }
|
|
|
+ //单元格数据是否存在
|
|
|
+ function _isDef(data) {
|
|
|
+ return typeof data !== "undefined" && data !== null && data !== "";
|
|
|
+ }
|
|
|
|
|
|
- //去除转义字符
|
|
|
- function _deESC(data) {
|
|
|
- return _isDef(data) ? data.toString().replace(/[\r\n\s\t]/g, '') : data;
|
|
|
- }
|
|
|
+ //去除转义字符
|
|
|
+ function _deESC(data) {
|
|
|
+ return _isDef(data) ? data.toString().replace(/[\r\n\s\t]/g, "") : data;
|
|
|
+ }
|
|
|
|
|
|
- function _deNR(data) {
|
|
|
- return _isDef(data) ? data.toString().replace(/[\r\n]/g, '') : data;
|
|
|
+ function _deNR(data) {
|
|
|
+ return _isDef(data) ? data.toString().replace(/[\r\n]/g, "") : data;
|
|
|
+ }
|
|
|
+ //find 返回最后匹配
|
|
|
+ function findLast(datas, func) {
|
|
|
+ let filter = datas.filter(func);
|
|
|
+ if (filter.length > 0) {
|
|
|
+ return filter[filter.length - 1];
|
|
|
}
|
|
|
- //find 返回最后匹配
|
|
|
- function findLast(datas, func) {
|
|
|
- let filter = datas.filter(func);
|
|
|
- if (filter.length > 0) {
|
|
|
- return filter[filter.length - 1];
|
|
|
- }
|
|
|
- return null;
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ const fileType = {
|
|
|
+ gcl: 0, //工程量清单
|
|
|
+ qdsl: 1, //清单示例
|
|
|
+ gclex: 2, // 单机版导出的工程量清单预算表,需要转换成清单示例表来处理
|
|
|
+ };
|
|
|
+ //获取列字段对应
|
|
|
+ function getColMapping(type) {
|
|
|
+ if (type === 0) {
|
|
|
+ //工程量清单
|
|
|
+ return { code: 0, name: 1, unit: 2, quantity: 4, unitPrice: 5 };
|
|
|
+ } else {
|
|
|
+ //清单示例表
|
|
|
+ return { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
|
|
|
}
|
|
|
- const fileType = {
|
|
|
- gcl: 0, //工程量清单
|
|
|
- qdsl: 1, //清单示例
|
|
|
- gclex: 2, // 单机版导出的工程量清单预算表,需要转换成清单示例表来处理
|
|
|
- };
|
|
|
- //获取列字段对应
|
|
|
- function getColMapping(type) {
|
|
|
- if (type === 0) { //工程量清单
|
|
|
- return { code: 0, name: 1, unit: 2, quantity: 4, unitPrice: 5 };
|
|
|
- } else { //清单示例表
|
|
|
- return { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
|
|
|
- }
|
|
|
+ }
|
|
|
+ function isGCLHead(dataRow, nextDataRow) {
|
|
|
+ const cell = dataRow[0];
|
|
|
+ const nextCell = nextDataRow && nextDataRow[0];
|
|
|
+ return cell && cell.value === "工程量清单" && (!nextCell || !/建设项目名称/.test(nextCell.value)); // 兼容招清单01-1表
|
|
|
+ }
|
|
|
+ function isGCLExtendHead(dataRow, nextDataRow) {
|
|
|
+ const cell = dataRow[0];
|
|
|
+ const nextCell = nextDataRow && nextDataRow[0];
|
|
|
+ if ((cell && cell.value === "工程量清单预算表") || (nextCell && /建设项目名称/.test(nextCell.value))) {
|
|
|
+ // 兼容招清单01-1表
|
|
|
+ return true;
|
|
|
}
|
|
|
- function isGCLHead(dataRow, nextDataRow) {
|
|
|
- const cell = dataRow[0];
|
|
|
- const nextCell = nextDataRow && nextDataRow[0];
|
|
|
- return cell && cell.value === '工程量清单' && (!nextCell || !/建设项目名称/.test(nextCell.value)); // 兼容招清单01-1表
|
|
|
+ }
|
|
|
+ //分析文件,1、工程量清单 2、清单示例表
|
|
|
+ function getFileType(sheetData) {
|
|
|
+ let dataTable = sheetData.data.dataTable,
|
|
|
+ // rowCount = sheetData.rowCount;
|
|
|
+ rowCount = sheetData.rows.length;
|
|
|
+ for (let row = 0; row < rowCount; row++) {
|
|
|
+ if (isGCLHead(dataTable[row], dataTable[row + 1])) {
|
|
|
+ return fileType.gcl;
|
|
|
+ }
|
|
|
+ if (isGCLExtendHead(dataTable[row], dataTable[row + 1])) {
|
|
|
+ return fileType.gclex;
|
|
|
+ }
|
|
|
}
|
|
|
- function isGCLExtendHead(dataRow, nextDataRow) {
|
|
|
- const cell = dataRow[0];
|
|
|
- const nextCell = nextDataRow && nextDataRow[0];
|
|
|
- if ((cell && cell.value === '工程量清单预算表') || (nextCell && /建设项目名称/.test(nextCell.value))) { // 兼容招清单01-1表
|
|
|
- return true;
|
|
|
+ return fileType.qdsl;
|
|
|
+ }
|
|
|
+ //提取工程量清单数据
|
|
|
+ //层级由depth确定,表格里最顶层depth为0(表头里一清单),表格内容里数据的depth为空格数+1
|
|
|
+ function extractGCLDatas(sheetData, colMapping) {
|
|
|
+ let dataTable = sheetData.data.dataTable,
|
|
|
+ // rowCount = sheetData.rowCount;
|
|
|
+ rowCount = sheetData.rows.length;
|
|
|
+ let rst = [];
|
|
|
+ for (let row = 0; row < rowCount; row++) {
|
|
|
+ //表格中顶层节点
|
|
|
+ if (isGCLHead(dataTable[row], dataTable[row + 1])) {
|
|
|
+ let rootRow = dataTable[row + 2];
|
|
|
+ let name = rootRow[0].value ? _deNR(rootRow[0].value) : "";
|
|
|
+ let existsRoot = findLast(rst, (x) => x.name === name && x.depth === 0);
|
|
|
+ if (!existsRoot) {
|
|
|
+ let root = {
|
|
|
+ ID: uuid.v1(),
|
|
|
+ NextSiblingID: -1,
|
|
|
+ ParentID: -1,
|
|
|
+ name: name,
|
|
|
+ depth: 0,
|
|
|
+ parent: null,
|
|
|
+ unitPriceAnalysis: 1,
|
|
|
+ };
|
|
|
+ let preData = findLast(rst, (x) => x.depth === root.depth);
|
|
|
+ if (preData) {
|
|
|
+ preData.NextSiblingID = root.ID;
|
|
|
+ }
|
|
|
+ rst.push(root);
|
|
|
}
|
|
|
+ row += 3;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ let code = dataTable[row][colMapping.code] ? dataTable[row][colMapping.code].value : null,
|
|
|
+ name = dataTable[row][colMapping.name] ? _deNR(dataTable[row][colMapping.name].value) : null,
|
|
|
+ unit = dataTable[row][colMapping.unit] ? dataTable[row][colMapping.unit].value : null,
|
|
|
+ quantity = dataTable[row][colMapping.quantity] ? dataTable[row][colMapping.quantity].value : null,
|
|
|
+ unitPrice = dataTable[row][colMapping.unitPrice] ? dataTable[row][colMapping.unitPrice].value : null;
|
|
|
+ if ((!code && !name) || /合计/.test(code)) {
|
|
|
+ //过滤掉同时没有编号和名称的、过滤合计行
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // “子目号”、“单位”、“数量”都为空,“子目名称”不为空时,应将此行清单名称合并到上一行
|
|
|
+ let lastData = rst[rst.length - 1];
|
|
|
+ if (!code && !unit && !quantity && name) {
|
|
|
+ lastData.name += name;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //表格内的数据
|
|
|
+ code = String(code);
|
|
|
+ let depth = getDepth(code);
|
|
|
+ let data = {
|
|
|
+ ID: uuid.v1(),
|
|
|
+ NextSiblingID: -1,
|
|
|
+ ParentID: -1,
|
|
|
+ code: code,
|
|
|
+ name: name,
|
|
|
+ unit: unit,
|
|
|
+ quantity: quantity,
|
|
|
+ depth: depth,
|
|
|
+ unitPriceAnalysis: 1,
|
|
|
+ };
|
|
|
+ if (+unitPrice && +quantity) {
|
|
|
+ unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
|
|
|
+ const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
|
|
|
+ data.fees = [
|
|
|
+ {
|
|
|
+ fieldName: "common",
|
|
|
+ tenderTotalFee: totalPrice,
|
|
|
+ tenderUnitFee: unitPrice,
|
|
|
+ totalFee: totalPrice,
|
|
|
+ unitFee: unitPrice,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ data.calcFlag = treeNodeCalcFlag.customUnitPrice;
|
|
|
+ }
|
|
|
+ //获取data的父节点链,成为兄弟节点,只能在父链里找前兄弟(不能跨父链)
|
|
|
+ let parents = getParents(lastData);
|
|
|
+ let preData = findLast(parents, (x) => x.depth === depth);
|
|
|
+ if (preData) {
|
|
|
+ preData.NextSiblingID = data.ID;
|
|
|
+ data.ParentID = preData.ParentID;
|
|
|
+ data.parent = preData.parent;
|
|
|
+ } else {
|
|
|
+ data.ParentID = lastData.ID;
|
|
|
+ data.parent = lastData;
|
|
|
+ }
|
|
|
+ rst.push(data);
|
|
|
}
|
|
|
- //分析文件,1、工程量清单 2、清单示例表
|
|
|
- function getFileType(sheetData) {
|
|
|
- let dataTable = sheetData.data.dataTable,
|
|
|
- // rowCount = sheetData.rowCount;
|
|
|
- rowCount = sheetData.rows.length;
|
|
|
- for (let row = 0; row < rowCount; row++) {
|
|
|
- if (isGCLHead(dataTable[row], dataTable[row + 1])) {
|
|
|
- return fileType.gcl;
|
|
|
- }
|
|
|
- if (isGCLExtendHead(dataTable[row], dataTable[row + 1])) {
|
|
|
- return fileType.gclex;
|
|
|
- }
|
|
|
- }
|
|
|
- return fileType.qdsl;
|
|
|
+ console.log(rst);
|
|
|
+ return rst;
|
|
|
+ function getDepth(code) {
|
|
|
+ if (!code) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ let match = code.match(/\s/g);
|
|
|
+ return match ? match.length + 1 : 1;
|
|
|
}
|
|
|
- //提取工程量清单数据
|
|
|
- //层级由depth确定,表格里最顶层depth为0(表头里一清单),表格内容里数据的depth为空格数+1
|
|
|
- function extractGCLDatas(sheetData, colMapping) {
|
|
|
- let dataTable = sheetData.data.dataTable,
|
|
|
- // rowCount = sheetData.rowCount;
|
|
|
- rowCount = sheetData.rows.length;
|
|
|
- let rst = [];
|
|
|
- for (let row = 0; row < rowCount; row++) {
|
|
|
- //表格中顶层节点
|
|
|
- if (isGCLHead(dataTable[row], dataTable[row + 1])) {
|
|
|
- let rootRow = dataTable[row + 2];
|
|
|
- let name = rootRow[0].value ? _deNR(rootRow[0].value) : '';
|
|
|
- let existsRoot = findLast(rst, x => x.name === name && x.depth === 0);
|
|
|
- if (!existsRoot) {
|
|
|
- let root = {
|
|
|
- ID: uuid.v1(),
|
|
|
- NextSiblingID: -1,
|
|
|
- ParentID: -1,
|
|
|
- name: name,
|
|
|
- depth: 0,
|
|
|
- parent: null,
|
|
|
- unitPriceAnalysis: 1
|
|
|
- };
|
|
|
- let preData = findLast(rst, x => x.depth === root.depth);
|
|
|
- if (preData) {
|
|
|
- preData.NextSiblingID = root.ID;
|
|
|
- }
|
|
|
- rst.push(root);
|
|
|
- }
|
|
|
- row += 3;
|
|
|
- continue;
|
|
|
- }
|
|
|
- let code = dataTable[row][colMapping.code] ? dataTable[row][colMapping.code].value : null,
|
|
|
- name = dataTable[row][colMapping.name] ? _deNR(dataTable[row][colMapping.name].value) : null,
|
|
|
- unit = dataTable[row][colMapping.unit] ? dataTable[row][colMapping.unit].value : null,
|
|
|
- quantity = dataTable[row][colMapping.quantity] ? dataTable[row][colMapping.quantity].value : null,
|
|
|
- unitPrice = dataTable[row][colMapping.unitPrice] ? dataTable[row][colMapping.unitPrice].value : null;
|
|
|
- if (!code && !name || /合计/.test(code)) { //过滤掉同时没有编号和名称的、过滤合计行
|
|
|
- continue;
|
|
|
- }
|
|
|
- // “子目号”、“单位”、“数量”都为空,“子目名称”不为空时,应将此行清单名称合并到上一行
|
|
|
- let lastData = rst[rst.length - 1];
|
|
|
- if (!code && !unit && !quantity && name) {
|
|
|
- lastData.name += name;
|
|
|
- continue;
|
|
|
- }
|
|
|
- //表格内的数据
|
|
|
- code = String(code);
|
|
|
- let depth = getDepth(code);
|
|
|
- let data = {
|
|
|
- ID: uuid.v1(),
|
|
|
- NextSiblingID: -1,
|
|
|
- ParentID: -1,
|
|
|
- code: code,
|
|
|
- name: name,
|
|
|
- unit: unit,
|
|
|
- quantity: quantity,
|
|
|
- depth: depth,
|
|
|
- unitPriceAnalysis: 1,
|
|
|
- };
|
|
|
- if (+unitPrice && +quantity) {
|
|
|
- unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
|
|
|
- const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
|
|
|
- data.fees = [
|
|
|
- {
|
|
|
- fieldName: "common",
|
|
|
- tenderTotalFee: totalPrice,
|
|
|
- tenderUnitFee: unitPrice,
|
|
|
- totalFee: totalPrice,
|
|
|
- unitFee: unitPrice,
|
|
|
- }
|
|
|
- ];
|
|
|
- data.calcFlag = treeNodeCalcFlag.customUnitPrice;
|
|
|
- }
|
|
|
- //获取data的父节点链,成为兄弟节点,只能在父链里找前兄弟(不能跨父链)
|
|
|
- let parents = getParents(lastData);
|
|
|
- let preData = findLast(parents, x => x.depth === depth);
|
|
|
- if (preData) {
|
|
|
- preData.NextSiblingID = data.ID;
|
|
|
- data.ParentID = preData.ParentID;
|
|
|
- data.parent = preData.parent;
|
|
|
- } else {
|
|
|
- data.ParentID = lastData.ID;
|
|
|
- data.parent = lastData;
|
|
|
- }
|
|
|
- rst.push(data);
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
- console.log(rst);
|
|
|
- return rst;
|
|
|
- function getDepth(code) {
|
|
|
- if (!code) {
|
|
|
- return 1;
|
|
|
- }
|
|
|
- let match = code.match(/\s/g);
|
|
|
- return match ? match.length + 1 : 1;
|
|
|
- }
|
|
|
+ function getParents(data) {
|
|
|
+ let rst = [];
|
|
|
+ let parent = data.parent;
|
|
|
+ while (parent) {
|
|
|
+ rst.push(parent);
|
|
|
+ parent = parent.parent;
|
|
|
}
|
|
|
+ rst.push(data);
|
|
|
+ return rst;
|
|
|
+ }
|
|
|
|
|
|
- function getParents(data) {
|
|
|
- let rst = [];
|
|
|
- let parent = data.parent;
|
|
|
- while (parent) {
|
|
|
- rst.push(parent);
|
|
|
- parent = parent.parent;
|
|
|
- }
|
|
|
- rst.push(data);
|
|
|
- return rst;
|
|
|
+ //获取编号前缀: 101-1 => 101 101-1-1 => 101-1
|
|
|
+ function getPrefix(v) {
|
|
|
+ if (!v) {
|
|
|
+ return null;
|
|
|
}
|
|
|
+ let reg = /(.*)-/;
|
|
|
+ let match = reg.exec(v);
|
|
|
+ return match ? match[1] : null;
|
|
|
+ }
|
|
|
|
|
|
- //获取编号前缀: 101-1 => 101 101-1-1 => 101-1
|
|
|
- function getPrefix(v) {
|
|
|
- if (!v) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- let reg = /(.*)-/;
|
|
|
- let match = reg.exec(v);
|
|
|
- return match ? match[1] : null;
|
|
|
- }
|
|
|
+ // 示例列映射
|
|
|
+ const slColMap = { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
|
|
|
|
|
|
- // 示例列映射
|
|
|
- const slColMap = { code: 0, name: 1, unit: 2, quantity: 3, unitPrice: 4 };
|
|
|
-
|
|
|
- function isValidGCLExRow(rowData) {
|
|
|
- if (rowData[0] && /编制[::]/.test(rowData[0].value)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (rowData[1] && /合计/.test(rowData[1].value)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if ((!rowData[slColMap.code] || !rowData[slColMap.code].value) &&
|
|
|
- (!rowData[slColMap.name] || !rowData[slColMap.name].value) &&
|
|
|
- (!rowData[slColMap.unit] || !rowData[slColMap.unit].value) &&
|
|
|
- (!rowData[slColMap.quantity] || !rowData[slColMap.quantity].value)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
+ function isValidGCLExRow(rowData) {
|
|
|
+ if (rowData[0] && /编制[::]/.test(rowData[0].value)) {
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
- // 将“工程量清单预算表”去掉表头表尾,并转换成清单示例表。
|
|
|
- // 工程量清单预算表的格式可参考需求:BUG #3037
|
|
|
- function transformGCLExToSL(sheetData) {
|
|
|
- const rst = {
|
|
|
- data: { dataTable: [] },
|
|
|
- rowCount: 0,
|
|
|
- };
|
|
|
- const dataTable = sheetData.data.dataTable;
|
|
|
- const rowCount = sheetData.rows.length;
|
|
|
- let preRootName;
|
|
|
- for (let row = 0; row < rowCount; row++) {
|
|
|
- const rowData = dataTable[row];
|
|
|
- if (isGCLExtendHead(rowData, dataTable[row + 1])) {
|
|
|
- const rootRowdata = dataTable[row + 3];
|
|
|
- const name = rootRowdata[0].value;
|
|
|
- if (name) {
|
|
|
- const rootName = name.replace('工程量清单', '清单');
|
|
|
- if (rootName !== preRootName) {
|
|
|
- preRootName = rootName;
|
|
|
- rst.data.dataTable.push({
|
|
|
- [slColMap.name]: { value: rootName }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- row += 4;
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (isValidGCLExRow(rowData)) {
|
|
|
- const cellData = {
|
|
|
- [slColMap.code]: { value: rowData[slColMap.code] && rowData[slColMap.code].value || null },
|
|
|
- [slColMap.name]: { value: rowData[slColMap.name] && rowData[slColMap.name].value || null },
|
|
|
- [slColMap.unit]: { value: rowData[slColMap.unit] && rowData[slColMap.unit].value || null },
|
|
|
- [slColMap.quantity]: { value: rowData[slColMap.quantity] && rowData[slColMap.quantity].value || null },
|
|
|
- [slColMap.unitPrice]: { value: rowData[slColMap.unitPrice] && rowData[slColMap.unitPrice].value || null },
|
|
|
- };
|
|
|
- rst.data.dataTable.push(cellData);
|
|
|
- }
|
|
|
- }
|
|
|
- rst.rowCount = rst.data.dataTable.length;
|
|
|
- return rst;
|
|
|
+ if (rowData[1] && /合计/.test(rowData[1].value)) {
|
|
|
+ return false;
|
|
|
}
|
|
|
+ if (
|
|
|
+ (!rowData[slColMap.code] || !rowData[slColMap.code].value) &&
|
|
|
+ (!rowData[slColMap.name] || !rowData[slColMap.name].value) &&
|
|
|
+ (!rowData[slColMap.unit] || !rowData[slColMap.unit].value) &&
|
|
|
+ (!rowData[slColMap.quantity] || !rowData[slColMap.quantity].value)
|
|
|
+ ) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
- //提取清单示例数据
|
|
|
- function extractSLDatas(sheetData) {
|
|
|
- let dataTable = sheetData.data.dataTable,
|
|
|
- rowCount = sheetData.rows.length;
|
|
|
- let rst = [];
|
|
|
- let curRoot = null;
|
|
|
- for (let row = 0; row < rowCount; row++) {
|
|
|
- let code = dataTable[row][slColMap.code] && dataTable[row][slColMap.code].value ? String(dataTable[row][slColMap.code].value).trim() : null,
|
|
|
- name = dataTable[row][slColMap.name] ? _deNR(dataTable[row][slColMap.name].value) : null,
|
|
|
- unit = dataTable[row][slColMap.unit] ? dataTable[row][slColMap.unit].value : null,
|
|
|
- quantity = dataTable[row][slColMap.quantity] ? dataTable[row][slColMap.quantity].value : null,
|
|
|
- unitPrice = dataTable[row][slColMap.unitPrice] ? dataTable[row][slColMap.unitPrice].value : null;
|
|
|
- if (!code) { //没有编号的数据,名称必须为:清单 第xx章,认为新的表根节点
|
|
|
- const reg = /清单\s+第[^章]+章/;
|
|
|
- //if (name && /清单 第\d+章/.test(name)) {
|
|
|
- if (name && reg.test(name)) {
|
|
|
- curRoot = {
|
|
|
- code: null,
|
|
|
- name: name,
|
|
|
- ID: uuid.v1(),
|
|
|
- ParentID: -1,
|
|
|
- NextSiblingID: -1,
|
|
|
- parent: null,
|
|
|
- unitPriceAnalysis: 1
|
|
|
- };
|
|
|
- rst.push(curRoot);
|
|
|
- } else {
|
|
|
- curRoot = null;
|
|
|
- }
|
|
|
- } else if (!curRoot) { //根节点为无效根节点,其下子数据全部过滤掉
|
|
|
- continue;
|
|
|
- } else {
|
|
|
- //有code且有有效表根节点
|
|
|
- let prefix = getPrefix(code);
|
|
|
- let data = {
|
|
|
- code: code,
|
|
|
- name: name,
|
|
|
- unit: unit,
|
|
|
- quantity: quantity,
|
|
|
- quantityEXP: "" + quantity,
|
|
|
- ID: uuid.v1(),
|
|
|
- NextSiblingID: -1,
|
|
|
- unitPriceAnalysis: 1
|
|
|
- };
|
|
|
- if (+unitPrice && +quantity) {
|
|
|
- unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
|
|
|
- const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
|
|
|
- data.fees = [
|
|
|
- {
|
|
|
- fieldName: "common",
|
|
|
- tenderTotalFee: totalPrice,
|
|
|
- tenderUnitFee: unitPrice,
|
|
|
- totalFee: totalPrice,
|
|
|
- unitFee: unitPrice,
|
|
|
- }
|
|
|
- ];
|
|
|
- data.calcFlag = treeNodeCalcFlag.customUnitPrice;
|
|
|
- }
|
|
|
- let lastData = rst[rst.length - 1];
|
|
|
- let parents = getParents(lastData);
|
|
|
- //某数据编号为此数据的前缀,则某数据为此数据的父节点
|
|
|
- let parentData = findLast(parents, x => prefix === x.code);
|
|
|
- if (!parentData && prefix === '') { // -x的数据,在父链上找不到编号与prefix相同的数据时,父链上-x的数据,则这两数据为兄弟节点,没有则上一行数据为其父节点
|
|
|
- let samePrefixData = findLast(parents, x => getPrefix(x.code) === prefix);
|
|
|
- parentData = samePrefixData ? samePrefixData.parent : lastData;
|
|
|
- } else if (!parentData && prefix !== '') { //不是-x的数据,在父链上找不到编号与prefix相同的数据时,表根节点为其父节点
|
|
|
- parentData = curRoot;
|
|
|
- }
|
|
|
- data.ParentID = parentData.ID;
|
|
|
- data.parent = parentData;
|
|
|
- let preData = findLast(parents, x => x.ParentID === data.ParentID);
|
|
|
- if (preData) {
|
|
|
- preData.NextSiblingID = data.ID;
|
|
|
- }
|
|
|
- rst.push(data);
|
|
|
- }
|
|
|
+ // 将“工程量清单预算表”去掉表头表尾,并转换成清单示例表。
|
|
|
+ // 工程量清单预算表的格式可参考需求:BUG #3037
|
|
|
+ function transformGCLExToSL(sheetData) {
|
|
|
+ const rst = {
|
|
|
+ data: { dataTable: [] },
|
|
|
+ rowCount: 0,
|
|
|
+ };
|
|
|
+ const dataTable = sheetData.data.dataTable;
|
|
|
+ const rowCount = sheetData.rows.length;
|
|
|
+ let preRootName;
|
|
|
+ for (let row = 0; row < rowCount; row++) {
|
|
|
+ const rowData = dataTable[row];
|
|
|
+ if (isGCLExtendHead(rowData, dataTable[row + 1])) {
|
|
|
+ const rootRowdata = dataTable[row + 3];
|
|
|
+ const name = rootRowdata[0].value;
|
|
|
+ if (name) {
|
|
|
+ const rootName = name.replace("工程量清单", "清单");
|
|
|
+ if (rootName !== preRootName) {
|
|
|
+ preRootName = rootName;
|
|
|
+ rst.data.dataTable.push({
|
|
|
+ [slColMap.name]: { value: rootName },
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
- console.log(rst);
|
|
|
- return rst;
|
|
|
+ row += 4;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (isValidGCLExRow(rowData)) {
|
|
|
+ const cellData = {
|
|
|
+ [slColMap.code]: { value: (rowData[slColMap.code] && rowData[slColMap.code].value) || null },
|
|
|
+ [slColMap.name]: { value: (rowData[slColMap.name] && rowData[slColMap.name].value) || null },
|
|
|
+ [slColMap.unit]: { value: (rowData[slColMap.unit] && rowData[slColMap.unit].value) || null },
|
|
|
+ [slColMap.quantity]: { value: (rowData[slColMap.quantity] && rowData[slColMap.quantity].value) || null },
|
|
|
+ [slColMap.unitPrice]: { value: (rowData[slColMap.unitPrice] && rowData[slColMap.unitPrice].value) || null },
|
|
|
+ };
|
|
|
+ rst.data.dataTable.push(cellData);
|
|
|
+ }
|
|
|
}
|
|
|
+ rst.rowCount = rst.data.dataTable.length;
|
|
|
+ return rst;
|
|
|
+ }
|
|
|
|
|
|
- function extactDatas(sheets) {
|
|
|
- let rst = [];
|
|
|
- let curSheetType = null;
|
|
|
- for (let sheetName in sheets) {
|
|
|
- let sheetData = sheets[sheetName];
|
|
|
- if (!sheetData.data.dataTable || sheetData.index !== 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- let sheetType = getFileType(sheetData);
|
|
|
- if (curSheetType !== null && sheetType !== curSheetType) {
|
|
|
- throw 'excel文件中存在不同格式的表格。';
|
|
|
- }
|
|
|
- curSheetType = sheetType;
|
|
|
- let colMapping = getColMapping(sheetType);
|
|
|
- let datas = [];
|
|
|
- if (sheetType === fileType.gcl) {
|
|
|
- datas = extractGCLDatas(sheetData, colMapping);
|
|
|
- } else if (sheetType === fileType.qdsl) {
|
|
|
- datas = extractSLDatas(sheetData, colMapping);
|
|
|
- } else {
|
|
|
- const slSheetData = transformGCLExToSL(sheetData);
|
|
|
- datas = extractSLDatas(slSheetData, colMapping);
|
|
|
- }
|
|
|
- rst = rst.concat(datas);
|
|
|
+ //提取清单示例数据
|
|
|
+ function extractSLDatas(sheetData) {
|
|
|
+ let dataTable = sheetData.data.dataTable,
|
|
|
+ rowCount = sheetData.rows.length;
|
|
|
+ let rst = [];
|
|
|
+ let curRoot = null;
|
|
|
+ for (let row = 0; row < rowCount; row++) {
|
|
|
+ let code = dataTable[row][slColMap.code] && dataTable[row][slColMap.code].value ? String(dataTable[row][slColMap.code].value).trim() : null,
|
|
|
+ name = dataTable[row][slColMap.name] ? _deNR(dataTable[row][slColMap.name].value) : null,
|
|
|
+ unit = dataTable[row][slColMap.unit] ? dataTable[row][slColMap.unit].value : null,
|
|
|
+ quantity = dataTable[row][slColMap.quantity] ? dataTable[row][slColMap.quantity].value : null,
|
|
|
+ unitPrice = dataTable[row][slColMap.unitPrice] ? dataTable[row][slColMap.unitPrice].value : null;
|
|
|
+ if (!code) {
|
|
|
+ //没有编号的数据,名称必须为:清单 第xx章,认为新的表根节点
|
|
|
+ const reg = /清单\s+第[^章]+章/;
|
|
|
+ //if (name && /清单 第\d+章/.test(name)) {
|
|
|
+ if (name && reg.test(name)) {
|
|
|
+ curRoot = {
|
|
|
+ code: null,
|
|
|
+ name: name,
|
|
|
+ ID: uuid.v1(),
|
|
|
+ ParentID: -1,
|
|
|
+ NextSiblingID: -1,
|
|
|
+ parent: null,
|
|
|
+ unitPriceAnalysis: 1,
|
|
|
+ };
|
|
|
+ rst.push(curRoot);
|
|
|
+ } else {
|
|
|
+ curRoot = null;
|
|
|
}
|
|
|
- //编号去除空格 清除多余数据 设置数据
|
|
|
- for (let data of rst) {
|
|
|
- if (data.code && typeof data.code === 'string') {
|
|
|
- data.code = data.code.replace(/\s/g, '');
|
|
|
- }
|
|
|
- if (data.unit === '㎡') {
|
|
|
- data.unit = 'm2';
|
|
|
- } else if (data.unit === 'm³') {
|
|
|
- data.unit = 'm3';
|
|
|
- }
|
|
|
- data.projectID = projectObj.project.ID();
|
|
|
- data.type = billType.BILL;
|
|
|
- delete data.parent;
|
|
|
- delete data.depth;
|
|
|
+ } else if (!curRoot) {
|
|
|
+ //根节点为无效根节点,其下子数据全部过滤掉
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ //有code且有有效表根节点
|
|
|
+ let prefix = getPrefix(code);
|
|
|
+ let data = {
|
|
|
+ code: code,
|
|
|
+ name: name,
|
|
|
+ unit: unit,
|
|
|
+ quantity: quantity,
|
|
|
+ quantityEXP: "" + quantity,
|
|
|
+ ID: uuid.v1(),
|
|
|
+ NextSiblingID: -1,
|
|
|
+ unitPriceAnalysis: 1,
|
|
|
+ };
|
|
|
+ if (+unitPrice && +quantity) {
|
|
|
+ unitPrice = scMathUtil.roundForObj(unitPrice, decimalObj.bills.unitPrice);
|
|
|
+ const totalPrice = scMathUtil.roundForObj(unitPrice * +quantity, decimalObj.bills.totalPrice);
|
|
|
+ data.fees = [
|
|
|
+ {
|
|
|
+ fieldName: "common",
|
|
|
+ tenderTotalFee: totalPrice,
|
|
|
+ tenderUnitFee: unitPrice,
|
|
|
+ totalFee: totalPrice,
|
|
|
+ unitFee: unitPrice,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ data.calcFlag = treeNodeCalcFlag.customUnitPrice;
|
|
|
}
|
|
|
- //将表根节点的ParentID设置成第100章至700章清单的ID
|
|
|
- let fixedBill = projectObj.project.Bills.tree.roots.find(node => node.data &&
|
|
|
- node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.ONE_SEVEN_BILLS);
|
|
|
- let rootDatas = rst.filter(data => data.ParentID === -1);
|
|
|
- for (let root of rootDatas) {
|
|
|
- root.ParentID = fixedBill.data.ID;
|
|
|
+ let lastData = rst[rst.length - 1];
|
|
|
+ let parents = getParents(lastData);
|
|
|
+ //某数据编号为此数据的前缀,则某数据为此数据的父节点
|
|
|
+ let parentData = findLast(parents, (x) => prefix === x.code);
|
|
|
+ if (!parentData && prefix === "") {
|
|
|
+ // -x的数据,在父链上找不到编号与prefix相同的数据时,父链上-x的数据,则这两数据为兄弟节点,没有则上一行数据为其父节点
|
|
|
+ let samePrefixData = findLast(parents, (x) => getPrefix(x.code) === prefix);
|
|
|
+ parentData = samePrefixData ? samePrefixData.parent : lastData;
|
|
|
+ } else if (!parentData && prefix !== "") {
|
|
|
+ //不是-x的数据,在父链上找不到编号与prefix相同的数据时,表根节点为其父节点
|
|
|
+ parentData = curRoot;
|
|
|
}
|
|
|
- //清单 第100章 总则清单需要加上固定ID
|
|
|
- let oneHundredBills = rootDatas.find(data => data.name && /第100章/.test(data.name));
|
|
|
- if (oneHundredBills) {
|
|
|
- oneHundredBills.flags = [{ flag: fixedFlag.ONE_HUNDRED_BILLS, fieldName: 'fixed' }];
|
|
|
+ data.ParentID = parentData.ID;
|
|
|
+ data.parent = parentData;
|
|
|
+ let preData = findLast(parents, (x) => x.ParentID === data.ParentID);
|
|
|
+ if (preData) {
|
|
|
+ preData.NextSiblingID = data.ID;
|
|
|
}
|
|
|
- return rst;
|
|
|
+ rst.push(data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(rst);
|
|
|
+ return rst;
|
|
|
+ }
|
|
|
+
|
|
|
+ function extactDatas(sheets) {
|
|
|
+ let rst = [];
|
|
|
+ let curSheetType = null;
|
|
|
+ for (let sheetName in sheets) {
|
|
|
+ let sheetData = sheets[sheetName];
|
|
|
+ if (!sheetData.data.dataTable || sheetData.index !== 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ let sheetType = getFileType(sheetData);
|
|
|
+ if (curSheetType !== null && sheetType !== curSheetType) {
|
|
|
+ throw "excel文件中存在不同格式的表格。";
|
|
|
+ }
|
|
|
+ curSheetType = sheetType;
|
|
|
+ let colMapping = getColMapping(sheetType);
|
|
|
+ let datas = [];
|
|
|
+ if (sheetType === fileType.gcl) {
|
|
|
+ datas = extractGCLDatas(sheetData, colMapping);
|
|
|
+ } else if (sheetType === fileType.qdsl) {
|
|
|
+ datas = extractSLDatas(sheetData, colMapping);
|
|
|
+ } else {
|
|
|
+ const slSheetData = transformGCLExToSL(sheetData);
|
|
|
+ datas = extractSLDatas(slSheetData, colMapping);
|
|
|
+ }
|
|
|
+ rst = rst.concat(datas);
|
|
|
+ }
|
|
|
+ //编号去除空格 清除多余数据 设置数据
|
|
|
+ for (let data of rst) {
|
|
|
+ if (data.code && typeof data.code === "string") {
|
|
|
+ data.code = data.code.replace(/\s/g, "");
|
|
|
+ }
|
|
|
+ if (data.unit === "㎡") {
|
|
|
+ data.unit = "m2";
|
|
|
+ } else if (data.unit === "m³") {
|
|
|
+ data.unit = "m3";
|
|
|
+ }
|
|
|
+ data.projectID = projectObj.project.ID();
|
|
|
+ data.type = billType.BILL;
|
|
|
+ delete data.parent;
|
|
|
+ delete data.depth;
|
|
|
+ }
|
|
|
+ //将表根节点的ParentID设置成第100章至700章清单的ID
|
|
|
+ let fixedBill = projectObj.project.Bills.tree.roots.find(
|
|
|
+ (node) => node.data && node.data.flagsIndex && node.data.flagsIndex.fixed && node.data.flagsIndex.fixed.flag === fixedFlag.ONE_SEVEN_BILLS
|
|
|
+ );
|
|
|
+ let rootDatas = rst.filter((data) => data.ParentID === -1);
|
|
|
+ for (let root of rootDatas) {
|
|
|
+ root.ParentID = fixedBill.data.ID;
|
|
|
+ }
|
|
|
+ //清单 第100章 总则清单需要加上固定ID
|
|
|
+ let oneHundredBills = rootDatas.find((data) => data.name && /第100章/.test(data.name));
|
|
|
+ if (oneHundredBills) {
|
|
|
+ oneHundredBills.flags = [{ flag: fixedFlag.ONE_HUNDRED_BILLS, fieldName: "fixed" }];
|
|
|
}
|
|
|
+ return rst;
|
|
|
+ }
|
|
|
|
|
|
- return { extactDatas }
|
|
|
-})();
|
|
|
+ return { extactDatas };
|
|
|
+})();
|