Переглянути джерело

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

MaiXinRong 2 роки тому
батько
коміт
90400a3aec

+ 2 - 0
app/controller/change_controller.js

@@ -714,6 +714,7 @@ module.exports = app => {
                                 cl['audit_amount_' + au.uid] = audit_amount[index - 1] ? audit_amount[index - 1] : null;
                             }
                         }
+                        cl.changed_amount = (change.status === audit.flow.status.backnew || change.status === audit.flow.status.checking || change.status === audit.flow.status.checked) && audit_amount !== '' ? audit_amount[audit_amount.length - 1] : cl.camount;
                     }
                     renderData.changeList = changeList;
                     renderData.auditList2 = auditList2;
@@ -763,6 +764,7 @@ module.exports = app => {
                                 cl['audit_amount_' + au.uid] = au.uid === ctx.session.sessionUser.accountId ? cl.spamount : (audit_amount[index - 1] ? audit_amount[index - 1] : null);
                             }
                         }
+                        cl.changed_amount = (change.status === audit.flow.status.backnew || change.status === audit.flow.status.checking || change.status === audit.flow.status.checked) && audit_amount !== '' ? audit_amount[audit_amount.length - 1] : cl.camount;
                     }
                     renderData.changeList = changeList;
                     renderData.changeLedgerList = await ctx.service.changeLedger.getAllDataByCondition({ where: { tender_id: ctx.tender.id } });

+ 1 - 1
app/controller/material_controller.js

