Pārlūkot izejas kodu

导入清单逻辑修改

zhongzewei 7 gadi atpakaļ
vecāks
revīzija
107f629ec1

+ 130 - 25
modules/main/controllers/bills_controller.js

@@ -209,6 +209,7 @@ module.exports = {
         const uploadOption = {
             uploadDir: './public'
         };
+        const uploadType = {lj: 'lj', gld: 'gld'};
         const form = new multiparty.Form(uploadOption);
         let uploadFullName;
         form.parse(req, async function(err, fields, files) {
@@ -226,6 +227,12 @@ module.exports = {
                 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;
+                //广联达表始终插入到分部分项,将文件名重命名为分部分项触发导入到分部分项部分
+                if(fileType === uploadType.gld){
+                    file.originalFilename = '广联达分部分项工程';
+                }
                 // 重命名文件名
                 uploadFullName = uploadOption.uploadDir + '/' + file.originalFilename;
                 fs.renameSync(file.path, uploadFullName);
@@ -234,13 +241,34 @@ module.exports = {
                 if (sheet[0] === undefined || sheet[0].data === undefined) {
                     throw 'excel没有对应数据';
                 }
-                //导入的数据是否含有固定行(分部分项、施工技术措施项目、施工组织措施项目,通过文件名判断)
+                //获取表的列设置确定导入的格式是否合法(09、广联达)
+               //console.log(sheet[0].data);
+                let colMapping = getColMapping(sheet[0].data);
+                console.log(`colMapping`);
+                console.log(colMapping);
+
+                //导入的数据是否含有固定行(分部分项、施工技术措施项目、施工组织措施项目,通过文件名判断)、确定导入位置
                 let flag = getImportFlag(file.originalFilename);
                 if(!flag){
                     throw 'excel数据错误';
                 }
                 let fixedBill = await billsData.model.findOne({projectID: projectID, 'flags.flag': flag, deleteInfo: null});
                 let insertFixedBill = null;
+
+                let vData = getValidImportData(colMapping, sheet[0].data, fixedBill);
+                console.log(`vData`);
+                console.log(vData);
+                for(let rData of vData){
+                    let t = {};
+                    t.serialNo = rData[colMapping.serialNo];
+                    t.code = rData[colMapping.code];
+                    t.name = rData[colMapping.name];
+                    t.itemCharacterText = rData[colMapping.itemCharacterText];
+                    t.unit = rData[colMapping.unit];
+                    t.quantity = rData[colMapping.quantity];
+                    console.log(t);
+                }
+               // throw 'test';
                 //导入xx措施项目,若不存在此固定清单,则先插入相关固定清单
                 if(!fixedBill){
                     //分部分项工程(不可删除)应存在
@@ -277,7 +305,14 @@ module.exports = {
                     stdCharacters = await stdBillCharacterModel.find({billsLibId: billsLibId, deleted: false});
                 }
                 //将excel数据转换成清单树结构数据
-                let insertDatas = parseToBillData(getValidImportData(sheet[0].data, fixedBill), getColMapping(sheet[0].data), fixedBill, projectID, {stdBills: stdBills, stdJobs: stdJobs, stdCharacters: stdCharacters});
+                console.log(`sheet[0].data`);
+                console.log(sheet[0].data);
+                let insertDatas = parseToBillDsata(getValidImportData(colMapping, sheet[0].data, fixedBill), colMapping, fixedBill, projectID, {stdBills: stdBills, stdJobs: stdJobs, stdCharacters: stdCharacters});
+                console.log(`insertDatas`);
+                console.log(insertDatas);
+                if(insertDatas.length === 0){
+                    throw 'excel无有效数据';
+                }
                 //删除相关数据
                 let deleteDatas = await billsData.deepDeleteBill([fixedBill], req.session.sessionUser.id);
                 //新增清单数据
@@ -296,7 +331,8 @@ module.exports = {
                     fs.unlink(uploadFullName);
                 }
                 responseData.err = 1;
-                responseData.msg = error;
+                console.log(error);
+                responseData.msg = typeof error === 'object' ? '上传失败' : error;
                 res.json(responseData);
             }
 
@@ -305,30 +341,48 @@ module.exports = {
 
 };
 
+//是否是有效的表头列格式
+function isValidSheet(sheetData, fileType){
+
+}
+
 //提取excel表头列对应数据
 function getColMapping(sheetData){
     //获取表头
     let headRow = [];
     for(let rData of sheetData) {
-        if (rData[0] && rData[0].toString().replace(/\s/g, '') === '序号') {
-            headRow = rData;
-            break;
+        //寻找含有序号的行,认作表头行
+        for(let cData of rData){
+            if (cData && cData.toString().replace(/\s/g, '') === '序号') {
+                headRow = rData;
+                break;
+            }
         }
     }
-    //获取表头列与列号对应关系
+    //获取需要的表头列与列号对应关系
     let colMapping = {};
     for(let c = 0; c < headRow.length; c++){
         if(headRow[c]){
             headRow[c] = headRow[c].toString().replace(/\s/g, '');
-            switch(headRow[c]){
-                case '序号': colMapping.serialNo = c; break;
-                case '项目编码': colMapping.code = c; break;
-                case '项目名称': colMapping.name = c; break;
-                case '项目特征': colMapping.itemCharacterText = c; break;
-                case '计量单位': colMapping.unit = c; break;
-                case '工程量': colMapping.quantity = c; break;
+            //重复的,只取第一个
+            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.code === undefined){
+                colMapping.quantity = c;
             }
-
         }
     }
     return colMapping;
@@ -342,12 +396,39 @@ function rowExistData(rowData){
     return false;
 }
 //提取excel表数据中的有效数据(去表头表尾,提取其中的excel数据)(根据fixedBill获取栏头占行数)
-function getValidImportData(sheetData, fixedBill){
+function getValidImportData(colMapping, sheetData, fixedBill){
     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(rData[0]){
+        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, '');
             //表头
@@ -365,7 +446,7 @@ function getValidImportData(sheetData, fixedBill){
         }
         if(withingD && rowExistData(rData)){
             validData.push(rData);
-        }
+        }*/
     }
     return validData;
 }
@@ -386,17 +467,32 @@ function parseToBillData(validData, colMapping, fixedBill, projectID, stdData){
     let preRootID = -1,
         preLeafID = -1,
         preID = -1;
-    //合并了项目特征,且行有数据
+    function isDef(data){
+        return typeof data !== 'undefined' && data !== null && data !== '';
+    }
+    //去除转义字符
+    function removeESC(data){
+        return isDef(data) ? data.toString().replace(/[\r,\n,\s,\t]/g, '') : data;
+    }
+    //父节点:1.无序号 2有编码
     function isRoot(rData){
-        return rData[colMapping.itemCharacterText] !== undefined && rData[colMapping.itemCharacterText] === '' && rowExistData(rData);
+        //序号和编码去除转义字符(有的表格单元格看起来是没数据,实际含有\r,\n等数据)
+        let serialNo = removeESC(rData[colMapping.serialNo]);
+        let code = removeESC(rData[colMapping.code]);
+        return !isDef(serialNo) && isDef(code);
     }
-    //不合并且有序号
+    //子节点:有序号
     function isLeaf(rData){
-        return (rData[colMapping] === undefined || rData[colMapping] !== '') && rData[colMapping.serialNo] && rData[colMapping.serialNo] !== '';
+        let serialNo = removeESC(rData[colMapping.serialNo]);
+        return isDef(serialNo);
     }
-    //续数据,上一行数据是有效节点且无序号
+    //续数据:1. 前数据有效 2.无序号 3.无编码 4.有名称或特征
     function isExtend(preData, rData){
-        return preData && (isRoot(preData) || isLeaf(preData)) &&  !isRoot(rData) && (rData[colMapping.serialNo] === undefined || rData[colMapping.serialNo] === '');
+        let serialNo = removeESC(rData[colMapping.serialNo]);
+        let code = removeESC(rData[colMapping.code]);
+        let name = rData[colMapping.name];
+        let itemCharacterText = 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){
@@ -443,11 +539,20 @@ function parseToBillData(validData, colMapping, fixedBill, projectID, stdData){
                 }
             }
         }
-        if(!isMatch && excelBill.type === billType.FX){//分项在标准清单中不匹配,则识别为补项
+        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] === '施工技术措施项目'

+ 4 - 0
web/building_saas/main/html/main.html

@@ -1421,6 +1421,10 @@
             }
 
             $(document).ready(function(){
+                let a = '';
+                if(a === ''){
+                    console.log('a');
+                }
                 //
             });
         </SCRIPT>

+ 16 - 0
web/building_saas/main/js/views/project_view.js

@@ -1961,6 +1961,16 @@ function canInsertRationNode(selected) {//判断是否能插入定额、量价
     }
 }
 
+//导入类型(09表、广联达)
+const uploadType = {lj: 'lj', gld: 'gld'};
+let fileType = uploadType.lj;
+
+$('#uploadLj').click(function () {
+    fileType = uploadType.lj;
+});
+$('#uploadGld').click(function () {
+   fileType = uploadType.gld;
+});
 
 //选择要导入的excel文件
 $('#customFile').change(function () {
@@ -1968,6 +1978,7 @@ $('#customFile').change(function () {
     if(file.files.length > 0){
         $('.custom-file-label').text(`${file.files[0].name} 准备导入上传`);
         $('#uploadAlert').hide();
+        console.log(file.files);
     }
     else{
         $('.custom-file-label').text(`请选择上传文件`);
@@ -1988,6 +1999,8 @@ $('#uploadConfirm').click(function () {
         if(!projectID || projectID <= 0){
             throw '项目数据出错';
         }
+        //导入表类型(09lj、广联达gld)
+        formData.append('fileType', fileType);
         formData.append('projectID', projectID);
         //要去匹配的清单库(第一个)
         let matchBillLibId = projectInfoObj.projectInfo.engineeringInfo.bill_lib.length > 0 ? projectInfoObj.projectInfo.engineeringInfo.bill_lib[0].id : null;
@@ -2012,6 +2025,9 @@ $('#uploadConfirm').click(function () {
                     $('#import').modal("hide");
                     //更新前端
                     doAfterImport(response.data);
+                    if($.bootstrapLoading.isLoading()){
+                        $.bootstrapLoading.end();
+                    }
                 } else {
                     const message = response.msg !== undefined ? response.msg : '上传失败!';
                     $.bootstrapLoading.end();

+ 8 - 1
web/common/html/header.html

@@ -8,8 +8,15 @@
         <li class="nav-item">
             <a class="nav-link" href="#" aria-expanded="false" data-toggle="modal" data-target="#poj-set"><i class="fa fa-cube"></i> 项目属性</a>
         </li>
-        <li class="nav-item">
+        <!--<li class="nav-item">
             <a class="nav-link" href="#import" data-toggle="modal" data-target="#import"><i class="fa fa-cloud-upload"></i> 导入</a>
+        </li>-->
+        <li class="nav-item dropdown">
+            <a class="nav-link dropdown-toggle" href="javascript:void(0);" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa  fa-cloud-upload"></i> 导入</a>
+            <div class="dropdown-menu">
+                <a id="uploadLj" class="dropdown-item" href="#import" data-toggle="modal" data-target="#import">导入09表Excel清单</a>
+              <!--  <a id="uploadGld" class="dropdown-item" href="#import" data-toggle="modal" data-target="#import">导入广联达算量Excel清单</a>-->
+            </div>
         </li>
         <li class="nav-item dropdown">
             <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-wrench"></i> 工具</a>