Browse Source

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

Tony Kang 2 years ago
parent
commit
56fa8cfe21
41 changed files with 1473 additions and 96 deletions
  1. 9 0
      app/base/base_service.js
  2. 15 1
      app/const/tender_info.js
  3. 7 0
      app/controller/payment_controller.js
  4. 6 1
      app/controller/tender_controller.js
  5. 117 0
      app/lib/rm/base.js
  6. 128 0
      app/lib/rm/payment_safe.js
  7. 3 3
      app/lib/rptCustomData.js
  8. 1 0
      app/lib/rpt_data_analysis.js
  9. 2 2
      app/public/css/main.css
  10. 21 0
      app/public/js/change_information_set.js
  11. 138 25
      app/public/js/file_detail.js
  12. 10 7
      app/public/js/material.js
  13. 9 8
      app/public/js/material_checklist.js
  14. 3 3
      app/public/js/path_tree.js
  15. 205 1
      app/public/js/payment_list.js
  16. 6 5
      app/public/js/payment_process.js
  17. 7 5
      app/public/js/payment_safe.js
  18. 4 0
      app/public/js/revise_price.js
  19. 1 0
      app/public/js/shares/cs_tools.js
  20. 1 0
      app/public/js/shares/tenders2tree.js
  21. 3 2
      app/public/js/spreadjs_rela/spreadjs_zh.js
  22. 4 4
      app/public/js/tender_list_info.js
  23. 2 2
      app/public/js/tender_list_progress.js
  24. 1 1
      app/service/change_audit_list.js
  25. 27 12
      app/service/filing.js
  26. 58 1
      app/service/payment_detail.js
  27. 2 2
      app/service/payment_safe_bills.js
  28. 4 0
      app/service/payment_tender.js
  29. 118 0
      app/service/payment_tender_info.js
  30. 1 1
      app/service/project.js
  31. 12 0
      app/service/report.js
  32. 35 0
      app/service/rpt_stage_sum_memory.js
  33. 10 2
      app/view/file/file.ejs
  34. 3 3
      app/view/file/file_modal.ejs
  35. 5 1
      app/view/payment/audit_modal.ejs
  36. 6 1
      app/view/payment/list.ejs
  37. 442 0
      app/view/payment/list_modal.ejs
  38. 2 2
      app/view/payment/process.ejs
  39. 2 0
      app/view/payment_safe/index.ejs
  40. 38 0
      app/view/tender/detail_modal.ejs
  41. 5 1
      config/web.js

+ 9 - 0
app/base/base_service.js

@@ -229,5 +229,14 @@ class BaseService extends Service {
     round(value, decimal) {
         return this.ctx.helper.round(value, this._.isNumber(decimal) ? decimal : 8);
     }
+
+    // 针对大批量数据插入,优化插入datas,按50条为分隔
+    async insertBigDatas(transaction, insertDatas) {
+        const batchSize = 50;
+        for (let i = 0; i < insertDatas.length; i += batchSize) {
+            const batchDatas = insertDatas.splice(i, i + batchSize);
+            await transaction.insert(this.tableName, batchDatas);
+        }
+    }
 }
 module.exports = BaseService;

+ 15 - 1
app/const/tender_info.js

@@ -53,6 +53,11 @@ const defaultInfo = {
             corporation: '',
             date: '',
         },
