Преглед на файлове

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

MaiXinRong преди 2 години
родител
ревизия
e18c178c42

+ 126 - 104
app/controller/report_archive_controller.js

@@ -218,6 +218,8 @@ module.exports = app => {
             const rptId = params.rptId;
             const ttlPgs = params.ttlPgs;
             const uuid = params.uuid;
+            const childUuids = params.childUuids;
+            const splitArcPages = params.splitArcPages;
             const reportName = params.reportName;
             const userId = ctx.session.sessionUser.accountId;
             const content = params.content;
@@ -234,6 +236,8 @@ module.exports = app => {
                             item.total_page = ttlPgs;
                             item.user_id = userId;
                             item.report_name = reportName;
+                            item.childUuids = childUuids;
+                            item.splitArcPages = splitArcPages;
                             hasArchive = true;
                             break;
                         }
@@ -241,7 +245,7 @@ module.exports = app => {
                 }
                 if (!hasArchive) {
                     // 表示有新的要加
-                    contentArr.push({ rpt_id: rptId, uuid, total_page: ttlPgs, encryption: content, user_id: userId, report_name: reportName });
+                    contentArr.push({ rpt_id: rptId, uuid, total_page: ttlPgs, encryption: content, user_id: userId, report_name: reportName, childUuids, splitArcPages });
                 } else {
                     //
                 }
@@ -251,13 +255,128 @@ module.exports = app => {
             } else {
                 // 需要增加
                 const archiveArr = [];
-                archiveArr.push({ rpt_id: rptId, uuid, total_page: ttlPgs, encryption: content, user_id: userId, report_name: reportName });
+                archiveArr.push({ rpt_id: rptId, uuid, total_page: ttlPgs, encryption: content, user_id: userId, report_name: reportName, childUuids, splitArcPages });
                 const addedRst = await ctx.service.rptArchiveEncryption.createArchiveEncryption(prjId, stgId, archiveArr);
                 // console.log(addedRst);
                 ctx.body = { err: 0, msg: '', data: { addedRst: archiveArr } };
             }
         }
 
