Przeglądaj źródła

导入ybp相关

MaiXinRong 6 miesięcy temu
rodzic
commit
21e12714fa

+ 30 - 0
app/controller/ledger_controller.js

@@ -25,6 +25,7 @@ const sendToWormhole = require('stream-wormhole');
 const spreadSetting = require('../lib/spread_setting');
 const PermissionCheck = require('../const/account_permission').PermissionCheck;
 const streamToArray = require('stream-to-array');
+const DSK = require('../lib/dsk');
 
 module.exports = app => {
 
@@ -559,6 +560,35 @@ module.exports = app => {
             } catch (err) {
                 await sendToWormhole(stream);
                 ctx.log(err);
+                ctx.ajaxErrorBody(err, '导入计价文件出错');
+            }
+        }
+
+        async importDsk(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.subjects || data.subjects.length === 0) throw '无导入计价数据';
+
+                // 拼凑ybp数据
+                const ybpData = { header: {}, subjects: [] };
+                const dsk = new DSK(ctx);
+                for (const s of data.subjects) {
+                    const subject = { project: { name: '' }, rations: [], };
+                    subject.bills = await dsk.getProjectBills(s.compilationId, s.subjectId);
+                    // 拼凑fees.marketCommon.totalFee,fees.marketLabour.totalFee防止出错
+                    subject.bills.forEach(b => {
+                        b.fees = {
+                            marketCommon: { unitPrice: b.unitPrice, totalFee: b.totalPrice },
+                            marketLabour: { unitPrice: 0, totalFee: 0 },
+                        };
+                    });
+                    ybpData.subjects.push(subject);
+                }
+                const bills = await ctx.service.ledger.importYbpData(ctx.tender, ybpData);
+                ctx.body = { err: 0, msg: '', data: { bills, pos: [] }};
+            } catch (err) {
+                ctx.log(err);
+                ctx.ajaxErrorBody(err, '导入计价分段出错');
             }
         }
         // async uploadExcel(ctx) {

+ 9 - 0
app/controller/pay_controller.js

@@ -0,0 +1,9 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */

+ 15 - 4
app/lib/ybp_tree.js

@@ -167,8 +167,9 @@ class YbpImportTree {
         const setting = this.setting;
         const compareData = { kind: node.kind };
         const hasUp = (!node.children || node.children.length === 0) && defaultMerge.indexOf(compareData.kind) < 0;
-        compareData.code = defaultMerge.indexOf(compareData.kind) < 0 ? '' : node.code || '';
-        compareData.b_code = defaultMerge.indexOf(compareData.kind) < 0 ? node.code || '' : '';
+        const isXmj = defaultMerge.indexOf(compareData.kind) >= 0;
+        compareData.code = isXmj ? node.code || '' : '';
+        compareData.b_code = isXmj ? '' : node.code || '';
         compareData.name = node.name || '';
         compareData.unit = node.unit || '';
         compareData.unit_price = hasUp
@@ -192,11 +193,21 @@ class YbpImportTree {
                 this.children.push(cur);
             }
             this.datas.push(cur);
-            cur.quantity = node.quantity || 0;
+            cur.dgn_qty1 = isXmj ? node.quantity || 0 : 0;
+            cur.dgn_qty2 = isXmj ? node.quantity2 || 0 : 0;
+            cur.quantity = isXmj ? 0 : node.quantity || 0;
             cur.total_fee = node.fees ? node.fees.marketCommon.totalFee : 0;
             cur.labour_fee = node.fees && node.fees.marketLabour ? node.fees.marketLabour.totalFee : 0;
         } else {
-            cur.quantity = this.helper.add(cur.quantity, node.quantity);
+            cur.dgn_qty1 = isXmj ? node.quantity || 0 : 0;
+            cur.dgn_qty2 = isXmj ? node.quantity2 || 0 : 0;
+            cur.quantity = isXmj ? 0 : node.quantity || 0;
+            if (isXmj) {
+                cur.dgn_qty1 = this.helper.add(cur.dgn_qty1, node.quantity || 0);
+                cur.dgn_qty2 = this.helper.add(cur.dgn_qty2, node.quantity2 || 0);
+            } else {
+                cur.quantity = this.helper.add(cur.quantity, node.quantity || 0);
+            }
             cur.total_fee = this.helper.add(cur.total_fee, node.fees ? node.fees.marketCommon.totalFee : 0);
             cur.labour_fee = this.helper.add(cur.labour_fee, node.fees && node.fees.marketLabour ? node.fees.marketLabour.totalFee : 0);
         }

