Browse Source

其它标段同步设置

laiguoran 4 years ago
parent
commit
ddab749bf2

+ 25 - 2
app/controller/tender_controller.js

@@ -754,6 +754,7 @@ module.exports = app => {
                 const groupList = accountList.filter(item => item.account_group === idx);
                 return { groupName: item, groupList };
             });
+            // 获取固定审批流 or 固定终审
             for (const sp of shenpiConst.sp_lc) {
                 sp.status = ctx.tender.info.shenpi ? ctx.tender.info.shenpi[sp.code] : shenpiConst.sp_status.sqspr;
                 if (sp.status === shenpiConst.sp_status.gdspl) {
@@ -762,13 +763,32 @@ module.exports = app => {
                     sp.audit = await ctx.service.shenpiAudit.getAudit(ctx.tender.id, sp.type, sp.status);
                 }
             }
-            // 获取固定审批流 or 固定终审
+            const tenders = await ctx.service.tender.getList('', null, 1);
+            for (const tender of tenders) {
+                tender.shenpiInfo = await ctx.service.tenderInfo.getTenderShenpiInfo(tender.id);
+                // 获取所有的固定审批流或固定终审
+                const shenpiauditList = {};
+                for (const shenpi in tender.shenpiInfo) {
+                    if (tender.shenpiInfo[shenpi] === shenpiConst.sp_status.gdspl) {
+                        const shenpiList = await ctx.service.shenpiAudit.getAllDataByCondition({ where: { tid: tender.id, sp_type: shenpiConst.sp_type[shenpi], sp_status: tender.shenpiInfo[shenpi] } });
+                        const shenpiIdList = ctx.helper._.map(shenpiList, 'audit_id');
+                        shenpiauditList[shenpi] = shenpiIdList.length ? shenpiIdList : null;
+                    } else if (tender.shenpiInfo[shenpi] === shenpiConst.sp_status.gdzs) {
+                        const shenpiInfo = await ctx.service.shenpiAudit.getDataByCondition({ tid: tender.id, sp_type: shenpiConst.sp_type[shenpi], sp_status: tender.shenpiInfo[shenpi] });
+                        shenpiauditList[shenpi] = shenpiInfo && shenpiInfo.audit_id ? [shenpiInfo.audit_id] : null;
+                    }
+                }
+                tender.shenpiauditList = shenpiauditList;
+            }
+            const categoryData = await ctx.service.category.getAllCategory(ctx.session.sessionProject.id);
             const renderData = {
                 shenpi: shenpiConst,
                 accountList,
                 accountGroup: accountGroupList,
+                tenders,
+                categoryData,
             };
-            await this._list('tender/shenpi.ejs', renderData);
+            await this._list('tender/shenpi.ejs', renderData, 'tender/shenpi_modal.ejs');
         }
 
         async saveTenderInfoShenpi(ctx) {
@@ -829,6 +849,9 @@ module.exports = app => {
                     case 'del':
                         await ctx.service.shenpiAudit.removeAudit(data);
                         break;
+                    case 'copy2ot':
+                        await ctx.service.shenpiAudit.copyAudit2otherTender(data);
+                        break;
                     default:break;
                 }
                 ctx.body = { err: 0, msg: '' };

+ 219 - 7
app/public/js/shenpi.js

@@ -7,7 +7,169 @@
  * @date 2020/10/09
  * @version
  */
-
+const tenderTree = [];
+let parentId = 0;
+// 查询方法
+function findNode (key, value, arr) {
+    for (const a of arr) {
+        if (a[key] && a[key] === value) {
+            return a;
+        }
+    }
+}
+// 初始化TenderTree数据
+function initTenderTree () {
+    const levelCategory = category.filter(function (c) {
+        return c.level && c.level > 0;
+    });
+    function findCategoryNode(cid, value, array) {
+        for (const a of array) {
+            if (a.cid === cid && a.vid === value) {
+                return a;
+            }
+        }
+    }
+    function getCategoryNode(category, value, parent, i = null) {
+        const array = parent ?  parent.children : tenderTree;
+        let cate = findCategoryNode(category.id, value, array);
+        if (!cate) {
+            const cateValue = findNode('id', value, category.value);
+            if (!cateValue) return null;
+            cate = {
+                cid: category.id,
+                vid: value,
+                name: cateValue.value,
+                children: [],
+                level: i ? i : category.level,
+                sort_id: ++parentId,
+            };
+            array.push(cate);
+        }
+        return cate;
+    }
+    function loadTenderCategory (tender) {
+        let tenderCategory = null;
+        for (const [index,lc] of levelCategory.entries()) {
+            const tenderCate = findNode('cid', lc.id, tender.category);
+            if (tenderCate) {
+                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
+            } else {
+                if (index === 0 && tender.category) {
+                    for (const [i,c] of tender.category.entries()) {
+                        const cate = findNode('id', c.cid, category);
+                        tenderCategory = getCategoryNode(cate, c.value, tenderCategory, i+1);
+                    }
+                }
+                return tenderCategory;
+            }
+        }
+        return tenderCategory;
+    }
+    function calculateTender(tender) {
+        if (tender.lastStage) {
+            tender.gather_tp = ZhCalc.add(tender.lastStage.contract_tp, tender.lastStage.qc_tp);
+            tender.end_contract_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.contract_tp);
+            tender.end_qc_tp = ZhCalc.add(tender.lastStage.pre_qc_tp, tender.lastStage.qc_tp);
+            tender.end_gather_tp = ZhCalc.add(tender.end_contract_tp, tender.end_qc_tp);
+            tender.pre_gather_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.pre_qc_tp);
+            tender.yf_tp = ZhCalc.add(tender.lastStage.yf_tp);
+            tender.end_yf_tp = ZhCalc.add(tender.lastStage.pre_yf_tp, tender.yf_tp);
+        }
+    }
+    tenderTree.splice(0, tenderTree.length);
+    for (const t of tenders) {
+        calculateTender(t);
+        t.valid = true;
+        delete t.level;
+        if (t.category && levelCategory.length > 0) {
+            const parent = loadTenderCategory(t);
+            if (parent) {
+                t.level = parent.level + 1;
+                parent.children.push(t);
+            } else {
+                tenderTree.push(t);
+            }
+        } else {
+            tenderTree.push(t);
+        }
+    }
+}
+function recursiveGetTenderNodeHtml (node, arr, pid, this_code, this_status, aidList = []) {
+    const html = [];
+    html.push('<tr pid="' + pid + '">');
+    // 名称
+    html.push('<td class="in-' + node.level + '">');
+    if (node.cid) {
+        html.push('<i class="fa fa-folder-o"></i> ', node.name);
+    } else {
+        html.push('<span class="text-muted mr-2">');
+        html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+        html.push('</span>');
+        //html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
+        html.push('<a href="javascript: void(0)" id="' + node.id + '">', node.name, '</a>');
+    }
+    html.push('</td>');
+    // 创建人
+    // html.push('<td>', sp_status_list[node.shenpiInfo[shenpi_type]].name, '</td>');
+    html.push('<td>');
+    if (!node.cid) {
+        let auditList = [];
+        let tender_status = 1;
+        if(cur_tenderid === node.id) {
+            html.push(sp_status_list[this_status].name);
+            auditList = aidList;
+            tender_status = this_status;
+        } else {
+            html.push(sp_status_list[node.shenpiInfo[this_code]].name);
+            auditList = node.shenpiauditList[this_code];
+            tender_status = node.shenpiInfo[this_code];
+        }
+        if(tender_status === sp_status.gdspl || tender_status === sp_status.gdzs) {
+            const nameList = [];
+            if(auditList) {
+                for (const uid of auditList) {
+                    const user = _.find(accountList, { id: uid });
+                    nameList.push(user.name);
+                }
+            }
+            html.push('<i class="fa fa-question-circle text-primary" data-container="body" data-toggle="tooltip" data-placement="bottom" ' +
+                'data-original-title="'+ (nameList.length > 0 ? nameList.join('-') : '') +'"></i>');
+        }
+    }
+    html.push('</td>');
+    html.push('<td>');
+    if (!node.cid) {
+        html.push('<input data-tid="'+ node.id +'" type="checkbox"'+ (cur_tenderid === node.id ? ' checked disabled' : '') +'>');
+    }
+    html.push('</td>');
+    html.push('</tr>');
+    if (node.children) {
+        for (const c of node.children) {
+            html.push(recursiveGetTenderNodeHtml(c, node.children, node.sort_id, this_code, this_status, aidList));
+        }
+    }
+    return html.join('');
+}
+// 根据TenderTree数据获取Html代码
+function getTenderTreeHtml (this_code, this_status, aidList = []) {
+    if (tenderTree.length > 0) {
+        const html = [];
+        html.push('<table class="table table-hover table-bordered">');
+        html.push('<thead>', '<tr>');
+        html.push('<th>名称</th>');
+        html.push('<th width="100">审批流程</th>');
+        html.push('<th width="40">选择</th>');
+        html.push('</tr>', '</thead>');
+        parentId = 0;
+        for (const t of tenderTree) {
+            html.push(recursiveGetTenderNodeHtml(t, tenderTree, '', this_code, this_status, aidList));
+        }
+        html.push('</table>');
+        return html.join('');
+    } else {
+        return EmptyTenderHtml.join('');
+    }
+}
 $(document).ready(function () {
     let timer = null;
     let oldSearchVal = null;
@@ -86,8 +248,7 @@ $(document).ready(function () {
             status: this_status
         };
         const _self = $(this);
-        const tenderId = window.location.pathname.split('/')[2];
-        postData('/tender/' + tenderId + '/shenpi/save', prop, function (data) {
+        postData('/tender/' + cur_tenderid + '/shenpi/save', prop, function (data) {
             if (this_status === sp_status.sqspr) {
                 _self.parents('.form-group').siblings('.lc-show').html('');
             } else if (this_status === sp_status.gdspl) {
@@ -145,8 +306,7 @@ $(document).ready(function () {
                 type: 'add',
             };
             const _self = $(this);
-            const tenderId = window.location.pathname.split('/')[2];
-            postData('/tender/' + tenderId + '/shenpi/audit/save', prop, function (data) {
+            postData('/tender/' + cur_tenderid + '/shenpi/audit/save', prop, function (data) {
                 if (this_status === sp_status.gdspl) {
                     _self.parents('ul').append('<li class="pl-3"><a href="javascript:void(0);" class="add-audit"><i class="fa fa-plus"></i> 添加流程</a></li>');
                 }
@@ -168,8 +328,7 @@ $(document).ready(function () {
             type: 'del',
         };
         const _self = $(this);
-        const tenderId = window.location.pathname.split('/')[2];
-        postData('/tender/' + tenderId + '/shenpi/audit/save', prop, function (data) {
+        postData('/tender/' + cur_tenderid + '/shenpi/audit/save', prop, function (data) {
             if (this_status === sp_status.gdspl) {
                 const _selflc = _self.parents('.lc-show');
                 _self.parents('li').remove();
@@ -257,4 +416,57 @@ $(document).ready(function () {
             '                                        </li>';
         return html;
     }
+
+
+    initTenderTree();
+
+    $('.set-otherTender').on('click', function () {
+        const this_code = $(this).data('code');
+        const this_status = parseInt($(this).siblings('.lc-show').siblings('.form-group').find('input:checked').val());
+        const aid_num = $(this).siblings('.lc-show').children('ul').find('.remove-audit').length;
+        const aidList = [];
+        for (let i = 0; i < aid_num; i++) {
+            const aid = parseInt($(this).siblings('.lc-show').children('ul').find('.remove-audit').eq(i).data('id'));
+            aidList.push(aid);
+        }
+        const html = getTenderTreeHtml(this_code, this_status, aidList);
+        $('#shenpi-name').text($(this).data('name'));
+        $('#shenpi_code').val(this_code);
+        $('#shenpi_status').val(this_status);
+        $('#shenpi_auditors').val(aidList.join(','));
+        $('#tender-list').html(html);
+        setTimeout(function () { $("#tender-list [data-toggle='tooltip']").tooltip(); },800);
+    });
+
+    $('#save-other-shenpi').click(function () {
+        $(this).attr('disabled', true);
+        const num = $('#tender-list input:checked').length;
+        if (num < 2) {
+            toastr.warning('请选择需要设置审批同步的标段');
+            return;
+        }
+        const data = {
+            type: 'copy2ot',
+            status: $('#shenpi_status').val(),
+            code: $('#shenpi_code').val(),
+        };
+        if(data.code !== shenpi_status.gdspl) {
+            data.aidList = $('#shenpi_auditors').val();
+        }
+        // 获取已选中的标段
+        const tenderList = [];
+        for (let i = 0; i < num; i++) {
+            const tid = parseInt($('#tender-list input:checked').eq(i).data('tid'));
+            if (tid !== cur_tenderid) {
+                tenderList.push(tid);
+            }
+        }
+        data.tidList = tenderList.join(',');
+        postData('/tender/' + cur_tenderid + '/shenpi/audit/save', data, function () {
+            toastr.success('设置成功');
+            setTimeout(function () {
+                window.location.reload();
+            }, 1000)
+        })
+    })
 });

+ 53 - 0
app/service/shenpi_audit.js

@@ -7,6 +7,7 @@
  * @date 2017/10/25
  * @version
  */
+const shenpiConst = require('../const/shenpi');
 
 module.exports = app => {
 
@@ -57,6 +58,58 @@ module.exports = app => {
             };
             return await this.db.delete(this.tableName, delData);
         }
+
+        async copyAudit2otherTender(data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const shenpi_status = parseInt(data.status);
+                // 1.复制修改当前审批到其他的tender_info里
+                // 2.删除其他的shenpiAudit
+                // 3.添加新的shenpiAudit(还要针对该标段是否为原报进行处理)
+                const tenderInfoUpdateList = [];
+                const tenders = [];
+                for (const tid of data.tidList.split(',')) {
+                    // 获取原报
+                    const tender = await this.ctx.service.tender.getDataById(tid);
+                    if (tender) {
+                        tenders.push({ id: parseInt(tid), user_id: tender.user_id });
+                        const shenpiInfo = await this.ctx.service.tenderInfo.getTenderShenpiInfo(tid);
+                        // 把当前期状态复制到其他标段里
+                        if (shenpiInfo[data.code] !== shenpi_status) {
+                            shenpiInfo[data.code] = shenpi_status;
+                            tenderInfoUpdateList.push({ row: { shenpi: JSON.stringify(shenpiInfo) }, where: { tid: parseInt(tid) } });
+                        }
+                    }
+                }
+                if (tenderInfoUpdateList.length > 0) await transaction.updateRows(this.ctx.service.tenderInfo.tableName, tenderInfoUpdateList);
+                const insertList = [];
+                const needYB = ['ledger', 'revise', 'change'];
+                const canYB = needYB.indexOf(data.code) !== -1;
+                for (const t of tenders) {
+                    if (shenpi_status !== shenpiConst.sp_status.sqspr) {
+                        await transaction.delete(this.tableName, { tid: t.id, sp_type: shenpiConst.sp_type[data.code], sp_status: shenpi_status });
+                        for (const aid of data.aidList.split(',')) {
+                            if (aid !== t.user_id || (aid === t.user_id && canYB)) {
+                                const insertData = {
+                                    tid: t.id,
+                                    sp_type: shenpiConst.sp_type[data.code],
+                                    sp_status: shenpi_status,
+                                    audit_id: parseInt(aid),
+                                };
+                                insertList.push(insertData);
+                            }
+                        }
+                    }
+                }
+                // console.log(tenderInfoUpdateList, insertList);
+                if (insertList.length > 0) await transaction.insert(this.tableName, insertList);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
 
     return ShenpiAudit;

+ 11 - 0
app/service/tender_info.js

@@ -334,6 +334,17 @@ module.exports = app => {
                     { decimal: JSON.stringify(newDecimal) }, { where: { tid: tenderId } });
             }
         }
+
+        /**
+         * 获取标段审批相关信息 (审批设置用)
+         * @param tenderId
+         * @return {Promise<void>}
+         */
+        async getTenderShenpiInfo(tenderId) {
+            const info = await this.getDataByCondition({ tid: tenderId });
+            const shenpiInfo = !info.shenpi || info.shenpi === '' ? defaultInfo.shenpi : JSON.parse(info.shenpi);
+            return shenpiInfo;
+        }
     }
 
     return TenderInfo;

+ 4 - 0
app/view/tender/shenpi.ejs

@@ -14,6 +14,7 @@
                         <% for (const sp of shenpi.sp_lc) { %>
                             <div class="card mb-3">
                                 <div class="card-body">
+                                    <a class="pull-right set-otherTender" data-name="<%- sp.name %>" data-code="<%- sp.code %>" href="#batch" data-toggle="modal" data-target="#batch">设置其他标段</a>
                                     <h5 class="card-title"><%- sp.name %></h5>
                                     <div class="form-group">
                                         <div class="form-group form-check">
@@ -145,6 +146,9 @@
     const accountGroup = JSON.parse('<%- JSON.stringify(accountGroup) %>');
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
     const cur_uid = parseInt('<%- ctx.tender.data.user_id %>');
+    const cur_tenderid = parseInt('<%- ctx.tender.id %>');
+    const tenders = JSON.parse('<%- JSON.stringify(tenders) %>');
+    const category = JSON.parse('<%- JSON.stringify(categoryData) %>');
 </script>
 <script src="/public/js/shenpi.js"></script>
 <script>