Przeglądaj źródła

中间计量改版

MaiXinRong 7 lat temu
rodzic
commit
e4dcb0f0b3

+ 2 - 2
app/const/audit.js

@@ -16,10 +16,10 @@ const status = {
 };
 
 const statusString = [];
-statusString[status.uncheck] = '未开始审批';
+statusString[status.uncheck] = '未上报';
 statusString[status.checking] = '审批中';
 statusString[status.checked] = '审批完成';
-statusString[status.checkNo] = '退回';
+statusString[status.checkNo] = '审批退回';
 
 const statusClass = [];
 statusClass[status.uncheck] = '';

+ 2 - 2
app/controller/ledger_controller.js

@@ -50,12 +50,12 @@ module.exports = app => {
                 tenderData.ledger_times = 1;
             }
             const curAuditor = await ctx.service.ledgerAudit.getCurAuditor(tenderId, tenderData.ledger_times);
-            const auditors = await ctx.service.ledgerAudit.getAuditors(tenderId, tenderData.ledger_times);
             const times = tenderData.ledger_status === auditConst.status.checkNo ? tenderData.ledger_times - 1 : tenderData.ledger_times;
+            const auditors = await ctx.service.ledgerAudit.getAuditors(tenderId, times);
             const content = await ctx.service.ledgerAuditContent.getAllDataByCondition({
                 where: {tender_id: tenderId, times: times, audit_id: auditors[0].audit_id}
             });
-            const ledgerData = await ctx.service.ledger.getDataByTenderId(tenderId);
+            const ledgerData = await ctx.service.ledger.getDataByTenderId(tenderId, 4);
             const renderData = {
                 tenderData,
                 auditConst,

+ 279 - 0
app/controller/measure_audit_controller.js

@@ -0,0 +1,279 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const auditConst = require('../const/audit');
+const spreadConst = require('../const/spread');
+
+module.exports = app => {
+    class MeasureAuditController extends app.BaseController {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局context
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            ctx.showProject = true;
+        }
+
+        /**
+         * 中间计量--计量审批 页面 (Get)
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async list(ctx) {
+            try {
+                const tenderId = ctx.session.sessionUser.tenderId;
+                if (!tenderId) {
+                    throw '当前未打开标段';
+                }
+
+                const works = await ctx.service.measure.joinMeasure(tenderId, ctx.session.sessionUser.accountId);
+                for (const w of works) {
+                    w.in_time_str = moment(w.in_time_str).format('YYYYMM');
+                    if (w.times > 1 && w.status === auditConst.status.checkNo) {
+                        w.curAuditor = await ctx.service.measureAudit.getAuditor(w.mid, w.user_id, w.times);
+                    } else {
+                        w.curAuditor = await ctx.service.measureAudit.getCurAuditor(w.mid, w.times);
+                    }
+                }
+                const renderData = {
+                    works,
+                    auditConst,
+                };
+                await this.layout('measure/list.ejs', renderData);
+            } catch (err) {
+                console.log(err);
+                ctx.redirect(ctx.request.referrer);
+            }
+        }
+
+        /**
+         * 中间计量审批页面 (Get)
+         *
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async index(ctx) {
+            try {
+                const tenderId = ctx.session.sessionUser.tenderId;
+                if (!tenderId) {
+                    throw '当前未打开标段';
+                }
+
+                const mid = ctx.params.mid;
+                const measure = mid ? await ctx.service.measure.getDataByCondition({mid: mid}) : null;
+                if (!measure) {
+                    throw '查看的中间计量不存在';
+                }
+                const curAuditor = await ctx.service.measureAudit.getCurAuditor(measure.mid, measure.times);
+                const times = (measure.times > 1 && measure.status === auditConst.status.checkNo) ? measure.times - 1 : measure.times;
+                const auditors = await ctx.service.measureAudit.getAuditors(measure.mid, times);
+                const bills = await ctx.service.measureBills.getBillsDetailWithParent(tenderId, mid);
+
+                const renderData = {
+                    measure,
+                    billsData: JSON.stringify(bills),
+                    curAuditor,
+                    auditors,
+                    auditConst,
+                    measureSpreadSetting: JSON.stringify(spreadConst.measureSpread),
+                }
+                await this.layout('measure/audit.ejs', renderData, 'measure/audit_modal.ejs');
+            } catch (err) {
+                console.log(err);
+                ctx.redirect(ctx.request.headers.referrer);
+            }
+        };
+
+        /**
+         * 新增审批人(Ajax)
+         *
+         * @param {Object} ctx - egg全局context
+         * @returns {Promise<void>}
+         */
+        async add(ctx) {
+            const responseData = {
+                err: 0,
+                msg: '',
+                data: [],
+            };
+            try {
+                const tenderId = ctx.session.sessionUser.tenderId;
+                if (!tenderId) {
+                    throw '当前未打开标段';
+                }
+
+                const data = JSON.parse(ctx.request.body.data);
+                const mid = data.mid;
+                const id = data.auditorId;
+                if (!mid ||  isNaN(id) || id <= 0) {
+                    throw '参数错误';
+                }
+
+                const auditor = await ctx.service.measureAudit.getAuditor(mid, id);
+                if (auditor) {
+                    throw '该审批人已存在,请勿重复添加';
+                }
+
+                const result = await ctx.service.measureAudit.addAuditor(tenderId, mid, id);
+                if (!result) {
+                    throw '添加审批人失败';
+                }
+
+                responseData.data = await ctx.service.measureAudit.getAuditor(mid, id);
+            } catch (err) {
+                console.log(err);
+                responseData.err = 1;
+                responseData.msg = err.toString();
+            }
+
+            ctx.body = responseData;
+        }
+
+        /**
+         * 移除审批人 (Ajax)
+         *
+         * @param {Object} ctx - egg全局context
+         * @returns {Promise<void>}
+         */
+        async remove(ctx) {
+            const responseData = {
+                err: 0,
+                msg: '',
+                data: [],
+            };
+            try {
+                const tenderId = ctx.session.sessionUser.tenderId;
+                if (!tenderId) {
+                    throw '当前未打开标段';
+                }
+
+                const data = JSON.parse(ctx.request.body.data);
+                const mid = data.mid;
+                const id = data.auditorId;
+                if (!mid ||  isNaN(id) || id <= 0) {
+                    throw '参数错误';
+                }
+
+                const measure = await ctx.service.measure.getDataByCondition({mid: mid});
+                const auditor = await ctx.service.measureAudit.getAuditor(mid, id);
+                if (!measure || !auditor) {
+                    throw '提交数据错误';
+                }
+
+                const result = await ctx.service.measureAudit.deleteAuditor(mid, id, measure.times);
+                if (!result) {
+                    throw '移除审批人失败';
+                }
+
+                responseData.data = await ctx.service.measureAudit.getAuditors(mid);
+            } catch (err) {
+                console.log(err);
+                responseData.err = 1;
+                responseData.msg = err.toString();
+            }
+
+            ctx.body = responseData;
+        }
+
+        /**
+         * 上报 (Ajax)
+         *
+         * @param {Object} ctx - egg全局context
+         * @returns {Promise<void>}
+         */
+        async start(ctx) {
+            const responseData = {
+                err: 0,
+                msg: '',
+                data: {},
+            };
+            try {
+                const tenderId = ctx.session.sessionUser.tenderId;
+                if (!tenderId) {
+                    throw '未打开标段';
+                }
+
+                const data = JSON.parse(ctx.request.body.data);
+                const mid = data.mid;
+                if (!mid) {
+                    throw '参数错误';
+                }
+
+                const measure = await ctx.service.measure.getDataByCondition({mid: mid});
+                if (!measure || measure.status === auditConst.status.checking || measure.status === auditConst.status.checked) {
+                    throw '中间计量数据有误';
+                }
+                if (measure.user_id !== ctx.session.sessionUser.accountId) {
+                    throw '上报失败';
+                }
+
+                await ctx.service.measureAudit.start(mid, measure.times);
+                responseData.data = await ctx.service.measure.getDataByCondition({mid: mid});
+                responseData.data.auditors = await ctx.service.measureAudit.getAuditors(measure.mid, measure.times);
+                responseData.data.curAuditor = await ctx.service.measureAudit.getCurAuditor(measure.mid, measure.times);
+            } catch (err) {
+                console.log(err);
+                responseData.err = 1;
+                responseData.msg = err.toString();
+                responseData.data = {};
+            }
+
+            ctx.body = responseData;
+        }
+
+        /**
+         * 审批 (Post)
+         *
+         * @param {Object} ctx - egg全局context
+         * @returns {Promise<void>}
+         */
+        async check(ctx) {
+            try {
+                const tenderId = ctx.session.sessionUser.tenderId;
+                if (!tenderId) {
+                    throw '当前未打开标段';
+                }
+
+                const mid = ctx.request.body.mid;
+                if (!mid) {
+                    throw '参数错误';
+                }
+                const measure = await ctx.service.measure.getDataByCondition({mid: mid});
+                if (!measure || measure.status !== auditConst.status.checking) {
+                    throw '中间计量数据有误';
+                }
+                const curAudit = await ctx.service.measureAudit.getCurAuditor(mid, measure.times);
+                if (curAudit.audit_id !== ctx.session.sessionUser.accountId) {
+                    throw '审批失败';
+                }
+
+                const checkType = parseInt(ctx.request.body.checkType);
+                if (!checkType || isNaN(checkType)) {
+                    throw '提交数据错误';
+                }
+
+                await ctx.service.measureAudit.check(mid, checkType, ctx.request.body.opinion, measure.times);
+
+                ctx.redirect(ctx.request.headers.referer);
+            } catch (err) {
+                console.log(err);
+                ctx.session.postError = err.toString();
+                ctx.redirect(ctx.request.headers.referer);
+            }
+        }
+
+    };
+
+    return MeasureAuditController;
+};

+ 67 - 20
app/controller/measure_controller.js

@@ -10,6 +10,7 @@
 
 const spreadConst = require('../const/spread');
 const codeRuleConst = require('../const/code_rule');
+const auditConst = require('../const/audit');
 const moment = require('moment');
 
 module.exports = app => {
@@ -29,6 +30,57 @@ module.exports = app => {
             ctx.showTitle = true;
         }
 
+        async list(ctx) {
+            try {
+                const tenderList = ctx.tenderList;
+                const tenderData = ctx.tenderData;
+
+                const codeRule = tenderData.m_rule ? JSON.parse(tenderData.m_rule) : [];
+                for (const rule of codeRule) {
+                    switch (rule.rule_type) {
+                        case codeRuleConst.measure.ruleType.tenderName:
+                            rule.preview = tenderData.name;
+                            break;
+                        case codeRuleConst.measure.ruleType.inDate:
+                            rule.preview = moment().format('YYYYMM');
+                            break;
+                        case codeRuleConst.measure.ruleType.text:
+                            rule.preview = rule.text;
+                            break;
+                        case codeRuleConst.measure.ruleType.addNo:
+                            const s = '0000000000';
+                            rule.preview = s.substr(s.length - rule.format);
+                            break;
+                    }
+                }
+                const works = await ctx.service.measure.getAllDataByCondition({
+                    where: {tender_id: tenderData.id, user_id: ctx.session.sessionUser.accountId}
+                });
+                for (const w of works) {
+                    w.in_time_str = moment(w.in_time_str).format('YYYYMM');
+                    if (w.times > 1 && w.status === auditConst.status.checkNo) {
+                        w.curAuditor = await ctx.service.measureAudit.getAuditor(w.mid, w.user_id, w.times);
+                    } else {
+                        w.curAuditor = await ctx.service.measureAudit.getCurAuditor(w.mid, w.times);
+                    }
+                }
+
+                const renderData = {
+                    tenderData,
+                    tenderList,
+                    ruleType: codeRuleConst.ruleType.measure,
+                    ruleConst: codeRuleConst.measure,
+                    codeRule,
+                    works,
+                    auditConst,
+                };
+                await this.layout('measure/wlist.ejs', renderData, 'measure/wlist_modal.ejs');
+            } catch (err) {
+                console.log(err);
+                this.redirect(ctx.menuList.dashboard.url);
+            }
+        }
+
         /**
          * 中间计量--计量编制 页面 (Get)
          *
@@ -39,7 +91,6 @@ module.exports = app => {
             try {
                 const tenderList = ctx.tenderList;
                 const tenderData = ctx.tenderData;
-
                 const codeRule = tenderData.m_rule ? JSON.parse(tenderData.m_rule) : [];
                 for (const rule of codeRule) {
                     switch (rule.rule_type) {
@@ -59,16 +110,13 @@ module.exports = app => {
                     }
                 }
 
-                const measures = await ctx.service.measure.getAllDataByCondition({
-                    where: {tender_id: tenderData.id}
-                });
+                const mid = ctx.params.mid
+                const measure = await ctx.service.measure.getDataByCondition({mid: mid});
                 const renderData = {
                     tenderData,
                     tenderList,
-                    ruleType: codeRuleConst.ruleType.measure,
-                    ruleConst: codeRuleConst.measure,
-                    codeRule,
-                    measures,
+                    auditConst,
+                    measure,
                     measureSpreadSetting: JSON.stringify(spreadConst.measureSpread),
                 };
                 await this.layout('measure/work.ejs', renderData, 'measure/work_modal.ejs');
@@ -147,7 +195,7 @@ module.exports = app => {
                 const tenderData = await ctx.service.tender.getDataById(tenderId);
 
                 const data = JSON.parse(ctx.request.body.data);
-                await ctx.service.measure.add(tenderId, data.code, data.date, data.stage);
+                await ctx.service.measure.add(tenderId, data.code, ctx.session.sessionUser.accountId, data.date, data.stage);
 
                 responseData.data = await ctx.service.measure.getDataByCondition({
                     tender_id: tenderId, code: data.code,
@@ -187,9 +235,19 @@ module.exports = app => {
                     tender_id: tenderId,
                     mid: data.mid,
                 });
+                if (!measure.times) {
+                    measure.times = 1;
+                }
+
                 measure.pos = await ctx.service.measurePos.getPosDetail(tenderId, data.mid);
                 measure.bills = await ctx.service.measureBills.getBillsDetail(tenderId, data.mid);
                 measure.billsTree = await ctx.service.measureBills.getBillsDetailWithParent(tenderId, data.mid);
+                measure.curAuditor = await ctx.service.measureAudit.getCurAuditor(data.mid, measure.times);
+                if (measure.times > 1 && measure.status === auditConst.status.checkNo) {
+                    measure.auditors = await ctx.service.measureAudit.getAuditors(data.mid, measure.times-1);
+                } else {
+                    measure.auditors = await ctx.service.measureAudit.getAuditors(data.mid, measure.times);
+                }
 
                 responseData.data = measure;
             } catch (err) {
@@ -374,17 +432,6 @@ module.exports = app => {
 
             ctx.body = responseData;
         }
-
-        /**
-         * 中间计量--计量审批 页面 (Get)
-         *
-         * @param {Object} ctx - egg全局变量
-         * @return {void}
-         */
-        async list(ctx) {
-            const renderData = {};
-            await this.layout('measure/list.ejs', renderData);
-        }
     }
 
     return MeasureController;

