Browse Source

签名速度优化更新

laiguoran 4 years ago
parent
commit
22f6eafdd9

+ 43 - 5
app/controller/report_archive_controller.js

@@ -15,6 +15,7 @@ const auditConst = require('../const/audit');
 const signConst = require('../const/sign');
 const shenpiConst = require('../const/shenpi');
 const accountGroup = require('../const/account_group').group;
+const sendToWormhole = require('stream-wormhole');
 
 module.exports = app => {
     class ReportArchiveController extends app.BaseController {
@@ -73,7 +74,7 @@ module.exports = app => {
                 if (archiveEncryptions.length > 0) {
                     archiveEncryptionList = JSON.parse(archiveEncryptions[0].content);
                 }
-            } else {
+            } else if (stageList.length > 0 && stageList[0].status === auditConst.stage.status.checked) {
                 // console.log('stageList[0].id: ' + stageList[0].id);
                 let archives = [];
                 for (let sidx = stageList.length - 1; sidx >= 0; sidx--) {
@@ -83,6 +84,8 @@ module.exports = app => {
                         break;
                     }
                 }
+
+                ctx.stage = ctx.stage ? ctx.stage : stageList[stageList.length - 1];
                 // const archives = await ctx.service.rptArchive.getPrjStgArchive(tender.data.project_id, stageList[stageList.length - 1].id);
                 const archiveEncryptions = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(tender.data.project_id, ctx.stage.id);
                 // stage_id = stageList[0].id;
@@ -124,7 +127,7 @@ module.exports = app => {
                 stg_order: stage_order,
                 stg_times: stage_times,
                 stg_status: stage_status,
-                stage_list: JSON.stringify(stageList),
+                stage_list: stageList.length > 0 && stageList[0].status === auditConst.stage.status.checked ? JSON.stringify(stageList) : JSON.stringify([]),
                 tenderMenu,
                 measureType,
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.report.main),
@@ -526,6 +529,7 @@ module.exports = app => {
                     }
                 }
 
+
                 const archiveEncryptions = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(tender.data.project_id, ctx.stage.id);
                 // stage_id = stageList[0].id;
                 // stage_order = stageList[0].order;
@@ -588,6 +592,13 @@ module.exports = app => {
                 let signData;
                 const netcaSignApi = signConst.path.api;
                 switch (data.type) {
+                    case 'getPdfBase64':
+                        const pdfResult = await ctx.oss.get(data.path);
+                        if (pdfResult.res.status !== 200) {
+                            throw '该文件不存在';
+                        }
+                        response.data = Buffer.from(pdfResult.content, 'binary').toString('base64');
+                        break;
                     case 'pdfIsExist':
                         const pdfMsg = await ctx.oss.head('archive/sign/' + data.uuid + '.PDF');
                         response.data = pdfMsg.res.status === 200;
@@ -612,10 +623,10 @@ module.exports = app => {
                         // console.log(result3);
                         if (result3.code === 0) {
                             // const result3 = await ctx.helper.sendMoreRequest(netcaSignApi + result2.data);
-                            const oss_reuslt = await ctx.oss.put('archive/sign/' + data.requestJson.fileName + '.PDF', result3.data);
-                            if (oss_reuslt && oss_reuslt.res && oss_reuslt.res.status === 200) {
+                            const oss_result = await ctx.oss.put('archive/sign/' + data.requestJson.fileName + '.PDF', result3.data);
+                            if (oss_result && oss_result.res && oss_result.res.status === 200) {
                                 if (data.end) {
-                                    const versionId = oss_reuslt.res.headers['x-oss-version-id'];
+                                    const versionId = oss_result.res.headers['x-oss-version-id'];
                                     // 记录签名和保存
                                     await ctx.service.netcasignLog.add(data.requestJson.fileName, data.role, ctx.session.sessionUser.accountId, versionId);
                                     const signLogList = await ctx.service.netcasignLog.getLogList(ctx.tender.id);
@@ -655,6 +666,33 @@ module.exports = app => {
 
             ctx.body = response;
         }
+        /**
+         * 网证通电子签名报表上传
+         *
+         * @param {object} ctx - egg全局变量
+         * @return {void}
+         */
+        async signFile(ctx) {
+            const stream = await ctx.getFileStream();
+            try {
+                const uuid = stream.fields.uuid;
+                const role = stream.fields.role;
+                const oss_result = await ctx.oss.put('archive/sign/' + uuid + '.PDF', stream);
+                if (!(oss_result && oss_result.url && oss_result.res.status === 200)) {
+                    throw '上传文件失败';
+                }
+                const versionId = oss_result.res.headers['x-oss-version-id'];
+                // 记录签名和保存
+                await ctx.service.netcasignLog.add(uuid, role, ctx.session.sessionUser.accountId, versionId);
+                const signLogList = await ctx.service.netcasignLog.getLogList(ctx.tender.id);
+                ctx.body = { err: 0, msg: '', data: signLogList };
+            } catch (err) {
+                // 必须将上传的文件流消费掉,要不然浏览器响应会卡死
+                await sendToWormhole(stream);
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
 
         async roundNetcaSign(ctx, postData2, round = 3) {
             let response = {

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

@@ -186,6 +186,7 @@ let rptArchiveObj = {
                 } else {
                     me.currentArchivePdfPath = oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
                     $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="750px" width="100%" style="border: none;"></iframe>');
+                    console.log(me.currentArchivePdfPath);
                 }
                 // let uuIdUrl =  "/getArchivedFileByUUID/" + me.currentArchiveUuid + "/" + stringUtil.replaceAll(me.currentNode.name, "#", "_");
                 // console.log(uuIdUrl);
@@ -654,6 +655,21 @@ function getBlob(url) {
         xhr.send();
     });
 }
+/**
+ * pdf base64 转 blob
+ * @param  {String} dataUrl base64码
+ * @return {Promise}
+ */
+function convertBase64UrlToBlob(dataUrl) {
+    //去掉url的头,并转换为byte
+    var bytes = window.atob(dataUrl);
+    //处理异常,将ascii码小于0的转换为大于0
+    var ab = new Uint8Array(bytes.length);
+    for (var i = 0; i < bytes.length; i++) {
+        ab[i] = bytes.charCodeAt(i);
+    }
+    return new Blob([ab], { type: 'application/pdf' });
+}
 
 /**
  * 保存

+ 1 - 0
app/router.js

@@ -363,6 +363,7 @@ module.exports = app => {
     // 电子签名
     app.get('/tender/:id/signReport', sessionAuth, tenderCheck, uncheckTenderCheck, 'reportArchiveController.signReport');
     app.post('/tender/:id/signReport/post', sessionAuth, tenderCheck, uncheckTenderCheck, 'reportArchiveController.signPost');
+    app.post('/tender/:id/signReport/file', sessionAuth, tenderCheck, uncheckTenderCheck, 'reportArchiveController.signFile');
 
 
     // 变更管理

+ 82 - 29
app/view/report/index_sign.ejs

@@ -154,6 +154,7 @@
 
 <script src="/public/netcasign/js/base64.min.js"></script>
 <script src="/public/netcasign/js/netcawebsocket.js"></script>
+<script src="/public/netcasign/js/netcaseal.js"></script>
 <script src="/public/netcasign/js/appPackage.js"></script>
 <script type="text/javascript">
     let current_stage_order = -1;
@@ -382,6 +383,11 @@
 
         let signDigest = '';
 
+        function clock() {
+            let t = new Date();
+
+        }
+
         $('#sign_pdf').click(function () {
             $(this).attr('disabled', true);
             $(this).text('签名条件判断中...');
@@ -432,7 +438,7 @@
                 $(this).text('确定');
                 return false;
             }
-            // 判断是否有驱动,并禁止多个ukey插入
+            // 判断是否有驱动,并禁止多个ukey同时插入
 
             const _self = $(this);
             const params={};
@@ -444,7 +450,6 @@
                         _self.attr('disabled', false);
                         _self.text('确定');
                         return false;
-                        return;
                     } else if (res.deviceCount === 1) {
                         const cert = res.certInfo[0];
                         const keyId = getNetcaKeyId(cert);
@@ -463,41 +468,89 @@
                             failedCallBack);
 
                         function successGetCertEncodeCallBack(res) {
-                            if (signDigest !== '') {
-                                signPdf();
-                            } else {
-                                // 开始签名!
+                            const path = rptArchiveObj.currentArchivePdfPath.split('/').slice(3).join('/').split('?')[0];
+                            console.time();
+                            postData('/tender/'+ TENDER_ID +'/signReport/post', {type: 'getPdfBase64', path}, function (result2) {
+                                // 生成签名后的base64并上传到oss上,文件太大可能会有bug,需要观察
+                                // 开始签名, 页数如果太多要循环调用,以30页为1个循环,防止签太久内存过大溢出
                                 const encrypt = rptArchiveObj.currentEncryptionList.encryption[val];
-                                console.log(encrypt);
+                                const roundNum = 30;
+                                const signRound = Math.ceil(rptArchiveObj.currentEncryptionList.total_page/roundNum);
+                                _self.text('签名中,请勿关闭本页...');
                                 const requestJson = {
-                                    width: encrypt.areas[0].width*0.75,
-                                    height: encrypt.areas[0].height*0.75,
-                                    x: encrypt.areas[0].Left*0.75,
-                                    y: encrypt.areas[0].Top*0.75,
-                                    // page: rptArchiveObj.currentEncryptionList.total_page ? rptArchiveObj.currentEncryptionList.total_page : 1,
-                                    page: curr_sign_page,
-                                    // url: 'https://measure-sign-pdf.oss-cn-shenzhen.aliyuncs.com/archive/'+ rptArchiveObj.currentArchiveUuid + '.PDF',
-                                    url: rptArchiveObj.currentArchivePdfPath,
-                                    hashAlgo: 'SHA256',
-                                    documentId: new Date().getTime(),
-                                    imageBase64: base64Set(netcaSignData.sign_base64),
-                                    certContent: res.certCode,
+                                    srcBytes: result2,
+                                    certEncode: res.certCode,
+                                    selMode: 1,
+                                    sealImageEncode: base64Set(netcaSignData.sign_base64),
+                                    revInfoIncludeFlag: false,
+                                    SignPosition: {
+                                        startPage: 1,
+                                        endPage: -1,
+                                        xPos: parseInt(encrypt.areas[0].Left*0.75),
+                                        yPos: parseInt(encrypt.areas[0].Top*0.75),
+                                        width: parseInt(encrypt.areas[0].width*0.75),
+                                        height: parseInt(encrypt.areas[0].height*0.75),
+                                    },
                                 }
-                                console.log(requestJson);
-                                // 先获取摘要值
-                                postData('/tender/'+ TENDER_ID +'/signReport/post', { type: 'assemblyDigest', requestJson}, function (result) {
-                                    if(result.code === 0) {
-                                        signDigest = result.data;
-                                        signPdf(res);
+                                signPdfRound(requestJson, 1, signRound, roundNum, encrypt.name);
+                            });
+                        }
+
+                        function signPdfRound(requestJson, num, round, roundNum, name) {
+                            if (num !== round) {
+                                requestJson.SignPosition.startPage = (num-1)*roundNum + 1;
+                                requestJson.SignPosition.endPage = num+1 > round ? -1 : num*roundNum;
+                            }
+                            console.log((num-1)*roundNum + 1, num+1 > round ? -1 : num*roundNum);
+                            NetcaPKI.SignatureCreatorSignSealEx(requestJson)
+                                .Then(function (res)
+                                {
+                                    if (num !== round) {
+                                        requestJson.srcBytes = res.destFileEncode;
+                                        let uhtml = ' <span class="text-success"><i class="fa fa-check"></i> '+ name +'('+ USER_NAME +')</span>';
+                                        const nowRound = (num-1)*roundNum;
+                                        for (let i = 0; i < roundNum; i++) {
+                                            $('#page-list tr').eq(nowRound + i).children('td').eq(2).append(uhtml);
+                                        }
+                                        ++num;
+                                        signPdfRound(requestJson, num, round, roundNum, name);
                                     } else {
-                                        failedCallBack(result);
+                                        const doc = convertBase64UrlToBlob(res.destFileEncode);
+                                        const formData = new FormData();
+                                        formData.append('uuid',  rptArchiveObj.currentArchiveUuid);
+                                        formData.append('role',  name);
+                                        formData.append('file', doc, 'test.pdf');
+                                        postDataWithFile('/tender/'+ TENDER_ID +'/signReport/file', formData, function (result) {
+                                            toastr.success("已成功签名");
+                                            signLogList = result;
+                                            signDigest = '';
+                                            rptArchiveObj._updateSignHtmlAndFrame(true);
+                                            $('#sign').modal('hide');
+                                            _self.attr('disabled', false);
+                                            _self.text('确定');
+                                            console.timeEnd();
+                                            return true;
+                                        }, function () {
+                                            console.timeEnd();
+                                            _self.attr('disabled', false);
+                                            _self.text('确定');
+                                            return false;
+                                        })
+                                    }
+                                })
+                                .Catch(function (res)
+                                {
+                                    if (res.status === -1915) {
+                                        toastr.warning('您已取消签名');
+                                    } else {
+                                        toastr.error('网证通签名报错:' + res.msg);
                                     }
-                                }, function () {
                                     _self.attr('disabled', false);
                                     _self.text('确定');
+                                    console.log(res.msg);
+                                    console.timeEnd();
                                     return false;
-                                })
-                            }
+                                });
                         }
                         function signPdf(res2) {
                             const certEncode = "";

+ 1 - 1
config/config.default.js

@@ -127,7 +127,7 @@ module.exports = appInfo => {
             '.ppt', '.pptx',
             '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.cad', '.dwg',
             '.zip', '.rar', '.7z', ''],
-        fileSize: '30mb',
+        fileSize: '100mb',
         fields: '15',
     };
 

+ 1 - 1
config/config.local.js

@@ -63,7 +63,7 @@ module.exports = appInfo => {
             '.pdf',
             '.png', '.jpg', '.jpeg', '.gif', '.bmp',
             '.zip', '.rar', '.7z'],
-        fileSize: '30mb',
+        fileSize: '100mb',
     };
 
     // session配置