瀏覽代碼

草图功能更改

laiguoran 4 年之前
父節點
當前提交
017b358d72

+ 42 - 0
app/controller/schedule_controller.js

@@ -77,12 +77,21 @@ module.exports = app => {
             const tender = ctx.tender;
             const schedule = await ctx.service.schedule.getDataByCondition({ tid: tender.id });
             const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'asc']] });
+            const stageOrderList = await ctx.service.stage.getAllDataByCondition({ columns: ['id', 'order'], where: { tid: tender.id } });
+            const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: tender.id } });
+            let curScheduleStage = scheduleStage.length > 0 ? scheduleStage[scheduleStage.length - 1] : null;
+            if (ctx.params.order && scheduleStage.length > 0) {
+                curScheduleStage = _.find(scheduleStage, { order: parseInt(ctx.params.order) });
+            }
             const renderData = {
                 tender: tender.data,
                 tenderInfo: tender.info,
                 schedule,
                 scheduleMonth,
                 measureType,
+                stageOrderList,
+                scheduleStage,
+                curScheduleStage,
                 scheduleLedgerList: await this._getSelectedLedgerList(ctx),
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.stageTp),
             };
@@ -181,6 +190,39 @@ module.exports = app => {
         }
 
         /**
+         * 计量进度金额模式计算方式提交(Ajax)
+         *
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async saveStageTp(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const responseData = {
+                    err: 0,
+                    msg: '',
+                    data: {},
+                };
+                switch (data.type) {
+                    case 'add_stage':
+                        responseData.data = await ctx.service.scheduleStage.add(data.postData);
+                        break;
+                    case 'del_stage':
+                        responseData.data = await ctx.service.scheduleStage.del(data.postData);
+                        break;
+                    case 'reload_stage':
+                        responseData.data = await ctx.service.scheduleStage.changeOrder(data.postData);
+                        break;
+                    default: throw '参数有误';
+                }
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
+
+        /**
          * 计量进度工程量模式计算方式提交(Ajax)
          *
          * @param ctx

+ 3 - 3
app/public/js/schedule_stage_gcl.js

@@ -53,7 +53,7 @@ $(function () {
     const monthsCols = [];
     if(scheduleMonth.length > 0) {
         for (const sm of scheduleMonth) {
-            if (sm.stage_used === 1) {
+            if (sm.stage_gcl_used === 1) {
                 const yearmonth = sm.yearmonth.split('-')[0] + '年' + parseInt(sm.yearmonth.split('-')[1]) + '月';
                 const cols = {title: yearmonth + '|计划工程量', colSpan: '4|1', rowSpan: '1|1', field: sm.yearmonth+'_plan_gcl', hAlign: 2, width: 90, type: 'Number', readOnly: true};
                 const cols2 = {title: '|计划金额(万元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_plan_tp', hAlign: 2, width: 90, type: 'Number', readOnly: true};
@@ -96,7 +96,7 @@ $(function () {
         const showList = ['ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
             'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price'];
         for (const m of scheduleMonth) {
-            if (m.stage_used === 1) {
+            if (m.stage_gcl_used === 1) {
                 showList.push(m.yearmonth + '_plan_tp');
                 showList.push(m.yearmonth + '_plan_gcl');
                 showList.push(m.yearmonth + '_sj_tp');
@@ -385,7 +385,7 @@ function setMonthToLedger(ledgerList, slm) {
     if (slm.length > 0) {
         for(const s of slm) {
             const index = _.findIndex(ledgerList, { 'ledger_id': s.lid });
-            const canCalc = _.find(scheduleMonth, { 'yearmonth': s.yearmonth, 'stage_used': 1});
+            const canCalc = _.find(scheduleMonth, { 'yearmonth': s.yearmonth, 'stage_gcl_used': 1});
             if (index && index !== -1 && canCalc) {
                 ledgerList[index][s.yearmonth + '_plan_tp'] = s.plan_tp;
                 ledgerList[index][s.yearmonth + '_plan_gcl'] = s.plan_gcl;

+ 92 - 213
app/public/js/schedule_stage_tp.js

@@ -22,9 +22,6 @@ $(function () {
         level: 'level',
         rootId: -1,
         fullPath: 'full_path',
-        //treeCacheKey: 'ledger_bills_fold' + '_' + getTenderId(),
-        // markFoldKey: 'bills-fold',
-        // markFoldSubKey: window.location.pathname.split('/')[2],
     };
     const ledgerTree = createNewPathTree('filter', treeSetting);
 
@@ -37,16 +34,16 @@ $(function () {
         {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '自开工至本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '截止本期完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '截止本期完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本年计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本年累计完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '本期完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '本期完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '下月计划|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
         {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
     ];
@@ -71,59 +68,69 @@ $(function () {
     SpreadJsObj.initSheet(ledgerSpread.getActiveSheet(), ledgerSpreadSetting);
     SpreadJsObj.selChangedRefreshBackColor(ledgerSpread.getActiveSheet());
 
-    postData('/tender/' + getTenderId() + '/schedule/ledger/load', {}, function (data) {
-        // let treeData = [];
-        // for(const sl of selectedLedgerList) {
-        //     const one = _.find(data, { 'ledger_id' : sl });
-        //     treeData.push(one);
-        // }
-        // treeData = setLeafData(treeData);
-        // console.log(treeData);
-        // let treeData = data;
-        const calcList = ['total_price'];
-        const showList = ['ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
-            'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price'];
-        for (const m of scheduleMonth) {
-            if (m.stage_used === 1) {
-                showList.push(m.yearmonth + '_plan_tp');
-                showList.push(m.yearmonth + '_plan_gcl');
-                showList.push(m.yearmonth + '_sj_tp');
-                showList.push(m.yearmonth + '_sj_gcl');
-            }
-            // calcList.push(m + '_tp');
-            // calcList.push(m + '_gcl');
-        }
-        const baseLedgerTree = createNewPathTree('base', {
-            id: 'ledger_id',
-            pid: 'ledger_pid',
-            order: 'order',
-            level: 'level',
-            rootId: -1,
-            fullPath: 'full_path',
-            calcFields: calcList,
-            calcFun: function (node) {
+    if (curScheduleStage && curScheduleStage.order) {
+        postData('/tender/' + getTenderId() + '/measure/stage/' + curScheduleStage.order + '/load', { filter: 'ledger' }, function (data) {
+            const calcList = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
+                'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
+            const showList = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
+                'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
+                'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
+            const baseLedgerTree = createNewPathTree('base', {
+                id: 'ledger_id',
+                pid: 'ledger_pid',
+                order: 'order',
+                level: 'level',
+                rootId: -1,
+                fullPath: 'full_path',
+                calcFields: calcList,
+            });
+            baseLedgerTree.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil', 'used', 'contract_expr'];
+            baseLedgerTree.calcFun = function (node) {
+                if (!node.children || node.children.length === 0) {
+                    node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
+                    node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+                    node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
+                    node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
+                    node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
+                }
+                node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
+                node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
+                node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
+                node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
+                node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
+                node.end_final_tp = ZhCalc.add(node.end_qc_tp, node.total_price);
+                if (!node.children || node.children.length === 0) {
+                    if (node.end_contract_qty) {
+                        node.end_correct_tp = ZhCalc.add(node.end_qc_tp, ZhCalc.mul(node.end_contract_qty, node.unit_price, tenderInfo.decimal.tp));
+                    } else {
+                        node.end_correct_tp = node.end_gather_tp;
+                    }
+                }
+                node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.end_final_tp), 100, 2);
+                node.end_correct_percent = ZhCalc.mul(ZhCalc.div(node.end_correct_tp, node.end_final_tp), 100, 2);
+                node.final_dgn_price = ZhCalc.round(ZhCalc.div(node.end_gather_tp, ZhCalc.add(node.deal_dgn_qty1, node.c_dgn_qty1)), tenderInfo.decimal.up);
                 node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
-            }
-        });
-        const newLedgerList = setMonthToLedger(data.bills, data.slm);
-        baseLedgerTree.loadDatas(newLedgerList);
-        treeCalc.calculateAll(baseLedgerTree);
-        console.log(baseLedgerTree);
-        for (const d of baseLedgerTree.nodes) {
-            if (!d.b_code) {
-                const one = _.find(selectedLedgerList, function (item) {
-                    return item === d.ledger_id;
-                });
-                if(one) {
-                    ledgerTree.addData(d, showList);
+            };
+            // const newLedgerList = setMonthToLedger(data.bills, data.slm);
+            baseLedgerTree.loadDatas(data.ledgerData);
+            treeCalc.calculateAll(baseLedgerTree);
+            console.log(baseLedgerTree);
+            for (const d of baseLedgerTree.nodes) {
+                if (!d.b_code) {
+                    const one = _.find(selectedLedgerList, function (item) {
+                        return item === d.ledger_id;
+                    });
+                    if(one) {
+                        ledgerTree.addData(d, showList);
+                    }
                 }
             }
-        }
-        console.log(ledgerTree);
-        ledgerTree.sortTreeNode(true);
-        // console.log(ledgerTree);
-        SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
-    }, null, true);
+            console.log(ledgerTree);
+            ledgerTree.sortTreeNode(true);
+            // console.log(ledgerTree);
+            SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
+        }, null, true);
+    }
 
     const ledgerSpreadObj = {
         refreshTree: function (sheet, data) {
@@ -175,183 +182,55 @@ $(function () {
                 }
             });
         },
-        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 = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
-                const orgValue = select[col.field];
-                if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                    return;
-                }
-                if (isNaN(validText)) {
-                    toastr.error('不能输入其它非数字类型字符');
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                    return;
-                }
-                const yearmonth = col.field.split('_')[0];
-                // 判断输入位数,提示
-                const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.up) +'})?$');
-                if (validText !== null && (!reg.test(validText))) {
-                    toastr.error('输入工程量小数位数不能大于' + tenderInfo.decimal.up + '位');
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                    return;
-                }
-                const sj_gcl = validText;
-                const sj_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), tenderInfo.decimal.tp) : 0;
-                select[col.field] = validText;
-                const updateData = {
-                    lid: select.ledger_id,
-                    yearmonth,
-                    sj_gcl,
-                    sj_tp,
-                };
-                console.log(updateData);
-                postData(window.location.pathname + '/save', {type: 'ledger_edit', postData: updateData}, function (result) {
-                    select[yearmonth + '_sj_tp'] = sj_tp;
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                },function () {
-                    select[col.field] = orgValue;
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                })
-            }
-        },
-        deletePress: function (sheet) {
-            return;
-        },
-        clipboardPasted(e, info) {
-            const hint = {
-                cellError: {type: 'error', msg: '粘贴内容超出了表格范围'},
-                numberExpr: {type: 'error', msg: '不能粘贴其它非数字类型字符'},
-                numberCan: {type: 'error', msg: '请粘贴大于0并且小于3位小数的浮点数'},
-            };
-            const range = info.cellRange;
-            const sortData = info.sheet.zh_data || [];
-            if (info.cellRange.row + info.cellRange.rowCount > sortData.length) {
-                toastMessageUniq(hint.cellError);
-                SpreadJsObj.reLoadSheetHeader(materialMonthSpread.getActiveSheet());
-                SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
-                return;
-            }
-            if (sortData.length > 0 && range.col + range.colCount > 4 + months.length) {
-                toastMessageUniq(hint.cellError);
-                SpreadJsObj.reLoadSheetHeader(materialMonthSpread.getActiveSheet());
-                SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
-                return;
-            }
-            const data = [];
-            for (let iRow = 0; iRow < range.rowCount; iRow++) {
-                let bPaste = true;
-                const curRow = range.row + iRow;
-                const materialMonthData = sortData[curRow];
-                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 orgValue = sortData[curRow][colSetting.field];
-                    if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
-                        sameCol++;
-                        if (range.colCount === sameCol)  {
-                            bPaste = false;
-                        }
-                        continue;
-                    }
-                    const num = parseFloat(validText);
-                    if (isNaN(validText)) {
-                        toastMessageUniq(getPasteHint(hint.numberExpr, hintRow));
-                        bPaste = false;
-                        continue;
-                    }
-                    if (validText !== null && (num < 0 || !/^\d+(\.\d{1,3})?$/.test(num))) {
-                        toastMessageUniq(getPasteHint(hint.numberCan, hintRow));
-                        bPaste = false;
-                        continue;
-                    }
-                    materialMonthData[colSetting.field] = validText;
-                    sortData[curRow][colSetting.field] = validText;
-                }
-                if (bPaste) {
-                    data.push(materialMonthData);
-                } else {
-                    SpreadJsObj.reLoadRowData(info.sheet, curRow);
-                }
-            }
-            if (data.length === 0) {
-                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
-                return;
-            }
-            // // 更新至服务器
-            // postData(window.location.pathname + '/month/save', { type:'paste', updateData: data }, function (result) {
-            //     SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
-            //     materialBillsData = result.materialBillsData;
-            //     SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
-            //     m_tp = result.m_tp;
-            //     resetTpTable();
-            // }, function () {
-            //     SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
-            //     return;
-            // });
-        },
     };
 
-    ledgerSpread.bind(spreadNS.Events.EditEnded, ledgerSpreadObj.editEnded);
-    SpreadJsObj.addDeleteBind(ledgerSpread, ledgerSpreadObj.deletePress);
-
-    // 月份添加
-    $('#add-month').click(function () {
-        const id = parseInt($('#month-select').val());
-        if(id === 0) {
+    $('#add-stage').click(function () {
+        const yearmonth = $('#month_list').val();
+        const order = parseInt($('#stage_list').val());
+        if (yearmonth === '0') {
             toastr.error('请选择计划进度月');
             return;
         }
+        if (order === 0) {
+            toastr.error('请选择计量期');
+            return;
+        }
         const _self = $(this);
-        postData(window.location.pathname + '/save', {type: 'add_stage', postData: { id: id }}, function (result) {
+        postData(window.location.pathname + '/save', {type: 'add_stage', postData: { yearmonth, order }}, function (result) {
             _self.addClass('disabled').attr('disabled', true);
-            toastr.success('创建成功');
+            toastr.success('新增成功');
             setTimeout(function () {
                 window.location.reload();
             }, 500)
         })
     });
 
-    $('#month-table input[type="checkbox"]').click(function () {
-        const selectedMonth = [];
-        $('#month-table input:checkbox:checked').each(function () {
-            selectedMonth.push('「' + $(this).parents('td').siblings('td').text() + '」');
-        });
-        if(selectedMonth.length > 0) {
-            $('#del-month-list').text(selectedMonth.join(''));
-            $('#del-month-list').parent().show();
-            $('#del-month').removeAttr('disabled');
-        } else {
-            $('#del-month-list').parent().hide();
-            $('#del-month').attr('disabled', true);
+    $('#reload-stage').click(function () {
+        const order = parseInt($('#reload-stage-list').val());
+        const id = parseInt($(this).data('id'));
+        if (order === 0) {
+            toastr.error('请选择计量期');
+            return;
         }
+        const _self = $(this);
+        postData('/tender/'+ getTenderId() + '/schedule/stage/save', {type: 'reload_stage', postData: { id, order }}, function (result) {
+            _self.addClass('disabled').attr('disabled', true);
+            toastr.success('重新生成成功');
+            setTimeout(function () {
+                window.location.href = '/tender/'+ getTenderId() + '/schedule/stage/order/' + order;
+            }, 500)
+        })
     });
 
-    $('#del-month').click(function () {
-        const selectedMonth = [];
-        $('#month-table input:checkbox:checked').each(function () {
-            selectedMonth.push($(this).parents('td').siblings().text());
-        });
-        if (selectedMonth.length === 0) {
-            toastr.error('请选择删除的计划周期');
-            return;
-        }
+    $('#del-stage').click(function () {
+        const id = parseInt($(this).data('id'));
         const _self = $(this);
-        postData(window.location.pathname + '/save', {type: 'del_stage', postData: selectedMonth}, function (result) {
+        postData('/tender/'+ getTenderId() + '/schedule/stage/save', {type: 'del_stage', postData: { id }}, function (result) {
             _self.addClass('disabled').attr('disabled', true);
             toastr.success('删除成功');
             setTimeout(function () {
-                window.location.reload();
+                window.location.href = '/tender/'+ getTenderId() + '/schedule/stage';
             }, 500)
-
         })
     });
 

+ 67 - 13
app/public/js/stage.js

@@ -2874,6 +2874,24 @@ $(document).ready(() => {
                     }
                 });
             }
+            function upload(formData) {
+                if (formData.length < 1) {
+                    return;
+                }
+                postDataWithFile(window.location.pathname + '/detail/add-img', formData, function (result) {
+                    const html = [];
+                    html.push('<div class="img-item">');
+                    html.push('<div class="img-bar">');
+                    html.push('<a href="javascript: void(0);" class="text-danger" title="删除"><i class="fa fa-remove" style="font-size: 24px"></i></a>');
+                    html.push('</div>');
+                    html.push('<div class="focus" style="width:100%; height:100%"><img src="', '/' + result, '" id="draggable" style="width:100%; height:100%"></div>');
+                    html.push('</div>');
+                    $('.img-view').append(html.join(''));
+                    $('.img-bar').click(removeImageItem);
+                    setdraggrable();
+                    $('#upload-img-file').val('');
+                });
+            }
             // 移动图片
             const moveImageItem = function (ev) {
                 const item = this;
@@ -2934,6 +2952,54 @@ $(document).ready(() => {
             $('#upload-img').click(function () {
                 $('#upload-img-file').trigger('click');
             });
+            // 拖拽上传
+            //拖拽上传文件
+            const dragbox = document.querySelector('#upload-img');
+            dragbox.addEventListener('dragover', function(e) {
+                e.preventDefault(); // 必须阻止默认事件
+            }, false);
+            dragbox.addEventListener('drop', function(e) {
+                e.preventDefault(); // 阻止默认事件
+                var file = null,
+                    data = e.dataTransfer.types;
+                for (var i = 0; i < data.length; i += 1) {
+                    if (data[i] === 'Files') {
+                        file = e.dataTransfer.files; //获取文件
+                        break;
+                    }else{
+                        var text = e.dataTransfer.getData('text/plain');
+                        $('.dragFile').append(text); //将拖拽的文字添加到容器里
+                        break;
+                    }
+                }
+                if (file && file[0].type.indexOf('image') !== -1) {
+                    var formData = new FormData();
+                    formData.append('file', file[0]); //上传单个文件的添加方式
+                    upload(formData); //upload 异步上传
+                }
+            }, false);
+            // 粘贴上传
+            $(".img-view").on('paste', function(ev) {
+                var file = null,
+                    data = (event.clipboardData || window.clipboardData).items;
+                for (var i = 0; i < data.length; i += 1) {
+                    if ((data[i].kind == 'string') && (data[i].type.match('^text/plain'))) {
+                        data[i].getAsString(function(str) {
+                            $('.dragFile').append(str); //容器里追加拷贝的文字
+                        })
+                        break;
+                    } else if ((data[i].kind == 'file') && (data[i].type.match('^image/'))) {
+                        file = data[i].getAsFile(); //读取图片文件
+                        break;
+                    }
+                }
+                if (file) {
+                    var formData = new FormData();
+                    formData.append('file', file); //上传单个文件的添加方式
+                    upload(formData); //异步上传文件
+                }
+            });
+
             $('#upload-img-file').change(function () {
                 const file = this.files[0];
                 const ext = file.name.toLowerCase().split('.').splice(-1)[0];
@@ -2945,19 +3011,7 @@ $(document).ready(() => {
                 if ($(this).val()) {
                     const formData = new FormData();
                     formData.append('file', this.files[0]);
-                    postDataWithFile(window.location.pathname + '/detail/add-img', formData, function (result) {
-                        const html = [];
-                        html.push('<div class="img-item">');
-                        html.push('<div class="img-bar">');
-                        html.push('<a href="javascript: void(0);" class="text-danger" title="删除"><i class="fa fa-remove" style="font-size: 24px"></i></a>');
-                        html.push('</div>');
-                        html.push('<div class="focus" style="width:100%; height:100%"><img src="', '/' + result, '" id="draggable" style="width:100%; height:100%"></div>');
-                        html.push('</div>');
-                        $('.img-view').append(html.join(''));
-                        $('.img-bar').click(removeImageItem);
-                        setdraggrable();
-                        $('#upload-img-file').val('');
-                    });
+                    upload(formData);
                 }
             });
 

+ 2 - 0
app/router.js

@@ -442,6 +442,8 @@ module.exports = app => {
     app.get('/tender/:id/schedule/plan', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.plan');
     app.post('/tender/:id/schedule/plan/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.savePlan');
     app.get('/tender/:id/schedule/stage', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.stageTp');
+    app.get('/tender/:id/schedule/stage/order/:order', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.stageTp');
+    app.post('/tender/:id/schedule/stage/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.saveStageTp');
     app.get('/tender/:id/schedule/stage/gcl', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.stageGcl');
     app.post('/tender/:id/schedule/stage/gcl/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.saveStageGcl');
 

+ 2 - 2
app/service/schedule_month.js

@@ -82,7 +82,7 @@ module.exports = app => {
         async addStageUsed(data) {
             const updateData = {
                 id: data.id,
-                stage_used: 1,
+                stage_gcl_used: 1,
             };
             return await this.db.update(this.tableName, updateData);
         }
@@ -93,7 +93,7 @@ module.exports = app => {
                 const updateDatas = [];
                 const updateLmDatas = [];
                 for (const m of data) {
-                    updateDatas.push({ row: { stage_used: 0, sj_gcl: null, sj_tp: null }, where: { yearmonth: m, tid: this.ctx.tender.id } });
+                    updateDatas.push({ row: { stage_gcl_used: 0, sj_gcl: null, sj_tp: null }, where: { yearmonth: m, tid: this.ctx.tender.id } });
                     updateLmDatas.push({ row: { sj_gcl: null, sj_tp: null }, where: { yearmonth: m, tid: this.ctx.tender.id } });
                 }
                 if (updateDatas.length > 0) await transaction.updateRows(this.tableName, updateDatas);

+ 85 - 0
app/service/schedule_stage.js

@@ -0,0 +1,85 @@
+'use strict';
+
+module.exports = app => {
+    class ScheduleStage extends app.BaseService {
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'schedule_stage';
+        }
+
+        async getLastPlanMonth() {
+            const sql = 'SELECT `yearmonth` FROM ?? WHERE `tid` = ? ORDER BY `yearmonth` DESC Limit 0,1';
+            const sqlParam = [this.tableName, this.ctx.tender.id];
+            return await this.db.query(sql, sqlParam);
+        }
+
+        async add(data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const insertData = {
+                    tid: this.ctx.tender.id,
+                    yearmonth: data.yearmonth,
+                    order: data.order,
+                };
+                // 更新schedule_month stage_tp_used为1
+                const updateData = {
+                    stage_tp_used: 1,
+                };
+                const option = {
+                    where: {
+                        tid: this.ctx.tender.id,
+                        yearmonth: data.yearmonth,
+                    },
+                };
+                await transaction.update(this.ctx.service.scheduleMonth.tableName, updateData, option);
+                await transaction.insert(this.tableName, insertData);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async del(data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const info = await this.getDataById(data.id);
+                await transaction.delete(this.tableName, { id: data.id });
+                // 更新schedule_month stage_tp_used为0
+                const updateData = {
+                    stage_tp_used: 0,
+                };
+                const option = {
+                    where: {
+                        tid: this.ctx.tender.id,
+                        yearmonth: info.yearmonth,
+                    },
+                };
+                await transaction.update(this.ctx.service.scheduleMonth.tableName, updateData, option);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async changeOrder(data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const updateData = {
+                    id: data.id,
+                    order: data.order,
+                };
+                await transaction.update(this.tableName, updateData);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+    }
+    return ScheduleStage;
+};

+ 1 - 1
app/view/schedule/plan_modal.ejs

@@ -33,7 +33,7 @@
                     <% for (const m of scheduleMonth) { %>
                     <tr>
                         <td><%- m.yearmonth %></td>
-                        <td><% if (m.stage_used === 0) { %><label></label><input type="checkbox" value="<%- m.id %>"><% } %></td>
+                        <td><% if (m.stage_gcl_used === 0 && m.stage_tp_used) { %><label></label><input type="checkbox" value="<%- m.id %>"><% } %></td>
                     </tr>
                     <% } %>
                 </table>

+ 2 - 2
app/view/schedule/stage_gcl_modal.ejs

@@ -11,7 +11,7 @@
                     <select class="form-control" id="month-select">
                         <option value="0">选择计量月</option>
                         <% for (const m of scheduleMonth) { %>
-                            <% if (m.stage_used === 0) { %>
+                            <% if (m.stage_gcl_used === 0) { %>
                             <option value="<%- m.id %>"><%- m.yearmonth.split('-')[0] %>年<%- parseInt(m.yearmonth.split('-')[1]) %>月 %></option>
                             <% } %>
                         <% } %>
@@ -36,7 +36,7 @@
                 <table class="table table-bordered table-hover" id="month-table">
                     <tr><th>计量月</th><th width="100">删除</th></tr>
                     <% for (const m of scheduleMonth) { %>
-                    <% if (m.stage_used === 1) { %>
+                    <% if (m.stage_gcl_used === 1) { %>
                     <tr><td><%- m.yearmonth %></td><td><label></label><input type="checkbox" value="<%- m.id %>"></td></tr>
                     <% } %>
                     <% } %>

+ 11 - 2
app/view/schedule/stage_tp.ejs

@@ -14,23 +14,31 @@
                         </a>
                     </div>
                 </div>
+                <% if (scheduleStage.length > 0) { %>
                 <div class="d-inline-block">
                     <div class="dropdown">
                         <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                            2020年3月(第3期)
+                            <%- curScheduleStage.yearmonth.split('-')[0] %>年<%- parseInt(curScheduleStage.yearmonth.split('-')[1]) %>月(第<%- curScheduleStage.order %>期)
                         </button>
                         <div class="dropdown-menu" aria-labelledby="dropdownMenuButton" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 26px, 0px); top: 0px; left: 0px; will-change: transform;">
-                            <a class="dropdown-item" href="#">2020年2月(第2期)</a>
+                            <% for (const s of scheduleStage) { %>
+                            <% if (s.id !== curScheduleStage.id) { %>
+                            <a class="dropdown-item" href="/tender/<%- tender.id %>/schedule/stage/order/<%- s.order %>"><%- s.yearmonth.split('-')[0] %>年<%- parseInt(s.yearmonth.split('-')[1]) %>月(第<%- s.order %>期)</a>
+                            <% } %>
+                            <% } %>
                         </div>
                     </div>
                 </div>
                 <div class="d-inline-flex">
                     <a href="#delete" data-toggle="modal" data-target="#delete" class="btn btn-sm btn-outline-danger">删除本期进度</a>
                 </div>
+                <% } %>
             </div>
             <div class="ml-auto">
                 <a href="" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#add">创建新计量进度</a>
+                <% if (scheduleStage.length > 0) { %>
                 <a href="" class="btn btn-sm btn-warning" data-toggle="modal" data-target="#re-build">重新生成本月进度</a>
+                <% } %>
             </div>
         </div>
     </div>
@@ -48,5 +56,6 @@
     const measureType = JSON.parse('<%- JSON.stringify(measureType) %>');
     const schedule = JSON.parse('<%- JSON.stringify(schedule) %>');
     const scheduleMonth = JSON.parse('<%- JSON.stringify(scheduleMonth) %>');
+    const curScheduleStage = JSON.parse('<%- JSON.stringify(curScheduleStage) %>');
     const monthList = _.map(scheduleMonth, 'yearmonth');
 </script>

+ 28 - 13
app/view/schedule/stage_tp_modal.ejs

@@ -8,26 +8,35 @@
             <div class="modal-body">
                 <div class="form-group">
                     <label>计划进度月</label>
-                    <select class="form-control">
-                        <option>2020年1月</option>
-                        <option>2020年2月</option>
-                        <option>2020年3月</option>
+                    <select class="form-control" id="month_list">
+                        <option value="0">选择计划进度月</option>
+                        <% for (const m of scheduleMonth) { %>
+                        <% if (!ctx.helper._.find(scheduleStage, { yearmonth: m.yearmonth })) { %>
+                        <option value="<%- m.yearmonth %>"><%- m.yearmonth.split('-')[0] %>年<%- parseInt(m.yearmonth.split('-')[1]) %>月 %></option>
+                        <% } %>
+                        <% } %>
                     </select>
                 </div>
                 <div class="form-group">
                     <label>计量期</label>
-                    <select class="form-control">
-                        <option>第3期</option>
+                    <select class="form-control" id="stage_list">
+                        <option value="0">选择计量期</option>
+                        <% for (const so of stageOrderList) { %>
+                        <% if (!ctx.helper._.find(scheduleStage, { order: so.order })) { %>
+                        <option value="<%- so.order %>">第<%- so.order %>期</option>
+                        <% } %>
+                        <% } %>
                     </select>
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-sm btn-primary" >确认创建</button>
+                <button type="button" class="btn btn-sm btn-primary" id="add-stage">确认创建</button>
             </div>
         </div>
     </div>
 </div>
+<% if (scheduleStage.length > 0) { %>
 <!--重新生成本月计量进度-->
 <div class="modal fade" id="re-build" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -37,18 +46,23 @@
             </div>
             <div class="modal-body">
                 <div class="form-group">
-                    <label>计划进度月:2020年3月</label>
+                    <label>计划进度月:<%- curScheduleStage.yearmonth.split('-')[0] %>年<%- parseInt(curScheduleStage.yearmonth.split('-')[1]) %>月</label>
                 </div>
                 <div class="form-group">
                     <label>计量期</label>
-                    <select class="form-control">
-                        <option>第3期</option>
+                    <select class="form-control" id="reload-stage-list">
+                        <option value="0">选择计量期</option>
+                        <% for (const so of stageOrderList) { %>
+                        <% if (!ctx.helper._.find(scheduleStage, { order: so.order })) { %>
+                        <option value="<%- so.order %>">第<%- so.order %>期</option>
+                        <% } %>
+                        <% } %>
                     </select>
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-sm btn-primary" >确认生成</button>
+                <button type="button" class="btn btn-sm btn-primary" data-id="<%- curScheduleStage.id %>" id="reload-stage">确认生成</button>
             </div>
         </div>
     </div>
@@ -61,16 +75,17 @@
                 <h5 class="modal-title">删除本期计量进度</h5>
             </div>
             <div class="modal-body">
-                <h6>确认删除「2020年3月(第3期)」计量进度?</h6>
+                <h6>确认删除「<%- curScheduleStage.yearmonth.split('-')[0] %>年<%- parseInt(curScheduleStage.yearmonth.split('-')[1]) %>月(第<%- curScheduleStage.order %>期)」计量进度?</h6>
                 <h6>删除后,数据无法恢复,请谨慎操作。</h6>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-sm btn-danger">确定删除</button>
+                <button type="button" class="btn btn-sm btn-danger" data-id="<%- curScheduleStage.id %>" id="del-stage">确定删除</button>
             </div>
         </div>
     </div>
 </div>
+<% } %>
 <!--首次使用提示-->
 <div class="modal fade" id="second" data-backdrop="static">
     <div class="modal-dialog" role="document">

+ 12 - 4
app/view/stage/modal.ejs

@@ -322,10 +322,18 @@
                 <h5 class="modal-title">添加草图</h5>
             </div>
             <div class="modal-body">
-                <p>
-                    <input type="file" id="upload-img-file" style="display: none;">
-                    <a href="javascript: void(0);" class="btn btn-outline-primary btn-sm" id="upload-img">上传图片</a>
-                </p>
+                <!--<p>-->
+                    <!--<input type="file" id="upload-img-file" style="display: none;">-->
+                    <!--<a href="javascript: void(0);" class="btn btn-outline-primary btn-sm" id="upload-img">上传图片</a>-->
+                <!--</p>-->
+                <input type="file" id="upload-img-file" style="display: none;">
+                <div class="card mb-2" id="upload-img">
+                    <div class="card-body p-1">
+                        <div class="text-center"><i class="fa fa-folder-open-o fa-3x"></i></div>
+                        <div class="text-center">点击或拖动图片文件到这里进行上传</div>
+                        <div class="text-center text-muted">仅支持单个文件上传,可以通过QQ、微信截图粘贴上传</div>
+                    </div>
+                </div>
                 <div class="img-view">
                 </div>
                 <div class="mt-2">

+ 8 - 8
app/view/tender/tender_sub_menu.ejs

@@ -43,14 +43,14 @@
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/material') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-line-chart"></i> <span>材料调差</span></a></li>
             </ul>
         </div>
-        <!--<div class="nav-box">-->
-            <!--<h3><i class="fa fa-bar-chart "></i> 形象进度</h3>-->
-            <!--<ul class="nav-list list-unstyled sub-list">-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage/gcl') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>-->
-            <!--</ul>-->
-        <!--</div>-->
+        <div class="nav-box">
+            <h3><i class="fa fa-bar-chart "></i> 形象进度</h3>
+            <ul class="nav-list list-unstyled sub-list">
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>
+                <li <% if (ctx.url.indexOf('/tender/' + ctx.tender.id + '/schedule/stage') !== -1) { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>
+            </ul>
+        </div>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/report') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/report"><i class="fa fa-file-text-o"></i> <span>报表</span></a></li>

+ 8 - 8
app/view/tender/tender_sub_mini_menu.ejs

@@ -41,14 +41,14 @@
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/material') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-line-chart"></i> <span>材料调差</span></a></li>
             </ul>
         </div>
-        <!--<div class="nav-box">-->
-            <!--<h3><i class="fa fa-bar-chart "></i> 形象进度</h3>-->
-            <!--<ul class="nav-list list-unstyled sub-list">-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage/gcl') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>-->
-            <!--</ul>-->
-        <!--</div>-->
+        <div class="nav-box">
+            <h3><i class="fa fa-bar-chart "></i> 形象进度</h3>
+            <ul class="nav-list list-unstyled sub-list">
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage/gcl') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>
+            </ul>
+        </div>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/report') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/report"><i class="fa fa-file-text-o"></i> <span>报表</span></a></li>