Explorar o código

台账审批管理员修改流程更新

ellisran hai 9 meses
pai
achega
48f4016b72

+ 4 - 3
app/controller/ledger_audit_controller.js

@@ -193,9 +193,10 @@ module.exports = app => {
             try {
                 const data = JSON.parse(ctx.request.body.data);
                 if (ctx.session.sessionUser.is_admin && ctx.tender.ledger_status !== auditConst.status.checked) {
-                    await ctx.service.ledgerAudit.saveAudit(ctx.tender.id, ctx.tender.data.ledger_times, data);
-                    const auditors = await ctx.service.ledgerAudit.getAuditorsWithOwner(ctx.tender.id, ctx.tender.data.ledger_times);
-                    ctx.body = { err: 0, msg: '', data: auditors };
+                    await ctx.service.ledgerAudit.saveAudit(ctx.tender.id, ctx.tender.data.ledger_times, 0, data);
+                    const auditorUniqs = await ctx.service.ledgerAudit.getUniqUserGroup(ctx.tender.id, ctx.tender.data.ledger_times);
+                    const auditors = await ctx.service.ledgerAudit.getAuditors(ctx.tender.id, ctx.tender.data.ledger_times);
+                    ctx.body = { err: 0, msg: '', data: { auditorUniqs, auditors } };
                 } else {
                     throw '您无权进行该操作';
                 }

+ 108 - 93
app/public/js/ledger.js

@@ -4280,6 +4280,59 @@ $(document).ready(function() {
         }, 400);
     });
 
+    const getAdminEditShenpiListHtml = function(auditGroup) {
+        const html = [];
+        for (const [i, group] of auditGroup.entries()) {
+            if (i === 0) continue;
+            for (const [j, auditor] of group.entries()) {
+                html.push('<tr>');
+                if (j === 0) {
+                    const auditTypeHtml = auditor.type === auditType.key.common ? '' : `<span class="ml-2 badge badge-pill badge-${auditType.info[auditor.audit_type].class} p-1"><small>${auditType.info[auditor.audit_type].short}</small></span>`;
+                    html.push(`<td class="text-left d-flex">${i + '审'}${auditTypeHtml}</td>`);
+                } else {
+                    html.push(`<td class="text-left d-flex"></td>`);
+                }
+                html.push(`<td></span> ${auditor.name} <small class="text-muted">${auditor.role}</small></td>`);
+                html.push(`<td style="text-align: center"><span class="${auditConst.auditStringClass[auditor.status]}">${ auditor.status !== auditConst.status.uncheck ? auditConst.auditString[auditor.status] : '待审批' }</span></td>`);
+                html.push('<td style="text-align: center">');
+                if (auditor.status === auditConst.status.checking && j === group.length - 1) {
+                    html.push('<span class="dropdown mr-2">',
+                        `<a href="javascript: void(0)" class="add-audit" id="${auditor.audit_id}_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>`,
+                        makeSelectAudit(auditor.audit_id+'_add', auditor.audit_id, 'add'),'</div>', '</span>');
+                }
+                if (auditor.status === auditConst.status.uncheck) {
+                    if (j === group.length - 1) {
+                        html.push('<span class="dropdown mr-2">',
+                            `<a href="javascript: void(0)" class="add-audit" id="${auditor.audit_id}_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>`,
+                            makeSelectAudit(auditor.audit_id+'_add', auditor.audit_id, 'add'),'</div>', '</span>');
+                        if (auditor.audit_type !== auditType.key.common) {
+                            html.push('<span class="dropdown mr-2">',
+                                `<a href="javascript: void(0)" class="add-audit" id="${auditor.audit_id}_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">平级</a>`,
+                                makeSelectAudit(auditor.audit_id+'_add-sibling', auditor.audit_id, 'add-sibling'),'</div>', '</span>');
+                        }
+                    }
+                    html.push('<span class="dropdown mr-2">',
+                        `<a href="javascript: void(0)" class="add-audit" id="${auditor.audit_id}_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">更换</a>`,
+                        makeSelectAudit(auditor.audit_id+'_change', auditor.audit_id, 'change'),'</div>', '</span>');
+                    html.push(`<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="${auditor.audit_id}">移除</button>
+                                            <button class="btn btn-sm btn-secondary">取消</button>
+                                        </div>
+                                    </div>
+                                    </span>`);
+                }
+                html.push('</td>');
+                html.push('</tr>');
+            }
+        }
+        return html.join('');
+    };
+
     $('body').on('click', '#admin-edit-shenpi dl dd', function () {
         const id = parseInt($(this).attr('data-id'));
         if (!id) return;
@@ -4294,64 +4347,15 @@ $(document).ready(function() {
             toastr.warning('该审核人已存在,请勿重复添加');
             return;
         }
-        const order = parseInt($(this).parents('tr').find('.shenpi-order').text());
-        const curAuditorIndex = _.findIndex(auditorList, { audit_id: this_aid });
         const prop = {
             operate: this_operate,
             old_aid: this_aid,
             new_aid: user.id,
         };
         postData('/tender/' + getTenderId() + '/ledger/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, { audit_id: user.id, company: user.company, name: user.name, role: user.role });
-                updateOrder(user.id);
-            } else if (this_operate === 'change') {
-                const this_user = _.find(auditorList, { audit_id: this_aid });
-                this_user.audit_id = 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);
+            auditorList = datas.auditors;
+            $('#admin-edit-shenpi-list').html(getAdminEditShenpiListHtml(datas.auditorUniqs));
+            changeLiucheng(datas.auditorUniqs);
         });
     });
 
