Selaa lähdekoodia

feat: 清单精灵编辑器,在左侧工具栏,新增“自动配置材料”

DSK-401
vian 3 vuotta sitten
vanhempi
commit
f7c43f9232

+ 13 - 0
modules/std_billsGuidance_lib/controllers/libController.js

@@ -153,6 +153,19 @@ class BillsGuideLibController extends BaseController{
         }
     }
 
+    async autoSetMaterial(req, res) {
+        try{
+            res.setTimeout(1000 * 60 * 10); // 不设置的话,处理时间过长,会触发默认的响应超时,报错(前端报错,后台还继续在处理)
+            const data = JSON.parse(req.body.data);
+            await billsGuidanceFacade.autoSetMaterial(data.libID);
+            callback(req, res, 0, '', []);
+        }
+        catch(err){
+            console.log(err);
+            callback(req, res, 1, err.message, []);
+        }
+    }
+
     async exportClassExcel(req, res) {
         try{
             const excelData = await billsGuidanceFacade.getClassExcelData(req.query.libID);

+ 155 - 2
modules/std_billsGuidance_lib/facade/facades.js

@@ -42,7 +42,8 @@ module.exports = {
     editBillMaterials,
     generateClassData,
     getClassExcelData,
-    testItems
+    autoSetMaterial,
+    testItems,
 };
 
 function setChildren(bill, parentMap) {
@@ -915,7 +916,6 @@ function combineData(codeData, requireRationData, optionalRationData, classGroup
     return { itemClassData: finData, unMatchRation };
 }
 
-
 // 生成清单分类
 async function generateClassData(libID) {
     const lib = await billsGuideLibModel.findOne({ ID: libID }).lean();
@@ -1099,4 +1099,157 @@ async function testItems(libID) {
    
        }*/
     return delBulk.length;
+}
+
+// 获取清单ID - 指引数据映射
+async function getGuidanceMap(libID) {
+    const guidanceItems = await billsGuideItemsModel.find({ libID }, '-_id').lean();
+    // 清单ID - 指引数据映射
+    const guidanceMap = {};
+    guidanceItems.forEach(item => {
+        (guidanceMap[item.billsID] || (guidanceMap[item.billsID] = [])).push(item);
+    });
+    return guidanceMap;
+}
+
+// 获取清单树
+async function getBillTree(libID) {
+    const lib = await billsGuideLibModel.findOne({ ID: libID }).lean();
+    if (!lib) {
+        throw new Error('无有效精灵库');
+    }
+    const bills = await stdBillsModel.find({ billsLibId: lib.billsLibId }, '-_id ID ParentID NextSiblingID name code unit').lean();
+    const billTree = idTree.createNew({ id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true });
+    billTree.loadDatas(bills);
+    return billTree;
+}
+
+// 获取定额ID - 人材机数组 映射
+async function getRationIDGljMap(rationIDs) {
+    let allGljList = [];
+    const rations = await stdRationModel.find({ ID: { $in: rationIDs } }, '-_id ID rationGljList');
+    const gljIDs = [];
+    rations.forEach(ration => {
+        if (ration.rationGljList && ration.rationGljList.length) {
+            gljIDs.push(...ration.rationGljList.map(rGlj => rGlj.gljId));
+        }
+    });
+    if (gljIDs.length) {
+        allGljList = await gljModel.find({ ID: { $in: [...new Set(gljIDs)] } }, '-_id ID code name specs gljType').lean();
+    }
+    const gljMap = {};
+    allGljList.forEach(glj => gljMap[glj.ID] = glj);
+    const rationIDGljMap = {};
+    rations.forEach(ration => {
+        if (ration.rationGljList && ration.rationGljList.length) {
+            rationIDGljMap[ration.ID] = ration.rationGljList.map(rGlj => gljMap[rGlj.gljId]);
+        } else {
+            rationIDGljMap[ration.ID] = [];
+        }
+    });
+    return rationIDGljMap;
+}
+
+// 需要自动配置材料的工序行
+function needAutoMaterialNode(node) {
+    const needAutoNames = [
+        '水泥强度等级',
+        '混凝土强度等级',
+        '砂浆强度等级',
+        '砌筑砂浆强度等级',
+        '砂浆配合比',
+        '砂强度等级',
+        '构件混凝土强度等级',
+    ];
+    const name = (node.data.name || '').trim();
+    return isProcessNode(node) && needAutoNames.includes(name);
+}
+
+// 获取需要自动配置的数据
+function getNeedAutoSetData(leafBills, guidanceMap) {
+    const allRationIDs = [];
+    const toAutoSetData = []; // 准备要自动配置的数据
+    const markMaterialIDs = []; // 需要打勾材料的数据ID
+    for (let billNode of leafBills) {
+        const guidanceItems = guidanceMap[billNode.data.ID];
+        if (!guidanceItems || !guidanceItems.length) {
+            continue;
+        }
+        const guidanceTree = idTree.createNew({ id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true });
+        guidanceTree.loadDatas(guidanceItems);
+        const needAutoSetItems = guidanceTree.items.filter(node => needAutoMaterialNode(node));
+        // 存在需要自动配置材料
+        if (needAutoSetItems.length) {
+            const rationIDs = guidanceTree.items
+                .filter(node => node.data.rationID)
+                .map(node => node.data.rationID);
+            allRationIDs.push(...rationIDs);
+            markMaterialIDs.push(...needAutoSetItems.map(node => node.data.ID));
+            toAutoSetData.push({
+                rationIDs, // 选择的材料只能从当前定额人材机下选
+                billID: billNode.data.ID,
+            });
+        }
+    }
+
+    return { allRationIDs, markMaterialIDs, toAutoSetData };
+}
+
+const autoSetGljCodes = [
+    '0401',
+    '8001',
+    '8003',
+    '8005',
+    '8009',
+    '8011',
+    '8013',
+    '8015',
+    '8017',
+    '8019',
+    '8021',
+]
+
+// 自动配置材料
+async function autoSetMaterial(libID) {
+    const billTree = await getBillTree(libID);
+    const guidanceMap = await getGuidanceMap(libID);
+    const leafBills = billTree.items.filter(node => !node.children || !node.children.length);
+    const { allRationIDs, markMaterialIDs, toAutoSetData } = getNeedAutoSetData(leafBills, guidanceMap);
+    if (!toAutoSetData.length) {
+        return;
+    }
+    const rationIDGljMap = await getRationIDGljMap([...new Set(allRationIDs)]);
+    const billMaterials = []; // 自动配置材料 (如果原本有配置,则替换原本的:删除旧的doc,插入新的doc)
+    const billIDs = [];
+    toAutoSetData.forEach(({ billID, rationIDs }) => {
+        billIDs.push(billID);
+        // 清单工料机
+        const billGljList = rationIDs.reduce((list, cur) => {
+            if (rationIDGljMap[cur]) {
+                list.push(...rationIDGljMap[cur])
+            }
+            return list;
+        }, []);
+        // 从清单工料机列表中筛选,当前清单下定额工料机中存在的,配置到“配置材料”中,需要命中材料编码前四位
+        const materialIDs = [];
+        billGljList.forEach(glj => {
+            const fourCode = (glj.code || '').substr(0, 4);
+            if (autoSetGljCodes.includes(fourCode) && !materialIDs.includes(glj.ID)) {
+                materialIDs.push(glj.ID);
+            }
+        });
+        const materials = materialIDs.map(gljID => ({ gljID }));
+        billMaterials.push({
+            libID,
+            billID,
+            ID: uuidV1(),
+            materials
+        });
+    });
+    // 打勾材料
+    await billsGuideItemsModel.updateMany({ ID: { $in: markMaterialIDs } }, { $set: { isMaterial: true } });
+    // 删除要被替换的清单材料
+    await billMaterialModel.deleteMany({ libID, billID: { $in: billIDs } });
+    // 插入新的材料
+    await billMaterialModel.insertMany(billMaterials);
 }

+ 1 - 0
modules/std_billsGuidance_lib/routes/routes.js

@@ -27,6 +27,7 @@ module.exports = function (app) {
     router.post('/getBillMaterials', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.getBillMaterials);
     router.post('/editBillMaterials', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.editBillMaterials);
     router.post('/generateClassData', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.generateClassData);
+    router.post('/autoSetMaterial', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.autoSetMaterial);
     router.get('/exportClassExcel', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.exportClassExcel);
     //test
     //router.post('/testItems', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.testItems);

+ 1 - 0
web/maintain/billsGuidance_lib/html/zhiyin.html

@@ -69,6 +69,7 @@
                                     <button id="searchBillBtn" class="btn btn-secondary btn-sm" type="button"><i class="fa fa-search" aria-hidden="true"></i></button>
                                 </span>
                                 </div>
+                                <a id="autoSetMaterial" href="javascript:void(0);" class="btn btn-sm"><i class="fa fa-edit" aria-hidden="true"></i> 自动配置材料</a>
                                 <a id="buildExcel" href="javascript:void(0);" class="btn btn-sm"><i class="fa fa-sign-out" aria-hidden="true"></i> 导出excel</a>
                                
                             </div>

+ 17 - 21
web/maintain/billsGuidance_lib/js/billsGuidance.js

@@ -636,7 +636,7 @@ const billsGuidance = (function () {
 
     //清单表焦点控制
     //@param {Number}row @return {void}
-    function billsInitSel(row, oldSel) {
+    function billsInitSel(row, oldSel, force = false) {
         let guideSheet = guideItem.workBook.getActiveSheet();
         cleanData(guideSheet, guideItem.headers, -1);
         let node = bills.tree.items[row];
@@ -654,7 +654,7 @@ const billsGuidance = (function () {
         $('#editMaterial').removeClass('disabled');
         //显示备注
         $('.main-side-bottom').find('textarea').val(node.data.comment ? node.data.comment : '');
-        if (!node.guidance.tree) {
+        if (!node.guidance.tree || force) {
             getItemsByBills(libID, node.data.ID, function (rstData) {
                 initTree(node.guidance, guideSheet, guideItem.treeSetting, rstData);
                 setNodesExpandState(node.guidance.tree.items, curExpandState);
@@ -882,6 +882,8 @@ const billsGuidance = (function () {
         if (isProcessNode(node)) {
             $('.main-bottom-content').find('textarea').attr('readonly', false);
         }
+        // 配置材料
+        $('#editMaterial').removeClass('disabled');
     }
     //项目指引表焦点控制
     //@param {Number}row @return {void}
@@ -2264,25 +2266,6 @@ const billsGuidance = (function () {
     //@return {void}
     function initDomEvents() {
 
-    // $('#autoSetMaterialBtn').on("click",()=>{
-    //     console.log(libID);
-    //     console.log(bills.cache);
-    //     const billIDList=[];
-    //     for(let i=0;i<20;i++){
-    //         billIDList.push(bills.cache[i].ID);
-    //     }
-    //     const rationItems = await billsGuideItemsModel.find({ libID, billsID: { $in: billIDList }, rationID: { $ne: null } }, '-_id rationID billsID').lean();
-    // //     bills.cache.forEach((item,index)=>{
-
-    // // })
-    //     const aa= { 
-    //             grid:'std_billsGuidance_materials',
-    //             libID: 'cf851660-3534-11ec-9641-2da8021b8e4e',
-    //             billID: '1d2fc566-0a9b-11ea-a33d-5388f9783b09' 
-    //         }
-    //     })
-
-
         // 清单材料窗口
         $("#bill-material-modal").on('hidden.bs.modal', function () {
             billMaterial.cache = [];
@@ -2296,6 +2279,19 @@ const billsGuidance = (function () {
             }
         });
 
+        /* 自动配置材料 */
+        $('#autoSetMaterial').click(async function() {
+            $.bootstrapLoading.start();
+            try {
+                await ajaxPost('/billsGuidance/api/autoSetMaterial', { libID}, 1000 * 60 * 10);
+                // 刷新显示
+                window.location.reload();
+            } catch (error) {
+                alert(error);
+            }
+            $.bootstrapLoading.end();
+        });
+
         /* excel */
         // 生成excel
         $('#buildExcel').click(function () {