Selaa lähdekoodia

概算投资-关联标段,造价对比-决算对比,调整

MaiXinRong 3 vuotta sitten
vanhempi
commit
39da443e4b

+ 117 - 74
app/public/js/budget_compare.js

@@ -151,66 +151,6 @@ $(document).ready(() => {
             compareSpread.refresh();
         }
     });
-
-    $('#sf-select-all').click(function() {
-        $('[name=sf-tender]').prop("checked", this.checked);
-    });
-    $('#select-final-ok').click(() => {
-        const rela = [];
-        const select = $('[name=sf-tender]:checked');
-        for (const s of select) {
-            rela.push(parseInt(s.getAttribute('tid')));
-        }
-        if (rela.length === 0) return;
-        postData(window.location.pathname + '/final', {id: rela}, function(result) {
-            if (spreadSetting.cols.length < 13) {
-                spreadSetting.cols.push(...[
-                    {title: '台账|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'dgn_qty', hAlign: 2, width: 80},
-                    {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'dgn_price', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '决算|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'final_dgn_qty', hAlign: 2, width: 80},
-                    {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'final_dgn_price', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'final_tp', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '增幅%|数量1/数量2', colSpan: '2|1', rowSpan: '1|1', field: 'grow_dgn_qty', hAlign: 2, width: 80},
-                    {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'grow_tp', hAlign: 2, width: 80, type: 'Number'},
-                ]);
-            }
-            const setting = { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price', 'end_gather_tp'] };
-            compareTree.clearFinal();
-            for (const r of result) {
-                const tree = createNewPathTree('ledger', setting);
-                tree.loadDatas(r);
-                treeCalc.calculateAll(tree);
-                compareTree.loadTree(tree, function (cur, source) {
-                    cur.total_price = ZhCalc.add(cur.total_price, source.total_price);
-                    cur.dgn_qty1 = ZhCalc.add(cur.dgn_qty1, source.dgn_qty1);
-                    cur.dgn_qty2 = ZhCalc.add(cur.dgn_qty2, source.dgn_qty2);
-                    cur.final_dgn_qty1 = ZhCalc.sum([cur.final_dgn_qty1, source.deal_dgn_qty1, source.c_dgn_qty1]);
-                    cur.final_dgn_qty2 = ZhCalc.sum([cur.final_dgn_qty2, source.deal_dgn_qty2, source.c_dgn_qty2]);
-                    cur.final_tp = ZhCalc.add(cur.final_tp, source.end_gather_tp);
-                });
-            }
-            compareTree.afterLoad(node => {
-                node.dgn_price = ZhCalc.div(node.total_price, node.dgn_qty1, 2);
-                node.dgn_qty = node.dgn_qty1
-                    ? (node.dgn_qty2 ? node.dgn_qty1 + '/' + node.dgn_qty2 : node.dgn_qty1)
-                    : (node.dgn_qty2 ? '/' + node.dgn_qty2 : '');
-                node.final_dgn_price = ZhCalc.div(node.final_tp, node.final_dgn_qty1, 2);
-                node.final_dgn_qty = node.final_dgn_qty1
-                    ? (node.final_dgn_qty2 ? node.final_dgn_qty1 + '/' + node.final_dgn_qty2 : node.final_dgn_qty1)
-                    : (node.final_dgn_qty2 ? '/' + node.final_dgn_qty2 : '');
-                node.grow_dgn_qty1 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty1, node.gai_dgn_qty1), node.gai_dgn_qty1, 4), 100);
-                node.grow_dgn_qty2 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty2, node.gai_dgn_qty2), node.gai_dgn_qty2, 4), 100);
-                node.grow_dgn_qty = node.grow_dgn_qty1
-                    ? (node.grow_dgn_qty2 ? node.grow_dgn_qty1 + '/' + node.grow_dgn_qty2 : node.grow_dgn_qty1)
-                    : (node.grow_dgn_qty2 ? '/' + node.grow_dgn_qty2 : '');
-                node.grow_tp = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_tp, node.gai_tp), node.gai_tp, 4), 100);
-            });
-            SpreadJsObj.reLoadSheetHeader(compareSheet);
-            SpreadJsObj.reLoadSheetData(compareSheet);
-            $('#select-final').modal('hide');
-        });
-    });
     // 显示层次
     (function (select, sheet) {
         $(select).click(function () {
@@ -239,21 +179,124 @@ $(document).ready(() => {
     })('a[name=showLevel]', compareSheet);
 
 
-    $('#valid-tender-list').html((function() {
-        const html = [];
-        const tree = Tender2Tree.convert(category, tenderList, null, null, function (node, source) {
-            node.lastStageOrder = source.lastStageOrder;
-            node.lastStageStatus = source.lastStageStatus;
-        });
+    class sfObject {
+        constructor() {
+            const self = this;
+            this.selectTree = Tender2Tree.convert(category, tenderList, null, null, function (node, source) {
+                node.lastStageOrder =`第${source.lastStageOrder}期`;
+                node.lastStageStatus = source.lastStageStatus;
+            });
+            const sfSpreadSetting = {
+                cols: [
+                    {title: '选择', field: 'selected', hAlign: 1, width: 40, formatter: '@', cellType: 'checkbox'},
+                    {title: '名称', field: 'name', hAlign: 0, width: 180, formatter: '@', cellType: 'tree'},
+                    {title: '期数', field: 'lastStageOrder', hAlign: 1, width: 60, formatter: '@'},
+                    {title: '审批状态', field: 'lastStageStatus', hAlign: 1, width: 60, formatter: '@'},
+                ],
+                emptyRows: 0,
+                headRows: 1,
+                headRowHeight: [32],
+                defaultRowHeight: 21,
+                headerFont: '12px 微软雅黑',
+                font: '12px 微软雅黑',
+                headColWidth: [30],
+                selectedBackColor: '#fffacd',
+                readOnly: true,
+            };
+            this.spread = SpreadJsObj.createNewSpread($('#sf-spread')[0]);
+            this.sheet = this.spread.getActiveSheet();
+            SpreadJsObj.initSheet(this.sheet, sfSpreadSetting);
+            SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Tree, this.selectTree);
+
+            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;
 
-        for (const t of tree.nodes) {
-            if (t.cid) {
-                html.push(`<tr><td></td><td class="in-${t.level}"><i class="fa fa-folder-o"></i> ${t.name}</td><td></td><td></td></tr>`);
-            } else if (t.tid) {
-                const icon = tree.isLastSibling(t) ? '└' : '├';
-                html.push(`<tr><td class="text-center"><input type="checkbox" name="sf-tender" tid="${t.tid}"></td><td class="in-${t.level}">${icon} ${t.name}</td><td>第${t.lastStageOrder}期</td><td>${t.lastStageStatus}</td></tr>`);
+                const node = SpreadJsObj.getSelectObject(info.sheet);
+                self.selectNode(node, !node[col.field]);
+                SpreadJsObj.reloadColData(info.sheet, 0);
+            });
+
+
+            $('#sf-select-all').click(function() {
+                for (const n of self.selectTree.nodes) {
+                    n.selected = this.checked;
+                }
+                SpreadJsObj.reloadColData(self.sheet, 0);
+            });
+            $('#select-final-ok').click(() => {
+                const rela = self.getSelects();
+                if (rela.length === 0) return;
+                postData(window.location.pathname + '/final', {id: rela}, function(result) {
+                    if (spreadSetting.cols.length < 13) {
+                        spreadSetting.cols.push(...[
+                            {title: '台账|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'dgn_qty', hAlign: 2, width: 80},
+                            {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'dgn_price', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '决算|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'final_dgn_qty', hAlign: 2, width: 80},
+                            {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'final_dgn_price', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'final_tp', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '增幅%|数量1/数量2', colSpan: '2|1', rowSpan: '1|1', field: 'grow_dgn_qty', hAlign: 2, width: 80},
+                            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'grow_tp', hAlign: 2, width: 80, type: 'Number'},
+                        ]);
+                    }
+                    const setting = { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price', 'end_gather_tp'] };
+                    compareTree.clearFinal();
+                    for (const r of result) {
+                        const tree = createNewPathTree('ledger', setting);
+                        tree.loadDatas(r);
+                        treeCalc.calculateAll(tree);
+                        compareTree.loadTree(tree, function (cur, source) {
+                            cur.total_price = ZhCalc.add(cur.total_price, source.total_price);
+                            cur.dgn_qty1 = ZhCalc.add(cur.dgn_qty1, source.dgn_qty1);
+                            cur.dgn_qty2 = ZhCalc.add(cur.dgn_qty2, source.dgn_qty2);
+                            cur.final_dgn_qty1 = ZhCalc.sum([cur.final_dgn_qty1, source.deal_dgn_qty1, source.c_dgn_qty1]);
+                            cur.final_dgn_qty2 = ZhCalc.sum([cur.final_dgn_qty2, source.deal_dgn_qty2, source.c_dgn_qty2]);
+                            cur.final_tp = ZhCalc.add(cur.final_tp, source.end_gather_tp);
+                        });
+                    }
+                    compareTree.afterLoad(node => {
+                        node.dgn_price = ZhCalc.div(node.total_price, node.dgn_qty1, 2);
+                        node.dgn_qty = node.dgn_qty1
+                            ? (node.dgn_qty2 ? node.dgn_qty1 + '/' + node.dgn_qty2 : node.dgn_qty1)
+                            : (node.dgn_qty2 ? '/' + node.dgn_qty2 : '');
+                        node.final_dgn_price = ZhCalc.div(node.final_tp, node.final_dgn_qty1, 2);
+                        node.final_dgn_qty = node.final_dgn_qty1
+                            ? (node.final_dgn_qty2 ? node.final_dgn_qty1 + '/' + node.final_dgn_qty2 : node.final_dgn_qty1)
+                            : (node.final_dgn_qty2 ? '/' + node.final_dgn_qty2 : '');
+                        node.grow_dgn_qty1 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty1, node.gai_dgn_qty1), node.gai_dgn_qty1, 4), 100);
+                        node.grow_dgn_qty2 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty2, node.gai_dgn_qty2), node.gai_dgn_qty2, 4), 100);
+                        node.grow_dgn_qty = node.grow_dgn_qty1
+                            ? (node.grow_dgn_qty2 ? node.grow_dgn_qty1 + '/' + node.grow_dgn_qty2 : node.grow_dgn_qty1)
+                            : (node.grow_dgn_qty2 ? '/' + node.grow_dgn_qty2 : '');
+                        node.grow_tp = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_tp, node.gai_tp), node.gai_tp, 4), 100);
+                    });
+                    SpreadJsObj.reLoadSheetHeader(compareSheet);
+                    SpreadJsObj.reLoadSheetData(compareSheet);
+                    $('#select-final').modal('hide');
+                });
+            });
+        }
+        selectNode(node, select) {
+            const posterity = this.selectTree.getPosterity(node);
+            posterity.unshift(node);
+            for (const p of posterity) {
+                p.selected = select;
+            }
+        }
+        getSelects() {
+            const select = [];
+            for (const n of this.selectTree.nodes) {
+                if ((!n.children || n.children.length === 0) && n.selected) select.push(n.tid);
             }
+            return select;
         }
