Bläddra i källkod

1. 新建标段,选择计价规范,根据计价规范,初始化台账
2. 根据计价规范,加载可用的标准清单(台账分解,台账修订)
3. 工程量清单、项目节,可选择标准清单

MaiXinRong 6 år sedan
förälder
incheckning
34ef27ea47

+ 2 - 2
app/const/spread.js

@@ -51,7 +51,7 @@ const withCl = {
             {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
         ],
-        emptyRows: 20,
+        emptyRows: 3,
         headRows: 2,
         headRowHeight: [35, 35],
         defaultRowHeight: 21,
@@ -86,7 +86,7 @@ const withoutCl = {
             {title: '施工图复核数量', colSpan: '1', rowSpan: '1', field: 'sgfh_qty', hAlign: 2, width: 120, type: 'Number'},
             {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
         ],
-        emptyRows: 20,
+        emptyRows: 3,
         headRows: 1,
         headRowHeight: [40],
         defaultRowHeight: 21,

+ 3 - 0
app/controller/ledger_controller.js

@@ -123,6 +123,7 @@ module.exports = app => {
                         auditHistory.push(await ctx.service.ledgerAudit.getAuditors(ctx.tender.id, i));
                     }
                 }
+                const [stdBills, stdChapters] = await this.ctx.service.valuation.getValuationStdList(ctx.tender.data.valuation);
                 const renderData = {
                     tender: tender.data,
                     tenderInfo: tender.info,
@@ -139,6 +140,8 @@ module.exports = app => {
                     preUrl: '/tender/' + tender.id,
                     measureType,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.ledger.explode),
+                    stdBills,
+                    stdChapters,
                 };
                 if ((tender.data.ledger_status === auditConst.status.uncheck || tender.data.ledger_status === auditConst.status.checkNo) && tender.data.user_id === ctx.session.sessionUser.accountId) {
                     renderData.accountGroup = accountGroup;

+ 3 - 0
app/controller/revise_controller.js

@@ -62,6 +62,7 @@ module.exports = app => {
                 const count = await ctx.service.ledgerRevise.count({tid: ctx.tender.id});
                 const ledgerRevise = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id);
                 const addValid = await this._getAddReviseValid(ctx);
+                const [stdBills, stdChapters] = await this.ctx.service.valuation.getValuationStdList(ctx.tender.data.valuation);
                 const renderData = {
                     tender: ctx.tender.data,
                     tenderMenu: this.menu.tenderMenu,
@@ -74,6 +75,8 @@ module.exports = app => {
                     ledgerRevise,
                     addValid,
                     auditConst: audit.revise,
+                    stdBills,
+                    stdChapters,
                 };
                 await this.layout('revise/index.ejs', renderData, 'revise/modal.ejs');
             } catch (err) {

+ 3 - 1
app/controller/tender_controller.js

@@ -43,6 +43,7 @@ module.exports = app => {
                     t.completeStage = await this.ctx.service.stage.getLastestCompleteStage(t.id);
                 }
                 const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
+                const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id);
                 const renderData = {
                     tenderList,
                     tenderConst,
@@ -53,6 +54,7 @@ module.exports = app => {
                     jsFiles: this.app.jsFiles.common.concat(this.jsFiles),
                     auditConst,
                     userPermission,
+                    valuations,
                 };
                 await this.layout(view, renderData, modal);
             } catch (err) {
@@ -121,7 +123,7 @@ module.exports = app => {
                 }
                 console.log(ctx.request.body.data);
                 const data = JSON.parse(ctx.request.body.data);
-                if (!data.name || data.name === '') {
+                if (!data.name || data.name === '' || !data.valuation) {
                     throw '标段信息不完整';
                 }
 

+ 25 - 11
app/public/js/ledger.js

@@ -1076,7 +1076,7 @@ $(document).ready(function() {
             showSideTools(tab.hasClass('active'));
             if (tab.attr('content') === '#std-chapter') {
                 if (!stdChapter) {
-                    stdChapter = new stdLib('#std-chapter-spread', 'chapter', {
+                    stdChapter = new stdLib('#std-chapter', 'chapter', {
                         id: 'chapter_id',
                         pid: 'pid',
                         order: 'order',
@@ -1095,12 +1095,12 @@ $(document).ready(function() {
                         headRowHeight: [40],
                         defaultRowHeight: 21,
                     });
-                    stdChapter.loadLib(1);
+                    stdChapter.loadLib($('select', '#std-chapter').val());
                 }
                 stdChapter.spread.refresh();
             } else if (tab.attr('content') === '#std-bills') {
                 if (!stdBills) {
-                    stdBills = new stdLib('#std-bills-spread', 'bills', {
+                    stdBills = new stdLib('#std-bills', 'bills', {
                         id: 'bill_id',
                         pid: 'pid',
                         order: 'order',
@@ -1109,7 +1109,7 @@ $(document).ready(function() {
                         keys: ['id', 'list_id', 'bill_id']
                     }, {
                         cols: [
-                            {title: '清单编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true, cellType: 'tree'},
+                            {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true, cellType: 'tree'},
                             {title: '名称', field: 'name', hAlign: 0, width: 230, formatter: '@', readOnly: true},
                             {title: '单位', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true}
                         ],
@@ -1119,14 +1119,14 @@ $(document).ready(function() {
                         headRowHeight: [40],
                         defaultRowHeight: 21,
                     });
-                    stdBills.loadLib(1);
+                    stdBills.loadLib($('select', '#std-bills').val());
                 }
                 stdBills.spread.refresh();
             } else if (tab.attr('content') === '#deal-bills') {
                 if (!dealBills) {
                     dealBills = new DealBills('#deal-bills-spread', {
                         cols: [
-                            {title: '清单编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+                            {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
                             {title: '名称', field: 'name', hAlign: 0, width: 230, formatter: '@', readOnly: true},
                             {title: '单位', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
                             {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
@@ -1180,7 +1180,8 @@ $(document).ready(function() {
 
     class stdLib {
         constructor(selector, stdType, treeSetting, spreadSetting) {
-            this.obj = $(selector)[0];
+            const self = this;
+            this.obj = $(selector + '-spread')[0];
             this.url = '/std/' + stdType;
             this.treeSetting = treeSetting;
             treeSetting.preUrl = this.url;
@@ -1218,13 +1219,26 @@ $(document).ready(function() {
                 });
             });
             this.pathTree = createNewPathTree('base', this.treeSetting);
+            this.cacheLib = [];
+            $('select', selector).change(function () {
+                self.loadLib(parseInt(this.value));
+            });
         }
         loadLib (listId) {
-            const self = this;
-            postData(this.url+'/get-data', {list_id: listId}, function (data) {
-                self.pathTree.loadDatas(data);
-                SpreadJsObj.loadSheetData(self.spread.getActiveSheet(), 'tree', self.pathTree);
+            const cacheData = this.cacheLib.find(function (lib) {
+                return lib.id === listId;
             });
+            if (cacheData) {
+                this.pathTree.loadDatas(cacheData.data);
+                SpreadJsObj.loadSheetData(this.spread.getActiveSheet(), 'tree', this.pathTree);
+            } else {
+                const self = this;
+                postData(this.url+'/get-data', {list_id: listId}, function (data) {
+                    self.cacheLib.push({id: listId, data: data});
+                    self.pathTree.loadDatas(data);
+                    SpreadJsObj.loadSheetData(self.spread.getActiveSheet(), 'tree', self.pathTree);
+                });
+            }
         }
     }
     class DealBills {

+ 25 - 11
app/public/js/revise.js

@@ -318,8 +318,9 @@ $(document).ready(() => {
     });
 
     class stdLib {
-        constructor(obj, stdType, treeSetting, spreadSetting) {
-            this.obj = obj;
+        constructor(selector, stdType, treeSetting, spreadSetting) {
+            const self = this;
+            this.obj = $(selector + '-spread')[0];
             this.url = '/std/' + stdType;
             this.treeSetting = treeSetting;
             treeSetting.preUrl = this.url;
@@ -349,13 +350,26 @@ $(document).ready(() => {
                 });
             });
             this.pathTree = createNewPathTree('base', this.treeSetting);
+            this.cacheLib = [];
+            $('select', selector).change(function () {
+                self.loadLib(parseInt(this.value));
+            });
         }
         loadLib (listId) {
-            const self = this;
-            postData(this.url+'/get-data', {list_id: listId}, function (data) {
-                self.pathTree.loadDatas(data);
-                SpreadJsObj.loadSheetData(self.spread.getActiveSheet(), 'tree', self.pathTree);
+            const cacheData = this.cacheLib.find(function (lib) {
+                return lib.id === listId;
             });
+            if (cacheData) {
+                this.pathTree.loadDatas(cacheData.data);
+                SpreadJsObj.loadSheetData(this.spread.getActiveSheet(), 'tree', this.pathTree);
+            } else {
+                const self = this;
+                postData(this.url+'/get-data', {list_id: listId}, function (data) {
+                    self.cacheLib.push({id: listId, data: data});
+                    self.pathTree.loadDatas(data);
+                    SpreadJsObj.loadSheetData(self.spread.getActiveSheet(), 'tree', self.pathTree);
+                });
+            }
         }
     }
     class DealBills {
@@ -642,7 +656,7 @@ $(document).ready(() => {
             showSideTools(tab.hasClass('active'));
             if (tab.attr('content') === '#std-chapter') {
                 if (!stdChapter) {
-                    stdChapter = new stdLib($('#std-chapter-spread')[0], 'chapter', {
+                    stdChapter = new stdLib('#std-chapter', 'chapter', {
                         id: 'chapter_id',
                         pid: 'pid',
                         order: 'order',
@@ -661,12 +675,12 @@ $(document).ready(() => {
                         headRowHeight: [40],
                         defaultRowHeight: 21,
                     });
-                    stdChapter.loadLib(1);
+                    stdChapter.loadLib($('select', '#std-chapter').val());
                 }
                 stdChapter.spread.refresh();
             } else if (tab.attr('content') === '#std-bills') {
                 if (!stdBills) {
-                    stdBills = new stdLib($('#std-bills-spread')[0], 'bills', {
+                    stdBills = new stdLib('#std-bills', 'bills', {
                         id: 'bill_id',
                         pid: 'pid',
                         order: 'order',
@@ -675,7 +689,7 @@ $(document).ready(() => {
                         keys: ['id', 'list_id', 'bill_id']
                     }, {
                         cols: [
-                            {title: '清单编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true, cellType: 'tree'},
+                            {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true, cellType: 'tree'},
                             {title: '名称', field: 'name', hAlign: 0, width: 230, formatter: '@', readOnly: true},
                             {title: '单位', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true}
                         ],
@@ -685,7 +699,7 @@ $(document).ready(() => {
                         headRowHeight: [40],
                         defaultRowHeight: 21,
                     });
-                    stdBills.loadLib(1);
+                    stdBills.loadLib($('select', '#std-bills').val());
                 }
                 stdBills.spread.refresh();
             } else if (tab.attr('content') === '#deal-bills') {

+ 6 - 0
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -115,6 +115,10 @@ const SpreadJsObj = {
         sheet.options.protectionOptions = option;
         sheet.options.isProtected = true;
         sheet.options.allowCellOverflow = false;
+
+        const defaultStyle = sheet.getDefaultStyle();
+        defaultStyle.locked = false;
+        sheet.setDefaultStyle(defaultStyle);
     },
     /**
      * sheet批量操作优化(sheet操作大批量数据时, 屏蔽数据刷新, 可优化大量时间)
@@ -262,11 +266,13 @@ const SpreadJsObj = {
         if (sheet.zh_setting.headerFont) {
             const vStyle = new spreadNS.Style();
             vStyle.font = sheet.zh_setting.headerFont;
+            vStyle.locked = false;
             sheet.setDefaultStyle(vStyle, spreadNS.SheetArea.colHeader);
         }
         if (sheet.zh_setting.font) {
             const vStyle = new spreadNS.Style();
             vStyle.font = sheet.zh_setting.font;
+            vStyle.locked = false;
             sheet.setDefaultStyle(vStyle, spreadNS.SheetArea.viewport);
         }
     },

+ 0 - 1
app/public/js/stage.js

@@ -716,7 +716,6 @@ $(document).ready(() => {
                     break;
                 }
             }
-            console.log(data);
             if (data.updateData.length === 0) {
                 toastr.info('其下全部部位明细均已计量');
                 return;

+ 0 - 1
app/public/js/stage_im.js

@@ -172,7 +172,6 @@ const stageIm = (function () {
             _.assignInWith(im, cd, function (oV, sV, key) {
                 return imFields.indexOf(key) > -1 && sV !== undefined ? sV : oV;
             });
-            console.log(im);
         }
     }
 

+ 1 - 0
app/public/js/tender_list.js

@@ -383,6 +383,7 @@ $(document).ready(() => {
     $('#add-bd-ok').click(function () {
         const data = {
             name: $('[name=name]', '#add-bd').val(),
+            valuation: $('[name=valuation]:checked').val(),
             category: [],
         };
         if (!data.name || data.name === '') {

+ 1 - 0
app/public/js/tender_list_manage.js

@@ -383,6 +383,7 @@ $(document).ready(() => {
     $('#add-bd-ok').click(function () {
         const data = {
             name: $('[name=name]', '#add-bd').val(),
+            valuation: $('[name=valuation]:checked').val(),
             category: [],
         };
         if (!data.name || data.name === '') {

+ 1 - 0
app/public/js/tender_list_progress.js

@@ -350,6 +350,7 @@ $(document).ready(() => {
     $('#add-bd-ok').click(function () {
         const data = {
             name: $('[name=name]', '#add-bd').val(),
+            valuation: $('[name=valuation]:checked').val(),
             category: [],
         };
         if (!data.name || data.name === '') {

+ 1 - 0
app/service/ledger.js

@@ -766,6 +766,7 @@ module.exports = app => {
                 name: stdData.name,
                 unit: stdData.unit,
                 source: stdData.source,
+                node_type: stdData.node_type,
             };
             result.code = stdData.code ? stdData.code : '';
             result.b_code = stdData.b_code ? stdData.b_code : '';

+ 0 - 7
app/service/standard_lib.js

@@ -24,10 +24,6 @@ class StandardLib extends BaseTreeService {
         this.stdType = '';
     }
 
-    // 供子类继承(不同的标准库可能需要转换一下数据)
-    convertData (data) {
-    }
-
 
     /**
      * 实例中具体的dataId使用字段不相同,统一赋值到source下
@@ -61,7 +57,6 @@ class StandardLib extends BaseTreeService {
         const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
         const node = await this.db.queryOne(sql, sqlParam);
         this.setSourceData(node);
-        this.convertData(node);
 
         return node;
     }
@@ -84,7 +79,6 @@ class StandardLib extends BaseTreeService {
         const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
         const resultData = await this.db.query(sql, sqlParam);
         this.setSourceData(resultData);
-        this.convertData(resultData);
         return resultData;
     }
     /**
@@ -110,7 +104,6 @@ class StandardLib extends BaseTreeService {
         const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
         const data = await this.db.query(sql, sqlParam);
         this.setSourceData(data);
-        this.convertData(data);
         return data;
     };
 }

+ 0 - 17
app/service/std_bills.js

@@ -32,23 +32,6 @@ module.exports = app => {
             }, 'bill');
             this.stdType = 'bill';
         }
-
-        /**
-         * 查询数据后,转换数据(用于兼容项目节与清单的不同)
-         * @param data
-         */
-        convertData (data) {
-            if (data instanceof Array) {
-                for (const d of data) {
-                    d.b_code = d.code;
-                    delete d.code;
-                }
-            } else if (data.code) {
-                data.b_code = data.code;
-                delete data.code;
-            }
-        }
-
     }
 
     return StdBills;

+ 4 - 2
app/service/tender.js

@@ -12,7 +12,7 @@ const tenderConst = require('../const/tender');
 const auditConst = require('../const/audit');
 const fs = require('fs');
 const path = require('path');
-const commonQueryColumns = ['id', 'project_id', 'name', 'status', 'category', 'ledger_times', 'ledger_status', 'measure_type', 'user_id'];
+const commonQueryColumns = ['id', 'project_id', 'name', 'status', 'category', 'ledger_times', 'ledger_status', 'measure_type', 'user_id', 'valuation'];
 
 module.exports = app => {
 
@@ -163,6 +163,7 @@ module.exports = app => {
          */
         async add(data) {
             let result = false;
+            const templateId = await this.ctx.service.valuation.getValuationTemplate(data.valuation);
             this.transaction = await this.db.beginTransaction();
             try {
                 // 获取当前用户信息
@@ -177,6 +178,7 @@ module.exports = app => {
                     user_id: sessionUser.accountId,
                     create_time: new Date(),
                     category: JSON.stringify(data.category),
+                    valuation: data.valuation,
                 };
                 const operate = await this.transaction.insert(this.tableName, insertData);
 
@@ -186,7 +188,7 @@ module.exports = app => {
                 }
 
                 // 获取标段项目节点模板
-                const tenderNodeTemplateData = await this.ctx.service.tenderNodeTemplate.getData();
+                const tenderNodeTemplateData = await this.ctx.service.tenderNodeTemplate.getData(templateId);
                 // 复制模板数据到标段数据表
                 result = await this.ctx.service.ledger.innerAdd(tenderNodeTemplateData, operate.insertId, this.transaction);
                 if (!result) {

+ 4 - 2
app/service/tender_node_template.js

@@ -26,10 +26,11 @@ module.exports = app => {
         /**
          * 获取模板数据
          *
+         * @param {Integer} tid - 模板id
          * @param {Boolean} isCache - 是否使用缓存
          * @return {Array} - 返回模板数据
          */
-        async getData(isCache = true) {
+        async getData(tid, isCache = true) {
             const cacheKey = 'tenderTPL';
             const data = await this.cache.get(cacheKey);
 
@@ -39,7 +40,8 @@ module.exports = app => {
 
             // 获取所有数据
             const templateData = await this.db.select(this.tableName, {
-                columns: ['code', 'name', 'unit', 'source', 'remark', 'pid', 'level', 'order', 'full_path', 'is_leaf', 'template_id'],
+                where: {list_id: tid},
+                columns: ['code', 'name', 'unit', 'source', 'remark', 'pid', 'level', 'order', 'full_path', 'is_leaf', 'template_id', 'node_type'],
             });
             if (templateData.length <= 0) {
                 return [];

+ 58 - 0
app/service/valuation.js

@@ -0,0 +1,58 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = app => {
+
+    class Valuation extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'valuation_list';
+        }
+
+        async getProjectValidValuation(pid) {
+            const project = await this.ctx.service.project.getDataById(pid);
+            const vid =  this._.map(project.valuation.split(','), this._.toInteger);
+            return await this.db.select(this.tableName, {
+                where: {id: vid},
+                columns: ['id', 'name'],
+            });
+        }
+
+        async getValuationTemplate(id) {
+            const valuation = await this.getDataById(id);
+            return parseInt(valuation.template_id);
+        }
+
+        async getValuationStdList(id) {
+            const valuation = await this.getDataById(id);
+            const billsId = this._.map(valuation.bill_id.split(','), this._.toInteger);
+            const chaptersId = this._.map(valuation.chapter_id.split(','), this._.toInteger);
+            const billsList = await this.db.select('zh_bill_list', {
+                where: {id: billsId},
+                columns: ['id', 'name'],
+            });
+            const chapterList = await this.db.select('zh_project_chapter_list', {
+                where: {id: chaptersId},
+                columns: ['id', 'name'],
+            });
+            return [billsList, chapterList];
+        }
+
+    }
+
+    return Valuation;
+};

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

@@ -101,7 +101,11 @@
                     <div id="std-chapter" class="tab-pane">
                         <div class="sjs-bar-2">
                             <div class="pb-1">
-                                <select class="form-control form-control-sm"><option>0号计量台帐部位参考(项目节)</option></select>
+                                <select class="form-control form-control-sm">
+                                    <% for (const c of stdChapters) { %>
+                                    <option value="<%- c.id %>" <% if (stdChapters.indexOf(c) === 0) { %>selected<% } %>><%- c.name %></option>
+                                    <% } %>
+                                </select>
                             </div>
                         </div>
                         <div id="std-chapter-spread" class="sjs-sh-2">
@@ -110,7 +114,11 @@
                     <div id="std-bills" class="tab-pane">
                         <div class="sjs-bar-3">
                             <div class="pb-1">
-                                <select class="form-control form-control-sm"><option>0号计量台帐清单参考(工程量清单)</option></select>
+                                <select class="form-control form-control-sm">
+                                    <% for (const b of stdBills) { %>
+                                    <option value="<%- b.id %>" <% if (stdBills.indexOf(b) === 0) { %>selected<% } %>><%- b.name %></option>
+                                    <% } %>
+                                </select>
                             </div>
                         </div>
                         <div id="std-bills-spread" class="sjs-sh-3">

+ 11 - 0
app/view/tender/modal.ejs

@@ -10,6 +10,17 @@
                     <label>标段名称<b class="text-danger">*</b></label>
                     <input class="form-control"  placeholder="输入标段名称" type="text" name="name">
                 </div>
+                <div class="form-group">
+                    <label ><b class="text-danger">*</b>计价规范</label>
+                    <div>
+                        <% for (const v of valuations) { %>
+                        <div class="form-check form-check-inline mt-2">
+                            <input class="form-check-input" name="valuation" type="radio" id="valuation<%- v.id %>" value="<%- v.id %>" checked="">
+                            <label class="form-check-label" for="valuation<%- v.id %>"><%- v.name %></label>
+                        </div>
+                        <% } %>
+                    </div>
+                </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>