BIN
app/public/images/dsk.png


BIN
app/public/images/ybpx.png


+ 38 - 0
app/public/js/ledger.js

@@ -4962,6 +4962,7 @@ $(document).ready(function() {
           $('#showAttachment').attr('file-id', '');
       });
   });
+
     $('#upload-ybp-file').click(function () {
         const file = $('#ybp-file')[0];
         const formData = new FormData();
@@ -4978,6 +4979,43 @@ $(document).ready(function() {
             $('#upload-ybp').modal('hide');
         });
     });
+    $('#id-upload-ybp').click(function() {
+        $('#import-dsk').modal('hide');
+        $('#upload-ybp').modal('show');
+    });
+    $('#id-post-dsk').click(async function() {
+        if (dsk.checkBind()) {
+            $('#import-dsk').modal('hide');
+            dsk.chooseSubject({
+                validCheck: function (node, tree) {
+                    const checkType = node.type !== dsk.projectTypeKey.folder;
+                    if (!checkType) {
+                        toastr.warning('请勿选择文件夹');
+                        return false;
+                    }
+                    const choosed = tree.datas.filter(x => { return !!x.selected; });
+                    if (choosed.length === 0) return true;
+                    if (node.project_id !== choosed[0].project_id) {
+                        toastr.warning('请勿跨建设项目选择');
+                        return false;
+                    }
+                    return true;
+                },
+                callback: async function (subjects) {
+                    postData('ledger/dsk', {subjects}, function (result) {
+                        ledgerTree.loadDatas(result.bills);
+                        treeCalc.calculateAll(ledgerTree);
+                        SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
+                        pos.loadDatas(result.pos);
+                        posOperationObj.loadCurPosData();
+                        checkShowLast(result.bills.length);
+                    });
+                }
+            });
+        } else {
+            window.open('/profile/sms');
+        }
+    });
 });
 // 生成当前节点列表
 function getNodeList(node) {

+ 6 - 2
app/public/js/measure_compare.js

@@ -431,18 +431,22 @@ $(document).ready(() => {
         }
         if (loadData.length > 0) {
             postData(window.location.pathname + '/load', {stages: loadData}, function (result) {
-                cTree.clearSumData();
                 for (const aData of result.stages) {
                     calculateStageLedgerData(aData.bills);
                     cTree.loadMinorData(aData.bills, aData.order + '', ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp'], ['contract_tp', 'qc_tp', 'gather_tp']);
-                    treeCalc.calculateAll(cTree);
                     calculateStagePosData(aData.pos);
                     cPos.loadMinorData(aData.pos, aData.order + '', ['contract_qty', 'qc_qty', 'gather_qty']);
                 }
+                cTree.reCalcSumData(['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp'], showData);
+                treeCalc.calculateAll(cTree);
+                cPos.reCalcSumData(['contract_qty', 'qc_qty', 'gather_qty'], showData);
                 refreshView();
                 $('#select-qi').modal('hide');
             }, null, true);
         } else {
+            cTree.reCalcSumData(['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp'], showData);
+            treeCalc.calculateAll(cTree);
+            cPos.reCalcSumData(['contract_qty', 'qc_qty', 'gather_qty'], showData);
             refreshView();
             $('#select-qi').modal('hide');
         }

+ 25 - 5
app/public/js/path_tree.js

@@ -259,7 +259,6 @@ class MasterPosData extends PosData {
                 for (const prop of fields) {
                     if (data[prop] !== undefined) {
                         node[prop + fieldSuf] = data[prop];
-                        node['sum_' + prop] = ZhCalc.add(node['sum_' + prop], data[prop]);
                     }
                 }
                 loadedData.push(node);
@@ -267,6 +266,21 @@ class MasterPosData extends PosData {
         }
         return loadedData;
     }
+
+    reCalcSumData(fields, fieldSufs) {
+        this.datas.forEach(d => {
+            for (const prop of fields) {
+                delete d['sum_' + prop];
+            }
+            for (const prop of fields) {
+                for (const s of fieldSufs) {
+                    if (d[prop + s] !== undefined) {
+                        d['sum_'+ prop] = ZhCalc.add(d['sum_' + prop], d[prop + s]);
+                    }
+                }
+            }
+        });
+    }
 }
 
 const createNewPathTree = function (type, setting) {
@@ -1636,7 +1650,6 @@ const createNewPathTree = function (type, setting) {
                     for (const prop of fields) {
                         if (data[prop] !== undefined) {
                             node[prop + fieldSuf] = data[prop];
-                            node['sum_' + prop] = ZhCalc.add(node['sum_' + prop], data[prop]);
                         }
                     }
                     loadedData.push(node);
@@ -1645,10 +1658,17 @@ const createNewPathTree = function (type, setting) {
             return loadedData;
         }
 
-        clearSumData() {
+        reCalcSumData(fields, fieldSufs) {
             this.datas.forEach(d => {
-                for (const prop in d) {
-                    if (prop.indexOf('sum_') === 0) delete d[prop];
+                for (const prop of fields) {
+                    delete d['sum_' + prop];
+                }
+                for (const prop of fields) {
+                    for (const s of fieldSufs) {
+                        if (d[prop + s] !== undefined) {
+                            d['sum_'+ prop] = ZhCalc.add(d['sum_' + prop], d[prop + s]);
+                        }
+                    }
                 }
             });
         }

+ 287 - 0
app/public/js/shares/dsk.js

@@ -0,0 +1,287 @@
+'use strict';
+
+const dsk = (function () {
+    const projectType = [
+        { key: 'folder', value: 1, name: '文件夹' },
+        { key: 'project', value: 2, name: '建设项目' },
+        { key: 'unit', value: 3, name: '单位工程' },
+        { key: 'item', value: 4, name: '单项工程' },
+    ];
+    const projectTypeKey = (function(arr) {
+        const result = {};
+        for (const a of arr) {
+            result[a.key] = a.value;
+        }
+        return result;
+    })(projectType);
+    const checkBind = async function() {
+        const data = await postDataAsync('/profile/dsk/api', {type: 'hadbind'});
+        return data !== 1 && data !== 2;
+    };
+    const loadCompilation = async function () {
+        const data = await postDataAsync('/profile/dsk/api', {type: 'compilation'});
+        return data.compilation;
+    };
+    const loadProject = async function(compilationId, showWaiting = true) {
+        return await postDataAsync('/profile/dsk/api', {type: 'project', compilationId}, showWaiting);
+    };
+    const loadProjectTree = async function (compilationId, projectId, showWaiting = true) {
+        return await postDataAsync('/profile/dsk/api', {type: 'project_tree', compilationId, projectId}, showWaiting)
+    };
+    const loadBills = async function(compilationId, subjectId, showWaiting = true) {
+        return await postDataAsync('/profile/dsk/api', {type: 'project_bills', compilationId, treeId: subjectId}, showWaiting)
+    };
+
+    class DskTree {
+        /**
+         *
+         * @param setting - {Object}配置
+         * setting中必须设置id,pid,order,rootId(id, 父id, 同层排序, 根节点id)
+         * e.g.{id: 'ID', pid: 'parentID', order: 'seq'}
+         * 目前仅用于载入建筑ybp文件中的清单部分,生成树结构以便汇总导入
+         */
+        constructor(setting) {
+            this.setting = JSON.parse(JSON.stringify(setting));
+            this.clearDatas();
+        }
+        clearDatas() {
+            // 数据集合
+            this.datas = [];
+            // id索引
+            this.items = {};
+            // 排序索引
+            this.nodes = [];
+            // 首层节点
+            this.children = [];
+        }
+
+        sortChildren(children, recursive) {
+            const setting = this.setting;
+            children.sort((x, y) => { return x[setting.order] > y[setting.order]; });
+
+            if (!recursive) return;
+            for (const c of children) {
+                this.sortChildren(c.children);
+            }
+        }
+        sort() {
+            this.sortChildren(this.children, true);
+            const self = this;
+            const _loadNode = function(node) {
+                self.nodes.push(node);
+                for (const c of node.children) {
+                    _loadNode(c);
+                }
+            };
+            for (const child of this.children) {
+                _loadNode(child);
+            }
+        }
+        loadDatas(datas) {
+            this.clearDatas();
+            const setting = this.setting;
+            const self = this;
+            const _loadData = function(d) {
+                if (d[setting.pid] === setting.rootId) {
+                    self.children.push(d);
+                } else {
+                    let parent = self.items[d[setting.pid]];
+                    if (!parent) {
+                        parent = datas.find(x => { return x[setting.id] === d[setting.pid]; });
+                        if (!parent) {
+                            // console.log(d[setting.pid]);
+                            return null;
+                        }
+                        parent = _loadData(parent);
+                    }
+                    if (!parent) return null;
+                    parent.children.push(d);
+                }
+                d.children = [];
+                self.datas.push(d);
+                self.items[d[setting.id]] = d;
+                return d;
+            };
+            for (const d of datas) {
+                if (this.items[d[setting.id]]) continue;
+                _loadData(d);
+            }
+            this.sort();
+        }
+    }
+
+    const chooseSubjectObj = {
+        obj: null,
+        compilationObj: null,
+        subjectSpread: null,
+        subjectSheet: null,
+        compliation: null,
+        loadCompilation: async function() {
+            if (this.compliation) return;
+
+            this.compliation = await loadCompilation();
+            for (const c of this.compliation) {
+                c.project = await loadProject(c.ID);
+            }
+            const html = [];
+            for (const c of this.compliation) {
+                html.push(`<option value="${c.ID}">${c.name}</option>`);
+            }
+            this.compilationObj.html(html.join(''));
+        },
+        analysisSubjectTree(compilation) {
+            const subjectTree = createNewPathTree('gather', {
+                id: 'id',
+                pid: 'pid',
+                order: 'sort',
+                level: 'level',
+                rootId: -1,
+                fullPath: 'full_path',
+            });
+            const tempTree = new DskTree({ id: 'ID', pid: 'parentID', order: 'seq', rootId: '-1' });
+            tempTree.loadDatas(compilation.project);
+            const projectTree = new DskTree({ id: 'ID', pid: 'parentID', order: 'seq', rootId: '-1' });
+
+            const loadProjectTreeNode = function (data, parent, project) {
+                let cur;
+                if (data.type === projectTypeKey.project) {
+                    cur = parent;
+                } else {
+                    const type = projectType.find(x => { return x.value === data.type; });
+                    const node = { type: type.value, type_str: type.name, dsk_id: data.ID, name: data.name, project_id: project.ID, compilation_id: compilation.ID };
+                    cur = subjectTree.addNode(node, parent);
+                }
+                if (data.children) {
+                    data.children.forEach(c => {
+                        loadProjectTreeNode(c, cur, project);
+                    })
+                }
+            };
+            const loadTempTreeNode = function (data, parent) {
+                const type = projectType.find(x => { return x.value === data.type; });
+                const node = { type: type.value, type_str: type.name, dsk_id: data.ID, name: data.name, compilation_id: compilation.ID };
+                const cur = subjectTree.addNode(node, parent);
+                if (data.children) {
+                    data.children.forEach(c => {
+                        loadTempTreeNode(c, cur);
+                    })
+                }
+                if (data.type === projectTypeKey.project) {
+                    projectTree.loadDatas(data.subjects);
+                    cur.project_id = data.ID;
+                    projectTree.children.forEach(c => {
+                        loadProjectTreeNode(c, cur, data);
+                    });
+                }
+            };
+            tempTree.children.forEach(c => {
+                loadTempTreeNode(c, null);
+            });
+            subjectTree.sortTreeNode(true);
+            compilation.subjectTree = subjectTree;
+        },
+        loadSubjects: async function (compilationId) {
+            showWaitingView();
+            const compilation = compilationId ? this.compliation.find(x => { return x.ID === compilationId}) : this.compliation[0];
+            if (!compilation) return;
+            if (!compilation.subjectTree) {
+                for (const p of compilation.project) {
+                    if (p.type === projectTypeKey.project) p.subjects = await loadProjectTree(compilation.ID, p.ID, false);
+                }
+                this.analysisSubjectTree(compilation);
+            }
+            SpreadJsObj.loadSheetData(this.subjectSheet, SpreadJsObj.DataType.Tree, compilation.subjectTree);
+            closeWaitingView();
+        },
+        getSelectSubjects: function () {
+            const tree = this.subjectSheet.zh_tree;
+            if (!tree) return [];
+
+            return tree.datas.filter(x => { return x.type === projectTypeKey.item && x.selected; }).map(x => { return { compilationId: x.compilation_id, subjectId: x.dsk_id }; });
+        },
+        csButtonClicked: function(e, info) {
+            if (!info.sheet.zh_setting) return;
+
+            const col = info.sheet.zh_setting.cols[info.col];
+            if (col.field !== 'selected') return;
+
+            const tree = info.sheet.zh_tree;
+            const node = SpreadJsObj.getSelectObject(info.sheet);
+            if (!node.selected) {
+                const canChoose = chooseSubjectObj.setting.validCheck ? chooseSubjectObj.setting.validCheck(node, tree) : true;
+                if (!canChoose) return;
+            }
+
+            node.selected = !node.selected;
+            if (node.children && node.children.length > 0) {
+                const posterity = tree.getPosterity(node);
+                for (const p of posterity) {
+                    p.selected = node.selected;
+                }
+                SpreadJsObj.reLoadRowData(info.sheet, info.row, posterity.length + 1);
+            } else {
+                SpreadJsObj.reLoadRowData(info.sheet, info.row, 1);
+            }
+        },
+        init() {
+            if (this.subjectSpread) return;
+
+            this.obj = $('#choose-dsk-subject');
+            this.compilationObj = $('#cdsks-compilation');
+            this.subjectSpread = SpreadJsObj.createNewSpread($('#cdsks-spread')[0]);
+            this.subjectSheet = this.subjectSpread.getActiveSheet();
+            SpreadJsObj.initSheet(this.subjectSheet, {
+                cols: [
+                    {title: '选择', field: 'selected', hAlign: 1, width: 60, formatter: '@', cellType: 'checkbox'},
+                    {title: '项目/分段名称', field: 'name', hAlign: 0, width: 740, formatter: '@', cellType: 'tree'},
+                    {title: '类型', field: 'type_str', hAlign: 0, width: 80, formatter: '@' },
+                ],
+                emptyRows: 0,
+                headRows: 1,
+                headRowHeight: [32],
+                defaultRowHeight: 21,
+                headerFont: '12px 微软雅黑',
+                font: '12px 微软雅黑',
+                selectedBackColor: '#fffacd',
+                readOnly: true,
+            });
+            this.subjectSpread.bind(spreadNS.Events.ButtonClicked, this.csButtonClicked);
+
+            $('#choose-dsk-subject-ok').click(() => {
+                if (chooseSubjectObj.setting.callback) {
+                    const subjects = chooseSubjectObj.getSelectSubjects();
+                    if (subjects.length === 0) {
+                        toastr.warning('请选择导入的计价分段');
+                        return;
+                    }
+                    chooseSubjectObj.setting.callback(subjects);
+                    this.obj.modal('hide');
+                }
+            });
+            $('#choose-dsk-subject').on('shown.bs.modal', function() {
+                chooseSubjectObj.subjectSpread.refresh();
+            });
+            $('#cdsks-compilation').click(function() {
+                chooseSubjectObj.loadSubjects(this.value);
+            });
+        },
+        async show (setting) {
+            this.init();
+            this.setting = setting;
+            this.obj.modal('show');
+            await this.loadCompilation();
+            await this.loadSubjects();
+        }
+    };
+
+    const chooseSubject = function (setting) {
+        chooseSubjectObj.show(setting);
+    };
+
+    return {
+        projectType, projectTypeKey,
+        checkBind, loadCompilation, loadProject, loadProjectTree, loadBills,
+        chooseSubject
+    };
+})();
+

+ 1 - 0
app/router.js

@@ -242,6 +242,7 @@ module.exports = app => {
     app.post('/tender/:id/ledger/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.update');
     app.post('/tender/:id/ledger/upload-excel/:ueType', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.uploadExcel');
     app.post('/tender/:id/ledger/ybp', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.uploadYbp');
+    app.post('/tender/:id/ledger/dsk', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.importDsk');
     app.get('/tender/:id/ledger/download/:file', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.download');
     app.post('/tender/:id/anc-gcl/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.ancGclUpdate');
     app.post('/tender/:id/pos/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.posUpdate');

+ 16 - 8
app/service/ledger.js

@@ -707,8 +707,7 @@ module.exports = app => {
             }
         }
 
-        async importYbp(tender, ybp) {
-            const YBP = require('../lib/ybp');
+        async importYbpData(tender, ybpData) {
             const YbpTrees = require('../lib/ybp_tree');
             const gatherTreeSetting = {
                 id: 'ledger_id', pid: 'ledger_pid', order: 'order', full_path: 'full_path', level: 'level', rootId: -1,
@@ -722,8 +721,6 @@ module.exports = app => {
             const ybpTreeSetting = { id: 'ID', pid: 'parentID', order: 'seq', rootId: '-1' };
             const helper = this.ctx.helper;
 
-            const ybpAnalysis = new YBP(this.ctx);
-            const ybpData = ybpAnalysis.decryptBuffer(ybp);
             const gatherTree = new YbpTrees.YbpImportTree(gatherTreeSetting, YbpTrees.YbpImportType.flow, helper, tender.info.decimal);
             for (const subject of ybpData.subjects) {
                 if (!subject.bills || subject.bills.length === 0) continue;
@@ -761,6 +758,7 @@ module.exports = app => {
             const bills = [], glj = [];
             for (const n of gatherTree.nodes) {
                 const billsId = this.uuid.v4();
+                const isLeaf = !n.children || n.children.length === 0;
                 bills.push({
                     id: billsId,
                     tender_id: tender.id,
@@ -769,16 +767,18 @@ module.exports = app => {
                     level: n.level,
                     order: n.order,
                     full_path: n.full_path,
-                    is_leaf: !n.children || n.children.length === 0,
+                    is_leaf: isLeaf,
                     code: n.code,
                     b_code: n.b_code,
                     name: n.name,
                     unit: n.unit,
-                    unit_price: n.unit_price || 0,
+                    unit_price: isLeaf ? n.unit_price || 0 : 0,
                     sgfh_qty: n.quantity || 0,
-                    sgfh_tp: n.total_price || 0,
+                    sgfh_tp: isLeaf ? n.total_price || 0 : 0,
                     quantity: n.quantity || 0,
-                    total_price: n.total_price || 0,
+                    total_price: isLeaf ? n.total_price || 0 : 0,
+                    dgn_qty1: n.dgn_qty1 || 0,
+                    dgn_qty2: n.dgn_qty2 || 0,
                     memo: n.source.join(';'),
                 });
                 if (!n.glj) continue;
@@ -808,6 +808,14 @@ module.exports = app => {
             }
         }
 
+        async importYbp(tender, ybp) {
+            const YBP = require('../lib/ybp');
+            const ybpAnalysis = new YBP(this.ctx);
+            const ybpData = ybpAnalysis.decryptBuffer(ybp);
+
+            await this.importYbpData(tender, ybpData);
+        }
+
         async sumLoad(lid, tenders) {
             const maxId = await this._getMaxLid(this.ctx.tender.id);
             const select = await this.getDataById(lid);

+ 1 - 0
app/service/project_account.js

@@ -235,6 +235,7 @@ module.exports = app => {
                         sessionToken,
                         loginType,
                         loginStatus,
+                        dskAccountData: accountData.dsk_account ? JSON.parse(accountData.dsk_account) : null,
                         // permission,
                         // cooperation,
                     };

+ 2 - 1
app/view/ledger/explode.ejs

@@ -43,7 +43,7 @@
                     <a id="exportLedger" class="btn btn-primary btn-sm" href="javascript: void(0)">导出台账Excel</a>
                 </div>
                 <div class="d-inline-block ml-1">
-                    <a href="#upload-ybp" data-toggle="modal" data-target="#upload-ybp" class="btn btn-sm btn-primary">导入计价文件</a>
+                    <a href="#import-dsk" data-toggle="modal" data-target="#import-dsk" class="btn btn-sm btn-primary">导入计价文件</a>
                 </div>
                 <% if (syncLedgerUrl) { %>
                 <div class="d-inline-block ml-1">
@@ -357,6 +357,7 @@
 </div>
 <script src="/public/js/moment/moment.min.js"></script>
 <script type="text/javascript">
+    const dskAccountData = JSON.parse('<%- JSON.stringify(ctx.session.sessionUser.dskAccountData) %>');
     const readOnly = <%- ctx.tender.ledgerReadOnly %>;
     const contractExpr = <%- !!ctx.session.sessionProject.page_show.openContractExpr && tender.ledger_status === auditConst.status.checked %>;
     const deleteFilePermission = <%- deleteFilePermission %>;

+ 43 - 0
app/view/ledger/explode_modal.ejs

@@ -56,6 +56,48 @@
     </div>
 </div>
 <!--上传计价文件-->
+<div class="modal fade" id="import-dsk" data-backdrop="static" aria-modal="true">
+    <div class="modal-dialog" role="document" style="width:400px">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">选择计价文件</h5>
+                <div class="btn-group ml-auto">
+                    <a href="" data-toggle="dropdown" title="文件类型说明"><i class="fa fa-question-circle"></i></a>
+                    <div class="dropdown-menu bg-dark">
+                        <a class="dropdown-item text-light" href="#">1、yup/ybpx文件:纵横在线云计价大司空导出的项目或者标段文件。</a>
+                        <a class="dropdown-item text-light" href="#">2、在线计价文件:绑定纵横在线云计价大司空账号,获取账号下的项目文件。</a>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-body">
+                <p>请选择合适的方式导入文件</p>
+                <div class="d-flex justify-content-between">
+                    <div></div>
+                    <div class="card card-upload-width p-2" id="id-upload-ybp">
+                        <input type="file" id="btn_file" style="display:none">
+                        <div class="card-body p-0">
+                            <div class="m-2"><img src="/public/images/ybpx.png" class="rounded m-auto d-block"></div>
+                            <div class="text-center my-3">上传yup/ybpx文件</div>
+                        </div>
+                    </div>
+                    <div class="card card-upload-width p-2" data-toggle="modal" data-target="#binddskuser" id="id-post-dsk">
+                        <div class="card-body p-0">
+                            <div class="m-2"><img src="/public/images/dsk.png" class="rounded m-auto d-block"></div>
+                            <div class="text-center mt-3 ">获取在线计价文件</div>
+                        </div>
+                    </div>
+                    <div></div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <div class="ml-auto">
+                    <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                    <button type="button" class="btn btn-sm btn-primary">确定</button>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
 <div class="modal fade" id="upload-ybp" data-backdrop="static" enctype="multipart/form-data">
     <div class="modal-dialog" role="document">
         <div class="modal-content">
@@ -535,3 +577,4 @@
 <% include ./audit_modal.ejs %>
 <% include ../shares/hint_modal.ejs %>
 <% include ../shares/batch_replace_modal.ejs %>
+<% include ../shares/dsk_modal.ejs %>

+ 23 - 0
app/view/shares/dsk_modal.ejs

@@ -0,0 +1,23 @@
+<div class="modal fade" id="choose-dsk-subject" data-backdrop="static">
+    <div class="modal-dialog modal-lgx" role="document" >
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">选择计价分段</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-inline mb-2">
+                    <label for="inputPassword2" class="">编制办法:</label>
+                    <select class="form-control form-control-sm" style="width:300px" id="cdsks-compilation">
+                    </select>
+                </div>
+                <div class="modal-height-500" id="cdsks-spread">
+                    <div ></div>
+                </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="choose-dsk-subject-ok">确定</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 5 - 0
app/view/tender/tender_sub_menu.ejs

@@ -33,6 +33,11 @@
             </ul>
         </div>
         <div class="nav-box">
+            <ul class="nav-list list-unstyled">
+                <li <% if (ctx.url.indexOf('/tender/' + ctx.tender.id + '/pay') !== -1) { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/pay" class="h3"><i class="fa fa-pie-chart fa-fw"></i> <span>合同支付</span></a></li>
+            </ul>
+        </div>
+        <div class="nav-box">
             <% if (!ctx.session.sessionProject.page_show.openChangeProject && !ctx.session.sessionProject.page_show.openChangeApply && !ctx.session.sessionProject.page_show.openChangePlan) { %>
             <ul class="nav-list list-unstyled">
                 <li <% if (ctx.url.indexOf('/tender/' + ctx.tender.id + '/change') !== -1) { %>class="active"<% } %>><a class="change_sort_link h3" href="/tender/<%- ctx.tender.id %>/change"><i class="fa fa-retweet fa-fw"></i> <span>工程变更</span></a></li>

+ 1 - 0
config/web.js

@@ -189,6 +189,7 @@ const JsFiles = {
                     '/public/js/file-saver/FileSaver.js',
                 ],
                 mergeFiles: [
+                    '/public/js/shares/dsk.js',
                     '/public/js/sub_menu.js',
                     '/public/js/div_resizer.js',
                     '/public/js/spreadjs_rela/spreadjs_zh.js',