Browse Source

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

MaiXinRong 2 years ago
parent
commit
8266e9c306

+ 1 - 1
app/const/payment.js

@@ -34,7 +34,7 @@ const const_rpt_list = [
 
 const setting_modes = {
     safe: {
-        name: '安全生产费',
+        name: '安全生产费(当前版本未做功能,请忽略)',
         checked: false,
         value: 1,
     },

+ 84 - 12
app/controller/payment_controller.js

@@ -252,7 +252,7 @@ module.exports = app => {
                 const modes = projectInfo.payment_setting ? JSON.parse(projectInfo.payment_setting) : ctx.helper._.cloneDeep(paymentConst.setting_modes);
                 for (const m in modes) {
                     const detailCount = await ctx.service.paymentDetail.getCountByPidType(ctx.session.sessionProject.id, modes[m].value);
-                    modes[m].can_check = !detailCount;
+                    modes[m].can_check = !detailCount && modes[m].value !== 1;
                 }
                 const renderData = {
                     setting_modes: paymentConst.setting_modes,
@@ -305,6 +305,55 @@ module.exports = app => {
         async detail(ctx) {
             try {
                 await this._getDetailAuditViewData(ctx);
+                // 报表信息实时更新
+                if (ctx.trInfo.uid === ctx.session.sessionUser.accountId && ctx.trInfo.is_del === 0 && ctx.trInfo.rpt_id &&
+                    (ctx.detail.status === auditConst.status.uncheck || ctx.detail.status === auditConst.status.checkNo)) {
+                    const rptTpl = await ctx.service.rptTpl.getDataById(ctx.trInfo.rpt_id);
+                    if (rptTpl) {
+                        const pageRst = await ctx.service.jpcReport.getAllPreviewPagesCommon(rptTpl, 'A4');
+                        const rptMsg = pageRst.items[0];
+                        // 判断与原有的报表审批人列表是否有区别
+                        let difference = false;
+                        let auditDifference = false;
+                        let needChange = false;
+                        if (ctx.trInfo.report_items_json) {
+                            const report_items_json = JSON.parse(ctx.trInfo.report_items_json);
+                            const items = ['cells', 'signature_audit_cells', 'signature_cells', 'signature_date_cells', 'interact_cells'];
+                            for (const item of items) {
+                                if (report_items_json[item] &&
+                                    !ctx.helper._.isEmpty(ctx.helper._.differenceWith(JSON.parse(JSON.stringify(rptMsg[item])), report_items_json[item], ctx.helper._.isEqual))) {
+                                    // 因为interact_cells里存在undefind值,必须先用JSON.parse和JSON.stringify转义才能对比
+                                    difference = true;
+                                    needChange = true;
+                                    if (item === 'signature_cells') {
+                                        auditDifference = true;
+                                    }
+                                    // break;
+                                }
+                            }
+                        } else {
+                            difference = true;
+                        }
+                        if (difference) {
+                            // 删除rpt_audit重新配置
+                            const updateData = {
+                                id: ctx.trInfo.id,
+                                report_items_json: JSON.stringify(ctx.helper._.cloneDeep(rptMsg)),
+                            };
+                            // 删除rpt_audit重新配置
+                            if (auditDifference) {
+                                updateData.rpt_audit = null;
+                                ctx.trInfo.rpt_audit = null;
+                            }
+                            if (needChange) {
+                                updateData.is_change = 1;
+                                ctx.trInfo.is_change = 1;
+                            }
+                            await ctx.service.paymentTenderRpt.defaultUpdate(updateData);
+                            ctx.trInfo.report_items_json = rptMsg;
+                        }
+                    }
+                }
                 const renderData = {
                     trInfo: ctx.trInfo,
                     paymentConst,
@@ -375,7 +424,6 @@ module.exports = app => {
                         const groupList = accountList.filter(item => item.account_group === idx);
                         return { groupName: item, groupList };
                     });
-                    renderData.rptAuditList = await ctx.service.paymentRptAudit.getAllDataByCondition({ where: { td_id: ctx.detail.id } });
                 }
                 await this.layout('payment/detail.ejs', renderData, 'payment/detail_modal.ejs');
             } catch (err) {
@@ -399,7 +447,7 @@ module.exports = app => {
                 if (ctx.detail.uid !== ctx.session.sessionUser.accountId && data.type !== 'update_sign') {
                     throw '您无权操作';
                 }
-                if (data.type !== 'update_sign' && (ctx.detail.status === auditConst.status.checking || ctx.detail.status === auditConst.status.checked)) {
+                if (data.type !== 'update_sign' && ctx.detail.status !== auditConst.status.uncheck && ctx.detail.status !== auditConst.status.checkNo) {
                     throw '您无权操作';
                 }
                 const responseData = {
@@ -451,6 +499,16 @@ module.exports = app => {
                         }
                         responseData.data = await ctx.service.paymentDetailAudit.getAuditors(ctx.detail.id, ctx.detail.times);
                         break;
+                    case 'follow_rpt_audit':
+                        if (ctx.trInfo.shenpi_status === shenpiConst.sp_status.gdspl) {
+                            throw '当前表单已设置为固定审批流,无法同步';
+                        }
+                        const result3 = await ctx.service.paymentDetailAudit.followAuditByRptAudit(ctx.detail);
+                        if (!result3) {
+                            throw '同步表单角色失败';
+                        }
+                        responseData.data = await ctx.service.paymentDetailAudit.getAuditorsWithOwner(ctx.detail.id, ctx.detail.times);
+                        break;
                     default: throw '参数有误';
                 }
                 ctx.body = responseData;
@@ -529,7 +587,7 @@ module.exports = app => {
                 await this.getNewRptProjectList(ctx, newRptList, rptProjectList, 1);
                 const tenderRptList = await ctx.service.paymentTenderRpt.getProcessList(ctx.tender.id);
                 if (tenderRptList === -1) {
-                    throw '未配置审批模块,请联系管理员处理';
+                    throw '未配置表单设置,请联系管理员处理';
                 }
                 return await ctx.service.paymentTenderRpt.checkAndUpdateList(tenderRptList, rptProjectList, formProcess);
             }
@@ -636,7 +694,7 @@ module.exports = app => {
             try {
                 const tenderRptList = await this._returnRptProjectList(ctx);
                 if (tenderRptList === -1) {
-                    throw '未配置审批模块,请联系管理员处理';
+                    throw '未配置表单设置,请联系管理员处理';
                 }
                 if (tenderRptList.length === 0) {
                     throw '未配置表单设置,请联系管理员处理';
@@ -684,6 +742,8 @@ module.exports = app => {
                         renderData.rptMsg = pageRst.items[0];
                         // 判断与原有的报表审批人列表是否有区别
                         let difference = false;
+                        let auditDifference = false;
+                        let needChange = false;
                         if (trInfo.report_items_json) {
                             const report_items_json = JSON.parse(trInfo.report_items_json);
                             const items = ['cells', 'signature_audit_cells', 'signature_cells', 'signature_date_cells', 'interact_cells'];
@@ -692,20 +752,32 @@ module.exports = app => {
                                     !ctx.helper._.isEmpty(ctx.helper._.differenceWith(JSON.parse(JSON.stringify(renderData.rptMsg[item])), report_items_json[item], ctx.helper._.isEqual))) {
                                     // 因为interact_cells里存在undefind值,必须先用JSON.parse和JSON.stringify转义才能对比
                                     difference = true;
-                                    break;
+                                    needChange = true;
+                                    if (item === 'signature_cells') {
+                                        auditDifference = true;
+                                    }
+                                    // break;
                                 }
                             }
+                        } else {
+                            difference = true;
                         }
                         if (difference) {
                             // 删除rpt_audit重新配置
-                            await ctx.service.paymentTenderRpt.defaultUpdate({
+                            const updateData = {
                                 id: trInfo.id,
                                 report_items_json: JSON.stringify(ctx.helper._.cloneDeep(renderData.rptMsg)),
-                                rpt_audit: null,
-                                is_change: 1,
-                            });
-                            trInfo.rpt_audit = null;
-                            trInfo.is_change = 1;
+                            };
+                            // 删除rpt_audit重新配置
+                            if (auditDifference) {
+                                updateData.rpt_audit = null;
+                                trInfo.rpt_audit = null;
+                            }
+                            if (needChange) {
+                                updateData.is_change = 1;
+                                trInfo.is_change = 1;
+                            }
+                            await ctx.service.paymentTenderRpt.defaultUpdate(updateData);
                             trInfo.report_items_json = renderData.rptMsg;
                         }
                         if (trInfo.rpt_audit) {

+ 3 - 8
app/middleware/payment_detail_check.js

@@ -37,11 +37,10 @@ module.exports = options => {
             // 读取原报、审核人数据
             detail.auditors = yield this.service.paymentDetailAudit.getAuditors(detail.id, detail.times);
             detail.curAuditor = yield this.service.paymentDetailAudit.getCurAuditor(detail.id, detail.times);
-            const rptAudits = yield this.service.paymentRptAudit.getAllDataByCondition({ where: { td_id: detail.id } });
-
+            detail.rptAudits = yield this.service.paymentRptAudit.getListByDetail(detail.id);
             const accountId = this.session.sessionUser.accountId,
                 auditorIds = _.map(detail.auditors, 'aid'),
-                rptAuditIds = _.map(rptAudits, 'uid');
+                rptAuditIds = _.map(detail.rptAudits, 'uid');
             if (accountId === detail.uid) { // 原报
                 detail.curTimes = detail.times;
                 if (detail.status === status.uncheck || detail.status === status.checkNo) {
@@ -60,7 +59,7 @@ module.exports = options => {
                 } else {
                     detail.curOrder = detail.curAuditor.order;
                 }
-            } else if (auditorIds.indexOf(accountId) !== -1) { // 审批人
+            } else if (auditorIds.indexOf(accountId) !== -1 || rptAuditIds.indexOf(accountId) !== -1 || this.payment.auditPermission.view_all) { // 审批人及签署人及查看所有权人
                 if (detail.status === status.uncheck) {
                     throw '您无权查看该数据';
                 }
@@ -76,10 +75,6 @@ module.exports = options => {
                 } else {
                     detail.curOrder = accountId === detail.curAuditor.aid ? detail.curAuditor.order : detail.curAuditor.order - 1;
                 }
-            } else if (rptAuditIds.indexOf(accountId) !== -1 || this.payment.auditPermission.view_all) {
-                if (detail.status === status.uncheck || detail.status === status.checkNo) {
-                    throw '您无权查看该数据';
-                }
             } else { // 其他不可见
                 throw '您无权查看该数据';
             }

+ 3 - 0
app/middleware/payment_tender_check.js

@@ -33,6 +33,9 @@ module.exports = options => {
                 if (!modes[m]) modes[m] = _.cloneDeep(paymentConst.setting_modes[m]);
             }
             const auditPermission = yield this.service.paymentPermissionAudit.getOnePermission(this.session.sessionUser.is_admin, this.session.sessionUser.accountId);
+            if (!auditPermission) {
+                throw '权限不足';
+            }
             if (!tender) {
                 throw '标段不存在';
             }

+ 6 - 0
app/public/js/payment_detail.js

@@ -106,6 +106,9 @@ $(function () {
             }
             postData('/payment/' + tenderId + '/detail/' + detailId + '/save', { type: 'update_sign', signature_msg: rptAudit.signature_msg }, function (result) {
                 auditRptPrintHelper.showPage();
+                // 更新签署进度图表展示
+                $('#rpt_audit_sign td').eq(3).html(rptAudit.signature_msg.sign_path !== null ? '<i class="fa fa-check text-success"></i>' : '');
+                $('#rpt_audit_sign td').eq(4).html(rptAudit.signature_msg.company_stamp !== null || rptAudit.signature_msg.stamp_path !== null ? '<i class="fa fa-check text-success"></i>' : '');
             });
             $('#sub-sp5').modal('hide');
         } else {
@@ -116,6 +119,9 @@ $(function () {
 
     let timer = null
     function checkAndUpdate(index, newVal, _self) {
+        if (tesRpttData.items[0].interact_cells[index].DataType === 'intact_type_number' && _.indexOf(tesRpttData.items[0].interact_cells[index].Value, '元') !== -1) {
+            newVal = newVal + '元';
+        }
         console.log(index, newVal);
         clearTimeout(timer);
         timer = setTimeout(() => {

+ 48 - 56
app/public/js/payment_detail_audit.js

@@ -69,68 +69,52 @@ $(document).ready(function () {
             })
         }
         return false
-    })
+    });
+
+    function remakeShenpiHtml(datas) {
+        const html = [];
+        // 如果是重新上报,添加到重新上报列表中
+        const auditorshtml = [];
+        for (const [index,data] of datas.entries()) {
+            if (index !== 0) {
+                html.push('<li class="list-group-item" auditorId="'+ data.aid +'">');
+                if (shenpi_status === shenpiConst.sp_status.sqspr || (shenpi_status === shenpiConst.sp_status.gdzs && index+1 !== datas.length)) {
+                    html.push('<a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
+                }
+                html.push('<span>');
+                html.push(data.order + ' ');
+                html.push(data.name + ' ');
+                html.push('</span>');
+                if (_.findIndex(rptAuditList, { uid: data.aid }) !== -1) {
+                    html.push('&nbsp;(' + _.find(rptAuditList, { uid: data.aid }).signature_name + ')');
+                }
+                html.push('<small class="text-muted">');
+                html.push(data.role);
+                html.push('</small></li>');
+            }
+            // 添加新审批人流程修改
+            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>');
+        }
+        $('#auditors').html(html.join(''));
+        $('#auditors-list').html(auditorshtml.join(''));
+    }
 
     // 添加到审批流程中
     $('dl').on('click', 'dd', function () {
         const id = parseInt($(this).data('id'));
         if (id) {
             postData('/payment/' + tenderId + '/detail/' + detailId + '/save', { type: 'add_audit', auditorId: id }, (datas) => {
-                const html = [];
-                // 如果是重新上报,添加到重新上报列表中
-                const auditorshtml = [];
-                for (const [index,data] of datas.entries()) {
-                    if (index !== 0) {
-                        html.push('<li class="list-group-item" auditorId="'+ data.aid +'">');
-                        if (shenpi_status === shenpiConst.sp_status.sqspr || (shenpi_status === shenpiConst.sp_status.gdzs && index+1 !== datas.length)) {
-                            html.push('<a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
-                        }
-                        html.push('<span>');
-                        html.push(data.order + ' ');
-                        html.push(data.name + ' ');
-                        html.push('</span>');
-                        if (_.findIndex(rptAuditList, { uid: data.aid }) !== -1) {
-                            html.push('&nbsp;(' + _.find(rptAuditList, { uid: data.aid }).signature_name + ')');
-                        }
-                        html.push('<small class="text-muted">');
-                        html.push(data.role);
-                        html.push('</small></li>');
-                    }
-                    // 添加新审批人流程修改
-                    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>');
-                }
-                $('#auditors').html(html.join(''));
-
-
-                // 重新上报时。令其它的审批人流程图标转换
-                // $('#auditors-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                // for (let i = 0; i < $('#auditors-list li').length; i++) {
-                //     $('#auditors-list li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
-                //     $('#auditors-list2 li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
-                // }
-
-                $('#auditors-list').html(auditorshtml.join(''));
-
-                // const auditorshtml2 = [];
-                // // 重新上报时。令其它的审批人流程图标转换
-                // $('#auditors-list2 li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                // // 添加新审批人
-                // auditorshtml2.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
-                // auditorshtml2.push('<h5 class="card-title"><i class="fa fa-stop-circle"></i> ');
-                // auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
-                // auditorshtml2.push('<span class="pull-right">终审</span>');
-                // auditorshtml2.push('</h5></li>');
-                // $('#auditors-list2').append(auditorshtml2.join(''));
+                remakeShenpiHtml(datas);
             });
         }
     });
@@ -207,6 +191,14 @@ $(document).ready(function () {
             }
         });
     });
+
+    // 同步报表角色
+    $('#follow_rpt_audit_btn').click(function () {
+        postData('/payment/' + tenderId + '/detail/' + detailId + '/save', { type: 'follow_rpt_audit' }, (datas) => {
+            toastr.success('同步成功');
+            remakeShenpiHtml(datas);
+        });
+    });
 });
 // 检查上报情况
 function checkAuditorFrom () {

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

@@ -77,7 +77,7 @@ $(function () {
             if (node.uid === uid || is_admin) {
                 html.push('<a class="dropdown-item edit_name_btn" data-type="'+ (node.parent_id === undefined ? 'tender' : 'folder') +'" data-id="'+ node.id +'" href="javascript:void(0);"><i class="fa fa-edit mr-2"></i>重命名</a>\n');
             }
-            if (!node.had_tender && node.uid === uid || is_admin) {
+            if (!node.had_tender && (node.uid === uid || is_admin)) {
                 if (node.have_detail) {
                     html.push('<a class="dropdown-item" style="cursor:not-allowed" href="javascript:void(0);" data-toggle="tooltip" data-placement="bottom" title="请先删除所有审批期数据"><i class="fa fa-remove mr-2"></i>删除</a>\n');
                 } else {

+ 14 - 7
app/public/js/payment_process.js

@@ -25,6 +25,7 @@ $(function () {
                 html.push(`<tr data-id="${data.id}">\n`);
                 html.push(`<td>${data.rpt_name}</td>\n`);
                 html.push(`<td>${data.user_name}</td>\n`);
+                html.push(`<td>${data.uid ? _.find(accountList, { id: data.uid }).name : ''}</td>\n`);
                 html.push('</tr>\n');
             }
             tenderRptList = result;
@@ -56,8 +57,10 @@ $(function () {
                         <span class="text-muted">${item.role || ''}</span>
                     </dd>`
                 });
-                $('#' + code + '_dropdownMenu .book-list').empty();
-                $('#' + code + '_dropdownMenu .book-list').append(html);
+                $(this).parents('.dropdown-menu').children('.book-list').empty();
+                $(this).parents('.dropdown-menu').children('.book-list').append(html);
+                // $('#' + code + '_dropdownMenu .book-list').empty();
+                // $('#' + code + '_dropdownMenu .book-list').append(html);
             } else {
                 if (!$('#' + code + '_dropdownMenu .acc-btn').length) {
                     accountGroup.forEach((group, idx) => {
@@ -76,8 +79,10 @@ $(function () {
                         });
                         html += '</div>';
                     });
-                    $('#' + code + '_dropdownMenu .book-list').empty();
-                    $('#' + code + '_dropdownMenu .book-list').append(html);
+                    // $('#' + code + '_dropdownMenu .book-list').empty();
+                    // $('#' + code + '_dropdownMenu .book-list').append(html);
+                    $(this).parents('.dropdown-menu').children('.book-list').empty();
+                    $(this).parents('.dropdown-menu').children('.book-list').append(html);
                 }
             }
         }, 400);
@@ -178,7 +183,7 @@ $(function () {
             html +='<div><span class="d-inline-block">\n' +
                 '                                                <div class="dropdown text-right">\n' +
                 '                                                    <button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button" id="' + tr_id + '_dropdownMenuButton2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">\n' +
-                '                                                        选择审批人\n' +
+                '                                                        选择上报人\n' +
                 '                                                    </button>\n' +
                 '                                                    <div class="dropdown-menu dropdown-menu-right" id="' + tr_id + '_dropdownMenu2" aria-labelledby="' + tr_id + '_dropdownMenuButton2" style="width:220px">\n' +
                 '                                                        <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"\n' +
@@ -318,7 +323,9 @@ $(function () {
             if (result.updateRows) {
                 toastr.warning('上报人不能同时作为审批人,审批流已移除 ' + user.name);
             }
+            $('#tender_rpt_table tr[data-id="'+ this_tr_id +'"]').children('td').eq(2).html(user.name);
             makeProcess(this_tr_id);
+
         });
         //
         // const this_status = parseInt($(this).parents('.lc-show').siblings('.form-group').find('input:checked').val());
@@ -475,8 +482,8 @@ $(function () {
     };
 
     $('#add-rpt').on('show.bs.modal', function () {
-        $('#rpt-table').find('input:checked:not(:disabled)').prop('checked', false);
-        $('#rpt-table').find('input:not(:disabled)').each(function () {
+        $('#rpt_table').find('input:checked:not(:disabled)').prop('checked', false);
+        $('#rpt_table').find('input:not(:disabled)').each(function () {
             if (_.findIndex(tenderRptList, { rpt_id: parseInt($(this).val()) }) !== -1) {
                 $(this).prop('checked', true);
             }

+ 2 - 48
app/public/report/js/rpt_jspdf.js

@@ -203,55 +203,9 @@ const JpcJsPDFHelper = {
             }
         }
 
-        function private_getProperSignatureArea(cell, control) {
-            // 约定默认长宽比例是2:1,图片分辨率是600*300
-            const rst = [0, 0, 0, 0]; // left, top, right, bottom
-            if (cell && cell[JV.PROP_AREA]) {
-                if (cell.hasOwnProperty('isOrgShow') && cell.isOrgShow) {
-                    rst[JV.IDX_LEFT] = cell[JV.PROP_AREA][JV.PROP_LEFT];
-                    rst[JV.IDX_TOP] = cell[JV.PROP_AREA][JV.PROP_TOP];
-                    rst[JV.IDX_RIGHT] = cell[JV.PROP_AREA][JV.PROP_RIGHT];
-                    rst[JV.IDX_BOTTOM] = cell[JV.PROP_AREA][JV.PROP_BOTTOM];
-                } else {
-                    let width = cell[JV.PROP_AREA][JV.PROP_RIGHT] - cell[JV.PROP_AREA][JV.PROP_LEFT],
-                        height = cell[JV.PROP_AREA][JV.PROP_BOTTOM] - cell[JV.PROP_AREA][JV.PROP_TOP];
-                    if (width > height * 2) {
-                        width = height * 2;
-                    } else {
-                        height = width / 2;
-                    }
-                    switch (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]]) {
-                        case 'left':
-                            rst[0] = cell[JV.PROP_AREA][JV.PROP_LEFT];
-                            rst[1] = cell[JV.PROP_AREA][JV.PROP_TOP];
-                            rst[2] = rst[0] + width;
-                            rst[3] = rst[1] + height;
-                            break;
-                        case 'right':
-                            rst[2] = cell[JV.PROP_AREA][JV.PROP_RIGHT];
-                            rst[3] = cell[JV.PROP_AREA][JV.PROP_BOTTOM];
-                            rst[0] = rst[2] - width;
-                            rst[1] = rst[3] - height;
-                            break;
-                        default:
-                            //center
-                            rst[0] = (cell[JV.PROP_AREA][JV.PROP_LEFT] + cell[JV.PROP_AREA][JV.PROP_RIGHT] - width) / 2;
-                            rst[1] = cell[JV.PROP_AREA][JV.PROP_TOP];
-                            rst[2] = rst[0] + width;
-                            rst[3] = rst[1] + height;
-                            break;
-                    }
-                }
-            }
-            rst[0] = rst[0] + offsetX;
-            rst[2] = rst[2] + offsetX;
-            rst[1] = rst[1] + offsetY;
-            rst[3] = rst[3] + offsetY;
-            return rst;
-        }
-
         function private_drawImage(doc, ctx, cell, control, imageData, orgSize = false, offsetArea) {
-            let area = private_getProperSignatureArea(cell, control);
+            // let area = private_getProperSignatureArea(cell, control);
+            let area = getProperSignatureArea(cell, control, offsetX, offsetY, JV);
             if (orgSize) {
                 area[0] = cell[JV.PROP_AREA][JV.PROP_LEFT] + offsetX; // Left
                 area[1] = cell[JV.PROP_AREA][JV.PROP_TOP] + offsetX; // Top

+ 52 - 0
app/service/payment_detail_audit.js

@@ -450,6 +450,14 @@ module.exports = app => {
                     times: times + 1,
                     report_json: JSON.stringify(report_json),
                 });
+                // 清空签名
+                await transaction.update(this.ctx.service.paymentRptAudit.tableName, {
+                    signature_msg: null,
+                }, {
+                    where: {
+                        td_id: detailId,
+                    },
+                });
                 // 拷贝新一次审核流程列表
                 await transaction.insert(this.tableName, auditors);
 
@@ -529,6 +537,50 @@ module.exports = app => {
                     throw '无效审批操作';
             }
         }
+
+        async followAuditByRptAudit(detail) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const newAuditIds = this._.map(detail.rptAudits, 'uid');
+                // 去除上报人
+                if (this._.includes(newAuditIds, detail.uid)) {
+                    this._.pull(newAuditIds, detail.uid);
+                }
+                // 如果存在固定终审,判断它是否在报表人员里,存在则把该id移到最后,不存在则插入newAuditIds最后;
+                if (this.ctx.trInfo.sp_status === shenpiConst.sp_status.gdzs) {
+                    const gdzsInfo = await this.ctx.service.paymentShenpiAudit.getAudit(detail.tender_id, detail.tr_id, shenpiConst.sp_status.gdzs);
+                    if (gdzsInfo && gdzsInfo.audit_id !== newAuditIds[newAuditIds.length - 1]) {
+                        if (this._.includes(newAuditIds, gdzsInfo.audit_id)) {
+                            this._.pull(newAuditIds, gdzsInfo.audit_id);
+                        }
+                        newAuditIds.push(gdzsInfo.audit_id);
+                    }
+                }
+                // 删除原审批流
+                await transaction.delete(this.tableName, { td_id: detail.id, times: detail.times });
+                // 添加新审批流
+                const insertDatas = [];
+                let order = 1;
+                for (const id of newAuditIds) {
+                    insertDatas.push({
+                        tender_id: detail.tender_id,
+                        tr_id: detail.tr_id,
+                        td_id: detail.id,
+                        aid: id,
+                        order,
+                        times: detail.times,
+                        status: auditConst.status.uncheck,
+                    });
+                    order = order + 1;
+                }
+                if (insertDatas.length > 0) await transaction.insert(this.tableName, insertDatas);
+                await transaction.commit();
+                return true;
+            } catch (error) {
+                await transaction.rollback();
+                throw error;
+            }
+        }
     }
 
     return PaymentDetailAudit;

+ 24 - 4
app/service/payment_folder.js

@@ -64,7 +64,19 @@ module.exports = app => {
                     throw '您没有权限删除此目录';
                 }
                 let ids = [info.id];
-                if (info.parent_path) {
+                if (info.parent_id === 0) {
+                    const childList = await this.getAllDataByCondition({ where: { parent_id: info.id } });
+                    if (childList.length > 0) {
+                        ids = [...ids, ...this._.map(childList, 'id')];
+                        for (const c of childList) {
+                            const deleteData = await this.getDataByParentPath(this.tableName, c.parent_path + '-' + c.id + '%', transaction);
+                            if (deleteData.length > 0) {
+                                const delids = this._.map(deleteData, 'id');
+                                ids = [...ids, ...delids];
+                            }
+                        }
+                    }
+                } else if (info.parent_path) {
                     const deleteData = await this.getDataByParentPath(this.tableName, info.parent_path + '-' + info.id + '%', transaction);
                     if (deleteData.length > 0) {
                         const delids = this._.map(deleteData, 'id');
@@ -118,6 +130,7 @@ module.exports = app => {
                 if (folderList.length > 0) {
                     const leafFolderList = this._.filter(folderList, { is_leaf: 1 });
                     const parentFolderIdList = this._.map(this._.filter(folderList, { is_leaf: 0 }), 'id');
+                    const allNotExistFolderIds = [];
                     for (const lf of leafFolderList) {
                         let parentPathArray = lf.parent_path !== '' ? lf.parent_path.split('-') : [];
                         if (parentPathArray.length > 0) {
@@ -127,14 +140,21 @@ module.exports = app => {
                         }
                         const notExistFolderIds = this._.difference(parentPathArray, parentFolderIdList);
                         if (notExistFolderIds.length > 0) {
-                            const newFolderList = await this.getAllDataByCondition({ where: { id: notExistFolderIds } });
-                            console.log(newFolderList);
-                            folderList = [...folderList, ...newFolderList];
+                            for (const id of notExistFolderIds) {
+                                if (!this._.includes(allNotExistFolderIds, id)) {
+                                    allNotExistFolderIds.push(id);
+                                }
+                            }
                         }
                     }
+                    if (allNotExistFolderIds.length > 0) {
+                        const newFolderList = await this.getAllDataByCondition({ where: { id: allNotExistFolderIds } });
+                        folderList = [...folderList, ...newFolderList];
+                    }
                 }
             }
             if (folderList.length > 0) {
+                // folderList = this._.uniqBy(folderList, 'id');
                 for (const f of folderList) {
                     const userInfo = this._.find(accountList, { id: f.uid });
                     f.user_name = userInfo ? userInfo.name : '';

+ 12 - 0
app/service/payment_rpt_audit.js

@@ -70,6 +70,18 @@ module.exports = app => {
             }
             await transaction.updateRows(this.tableName, updateData);
         }
+
+        async getListByDetail(td_id) {
+            const sql = 'SELECT pra.*, pa.name as user_name FROM ?? as pra LEFT JOIN ?? as pa ON pra.`uid` = pa.`id` WHERE td_id = ?';
+            const params = [this.tableName, this.ctx.service.projectAccount.tableName, td_id];
+            const list = await this.db.query(sql, params);
+            if (list.length > 0) {
+                for (const ra of list) {
+                    ra.signature_msg = ra.signature_msg ? JSON.parse(ra.signature_msg) : null;
+                }
+            }
+            return list;
+        }
     }
 
     return PaymentRptAudit;

+ 4 - 4
app/service/payment_tender.js

@@ -25,9 +25,9 @@ module.exports = app => {
             }
             const typeValues = [];
             const projectInfo = await this.ctx.service.project.getDataById(this.ctx.session.sessionProject.id);
-            const modes = projectInfo.payment_setting ? JSON.parse(projectInfo.payment_setting) : _.cloneDeep(paymentConst.setting_modes);
+            const modes = projectInfo.payment_setting ? JSON.parse(projectInfo.payment_setting) : this._.cloneDeep(paymentConst.setting_modes);
             for (const m in paymentConst.setting_modes) {
-                if (!modes[m]) modes[m] = _.cloneDeep(paymentConst.setting_modes[m]);
+                if (!modes[m]) modes[m] = this._.cloneDeep(paymentConst.setting_modes[m]);
                 if (modes[m].checked) {
                     typeValues.push(modes[m].value);
                 }
@@ -35,13 +35,13 @@ module.exports = app => {
             if (typeValues.length === 0) {
                 return -1;
             }
-            const sql = 'SELECT pt.*, pa.name as user_name FROM ?? as pt LEFT JOIN ?? as pa ON pt.`uid` = pa.`id` WHERE pid = ? AND pt.`uid` = ? ' +
+            const sql = 'SELECT pt.*, pa.name as user_name FROM ?? as pt LEFT JOIN ?? as pa ON pt.`uid` = pa.`id` WHERE pid = ? AND (pt.`uid` = ? ' +
                 'OR pt.`id` in (SELECT pr.`tender_id` FROM ?? as pr WHERE pr.`uid` = ? AND pr.`type` IN (' + this.ctx.helper.getInArrStrSqlFilter(typeValues) + '))' +
                 'OR pt.`id` in (SELECT pd.`tender_id` FROM ?? as pd WHERE pd.`uid` = ?)' +
                 'OR pt.`id` in (SELECT pda.`tender_id` FROM ?? as pda LEFT JOIN ?? as pd ON pda.`tender_id` = pd.`tender_id` ' +
                 'WHERE pd.`status` != ' + auditConst.status.uncheck + ' AND pda.`aid` = ?)' +
                 'OR pt.`id` in (SELECT pra.`tender_id` FROM ?? as pra LEFT JOIN ?? as pd ON pra.`tender_id` = pd.`tender_id` ' +
-                'WHERE pd.`status` != ' + auditConst.status.uncheck + ' AND pd.`status` !=' + auditConst.status.checkNo + ' AND pra.`uid` = ?)';
+                'WHERE pd.`status` != ' + auditConst.status.uncheck + ' AND pd.`status` !=' + auditConst.status.checkNo + ' AND pra.`uid` = ?))';
             const params = [this.tableName, this.ctx.service.projectAccount.tableName, this.ctx.session.sessionProject.id, uid,
                 this.ctx.service.paymentTenderRpt.tableName, uid,
                 this.ctx.service.paymentDetail.tableName, uid,

+ 1 - 0
app/service/payment_tender_rpt.js

@@ -237,6 +237,7 @@ module.exports = app => {
                 const result1 = await this.ctx.service.paymentDetail.updateReport(transaction, tr_id, data.uid);
                 // 判断固定审批流或固定终审是否存在上报人,有则移除
                 const result2 = await this.ctx.service.paymentShenpiAudit.removeAuditByReport(transaction, tr_id, data.uid);
+                await this.ctx.service.paymentPermissionAudit.saveAudits(this.ctx.session.sessionProject.id, [userInfo], transaction);
                 await transaction.commit();
                 let tenderRptList = await this.getProcessList(this.ctx.tender.id);
                 tenderRptList = this._.filter(tenderRptList, { type: 0, is_del: 0 });

+ 6 - 5
app/view/payment/audit_modal.ejs

@@ -17,12 +17,12 @@
                                     报表表单角色
                                 </div>
                                 <ul class="list-group list-group-flush">
-                                    <% for (const [index, ra] of rptAuditList.entries()) { %>
+                                    <% for (const [index, ra] of ctx.detail.rptAudits.entries()) { %>
                                         <li class="list-group-item">
                                             <div class="row">
                                                 <span class="col-2"><%- index+1 %></span>
                                                 <span class="col-6"><%- ra.signature_name %></span>
-                                                <span class="col-4"><%- ctx.helper._.findIndex(accountList, { id: ra.uid }) !== -1 ? ctx.helper._.find(accountList, { id: ra.uid }).name : '' %></span>
+                                                <span class="col-4"><%- ra.user_name %></span>
                                             </div>
                                         </li>
                                     <% } %>
@@ -32,6 +32,7 @@
                         <div class="col-7" style="overflow: auto">
                             <div class="dropdown text-right">
                                 <% if (trInfo.sp_status !== shenpiConst.sp_status.gdspl && ctx.session.sessionUser.accountId === ctx.detail.uid) { %>
+                                    <button class="btn btn-sm btn-primary mr-2" id="follow_rpt_audit_btn">同步表单角色</button>
                                     <button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button"
                                             id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
                                             aria-expanded="false">
@@ -48,7 +49,7 @@
                                                     <% group.groupList.forEach(item => { %>
                                                         <% if (item.id !== ctx.session.sessionUser.accountId) { %>
                                                             <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> <% if (ctx.helper._.findIndex(rptAuditList, { uid: item.id }) !== -1) { %>&nbsp;(<%- ctx.helper._.find(rptAuditList, { uid: item.id }).signature_name %>)<% } %><span
+                                                                <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span> <% if (ctx.helper._.findIndex(ctx.detail.rptAudits, { uid: item.id }) !== -1) { %>&nbsp;(<%- ctx.helper._.find(ctx.detail.rptAudits, { uid: item.id }).signature_name %>)<% } %><span
                                                                             class="ml-auto"><%- item.mobile %></span></p>
                                                                 <span class="text-muted"><%- item.role %></span>
                                                             </dd>
@@ -73,7 +74,7 @@
                                                     <a href="javascript: void(0)" class="text-danger pull-right">移除</a>
                                                 <% } %>
                                                 <span><%- ctx.detail.auditorList[i].order %> <%- ctx.detail.auditorList[i].name %></span>
-                                                <% if (ctx.helper._.findIndex(rptAuditList, { uid: ctx.detail.auditorList[i].aid }) !== -1) { %>&nbsp;(<%- ctx.helper._.find(rptAuditList, { uid: ctx.detail.auditorList[i].aid }).signature_name %>)<% } %>
+                                                <% if (ctx.helper._.findIndex(ctx.detail.rptAudits, { uid: ctx.detail.auditorList[i].aid }) !== -1) { %>&nbsp;(<%- ctx.helper._.find(ctx.detail.rptAudits, { uid: ctx.detail.auditorList[i].aid }).signature_name %>)<% } %>
                                                 <small class="text-muted"><%- ctx.detail.auditorList[i].role %></small>
                                             </li>
                                         <% } %>
@@ -776,7 +777,7 @@
         const accountList = JSON.parse(unescape('<%- escape(JSON.stringify(accountList)) %>'));
         const shenpi_status = <%- trInfo.sp_status %>;
         const shenpiConst =  JSON.parse('<%- JSON.stringify(shenpiConst) %>');
-        const rptAuditList = JSON.parse(unescape('<%- escape(JSON.stringify(rptAuditList)) %>'));
+        const rptAuditList = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.detail.rptAudits)) %>'));
     </script>
 <% } %>
 <script>const cur_uid = parseInt('<%- ctx.session.sessionUser.accountId %>');</script>

+ 23 - 4
app/view/payment/detail.ejs

@@ -23,6 +23,7 @@
                 ) { %>
                 <a href="#sub-sp5" data-toggle="modal" data-target="#sub-sp5" class="btn btn-sm btn-primary pull-right mr-2">签字意见</a>
                 <% } %>
+                <a href="#sign-flow" data-toggle="modal" data-target="#sign-flow" class="btn btn-sm btn-outline-success pull-right mr-2">签署进度</a>
                 <% } %>
             </div>
         </div>
@@ -41,7 +42,7 @@
                                 <% if (item.type === 'textarea') { %>
                                     <textarea <% if (ctx.detail.readOnly) { %>readonly<% } %> class="form-control form-control-sm" data-index="<%- item.index %>"><%- item.value %></textarea>
                                 <% } else { %>
-                                    <input <% if (ctx.detail.readOnly) { %>readonly<% } %> type="<%- item.type %>" value="<%- item.value %>"  data-index="<%- item.index %>" class="form-control form-control-sm" placeholder="请输入">
+                                    <input <% if (ctx.detail.readOnly) { %>readonly<% } %> type="<%- item.type %>" value="<%- item.type === 'number' && ctx.helper._.indexOf(item.value, '元') !== -1 ? parseFloat(item.value) : item.value %>"  data-index="<%- item.index %>" class="form-control form-control-sm" placeholder="请输入">
                                 <% } %>
                             </div>
                             <% } %>
@@ -223,7 +224,7 @@
     //     iniPage();
     // });
 
-    function _getAdhocDummyCells(srcCell, rstCells) {
+    function _getAdhocDummyCells(srcCell, rstCells, controls = null) {
         if (typeof srcCell.path === 'string') {
             let paths = srcCell.path.split('!;!');
             for (let dtlPathIdx = 0; dtlPathIdx < paths.length; dtlPathIdx++) {
@@ -239,13 +240,30 @@
                         couldCreate = false;
                     }
                     if (couldCreate) {
+                        let area = srcCell.area;
+                        if ((dtlPathIdx === 0) && (srcCell.orgArea)) {
+                            area = JSON.parse(JSON.stringify(srcCell.orgArea));
+                            let control = srcCell[JV.PROP_CONTROL];
+                            if (typeof srcCell[JV.PROP_CONTROL] === "string") {
+                                control = controls[srcCell[JV.PROP_CONTROL]];
+                            }
+                            let tmpArea = srcCell.area;
+                            srcCell.area = area;
+                            let signArea = getProperSignatureArea(srcCell, control, 0, 0, JV);
+                            srcCell.area = tmpArea;
+                            area[JV.PROP_LEFT] = signArea[0];
+                            area[JV.PROP_TOP] = signArea[1];
+                            area[JV.PROP_RIGHT] = signArea[2];
+                            area[JV.PROP_BOTTOM] = signArea[3];
+                        }
                         const newStampCell = {
                             signature_name: 'dummy_pic',
                             control: srcCell.control,
                             style: srcCell.style,
                             path: imgSrc,
                             isStamp: true,
-                            area: srcCell.area,
+                            area,
+                            // isOrgShow: (dtlPathIdx === 0),
                         };
                         rstCells.push(newStampCell);
                     }
@@ -292,9 +310,10 @@
         // 1. 先找有没有dummy
         for (let pageData of pageDataArr) {
             let tmpDummyCells = [];
+            let controls = pageData[JV.NODE_CONTROL_COLLECTION];
             for (let page of pageData.items) {
                 for (let dCell of page.signature_cells) {
-                    _getAdhocDummyCells(dCell, tmpDummyCells);
+                    _getAdhocDummyCells(dCell, tmpDummyCells, controls);
                 }
                 if (tmpDummyCells.length > 0) {
                     page.signature_cells = page.signature_cells.concat(tmpDummyCells);

+ 37 - 0
app/view/payment/detail_modal.ejs

@@ -100,4 +100,41 @@
     </div>
 </div>
 <% } %>
+<!--签署进度-->
+<div class="modal fade" id="sign-flow" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">签署进度</h5>
+            </div>
+            <div class="modal-body">
+                <table class="table table-bordered">
+                    <thead class="text-center">
+                    <tr>
+                        <th>序号</th>
+                        <th>表单角色</th>
+                        <th>签署人</th>
+                        <th>签字</th>
+                        <th>签章</th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <% for (const [index, ra] of ctx.detail.rptAudits.entries()) { %>
+                    <tr class="text-center" <% if (rptAudit && rptAudit.id === ra.id) { %>id="rpt_audit_sign"<% } %>>
+                        <td><%- index+1 %></td>
+                        <td><%- ra.signature_name %></td>
+                        <td><%- ra.user_name %></td>
+                        <td><% if (ra.signature_msg && ra.signature_msg.sign_path !== null ) { %><i class="fa fa-check text-success"></i><% } %></td>
+                        <td><% if (ra.signature_msg && (ra.signature_msg.stamp_path !== null || ra.signature_msg.company_stamp !== null)) { %><i class="fa fa-check text-success"></i><% } %></td>
+                    </tr>
+                    <% } %>
+                    </tbody>
+                </table>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
 <% include ./audit_modal.ejs %>

+ 6 - 1
app/view/payment/list_modal.ejs

@@ -12,7 +12,7 @@
                     <tr>
                         <th>序号</th>
                         <th>表单角色</th>
-                        <th>审批人</th>
+                        <th>签署人</th>
                     </tr>
                     </thead>
                     <tbody>
@@ -74,6 +74,11 @@
                 <form>
                     <div class="form-group">
                         <!--<a href="#" class="float-right"><i class="fa fa-cog"></i></a>-->
+                        <label for="add-detail-code">期数</label>
+                        <input type="text" class="form-control form-control-sm"  value="第<%- (!trDetailList || trDetailList.length === 0 ? '1' : (trDetailList && trDetailList.length >= 1 ? trDetailList[0].order + 1 : '')) %>期" readonly>
+                    </div>
+                    <div class="form-group">
+                        <!--<a href="#" class="float-right"><i class="fa fa-cog"></i></a>-->
                         <label for="add-detail-code">编号</label>
                         <input type="text" class="form-control form-control-sm" name="add_code" id="add-detail-code" placeholder="请输入编号" value="">
                     </div>

+ 5 - 3
app/view/payment/process.ejs

@@ -69,15 +69,17 @@
                                     <table class="table table-bordered">
                                         <thead>
                                         <tr>
-                                            <th>名称</th>
-                                            <th>添加人</th>
+                                            <th class="text-center">名称</th>
+                                            <th class="text-center">添加人</th>
+                                            <th class="text-center">上报人</th>
                                         </tr>
                                         </thead>
                                         <tbody id="tender_rpt_table" style="cursor: pointer">
                                         <% for (const tr of tenderRptList) { %>
                                         <tr data-id="<%- tr.id %>">
                                             <td><%- tr.rpt_name  %></td>
-                                            <td><%- tr.user_name %></td>
+                                            <td class="text-center"><%- tr.user_name %></td>
+                                            <td class="text-center"><%- tr.uid ? ctx.helper._.find(accountList, { id: tr.uid }).name : '' %></td>
                                         </tr>
                                         <% } %>
                                         </tbody>

+ 1 - 1
app/view/payment/process_modal.ejs

@@ -5,7 +5,7 @@
                 <h5 class="modal-title">添加表单</h5>
             </div>
             <div class="modal-body" style="max-height:800px;overflow: auto">
-                <table id="rpt-table" class="table table-bordered">
+                <table id="rpt-table1" class="table table-bordered">
                     <thead>
                     <tr>
                         <th class="text-center"><input type="checkbox" id="select_all_rpt_checkbox"> 选择</th>

+ 3 - 1
sql/update.sql

@@ -15,4 +15,6 @@ UPDATE `zh_sub_project` p LEFT JOIN `zh_budget` b ON p.budget_id = b.id SET p.st
 UPDATE `zh_sub_project` p LEFT JOIN `zh_budget_std` bs ON p.std_id = bs.id SET p.std_name = IFNULL(bs.name, '');
 
 -- index
-ALTER TABLE `zh_material_bills_history` ADD INDEX `idx_mbid_mid_mspread` (`mb_id`, `mid`, `m_spread`);
+ALTER TABLE `zh_material_bills_history` ADD INDEX `idx_mbid_mid_mspread` (`mb_id`, `mid`, `m_spread`);
+
+ALTER TABLE `zh_project` ADD `payment_setting` JSON NULL DEFAULT NULL COMMENT '支付审批模块设置' AFTER `fun_set`;