瀏覽代碼

调差单个明细计量功能

laiguoran 3 年之前
父節點
當前提交
180f3448d4

+ 16 - 2
app/const/cld_office.js

@@ -33,7 +33,14 @@ const officeType = {
     JIANGSU: 24,
     LIAONING: 25,
     NINGXIA: 26,
-    YJZX: 27,
+    SHANXI: 27,
+    SHAN3XI: 28,
+    SHANGHAI: 29,
+    TIANJIN: 30,
+    XIZANG: 31,
+    XINJIANG: 32,
+    QINGHAI: 33,
+    YJZX: 100,
 };
 
 const office = [];
@@ -46,7 +53,7 @@ office[officeType.SICHUAN] = '四川办';
 office[officeType.CHONGQING] = '重庆办';
 office[officeType.NEIMENG] = '内蒙办';
 office[officeType.ZHEJIANG] = '浙江办';
-office[officeType.SHANDONG] = '上海办';
+office[officeType.SHANDONG] = '山东办';
 office[officeType.ZONGBU] = '总部';
 office[officeType.YUNNAN] = '云南办';
 office[officeType.GUIZHOU] = '贵州办';
@@ -62,6 +69,13 @@ office[officeType.JILIN] = '吉林办';
 office[officeType.JIANGSU] = '江苏办';
 office[officeType.LIAONING] = '辽宁办';
 office[officeType.NINGXIA] = '宁夏办';
+office[officeType.SHANXI] = '山西办';
+office[officeType.SHAN3XI] = '陕西办';
+office[officeType.SHANGHAI] = '上海办';
+office[officeType.TIANJIN] = '天津办';
+office[officeType.XIZANG] = '西藏办';
+office[officeType.XINJIANG] = '新疆办';
+office[officeType.QINGHAI] = '青海办';
 office[officeType.YJZX] = '总部-造价研究中心';
 // const office = [
 //     {id: officeType.ANHUI, name: '安徽办'},

+ 14 - 3
app/controller/material_controller.js

@@ -479,6 +479,7 @@ module.exports = app => {
                 // 取所有已被调用的工料清单表
                 responseData.data.materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, ctx.material.id);
                 responseData.data.materialNotJoinListData = await ctx.service.materialListNotjoin.getAllDataByCondition({ where: { tid: ctx.tender.id, mid: ctx.material.id } });
+                responseData.data.materialSelfListData = await ctx.service.materialListSelf.getAllDataByCondition({ where: { tid: ctx.tender.id, mid: ctx.material.id } });
                 // 获取清单数据
                 responseData.data.ledger = await ctx.service.ledger.getData(ctx.tender.id);
                 responseData.data.pos = await ctx.service.pos.getPosData({ tid: ctx.tender.id });
@@ -491,7 +492,7 @@ module.exports = app => {
                     return ctx.helper.compareCode(a.b_code, b.b_code);
                 });
                 const lastMaterial = await ctx.service.material.getLastestMaterial(ctx.tender.id, true);