+ 0 - 1
app/controller/tender_controller.js

@@ -175,7 +175,6 @@ module.exports = app => {
                     id: tenderId,
                 };
                 updateData[codeRuleConst.ruleField[data.rule]] = data.data;
-                console.log(updateData);
 
                 const result = await ctx.service.tender.db.update(ctx.service.tender.tableName, updateData);
                 if (result.affectedRows !== 1) {

+ 42 - 0
app/public/css/main.css

@@ -462,3 +462,45 @@ body {
   height:400px;
   overflow: hidden
 }
+.toast{
+  position: absolute;
+  top: 0;
+  width: 65%;
+  left: 0;
+  right: 0;
+  margin: 0 auto;
+  opacity: 0.8;
+  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
+  z-index: 999;
+  padding: 15px;
+  border-radius: 3px;
+  color: #ffffff;
+  display: none;
+}
+.toast .message{
+  padding-left: 50px;
+  display: inline-block;
+  font-size: 14px;
+}
+.toast i.icon{
+  font-size: 25px;
+  position: absolute;
+  left: 23px;
+  top: 13px;
+}
+.toast.success{
+  background: rgba(16, 196, 105, 0.8);
+  border: 2px solid #10c469
+}
+.toast.error{
+  background-color: rgba(255, 91, 91, 0.8);
+  border: 2px solid #ff5b5b;
+}
+.toast.warning {
+  background-color: rgba(249, 200, 81, 0.8);
+  border: 2px solid #f9c851;
+}
+.toast.info {
+  background-color: rgba(53, 184, 224, 0.8);
+  border: 2px solid #35b8e0;
+}

+ 17 - 1
app/public/js/global.js

@@ -160,4 +160,20 @@ const postDataWithFile = function (url, formData, successCallback, errorCallBack
             }
         }
     });
-};
+};
+
+/**
+ * 获取url中参数
+ * @param variable
+ * @returns {*}
+ */
+function getQueryVariable(variable) {
+    console.log(window.location.pathname);
+    var query = window.location.search.substring(1);
+    var vars = query.split("&");
+    for (var i=0;i<vars.length;i++) {
+        var pair = vars[i].split("=");
+        if(pair[0] == variable){return pair[1];}
+    }
+    return(false);
+}

+ 1 - 1
app/public/js/ledger.js