@@ -377,8 +377,8 @@ module.exports = app => {
         async info(ctx) {
             try {
                 await this._getMaterialAuditViewData(ctx);
-                const renderData = await this._getDefaultRenderData(ctx);
                 await this._setEditTaxPermission(ctx);
+                const renderData = await this._getDefaultRenderData(ctx);
                 renderData.materialBillsData = await this._getMaterialBillsData(ctx);
                 // 取对应期的截取上期的调差金额和应耗数量
                 if (ctx.material.highOrder !== ctx.material.order) {

+ 61 - 2
app/controller/profile_controller.js

@@ -364,10 +364,16 @@ module.exports = app => {
                     if (!accountData.stamp_path) {
                         throw '不存在签章';
                     }
+                    const stamp_path_list = accountData.stamp_path.split('!;!');
+                    const spIndex = ctx.helper._.indexOf(stamp_path_list, data.src);
+                    if (spIndex === -1) {
+                        throw '不存在此签章';
+                    }
                     // 删除oss文件
-                    await ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + accountData.stamp_path);
+                    await ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + stamp_path_list[spIndex]);
+                    stamp_path_list.splice(spIndex, 1);
                     // 删除库
-                    result = await ctx.service.projectAccount.update({ stamp_path: null }, { id: sessionUser.accountId });
+                    result = await ctx.service.projectAccount.update({ stamp_path: stamp_path_list.length === 0 ? null : stamp_path_list.join('!;!') }, { id: sessionUser.accountId });
                 } else {
                     if (accountData.sign_path === '') {
                         throw '不存在签名';
@@ -462,6 +468,59 @@ module.exports = app => {
         }
 
         /**
+         * 上传签章图(多选)
+         *
+         * @param {object} ctx - egg全局变量
+         * @return {void}
+         */
+        async stampUpload(ctx) {
+            const responseData = {
+                err: 0, msg: '', data: null,
+            };
+            let stream;
+            try {
+                const parts = ctx.multipart({ autoFields: true });
+                const paths = [];
+                let index = 0;
+                while ((stream = await parts()) !== undefined) {
+                    // 判断用户是否选择上传文件
+                    if (!stream.filename) {
+                        throw '请选择上传的文件!';
+                    }
+                    const fileInfo = path.parse(stream.filename);
+                    const create_time = Date.parse(new Date()) / 1000;
+                    const filepath = `app/public/upload/sign/profile/qianzhang_${create_time + index.toString() + fileInfo.ext}`;
+                    // await ctx.helper.saveStreamFile(stream, path.resolve(this.app.baseDir, filepath));
+                    await ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + filepath, stream);
+                    if (stream) {
+                        await sendToWormhole(stream);
+                    }
+                    paths.push(filepath);
+                    ++index;
+                }
+                // 获取账号数据
+                const accountData = await ctx.service.projectAccount.getDataByCondition({ id: ctx.session.sessionUser.accountId });
+                const stamp_path = accountData.stamp_path ? accountData.stamp_path.split('!;!') : [];
+                const stamp_path_list = ctx.helper._.concat(stamp_path, paths);
+                const result = await ctx.service.projectAccount.update({ stamp_path: stamp_path_list.join('!;!') }, { id: ctx.session.sessionUser.accountId });
+                if (result) {
+                    responseData.data = { stamp_path: stamp_path_list };
+                } else {
+                    throw '添加数据库失败';
+                }
+            } catch (err) {
+                this.log(err);
+                // 失败需要消耗掉stream 以防卡死
+                if (stream) {
+                    await sendToWormhole(stream);
+                }
+                responseData.err = 1;
+                responseData.msg = err.toString();
+            }
+            ctx.body = responseData;
+        }
+
+        /**
          * 账号安全
          *
          * @param {object} ctx - egg全局变量

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

@@ -2046,3 +2046,18 @@ animation:shake 1s .2s ease both;}
 .card-gk-active .card-gk-bottom{
   display: inline-block;
 }
+
+.stamp-img{
+  cursor: pointer;
+}
+
+.private-stamp-img{
+  display: inline-block;
+  margin: auto;
+  vertical-align: middle; 
+}
+.private-stamp-img .check-state{
+  position: absolute;
+  right: 10px;
+  top: 10px;
+}

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

@@ -984,7 +984,7 @@ $(document).ready(() => {
                 const quantity = leaf.quantity !== undefined && leaf.quantity !== null ? leaf.quantity : 0;
                 const gcl_id = leaf.gcl_id ? leaf.gcl_id : '';
                 const mx_id = leaf.mx_id ? leaf.mx_id : '';
-                const bwmx = leaf.bwmx !== undefined ? leaf.bwmx : (gcl.leafXmjs.length > 1 && gcl.name ? gcl.name : undefined);
+                const bwmx = leaf.bwmx !== undefined ? leaf.bwmx : undefined;
                 const pushMsg = leaf.code + '!_!' + (leaf.jldy ? leaf.jldy : '') + '!_!' +
                     (leaf.dwgc ? leaf.dwgc : '') + '!_!' + (leaf.fbgc ? leaf.fbgc : '') + '!_!' + (leaf.fxgc ? leaf.fxgc : '')
                     + '!_!' + (leaf.gcl_id ? leaf.gcl_id : '0') + '!_!' + (leaf.mx_id ? leaf.mx_id : '') + '!_!' +
@@ -1646,7 +1646,7 @@ function tableDataRemake(changeListData) {
                                 (leafInfo.fxgc ? leafInfo.fxgc : '') + '!_!' +
                                 (leafInfo.gcl_id ? leafInfo.gcl_id : '') + '!_!' +
                                 (leafInfo.mx_id ? leafInfo.mx_id : '') + '!_!' +
-                                (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (listinfo.leafXmjs.length > 1 && listinfo.name ? listinfo.name : (leafInfo.jldy !== undefined ? leafInfo.jldy : ''))) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                                (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (leafInfo.jldy !== undefined ? leafInfo.jldy : '')) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
                         } else {
                             toastr.warning('台账清单列表已不存在'+ clinfo.code +',已更新变更清单列表');
                             if (changeStatus !== auditConst.status.revise) {
@@ -1686,7 +1686,7 @@ function tableDataRemake(changeListData) {
                                 (leafInfo.fxgc ? leafInfo.fxgc : '') + '!_!' +
                                 (leafInfo.gcl_id ? leafInfo.gcl_id : '') + '!_!' +
                                 (leafInfo.mx_id ? leafInfo.mx_id : '') + '!_!' +
-                                (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (listinfo.leafXmjs.length > 1 && listinfo.name ? listinfo.name : (leafInfo.jldy !== undefined ? leafInfo.jldy : ''))) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                                (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (leafInfo.jldy !== undefined ? leafInfo.jldy : '')) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
                         } else {
                             // console.log(clinfo, listinfo.leafXmjs);
                             // changeList.splice(index, 1);

+ 17 - 6
app/public/js/change_information_show.js

@@ -22,6 +22,8 @@ $(document).ready(() => {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'ca_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.ca_tp'},
             {title: '审批后变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'samount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.samount'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sa_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.sa_tp'},
+            {title: '变更后|数量', colSpan: '2|1', rowSpan: '1|1', field: 'samount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.changed_amount'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sa_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.changed_tp'},
         ],
         emptyRows: 0,
         headRows: 2,
@@ -90,6 +92,12 @@ $(document).ready(() => {
             sa_tp: function (data) {
                 return ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.samount, findDecimal(data.unit))), totalPriceUnit);
             },
+            changed_amount: function (data) {
+                return ZhCalc.round(data.changed_amount, findDecimal(data.unit));
+            },
+            changed_tp: function (data) {
+                return ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.changed_amount, findDecimal(data.unit))), totalPriceUnit);
+            },
         },
     };
 
@@ -122,10 +130,10 @@ $(document).ready(() => {
                 for(let i = 0; i <= rowCount - 1; i++){
                     const data = {
                         unit_price: changeSpreadSheet.getValue(i, 3),
-                        amount: parseFloat(changeSpreadSheet.getValue(i, 12 + parseInt(j)*2)),
+                        amount: parseFloat(changeSpreadSheet.getValue(i, 14 + parseInt(j)*2)),
                     };
                     const sum = ZhCalc.round(ZhCalc.mul(data.unit_price, data.amount), totalPriceUnit);
-                    changeSpreadSheet.setValue(i, 13 + j*2, sum !== 0 ? sum : null);
+                    changeSpreadSheet.setValue(i, 15 + j*2, sum !== 0 ? sum : null);
                 }
             }
         },
@@ -133,27 +141,30 @@ $(document).ready(() => {
             const rowCount = changeSpreadSheet.getRowCount();
             let oSum = 0,
                 cSum = 0,
-                sSum = 0;
+                sSum = 0,
+                cdSum = 0;
             for(let i = 0; i < rowCount - 1; i++){
                 oSum = ZhCalc.add(oSum, changeSpreadSheet.getValue(i, 7));
                 cSum = ZhCalc.add(cSum, changeSpreadSheet.getValue(i, 9));
                 sSum = ZhCalc.add(sSum, changeSpreadSheet.getValue(i, 11));
+                cdSum = ZhCalc.add(cdSum, changeSpreadSheet.getValue(i, 13));
             }
             changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 7, oSum !== 0 ? oSum : null);
             changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 9, cSum !== 0 ? cSum : null);
             changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 11, sSum !== 0 ? sSum : null);
+            changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 13, cdSum !== 0 ? cdSum : null);
             // 用户的数据合计
             for (const j in aidList) {
                 let audit_sum = 0;
                 for(let i = 0; i < rowCount - 1; i++){
-                    audit_sum = ZhCalc.add(audit_sum, changeSpreadSheet.getValue(i, 13 + j*2));
+                    audit_sum = ZhCalc.add(audit_sum, changeSpreadSheet.getValue(i, 15 + j*2));
                 }
-                changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 13 + j*2, audit_sum !== 0 ? audit_sum : null);
+                changeSpreadSheet.setValue(changeSpreadSheet.getRowCount() - 1, 15 + j*2, audit_sum !== 0 ? audit_sum : null);
             }
         },
         showHideAudit: function (show = false) {
             const count = changeSpreadSetting.cols.length;
-            for (let i = 12; i < count; i++) {
+            for (let i = 14; i < count; i++) {
                 changeSpreadSheet.setColumnVisible(i, show, GC.Spread.Sheets.SheetArea.viewport);
             }
             changeSpreadSheet.setColumnVisible(10, !show, GC.Spread.Sheets.SheetArea.viewport);

+ 15 - 2
app/public/js/material.js

@@ -88,8 +88,8 @@ function resetTpTable() {
     if (isStageSelf) {
         let html = '';
         for (const ms of materialStageData) {
-            const taxHtml = materialTax ? '                                        <td class="text-center">' + ms.m_tax_tp + '</td>\n' : '';
-            html += '<tr><td>第' + ms.order + '期</td><td class="text-center">' + ms.m_tp + '</td>\n' +
+            const taxHtml = materialTax ? '                                        <td class="text-center">' + (ms.m_tax_tp !== null ? ms.m_tax_tp : '') + '</td>\n' : '';
+            html += '<tr><td>第' + ms.order + '期</td><td class="text-center">' + (ms.m_tp !== null ? ms.m_tp : '') + '</td>\n' +
                 taxHtml +
                 '                                </tr>';
         }
@@ -313,6 +313,19 @@ $(document).ready(() => {
                     }
                 }
             }
+            if (datas.billsData && datas.billsData.length > 0) {
+                if (datas.billsData.length === materialBillsData.length) {
+                    // 全体替换
+                    materialBillsData = datas.billsData;
+                    materialSpreadObj.getMaterialBillsData();
+                } else {
+                    for (const b of datas.billsData) {
+                        const index = _.findIndex(materialBillsData, {id: b.id});
+                        materialBillsData.splice(index, 1, b);
+                        materialSpreadObj.updateOneMaterialBill(materialBillsData[index]);
+                    }
+                }
+            }
         },
         materialSheetReset: function (redo = false) {
             let newMaterialBillsData = _.cloneDeep(materialBillsData);

+ 46 - 17
app/public/js/profile.js

@@ -120,9 +120,12 @@ $(document).ready(function() {
         });
 
         // 移除签章
-        $('#delete-stamp').click(function () {
-            postData('/profile/sign/delete', { type: 'stamp' }, function (result) {
-                $('#stamp-show').html('');
+        $('body').on('click', '.delete-stamp', function () {
+            let imgSrc = $(this).siblings('img').attr('src');
+            imgSrc = _.replace(imgSrc, fujianOssPath, '');
+            const _self = $(this);
+            postData('/profile/sign/delete', { type: 'stamp', src: imgSrc }, function (result) {
+                _self.parents('.stamp-show').remove();
                 toastr.success('移除成功');
             })
         });
@@ -141,6 +144,11 @@ $(document).ready(function() {
         // 上传签名
         $('#sign-upload').change(function () {
             const file = this.files[0];
+            const filesize = file.size;
+            if (filesize > 1 * 1024 * 1024) {
+                toastr.error('存在上传文件大小过大!');
+                return false;
+            }
             const ext = file.name.toLowerCase().split('.').splice(-1)[0];
             const imgStr = /(jpg|jpeg|png|bmp|BMP|JPG|PNG|JPEG)$/;
             if (!imgStr.test(ext)) {
@@ -160,23 +168,44 @@ $(document).ready(function() {
 
         // 上传签章
         $('#stamp-upload').change(function () {
-            const file = this.files[0];
-            const ext = file.name.toLowerCase().split('.').splice(-1)[0];
-            const imgStr = /(jpg|jpeg|png|bmp|BMP|JPG|PNG|JPEG)$/;
-            if (!imgStr.test(ext)) {
-                toastr.error('请上传正确的图片格式文件');
+            const hadstamp = $('#show-stamp .stamp-show').length;
+            const files = this.files;
+            if (hadstamp + files.length > 5) {
+                toastr.error('最多只能5个签章');
                 return
             }
-            if ($(this).val()) {
-                const formData = new FormData();
-                formData.append('type', 'stamp');
-                formData.append('file', this.files[0]);
-                postDataWithFile('/profile/sign/upload', formData, function (result) {
-                    const html = '<img src="'+ fujianOssPath + result.stamp_path +'" width="90">';
-                    $('#stamp-show').html(html);
-                    $('#stamp-upload').val('');
-                });
+            const formData = new FormData();
+            for (const file of files) {
+                if (file === undefined) {
+                    toast('未选择上传文件!', 'error');
+                    return false;
+                }
+                const ext = file.name.toLowerCase().split('.').splice(-1)[0];
+                const imgStr = /(jpg|jpeg|png|bmp|BMP|JPG|PNG|JPEG)$/;
+                if (!imgStr.test(ext)) {
+                    toastr.error('请上传正确的图片格式文件');
+                    return
+                }
+                const filesize = file.size;
+                if (filesize > 1 * 1024 * 1024) {
+                    toastr.error('存在上传文件大小过大!');
+                    return false;
+                }
+                formData.append('file[]', file);
             }
+            postDataWithFile('/profile/stamp/upload', formData, function (result) {
+                let html = '';
+                for (const [index, sp] of result.stamp_path.entries()) {
+                    html += '<div class="position-absolute fixed-top stamp-show" style="left:'+ (50 + index*130) + 'px;top: 280px;width: 100px">\n' +
+                        '                                    <div class="position-relative">\n' +
+                        '                                        <a href="javascript:void(0);" title="移除签章" class="position-absolute delete-stamp" style="right: 0;top: 0;color: red;font-size:20px;font-weight: bold;text-decoration:none;">×</a>\n' +
+                        '                                        <img src="'+ fujianOssPath + sp +'" width="90">\n' +
+                        '                                    </div>\n' +
+                        '                                </div>';
+                }
+                $('#show-stamp').html(html);
+                $('#stamp-upload').val('');
+            });
         })
     } catch (error) {
         console.log(error);

+ 71 - 8
app/public/report/js/rpt_signature.js

@@ -137,6 +137,9 @@ let rptSignatureHelper = {
             }
             let roleRel = null;
             if (directAcc) {
+
+              
+
                 rptSignatureHelper.pushDomElementByUser(elementsStrArr, userAcc.name, userAcc.role);
                 // 还有ROLE_REL_LIST
                 let roleRelObj = {};
@@ -150,7 +153,7 @@ let rptSignatureHelper = {
                 roleRelObj.type = '用户';
                 roleRelObj.sign_output = [NORMAL_SIGN_STR]; // 默认是签字(还有:COMPANY_SIGN_STR:单位章, PRIVATE_SIGN_STR:个人章)
                 roleRelObj.company_stamp_path = rptSignatureHelper._getCompanySign(directAcc.company);
-                roleRelObj.private_stamp_path = (userAcc.stamp_path && userAcc.stamp_path !== '') ? userAcc.stamp_path : '';
+                roleRelObj.private_stamp_path = rptSignatureHelper._get_newPrivate_stamp_path(roleRelObj,userAcc);
                 roleRelObj.role = (userAcc.role === '')?DFT_ROLE_NAME:userAcc.role;
                 ROLE_REL_LIST.push(roleRelObj);
                 roleRel = roleRelObj;
@@ -168,7 +171,7 @@ let rptSignatureHelper = {
                 roleRelObj.acc_id = userAcc.id;
                 roleRelObj.sign_output = [NORMAL_SIGN_STR]; // 默认是签字(还有:COMPANY_SIGN_STR:单位章, PRIVATE_SIGN_STR:个人章)
                 roleRelObj.company_stamp_path = rptSignatureHelper._getCompanySign(userAcc.company);
-                roleRelObj.private_stamp_path = (userAcc.stamp_path && userAcc.stamp_path !== '') ? userAcc.stamp_path : null;
+                roleRelObj.private_stamp_path = rptSignatureHelper._get_newPrivate_stamp_path(roleRelObj,userAcc);
                 roleRelObj.type = '角色';
                 roleRelObj.role = (userAcc.role === '')?DFT_ROLE_NAME:userAcc.role;
                 roleRelObj.role_name = roleAcc.name;
@@ -253,7 +256,7 @@ let rptSignatureHelper = {
                             }
                             const userAcc = rptSignatureHelper.getUserAccount(role_rel.acc_id);
                             if (userAcc) {
-                                role_rel.private_stamp_path = (userAcc.stamp_path && userAcc.stamp_path !== '') ? userAcc.stamp_path : '';
+                                role_rel.private_stamp_path = rptSignatureHelper._get_newPrivate_stamp_path(role_rel,userAcc);
                                 role_rel.company_stamp_path = rptSignatureHelper._getCompanySign(userAcc.company);
                             }
                     
@@ -280,7 +283,8 @@ let rptSignatureHelper = {
             }
         }
     },
-    checkAndShowCrossTendersESignature: function () {
+    checkAndShowCrossTendersESignature: function (fujianOssPath) {
+        rptSignatureHelper.fujianOssPath=fujianOssPath;
         let btnDom = $('#btn_cross_tender')[0];
         if (zTreeOprObj.currentNode) {
             if (btnDom) btnDom.style.display = '';
@@ -312,7 +316,7 @@ let rptSignatureHelper = {
         const companySignChkStr = (role_rel.sign_output.indexOf(COMPANY_SIGN_STR) >= 0) ? 'checked' : '';
         const privateSignChkStr = (role_rel.sign_output.indexOf(PRIVATE_SIGN_STR) >= 0) ? 'checked' : '';
         // 1. 签章类型:签字 单位章 个人章....
-        elementsStrArr.push('<div class="col-6">');
+        elementsStrArr.push('<div class="col-8">');
         elementsStrArr.push('   <div class="form-control form-control-sm d-inline pt-2">');
         elementsStrArr.push('       <div class="form-check form-check-inline px-2">');
         elementsStrArr.push(`           <input class="form-check-input" type="checkbox" id="${idSuffixStr}_sign1" value="option1" ${normalSignChkStr} onchange="rptSignatureHelper._changeSignType(this, '${role_rel.signature_name}', '${NORMAL_SIGN_STR}')" >`);
@@ -322,6 +326,9 @@ let rptSignatureHelper = {
         // let chkType = hasIndividualStamp ? `radio` : 'checkbox';
         const chkType = 'checkbox';
         let rdoNameStr = `dtp_${role_rel.signature_name}_${rptSignatureHelper.currentSelectedESignParentDivId}`;
+        // 个人章列表
+        const stampPathList=userAcc.stamp_path?userAcc.stamp_path.split('!;!'):[];
+
         if (hasIndividualStamp) {
             elementsStrArr.push('       <div class="form-check form-check-inline mx-1">');
             elementsStrArr.push('           <div class="form-group">');
@@ -330,8 +337,11 @@ let rptSignatureHelper = {
             elementsStrArr.push(`                   <label class="form-check-label" for="${idSuffixStr}_sign2">单位章</label>`);
             elementsStrArr.push('               </div>');
             elementsStrArr.push('               <div class="form-check form-check-inline">');
-            elementsStrArr.push(`                   <input class="form-check-input" type="${chkType}" id="${idSuffixStr}_sign3" value="individualStamp" name="${rdoNameStr}" onchange="rptSignatureHelper._changeSignType(this, '${role_rel.signature_name}', '${PRIVATE_SIGN_STR}')" ${privateSignChkStr}>`);
+            elementsStrArr.push(`                   <input class="form-check-input" type="${chkType}" id="${idSuffixStr}_sign3" value="individualStamp" name="${rdoNameStr}" onchange="rptSignatureHelper._changeSignType(this, '${role_rel.signature_name}', '${PRIVATE_SIGN_STR}','${userAcc.stamp_path}')" ${privateSignChkStr}>`);
             elementsStrArr.push(`                   <label class="form-check-label" for="${idSuffixStr}_sign3">个人章</label>`);
+            if(stampPathList.length>1){
+            elementsStrArr.push(`                   <a class="pl-2" href="#chose-private-stamp-path" data-toggle="modal" data-target="#chose-private-stamp-path" onclick="rptSignatureHelper.currentSelectedESignAccDom = this.parentNode;rptSignatureHelper.initChosePrivateStampPath('${userAcc.stamp_path}','${role_rel.signature_name}') ">选择个人章</a>`);
+            } 
             elementsStrArr.push('               </div>');
             elementsStrArr.push('           </div>');
             elementsStrArr.push('       </div>');
@@ -344,7 +354,7 @@ let rptSignatureHelper = {
         elementsStrArr.push('   </div>');
         elementsStrArr.push('</div>');
         // 2. 日期
-        elementsStrArr.push('<div class="col-6">');
+        elementsStrArr.push('<div class="col-4">');
         let dftDate = '';
         if (role_rel.sign_date !== '' && role_rel.sign_date.length > 20) {
             dftDate = (new Date(role_rel.sign_date)).Format('yyyy-MM-dd');
@@ -861,13 +871,17 @@ let rptSignatureHelper = {
             }
         }
     },
-    _changeSignType: function(dom, signature_name, chkStr) {
+    _changeSignType: function(dom, signature_name, chkStr, userStamp) {
         for (const roleRel of ROLE_REL_LIST) {
             if (roleRel.signature_name === signature_name) {
                 if (dom.checked) {
                     if (roleRel.sign_output.indexOf(chkStr) < 0) {
                         roleRel.sign_output.push(chkStr);
                     }
+                    if(chkStr==='private_stamp'&&!roleRel.private_stamp_path && userStamp){
+                        roleRel.private_stamp_path = userStamp.split('!;!')[0] ;
+                        console.log(roleRel.private_stamp_path);
+                    }
                 } else {
                     let idx = roleRel.sign_output.indexOf(chkStr);
                     if (idx >= 0) {
@@ -908,6 +922,53 @@ let rptSignatureHelper = {
         targetCell.area.Right = pLeft + STD_STAMP_SIZE_WIDTH;
         targetCell.area.Bottom = pTop + STD_STAMP_SIZE_HEIGHT;
     },
+    initChosePrivateStampPath:function(stampPathList,signature_name){
+        let currentStamp='';
+        const targetNode= ROLE_REL_LIST.find(item=>item.signature_name===signature_name);
+        if(targetNode) currentStamp=targetNode.private_stamp_path
+        let content=`<div class='row justify-content-md-center'>`;
+        stampPathList.split('!;!').forEach(item=>{
+            content+=`<div class="card col-3 p-2 m-3 d-flex ${currentStamp===item?'card-gk-active':''} stamp-img">
+                            <div class="p-0 private-stamp-img">
+                                <div  class="sel-width check-state ${currentStamp===item?'sel-blue':''} "></div>
+                                <img src="${rptSignatureHelper.fujianOssPath}${item}" data-src='${item}' class="img-fluid" alt="...">
+                            </div>
+                        </div>`;
+        })
+        
+        for(let i=0;i<stampPathList.length%3;i++){
+            content+=`<div class="col-3 p-2 m-3"></div>`;
+        }
+
+        content+=` </div><div class='privateStampRoleName' data-name='${signature_name}'></div>`;
+
+        $('#chose-private-stamp-path .modal-body').empty().append(content);
+        $('.stamp-img').on('click',(e)=>{
+            $('.stamp-img').removeClass('card-gk-active');
+            $('.stamp-img').find('.sel-width').removeClass('sel-blue');
+            $(e.currentTarget).addClass('card-gk-active');
+            $(e.currentTarget).find('.sel-width').addClass('sel-blue');
+        })
+    },
+    setPrivateStamp(e){
+        const imgSrc= $('.stamp-img.card-gk-active').find('.img-fluid').data('src');
+        const privateStampRoleName=$('.privateStampRoleName').data('name');
+        const targetNode= ROLE_REL_LIST.find(item=>item.signature_name==privateStampRoleName);
+        targetNode.private_stamp_path=imgSrc;
+        $('#chose-private-stamp-path').modal('hide');
+    },
+    _get_newPrivate_stamp_path(roleRelObj,userAcc){
+        if(!roleRelObj.private_stamp_path){
+            if(!userAcc.stamp_path) return '';
+            if(userAcc.stamp_path.split('!;!').length===1){
+                return userAcc.stamp_path;
+            }else{
+                return userAcc.stamp_path.split('!;!')[0];
+            }
+        }
+        return roleRelObj.private_stamp_path;
+
+    }
 }
 
 function _getSignDateByAllScenarios(userAccId) {
@@ -1176,3 +1237,5 @@ function getHttpBlobText(url) {
         xhr.send();
     });
 }
+
+

+ 1 - 0
app/router.js

@@ -574,6 +574,7 @@ module.exports = app => {
     // app.get('/profile/netcasign/upload', sessionAuth, 'profileController.netcasignload');
     app.post('/profile/sign/delete', sessionAuth, 'profileController.signDelete');
     app.post('/profile/sign/upload', sessionAuth, 'profileController.signUpload');
+    app.post('/profile/stamp/upload', sessionAuth, 'profileController.stampUpload');
     app.get('/profile/safe', sessionAuth, 'profileController.safe');
     app.post('/profile/save', sessionAuth, 'profileController.saveBase');
     app.post('/profile/password', sessionAuth, 'profileController.modifyPassword');

+ 4 - 0
app/service/material_bills.js

@@ -292,6 +292,9 @@ module.exports = app => {
                         await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id, id: ms_id } });
                 }
                 await transaction.update(this.tableName, data);
+                if (this.ctx.material.is_stage_self) {
+                    result.billsData = await transaction.select(this.tableName, { where: { id: data.id } });
+                }
                 result.m_tp = await this.calcMaterialMTp(transaction);
                 await transaction.commit();
                 return result;
@@ -410,6 +413,7 @@ module.exports = app => {
                     await this.ctx.service.materialStage.updateMtp(transaction, ms_id);
                     result.stageBillsData = await transaction.select(this.ctx.service.materialStageBills.tableName, { where: { mid: this.ctx.material.id } });
                     result.stageData = await transaction.select(this.ctx.service.materialStage.tableName, { where: { mid: this.ctx.material.id } });
+                    result.billsData = await transaction.select(this.tableName, { where: { mid: this.ctx.material.id } });
                 }
                 result.m_tp = await this.calcMaterialMTp(transaction);
                 await transaction.commit();

+ 1 - 1
app/view/dashboard/index.ejs

@@ -18,7 +18,7 @@
     <div class="content-wrap my-3">
         <% if (!authMobile) { %>
             <div class="text-danger px-3 mb-3 mobile-height">
-                <strong>您的账号未认证手机。</strong> 设置认证手机后,可以用于「找回密码」及接收「短信通知」。<a class="badge badge-danger" href="/profile/sms">点击设置</a>
+                <strong>您的账号未认证手机。</strong> 设置认证手机后,可以用于 找回密码 及 接收验证码。<a class="badge badge-danger" href="/profile/sms">点击设置</a>
             </div>
         <% } %>
         <% if (maintainData.status !== maintainConst.status.notset && new Date().getTime() + (86400*1000) > parseFloat(maintainData.maintain_time)) { %>

+ 4 - 4
app/view/material/info.ejs

@@ -184,9 +184,9 @@
                                 </thead>
                                 <tbody id="materialStageTable">
                                 <% for (const ms of materialStageData) { %>
-                                <tr><td>第<%- ms.order %>期</td><td class="text-center"><%- ms.m_tp %></td>
+                                <tr><td>第<%- ms.order %>期</td><td class="text-center"><%- ms.m_tp !== null ? ms.m_tp : null %></td>
                                     <% if (material.material_tax) { %>
-                                        <td class="text-center"><%- ms.m_tax_tp %></td>
+                                        <td class="text-center"><%- ms.m_tax_tp !== null ? ms.m_tax_tp : null %></td>
                                     <% } %>
                                 </tr>
                                 <% } %>
@@ -228,12 +228,12 @@
 <script>
     const materialType = JSON.parse('<%- materialType %>');
     const isStageSelf = parseInt('<%- material.is_stage_self %>');
-    const editTaxPermission = <%- material.editTaxPermission %>;
+    const editTaxPermission = <%- material.editTaxPermission ? material.editTaxPermission : false %>;
     const editForAudit = <%- material.editForAudit %>;
     let materialBillsData = JSON.parse(unescape('<%- escape(JSON.stringify(materialBillsData)) %>'));
     let materialStageData = isStageSelf ? JSON.parse(unescape('<%- escape(JSON.stringify(materialStageData)) %>')) : [];
     let materialStageBillsData = isStageSelf ? JSON.parse(unescape('<%- escape(JSON.stringify(materialStageBillsData)) %>')) : [];
-    const materialListData = JSON.parse('<%- JSON.stringify(materialListData) %>');
+    const materialListData = JSON.parse(unescape('<%- escape(JSON.stringify(materialListData)) %>'));
     const readOnly = <%- material.readOnly %>;
     const materialID = <%- material.id %>;
     const materialTax = <%- material.material_tax %>;

+ 29 - 19
app/view/profile/sign.ejs

@@ -15,9 +15,10 @@
                 </nav>
                 <% } %>
                 <div class="row m-0">
-                    <div class="col-5 my-3">
+                    <div class="col-5 my-2">
                         <!--账号资料-->
                         <form>
+                            <div class="pb-2"><b>签字管理</b></div>
                             <div class="form-group">
                                 <div class="form-check form-check-inline">
                                     <input class="form-check-input sign-type" type="radio" name="sign" id="sign-type-1" value="1" checked>
@@ -39,31 +40,40 @@
                                 <small class="form-text text-danger">微信扫码使用在线手写程序</small>
                             </div>
                             <button type="button" class="btn btn-danger btn-sm" id="delete-sign">移除签名</button>
+                            <div class="mt-2 py-2"><b>签章管理</b></div>
                             <div class="form-group">
-                                <label for="stamp">上传签章</label>
-                                <input type="file" class="form-control-file" id="stamp-upload">
+                                <label for="stamp">上传签章(最多上传5个)</label>
+                                <input type="file" class="form-control-file" multiple id="stamp-upload">
                                 <small class="form-text text-danger">图片大小为600x300,格式PNG透明背景。</small>
+                                <small class="form-text text-danger">点击预览签章图片上删除按钮,即可移除签章</small>
                             </div>
-                            <button type="button" class="btn btn-sm btn-danger" id="delete-stamp">移除签章</button>
-                            <div class="form-group">
-                                <label>签名图预览</label>
-                                <div>
+                            <!--<button type="button" class="btn btn-sm btn-danger" id="delete-stamp">移除签章</button>-->
+                        </form>
+                    </div>
+                    <div class="col-12 w-100">
+                        <div class="mb-2"><b>签名/签章图预览</b></div>
+                        <div>
+                            <div class="position-relative">
+                                <img src="/public/images/baobiao3.png">
+                                <div class="position-absolute fixed-top" id="sign-show" style="left:290px;top:320px">
+                                    <% if (accountData.sign_path !== '') { %>
+                                        <img src="/public/upload/sign/<%= accountData.sign_path %>" width="90">
+                                    <% } %>
+                                </div>
+                                <div id="show-stamp">
+                                <% if (accountData.stamp_path) { %>
+                                <% for (const [index,sp] of accountData.stamp_path.split('!;!').entries()) { %>
+                                <div class="position-absolute fixed-top stamp-show" style="left:<%- (50 + index*130) %>px;top: 280px;width: 100px">
                                     <div class="position-relative">
-                                        <img src="/public/images/baobiao3.png">
-                                        <div class="position-absolute fixed-top" id="sign-show" style="left:290px;top:320px">
-                                            <% if (accountData.sign_path !== '') { %>
-                                                <img src="/public/upload/sign/<%= accountData.sign_path %>" width="90">
-                                            <% } %>
-                                        </div>
-                                        <div class="position-absolute fixed-top" id="stamp-show" style="left:300px;top:260px">
-                                            <% if (accountData.stamp_path) { %>
-                                                <img src="<%- fujianOssPath + accountData.stamp_path %>" width="90">
-                                            <% } %>
-                                        </div>
+                                        <a href="javascript:void(0);" title="移除签章" class="position-absolute delete-stamp" style="right: 0;top: 0;color: red;font-size:20px;font-weight: bold;text-decoration:none;">×</a>
+                                        <img src="<%- fujianOssPath + sp %>" width="90">
                                     </div>
                                 </div>
+                                <% } %>
+                                <% } %>
+                                </div>
                             </div>
-                        </form>
+                        </div>
                     </div>
                 </div>
             </div>

+ 2 - 1
app/view/report/index.ejs

@@ -165,7 +165,7 @@
                             <% if (!pageShow.openNetCaSign) { %>
                             <div class="panel" id="pnl_eSignature">
                                 <div class="panel-body">
-                                    <button class="btn btn-outline-primary btn-sm" type="button" data-toggle="modal" data-target="#eSignature" onclick="rptSignatureHelper.resetESignature(zTreeOprObj.currentRptPageRst, 'eSignatureBodyDiv'); rptSignatureHelper.checkAndShowCrossTendersESignature();">
+                                    <button class="btn btn-outline-primary btn-sm" type="button" data-toggle="modal" data-target="#eSignature" onclick="rptSignatureHelper.resetESignature(zTreeOprObj.currentRptPageRst, 'eSignatureBodyDiv'); rptSignatureHelper.checkAndShowCrossTendersESignature(fujianOssPath);">
                                         <i class="fa fa-pencil"></i><br>
                                         签字
                                     </button>
@@ -400,6 +400,7 @@
     const CONSTRUCT_UNIT_LIST = <%- unitList %>;
     const ROLE_LIST = <%- role_list %>;
     const CUST_NAME = '<%- ctx.session.sessionUser.name %>';
+    const fujianOssPath = '<%- ctx.app.config.fujianOssPath %>';
     const PRE_PAY = <%- prePay %>;
     if (localStorage[CUST_NAME + '_custCfg']) {
         CUST_CFG = JSON.parse(localStorage[CUST_NAME + '_custCfg']);

+ 21 - 0
app/view/report/rpt_all_popup.ejs

@@ -314,6 +314,27 @@
         </div>
     </div>
 </div>
+<!--选择个人章-->
+<div class="modal fade" id="chose-private-stamp-path" data-backdrop="static">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title" id="audit-select-title">选择个人章</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+               
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button id="audit-select-ok" class="btn btn-primary btn-sm" onclick="rptSignatureHelper.setPrivateStamp(this)">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+
 <!--选择审批人-->
 <div class="modal fade" id="audit-select" data-backdrop="static">
     <div class="modal-dialog" role="document">

+ 3 - 1
sql/update.sql

@@ -3,4 +3,6 @@ ADD COLUMN `push_count`  int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '执行推
 -- 以上于2022/11/2更新uat、prod,下次更新时,不可执行
 
 ALTER TABLE `zh_cooperation_confirm`
-ADD COLUMN `locked`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否锁定' AFTER `create_time`;
+ADD COLUMN `locked`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否锁定' AFTER `create_time`;
+
+ALTER TABLE `zh_project_account` CHANGE `stamp_path` `stamp_path` VARCHAR(5000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户签章oss地址';