-                if (!lastMaterial.is_new) {
+                if (lastMaterial && !lastMaterial.is_new) {
                     const materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, lastMaterial.id);
                     const hadBillsList = [];
                     for (const ml of materialListData) {
@@ -547,7 +548,7 @@ module.exports = app => {
                 // 获取gclidlist值
                 const lastMaterial = await ctx.service.material.getLastestCompleteMaterial(ctx.tender.id);
                 // responseData.data.materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, lastMaterial.id);
-                if (!lastMaterial.is_new) {
+                if (lastMaterial && !lastMaterial.is_new) {
                     const materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, lastMaterial.id);
                     const hadBillsList = [];
                     for (const ml of materialListData) {
@@ -568,6 +569,10 @@ module.exports = app => {
                 }
                 const hadBillsList = await ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: ctx.tender.id } });
                 responseData.data.gclList = hadBillsList;
+
+                // 获取上一期的单独设置的清单明细
+                responseData.data.materialListForSelf = lastMaterial ? await ctx.service.materialList.getAllDataByCondition({ where: { tid: ctx.tender.id, mid: lastMaterial.id, is_self: 1 } }) : [];
+                responseData.data.selfList = lastMaterial ? await ctx.service.materialListSelf.getAllDataByCondition({ where: { tid: ctx.tender.id, mid: lastMaterial.id } }) : [];
                 // 获取清单设置已选清单
                 // const materialChecklistData = await ctx.service.materialChecklist.getAllDataByCondition({ where: { tid: ctx.tender.id } });
                 // responseData.data.materialChecklistData = materialChecklistData.sort(function(a, b) {
@@ -718,7 +723,7 @@ module.exports = app => {
                     msg: '',
                     data: {},
                 };
-                if (ctx.session.sessionProject.page_show.openMaterialChecklist && (data.type !== 'join' && data.type !== 'notjoin' && data.type !== 'useOther')) {
+                if (ctx.session.sessionProject.page_show.openMaterialChecklist && ctx.app._.findIndex(['join', 'notjoin', 'self', 'noself', 'useOther'], data.type) === -1) {
                     throw '清单设置功能已启动,请前往清单设置页操作清单内容';
                 }
                 switch (data.type) {
@@ -747,6 +752,12 @@ module.exports = app => {
                     case 'notjoin':
                         responseData.data = await ctx.service.materialListNotjoin.add(data.select);
                         break;
+                    case 'self':
+                        responseData.data = await ctx.service.materialListSelf.add(data.select);
+                        break;
+                    case 'noself':
+                        await ctx.service.materialListSelf.del(data.select.id);
+                        break;
                     case 'paste':
                         await ctx.service.materialList.saveDatas(data.updateData);
                         // 取所有工料表

+ 603 - 91
app/public/js/material_list.js

@@ -23,6 +23,17 @@ function findNotJoinLeafXmj(x, type = '') {
     });
 }
 
+function findSelfLeafXmj(x, type = '') {
+    if (type === 'index') {
+        return selfList.findIndex(function (item) {
+            return item.gcl_id === x.gcl_id && item.xmj_id === x.id && (x.mx_id === undefined || (x.mx_id !== undefined && x.mx_id === item.mx_id));
+        });
+    }
+    return selfList.find(function (item) {
+        return item.gcl_id === x.gcl_id && item.xmj_id === x.id && (x.mx_id === undefined || (x.mx_id !== undefined && x.mx_id === item.mx_id));
+    });
+}
+
 function getMpSpreadByMBData(id) {
     const info = materialBillsData.find(function (item) {
         return item.id === parseInt(id);
@@ -119,7 +130,11 @@ $(document).ready(() => {
             .css("left", hitInfo.x - 15);
         $(this._toolTipElement).hide();
         // document.body.insertBefore(this._toolTipElement, null);
-        $('#material-spread-div').append(this._toolTipElement, null);
+        if (hitInfo.sheet.yn === 4) { // 用于区分上下两个工料关联表
+            $('#material-self-spread-div').append(this._toolTipElement, null);
+        } else {
+            $('#material-spread-div').append(this._toolTipElement, null);
+        }
         $(this._toolTipElement).show("fast");
     };
     TipCellType.prototype.processMouseLeave = function (hitInfo) {
@@ -169,7 +184,7 @@ $(document).ready(() => {
             SpreadJsObj.loadSheetData(leafXmjSpread.getActiveSheet(), SpreadJsObj.DataType.Data, leafXmjs);
 
             // 对清单调差工料table的单位数量进行改变
-            materialSpreadSetting.cols[materialSpreadSetting.cols.length - 2].title = '|' + '每' + gcl.unit + '数量 �';
+            // materialSpreadSetting.cols[materialSpreadSetting.cols.length - 2].title = '|' + '每' + gcl.unit + '数量 �';
             // SpreadJsObj.initSheet(materialSpread.getActiveSheet(), materialSpreadSetting);
         } else {
             SpreadJsObj.loadSheetData(leafXmjSpread.getActiveSheet(), SpreadJsObj.DataType.Data, []);
@@ -201,6 +216,21 @@ $(document).ready(() => {
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
         readOnly: true,
+        rowHeader:[
+            {
+                rowHeaderType: 'circle',
+                setting: {
+                    size: 5,
+                    indent: 16,
+                    getColor: function (index, data) {
+                        if (!data) return;
+                        if (_.findIndex(selfList, { gcl_id: data.gcl_id, xmj_id: data.id, mx_id: (data.mx_id ? data.mx_id : null) }) !== -1) {
+                            return '#dc3545';
+                        }
+                    }
+                },
+            },
+        ],
     };
     // 加载清单数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
     postData(window.location.pathname + '/load', {}, async function (result) {
@@ -209,8 +239,9 @@ $(document).ready(() => {
         pos = result.pos;
         curPosData = result.curPosData;
         materialListData = result.materialListData;
-        const gclList = result.gclList;
+        gclList = result.gclList;
         notJoinList = result.materialNotJoinListData;
+        selfList = result.materialSelfListData;
         materialChecklistData = result.materialChecklistData;
         // 解析清单汇总数据
         gclGatherModel.loadLedgerData(ledger, curLedgerData);
@@ -274,8 +305,17 @@ $(document).ready(() => {
                 return item.qc_qty || item.contract_qty
             });
             // 取交集
+            const selfListGcl = _.uniq(_.map(selfList, 'gcl_id'));
             gclGatherData = _.filter(gclGatherData, function (item) {
-                return _.find(materialChecklistData, { b_code: item.b_code, name: item.name, unit: item.unit, unit_price: item.unit_price });
+                if(_.find(materialChecklistData, { b_code: item.b_code, name: item.name, unit: item.unit, unit_price: item.unit_price })) {
+                    return true;
+                } else {
+                    const gcl_ids = item.leafXmjs ? _.uniq(_.map(item.leafXmjs, 'gcl_id')) : [];
+                    const jiaoji = _.intersection(gcl_ids, selfListGcl);
+                    if (jiaoji.length > 0) {
+                        return true;
+                    }
+                }
             });
         } else {
             gclGatherData = gclGatherData.filter(item => {
@@ -287,11 +327,16 @@ $(document).ready(() => {
         // 加载清单数据
         SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Data, gclGatherData);
         loadLeafXmjData(0);
-        loadMaterialData(0, 0);
+        loadMaterialData(0);
+        loadXmjMaterialData(0, 0);
         const sheet = materialSpread.getActiveSheet();
         sheet.suspendPaint();
         sheet.setCellType(1, 3, new TipCellType(), spreadNS.SheetArea.colHeader);
         sheet.resumePaint();
+        const selfSheet = materialSelfSpread.getActiveSheet();
+        selfSheet.suspendPaint();
+        selfSheet.setCellType(1, 3, new TipCellType(), spreadNS.SheetArea.colHeader);
+        selfSheet.resumePaint();
         checkNotJoinMaterialData();
     });
     // const leafXmjCol = {
@@ -356,27 +401,115 @@ $(document).ready(() => {
     SpreadJsObj.initSpreadSettingEvents(materialSpreadSetting, materialCol);
     // 获取项目节数据
     let materialList = [];
-    function loadMaterialData(iGclRow, iLXmjRow) {
+    function loadMaterialData(iGclRow) {
+        const gcl = gclGatherData[iGclRow];
+        if (gcl && gcl.leafXmjs) {
+            const gcl_ids = gcl.leafXmjs ? _.uniq(_.map(gcl.leafXmjs, 'gcl_id')) : [];
+            materialList = [];
+            const newMaterialList = _.uniqBy(_.filter(gclList, function (m) {
+                return _.indexOf(gcl_ids, m.gcl_id) !== -1;
+            }), 'mb_id');
+            for(const m of newMaterialList) {
+                const bills = _.find(materialBillsData, { id: m.mb_id });
+                if(bills) {
+                    m.code = bills.code;
+                    m.name = bills.name;
+                    m.unit = bills.unit;
+                }
+            }
+            console.log(newMaterialList);
+            materialList = newMaterialList;
+            // 对清单调差工料table的单位数量进行改变
+            materialSpreadSetting.cols[materialSpreadSetting.cols.length - 2].title = '|' + '每' + gcl.unit + '数量 �';
+            SpreadJsObj.initSheet(materialSpread.getActiveSheet(), materialSpreadSetting);
+            SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialList);
+        } else {
+            materialSpreadSetting.cols[materialSpreadSetting.cols.length - 2].title = '数量 �';
+            SpreadJsObj.initSheet(materialSpread.getActiveSheet(), materialSpreadSetting);
+            SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, []);
+        }
+        SpreadJsObj.resetTopAndSelect(materialSpread.getActiveSheet());
+    }
+
+    // 调差清单工料table
+    const materialSelfSpread = SpreadJsObj.createNewSpread($('#material-self-spread')[0]);
+    const materialSelfSpreadSetting = {
+        cols: [
+            {title: '明细清单工料含量|编号', colSpan: '5|1', rowSpan: '1|1', field: 'code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
+            {title: '|名称', colSpan: '|1', rowSpan: '|1', field: 'name', hAlign: 0, width: 100, formatter: '@', readOnly: true},
+            {title: '|单位', colSpan: '|1', rowSpan: '|1', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true},
+            {title: '|数量 �', colSpan: '|1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 80, type: 'Number', readOnly: 'readOnly.isEdit'},
+            {title: '|计算式', colSpan: '1', rowSpan: '|1', field: 'expr', hAlign: 2, width: 120, formatter: '@', readOnly: 'readOnly.isEdit'},
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+    };
+
+    const materialSelfBase = {
+        isEdit: function (data, type = 'normal') {
+            // 是否本期添加的工料
+            // return data.order === stage_order && !openMaterialChecklist;
+            let flag = true;
+            if (type === 'del') {
+                flag = data.order === stage_order;
+            }
+            return flag && !openMaterialChecklist;
+        }
+    };
+
+    const materialSelfCol = {
+        readOnly: {
+            isEdit: function (data) {
+                // const sheet = leafXmjSpread.getActiveSheet();
+                // const select = SpreadJsObj.getSelectObject(sheet);
+                // const notx = findNotJoinLeafXmj(select);
+                // return !(!readOnly && notx === undefined && materialBase.isEdit(data));
+                return !(!readOnly && materialSelfBase.isEdit(data));
+            },
+        },
+    };
+    SpreadJsObj.initSpreadSettingEvents(materialSelfSpreadSetting, materialSelfCol);
+    let materialListSelf = [];
+    function loadXmjMaterialData(iGclRow, iLXmjRow) {
+        // 存在单独设置的才展示,不然隐藏
         const gcl = gclGatherData[iGclRow];
         const leafXmjs = gcl && gcl.leafXmjs ? gcl.leafXmjs.filter(item => {
             return item.qc_qty || item.contract_qty
         }) : null;
-        console.log(gcl, leafXmjs);
         if (leafXmjs) {
             const xmj = leafXmjs[iLXmjRow];
             console.log(xmj, iLXmjRow);
-            materialList = [];
-            for (const m of materialListData) {
-                if (m.gcl_id === xmj.gcl_id && m.xmj_id === xmj.id && ((xmj.mx_id !==undefined && m.mx_id === xmj.mx_id) || xmj.mx_id === undefined)) {
-                    materialList.push(m);
+            materialListSelf = [];
+            if (_.findIndex(selfList, { gcl_id: xmj.gcl_id, xmj_id: xmj.id, mx_id: (xmj.mx_id ? xmj.mx_id : null) }) != -1) {
+                for (const m of materialListData) {
+                    if (m.gcl_id === xmj.gcl_id && m.xmj_id === xmj.id && ((xmj.mx_id !==undefined && m.mx_id === xmj.mx_id) || xmj.mx_id === undefined)) {
+                        materialListSelf.push(m);
+                    }
                 }
+                $('#material-self-spread-div').addClass('active');
+                showSelfSideTools(true);
+            } else {
+                $('#material-self-spread-div').removeClass('active');
+                showSelfSideTools(false);
             }
-            console.log(xmj, materialList);
-            SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialList);
+            // 对清单调差工料table的单位数量进行改变
+            materialSelfSpreadSetting.cols[materialSelfSpreadSetting.cols.length - 2].title = '|' + '每' + gcl.unit + '数量 �';
+            SpreadJsObj.initSheet(materialSelfSpread.getActiveSheet(), materialSelfSpreadSetting);
+            SpreadJsObj.loadSheetData(materialSelfSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialListSelf);
         } else {
-            SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, []);
+            $('#material-self-spread-div').removeClass('active');
+            showSelfSideTools(false);
+            materialSpreadSetting.cols[materialSelfSpreadSetting.cols.length - 2].title = '数量 �';
+            SpreadJsObj.initSheet(materialSelfSpread.getActiveSheet(), materialSelfSpreadSetting);
+            SpreadJsObj.loadSheetData(materialSelfSpread.getActiveSheet(), SpreadJsObj.DataType.Data, []);
         }
-        // SpreadJsObj.reLoadSheetData(leafXmjSpread.getActiveSheet());
+        SpreadJsObj.resetTopAndSelect(materialSelfSpread.getActiveSheet());
+        leafXmjSpread.refresh();
+        materialSelfSpread.refresh();
     }
 
     // SpreadJsObj.locateTreeNode(ledgerSpread.getActiveSheet(), )
@@ -405,11 +538,13 @@ $(document).ready(() => {
     }
     // checkNotJoinMaterialData();
     // 对添加工料表格赋值
-    function changeMaterialTable() {
+    function changeMaterialTable(from = 'all') {
         $('#materialBills tr').removeClass('table-secondary');
         $('#materialBills').find('input').removeAttr('disabled');
         $('#materialBills').find('input').prop('checked', false);
-        for (const [index, ml] of materialList.entries()) {
+        const searchList = from === 'self' ? materialListSelf : materialList;
+        console.log(searchList);
+        for (const [index, ml] of searchList.entries()) {
             const mbIndex = materialBillsData.findIndex(function (item) {
                 return item.id === ml.mb_id;
             });
@@ -434,57 +569,67 @@ $(document).ready(() => {
         for (let s = 0; s < selectList.length; s++) {
             mb_id.push($('#materialBills').find('input:checked').eq(s).val());
         }
-        // 获取当前项目节或部位明细id
-        const sheet = ledgerSpread.getActiveSheet();
-        const select = SpreadJsObj.getSelectObject(sheet);
-        const index = gclGatherData.indexOf(select);
-        const leafXmjSheet = leafXmjSpread.getActiveSheet();
-        const leafXmjSelect = SpreadJsObj.getSelectObject(leafXmjSheet);
-        const gcl = gclGatherData[index].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
-        const leafXmjIndex = gcl.indexOf(leafXmjSelect);
-        // const xmj = gcl[leafXmjIndex];
-        // const data = {
-        //     xmj_id: xmj.id,
-        //     gcl_id: xmj.gcl_id,
-        //     mx_id: xmj.mx_id !== undefined ? xmj.mx_id : '',
-        //     mb_id: mb_id,
-        //     gather_qty: xmj.gather_qty,
-        // };
-        const datas = [];
-        for (const xmj of gcl) {
+        const type = $('#add_type').val();
+        if (type === 'all') {
+            // 获取当前项目节或部位明细id
+            const sheet = ledgerSpread.getActiveSheet();
+            const select = SpreadJsObj.getSelectObject(sheet);
+            const index = gclGatherData.indexOf(select);
+            const gcl = gclGatherData[index].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
+            const datas = [];
+            for (const xmj of gcl) {
+                const notx = findNotJoinLeafXmj(xmj);
+                const data = {
+                    xmj_id: xmj.id,
+                    gcl_id: xmj.gcl_id,
+                    mx_id: xmj.mx_id ? xmj.mx_id : null,
+                    gather_qty: xmj.gather_qty,
+                    is_join: notx === undefined ? 1 : 0,
+                };
+                datas.push(data);
+            }
+            console.log(datas, gcl, mb_id);
+            postData(window.location.pathname + '/save', {type: 'adds', postData: {xmjs: datas, mbIds: mb_id}}, function (result) {
+                materialListData = result.materialListData;
+                gclList = result.gclList;
+                // toastr.success('已成功应用');
+                calculateJiaCha(gclGatherData);
+                // const index = gclGatherData.indexOf(ledgerSelect);
+                loadLeafXmjData(index);
+                // const xmjSheet = leafXmjSpread.getActiveSheet();
+                // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
+                // const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
+                loadMaterialData(index);
+                SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
+                $('#addgl').modal('hide');
+            });
+        } else if (type === 'self') {
+            // 获取当前项目节或部位明细id
+            const sheet = ledgerSpread.getActiveSheet();
+            const select = SpreadJsObj.getSelectObject(sheet);
+            const index = gclGatherData.indexOf(select);
+            const leafXmjSheet = leafXmjSpread.getActiveSheet();
+            const leafXmjSelect = SpreadJsObj.getSelectObject(leafXmjSheet);
+            const gcl = gclGatherData[index].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
+            const leafXmjIndex = gcl.indexOf(leafXmjSelect);
+            const xmj = gcl[leafXmjIndex];
             const notx = findNotJoinLeafXmj(xmj);
             const data = {
                 xmj_id: xmj.id,
                 gcl_id: xmj.gcl_id,
-                mx_id: xmj.mx_id !== undefined ? xmj.mx_id : '',
+                mx_id: xmj.mx_id ? xmj.mx_id : null,
+                mb_id: mb_id,
                 gather_qty: xmj.gather_qty,
                 is_join: notx === undefined ? 1 : 0,
             };
-            datas.push(data);
+            console.log(data);
+            postData(window.location.pathname + '/save', {type: 'add', postData: data}, function (result) {
+                // 添加到materialList里
+                materialListData = result;
+                loadXmjMaterialData(index, leafXmjIndex);
+                $('#addgl').modal('hide');
+            });
         }
-
-
-        // 上传到数据库
-        console.log(datas, gcl, mb_id);
-        postData(window.location.pathname + '/save', {type: 'adds', postData: {xmjs: datas, mbIds: mb_id}}, function (result) {
-            materialListData = result;
-            // toastr.success('已成功应用');
-            calculateJiaCha(gclGatherData);
-            // const index = gclGatherData.indexOf(ledgerSelect);
-            loadLeafXmjData(index);
-            // const xmjSheet = leafXmjSpread.getActiveSheet();
-            // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
-            // const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
-            loadMaterialData(index, leafXmjIndex);
-            SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
-            $('#addgl').modal('hide');
-        });
-        // postData(window.location.pathname + '/save', {type: 'add', postData: data}, function (result) {
-        //     // 添加到materialList里
-        //     materialListData = result;
-        //     loadMaterialData(index, leafXmjIndex);
-        //     $('#addgl').modal('hide');
-        // });
         $('#materialBills').find('input:disabled').prop('checked', true);
     });
     if (!readOnly) {
@@ -527,6 +672,31 @@ $(document).ready(() => {
                     SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
                 });
             },
+            checkSelfMaterial: function (type) {
+                const [iGclRow, iRow, nRow, sheet, select] = leafXmjSpreadObj.getSelect();
+                // const color = type === 'self' ? '' : '#d6d8db';
+                const data = {
+                    type: type,
+                    select: type === 'noself' ? findSelfLeafXmj(select) : select,
+                };
+                console.log(iGclRow, iRow, nRow, select);
+                console.log(materialList);
+                // 添加到
+                postData(window.location.pathname + '/save', data, function (result) {
+                    if (type === 'noself') {
+                        const index = findSelfLeafXmj(select, 'index');
+                        selfList.splice(index, 1);
+                    } else {
+                        selfList.push(result);
+                    }
+                    gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(select);
+                    calculateJiaCha(gclGatherData, iGclRow);
+                    SpreadJsObj.reLoadRowData(sheet, nRow);
+                    // sheet.getRange(nRow, -1, 1, -1).backColor(color);
+                    loadXmjMaterialData(iGclRow, nRow);
+                    SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
+                });
+            },
         }
         // leafXmj右键功能
         $.contextMenu({
@@ -577,8 +747,49 @@ $(document).ready(() => {
                             return true;
                         }
                     },
-
-                }
+                },
+                'self': {
+                    name: '单独添加工料',
+                    icon: 'fa-sign-in',
+                    callback: function (key, opt) {
+                        leafXmjSpreadObj.checkSelfMaterial('self');
+                    },
+                    visible: function (key, opt) {
+                        const sheet = leafXmjSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        const sel = sheet.getSelections()[0];
+                        if (!select || sel.rowCount !== 1) {
+                            return false;
+                        }
+                        const notx = findSelfLeafXmj(select);
+                        if (!readOnly && select && notx === undefined) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    }
+                },
+                'noself': {
+                    name: '取消单独添加工料',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        leafXmjSpreadObj.checkSelfMaterial('noself');
+                    },
+                    visible: function (key, opt) {
+                        const sheet = leafXmjSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        const sel = sheet.getSelections()[0];
+                        if (!select || sel.rowCount !== 1) {
+                            return false;
+                        }
+                        const notx = findSelfLeafXmj(select);
+                        if (!readOnly && select && notx === undefined) {
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    },
+                },
             }
         });
         // material-spread右键功能
@@ -589,29 +800,30 @@ $(document).ready(() => {
                 const sheet = ledgerSpread.getActiveSheet();
                 const select = SpreadJsObj.getSelectObject(sheet);
                 const index = gclGatherData.indexOf(select);
-                const leafXmjSheet = leafXmjSpread.getActiveSheet();
-                const leafXmjSelect = SpreadJsObj.getSelectObject(leafXmjSheet);
+                // const leafXmjSheet = leafXmjSpread.getActiveSheet();
+                // const leafXmjSelect = SpreadJsObj.getSelectObject(leafXmjSheet);
                 const gcl = gclGatherData[index].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
-                const leafXmjIndex = gcl.indexOf(leafXmjSelect);
+                // const leafXmjIndex = gcl.indexOf(leafXmjSelect);
                 const datas = [];
                 for (const xmj of gcl) {
                     const data = {
                         xmj_id: xmj.id,
                         gcl_id: xmj.gcl_id,
-                        mx_id: xmj.mx_id !== undefined ? xmj.mx_id : '',
+                        mx_id: xmj.mx_id ? xmj.mx_id : null,
                     };
                     datas.push(data);
                 }
                 console.log(datas, materialSelect.mb_id);
                 postData(window.location.pathname + '/save', {type: 'dels', postData: { xmjs: datas, mb_id: materialSelect.mb_id }}, function (result) {
-                    materialListData = result;
+                    materialListData = result.materialListData;
+                    gclList = result.gclList;
                     calculateJiaCha(gclGatherData);
                     // const index = gclGatherData.indexOf(ledgerSelect);
                     loadLeafXmjData(index);
                     // const xmjSheet = leafXmjSpread.getActiveSheet();
                     // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
                     // const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
-                    loadMaterialData(index, leafXmjIndex);
+                    loadMaterialData(index);
                     SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
                 });
                 // postData(window.location.pathname + '/save', {type: 'del', id: select.id, mb_id: select.mb_id}, function (result) {
@@ -691,28 +903,29 @@ $(document).ready(() => {
                     const ledgerSelect = SpreadJsObj.getSelectObject(ledgerSheet);
                     const index = gclGatherData.indexOf(ledgerSelect);
                     const gcl = gclGatherData[index].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
-                    const xmjSheet = leafXmjSpread.getActiveSheet();
-                    const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
-                    const xmjIndex = gcl.indexOf(xmjSelect);
+                    // const xmjSheet = leafXmjSpread.getActiveSheet();
+                    // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
+                    // const xmjIndex = gcl.indexOf(xmjSelect);
                     const datas = [];
                     for (const xmj of gcl) {
                         const data = {
                             xmj_id: xmj.id,
                             gcl_id: xmj.gcl_id,
-                            mx_id: xmj.mx_id !== undefined ? xmj.mx_id : '',
+                            mx_id: xmj.mx_id ? xmj.mx_id : null,
                         };
                         datas.push(data);
                     }
                     console.log(exprQuantity, datas, select.mb_id);
                     postData(window.location.pathname + '/save', { type:'updates', updateData: { xmjs: datas, expr: exprQuantity.expr, quantity: exprQuantity.quantity, mb_id: select.mb_id } }, function (result) {
-                        materialListData = result;
+                        materialListData = result.materialListData;
+                        gclList = result.gclList;
                         calculateJiaCha(gclGatherData);
                         // const index = gclGatherData.indexOf(ledgerSelect);
                         loadLeafXmjData(index);
                         // const xmjSheet = leafXmjSpread.getActiveSheet();
                         // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
                         // const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
-                        loadMaterialData(index, xmjIndex);
+                        loadMaterialData(index);
                         SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
                         materialSpread.getActiveSheet().setSelection(info.row + 1, info.col, 1, 1);
                     }, function () {
@@ -819,29 +1032,30 @@ $(document).ready(() => {
                 const ledgerSelect = SpreadJsObj.getSelectObject(ledgerSheet);
                 const index = gclGatherData.indexOf(ledgerSelect);
                 const gcl = gclGatherData[index].leafXmjs.filter(item => item.gather_qty !== null && item.gather_qty !== undefined);
-                const xmjSheet = leafXmjSpread.getActiveSheet();
-                const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
-                const xmjIndex = gcl.indexOf(xmjSelect);
+                // const xmjSheet = leafXmjSpread.getActiveSheet();
+                // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
+                // const xmjIndex = gcl.indexOf(xmjSelect);
                 const datas = [];
                 for (const xmj of gcl) {
                     const data2 = {
                         xmj_id: xmj.id,
                         gcl_id: xmj.gcl_id,
-                        mx_id: xmj.mx_id !== undefined ? xmj.mx_id : '',
+                        mx_id: xmj.mx_id ? xmj.mx_id : null,
                     };
                     datas.push(data2);
                 }
                 console.log(data, datas);
                 // 更新至服务器
                 postData(window.location.pathname + '/save', { type:'pastes', updateData: { xmjs: datas, pasteData: data } }, function (result) {
-                    materialListData = result;
+                    materialListData = result.materialListData;
+                    gclList = result.gclList;
                     calculateJiaCha(gclGatherData);
                     // const index = gclGatherData.indexOf(ledgerSelect);
                     loadLeafXmjData(index);
                     // const xmjSheet = leafXmjSpread.getActiveSheet();
                     // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
                     // const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
-                    loadMaterialData(index, xmjIndex);
+                    loadMaterialData(index);
                     SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
                     materialSpread.getActiveSheet().setSelection(info.cellRange.row, info.cellRange.col, info.cellRange.rowCount, info.cellRange.colCount);
                 }, function () {
@@ -988,6 +1202,202 @@ $(document).ready(() => {
         materialSpread.bind(spreadNS.Events.EditEnded, materialSpreadObj.editEnded);
         materialSpread.bind(spreadNS.Events.ClipboardPasted, materialSpreadObj.clipboardPasted);
         SpreadJsObj.addDeleteBind(materialSpread, materialSpreadObj.deletePress);
+        // material-spread右键功能
+        const materialSelfSpreadObj = {
+            del: function () {
+                const sheet = materialSelfSpread.getActiveSheet();
+                const select = SpreadJsObj.getSelectObject(sheet);
+                console.log(select);
+                postData(window.location.pathname + '/save', {type: 'del', id: select.id, mb_id: select.mb_id}, function (result) {
+                    const index = materialListSelf.indexOf(select);
+                    materialListSelf.splice(index, 1);
+                    sheet.deleteRows(index, 1);
+                    SpreadJsObj.reLoadSheetData(materialSelfSpread.getActiveSheet());
+                    const sel = sheet.getSelections();
+                    sheet.setSelection(index > 0 ? index - 1 : 0, sel.length > 0 ? sel[0].col : 0, 1, 1);
+                    const materialListIndex = materialListData.indexOf(select);
+                    materialListData.splice(materialListIndex, 1);
+                    const [iGclRow, iRow, nRow, lsheet, lselect] = leafXmjSpreadObj.getSelect();
+                    gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(lselect);
+                    calculateJiaCha(gclGatherData, iGclRow);
+                    SpreadJsObj.reLoadRowData(lsheet, nRow);
+                    SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
+                });
+            },
+            deletePress: function (sheet) {
+                return;
+            },
+            editStarting: function (e, info) {
+                const col = info.sheet.zh_setting.cols[info.col];
+                const select = SpreadJsObj.getSelectObject(info.sheet);
+                if (col.field === 'quantity') {
+                    if (select.expr && select.expr !== '') {
+                        info.sheet.getCell(info.row, info.col).text(select.expr);
+                    }
+                }
+            },
+            editEnded: function (e, info) {
+                if (info.sheet.zh_setting) {
+                    const select = SpreadJsObj.getSelectObject(info.sheet);
+                    const col = info.sheet.zh_setting.cols[info.col];
+                    // 未改变值则不提交
+                    // const validText = info.editingText ? (typeof(info.editingText) === 'String' ? info.editingText.replace('\n', '') : info.editingText) : null;
+                    // const validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
+                    // let orgValue = select[col.field];
+                    const validText = info.editingText ? info.editingText.replace('\n', '') : null;
+                    let orgValue;
+                    if (col.field === 'quantity') {
+                        orgValue = validText && validText !== ''
+                            ? _.toNumber(validText) ? select.quantity : select.expr
+                            : (select.expr && select.expr !== '') ? select.expr : select.quantity;
+                    } else {
+                        orgValue = select[col.field];
+                    }
+                    if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === '' || validText === null))) {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    const exprQuantity = {
+                        expr: '',
+                        quantity: 0,
+                    };
+                    const [valid, msg] = materialSpreadObj._checkExpr(validText, exprQuantity);
+                    if (!valid) {
+                        toastr.error(msg);
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    if (isNaN(exprQuantity.quantity)) {
+                        toastr.error('不能输入其它非数字类型字符');
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    const num = parseFloat(exprQuantity.quantity);
+                    if (num < 0 || !/^\d+(\.\d{1,6})?$/.test(num)) {
+                        // toastr.error('数量值必须大于0并且小于6位小数的浮点数');
+                        // SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        // return;
+                        toastr.warning('已保留6位小数');
+                        exprQuantity.quantity = ZhCalc.round(num, 6);
+                    }
+                    // 更新至服务器
+                    console.log(exprQuantity, select.mb_id);
+                    postData(window.location.pathname + '/save', { type:'update', updateData: { id: select.id, expr: exprQuantity.expr, quantity: exprQuantity.quantity, mb_id: select.mb_id } }, function (result) {
+                        const materialListIndex = materialListData.indexOf(select);
+                        const index = materialList.indexOf(select);
+                        select.quantity = exprQuantity.quantity;
+                        select.expr = exprQuantity.expr;
+                        materialListData.splice(materialListIndex, 1, select);
+                        materialList.indexOf(index, 1, select);
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        const [iGclRow, iRow, nRow, sheet, lselect] = leafXmjSpreadObj.getSelect();
+                        gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(lselect);
+                        calculateJiaCha(gclGatherData, iGclRow);
+                        SpreadJsObj.reLoadRowData(sheet, nRow);
+                        SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
+                    }, function () {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    });
+                }
+            },
+            clipboardPasted(e, info) {
+                const hint = {
+                    cellError: {type: 'error', msg: '粘贴内容超出了表格范围'},
+                    numberExpr: {type: 'error', msg: '不能粘贴其它非数字类型字符'},
+                    numberCan: {type: 'warning', msg: '已保留6位小数'},
+                };
+                const range = info.cellRange;
+                const sortData = info.sheet.zh_data || [];
+                if (range.row + range.rowCount > sortData.length) {
+                    toastMessageUniq(hint.cellError);
+                    SpreadJsObj.reLoadSheetHeader(materialSpread.getActiveSheet());
+                    SpreadJsObj.reLoadSheetData(materialSpread.getActiveSheet());
+                    return;
+                }
+                if (sortData.length > 0 && range.col + range.colCount > 5) {
+                    toastMessageUniq(hint.cellError);
+                    SpreadJsObj.reLoadSheetHeader(materialSpread.getActiveSheet());
+                    SpreadJsObj.reLoadSheetData(materialSpread.getActiveSheet());
+                    return;
+                }
+                const data = [];
+                for (let iRow = 0; iRow < range.rowCount; iRow++) {
+                    let bPaste = true;
+                    const curRow = range.row + iRow;
+                    const materialData = { id: sortData[curRow].id, mb_id: sortData[curRow].mb_id };
+                    const hintRow = range.rowCount > 1 ? curRow : '';
+                    let sameCol = 0;
+                    for (let iCol = 0; iCol < range.colCount; iCol++) {
+                        const curCol = range.col + iCol;
+                        const colSetting = info.sheet.zh_setting.cols[curCol];
+                        if (!colSetting) continue;
+
+                        // let validText = info.sheet.getText(curRow, curCol);
+                        // validText = is_numeric(validText) ? parseFloat(validText) : (validText ? trimInvalidChar(validText) : null);
+                        const validText = info.sheet.getText(curRow, curCol).replace('\n', '');
+                        const orgValue = sortData[curRow][colSetting.field];
+                        if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
+                            sameCol++;
+                            if (range.colCount === sameCol)  {
+                                bPaste = false;
+                            }
+                            continue;
+                        }
+                        const exprQuantity = {
+                            expr: '',
+                            quantity: 0,
+                        };
+                        const [valid, msg] = materialSpreadObj._checkExpr(validText, exprQuantity);
+                        if (!valid) {
+                            toastMessageUniq(getPasteHint(msg, hintRow));
+                            bPaste = false;
+                            continue;
+                        }
+                        if (isNaN(exprQuantity.quantity)) {
+                            toastMessageUniq(getPasteHint(hint.numberExpr, hintRow));
+                            bPaste = false;
+                            continue;
+                        }
+                        const num = parseFloat(exprQuantity.quantity);
+                        if (num < 0 || !/^\d+(\.\d{1,6})?$/.test(num)) {
+                            toastMessageUniq(getPasteHint(hint.numberCan, hintRow));
+                            // bPaste = false;
+                            // continue;
+                            exprQuantity.quantity = ZhCalc.round(num, 6);
+                        }
+                        // materialData[colSetting.field] = validText;
+                        materialData.expr = exprQuantity.expr;
+                        materialData.quantity = exprQuantity.quantity;
+                    }
+                    if (bPaste) {
+                        data.push(materialData);
+                        // rowData.push(curRow);
+                    } else {
+                        SpreadJsObj.reLoadRowData(info.sheet, curRow);
+                    }
+                }
+                if (data.length === 0) {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                    return;
+                }
+                console.log(data);
+                postData(window.location.pathname + '/save', { type:'paste', updateData: data }, function (result) {
+                    materialListData = result;
+                    const [iGclRow, iRow, nRow, sheet, lselect] = leafXmjSpreadObj.getSelect();
+                    gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(lselect);
+                    calculateJiaCha(gclGatherData, iGclRow);
+                    // SpreadJsObj.reLoadRowData(sheet, nRow);
+                    SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
+                    loadXmjMaterialData(iGclRow, nRow);
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                });
+            },
+        };
+        materialSelfSpread.bind(spreadNS.Events.EditStarting, materialSelfSpreadObj.editStarting);
+        materialSelfSpread.bind(spreadNS.Events.EditEnded, materialSelfSpreadObj.editEnded);
+        materialSelfSpread.bind(spreadNS.Events.ClipboardPasted, materialSelfSpreadObj.clipboardPasted);
+        SpreadJsObj.addDeleteBind(materialSelfSpread, materialSelfSpreadObj.deletePress);
         if (!openMaterialChecklist) {
             $.contextMenu({
                 selector: '#material-spread',
@@ -1002,6 +1412,7 @@ $(document).ready(() => {
                         callback: function (key, opt) {
                             // 获取已选清单
                             changeMaterialTable();
+                            $('#add_type').val('all');
                             $('#addgl').modal('show');
                         },
                         disabled: function (key, opt) {
@@ -1041,6 +1452,58 @@ $(document).ready(() => {
                 }
             });
         }
+        $.contextMenu({
+            selector: '#material-self-spread',
+            build: function ($trigger, e) {
+                const target = SpreadJsObj.safeRightClickSelection($trigger, e, materialSelfSpread);
+                return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                'create': {
+                    name: '添加工料',
+                    icon: 'fa-sign-in',
+                    callback: function (key, opt) {
+                        // 获取已选清单
+                        changeMaterialTable('self');
+                        $('#add_type').val('self');
+                        $('#addgl').modal('show');
+                    },
+                    disabled: function (key, opt) {
+                        const sheet = leafXmjSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        // const notx = findNotJoinLeafXmj(select);
+                        if (!select) {
+                            return true;
+                        }
+                        // if (!readOnly && notx === undefined) {
+                        //     return false;
+                        // } else {
+                        //     return true;
+                        // }
+                        return readOnly;
+                    }
+                },
+                'delete': {
+                    name: '删除工料',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        materialSelfSpreadObj.del(materialSelfSpread.getActiveSheet());
+                    },
+                    disabled: function (key, opt) {
+                        const sheet = materialSelfSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        if (!select) {
+                            return true;
+                        }
+                        if (!readOnly && select && materialSelfBase.isEdit(select, 'del')) {
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                },
+            }
+        });
     }
 
     // 应用调差工料至其他清单明细
@@ -1069,15 +1532,16 @@ $(document).ready(() => {
         console.log(needAddList, materialList);
         // 更新至服务器
         postData(window.location.pathname + '/save', { type:'useOther', postData: { addXmj: needAddList, materialBills: materialList } }, function (result) {
-            materialListData = result;
+            materialListData = result.materialListData;
+            gclList = result.gclList;
             toastr.success('已成功应用');
             calculateJiaCha(gclGatherData);
             const index = gclGatherData.indexOf(ledgerSelect);
             loadLeafXmjData(index);
-            const xmjSheet = leafXmjSpread.getActiveSheet();
-            const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
-            const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
-            loadMaterialData(index, xmjIndex);
+            // const xmjSheet = leafXmjSpread.getActiveSheet();
+            // const xmjSelect = SpreadJsObj.getSelectObject(xmjSheet);
+            // const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
+            loadMaterialData(index);
             SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
         });
     });
@@ -1089,13 +1553,14 @@ $(document).ready(() => {
             if (iNewRow !== iOldRow) {
                 loadLeafXmjData(iNewRow);
                 SpreadJsObj.resetTopAndSelect(leafXmjSpread.getActiveSheet());
-                loadMaterialData(iNewRow, 0);
+                loadMaterialData(iNewRow);
+                loadXmjMaterialData(iNewRow, 0);
                 checkNotJoinMaterialData();
             }
         }
 
     });
-    // 切换项目节数据清单明细行,读取已调用的清单工料数据
+    // 切换项目节数据清单明细行,读取单独的清单工料数据
     leafXmjSpread.getActiveSheet().bind(spreadNS.Events.SelectionChanged, function (e, info) {
         if (info.oldSelections !== undefined) {
             const iOldRow = info.oldSelections[0].row, iNewRow = info.newSelections[0].row;
@@ -1103,8 +1568,8 @@ $(document).ready(() => {
                 const sheet = ledgerSpread.getActiveSheet();
                 const select = SpreadJsObj.getSelectObject(sheet);
                 const index = gclGatherData.indexOf(select);
-                loadMaterialData(index, iNewRow);
-                SpreadJsObj.resetTopAndSelect(materialSpread.getActiveSheet());
+                loadXmjMaterialData(index, iNewRow);
+                SpreadJsObj.resetTopAndSelect(materialSelfSpread.getActiveSheet());
             }
         }
     });
@@ -1145,10 +1610,12 @@ $(document).ready(() => {
         calculateJiaCha(gclGatherData);
         SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Data, gclGatherData);
         loadLeafXmjData(0);
-        loadMaterialData(0, 0);
+        loadMaterialData(0);
+        loadXmjMaterialData(0, 0);
         SpreadJsObj.resetTopAndSelect(ledgerSpread.getActiveSheet());
         SpreadJsObj.resetTopAndSelect(leafXmjSpread.getActiveSheet());
         SpreadJsObj.resetTopAndSelect(materialSpread.getActiveSheet());
+        SpreadJsObj.resetTopAndSelect(materialSelfSpread.getActiveSheet());
         checkNotJoinMaterialData();
     });
 
@@ -1169,9 +1636,17 @@ $(document).ready(() => {
             ledgerSpread.refresh();
             leafXmjSpread.refresh();
             materialSpread.refresh();
+            materialSelfSpread.refresh();
         }
     });
 
+    $(window).resize(function () {
+        ledgerSpread.refresh();
+        leafXmjSpread.refresh();
+        materialSpread.refresh();
+        materialSelfSpread.refresh();
+    });
+
     $.divResizer({
         select: '#right-spr',
         callback: function () {
@@ -1184,6 +1659,16 @@ $(document).ready(() => {
     });
 
     $.divResizer({
+        select: '#right-spr2',
+        callback: function () {
+            leafXmjSpread.refresh();
+            materialSelfSpread.refresh();
+            // const width = (($('#right-view2').width()/$('#right-view2').parent('div').width())*100).toFixed();
+            // setLocalCache('material_list3_' + materialID, width);
+        }
+    });
+
+    $.divResizer({
         select: '#main-resize',
         callback: function () {
             materialSpread.refresh();
@@ -1191,6 +1676,7 @@ $(document).ready(() => {
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
             $(".sp-wrap").height(bcontent-30);
             leafXmjSpread.refresh();
+            materialSelfSpread.refresh();
             const height = $('.bcontent-wrap').height();
             setLocalCache('material_list2_' + materialID, height);
         }
@@ -1227,7 +1713,7 @@ $(document).ready(() => {
         $('.tab-content .tab-select-show').removeClass('active');
         tab.addClass('active');
         tabPanel.addClass('active');
-        $('#right-view').width(getLocalCache('material_list_' + materialID) + '%');
+        $('#right-view').css('width', getLocalCache('material_list_' + materialID) + '%');
         showSideTools(tab.hasClass('active'));
         ledgerSpread.refresh();
         // leafXmjSpread.refresh();
@@ -1242,8 +1728,34 @@ $(document).ready(() => {
         materialSpread.refresh();
         ledgerSpread.refresh();
         leafXmjSpread.refresh();
+        materialSelfSpread.refresh();
     }
     function getObjHeight(select) {
         return select.length > 0 ? select.height() : 0;
     }
+
+    const showSelfSideTools = function (show) {
+        const left = $('#left-view2'), right = $('#right-view2'), parent = left.parent();
+        if (show) {
+            right.show();
+            autoFlashHeight();
+            /**
+             * right.show()后, parent被撑开成2倍left.height, 导致parent.width减少了10px
+             * 第一次left.width调整后,parent的缩回left.height, 此时parent.width又增加了10px
+             * 故需要通过最终的parent.width再计算一次left.width
+             *
+             * Q: 为什么不通过先计算left.width的宽度,以避免计算两次left.width?
+             * A: 右侧工具栏不一定显示,当右侧工具栏显示过一次后,就必须使用parent和right来计算left.width
+             *
+             */
+                //left.css('width', parent.width() - right.outerWidth());
+                //left.css('width', parent.width() - right.outerWidth());
+            const percent = 100 - right.outerWidth() /parent.width() * 100;
+            left.css('width', percent + '%');
+        } else {
+            // left.css('width', parent.width());
+            left.css('width', '100%');
+            right.hide();
+        }
+    };
 });

+ 37 - 16
app/public/js/measure_material.js

@@ -275,6 +275,8 @@ $(function () {
             const pos = result.pos;
             const curPosData = result.curPosData;
             const gclList = result.gclList;
+            const selfList = result.selfList;
+            const materialListForSelf = result.materialListForSelf;
             gclGatherModel.loadLedgerData(ledger, curLedgerData);
             gclGatherModel.loadPosData(pos, curPosData);
             const gclGatherData = gclGatherModel.gatherGclData();
@@ -284,6 +286,7 @@ $(function () {
             // 获取需要新增的工料关联清单
             const insertGcl = [];
             const removeGclList = [];
+            const insertSelfList = [];// 需要单独添加的明细清单工料含量列表
             for (const g of gclList) {
                 const gcl = _.find(gclGatherData, function (item) {
                     return item.leafXmjs && item.leafXmjs.length > 0 && _.findIndex(item.leafXmjs, { gcl_id : g.gcl_id }) !== -1;
@@ -310,28 +313,45 @@ $(function () {
             for (const one of insertGcl) {
                 if (one.leafXmjs && one.leafXmjs.length > 0) {
                     for (const xmj of one.leafXmjs) {
-                        const newgcl = _.find(gclList, { gcl_id: xmj.gcl_id });
-                        for (const bill of one.bills) {
-                            insertList.push({
-                                gcl_id: xmj.gcl_id,
-                                mx_id: xmj.mx_id ? xmj.mx_id : null,
-                                xmj_id: xmj.id ? xmj.id : null,
-                                gather_qty: xmj.gather_qty,
-                                quantity: bill.quantity,
-                                expr: bill.expr,
-                                mb_id: bill.mb_id,
-                                order: bill.order,
-                            });
-                            if (!newgcl) {
-                                insertGclList.push({
+                        const is_self = _.findIndex(selfList, { gcl_id: xmj.gcl_id, xmj_id: xmj.id, mx_id: xmj.mx_id ? xmj.mx_id : null }) !== -1;// 区分单独计量的明细工料含量
+                        if (is_self) {
+                            const billsList = _.filter(materialListForSelf, { gcl_id: xmj.gcl_id, xmj_id: xmj.id, mx_id: xmj.mx_id ? xmj.mx_id : null });
+                            for (const bill of billsList) {
+                                insertSelfList.push({
                                     gcl_id: xmj.gcl_id,
+                                    mx_id: xmj.mx_id ? xmj.mx_id : null,
+                                    xmj_id: xmj.id ? xmj.id : null,
+                                    gather_qty: xmj.gather_qty,
+                                    quantity: bill.quantity,
+                                    expr: bill.expr,
+                                    mb_id: bill.mb_id,
+                                    order: bill.order,
+                                })
+                            }
+                        } else {
+                            const newgcl = _.find(gclList, { gcl_id: xmj.gcl_id });
+                            for (const bill of one.bills) {
+                                insertList.push({
+                                    gcl_id: xmj.gcl_id,
+                                    mx_id: xmj.mx_id ? xmj.mx_id : null,
+                                    xmj_id: xmj.id ? xmj.id : null,
+                                    gather_qty: xmj.gather_qty,
                                     quantity: bill.quantity,
                                     expr: bill.expr,
-                                    old_quantity: bill.quantity,
-                                    old_expr: bill.expr,
                                     mb_id: bill.mb_id,
                                     order: bill.order,
                                 });
+                                if (!newgcl) {
+                                    insertGclList.push({
+                                        gcl_id: xmj.gcl_id,
+                                        quantity: bill.quantity,
+                                        expr: bill.expr,
+                                        old_quantity: bill.quantity,
+                                        old_expr: bill.expr,
+                                        mb_id: bill.mb_id,
+                                        order: bill.order,
+                                    });
+                                }
                             }
                         }
                     }
@@ -339,6 +359,7 @@ $(function () {
             }
             // 可能需要新增list_gcl表
             newMaterialData.material_list = insertList;
+            newMaterialData.material_self_list = insertSelfList;
             newMaterialData.insertGclList = insertGclList;
             newMaterialData.removeGclList = removeGclList;
             console.log(newMaterialData);

+ 5 - 1
app/service/material.js

@@ -175,9 +175,12 @@ module.exports = app => {
                     // 复制不参与调差清单
                     const preNotJoinList = await this.ctx.service.materialListNotjoin.getAllDataByCondition({ where: { tid: this.ctx.tender.id, mid: preMaterial.id } });
                     await this.ctx.service.materialListNotjoin.copyNewStageNotJoinList(transaction, preNotJoinList, newMaterial.id);
+                    // 复制单独计量调差清单
+                    const preSelfList = await this.ctx.service.materialListSelf.getAllDataByCondition({ where: { tid: this.ctx.tender.id, mid: preMaterial.id } });
+                    await this.ctx.service.materialListSelf.copyNewStageSelfList(transaction, preSelfList, newMaterial.id);
                     // 复制调差清单工料关联表
                     // await this.ctx.service.materialList.copyPreMaterialList(transaction, preMaterial, newMaterial);
-                    await this.ctx.service.materialList.copyPreMaterialList2(transaction, data.material_list, preNotJoinList, newMaterial);
+                    await this.ctx.service.materialList.copyPreMaterialList2(transaction, data.material_list, data.material_self_list, preNotJoinList, newMaterial);
                     // 新增或删除list_gcl表
                     await this.ctx.service.materialListGcl.insertOrDelGcl(transaction, data.insertGclList, data.removeGclList, newMaterial.id);
                     // 设置list_gcl表old=>new更新
@@ -235,6 +238,7 @@ module.exports = app => {
                 await transaction.delete(this.ctx.service.materialBills.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialList.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialListGcl.tableName, { mid: id });
+                await transaction.delete(this.ctx.service.materialListSelf.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialListNotjoin.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialBillsHistory.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialFile.tableName, { mid: id });

+ 87 - 40
app/service/material_list.js

@@ -42,6 +42,8 @@ module.exports = app => {
                     xmj_id: data.xmj_id,
                     mx_id: data.mx_id,
                     gather_qty: data.gather_qty,
+                    is_join: data.is_join,
+                    is_self: 1,
                     in_time: new Date(),
                 };
                 list.push(newLists);
@@ -299,7 +301,7 @@ module.exports = app => {
          * @param newMid
          * @return {Promise<void>}
          */
-        async copyPreMaterialList2(transaction, materialListData, notJoinList, newMaterial) {
+        async copyPreMaterialList2(transaction, materialListData, materialSelfListData, notJoinList, newMaterial) {
             if (materialListData && materialListData.length > 0) {
                 const copyMLArray = [];
                 for (const ml of materialListData) {
@@ -320,7 +322,30 @@ module.exports = app => {
                     };
                     copyMLArray.push(newMaterialList);
                 }
-                return copyMLArray.length !== 0 ? await transaction.insert(this.tableName, copyMLArray) : true;
+                if (copyMLArray.length !== 0) await transaction.insert(this.tableName, copyMLArray);
+            }
+            if (materialSelfListData && materialSelfListData.length > 0) {
+                const copyMLArray2 = [];
+                for (const ml of materialSelfListData) {
+                    const is_join = this._.find(notJoinList, { gcl_id: ml.gcl_id, xmj_id: ml.xmj_id, mx_id: ml.mx_id });
+                    const newMaterialList = {
+                        tid: newMaterial.tid,
+                        order: ml.order,
+                        mid: newMaterial.id,
+                        mb_id: ml.mb_id,
+                        gcl_id: ml.gcl_id,
+                        xmj_id: ml.xmj_id,
+                        mx_id: ml.mx_id,
+                        gather_qty: ml.gather_qty,
+                        quantity: ml.quantity ? ml.quantity : 0,
+                        expr: ml.expr ? ml.expr : '',
+                        is_join: is_join ? 0 : 1,
+                        is_self: 1,
+                        in_time: new Date(),
+                    };
+                    copyMLArray2.push(newMaterialList);
+                }
+                if (copyMLArray2.length !== 0) await transaction.insert(this.tableName, copyMLArray2);
             }
         }
 
@@ -340,6 +365,7 @@ module.exports = app => {
                 // const delList = [];
                 // const mb_idList = [];
                 for (const xmj of datas.xmjs) {
+                    const selfList = await transaction.select(this.ctx.service.materialListSelf.tableName, { where: { tid: this.ctx.tender.id, mid: this.ctx.material.id } });
                     for (const mb of datas.mbIds) {
                         // // 旧数据兼容问题,要去删除相同已存在的工料
                         // const mlInfo = await this.getDataByCondition({
@@ -353,7 +379,7 @@ module.exports = app => {
                         //     delList.push(mlInfo.id);
                         //     mb_idList.push(mb);
                         // }
-                        if (xmj.gather_qty) {
+                        if (xmj.gather_qty && this._.findIndex(selfList, { gcl_id: xmj.gcl_id, xmj_id: xmj.xmj_id, mx_id: xmj.mx_id }) === -1) {
                             const newLists = {
                                 tid: this.ctx.tender.id,
                                 order: this.ctx.material.order,
@@ -390,7 +416,7 @@ module.exports = app => {
                 // 新增工料清单关联
                 if (list.length > 0) {
                     const result = await transaction.insert(this.tableName, list);
-                    if (result.affectedRows === 0 ) {
+                    if (result.affectedRows === 0) {
                         throw '新增工料数据失败';
                     }
                 }
@@ -411,7 +437,11 @@ module.exports = app => {
                 //     }
                 // }
                 await transaction.commit();
-                return checklist ? await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } }) : await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id);
+                const gclList = await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
+                return checklist ? gclList : {
+                    gclList,
+                    materialListData: await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id),
+                };
             } catch (err) {
                 await transaction.rollback();
                 throw err;
@@ -432,7 +462,7 @@ module.exports = app => {
                 // 判断是否可删
                 const listGcl = [];
                 for (const xmj of datas.xmjs) {
-                    await transaction.delete(this.tableName, { tid: this.ctx.tender.id, mid: this.ctx.material.id, mb_id: datas.mb_id, gcl_id: xmj.gcl_id, xmj_id: xmj.xmj_id, mx_id: xmj.mx_id });
+                    await transaction.delete(this.tableName, { tid: this.ctx.tender.id, mid: this.ctx.material.id, mb_id: datas.mb_id, gcl_id: xmj.gcl_id, xmj_id: xmj.xmj_id, mx_id: xmj.mx_id, is_self: 0 });
                     if (this._.indexOf(listGcl, xmj.gcl_id) === -1) {
                         await transaction.delete(this.service.materialListGcl.tableName, { tid: this.ctx.tender.id, mid: this.ctx.material.id, mb_id: datas.mb_id, gcl_id: xmj.gcl_id });
                         listGcl.push(xmj.gcl_id);
@@ -445,7 +475,11 @@ module.exports = app => {
                 }
                 await transaction.commit();
                 // console.log(datas);
-                return checklist ? await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } }) : await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id);
+                const gclList = await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
+                return checklist ? gclList : {
+                    gclList,
+                    materialListData: await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id),
+                };
             } catch (err) {
                 await transaction.rollback();
                 throw err;
@@ -469,22 +503,25 @@ module.exports = app => {
                 const updateDatas = [];
                 const updateListGcl = [];
                 const listGcl = [];
+                const selfList = await transaction.select(this.ctx.service.materialListSelf.tableName, { where: { tid: this.ctx.tender.id, mid: this.ctx.material.id } });
                 for (const xmj of datas.xmjs) {
-                    const udata = {
-                        row: {
-                            expr: datas.expr,
-                            quantity: datas.quantity,
-                        },
-                        where: {
-                            tid: this.ctx.tender.id,
-                            mid: this.ctx.material.id,
-                            mb_id,
-                            gcl_id: xmj.gcl_id,
-                            xmj_id: xmj.xmj_id,
-                            mx_id: xmj.mx_id,
-                        },
-                    };
-                    updateDatas.push(udata);
+                    if (this._.findIndex(selfList, { gcl_id: xmj.gcl_id, xmj_id: xmj.xmj_id, mx_id: xmj.mx_id }) === -1) {
+                        const udata = {
+                            row: {
+                                expr: datas.expr,
+                                quantity: datas.quantity,
+                            },
+                            where: {
+                                tid: this.ctx.tender.id,
+                                mid: this.ctx.material.id,
+                                mb_id,
+                                gcl_id: xmj.gcl_id,
+                                xmj_id: xmj.xmj_id,
+                                mx_id: xmj.mx_id,
+                            },
+                        };
+                        updateDatas.push(udata);
+                    }
                     if (this._.indexOf(listGcl, xmj.gcl_id) === -1) {
                         listGcl.push(xmj.gcl_id);
                         updateListGcl.push({
@@ -505,7 +542,11 @@ module.exports = app => {
                 if (updateListGcl.length > 0) await transaction.updateRows(this.service.materialListGcl.tableName, updateListGcl);
                 await this.calcQuantityByML(transaction, mb_id);
                 await transaction.commit();
-                return checklist ? await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } }) : await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id);
+                const gclList = await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
+                return checklist ? gclList : {
+                    gclList,
+                    materialListData: await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id),
+                };
             } catch (err) {
                 await transaction.rollback();
                 throw err;
@@ -525,27 +566,29 @@ module.exports = app => {
             // 判断t_type是否为费用
             const transaction = await this.db.beginTransaction();
             try {
-
+                const selfList = await transaction.select(this.ctx.service.materialListSelf.tableName, { where: { tid: this.ctx.tender.id, mid: this.ctx.material.id } });
                 for (const data of datas.pasteData) {
                     const updateDatas = [];
                     const updateListGcl = [];
                     const listGcl = [];
                     for (const xmj of datas.xmjs) {
-                        const udata = {
-                            row: {
-                                expr: data.expr,
-                                quantity: data.quantity,
-                            },
-                            where: {
-                                tid: this.ctx.tender.id,
-                                mid: this.ctx.material.id,
-                                mb_id: data.mb_id,
-                                gcl_id: xmj.gcl_id,
-                                xmj_id: xmj.xmj_id,
-                                mx_id: xmj.mx_id,
-                            },
-                        };
-                        updateDatas.push(udata);
+                        if (this._.findIndex(selfList, { gcl_id: xmj.gcl_id, xmj_id: xmj.xmj_id, mx_id: xmj.mx_id }) === -1) {
+                            const udata = {
+                                row: {
+                                    expr: data.expr,
+                                    quantity: data.quantity,
+                                },
+                                where: {
+                                    tid: this.ctx.tender.id,
+                                    mid: this.ctx.material.id,
+                                    mb_id: data.mb_id,
+                                    gcl_id: xmj.gcl_id,
+                                    xmj_id: xmj.xmj_id,
+                                    mx_id: xmj.mx_id,
+                                },
+                            };
+                            updateDatas.push(udata);
+                        }
                         if (this._.indexOf(listGcl, xmj.gcl_id) === -1) {
                             listGcl.push(xmj.gcl_id);
                             updateListGcl.push({
@@ -567,7 +610,11 @@ module.exports = app => {
                     await this.calcQuantityByML(transaction, data.mb_id);
                 }
                 await transaction.commit();
-                return checklist ? await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } }) : await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id);
+                const gclList = await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
+                return checklist ? gclList : {
+                    gclList,
+                    materialListData: await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id),
+                };
             } catch (err) {
                 await transaction.rollback();
                 throw err;

+ 183 - 0
app/service/material_list_self.js

@@ -0,0 +1,183 @@
+'use strict';
+
+/**
+ * 单独计量单元设置-清单关联表 数据模型
+ *
+ * @author Mai
+ * @date 2018/8/13
+ * @version
+ */
+
+
+module.exports = app => {
+    class MaterialListSelf extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'material_list_self';
+        }
+
+        /**
+         * 添加单独计量的清单
+         * @return {void}
+         */
+        async add(data) {
+            if (!this.ctx.tender || !this.ctx.material) {
+                throw '数据错误';
+            }
+            const transaction = await this.db.beginTransaction();
+            try {
+                const newListSelf = {
+                    tid: this.ctx.tender.id,
+                    mid: this.ctx.material.id,
+                    gcl_id: data.gcl_id,
+                    xmj_id: data.id,
+                    mx_id: data.mx_id !== undefined ? data.mx_id : null,
+                    in_time: new Date(),
+                };
+                // 更新list表为is_self为1
+                await transaction.update(this.ctx.service.materialList.tableName, { is_self: 1 }, {
+                    where: {
+                        tid: this.ctx.tender.id,
+                        mid: this.ctx.material.id,
+                        gcl_id: data.gcl_id,
+                        xmj_id: data.id,
+                        mx_id: data.mx_id ? data.mx_id : null,
+                    },
+                });
+                // data.xmj_id = data.id;
+                // data.mx_id = data.mx_id !== undefined ? data.mx_id : null;
+                // await this.updateAllMaterials(transaction, data, 'add');
+                // 新增不参与调差清单
+                const result = await transaction.insert(this.tableName, newListSelf);
+                if (result.affectedRows === 0) {
+                    throw '新增不参与调差清单数据失败';
+                }
+                await transaction.commit();
+                return await this.getDataById(result.insertId);
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
+         * 删除单独计量的清单
+         * @param {int} id 工料id
+         * @return {void}
+         */
+        async del(id) {
+            if (!this.ctx.tender || !this.ctx.material) {
+                throw '数据错误';
+            }
+            const transaction = await this.db.beginTransaction();
+            try {
+                const selfInfo = await this.getDataById(id);
+                await this.updateAllMaterials(transaction, selfInfo);
+                // 判断是否可删
+                const result = await transaction.delete(this.tableName, { id });
+                await transaction.commit();
+                return result;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
+         * 修改调差list和bill和material对应值
+         * @param transaction
+         * @returns {Promise<void>}
+         */
+        async updateAllMaterials(transaction, data, type) {
+            // 先判断material_list是否存在值并quantity不为null
+            const searchSql = {
+                mid: this.ctx.material.id,
+                gcl_id: data.gcl_id,
+                xmj_id: data.xmj_id,
+            };
+            if (data.mx_id !== null) {
+                searchSql.mx_id = data.mx_id;
+            }
+            const materialListData = await this.ctx.service.materialList.getAllDataByCondition({
+                where: searchSql,
+            });
+            if (materialListData && materialListData.length > 0) {
+                const gather_qty = materialListData[0].gather_qty;
+                const is_join = materialListData[0].is_join;
+                const mbIdList = [];
+                for (const ml of materialListData) {
+                    if (mbIdList.indexOf(ml.mb_id) === -1) {
+                        mbIdList.push(ml.mb_id);
+                    }
+                }
+                await transaction.delete(this.ctx.service.materialList.tableName, {
+                    tid: this.ctx.tender.id,
+                    mid: this.ctx.material.id,
+                    gcl_id: data.gcl_id,
+                    xmj_id: data.xmj_id,
+                    mx_id: data.mx_id ? data.mx_id : null,
+                });
+                const materialListGclData = await this.ctx.service.materialListGcl.getAllDataByCondition({
+                    where: { tid: this.ctx.tender.id, gcl_id: data.gcl_id },
+                });
+                const insertList = [];
+                for (const m of materialListGclData) {
+                    insertList.push({
+                        tid: this.ctx.tender.id,
+                        order: m.order,
+                        mid: this.ctx.material.id,
+                        mb_id: m.mb_id,
+                        gcl_id: data.gcl_id,
+                        xmj_id: data.xmj_id,
+                        mx_id: data.mx_id,
+                        gather_qty,
+                        quantity: m.quantity,
+                        expr: m.expr,
+                        is_join,
+                        is_self: 0,
+                        in_time: new Date(),
+                    });
+                }
+                if (insertList.length > 0) await transaction.insert(this.ctx.service.materialList.tableName, insertList);
+                // 重新计算金额
+                for (const mb_id of mbIdList) {
+                    await this.service.materialList.calcQuantityByML(transaction, mb_id);
+                }
+            }
+        }
+
+        /**
+         * 复制上一期不参与调差的清单到下一期中
+         * @param {Object} transaction - 新增一期的事务
+         * @param {Object} list 上期清单
+         * @param {int} mid 工料id
+         * @return {void}
+         */
+        async copyNewStageSelfList(transaction, list, mid) {
+            if (!this.ctx.tender) {
+                throw '数据错误';
+            }
+            const selfList = [];
+            for (const mb of list) {
+                const newLists = {
+                    tid: mb.tid,
+                    mid,
+                    gcl_id: mb.gcl_id,
+                    xmj_id: mb.xmj_id,
+                    mx_id: mb.mx_id,
+                    in_time: new Date(),
+                };
+                selfList.push(newLists);
+            }
+            // 复制上一期不参与调差的清单
+            return selfList.length > 0 ? await transaction.insert(this.tableName, selfList) : true;
+        }
+    }
+    return MaterialListSelf;
+};

+ 14 - 2
app/view/material/list.ejs

@@ -60,8 +60,20 @@
                             </li>
                         </ul>
                     </div>
-                    <div class="sp-wrap" id="leaf-xmj-spread">
+                    <div class="sp-wrap row w-100 sub-content">
+                        <div class="c-body" id="left-view2" style="width: 70%">
+                            <div class="sp-wrap" id="leaf-xmj-spread"></div>
+                        </div>
+                        <div class="c-body" id="right-view2" style="width: 30%">
+                            <div class="resize-x" id="right-spr2" r-Type="width" div1="#left-view2" div2="#right-view2" title="调整大小" a-type="percent"><!--调整左右高度条--></div>
+                            <div class="tab-content">
+                                <div class="tab-pane" id="material-self-spread-div" style="position: relative">
+                                    <div class="sp-wrap" id="material-self-spread"></div>
+                                </div>
+                            </div>
+                        </div>
                     </div>
+                    <!--<div class="sp-wrap" id="leaf-xmj-spread"></div>-->
                 </div>
             </div>
         </div>
@@ -84,5 +96,5 @@
     const tenderID = <%- tender.id %>;
     const materialDecimal = JSON.parse(unescape('<%- escape(JSON.stringify(material.decimal)) %>'));
     const openMaterialChecklist = parseInt(<%- ctx.session.sessionProject.page_show.openMaterialChecklist %>);
-    let materialListData, materialChecklistData, notJoinList, ledger, curLedgerData, pos, curPosData, gclGatherData;
+    let materialListData, materialChecklistData, notJoinList, ledger, curLedgerData, pos, curPosData, gclGatherData, gclList, selfList;
 </script>

+ 1 - 0
app/view/material/list_modal.ejs

@@ -43,6 +43,7 @@
                 </div>
             </div>
             <div class="modal-footer">
+                <input type="hidden" id="add_type" value="all" >
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <button type="button" class="btn btn-primary btn-sm" id="add_material_bill">确定添加</button>
             </div>

+ 4 - 0
sql/update.sql

@@ -68,3 +68,7 @@ UPDATE `zh_material_list_gcl` SET `old_quantity`=`quantity`,`old_expr`=`expr`;
 ALTER TABLE `zh_material` ADD `exponent_rate` TINYINT(3) NULL DEFAULT '0' COMMENT '材料税税率' AFTER `rate`;
 
 UPDATE `zh_material` SET `exponent_rate`=`rate`;
+
+ALTER TABLE `zh_material_list` ADD `is_self` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否为单独添加的工料清单关联' AFTER `is_join`;
+
+UPDATE `zh_material_list` SET `mx_id`= null WHERE `mx_id` = '';