-        return html.join('');
-    })());
+    }
+
+    let sfSelect;
+    $('#select-final').on('shown.bs.modal', () => {
+        if (!sfSelect) sfSelect = new sfObject();
+    });
 });

+ 89 - 41
app/public/js/budget_list.js

@@ -48,19 +48,6 @@ const delBudget = function () {
     });
 };
 
-const relaTender = function () {
-    // todo 选择标段
-    const rela = [];
-    const select = $('[name=select-rela-check]:checked');
-    for (const s of select) {
-        rela.push(s.getAttribute('tid'));
-    }
-    postData('/budget/save', { id: curBudget.id, rela_tender: rela.join(',') }, function () {
-        $(`[bid=${curBudget.id}]`)[0].setAttribute('rela-tender', rela.join(','));
-        $('#select-rela').modal('hide');
-    });
-};
-
 
 $(document).ready(() => {
     autoFlashHeight();
@@ -70,34 +57,6 @@ $(document).ready(() => {
     $('#del-budget').on('show.bs.modal', () => {
         $('#del-budget-name').text(curBudget.name);
     });
-    $('#sr-select-all').click(function () {
-        $('[name=select-rela-check]').prop("checked", this.checked);
-    });
-    $('#select-rela').on('show.bs.modal', () => {
-        $('#sr-select-all')[0].checked = false;
-        $('#valid-rela-tender').html('');
-        postData(`/budget/rela?id=${curBudget.id}`, {}, tenders => {
-            const rela = curBudget.rela_tender ? curBudget.rela_tender.split(',') : [];
-            const html = [];
-            const tree = Tender2Tree.convert(category, tenders, null, null, function (node, source) {
-                node.lastStageOrder = source.lastStageOrder;
-                node.lastStageStatus = source.lastStageStatus;
-            });
-
-            for (const t of tree.nodes) {
-                if (t.cid) {
-                    html.push(`<tr><td></td><td class="in-${t.level}"><i class="fa fa-folder-o"></i> ${t.name}</td><td></td><td></td></tr>`);
-                } else if (t.tid) {
-                    const icon = tree.isLastSibling(t) ? '└' : '├';
-                    html.push(`<tr><td class="text-center"><input type="checkbox" name="select-rela-check" tid="${t.tid}"></td><td class="in-${t.level}">${icon} ${t.name}</td><td>第${t.lastStageOrder}期</td><td>${t.lastStageStatus}</td></tr>`);
-                }
-            }
-            $('#valid-rela-tender').html(html.join(''));
-            for (const r of rela) {
-                $(`[tid=${r}]`).attr("checked", "checked");
-            }
-        });
-    });
 
     let timer = null;
     let oldSearchVal = null;
@@ -224,4 +183,93 @@ $(document).ready(() => {
             mem.permission.splice(mem.permission.indexOf(permissionConst[this.getAttribute('ptype')].value), 1);
         }
     });
+
+    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: 180, formatter: '@', cellType: 'tree'},
+                    {title: '期数', field: 'lastStageOrder', hAlign: 1, width: 60, formatter: '@'},
+                    {title: '审批状态', field: 'lastStageStatus', hAlign: 1, width: 60, formatter: '@'},
+                ],
+                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);
+            });
+
+
+
+            $('#sr-select-all').click(function () {
+                if (!self.selectTree) return;
+                for (const n of self.selectTree.nodes) {
+                    n.selected = this.checked;
+                }
+                SpreadJsObj.reloadColData(self.sheet, 0);
+            });
+            $('#select-rela-ok').click(() => {
+                const rela = self.getSelects();
+                postData('/budget/save', { id: curBudget.id, rela_tender: rela.join(',') }, function () {
+                    $(`[bid=${curBudget.id}]`)[0].setAttribute('rela-tender', rela.join(','));
+                    $('#select-rela').modal('hide');
+                });
+            });
+        }
+        selectNode(node, select) {
+            const posterity = this.selectTree.getPosterity(node);
+            posterity.unshift(node);
+            for (const p of posterity) {
+                p.selected = select;
+            }
+        }
+        getSelects() {
+            const select = [];
+            for (const n of this.selectTree.nodes) {
+                if ((!n.children || n.children.length === 0) && n.selected) select.push(n.tid);
+            }
+            return select;
+        }
+        init() {
+            $('#sr-select-all')[0].checked = false;
+            const self = this;
+            postData(`/budget/rela?id=${curBudget.id}`, {}, tenders => {
+                const rela = curBudget.rela_tender ? curBudget.rela_tender.split(',') : [];
+                self.selectTree = Tender2Tree.convert(category, tenders, null, null, function (node, source) {
+                    node.lastStageOrder = source.lastStageOrder;
+                    node.lastStageStatus = source.lastStageStatus;
+                });
+                for (const node of self.selectTree.nodes) {
+                    node.selected = rela.indexOf(node.tid + '') >= 0;
+                }
+                SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Tree, this.selectTree);
+            });
+        }
+    }
+    let srSelect;
+    $('#select-rela').on('shown.bs.modal', () => {
+        if (!srSelect) srSelect = new srObject();
+        srSelect.init();
+    });
 });

