소스 검색

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

MaiXinRong 4 년 전
부모
커밋
95b80ddb42
39개의 변경된 파일3899개의 추가작업 그리고 198개의 파일을 삭제
  1. 42 0
      app/const/page_show.js
  2. 88 1
      app/controller/profile_controller.js
  3. 8 3
      app/controller/report_archive_controller.js
  4. 1 9
      app/controller/report_controller.js
  5. 27 12
      app/controller/sign_controller.js
  6. 1 1
      app/controller/tender_controller.js
  7. 1 1
      app/middleware/tender_check.js
  8. 25 0
      app/public/js/draw.js
  9. 5 5
      app/public/js/profile.js
  10. 2971 0
      app/public/netcasign/js/appPackage.js
  11. 20 15
      app/public/netcasign/js/netcasealpdf.js
  12. 3 3
      app/public/report/js/jpc_output_value_define.js
  13. 21 0
      app/public/report/js/rpt_archive.js
  14. 16 0
      app/public/report/js/rpt_main.js
  15. 14 0
      app/public/report/js/rpt_preview_common.js
  16. 2 10
      app/public/report/js/rpt_print.js
  17. 8 7
      app/reports/rpt_component/jpc_value_define.js
  18. 4 0
      app/router.js
  19. 56 0
      app/service/netcasign.js
  20. 15 3
      app/service/project_account.js
  21. 151 0
      app/view/profile/netcasign.ejs
  22. 42 36
      app/view/profile/sign.ejs
  23. 62 0
      app/view/profile/sign_modal.ejs
  24. 2 2
      app/view/profile/sub_menu.ejs
  25. 126 4
      app/view/report/archive_pdf.ejs
  26. 17 0
      app/view/report/index.ejs
  27. 17 8
      app/view/report/index_archive.ejs
  28. 63 0
      app/view/report/index_archive_modal.ejs
  29. 7 7
      app/view/report/rpt_all_popup.ejs
  30. 52 9
      app/view/report/rpt_print.ejs
  31. 0 49
      app/view/report/rpt_printA3.ejs
  32. 23 4
      app/view/sign/info.ejs
  33. 2 2
      app/view/stage/stage_sub_menu.ejs
  34. 2 2
      app/view/stage/stage_sub_mini_menu.ejs
  35. 1 1
      app/view/tender/detail.ejs
  36. 1 1
      app/view/tender/detail_modal.ejs
  37. 1 1
      app/view/tender/tender_sub_menu.ejs
  38. 1 1
      app/view/tender/tender_sub_mini_menu.ejs
  39. 1 1
      config/menu.js

+ 42 - 0
app/const/page_show.js

@@ -0,0 +1,42 @@
+'use strict';
+
+/**
+ * 前台页面展示相关
+ *
+ * @author Ellisran
+ * @date
+ * @version
+ */
+
+const pageStatus = {
+    show: 1,
+    hide: 0,
+};
+
+// const pageControl = [
+//     { title: '开启「部位台帐」', name: 'bwtz', value: pageStatus.show, type: 'checkbox' },
+//     { title: '开启「投资进度」功能', name: 'xxjd', value: pageStatus.show, type: 'checkbox' },
+//     { title: '开启「其他台账」功能', name: 'stageExtra', value: pageStatus.show, type: 'checkbox' },
+//     { title: '关闭报表「导出PDF」', name: 'closeExportPdf', value: pageStatus.show, type: 'checkbox' },
+//     { title: '关闭报表「导出Excel」', name: 'closeExportExcel', value: pageStatus.show, type: 'checkbox' },
+//     { title: '关闭报表「水印」', name: 'closeWatermark', value: pageStatus.show, type: 'checkbox' },
+//     { title: '开启报表「跨标段批量签名」', name: 'openSign', value: pageStatus.show, type: 'checkbox' },
+//     { title: '开启签名「网证通电子签名」', name: 'openNetCaSign', value: pageStatus.show, type: 'checkbox' },
+// ];
+
+const defaultSetting = {
+    bwtz: 0,
+    xxjd: 0,
+    stageExtra: 1,
+    closeExportPdf: 0,
+    closeExportExcel: 0,
+    closeWatermark: 0,
+    openSign: 0,
+    openNetCaSign: 0,
+};
+
+
+module.exports = {
+    pageStatus,
+    defaultSetting,
+};

+ 88 - 1
app/controller/profile_controller.js