+        audit: {
+            company: '',
+            corporation: '',
+            date: '',
+        }
     },
     // 技术参数
     tech_param: {
@@ -172,7 +177,7 @@ const defaultInfo = {
         same_code: true,
         sibling: true,
         over: true,
-        banMinusChangeBills: false,
+        banMinusChangeBills: true,
     },
     fun_rela: {
         hintOver: true,
@@ -196,6 +201,14 @@ const tzDefaultInfo = (function () {
     const result = JSON.parse(JSON.stringify(defaultInfo));
     return result;
 })(defaultInfo);
+const paymentDefaultInfo = (function () {
+    const result = {};
+    result.deal_info = JSON.parse(JSON.stringify(defaultInfo.deal_info));
+    result.construction_unit = JSON.parse(JSON.stringify(defaultInfo.construction_unit));
+    result.tech_param = JSON.parse(JSON.stringify(defaultInfo.tech_param));
+
+    return result;
+})(defaultInfo);
 
 module.exports = {
     parseInfo,
@@ -203,4 +216,5 @@ module.exports = {
     defaultInfo,
     gclDefaultInfo,
     tzDefaultInfo,
+    paymentDefaultInfo,
 };

+ 7 - 0
app/controller/payment_controller.js

@@ -237,6 +237,9 @@ module.exports = app => {
                         }
                         await ctx.service.project.defaultUpdate({ id: ctx.session.sessionProject.id, payment_setting: JSON.stringify(modes) });
                         break;
+                    case 'info':
+                        await ctx.service.paymentTenderInfo.saveTenderInfo(data.postData.id, data.postData.info);
+                        break;
                     default: throw '参数有误';
                 }
                 // 先获取你创建的标段及参与的标段
@@ -764,6 +767,8 @@ module.exports = app => {
                     }
                     trDetailList[0].emptySign = await ctx.service.paymentRptAudit.haveEmptySign(trDetailList[0].id);
                 }
+                const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
+                const tenderInfo = await this.ctx.service.paymentTenderInfo.getTenderInfo(ctx.paymentTender.id);
                 const renderData = {
                     tender: ctx.paymentTender,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.payment.list),
@@ -776,6 +781,8 @@ module.exports = app => {
                     accountList: [],
                     paymentConst,
                     preUrl: '/payment/' + ctx.paymentTender.id + '/list/' + trInfo.id,
+                    categoryData,
+                    tenderInfo,
                 };
                 // 获取报表信息,新增时及设置报表角色时使用
                 if (trInfo.uid === ctx.session.sessionUser.accountId && trInfo.is_del === 0 && trInfo.rpt_id) {

+ 6 - 1
app/controller/tender_controller.js

@@ -1319,7 +1319,9 @@ module.exports = app => {
                         t.lastStage = await this.ctx.service.stage.getLastestStage(t.id, false);
                     }
                 }
-                if (data.type === 'ledger') {
+                if (data.type === 'all') {
+                    responseData.data.tenders = tenderList;
+                } else if (data.type === 'ledger') {
                     responseData.data.tenders = tenderList.filter(x => {
                         return x.ledger_status === auditConst.ledger.status.checked;
                     });
@@ -1633,6 +1635,9 @@ module.exports = app => {
                         case 'show_level':
                             responseData.data[f] = ctx.tender.data.rpt_show_level;
                             break;
+                        case 'tender_info':
+                            responseData.data[f] = ctx.tender.info;
+                            break;
                         default:
                             throw '未知数据类型';
                     }

+ 117 - 0
app/lib/rm/base.js

@@ -0,0 +1,117 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+class rptMemBase {
+    constructor(ctx, bindData) {
+        this.ctx = ctx;
+        // 绑定表配置 -- 绑定表指几个数据表,共用一个加载逻辑,存在任一张时,其他表均同步加载
+        this.bindData = bindData;
+    }
+
+    /**
+     * 数据表分类(普通表,绑定表)
+     * @param sourceFilters
+     * @returns {*[]}
+     */
+    getFilter(sourceFilters) {
+        const common = [], spec = [];
+        for (const sf of sourceFilters) {
+            let bSpec = false;
+            for (const key in this.bindData) {
+                const b = this.bindData[key];
+                if (b.indexOf(sf) >= 0) {
+                    bSpec = true;
+                    if (spec.indexOf(key) === -1) {
+                        spec.push(key);
+                        break;
+                    }
+                }
+            }
+            if (!bSpec) common.push(sf);
+        }
+        return [common, spec];
+    }
+
+    getFieldKeys(source, filter) {
+        const result = [];
+        for (const f of filter) {
+            if (source[f]) result.push(...source[f]);
+        }
+        return result;
+    }
+
+    /**
+     * 获取普通表数据(请在子类重构)
+     * @param params 报表基础传参
+     * @param tableName 表名
+     * @param fields 数据列名
+     * @returns {Promise<void>}
+     */
+    getCommonData(params, tableName, fields) {
+        throw '基础报表数据不可使用';
+    }
+
+    /**
+     * 获取绑定表数据(请在子类重构)
+     * @param params 报表基础传参
+     * @param key
+     * @param fields 数据列名
+     * @returns {Promise<void>}
+     */
+    async getBindData(params, key, fields) {
+        throw '基础报表数据不可使用';
+    }
+
+    /**
+     * 读取报表数据前的预加载部分,子类按需重构
+     * @returns {Promise<void>}
+     */
+    async doBeforeLoadReport(params) {
+        return;
+    }
+
+    /**
+     * 获取报表数据
+     * @param params 报表基础传参
+     * @param sourceFilters 数据表
+     * @param memFieldKeys 数据表-数据列
+     * @returns {Promise<void>}
+     */
+    async getReportData(params, sourceFilters, memFieldKeys) {
+        // 预加载部分(tenderCheck,stageCheck,paymentSafeCheck...)
+        await this.doBeforeLoadReport(params);
+
+        const rst = {};
+        // 数据表分类为普通表,绑定表
+        const [filters, bindFilters] = this.getFilter(sourceFilters);
+        // 加载普通表数据
+        const runnableRst = [];
+        const runnableKey = []; // 这个配合runnableRst用,未来考虑并行查询优化
+        for (const filter of filters) {
+            if (runnableKey.indexOf(filter) >= 0) return;
+            runnableKey.push(filter);
+            runnableRst.push(this.getCommonData(params, filter, memFieldKeys[filter]));
+        }
+        const queryRst = await Promise.all(runnableRst);
+        for (let idx = 0; idx < runnableKey.length; idx++) {
+            rst[runnableKey[idx]] = queryRst[idx];
+        }
+        // 加载绑定表数据局
+        for (const bindFilter of bindFilters) {
+            const resultData = await this.getBindData(params, this.getFieldKeys(memFieldKeys, this.bindData[bindFilter]));
+            for (const d in resultData) {
+                rst[d] = resultData[d];
+            }
+        }
+        return rst;
+    }
+}
+
+module.exports = rptMemBase;

+ 128 - 0
app/lib/rm/payment_safe.js

@@ -0,0 +1,128 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const RptMemBase = require('./base');
+const bindData = {};
+const Ledger = require('../ledger');
+
+class rptMemPaymentSafe extends RptMemBase {
+    constructor(ctx) {
+        super(ctx, bindData);
+    }
+
+    async doCheckTender(tenderId) {
+        if (this.ctx.paymentTender) return;
+        this.ctx.paymentTender = await this.ctx.service.paymentTender.doCheckTender(tenderId);
+    }
+
+    async doCheckDetail(detailId) {
+        if (this.ctx.detail) return;
+        this.ctx.detail = await this.ctx.service.paymentDetail.doCheckDetail(detailId);
+    }
+
+    async doBeforeLoadReport(params) {
+        await this.doCheckTender(params.tender_id);
+        await this.doCheckDetail(params.detail_id);
+    }
+
+    async getSafeBills() {
+        const bills = this.ctx.detail.readOnly
+            ? await ctx.service.paymentSafeBills.getReadData(ctx.detail)
+            : await ctx.service.paymentSafeBills.getEditData(ctx.detail);
+        const setting = {
+            id: 'tree_id',
+            pid: 'tree_pid',
+            order: 'tree_order',
+            level: 'tree_level',
+            isLeaf: 'tree_is_leaf',
+            fullPath: 'tree_full_path',
+            rootId: -1,
+            calcFields: ['pre_tp', 'cur_tp', 'end_tp'],
+        };
+        const billsTree = new Ledger.billsTree(this.ctx, setting);
+        billsTree.loadDatas(bills);
+        billsTree.calculateAll();
+        return billsTree.getDefaultData();
+    }
+    _analysisCompareData(datas, roles){
+        const findHis = function (role, history) {
+            let his = null;
+            for (const h of history) {
+                if (h.times < role.times || (h.times === role.times && h.order <= role.order)) {
+                    his = h;
+                } else {
+                    break;
+                }
+            }
+            return his;
+        };
+        for (const d of datas) {
+            if (!d.tree_is_leaf) continue;
+            d.his_qty = [];
+            d.his_tp = [];
+            d.cur_his.sort((x, y) => { return x.times === y.times ? x.order - y.order : x.times - y.times; });
+            for (const r of roles) {
+                if (r.latest) {
+                    d[`qty_${r.order}`] = d.cur_qty;
+                    d[`tp_${r.order}`] = d.cur_tp;
+                    d.his_qty.push(d.cur_qty);
+                    d.his_tp.push(d.cur_tp);
+                } else {
+                    const rHis = findHis(r, d.cur_his);
+                    if (rHis) {
+                        d[`qty_${r.order}`] = rHis.qty;
+                        d[`tp_${r.order}`] = rHis.tp;
+                    }
+                    d.his_qty.push(rHis ? rHis.qty : 0);
+                    d.his_tp.push(rHis ? rHis.tp : 0);
+                }
+            }
+        }
+    }
+    async getSafeBillsCompare() {
+        const bills = await ctx.service.paymentSafeBills.getCompareData(ctx.detail);
+        const roles = await ctx.service.paymentDetailAudit.getViewFlow(ctx.detail);
+        this._analysisCompareData(bills, roles);
+        const setting = {
+            id: 'tree_id',
+            pid: 'tree_pid',
+            order: 'tree_order',
+            level: 'tree_level',
+            isLeaf: 'tree_is_leaf',
+            fullPath: 'tree_full_path',
+            rootId: -1,
+        };
+        setting.calcFields = roles.map(x => { return `tp_${x.order}`});
+        setting.calcFields.push('pre_tp');
+        const compareTree = new Ledger.billsTree(this.ctx, setting);
+        compareTree.loadDatas(bills);
+        compareTree.calculateAll();
+        return compareTree.getDefaultData();
+    }
+
+    getCommonData(params, tableName, fields) {
+        switch (tableName) {
+            case 'mem_payment_tender':
+                return this.ctx.paymentTender;
+            case 'mem_payment_tender':
+                return this.ctx.service.paymentTenderInfo.getTenderInfo(params.tender_id);
+            case 'mem_payment_detail':
+                return this.ctx.detail;
+            case 'mem_payment_safe_bills':
+                return this.getSafeBills();
+            case 'mem_payment_safe_bills_compare':
+                return this.getSafeBillsCompare();
+            default:
+                return [];
+        }
+    }
+}
+
+module.exports = rptMemPaymentSafe;

+ 3 - 3
app/lib/rptCustomData.js

@@ -522,9 +522,9 @@ class fjHelper {
     }
     async _getStageBillsData(tid, sid) {
         const helper = this.ctx.helper;
-        const billsData = await this.ctx.app.mysql.select(this.ctx.service.ledger.tableName, {
-            where: { tender_id: tid, is_leaf: 1 }
-        });
+        const billsData = this.ctx.stage.ledgerHis
+            ? await this.ctx.helper.loadLedgerDataFromOss(this.ctx.stage.ledgerHis.bills_file)
+            : await this.ctx.service.ledger.getData(this.ctx.tender.id);
 
         const preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
         const curStage = this.ctx.stage.readOnly

+ 1 - 0
app/lib/rpt_data_analysis.js

@@ -1435,6 +1435,7 @@ const stageSelectConverse = {
             for (const t of options.table) {
                 switch (t) {
                     case 'mem_stage_sum_bills':
+                    case 'mem_stage_sum_pos':
                     case 'mem_stage_sum_pay':
                     case 'mem_union_data':
                         data[t] = this._commonConverse(ctx.helper, data[t], gsCustom.stages);

+ 2 - 2
app/public/css/main.css

@@ -680,11 +680,11 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
   width:55px;
   text-align: center;
   display: inline-block;
-  padding:15px 0;
+  padding:10px 0;
   font-size: 12px
 }
 .bg-nav a i{
-  font-size:22px;
+  font-size:18px;
 }
 
 .bg-nav a span{

+ 21 - 0
app/public/js/change_information_set.js

@@ -1618,6 +1618,21 @@ function checkChangeFrom() {
     if(!checkAuditorFrom ()) {
         returnFlag = true;
     }
+    // 判断非空白变更清单是否有重复值(gcl_id及mx_id),如果存在完全相同则需要提示并删除,上报失败,这功能主要是因为清单数据过多服务器处理不过来偶然出现
+    const doubleList = findDuplicates(_.filter(changeList, item => item.lid != 0));
+    if (doubleList.length > 0) {
+        for (const double of doubleList) {
+            const msgIndex = [];
+            for (const one of double) {
+                const index = _.findIndex(changeList, { id: one.id });
+                if (index !== -1) msgIndex.push(index+1);
+            }
+            if (msgIndex.length > 0) {
+                toastr.error('第 ' + msgIndex.splice(',') + ' 行变更清单 ' + double[0].code + ' 重复,请只保留一条数据');
+            }
+        }
+        returnFlag = true;
+    }
     if (returnFlag) {
         return false;
     }
@@ -1634,6 +1649,12 @@ function checkAuditorFrom () {
     }
     return true;
 }
+// 找出数组中相同的清单
+function findDuplicates(arr, keys = ['gcl_id', 'mx_id']) {
+    const groupedData = _.groupBy(arr, item => JSON.stringify(_.pick(item, keys)));
+    const duplicates = _.filter(groupedData, group => group.length > 1);
+    return _.values(duplicates);
+}
 
 function tableDataRemake(changeListData) {
     $('#table-list-select tr').removeClass('table-warning');

+ 138 - 25
app/public/js/file_detail.js

@@ -1,7 +1,5 @@
 $(document).ready(function() {
     autoFlashHeight();
-    console.log($(".sjs-height-0").height());
-    console.log($('#add-slibing').parent().parent().height());
     $('#filing').height($(".sjs-height-0").height() - $('#add-slibing').parent().parent().height() - 10);
     class FilingObj {
         constructor(setting) {
@@ -21,34 +19,51 @@ $(document).ready(function() {
             const cache = getLocalCache(this.expandKey);
             this.expandCache = cache ? _.uniq(cache.split(',')) : [];
             this.curFilingKey = 'cur-filing-' + window.location.pathname.split('/')[2];
+            $('#filing').height($(".sjs-height-0").height()-$('.d-flex',".sjs-height-0").height());
         }
-        analysisFiling(data) {
-            const self = this;
-            this.dragTree.loadDatas(data);
+        calcTotalFileCount() {
             this.dragTree.recursiveFun(this.dragTree.children, x => {
                 if (x.children && x.children.length > 0) {
-                    x.total_file_count = x.children.map(y => {
-                        return y.total_file_count;
-                    }).reduce((pre, value) => {
-                        return pre + value
+                    x.total_file_count = x.children.reduce((pre, c) => {
+                        return pre + c.total_file_count
                     }, 0);
+                    // x.total_file_count = x.children.map(y => {
+                    //     return y.total_file_count;
+                    // }).reduce((pre, value) => {
+                    //     return pre + value
+                    // }, 0);
                 } else {
                     x.total_file_count = x.file_count;
                 }
             });
+        }
+        _loadFilingSourceNode() {
+            const self = this;
+            const loadChildren = function(children) {
+                for (const child of children) {
+                    if (child.children && child.children.length > 0) loadChildren(child.children);
+                    child.source_node = self.dragTree.getItems(child.id);
+                }
+            };
+            const nodes = this.filingTree.getNodes();
+            loadChildren(nodes);
+        }
+        loadFiling() {
+            const self = this;
+            if (this.filingTree) $.fn.zTree.destroy(this.setting.treeId);
             const sortNodes = this.dragTree.nodes.map(x => {
                 const result = {
                     id: x.id,
                     tree_pid: x.tree_pid,
                     name: x.name + (x.total_file_count > 0 ? `(${x.total_file_count})` : ''),
                     spid: x.spid,
-                    source_node: x,
                 };
-                if (result.source_node.is_fixed) result.isParent = true;
-                if (result.source_node.is_folder || result.source_node.is_fixed) result.open = self.expandCache.indexOf(result.id) >= 0;
+                if (x.is_fixed) result.isParent = true;
+                if (x.is_folder || x.is_fixed) result.open = self.expandCache.indexOf(result.id) >= 0;
                 return result;
             });
             this.filingTree = $.fn.zTree.init($('#filing'), this.setting, sortNodes);
+            this._loadFilingSourceNode();
             const curCache = getLocalCache(this.curFilingKey);
             const curNode = curCache ? this.filingTree.getNodeByParam('id', curCache) : null;
             if (curNode){
@@ -56,6 +71,11 @@ $(document).ready(function() {
                 filingObj.setCurFiling(curNode);
             }
         }
+        analysisFiling(data) {
+            this.dragTree.loadDatas(data);
+            this.calcTotalFileCount();
+            this.loadFiling();
+        }
         _getFileNameHtml(file) {
             const editHtml = file.canEdit ? `<a href="javascript: void(0);" class="mr-1" name="edit-file" fid="${file.id}"><i class="fa fa-pencil fa-fw"></i></a>` : '';
             const viewHtml = file.viewpath ? `<a href="${file.viewpath}" class="mr-1" target="_blank"><i class="fa fa-eye fa-fw"></i></a>` : '';
@@ -135,7 +155,8 @@ $(document).ready(function() {
             postData('filing/add', { tree_pid: node.tree_pid, tree_pre_id: node.id }, function(result) {
                 const refreshData = self.dragTree.loadPostData(result);
                 const newNode = refreshData.create[0];
-                self.filingTree.addNodes(node.getParentNode(), node.getIndex() + 1, [{ id: newNode.id, tree_pid: newNode.tree_pid, name: newNode.name, spid: newNode.spid, source_node: newNode}]);
+                const nodes = self.filingTree.addNodes(node.getParentNode(), node.getIndex() + 1, [{ id: newNode.id, tree_pid: newNode.tree_pid, name: newNode.name, spid: newNode.spid }]);
+                nodes[0].source_node = newNode;
             });
         }
         addChildFiling(node) {
@@ -143,7 +164,8 @@ $(document).ready(function() {
             postData('filing/add', { tree_pid: node.id }, function(result) {
                 const refreshData = self.dragTree.loadPostData(result);
                 const newNode = refreshData.create[0];
-                self.filingTree.addNodes(node, -1, [{ id: newNode.id, tree_pid: newNode.tree_pid, name: newNode.name, spid: newNode.spid, source_node: newNode}]);
+                const nodes = self.filingTree.addNodes(node, -1, [{ id: newNode.id, tree_pid: newNode.tree_pid, name: newNode.name, spid: newNode.spid}]);
+                nodes[0].source_node = newNode;
             });
         }
         delFiling(node, callback) {
@@ -182,8 +204,8 @@ $(document).ready(function() {
                     toastr.error('未选择上传文件。');
                     return false;
                 }
-                if (file.size > 30 * 1024 * 1024) {
-                    toastr.error('上传文件大小超过30MB。');
+                if (file.size > 50 * 1024 * 1024) {
+                    toastr.error('上传文件大小超过50MB。');
                     return false;
                 }
                 const fileext = '.' + file.name.toLowerCase().split('.').splice(-1)[0];
@@ -292,16 +314,54 @@ $(document).ready(function() {
             }
             setLocalCache(this.expandKey, this.expandCache.join(','));
         }
-        moveFiling(node, tree_order) {
-            if (tree_order === node.source_node.tree_order) return;
+        expandByLevel(level) {
+            this.expandByCustom(x => {
+                return x.level + 1 < level;
+            })
+        }
+        expandByCustom(fun) {
+            const self = this;
+            const expandCache = [];
+            const expandChildren = function(children) {
+                for (const child of children) {
+                    if (!child.children || child.children.length === 0) continue;
+                    const expand = fun(child);
+                    if (expand) expandCache.push(child.id);
+                    self.filingTree.expandNode(child, expand, false, false);
+                    expandChildren(child.children);
+                }
+            };
+            const nodes = this.filingTree.getNodes();
+            expandChildren(nodes);
+            this.expandCache = expandCache;
+            setLocalCache(this.expandKey, this.expandCache.join(','));
+        }
+        moveFiling(node, tree_pid, tree_order) {
+            if (tree_pid === node.source_node.tree_pid && tree_order === node.source_node.tree_order) return;
 
             const self = this;
-            postData('filing/move', { id: node.id, tree_order }, function(result) {
-                self.dragTree.loadPostData(result);
+            postData('filing/move', { id: node.id, tree_pid, tree_order }, function(result) {
+                const refresh = self.dragTree.loadPostData(result);
+                self.calcTotalFileCount();
+                const updated = [];
+                for (const u of refresh.update) {
+                    const node = self.filingTree.getNodeByParam('id', u.id);
+                    if (node) {
+                        const path = node.getPath();
+                        for (const p of path) {
+                            if (updated.indexOf(p.id) >= 0) continue;
+
+                            p.name = p.source_node.name + (p.source_node.total_file_count > 0 ? `(${p.source_node.total_file_count})` : '');
+                            filingObj.filingTree.updateNode(p);
+                            updated.push(p.id);
+                        }
+                    }
+                }
             });
         }
     }
     const levelTreeSetting = {
+        treeId: 'filing',
         view: {
             selectedMulti: false
         },
@@ -361,15 +421,46 @@ $(document).ready(function() {
                 filingObj.expandFiling(node, false);
             },
             beforeDrop: function(key, nodes, target, moveType, isCopy) {
+                if (!canFiling) return false;
                 if (!target) return false;
-                if (nodes[0].tree_pid !== target.tree_pid) return false;
+                if (nodes[0].level < 1) {
+                    toastr.error('顶层节点请勿移动');
+                    return false;
+                }
+                if (nodes[0].source_node.filing_type !== target.source_node.filing_type) {
+                    toastr.error('请勿跨越最顶层节点移动');
+                    return false;
+                }
+                if (target.source_node.file_count > 0 && moveType === 'inner') {
+                    toastr.error(`节点[${target.source_node.name}]下存在文件,不可添加子级`);
+                    return false;
+                }
 
-                const order = target.getIndex() + 1;
-                const max = target.getParentNode().children.length;
+                const order = nodes[0].getIndex() + 1;
+                const targetOrder = target.getIndex() + 1;
+                const targetMax = target.getParentNode().children.length;
                 if (moveType === 'prev') {
-                    filingObj.moveFiling(nodes[0], order === 1 ? 1 : order - 1)
+                    if (target.tree_pid === nodes[0].tree_pid) {
+                        if (targetOrder > order) {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === 1 ? 1 : targetOrder - 1);
+                        } else {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === 1 ? 1 : targetOrder);
+                        }
+                    } else {
+                        filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === 1 ? 1 : targetOrder);
+                    }
                 } else if (moveType === 'next') {
-                    filingObj.moveFiling(nodes[0], order === max ? max : order + 1);
+                    if (target.tree_pid === nodes[0].tree_pid) {
+                        if (targetOrder < order) {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === targetMax ? targetMax : targetOrder + 1);
+                        } else {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === targetMax ? targetMax : targetOrder);
+                        }
+                    } else {
+                        filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder + 1);
+                    }
+                } else if (moveType === 'inner') {
+                    filingObj.moveFiling(nodes[0], target.tree_id, targetMax + 1);
                 }
             }
         }
@@ -986,4 +1077,26 @@ $(document).ready(function() {
         modal: '#filing-permission',
         list: '#filing-valid',
     });
+
+    // 显示层次
+    (function (select) {
+        $(select).click(function () {
+            const tag = $(this).attr('tag');
+            setTimeout(() => {
+                showWaitingView();
+                switch (tag) {
+                    case "1":
+                    case "2":
+                    case "3":
+                    case "4":
+                        filingObj.expandByLevel(parseInt(tag));
+                        break;
+                    case "last":
+                        filingObj.expandByCustom(() => { return true; });
+                        break;
+                }
+                closeWaitingView();
+            }, 100);
+        });
+    })('a[name=showLevel]');
 });

+ 10 - 7
app/public/js/material.js

@@ -175,9 +175,8 @@ $(document).ready(() => {
     spCol.normalImg = '#ellipsis-icon';
     spCol.indent = 5;
     spCol.showImage = function (data) {
-        // console.log(data, data.t_type);
         // return !readOnly && data.t_type === 2 && data.mid === materialID;
-        return data.t_type === 2;
+        return data && data.t_type === 2;
     };
 
     materialSpreadSetting.imageClick = function (data) {
@@ -333,12 +332,14 @@ $(document).ready(() => {
             }
         },
         materialSheetReset: function (redo = false) {
+
             let newMaterialBillsData = _.cloneDeep(materialBillsData);
             if($('#bills0_list').is(':checked')) {
                 newMaterialBillsData = _.filter(materialBillsData, function (item) {
                     return item.quantity !== null && item.quantity !== 0;
                 });
                 if (redo) {
+                    materialSpread.getActiveSheet().reset();
                     SpreadJsObj.initSpreadSettingEvents(materialSpreadSetting, materialCol);
                     SpreadJsObj.initSheet(materialSpread.getActiveSheet(), materialSpreadSetting);
                 }
@@ -395,6 +396,7 @@ $(document).ready(() => {
                     SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, newMaterialBillsData);
                     // materialSpreadObj.materialSheetReset();
                     sheet.setSelection(newMaterialBillsData.length - 1, 0, 1, 1);
+                    console.log(sheet);
                     materialSpreadObj.refreshActn();
                     // 月信息价需要同时添加空白的list
                     if (months.length > 0) {
@@ -439,9 +441,9 @@ $(document).ready(() => {
                     });
                     newIndex = _.findIndex(newMaterialBillsData, { id: select.id });
                 }
-                sheet.deleteRows(newIndex, 1);
-                sheet.zh_data.splice(newIndex, 1);
-
+                // sheet.deleteRows(newIndex, 1);
+                // sheet.zh_data.splice(newIndex, 1);
+                materialSpreadObj.materialSheetReset(true);
                 resetTpTable();
                 // SpreadJsObj.reLoadSheetData(materialSpread.getActiveSheet());
                 sheet.setSelection(newIndex > 0 ? newIndex - 1 : 0, sel.length > 0 ? sel[0].col : 0, 1, 1);
@@ -1587,6 +1589,7 @@ $(document).ready(() => {
                     if (/(xls|xlsx|XLS|XLSX)$/.test(ext)) {
                         const workbook = XLSX.read(data, {type: 'binary'}); // 以二进制流方式读取得到整份excel表格对象
                         const jsonData = transExcel(XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]], { defval: null }));
+                        console.log(jsonData);
                         if (!(jsonData[0] && jsonData[0].code !== undefined && jsonData[0].code !== null && jsonData[0].unit !== undefined && jsonData[0].name !== undefined &&
                             jsonData[0].spec !== undefined && jsonData[0].msg_tp !== undefined && jsonData[0].msg_times !== undefined)) {
                             throw 'excel必须按指定格式内容上传';
@@ -1646,7 +1649,7 @@ $(document).ready(() => {
                             }
                             toastr.success(msg.length > 1 ? msg.join(',并') : msg[0]);
                         } else {
-                            toastr.warning('导入的工料数据都已存在');
+                            toastr.warning('不存在可导入的信息价数据');
                         }
                         $('#import-info').modal('hide');
                     });
@@ -1932,7 +1935,7 @@ $(document).ready(() => {
             zhKeys.forEach(zhKey => {
                 const enKey = mapInfo[zhKey];
 
-                enObj[enKey] = zhObj[zhKey];
+                enObj[enKey] = zhObj[zhKey] && _.isString(zhObj[zhKey]) ? _.trim(zhObj[zhKey]) : zhObj[zhKey];
             });
 
             return enObj

+ 9 - 8
app/public/js/material_checklist.js

@@ -1165,9 +1165,9 @@ $(document).ready(() => {
                 for (const t of tree) {
                     if(t.children.length === 0) continue;
                     const findObject = {
-                        b_code: t.b_code,
-                        name: t.name,
-                        unit: t.unit,
+                        b_code: t.b_code ? t.b_code.toString() : t.b_code,
+                        name: t.name.toString() ? t.name.toString() : t.name,
+                        unit: t.unit.toString() ? t.unit.toString() : t.unit,
                     };
                     if (!ignoreUnitPrice) findObject.unit_price = t.unit_price ? parseFloat(t.unit_price) : null;
                     const order = _.findIndex(gclGatherData, findObject);
@@ -1336,9 +1336,9 @@ $(document).ready(() => {
                 if (mbList.length === 0) {
                     continue;
                 }
-                const findObject = { b_code: t.b_code,
-                    name: t.name,
-                    unit: t.unit,
+                const findObject = { b_code: t.b_code ? t.b_code.toString() : t.b_code,
+                    name: t.name ? t.name.toString() : t.name,
+                    unit: t.unit ? t.unit.toString() : t.unit,
                 };
                 if (!ignoreUnitPrice) findObject.unit_price = t.unit_price ? parseFloat(t.unit_price) : null;
                 const gclIndex = _.findIndex(gclGatherData, findObject);
@@ -1363,7 +1363,8 @@ $(document).ready(() => {
                     const gclData = gclGatherData[gclIndex];
                     for (const [index, ms] of materialStageData.entries()) {
                         if (ms.id !== ms_id) {
-                            const gclFindObject = { b_code: gclData.b_code, name: gclData.name, unit: gclData.unit };
+                            const gclFindObject = { b_code: gclData.b_code ? gclData.b_code.toString() : gclData.b_code,
+                                name: gclData.name ? gclData.name.toString() : gclData.name, unit: gclData.unit ? gclData.unit.toString() : gclData.unit };
                             if (!ignoreUnitPrice) gclFindObject.unit_price = gclData.unit_price;
                             const gclOther = _.find(gclGatherListData[index], gclFindObject);
                             if (gclOther) {
@@ -1429,7 +1430,7 @@ $(document).ready(() => {
             zhKeys.forEach(zhKey => {
                 const enKey = mapInfo[zhKey];
 
-                enObj[enKey] = zhObj[zhKey];
+                enObj[enKey] = zhObj[zhKey] && _.isString(zhObj[zhKey]) ? _.trim(zhObj[zhKey]) : zhObj[zhKey];
             });
 
             return enObj

+ 3 - 3
app/public/js/path_tree.js

@@ -417,7 +417,7 @@ const createNewPathTree = function (type, setting) {
                 }
                 parents.push(...this.getAllParents(node));
             }
-            this.sortByLevel(parents)
+            this.sortByLevelConverse(parents);
             for (const parent of parents) {
                 if (!parent.children || parent.children.length === 0) continue;
                 parent.filter = !parent.children.find(x => { return !x.filter });
@@ -557,9 +557,9 @@ const createNewPathTree = function (type, setting) {
             const self = this;
             let posterity;
             if (node.full_path !== '') {
-                const reg = new RegExp('^' + node.full_path + '-');
+                const reg = new RegExp('^' + node[self.setting.fullPath] + '-');
                 posterity = this.datas.filter(function (x) {
-                    return reg.test(x.full_path);
+                    return reg.test(x[self.setting.fullPath]);
                 });
             } else {
                 posterity = this._recursiveGetPosterity(node);

+ 205 - 1
app/public/js/payment_list.js

@@ -155,7 +155,11 @@ $(function () {
         }
         console.log($('#add-detail-time').val());
         postData('/payment/' + tenderId + '/list/' + trId + '/save', { type: 'add-detail', code: _.trim($('#add-detail-code').val()), s_time: $('#add-detail-time').val() }, function (result) {
-            window.location.href = '/payment/' + tenderId + '/detail/' + result.id;
+            if (result.type) {
+                window.location.href = '/payment/' + tenderId + '/safe/' + result.id + '/bills';
+            } else {
+                window.location.href = '/payment/' + tenderId + '/detail/' + result.id;
+            }
         });
     });
 
@@ -367,4 +371,204 @@ $(function () {
         }
         return `${year}<span>${mon}-${day}</span><span>${hour}:${minute}:${scond}</span>`;
     };
+
+    class srObject {
+        constructor() {
+            const self = this;
+            this.selectTree = null;
+            const srSpreadSetting = {
+                cols: [
+                    {title: '选择', field: 'selected', hAlign: 1, width: 40, formatter: '@', cellType: 'checkbox'},
+                    {title: '名称', field: 'name', hAlign: 0, width: 300, formatter: '@', cellType: 'tree'},
+                ],
+                emptyRows: 0,
+                headRows: 1,
+                headRowHeight: [32],
+                defaultRowHeight: 21,
+                headerFont: '12px 微软雅黑',
+                font: '12px 微软雅黑',
+                headColWidth: [30],
+                selectedBackColor: '#fffacd',
+                readOnly: true,
+            };
+            this.spread = SpreadJsObj.createNewSpread($('#sr-spread')[0]);
+            this.sheet = this.spread.getActiveSheet();
+            SpreadJsObj.initSheet(this.sheet, srSpreadSetting);
+
+            this.spread.bind(spreadNS.Events.ButtonClicked, function (e, info) {
+                if (!info.sheet.zh_setting) return;
+
+                const col = info.sheet.zh_setting.cols[info.col];
+                if (col.field !== 'selected') return;
+
+                const node = SpreadJsObj.getSelectObject(info.sheet);
+                self.selectNode(node, !node[col.field]);
+                SpreadJsObj.reloadColData(info.sheet, 0);
+            });
+
+            $('#sync-attr-ok').click(() => {
+                const select = self.getSelects();
+                if (select.length === 0) return;
+                if (!select[0].measure_type) {
+                    toastr.warning(`标段[${select[0].name}]未填写任何内容,请选择其他标段`);
+                    return;
+                }
+
+                postData(`/tender/${select[0].tid}/load`, { filter: 'tender_info' }, function (result) {
+                    property.deal_info = result.tender_info.deal_info;
+                    property.construction_unit = result.tender_info.construction_unit;
+                    property.tech_param = result.tender_info.tech_param;
+                    loadCommonProperty(property);
+                    $('#sync-attr').modal('hide');
+                });
+            });
+        }
+        selectNode(node, select) {
+            if (node.children && node.children.length > 0) return;
+            if (select) {
+                this.selectTree.nodes.forEach(x => { x.selected = false });
+            }
+            node.selected = select;
+        }
+        getSelects() {
+            const select = [];
+            for (const n of this.selectTree.nodes) {
+                if ((!n.children || n.children.length === 0) && n.selected) select.push(n);
+            }
+            return select;
+        }
+        init() {
+            const self = this;
+            postData(`/list/load2`, { type: 'all'}, result => {
+                self.selectTree = Tender2Tree.convert(category, result.tenders);
+                SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Tree, this.selectTree);
+            });
+        }
+    }
+    let srSelect;
+    $('#sync-attr').on('shown.bs.modal', () => {
+        if (!srSelect) srSelect = new srObject();
+        srSelect.init();
+    });
+
+    $('#bd-attr').on('show.bs.modal', function () {
+        loadCommonProperty();
+    });
 });
+
+// 标段属性相关
+function loadCommonProperty () {
+    // 合同信息
+    $('#build-name').val(property.deal_info.buildName);
+    $('#deal-code').val(property.deal_info.dealCode);
+    $('#deal-name').val(property.deal_info.dealName);
+    $('#project-type').val(property.deal_info.projectType);
+    $('#deal-type').val(property.deal_info.dealType);
+    $('#final-code').val(property.deal_info.finalCode);
+
+    // 参建单位
+    // 建设单位
+    $('#build-company').val(property.construction_unit.build.company);
+    $('#build-corporation').val(property.construction_unit.build.corporation);
+    $('#build-date').val(property.construction_unit.build.date);
+    // 承包单位1
+    $('#contract1-company').val(property.construction_unit.contract1.company);
+    $('#contract1-corporation').val(property.construction_unit.contract1.corporation);
+    $('#contract1-date').val(property.construction_unit.contract1.date);
+    $('#contract1-management').val(property.construction_unit.contract1.management);
+    // 承包单位2
+    $('#contract2-company').val(property.construction_unit.contract2.company);
+    $('#contract2-corporation').val(property.construction_unit.contract2.corporation);
+    $('#contract2-date').val(property.construction_unit.contract2.date);
+    // 监理单位1
+    $('#supervision1-company').val(property.construction_unit.supervision1.company);
+    $('#supervision1-corporation').val(property.construction_unit.supervision1.corporation);
+    $('#supervision1-date').val(property.construction_unit.supervision1.date);
+    // 监理单位2
+    $('#supervision2-company').val(property.construction_unit.supervision2.company);
+    $('#supervision2-corporation').val(property.construction_unit.supervision2.corporation);
+    $('#supervision2-date').val(property.construction_unit.supervision2.date);
+    // 检测单位
+    $('#detect-company').val(property.construction_unit.detect.company);
+    $('#detect-corporation').val(property.construction_unit.detect.corporation);
+    $('#detect-date').val(property.construction_unit.detect.date);
+
+    // 技术参数
+    $('#load-level').find("option:contains('" + property.tech_param.loadLevel + "')").attr("selected",true);
+    $('#length').val(property.tech_param.loadLength);
+    $('#start-peg').val(property.tech_param.startPeg);
+    $('#end-peg').val(property.tech_param.endPeg);
+    $('#lane-count').val(property.tech_param.laneCount);
+    $('#deal-period').val(property.tech_param.dealPeriod);
+    $('#start-date').val(property.tech_param.startDate);
+    $('#plan-end-date').val(property.tech_param.planEndDate);
+    $('#real-start-date').val(property.tech_param.realStartDate);
+    $('#real-end-date').val(property.tech_param.realEndDate);
+    $('#structure-scale').val(property.tech_param.structureScale);
+}
+
+function postAttr () {
+    const info = {
+        deal_info: {
+            buildName: $('#build-name').val(),
+            dealCode: $('#deal-code').val(),
+            dealName: $('#deal-name').val(),
+            projectType: $('#project-type').val(),
+            dealType: $('#deal-type').val(),
+            finalCode: $('#final-code').val(),
+        },
+        construction_unit: {
+            build: {
+                company: $('#build-company').val(),
+                corporation: $('#build-corporation').val(),
+                date: $('#build-date').val(),
+            },
+            contract1: {
+                company: $('#contract1-company').val(),
+                corporation: $('#contract1-corporation').val(),
+                date: $('#contract1-date').val(),
+                management: $('#contract1-management').val(),
+            },
+            contract2: {
+                company: $('#contract2-company').val(),
+                corporation: $('#contract2-corporation').val(),
+                date: $('#contract2-date').val(),
+            },
+            supervision1: {
+                company: $('#supervision1-company').val(),
+                corporation: $('#supervision1-corporation').val(),
+                date: $('#supervision1-date').val(),
+            },
+            supervision2: {
+                company: $('#supervision2-company').val(),
+                corporation: $('#supervision2-corporation').val(),
+                date: $('#supervision2-date').val(),
+            },
+            detect: {
+                company: $('#detect-company').val(),
+                corporation: $('#detect-corporation').val(),
+                date: $('#detect-date').val(),
+            },
+        },
+        tech_param: {
+            loadLevel: $('#load-level').find("option:selected").text(),
+            loadLength: _.toNumber($('#length').val()),
+            startPeg: $('#start-peg').val(),
+            endPeg: $('#end-peg').val(),
+            laneCount: _.toNumber($('#lane-count').val()),
+            dealPeriod: $('#deal-period').val(),
+            startDate: $('#start-date').val(),
+            planEndDate: $('#plan-end-date').val(),
+            realStartDate: $('#real-start-date').val(),
+            realEndDate: $('#real-end-date').val(),
+            structureScale: $('#structure-scale').val(),
+        },
+    };
+    const tenderId = window.location.pathname.split('/')[2];
+    postData('/payment/save', { type: 'info', postData: { id: tenderId, info} }, function (data) {
+        property.deal_info = info.deal_info;
+        property.construction_unit = info.construction_unit;
+        property.tech_param = info.tech_param;
+        $('#bd-attr').modal('hide');
+    });
+}

+ 6 - 5
app/public/js/payment_process.js

@@ -196,7 +196,7 @@ $(function () {
                 '</div>';
         }
         $('#rpt_user').html(html);
-        $('#process_set input[name="tender_process"][value="'+ trInfo.sp_status +'"]').prop('checked', true);
+        $('input[name="tender_process"][value="'+ trInfo.sp_status +'"]', '#process_set').prop('checked', true);
         const spt = sp_status_list[trInfo.sp_status];
         $('#process_set').find('.alert-warning').text(spt.name + ':' + spt.msg);
         const prop = {
@@ -229,7 +229,7 @@ $(function () {
     });
 
     // 更改审批流程状态
-    $('#process_set .form-check input').on('change', function () {
+    $('#process_set').on('change', `.form-check input`, function () {
         // 获取所有审批的checked值并更新
         const this_status = parseInt($(this).val());
         const this_tr_id = parseInt($('#tender_rpt_table').find('.table-warning').attr('data-id'));
@@ -545,7 +545,7 @@ $(function () {
             });
 
             // 更改审批流程状态
-            $('.form-check input', setting.domId).on('change', function () {
+            $(setting.domId).on('change', '[name=detail_process]', function () {
                 // 获取所有审批的checked值并更新
                 const status = parseInt($(this).val());
                 let tr_id = self.rptInfo.id;
@@ -555,7 +555,8 @@ $(function () {
                 const prop = { type: 'change-status', tr_id, status };
                 postData('/payment/' + tenderId + '/process/save', prop, function (data) {
                     self.rptInfo.sp_status = status;
-                    self.setLcShowHtml(self.rptInfo, data);
+                    self.rptInfo.auditData = data;
+                    self.setLcShowHtml();
                 });
             });
 
@@ -742,7 +743,7 @@ $(function () {
             this.obj.attr('data-trid', this.rptInfo.id);
             $('.card-title', this.domId).find('.card-title').text(this.rptInfo.rpt_name);
             this.refreshUserHtml();
-            $('input[name="tender_process"][value="'+ this.rptInfo.sp_status +'"]', this.obj).prop('checked', true).attr('data-trid', this.rptInfo.id);
+            $('input[name="detail_process"][value="'+ this.rptInfo.sp_status +'"]', this.obj).prop('checked', true).attr('data-trid', this.rptInfo.id);
             const spt = sp_status_list[this.rptInfo.sp_status];
             $('.alert-warning', this.domId).text(spt.name + ':' + spt.msg);
             this.loadAuditList();

+ 7 - 5
app/public/js/payment_safe.js

@@ -125,10 +125,8 @@ $(document).ready(function() {
             setObjEnable($('a[name=base-opr][type=delete]'), valid && first && sameParent && first.tree_level > 1 && !nodeUsed);
             setObjEnable($('a[name=base-opr][type=up-move]'), valid && first && sameParent && first.tree_level > 1 && preNode);
             setObjEnable($('a[name=base-opr][type=down-move]'), valid && first && sameParent && first.tree_level > 1 && !tree.isLastSibling(last));
-            setObjEnable($('a[name=base-opr][type=up-level]'), valid && first && sameParent && tree.getParent(first) && !nodeUsed
-                && first.tree_level > 2 && !tree.isLastSibling(last));
-            setObjEnable($('a[name=base-opr][type=down-level]'), valid && first && sameParent
-                && first.tree_level > 1 && preNode && !this.checkNodeUsed(tree, preNode));
+            setObjEnable($('a[name=base-opr][type=up-level]'), valid && first && sameParent && tree.getParent(first) && !nodeUsed && first.tree_level > 2);
+            setObjEnable($('a[name=base-opr][type=down-level]'), valid && first && sameParent && first.tree_level > 1 && preNode && !this.checkNodeUsed(tree, preNode));
         }
         loadRelaData() {
             this.refreshOperationValid();
@@ -211,7 +209,11 @@ $(document).ready(function() {
             return [this.tree, node, count];
         }
         checkNodeUsed(tree, node) {
-            // todo 检查节点是否已使用
+            if (node.pre_qty || node.pre_tp) return true;
+            const posterity = tree.getPosterity(node);
+            for (const p of posterity) {
+                if (p.pre_qty || p.pre_tp) return true;
+            }
             return false;
         }
         baseOpr(type, addCount = 1) {

+ 4 - 0
app/public/js/revise_price.js

@@ -78,6 +78,7 @@ $(document).ready(() => {
         defaultRowHeight: 21,
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
+        selectedBackColor: '#fffacd',
         readOnly,
         getColor: function (sheet, data, row, col, defaultColor) {
             if (!data) return defaultColor;
@@ -198,6 +199,9 @@ $(document).ready(() => {
                 }
                 this.tree.loadFilter(invalid.join(','), 'filter');
             }
+            console.log(this.tree.nodes.find(x => { return x.code === '1'}));
+            console.log(this.tree.nodes.find(x => { return x.code === '1-2'}));
+            console.log(this.tree.nodes.find(x => { return x.code === '1-2-2'}));
         }
         refreshChangeRela(price, samePrice) {
             if (!samePrice) samePrice = this.getSamePrice(price);

+ 1 - 0
app/public/js/shares/cs_tools.js

@@ -1314,6 +1314,7 @@ const showSelectTab = function(select, spread, afterShow) {
 
         const spread = SpreadJsObj.createNewSpread($(`#std-${setting.stdType}-spread`)[0]);
         const sheet = spread.getActiveSheet();
+        if (setting.spreadSetting) setting.spreadSetting.stdType = setting.stdType;
         SpreadJsObj.initSheet(sheet, setting.spreadSetting || spreadSetting);
 
         if (setting.cellDoubleClick) sheet.bind(spreadNS.Events.CellDoubleClick, setting.cellDoubleClick);

+ 1 - 0
app/public/js/shares/tenders2tree.js

@@ -87,6 +87,7 @@ const Tender2Tree = (function () {
                 name: t.name,
                 phase: t.lastStage ? '第' + t.lastStage.order + '期' : '台账',
                 stageCount: t.lastStage ? t.lastStage.order : 0,
+                measure_type: t.measure_type,
             };
             if (ledgerAuditConst && stageAuditConst) {
                 node.status = t.lastStage ? stageAuditConst.statusString[t.lastStage.status] : ledgerAuditConst.statusString[t.ledger_status];

+ 3 - 2
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -1498,17 +1498,18 @@ const SpreadJsObj = {
 
                 const tree = hitinfo.sheet.zh_tree;
                 if (!tree) { return; }
+                const setting = tree.setting;
 
                 const node = tree.nodes[hitinfo.row];
                 if (!node) { return; }
 
-                let centerX = hitinfo.cellRect.x + offset + (node.level - 1) * indent + (node.level) * levelIndent + indent / 2 + xOffset;
+                let centerX = hitinfo.cellRect.x + offset + (node[setting.level] - 1) * indent + (node[setting.level]) * levelIndent + indent / 2 + xOffset;
                 let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;
 
                 // 点击展开节点时,如果已加载子项,则展开,反之这加载子项,展开
                 if (Math.abs(hitinfo.x - centerX) < halfBoxLength && Math.abs(hitinfo.y - centerY) < halfBoxLength) {
                     const children = tree.getChildren(node);
-                    if (!node.expanded && !node.is_leaf && children.length === 0 && tree.loadChildren) {
+                    if (!node.expanded && !node[setting.isLeaf] && children.length === 0 && tree.loadChildren) {
                         tree.loadChildren(node, function () {
                             node.expanded = true;
                             const children = tree.getChildren(node);

+ 4 - 4
app/public/js/tender_list_info.js

@@ -24,13 +24,13 @@ const tenderListSpec = (function(){
         }
         html.push('</td>');
         // 计量模式
-        html.push('<td style="width: 75px" class="text-center">');
+        html.push('<td style="width: 85px" class="text-center">');
         if (node.measure_type) {
             html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
         }
         html.push('</td>');
         // 计量进度
-        html.push('<td style="width: 105px">');
+        html.push('<td style="width: 125px">');
         if (!node.cid && node.cur_flow) {
             if (node.progress) {
                 html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
@@ -114,8 +114,8 @@ const tenderListSpec = (function(){
         html.push('<table class="table table-hover table-bordered">');
         html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
         html.push('<th class="text-center" style="min-width: 300px;">', '标段名称', '</th>');
-        html.push('<th class="text-center" style="width: 75px">', '计量模式', '</th>');
-        html.push('<th class="text-center" style="width: 105px">', '计量进度', '</th>');
+        html.push('<th class="text-center" style="width: 85px">', '计量模式', '</th>');
+        html.push('<th class="text-center" style="width: 125px">', '计量进度', '</th>');
         html.push('<th class="text-center" style="width: 230px">', '当前流程', '</th>');
         // html.push('<th class="text-center" style="width: 7%">', '上一流程审批时间', '</th>');
         html.push('<th class="text-center" style="width: 100px">', '签约合同价', '</th>');

+ 2 - 2
app/public/js/tender_list_progress.js

@@ -29,7 +29,7 @@ const tenderListSpec = (function(){
         const html = [];
         html.push('<tr pid="' + pid + '">');
         // 名称
-        html.push('<td width="20%" class="in-' + node.level + '">');
+        html.push('<td width="25%" class="in-' + node.level + '">');
         if (node.cid) {
             html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
         } else {
@@ -51,7 +51,7 @@ const tenderListSpec = (function(){
         }
         html.push('</td>');
         // 当前流程
-        html.push('<td style="width: 13%">');
+        html.push('<td style="width: 8%">');
         if (!node.cid && node.cur_flow) {
             if (node.stage_status !== undefined) {
                 const curUser = node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : '');

+ 1 - 1
app/service/change_audit_list.js

@@ -313,7 +313,7 @@ module.exports = app => {
                     order = order ? order + 1 : null;
                     insertDatas.push(data);
                 }
-                if (insertDatas.length > 0) await transaction.insert(this.tableName, insertDatas);
+                if (insertDatas.length > 0) await this.insertBigDatas(transaction, insertDatas);
                 await this.calcCamountSum(transaction);
                 if (!order_by) {
                     // 更新stage_change和stage_change_final的cbid

+ 27 - 12
app/service/filing.js

@@ -177,22 +177,37 @@ module.exports = app => {
 
         async move(data) {
             const filing = await this.getDataById(data.id);
-            const silbing = await this.getAllDataByCondition({ where: { tree_pid: filing.tree_pid, is_deleted: 0 } });
-            const updateData = [{ id: filing.id, tree_order: data.tree_order }];
-            if (data.tree_order < filing.tree_order) {
-                silbing.forEach(x => {
-                    if (x.id === filing.id) return;
-                    if (x.tree_order < data.tree_order) return;
-                    if (x.tree_order > filing.tree_order) return;
-                    updateData.push({id: x.id, tree_order: x.tree_order + 1});
-                });
+            if (!filing) throw '移动的分类不存在,请刷新页面后重试';
+            const parent = await this.getDataById(data.tree_pid);
+            if (!parent) throw '移动后的分类不存在,请刷新页面后重试';
+            const sibling = await this.getAllDataByCondition({ where: { tree_pid: data.tree_pid, is_deleted: 0 } });
+            const updateData = [{ id: filing.id, tree_order: data.tree_order, tree_pid: data.tree_pid, tree_level: parent.tree_level + 1 }];
+            if (data.tree_pid === filing.tree_pid) {
+                if (data.tree_order < filing.tree_order) {
+                    sibling.forEach(x => {
+                        if (x.id === filing.id) return;
+                        if (x.tree_order < data.tree_order) return;
+                        if (x.tree_order > filing.tree_order) return;
+                        updateData.push({id: x.id, tree_order: x.tree_order + 1});
+                    });
+                } else {
+                    sibling.forEach(x => {
+                        if (x.id === filing.id) return;
+                        if (x.tree_order < filing.tree_order) return;
+                        if (x.tree_order > data.tree_order) return;
+                        updateData.push({id: x.id, tree_order: x.tree_order - 1});
+                    });
+                }
             } else {
-                silbing.forEach(x => {
-                    if (x.id === filing.id) return;
+                const orgSibling = await this.getAllDataByCondition({ where: { tree_pid: filing.tree_pid, is_deleted: 0 } });
+                orgSibling.forEach(x => {
                     if (x.tree_order < filing.tree_order) return;
-                    if (x.tree_order > data.tree_order) return;
                     updateData.push({id: x.id, tree_order: x.tree_order - 1});
                 });
+                sibling.forEach(x => {
+                    if (x.tree_order < data.tree_order) return;
+                    updateData.push({id: x.id, tree_order: x.tree_order + 1});
+                })
             }
             await this.db.updateRows(this.tableName, updateData);
             return { update: updateData };

+ 58 - 1
app/service/payment_detail.js

@@ -72,7 +72,7 @@ module.exports = app => {
                 const newDetail = {
                     tender_id: this.ctx.paymentTender.id,
                     tr_id: trInfo.id,
-                    order: preDetail.order ? preDetail.order + 1 : 1,
+                    order: preDetail && preDetail.order ? preDetail.order + 1 : 1,
                     times: 1,
                     status: auditConst.status.uncheck,
                     uid: this.ctx.session.sessionUser.accountId,
@@ -336,6 +336,63 @@ module.exports = app => {
             }
             return true;
         }
+
+        async doCheckDetail(id) {
+            const accountId = this.ctx.session.sessionUser.accountId;
+            const auditPermission = await this.service.paymentPermissionAudit.getOnePermission(this.session.sessionUser.is_admin, accountId);
+            if (!auditPermission) throw '权限不足';
+
+            const detail = await this.getDataById(id);
+            if (!detail) throw '支付审批表单不存在';
+            const trInfo = await this.ctx.service.paymentTenderRpt.getDataById(detail.tr_id);
+            if (!trInfo) throw '支付审批报表不存在';
+
+            // 读取原报、审核人数据
+            detail.auditors = await this.ctx.service.paymentDetailAudit.getAuditors(detail.id, detail.times);
+            detail.curAuditor = await this.ctx.service.paymentDetailAudit.getCurAuditor(detail.id, detail.times);
+            detail.rptAudits = await this.ctx.service.paymentRptAudit.getListByDetail(detail.id);
+            const auditorIds = _.map(detail.auditors, 'aid'), rptAuditIds = _.map(detail.rptAudits, 'uid');
+
+            if (accountId === detail.uid) { // 原报
+                detail.curTimes = detail.times;
+                if (detail.status === status.uncheck || detail.status === status.checkNo) {
+                    detail.curOrder = 0;
+                } else if (detail.status === status.checked) {
+                    detail.curOrder = _.max(_.map(detail.auditors, 'order'));
+                } else {
+                    detail.curOrder = detail.curAuditor.aid === accountId ? detail.curAuditor.order : detail.curAuditor.order - 1;
+                }
+                detail.filePermission = true;
+            } else if (auditorIds.indexOf(accountId) !== -1 || rptAuditIds.indexOf(accountId) !== -1 || auditPermission.view_all) { // 审批人及签署人及查看所有权人
+                if (detail.status === status.uncheck) {
+                    throw '您无权查看该数据';
+                }
+                detail.curTimes = detail.status === status.checkNo ? detail.times - 1 : detail.times;
+                if (detail.status === status.checked) {
+                    detail.curOrder = _.max(_.map(detail.auditors, 'order'));
+                } else if (detail.status === status.checkNo) {
+                    const audit = await this.ctx.service.paymentDetailAudit.getDataByCondition({
+                        td_id: detail.id, times: detail.times, status: status.checkNo,
+                    });
+                    detail.curOrder = audit.order;
+                } else {
+                    detail.curOrder = accountId === detail.curAuditor.aid ? detail.curAuditor.order : detail.curAuditor.order - 1;
+                }
+                detail.filePermission = auditorIds.indexOf(accountId) !== -1 || rptAuditIds.indexOf(accountId) !== -1;
+            } else { // 其他不可见
+                throw '您无权查看该数据';
+            }
+
+            // 获取最新的期
+            detail.highOrder = await this.service.paymentDetail.count({ tr_id: detail.tr_id });
+            detail.readOnly = !((detail.status === status.uncheck || detail.status === status.checkNo) && accountId === detail.uid);
+            if (detail.readOnly && detail.type === paymentConst.modes_value_object.safe) {
+                if ((detail.status === status.checking || detail.status === status.checkNoPre) && detail.curAuditor && detail.curAuditor.aid === accountId) {
+                    detail.readOnly = false;
+                }
+            }
+            return detail;
+        }
     }
     return PaymentDetail;
 };

+ 2 - 2
app/service/payment_safe_bills.js

@@ -16,7 +16,7 @@ const SafeBillsFields = {
     fixedFields: ['safe_id', 'tender_id', 'pre_qty', 'pre_tp', 'cur_read_qty', 'cur_read_tp', 'cur_his', 'add_user_id', 'add_time'],
     treeFields: ['id', 'detail_id', 'tree_id', 'tree_pid', 'tree_level', 'tree_order', 'tree_full_path', 'tree_is_leaf'],
 };
-SafeBillsFields.editQueryFields = [...SafeBillsFields.treeFields, ...SafeBillsFields.textFields, ...SafeBillsFields.calcFields];
+SafeBillsFields.editQueryFields = [...SafeBillsFields.treeFields, ...SafeBillsFields.textFields, ...SafeBillsFields.calcFields, 'pre_qty', 'pre_tp'];
 SafeBillsFields.readQueryFields = [...SafeBillsFields.treeFields, ...SafeBillsFields.textFields, 'unit_price', 'pre_qty', 'pre_tp', 'cur_read_qty', 'cur_read_tp'];
 SafeBillsFields.compareQueryFields = [...SafeBillsFields.treeFields, ...SafeBillsFields.textFields, 'unit_price', 'cur_his', 'cur_qty', 'cur_tp'];
 SafeBillsFields.preQueryFields = [...SafeBillsFields.treeFields, ...SafeBillsFields.textFields, 'tender_id', 'unit_price', 'end_qty', 'end_tp', 'add_user_id', 'add_time', 'update_user_id', 'update_time'];
@@ -455,7 +455,7 @@ module.exports = app => {
             const createData = await this.getDataByFullPath(detail.id, insertData[0][this.setting.fullPath] + '%');
             const updateData = await this.getNextsData(detail.id, targetId, insertData[0][this.setting.order]);
             if (updateParent) {
-                updateData.push(await this.getDataByCondition({ id: updateParent.id }));
+                updateData.push(await this.getDataById(parent.id));
             }
             return { create: createData, update: updateData };
         }

+ 4 - 0
app/service/payment_tender.js

@@ -143,6 +143,10 @@ module.exports = app => {
         // async getChildrenByParentId(parentId, transaction = null) {
         //     const list = await this.getAllDataByCondition({ where: { parent_id: parentId } });
         // }
+
+        async doCheckTender(id) {
+            return await this.service.paymentTender.getDataById(id);
+        }
     }
     return paymentTender;
 };

+ 118 - 0
app/service/payment_tender_info.js

@@ -0,0 +1,118 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2018/10/30
+ * @version
+ */
+
+const infoConst = require('../const/tender_info');
+const parseInfo = infoConst.parseInfo;
+const arrayInfo = infoConst.arrayInfo;
+
+module.exports = app => {
+
+    class PaymentTenderInfo extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'payment_tender_info';
+        }
+
+        get DefaultInfo () {
+            return infoConst.paymentDefaultInfo;
+        }
+
+        /**
+         * 新增 标段相关信息
+         *
+         * @param tenderId - 标段Id
+         * @param projectId - 项目Id
+         * @param transaction - 事务
+         * @return {Promise<void>}
+         */
+        async addTenderInfo(tenderId, projectId, transaction) {
+            const defaultInfo = this.DefaultInfo;
+            const info = JSON.parse(JSON.stringify(defaultInfo));
+            info.id = tenderId;
+            info.pid = projectId;
+            for (const pi of parseInfo) {
+                if (info[pi] === undefined) continue;
+                info[pi] = JSON.stringify(info[pi]);
+            }
+            for (const pi of arrayInfo) {
+                if (info[pi] === undefined) continue;
+                info[pi] = JSON.stringify(info[pi]);
+            }
+
+            if (transaction) {
+                await transaction.insert(this.tableName, info);
+            } else {
+                await this.db.insert(this.tableName, info);
+            }
+            return info;
+        }
+
+        /**
+         * 获取标段相关信息
+         * @param tenderId
+         * @return {Promise<void>}
+         */
+        async getTenderInfo(tenderId, projectId) {
+            const defaultInfo = this.DefaultInfo;
+            let info = await this.getDataByCondition({ id: tenderId });
+            // 兼容不存在info的情况
+            if (!info) info = await this.addTenderInfo(tenderId, projectId || this.ctx.session.sessionProject.id);
+            for (const pi of parseInfo) {
+                if (info[pi] === undefined) continue;
+
+                info[pi] = !info[pi] || info[pi] === '' ? defaultInfo[pi] : JSON.parse(info[pi]);
+                this.ctx.helper._.defaultsDeep(info[pi], defaultInfo[pi]);
+            }
+            for (const ai of arrayInfo) {
+                if (info[ai] === undefined) continue;
+
+                info[ai] = !info[ai] || info[ai] === '' ? defaultInfo[ai] : JSON.parse(info[ai]);
+            }
+            return info;
+        }
+
+        /**
+         * 保存标段相关信息
+         *
+         * @param data
+         * @return {Promise<void>}
+         */
+        async saveTenderInfo(tenderId, data) {
+            for (const di in data) {
+                if (parseInfo.indexOf(di) >= 0 || arrayInfo.indexOf(di) >= 0) {
+                    data[di] = JSON.stringify(data[di]);
+                }
+            }
+            await this.db.update(this.tableName, data, { where: { id: tenderId } });
+        }
+
+        /**
+         * 拷贝标段数据至当前标段
+         * @param {number} id - 当前标段id
+         * @param {number} copy_id - 被拷贝的标段id
+         */
+        async copyTenderHandler(id, copy_id) {
+            const [data] = await this.ctx.service.tenderInfo.getDataByCondition({
+                where: { id: copy_id },
+                columns: ['deal_info', 'construction_unit', 'tech_param'],
+            });
+            await this.defaultUpdate(data, { id });
+        }
+    }
+
+    return PaymentTenderInfo;
+};

+ 1 - 1
app/service/project.js

@@ -11,7 +11,7 @@ const imType = require('../const/tender').imType;
 const defaultFunRela = {
     banOver: true,
     hintOver: true,
-    banMinusChangeBills: false,
+    banMinusChangeBills: true,
     minusNoValue: true,
     lockPayExpr: false,
     imType: imType.zl.value,

+ 12 - 0
app/service/report.js

@@ -278,6 +278,11 @@ module.exports = app => {
                                 customDefine.stage_select, customSelect ? customSelect.stage_select : null, true));
                             runnableKey.push(filter);
                             break;
+                        case 'mem_stage_sum_pos':
+                            runnableRst.push(service.rptStageSumMemory.getStageSumPos(params.tender_id, memFieldKeys[filter],
+                                customDefine.stage_select, customSelect ? customSelect.stage_select : null));
+                            runnableKey.push(filter);
+                            break;
                         case 'mem_stage_sum_pay':
                             runnableRst.push(service.rptStageSumMemory.getStageSumPay(params.tender_id, memFieldKeys[filter],
                                 customDefine.stage_select, customSelect ? customSelect.stage_select : null));
@@ -493,6 +498,13 @@ module.exports = app => {
             return rst;
         }
 
+        async payment_safe(params, sourceFilters, memFieldKeys) {
+            const RptPaymentSafe = require('../lib/rm/payment_safe');
+            const rptPaymentSafe = new RptPaymentSafe(this.ctx);
+
+            return rptPaymentSafe.getReportData(params, sourceFilters, memFieldKeys);
+        }
+
         async getReportData(source_type, params, sourceFilters, memFieldKeys, customDefine, customSelect) {
             const sourceType = sourceTypeConst.sourceTypeData.find(x => { return x.id === source_type; });
             if (!sourceType && !this[sourceType.key]) return {};

+ 35 - 0
app/service/rpt_stage_sum_memory.js

@@ -81,6 +81,41 @@ module.exports = app => {
             return showLevel ? billsTree.getDefaultDatasByLevel(this.ctx.tender.rpt_show_level) : billsTree.getDefaultDatas();
         }
 
+
+        async getStageSumBills(tid, memFieldKeys, gsDefine, gsCustom) {
+            const self = this;
+            if (!gsDefine || !gsDefine.enable) return [];
+            if (!gsCustom || !gsCustom.stages || gsCustom.stages.length === 0) return [];
+
+            await this.ctx.service.tender.checkTender(tid);
+            const posData = await this.ctx.service.pos.getAllDataByCondition({ where: { tid: tender.id} });
+            const calcPrefix = [];
+            for (const s of gsCustom.stages) {
+                const stage = await this.db.get(this.ctx.service.stage.tableName, { tid: this.ctx.tender.id, order: s });
+                if (!stage) continue;
+                await this.ctx.service.stage.doCheckStage(stage);
+
+                const prefix = 's_' + stage.order + '_';
+                calcPrefix.push(prefix);
+                const defaultData = {};
+                defaultData[prefix + 'order'] = stage.order;
+
+                const curStage = stage.readOnly
+                    ? await this.ctx.service.stagePos.getAuditorStageData2(this.ctx.tender.id, stage.id, stage.curTimes, stage.curOrder)
+                    : await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, stage.id);
+                this.ctx.helper.assignRelaData(posData, [
+                    {data: curStage, fields: ['contract_qty', 'qc_qty'], prefix: prefix, relaId: 'lid', defaultData},
+                ]);
+            }
+            posData.forEach(x => {
+                for (const cp of calcPrefix) {
+                    x[cp + 'gather_qty'] = self.helper.add(x[cp + 'contract_qty'], x[cp + 'qc_qty']);
+                }
+            });
+
+            return posData;
+        }
+
         /**
          * 合同支付
          */

+ 10 - 2
app/view/file/file.ejs

@@ -14,11 +14,19 @@
             <div class="sjs-height-0 row">
                 <div class="col-3">
                     <div class="d-flex flex-row">
+                        <div class="btn-group">
+                            <button type="button" class="btn btn-sm  text-primary dropdown-toggle" data-toggle="dropdown" id="zhankai" aria-expanded="false">显示层级</button>
+                            <div class="dropdown-menu" aria-labelledby="zhankai" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 21px, 0px); top: 0px; left: 0px; will-change: transform;">
+                                <a class="dropdown-item" name="showLevel" tag="1" href="javascript: void(0);">第一层</a>
+                                <a class="dropdown-item" name="showLevel" tag="2" href="javascript: void(0);">第二层</a>
+                                <a class="dropdown-item" name="showLevel" tag="3" href="javascript: void(0);">第三层</a>
+                                <a class="dropdown-item" name="showLevel" tag="4" href="javascript: void(0);">第四层</a>
+                                <a class="dropdown-item" name="showLevel" tag="last" href="javascript: void(0);">最底层</a>
+                            </div>
+                        </div>
                         <% if (canFiling) { %>
                         <div class="p-2"><a href="javascript: void(0);" id="add-slibing">添加同级</a></div>
                         <div class="p-2"><a href="javascript: void(0);" id="add-child">添加子级</a></div>
-                        <% } else { %>
-                        <div class="p-2 ml-2">分类目录</div>
                         <% } %>
                     </div>
                     <ul id="filing" class="ztree" style="overflow: auto"></ul>

+ 3 - 3
app/view/file/file_modal.ejs

@@ -41,7 +41,7 @@
                             <div class="p-2"><a href="javascript: void(0);" id="batch-del-filing" class="text-danger">批量删除</a></div>
                             <div class="p-2"><a href="javascript: void(0);" id="sync-filing">同步授权至其他类别</a></div>
                         </div>
-                        <div class="modal-height-400">
+                        <div class="modal-height-400 scroll-y">
                             <table class="table table-bordered">
                                 <thead>
                                 <tr><th>选择</th><th>用户名</th><th>授权时间</th><th>权限</th><th>操作</th></tr>
@@ -71,7 +71,7 @@
             </div>
             <div class="modal-body">
                 <div class="form-group">
-                    <label for="formGroupExampleInput">单个文件大小限制:30MB,支持<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="doc,docx,xls,xlsx,ppt,pptx,pdf">office等文档格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="jpg,png,bmp">图片格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="rar,zip">压缩包格式</span></label>
+                    <label for="formGroupExampleInput">单个文件大小限制:50MB,支持<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="doc,docx,xls,xlsx,ppt,pptx,pdf">office等文档格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="jpg,png,bmp">图片格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="rar,zip">压缩包格式</span></label>
                     <input type="file" class="" id="upload-file" multiple>
                 </div>
             </div>
@@ -112,7 +112,7 @@
                         <div class="d-flex justify-content-center bg-graye">
                             <div class="p-2">标段列表</div>
                         </div>
-                        <div class="modal-height-400">
+                        <div class="modal-height-400 scroll-y">
                             <ul id="rela-tender" class="ztree"></ul>
                         </div>
                     </div>

+ 5 - 1
app/view/payment/audit_modal.ejs

@@ -8,6 +8,7 @@
                 </div>
                 <div class="modal-body">
                     <div class="row">
+                        <% if (trInfo.type !== paymentConst.modes_value_object.safe) { %>
                         <div class="col-5">
                             <% if (trInfo.sp_status !== shenpiConst.sp_status.gdspl && ctx.session.sessionUser.accountId === ctx.detail.uid) { %>
                                 <div class="dropdown text-right pt-1">&nbsp;</div>
@@ -29,10 +30,13 @@
                                 </ul>
                             </div>
                         </div>
-                        <div class="col-7" style="overflow: auto">
+                        <% } %>
+                        <div class="col" style="overflow: auto">
                             <div class="dropdown text-right">
                                 <% if (trInfo.sp_status !== shenpiConst.sp_status.gdspl && ctx.session.sessionUser.accountId === ctx.detail.uid) { %>
+                                    <% if (trInfo.type !== paymentConst.modes_value_object.safe) { %>
                                     <button class="btn btn-sm btn-primary mr-2" id="follow_rpt_audit_btn">同步表单角色</button>
+                                    <% } %>
                                     <button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button"
                                             id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
                                             aria-expanded="false">

+ 6 - 1
app/view/payment/list.ejs

@@ -1,7 +1,12 @@
 <div class="panel-content">
     <div class="panel-title fluid">
         <div class="title-main  d-flex justify-content-between">
-            <div><a class="mr-2" href="/payment"><i class="fa fa-chevron-left"></i> 返回</a><%- ctx.paymentTender.name %></div>
+            <div>
+                <a class="mr-2" href="/payment"><i class="fa fa-chevron-left"></i> 返回</a><%- ctx.paymentTender.name %>
+            </div>
+            <div>
+                <a href="#bd-attr" data-toggle="modal" data-target="#bd-attr" class="btn btn-sm btn-outline-primary pull-right ml-2">标段属性</a>
+            </div>
             <div>
                 <% if (ctx.session.sessionUser.accountId === trInfo.uid && trInfo.is_del === 0 && (rptMsg || trInfo.type === paymentConst.modes_value_object.safe)) { %>
                 <% if (trDetailList.length === 0 || (trDetailList.length !== 0 && trDetailList[0].status === auditConst.status.checked)) { %>

+ 442 - 0
app/view/payment/list_modal.ejs

@@ -208,3 +208,445 @@
         </div>
     </div>
 </div>
+
+// 标段属性
+<div class="modal fade" id="bd-attr" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">标段属性</h5>
+            </div>
+            <div class="modal-height-500" style="overflow-y: auto">
+                <div class="modal-body">
+                    <ul class="nav nav-tabs nav-justified mb-2">
+                        <li class="nav-item">
+                            <a class="nav-link active" data-toggle="tab" href="#htxx" role="tab" aria-selected="true">合同信息</a>
+                        </li>
+                        <li class="nav-item">
+                            <a class="nav-link" data-toggle="tab" href="#cjdw" role="tab" aria-selected="false">参建单位</a>
+                        </li>
+                        <li class="nav-item">
+                            <a class="nav-link" data-toggle="tab" href="#jscs" role="tab">技术参数</a>
+                        </li>
+                    </ul>
+                    <div class="tab-content">
+                        <div class="tab-pane active" id="htxx">
+                            <div class="form-group">
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">建设项目名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="项目A" id="build-name" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">合同编号</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="deal-code" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">合同名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="deal-name" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">工程类别</span>
+                                            </div>
+                                            <select class="form-control" id="project-type">
+                                                <option value="">请选择</option>
+                                                <option value="设计">设计</option>
+                                                <option value="监理">监理</option>
+                                                <option value="施工">施工</option>
+                                                <option value="检测">检测</option>
+                                                <option value="其他">其他</option>
+                                            </select>
+                                        </div>
+                                    </div>
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">合同类别</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="deal-type">
+                                        </div>
+                                    </div>
+                                    <div class="col-12">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">结算书编号</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="final-code">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="cjdw">
+                            <div class="form-group mb-4">
+                                <label>建设单位:</label>
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">单位名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="build-company" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">法人代表</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="build-corporation" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">签订日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="build-date">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group mb-4">
+                                <label>承包单位1:</label>
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">单位名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="contract1-company" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">法人代表</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="contract1-corporation" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">签订日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="contract1-date">
+                                        </div>
+                                    </div>
+                                    <div class="col-12 mt-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">项目经理部</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="contract1-management" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group mb-4">
+                                <label>承包单位2:</label>
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">单位名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="contract2-company" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">法人代表</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="contract2-corporation" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">签订日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="contract2-date">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group mb-4">
+                                <label>监理单位1:</label>
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">单位名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="supervision1-company" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">法人代表</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="supervision1-corporation" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">签订日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="supervision1-date">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label>监理单位2:</label>
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">单位名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="supervision2-company" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">法人代表</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="supervision2-corporation" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">签订日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="supervision2-date">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label>检测单位:</label>
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">单位名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="detect-company" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">法人代表</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="detect-corporation" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">签订日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="detect-date">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="jscs">
+                            <div class="form-group">
+                                <div class="row">
+                                    <div class="col-6 pr-0 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">公路等级</span>
+                                            </div>
+                                            <select class="form-control" id="load-level">
+                                                <option>高速公路</option>
+                                                <option>一级公路</option>
+                                                <option>二级公路</option>
+                                                <option>三级公路</option>
+                                                <option>四级公路</option>
+                                            </select>
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">长度(KM)</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="length" min="0" max="10000"
+                                                   oninput="limitDealParamLength(this);limitReturn(this);" onchange="checkNumberValid(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">起始桩号</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="start-peg" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">终止桩号</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="end-peg" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:66px">车道数</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="lane-count" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text" style="width:90px">合同工期</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="deal-period" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">开工日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="start-date">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">计划完工日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="plan-end-date">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">实际开工日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="real-start-date">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">实际完工日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="real-end-date">
+                                        </div>
+                                    </div>
+                                    <div class="col-12">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">构造物规模</span>
+                                            </div>
+                                            <textarea class="form-control" id="structure-scale"></textarea>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button class="btn btn-sm btn-primary mr-auto" data-toggle="modal" data-target="#sync-attr">从计量标段同步</button>
+
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-sm btn-primary" onclick="postAttr();">确认修改</button>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="modal fade" id="sync-attr" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">选择标段</h5>
+            </div>
+            <div class="modal-body">
+                <h5>可选标段</h5>
+                <div id="sr-spread" style="height: 300px"></div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-sm btn-primary" id="sync-attr-ok">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    let property = JSON.parse(unescape('<%- escape(JSON.stringify(tenderInfo)) %>'));
+    const category = JSON.parse('<%- JSON.stringify(categoryData) %>');
+    // 根据Min Max限制Input输入
+    function limitInputMinMax (obj) {
+        if (_.toNumber(obj.value) > _.toNumber(obj.max)) {
+            obj.value = obj.max;
+        }
+        if(_.toNumber(obj.value) < _.toNumber(obj.min)) {
+            obj.value = obj.min;
+        }
+    }
+    // 根据Maxlength限制input输入
+    function limitMaxLength (obj) {
+        if (obj.value.length > obj.maxLength) {
+            obj.value = obj.value.substr(0, obj.maxLength);
+        }
+    }
+    // 根据正则限制输入
+    function limitReg(obj, reg) {
+        obj.value = obj.value.replace(reg, '');
+    }
+    // 小数位数 input 输入限制
+    function limitDecimal(obj) {
+        limitReg(obj, /[^\d]/g);
+        limitMaxLength(obj);
+        limitInputMinMax(obj);
+    }
+
+    function limitDealParamLength(obj) {
+        limitReg(obj, /[^\d\.]/g); // 过滤数字和.
+        limitReg(obj, /\.{2,}/g); // 过滤第二个.
+        limitInputMinMax(obj);
+    }
+
+    function limitReturn(obj) {
+        limitReg(obj, /\s/g);
+    }
+
+    function checkNumberValid(obj) {
+        const value = _.toNumber(obj.value);
+        obj.value = value ? value : '';
+    }
+</script>
+

+ 2 - 2
app/view/payment/process.ejs

@@ -37,8 +37,8 @@
                                                 <div class="form-group form-check">
                                                     <% for (const st in shenpi.sp_status_list) { %>
                                                     <div class="custom-control custom-checkbox custom-control-inline">
-                                                        <input type="radio" class="custom-control-input" value="<%- shenpi.sp_status_list[st].status %>" name="tender_process" id="tender_process_<%- shenpi.sp_status_list[st].status %>">
-                                                        <label class="custom-control-label" for="tender_process_<%- shenpi.sp_status_list[st].status %>"><%- shenpi.sp_status_list[st].name %></label>
+                                                        <input type="radio" class="custom-control-input" value="<%- shenpi.sp_status_list[st].status %>" name="detail_process" id="safe_process_<%- shenpi.sp_status_list[st].status %>">
+                                                        <label class="custom-control-label" for="safe_process_<%- shenpi.sp_status_list[st].status %>"><%- shenpi.sp_status_list[st].name %></label>
                                                     </div>
                                                     <% } %>
                                                 </div>

+ 2 - 0
app/view/payment_safe/index.ejs

@@ -181,4 +181,6 @@
 <script>
     const readOnly = <%- ctx.detail.readOnly %>;
     const stdBills = JSON.parse(unescape('<%- escape(JSON.stringify(stdBills)) %>'));
+    const tenderId = parseInt('<%- ctx.paymentTender.id %>');
+    const detailId = parseInt('<%- ctx.detail.id %>');
 </script>

+ 38 - 0
app/view/tender/detail_modal.ejs

@@ -266,6 +266,35 @@
                                     </div>
                                 </div>
                             </div>
+                            <div class="form-group">
+                                <label>跟踪审计单位:</label>
+                                <div class="row">
+                                    <div class="col-12 mb-2">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">单位名称</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="audit-company" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6 pr-0">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">法人代表</span>
+                                            </div>
+                                            <input type="text" class="form-control" value="" id="audit-corporation" maxlength="100" oninput="limitReturn(this)">
+                                        </div>
+                                    </div>
+                                    <div class="col-6">
+                                        <div class="input-group input-group-sm">
+                                            <div class="input-group-prepend">
+                                                <span class="input-group-text">签订日期</span>
+                                            </div>
+                                            <input type="date" class="form-control" value="" id="audit-date">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
                         </div>
                         <div class="tab-pane" id="jscs">
                             <div class="form-group">
@@ -964,6 +993,10 @@
         $('#detect-company').val(property.construction_unit.detect.company);
         $('#detect-corporation').val(property.construction_unit.detect.corporation);
         $('#detect-date').val(property.construction_unit.detect.date);
+        // 检测单位
+        $('#audit-company').val(property.construction_unit.audit.company);
+        $('#audit-corporation').val(property.construction_unit.audit.corporation);
+        $('#audit-date').val(property.construction_unit.audit.date);
 
         // 技术参数
         $('#load-level').find("option:contains('" + property.tech_param.loadLevel + "')").attr("selected",true);
@@ -1031,6 +1064,11 @@
                     corporation: $('#detect-corporation').val(),
                     date: $('#detect-date').val(),
                 },
+                audit: {
+                    company: $('#audit-company').val(),
+                    corporation: $('#audit-corporation').val(),
+                    date: $('#audit-date').val(),
+                },
             },
             tech_param: {
                 loadLevel: $('#load-level').find("option:selected").text(),

+ 5 - 1
config/web.js

@@ -1157,8 +1157,12 @@ const JsFiles = {
                 mergeFile: 'payment_process',
             },
             list: {
-                files: ['/public/js/moment/moment.min.js'],
+                files: ['/public/js/moment/moment.min.js',
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',],
                 mergeFiles: [
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/shares/tenders2tree.js',
                     '/public/js/payment_list.js',
                 ],
                 mergeFile: 'payment_list',