瀏覽代碼

修改审批流程功能no.1

laiguoran 2 年之前
父節點
當前提交
a7106efad8

+ 26 - 1
app/controller/stage_controller.js

@@ -64,7 +64,7 @@ module.exports = app => {
                 },
                 shenpiConst,
             };
-            if ((ctx.stage.status === auditConst.status.uncheck || ctx.stage.status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === ctx.stage.user_id) {
+            if (((ctx.stage.status === auditConst.status.uncheck || ctx.stage.status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === ctx.stage.user_id) || ctx.session.sessionUser.is_admin) {
                 // data.accountGroup = accountGroup;
                 // 获取所有项目参与者
                 const accountList = await ctx.service.projectAccount.getAllDataByCondition({
@@ -1432,6 +1432,31 @@ module.exports = app => {
             }
         }
 
+        async saveAudit(ctx) {
+            try {
+                if (ctx.stage.revising) {
+                    throw '台账修订中,请勿修改提交期数据';
+                }
+                const data = JSON.parse(ctx.request.body.data);
+                if (ctx.session.sessionUser.is_admin && ctx.stage.status !== auditConst.status.checked) {
+                    await ctx.service.stageAudit.saveAudit(ctx.stage.id, ctx.stage.times, data);
+                    const auditors = await ctx.service.stageAudit.getAuditGroupByListWithOwner(ctx.stage.id, ctx.stage.times);
+                    ctx.body = { err: 0, msg: '', data: auditors };
+                } else {
+                    throw '您无权进行该操作';
+                }
+            } catch (err) {
+                this.log(err);
+                // ctx.session.postError = err.toString();
+                // ctx.redirect(ctx.request.header.referer);
+                ctx.body = {
+                    err: 1,
+                    // url: ctx.request.header.referer,
+                    msg: err,
+                };
+            }
+        }
+
         /**
          * 清单汇总 页面 (Get)
          * @param ctx

+ 1 - 1
app/middleware/stage_check.js

@@ -102,7 +102,7 @@ module.exports = options => {
                     });
                     const preAudit = onAuditor.order !== 1 ? _.find(stage.auditors, { order: onAuditor.order - 1 }) : false;
                     const preAid = preAudit ? (preAudit.status !== status.checkAgain ? preAudit.aid : false) : stage.user_id;// 已发起重审无法撤回
-                    if (onAuditor.aid === preAid && preAudit.status === status.checkCancel) {
+                    if ((onAuditor.aid === preAid && preAudit.status === status.checkCancel) || preAudit.is_old === 1) {
                         stage.cancancel = 0;// 不可以多次撤回
                     } else if (preAid === accountId && preAid !== stage.user_id) {
                         if (preAudit.status === status.checked) {

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

@@ -124,7 +124,7 @@ $('a[data-target="#sp-list" ]').on('click', function () {
                                     <span class="pull-right ${auditConst.statusClass[auditor.status]}">
                                         ${auditor.status !== auditConst.status.uncheck ? auditConst.statusString[auditor.status] : ''}
                                         ${auditor.status === auditConst.status.checkNo ? user.name : ''}
-                                        ${auditor.status === auditConst.status.checkNoPre ? auditors[index+1].name : ''}
+                                        ${auditor.status === auditConst.status.checkNoPre && auditor.sort - 1 > 0 ? _.find(auditors, { sort: auditor.sort - 1 }).name : ''}
                                     </span>
                                 </p>
                                 <p class="text-muted mb-0">${auditor.role}</p>

+ 222 - 2
app/public/js/stage_audit.js

@@ -59,7 +59,7 @@ $(document).ready(function () {
     })
 
     // 添加审批流程按钮逻辑
-    $('.book-list').on('click', 'dt', function () {
+    $('body').on('click', '.book-list dt', function () {
         const idx = $(this).find('.acc-btn').attr('data-groupid')
         const type = $(this).find('.acc-btn').attr('data-type')
         if (type === 'hide') {
@@ -126,7 +126,7 @@ $(document).ready(function () {
     //     $('#account_list').html(account_html);
     // });
     // 添加到审批流程中
-    $('dl').on('click', 'dd', function () {
+    $('#book-list').on('click', 'dd', function () {
         const id = parseInt($(this).data('id'));
         if (id !== 0) {
             postData(getUrlPre() + '/audit/add', { auditorId: id }, (datas) => {
@@ -242,6 +242,226 @@ $(document).ready(function () {
     });
 
 
+    // 管理员更改审批流程js部分
+    let timer2 = null;
+    let oldSearchVal2 = null;
+    $('body').on('input propertychange', '.gr-search', function(e) {
+        oldSearchVal2 = e.target.value;
+        timer2 && clearTimeout(timer2);
+        timer2 = setTimeout(() => {
+            const newVal = $(this).val();
+            const code = $(this).attr('data-code');
+            let html = '';
+            if (newVal && newVal === oldSearchVal2) {
+                accountList.filter(item => item && item.id !== stage_uid && (item.name.indexOf(newVal) !== -1 || (item.mobile && item.mobile.indexOf(newVal) !== -1))).forEach(item => {
+                    html += `<dd class="border-bottom p-2 mb-0 " data-id="${item.id}" >
+                        <p class="mb-0 d-flex"><span class="text-primary">${item.name}</span><span
+                                class="ml-auto">${item.mobile || ''}</span></p>
+                        <span class="text-muted">${item.role || ''}</span>
+                    </dd>`
+                });
+                $('#' + code + '_dropdownMenu .book-list').empty();
+                $('#' + code + '_dropdownMenu .book-list').append(html);
+            } else {
+                if (!$('#' + code + '_dropdownMenu .acc-btn').length) {
+                    accountGroup.forEach((group, idx) => {
+                        if (!group) return;
+                        html += `<dt><a href="javascript: void(0);" class="acc-btn" data-groupid="${idx}" data-type="hide"><i class="fa fa-plus-square"></i>
+                        </a> ${group.groupName}</dt>
+                        <div class="dd-content" data-toggleid="${idx}">`;
+                        group.groupList.forEach(item => {
+                            if (item.id !== stage_uid) {
+                                html += `<dd class="border-bottom p-2 mb-0 " data-id="${item.id}" >
+                                    <p class="mb-0 d-flex"><span class="text-primary">${item.name}</span><span
+                                            class="ml-auto">${item.mobile || ''}</span></p>
+                                    <span class="text-muted">${item.role || ''}</span>
+                                </dd>`;
+                            }
+                        });
+                        html += '</div>';
+                    });
+                    $('#' + code + '_dropdownMenu .book-list').empty();
+                    $('#' + code + '_dropdownMenu .book-list').append(html);
+                }
+            }
+        }, 400);
+    });
+
+    $('body').on('click', '#admin-edit-shenpi dl dd', function () {
+        const id = parseInt($(this).attr('data-id'));
+        if (!id) return;
+
+        let this_aid = parseInt($(this).parents('.book-list').attr('data-aid'));
+        let this_operate = $(this).parents('.book-list').attr('data-operate');
+        const user = _.find(accountList, function (item) {
+            return item.id === id;
+        });
+        const auditorIndex = _.findIndex(auditorList, { aid: id });
+        if (auditorIndex !== -1) {
+            toastr.warning('该审核人已存在,请勿重复添加');
+            return;
+        }
+        const order = parseInt($(this).parents('tr').find('.shenpi-order').text());
+        const curAuditorIndex = _.findIndex(auditorList, { aid: this_aid });
+        const prop = {
+            operate: this_operate,
+            old_aid: this_aid,
+            new_aid: user.id,
+        };
+        postData(getUrlPre() + '/audit/save', prop, (datas) => {
+            if (this_operate === 'add') {
+                const addhtml = '<tr>\n' +
+                    `                                <td><span class="shenpi-order">${order+1}</span> ${user.name} <small class="text-muted">${user.role}</small></td>\n` +
+                    `                                <td style="text-align: center"><span class="">待审批</span></td>\n` +
+                    '                                <td style="text-align: center">\n' +
+                    '                                    <span class="dropdown mr-2">\n' +
+                    `                                    <a href="javascript: void(0)" class="add-audit" id="${user.id}_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>\n` +
+                    makeSelectAudit(user.id+'_add', user.id, 'add') +
+                    '                                        </div>\n' +
+                    '                                    </span>\n' +
+                    '                                    <span class="dropdown mr-2">\n' +
+                    `                                        <a href="javascript: void(0)" class="change-audit" id="${user.id}_change_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">更换</a>\n` +
+                    makeSelectAudit(user.id+'_change', user.id, 'change') +
+                    '                                    </span>\n' +
+                    '                                    <span class="dropdown">\n' +
+                    '                                    <a href="javascript: void(0)" class="text-danger" title="移除" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">移除</a>\n' +
+                    '                                    <div class="dropdown-menu">\n' +
+                    '                                        <span class="dropdown-item">确认移除审批人?</span>\n' +
+                    '                                        <div class="dropdown-divider"></div>\n' +
+                    '                                        <div class="px-2 py-1 text-center">\n' +
+                    `                                            <button class="remove-audit btn btn-sm btn-danger" data-id="${user.id}">移除</button>\n` +
+                    '                                            <button class="btn btn-sm btn-secondary">取消</button>\n' +
+                    '                                        </div>\n' +
+                    '                                    </div>\n' +
+                    '                                    </span>\n' +
+                    '                                </td>\n' +
+                    '                            </tr>';
+                $(this).parents('tr').after(addhtml);
+                auditorList.splice(curAuditorIndex+1, 0, { aid: user.id, company: user.company, name: user.name, role: user.role });
+                updateOrder(user.id);
+            } else if (this_operate === 'change') {
+                const this_user = _.find(auditorList, { aid: this_aid });
+                this_user.aid = user.id;
+                this_user.company = user.company;
+                this_user.role = user.role;
+                this_user.name = user.name;
+                auditorList.splice(curAuditorIndex, 1, this_user);
+                $(this).parents('tr').children('td').eq(0).html(`<span class="shenpi-order">${order}</span> ${user.name} <small class="text-muted">${user.role}</small>`);
+                // 替换所有aid
+                $(this).parents('.book-list').attr('data-aid', user.id);
+                $(this).parents('.dropdown-menu').attr('id', user.id +'_change_dropdownMenu').attr('aria-labelledby', user.id +'_change_dropdownMenuButton');
+                $(this).parents('.dropdown-menu').children('mb-2').children('input').attr('data-code', user.id +'_change');
+                $(this).parents('.dropdown-menu').siblings('.change-audit').attr('id', user.id +'_change_dropdownMenuButton');
+                $(this).parents('td').children('span').eq(0).find('.add-audit').attr('id', user.id +'_add_dropdownMenuButton');
+                $(this).parents('td').children('span').eq(0).find('.dropdown-menu').attr('id', user.id +'_add_dropdownMenu').attr('aria-labelledby', user.id +'_add_dropdownMenuButton');
+                $(this).parents('td').children('span').eq(0).find('.dropdown-menu').children('mb-2').children('input').attr('data-code', user.id +'_add');
+                $(this).parents('td').children('span').eq(0).find('.dropdown-menu').children('.book-list').attr('data-aid', user.id);
+                $(this).parents('td').children('span').eq(2).find('.remove-audit').attr('data-id', user.id);
+            }
+            changeLiucheng(datas);
+        });
+    });
+
+    // 移除审批人
+    $('body').on('click', '.remove-audit', function () {
+        const id = parseInt($(this).attr('data-id'));
+        const prop = {
+            operate: 'del',
+            old_aid: id,
+        };
+        postData(getUrlPre() + '/audit/save', prop, (datas) => {
+            updateOrder(id, 0);
+            const curAuditorIndex = _.findIndex(auditorList, { aid: id });
+            auditorList.splice(curAuditorIndex, 1);
+            $(this).parents('tr').remove();
+            changeLiucheng(datas);
+        });
+    });
+
+    // 比uid大的序号进行调整
+    function updateOrder(aid, num = 1) {
+        console.log('hello');
+        const index = _.findIndex(auditorList, { aid });
+        console.log(index, auditorList.length);
+        for (let i = index;i < auditorList.length; i++) {
+            console.log(i,i+num, auditorList.length);
+            $('#admin-edit-shenpi tbody').children('tr').eq(i).find('.shenpi-order').text(i+num);
+        }
+    }
+
+    function changeLiucheng(datas) {
+        const auditorshtml = [];
+        for (const [index,data] of datas.entries()) {
+            auditorshtml.push('<li class="list-group-item" data-auditorid="' + data.aid + '">');
+            auditorshtml.push('<i class="fa ' + (index+1 === datas.length ? 'fa-stop-circle' : 'fa-chevron-circle-down') + '"></i> ');
+            auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+            if (index === 0) {
+                auditorshtml.push('<span class="pull-right">原报</span>');
+            } else if (index+1 === datas.length) {
+                auditorshtml.push('<span class="pull-right">终审</span>');
+            } else {
+                auditorshtml.push('<span class="pull-right">'+ transFormToChinese(index) +'审</span>');
+            }
+            auditorshtml.push('</li>');
+        }
+        let html = '<li class="timeline-list-item pb-2">\n' +
+            '                                            <div class="timeline-item-date">\n' +
+            '                                                \n' +
+            '                                            </div>\n' +
+            '                                            <div class="timeline-item-icon bg-secondary text-light">\n' +
+            '                                            </div>\n' +
+            '                                            <div class="timeline-item-content">\n' +
+            '                                                <div class="card">\n' +
+            '                                                    <div class="card-body p-3">\n' +
+            '                                                        <div class="card-text">\n' +
+            `                                                            <p class="mb-1"><span class="h5">fuqingqing</span>\n` +
+            '                                                                <span class="pull-right ">\n' +
+            '                                                                    \n' +
+            '                                                                    \n' +
+            '                                                                    \n' +
+            '                                                                </span>\n' +
+            '                                                            </p>\n' +
+            `                                                            <p class="text-muted mb-0">测试角色</p>\n` +
+            '                                                        </div>\n' +
+            '                                                    </div>\n' +
+            '                                                </div>\n' +
+            '                                            </div>\n' +
+            '                                        </li>';
+        $('.auditors-list').html(auditorshtml.join(''));
+
+    }
+
+    // 审批流程-选择审批人html 生成
+    function makeSelectAudit(code, aid, status) {
+        let divhtml = '';
+        accountGroup.forEach((group, idx) => {
+            let didivhtml = '';
+            if(group) {
+                group.groupList.forEach(item => {
+                    didivhtml += item.id !== stage_uid ? '<dd class="border-bottom p-2 mb-0 " data-id="' + item.id + '" >\n' +
+                        '<p class="mb-0 d-flex"><span class="text-primary">' + item.name + '</span><span\n' +
+                        '                                                                                class="ml-auto">' + item.mobile + '</span></p>\n' +
+                        '                                                                    <span class="text-muted">' + item.role + '</span>\n' +
+                        '                                                                    </dd>\n' : '';
+                });
+                divhtml += '<dt><a href="javascript: void(0);" class="acc-btn" data-groupid="' + idx + '" data-type="hide"><i class="fa fa-plus-square"></i></a> ' + group.groupName + '</dt>\n' +
+                    '                                                                <div class="dd-content" data-toggleid="' + idx + '">\n' + didivhtml +
+                    '                                                                </div>\n';
+            }
+        });
+        let html = '<div class="dropdown-menu dropdown-menu-right" id="' + code + '_dropdownMenu" aria-labelledby="' + code + '_dropdownMenuButton" style="width:220px">\n' +
+            '                                                        <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"\n' +
+            '                                                                                     placeholder="姓名/手机 检索" autocomplete="off" data-code="' + code + '"></div>\n' +
+            '                                                        <dl class="list-unstyled book-list" data-aid="'+ aid +'" data-operate="'+ status +'">\n' + divhtml +
+            '                                                        </dl>\n' +
+            '                                                    </div>\n' +
+            '                                                </div>\n' +
+            '                                            </span>\n' +
+            '                                        </span>\n' +
+            '                                        </li>';
+        return html;
+    }
+
 });
 // 检查上报情况
 function checkAuditorFrom () {

+ 77 - 5
app/service/stage_audit.js

@@ -85,7 +85,7 @@ module.exports = app => {
          */
         async getAuditors(stageId, times = 1, order_sort = 'asc') {
             const sql =
-                'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, pa.sign_path, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time`, g.`sort` ' +
+                'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, pa.sign_path, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time`, la.`is_old`, g.`sort` ' +
                 'FROM ?? AS la, ?? AS pa, (SELECT sa.`aid`,(@i:=@i+1) as `sort` FROM (SELECT * FROM ?? WHERE `sid` = ? AND `times` = ? GROUP BY `aid` ORDER BY `order` ASC) sa, (select @i:=0) as it WHERE sa.`sid` = ? AND sa.`times` = ? GROUP BY sa.`aid`) as g ' +
                 'WHERE la.`sid` = ? and la.`times` = ? and la.`aid` = pa.`id` and g.`aid` = la.`aid` order by la.`order` ' +
                 order_sort;
@@ -1395,11 +1395,17 @@ module.exports = app => {
          * @return {Promise<*>}
          */
         async getAuditGroupByList(stageId, times) {
+            // const sql =
+            //     'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`sid`, la.`aid`, la.`order`, la.`status`' +
+            //     '  FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id` ' +
+            //     '  WHERE la.`sid` = ? and la.`times` = ? and la.`is_old` = 0 GROUP BY la.`aid` ORDER BY la.`order`';
+            // const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, stageId, times];
             const sql =
-                'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`sid`, la.`aid`, la.`order` ' +
-                '  FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id` ' +
-                '  WHERE la.`sid` = ? and la.`times` = ? GROUP BY la.`aid` ORDER BY la.`order`';
-            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, stageId, times];
+                'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`sid`, la.`order`, la.`status`' +
+                ' FROM (SELECT `aid`, max(`order`) `order` FROM ?? WHERE `sid` = ? and `times` = ? and `is_old` = ? GROUP BY aid) sa' +
+                ' LEFT JOIN ?? la ON sa.`aid` = la.`aid` AND sa.`order` = la.`order`' +
+                ' Left JOIN ?? AS pa On la.`aid` = pa.`id` WHERE la.`sid` = ? and la.`times` = ? and la.`is_old` = ? order BY la.`order`';
+            const sqlParam = [this.tableName, stageId, times, 0, this.tableName, this.ctx.service.projectAccount.tableName, stageId, times, 0];
             return await this.db.query(sql, sqlParam);
         }
 
@@ -1717,6 +1723,72 @@ module.exports = app => {
             const result = await this.db.queryOne(sql, sqlParam);
             return result ? result.num : 0;
         }
+
+        /**
+         * 删除本次审批流程
+         * @param {Number} stageId - 标段id
+         * @param {Number} times - 第几次审批
+         * @param {Object} data - 更改参数
+         * @return {Promise<void>}
+         */
+        async saveAudit(stageId, times, data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const auditors = await this.getAuditGroupByList(stageId, times);
+                const now_audit = this._.find(auditors, { aid: data.old_aid });
+                console.log(now_audit);
+                if (data.operate === 'add') {
+                    if (now_audit.status !== auditConst.status.uncheck && now_audit.status !== auditConst.status.checking) {
+                        throw '当前人下无法操作新增';
+                    }
+                    const newAudit = {
+                        tid: this.ctx.tender.id,
+                        sid: stageId,
+                        aid: data.new_aid,
+                        order: now_audit.order+1,
+                        times: times,
+                        status: 1
+                    };
+                    // order+1
+                    await this._syncOrderByDelete(transaction, stageId, now_audit.order+1, times, '+');
+                    await transaction.insert(this.tableName, newAudit);
+                    // 更新审批流程页数据,如果存在
+                } else if (data.operate === 'del') {
+                    if (now_audit.status !== auditConst.status.uncheck) {
+                        throw '当前人无法操作删除';
+                    }
+                    await transaction.delete(this.tableName, { sid: stageId, times, aid: now_audit.aid, order: now_audit.order });
+                    await this._syncOrderByDelete(transaction, stageId, now_audit.order, times);
+                    // 旧的更新为is_old为1
+                    await transaction.update(this.tableName, { is_old: 1 }, {
+                        where: {
+                            sid: stageId,
+                            times,
+                            aid: data.old_aid,
+                        }
+                    });
+                } else if (data.operate === 'change') {
+                    const nowAudit = await this.getDataByCondition({ sid: stageId, times, aid: now_audit.aid, order: now_audit.order });
+                    if (now_audit.status !== auditConst.status.uncheck || !nowAudit) {
+                        throw '当前人无法操作替换';
+                    }
+                    nowAudit.aid = data.new_aid;
+                    await transaction.update(this.tableName, nowAudit);
+                    // 旧的更新为is_old为1
+                    await transaction.update(this.tableName, { is_old: 1 }, {
+                        where: {
+                            sid: stageId,
+                            times,
+                            aid: data.old_aid,
+                        }
+                    });
+                }
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
 
     return StageAudit;

+ 164 - 10
app/view/stage/audit_modal.ejs

@@ -17,7 +17,7 @@
                         <div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton" style="width:220px">
                             <div class="mb-2 p-2"><input class="form-control form-control-sm" placeholder="姓名/手机 检索"
                                     id="gr-search" autocomplete="off"></div>
-                            <dl class="list-unstyled book-list">
+                            <dl class="list-unstyled book-list" id="book-list">
                                 <% accountGroup.forEach((group, idx) => { %>
                                 <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
                                         data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
@@ -81,12 +81,12 @@
                 <div class="modal-body">
                     <div class="row">
                         <div class="col-4">
-                            <% if(ctx.stage.status === auditConst.status.checkNo) { %>
-                            <a class="sp-list-item" href="#sub-sp" data-toggle="modal" data-target="#sub-sp"
+                            <% if(ctx.stage.status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+                            <a class="sp-list-item" href="#sub-sp2" data-toggle="modal" data-target="#sub-sp2"
                                 id="hideSp">修改审批流程</a>
                             <% } %>
                             <div class="card mt-3">
-                                <ul class="list-group list-group-flush" id="auditors-list">
+                                <ul class="list-group list-group-flush auditors-list" id="auditors-list">
                                     <% ctx.stage.auditors2.forEach((item, idx) => { %>
                                     <% if (idx === 0) { %>
                                     <li class="list-group-item" data-auditorId="<%- item.aid %>">
@@ -121,7 +121,7 @@
                                 <% } %>
                                 <div class="<%- idx < ctx.stage.auditHistory.length - 1 ? 'fold-card' : '' %>">
                                     <div class="text-center text-muted"><%- idx+1 %>#</div>
-                                    <ul class="timeline-list list-unstyled mt-2">
+                                    <ul class="timeline-list list-unstyled mt-2 <% if (idx === ctx.stage.auditHistory.length - 1 && ctx.stage.auditHistory.length !== 1) { %>last-auditor-list<% } %>">
                                         <% auditors.forEach((auditor, index) => { %>
                                         <% if (index === 0) { %>
                                         <li class="timeline-list-item pb-2">
@@ -267,9 +267,13 @@
                 </div>
                 <div class="modal-body">
                     <div class="row">
+                        <% if(ctx.stage.status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+                            <a class="sp-list-item" href="#sub-sp2" data-toggle="modal" data-target="#sub-sp2"
+                               id="hideSp">修改审批流程</a>
+                        <% } %>
                         <div class="col-4">
                             <div class="card mt-3">
-                                <ul class="list-group list-group-flush">
+                                <ul class="list-group list-group-flush auditors-list">
                                     <% ctx.stage.auditors2.forEach((item, idx) => { %>
                                     <% if (idx === 0) { %>
                                     <li class="list-group-item" data-auditorId="<%- item.aid %>">
@@ -304,7 +308,7 @@
                                 <% } %>
                             <div class="<%- idx < ctx.stage.auditHistory.length - 1 ? 'fold-card' : '' %>">
                                 <div class="text-center text-muted"><%- idx+1 %>#</div>
-                                <ul class="timeline-list list-unstyled mt-2">
+                                <ul class="timeline-list list-unstyled mt-2 <% if (idx === ctx.stage.auditHistory.length - 1 && ctx.stage.auditHistory.length !== 1) { %>last-auditor-list<% } %>">
                                     <% auditors.forEach((auditor, index) => { %>
                                     <% if (index === 0) { %>
                                     <li class="timeline-list-item pb-2">
@@ -457,9 +461,13 @@
                 </div>
                 <div class="modal-body">
                     <div class="row">
+                        <% if(ctx.stage.status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+                            <a class="sp-list-item" href="#sub-sp2" data-toggle="modal" data-target="#sub-sp2"
+                               id="hideSp">修改审批流程</a>
+                        <% } %>
                         <div class="col-4">
                             <div class="card mt-3">
-                                <ul class="list-group list-group-flush">
+                                <ul class="list-group list-group-flush auditors-list">
                                     <% ctx.stage.auditors2.forEach((item, idx) => { %>
                                     <% if (idx === 0) { %>
                                     <li class="list-group-item" data-auditorId="<%- item.aid %>">
@@ -493,7 +501,7 @@
                             <% } %>
                             <div class="<%- idx < ctx.stage.auditHistory.length - 1 ? 'fold-card' : '' %>">
                                 <div class="text-center text-muted"><%- idx+1 %>#</div>
-                                <ul class="timeline-list list-unstyled mt-2">
+                                <ul class="timeline-list list-unstyled mt-2 <% if (idx === ctx.stage.auditHistory.length - 1 && ctx.stage.auditHistory.length !== 1) { %>last-auditor-list<% } %>">
                                     <% auditors.forEach((auditor, index) => { %>
                                     <% if (index === 0) { %>
                                     <li class="timeline-list-item pb-2">
@@ -819,12 +827,158 @@
     </div>
 </div>
 <% } %>
-
+<% if (ctx.stage && ctx.stage.status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+<!--上报审批-->
+<div class="modal fade" id="sub-sp2" data-backdrop="static">
+    <div class="modal-dialog" style="max-width: 650px" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">修改审批流程</h5>
+            </div>
+            <div class="modal-body">
+                <div class="card mt-1">
+                    <div class="modal-height-500" style="overflow: visible">
+                        <style>
+                            #admin-edit-shenpi thead th {
+                                border-bottom: 0;
+                            }
+                            #admin-edit-shenpi td, #admin-edit-shenpi th {
+                                padding: 0.75rem;
+                            }
+                            #admin-edit-shenpi th {
+                                background: none;
+                                color: #212529;
+                                border-top: 0;
+                            }
+                        </style>
+                        <table class="table table-hover" id="admin-edit-shenpi">
+                            <thead>
+                            <tr class="card-header">
+                                <th>审批流程</th>
+                                <th width="80" style="text-align: center">审批状态</th>
+                                <th width="200" style="text-align: center">操作</th>
+                            </tr>
+                            </thead>
+                            <% for (let i = 1, iLen = ctx.stage.auditors2.length; i < iLen; i++) { %>
+                            <tr>
+                                <td><span class="shenpi-order"><%- i %></span> <%- ctx.stage.auditors2[i].name %> <small class="text-muted"><%- ctx.stage.auditors2[i].role %></small></td>
+                                <td style="text-align: center"><span class="<%- auditConst.auditStringClass[ctx.stage.auditors2[i].status] %>"><%- ctx.stage.auditors2[i].status !== auditConst.status.uncheck ? auditConst.auditString[ctx.stage.auditors2[i].status] : '待审批'  %></span></td>
+                                <td style="text-align: center">
+                                    <% if (ctx.stage.auditors2[i].status === auditConst.status.checking) { %>
+                                    <span class="dropdown mr-2">
+                                    <a href="javascript: void(0)" class="add-audit" id="<%- ctx.stage.auditors2[i].aid %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
+                                    <div class="dropdown-menu dropdown-menu-right" id="<%- ctx.stage.auditors2[i].aid %>_add_dropdownMenu" aria-labelledby="<%- ctx.stage.auditors2[i].aid %>_add_dropdownMenuButton" style="width:220px">
+                                        <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"
+                                                                     placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- ctx.stage.auditors2[i].aid %>_add"></div>
+                                        <dl class="list-unstyled book-list" data-aid="<%- ctx.stage.auditors2[i].aid %>" data-operate="add">
+                                            <% accountGroup.forEach((group, idx) => { %>
+                                                <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
+                                                       data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
+                                                <div class="dd-content" data-toggleid="<%- idx %>">
+                                                    <% group.groupList.forEach(item => { %>
+                                                        <% if (item.id !== ctx.stage.user_id) { %>
+                                                            <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>">
+                                                                <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
+                                                                            class="ml-auto"><%- item.mobile %></span></p>
+                                                                <span class="text-muted"><%- item.role %></span>
+                                                            </dd>
+                                                        <% } %>
+                                                    <% });%>
+                                                </div>
+                                            <% }) %>
+                                        </dl>
+                                    </div>
+                                    </span>
+                                    <% } %>
+                                    <% if (ctx.stage.auditors2[i].status === auditConst.status.uncheck) { %>
+                                    <span class="dropdown mr-2">
+                                    <a href="javascript: void(0)" class="add-audit" id="<%- ctx.stage.auditors2[i].aid %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
+                                        <div class="dropdown-menu dropdown-menu-right" id="<%- ctx.stage.auditors2[i].aid %>_add_dropdownMenu" aria-labelledby="<%- ctx.stage.auditors2[i].aid %>_add_dropdownMenuButton" style="width:220px">
+                                            <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"
+                                                                         placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- ctx.stage.auditors2[i].aid %>_add"></div>
+                                            <dl class="list-unstyled book-list" data-aid="<%- ctx.stage.auditors2[i].aid %>" data-operate="add">
+                                                <% accountGroup.forEach((group, idx) => { %>
+                                                    <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
+                                                           data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
+                                                    <div class="dd-content" data-toggleid="<%- idx %>">
+                                                        <% group.groupList.forEach(item => { %>
+                                                            <% if (item.id !== ctx.stage.user_id) { %>
+                                                                <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>">
+                                                                    <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
+                                                                                class="ml-auto"><%- item.mobile %></span></p>
+                                                                    <span class="text-muted"><%- item.role %></span>
+                                                                </dd>
+                                                            <% } %>
+                                                        <% });%>
+                                                    </div>
+                                                <% }) %>
+                                            </dl>
+                                        </div>
+                                    </span>
+                                    <span class="dropdown mr-2">
+                                        <a href="javascript: void(0)" class="change-audit" id="<%- ctx.stage.auditors2[i].aid %>_change_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">更换</a>
+                                        <div class="dropdown-menu dropdown-menu-right" id="<%- ctx.stage.auditors2[i].aid %>_change_dropdownMenu" aria-labelledby="<%- ctx.stage.auditors2[i].aid %>_change_dropdownMenuButton" style="width:220px">
+                                            <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"
+                                                                         placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- ctx.stage.auditors2[i].aid %>_change"></div>
+                                            <dl class="list-unstyled book-list" data-aid="<%- ctx.stage.auditors2[i].aid %>" data-operate="change">
+                                                <% accountGroup.forEach((group, idx) => { %>
+                                                    <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
+                                                           data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
+                                                    <div class="dd-content" data-toggleid="<%- idx %>">
+                                                        <% group.groupList.forEach(item => { %>
+                                                            <% if (item.id !== ctx.stage.user_id) { %>
+                                                                <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>">
+                                                                    <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
+                                                                                class="ml-auto"><%- item.mobile %></span></p>
+                                                                    <span class="text-muted"><%- item.role %></span>
+                                                                </dd>
+                                                            <% } %>
+                                                        <% });%>
+                                                    </div>
+                                                <% }) %>
+                                            </dl>
+                                        </div>
+                                    </span>
+                                    <span class="dropdown">
+                                    <a href="javascript: void(0)" class="text-danger" title="移除" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">移除</a>
+                                    <div class="dropdown-menu">
+                                        <span class="dropdown-item" href="javascript:void(0);">确认移除审批人?</span>
+                                        <div class="dropdown-divider"></div>
+                                        <div class="px-2 py-1 text-center">
+                                            <button class="remove-audit btn btn-sm btn-danger" data-id="<%- ctx.stage.auditors2[i].aid %>">移除</button>
+                                            <button class="btn btn-sm btn-secondary">取消</button>
+                                        </div>
+                                    </div>
+                                    </span>
+                                    <% } %>
+                                </td>
+                            </tr>
+                            <% } %>
+                        </table>
+                    </div>
+                </div>
+            </div>
+            <form class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+            </form>
+        </div>
+    </div>
+</div>
+<% } %>
 <% include ../shares/check_data_modal.ejs %>
 <script type="text/javascript">
     const csrf = '<%= ctx.csrf %>';
     const authMobile = '<%= authMobile %>';
 </script>
+<% if (ctx.stage && ctx.stage.status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+<script type="text/javascript">
+    const accountGroup = JSON.parse(unescape('<%- escape(JSON.stringify(accountGroup)) %>'));
+    const accountList = JSON.parse(unescape('<%- escape(JSON.stringify(accountList)) %>'));
+    const stage_uid = parseInt('<%= ctx.stage.user_id %>');
+    const auditorList = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.stage.auditors2)) %>'));
+    const cur_tenderid = parseInt('<%- ctx.tender.id %>');
+</script>
+<% } %>
 <% if (ctx.stage && (ctx.session.sessionUser.accountId === ctx.stage.user_id && (ctx.stage.status === auditConst.status.uncheck || ctx.stage.status === auditConst.status.checkNo))) { %>
 <script>
     const accountGroup = JSON.parse(unescape('<%- escape(JSON.stringify(accountGroup)) %>'));

+ 1 - 1
app/view/tender/modal.ejs

@@ -231,7 +231,7 @@
                                             class="pull-right
                                                             ${auditConst2.statusClass[auditor.status]}">${auditor.status !== auditConst2.status.uncheck ? auditConst2.statusString[auditor.status] : ''}
                                             ${auditor.status === auditConst2.status.checkNo ? user.name : ''}
-                                            ${auditor.status === auditConst2.status.checkNoPre ? (leftAuditors.find(item => item.order === auditor.sort-1) ? leftAuditors.find(item => item.order === auditor.sort-1).name : '') : ''}
+                                            ${auditor.status === auditConst2.status.checkNoPre && auditor.sort - 1 > 0 ? _.find(auditors, { sort: auditor.sort - 1 }).name : ''}
                                         </span>
                                     </p>
                                     <p class="text-muted mb-0">${auditor.role}</p>

+ 2 - 0
sql/update.sql

@@ -183,3 +183,5 @@ UPDATE zh_stage_pay sp LEFT JOIN zh_pay p ON sp.pid = p.id SET sp.porder = p.`or
 
 ALTER TABLE `zh_change_ledger` ADD `formc` TINYINT(1) NOT NULL DEFAULT '1' COMMENT '是否为变更新增(用于区分台账)' AFTER `ccid`;
 ALTER TABLE `zh_change_pos` ADD `formc` TINYINT(1) NOT NULL DEFAULT '1' COMMENT '是否为变更新增(用于区分台账)' AFTER `ccid`;
+
+ALTER TABLE `zh_stage_audit` ADD `is_old` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否为旧流程(用于管理员修改流程时旧数据保留但不影响新流程)' AFTER `lock_lid`;