| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793 | 'use strict';/** * Created by Tony on 2021/3/31. */const path = require('path');const uuidV1 = require('uuid').v1;const fs = require('fs');const MAX_ARCHIVE = 3;const tenderMenu = require('../../config/menu').tenderMenu;const measureType = require('../const/tender').measureType;const fsUtil = require('../public/js/fsUtil');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 {        /**         * 获取审批界面所需的 原报、审批人数据等         * @param ctx         * @return {Promise<void>}         * @private         */        async _getStageAuditViewData(ctx) {            if (!ctx.stage) return;            const times = ctx.stage.status === auditConst.stage.status.checkNo ? ctx.stage.times - 1 : ctx.stage.times;            ctx.stage.user = await ctx.service.projectAccount.getAccountInfoById(ctx.stage.user_id);            ctx.stage.auditHistory = [];            if (times >= 1) {                for (let i = 1; i <= times; i++) {                    ctx.stage.auditHistory.push(await ctx.service.stageAudit.getAuditors(ctx.stage.id, i));                }            }            // 获取审批流程中左边列表            ctx.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByListWithOwner(ctx.stage.id, times);            if (ctx.stage.status === auditConst.stage.status.uncheck || ctx.stage.status === auditConst.stage.status.checkNo) {                ctx.stage.auditorList = await ctx.service.stageAudit.getAuditors(ctx.stage.id, ctx.stage.times);            }        }        async index(ctx) {            await this._getStageAuditViewData(ctx);            const tender = ctx.tender;            const stage = ctx.stage;            let stage_id = -1;            let stage_order = -1;            let stage_times = -1;            let stage_status = -1;            const treeNodes = await ctx.service.rptTreeNode.getNodesByProjectId([-1, tender.data.project_id]);            const custTreeNodes = await ctx.service.rptTreeNodeCust.getCustFoldersByUserId(this.ctx.session.sessionUser.accountId);            const stageList = await ctx.service.stage.getValidStagesShort(tender.id);            const isAdmin = ctx.session.sessionUser.is_admin;            //            // 。。。            let archiveList = [];            let archiveEncryptionList = [];            // console.log('tender.data.project_id: ' + tender.data.project_id);            if (stage) {                // console.log('ctx.stage.id: ' + ctx.stage.id);                const archives = await ctx.service.rptArchive.getPrjStgArchive(tender.data.project_id, ctx.stage.id);                const archiveEncryptions = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(tender.data.project_id, ctx.stage.id);                stage_id = stage.id;                stage_order = stage.order;                stage_times = stage.times;                stage_status = stage.status;                if (archives.length > 0) {                    archiveList = JSON.parse(archives[0].content);                }                if (archiveEncryptions.length > 0) {                    archiveEncryptionList = JSON.parse(archiveEncryptions[0].content);                }            } 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--) {                    if (stageList[sidx].status === 3) {                        archives = await ctx.service.rptArchive.getPrjStgArchive(tender.data.project_id, stageList[sidx].id);                        ctx.stage = stageList[sidx]; // 为了sub menu用                        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;                // stage_order = stageList[0].order;                // stage_times = stageList[0].times;                // stage_status = stageList[0].status;                if (archives && archives.length > 0) {                    archiveList = JSON.parse(archives[0].content);                }                if (archiveEncryptions && archiveEncryptions.length > 0) {                    archiveEncryptionList = JSON.parse(archiveEncryptions[0].content);                }            }            let rpt_tpl_items = '{ customize: [], common: [] }';            if (custTreeNodes.length > 0) {                rpt_tpl_items = custTreeNodes[0].rpt_tpl_items;            }            // 获取用户权限            const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);            // 获取所有项目参与者            const accountList = await ctx.service.projectAccount.getAllDataByCondition({                where: { project_id: ctx.session.sessionProject.id, enable: 1 },                columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group', 'mobile'],            });            const newAccountGroup = accountGroup.map((item, idx) => {                const groupList = accountList.filter(item => item.account_group === idx);                return { groupName: item, groupList };            });            //            const renderData = {                tender: tender.data,                rpt_tpl_data: JSON.stringify(treeNodes),                cust_tpl_data: rpt_tpl_items,                project_id: tender.data.project_id,                tender_id: tender.id,                stg_id: stage_id,                stg_order: stage_order,                stg_times: stage_times,                stg_status: stage_status,                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),                stages: stageList,                auditConst: auditConst.stage,                archiveList,                archiveEncryptionList,                can_netcasign: false,                ossPath: signConst.path.oss,                shenpiConst,                preUrl: '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.params.order,                authMobile: accountInfo.auth_mobile,                accountGroup: newAccountGroup,                accountList,                isAdmin,            };            if (stage_id === -1) {                await this.layout('report/index_archive.ejs', renderData, 'report/archive_popup.ejs');            } else {                await this.layout('report/index_archive.ejs', renderData, 'report/stage_archive_modal.ejs');            }        }        async getReportArchive(ctx) {            const params = JSON.parse(ctx.request.body.params);            // ctx.body = await this._getReport(ctx, params);            const archives = await ctx.service.rptArchive.getPrjStgArchive(params.prjId, params.stgId);            const archiveEncryptions = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(params.prjId, params.stgId);            let archiveList = [];            let archiveEncryptionList = [];            if (archives.length > 0) {                archiveList = JSON.parse(archives[0].content);            }            if (archiveEncryptions.length > 0) {                archiveEncryptionList = JSON.parse(archiveEncryptions[0].content);            }            const lastAuditor = await ctx.service.stageAudit.getLastestAuditor(params.stgId, params.stgTimes, auditConst.stage.status.checked);            ctx.body = {                data: archiveList,                encryptionData: archiveEncryptionList,                lastAuditor,            };        }        async _updateReportArchiveAdhocInfo(ctx, params) {            const userId = ctx.session.sessionUser.accountId;            const prjId = params.prjId;            const stgId = params.stgId;            const rptId = params.rptId;            const ttlPgs = params.ttlPgs;            const uuid = params.uuid;            const reportName = params.reportName;            const reportAreas = params.signatureAreas;            // 这里要更新zh_rpt_archive表的相关数据            const orgArchiveList = await ctx.service.rptArchive.getPrjStgArchive(prjId, stgId);            if (orgArchiveList.length > 0) {                const contentArr = JSON.parse(orgArchiveList[0].content);                for (const item of contentArr) {                    if (parseInt(item.rpt_id) === parseInt(rptId)) {                        for (const rptItem of item.items) {                            if (rptItem.uuid === uuid) {                                rptItem.uid = userId;                                rptItem.reportName = reportName;                                rptItem.ttl_pages = ttlPgs;                                rptItem.signature_area = reportAreas;                                break;                            }                        }                        break;                    }                }                const updatedRst = await ctx.service.rptArchive.updateArchive(orgArchiveList[0].id, prjId, stgId, contentArr);            } else {                // 正常情况下不可能的分支            }        }        async addReportArchiveEncryption(ctx) {            const params = JSON.parse(ctx.request.body.params);            const prjId = params.prjId;            const stgId = params.stgId;            const rptId = params.rptId;            const ttlPgs = params.ttlPgs;            const uuid = params.uuid;            const reportName = params.reportName;            const userId = ctx.session.sessionUser.accountId;            const content = params.content;            const orgArchiveList = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(prjId, stgId);            if (orgArchiveList.length > 0) {                const contentArr = JSON.parse(orgArchiveList[0].content);                let hasArchive = false;                for (const item of contentArr) {                    if (item.rpt_id === rptId) {                        // 考虑到报表模板的稳定性,只保留一项来记录位置就足够了,都不考虑用uuid了                        if (item.uuid === uuid) {                            // 最后打脸了,还真的要考虑不同的uuid,不早说,TNND                            item.encryption = content;                            item.total_page = ttlPgs;                            item.user_id = userId;                            item.report_name = reportName;                            hasArchive = true;                            break;                        }                    }                }                if (!hasArchive) {                    // 表示有新的要加                    contentArr.push({ rpt_id: rptId, uuid, total_page: ttlPgs, encryption: content, user_id: userId, report_name: reportName });                } else {                    //                }                const updatedRst = await ctx.service.rptArchiveEncryption.updateArchiveEncryption(orgArchiveList[0].id, prjId, stgId, contentArr);                // console.log(updatedRst);                ctx.body = { err: 0, msg: '', data: { addedRst: contentArr } };            } else {                // 需要增加                const archiveArr = [];                archiveArr.push({ rpt_id: rptId, uuid, total_page: ttlPgs, encryption: content, user_id: userId, report_name: reportName });                const addedRst = await ctx.service.rptArchiveEncryption.createArchiveEncryption(prjId, stgId, archiveArr);                // console.log(addedRst);                ctx.body = { err: 0, msg: '', data: { addedRst: archiveArr } };            }        }        async addReportArchive(ctx) {            try {                const stream = await ctx.getFileStream();                const prjId = ctx.params.prjId;                const stgId = ctx.params.stgId;                const rptId = ctx.params.rptId;                const newUuidName = uuidV1();                const fileName = newUuidName + '.PDF';                // console.log('adding fileName: ' + fileName);                // await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, 'app', 'public/archive', fileName));                const oss_result = await ctx.app.signPdfOss.put('archive/' + fileName, stream);                if (!(oss_result && oss_result.url && oss_result.res.status === 200)) {                    throw '上传文件失败';                }                // const url = await ctx.oss.delete('archive/52d3e7f0-c7fb-11eb-b8c2-51b890b95d23.PDF');                // console.log(url);                // const flag = true;                // if (flag) {                //     throw 'ok';                // }                const updateDate = new Date();                const montStr = (updateDate.getMonth() + 1) < 10 ? ('0' + (updateDate.getMonth() + 1)) : (updateDate.getMonth() + 1);                const dateStr = (updateDate.getDate()) < 10 ? ('0' + updateDate.getDate()) : (updateDate.getDate());                let hrStr = '' + updateDate.getHours();                if (hrStr.length === 1) hrStr = '0' + hrStr;                let minStr = '' + updateDate.getMinutes();                if (minStr.length === 1) minStr = '0' + minStr;                let secStr = '' + updateDate.getSeconds();                if (secStr.length === 1) secStr = '0' + secStr;                // const dtStr = updateDate.getFullYear() + '-' + montStr + '-' + dateStr;                const dtStr = `${updateDate.getFullYear()}-${montStr}-${dateStr} ${hrStr}:${minStr}:${secStr}`;                const orgArchiveList = await ctx.service.rptArchive.getPrjStgArchive(prjId, stgId);                if (orgArchiveList.length > 0) {                    const contentArr = JSON.parse(orgArchiveList[0].content);                    let hasArchive = false;                    for (const item of contentArr) {                        if (item.rpt_id === rptId) {                            hasArchive = true;                            if (item.items.length >= MAX_ARCHIVE) {                                // 超出界限,需要删除时间最旧的那个                                let rmIdx = 0;                                for (let idx = 1; idx < item.items.length; idx++) {                                    if (item.items[rmIdx].updateDate_time < item.items[idx].updateDate_time) {                                        rmIdx = idx;                                    }                                }                                // 同时删除oss文件                                await ctx.app.signPdfOss.delete('archive/' + item.items[rmIdx].uuid + '.PDF');                                item.items.splice(rmIdx, 1);                            }                            const newItem = { uuid: newUuidName, updateDate_time: dtStr };                            item.items.push(newItem);                            break;                        }                    }                    if (!hasArchive) {                        // 表示有新的模板需要添加                        contentArr.push({ rpt_id: rptId, items: [{ uuid: newUuidName, updateDate_time: dtStr }] });                    }                    const updatedRst = await ctx.service.rptArchive.updateArchive(orgArchiveList[0].id, prjId, stgId, contentArr);                    // console.log(updatedRst);                    ctx.body = { err: 0, msg: newUuidName, data: { uuid: newUuidName, fileName, updateDate, addedRst: contentArr } };                } else {                    // 需要增加                    const archiveArr = [];                    archiveArr.push({ rpt_id: rptId, items: [{ uuid: newUuidName, updateDate_time: dtStr }] });                    const addedRst = await ctx.service.rptArchive.createArchive(prjId, stgId, archiveArr);                    // console.log(addedRst);                    ctx.body = { err: 0, msg: newUuidName, data: { uuid: newUuidName, fileName, updateDate, addedRst: archiveArr } };                }            } catch (err) {                this.log(err);                ctx.body = { err: 1, msg: err.toString(), data: null };            }        }        async updateReportArchiveEncryption(ctx) {            // 在add方法中已经处理            await this.addReportArchiveEncryption(ctx);        }        async updateReportArchive(ctx) {            try {                const stream = await ctx.getFileStream();                const prjId = ctx.params.prjId;                const stgId = ctx.params.stgId;                const rptId = ctx.params.rptId;                const orgUuidName = ctx.params.orgName;                const fileName = orgUuidName + '.PDF';                console.log('updating fileName: ' + fileName);                // await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, 'app', 'public/archive', fileName));                const oss_result = await ctx.app.signPdfOss.put('archive/' + fileName, stream);                if (!(oss_result && oss_result.url && oss_result.res.status === 200)) {                    throw '上传文件失败';                }                // 判断是否存在已签名文档,存在则删除文档并删除签名记录                const pdfMsg = await ctx.curl(signConst.path.oss + '/sign/' + orgUuidName + '.PDF');                if (pdfMsg && pdfMsg.status === 200) {                    const oss_reuslt = await ctx.app.signPdfOss.delete('archive/sign/' + fileName);                    if (oss_reuslt && oss_reuslt.res && oss_reuslt.res.status === 204) {                        const delSign_result = await ctx.service.netcasignLog.removeSign(orgUuidName);                    } else {                        throw '删除已签文档失败';                    }                }                const updateDate = new Date();                const montStr = (updateDate.getMonth() + 1) < 10 ? ('0' + (updateDate.getMonth() + 1)) : ((updateDate.getMonth() + 1));                const dateStr = (updateDate.getDate()) < 10 ? ('0' + (updateDate.getDate())) : ((updateDate.getDate()));                let hrStr = '' + updateDate.getHours();                if (hrStr.length === 1) hrStr = '0' + hrStr;                let minStr = '' + updateDate.getMinutes();                if (minStr.length === 1) minStr = '0' + minStr;                let secStr = '' + updateDate.getSeconds();                if (secStr.length === 1) secStr = '0' + secStr;                // const dtStr = updateDate.getFullYear() + '-' + montStr + '-' + dateStr;                const dtStr = `${updateDate.getFullYear()}-${montStr}-${dateStr} ${hrStr}:${minStr}:${secStr}`;                const orgArchiveList = await ctx.service.rptArchive.getPrjStgArchive(prjId, stgId);                if (orgArchiveList.length > 0) {                    const contentArr = JSON.parse(orgArchiveList[0].content);                    for (const item of contentArr) {                        if (item.rpt_id === rptId) {                            if (item.items && item.items.length > 0) {                                for (const subItem of item.items) {                                    if (subItem.uuid === orgUuidName) {                                        subItem.updateDate_time = dtStr;                                        break;                                    }                                }                            } else {                                item.items = [{ uuid: orgUuidName, updateDate_time: dtStr }];                            }                            break;                        }                    }                    const updatedRst = await ctx.service.rptArchive.updateArchive(orgArchiveList[0].id, prjId, stgId, contentArr);                    // console.log(updatedRst);                    ctx.body = { err: 0, msg: orgUuidName, data: { fileName, updateDate, updatedRst: contentArr } };                } else {                    // 需要增加                    const archiveArr = [];                    archiveArr.push({ rpt_id: rptId, items: [{ uuid: orgUuidName, updateDate_time: dtStr }] });                    const updatedRst = await ctx.service.rptArchive.createArchive(prjId, stgId, archiveArr);                    // console.log(updatedRst);                    ctx.body = { err: 0, msg: orgUuidName, data: { fileName, updateDate, updatedRst: archiveArr } };                }            } catch (err) {                this.log(err);                ctx.body = { err: 1, msg: err.toString(), data: null };            }        }        async _removeReportArchiveEncryption(ctx) {            let rst = null;            try {                const prjId = ctx.params.prjId;                const stgId = ctx.params.stgId;                const rptId = parseInt(ctx.params.rptId);                const uuid = ctx.params.orgName;                const orgArchiveList = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(prjId, stgId);                if (orgArchiveList.length > 0) {                    const contentArr = JSON.parse(orgArchiveList[0].content);                    for (let idx = contentArr.length - 1; idx >= 0; idx--) {                        if (contentArr[idx].rpt_id === rptId && contentArr[idx].uuid === uuid) {                            contentArr.splice(idx, 1);                            break;                        }                    }                    // const updatedRst = await ctx.service.rptArchive.updateArchive(prjId, stgId, contentArr);                    rst = await ctx.service.rptArchiveEncryption.updateArchiveEncryption(orgArchiveList[0].id, prjId, stgId, contentArr);                }            } catch (err) {                this.log(err);            }            return rst;        }        async removeReportArchiveEncryption(ctx) {            try {                const rst = await this._removeReportArchiveEncryption(ctx);                if (rst) {                    ctx.body = { err: 0, msg: '', data: { updatedRst: rst } };                } else {                    ctx.body = { err: 0, msg: '', data: { updatedRst: null } };                }            } catch (err) {                this.log(err);                ctx.body = { err: 1, msg: err.toString(), data: null };            }        }        async _removeReportArchive(ctx) {            let rst = null;            try {                const prjId = ctx.params.prjId;                const stgId = ctx.params.stgId;                const rptId = ctx.params.rptId;                const orgUuidName = ctx.params.orgName;                // const fileName = orgUuidName + '.PDF';                const orgArchiveList = await ctx.service.rptArchive.getPrjStgArchive(prjId, stgId);                if (orgArchiveList.length > 0) {                    const contentArr = JSON.parse(orgArchiveList[0].content);                    for (let idx = contentArr.length - 1; idx >= 0; idx--) {                        const item = contentArr[idx];                        if (item.rpt_id === rptId) {                            if (item.items && item.items.length > 0) {                                for (const subIdx in item.items) {                                    if (item.items[subIdx].uuid === orgUuidName) {                                        item.items.splice(subIdx, 1);                                        break;                                    }                                }                                if (item.items.length === 0) {                                    contentArr.splice(idx, 1);                                }                            }                            break;                        }                    }                    rst = await ctx.service.rptArchive.updateArchive(orgArchiveList[0].id, prjId, stgId, contentArr);                }            } catch (err) {                this.log(err);            }            return rst;        }        async removeReportArchive(ctx) {            try {                const orgUuidName = ctx.params.orgName;                const fileName = orgUuidName + '.PDF';                // console.log(ctx.params);                console.log('removing fileName: ' + fileName);                // const fullName = path.join(this.app.baseDir, 'app', 'public/archive', fileName);                const oss_sign_result = await ctx.app.signPdfOss.delete(`archive/sign/${fileName}`);                if (oss_sign_result && oss_sign_result.res && oss_sign_result.res.status === 204) {                    // console.log('删除归档的签名信息成功!');                    const oss_result = await ctx.app.signPdfOss.delete(`archive/${fileName}`);                    if (!(oss_result && oss_result.res.status === 204)) {                        throw '删除归档文件失败';                    }                } else {                    throw '删除归档签名文件失败';                }                // 还有加密签名信息                const archiveSignRemovedRst = await this._removeReportArchiveEncryption(ctx);                // console.log(archiveSignRemovedRst);                const archiveRemovedRst = await this._removeReportArchive(ctx);                if (archiveRemovedRst) {                    ctx.body = { err: 0, msg: orgUuidName, data: { fileName, updatedRst: archiveRemovedRst } };                } else {                    ctx.body = { err: 0, msg: orgUuidName, data: { fileName, updatedRst: null } };                }            } catch (err) {                this.log(err);                ctx.body = { err: 1, msg: err.toString(), data: null };            }        }        async addMultiReportArchive(ctx, params) {            // 暂时不支持        }        async getArchivedFileByUUID(ctx) {            // console.log('downloading : ' + ctx.params.uuid);            const uuid = ctx.params.uuid;            const rptName = ctx.params.rptName;            const suffix = '.PDF';            try {                const rptNameURI = encodeURI(rptName);                const filePath = this.app.baseDir + '/app/public/archive/';                // console.log('filePath: ' + filePath);                // await this.ctx.helper.recursiveMkdirSync(this.app.baseDir + '/app/public/download');                ctx.set({                    'Content-Type': 'application/vnd.openxmlformats',                    'Content-Disposition': 'attachment; filename="' + rptNameURI + suffix + "\"; filename*=utf-8''" + rptNameURI + suffix,                });                ctx.body = await fs.readFileSync(filePath + uuid + suffix);            } catch (e) {                console.log(e);            }        }        async pdfShow(ctx) {            // const renderData = {            //     can_netcasign: ctx.session.sessionProject.page_show.openNetCaSign === 1,            // };            await ctx.render('report/archive_pdf.ejs');        }        /*         *  网证通电子签名页,(和归档报表页高度相似)         */        async signReport(ctx) {            const tender = ctx.tender;            const stage = ctx.stage;            let stage_id = -1;            let stage_order = -1;            let stage_times = -1;            let stage_status = -1;            const treeNodes = await ctx.service.rptTreeNode.getNodesByProjectId([-1, tender.data.project_id]);            const custTreeNodes = await ctx.service.rptTreeNodeCust.getCustFoldersByUserId(this.ctx.session.sessionUser.accountId);            const stageList = await ctx.service.stage.getValidStagesShort(tender.id);            //            // 。。。            let archiveList = [];            let archiveEncryptionList = [];            // console.log('tender.data.project_id: ' + tender.data.project_id);            if (stage) {                // console.log('ctx.stage.id: ' + ctx.stage.id);                const archives = await ctx.service.rptArchive.getPrjStgArchive(tender.data.project_id, ctx.stage.id);                const archiveEncryptions = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(tender.data.project_id, ctx.stage.id);                stage_id = stage.id;                stage_order = stage.order;                stage_times = stage.times;                stage_status = stage.status;                if (archives.length > 0) {                    archiveList = JSON.parse(archives[0].content);                }                console.log('2:', archiveEncryptions, ctx.stage.id);                if (archiveEncryptions.length > 0) {                    archiveEncryptionList = JSON.parse(archiveEncryptions[0].content);                }            } else if (stageList.length > 0 && stageList[0].status === auditConst.stage.status.checked) {                // console.log('stageList[0].id: ' + stageList[0].id);                // const archives = await ctx.service.rptArchive.getPrjStgArchive(tender.data.project_id, stageList[stageList.length - 1].id);                let archives = [];                for (let sidx = stageList.length - 1; sidx >= 0; sidx--) {                    if (stageList[sidx].status === 3) {                        archives = await ctx.service.rptArchive.getPrjStgArchive(tender.data.project_id, stageList[sidx].id);                        ctx.stage = stageList[sidx]; // 为了sub menu用                        break;                    }                }                ctx.stage = ctx.stage ? ctx.stage : stageList[stageList.length - 1];                const archiveEncryptions = await ctx.service.rptArchiveEncryption.getPrjStgArchiveEncryption(tender.data.project_id, ctx.stage.id);                // stage_id = stageList[0].id;                // stage_order = stageList[0].order;                // stage_times = stageList[0].times;                // stage_status = stageList[0].status;                if (archives && archives.length > 0) {                    archiveList = JSON.parse(archives[0].content);                }                if (archiveEncryptions && archiveEncryptions.length > 0) {                    archiveEncryptionList = JSON.parse(archiveEncryptions[0].content);                }            }            let rpt_tpl_items = '{ customize: [], common: [] }';            if (custTreeNodes.length > 0) {                rpt_tpl_items = custTreeNodes[0].rpt_tpl_items;            }            // 获取ukey绑定数据            const netcaSignData = await ctx.service.netcasign.getDataByCondition({ uid: ctx.session.sessionUser.accountId });            // 获取已签名数据            const signLogList = await ctx.service.netcasignLog.getLogList(ctx.tender.id);            const renderData = {                tender: tender.data,                rpt_tpl_data: JSON.stringify(treeNodes),                cust_tpl_data: rpt_tpl_items,                project_id: tender.data.project_id,                tender_id: tender.id,                stg_id: stage_id,                stg_order: stage_order,                stg_times: stage_times,                stg_status: stage_status,                stage_list: JSON.stringify(stageList),                tenderMenu,                measureType,                jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.report.main),                stages: stageList,                auditConst: auditConst.stage,                archiveList,                archiveEncryptionList,                netcaSignData,                can_netcasign: ctx.session.sessionProject.page_show.openNetCaSign === 1,                ossPath: signConst.path.oss,                signLogList,            };            await this.layout('report/index_sign.ejs', renderData, 'report/index_sign_modal.ejs');        }        /**         * 网证通电子签名接口         *         * @param {object} ctx - egg全局变量         * @return {void}         */        async signPost(ctx) {            const response = {                err: 0,                msg: '',            };            try {                const data = JSON.parse(ctx.request.body.data);                let signData;                const netcaSignApi = signConst.path.api;                switch (data.type) {                    case 'getPdfBase64':                        const pdfResult = await ctx.app.signPdfOss.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.app.signPdfOss.head('archive/sign/' + data.uuid + '.PDF');                        response.data = pdfMsg.res.status === 200;                        break;                    // 获取摘要值                    case 'assemblyDigest':                        const postData = {                            requestJson: JSON.stringify(data.requestJson),                        };                        const result = await ctx.helper.sendMoreRequest(netcaSignApi + '/assemblyDigest', postData, 'POST');                        response.data = result;                        break;                    // 生成签名pdf                    case 'assemblyPdf':                        const postData2 = {                            requestJson: JSON.stringify(data.requestJson),                        };                        const result3 = await this.roundNetcaSign(ctx, postData2);                        // const result2 = await ctx.helper.sendMoreRequest(netcaSignApi + '/assemblyPdf', postData2, 'POST');                        // 上传到oss                        // console.log(result3);                        if (result3.code === 0) {                            // const result3 = await ctx.helper.sendMoreRequest(netcaSignApi + result2.data);                            const oss_result = await ctx.app.signPdfOss.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_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);                                    response.data = signLogList;                                } else {                                    // next page                                }                            } else {                                throw '上传文件失败';                            }                        } else {                            throw result3.msg;                        }                        break;                    // 移除签名和已签移除pdf                    case 'removeSign':                        const oss_reuslt = await ctx.app.signPdfOss.delete('archive/sign/' + data.uuid + '.PDF');                        if (oss_reuslt && oss_reuslt.res && oss_reuslt.res.status === 204) {                            const delSign_result = await ctx.service.netcasignLog.removeSign(data.uuid);                            const signLogList = await ctx.service.netcasignLog.getLogList(ctx.tender.id);                            response.data = signLogList;                        } else {                            throw '删除文件失败';                        }                        break;                    default:throw '参数有误';                }            } catch (error) {                response.err = 1;                response.msg = error.toString();                const data = JSON.parse(ctx.request.body.data);                if (data && data.type === 'pdfIsExist') {                    response.err = 0;                    response.data = false;                }            }            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.app.signPdfOss.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 = {                code: 0,                data: '',            };            // 无法获取到result3,因为result2生成的pdf已损坏,请重复获取result2,直到获取成功或尝试3次失败后报错为止            try {                const netcaSignApi = signConst.path.api;                const result2 = await ctx.helper.sendMoreRequest(netcaSignApi + '/assemblyPdf', postData2, 'POST');                if (result2.code === 0) {                    const result3 = await ctx.curl(netcaSignApi + result2.data, {                        timeout: 300000, // 超时 5分钟中                    });                    if (result3) {                        response.data = result3.data;                    } else {                        if (round > 0) {                            round = round - 1;                            response = await this.roundNetcaSign(ctx, postData2, round);                        } else {                            throw 'pdf获取失败,网证通接口无法生成pdf';                        }                    }                }            } catch (error) {                response.code = 1;                response.msg = error;            }            return response;        }    }    return ReportArchiveController;};
 |