+        async _updateArchiveCommon(ctx, prjId, stgId, rptId, parentUuidName, childUuids) {
+            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} ${hrStr}:${minStr}:${secStr}`;
+            let rst = null;
+            const fileName = parentUuidName + '.PDF';
+            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;
+                        let updateRmIdx = -1;
+                        for (let idx = 0; idx < item.items.length; idx++) {
+                            if (parentUuidName === item.items[idx].uuid) {
+                                // 这里的判断是否是update archive逻辑(是否存在相同uuid的item)
+                                updateRmIdx = idx;
+                                break;
+                            }
+                        }
+                        if (updateRmIdx < 0 && item.items.length >= MAX_ARCHIVE) {
+                            updateRmIdx = 0;
+                            for (let idx = 1; idx < item.items.length; idx++) {
+                                if (item.items[updateRmIdx].updateDate_time < item.items[idx].updateDate_time) {
+                                    updateRmIdx = idx;
+                                }
+                            }
+                        }
+
+                        if (updateRmIdx >= 0) {
+                            // 删除oss文件
+                            await ctx.app.signPdfOss.delete(`archive/${item.items[updateRmIdx].uuid}.PDF`);
+                            // 以及删除子oss文件
+                            if (item.items[updateRmIdx].childUuids && item.items[updateRmIdx].childUuids.length > 0) {
+                                for (const childUuid of item.items[updateRmIdx].childUuids) {
+                                    await ctx.app.signPdfOss.delete(`archive/${childUuid}.PDF`);
+                                }
+                            }
+                            item.items.splice(updateRmIdx, 1);
+                        }
+
+                        const newItem = { uuid: parentUuidName, updateDate_time: dtStr, childUuids };
+                        item.items.push(newItem);
+                        break;
+                    }
+                }
+                if (!hasArchive) {
+                    // 表示有新的模板需要添加
+                    contentArr.push({ rpt_id: rptId, items: [{ uuid: parentUuidName, updateDate_time: dtStr, childUuids }] });
+                }
+                const updatedRst = await ctx.service.rptArchive.updateArchive(orgArchiveList[0].id, prjId, stgId, contentArr);
+                // console.log(updatedRst);
+                rst = { err: 0, msg: parentUuidName, data: { uuid: parentUuidName, fileName, updateDate, updatedRst: contentArr } };
+            } else {
+                // 需要增加
+                const archiveArr = [];
+                archiveArr.push({ rpt_id: rptId, items: [{ uuid: parentUuidName, updateDate_time: dtStr, childUuids }] });
+                const addedRst = await ctx.service.rptArchive.createArchive(prjId, stgId, archiveArr);
+                rst = { err: 0, msg: parentUuidName, data: { uuid: parentUuidName, fileName, updateDate, updatedRst: archiveArr } };
+            }
+            return rst;
+        }
+
+        async addParentChildrenArchiveReports(ctx) {
+            // 接收多个子母PDF
+            let stream;
+            try {
+                const prjId = ctx.params.prjId;
+                const stgId = ctx.params.stgId;
+                const rptId = ctx.params.rptId;
+                const parentUuid = uuidV1();
+                const childUuids = [];
+                // const newUuidName = uuidV1();
+                const parts = ctx.multipart({ autoFields: true });
+                stream = await parts();
+                let index = 0;
+                while (stream !== undefined) {
+                    /*
+                    // 测试保存文件
+                    await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, 'app/public/upload/', stream.filename));
+                    await sendToWormhole(stream);
+                    //*/
+                    let fileName = parentUuid;
+                    if (index > 0) {
+                        fileName = uuidV1();
+                        childUuids.push(fileName);
+                    }
+                    const oss_result = await ctx.app.signPdfOss.put('archive/' + fileName, stream);
+                    if (!(oss_result && oss_result.url && oss_result.res.status === 200)) {
+                        throw '上传文件失败';
+                    }
+                    index++;
+                    stream = await parts();
+                }
+                const body = this._updateArchiveCommon(ctx, prjId, stgId, rptId, parentUuid, childUuids);
+                ctx.body = body;
+            } catch (error) {
+                ctx.helper.log(error);
+                // 失败需要消耗掉stream 以防卡死
+                if (stream) {
+                    await sendToWormhole(stream);
+                }
+                ctx.body = this.ajaxErrorBody(error, '上传附件失败,请重试');
+            }
+        }
+
         async addReportArchive(ctx) {
             try {
                 const stream = await ctx.getFileStream();
@@ -266,69 +385,12 @@ module.exports = app => {
                 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 } };
-                }
+                const body = this._updateArchiveCommon(ctx, prjId, stgId, rptId, newUuidName, []);
+                ctx.body = body;
             } catch (err) {
                 this.log(err);
                 ctx.body = { err: 1, msg: err.toString(), data: null };
@@ -365,48 +427,8 @@ module.exports = app => {
                     }
                 }
 
-                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 } };
-                }
+                const body = this._updateArchiveCommon(ctx, prjId, stgId, rptId, orgUuidName, []);
+                ctx.body = body;
             } catch (err) {
                 this.log(err);
                 ctx.body = { err: 1, msg: err.toString(), data: null };
@@ -806,7 +828,7 @@ module.exports = app => {
 
                 await this.ctx.service.specMsg.addReportMsg(null, this.ctx.session.sessionProject.id, this.ctx.tender.data, stage, pushOperate.report.file);
                 ctx.body = { err: 0, msg: '提交成功,稍后将同步至档案系统', data: null };
-            } catch(err) {
+            } catch (err) {
                 this.ctx.log(err);
                 this.ctx.ajaxErrorBody(err, '操作失败');
             }

+ 1 - 336
app/controller/report_controller.js

@@ -402,6 +402,7 @@ module.exports = app => {
                 throw '获取模板失败';
             }
             rptTpl = JSON.parse(rptTpl[0].rpt_content);
+            rptTpl.id = params.rpt_tpl_id;
             // console.log('get the template!');
             const customSelect = rptTpl[JV.NODE_CUSTOM_DEFINE] && rptTpl[JV.NODE_CUSTOM_DEFINE][JV.NODE_CUS_AUDIT_SELECT].enable
                 ? await ctx.service.rptCustomDefine.getCustomDefine(params.tender_id, params.stage_id, params.rpt_tpl_id)
@@ -894,20 +895,6 @@ module.exports = app => {
             try {
                 const data = JSON.parse(ctx.request.body.data);
                 await this.ctx.service.rptCustomDefine.saveCustomSelect(data);
-                // const sid = data.gather_select ? -1 : data.stage_id;
-                // const filter = {tid: data.tender_id, sid: sid, rid: data.rpt_tpl_id};
-                // const count = await ctx.service.rptCustomDefine.count(filter);
-                // const updateData = {};
-                // if (data.audit_select) updateData.audit_select = JSON.stringify(data.audit_select);
-                // if (data.gather_select) updateData.gather_select = JSON.stringify(data.gather_select);
-                // if (count > 0) {
-                //     await ctx.service.rptCustomDefine.update(updateData, filter);
-                // } else {
-                //     updateData.tid = data.tender_id;
-                //     updateData.sid = sid;
-                //     updateData.rid = data.rpt_tpl_id;
-                //     await ctx.service.rptCustomDefine.db.insert(ctx.service.rptCustomDefine.tableName, updateData);
-                // }
                 const result = await this._getReport(ctx, data);
                 ctx.body = { err: 0, msg: '', data: result };
             } catch (err) {
@@ -919,328 +906,6 @@ module.exports = app => {
     return ReportController;
 };
 
-async function checkStg(ctx, params) {
-    if (ctx.stage === null || ctx.stage === undefined || parseInt(ctx.stage.id) !== parseInt(params.stage_id)) {
-        await ctx.service.stage.checkStage(params.stage_id);
-        if (ctx.stage) {
-            params.stage_order = ctx.stage.curOrder;
-        }
-    }
-}
-
-async function getMultiRptsCommon(ctx, params, outputType, baseDir) {
-    for (let idx = 0; idx < params.rpt_ids.length; idx++) {
-        params.rpt_ids[idx] = parseInt(params.rpt_ids[idx]); // 转换一下,以防万一
-    }
-    const rptTpls = await ctx.service.rptTpl.getAllTplByIds(params.rpt_ids);
-    rptTpls.sort(function(rpt1, rpt2) {
-        return params.rpt_ids.indexOf(rpt1.id) - params.rpt_ids.indexOf(rpt2.id);
-    });
-    for (let rtIdx = 0; rtIdx < rptTpls.length; rtIdx++) {
-        const id = rptTpls[rtIdx].id;
-        rptTpls[rtIdx] = JSON.parse(rptTpls[rtIdx].rpt_content);
-        rptTpls[rtIdx].id = id;
-    }
-
-    const rptDataUtil = new rptDataExtractor();
-    const filterTables = [];
-    const memFieldKeys = {};
-    let customSelect = {};
-    let customDefine = {};
-    for (const rptTpl of rptTpls) {
-        rptDataUtil.initialize(rptTpl);
-        const filter = rptDataUtil.getDataRequestFilter();
-        // console.log(filter);
-        for (const table of filter.tables) {
-            if (filterTables.indexOf(table) < 0 && needCustomTables.indexOf(table) < 0) {
-                filterTables.push(table);
-            }
-            // memFieldKeys[table] = [];
-        }
-        for (const tableKeyProp in filter.memFieldKeys) {
-            if (needCustomTables.indexOf(tableKeyProp) >= 0) continue;
-            if (!memFieldKeys.hasOwnProperty(tableKeyProp)) {
-                memFieldKeys[tableKeyProp] = [];
-            }
-            for (const mfKey of filter.memFieldKeys[tableKeyProp]) {
-                if (memFieldKeys[tableKeyProp].indexOf(mfKey) < 0) {
-                    memFieldKeys[tableKeyProp].push(mfKey);
-                }
-            }
-        }
-
-        // 输出报表的时候要把客户选择的数据的参数加进来
-        let finCustomSelect = {};
-        if (rptTpl[JV.NODE_CUSTOM_DEFINE]) {
-            finCustomSelect = rptTpl[JV.NODE_CUSTOM_DEFINE] && rptTpl[JV.NODE_CUSTOM_DEFINE][JV.NODE_CUS_AUDIT_SELECT].enable
-                ? await ctx.service.rptCustomDefine.getCustomDefine(params.tender_id, params.stage_id, rptTpl.id)
-                : await ctx.service.rptCustomDefine.getCustomDefine(params.tender_id, -1, rptTpl.id);
-        }
-        if (finCustomSelect) {
-            customDefine = rptTpl[JV.NODE_CUSTOM_DEFINE];
-            customSelect = finCustomSelect;
-        }
-
-    }
-    const rawDataObj = await ctx.service.report.getReportData(params, filterTables, memFieldKeys, customDefine, customSelect);
-    // const rawDataObj = await ctx.service.report.getReportData(params, filterTables, memFieldKeys, {}, {});
-    try {
-        const rptPageRstArray = [];
-        // 1. 这里只用一份数据,根据实际应用情况,先备份
-        // const backupData = {};
-        // for (let filterIdx = 0; filterIdx < filterTables.length; filterIdx++) {
-        //     backupData[filterTables[filterIdx]] = [];
-        //     Object.assign(backupData[filterTables[filterIdx]], rawDataObj[filterTables[filterIdx]]);
-        // }
-        // 2. 一个一个模板创建数据
-        // let defProperties = await ctx.service.rptPreDefineCfg.getCfgById('Administrator');
-        // defProperties = JSON.parse(defProperties[0].defined_content);
-        const defProperties = RPT_DEF_PROPERTIES;
-        for (let tplIdx = 0; tplIdx < rptTpls.length; tplIdx++) {
-            const rptTpl = (rptTpls[tplIdx]._doc) ? rptTpls[tplIdx]._doc : rptTpls[tplIdx];
-            rptDataUtil.initialize(rptTpl);
-            let customSelect = rptTpl[JV.NODE_CUSTOM_DEFINE] && rptTpl[JV.NODE_CUSTOM_DEFINE][JV.NODE_CUS_AUDIT_SELECT].enable
-                ? await ctx.service.rptCustomDefine.getCustomDefine(params.tender_id, params.stage_id, rptTpl.id)
-                : await ctx.service.rptCustomDefine.getCustomDefine(params.tender_id, -1, rptTpl.id);
-            if (rptTpl[JV.NODE_CUSTOM_DEFINE] && rptTpl[JV.NODE_CUSTOM_DEFINE][JV.NODE_CUS_CHANGE_SELECT] && rptTpl[JV.NODE_CUSTOM_DEFINE][JV.NODE_CUS_CHANGE_SELECT].enable) {
-                customSelect = { tid: params.tender_id, rid: params.rpt_tpl_id, sid: -1, change_select: params.customSelect[tplIdx].change_select };
-            }
-
-            // 从汇总的rawDataObj中拷贝所需数据表至curRawDataObj,以供后续使用
-            const curRawDataObj = {};
-            const filter = rptDataUtil.getDataRequestFilter();
-            for (const table of filter.tables) {
-                curRawDataObj[table] = ctx.helper.clone(rawDataObj[table]);
-            }
-            // 如果是用户交互类型的表,则应该单独获取数据
-            if ((params.customSelect && params.customSelect[tplIdx]) || rptTpl[JV.NODE_CUSTOM_DEFINE][JV.NODE_CUS_OPTION]) {
-                const cfTables = [],
-                    cmFieldKeys = [];
-                const curFilter = rptDataUtil.getDataRequestFilter();
-                for (const table of curFilter.tables) {
-                    if (needCustomTables.indexOf(table) >= 0) {
-                        cfTables.push(table);
-                    }
-                }
-                for (const tableKeyProp in filter.memFieldKeys) {
-                    if (needCustomTables.indexOf(tableKeyProp) < 0) continue;
-                    if (!cmFieldKeys.hasOwnProperty(tableKeyProp)) {
-                        cmFieldKeys[tableKeyProp] = [];
-                    }
-                    for (const mfKey of filter.memFieldKeys[tableKeyProp]) {
-                        if (cmFieldKeys[tableKeyProp].indexOf(mfKey) < 0) {
-                            cmFieldKeys[tableKeyProp].push(mfKey);
-                        }
-                    }
-                }
-                const customRawDataObj = await ctx.service.report.getReportData(params, cfTables, cmFieldKeys,
-                    rptTpl[JV.NODE_CUSTOM_DEFINE], customSelect);
-                for (const prop in customRawDataObj) {
-                    curRawDataObj[prop] = customRawDataObj[prop];
-                }
-            }
-
-            const tplData = rptDataUtil.assembleData(ctx, curRawDataObj, baseDir, null, customSelect);
-            const printCom = JpcEx.createNew();
-            rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE] = params.pageSize;
-
-            if (params.pageSize) rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE] = params.pageSize;
-            if (params.orientation && (params.orientation !== 'null')) rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_ORIENTATION] = params.orientation;
-            if (params.custCfg) setupCustomizeCfg(params.custCfg, rptTpl, defProperties);
-            const dftOption = params.option || JV.PAGING_OPTION_NORMAL;
-
-            printCom.initialize(rptTpl);
-            // console.log(rptTpl);
-            printCom.analyzeData(ctx.helper, rptTpl, tplData, defProperties, dftOption, outputType, customSelect);
-            const maxPages = printCom.totalPages;
-            let pageRst = null;
-            // console.log(maxPages);
-            if (maxPages > 0) {
-                pageRst = printCom.outputAsSimpleJSONPageArray(ctx.helper, rptTpl, tplData, 1, maxPages, defProperties, params.custCfg, customSelect);
-            } else {
-                pageRst = printCom.outputAsPreviewPage(rptTpl, defProperties);
-            }
-            pageRst.id = rptTpl.id;
-            rptPageRstArray.push(pageRst);
-            // 注意:这里需要把备份数据assign回去!!!
-            // if (tplIdx < rptTpls.length - 1) {
-            //     for (let filterIdx = 0; filterIdx < filterTables.length; filterIdx++) {
-            //         backupData[filterTables[filterIdx]] = [];
-            //         Object.assign(rawDataObj[filterTables[filterIdx]], backupData[filterTables[filterIdx]]);
-            //     }
-            // }
-        }
-        return rptPageRstArray;
-    } catch (ex) {
-        console.log('报表数据异常(getMultiRptsCommon): project_id ' + params.project_id + ', tender_id: ' + params.tender_id + ', stage_id: ' + params.stage_id);
-        console.log(ex);
-    } finally {
-        //
-    }
-}
-
-function setupCustomizeCfg(customizeCfg, rptTpl, defProperties) {
-    const tmpObj = {};
-    // 1. 字体
-    const newFonts = [];
-    for (const font of defProperties.fonts) {
-        const copyFont = {};
-        copyFont.ID = font.ID;
-        for (const fontProp of JV.FONT_PROPS) {
-            copyFont[fontProp] = font[fontProp];
-        }
-        newFonts.push(copyFont);
-        tmpObj[font.ID] = copyFont;
-    }
-    const private_setup_font = function(propStr, newFont) {
-        if (tmpObj[propStr]) {
-            tmpObj[propStr].Name = newFont.Name;
-            tmpObj[propStr].FontHeight = String(newFont.FontHeight);
-            tmpObj[propStr].FontBold = newFont.FontBold;
-            tmpObj[propStr].FontItalic = newFont.FontItalic;
-            tmpObj[propStr].FontUnderline = newFont.FontUnderline;
-        }
-    };
-    for (const custFont of customizeCfg.fonts) {
-        switch (custFont.CfgDispName) {
-            case '表标题':
-                private_setup_font('ReportTitle_Main', custFont);
-                break;
-            case '列标题':
-                private_setup_font('HeaderColumn', custFont);
-                private_setup_font('FooterColumn', custFont);
-                break;
-            case '正文内容':
-                private_setup_font('Content', custFont);
-                break;
-            case '合计':
-                private_setup_font('GrandTotal', custFont);
-                private_setup_font('SectionTotal', custFont);
-                break;
-            case '表眉/表脚':
-                private_setup_font('Header', custFont);
-                private_setup_font('Footer', custFont);
-                break;
-            default:
-                break;
-        }
-    }
-    // 1.1 窄体
-    if (tmpObj.Content_Narrow) {
-        if (customizeCfg.isNarrow) {
-            tmpObj.Content_Narrow.Name = 'Arial Narrow';
-        } else {
-            if (tmpObj.Content) {
-                tmpObj.Content_Narrow.Name = tmpObj.Content.Name;
-            } else {
-                tmpObj.Content_Narrow.Name = '宋体';
-            }
-        }
-    }
-    defProperties.fonts = newFonts;
-    // 2. 页边距
-    rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_LEFT] = customizeCfg.margins[JV.PROP_LEFT] / 10;
-    rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_RIGHT] = customizeCfg.margins[JV.PROP_RIGHT] / 10;
-    rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_TOP] = customizeCfg.margins[JV.PROP_TOP] / 10;
-    rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_BOTTOM] = customizeCfg.margins[JV.PROP_BOTTOM] / 10;
-    // 3. 边框宽度
-    if (customizeCfg.hasOwnProperty('borderThick')) {
-        for (let i = 0; i < defProperties.styles.length; i++) {
-            const style = defProperties.styles[i];
-            if (style.ID === 'BORDER_ALL_AROUND') {
-                for (const border of style.border_style) {
-                    border.LineWeight = customizeCfg.borderThick;
-                }
-            }
-        }
-    }
-    // 4. 边框竖线
-    if (!(customizeCfg.showVerticalLine)) {
-        const private_copy_border = function(src) {
-            const rst = {};
-            rst.Position = src.Position;
-            rst.LineWeight = src.LineWeight;
-            rst.DashStyle = src.DashStyle;
-            rst.Color = src.Color;
-            return rst;
-        };
-        const newStyles = [];
-        for (let i = 0; i < defProperties.styles.length; i++) {
-            const style = defProperties.styles[i];
-            newStyles.push(style);
-            if (style.ID === 'BORDER_ALL_AROUND') {
-                const newStyle = {};
-                newStyle.ID = style.ID;
-                newStyle.CfgDispName = style.CfgDispName;
-                newStyle.border_style = [];
-                for (const border of style.border_style) {
-                    const newBorder = private_copy_border(border);
-                    newStyle.border_style.push(newBorder);
-                    if (border.Position === 'Left' || border.Position === 'Right') {
-                        newBorder.LineWeight = 0;
-                    }
-                }
-                newStyles[newStyles.length - 1] = newStyle;
-            }
-        }
-        defProperties.styles = newStyles;
-    }
-    // 5. 补0
-    const private_Setup_Format = function(tabFields) {
-        if (tabFields) {
-            for (const tabField of tabFields) {
-                if (tabField[JV.PROP_FORMAT]) {
-                    tabField[JV.PROP_FORMAT] = tabField[JV.PROP_FORMAT].replace(new RegExp('#', 'gm'), '0');
-                }
-            }
-        }
-    };
-    if (customizeCfg.fillZero) {
-        if (rptTpl[JV.NODE_FLOW_INFO]) {
-            if (rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_FLOW_FIELDS]);
-            if (rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_PAGE_SUM]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_PAGE_SUM][JV.PROP_SUM_FIELDS]);
-            if (rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_SEG_SUM]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_SEG_SUM][JV.PROP_SUM_FIELDS]);
-            if (rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP] && rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES][JV.PROP_SUM_FIELDS]);
-            if (rptTpl[JV.NODE_FLOW_INFO][JV.NODE_DISCRETE_INFO]) {
-                for (const discrete of rptTpl[JV.NODE_FLOW_INFO][JV.NODE_DISCRETE_INFO]) {
-                    private_Setup_Format(discrete[JV.PROP_DISCRETE_FIELDS]);
-                }
-            }
-            if (rptTpl[JV.NODE_FLOW_INFO_EX]) {
-                if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_CONTENT]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_CONTENT][JV.PROP_FLOW_FIELDS]);
-                if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_PAGE_SUM]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_PAGE_SUM][JV.PROP_SUM_FIELDS]);
-                if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_SEG_SUM]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_SEG_SUM][JV.PROP_SUM_FIELDS]);
-                if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP][JV.PROP_SUM_FIELDS]);
-                if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP] && rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES]) private_Setup_Format(rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES][JV.PROP_SUM_FIELDS]);
-                if (rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_DISCRETE_INFO]) {
-                    for (const discrete of rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_DISCRETE_INFO]) {
-                        private_Setup_Format(discrete[JV.PROP_DISCRETE_FIELDS]);
-                    }
-                }
-            }
-        } else if (rptTpl[JV.NODE_BILL_INFO]) {
-            if (rptTpl[JV.NODE_BILL_INFO][JV.NODE_BILL_CONTENT]) private_Setup_Format(rptTpl[JV.NODE_BILL_INFO][JV.NODE_BILL_CONTENT][JV.PROP_BILL_FIELDS]);
-            if (rptTpl[JV.NODE_BILL_INFO][JV.NODE_DISCRETE_INFO]) {
-                for (const discrete of rptTpl[JV.NODE_BILL_INFO][JV.NODE_DISCRETE_INFO]) {
-                    private_Setup_Format(discrete[JV.PROP_DISCRETE_FIELDS]);
-                }
-            }
-        } else if (rptTpl[JV.NODE_CROSS_INFO]) {
-            if (rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_CONTENT]) private_Setup_Format(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_CONTENT][JV.TAB_CROSS_FIELDS]);
-            if (rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW]) private_Setup_Format(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW][JV.TAB_CROSS_FIELDS]);
-            if (rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL]) private_Setup_Format(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL][JV.TAB_CROSS_FIELDS]);
-            if (rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL_SUM]) private_Setup_Format(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL_SUM][JV.TAB_CROSS_FIELDS]);
-            if (rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_EXT]) private_Setup_Format(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_EXT][JV.TAB_CROSS_FIELDS]);
-            if (rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_SUM_EXT]) private_Setup_Format(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_SUM_EXT][JV.TAB_CROSS_FIELDS]);
-            if (rptTpl[JV.NODE_CROSS_INFO][JV.NODE_DISCRETE_INFO]) {
-                for (const discrete of rptTpl[JV.NODE_CROSS_INFO][JV.NODE_DISCRETE_INFO]) {
-                    private_Setup_Format(discrete[JV.PROP_DISCRETE_FIELDS]);
-                }
-            }
-        }
-    }
-}
-
 function isFileExisted(file) {
     return new Promise(function(resolve, reject) {
         fs.access(file, err => {

+ 32 - 29
app/public/report/js/jpc_output.js

@@ -453,37 +453,40 @@ let JpcCanvasOutput = {
                     // private_drawImage(cell, control, img);
                 };
             } else if (cell.path) {
-                const img = new Image();
-                // img.src = cell.path;
-                if (cell.path.indexOf(OSS_PATH) < 0 && cell.path[0] !== '/') {
-                    img.src = OSS_PATH + cell.path;
-                } else {
-                    img.src = cell.path;
-                }
-                img.crossOrigin = 'anonymous';
-                img.onload = function() {
-                    if (cell.signature_name.indexOf(JV.SIGNATURE_NAME_DUMMY) >= 0) {
-                        private_drawImage(cell, control, img,moveSignatureTool, (!!cell.isStamp), [1, 1, 1, 1]);
-                    } else {
-                        private_drawImage(cell, control, img,moveSignatureTool);
-                    }
-                    // private_drawImage(cell, control, img, (!!cell.isStamp));
-                };
-                img.onerror = function() {
-                    console.log('cell.path error: ' + cell.path);
-                    const noCroimg = new Image();
-                    if (cell.path.indexOf(OSS_PATH) < 0 && cell.path[0] !== '/') {
-                        noCroimg.src = OSS_PATH + cell.path;
-                    } else {
-                        noCroimg.src = cell.path;
-                    }
-                    noCroimg.onload = function() {
-                        if (cell.signature_name.indexOf(JV.SIGNATURE_NAME_DUMMY) >= 0) {
-                            private_drawImage(cell, control, noCroimg,moveSignatureTool, (!!cell.isStamp), [1, 1, 1, 1]);
+                let paths = cell.path.split('!;!');
+                for (let dtlPath of paths) {
+                    if (typeof dtlPath === 'string' && dtlPath.length > 10) {
+                        const img = new Image();
+                        if (dtlPath.indexOf(OSS_PATH) < 0 && dtlPath[0] !== '/') {
+                            img.src = OSS_PATH + dtlPath;
                         } else {
-                            private_drawImage(cell, control, noCroimg,moveSignatureTool);
+                            img.src = dtlPath;
                         }
-                    };
+                        img.crossOrigin = 'anonymous';
+                        img.onload = function() {
+                            if (cell.signature_name.indexOf(JV.SIGNATURE_NAME_DUMMY) >= 0) {
+                                private_drawImage(cell, control, img,moveSignatureTool, (!!cell.isStamp), [1, 1, 1, 1]);
+                            } else {
+                                private_drawImage(cell, control, img,moveSignatureTool);
+                            }
+                        };
+                        img.onerror = function() {
+                            console.log('cell.path error: ' + dtlPath);
+                            const noCroimg = new Image();
+                            if (dtlPath.indexOf(OSS_PATH) < 0 && dtlPath[0] !== '/') {
+                                noCroimg.src = OSS_PATH + dtlPath;
+                            } else {
+                                noCroimg.src = dtlPath;
+                            }
+                            noCroimg.onload = function() {
+                                if (cell.signature_name.indexOf(JV.SIGNATURE_NAME_DUMMY) >= 0) {
+                                    private_drawImage(cell, control, noCroimg,moveSignatureTool, (!!cell.isStamp), [1, 1, 1, 1]);
+                                } else {
+                                    private_drawImage(cell, control, noCroimg,moveSignatureTool);
+                                }
+                            };
+                        }
+                    }
                 }
             }
         }

+ 30 - 5
app/public/report/js/rpt_archive.js

@@ -600,13 +600,28 @@ let rptArchiveObj = {
                 let pageEncryptInfo = rptArchiveObj._getPageSignatureInfo(currentRptPageRst, currentNode.refId);
                 // console.log(pageEncryptInfo);
                 let formData = new FormData();
-                formData.append('file', doc.output('blob'), 'upload.pdf'); //上传单个文件的添加方式
+                formData.append('file', doc.output('blob'), 'upload.pdf');
+                // formData.append('size', pFile.size);
+                if (currentRptPageRst.splitArcPages) {
+                    let docs = JpcJsPDFHelper.getChildrenDocs(currentRptPageRst, rptControlObj.getCurrentPageSize(), ROLE_REL_LIST, STAGE_AUDIT);
+                    for (let docIdx = 0; docIdx < docs.length; docIdx++) {
+                        let file = docs[docIdx].output('blob');
+                        formData.append('file', file, `upload_child_${docIdx}.pdf`);
+                    }
+                }
                 if (!rptArchiveObj._chkIfFullArchives(currentNode)) {
-                    postDataWithFile('/tender/report_api/addArchive/' + PROJECT_ID + '/' + current_stage_id + '/' + currentNode.refId, formData, function (result) {
+                    let archiveUrl = `/tender/report_api/addArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}`;
+                    if (currentRptPageRst.splitArcPages && currentRptPageRst.splitArcPages.length > 0) {
+                        archiveUrl = `/tender/report_api/addParentChildrenArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}`;
+                    }
+                    postDataWithFile(archiveUrl, formData, function (result) {
+                    // postDataWithFile('/tender/report_api/addArchive/' + PROJECT_ID + '/' + current_stage_id + '/' + currentNode.refId, formData, function (result) {
+                    // postDataWithFile('/tender/report_api/addParentChildrenArchive/' + PROJECT_ID + '/' + current_stage_id + '/' + currentNode.refId, formData, function (result) { // 测试
                         // 成功后,更新当前页面
-                        if (result.addedRst) {
+                        //*
+                        if (result.updatedRst) {
                             // console.log(result);
-                            ARCHIVE_LIST = result.addedRst;
+                            ARCHIVE_LIST = result.updatedRst;
                             rptArchiveObj.showArchivedItem(currentNode);
                             zTreeOprObj.refreshNodes();
                             //第二步:增加加密信息
@@ -617,6 +632,8 @@ let rptArchiveObj = {
                             params.ttlPgs = currentRptPageRst.items.length;
                             params.content = pageEncryptInfo;
                             params.uuid = result.uuid; //正确返回时,带着uuid回来
+                            params.childUuids = result.childUuids; //还有子uuid
+                            params.splitArcPages = currentRptPageRst.splitArcPages ? currentRptPageRst.splitArcPages : [];
                             params.reportName = currentNode.name;
                             CommonAjax.postXsrfEx("/tender/report_api/addArchiveEncryption", params, 10000, true, getCookie('csrfToken_j'),
                                 function(rst){
@@ -643,6 +660,7 @@ let rptArchiveObj = {
                                 }
                             );
                         }
+                        //*/
                     }, function (error){
                         if (cb) {
                             cb('err', 'add archive err!', null);
@@ -659,7 +677,12 @@ let rptArchiveObj = {
                                 orgName = aItem.items[idx].uuid;
                             }
                         }
-                        postDataWithFile('/tender/report_api/updateArchive/' + PROJECT_ID + '/' + current_stage_id + '/' + currentNode.refId + '/' + orgName, formData, function (result) {
+                        let archiveUrl = `/tender/report_api/updateArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}/${orgName}`;
+                        if (currentRptPageRst.splitArcPages && currentRptPageRst.splitArcPages.length > 0) {
+                            archiveUrl = `/tender/report_api/addParentChildrenArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}/${orgName}`;
+                        }
+                        postDataWithFile(archiveUrl, formData, function (result) {
+                        // postDataWithFile('/tender/report_api/updateArchive/' + PROJECT_ID + '/' + current_stage_id + '/' + currentNode.refId + '/' + orgName, formData, function (result) {
                             // 成功后,更新当前页面
                             if (result.updatedRst) {
                                 // console.log(result);
@@ -673,6 +696,8 @@ let rptArchiveObj = {
                                 params.rptId = currentNode.refId;
                                 params.ttlPgs = currentRptPageRst.items.length;
                                 params.content = pageEncryptInfo;
+                                params.childUuids = result.updatedRst.childUuids;
+                                params.splitArcPages = (currentRptPageRst.splitArcPages) ? currentRptPageRst.splitArcPages : [];
                                 params.uuid = orgName;
                                 CommonAjax.postXsrfEx("/tender/report_api/updateArchiveEncryption", params, 10000, true, getCookie('csrfToken_j'),
                                     function(result){

+ 1 - 1
app/public/report/js/rpt_custom.js

@@ -1005,7 +1005,7 @@ const rptCustomObj = (function () {
             data: {'params': JSON.stringify(params)},
             dataType: 'json',
             cache: false,
-            timeout: 60000,
+            timeout: 300000,
             beforeSend: function(xhr) {
                 let csrfToken = Cookies.get('csrfToken_j');
                 xhr.setRequestHeader('x-csrf-token', csrfToken);

+ 23 - 1
app/public/report/js/rpt_jspdf.js

@@ -7,7 +7,7 @@ const PDF_SCALE = 0.75;
 // const DPI = getScreenDPI();
 const NORMAL_LINE_WEIGHT = 0.5;
 
-let JpcJsPDFHelper = {
+const JpcJsPDFHelper = {
     doc: null,
     initialize: function (orientation, unit, format) {
         let me = this;
@@ -707,5 +707,27 @@ let JpcJsPDFHelper = {
             }
             return rotateOptions;
         }
+    },
+    getChildrenDocs: function(pageData, paperSize, signatureRelArr, signAuditArr) {
+        let rst = [];
+        if (pageData.splitArcPages && pageData.splitArcPages.length > 0) {
+            let prePageVal = pageData.splitArcPages[0];
+            let indPages = [];
+            const orgItems = pageData.items;
+            for (let pIdx = 0; pIdx < pageData.splitArcPages.length; pIdx++) {
+                if (prePageVal !== pageData.splitArcPages[pIdx]) {
+                    pageData.items = indPages;
+                    rst.push(JpcJsPDFHelper._createPdf(pageData, paperSize, signatureRelArr, signAuditArr));
+                    indPages = [];
+                    prePageVal = pageData.splitArcPages[pIdx];
+                }
+                indPages.push(orgItems[pIdx]);
+                if (pIdx === pageData.splitArcPages.length - 1) {
+                    pageData.items = indPages;
+                    rst.push(JpcJsPDFHelper._createPdf(pageData, paperSize, signatureRelArr, signAuditArr));
+                }
+            }
+        }
+        return rst;
     }
 }

+ 31 - 74
app/public/report/js/rpt_main.js

@@ -680,7 +680,7 @@ let rptControlObj = {
             }
             if (node.flags && node.flags.amendmentType === 'splitArchive') {
                 // splitArchives.push(node.refId);
-                splitArchives.push({rpt_id: node.refId, split_field_id: parseInt(node.splitArchiveField)});
+                splitArchives.push({rpt_id: node.refId, split_field_id: parseInt(node.flags.splitArchiveField)});
             }
         }
     },
@@ -1047,6 +1047,7 @@ let rptControlObj = {
             const signatureRelArr = [];
             if (refRptTplIds.length > 0) {
                 let params = rptControlObj.creatCommonExportParam(refRptTplIds);
+                params.splitArchives = splitArchives;
                 // params.getPicFlag = true; //专门针对草图项,只有此项为true,才需要把草图信息带过来,预览及打印动态加载草图 // 纠结:但这样还是解决不了效率问题,得另外想交互方式
                 await rptCustomObj.getCustomSelect(params);
                 delete params.orientation; // 打印时有勾选的话,不需要提供方向
@@ -1204,95 +1205,44 @@ let rptControlObj = {
 
 function downloadPDFReport(pageDataArr, pageSize, rpt_names, signatureRelArr, signatureRelInfo, refRptTplIds, STAGE_AUDIT) {
     rptControlObj.currentDownloadIdx = 0;
-    const _resetPageDataByBreaks = function(breakAmt, newRptNames) {
-        let rst = [];
-        for (let pi = 0; pi < pageDataArr.length; pi++) {
-            let pageItem = pageDataArr[pi];
-            let currentRptName = rpt_names[pi];
-            if (pageItem.items.length > breakAmt) {
-                let pa = Math.floor(pageItem.items.length / breakAmt);
-                if (pageItem.items.length % breakAmt > 0) {
-                    pa++;
-                }
-                for (let idx = 0; idx < pa; idx++) {
-                    let newPageDataObj = {items: []};
-                    // newPageDataObj[JV.NODE_PAGE_INFO] = JSON.parse(JSON.stringify(pageItem[JV.NODE_PAGE_INFO]));
-                    newPageDataObj[JV.NODE_PAGE_INFO] = pageItem[JV.NODE_PAGE_INFO];
-                    // newPageDataObj[JV.BAND_PROP_MERGE_BAND] = JSON.parse(JSON.stringify(pageItem[JV.BAND_PROP_MERGE_BAND]));
-                    newPageDataObj[JV.BAND_PROP_MERGE_BAND] = pageItem[JV.BAND_PROP_MERGE_BAND];
-
-                    newPageDataObj[JV.NODE_FONT_COLLECTION] = pageItem[JV.NODE_FONT_COLLECTION];
-                    newPageDataObj[JV.NODE_STYLE_COLLECTION] = pageItem[JV.NODE_STYLE_COLLECTION];
-                    newPageDataObj[JV.NODE_CONTROL_COLLECTION] = pageItem[JV.NODE_CONTROL_COLLECTION];
-
-                    for ( let dIdx = idx * breakAmt; dIdx < (Math.min( (idx + 1) * breakAmt, pageItem.items.length)); dIdx++) {
-                        // newPageDataObj.items.push(JSON.parse(JSON.stringify( pageItem.items[dIdx] )));
-                        newPageDataObj.items.push(pageItem.items[dIdx]);
-                    }
-                    rst.push(newPageDataObj);
-                    newRptNames.push(currentRptName + '_' + (idx + 1));
-                }
-            } else {
-                rst.push(pageItem);
-                newRptNames.push(currentRptName);
-            }
-        }
-        return rst;
-    };
-
     const private_download = function(newPageDataArr, new_rpt_names) {
         if (rptControlObj.currentDownloadIdx < newPageDataArr.length) {
             let singleSignatureRelArr = [];
             for (let rIdx = 0; rIdx < signatureRelInfo.length; rIdx++) {
-                // for (const rptId of refRptTplIds) {
-                //     if (signatureRelInfo[rIdx].rpt_id === rptId) {
-                //         singleSignatureRelArr = signatureRelArr[rIdx]; // 有些报表可能没有签名
-                //         break;
-                //     }
-                // }
                 let rptId = refRptTplIds[rptControlObj.currentDownloadIdx];
                 if (signatureRelInfo[rIdx].rpt_id === rptId) {
                     singleSignatureRelArr = signatureRelArr[rIdx]; // 有些报表可能没有签名
                     break;
                 }
-                // if (signatureRelInfo[rIdx].rpt_id === refRptTplIds[idx]) {
-                //     singleSignatureRelArr = signatureRelArr[rIdx]; // 有些报表可能没有签名
-                //     break;
-                // }
             }
             let pageData = newPageDataArr[rptControlObj.currentDownloadIdx];
             let rptName = new_rpt_names[rptControlObj.currentDownloadIdx];
             rptControlObj.currentDownloadIdx++;
-            /*
-            // 临时代码,为大批量草图PDF下载用(强制分页)
-            const MAX_PAGES_AMT  = 100;
-            const orgItems = pageData.items;
-            let ttlSec = parseInt(orgItems.length / MAX_PAGES_AMT);
-            if (orgItems.length % MAX_PAGES_AMT > 0) {
-                ttlSec++;
-            }
-            for (let idx = 0; idx < ttlSec; idx++) {
-                let indPages = [];
-                for (let pi = idx * MAX_PAGES_AMT; pi < Math.min((idx + 1) * MAX_PAGES_AMT, orgItems.length); pi++ ) {
-                    indPages.push(orgItems[pi]);
-                }
-                pageData.items = indPages;
-                JpcJsPDFHelper.outputAsPdf(pageData, pageSize, rptName + idx, singleSignatureRelArr, STAGE_AUDIT);
-            }
-            pageData.items = orgItems;
-            //*/
 
             JpcJsPDFHelper.outputAsPdf(pageData, pageSize, rptName, singleSignatureRelArr, STAGE_AUDIT); // 精确控制签名
+            if (pageData.splitArcPages) {
+                // let prePageVal = pageData.splitArcPages[0], rptNameIdx = 0;
+                // let indPages = [];
+                // const orgItems = pageData.items;
+                // for (let pIdx = 0; pIdx < pageData.splitArcPages.length; pIdx++) {
+                //     if (prePageVal !== pageData.splitArcPages[pIdx]) {
+                //         pageData.items = indPages;
+                //         JpcJsPDFHelper.outputAsPdf(pageData, pageSize, `${rptName}_${rptNameIdx}`, singleSignatureRelArr, STAGE_AUDIT);
+                //         rptNameIdx++;
+                //         indPages = [];
+                //         prePageVal = pageData.splitArcPages[pIdx];
+                //     }
+                //     indPages.push(orgItems[pIdx]);
+                //     if (pIdx === pageData.splitArcPages.length - 1) {
+                //         pageData.items = indPages;
+                //         JpcJsPDFHelper.outputAsPdf(pageData, pageSize, `${rptName}_${rptNameIdx}`, singleSignatureRelArr, STAGE_AUDIT);
+                //     }
+                // }
+                // 已验证拆分ok
+            }
             if (rptControlObj.currentDownloadIdx < newPageDataArr.length) setTimeout(private_download(newPageDataArr, new_rpt_names), 2000);
         }
     };
-    /*
-    // 这里控制导出PDF的页码数量(如果有设置的话)
-    let newRptNames = []; //这个为导出PDF控制分页用
-    let newPageDataRst = _resetPageDataByBreaks(10, newRptNames);
-    private_download(newPageDataRst, newRptNames);
-    /*/
-
     // 导出PDF真实优化代码
     let picPaths = [], dummyPicAmt = 0, dummyCells = [], dupPicPath = [], dupPicCell = [];
     // 1. 先找有没有dummy
@@ -1420,8 +1370,15 @@ function _getSplitAmendmentParam(params, tplNode) {
     if (params.amendmentType === undefined || params.amendmentType === null) {
         params.splitArchives = [];
     }
-    if (tplNode.flags && tplNode.flags.amendmentType === 'splitArchive' && !params.splitArchiveReports.includes(tplNode.refId)) {
-        params.splitArchives.push({rpt_id: tplNode.refId, split_field_id: parseInt(tplNode.splitArchiveField)});
+    if (tplNode.flags && tplNode.flags.amendmentType === 'splitArchive') {
+        let hasSplit = false;
+        for (let spl of params.splitArchives) {
+            if (spl.split_field_id == tplNode.splitArchiveField) {
+                hasSplit = true;
+                break;
+            }
+        }
+        if (!hasSplit) params.splitArchives.push({rpt_id: tplNode.refId, split_field_id: parseInt(tplNode.flags.splitArchiveField)});
     }
 }
 

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

@@ -153,8 +153,8 @@ let rptPrintHelper = {
                 }
             }
             let svgPageArr = [];
-            console.log(pixelSize);
-            svgPageArr.push("<svg width='" + pixelSize[0] + "' height='" + pixelSize[1] + "'>");
+            // console.log(pixelSize);
+            svgPageArr.push(`<svg width='${pixelSize[0]}' height='${pixelSize[1]}'>"`);
             // let adjustY = 0.5 * ((idx + 1) % 2);
             let adjustY = 0.5;
             for (let cell of page.cells) {

+ 15 - 0
app/reports/rpt_component/jpc_bill_tab.js

@@ -47,6 +47,21 @@ JpcBillTabSrv.prototype.createNew = function() {
             }
         }
         me.totalPages = rst;
