Kaynağa Gözat

判断0逻辑改进 + code sync

TonyKang 4 yıl önce
ebeveyn
işleme
40ebf11726

+ 30 - 0
app/controller/signature_controller.js

@@ -55,6 +55,36 @@ module.exports = app => {
         }
 
         /**
+         * 获取多个标段签名角色关联
+         *
+         * @param {Object} ctx - egg全局context
+         * @return {void}
+         */
+        async getMultiRoleRptRels(ctx) {
+            const params = JSON.parse(ctx.request.body.params);
+            const conParams = params.selectedTenders;
+            const rst = await ctx.service.roleRptRel.getCrossTenderRoleRptRels(conParams);
+            ctx.body = { data: rst };
+            ctx.status = 201;
+        }
+
+        /**
+         * 跨标段更新签名角色关联
+         *
+         * @param {Object} ctx - egg全局context
+         * @return {void}
+         */
+        async updateCrossTendersRoleRelationship(ctx) {
+            const params = JSON.parse(ctx.request.body.params);
+            const conParams = params.selectedTenders;
+            const roleRel = params.originalRoleRelList;
+            // updateMultiRoleRelationship
+            const rst = await ctx.service.roleRptRel.updateMultiRoleRelationship(conParams, roleRel);
+            ctx.body = { data: rst };
+            ctx.status = 201;
+        }
+
+        /**
          * 更新最近使用签名
          *
          * @param {Object} ctx - egg全局context

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

@@ -4,7 +4,7 @@
 
 const   TPL_TYPE_NODE = 1,
         TPL_TYPE_TEMPLATE = 2;
-let rpt_tpl_setting = {
+const rpt_tpl_setting = {
     view: {
         selectedMulti: false
     },
@@ -30,7 +30,7 @@ let rpt_tpl_setting = {
     }
 };
 
-let rpt_prj_folder_setting = {
+const rpt_prj_folder_setting = {
     view: {
         selectedMulti: false
     },

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

@@ -354,7 +354,7 @@ let zTreeOprObj = {
     requestNormalReport: function (params) {
         let me = zTreeOprObj;
         $.bootstrapLoading.start();
-        CommonAjax.postXsrfEx("/tender/report_api/getReport", params, 60000, true, getCookie('csrfToken'),
+        CommonAjax.postXsrfEx("/tender/report_api/getReport", params, 300000, true, getCookie('csrfToken'),
             function(result){
                 $.bootstrapLoading.end();
                 let pageRst = result.data;

+ 111 - 60
app/public/report/js/rpt_signature.js

@@ -189,74 +189,84 @@ let rptSignatureHelper = {
     },
     resetESignature: function (pageRst, signatureDivId) {
         // let body = $('#eSignatureBodyDiv');
-        let body = $('#' + signatureDivId);
-        body.empty();
-        const signature_cells = [];
-        const singatureNameArr = [];
-        for (const page of pageRst.items) {
-            if (page.signature_cells) {
-                for (const sCell of page.signature_cells) {
-                    if (sCell.signature_name !== null && sCell.signature_name !== undefined && sCell.signature_name !== 'dummy_pic') {
-                        if (singatureNameArr.indexOf(sCell.signature_name) < 0) {
-                            signature_cells.push(sCell);
-                            singatureNameArr.push(sCell.signature_name);
+        if (pageRst !== null) {
+            let body = $('#' + signatureDivId);
+            body.empty();
+            const signature_cells = [];
+            const singatureNameArr = [];
+            for (const page of pageRst.items) {
+                if (page.signature_cells) {
+                    for (const sCell of page.signature_cells) {
+                        if (sCell.signature_name !== null && sCell.signature_name !== undefined && sCell.signature_name !== 'dummy_pic') {
+                            if (singatureNameArr.indexOf(sCell.signature_name) < 0) {
+                                signature_cells.push(sCell);
+                                singatureNameArr.push(sCell.signature_name);
+                            }
                         }
                     }
                 }
             }
-        }
-        if (signature_cells.length > 0) {
-            const elementsStrArr = [];
-            const elementsDateStrArr = [];
-            for (let scIdx = 0; scIdx < signature_cells.length; scIdx++) {
-                const sCell = signature_cells[scIdx];
-                elementsStrArr.push('<div class="form-group row">');
-                elementsStrArr.push('<label for="staticEmail" class="col-sm-3 col-form-label pr-0">' + sCell.signature_name + '</label>');
-                elementsStrArr.push('<div class="col-sm-9">');
-                elementsStrArr.push('<ul class="list-group">');
-                elementsStrArr.push('<li class="list-group-item">');
-                let hasPic = false;
-                //新需求中,即使没有审核,也可以设置签名
-                for (let idx = 0; idx < ROLE_REL_LIST.length; idx++) {
-                    const role_rel = ROLE_REL_LIST[idx];
-                    if (role_rel.signature_name === sCell.signature_name) {
-                        if (role_rel.type === '用户') {
-                            rptSignatureHelper.pushDomElementByUser(elementsStrArr, role_rel.user_name, role_rel.role);
-                        } else {
-                            //角色
-                            rptSignatureHelper.pushDomElementByRole(elementsStrArr, role_rel.role_name, role_rel.user_name);
-                        }
-                        const idSuffixStr = 'dtp_' + role_rel.signature_name;
-                        elementsStrArr.push('<div class="">');
-                        if (role_rel.sign_date !== '') {
-                            const dt = new Date(role_rel.sign_date);
-                            const dtVal = dt.Format('yyyy-MM-dd');
-                            //elementsStrArr.push('<input class="datepicker-here form-control form-control-sm mt-0" placeholder="选择签名日期" data-language="zh" type="text" value="' + (new Date(role_rel.sign_date)).Format('yyyy-M-d') + '">');
-                            // elementsStrArr.push('<input id="' + idSuffixStr + '" class="datepicker-here form-control form-control-sm mt-0" placeholder="选择签名日期" data-language="zh" type="text" readonly="true" value="' + dtVal + '"');
-                            elementsStrArr.push('<input id="' + idSuffixStr + '" class="form-control form-control-sm mt-0" placeholder="选择签名日期" type="date" value="' + dtVal + '"');
-                        } else {
-                            // elementsStrArr.push('<input id="' + idSuffixStr + '" class="datepicker-here form-control form-control-sm mt-0" placeholder="选择签名日期" data-language="zh" type="text" readonly="true"');
-                            elementsStrArr.push('<input id="' + idSuffixStr + '" class="form-control form-control-sm mt-0" placeholder="选择签名日期" type="date"');
+            if (signature_cells.length > 0) {
+                const elementsStrArr = [];
+                const elementsDateStrArr = [];
+                for (let scIdx = 0; scIdx < signature_cells.length; scIdx++) {
+                    const sCell = signature_cells[scIdx];
+                    elementsStrArr.push('<div class="form-group row">');
+                    elementsStrArr.push('<label for="staticEmail" class="col-sm-3 col-form-label pr-0">' + sCell.signature_name + '</label>');
+                    elementsStrArr.push('<div class="col-sm-9">');
+                    elementsStrArr.push('<ul class="list-group">');
+                    elementsStrArr.push('<li class="list-group-item">');
+                    let hasPic = false;
+                    //新需求中,即使没有审核,也可以设置签名
+                    for (let idx = 0; idx < ROLE_REL_LIST.length; idx++) {
+                        const role_rel = ROLE_REL_LIST[idx];
+                        if (role_rel.signature_name === sCell.signature_name) {
+                            if (role_rel.type === '用户') {
+                                rptSignatureHelper.pushDomElementByUser(elementsStrArr, role_rel.user_name, role_rel.role);
+                            } else {
+                                //角色
+                                rptSignatureHelper.pushDomElementByRole(elementsStrArr, role_rel.role_name, role_rel.user_name);
+                            }
+                            const idSuffixStr = 'dtp_' + role_rel.signature_name;
+                            elementsStrArr.push('<div class="">');
+                            if (role_rel.sign_date !== '') {
+                                const dt = new Date(role_rel.sign_date);
+                                const dtVal = dt.Format('yyyy-MM-dd');
+                                //elementsStrArr.push('<input class="datepicker-here form-control form-control-sm mt-0" placeholder="选择签名日期" data-language="zh" type="text" value="' + (new Date(role_rel.sign_date)).Format('yyyy-M-d') + '">');
+                                // elementsStrArr.push('<input id="' + idSuffixStr + '" class="datepicker-here form-control form-control-sm mt-0" placeholder="选择签名日期" data-language="zh" type="text" readonly="true" value="' + dtVal + '"');
+                                elementsStrArr.push('<input id="' + idSuffixStr + '" class="form-control form-control-sm mt-0" placeholder="选择签名日期" type="date" value="' + dtVal + '"');
+                            } else {
+                                // elementsStrArr.push('<input id="' + idSuffixStr + '" class="datepicker-here form-control form-control-sm mt-0" placeholder="选择签名日期" data-language="zh" type="text" readonly="true"');
+                                elementsStrArr.push('<input id="' + idSuffixStr + '" class="form-control form-control-sm mt-0" placeholder="选择签名日期" type="date"');
+                            }
+                            hasPic = true;
+                            break;
                         }
-                        hasPic = true;
-                        break;
                     }
+                    if (!hasPic) {
+                        // 在交互操作中,有可能实际上是没有
+                        elementsStrArr.push('<a href="#add-sign" onclick="rptSignatureHelper.currentSelectedESignAccDom = this.parentNode; rptSignatureHelper.currentSelectedESignAccName = \'' + sCell.signature_name + '\'" data-toggle="modal" data-target="#add-sign"><i class="fa fa-plus"></i> 添加签名</a>');
+                    }
+                    // if (sCell.path || sCell.pic) {
+                    // } else {
+                    //     elementsStrArr.push('<a href="#add-sign" onclick="rptSignatureHelper.currentSelectedESignAccDom = this.parentNode; rptSignatureHelper.currentSelectedESignAccName = \'' + sCell.signature_name + '\'" data-toggle="modal" data-target="#add-sign"><i class="fa fa-plus"></i> 添加签名</a>');
+                    // }
+                    elementsStrArr.push('</li>');
+                    elementsStrArr.push('</ul>');
+                    elementsStrArr.push('</div>');
+                    elementsStrArr.push('</div>');
+                    //还有签名日期(用不用得上不管,先放上去再说)
                 }
-                if (!hasPic) {
-                    // 在交互操作中,有可能实际上是没有
-                    elementsStrArr.push('<a href="#add-sign" onclick="rptSignatureHelper.currentSelectedESignAccDom = this.parentNode; rptSignatureHelper.currentSelectedESignAccName = \'' + sCell.signature_name + '\'" data-toggle="modal" data-target="#add-sign"><i class="fa fa-plus"></i> 添加签名</a>');
-                }
-                // if (sCell.path || sCell.pic) {
-                // } else {
-                //     elementsStrArr.push('<a href="#add-sign" onclick="rptSignatureHelper.currentSelectedESignAccDom = this.parentNode; rptSignatureHelper.currentSelectedESignAccName = \'' + sCell.signature_name + '\'" data-toggle="modal" data-target="#add-sign"><i class="fa fa-plus"></i> 添加签名</a>');
-                // }
-                elementsStrArr.push('</li>');
-                elementsStrArr.push('</ul>');
-                elementsStrArr.push('</div>');
-                elementsStrArr.push('</div>');
-                //还有签名日期(用不用得上不管,先放上去再说)
+                body.append(elementsStrArr.join(' '));
             }
-            body.append(elementsStrArr.join(' '));
+        }
+    },
+    checkAndShowCrossTendersESignature: function () {
+        let btnDom = $('#btn_cross_tender')[0];
+        if (zTreeOprObj.currentNode) {
+            btnDom.style.display = '';
+        } else {
+            btnDom.style.display = 'none';
         }
     },
     pushDomElementByUser: function (elementsStrArr, userName, userRole) {
@@ -397,6 +407,47 @@ let rptSignatureHelper = {
             }
         }
     },
+    setupAfterSelectMultiTenders: function (selectedTenders) {
+        //跨标段选择,有不少要注意的交互:
+        //0. 签名日期
+        rptSignatureHelper.resetSignDate();
+        rptSignatureHelper.resetSignAudit();
+        //1. 重刷page
+        if (current_stage_status === 3) {
+            for (const page of zTreeOprObj.currentRptPageRst.items) {
+                if (page.signature_cells) {
+                    for (const sCell of page.signature_cells) {
+                        if (sCell.hasOwnProperty('pre_path')) {
+                            sCell.path = sCell.pre_path;
+                            delete sCell.pre_path;
+                        }
+                    }
+                }
+            }
+            zTreeOprObj.showPage(zTreeOprObj.currentPage, zTreeOprObj.canvas);
+        }
+        //2. 集中请求
+        let params = {};
+        params.id = CURRENT_ROLE_REL_ID;
+        params.tender_id = TENDER_ID;
+        params.stage_id = getStageId();
+        params.rpt_id = zTreeOprObj.currentNode.refId;
+        params.rel_content = ROLE_REL_LIST;
+        params.selectedTenders = selectedTenders;
+        rptSignatureHelper.originalRoleRelList = JSON.parse(JSON.stringify(ROLE_REL_LIST));
+        // CommonAjax.postXsrfEx("/tender/report_api/updateMultiRoleRelationship", params, 10000, true, getCookie('csrfToken'),
+        //     function(result){
+        //         console.log(result);
+        //         if (result.data && result.data.insertId > 0) {
+        //             CURRENT_ROLE_REL_ID = result.data.insertId;
+        //         }
+        //     }, function(err){
+        //         // hintBox.unWaitBox();
+        //     }, function(ex){
+        //         // hintBox.unWaitBox();
+        //     }
+        // );
+    },
     setupAfterSelectSignature: function () {
         //0. 签名日期
         rptSignatureHelper.resetSignDate();

+ 10 - 1
app/reports/rpt_component/helper/jpc_helper_field.js

@@ -86,7 +86,16 @@ const JpcFieldHelper = {
             if (showZero && showZero === 'F') {
                 const val = parseFloat(cell[JV.PROP_VALUE]);
                 if (val === 0) {
-                    cell[JV.PROP_VALUE] = '';
+                    let chkRst = true;
+                    if (typeof cell[JV.PROP_VALUE] === 'string' && cell[JV.PROP_VALUE].length > 1) {
+                        for (let idx = 0; idx < cell[JV.PROP_VALUE].length; idx++) {
+                            if (cell[JV.PROP_VALUE][idx] !== '0' && cell[JV.PROP_VALUE][idx] !== '.') {
+                                chkRst = false;
+                                break;
+                            }
+                        }
+                    }
+                    if (chkRst) cell[JV.PROP_VALUE] = '';
                 }
             }
         }

+ 2 - 0
app/router.js

@@ -305,6 +305,8 @@ module.exports = app => {
     app.post('/tender/report_api/createSignatureRole', sessionAuth, 'signatureController.createSignatureRole');
     app.post('/tender/report_api/updateSignatureUsed', sessionAuth, datetimeFill, 'signatureController.updateSignatureUsed');
     app.post('/tender/report_api/updateRoleRelationship', sessionAuth, 'signatureController.updateRoleRel');
+    app.post('/tender/report_api/updateMultiRoleRelationship', sessionAuth, 'signatureController.updateCrossTendersRoleRelationship');
+    app.post('/tender/report_api/getMultiRoleRelationships', sessionAuth, 'signatureController.getMultiRoleRptRels');
     app.post('/tender/report_api/createRoleRelationship', sessionAuth, 'signatureController.createRoleRel');
     app.post('/tender/report_api/updateCustNode', sessionAuth, 'reportController.updateCustNode');
     app.post('/report/cDefine', sessionAuth, 'reportController.setCustomDefine');

+ 47 - 0
app/service/role_rpt_rel.js

@@ -53,6 +53,27 @@ module.exports = app => {
             return list;
         }
 
+        async getCrossTenderRoleRptRels(selectedTenders) {
+            let rst = [];
+            // 条件比较特别,需要直接写sql
+            if (selectedTenders.length > 0) {
+                let where_sql = '';
+                for (let idx = 0; idx < selectedTenders.length; idx++) {
+                    if (idx === 0) {
+                        where_sql = '(tender_id = ' + selectedTenders[idx][0] + ' AND sid = ' + selectedTenders[idx][1] + ' AND rpt_id = ' + selectedTenders[idx][2] + ')';
+                    } else {
+                        where_sql = where_sql + ' OR (tender_id = ' + selectedTenders[idx][0] + ' AND sid = ' + selectedTenders[idx][1] + ' AND rpt_id = ' + selectedTenders[idx][2] + ')';
+                    }
+                }
+                const sql = 'SELECT ?? FROM ?? WHERE ' + where_sql;
+                const columns = ['id', 'tender_id', 'rpt_id', 'sid', 'rel_content'];
+                const sqlParam = [columns, this.tableName];
+                rst = await this.db.query(sql, sqlParam);
+                console.log(rst);
+            }
+            return rst;
+        }
+
         async getRoleRptRelByDetailIds(tenderId, rptId, sid) {
             this.initSqlBuilder();
             this.sqlBuilder.setAndWhere('tender_id', {
@@ -76,6 +97,9 @@ module.exports = app => {
             });
             this.sqlBuilder.columns = ['id', 'tender_id', 'rpt_id', 'sid', 'rel_content'];
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
+            // console.log(sql);
+            // console.log(this.tableName);
+            // console.log(sqlParam);
             const list = await this.db.query(sql, sqlParam);
             // console.log(list);
             return list;
@@ -144,6 +168,29 @@ module.exports = app => {
             }
             return rst;
         }
+
+        async updateMultiRoleRelationship(orgParams, newRelArr) {
+            let rst = false;
+            this.transaction = await this.db.beginTransaction();
+            try {
+                // const data = { id: id, tender_id: tender_id, rpt_id: rpt_id, sid: sid, rel_content: JSON.stringify(relArr) };
+                // rst = await this.transaction.update(this.tableName, data);
+                // this.transaction.commit();
+                for (let idx = 0; idx < orgParams.length; idx++) {
+                    const param = orgParams[idx];
+                    const data = { tender_id: param[0], sid: param[1], rpt_id: param[2] };
+                    await this.transaction.delete(this.tableName, data);
+                    this.createRoleRelationship(param[0], param[2], param[0], newRelArr);
+                }
+                rst = true;
+                this.transaction.commit();
+            } catch (ex) {
+                console.log(ex.toString());
+                // 回滚
+                await this.transaction.rollback();
+            }
+            return rst;
+        }
     }
     return RoleRptRel;
 };

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

@@ -114,7 +114,7 @@
                             </div>
                             <div class="panel" id="pnl_eSignature">
                                 <div class="panel-body">
-                                    <button class="btn btn-outline-primary btn-sm" type="button" data-toggle="modal" data-target="#eSignature" onclick="rptSignatureHelper.resetESignature(zTreeOprObj.currentRptPageRst, 'eSignatureBodyDiv')">
+                                    <button class="btn btn-outline-primary btn-sm" type="button" data-toggle="modal" data-target="#eSignature" onclick="rptSignatureHelper.resetESignature(zTreeOprObj.currentRptPageRst, 'eSignatureBodyDiv'); rptSignatureHelper.checkAndShowCrossTendersESignature();">
                                         <i class="fa fa-pencil"></i><br>
                                         电子签名
                                     </button>

+ 157 - 12
app/view/report/rpt_all_popup.ejs

@@ -204,7 +204,7 @@
             </div>
             <div class="modal-footer">
                 <!--
-                <button type="button" class="btn btn-sm btn-link float-left" data-dismiss="modal" data-toggle="modal" data-target="#batch-eSignature" id="batch-setupProjSignature" onclick="rptSignatureHelper.resetESignature(zTreeOprObj.currentRptPageRst, 'batch-eSignatureBodyDiv')">批量设置其他标段</button>
+                <button type="button" id="btn_cross_tender" class="btn btn-sm btn-link float-left" data-dismiss="modal" data-toggle="modal" data-target="#batch-eSignature" id="batch-setupProjSignature" onclick="rptSignatureHelper.resetESignature(zTreeOprObj.currentRptPageRst, 'batch-eSignatureBodyDiv'); buildTendersTree();">批量设置其他标段</button>
 
                 <button type="button" class="btn btn-sm btn-link float-left" data-toggle="modal" data-target="#batch-eSignature" id="hidden_show_batch_eSignature" style="display:none"></button>
                 <button type="button" class="btn btn-sm btn-link float-left" data-dismiss="modal" onclick="setTimeout(function(){$('#hidden_show_batch_eSignature').trigger('click');}, 50);">批量设置其他标段</button>
@@ -227,7 +227,7 @@
             <div class="modal-body">
                 <div class="row">
                     <div class="col-6">
-                        <table class="table table-hover table-bordered" id="batch_projects_individual">
+                        <table class="table table-hover table-bordered" id="batch_tenders_individual">
                         </table>
                     </div>
                     <div class="col-6" id="batch-eSignatureBodyDiv"></div>
@@ -236,7 +236,7 @@
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <a href="" class="btn btn-sm btn-primary">确定</a>
+                <a href="javascript:void(0);" onclick="rptSignatureHelper.setupAfterSelectMultiTenders(SELECTED_TENDERS)" class="btn btn-sm btn-primary">确定</a>
             </div>
         </div>
     </div>
@@ -462,10 +462,11 @@
     zTreeOprObj.iniFontCfgDom(CUST_CFG);
     buildCustRptCommon('report_cust_group_common', ORG_TOP_TREE_NODES[1], CUST_TREE_NODES.common, 'true');
     buildCustRptCommon('report_cust_group_individual', ORG_TOP_TREE_NODES[0], CUST_TREE_NODES.customize, 'false');
-    //buildTendersTree();
+    let SELECTED_TENDERS = [];
 
     function buildTendersTree() {
         let sortedCat = [];
+        SELECTED_TENDERS = [];
         for (const cat of category) {
             if (cat.level > 0) {
                 sortedCat.push(cat);
@@ -485,7 +486,8 @@
                             name: nv.value,
                             id : nv.id,
                             cid : nv.cid,
-                            items: []
+                            items: [],
+                            isParent: true
                         };
                         parentItems.push(item);
                         _createItems(item.items, grpLv + 1);
@@ -505,7 +507,7 @@
         //3. 把标段挂上去
         let tmpCacheArr = []; //这个临时用来储存相应标段节点挂接信息
         let _putTender = function (catLv, tender, parentItems) {
-            if (catLv < tender.category.length) {
+            if (catLv < tender.category.length && tender.lastStage !== undefined && tender.lastStage !== null) {
                 let isSorted = false;
                 for (let sCat of sortedCat) {
                     if (sCat.id === tender.category[catLv].cid && sCat.level > 0) {
@@ -522,13 +524,16 @@
                             } else {
                                 //就是这个了
                                 let tdItem = {
-                                    name: tender.value,
+                                    name: tender.name,
                                     id : -1,
                                     cid : -1,
-                                    prj_id: tender.id,
-                                    last_stage: -1,
-                                    signature: '',
-                                    items: []
+                                    tender_id: tender.id,
+                                    last_stage: tender.lastStage.order,
+                                    last_stage_id: tender.lastStage.id,
+                                    report_id: zTreeOprObj.currentNode.refId,
+                                    signature: '临时',
+                                    items: [],
+                                    isParent: false
                                 }; //标段节点
                                 //
                                 tmpCacheArr.push([item, tdItem]);
@@ -544,7 +549,93 @@
         for (const pairItem of tmpCacheArr) {
             pairItem[0].items.push(pairItem[1]);
         }
-        console.log(treeCache);
+        //4. 剔除空items的项
+        let _removeEmptyItems = function (parentItem) {
+            let rst = false;
+            if (parentItem.items.length === 0) {
+                if (parentItem.isParent) {
+                    rst = true;
+                }
+            } else {
+                for (let idx = parentItem.items.length - 1; idx >= 0; idx--) {
+                    if (_removeEmptyItems(parentItem.items[idx])) {
+                        parentItem.items.splice(idx, 1);
+                    }
+                }
+                rst = parentItem.items.length === 0;
+            }
+            return rst;
+        }
+        for (let idx = treeCache.length - 1; idx >= 0; idx--) {
+            if (_removeEmptyItems(treeCache[idx])) {
+                treeCache.splice(idx, 1);
+            }
+        }
+        //console.log(treeCache);
+        //还要请求各标段的原签名数据
+        let params = {};
+        params.selectedTenders = [];
+        let _getTenderRelatedInfos = function(parentItem, rstArr) {
+            if (parentItem.items.length === 0) {
+                if (!parentItem.isParent) {
+                    rstArr.push([parentItem.tender_id, parentItem.last_stage_id, parentItem.report_id]);
+                }
+            } else {
+                for (let idx = parentItem.items.length - 1; idx >= 0; idx--) {
+                    _getTenderRelatedInfos(parentItem.items[idx], rstArr);
+                }
+            }
+        };
+        let _addHint = function(parentItem, relArr) {
+            if (parentItem.items.length === 0) {
+                if (!parentItem.isParent) {
+                    for (const rel of relArr) {
+                        if (rel.tender_id === parentItem.tender_id && rel.sid === parentItem.last_stage_id && rel.rpt_id === parentItem.report_id) {
+                            let hintStr = '';
+                            if (rel.rel_content instanceof Array) {
+                                for (let idx = 0; idx < rel.rel_content.length; idx++) {
+                                    const dtlRel = rel.rel_content[idx];
+                                    if (idx > 0) {
+                                        hintStr = hintStr + '、';
+                                    }
+                                    hintStr = hintStr + '(' + dtlRel.signature_name + ')' + dtlRel.user_name;
+                                }
+                            }
+                            parentItem.signature = hintStr;
+                            break;
+                        }
+                    }
+                }
+            } else {
+                for (let idx = parentItem.items.length - 1; idx >= 0; idx--) {
+                    _getTenderRelatedInfos(parentItem.items[idx], relArr);
+                }
+            }
+        };
+        for (let idx = treeCache.length - 1; idx >= 0; idx--) {
+            _getTenderRelatedInfos(treeCache[idx], params.selectedTenders);
+        }
+        $.bootstrapLoading.start();
+        CommonAjax.postXsrfEx("/tender/report_api/getMultiRoleRelationships", params, 30000, true, getCookie('csrfToken'),
+            function(result){
+                $.bootstrapLoading.end();
+                let relArr = result.data;
+                for (const rel of relArr) {
+                    rel.rel_content = JSON.parse(rel.rel_content);
+                }
+                console.log(relArr);
+                //5. 加hint
+                for (let idx = treeCache.length - 1; idx >= 0; idx--) {
+                    _addHint(treeCache[idx], relArr);
+                }
+                //6. 建树
+                _buildTenderTree('batch_tenders_individual', treeCache);
+            }, function(err){
+                $.bootstrapLoading.end();
+            }, function(ex){
+                $.bootstrapLoading.end();
+            }
+        );
     }
 
     function searchAccount() {
@@ -553,6 +644,46 @@
         }
     }
 
+    function _buildTenderTree(tbDomId, tendersArr) {
+        let tbDom = $("#" + tbDomId);
+        tbDom.empty();
+        //tbDom.append('<tr><th>类别</th><th>包含报表</th><th>显示</th></tr>');
+        tbDom.append('<thead><tr><th>名称</th><th width="50">计量期</th><th width="40">签名</th><th width="40">选择</th></tr></thead>');
+        tbDom.append('<tbody>');
+        const _createRow = function (rowItem, lv) {
+            let tdClassStr = 'in-' + lv;
+            if (rowItem.isParent) {
+                tbDom.append('<tr><td class="' + tdClassStr + '"><i class="fa fa-folder-o"></i>&nbsp;&nbsp;' + rowItem.name + '</td><td></td><td></td><td></td></tr>');
+            } else {
+                let hrefStr = '/tender/' + rowItem.tender_id;
+                //<a href="biaoduan-panel.html" target="_blank">WWUJ-1</a>
+                let lastStgStr = '';
+                if (rowItem.last_stage === -1) {
+                    lastStgStr = '台账';
+                } else {
+                    lastStgStr = '第' + rowItem.last_stage + '期';
+                }
+                //let chgStr = 'changeCrossTender(this, SELECTED_TENDERS,' + rowItem.tender_id + ', ' + rowItem.last_stage_id + ', ' + rowItem.report_id + ')';
+                if (rowItem.signature !== undefined && rowItem.signature !== null && rowItem.signature !== '') {
+                    let hintStr = '<i class="fa fa-exclamation-circle text-primary" data-container="body" data-toggle="tooltip" data-placement="bottom" data-original-title="' + rowItem.signature + '"></i>';
+                    tbDom.append('<tr><td class="' + tdClassStr + '"><a href="' + hrefStr + '" target="_blank">' + rowItem.name + '</a></td><td>' + lastStgStr + '</td><td>' + hintStr + '</td><td><input type="checkbox" onclick="changeCrossTender(this, SELECTED_TENDERS, ' + rowItem.tender_id + ', ' + rowItem.last_stage_id + ', ' + rowItem.report_id + ')' + '"></td></tr>');
+                } else {
+                    tbDom.append('<tr><td class="' + tdClassStr + '"><a href="' + hrefStr + '" target="_blank">' + rowItem.name + '</a></td><td>' + lastStgStr + '</td><td></td><td><input type="checkbox" onclick="changeCrossTender(this, SELECTED_TENDERS, ' + rowItem.tender_id + ', ' + rowItem.last_stage_id + ', ' + rowItem.report_id + ')' + '"></td></tr>');
+                }
+            }
+            if (rowItem.items && rowItem.items.length > 0) {
+                for (const subItem of rowItem.items) {
+                    _createRow(subItem, lv + 1);
+                }
+            }
+        }
+        let grpLv = 1;
+        for (const tItem of tendersArr) {
+            _createRow(tItem, grpLv);
+        }
+        tbDom.append('</tbody>');
+    }
+
     function buildCustRptCommon(tbDomId, topTreeNode, checkingArr, isCommonStr) {
         let tbDom = $("#" + tbDomId);
         tbDom.empty();
@@ -656,6 +787,20 @@
         buildCustRptCommon('report_cust_group_individual', ORG_TOP_TREE_NODES[0], CUST_TREE_NODES.customize, 'false');
     }
 
+    function changeCrossTender(dom, rstArr, tenderId, stageId, reportId) {
+        if (dom.checked) {
+            let item = [tenderId, stageId, reportId];
+            rstArr.push(item);
+        } else {
+            for (let idx = rstArr.length - 1; idx >= 0; idx--) {
+                if (rstArr[idx][0] === tenderId && rstArr[idx][1] === stageId && rstArr[idx][2] === reportId) {
+                    rstArr.splice(idx, 1); //删除当前标段
+                    //这里不break,防止一些冗余数据
+                }
+            }
+        }
+    }
+
     function changeFolder(dom, isCommon, parentIdStr) {
         let prop = null;
         if (isCommon) {

+ 3 - 1
sql/update.sql

@@ -1,4 +1,6 @@
 ALTER TABLE `zh_change` ADD `tp_decimal` TINYINT(3) NULL DEFAULT NULL COMMENT '金额位数' AFTER `sin_time`;
 
 ALTER TABLE `zh_tender_info`
-ADD COLUMN `bid_info`  varchar(200) NULL AFTER `tech_param`;
+ADD COLUMN `bid_info`  varchar(200) NULL AFTER `tech_param`;
+
+CREATE UNIQUE INDEX `idx_tid_sid_rid`  ON `zh_rpt_custom_define` (tid, sid, rid) COMMENT '电子签名数据索引' ALGORITHM DEFAULT LOCK DEFAULT;