|  | @@ -15,6 +15,7 @@ let stdBillsModel = mongoose.model('std_bills_lib_bills');
 | 
	
		
			
				|  |  |  let stdBillJobsModel = mongoose.model('std_bills_lib_jobContent');
 | 
	
		
			
				|  |  |  let stdBillCharacterModel = mongoose.model('std_bills_lib_itemCharacter');
 | 
	
		
			
				|  |  |  import fixedFlag from  '../../common/const/bills_fixed';
 | 
	
		
			
				|  |  | +let LZString = require('lz-string');
 | 
	
		
			
				|  |  |  const uuidV1 = require('uuid/v1');
 | 
	
		
			
				|  |  |  const billType ={
 | 
	
		
			
				|  |  |      DXFY:1,//大项费用
 | 
	
	
		
			
				|  | @@ -201,19 +202,13 @@ module.exports = {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |      //导入清单
 | 
	
		
			
				|  |  | -    upload: async function(req, res){
 | 
	
		
			
				|  |  | +    import: async function(req, res){
 | 
	
		
			
				|  |  |          let responseData = {
 | 
	
		
			
				|  |  |              err: 0,
 | 
	
		
			
				|  |  |              msg: '',
 | 
	
		
			
				|  |  |              data: []
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  | -        const allowHeader = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
 | 
	
		
			
				|  |  | -        const uploadOption = {
 | 
	
		
			
				|  |  | -            uploadDir: './public'
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -        const form = new multiparty.Form(uploadOption);
 | 
	
		
			
				|  |  | -        let uploadFullName;
 | 
	
		
			
				|  |  | -        let parseSheetDateA = +new Date();
 | 
	
		
			
				|  |  | +        const form = new multiparty.Form();
 | 
	
		
			
				|  |  |          form.parse(req, async function(err, fields, files) {
 | 
	
		
			
				|  |  |              try{
 | 
	
		
			
				|  |  |                  const projectID = fields.projectID !== undefined && fields.projectID.length > 0 ?
 | 
	
	
		
			
				|  | @@ -221,65 +216,13 @@ module.exports = {
 | 
	
		
			
				|  |  |                  if (projectID <= 0) {
 | 
	
		
			
				|  |  |                      throw '参数错误';
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -                const file = files.file !== undefined ? files.file[0] : null;
 | 
	
		
			
				|  |  | -                if (err || file === null) {
 | 
	
		
			
				|  |  | -                    throw '上传失败';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                // 判断类型
 | 
	
		
			
				|  |  | -                if (file.headers['content-type'] === undefined || allowHeader.indexOf(file.headers['content-type']) < 0) {
 | 
	
		
			
				|  |  | -                    throw '不支持该类型';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //导入表类型(09表lj、广联达gld)
 | 
	
		
			
				|  |  | -                const fileType = fields.fileType !== undefined && fields.fileType.length > 0 ? fields.fileType[0] : uploadType.lj;
 | 
	
		
			
				|  |  | -                // 重命名文件名
 | 
	
		
			
				|  |  | -                uploadFullName = uploadOption.uploadDir + '/' + file.originalFilename;
 | 
	
		
			
				|  |  | -                fs.renameSync(file.path, uploadFullName);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                const sheets = excel.parse(uploadFullName);
 | 
	
		
			
				|  |  | -                if (sheets[0] === undefined || sheets[0].data === undefined) {
 | 
	
		
			
				|  |  | -                    throw 'excel没有对应数据';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //出现错误的表表名,前端提示用
 | 
	
		
			
				|  |  | -                let invalidSheets = [];
 | 
	
		
			
				|  |  | -                let validSheets = {fbfx: [], jscsxm: [], zzcsxm: []};
 | 
	
		
			
				|  |  | -                //获得选择的导入的表及导入位置
 | 
	
		
			
				|  |  | -                const uploadWorkBook = fields.uploadWorkBook !== undefined && fields.uploadWorkBook.length > 0 ? JSON.parse(fields.uploadWorkBook[0]) : [];
 | 
	
		
			
				|  |  | -                //识别非法和合法表,sheetInfo存储前端勾选的表的位置索引以及选择的导入位置
 | 
	
		
			
				|  |  | -                for(let sheetInfo of uploadWorkBook){
 | 
	
		
			
				|  |  | -                    let sheet = sheets[sheetInfo.sheetIdx];
 | 
	
		
			
				|  |  | -                    if(sheet.data === undefined){
 | 
	
		
			
				|  |  | -                        invalidSheets.push(sheet.name);
 | 
	
		
			
				|  |  | -                        continue;
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    //获取表的列设置确定导入的格式是否合法(09、广联达)
 | 
	
		
			
				|  |  | -                    let colMapping = getColMapping(sheet.data);
 | 
	
		
			
				|  |  | -                    if(!isValidSheet(colMapping, fileType)){
 | 
	
		
			
				|  |  | -                        invalidSheets.push(sheet.name);
 | 
	
		
			
				|  |  | -                        continue;
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    //合法的表
 | 
	
		
			
				|  |  | -                    sheet.colMapping = colMapping;
 | 
	
		
			
				|  |  | -                    //将合法的表按导入位置分类当做一个表来处理
 | 
	
		
			
				|  |  | -                    if(validSheets[sheetInfo.position] !== undefined){
 | 
	
		
			
				|  |  | -                        validSheets[sheetInfo.position].push(sheet)
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +                //导入清单数据
 | 
	
		
			
				|  |  | +                let compressData = fields.compressData !== undefined && fields.compressData.length > 0 ?
 | 
	
		
			
				|  |  | +                    fields.compressData[0] : null;
 | 
	
		
			
				|  |  | +                if(compressData === null){
 | 
	
		
			
				|  |  | +                    throw 'excel没有对应数据'
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -                let parseSheetB = +new Date();
 | 
	
		
			
				|  |  | -                console.log(`解析表时间: ${parseSheetB - parseSheetDateA}===================================================================`);
 | 
	
		
			
				|  |  | -                //合并同类表并提取表的有效数据
 | 
	
		
			
				|  |  | -                let validSheetDataA = +new Date();
 | 
	
		
			
				|  |  | -                let toImportSheets = [];
 | 
	
		
			
				|  |  | -                for(let uploadPosition in validSheets){
 | 
	
		
			
				|  |  | -                    let validExcelData = [];
 | 
	
		
			
				|  |  | -                    for(let uSheet of validSheets[uploadPosition]){
 | 
	
		
			
				|  |  | -                        validExcelData = validExcelData.concat(getValidImportData(uSheet.colMapping, uSheet.data))
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    if(validSheets[uploadPosition].length > 0){
 | 
	
		
			
				|  |  | -                        toImportSheets.push({position: uploadPosition, colMapping: validSheets[uploadPosition][0].colMapping, validExcelData: validExcelData});
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                let validSheetDataB = +new Date();
 | 
	
		
			
				|  |  | -                console.log(`获取表格有效数据时间: ${validSheetDataB - validSheetDataA}==========================================================`);
 | 
	
		
			
				|  |  | +                let importData = JSON.parse(LZString.decompressFromUTF16(compressData));
 | 
	
		
			
				|  |  |                  //匹配的清单库
 | 
	
		
			
				|  |  |                  let stdDateA = +new Date();
 | 
	
		
			
				|  |  |                  const billsLibId = fields.billsLibId !== undefined && fields.billsLibId.length > 0 && fields.billsLibId[0]? parseInt(fields.billsLibId[0]) : null;
 | 
	
	
		
			
				|  | @@ -290,33 +233,21 @@ module.exports = {
 | 
	
		
			
				|  |  |                      stdCharacters = await stdBillCharacterModel.find({billsLibId: billsLibId, deleted: false});
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  let stdData = {stdBills: stdBills, stdJobs: stdJobs, stdCharacters: stdCharacters};
 | 
	
		
			
				|  |  | -                let stdDateB = +new Date();
 | 
	
		
			
				|  |  | -                console.log(`获取标准清单库数据时间: ${stdDateB - stdDateA}`);
 | 
	
		
			
				|  |  |                  //导入表
 | 
	
		
			
				|  |  |                  let importDateA = +new Date();
 | 
	
		
			
				|  |  | -                for(let importData of toImportSheets){
 | 
	
		
			
				|  |  | -                    let updateFrontData = await importSheet(importData, req.session.sessionUser.id, projectID, stdData);
 | 
	
		
			
				|  |  | -                    if(updateFrontData){
 | 
	
		
			
				|  |  | -                        responseData.data.push(updateFrontData);
 | 
	
		
			
				|  |  | +                for(let position in importData){
 | 
	
		
			
				|  |  | +                    if(importData[position].length > 0){
 | 
	
		
			
				|  |  | +                        let updateFrontData = await importSheet(position, importData[position], req.session.sessionUser.id, projectID, stdData);
 | 
	
		
			
				|  |  | +                        if(updateFrontData){
 | 
	
		
			
				|  |  | +                            responseData.data.push(updateFrontData);
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |                  let importDateB = +new Date();
 | 
	
		
			
				|  |  |                  console.log(`导入时间: ${importDateB - importDateA}=========================================================================`);
 | 
	
		
			
				|  |  | -                if(responseData.data.length === 0){
 | 
	
		
			
				|  |  | -                    throw 'excel无有效数据';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                if(invalidSheets.length > 0){
 | 
	
		
			
				|  |  | -                    let msg = invalidSheets.join('、');
 | 
	
		
			
				|  |  | -                    responseData.msg = `${msg},导入失败`;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                //删除暂存文件
 | 
	
		
			
				|  |  | -                fs.unlink(uploadFullName);
 | 
	
		
			
				|  |  |                  res.json(responseData);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              catch (error){
 | 
	
		
			
				|  |  | -                if(fs.existsSync(uploadFullName)){
 | 
	
		
			
				|  |  | -                    fs.unlink(uploadFullName);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  |                  responseData.err = 1;
 | 
	
		
			
				|  |  |                  console.log(error);
 | 
	
		
			
				|  |  |                  responseData.msg = typeof error === 'object' ? '上传失败' : error;
 | 
	
	
		
			
				|  | @@ -327,10 +258,9 @@ module.exports = {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -//
 | 
	
		
			
				|  |  | -async function importSheet(importData, userID, projectID, stdData){
 | 
	
		
			
				|  |  | +async function importSheet(position, excelBills, userID, projectID, stdData){
 | 
	
		
			
				|  |  |          //导入位置的有固定行
 | 
	
		
			
				|  |  | -        let flag = getImportFlag(importData.position);
 | 
	
		
			
				|  |  | +        let flag = getImportFlag(position);
 | 
	
		
			
				|  |  |          if(!flag){
 | 
	
		
			
				|  |  |              throw 'excel数据错误';
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -361,169 +291,19 @@ async function importSheet(importData, userID, projectID, stdData){
 | 
	
		
			
				|  |  |              await billsData.model.create(insertFixedBill);
 | 
	
		
			
				|  |  |              fixedBill = insertFixedBill;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        //将excel数据转换成清单树结构数据
 | 
	
		
			
				|  |  | -        let insertDatas = parseToBillData(importData.validExcelData, importData.colMapping, fixedBill, projectID, stdData);
 | 
	
		
			
				|  |  | -        /*if(insertDatas.length === 0){
 | 
	
		
			
				|  |  | -            throw 'excel无有效数据';
 | 
	
		
			
				|  |  | -        }*/
 | 
	
		
			
				|  |  | -        if(insertDatas.length === 0){
 | 
	
		
			
				|  |  | -            return null;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        //将excel清单数据转换成完整清单数据(设置ParentID、匹配标准清单库)
 | 
	
		
			
				|  |  | +        parseToCompleteBills(excelBills, fixedBill, stdData);
 | 
	
		
			
				|  |  |          //删除相关数据
 | 
	
		
			
				|  |  |          let deleteDatas = await billsData.deepDeleteBill([fixedBill], userID);
 | 
	
		
			
				|  |  |          //新增清单数据
 | 
	
		
			
				|  |  | -        await billsData.importBills(insertDatas);
 | 
	
		
			
				|  |  | +        await billsData.importBills(excelBills);
 | 
	
		
			
				|  |  |          //返回数据以更新前端
 | 
	
		
			
				|  |  |          if(insertFixedBill){
 | 
	
		
			
				|  |  | -            insertDatas.push(insertFixedBill);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        return {fixedBill: fixedBill, insert: {bill: insertDatas, ration: []}, remove: {bill: deleteDatas.bill, ration: deleteDatas.ration}};
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -//是否是有效的表头列格式,只要含有各表需要的列就行,不严格控制多少列
 | 
	
		
			
				|  |  | -function isValidSheet(colMapping, fileType){
 | 
	
		
			
				|  |  | -    function hasField(field, all){
 | 
	
		
			
				|  |  | -        for(let i of all){
 | 
	
		
			
				|  |  | -            if(field === i){
 | 
	
		
			
				|  |  | -                return true;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    let needFields;
 | 
	
		
			
				|  |  | -    if(fileType === uploadType.lj){
 | 
	
		
			
				|  |  | -        //09表:序号、项目编码、项目名称、项目特征、计量单位、工程量、金额
 | 
	
		
			
				|  |  | -        needFields = ['serialNo', 'code', 'name', 'money'];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    else {
 | 
	
		
			
				|  |  | -        //广联达表:序号、项目编码、项目名称、项目特征、计量单位、工程量、工程量明细、费用明细
 | 
	
		
			
				|  |  | -        needFields = ['serialNo', 'code', 'name', 'itemCharacterText', 'unit', 'quantity', 'quantityDetail', 'feeDetail'];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    let hasFieldCount = 0;
 | 
	
		
			
				|  |  | -    for(let attr in colMapping){
 | 
	
		
			
				|  |  | -        if(hasField(attr, needFields)){
 | 
	
		
			
				|  |  | -            hasFieldCount++;
 | 
	
		
			
				|  |  | +            excelBills.push(insertFixedBill);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return hasFieldCount === needFields.length;
 | 
	
		
			
				|  |  | +        return {fixedBill: fixedBill, insert: {bill: excelBills, ration: []}, remove: {bill: deleteDatas.bill, ration: deleteDatas.ration}};
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -//提取excel表头列对应数据
 | 
	
		
			
				|  |  | -function getColMapping(sheetData){
 | 
	
		
			
				|  |  | -    //获取表头
 | 
	
		
			
				|  |  | -    function getHeadRow(sheetData){
 | 
	
		
			
				|  |  | -        for(let rData of sheetData) {
 | 
	
		
			
				|  |  | -            //寻找含有序号的行,认作表头行
 | 
	
		
			
				|  |  | -            for(let cData of rData){
 | 
	
		
			
				|  |  | -                if (cData && cData.toString().replace(/\s/g, '') === '序号') {
 | 
	
		
			
				|  |  | -                    headRow = rData;
 | 
	
		
			
				|  |  | -                    return rData;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        return [];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    //获取需要的表头列与列号对应关系
 | 
	
		
			
				|  |  | -    let colMapping = {};
 | 
	
		
			
				|  |  | -    let headRow = getHeadRow(sheetData);
 | 
	
		
			
				|  |  | -    for(let c = 0; c < headRow.length; c++){
 | 
	
		
			
				|  |  | -        if(headRow[c]){
 | 
	
		
			
				|  |  | -            headRow[c] = headRow[c].toString().replace(/\s/g, '');
 | 
	
		
			
				|  |  | -            //重复的,只取第一个
 | 
	
		
			
				|  |  | -            if(headRow[c] === '序号' && colMapping.serialNo === undefined){
 | 
	
		
			
				|  |  | -                colMapping.serialNo = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if((headRow[c] === '编码' || headRow[c] === '项目编码') && colMapping.code === undefined){
 | 
	
		
			
				|  |  | -                colMapping.code = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if((headRow[c] === '名称' || headRow[c] === '项目名称') && colMapping.name === undefined){
 | 
	
		
			
				|  |  | -                colMapping.name = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if((headRow[c] === '特征' || headRow[c] === '项目特征') && colMapping.itemCharacterText === undefined){
 | 
	
		
			
				|  |  | -                colMapping.itemCharacterText = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if((headRow[c] === '单位' || headRow[c] === '计量单位') && colMapping.unit === undefined){
 | 
	
		
			
				|  |  | -                colMapping.unit = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if((headRow[c] === '工程量' || headRow[c] === '项目工程量') && colMapping.quantity === undefined){
 | 
	
		
			
				|  |  | -                colMapping.quantity = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if(headRow[c].includes('金额') && colMapping.money === undefined){
 | 
	
		
			
				|  |  | -                colMapping.money = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if(headRow[c] === '工程量明细' && colMapping.quantityDetail === undefined){
 | 
	
		
			
				|  |  | -                colMapping.quantityDetail = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if(headRow[c] === '费用明细' && colMapping.feeDetail === undefined){
 | 
	
		
			
				|  |  | -                colMapping.feeDetail = c;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return colMapping;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -function rowExistData(rowData){
 | 
	
		
			
				|  |  | -    for(let cData of rowData){
 | 
	
		
			
				|  |  | -        if(cData !== undefined && cData !== ''){
 | 
	
		
			
				|  |  | -            return true;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -//提取excel表数据中的有效数据(去表头表尾,提取其中的excel数据)(根据fixedBill获取栏头占行数)
 | 
	
		
			
				|  |  | -function getValidImportData(colMapping, sheetData){
 | 
	
		
			
				|  |  | -    let withingD = false;
 | 
	
		
			
				|  |  | -    let validData = [];
 | 
	
		
			
				|  |  | -    function isHead(rData){
 | 
	
		
			
				|  |  | -        return rData[colMapping.serialNo] && rData[colMapping.serialNo].toString().replace(/\s/g, '') === '序号';
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    function isTail(rData){
 | 
	
		
			
				|  |  | -        for(let cData of rData){
 | 
	
		
			
				|  |  | -            if(cData){
 | 
	
		
			
				|  |  | -                let trimCData = cData.toString().replace(/\s/g, '');
 | 
	
		
			
				|  |  | -                if(trimCData === '本页小计' || trimCData === '本页小计'){
 | 
	
		
			
				|  |  | -                    return true;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    for(let r = 0; r < sheetData.length; r++){
 | 
	
		
			
				|  |  | -        let rData = sheetData[r];
 | 
	
		
			
				|  |  | -        if(isHead(rData)){
 | 
	
		
			
				|  |  | -            withingD = true;
 | 
	
		
			
				|  |  | -          /*  if(fixedBill.name !== '施工组织措施项目'){
 | 
	
		
			
				|  |  | -                r++;
 | 
	
		
			
				|  |  | -            }*/
 | 
	
		
			
				|  |  | -            continue;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        else if(isTail(rData)){
 | 
	
		
			
				|  |  | -            withingD = false;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if(withingD && rowExistData(rData)){
 | 
	
		
			
				|  |  | -            validData.push(rData);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        /*if(rData[0]){
 | 
	
		
			
				|  |  | -            //首列去空格
 | 
	
		
			
				|  |  | -            rData[0] = rData[0].toString().replace(/\s/g, '');
 | 
	
		
			
				|  |  | -            //表头
 | 
	
		
			
				|  |  | -            if(rData[0] === '序号'){
 | 
	
		
			
				|  |  | -                withingD = true;
 | 
	
		
			
				|  |  | -                if(fixedBill.name !== '施工组织措施项目'){
 | 
	
		
			
				|  |  | -                    r++;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                continue;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            //表尾
 | 
	
		
			
				|  |  | -            else if(rData[0] === '本页小计' || rData[0] === '合计'){
 | 
	
		
			
				|  |  | -                withingD = false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if(withingD && rowExistData(rData)){
 | 
	
		
			
				|  |  | -            validData.push(rData);
 | 
	
		
			
				|  |  | -        }*/
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return validData;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  function getImportFlag(position){
 | 
	
		
			
				|  |  |      const fixedItem = {'fbfx': fixedFlag.SUB_ENGINERRING, 'jscsxm': fixedFlag.CONSTRUCTION_TECH, 'zzcsxm': fixedFlag.CONSTRUCTION_ORGANIZATION};
 | 
	
	
		
			
				|  | @@ -532,46 +312,22 @@ function getImportFlag(position){
 | 
	
		
			
				|  |  |  function isDef(data){
 | 
	
		
			
				|  |  |      return typeof data !== 'undefined' && data !== null && data !== '';
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -//excel数据转换成清单数据
 | 
	
		
			
				|  |  | -function parseToBillData(validData, colMapping, fixedBill, projectID, stdData){
 | 
	
		
			
				|  |  | -    let rst = [];
 | 
	
		
			
				|  |  | -    let billIdx = {};
 | 
	
		
			
				|  |  | -    let preRootID = -1,
 | 
	
		
			
				|  |  | -        preLeafID = -1,
 | 
	
		
			
				|  |  | -        preID = -1;
 | 
	
		
			
				|  |  | -    //去除转义字符
 | 
	
		
			
				|  |  | -    function removeESC(data){
 | 
	
		
			
				|  |  | -        return isDef(data) ? data.toString().replace(/[\r,\n,\s,\t]/g, '') : data;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    //父节点:1.无序号 2有编码
 | 
	
		
			
				|  |  | -    function isRoot(rData){
 | 
	
		
			
				|  |  | -        //序号和编码去除转义字符(有的表格单元格看起来是没数据,实际含有\r,\n等数据)
 | 
	
		
			
				|  |  | -        let serialNo = removeESC(rData[colMapping.serialNo]);
 | 
	
		
			
				|  |  | -        let code = removeESC(rData[colMapping.code]);
 | 
	
		
			
				|  |  | -        return !isDef(serialNo) && isDef(code);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    //子节点:有序号
 | 
	
		
			
				|  |  | -    function isLeaf(rData){
 | 
	
		
			
				|  |  | -        let serialNo = removeESC(rData[colMapping.serialNo]);
 | 
	
		
			
				|  |  | -        return isDef(serialNo);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    //续数据:1. 前数据有效 2.无序号 3.无编码 4.有名称或特征
 | 
	
		
			
				|  |  | -    function isExtend(preData, rData){
 | 
	
		
			
				|  |  | -        let serialNo = removeESC(rData[colMapping.serialNo]);
 | 
	
		
			
				|  |  | -        let code = removeESC(rData[colMapping.code]);
 | 
	
		
			
				|  |  | -        let name = removeESC(rData[colMapping.name]);
 | 
	
		
			
				|  |  | -        let itemCharacterText = removeESC(rData[colMapping.itemCharacterText]);
 | 
	
		
			
				|  |  | -        return isDef(preData) && (isRoot(preData) || isLeaf(preData)) && !isDef(serialNo) && !isDef(code) && (isDef(name) || isDef(itemCharacterText));
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    function getBillType(rData, flag){
 | 
	
		
			
				|  |  | -        if(flag === fixedFlag.CONSTRUCTION_TECH || flag === fixedFlag.CONSTRUCTION_ORGANIZATION){
 | 
	
		
			
				|  |  | -            return billType.BILL;
 | 
	
		
			
				|  |  | +//将前端解析生成的清单节点数据完善(ParentID、匹配标准清单)
 | 
	
		
			
				|  |  | +function parseToCompleteBills(excelBills, fixedBills, stdData){
 | 
	
		
			
				|  |  | +    //设置清单ParentID
 | 
	
		
			
				|  |  | +    let rootID = fixedBills ? fixedBills.ID: -1;
 | 
	
		
			
				|  |  | +    for(let bills of excelBills){
 | 
	
		
			
				|  |  | +        if(bills.nodeType === 'root'){
 | 
	
		
			
				|  |  | +            rootID = bills.ID;
 | 
	
		
			
				|  |  | +            bills.ParentID = fixedBills.ID;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        else if(flag === fixedFlag.SUB_ENGINERRING){
 | 
	
		
			
				|  |  | -            return isLeaf(rData) ? billType.FX : billType.FB;
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +            bills.ParentID = rootID;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        return null;
 | 
	
		
			
				|  |  | +        delete bills.nodeType;
 | 
	
		
			
				|  |  | +        matchStdBill(bills, stdData);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      //excel数据与标准库数据匹配,根据清单前九位编码匹配,匹配成功则获取标准清单对应的工程专业、特征及内容
 | 
	
		
			
				|  |  |      function matchStdBill(excelBill, stdData){
 | 
	
		
			
				|  |  |          let isMatch = false;
 | 
	
	
		
			
				|  | @@ -610,86 +366,9 @@ function parseToBillData(validData, colMapping, fixedBill, projectID, stdData){
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          if(!isMatch && excelBill.type === billType.FX){//分项不为空,同时在标准清单中不匹配,则识别为补项
 | 
	
		
			
				|  |  | -                excelBill.type = billType.BX;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    for(let r = 0; r < validData.length; r++){
 | 
	
		
			
				|  |  | -       /* //序号和编码去除转义字符(有的表格单元格看起来是没数据,实际含有\r,\n等数据)
 | 
	
		
			
				|  |  | -        let serialNo = validData[r][colMapping.serialNo];
 | 
	
		
			
				|  |  | -        let code = validData[r][colMapping.code];
 | 
	
		
			
				|  |  | -        if(isDef(serialNo)){
 | 
	
		
			
				|  |  | -            serialNo = removeESC(serialNo);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if(isDef(code)){
 | 
	
		
			
				|  |  | -            code = removeESC(code);
 | 
	
		
			
				|  |  | -        }*/
 | 
	
		
			
				|  |  | -        let preData = validData[r-1],
 | 
	
		
			
				|  |  | -            rData = validData[r];
 | 
	
		
			
				|  |  | -        if(fixedBill.flags[0].flag == fixedFlag.CONSTRUCTION_TECH && rData[colMapping.name] === '施工技术措施项目'
 | 
	
		
			
				|  |  | -            || fixedBill.flags[0].flag == fixedFlag.CONSTRUCTION_ORGANIZATION && rData[colMapping.name] === '施工组织措施项目'){
 | 
	
		
			
				|  |  | -            continue;
 | 
	
		
			
				|  |  | +            excelBill.type = billType.BX;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        //过滤无效数据
 | 
	
		
			
				|  |  | -        if(!isRoot(rData) && !isLeaf(rData) && !isExtend(preData, rData)){
 | 
	
		
			
				|  |  | -            continue;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if(isExtend(preData, rData)){
 | 
	
		
			
				|  |  | -            let preBill = billIdx[preID];
 | 
	
		
			
				|  |  | -            if(preBill){
 | 
	
		
			
				|  |  | -                //合并续数据
 | 
	
		
			
				|  |  | -                preBill.code += rData[colMapping.code] ? rData[colMapping.code] : '';
 | 
	
		
			
				|  |  | -                preBill.name += rData[colMapping.name] ? rData[colMapping.name] : '';
 | 
	
		
			
				|  |  | -                preBill.itemCharacterText += rData[colMapping.itemCharacterText] ? rData[colMapping.itemCharacterText] : '';
 | 
	
		
			
				|  |  | -                preBill.unit += rData[colMapping.unit] ? rData[colMapping.unit] : '';
 | 
	
		
			
				|  |  | -                preBill.quantity += rData[colMapping.quantity] ? rData[colMapping.quantity] : '';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        else {
 | 
	
		
			
				|  |  | -            let newID = uuidV1();
 | 
	
		
			
				|  |  | -            let pID = -1;
 | 
	
		
			
				|  |  | -            let preBill = null;
 | 
	
		
			
				|  |  | -            if(isRoot(rData)){
 | 
	
		
			
				|  |  | -                pID = fixedBill.ID;
 | 
	
		
			
				|  |  | -                preBill = billIdx[preRootID];
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else if(isLeaf(rData)){
 | 
	
		
			
				|  |  | -                pID = preRootID !== -1 ? preRootID : fixedBill.ID;
 | 
	
		
			
				|  |  | -                preBill = billIdx[preLeafID];
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            //set bill data
 | 
	
		
			
				|  |  | -            billIdx[newID] = {
 | 
	
		
			
				|  |  | -                ID: newID, ParentID: pID, NextSiblingID: -1,
 | 
	
		
			
				|  |  | -                code: rData[colMapping.code] ? removeESC(rData[colMapping.code]) : '',
 | 
	
		
			
				|  |  | -                name: rData[colMapping.name] ? removeESC(rData[colMapping.name]) : '',
 | 
	
		
			
				|  |  | -                itemCharacterText: rData[colMapping.itemCharacterText] ? rData[colMapping.itemCharacterText] : '',
 | 
	
		
			
				|  |  | -                itemCharacter: [],
 | 
	
		
			
				|  |  | -                jobContentText: '',
 | 
	
		
			
				|  |  | -                jobContent: [],
 | 
	
		
			
				|  |  | -                programID: null,
 | 
	
		
			
				|  |  | -                unit: rData[colMapping.unit] ? rData[colMapping.unit] : '',
 | 
	
		
			
				|  |  | -                quantity: rData[colMapping.quantity] ? rData[colMapping.quantity] : '',
 | 
	
		
			
				|  |  | -                //安全文明
 | 
	
		
			
				|  |  | -                flags: fixedBill.flags[0].flag === fixedFlag.CONSTRUCTION_ORGANIZATION && (rData[colMapping.name] === '安全文明施工专项费用' || rData[colMapping.name] === '安全文明施工费') ?
 | 
	
		
			
				|  |  | -                    [{fieldName: 'fixed', flag: fixedFlag.SAFETY_CONSTRUCTION}] : [],
 | 
	
		
			
				|  |  | -                fees: [],
 | 
	
		
			
				|  |  | -                projectID: projectID,
 | 
	
		
			
				|  |  | -                type: getBillType(rData, fixedBill.flags[0].flag)};
 | 
	
		
			
				|  |  | -            //match stdBill and reset programID、jobContent、itemCharacter
 | 
	
		
			
				|  |  | -            matchStdBill(billIdx[newID], stdData);
 | 
	
		
			
				|  |  | -            //update preBill NextSibling
 | 
	
		
			
				|  |  | -            if(preBill){
 | 
	
		
			
				|  |  | -                preBill.NextSiblingID = newID;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            //set new preID
 | 
	
		
			
				|  |  | -            preID = newID;
 | 
	
		
			
				|  |  | -            preRootID = isRoot(rData) ? newID : preRootID;
 | 
	
		
			
				|  |  | -            preLeafID = isLeaf(rData) ? newID : preLeafID;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    for(let i in billIdx){
 | 
	
		
			
				|  |  | -        rst.push(billIdx[i]);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return rst;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  async function doBillsOrRationsDelete(data) {
 |