+ 2 - 13
app/view/budget/compare_modal.ejs

@@ -4,20 +4,9 @@
             <div class="modal-header">
                 <h5 class="modal-title">选择决算标段</h5>
             </div>
-            <div class="modal-body" style="display: block; overflow: auto; height: 500px">
+            <div class="modal-body">
                 <h5>可选标段</h5>
-                <table class="table table-sm table-bordered">
-                    <thead>
-                    <tr class="text-center">
-                        <th>选择</th>
-                        <th>标段名称</th>
-                        <th>期数</th>
-                        <th>状态</th>
-                    </tr>
-                    </thead>
-                    <tbody id="valid-tender-list">
-                    </tbody>
-                </table>
+                <div id="sf-spread" style="height: 300px"></div>
             </div>
             <div class="modal-footer">
                 <div class="form-check form-check-inline">

+ 3 - 10
app/view/budget/list_modal.ejs

@@ -77,16 +77,9 @@
             <div class="modal-header">
                 <h5 class="modal-title">选择决算标段</h5>
             </div>
-            <div class="modal-body" style="display: block; overflow: auto; height: 500px">
+            <div class="modal-body">
                 <h5>可选标段</h5>
-                <table class="table table-sm table-bordered">
-                    <tr class="text-center"><th>选择</th><th>标段名称</th><th>期数</th><th>状态</th></tr>
-                    <tbody id="valid-rela-tender">
-                    <% for (const t of tenderList) { %>
-                    <tr><td class="text-center"><input type="checkbox" name="select-rela-check" tid="<%- t.id %>"></td><td><%- t.name %></td><td>第<%- t.lastStage.order %>期</td><td><%- auditConst.stage.statusString[t.lastStage.status] %></td></tr>
-                    <% } %>
-                    </tbody>
-                </table>
+                <div id="sr-spread" style="height: 300px"></div>
             </div>
             <div class="modal-footer">
                 <div class="form-check form-check-inline">
@@ -94,7 +87,7 @@
                     <label class="form-check-label" for="sr-select-all">全选</label>
                 </div>
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-sm btn-primary" onclick="relaTender();">确定</button>
+                <button type="button" class="btn btn-sm btn-primary" id="select-rela-ok">确定</button>
             </div>
         </div>
     </div>

+ 2 - 0
config/web.js

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