+        if (dataObj.splitArcVals) {
+            // 账单式表 分割
+            let preVal = dataObj.splitArcVals[0];
+            let pgIdx = 1;
+            const pagesForPreSplit = [];
+            pagesForPreSplit.push(pgIdx);
+            for (let idx = 1; idx < dataObj.splitArcVals.length; idx++) {
+                if (preVal !== dataObj.splitArcVals[idx]) {
+                    preVal = dataObj.splitArcVals[idx];
+                    pgIdx++;
+                }
+                pagesForPreSplit.push(pgIdx);
+            }
+            dataObj.splitArcPages = pagesForPreSplit;
+        }
         return rst;
     };
     JpcBillTabResult.outputAsPreviewPage = function(rptTpl, bands, controls, $CURRENT_RPT) {

+ 37 - 33
app/reports/rpt_component/jpc_data.js

@@ -1,60 +1,64 @@
-let JV = require('./jpc_value_define');
-let jpc_common_helper = require("./helper/jpc_helper_common");
-let JpcData = {
-    createNew: function() {
-        let JpcDataRst = {};
+'use strict';
+
+const JV = require('./jpc_value_define');
+const jpc_common_helper = require('./helper/jpc_helper_common');
+const JpcData = {
+    createNew() {
+        const JpcDataRst = {};
         JpcDataRst.dataSeq = [];
         JpcDataRst.exDataSeq = [];
         JpcDataRst.analyzeData = function(rptTpl, dataObj) {
-            let me = this;
-            let private_analyse = function(MASTER_FIELD_STR, DETAIL_FIELD_STR, MASTER_DATA_STR, DETAIL_DATA_STR, dataSeqArr) {
-                //1. get ID fields
-                let masterIDs = [];
+            const me = this;
+            const private_analyse = function(MASTER_FIELD_STR, DETAIL_FIELD_STR, MASTER_DATA_STR, DETAIL_DATA_STR, dataSeqArr) {
+                // 1. get ID fields
+                const masterIDs = [];
                 if (rptTpl[JV.NODE_FIELD_MAP][MASTER_FIELD_STR]) {
                     for (let i = 0; i < rptTpl[JV.NODE_FIELD_MAP][MASTER_FIELD_STR].length; i++) {
-                        let mstFieldObj = rptTpl[JV.NODE_FIELD_MAP][MASTER_FIELD_STR][i];
+                        const mstFieldObj = rptTpl[JV.NODE_FIELD_MAP][MASTER_FIELD_STR][i];
                         if (jpc_common_helper.getBoolean(mstFieldObj[JV.PROP_IS_ID])) {
-                            masterIDs.push({"idx": i, "seq": mstFieldObj[JV.PROP_ID_SEQ]});
+                            masterIDs.push({ idx: i, seq: mstFieldObj[JV.PROP_ID_SEQ] });
                         }
                     }
                 }
-                let detailIDs = [];
+                const detailIDs = [];
                 if (rptTpl[JV.NODE_FIELD_MAP][DETAIL_FIELD_STR]) {
                     for (let i = 0; i < rptTpl[JV.NODE_FIELD_MAP][DETAIL_FIELD_STR].length; i++) {
-                        let dtlFieldObj = rptTpl[JV.NODE_FIELD_MAP][DETAIL_FIELD_STR][i];
+                        const dtlFieldObj = rptTpl[JV.NODE_FIELD_MAP][DETAIL_FIELD_STR][i];
                         if (jpc_common_helper.getBoolean(dtlFieldObj[JV.PROP_IS_ID])) {
-                            detailIDs.push({"idx": i, "seq": dtlFieldObj[JV.PROP_ID_SEQ]});
+                            detailIDs.push({ idx: i, seq: dtlFieldObj[JV.PROP_ID_SEQ] });
                         }
                     }
                 }
-                //2. sort the ID fields
+                // 2. sort the ID fields
                 if (masterIDs.length > 1) {
                     masterIDs.sort(function(a, b) {
-                        return 1*a["seq"] - 1*b["seq"];
-                    })
+                        return 1 * a.seq - 1 * b.seq;
+                    });
                 }
                 if (detailIDs.length > 1) {
                     detailIDs.sort(function(a, b) {
-                        return 1*a["seq"] - 1*b["seq"];
-                    })
+                        return 1 * a.seq - 1 * b.seq;
+                    });
                 }
-                //3. prepare data sequence
+                // 3. prepare data sequence
                 if (masterIDs.length > 0) {
-                    let mst_dt_len = 0, dtl_dt_len = 0, mst_fields = [];
+                    let mst_dt_len = 0,
+                        dtl_dt_len = 0;
+                    const mst_fields = [];
                     for (let i = 0; i < masterIDs.length; i++) {
-                        mst_fields.push(dataObj[MASTER_DATA_STR][masterIDs[i]["idx"]]);
-                        mst_dt_len = dataObj[MASTER_DATA_STR][masterIDs[i]["idx"]].length;
+                        mst_fields.push(dataObj[MASTER_DATA_STR][masterIDs[i].idx]);
+                        mst_dt_len = dataObj[MASTER_DATA_STR][masterIDs[i].idx].length;
                     }
-                    let dtl_fields = [];
+                    const dtl_fields = [];
                     for (let i = 0; i < detailIDs.length; i++) {
-                        dtl_fields.push(dataObj[DETAIL_DATA_STR][detailIDs[i]["idx"]]);
-                        dtl_dt_len = dataObj[DETAIL_DATA_STR][detailIDs[i]["idx"]].length;
+                        dtl_fields.push(dataObj[DETAIL_DATA_STR][detailIDs[i].idx]);
+                        dtl_dt_len = dataObj[DETAIL_DATA_STR][detailIDs[i].idx].length;
                     }
                     let sIdx = 0;
                     let isEqual = true;
                     for (let i = 0; i < mst_dt_len; i++) {
                         dataSeqArr.push([]);
-                        //then compare the master/detail ID-field value
+                        // then compare the master/detail ID-field value
                         for (let j = sIdx; j < dtl_dt_len; j++) {
                             isEqual = true;
                             for (let k = 0; k < mst_fields.length; k++) {
@@ -67,7 +71,7 @@ let JpcData = {
                                 dataSeqArr[i].push(j);
                             } else {
                                 sIdx = j;
-                                //below logic is for the data robustness purpose, to avoid those strange record(detail level) which could not match even one of the master record!
+                                // below logic is for the data robustness purpose, to avoid those strange record(detail level) which could not match even one of the master record!
                                 if (i < mst_dt_len - 1 && j < dtl_dt_len - 1) {
                                     for (let j1 = j; j1 < dtl_dt_len; j1++) {
                                         isEqual = true;
@@ -87,10 +91,10 @@ let JpcData = {
                             }
                         }
                     }
-                } else { //if no master data
+                } else { // if no master data
                     if (dataObj && dataObj[DETAIL_DATA_STR] && dataObj[DETAIL_DATA_STR].length > 0) {
-                        //may be bill type report which may only have discrete fields!
-                        let field = dataObj[DETAIL_DATA_STR][0];
+                        // may be bill type report which may only have discrete fields!
+                        const field = dataObj[DETAIL_DATA_STR][0];
                         dataSeqArr.push([]);
                         for (let i = 0; i < field.length; i++) {
                             dataSeqArr[0].push(i);
@@ -106,7 +110,7 @@ let JpcData = {
             }
         };
         return JpcDataRst;
-    }
+    },
 };
 
-module.exports = JpcData;
+module.exports = JpcData;

+ 16 - 1
app/reports/rpt_component/jpc_ex.js

@@ -168,7 +168,7 @@ JpcExSrv.prototype.createNew = function() {
         me.events = JpcEvent.createNew(rptTpl);
     };
 
-    JpcResult.analyzeData = function($CTX_HELPER, rptTpl, dataObj, defProperties, option, outputType, $CUSTOM_DEFINE) {
+    JpcResult.analyzeData = function($CTX_HELPER, rptTpl, dataObj, defProperties, option, outputType, $CUSTOM_DEFINE, splitArchives = []) {
         const me = this;
         const dftPagingOption = option || JV.PAGING_OPTION_NORMAL;
         // 1. data object
@@ -182,6 +182,21 @@ JpcExSrv.prototype.createNew = function() {
             me.crossTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
         } else {
             dataHelper.analyzeData(rptTpl, dataObj);
+            if (splitArchives.length > 0) {
+                // 这里需要根据标记指标拆分数据 {rpt_id: tplNode.refId, split_field_id: parseInt(tplNode.splitArchiveField)
+                for (const splitArc of splitArchives) {
+                    if (splitArc.rpt_id === rptTpl.id) {
+                        // 匹配报表ID通过,再找分割指示指标
+                        const splitField = $JE.F(splitArc.split_field_id, me);
+                        if (splitField) {
+                            rptTpl.splitFieldId = splitArc.split_field_id;
+                            const df = $JE.getFieldValueArray(splitField, dataObj);
+                            dataObj.splitArcVals = df;
+                            break;
+                        }
+                    }
+                }
+            }
             // 2. tab object
             // pre-condition: the data should be sorted in SQL/NoSQL level!
             // let dt1 = new Date();

+ 2 - 0
app/router.js

@@ -439,6 +439,8 @@ module.exports = app => {
     app.post('/report/cDefine', sessionAuth, 'reportController.setCustomDefine');
 
     app.post('/tender/report_api/addArchive/:prjId/:stgId/:rptId', sessionAuth, 'reportArchiveController.addReportArchive');
+    app.post('/tender/report_api/addParentChildrenArchive/:prjId/:stgId/:rptId', sessionAuth, 'reportArchiveController.addParentChildrenArchiveReports');
+
     app.post('/tender/report_api/updateArchive/:prjId/:stgId/:rptId/:orgName', sessionAuth, 'reportArchiveController.updateReportArchive');
     app.post('/tender/report_api/removeArchive/:prjId/:stgId/:rptId/:orgName', sessionAuth, 'reportArchiveController.removeReportArchive');
 

+ 4 - 2
app/service/jpc_report.js

@@ -56,7 +56,7 @@ module.exports = app => {
                 }
                 const dftOption = params.option || JV.PAGING_OPTION_NORMAL;
                 printCom.initialize(rptTpl);
-                printCom.analyzeData(ctx.helper, rptTpl, tplData, defProperties, dftOption, outputType, customSelect);
+                printCom.analyzeData(ctx.helper, rptTpl, tplData, defProperties, dftOption, outputType, customSelect, params.splitArchives);
                 const maxPages = printCom.totalPages;
                 let pageRst = null;
                 if (maxPages > 0) {
@@ -65,6 +65,7 @@ module.exports = app => {
                     pageRst = printCom.outputAsPreviewPage(rptTpl, defProperties);
                 }
                 pageRst.id = params.rpt_tpl_id;
+                if (tplData.splitArcPages) pageRst.splitArcPages = tplData.splitArcPages;
                 return pageRst;
             } catch (ex) {
                 console.log('报表数据异常, tender id: ' + params.tender_id);
@@ -189,7 +190,7 @@ module.exports = app => {
 
                     printCom.initialize(rptTpl);
                     // console.log(rptTpl);
-                    printCom.analyzeData(ctx.helper, rptTpl, tplData, defProperties, dftOption, outputType, customSelect);
+                    printCom.analyzeData(ctx.helper, rptTpl, tplData, defProperties, dftOption, outputType, customSelect, params.splitArchives);
                     const maxPages = printCom.totalPages;
                     let pageRst = null;
                     // console.log(maxPages);
@@ -199,6 +200,7 @@ module.exports = app => {
                         pageRst = printCom.outputAsPreviewPage(rptTpl, defProperties);
                     }
                     pageRst.id = rptTpl.id;
+                    if (tplData.splitArcPages) pageRst.splitArcPages = tplData.splitArcPages;
                     rptPageRstArray.push(pageRst);
                 }
                 return rptPageRstArray;