@@ -4363,62 +4367,73 @@ $(document).ready(function() {
             old_aid: id,
         };
         postData('/tender/' + getTenderId() + '/ledger/audit/save', prop, (datas) => {
-            updateOrder(id, 0);
-            const curAuditorIndex = _.findIndex(auditorList, { audit_id: id });
-            auditorList.splice(curAuditorIndex, 1);
-            $(this).parents('tr').remove();
-            changeLiucheng(datas);
+            auditorList = datas.auditors;
+            $('#admin-edit-shenpi-list').html(getAdminEditShenpiListHtml(datas.auditorUniqs));
+            changeLiucheng(datas.auditorUniqs);
         });
     });
 
-    // 比uid大的序号进行调整
-    function updateOrder(aid, num = 1) {
-        const index = _.findIndex(auditorList, { audit_id: aid });
-        for (let i = index;i < auditorList.length; i++) {
-            $('#admin-edit-shenpi tbody').children('tr').eq(i).find('.shenpi-order').text(i+num);
-        }
-    }
+    const getAuditTypeText = function (type) {
+        if (type === auditType.key.common) return '';
+        return `<span class="text-${auditType.info[type].class}">${auditType.info[type].long}</span>`;
+    };
 
     function changeLiucheng(datas) {
         const auditorshtml = [];
-        let lastAuditorHtml = '';
+        let lastAuditorHtml = [];
         for (const [index,data] of datas.entries()) {
-            auditorshtml.push('<li class="list-group-item" data-auditorid="' + data.audit_id + '">');
-            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>');
+            auditorshtml.push('<li class="list-group-item d-flex justify-content-between align-items-center">');
+            if (index === 0) {
+                auditorshtml.push('<span class="mr-1"><i class="fa fa fa-play-circle fa-rotate-90"></i></span>');
+            } else if (index+1 === datas.length) {
+                auditorshtml.push('<span class="mr-1"><i class="fa fa fa-stop-circle"></i></span>');
+            } else {
+                auditorshtml.push('<span class="mr-1"><i class="fa fa-chevron-circle-down"></i></span>');
+            }
+            auditorshtml.push('<span class="text-muted">');
+            for (const u of data) {
+                auditorshtml.push(`<small class="d-inline-block text-dark mx-1" title="${u.role}" data-auditorId="${u.audit_id}">${u.name}</small>`);
+            }
+            auditorshtml.push('</span>');
+            auditorshtml.push('<div class="d-flex ml-auto">');
+            if (data[0].audit_type !== auditType.key.common) auditorshtml.push(`<span class="badge badge-pill badge-${auditType.info[data[0].audit_type].class} p-1"><small>${auditType.info[data[0].audit_type].short}</small></span>`);
             if (index === 0) {
-                auditorshtml.push('<span class="pull-right">原报</span>');
+                auditorshtml.push('<span class="badge badge-light badge-pill ml-auto"><small>原报</small></span>');
             } else if (index+1 === datas.length) {
-                auditorshtml.push('<span class="pull-right">终审</span>');
+                auditorshtml.push('<span class="badge badge-light badge-pill"><small>终审</small></span>');
             } else {
-                auditorshtml.push('<span class="pull-right">'+ transFormToChinese(index) +'审</span>');
+                auditorshtml.push('<span class="badge badge-light badge-pill"><small>'+ transFormToChinese(index) +'审</small></span>');
             }
+            auditorshtml.push('</div>');
             auditorshtml.push('</li>');
-            if (data.status === auditConst.status.uncheck) {
-                lastAuditorHtml += '<li class="timeline-list-item pb-2 is_uncheck">\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">${data.name}</span>\n` +
-                    '                                                                <span class="pull-right ">\n' +
-                    '                                                                </span>\n' +
-                    '                                                            </p>\n' +
-                    `                                                            <p class="text-muted mb-0">${data.role}</p>\n` +
-                    '                                                        </div>\n' +
-                    '                                                    </div>\n' +
-                    '                                                </div>\n' +
-                    '                                            </div>\n' +
-                    '                                        </li>';
+            if (data[0].status === auditConst.status.uncheck) {
+                lastAuditorHtml.push('<li class="timeline-list-item pb-2 is_uncheck">');
+                if (index < datas.length - 1) {
+                    lastAuditorHtml.push('<div class="timeline-item-tail"></div>');
+                }
+                lastAuditorHtml.push('<div class="timeline-item-icon bg-secondary text-light"></div>');
+
+                lastAuditorHtml.push('<div class="timeline-item-content">');
+                lastAuditorHtml.push(`<div class="py-1">
+                        <span class="text-black-50">
+                        ${ index !== datas.length - 1 ? data[0].audit_order + '' : '终' }审 ${getAuditTypeText(data[0].audit_type)}
+                        </span>
+                    </div>`);
+                lastAuditorHtml.push('<div class="card"><div class="card-body px-3 py-0">');
+                for (const [i, auditor] of data.entries()) {
+                    lastAuditorHtml.push(`<div class="card-text p-2 py-3 row ${ ( i > 0 ? 'border-top' : '') }">`);
+                    lastAuditorHtml.push(`<div class="col"><span class="h6">${auditor.name}</span><span class="text-muted ml-1">${auditor.role}</span></div>`);
+                    lastAuditorHtml.push('<div class="col">');
+                    lastAuditorHtml.push('</div>');
+                    lastAuditorHtml.push('</div>');
+                }
+                lastAuditorHtml.push('</div></div>');
+                lastAuditorHtml.push('</div>');
+                lastAuditorHtml.push('</li>');
             }
         }
         $('.last-auditor-list .is_uncheck').remove();
-        $('.last-auditor-list').append(lastAuditorHtml);
+        $('.last-auditor-list').append(lastAuditorHtml.join(''));
         $('.auditors-list').html(auditorshtml.join(''));
 
     }

+ 3 - 1
app/public/js/stage.js

@@ -5372,7 +5372,9 @@ function makeOneShouFang(sf) {
     sf.name = lData.b_code;
     if (sf.pid) {
         const pData = _.find(posData, { id: sf.pid });
-        sf.name = lData.b_code + ' / ' + pData.name;
+        if (pData && pData.name) {
+            sf.name = lData.b_code + ' / ' + pData.name;
+        }
     }
     return sf;
 }

+ 32 - 6
app/service/ledger_audit.js

@@ -213,6 +213,8 @@ module.exports = app => {
 
         async getUniqUserGroup(tenderId, times) {
             const group = await this.getAuditorGroup(tenderId, times);
+            // 台账因为可选原报人为审批人,这里有点不同,这里要先过滤再取原报插入
+            const newGroup = this.groupAuditorsUniq(group);
             const sql =
                 'SELECT pa.`id` As audit_id, pa.`name`, pa.`company`, pa.`role`, ? As times, ? As tender_id, 0 As audit_order, 1 As audit_type' +
                 '  FROM ' + this.ctx.service.tender.tableName + ' As t' +
@@ -221,8 +223,8 @@ module.exports = app => {
                 '  WHERE t.id = ?';
             const sqlParam = [times, tenderId, tenderId];
             const user = await this.db.queryOne(sql, sqlParam);
-            group.unshift([ user ]);
-            return this.groupAuditorsUniq(group);
+            newGroup.unshift([ user ]);
+            return newGroup;
         }
 
         async getAuditorHistory(tenderId, times, reverse = false) {
@@ -915,7 +917,7 @@ module.exports = app => {
             // const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, tender_id, times];
             // return transaction ? await transaction.query(sql, sqlParam) : await this.db.query(sql, sqlParam);
             const sql =
-                'SELECT la.`audit_id`, la.`status`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`tender_id`, la.`audit_order` ' +
+                'SELECT la.`audit_id`, la.`status`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`tender_id`, la.`audit_order`, la.`audit_type` ' +
                 '  FROM ?? AS la Left Join ?? AS pa On la.`audit_id` = pa.`id`' +
                 '  WHERE la.`tender_id` = ? and la.`times` = ? ORDER BY la.`audit_order` DESC';
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, tender_id, times];
@@ -1012,11 +1014,15 @@ module.exports = app => {
          * @param {Object} data - 更改参数
          * @return {Promise<void>}
          */
-        async saveAudit(tenderId, times, data) {
+        async saveAudit(tenderId, times, sp_group, data) {
             const transaction = await this.db.beginTransaction();
             try {
                 const auditors = await this.getAuditGroupByList(tenderId, times);
                 const now_audit = this._.find(auditors, { audit_id: data.old_aid });
+                if (data.operate !== 'del') {
+                    const exist = await this.getDataByCondition({ tender_id: tenderId, times, audit_id: data.new_aid });
+                    if (exist) throw '该审核人已存在,请勿重复添加';
+                }
                 if (data.operate === 'add') {
                     if (now_audit.status !== auditConst.status.uncheck && now_audit.status !== auditConst.status.checking) {
                         throw '当前人下无法操作新增';
@@ -1025,6 +1031,7 @@ module.exports = app => {
                         tender_id: tenderId,
                         audit_id: data.new_aid,
                         audit_order: now_audit.audit_order + 1,
+                        audit_type: auditType.key.common,
                         times,
                         status: auditConst.status.uncheck,
                     };
@@ -1032,12 +1039,26 @@ module.exports = app => {
                     await this._syncOrderByDelete(transaction, tenderId, now_audit.audit_order + 1, times, '+');
                     await transaction.insert(this.tableName, newAudit);
                     // 更新审批流程页数据,如果存在
+                } else if (data.operate === 'add-sibling') {
+                    if (now_audit.status !== auditConst.status.uncheck && now_audit.status !== auditConst.status.checking) {
+                        throw '当前人下无法操作新增';
+                    }
+                    const newAudit = {
+                        tender_id: tenderId,
+                        audit_id: data.new_aid,
+                        audit_order: now_audit.audit_order,
+                        audit_type: now_audit.audit_type,
+                        times: times,
+                        status: auditConst.status.uncheck,
+                    };
+                    await transaction.insert(this.tableName, newAudit);
                 } else if (data.operate === 'del') {
                     if (now_audit.status !== auditConst.status.uncheck) {
                         throw '当前人无法操作删除';
                     }
+                    const flowAuditors = auditors.filter(x => { return x.audit_order === now_audit.audit_order; });
                     await transaction.delete(this.tableName, { tender_id: tenderId, times, audit_id: now_audit.audit_id, audit_order: now_audit.audit_order });
-                    await this._syncOrderByDelete(transaction, tenderId, now_audit.audit_order, times);
+                    if (flowAuditors.length === 1) await this._syncOrderByDelete(transaction, tenderId, now_audit.audit_order, times);
                 } else if (data.operate === 'change') {
                     const nowAudit = await this.getDataByCondition({ tender_id: tenderId, times, audit_id: now_audit.audit_id, audit_order: now_audit.audit_order });
                     if (now_audit.status !== auditConst.status.uncheck || !nowAudit) {
@@ -1046,7 +1067,12 @@ module.exports = app => {
                     nowAudit.audit_id = data.new_aid;
                     await transaction.update(this.tableName, nowAudit);
                 }
-                if (this.ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdspl || this.ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdzs) {
+                if (this.ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdspl) {
+                    const newAuditors = await transaction.select(this.tableName, { where: { tender_id: tenderId, times } });
+                    const newAuditorGroup = this.ctx.helper.groupAuditors(newAuditors, 'audit_order');
+                    const uniqNewAuditorGroup = this.ctx.helper.groupAuditorsUniq(newAuditorGroup);
+                    await this.ctx.service.shenpiAudit.updateAuditListWithAuditType(transaction, this.ctx.tender.id, this.ctx.tender.info.shenpi.ledger, shenpiConst.sp_type.ledger, uniqNewAuditorGroup, sp_group);
+                } else if (this.ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdzs) {
                     const newAuditors = await this.getAuditGroupByList(tenderId, times, transaction);
                     await this.ctx.service.shenpiAudit.updateAuditList(transaction, this.ctx.tender.id, this.ctx.tender.info.shenpi.ledger, shenpiConst.sp_type.ledger, this._.map(newAuditors, 'audit_id'));
                 }

+ 1 - 1
app/service/shenpi_audit.js

@@ -431,7 +431,7 @@ module.exports = app => {
                     tid: tenderId,
                     sp_type,
                     sp_status,
-                    audit_id: a.aid || a.uid,
+                    audit_id: a.aid || a.uid || a.audit_id,
                     audit_order: a.audit_order,
                     audit_type: a.audit_type,
                     sp_group,

+ 89 - 55
app/view/ledger/audit_modal.ejs

@@ -70,7 +70,7 @@
                             <% } %>
                         <div class="<%- idx < tender.auditHistory.length - 1 ? 'fold-card' : '' %>">
                             <div class="text-center text-muted"><%- idx+1 %>#</div>
-                            <ul class="timeline-list list-unstyled mt-2 <% if (idx === tender.auditHistory.length - 1 && tender.auditHistory.length > 1) { %>last-auditor-list<% } %>">
+                            <ul class="timeline-list list-unstyled mt-2 <% if (idx === tender.auditHistory.length - 1) { %>last-auditor-list<% } %>">
                                 <% his.forEach((group, index) => { %>
                                 <% if (index === 0) { %>
                                 <li class="timeline-list-item pb-2">
@@ -102,7 +102,7 @@
                                     </div>
                                 </li>
                                 <% } %>
-                                <li class="timeline-list-item pb-2 <% if (group.status === auditConst.status.uncheck && idx === tender.auditHistory.length - 1 && tender.auditHistory.length > 1) { %>is_uncheck<% } %>">
+                                <li class="timeline-list-item pb-2 <% if (group.status === auditConst.status.uncheck && idx === tender.auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <% if (group.endYear) { %>
                                     <div class="timeline-item-date">
                                         <%- group.endYear %>
@@ -251,7 +251,7 @@
                         <% } %>
                         <div class="<%- idx < tender.auditHistory.length - 1 ? 'fold-card' : '' %>">
                             <div class="text-center text-muted"><%- idx+1 %>#</div>
-                            <ul class="timeline-list list-unstyled mt-2 <% if (idx === tender.auditHistory.length - 1 && tender.auditHistory.length !== 1) { %>last-auditor-list<% } %>">
+                            <ul class="timeline-list list-unstyled mt-2 <% if (idx === tender.auditHistory.length - 1) { %>last-auditor-list<% } %>">
                                 <% his.forEach((group, index) => { %>
                                 <% if (index === 0) { %>
                                 <li class="timeline-list-item pb-2">
@@ -283,7 +283,7 @@
                                     </div>
                                 </li>
                                 <% } %>
-                                <li class="timeline-list-item pb-2 <% if (group.status === auditConst.status.uncheck && idx === tender.auditHistory.length - 1 && tender.auditHistory.length !== 1) { %>is_uncheck<% } %>">
+                                <li class="timeline-list-item pb-2 <% if (group.status === auditConst.status.uncheck && idx === tender.auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <% if (his.endYear) { %>
                                     <div class="timeline-item-date">
                                         <%- group.endYear %>
@@ -387,107 +387,141 @@
                             </style>
                             <table class="table table-hover" id="admin-edit-shenpi">
                                 <thead>
-                                <tr class="card-header">
-                                    <th>审批流程</th>
+                                <tr class="card-header text-center">
+                                    <th width="100px">审批流程</th>
+                                    <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 = auditors.length; i < iLen; i++) { %>
-                                    <tr>
-                                        <td><span class="shenpi-order"><%- i %></span> <%- auditors[i].name %> <small class="text-muted"><%- auditors[i].role %></small></td>
-                                        <td style="text-align: center"><span class="<%- auditConst.auditStringClass[auditors[i].status] %>"><%- auditors[i].status !== auditConst.status.uncheck ? auditConst.auditString[auditors[i].status] : '待审批'  %></span></td>
-                                        <td style="text-align: center">
-                                            <% if (auditors[i].status === auditConst.status.checking) { %>
-                                                <span class="dropdown mr-2">
-                                    <a href="javascript: void(0)" class="add-audit" id="<%- auditors[i].audit_id %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
-                                    <div class="dropdown-menu dropdown-menu-right" id="<%- auditors[i].audit_id %>_add_dropdownMenu" aria-labelledby="<%- auditors[i].audit_id %>_add_dropdownMenuButton" style="width:220px">
+                                <tbody id="admin-edit-shenpi-list">
+                                <% for (const [i, group] of tender.auditors2.entries()) { %>
+                                    <% if (i === 0) continue; %>
+                                    <% for (const [j, auditor] of group.entries()) { %>
+                                        <tr>
+                                            <td class="text-left d-flex">
+                                                <% if (j === 0) { %>
+                                                    <%- i + '审' %>
+                                                    <% if (auditor.audit_type !== auditType.key.common) { %>
+                                                        <span class="ml-2 badge badge-pill badge-<%-  auditType.info[auditor.audit_type].class %> p-1"><small><%- auditType.info[auditor.audit_type].short %></small></span>
+                                                    <% } %>
+                                                <% } %>
+                                            </td>
+                                            <td></span> <%- auditor.name %> <small class="text-muted"><%- auditor.role %></small></td>
+                                            <td style="text-align: center"><span class="<%- auditConst.auditStringClass[auditor.status] %>"><%- auditor.status !== auditConst.status.uncheck ? auditConst.auditString[auditor.status] : '待审批'  %></span></td>
+                                            <td style="text-align: center">
+                                                <% if (auditor.status === auditConst.status.checking && j === group.length - 1) { %>
+                                                    <span class="dropdown mr-2">
+                                    <a href="javascript: void(0)" class="add-audit" id="<%- auditor.audit_id %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
+                                    <div class="dropdown-menu dropdown-menu-right" id="<%- auditor.audit_id %>_add_dropdownMenu" aria-labelledby="<%- auditor.audit_id %>_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="<%- auditors[i].audit_id %>_add"></div>
-                                        <dl class="list-unstyled book-list" data-aid="<%- auditors[i].audit_id %>" data-operate="add">
+                                                                     placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- auditor.audit_id %>_add"></div>
+                                        <dl class="list-unstyled book-list" data-aid="<%- auditor.audit_id %>" 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.tender.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>
-                                                        <% } %>
+                                                        <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 (auditors[i].status === auditConst.status.uncheck) { %>
-                                                <span class="dropdown mr-2">
-                                    <a href="javascript: void(0)" class="add-audit" id="<%- auditors[i].audit_id %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
-                                        <div class="dropdown-menu dropdown-menu-right" id="<%- auditors[i].audit_id %>_add_dropdownMenu" aria-labelledby="<%- auditors[i].audit_id %>_add_dropdownMenuButton" style="width:220px">
+                                                <% } %>
+                                                <% if (auditor.status === auditConst.status.uncheck) { %>
+                                                    <% if (j === group.length - 1) { %>
+                                                        <span class="dropdown mr-2">
+                                    <a href="javascript: void(0)" class="add-audit" id="<%- auditor.audit_id %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
+                                        <div class="dropdown-menu dropdown-menu-right" id="<%- auditor.audit_id %>_add_dropdownMenu" aria-labelledby="<%- auditor.audit_id %>_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="<%- auditor.aid %>_add"></div>
+                                            <dl class="list-unstyled book-list" data-aid="<%- auditor.audit_id %>" 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 => { %>
+                                                            <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 (auditor.audit_type !== auditType.key.common) { %>
+                                                            <span class="dropdown mr-2">
+                                    <a href="javascript: void(0)" class="add-audit" id="<%- auditor.audit_id %>_add-sibling_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">平级</a>
+                                        <div class="dropdown-menu dropdown-menu-right" id="<%- auditor.audit_id %>_add-sibling_dropdownMenu" aria-labelledby="<%- auditor.audit_id %>_add-sibling_dropdownMenuButton" style="width:220px">
                                             <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"
-                                                                         placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- auditors[i].audit_id %>_add"></div>
-                                            <dl class="list-unstyled book-list" data-aid="<%- auditors[i].audit_id %>" data-operate="add">
+                                                                         placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- auditor.audit_id %>_add-sibling"></div>
+                                            <dl class="list-unstyled book-list" data-aid="<%- auditor.audit_id %>" data-operate="add-sibling">
                                                 <% 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.tender.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>
-                                                            <% } %>
+                                                            <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="<%- auditors[i].audit_id %>_change_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">更换</a>
-                                        <div class="dropdown-menu dropdown-menu-right" id="<%- auditors[i].audit_id %>_change_dropdownMenu" aria-labelledby="<%- auditors[i].audit_id %>_change_dropdownMenuButton" style="width:220px">
+                                                        <% } %>
+                                                    <% } %>
+                                                    <span class="dropdown mr-2">
+                                        <a href="javascript: void(0)" class="change-audit" id="<%- auditor.audit_id %>_change_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">更换</a>
+                                        <div class="dropdown-menu dropdown-menu-right" id="<%- auditor.audit_id %>_change_dropdownMenu" aria-labelledby="<%- auditor.audit_id %>_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="<%- auditors[i].audit_id %>_change"></div>
-                                            <dl class="list-unstyled book-list" data-aid="<%- auditors[i].audit_id %>" data-operate="change">
+                                                                         placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- auditor.audit_id %>_change"></div>
+                                            <dl class="list-unstyled book-list" data-aid="<%- auditor.audit_id %>" 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.tender.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>
-                                                            <% } %>
+                                                            <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">
+                                                    <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="<%- auditors[i].audit_id %>">移除</button>
+                                            <button class="remove-audit btn btn-sm btn-danger" data-id="<%- auditor.audit_id %>">移除</button>
                                             <button class="btn btn-sm btn-secondary">取消</button>
                                         </div>
                                     </div>
                                     </span>
-                                            <% } %>
-                                        </td>
-                                    </tr>
+                                                <% } %>
+                                            </td>
+                                        </tr>
+                                    <% } %>
                                 <% } %>
+                                </tbody>
                             </table>
                         </div>
                     </div>

+ 1 - 1
app/view/ledger/explode.ejs

@@ -398,6 +398,6 @@
 <script>
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
     const accountGroup = JSON.parse('<%- JSON.stringify(accountGroup) %>');
-    const auditorList = JSON.parse(unescape('<%- escape(JSON.stringify(auditors)) %>'));
+    let auditorList = JSON.parse(unescape('<%- escape(JSON.stringify(auditors)) %>'));
 </script>
 <% } %>

+ 2 - 2
app/view/ledger/explode_modal.ejs

@@ -158,7 +158,7 @@
                         审批流程
                     </div>
                     <div class="modal-height-500" style="overflow: auto">
-                    <ul class="list-group list-group-flush" id="auditors">
+                    <ul class="list-group list-group-flush auditors-list" id="auditors">
                         <% for (let i = 0, iLen = tender.auditorGroups.length; i < iLen; i++) { %>
                         <li class="list-group-item d-flex" auditorId="<%- tender.auditorGroups[i][0].audit_id %>">
                             <div class="col-auto"><%- i+1 %></div>
@@ -299,7 +299,7 @@
                                     </div>
                                 </li>
                                 <% } %>
-                                <li class="timeline-list-item pb-2 <% if (group.status === auditConst.status.uncheck && idx === tender.auditHistory.length - 1 && tender.auditHistory.length !== 1) { %>is_uncheck<% } %>">
+                                <li class="timeline-list-item pb-2 <% if (group.status === auditConst.status.uncheck && idx === tender.auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <% if (group.endYear) { %>
                                     <div class="timeline-item-date">
                                         <%- group.endYear %>