@@ -252,6 +252,90 @@ module.exports = app => {
         }
 
         /**
+         * 网证通电子签名页
+         *
+         * @param {object} ctx - egg全局变量
+         * @return {void}
+         */
+        async netcasign(ctx) {
+            // 获取当前用户数据
+            const sessionUser = ctx.session.sessionUser;
+
+            // 获取账号数据
+            const accountData = await ctx.service.projectAccount.getDataByCondition({ id: sessionUser.accountId });
+            const signData = await ctx.service.netcasign.getDataByCondition({ uid: sessionUser.accountId });
+
+            const renderData = {
+                accountData,
+                signData,
+            };
+            await this.layout('profile/netcasign.ejs', renderData, 'profile/sign_modal.ejs');
+        }
+
+        /**
+         * 网证通电子签名页面操作
+         *
+         * @param {object} ctx - egg全局变量
+         * @return {void}
+         */
+        async signSave(ctx) {
+            const response = {
+                err: 0,
+                msg: '',
+            };
+            try {
+                const sessionUser = ctx.session.sessionUser;
+                const data = JSON.parse(ctx.request.body.data);
+                let signData;
+                switch (data.type) {
+                    case 'bind':
+                        signData = await ctx.service.netcasign.getDataByCondition({ keyId: data.updateData.keyId });
+                        if (signData) {
+                            const accountData = await ctx.service.projectAccount.getDataByCondition({ id: signData.uid });
+                            throw '该Ukey已绑定于 ' + accountData.name + ', 不可重复绑定';
+                        }
+
+                        const result = await ctx.service.netcasign.add(data.updateData, sessionUser.accountId);
+                        if (!result) {
+                            throw '绑定Ukey失败';
+                        }
+                        response.data = await ctx.service.netcasign.getDataByCondition({ uid: sessionUser.accountId });
+                        break;
+                    case 'unbind':
+                        signData = await ctx.service.netcasign.getDataByCondition({ uid: sessionUser.accountId });
+                        if (!signData) {
+                            throw '当前用户不存在绑定证书,解除绑定失败';
+                        }
+                        await ctx.service.netcasign.del(sessionUser.accountId);
+                        break;
+                    case 'savesign':
+                        signData = await ctx.service.netcasign.getDataByCondition({ uid: sessionUser.accountId });
+                        if (!signData) {
+                            throw '当前用户不存在绑定证书';
+                        }
+                        await ctx.service.netcasign.save({ sign_base64: data.sign_base64 }, signData.id);
+                        break;
+                    case 'delsign':
+                        signData = await ctx.service.netcasign.getDataByCondition({ uid: sessionUser.accountId });
+                        if (!signData) {
+                            throw '当前用户不存在绑定证书';
+                        }
+                        if (signData && !signData.sign_base64) {
+                            throw '当前用户不存在签名,移除签名失败';
+                        }
+                        await ctx.service.netcasign.save({ sign_base64: null }, signData.id);
+                        break;
+                    default:throw '参数有误';
+                }
+            } catch (error) {
+                response.err = 1;
+                response.msg = error.toString();
+            }
+
+            ctx.body = response;
+        }
+
+        /**
          * 电子签名删除
          *
          * @param {object} ctx - egg全局变量
@@ -297,7 +381,10 @@ module.exports = app => {
                 // 获取当前用户数据
                 const sessionUser = ctx.session.sessionUser;
 
-                const text = 'http://' + ctx.request.header.host + '/sign?user_id=' + sessionUser.accountId + '&app_token=' + sessionUser.sessionToken;
+                let text = ctx.protocol + '://' + ctx.host + '/sign?user_id=' + sessionUser.accountId + '&app_token=' + sessionUser.sessionToken;
+                if (ctx.query.from === 'netcasign') {
+                    text += '&from=netcasign';
+                }
 
                 // 大小默认5,二维码周围间距默认1
                 const img = qr.image(text || '', { type: 'png', size: size || 5, margin: margin || 1 });

+ 8 - 3
app/controller/report_archive_controller.js

@@ -83,8 +83,9 @@ module.exports = app => {
                 auditConst: auditConst.stage,
                 archiveList,
                 archiveEncryptionList,
+                can_netcasign: ctx.session.sessionProject.page_show.openNetCaSign === 1,
             };
-            await this.layout('report/index_archive.ejs', renderData);
+            await this.layout('report/index_archive.ejs', renderData, 'report/index_archive_modal.ejs');
         }
 
         async getReportArchive(ctx) {
@@ -93,7 +94,8 @@ module.exports = app => {
 
             const archives = await ctx.service.rptArchive.getPrjStgArchive(params.prjId, params.stgId);
             const archiveEncryptions = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(params.prjId, params.stgId);
-            let archiveList = [], archiveEncryptionList = [];
+            let archiveList = [];
+            let archiveEncryptionList = [];
             if (archives.length > 0) {
                 archiveList = JSON.parse(archives[0].content);
             }
@@ -374,7 +376,10 @@ module.exports = app => {
         }
 
         async pdfShow(ctx) {
-            await ctx.render('report/archive_pdf.ejs');
+            const renderData = {
+                can_netcasign: ctx.session.sessionProject.page_show.openNetCaSign === 1,
+            };
+            await ctx.render('report/archive_pdf.ejs', renderData);
         }
     }
     return ReportArchiveController;

+ 1 - 9
app/controller/report_controller.js

@@ -73,10 +73,6 @@ module.exports = app => {
             try {
                 await this._getStageAuditViewData(ctx);
                 let pageShow = ctx.session.sessionProject.page_show;
-                if (pageShow === null || pageShow === undefined) {
-                    pageShow = {};
-                }
-                // console.log(pageShow);
                 pageShow.showArchive = 0;
                 const tender = ctx.tender;
                 const stage = ctx.stage;
@@ -334,11 +330,7 @@ module.exports = app => {
                     size: pageSize,
                     // orientation: params.orientation,
                 };
-                if (pageSize === 'A3') {
-                    await ctx.render('report/rpt_printA3.ejs', renderData);
-                } else {
-                    await ctx.render('report/rpt_print.ejs', renderData);
-                }
+                await ctx.render('report/rpt_print.ejs', renderData);
             } catch (err) {
                 this.log(err);
                 console.log(err);

+ 27 - 12
app/controller/sign_controller.js

@@ -30,9 +30,11 @@ module.exports = app => {
                 if (userinfo && userinfo.session_token && userinfo.session_token === ctx.query.app_token) {
                     renderData.id = userinfo.id;
                     renderData.name = userinfo.name;
+                    renderData.from = ctx.query.from ? ctx.query.from : '';
                     // renderData.role = userinfo.role;
                 } else {
-                    throw '参数有误, 无法访问本页.';
+                    // throw '参数有误, 无法访问本页';
+                    throw 'token已更新,请重新登录并再次扫码。';
                 }
             } catch (error) {
                 console.log(error);
@@ -49,18 +51,31 @@ module.exports = app => {
          */
         async save(ctx) {
             try {
-                const stream = await ctx.getFileStream({ requireFile: false });
-                const create_time = Date.parse(new Date()) / 1000;
-                const dirName = 'app/public/upload/sign/';
-                const fileName = moment().format('YYYYMMDD') + '_sign_' + create_time + '.png';
-                await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName));
-                await sendToWormhole(stream);
-
-                const result = await ctx.service.projectAccount.update({ sign_path: fileName }, { id: stream.fields.id });
-                if (result) {
-                    ctx.body = { err: 0, msg: '' };
+                if (ctx.request.body && ctx.request.body.id) {
+                    const signData = await ctx.service.netcasign.getDataByCondition({ uid: ctx.request.body.id });
+                    if (!signData) {
+                        throw '当前用户不存在绑定证书';
+                    }
+                    const result = await ctx.service.netcasign.save({ sign_base64: ctx.request.body.sign_base64 }, signData.id);
+                    if (result) {
+                        ctx.body = { err: 0, msg: '' };
+                    } else {
+                        throw '添加数据库失败';
+                    }
                 } else {
-                    throw '添加数据库失败';
+                    const stream = await ctx.getFileStream({ requireFile: false });
+                    const create_time = Date.parse(new Date()) / 1000;
+                    const dirName = 'app/public/upload/sign/';
+                    const fileName = moment().format('YYYYMMDD') + '_sign_' + create_time + '.png';
+                    await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName));
+                    await sendToWormhole(stream);
+
+                    const result = await ctx.service.projectAccount.update({ sign_path: fileName }, { id: stream.fields.id });
+                    if (result) {
+                        ctx.body = { err: 0, msg: '' };
+                    } else {
+                        throw '添加数据库失败';
+                    }
                 }
             } catch (err) {
                 this.log(err);

+ 1 - 1
app/controller/tender_controller.js

@@ -467,7 +467,7 @@ module.exports = app => {
                     renderData.accountList = accountList;
                     renderData.accountGroup = accountGroupList;
                 }
-                if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.xxjd) === 1 && ctx.session.sessionUser.is_admin) {
+                if (ctx.session.sessionProject.page_show.xxjd && ctx.session.sessionUser.is_admin) {
                     // 投资进度内容
                     renderData.scheduleAuditList = await ctx.service.scheduleAudit.getAllDataByCondition({ where: { tid: tender.id } });
                     renderData.scPermission = scheduleConst.permission;

+ 1 - 1
app/middleware/tender_check.js

@@ -77,7 +77,7 @@ module.exports = options => {
             tender.advanceAuditorsId = advanceAuditorsId;
             tender.ledgerUsers = tender.ledger_status === auditConst.status.uncheck ? [tender.data.user_id] : [tender.data.user_id, ...auditorsId];
             this.tender = tender;
-            this.session.sessionProject.page_show = yield this.service.project.getPageshow(this.session.sessionProject.id);
+            // this.session.sessionProject.page_show = yield this.service.project.getPageshow(this.session.sessionProject.id);
             // 投资进度权限获取
             let schedule_permission = scPermission.no;
             if (this.session.sessionUser.accountId === tender.data.user_id) {

+ 25 - 0
app/public/js/draw.js

@@ -217,6 +217,7 @@ Draw.prototype = {
     const xhr = new XMLHttpRequest();
     xhr.withCredentials = true;
     formData.append('id', id);
+    formData.append('from', from);
     formData.append('image', blob, 'sign');
 
     xhr.open('POST', url, true);
@@ -237,5 +238,29 @@ Draw.prototype = {
     };
     xhr.send(formData);
   },
+  uploadBase64(base64, url, success, failure) {
+    const xhr = new XMLHttpRequest();
+    xhr.withCredentials = true;
+    const data = encodeURIComponent('id') + '=' + encodeURIComponent(id) + '&' + encodeURIComponent('sign_base64') + '=' + encodeURIComponent(base64);
+
+    xhr.open('POST', url, true);
+    xhr.setRequestHeader("x-csrf-token", csrf);
+    xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded; charset=utf-8");
+    xhr.onload = () => {
+      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
+        success(xhr.responseText);
+      } else {
+        failure();
+      }
+    };
+    xhr.onerror = (e) => {
+      if (typeof failure === 'function') {
+        failure(e);
+      } else {
+        console.log(`upload img error: ${e}`);
+      }
+    };
+    xhr.send(data);
+  },
 };
 // export default Draw;

+ 5 - 5
app/public/js/profile.js

@@ -120,13 +120,13 @@ $(document).ready(function() {
         });
 
         // 签名模式切换
-        $('.sign-type').click(function () {
+        $('.sign-type').on('click', function () {
             if (parseInt($(this).val()) === 1) {
-                $('#show-upload').hide();
-                $('#show-qrcode').show();
+                $(this).parents('.form-group').siblings('.show-upload').hide();
+                $(this).parents('.form-group').siblings('.show-qrcode').show();
             } else {
-                $('#show-upload').show();
-                $('#show-qrcode').hide();
+                $(this).parents('.form-group').siblings('.show-upload').show();
+                $(this).parents('.form-group').siblings('.show-qrcode').hide();
             }
         });
 

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2971 - 0
app/public/netcasign/js/appPackage.js


+ 20 - 15
app/public/netcasign/js/netcasealpdf.js

@@ -1090,7 +1090,9 @@ var NetcaSignAPI = (function(){
 
     that.getSealConfigInfoFailCallBack = function(res){
         layer.closeAll('loading');
-        alert('获取电子签章客户端配置信息失败:' + res.msg);
+        // alert('获取电子签章客户端配置信息失败:' + res.msg);
+        $('.modal-background').show();
+
     };
     // 本文档找不到可验证的签名
     that.notFoundSignature = function() {
@@ -1269,18 +1271,18 @@ var NetcaSignAPI = (function(){
         if($(".netcafieldInfo").length){
             $(".netcafieldInfo").remove(); //先删除旧的签名域
         }
-        // var params = {
-        //     srcFile: '',
-        //     srcBytes: signBytes,
-		// 	srcStreamId: streamId
-        // };
-        // NetcaPKI.getSignatureFieldInfo(params)
-        //     .Then(function (res) {
-        //         that.getSignatureFieldInfoSuccessCallBack(res,streamId);
-        //     })
-        //     .Catch(function (res) {
-        //         that.getSignatureFieldInfoFailedCallBack(res);
-        //     });
+        var params = {
+            srcFile: '',
+            srcBytes: signBytes,
+			srcStreamId: streamId
+        };
+        NetcaPKI.getSignatureFieldInfo(params)
+            .Then(function (res) {
+                that.getSignatureFieldInfoSuccessCallBack(res,streamId);
+            })
+            .Catch(function (res) {
+                that.getSignatureFieldInfoFailedCallBack(res);
+            });
     };
     that.getSignatureFieldInfoSuccessCallBack = function(res,streamId){
 
@@ -1370,7 +1372,7 @@ var NetcaSignAPI = (function(){
     that.getSignatureFieldInfoFailedCallBack = function(res){
 
         layer.closeAll('loading');
-        alert('签名域信息失败:'+res.msg);
+        // alert('签名域信息失败:'+res.msg);
 
     };
     that.zoomPDFBySelectOptionScale = function(){
@@ -1991,7 +1993,10 @@ var NetcaPDFSeal = (function(){
                             globalPDFViewerApplication.pdfDocument.getData().then(function(data){
                                 // var PDFBytes = NetcaUtils.arrayBufferToBase64(data);
                                 NetcaPDFSeal.setPDFBytes(data);
-                                // NetcaSignAPI.getSealConfigInfo(data);
+                                if (can_netcasign) {
+                                    NetcaSignAPI.getSealConfigInfo(data);
+                                }
+
                             })
                         }
                     }

+ 3 - 3
app/public/report/js/jpc_output_value_define.js

@@ -58,9 +58,9 @@ let JV = {
     FONT_PROP_IDX_STRIKEOUT: 6,
     FONT_PROP_IDX_ANGLE: 7,
 
-    PAGES_SIZE_STR: ["A3", "A4", "A5", "B5", "LETTER", "LEGAL", "EXECUTIVE", "16K"],
-    PAGES_SIZE_IDX: [8, 9, 11, 13, 1, 5, 7, 93],
-    PAGES_SIZE: [[11.69, 16.54], [8.27, 11.69], [5.83, 8.27], [6.93, 9.84], [8.5, 11.0], [8.5, 14.0], [7.25, 10.5], [7.25, 10.5]],
+    PAGES_SIZE_STR: ['A3', 'A4', 'A5', 'B4', 'B5', 'LETTER', 'LEGAL', 'EXECUTIVE', '16K'],
+    PAGES_SIZE_IDX: [8, 9, 11, 12, 13, 1, 5, 7, 93],
+    PAGES_SIZE: [[11.693, 16.535], [8.268, 11.693], [5.827, 8.268], [9.84, 13.898], [6.93, 9.84], [8.5, 11.0], [8.5, 14.0], [7.25, 10.5], [7.25, 10.5]],
 
     OUTPUT_OFFSET: [2,2,1,3],
     OFFSET_IDX_LEFT: 0,

+ 21 - 0
app/public/report/js/rpt_archive.js

@@ -121,6 +121,27 @@ let rptArchiveObj = {
         let me = rptArchiveObj;
         if (me.currentNode && me.currentArchiveUuid) {
             try {
+                const msgSign = _.find(ARCHIVE_ENCRYPTION_LIST, {rpt_id: me.currentNode.ID});
+                console.log(msgSign);
+                let html = '';
+                let pagetr = '';
+                if (msgSign) {
+                    const rows = 12/msgSign.encryption.length < 3 ? 'col-3' : 'col-' + 12/msgSign.encryption.length;
+                    console.log(rows);
+                    for (const [index,role] of msgSign.encryption.entries()) {
+                        html += '<div class="'+ rows +'">\n' +
+                            '                                <div class="custom-control custom-radio custom-control-inline">\n' +
+                            '                                    <input type="radio" value="'+ index +'" id="customRadioInline'+ index +'" name="customRadioInline" class="custom-control-input">\n' +
+                            '                                    <label class="custom-control-label" for="customRadioInline'+ index +'">'+ role.name +'</label>\n' +
+                            '                                </div>\n' +
+                            '                            </div>';
+                    }
+                    for (let i = 1; i <= msgSign.total_page; i++) {
+                        pagetr += '<tr><td>页'+ i +'</td><td>'+ me.currentNode.name +'</td><td></td></tr>';
+                    }
+                }
+                $('#role-list').html(html);
+                $('#page-list').html(pagetr);
                 // let uuIdUrl =  "/getArchivedFileByUUID/" + me.currentArchiveUuid + "/" + stringUtil.replaceAll(me.currentNode.name, "#", "_");
                 // console.log(uuIdUrl);
                 $('#iframe_made').html('<iframe src="/archive/pdf/show?file=https://measure-sign-pdf.oss-cn-shenzhen.aliyuncs.com/archive/'+ me.currentArchiveUuid +'.PDF" height="750px" width="100%" style="border: none;"></iframe>');

+ 16 - 0
app/public/report/js/rpt_main.js

@@ -486,6 +486,7 @@ let zTreeOprObj = {
     displayPageValue: function() {
         let me = zTreeOprObj;
         $("#rpt_page_num")[0].value = me.currentPage + "/" + me.maxPages;
+        $("#rpt_fullscreen_page_num")[0].value = me.currentPage + "/" + me.maxPages;
     }
 };
 
@@ -521,6 +522,21 @@ let canvasOprObj = {
                 zTreeOprObj.showPage(zTreeOprObj.currentPage + 1, canvas);
             }
         }
+    },
+    showFullSreen: function () {
+        if (zTreeOprObj.currentRptPageRst) {
+            let orgH = zTreeOprObj.canvas.height;
+            let orgW = zTreeOprObj.canvas.width;
+            zTreeOprObj.canvas = document.getElementById("fullScrCanvas");
+            zTreeOprObj.canvas.height = orgH;
+            zTreeOprObj.canvas.width = orgW;
+            zTreeOprObj.showPage(zTreeOprObj.currentPage, zTreeOprObj.canvas);
+            $("#btn_show_full_screen").trigger("click");
+            $('#fullscreen').on('hide.bs.modal', function () {
+                zTreeOprObj.canvas = document.getElementById("rptCanvas");
+                zTreeOprObj.showPage(zTreeOprObj.currentPage, zTreeOprObj.canvas);
+            });
+        }
     }
 };
 

+ 14 - 0
app/public/report/js/rpt_preview_common.js

@@ -127,6 +127,19 @@ function printPageLoading_bk() {
 function showPreviewData(svgArr, actAreaArr, scaleFactor, pageSize, orientation, orgPixelSize) {
     let orgHeight = 793, orgWidth = 1122;
     let DFT_MARGIN = 2;
+    getScreenDPI();
+    //*
+    const pi = JV.PAGES_SIZE_STR.indexOf(pageSize);
+    if (pi >= 0) {
+        const sizeArr = JV.PAGES_SIZE[pi];
+        orgHeight = Math.round(sizeArr[0] * SCREEN_DPI[0]);
+        orgWidth = Math.round(sizeArr[1] * SCREEN_DPI[1]);
+    } else if (pageSize.indexOf('自定义') >= 0) {
+        //自定义
+    } else {
+        //其他未定义size(urgly size)
+    }
+    /*/
     if (pageSize === 'A3') {
         orgHeight = 1122;
         orgWidth = 793 * 2;
@@ -135,6 +148,7 @@ function showPreviewData(svgArr, actAreaArr, scaleFactor, pageSize, orientation,
     } else {
         //其他size(LEGAL, 16K etc.)
     }
+    //*/
     let pageHeight = orgHeight * scaleFactor, pageWidth = orgWidth * scaleFactor;
     if (orientation === "纵向") {
         pageHeight = orgWidth * scaleFactor;

+ 2 - 10
app/public/report/js/rpt_print.js

@@ -29,11 +29,7 @@ let rptPrintHelper = {
             sessionStorage.STAGE_AUDIT_ORG = JSON.stringify(STAGE_AUDIT_ORG);
             sessionStorage.current_stage_id = getStageId();
             // sessionStorage.STAGE_AUDIT = JSON.stringify(STAGE_AUDIT);
-            if (sessionStorage.pageSize === 'A3') {
-                window.open('/printReport/A3');
-            } else {
-                window.open('/printReport/A4');
-            }
+            window.open('/printReport/' + sessionStorage.pageSize);
         }
     },
     preview_bk: async function () {
@@ -98,11 +94,7 @@ let rptPrintHelper = {
                     sessionStorage.scaleFactor = 1;
                     sessionStorage.closeWaterMark = getCloseWatermark();
                     sessionStorage.waterMarkStr = COMMON_WATER_MARK_PIC_DATA;
-                    if (sessionStorage.pageSize === 'A3') {
-                        window.open('/printReport/A3');
-                    } else {
-                        window.open('/printReport/A4');
-                    }
+                    window.open('/printReport/' + sessionStorage.pageSize);
                 },
                 function(failRst){
                     sessionStorage.currentPageData = null;

+ 8 - 7
app/reports/rpt_component/jpc_value_define.js

@@ -297,11 +297,12 @@ module.exports = {
     ORIENTATION_LANDSCAPE: 'LANDSCAPE',
     ORIENTATION_PORTRAIT_CHN: '纵向',
     ORIENTATION_LANDSCAPE_CHN: '横向',
-    SIZE_A3: [11.69, 16.54],
-    SIZE_A4: [8.27, 11.69],
-    SIZE_A5: [5.83, 8.27],
+    SIZE_A3: [11.693, 16.535],
+    SIZE_A4: [8.268, 11.693],
+    SIZE_A5: [5.827, 8.268],
+    SIZE_B4: [9.84, 13.898],
     SIZE_B5: [6.93, 9.84],
-    SIZE_LETTER: [8.5, 11.0],
+    SIZE_LETTER: [8.5, 11.0], // 美、加等国的A4规格
     SIZE_LEGAL: [8.5, 14.0],
     SIZE_16K: [7.75, 10.75],
     SIZE_EXECUTIVE: [7.25, 10.5],
@@ -337,9 +338,9 @@ module.exports = {
     PAGE_SELF_DEFINE: '自定义',
     PAGE_SPECIAL_MERGE_POS: 'page_merge_pos',
 
-    PAGES_SIZE_STR: ['A3', 'A4', 'A5', 'B5', 'LETTER', 'LEGAL', 'EXECUTIVE', '16K'],
-    PAGES_SIZE_IDX: [8, 9, 11, 13, 1, 5, 7, 93],
-    PAGES_SIZE: [[11.69, 16.54], [8.27, 11.69], [5.83, 8.27], [6.93, 9.84], [8.5, 11.0], [8.5, 14.0], [7.25, 10.5], [7.25, 10.5]],
+    PAGES_SIZE_STR: ['A3', 'A4', 'A5', 'B4', 'B5', 'LETTER', 'LEGAL', 'EXECUTIVE', '16K'],
+    PAGES_SIZE_IDX: [8, 9, 11, 12, 13, 1, 5, 7, 93],
+    PAGES_SIZE: [[11.693, 16.535], [8.268, 11.693], [5.827, 8.268], [9.84, 13.898], [6.93, 9.84], [8.5, 11.0], [8.5, 14.0], [7.25, 10.5], [7.25, 10.5]],
 
     HUNDRED_PERCENT: 100.0,
 

+ 4 - 0
app/router.js

@@ -412,6 +412,10 @@ module.exports = app => {
     app.get('/profile/sms', sessionAuth, 'profileController.sms');
     app.post('/profile/sms/type', sessionAuth, 'profileController.smsType');
     app.get('/profile/sign', sessionAuth, 'profileController.sign');
+    app.get('/profile/sign/netca', sessionAuth, 'profileController.netcasign');
+    app.post('/profile/sign/save', sessionAuth, 'profileController.signSave');
+    // app.get('/profile/netcasign/delete', sessionAuth, 'profileController.netcasignDelete');
+    // 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.get('/profile/safe', sessionAuth, 'profileController.safe');

+ 56 - 0
app/service/netcasign.js

@@ -0,0 +1,56 @@
+'use strict';
+
+/**
+ * 网证通电子签名数据模型
+ *
+ * @author EllisRan
+ * @date 2021/7/15
+ * @version
+ */
+
+module.exports = app => {
+
+    class Netcasign extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'netcasign';
+        }
+
+        async add(data, uid) {
+            const insertData = {
+                uid,
+                name: data.name,
+                keyId: data.keyId,
+                create_time: new Date(),
+            };
+            const operate = await this.db.insert(this.tableName, insertData);
+            return operate.affectedRows > 0;
+        }
+
+        async del(uid) {
+            return await this.db.delete(this.tableName, { uid });
+        }
+
+        /**
+         * 保存数据
+         *
+         * @param {Object} data - post过来的数据
+         * @param {Number} id - 用于判断修改还是新增的id
+         * @return {boolean} - 操作结果
+         */
+        async save(data, id = 0) {
+            data.id = id;
+            const operate = await this.db.update(this.tableName, data);
+            return operate.affectedRows > 0;
+        }
+    }
+
+    return Netcasign;
+};

+ 15 - 3
app/service/project_account.js

@@ -15,6 +15,7 @@ const SMS = require('../lib/sms');
 const SmsAliConst = require('../const/sms_alitemplate');
 const loginWay = require('../const/setting').loginWay;
 const smsTypeConst = require('../const/sms_type').type;
+const pageShowConst = require('../const/page_show').defaultSetting;
 module.exports = app => {
 
     class ProjectAccount extends app.BaseService {
@@ -133,7 +134,7 @@ module.exports = app => {
                         code: projectData.code,
                         userAccount: projectData.user_account,
                         custom: projectData.custom,
-                        page_show: projectData.page_show ? JSON.parse(projectData.page_show) : null,
+                        page_show: await this.getPageShow(projectData.page_show),
                     };
 
                     // 查找对应数据
@@ -186,7 +187,7 @@ module.exports = app => {
                         name: projectData.name,
                         userAccount: projectData.user_account,
                         custom: projectData.custom,
-                        page_show: projectData.page_show ? JSON.parse(projectData.page_show) : null,
+                        page_show: await this.getPageShow(projectData.page_show),
                     };
 
                     // 查找对应数据
@@ -245,6 +246,17 @@ module.exports = app => {
             return result;
         }
 
+        async getPageShow(page_show) {
+            const info = page_show ? JSON.parse(page_show) : {};
+            console.log(info);
+            console.log(pageShowConst);
+            for (const pi in pageShowConst) {
+                info[pi] = !info[pi] || info[pi] === '' ? pageShowConst[pi] : parseInt(info[pi]);
+                this.ctx.helper._.defaults(info[pi], pageShowConst[pi]);
+            }
+            return info;
+        }
+
         /**
          * 根据项目id获取用户列表
          *
@@ -682,7 +694,7 @@ module.exports = app => {
                 name: projectData.name,
                 userAccount: projectData.user_account,
                 custom: projectData.custom,
-                page_show: projectData.page_show ? JSON.parse(projectData.page_show) : null,
+                page_show: await this.getPageShow(projectData.page_show),
             };
 
             // 查找对应数据

+ 151 - 0
app/view/profile/netcasign.ejs

@@ -0,0 +1,151 @@
+<% include ./sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2>签字管理</h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-body">
+            <div class="sjs-height-0">
+                <% if (ctx.session.sessionProject.page_show.openNetCaSign) { %>
+                <nav class="nav nav-tabs m-3" role="tablist">
+                    <a class="nav-item nav-link active" href="/profile/sign/netca">Ukey认证签名</a>
+                    <a class="nav-item nav-link" href="/profile/sign">签字设置</a>
+                </nav>
+                <% } %>
+                <div class="row m-0">
+                    <div class="col-9 my-3">
+                        <% if (!signData) { %>
+                            <div id="set_ukey" class="form-group">
+                                <label>网证通UKey</label>
+                                <div>
+                                    <button class="btn btn-sm btn-outline-primary" id="getCert">获取证书信息</button>
+                                    <small class="form-text text-danger">请先插入网证通UKey获取证书信息再绑定</small>
+                                    <textarea id="DeviceOutputId" readonly class="form-control mt-1 mb-1" rows="3"></textarea>
+                                    <input type="hidden" id="name" />
+                                    <input type="hidden" id="keyId" />
+                                    <button class="btn btn-sm btn-outline-primary" id="bind_btn">绑定</button>
+                                </div>
+                            </div>
+                        <% } %>
+                        <div id="had_ukey" <% if (!signData) { %>style="display: none"<% } %>>
+                            <div class="form-group">
+                                <label>网证通UKey</label>
+                                <div>
+                                    <small class="form-text text-secondary">已绑证书信息</small>
+                                    <textarea class="form-control mt-1 mb-1" id="had_textarea" readonly rows="3">证书主题:<%- signData ? signData.name : '' %>,keyId:<%- signData ? signData.keyId : '' %></textarea>
+                                    <button class="btn btn-sm btn-outline-danger" data-toggle="modal" data-target="#remove-netcasign">解除绑定</button>
+                                </div>
+                            </div>
+                            <!--账号资料-->
+                            <form>
+                                <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>
+                                        <label class="form-check-label" for="sign-type-1">在线手写签名图</label>
+                                    </div>
+                                    <div class="form-check form-check-inline">
+                                        <input class="form-check-input sign-type" type="radio" name="sign" id="sign-type-2" value="2">
+                                        <label class="form-check-label" for="sign-type-2">上传签名图</label>
+                                    </div>
+                                </div>
+                                <div class="form-group show-upload" style="display: none">
+                                    <label>上传签名图</label>
+                                    <input type="file" class="form-control-file" id="netcasign-upload">
+                                    <small class="form-text text-danger">图片大小为600x300,格式PNG透明背景。</small>
+                                </div>
+                                <div class="form-group show-qrcode">
+                                    <label>在线手写签名</label>
+                                    <div><img src="/profile/qrCode?from=netcasign" width="150"></div>
+                                    <small class="form-text text-danger">微信扫码使用在线手写程序</small>
+                                </div>
+                                <button id="remove-netcasign-sign-btn" type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#remove-netcasign-sign" <% if (!signData || !signData.sign_base64) { %>style="display: none" <% } %>>移除签名</button>
+                                <div class="form-group">
+                                    <label>签名图预览</label>
+                                    <div>
+                                        <div class="position-relative">
+                                            <img src="/public/images/baobiao3.png">
+                                            <div class="position-absolute fixed-top" id="netcasign-show" style="left:290px;top:320px">
+                                                <% if (signData && signData.sign_base64) { %>
+                                                    <img src="data:image/png;base64,<%- signData.sign_base64 %>" width="90">
+                                                <% } %>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </form>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script type="text/javascript">
+    const csrf = '<%= ctx.csrf %>';
+</script>
+<script type="text/javascript" src="/public/js/profile.js"></script>
+<script src="/public/netcasign/js/base64.min.js"></script>
+<script src="/public/netcasign/js/netcawebsocket.js"></script>
+<script src="/public/netcasign/js/appPackage.js"></script>
+<script>
+    $(function () {
+        $('#getCert').click(function () {
+            getCertList();
+        });
+
+        $('#bind_btn').click(function () {
+            if($('#DeviceOutputId').val() == '') {
+                toastr.error('请获取证书信息再绑定');
+                return;
+            }
+            postData('/profile/sign/save', {type: 'bind', updateData: {name: $('#name').val(), keyId: $('#keyId').val()}}, function (result) {
+                toastr.success('绑定成功');
+                $('#set_ukey').hide();
+                $('#had_ukey').show();
+                $('#had_textarea').val('证书主题:'+ result.name +',keyId:' + result.keyId);
+            })
+        });
+
+        $('#unbind_btn').click(function () {
+            postData('/profile/sign/save', {type: 'unbind'}, function (result) {
+                toastr.success('解绑成功');
+                window.location.href = '/profile/sign/netca';
+            })
+        });
+
+        $('#delsign_btn').click(function () {
+            postData('/profile/sign/save', {type: 'delsign'}, function (result) {
+                toastr.success('签名图已删除成功');
+                $('#remove-netcasign-sign-btn').hide();
+                $('#netcasign-show').html('');
+            })
+        });
+
+        // 上传签名
+        $('#netcasign-upload').change(function () {
+            const file = this.files[0];
+            const ext = file.name.toLowerCase().split('.').splice(-1)[0];
+            const imgStr = /(png|PNG)$/;
+            if (!imgStr.test(ext)) {
+                toast('请上传正确的图片格式文件','error');
+                return
+            }
+            if ($(this).val()) {
+                const reader = new FileReader();
+                reader.onload = function (evt) {
+                    console.log(evt.target.result);
+                    postData('/profile/sign/save', {type: 'savesign', sign_base64: evt.target.result.split(',')[1]}, function (result) {
+                        toastr.success('签名图设置成功');
+                        const html = '<img src="'+ evt.target.result +'" width="90">';
+                        $('#netcasign-show').html(html);
+                        $('#netcasign-upload').val('');
+                        $('#remove-netcasign-sign-btn').show();
+                    })
+                };
+                reader.readAsDataURL(file);
+            }
+        })
+    })
+</script>

+ 42 - 36
app/view/profile/sign.ejs

@@ -2,54 +2,60 @@
 <div class="panel-content">
     <div class="panel-title">
         <div class="title-main">
-            <h2>签字</h2>
+            <h2>签字管理</h2>
         </div>
     </div>
     <div class="content-wrap">
         <div class="c-body">
             <div class="sjs-height-0">
-            <div class="row m-0">
-                <div class="col-5 my-3">
-                    <!--账号资料-->
-                    <form>
-                        <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>
-                                <label class="form-check-label" for="sign-type-1">在线手写签名图</label>
+                <% if (ctx.session.sessionProject.page_show.openNetCaSign) { %>
+                <nav class="nav nav-tabs m-3" role="tablist">
+                    <a class="nav-item nav-link" href="/profile/sign/netca">Ukey认证签名</a>
+                    <a class="nav-item nav-link active" href="/profile/sign">签字设置</a>
+                </nav>
+                <% } %>
+                <div class="row m-0">
+                    <div class="col-5 my-3">
+                        <!--账号资料-->
+                        <form>
+                            <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>
+                                    <label class="form-check-label" for="sign-type-1">在线手写签名图</label>
+                                </div>
+                                <div class="form-check form-check-inline">
+                                    <input class="form-check-input sign-type" type="radio" name="sign" id="sign-type-2" value="2">
+                                    <label class="form-check-label" for="sign-type-2">上传签名图</label>
+                                </div>
                             </div>
-                            <div class="form-check form-check-inline">
-                                <input class="form-check-input sign-type" type="radio" name="sign" id="sign-type-2" value="2">
-                                <label class="form-check-label" for="sign-type-2">上传签名图</label>
+                            <div class="form-group" id="show-upload" style="display: none">
+                                <label>上传签名图</label>
+                                <input type="file" class="form-control-file" id="sign-upload">
+                                <small class="form-text text-danger">图片大小为600x300,格式PNG透明背景。</small>
                             </div>
-                        </div>
-                        <div class="form-group" id="show-upload" style="display: none">
-                            <label>上传签名图</label>
-                            <input type="file" class="form-control-file" id="sign-upload">
-                            <small class="form-text text-danger">图片大小为600x300,格式PNG透明背景。</small>
-                        </div>
-                        <div class="form-group" id="show-qrcode">
-                            <label>在线手写签名</label>
-                            <div><img src="/profile/qrCode" width="150"></div>
-                            <small class="form-text text-danger">微信扫码使用在线手写程序</small>
-                        </div>
-                        <button type="button" class="btn btn-danger btn-sm" id="delete-sign">移除签名</button>
-                        <div class="form-group">
-                            <label>签名图预览</label>
-                            <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 class="form-group" id="show-qrcode">
+                                <label>在线手写签名</label>
+                                <div><img src="/profile/qrCode" width="150"></div>
+                                <small class="form-text text-danger">微信扫码使用在线手写程序</small>
+                            </div>
+                            <button type="button" class="btn btn-danger btn-sm" id="delete-sign">移除签名</button>
+                            <div class="form-group">
+                                <label>签名图预览</label>
+                                <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>
                                 </div>
                             </div>
-                        </div>
-                    </form>
+                        </form>
+                    </div>
                 </div>
             </div>
-            </div>
         </div>
     </div>
 </div>

+ 62 - 0
app/view/profile/sign_modal.ejs

@@ -0,0 +1,62 @@
+<!--短信图示-->
+<div class="modal fade" id="remove-netcasign" >
+    <div class="modal-dialog" role="document">
+        <form class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">解除绑定</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <h6>确认解绑已绑证书信息并删除签名图?</h6>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-sm btn-danger" id="unbind_btn">确定解绑</button>
+            </div>
+        </form>
+    </div>
+</div>
+
+<div class="modal fade" id="remove-netcasign-sign" >
+    <div class="modal-dialog" role="document">
+        <form class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">移除签名</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <h6>确认移除已绑证书的签名图?</h6>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-sm btn-danger" data-dismiss="modal" id="delsign_btn">确定移除</button>
+            </div>
+        </form>
+    </div>
+</div>
+
+<div class="modal fade" id="netcasign-drive" >
+    <div class="modal-dialog" role="document">
+        <form class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">找不到签名驱动</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <h6>获取电子签章客户端配置信息失败:数字证书服务连接失败,请确认已安装最新的数字证书驱动!</h6>
+                <div class="custom-control mb-2">请下载下列软件解压并依次安装,安装完成后刷新本页重新加载</div>
+                <div class="custom-control mb-2">网证通安全客户端:<a href="http://dl.cnca.net/Drivers/网证通安全客户端.zip" target="_blank">网证通安全客户端</a></div>
+                <div class="custom-control mb-2">网证通电子签章软件:<a href="http://dl.cnca.net/Drivers/NETCA电子签章软件.zip" target="_blank">网证通电子签章软件</a></div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </form>
+    </div>
+</div>

+ 2 - 2
app/view/profile/sub_menu.ejs

@@ -7,8 +7,8 @@
             <ul class="nav-list list-unstyled">
                 <% for (const index in ctx.subMenu) { %>
                 <% if (ctx.subMenu[index].display === false) { %>
-                <li <% if (ctx.url === ctx.subMenu[index].url) { %>class="active"<% } %>>
-                    <a href="<%- ctx.subMenu[index].url %>">
+                <li <% if (ctx.url.indexOf(ctx.subMenu[index].url) !== -1) { %>class="active"<% } %>>
+                    <a href="<% if ( ctx.subMenu[index].url.indexOf(ctx.subMenu.sign.url) !== -1 && ctx.session.sessionProject.page_show.openNetCaSign) { %>/profile/sign/netca<% } else { %><%- ctx.subMenu[index].url %><% } %>">
                         <span><%- ctx.subMenu[index].name %></span>
                     </a>
                 </li>

+ 126 - 4
app/view/report/archive_pdf.ejs

@@ -10,6 +10,100 @@
     <link rel="stylesheet" href="/public/netcasign/ui/css/netcasignpdf.css">
     <link rel="stylesheet" href="/public/netcasign/ui/css/common.css">
     <link rel="resource" type="application/l10n" href="/public/netcasign/ui/locale/locale.properties">
+    <style>
+
+        .modal-background {
+            display: none;
+            position: fixed;
+            left: 0;
+            top: 0;
+            width: 100%;
+            height: 100%;
+            background-color: rgba(0,0,0,0.5);
+            font-size: 12px;
+            color: #212529;
+        }
+
+        .modal-content {
+            background:#fff;
+            width: 50%;
+            z-index: 100000;
+            margin: 12% auto;
+            overflow: auto;
+            border-radius: .3rem;
+        }
+        .modal-body {
+            /*background:#fff;*/
+            margin: auto;
+            /*height: 300px;*/
+            padding: 1rem;
+        }
+
+        .modal-header {
+            padding: .5rem 1rem;
+            border-bottom: 1px solid #dee2e6;
+            /*background: #5cd31b;*/
+        }
+
+        .modal-title {
+            font-size: 16px;
+            margin-bottom: 0;
+            line-height: 1.5;
+            font-weight: 500;
+        }
+
+        .modal-close-button {
+            float: right;
+            font-size: 22px;
+            cursor: pointer;
+        }
+
+        .modal-footer {
+            padding: .5rem 1rem;
+            border-top: 1px solid #dee2e6;
+            border-bottom-right-radius: .3rem;
+            border-bottom-left-radius: .3rem;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            /*background: #5cd31b;*/
+            /*color: white;*/
+        }
+        .modal-button {
+            font-size: 12px;
+            padding: 1px 0.6rem;
+            line-height: 1.5;
+            border-radius: .2rem;
+            color: #fff;
+            background-color: #6c757d;
+            border-color: #6c757d;
+            font-weight: 400;
+            cursor: pointer;
+            /*margin-right: .25rem;*/
+            vertical-align: baseline;
+            display: inline-block;
+            text-align: center;
+            border: 1px solid transparent;
+            transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
+            margin: 0;
+        }
+
+        .form-group {
+            margin-bottom: .5rem;
+        }
+        .mb-2 {
+            margin-bottom: .5rem!important;
+        }
+        .custom-control {
+            margin-bottom: .3rem;
+            color: #757575;
+            min-height: 1.2rem;
+            line-height: 1.2rem;
+            position: relative;
+            display: block;
+            padding-left: 1.5rem;
+        }
+    </style>
 </head>
 <body tabindex="1" class="loadingInProgress" oncontextmenu="return false;">
 <div  id="netcasignpdf">
@@ -396,6 +490,24 @@
     <img src="" alt="" id="NetcaSignMoveImage">
 </div>
 </div>
+<!-- 弹窗内容开始 -->
+<div class="modal-background">
+    <div class="modal-content">
+        <div class="modal-header">
+            <span class="modal-close-button hide-modal">×</span>
+            <h5 class="modal-title">找不到签名驱动</h5>
+        </div>
+        <div class="modal-body">
+            <div class="form-group">
+                <!--<div class="custom-control mb-2">获取电子签章客户端配置信息失败:数字证书服务连接失败,请确认已安装最新的数字证书驱动!</div>-->
+                <div class="custom-control mb-2">请下载下列软件解压并依次安装,安装完成后刷新本页重新加载</div>
+                <div class="custom-control mb-2">网证通安全客户端:<a href="http://dl.cnca.net/Drivers/网证通安全客户端.zip" target="_blank">网证通安全客户端</a></div>
+                <div class="custom-control mb-2">网证通电子签章软件:<a href="http://dl.cnca.net/Drivers/NETCA电子签章软件.zip" target="_blank">网证通电子签章软件</a></div>
+            </div>
+        </div>
+        <div class="modal-footer"><button class="modal-button hide-modal">关闭</button></div>
+    </div>
+</div>
 </body>
 
 </html>
@@ -408,19 +520,23 @@
 <script src="/public/netcasign/js/viewer.js"></script>
 <!--<![endif]-->
 <script src="/public/netcasign/ui/layer/layer.js"></script>
-<!--<script src="/public/netcasign/js/netcawebsocket.js"></script>-->
-<!--<script src="/public/netcasign/js/netcaseal.js"></script>-->
+<% if (can_netcasign) { %>
+<script src="/public/netcasign/js/netcawebsocket.js"></script>
+<script src="/public/netcasign/js/netcaseal.js"></script>
+<% } %>
 <script src="/public/netcasign/js/netcasealpdf.js"></script>
 <script src="/public/netcasign/example/appPackage.js"></script>
 <script>
-
+    const can_netcasign = <%- can_netcasign %>;
     initPDFEvent();
     function  initPDFEvent(){
         try {
 
             NetcaPDFSeal.init();
             NetcaPDFSeal.openPDFBytes('');
-            // demonstrationFn();
+            if (can_netcasign) {
+                demonstrationFn();
+            }
             // NetcaPDFSeal.openPDFWithUrl('https://measure-sign-pdf.oss-cn-shenzhen.aliyuncs.com/archive/072e3a20-c824-11eb-9ea7-3d3c8164295f.PDF');
         }
         catch(e) {
@@ -432,4 +548,10 @@
         NetcaPDFSeal.openPDFWithUrl(val);
     }
 
+    $(function () {
+        $('.hide-modal').on('click', function () {
+            $('.modal-background').hide();
+        });
+    })
+
 </script>

+ 17 - 0
app/view/report/index.ejs

@@ -95,6 +95,12 @@
                                             <button id="btnRptPageSize"  type="button" class="btn btn-outline-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">A4</button>
                                             <div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
                                                 <a class="dropdown-item" id="hrefRptPageSize" style="cursor:pointer" onclick="zTreeOprObj.changePageSize(this)">A3</a>
+                                                <!--
+                                                <a class="dropdown-item" id="hrefRptPageSize_A5" style="cursor:pointer" onclick="zTreeOprObj.changePageSize(this)">A5</a>
+                                                <a class="dropdown-item" id="hrefRptPageSize_B4" style="cursor:pointer" onclick="zTreeOprObj.changePageSize(this)">B4</a>
+                                                <a class="dropdown-item" id="hrefRptPageSize_B5" style="cursor:pointer" onclick="zTreeOprObj.changePageSize(this)">B5</a>
+                                                <a class="dropdown-item" id="hrefRptPageSize_LETTER" style="cursor:pointer" onclick="zTreeOprObj.changePageSize(this)">LETTER</a>
+                                                -->
                                             </div>
                                         </div>
                                     </div>
@@ -153,6 +159,17 @@
                                     翻页
                                 </div>
                             </div>
+                            <div class="panel">
+                                <div class="panel-body">
+                                    <div class="btn-group" role="group">
+                                        <button class="btn btn-outline-primary btn-sm" type="button" onclick="canvasOprObj.showFullSreen()">
+                                            <i class="fa fa-window-maximize"></i><br>
+                                            全屏显示
+                                        </button>
+                                        <button id="btn_show_full_screen" class="btn btn-outline-primary btn-sm" type="button" data-toggle="modal" data-target="#fullscreen" style="display: none;"></button>
+                                    </div>
+                                </div>
+                            </div>
                             <div class="panel" id="material" style="display: none;">
                                 <div class="panel-body">
                                     <div class="btn-group" role="group">

+ 17 - 8
app/view/report/index_archive.ejs

@@ -35,8 +35,8 @@
                 </div>
                 <div class="col-auto" id="main-view" style="width: 83%">
                     <div class="resize-x" id="right-spr" r-Type="width" div1="#tree-view" div2="#main-view" title="调整大小" a-type="percent"><!--调整左右高度条--></div>
-                    <div class="toolsbar-f d-flex justify-content-between">
-                        <div class="print-toolsbar">
+                    <div class="toolsbar-f d-flex justify-content-between position-absolute bg-light m-1">
+                        <div class="print-toolsbar p-0">
                             <div class="panel">
                                 <div class="panel-body" id="print_div">
                                     <div class="btn-group" role="group">
@@ -76,14 +76,23 @@
                                     历史归档
                                 </div>
                             </div>
-                        </div>
-                    </div>                    <div class="sjs-height-4">
-                        <div class="print-view form-view">
-                            <div class="pageContainer">
-                                <div class="page w-100" id="iframe_made">
-                                    <iframe src="/archive/pdf/show" height="750px" width="100%" style="border: none;"></iframe>
+                            <% if (can_netcasign) { %>
+                            <div class="panel">
+                                <div class="panel-body">
+                                    <div class="btn-group" role="group">
+                                        <button class="btn btn-outline-primary btn-sm" type="button" data-toggle="modal" data-target="#sign">
+                                            <i class="fa fa-pencil"></i><br>
+                                            电子签名 <span class="badge badge-primary">0</span>
+                                        </button>
+                                    </div>
                                 </div>
                             </div>
+                            <% } %>
+                        </div>
+                    </div>
+                    <div class="print-view form-view">
+                        <div class="pageContainer" id="iframe_made">
+                            <iframe src="/archive/pdf/show"  class="sjs-height-0 border-0" width="100%"></iframe>
                         </div>
                     </div>
                 </div>

+ 63 - 0
app/view/report/index_archive_modal.ejs

@@ -0,0 +1,63 @@
+<!--弹出批量电子签名-->
+<div class="modal fade" id="sign" data-backdrop="static">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-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">
+                <p>当前使用 #3 2021-03-02 归档报表进行签名,签名后其余归档仅能查看。</p>
+                <div class="card mb-3">
+                    <div class="card-header">选择签名位置</div>
+                    <div class="card-body py-3">
+                        <style>
+                            #role-list div:nth-child(n+5) {
+                                margin-top: 1rem;
+                            }
+                        </style>
+                        <div class="row" id="role-list">
+                            <div class="col-auto">
+                                <div class="custom-control custom-radio custom-control-inline">
+                                    <input type="radio" id="customRadioInline1" name="customRadioInline" class="custom-control-input">
+                                    <label class="custom-control-label" for="customRadioInline1">编制</label>
+                                </div>
+                            </div>
+                            <div class="col-auto">
+                                <div class="custom-control custom-radio custom-control-inline">
+                                    <input type="radio" id="customRadioInline2" name="customRadioInline" class="custom-control-input">
+                                    <label class="custom-control-label" for="customRadioInline2">复核</label>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="modal-height-300">
+                    <table class="table table-hover table-bordered">
+                        <thead>
+                        <tr><th colspan="4" class="text-center">签名页</th></tr>
+                        <tr><th width="60">页码</th>
+                            <th >名称</th>
+                            <th >签名</th>
+                            <!--<th width="40"><input type="checkbox"></td></th>-->
+                        </tr></thead>
+                        <tbody id="page-list">
+                        <tr><td>页1</td><td>工程费用表</td><td><span class="text-success"><i class="fa fa-check"></i> 编制(张三)</span></td><td><input type="checkbox"></td></tr>
+                        <tr><td>页2</td><td>工程费用表</td><td><span class="text-success"><i class="fa fa-check"></i> 编制(张三)</span></td><td><input type="checkbox"></td></tr>
+                        <tr><td>页3</td><td>工程费用表</td><td><span class="text-success"><i class="fa fa-check"></i> 编制(张三)</span><span class="text-success"><i class="fa fa-check"></i> 复核(李四)</span></td><td><input type="checkbox"></td></tr>
+                        <tr><td>页4</td><td>工程费用表</td><td></td><td><input type="checkbox"></td></tr>
+                        <tr><td>页5</td><td>工程费用表</td><td></td><td><input type="checkbox"></td></tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <!--<a href="" class="btn btn-sm btn-danger mr-5" data-toggle="modal" data-target="#sign2" data-dismiss="modal">撤销签名</a>-->
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                <a href="" class="btn btn-sm btn-primary">确定</a>
+            </div>
+        </div>
+    </div>
+</div>

+ 7 - 7
app/view/report/rpt_all_popup.ejs

@@ -518,6 +518,7 @@
             <div class="modal-header d-flex justify-content-between">
                 <h5 class="modal-title" id="fullScrTitle"></h5>
                 <div class="print-toolsbar">
+                    <!--
                     <div class="panel">
                         <div class="panel-body">
                             <div class="btn-group" role="group">
@@ -527,30 +528,29 @@
                             </div>
                         </div>
                     </div>
+                    -->
                     <div class="panel">
                         <div class="panel-body">
                             <div class="input-group input-group-sm">
                                 <div class="input-group-prepend">
-                                    <button type="button" class="btn btn-outline-primary btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="第一页"><i class="fa fa-angle-double-left "></i></button>
-                                    <button type="button" class="btn btn-outline-primary btn-sm" disabled="" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上一页"><i class="fa fa-angle-left "></i></button>
+                                    <button type="button" class="btn btn-outline-primary btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上一页" onclick="rptControlObj.prePage(this)"><i class="fa fa-angle-left "></i></button>
                                 </div>
-                                <input class="form-control" value="1/10" style="width:60px" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="输入页码按回车键,快速跳转">
+                                <input id="rpt_fullscreen_page_num" class="form-control" value="1/10" style="width:60px" onKeydown="rptControlObj.onKeydown(event, this)" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="输入页码按回车键,快速跳转">
                                 <div class="input-group-append">
-                                    <button type="button" class="btn btn-outline-primary btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下一页"><i class="fa fa-angle-right"></i></button>
-                                    <button type="button" class="btn btn-outline-primary btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="尾页"><i class="fa fa-angle-double-right "></i></button>
+                                    <button type="button" class="btn btn-outline-primary btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下一页" onclick="rptControlObj.nextPage(this)"><i class="fa fa-angle-right"></i></button>
                                 </div>
                             </div>
                         </div>
                     </div>
                     <div class="panel">
                         <div class="panel-body">
-                            <button type="button" class="btn btn-outline-primary btn-sm" data-dismiss="modal"><i class="fa fa-window-close-o"></i> 退出全屏</button>
+                            <button type="button" class="btn btn-outline-primary btn-sm" data-dismiss="modal" ><i class="fa fa-window-close-o"></i> 退出全屏</button>
                         </div>
                     </div>
                 </div>
             </div>
             <div class="modal-body">
-                <div class="modal-fullscreen">
+                <div class="modal-fullscreen pageContainer">
                     <canvas id="fullScrCanvas" height="100%" width="100%"></canvas>
                 </div>
             </div>

+ 52 - 9
app/view/report/rpt_print.ejs

@@ -25,19 +25,45 @@
         page-break-before: auto;
         page-break-after: auto;
     }
+    <% if(size === 'A4') { %>
+        @page {
+            size: A4 portrait;
+            margin-top: 0cm; margin-bottom: 0cm; margin-left: 0mm; margin-right: 0mm
+        }
+    <% } else if(size === 'A3') { %>
+    @page {
+        size: A3 portrait;
+        margin-top: 0cm; margin-bottom: 0cm; margin-left: 0mm; margin-right: 0mm
+    }
+    <% } else if(size === 'A5') { %>
+    @page {
+        size: A5 portrait;
+        margin-top: 0cm; margin-bottom: 0cm; margin-left: 0mm; margin-right: 0mm
+    }
+    <% } else if(size === 'B4') { %>
+    @page {
+        size: B4 portrait;
+        margin-top: 0cm; margin-bottom: 0cm; margin-left: 0mm; margin-right: 0mm
+    }
+    <% } else if(size === 'B5') { %>
+    @page {
+        size: B5 portrait;
+        margin-top: 0cm; margin-bottom: 0cm; margin-left: 0mm; margin-right: 0mm
+    }
+    <% } else if(size === 'LETTER') { %>
     @page {
-        size: A4 portrait;
-        margin-top: 0cm;
-        margin-bottom: 0cm;
-        margin-left: 0mm;
-        margin-right: 0mm
+        size: LETTER portrait;
+        margin-top: 0cm; margin-bottom: 0cm; margin-left: 0mm; margin-right: 0mm
     }
+    <% } else { %>
+        @page {
+            size: A4 portrait;
+            margin-top: 0cm; margin-bottom: 0cm; margin-left: 0mm; margin-right: 0mm
+        }
+    <% } %>
     @media print {
         body {
-            margin-top: 0mm;
-            margin-bottom: 0mm;
-            margin-left: 0mm;
-            margin-right: 0mm
+            margin-top: 0mm; margin-bottom: 0mm; margin-left: 0mm; margin-right: 0mm
         }
     }
     body {page: page}
@@ -65,5 +91,22 @@
     </div>
 </body>
 <SCRIPT type="text/javascript">
+    const SCREEN_DPI = [];
+    function getScreenDPI() {
+        if (SCREEN_DPI.length === 0) {
+            if (window.screen.deviceXDPI != undefined) {
+                SCREEN_DPI.push(window.screen.deviceXDPI);
+                SCREEN_DPI.push(window.screen.deviceYDPI);
+            } else {
+                let tmpNode = document.createElement("DIV");
+                tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
+                document.body.appendChild(tmpNode);
+                SCREEN_DPI.push(parseInt(tmpNode.offsetWidth));
+                SCREEN_DPI.push(parseInt(tmpNode.offsetHeight));
+                tmpNode.parentNode.removeChild(tmpNode);
+            }
+        }
+        return SCREEN_DPI;
+    }
 </SCRIPT>
 </html>

+ 0 - 49
app/view/report/rpt_printA3.ejs

@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title></title>
-    <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
-    <script type="text/javascript" src="/public/js/common_ajax.js"></script>
-    <script type="text/javascript" src="/public/report/js/jpc_output_value_define.js"></script>
-    <script type="text/javascript" src="/public/report/js/jpc_output.js"></script>
-    <script type="text/javascript" src="/public/report/js/rpt_print.js"></script>
-    <script type="text/javascript" src="/public/report/js/rpt_signature.js"></script>
-    <script type="text/javascript" src="/public/report/js/rpt_preview_common.js"></script>
-    <link rel="shortcut icon" href="/public/images/favicon.ico">
-</head>
-<style type="text/css">
-    .pageBreak {
-        page-break-before: auto;
-        page-break-after: auto;
-    }
-    @page {
-        size: A3 portrait;
-        margin-top: 0cm;
-        margin-bottom: 0cm;
-        margin-left: 0mm;
-        margin-right: 0mm
-    }
-    @media print {
-        body {
-            margin-top: 0mm;
-            margin-bottom: 0mm;
-            margin-left: 0mm;
-            margin-right: 0mm
-        }
-    }
-    body {page: page}
-    div {page: page}
-</style>
-<body onload="printPageLoading()" onbeforeunload="printPageClosing()">
-    <canvas id="chkCanvas" style="display:none"></canvas>
-    <div class="panel-body" id="print_preview_div" style="display:block">
-        <button class="btn btn-outline-primary btn-sm" type="button" onclick="printPage()">
-            <i class="fa fa-print"></i>
-            打印 <span id="checkCountPrint" class="badge badge-primary"></span>
-        </button>
-    </div>
-</body>
-<SCRIPT type="text/javascript">
-</SCRIPT>
-</html>

+ 23 - 4
app/view/sign/info.ejs

@@ -79,7 +79,7 @@
             <header>
                 <input type="button" value="返回" @click="showBox = false"/>
                 <input type="button" value="上传" @click="upload" :disabled="showSuccess"/>
-                <span v-show="showSuccess">已成功上传!</span>
+                <span v-show="showSuccess">已成功上传,请刷新电脑页面查看签名效果吧。</span>
             </header>
             <img :src="signImage">
         </div>
@@ -92,6 +92,7 @@
 <script>
     const id = '<%- id %>';
     const name = '<%- name %>';
+    const from = '<%- from %>';
     const csrf = '<%= ctx.csrf %>';
     new Vue({
         el: '#app',
@@ -168,8 +169,6 @@
                 if (!this.showSuccess) {
                     const image = this.draw.getPNGImage();
                     const blob = this.draw.dataURLtoBlob(image);
-
-                    const url = '/sign/save';
                     const successCallback = (response) => {
                         // console.log(response);
                         if (JSON.parse(response).err === 0) {
@@ -182,9 +181,29 @@
                         // console.log(error);
                         this.showSuccess = false;
                     };
-                    this.draw.upload(blob, url, successCallback, failureCallback);
+                    const url = '/sign/save';
+                    if (from === 'netcasign') {
+                        this.blobToBase64(blob).then(res => {
+                            this.draw.uploadBase64(res.split(',')[1], url, successCallback, failureCallback);
+                        });
+                    } else {
+                        this.draw.upload(blob, url, successCallback, failureCallback);
+                    }
                 }
             },
+            blobToBase64(blob) {
+                return new Promise((resolve, reject) => {
+                    const fileReader = new FileReader();
+                    fileReader.onload = (e) => {
+                        resolve(e.target.result);
+                    };
+                    // readAsDataURL
+                    fileReader.readAsDataURL(blob);
+                    fileReader.onerror = () => {
+                        reject(new Error('文件流异常'));
+                    };
+                });
+            }
         },
     });
 </script>

+ 2 - 2
app/view/stage/stage_sub_menu.ejs

@@ -15,7 +15,7 @@
                 </li>
             </ul>
         </div>
-        <% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.stageExtra) === 1) { %>
+        <% if (ctx.session.sessionProject.page_show.stageExtra1) { %>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/extra/jgcl') { %>active<% } %>">
@@ -31,7 +31,7 @@
                 </li>
             </ul>
         </div>
-        <% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.bwtz) === 1) { %>
+        <% if (ctx.session.sessionProject.page_show.bwtz) { %>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/bwtz') { %>active<% } %>">

+ 2 - 2
app/view/stage/stage_sub_mini_menu.ejs

@@ -17,7 +17,7 @@
                 </li>
             </ul>
         </div>
-        <% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.stageExtra) === 1) { %>
+        <% if (ctx.session.sessionProject.page_show.stageExtra) { %>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/extra/jgcl') { %>active<% } %>">
@@ -33,7 +33,7 @@
                 </li>
             </ul>
         </div>
-        <% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.bwtz) === 1) { %>
+        <% if (ctx.session.sessionProject.page_show.bwtz) { %>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/bwtz') { %>active<% } %>">

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

@@ -101,7 +101,7 @@
                                 <a href="#bd-set-6" data-toggle="modal" data-target="#bd-set-6" class="btn btn-sm btn-outline-primary">章节设置</a>
                                 <a href="#bd-set-7" data-toggle="modal" data-target="#bd-set-7" class="btn btn-sm btn-outline-primary">付款账号</a>
                                 <i class="mx-2">|</i>
-                                <% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.xxjd) === 1 && ctx.session.sessionUser.is_admin) { %>
+                                <% if (ctx.session.sessionProject.page_show.xxjd && ctx.session.sessionUser.is_admin) { %>
                                 <a href="#xxjd-set" data-toggle="modal" data-target="#xxjd-set" class="btn btn-sm btn-outline-primary">投资进度</a>
                                 <% } %>
                                 <a href="javascript: void(0);" class="btn btn-sm btn-outline-primary" id="copyBtn">拷贝设置</a>

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

@@ -1894,7 +1894,7 @@
     });
 </script>
 <% } %>
-<% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.xxjd) === 1 && ctx.session.sessionUser.is_admin) { %>
+<% if (ctx.session.sessionProject.page_show.xxjd && ctx.session.sessionUser.is_admin) { %>
 <!--标段设置-投资进度-->
 <div class="modal fade" id="xxjd-set" data-backdrop="static">
     <div class="modal-dialog" role="document">

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

@@ -43,7 +43,7 @@
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/material') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/material" class="h3"><i class="fa fa-line-chart fa-fw"></i> <span>材料调差</span></a></li>
             </ul>
         </div>
-        <% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.xxjd) === 1 && (ctx.tender.schedule_permission !== 0 || ctx.tender.isTourist)) { %>
+        <% if (ctx.session.sessionProject.page_show.xxjd && (ctx.tender.schedule_permission !== 0 || ctx.tender.isTourist)) { %>
         <div class="nav-box">
             <h3><i class="fa fa-bar-chart fa-fw"></i> 投资进度</h3>
             <ul class="nav-list list-unstyled sub-list">

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

@@ -45,7 +45,7 @@
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/material') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/material" class="h3"><i class="fa fa-line-chart fa-fw"></i> <span>材料调差</span></a></li>
             </ul>
         </div>
-        <% if (ctx.session.sessionProject.page_show !== null && parseInt(ctx.session.sessionProject.page_show.xxjd) === 1 && (ctx.tender.schedule_permission !== 0 || ctx.tender.isTourist)) { %>
+        <% if (ctx.session.sessionProject.page_show.xxjd && (ctx.tender.schedule_permission !== 0 || ctx.tender.isTourist)) { %>
             <div class="nav-box">
                 <h3><i class="fa fa-bar-chart fa-fw"></i> 投资进度</h3>
                 <ul class="nav-list list-unstyled sub-list">

+ 1 - 1
config/menu.js

@@ -310,7 +310,7 @@ const profileMenu = {
         url: '/profile/wechat',
     },
     sign: {
-        name: '签字',
+        name: '签字管理',
         display: false,
         url: '/profile/sign',
     },