@@ -867,7 +867,7 @@ $(document).ready(function() {
         const li = $(this).parent();
         const data = {
             auditorId: parseInt(li.attr('auditorId')),
-        }
+        };
         postData('/ledger/audit/delete', data, (data) => {
             li.remove();
             for (const a of data) {

+ 75 - 0
app/public/js/measure_audit.js

@@ -0,0 +1,75 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2018/7/24
+ * @version
+ */
+
+$(document).ready(() => {
+    autoFlashHeight();
+
+    const billsTree = createNewPathTree('measure', {
+        id: 'ledger_id',
+        pid: 'ledger_pid',
+        order: 'order',
+        level: 'level',
+        rootId: -1,
+        keys: ['id', 'tender_id', 'ledger_id'],
+    });
+    billsTree.loadDatas(billsData);
+    treeCalc.calculateAll(billsTree, ['total_price', 'deal_totalprice', 'qc_totalprice']);
+    const billsSpread = SpreadJsObj.createNewSpread($('#billsSpread')[0]);
+    const sheet = billsSpread.getActiveSheet();
+    SpreadJsObj.initSheet(sheet, measureSpreadSetting);
+    SpreadJsObj.loadSheetData(sheet, 'tree', billsTree);
+    /**
+     * 父项不可编辑
+     * sender - {type: 'EditStarting'}
+     * args - {sheet, sheetName, row, col, cancel}
+     */
+    sheet.bind(spreadNS.Events.EditStarting, function (sender, args) {
+        const sheet = args.sheet;
+        if (sheet.zh_tree) {
+            const node = sheet.zh_tree.nodes[args.row];
+            args.cancel = node ? !node.is_leaf : true;
+        } else {
+            args.cancel = true;
+        }
+    });
+    /**
+     * 最底层清单编辑后,提交
+     * sender - {type: 'EditEnding'}
+     * args - {sheet, sheetName, row, col, editor, editingText cancel}
+     */
+    sheet.bind(spreadNS.Events.EditEnding, function (sender, args) {
+        const sheet = args.sheet;
+        if (sheet.zh_tree || sheet.zh_setting) {
+            const node = sheet.zh_tree.nodes[args.row];
+            const col = sheet.zh_setting.cols[args.col];
+            if (node && node.is_leaf) {
+                const updateData = {
+                    mid: window.location.pathname.split('/')[3],
+                    bid: node.ledger_id,
+                    update: {},
+                }
+                updateData.update[col.field] = col.type === 'Number' ? parseFloat(args.editingText) : args.editingText;
+                postData('/measure/billsUpdate', updateData, function (data) {
+                    if (sheet.zh_tree.loadLeafData) {
+                        sheet.zh_tree.loadLeafData(data);
+                        const nodes = treeCalc.calculateParent(sheet.zh_tree, node, ['deal_totalprice', 'qc_totalprice']);
+                        SpreadJsObj.reLoadNodesData(sheet, nodes);
+                    }
+                }, function () {
+                    args.cancel = true;
+                });
+            } else {
+                args.cancel = true;
+            }
+        } else {
+            args.cancel = true;
+        }
+    });
+});

+ 181 - 0
app/public/js/measure_wlist.js

@@ -0,0 +1,181 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2018/8/6
+ * @version
+ */
+
+// 向后端请求中间计量号
+function getNewMeasureCode() {
+    postData('/measure/newCode', null, function (code) {
+        if (code !== '') {
+            $('#mj-code').val(code);
+        }
+    });
+}
+
+function getMeasureWorkHtml (data) {
+    const html = [];
+    html.push('<tr>');
+    html.push('<td>', '<a href="/measure/work/' + data.mid + '">', data.code, '</a>', '</td>');
+    html.push('<td>0.00</td>');
+    html.push('<td>' + moment(data.in_time).format('YYYYMM') + '</td>');
+    html.push('<td></td>');
+    html.push('<td>未上报</td>');
+    html.push('<td></td>');
+    html.push('<td><a href="#edit" data-toggle="modal" data-target="#edit" class="btn btn-outline-primary btn-sm">编辑</a></td>')
+    html.push('</tr>');
+    return html.join('');
+}
+
+class codeRuleSet {
+    constructor (obj) {
+        this.body = obj;
+        // 切换规则组件类型
+        $('select', obj).change(function () {
+            const codeType = this.selectedIndex;
+            if (codeType === ruleConst.ruleType.addNo) {
+                $('#format', obj).show();
+                $('#text', obj).show();
+                $('#text>label', obj).text('起始编号');
+                $('#text>input', obj).val('001');
+                const s = '0000000000' + 1;
+                $('#text>input', obj).val(s.substr(s.length - $('#format>input', obj).val()));
+            } else if (codeType === ruleConst.ruleType.text) {
+                $('#format', obj).hide();
+                $('#text', obj).show();
+                $('#text>label', obj).text('文本');
+                $('#text>input', obj).val('').attr('placeholder', '请在这里输入需要的文本');
+            } else {
+                $('#format', obj).hide();
+                $('#text', obj).hide();
+            }
+        });
+        // 修改编号位数
+        $('#format>input', obj).change(function () {
+            const s = '0000000000' + parseInt($('#text>input', obj).val());
+            $('#text>input', obj).val(s.substr(s.length - $(this).val()));
+        });
+        // 新增规则组件
+        $('#addRule', obj).click(function () {
+            const codeType = $('select', obj)[0].selectedIndex;
+            const rule = {rule_type: codeType}, html = [];
+            let preview;
+            switch (codeType) {
+                case ruleConst.ruleType.tenderName: {
+                    preview = $('#tenderName').text();
+                    break;
+                }
+                case ruleConst.ruleType.text: {
+                    rule.text =  $('#text>input', obj).val();
+                    preview = rule.text;
+                    break;
+                }
+                case ruleConst.ruleType.inDate: {
+                    preview = moment().format('YYYYMM');
+                    break;
+                }
+                case ruleConst.ruleType.addNo: {
+                    rule.format = parseInt($('#format>input', obj).val());
+                    rule.start = parseInt($('#text>input', obj).val());
+                    const s = '0000000000';
+                    preview = s.substr(s.length - rule.format);
+                    break;
+                }
+            }
+            // 更新规则
+            codeRule.push(rule);
+            // 更新规则显示
+            html.push('<span class="badge badge-light" title="' + ruleConst.ruleString[codeType] + '" rule="' + JSON.stringify(rule) + '">');
+            html.push('<span>' + preview + '</span>');
+            html.push('<a href="javascript: void(0);" class="text-danger" title="移除"><i class="fa fa-remove"></i></a>');
+            html.push('</span>');
+            const part = $('#ruleParts', obj).append(html.join(''));
+            // 更新规则预览
+            $('#preview', obj).text($('#preview', obj).text() + preview);
+
+            $('a', part).bind('click', function () {
+                const index = $('a', obj).index(this);
+                codeRule.splice(index, 1);
+                $(this).parent().remove();
+                const rules = $('span>span', obj), ruleText = [];
+                for (const r of rules) {
+                    ruleText.push(r.innerText);
+                }
+                $('#preview', obj).text(ruleText.join(''));
+            });
+        });
+        // 删除规则组件
+        $('a', $('#ruleParts', obj)).bind('click', function () {
+            const index = $('a', obj).index(this);
+            codeRule.splice(index, 1);
+            $(this).parent().remove();
+            const rules = $('span>span', obj), ruleText = [];
+            for (const r of rules) {
+                console.log(r.innerText + ':1');
+                ruleText.push(r.innerText);
+            }
+            $('#preview', obj).text('当前规则:' + ruleText.join(''));
+        });
+    }
+}
+
+$(document).ready(() => {
+    autoFlashHeight();
+    // 新增中间计量 modal显示
+    $('#add-mj').on('show.bs.modal', function() {
+        getNewMeasureCode();
+        if ($('#wlist').children.length === 0) {
+            $('#addCancel').hide();
+        } else {
+            $('#addCancel').show();
+        }
+        $('#mj-code').removeClass('is-invalid');
+    });
+    // 新增中间计量--刷新编号
+    $('#autoCode').click(getNewMeasureCode);
+    // 添加中间计量 确定
+    $('#addOk').click(function () {
+        const data = {
+            code: $('#mj-code').val(),
+            date: $('#mj-date').val(),
+        };
+        postData('/measure/add', data, function (rst) {
+            $('#mj-code').removeClass('is-invalid');
+            $('#mj-add').modal('hide');
+            $('#wlist').append(getMeasureWorkHtml(rst));
+        }, function () {
+            $('#mj-code').addClass('is-invalid');
+            $('#mj-Hint').show();
+        });
+    });
+
+    // 首次进入设置
+    if (!codeRule || codeRule.length === 0) {
+        codeRule = [];
+        const firstSet = new codeRuleSet($('div.modal-body', '#first'));
+        // 确认规则上传服务器
+        $('#setRule', '#first').bind('click', function () {
+            const data = {
+                rule: ruleType,
+                data: JSON.stringify(codeRule),
+            };
+            postData('/tender/rule', data, function () {
+                $('#first').modal('hide');
+                $('#add-mj').modal('show');
+            });
+        });
+
+        $('#first').modal('show');
+    } else if ($('#wlist').children.length === 0) {
+        $('#add-mj').modal('show');
+    }
+
+    // 中间计量设置页面
+    const obj = $('#rule');
+    console.log(obj);
+    const ruleSet = new codeRuleSet(obj);
+});

+ 195 - 207
app/public/js/measure_work.js

@@ -7,19 +7,13 @@
  * @date 2018/6/21
  * @version
  */
-
-// 向后端请求中间计量号
-function getNewMeasureCode() {
-    postData('/measure/newCode', null, function (code) {
-        if (code !== '') {
-            $('#mj-code').val(code);
-        }
-    });
+function getMid() {
+    return window.location.pathname.split('/')[3];
 }
 // 新增计量范围
 function addMeasurePos(pid) {
     postData('/measure/pos', {
-        mid: $('#measures').val(),
+        mid: window.location.pathname.split('/')[3],
         operate: 'add',
         pid: pid,
     }, function (data) {
@@ -35,41 +29,125 @@ function addMeasurePos(pid) {
 // 移除计量范围
 function removeMeasurePos(pid) {
     postData('/measure/pos', {
-        mid: $('#measures').val(),
+        mid: getMid(),
         operate: 'remove',
         pid: pid,
     }, function (data) {
         $('tr[id='+ pid +']', '#measurePosList').remove();
     })
 }
-
+//
+function getAuditorHtml(audit) {
+    const html = [];
+    html.push('<li class="list-group-item" auditorId="'+ audit.audit_id +'"><a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
+    html.push('<span>');
+    html.push(audit.order + ' ');
+    html.push(audit.name + ' ');
+    html.push('</span>');
+    html.push('<small class="text-muted">');
+    html.push(audit.role);
+    html.push('</small></li>')
+    return html.join('');
+}
+function bindRemoveAuditor(obj) {
+    obj.click(function () {
+        const li = $(this).parent();
+        const data = {
+            mid: getMid(),
+            auditorId: parseInt(li.attr('auditorId')),
+        }
+        postData('/measure/audit/remove', data, (data) => {
+            li.remove();
+            for (const a of data) {
+                const aLi = $('li[auditorId=' + a.audit_id + ']');
+                $('span', aLi).text(a.order + ' ' + a.name + ' ');
+            }
+        });
+    });
+}
+function getAuditStatuHtml(measure) {
+    const html = [];
+    if (measure.status === auditConst.status.checkNo) {
+        html.push('<a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm pull-right text-dark">报审退回</a>');
+    } else if (measure.status === auditConst.status.checking) {
+        html.push('<a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm pull-right text-dark">审批中</a>');
+    } else if (measure.status === auditConst.status.checked) {
+        html.push('<a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm pull-right">审批完成</a>');
+    }
+    if (measure.user_id === userId ) {
+        if (!measure.status || measure.status === auditConst.status.uncheck) {
+            html.push('<a href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm pull-right">上报审批</a>');
+        } else if (measure.status === auditConst.status.checkNo) {
+            html.push('<a href="#sub-sp" data-toggle="modal" data-target="#sub-sp2" class="btn btn-primary btn-sm pull-right">重新上报</a>');
+        }
+        html.push('<a href="#del" data-toggle="modal" data-target="#del" class="btn btn-outline-danger btn-sm pull-right">删除' + measure.code + '</a>');
+    }
+    return html.join('');
+}
+function getAuditListHtml(measure) {
+    const html = [];
+    for (const auditor of measure.auditors) {
+        html.push('<li class="list-group-item" auditorId="' + auditor.audit_id + '">');
+        if (auditor.status !== auditConst.status.uncheck) {
+            html.push('<span class="' + auditConst.statusClass[auditor.status] + ' pull-right">' + auditConst.statusString[auditor.status] + '</span>');
+        }
+        html.push('<h5 class="card-title">' + auditor.order + ' ' + auditor.name + ' <small class="text-muted">' + auditor.role + '</small></h5>');
+        html.push('<p class="card-text">', (auditor.opinion ? auditor.opinion : ''), ' ', (auditor.end_time ? moment(auditor.end_time).format('YYYY-MM-DD') : ''), '</p>');
+        html.push('</li>');
+    }
+    return html.join('');
+}
 
 $(document).ready(() => {
     autoFlashHeight();
 
-    // 新增中间计量 modal显示
-    $('#add-mj').on('show.bs.modal', function() {
-        getNewMeasureCode();
-        if ($('#measures')[0].options.length === 0) {
-            $('#addCancel').hide();
-        } else {
-            $('#addCancel').show();
+    // 上报审批 搜索
+    $('#searchAccount').click(() => {
+        const data = {
+            keyword: $('#searchName').val(),
         }
+        postData('/search/user', data, (data) => {
+            const resultDiv = $('#searchResult');
+            $('h5>span', resultDiv).text(data.name);
+            $('#addAuditor').attr('auditorId', data.id);
+            $('h6', resultDiv).text(data.role);
+            $('p', resultDiv).text(data.company);
+            resultDiv.show();
+        }, () => {
+            $('#searchResult').hide();
+        });
     });
-    // 新增中间计量--刷新编号
-    $('#autoCode').click(getNewMeasureCode);
-    // 添加中间计量 确定
-    $('#addOk').click(function () {
+    // 上报审批 添加审批人
+    $('#addAuditor').click(() => {
         const data = {
-            code: $('#mj-code').val(),
-            date: $('#mj-date').val(),
+            mid: getMid(),
+            auditorId: $('#addAuditor').attr('auditorId'),
         };
-        postData('/measure/list/add', data, function (rst) {
-            $('#mj-code').removeClass('is-invalid');
-            $('#mj-add').modal('hide');
-        }, function () {
-            $('#mj-code').addClass('is-invalid');
-            $('#mj-Hint').show();
+        postData('/measure/audit/add', data, (data) => {
+            $('#auditors').append(getAuditorHtml(data));
+            bindRemoveAuditor($('li[auditorId=' + data.audit_id + ']>a'));
+        });
+    });
+    // 上报审批
+    $('#auditStart').click(() => {
+        const data = { mid: getMid() };
+        postData('/measure/audit/start', data, function (data) {
+            $('#sub-sp').modal('hide');
+            // 审批状态等
+            $('#operate').html(getAuditStatuHtml(data));
+            // 审批流程列表
+            $('ul', '#sp-list').html(getAuditListHtml(data));
+        });
+    });
+    // 重新上报
+    $('#auditRestart').click(() => {
+        const data = { mid: getMid() };
+        postData('/measure/audit/start', data, function (data) {
+            $('#sub-sp2').modal('hide');
+            // 审批状态等
+            $('#operate').html(getAuditStatuHtml(data));
+            // 审批流程列表
+            $('ul', '#sp-list').html(getAuditListHtml(data));
         });
     });
 
@@ -132,17 +210,12 @@ $(document).ready(() => {
                         const col = sheet.zh_setting.cols[args.col];
                         if (node && node.is_leaf) {
                             const updateData = {
-                                mid: $('#measures').val(),
+                                mid: getMid(),
                                 bid: node.ledger_id,
                                 update: {},
                             }
                             updateData.update[col.field] = col.type === 'Number' ? parseFloat(args.editingText) : args.editingText;
-                            // begin test
-                            // node[col.field] = col.type === 'Number' ? parseFloat(args.editingText) : args.editingText;
-                            // node.deal_totalprice = node.unit_price * node.deal_quantity;
-                            // const nodes = treeCalc.calculateParent(sheet.zh_tree, node, ['deal_totalprice']);
-                            // SpreadJsObj.reLoadNodesData(sheet, nodes);
-                            // end test;
+
                             postData('/measure/billsUpdate', updateData, function (data) {
                                 if (sheet.zh_tree.loadLeafData) {
                                     sheet.zh_tree.loadLeafData(data);
@@ -162,12 +235,28 @@ $(document).ready(() => {
             } else {
                 SpreadJsObj.reLoadSheetData(billsSpread.getActiveSheet());
             }
+            // 审批状态等
+            $('#operate').html(getAuditStatuHtml(data));
+            $('ul', '#sp-list').html(getAuditListHtml(data));
+            // 上报审批 审批人列表
+            const ad = [];
+            for (const auditor of data.auditors) {
+                ad.push(getAuditorHtml(auditor));
+            }
+            $('#auditors').html(ad.join(''));
+            // 重新上报 审批人列表
+            if (data.status === auditConst.status.checkNo) {
+                $('#re-hint').text('重新上报后,将由 ' + data.auditors[0].name +' 继续审批');
+                $('#re-auditors').html(getAuditListHtml(data));
+            }
+            // 绑定移除方法
+            bindRemoveAuditor($('a', '#auditors'));
         });
     }
     // 新增计量清单
     function addMeasureBills (bid) {
         const data = {
-            mid: $('#measures').val(),
+            mid: getMid(),
             operate: 'add',
             bid: bid,
         };
@@ -179,7 +268,7 @@ $(document).ready(() => {
     // 移除计量清单
     function removeMeasureBills (bid) {
         const data = {
-            mid: $('#measures').val(),
+            mid: getMid(),
             operate: 'remove',
             bid: bid,
         };
@@ -199,175 +288,74 @@ $(document).ready(() => {
         }
     }
 
-    if (!codeRule || codeRule.length === 0) {
-        codeRule = [];
-        const firstSet = new codeRuleSet($('div.modal-body', '#first'));
-        // 确认规则上传服务器
-        $('#setRule', '#first').bind('click', function () {
-            const data = {
-                rule: ruleType,
-                data: JSON.stringify(codeRule),
-            };
-            postData('/tender/rule', data, function () {
-                $('#first').modal('hide');
-                $('#add-mj').modal('show');
-            });
-        });
-
-        $('#first').modal('show');
-    } else if ($('#measures')[0].options.length === 0) {
-        $('#add-mj').modal('show');
-    } else {
-        // 添加计量清单
-        $('#addMeasureBills').click(function () {
-            if ($('#measurePosList').children().length === 0) {
-                $('#add-pos').modal('show');
-            } else {
-                $('#add-qd').modal('show');
-            }
-        });
-        // 搜索项目节部位
-        $('#search-pos').click(function () {
-            const keyword = $('input', '#add-pos').val();
-            if (keyword !== '') {
-                postData('/measure/search', {
-                    mid: $('#measures').val(),
-                    searchType: 'pos',
-                    keyword: keyword
-                }, function (data) {
-                    const html = [];
-                    for (const d of data) {
-                        const tr = [];
-                        tr.push('<tr id="' + d.ledger_id +'">');
-                        tr.push('<td>' + d.code + '</td>');
-                        tr.push('<td>' + d.name + '</td>');
-                        tr.push('<td><a href="javascript: void(0)" onclick="addMeasurePos(' + d.ledger_id + ')">添加</a></td>');
-                        tr.push('</tr>');
-                        html.push(tr.join(''));
-                    }
-                    $('#searchedPosList').html(html.join(''));
-                });
-            }
-        });
-        // 选择计量清单
-        $('#chooseBills').click(function () {
-            $('#add-pos').modal('hide');
-            $('#add-qd').modal('show');
-        });
-        // 搜索计量清单
-        $('#search-bills').click(function () {
-            const keyword = $('input', '#add-qd').val();
-            if (keyword !== '') {
-                postData('/measure/search', {
-                    mid: $('#measures').val(),
-                    searchType: 'bills',
-                    keyword: keyword
-                }, function (data) {
-                    const html = [];
-                    for (const d of data) {
-                        const tr = [];
-                        const check = billsTree.getItems(d.ledger_id) ? 'checked' : '';
-                        tr.push('<tr id="' + d.ledger_id +'">');
-                        tr.push('<td>' + d.b_code + '</td>');
-                        tr.push('<td>' + d.name + '</td>');
-                        tr.push('<td>' + d.unit + '</td>');
-                        tr.push('<td>' + (d.unit_price ? d.unit_price : '') + '</td>');
-                        tr.push('<td><input type="checkbox" ' + check + '> 已选择</td>');
-                        tr.push('</tr>');
-                        html.push(tr.join(''));
-                    }
-                    $('#searchedBillsList').html(html.join(''));
-                    $('input[type=checkbox]', '#add-qd').click(checkMeasureBills);
-                });
-            }
-        });
-        // 选择计量范围
-        $('#choosePos').click(function () {
-            $('#add-qd').modal('hide');
+    // 添加计量清单
+    $('#addMeasureBills').click(function () {
+        if ($('#measurePosList').children().length === 0) {
             $('#add-pos').modal('show');
-        });
-
-        getMeasureDetail($('#measures').val());
-    }
-    const staticSet = new codeRuleSet($('#rule'), '#static');
-});
-
-class codeRuleSet {
-    constructor (obj) {
-        this.body = obj;
-        // 切换规则组件类型
-        $('select', obj).change(function () {
-            const codeType = this.selectedIndex;
-            if (codeType === ruleConst.ruleType.addNo) {
-                $('#format', obj).show();
-                $('#text', obj).show();
-                $('#text>label', obj).text('起始编号');
-                $('#text>input', obj).val('001');
-                const s = '0000000000' + 1;
-                $('#text>input', obj).val(s.substr(s.length - $('#format>input', obj).val()));
-            } else if (codeType === ruleConst.ruleType.text) {
-                $('#format', obj).hide();
-                $('#text', obj).show();
-                $('#text>label', obj).text('文本');
-                $('#text>input', obj).val('').attr('placeholder', '请在这里输入需要的文本');
-            } else {
-                $('#format', obj).hide();
-                $('#text', obj).hide();
-            }
-        });
-        // 修改编号位数
-        $('#format>input', obj).change(function () {
-            const s = '0000000000' + parseInt($('#text>input', obj).val());
-            $('#text>input', obj).val(s.substr(s.length - $(this).val()));
-        });
-        // 新增规则组件
-        $('#addRule', obj).click(function () {
-            const codeType = $('select', obj)[0].selectedIndex;
-            const rule = {rule_type: codeType}, html = [];
-            let preview;
-            switch (codeType) {
-                case ruleConst.ruleType.tenderName: {
-                    preview = $('#tenderName').text();
-                    break;
-                }
-                case ruleConst.ruleType.text: {
-                    rule.text =  $('#text>input', obj).val();
-                    preview = rule.text;
-                    break;
-                }
-                case ruleConst.ruleType.inDate: {
-                    preview = moment().format('YYYYMM');
-                    break;
-                }
-                case ruleConst.ruleType.addNo: {
-                    rule.format = parseInt($('#format>input', obj).val());
-                    rule.start = parseInt($('#text>input', obj).val());
-                    const s = '0000000000';
-                    preview = s.substr(s.length - rule.format);
-                    break;
+        } else {
+            $('#add-qd').modal('show');
+        }
+    });
+    // 搜索项目节部位
+    $('#search-pos').click(function () {
+        const keyword = $('input', '#add-pos').val();
+        if (keyword !== '') {
+            postData('/measure/search', {
+                mid: getMid(),
+                searchType: 'pos',
+                keyword: keyword
+            }, function (data) {
+                const html = [];
+                for (const d of data) {
+                    const tr = [];
+                    tr.push('<tr id="' + d.ledger_id +'">');
+                    tr.push('<td>' + d.code + '</td>');
+                    tr.push('<td>' + d.name + '</td>');
+                    tr.push('<td><a href="javascript: void(0)" onclick="addMeasurePos(' + d.ledger_id + ')">添加</a></td>');
+                    tr.push('</tr>');
+                    html.push(tr.join(''));
                 }
-            }
-            // 更新规则
-            codeRule.push(rule);
-            // 更新规则显示
-            html.push('<span class="badge badge-light" title="' + ruleConst.ruleString[codeType] + '" rule="' + JSON.stringify(rule) + '">');
-            html.push('<span>' + preview + '</span>');
-            html.push('<a href="javascript: void(0);" class="text-danger" title="移除"><i class="fa fa-remove"></i></a>');
-            html.push('</span>');
-            const part = $('#ruleParts', obj).append(html.join(''));
-            // 更新规则预览
-            $('#preview', obj).text($('#preview', obj).text() + preview);
-
-            $('a', part).bind('click', function () {
-                const index = $('a', obj).index(this);
-                codeRule.splice(index, 1);
-                $(this).parent().remove();
-                const rules = $('span>span', obj), ruleText = [];
-                for (const r of rules) {
-                    ruleText.push(r.innerText);
+                $('#searchedPosList').html(html.join(''));
+            });
+        }
+    });
+    // 选择计量清单
+    $('#chooseBills').click(function () {
+        $('#add-pos').modal('hide');
+        $('#add-qd').modal('show');
+    });
+    // 搜索计量清单
+    $('#search-bills').click(function () {
+        const keyword = $('input', '#add-qd').val();
+        if (keyword !== '') {
+            postData('/measure/search', {
+                mid: getMid(),
+                searchType: 'bills',
+                keyword: keyword
+            }, function (data) {
+                const html = [];
+                for (const d of data) {
+                    const tr = [];
+                    const check = billsTree.getItems(d.ledger_id) ? 'checked' : '';
+                    tr.push('<tr id="' + d.ledger_id +'">');
+                    tr.push('<td>' + d.b_code + '</td>');
+                    tr.push('<td>' + d.name + '</td>');
+                    tr.push('<td>' + d.unit + '</td>');
+                    tr.push('<td>' + (d.unit_price ? d.unit_price : '') + '</td>');
+                    tr.push('<td><input type="checkbox" ' + check + '> 已选择</td>');
+                    tr.push('</tr>');
+                    html.push(tr.join(''));
                 }
-                $('#preview', obj).text(ruleText.join(''));
+                $('#searchedBillsList').html(html.join(''));
+                $('input[type=checkbox]', '#add-qd').click(checkMeasureBills);
             });
-        });
-    }
-}
+        }
+    });
+    // 选择计量范围
+    $('#choosePos').click(function () {
+        $('#add-qd').modal('hide');
+        $('#add-pos').modal('show');
+    });
+
+    getMeasureDetail(getMid());
+});

+ 19 - 11
app/public/js/path_tree.js

@@ -21,6 +21,8 @@ const createNewPathTree = function (type, setting) {
             this.items = {};
             // 以排序为索引
             this.nodes = [];
+            // 索引
+            this.children = {};
             // 树设置
             this.setting = JSON.parse(JSON.stringify(setting));
         }
@@ -32,7 +34,8 @@ const createNewPathTree = function (type, setting) {
             const addSortNodes = function (nodes) {
                 for (let i = 0; i < nodes.length; i++) {
                     self.nodes.push(nodes[i]);
-                    addSortNodes(self.getChildren(nodes[i]));
+                    nodes[i].children = self.getChildren(nodes[i]);
+                    addSortNodes(nodes[i].children);
                 }
             };
             self.nodes = [];
@@ -54,8 +57,7 @@ const createNewPathTree = function (type, setting) {
             }
             this.sortTreeNode();
             for (const node of this.nodes) {
-                const children = this.getChildren(node);
-                node.expanded = children.length > 0;
+                node.expanded = node.children.length > 0;
                 node.visible = true;
             }
         }
@@ -83,8 +85,6 @@ const createNewPathTree = function (type, setting) {
          */
         getFullPathNodes (path) {
             const self = this, ids = path.split('.');
-            console.log(path);
-            console.log(ids);
             if (ids.length > 0) {
                 return this.nodes.filter((x) => {
                     return ids.indexOf('' + x[self.setting.id]) >= 0;
@@ -135,7 +135,7 @@ const createNewPathTree = function (type, setting) {
          * @private
          */
         _refreshChildrenVisible (node) {
-            const children = this.getChildren(node);
+            const children = node.children;//this.getChildren(node);
             for (const child of children) {
                 child.visible = node.expanded && node.visible;
                 this._refreshChildrenVisible(child);
@@ -197,7 +197,7 @@ const createNewPathTree = function (type, setting) {
             }
             this.sortTreeNode();
             for (const node of loadedData) {
-                const children = this.getChildren(node);
+                const children = node.children;
                 if (!node.expanded && children.length > 0) {
                     node.expanded = true;
                     this._refreshChildrenVisible(node);
@@ -218,6 +218,10 @@ const createNewPathTree = function (type, setting) {
                 const node = this.getItems(data[this.setting.id]);
                 if (node && this.getChildren(node).length === 0) {
                     delete this.items[itemsPre + node[this.setting.id]];
+                    if (node[this.setting.pid] !== this.setting.rootId) {
+                        const parent = this.items[itemsPre + node[this.setting.pid]];
+                        removeArrayData(parent.children, node);
+                    }
                     removeArrayData(this.datas, node);
                     removeArrayData(this.nodes, node);
                 }
@@ -269,7 +273,7 @@ const createNewPathTree = function (type, setting) {
             }
             this.sortTreeNode();
             for (const node of loadedData) {
-                const children = this.getChildren(node);
+                const children = node.children;
                 if (!node.expanded && children.length > 0) {
                     node.expanded = true;
                     this._refreshChildrenVisible(node);
@@ -354,7 +358,7 @@ const createNewPathTree = function (type, setting) {
             }
             this.sortTreeNode();
             for (const node of loadedData) {
-                const children = this.getChildren(node);
+                const children = node.children;
                 if (!node.expanded && children.length > 0) {
                     node.expanded = true;
                     this._refreshChildrenVisible(node);
@@ -376,6 +380,10 @@ const createNewPathTree = function (type, setting) {
                 const node = this.getItems(data[this.setting.id]);
                 if (node) {
                     delete this.items[itemsPre + node[this.setting.id]];
+                    if (node[this.setting.pid] !== this.setting.rootId) {
+                        const parent = this.getItems(node[this.setting.pid]);
+                        removeArrayData(parent.children, node);
+                    }
                     removeArrayData(this.datas, node);
                     removeArrayData(this.nodes, node);
                 }
@@ -405,14 +413,14 @@ const createNewPathTree = function (type, setting) {
             }
             this.sortTreeNode();
             for (const node of loadedData) {
-                const children = this.getChildren(node);
+                const children = node.children();
                 if (!node.expanded && children.length > 0) {
                     node.expaned = true;
                     this._refreshChildrenVisible(node);
                 }
             }
             for (const node of existData) {
-                const children = this.getChildren(node);
+                const children = node.children();
                 if (!node.expanded && children.length > 0) {
                     node.expanded = children.length > 0;
                     this._refreshChildrenVisible(node);

+ 2 - 0
app/public/js/spreadjs_rela/extend_celltype.js

@@ -228,9 +228,11 @@ SpreadJsExtendCellType = {
                     tree.setExpanded(node, !node.expanded);
                     SpreadJsObj.massOperationSheet(hitinfo.sheet, function () {
                         const posterity = tree.getPosterity(node);
+                        const time = new Date();
                         for (const child of posterity) {
                             hitinfo.sheet.setRowVisible(tree.nodes.indexOf(child), child.visible, hitinfo.sheetArea);
                         }
+                        console.log(new Date() - time);
                     });
                     hitinfo.sheet.repaint();
                 }

+ 7 - 0
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -621,12 +621,19 @@ const SpreadJsObj = {
                             SpreadJsObj.reLoadRowData(hitinfo.sheet, hitinfo.row + 1, children.length);
                         });
                     } else {
+                        const time = new Date();
                         tree.setExpanded(node, !node.expanded);
+                        console.log(node.code + ':calc');
+                        console.log(new Date() - time);
+
                         SpreadJsObj.massOperationSheet(hitinfo.sheet, function () {
                             const posterity = tree.getPosterity(node);
+                            const time = new Date();
                             for (const child of posterity) {
                                 hitinfo.sheet.setRowVisible(tree.nodes.indexOf(child), child.visible, hitinfo.sheetArea);
                             }
+                            console.log(node.code + ':refreshView');
+                            console.log(new Date() - time);
                         });
                         hitinfo.sheet.repaint();
                     }

+ 12 - 3
app/router.js

@@ -75,8 +75,10 @@ module.exports = app => {
     app.post('/tender/delete', sessionAuth, datetimeFill, 'tenderController.delete');
     app.post('/tender/rule', sessionAuth, 'tenderController.rule');
 
-    // 中间计量管理相关
-    app.get('/measure/work', sessionAuth, tenderSelect, 'measureController.work');
+    // 中间计量 - 计量编制相关
+    app.get('/measure/wlist', sessionAuth, tenderSelect, 'measureController.list');
+
+    app.get('/measure/work/:mid', sessionAuth, tenderSelect, 'measureController.work');
     app.post('/measure/newCode', sessionAuth, 'measureController.newCode');
     app.post('/measure/add', sessionAuth, 'measureController.addMeasure');
     app.post('/measure/search', sessionAuth, 'measureController.search');
@@ -84,7 +86,14 @@ module.exports = app => {
     app.post('/measure/bills', sessionAuth, 'measureController.bills');
     app.post('/measure/detail', sessionAuth, 'measureController.measureDetail');
     app.post('/measure/billsUpdate', sessionAuth, 'measureController.billsUpdate');
-    app.get('/measure/list', sessionAuth, 'measureController.list');
+
+    // 中间计量 - 计量审批相关
+    app.get('/measure/alist', sessionAuth, tenderSelect, 'measureAuditController.list');
+    app.get('/measure/audit/:mid', sessionAuth, 'measureAuditController.index');
+    app.post('/measure/audit/add', sessionAuth, 'measureAuditController.add');
+    app.post('/measure/audit/remove', sessionAuth, 'measureAuditController.remove');
+    app.post('/measure/audit/start', sessionAuth, 'measureAuditController.start');
+    app.post('/measure/audit/check', sessionAuth, 'measureAuditController.check');
 
     // 期计量管理相关
     app.get('/stage', sessionAuth, 'stageController.index');

+ 9 - 1
app/service/measure.js

@@ -30,7 +30,7 @@ module.exports = app => {
          * @param stage - 所属期
          * @returns {Promise<void>}
          */
-        async add(tenderId, code, date, stage) {
+        async add(tenderId, code, userId, date, stage) {
             const count = await this.ctx.service.measure.count({
                 tender_id: tenderId, code: code,
             });
@@ -40,6 +40,7 @@ module.exports = app => {
                     mid: this.uuid.v4(),
                     code: code,
                     in_time: new Date(),
+                    userId: userId,
                 };
                 const result = await this.ctx.service.measure.db.insert(this.tableName, newData);
                 if (result.affectedRow === 0) {
@@ -50,6 +51,13 @@ module.exports = app => {
             }
 
         }
+
+        async joinMeasure(tenderId, audit_id) {
+            const sql = 'SELECT M.* FROM ?? As M, ?? As MA ' +
+                ' WHERE M.`tender_id` = ? and MA.`audit_id` = ? and M.times = MA.times and MA.`order` > 0';
+            const sqlParam = [this.tableName, this.ctx.service.measureAudit.tableName, tenderId, audit_id];
+            return await this.db.query(sql, sqlParam);
+        }
     }
 
     return Measure;

+ 335 - 0
app/service/measure_audit.js

@@ -0,0 +1,335 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2018/7/16
+ * @version
+ */
+
+const auditConst = require('../const/audit');
+
+module.exports = app => {
+    class MeasureAudit extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'measure_audit';
+        }
+
+        /**
+         * 获取 中间计量 审核人信息
+         *
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} auditorId - 审核人id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<*>}
+         */
+        async getAuditor(mid, auditorId, times = 1) {
+            const sql = 'SELECT ma.*, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone` ' +
+                'FROM ?? AS ma, ?? AS pa ' +
+                'WHERE ma.`mid` = ? and ma.`audit_id` = ? and ma.`times` = ?' +
+                '    and ma.`audit_id` = pa.`id`';
+            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, mid, auditorId, times];
+            return await this.db.queryOne(sql, sqlParam);
+        }
+
+        /**
+         * 获取 中间计量 审核人列表信息
+         *
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<*>}
+         */
+        async getAuditors(mid, times = 1) {
+            const sql = 'SELECT ma.*, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone` ' +
+                'FROM ?? AS ma, ?? AS pa ' +
+                'WHERE ma.`mid` = ? and ma.`times` = ?' +
+                '    and ma.`audit_id` = pa.`id` and ma.`order` > 0';
+            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, mid, times];
+            return await this.db.query(sql, sqlParam);
+        }
+
+        /**
+         * 获取 中间计量 当前审核人
+         *
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<*>}
+         */
+        async getCurAuditor(mid, times = 1) {
+            const sql = 'SELECT ma.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, ma.`times`, ma.`order`, ma.`status`, ma.`opinion`, ma.`begin_time`, ma.`end_time` ' +
+                'FROM ?? AS ma, ?? AS pa ' +
+                'WHERE ma.`mid` = ? and ma.`status` = ? and ma.`times` = ?' +
+                '    and ma.`audit_id` = pa.`id`';
+            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, mid, auditConst.status.checking, times];
+            return await this.db.queryOne(sql, sqlParam);
+        }
+
+        /**
+         * 获取 中间计量 最新审核顺序
+         *
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<number>}
+         */
+        async getNewOrder(mid, times = 1) {
+            const sql = 'SELECT Max(??) As max_order FROM ?? Where `mid` = ? and `times` = ? and `order` > 0';
+            const sqlParam = ['order', this.tableName, mid, times];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result && result.max_order ? result.max_order + 1 : 1;
+        }
+
+        /**
+         * 新增审核人
+         *
+         * @param {Number} tenderId - 标段id
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} auditorId - 审核人id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<number>}
+         */
+        async addAuditor(tenderId, mid, auditorId, times = 1) {
+            const newOrder = await this.getNewOrder(mid, times);
+            const data = {
+                tender_id: tenderId,
+                mid: mid,
+                audit_id: auditorId,
+                times: times,
+                order: newOrder,
+                status: auditConst.status.uncheck,
+            };
+            const result = await this.db.insert(this.tableName, data);
+            return result.effectRows = 1;
+        }
+
+        /**
+         * 移除审核人时,同步其后审核人order
+         * @param transaction - 事务
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} auditorId - 审核人id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<*>}
+         * @private
+         */
+        async _syncOrderByDelete(transaction, mid, order, times) {
+            this.initSqlBuilder();
+            this.sqlBuilder.setAndWhere('mid', {
+                value: this.db.escape(mid),
+                operate: '='
+            });
+            this.sqlBuilder.setAndWhere('order', {
+                value: order,
+                operate: '>=',
+            });
+            this.sqlBuilder.setAndWhere('times', {
+                value: times,
+                operate: '=',
+            });
+            this.sqlBuilder.setUpdateData('order', {
+                value: 1,
+                selfOperate: '-',
+            });
+            const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
+            const data = await transaction.query(sql, sqlParam);
+
+            return data;
+        }
+
+        /**
+         * 移除审核人
+         *
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} auditorId - 审核人id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<boolean>}
+         */
+        async deleteAuditor(mid, auditorId, times = 1) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const condition = {mid: mid, audit_id: auditorId, times: times};
+                const auditor = await this.getDataByCondition(condition);
+                if (!auditor) {
+                    throw '该审核人不存在';
+                }
+                await this._syncOrderByDelete(transaction, mid, auditor.order, times);
+                await transaction.delete(this.tableName, condition);
+                await transaction.commit();
+            } catch(err) {
+                await transaction.rollback();
+                throw err;
+            }
+            return true;
+        }
+
+        _sumBills(bills) {
+            const result = {deal: 0, qc: 0};
+            for (const b of bills) {
+                result.deal = result.deal + (b.deal_totalprice ? b.deal_totalprice : 0);
+                result.qc = result.qc + (b.qc_totalprice ? b.qc_totalprice : 0);
+            }
+            return result;
+        }
+        /**
+         * 拷贝原报的历史数据
+         *
+         * @param transacation - 事务
+         * @param {uuid} mid - 中间计量
+         * @param {Number} times - 次数
+         * @returns {Promise<void>}
+         * @private
+         */
+        async _copyReportBillsHistory(transacation, mid, times) {
+            const bills = await this.ctx.service.measureBills.getAllDataByCondition({ where: {mid: mid}});
+            const sum = this._sumBills(bills);
+            const history = await this.getDataByCondition({mid: mid, times: times, order: 0});
+            if (history) {
+                await transacation.update(this.tableName, {
+                    id: history.id,
+                    bills: JSON.stringify(bills),
+                    deal_sum: sum.deal,
+                    qc_sum: sum.qc,
+                });
+            } else {
+                const measure = await this.ctx.service.measure.getDataByCondition({mid: mid});
+                await transacation.insert(this.tableName, {
+                    tender_id: measure.tender_id,
+                    mid: mid,
+                    times: times,
+                    order: 0,
+                    audit_id: measure.user_id,
+                    status: 0,
+                    bills: JSON.stringify(bills),
+                    deal_sum: sum.deal,
+                    qc_sum: sum.qc,
+                });
+            }
+            return sum;
+        }
+        /**
+         * 开始审批
+         *
+         * @param {uuid} mid - 中间计量id
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<boolean>}
+         */
+        async start(mid, times = 1) {
+            const audit = await this.getDataByCondition({mid: mid, times: times, order: 1});
+            if (!audit) {
+                throw '审核人信息错误';
+            }
+
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 记录历史数据
+                const sum = await this._copyReportBillsHistory(transaction, mid, times);
+                // 更新审核人状态
+                await transaction.update(this.tableName, {
+                    id: audit.id,
+                    status: auditConst.status.checking,
+                    begin_time: new Date(),
+                });
+                // 改变中间计量状态
+                await transaction.update(this.ctx.service.measure.tableName, {
+                    times: times,
+                    status: auditConst.status.checking,
+                    deal_sum: sum.deal,
+                    qc_sum: sum.qc,
+                }, {where: {mid: mid}});
+                await transaction.commit();
+            } catch(err) {
+                await transaction.rollback();
+                throw err;
+            }
+            return true;
+        }
+
+        /**
+         * 审批
+         * @param {uuid} mid - 中间计量id
+         * @param {auditConst.status.checked|auditConst.status.checkNo} checkType - 审批结果
+         * @param {Number} times - 第几次审批
+         * @returns {Promise<void>}
+         */
+        async check(mid, checkType, opinion, times = 1) {
+            if (checkType !== auditConst.status.checked && checkType !== auditConst.status.checkNo) {
+                throw '提交数据错误';
+            }
+
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 整理当前流程审核人状态更新
+                const time = new Date();
+                const audit = await this.getDataByCondition({mid: mid, times: times, status: auditConst.status.checking});
+                if (!audit) {
+                    throw '审核数据错误';
+                }
+                // 更新当前审核流程
+                const bills = await this.ctx.service.measureBills.getAllDataByCondition({ where: {mid: mid}});
+                const sum = this._sumBills(bills);
+                await transaction.update(this.tableName, {
+                    id: audit.id,
+                    status: checkType,
+                    opinion: opinion,
+                    end_time: time,
+                    bills: JSON.stringify(bills),
+                    deal_sum: sum.deal,
+                    qc_sum: sum.qc,
+                });
+                const measureTable = this.ctx.service.measure.tableName;
+                if (checkType === auditConst.status.checked) {
+                    const nextAudit = await this.getDataByCondition({mid: mid, times: times, order: audit.order + 1});
+                    // 无下一审核人表示,审核结束
+                    if (nextAudit) {
+                        await transaction.update(this.tableName, {id: nextAudit.id, status: auditConst.status.checking, begin_time: time});
+                        await transaction.update(measureTable, {deal_sum: sum.deal, qc_sum: sum.qc,}, {where: {mid: mid}});
+                    } else {
+                        // 同步标段信息
+                        await transaction.update(measureTable, {status: checkType, deal_sum: sum.deal, qc_sum: sum.qc,}, {where: {mid: mid}});
+                    }
+                } else {
+                    // 同步标段信息
+                    await transaction.update(measureTable, {times: times+1, status: checkType, deal_sum: sum.deal, qc_sum: sum.qc,}, {where: {mid: mid}});
+                    // 拷贝新一次审核流程列表
+                    const auditors = await this.getAllDataByCondition({
+                        where: {mid: mid, times: times},
+                        columns: ['tender_id', 'order', 'audit_id', 'mid']
+                    });
+                    for (const a of auditors) {
+                        a.times = times + 1;
+                        a.status = auditConst.status.uncheck;
+                    }
+                    await transaction.insert(this.tableName, auditors);
+                }
+
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
+         * 获取审核人需要审核的标段列表
+         *
+         * @param auditorId
+         * @returns {Promise<*>}
+         */
+        async getAuditTender(auditorId) {
+            const sql = 'SELECT ma.`audit_id`, ma.`times`, ma.`order`, ma.`begin_time`, t.`id`, t.`name`, t.`project_id`, t.`type`, t.`user_id` ' +
+                'FROM ?? AS ma, ?? AS t ' +
+                'WHERE ma.`audit_id` = ? and ma.`status` = ?' +
+                '    and ma.`tender_id` = t.`id`';
+            const sqlParam = [this.tableName, this.ctx.service.tender.tableName, auditorId, auditConst.status.checking];
+            return await this.db.query(sql, sqlParam);
+        }
+    }
+
+    return MeasureAudit;
+};

+ 1 - 1
app/view/layout/layout.ejs

@@ -70,7 +70,7 @@
         <%- content %>
     </div>
 </div>
-<div class="toast">
+<div class="toast" style="position: absolute; z-index: 9;">
     <i class="icon fa"></i>
     <span class="message"></span>
 </div>

+ 270 - 0
app/view/measure/audit.ejs

@@ -0,0 +1,270 @@
+<div class="panel-content">
+    <div class="panel-title fluid">
+        <div class="title-main d-flex justify-content-between">
+            <div>
+                <div class="d-inline-block mr-3">
+                    <ul class="nav nav-pills m-0">
+                        <li class="nav-item">
+                            <a class="nav-link" href="jiliang-qi.html">返回</a>
+                        </li>
+                        <li class="nav-item">
+                            <a class="nav-link active" href="jiliang-qi-detail.html">计量数据</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="d-inline-block">
+                    <div class="form-check-inline">
+                        <label class="form-check-label">
+                            <input class="form-check-input" type="checkbox">
+                            变更令
+                        </label>
+                    </div>
+                </div>
+            </div>
+            <div>
+                <% if (curAuditor && curAuditor.audit_id === ctx.session.sessionUser.accountId) { %>
+                    <!--审批-->
+                    <a href="#sp-done" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm pull-right">审批通过</a>
+                    <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm pull-right">审批退回</a>
+                <% } else { %>
+                    <% if (measure.status === auditConst.status.checking) { %>
+                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm pull-right">审批中</a>
+                    <% } else if (measure.status === auditConst.status.checkNo) { %>
+                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm pull-right text-muted">审批退回</a>
+                    <% } else if (measure.status === auditConst.status.checked) { %>
+                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm pull-right">审批完成</a>
+                    <% } %>
+                <% } %>
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap row pr-46">
+        <div class="c-header p-0 col-12"></div>
+        <div class="row w-100 sub-content">
+            <div class="c-body col-8">
+                <div class="sjs-height-1" id="billsSpread">
+                </div>
+            </div>
+            <div class="c-body col">
+                <div class="tab-content">
+                    <div id="biangeng" class="tab-pane active">
+                        <div class="sjs-bar row">
+                            <div class="col-auto">
+                                <select class="form-control form-control-sm">
+                                    <option>全部</option>
+                                    <option>可用变更令</option>
+                                    <option>本次计量已用</option>
+                                </select>
+                            </div>
+                        </div>
+                        <div class="sjs-height-3">
+                            <table class="table table-bordered">
+                                <tr><th></th><th>批复编号</th><th>名称</th><th>金额</th><th>已执行(%)</th></tr>
+                            </table>
+                        </div>
+                        <div class="sjs-bottom">
+                            <ul class="nav nav-tabs">
+                                <li class="nav-item">
+                                    <a class="nav-link active" data-toggle="tab" href="#qingdan" role="tab">变更清单</a>
+                                </li>
+                                <li class="nav-item">
+                                    <a class="nav-link" data-toggle="tab" href="#detail" role="tab">变更信息</a>
+                                </li>
+                                <li class="nav-item">
+                                    <a class="nav-link" data-toggle="tab" href="#fujian" role="tab">附件</a>
+                                </li>
+                            </ul>
+                            <div class="tab-content">
+                                <div id="qingdan" class="tab-pane active">
+                                    <div class="sjs-bottom-2">
+                                        <table class="table table-bordered">
+                                            <tr><th>清单编号</th><th>名称</th><th>单位</th><th>单价</th><th>数量</th><th>金额</th><th>已变更</th></tr>
+                                        </table>
+                                    </div>
+                                </div>
+                                <div id="detail" class="tab-pane">
+                                    <div class="sjs-bottom-2">
+                                        <div class="form-group">
+                                            <label>批复编号</label>
+                                            <input class="form-control form-control-sm" value="LZTJ-1标项目部发变更(2015)001号" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>申请编号</label>
+                                            <input class="form-control form-control-sm" value="LZTJ-1标项目部发变更(2015)001号" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>工程名称</label>
+                                            <input class="form-control form-control-sm" value="收费站出口右侧加宽段及K0+532基底换填" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>桩号</label>
+                                            <input class="form-control form-control-sm" value="K0+532" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>原设计图名称</label>
+                                            <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>原图号</label>
+                                            <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>变更设计图名称</label>
+                                            <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>变更图号</label>
+                                            <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>工程变更理由及内容</label>
+                                            <textarea class="form-control form-control-sm" rows="6" readonly>由于K0+532涵洞基底土质天然含水率为25%、收费站出口右侧加宽段K0+120-K0+190段基底土质天然含水率为28.8%。含水率较大形成过湿土,地基松软,无法满足承载力要求。经处项目办、设计、监理、施工单位四方勘察,采用抛石挤淤、砂砾换填以达到地基承载力。
+        												</textarea>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>工程变更合同依据</label>
+                                            <textarea class="form-control form-control-sm" rows="6" readonly></textarea>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>备注</label>
+                                            <textarea class="form-control form-control-sm" rows="3" readonly></textarea>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>变更类型</label>
+                                            <div class="checkbox">
+                                                <label class="checkbox-inline">
+                                                    <input id="inlineCheckbox1" value="option1" checked="" type="checkbox" disabled>A.位置
+                                                </label>
+                                                <!-- <label class="checkbox-inline">
+                                                  <input id="inlineCheckbox2" value="option2" type="checkbox">B.数量
+                                                </label>
+                                                <label class="checkbox-inline">
+                                                  <input id="inlineCheckbox3" value="option3" type="checkbox">C.结构
+                                                </label>
+                                                <label class="checkbox-inline">
+                                                  <input id="inlineCheckbox3" value="option3" checked="" type="checkbox">D.新增
+                                                </label>
+                                                <label class="checkbox-inline">
+                                                  <input id="inlineCheckbox3" value="option3" type="checkbox">E.取消
+                                                </label>
+                                                <label class="checkbox-inline">
+                                                  <input id="inlineCheckbox3" value="option3" type="checkbox">F.纠错
+                                                </label> -->
+                                            </div>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>变更类别 </label>
+                                            <select class="form-control form-control-sm" disabled><option>A类变更(设计变更)</option><option>B类变更(施工措施变)</option><option>C类变更(计划变更)</option><option>D类变更(条件变更)</option><option>E类变更(新增工程)</option></select>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>变更性质 </label>
+                                            <select class="form-control form-control-sm" disabled><option>一般设计变更</option><option>较大设计变更</option><option>重大设计变更</option></select>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>变更提出单位</label>
+                                            <!-- <a href="#editcompany" style="float:right;" class="" data-toggle="modal">编辑</a> -->
+                                            <select class="form-control form-control-sm" disabled><option>AA公司</option><option>BB公司</option></select>
+                                        </div>
+                                        <div class="form-group">
+                                            <label>费用承担方</label>
+                                            <div class="radio">
+                                                <label class="radio-inline">
+                                                    <input id="inlineCheckbox1" value="option1" checked="" type="radio" disabled> 业主
+                                                </label>
+                                                <!-- <label class="radio-inline">
+                                                  <input id="inlineCheckbox2" value="option2" type="radio"> 承包人
+                                                </label> -->
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div id="fujian" class="tab-pane">
+                                    <table class="table table-bordered">
+                                        <tr><th>名称</th><th>上传者</th></tr>
+                                        <tr><td><a href="">合同段工程变更现场办公会议纪要的通知.rar</a></td><th>张三</th></tr>
+                                    </table>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div id="jlbiao" class="tab-pane">
+                        <div class="sjs-bar row">
+                            <div class="col-auto"><a href="#" class="btn btn-outline-primary btn-sm">自动生成</a></div>
+                            <div class="col">
+                                <div class="input-group input-group-sm">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text" id="basic-addon3">表号前缀</span>
+                                    </div>
+                                    <input type="text" class="form-control" id="basic-url" aria-describedby="basic-addon3">
+                                </div>
+                            </div>
+                        </div>
+                        <div class="sjs-height-3">
+                            <table class="table table-bordered">
+                                <tr><th>编号</th><th>中间计量表号</th><th>交工证书/凭证表</th></tr>
+                            </table>
+                        </div>
+                        <div class="sjs-bottom">
+                            <div class="form-group">
+                                <label>变更令号:</label>
+                                <input class="form-control form-control-sm" type="text">
+                            </div>
+                            <div class="form-group">
+                                <label>部位:</label>
+                                <input class="form-control form-control-sm" type="text">
+                            </div>
+                            <div class="form-group">
+                                <label>起始桩号:</label>
+                                <input class="form-control form-control-sm" type="text">
+                            </div>
+                            <div class="form-group">
+                                <label>分部分项工程:</label>
+                                <input class="form-control form-control-sm" type="text">
+                            </div>
+                            <div class="form-group">
+                                <label>计量单元:</label>
+                                <input class="form-control form-control-sm" type="text">
+                            </div>
+                            <div class="form-group">
+                                <label>图号:</label>
+                                <input class="form-control form-control-sm" type="text">
+                            </div>
+                            <div class="form-group">
+                                <label>计算式说明:</label>
+                                <textarea class="form-control"></textarea>
+                            </div>
+                            <div class="form-group">
+                                <a href="#edit-img" data-toggle="modal" data-target="#edit-img"  class="pull-right">添加草图</a>
+                                <label>计算草图:</label>
+                                <p class="form-control"><img src="img/sketch/2.png" class="d-100"></p>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="side-menu">
+            <!--右侧菜单-->
+            <ul class="nav flex-column right-nav">
+                <li class="nav-item">
+                    <a class="nav-link active" data-toggle="tab" href="#biangeng" role="tab">变更令</a>
+                </li>
+                <li class="nav-item">
+                    <a class="nav-link" data-toggle="tab" href="#jlbiao" role="tab">中间计量表</a>
+                </li>
+            </ul>
+        </div>
+    </div>
+</div>
+<script>
+    const measureSpreadSetting = JSON.parse('<%- measureSpreadSetting %>');
+    const billsData = JSON.parse('<%- billsData %>');
+</script>
+<script src="/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
+<script>
+    GC.Spread.Sheets.LicenseKey = "559432293813965#A0y3iTOzEDOzkjMyMDN9UTNiojIklkI1pjIEJCLi4TPB9mM5AFNTd4cvZ7SaJUVy3CWKtWYXx4VVhjMpp7dYNGdx2ia9sEVlZGOTh7NRlTUwkWR9wEV4gmbjBDZ4ElR8N7cGdHVvEWVBtCOwIGW0ZmeYVWVr3mI0IyUiwCMzETN8kzNzYTM0IicfJye&Qf35VfiEzRwEkI0IyQiwiIwEjL6ByUKBCZhVmcwNlI0IiTis7W0ICZyBlIsIyNyMzM5ADI5ADNwcTMwIjI0ICdyNkIsIibj9SbvNmL4N7bjRnch56ciojIz5GRiwiI8+Y9sWY9QmZ0Jyp96uL9v6L0wap9biY9qiq95q197Wr9g+89iojIh94Wiqi";
+</script>
+<script src="/public/js/spreadjs_rela/spreadjs_zh<%= min %>.js"></script>
+<script src="/public/js/spreadjs_rela/extend_celltype.js"></script>
+<script src="/public/js/path_tree<%= min %>.js"></script>
+<script src="/public/js/measure_audit.js"></script>

+ 109 - 0
app/view/measure/audit_modal.ejs

@@ -0,0 +1,109 @@
+<% if (curAuditor && curAuditor.audit_id === ctx.session.sessionUser.accountId) { %>
+<!--审批通过-->
+<div class="modal fade" id="sp-done" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/measure/audit/check" method="post">
+            <div class="modal-header">
+                <h5 class="modal-title">审批通过</h5>
+            </div>
+            <div class="modal-body">
+                <div class="card mt-3">
+                    <ul class="list-group list-group-flush">
+                        <% for (let i = 0, iLen = auditors.length; i < iLen; i++) { %>
+                        <li class="list-group-item" auditorId="<%- auditors[i].audit_id %>">
+                            <% if (auditors[i].status !== auditConst.status.uncheck) { %>
+                            <span class="<%- auditConst.statusClass[auditors[i].status] %> pull-right"><%- auditConst.statusString[auditors[i].status] %></span>
+                            <% } %>
+                            <h5 class="card-title"><%- auditors[i].audit_order %> <%- auditors[i].name %> <small class="text-muted"><%- auditors[i].role %></small></h5>
+                            <% if (auditors[i].status === auditConst.status.checked) { %>
+                            <p class="card-text"><%- auditors[i].opinion %> <%- auditors[i].end_time ? auditors[i].end_time.toLocaleString() : '' %></p>
+                            <% } else if (auditors[i].status === auditConst.status.checking) { %>
+                            <div class="form-group">
+                                <label>审批意见<b class="text-danger">*</b></label>
+                                <textarea class="form-control" name="opinion"></textarea>
+                            </div>
+                            <% } %>
+                        </li>
+                        <% } %>
+                    </ul>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
+                <input type="hidden" name="mid" value="<%- measure.mid %>" />
+                <input type="hidden" name="checkType" value="<%= auditConst.status.checked %>" />
+                <button type="submit" class="btn btn-success" >确认通过</button>
+            </div>
+        </form>
+    </div>
+</div>
+<!--审批退回-->
+<div class="modal fade" id="sp-back" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/measure/audit/check" method="post">
+            <div class="modal-header">
+                <h5 class="modal-title">审批退回</h5>
+            </div>
+            <div class="modal-body">
+                <div class="card mt-3">
+                    <ul class="list-group list-group-flush">
+                        <% for (let i = 0, iLen = auditors.length; i < iLen; i++) { %>
+                        <li class="list-group-item" auditorId="<%- auditors[i].audit_id %>">
+                            <% if (auditors[i].status !== auditConst.status.uncheck) { %>
+                            <span class="<%- auditConst.statusClass[auditors[i].status] %> pull-right"><%- auditConst.statusString[auditors[i].status] %></span>
+                            <% } %>
+                            <h5 class="card-title"><%- auditors[i].audit_order %> <%- auditors[i].name %> <small class="text-muted"><%- auditors[i].role %></small></h5>
+                            <% if (auditors[i].status === auditConst.status.checked) { %>
+                            <p class="card-text"><%- auditors[i].opinion %> <%- auditors[i].end_time ? auditors[i].end_time.toLocaleString() : '' %></p>
+                            <% } else if (auditors[i].status === auditConst.status.checking) { %>
+                            <div class="form-group">
+                                <label>审批意见<b class="text-danger">*</b></label>
+                                <textarea class="form-control" name="opinion"></textarea>
+                            </div>
+                            <% } %>
+                        </li>
+                        <% } %>
+                    </ul>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
+                <input type="hidden" name="mid" value="<%- measure.mid %>" />
+                <input type="hidden" name="checkType" value="<%= auditConst.status.checkNo %>" />
+                <button type="submit" class="btn btn-warning" >确认退回</button>
+            </div>
+        </form>
+    </div>
+</div>
+<% } else { %>
+<!--审批流程/结果-->
+<div class="modal fade" id="sp-list" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">审批流程</h5>
+            </div>
+            <div class="modal-body">
+                <div class="card mt-3">
+                    <ul class="list-group list-group-flush">
+                        <% for (let i = 0, iLen = auditors.length; i < iLen; i++) { %>
+                        <li class="list-group-item" auditorId="<%- auditors[i].audit_id %>">
+                            <% if (auditors[i].status !== auditConst.status.uncheck) { %>
+                            <span class="<%- auditConst.statusClass[auditors[i].status] %> pull-right"><%- auditConst.statusString[auditors[i].status] %></span>
+                            <% } %>
+                            <h5 class="card-title"><%- auditors[i].audit_order %> <%- auditors[i].name %> <small class="text-muted"><%- auditors[i].role %></small></h5>
+                            <p class="card-text"><%- auditors[i].opinion %> <%- auditors[i].end_time ? auditors[i].end_time.toLocaleString() : '' %></p>
+                        </li>
+                        <% } %>
+                    </ul>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+<% } %>

+ 20 - 4
app/view/measure/list.ejs

@@ -20,10 +20,26 @@
                     <tr><th>计量编号</th><th>计量金额</th><th>计量月份</th><th>所属计量期</th><th>状态</th><th>当前处理人</th></tr>
                     </thead>
                     <tbody>
-                    <tr><td><a href="jiliang-approval.html">WWUJ-2-201710</a></td><td>34234234.00</td><td>201710</td><td>第 15 期</td><td><span class="text-muted">待上报</span></td><td>监理-张三</td></tr>
-                    <tr><td><a href="jiliang-approval.html">WWUJ-2-201710</a></td><td>34234234.00</td><td>201710</td><td>第 15 期</td><td><span class="text-warning">审批中</span></td><td>监理-张三</td></tr>
-                    <tr><td><a href="jiliang-approval.html">WWUJ-2-201710</a></td><td>34234234.00</td><td>201710</td><td>第 15 期</td><td><a href="jiliang-approval.html" class="btn-primary btn-sm">审批</a></td><td>监理-张三</td></tr>
-                    <tr><td><a href="jiliang-approval.html">WWUJ-2-201709</a></td><td>34234234.00</td><td>201710</td><td>第 14 期</td><td><span class="text-success">审批完成</span></td><td>业主-王五</td></tr>
+                    <% for (const w of works) { %>
+                        <tr>
+                            <td><a href="/measure/audit/<%- w.mid %>"><%- w.code %></a></td>
+                            <td class="text-right"><%- (w.deal_sum + w.qc_sum).toFixed(2) %></td>
+                            <td><%- w.in_time_str %></td>
+                            <td><%- w.sid %></td>
+                            <td>
+                                <% if (w.curAuditor && w.curAuditor.audit_id === ctx.session.sessionUser.accountId) { %>
+                                    <a href="/measure/audit/<%- w.mid %>" class="btn-primary btn-sm">审批</a>
+                                <% } else {%>
+                                    <span class="<%- auditConst.statusClass[w.status] %>"><%- auditConst.statusString[w.status] %></span>
+                                <% } %>
+                            </td>
+                            <td>
+                                <% if (w.curAuditor) { %>
+                                <%- w.curAuditor.role %>-<%- w.curAuditor.name %>
+                                <% } %>
+                            </td>
+                        </tr>
+                    <% } %>
                     </tbody>
                 </table>
             </div>

+ 119 - 0
app/view/measure/wlist.ejs

@@ -0,0 +1,119 @@
+<div class="panel-content">
+    <div class="panel-title fluid">
+        <div class="title-main d-flex justify-content-between">
+            <div>
+                <div class="btn-group" role="group" aria-label="Basic example">
+                    <button type="button" class="btn btn-secondary btn-sm">全部</button>
+                    <button type="button" class="btn btn-outline-secondary btn-sm">待上报</button>
+                    <button type="button" class="btn btn-outline-secondary btn-sm">审批中</button>
+                    <button type="button" class="btn btn-outline-secondary btn-sm">待审批</button>
+                    <button type="button" class="btn btn-outline-secondary btn-sm">审批完成</button>
+                </div>
+                <div class="btn-group dropdown">
+                    <button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" data-toggle="dropdown"><i class="fa fa-filter"></i> 筛选</button>
+                    <div class="dropdown-menu">
+                        <form class="px-3">
+                            <div class="form-group">
+                                <select class="form-control form-control-sm">
+                                    <option>计量年份</option>
+                                    <option>2018</option>
+                                    <option>2017</option>
+                                    <option>2016</option>
+                                </select>
+                            </div>
+                            <div class="form-group">
+                                <select class="form-control form-control-sm">
+                                    <option>计量月份</option>
+                                    <option>1月</option>
+                                    <option>2月</option>
+                                    <option>3月</option>
+                                    <option>4月</option>
+                                    <option>5月</option>
+                                    <option>6月</option>
+                                    <option>7月</option>
+                                    <option>8月</option>
+                                    <option>9月</option>
+                                    <option>10月</option>
+                                    <option>11月</option>
+                                    <option>12月</option>
+                                </select>
+                            </div>
+                            <div class="form-group">
+                                <select class="form-control form-control-sm">
+                                    <option>计量期</option>
+                                    <option>14期</option>
+                                    <option>13期</option>
+                                    <option>12期</option>
+                                    <option>11期</option>
+                                    <option>10期</option>
+                                    <option>9期</option>
+                                    <option>8期</option>
+                                    <option>7期</option>
+                                    <option>6期</option>
+                                    <option>5期</option>
+                                    <option>4期</option>
+                                    <option>3期</option>
+                                    <option>2期</option>
+                                    <option>1期</option>
+                                </select>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+            <div>
+                <div class="btn-group">
+                    <a href="#add-mj" data-toggle="modal" data-target="#add-mj" class="btn btn-primary btn-sm">添加中间计量</a>
+                </div>
+                <div class="btn-group">
+                    <a href="#setting" data-toggle="modal" data-target="#setting" class="btn btn-outline-primary btn-sm"><i class="fa fa-cog"></i></a>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header p-0 col-12">
+        </div>
+        <div class="c-body">
+            <div class="tab-content">
+                <table class="table table-bordered">
+                    <thead>
+                    <tr><th>计量编号</th><th>计量金额</th><th>计量月份</th><th>所属计量期</th><th>状态</th><th>当前处理人</th><th width="90"></th></tr>
+                    </thead>
+                    <tbody id="wlist">
+                    <% for (const w of works) { %>
+                    <tr>
+                        <td><a href="/measure/work/<%- w.mid %>"><%- w.code %></a></td>
+                        <td class="text-right"><%- (w.deal_sum + w.qc_sum).toFixed(2) %></td>
+                        <td><%- w.in_time_str %></td>
+                        <td><%- w.sid %></td>
+                        <td>
+                            <% if (w.curAuditor && w.curAuditor.audit_id === ctx.session.sessionUser.accountId) { %>
+                            <a href="/measure/audit/<%- w.mid %>" class="btn-primary btn-sm">审批</a>
+                            <% } else { %>
+                            <span class="<%- auditConst.statusClass[w.status] %>"><%- auditConst.statusString[w.status] %></span>
+                            <% } %>
+                        </td>
+                        <td>
+                            <% if (w.curAuditor) { %>
+                            <%- w.curAuditor.role %>-<%- w.curAuditor.name %>
+                            <% } %>
+                        </td>
+                        <td>
+                            <% if (w.status === auditConst.status.uncheck) { %>\
+                            <a href="#edit" data-toggle="modal" data-target="#edit" class="btn btn-outline-primary btn-sm">编辑</a>
+                            <% } %>
+                        </td>
+                    </tr>
+                    <% } %>
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const userId = <%- ctx.session.sessionUser.accountId%>;
+    const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
+</script>
+<script src="/public/js/measure_wlist.js"></script>

+ 239 - 0
app/view/measure/wlist_modal.ejs

@@ -0,0 +1,239 @@
+<!--弹出添加中间计量-->
+<div class="modal fade" id="add-mj" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">添加中间计量</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>中间计量编号<b class="text-danger">*</b></label>
+                    <div class="input-group">
+                        <input type="text" class="form-control" placeholder="请输入中间计量编号" value="WJQR1-201711" id="mj-code">
+                        <div class="input-group-append">
+                            <button class="btn btn-outline-secondary" type="button" title="自动编号" id="autoCode"><i class="fa fa-repeat"></i></button>
+                        </div>
+                        <div class="invalid-feedback" style="display: none" id="mj-Hint">您输入的编号已存在</div>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>计量月份</label>
+                    <input data-view="months" data-min-view="months" class="datepicker-here form-control" placeholder="按时间筛选" type="text" data-date-format="yyyy MM " data-language="zh" id="mj-date">
+                </div>
+                <div class="form-group">
+                    <label>计量期</label>
+                    <select class="form-control">
+                        <option disabled>选填</option>
+                    </select>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal" id="addCancel">关闭</button>
+                <button type="button" class="btn btn-primary" id="addOk">添加</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!--计量编号规则设置-->
+<div class="modal fade" id="setting" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">中间计量设置</h5>
+            </div>
+            <div class="modal-body">
+                <ul class="nav nav-tabs mb-3" role="tablist">
+                    <li class="nav-item">
+                        <a class="nav-link active" data-toggle="tab" href="#profile" role="tab">信息设置</a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" data-toggle="tab" href="#rule" role="tab">编号规则</a>
+                    </li>
+                </ul>
+                <div class="tab-content" >
+                    <div class="tab-pane fade show active" id="profile" role="tabpanel">
+                        <div class="form-group">
+                            <label>中间计量编号<b class="text-danger">*</b></label>
+                            <div class="input-group">
+                                <input type="text" class="form-control" placeholder="请输入中间计量编号" value="WJQR1-201711">
+                                <div class="input-group-append">
+                                    <button class="btn btn-outline-secondary" type="button" title="自动编号"><i class="fa fa-repeat"></i></button>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="form-group">
+                            <label>计量月份</label>
+                            <input data-view="months" data-min-view="months" class="datepicker-here form-control" placeholder="按时间筛选" type="text" data-date-format="yyyy MM " data-language="zh">
+                        </div>
+                        <div class="form-group">
+                            <label>计量期</label>
+                            <select class="form-control">
+                                <option>选填</option>
+                                <option>15</option>
+                                <option>14</option>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="tab-pane fade" id="rule" role="tabpanel">
+                        <h5 id="preview">
+                            当前规则:
+                            <% if (codeRule && codeRule instanceof Array) { %>
+                            <% const preview = []; %>
+                            <% for (const rule of codeRule) { %>
+                            <% preview.push(rule.preview); %>
+                            <% } %>
+                            <%- preview.join(''); %>
+                            <% } %>
+                        </h5>
+                        <h5 id="ruleParts">
+                            <% if (codeRule && codeRule instanceof Array) { %>
+                            <% for (const rule of codeRule) { %>
+                            <span class="badge badge-light" title="<%- ruleConst.ruleString[rule.rule_type]%>">
+                                        <span><%- rule.preview %></span>
+                                        <a href="javascript: void(0);" class="text-danger" title="移除"><i class="fa fa-remove"></i></a>
+                                    </span>
+                            <% } %>
+                            <% } %>
+                        </h5>
+                        <h5>添加新规则组件</h5>
+                        <div class="form-group">
+                            <select class="form-control">
+                                <option disabled selected>请选择组件</option>
+                                <% for (const index in ruleConst.ruleString) { %>
+                                <option value="<%- index %>"><%- ruleConst.ruleString[index] %></option>
+                                <% } %>
+                            </select>
+                        </div>
+                        <div class="form-group" id="format" style="display: none">
+                            <label>自动编号位数</label>
+                            <input min="3" class="form-control" step="1" max="6" value="3" type="number">
+                        </div>
+                        <div class="form-group" id="text" style="display: none">
+                            <label>起始编号</label>
+                            <input class="form-control" value="001" type="text">
+                        </div>
+                        <button class="btn btn-primary" id="addRule">添加组件</button>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer d-flex justify-content-between">
+                <div>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" class="btn btn-primary">确定</button>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<!--编辑中间计量-->
+<div class="modal fade" id="edit" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">编辑中间计量</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>中间计量编号<b class="text-danger">*</b></label>
+                    <div class="input-group">
+                        <input type="text" class="form-control" placeholder="请输入中间计量编号" value="WJQR1-201711">
+                        <div class="input-group-append">
+                            <button class="btn btn-outline-secondary" type="button" title="自动编号"><i class="fa fa-repeat"></i></button>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>计量月份</label>
+                    <input data-view="months" data-min-view="months" class="datepicker-here form-control" placeholder="按时间筛选" type="text" data-date-format="yyyy MM " data-language="zh">
+                </div>
+            </div>
+            <div class="modal-footer d-flex justify-content-between">
+                <a href="#del" data-toggle="modal" data-target="#del" class="btn btn-outline-danger btn-sm pull-right">删除 WJQR1-201710</a>
+                <div>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" class="btn btn-primary">确定</button>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<!--首次使用-->
+<div class="modal" id="first">
+    <div class="modal-dialog" role="document" >
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">设置中间计量编号规则</h5>
+            </div>
+            <div class="modal-body">
+                <h5 >
+                    当前规则:
+                    <span id="preview">
+                        <% if (codeRule && codeRule instanceof Array) { %>
+                        <% const preview = []; %>
+                        <% for (const rule of codeRule) { %>
+                        <% preview.push(rule.preview); %>
+                        <% } %>
+                        <%- preview.join(''); %>
+                        <% } %>
+                    </span>
+                </h5>
+                <h5 id="ruleParts">
+                    <% if (codeRule && codeRule instanceof Array) { %>
+                    <% for (const rule of codeRule) { %>
+                    <span class="badge badge-light" title="<%- ruleConst.ruleString[rule.rule_type]%>">
+                            <span>
+                                <%- rule.preview %>
+                            </span>
+                            <a href="javascript: void(0);" class="text-danger" title="移除"><i class="fa fa-remove"></i></a>
+                        </span>
+                    <% } %>
+                    <% } %>
+                </h5>
+                <h5>添加新规则组件</h5>
+                <div class="form-group">
+                    <select class="form-control">
+                        <option disabled selected>请选择组件</option>
+                        <% for (const index in ruleConst.ruleString) { %>
+                        <option value="<%- index %>"><%- ruleConst.ruleString[index] %></option>
+                        <% } %>
+                    </select>
+                </div>
+                <div class="form-group" id="format" style="display: none">
+                    <label>自动编号位数</label>
+                    <input min="3" class="form-control" step="1" max="6" value="3" type="number">
+                </div>
+                <div class="form-group" id="text" style="display: none">
+                    <label>起始编号</label>
+                    <input class="form-control" value="001" type="text">
+                </div>
+                <button class="btn btn-primary" id="addRule">添加组件</button>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <button class="btn btn-primary" id="setRule">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!--删除-->
+<div class="modal fade" id="del" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-body">
+                <h5>确认删除 WJQR1-201710 ?</h5>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-danger" >确认删除</button>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const ruleType = <%- ruleType %>;
+    const ruleConst = JSON.parse('<%- JSON.stringify(ruleConst) %>');
+    let codeRule = JSON.parse('<%- JSON.stringify(codeRule) %>');
+</script>
+<script src="/public/js/moment/moment.min.js"></script>
+<script src="/public/js/datepicker/datepicker.min.js"></script>
+<script src="/public/js/datepicker/datepicker.zh.js"></script>

+ 9 - 32
app/view/measure/work.ejs

@@ -2,42 +2,17 @@
     <div class="panel-title fluid">
         <div class="title-main d-flex justify-content-between">
             <div>
-                <div class="btn-group">
-                    <a href="#add-mj" data-toggle="modal" data-target="#add-mj" class="btn btn-primary btn-sm">添加中间计量</a>
-                </div>
-                <div class="btn-group">
-                    <select class="form-control form-control-sm mt-0" id="measures">
-                        <% for (const measure of measures) { %>
-                        <option value="<%- measure.mid %>"><%- measure.code %></option>
-                        <% } %>
-                    </select>
-                </div>
-                <div class="btn-group">
-                    <a href="#setting" data-toggle="modal" data-target="#setting" class="btn btn-outline-primary btn-sm"><i class="fa fa-cog"></i></a>
-                </div>
-                <div class="btn-group">
-                    <div class="form-check-inline">
-                        <label class="form-check-label">
-                            <input class="form-check-input" type="checkbox">
-                            审批过程
-                        </label>
-                    </div>
-                    <div class="form-check-inline">
-                        <label class="form-check-label">
-                            <input class="form-check-input" type="checkbox">
-                            变更令
-                        </label>
-                    </div>
-                </div>
+                <a href="/measure/wlist" class="btn btn-link btn-sm">返回</a>
                 <div class="btn-group">
                     <a href="javascript: void(0)" class="btn btn-success btn-sm" id="addMeasureBills">添加计量清单</a>
                 </div>
             </div>
-            <div>
-                <a href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm pull-right">上报审批</a>
-                <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-success btn-sm pull-right">审批完成</a>
-                <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm pull-right">审批中</a>
-                <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm pull-right text-muted">审批退回</a>
+            <div id="operate">
+                <!--<a href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm pull-right">上报审批</a>-->
+                <!--<a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-success btn-sm pull-right">审批完成</a>-->
+                <!--<a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm pull-right">审批中</a>-->
+                <!--<a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm pull-right text-muted">审批退回</a>-->
+                <!--<a href="#del" data-toggle="modal" data-target="#del" class="btn btn-outline-danger btn-sm pull-right">删除 WJQR1-201710</a>-->
             </div>
         </div>
     </div>
@@ -262,6 +237,8 @@
 </div>
 <script>
     const measureSpreadSetting = JSON.parse('<%- measureSpreadSetting %>');
+    const userId = <%- ctx.session.sessionUser.accountId%>;
+    const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
 </script>
 <script src="/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
 <script>

+ 33 - 170
app/view/measure/work_modal.ejs

@@ -133,158 +133,6 @@
         </div>
     </div>
 </div>
-<!--首次使用-->
-<div class="modal" id="first">
-    <div class="modal-dialog" role="document" >
-        <div class="modal-content">
-            <div class="modal-header">
-                <h5 class="modal-title">设置中间计量编号规则</h5>
-            </div>
-            <div class="modal-body">
-                <h5 >
-                    当前规则:
-                    <span id="preview">
-                        <% if (codeRule && codeRule instanceof Array) { %>
-                            <% const preview = []; %>
-                            <% for (const rule of codeRule) { %>
-                                <% preview.push(rule.preview); %>
-                            <% } %>
-                            <%- preview.join(''); %>
-                        <% } %>
-                    </span>
-                </h5>
-                <h5 id="ruleParts">
-                    <% if (codeRule && codeRule instanceof Array) { %>
-                        <% for (const rule of codeRule) { %>
-                        <span class="badge badge-light" title="<%- ruleConst.ruleString[rule.rule_type]%>">
-                            <span>
-                                <%- rule.preview %>
-                            </span>
-                            <a href="javascript: void(0);" class="text-danger" title="移除"><i class="fa fa-remove"></i></a>
-                        </span>
-                        <% } %>
-                    <% } %>
-                </h5>
-                <h5>添加新规则组件</h5>
-                <div class="form-group">
-                    <select class="form-control">
-                        <option disabled selected>请选择组件</option>
-                        <% for (const index in ruleConst.ruleString) { %>
-                            <option value="<%- index %>"><%- ruleConst.ruleString[index] %></option>
-                        <% } %>
-                    </select>
-                </div>
-                <div class="form-group" id="format" style="display: none">
-                    <label>自动编号位数</label>
-                    <input min="3" class="form-control" step="1" max="6" value="3" type="number">
-                </div>
-                <div class="form-group" id="text" style="display: none">
-                    <label>起始编号</label>
-                    <input class="form-control" value="001" type="text">
-                </div>
-                <button class="btn btn-primary" id="addRule">添加组件</button>
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                <button class="btn btn-primary" id="setRule">确定</button>
-            </div>
-        </div>
-    </div>
-</div>
-<!--设置-->
-<div class="modal fade" id="setting" data-backdrop="static">
-    <div class="modal-dialog" role="document">
-        <div class="modal-content">
-            <div class="modal-header">
-                <h5 class="modal-title">中间计量设置</h5>
-            </div>
-            <div class="modal-body">
-                <ul class="nav nav-tabs mb-3" role="tablist">
-                    <li class="nav-item">
-                        <a class="nav-link active" data-toggle="tab" href="#profile" role="tab">信息设置</a>
-                    </li>
-                    <li class="nav-item">
-                        <a class="nav-link" data-toggle="tab" href="#rule" role="tab">编号规则</a>
-                    </li>
-                </ul>
-                <div class="tab-content" >
-                    <div class="tab-pane fade show active" id="profile" role="tabpanel">
-                        <div class="form-group">
-                            <label>中间计量编号<b class="text-danger">*</b></label>
-                            <div class="input-group">
-                                <input type="text" class="form-control" placeholder="请输入中间计量编号" value="WJQR1-201711">
-                                <div class="input-group-append">
-                                    <button class="btn btn-outline-secondary" type="button" title="自动编号"><i class="fa fa-repeat"></i></button>
-                                </div>
-                            </div>
-                        </div>
-                        <div class="form-group">
-                            <label>计量月份</label>
-                            <input data-view="months" data-min-view="months" class="datepicker-here form-control" placeholder="按时间筛选" type="text" data-date-format="yyyy MM " data-language="zh">
-                        </div>
-                        <div class="form-group">
-                            <label>计量期</label>
-                            <select class="form-control">
-                                <option>选填</option>
-                                <option>15</option>
-                                <option>14</option>
-                            </select>
-                        </div>
-                    </div>
-                    <div class="tab-pane fade" id="rule" role="tabpanel">
-                        <h5 id="preview">
-                            当前规则:
-                            <% if (codeRule && codeRule instanceof Array) { %>
-                                <% const preview = []; %>
-                                <% for (const rule of codeRule) { %>
-                                    <% preview.push(rule.preview); %>
-                                <% } %>
-                                <%- preview.join(''); %>
-                            <% } %>
-                        </h5>
-                        <h5 id="ruleParts">
-                            <% if (codeRule && codeRule instanceof Array) { %>
-                                <% for (const rule of codeRule) { %>
-                                    <span class="badge badge-light" title="<%- ruleConst.ruleString[rule.rule_type]%>">
-                                        <span>
-                                            <%- rule.preview %>
-                                        </span>
-                                        <a href="javascript: void(0);" class="text-danger" title="移除"><i class="fa fa-remove"></i></a>
-                                    </span>
-                                <% } %>
-                            <% } %>
-                        </h5>
-                        <h5>添加新规则组件</h5>
-                        <div class="form-group">
-                            <select class="form-control">
-                                <option disabled selected>请选择组件</option>
-                                <% for (const index in ruleConst.ruleString) { %>
-                                <option value="<%- index %>"><%- ruleConst.ruleString[index] %></option>
-                                <% } %>
-                            </select>
-                        </div>
-                        <div class="form-group" id="format" style="display: none">
-                            <label>自动编号位数</label>
-                            <input min="3" class="form-control" step="1" max="6" value="3" type="number">
-                        </div>
-                        <div class="form-group" id="text" style="display: none">
-                            <label>起始编号</label>
-                            <input class="form-control" value="001" type="text">
-                        </div>
-                        <button class="btn btn-primary" id="addRule">添加组件</button>
-                    </div>
-                </div>
-            </div>
-            <div class="modal-footer d-flex justify-content-between">
-                <button type="button" class="btn btn-outline-danger text-truncate" style="max-width: 200px;" title="删除 WJQR1-201710">删除 WJQR1-201710</button>
-                <div>
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                    <button type="button" class="btn btn-primary">确定</button>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
 <!--上报审批-->
 <div class="modal fade" id="sub-sp" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -296,16 +144,17 @@
                 <div class="form-group">
                     <label>搜索审批人</label>
                     <div class="input-group">
-                        <input class="form-control" placeholder="请输入姓名进行检索" type="text">
+                        <input class="form-control" placeholder="请输入姓名进行检索" type="text" id="searchName">
                         <div class="input-group-append">
-                            <button class="btn btn-outline-secondary" type="button"><i class="fa fa-search"></i></button>
+                            <button class="btn btn-outline-secondary" type="button" id="searchAccount"><i class="fa fa-search"></i></button>
                         </div>
                     </div>
                 </div>
-                <div class="card border-primary">
+                <div class="card border-primary" id="searchResult" style="display: none">
                     <div class="card-body">
                         <h5 class="card-title">
-                            <a href="#" class="btn btn-primary btn-sm pull-right">添加</a>张三
+                            <a href="javascript: void(0)" class="btn btn-primary btn-sm pull-right" id="addAuditor">添加</a>
+                            <span>张三</span>
                         </h5>
                         <h6 class="card-subtitle mb-2 text-muted">监理</h6>
                         <p class="card-text">XXXXX公司</p>
@@ -315,16 +164,38 @@
                     <div class="card-header">
                         审批流程
                     </div>
-                    <ul class="list-group list-group-flush">
-                        <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a>1 张三  <small class="text-muted">监理</small></li>
-                        <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a>2 王五 <small class="text-muted">监理</small></li>
-                        <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a>3 李四 <small class="text-muted">监理</small></li>
+                    <ul class="list-group list-group-flush" id="auditors">
                     </ul>
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary">确认上报</button>
+                <button type="button" class="btn btn-primary" id="auditStart">确认上报</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!--重新上报-->
+<div class="modal fade" id="sub-sp2" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">重新上报</h5>
+            </div>
+            <div class="modal-body">
+                <div class="alert alert-primary" role="alert" id="re-hint">
+                </div>
+                <div class="card mt-3">
+                    <div class="card-header">
+                        审批流程
+                    </div>
+                    <ul class="list-group list-group-flush" id="re-auditors">
+                    </ul>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-primary" id="auditRestart">确认上报</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
             </div>
         </div>
     </div>
@@ -338,7 +209,7 @@
             </div>
             <div class="modal-body">
                 <div class="card mt-3">
-                    <ul class="list-group list-group-flush">
+                    <ul id="auditList" class="list-group list-group-flush">
                         <li class="list-group-item">
                             <span class="text-success pull-right">审批通过</span>
                             <h5 class="card-title">1 张三 <small class="text-muted">监理</small></h5>
@@ -392,11 +263,3 @@
         </div>
     </div>
 </div>
-<script>
-    const ruleType = <%- ruleType %>;
-    const ruleConst = JSON.parse('<%- JSON.stringify(ruleConst) %>');
-    let codeRule = JSON.parse('<%- JSON.stringify(codeRule) %>');
-</script>
-<script src="/public/js/moment/moment.min.js"></script>
-<script src="/public/js/datepicker/datepicker.min.js"></script>
-<script src="/public/js/datepicker/datepicker.zh.js"></script>

+ 1 - 1
config/config.qa.js

@@ -62,7 +62,7 @@ module.exports = appInfo => {
     };
 
     // 是否压缩替换前端js
-    config.min = true;
+    config.min = false;
 
     return config;
 };

+ 2 - 2
config/menu.js

@@ -70,11 +70,11 @@ const menu = {
         children: {
             middle: {
                 name: '计量编制',
-                url: '/measure/work',
+                url: '/measure/wlist',
             },
             list: {
                 name: '计量审批',
-                url: '/measure/list',
+                url: '/measure/alist',
             }
         },
     },