zhongzewei 7 年之前
父節點
當前提交
3899225dc2

+ 26 - 0
modules/all_models/std_billsGuidance_items.js

@@ -0,0 +1,26 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+//清单指引条目
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+
+const stdBillsGuidanceItems = new Schema({
+    libID: String,
+    ID: String, //uuid
+    ParentID: String,
+    NextSiblingID: String,
+    billsID: String, //关联清单的ID
+    name: String,
+    type: Number, //0:工作内容 1:定额
+    rationID: {type: Number, default: null}, //定额类型时
+    deleted: {type: Boolean, default: false}
+}, {versionKey: false});
+
+mongoose.model('std_billsGuidance_items', stdBillsGuidanceItems, 'std_billsGuidance_items');

+ 27 - 0
modules/all_models/std_billsGuidance_lib.js

@@ -0,0 +1,27 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+//清单指引库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+
+const stdBillsGuidanceLib = new Schema({
+    ID: String, //uuid
+    compilationId: String,
+    compilationName: String,
+    billsLibId: Number,
+    billsLibName: String,
+    name: String,
+    creator: String,
+    createDate: String,
+    deleted: {type: Boolean, default: false},
+}, {versionKey: false});
+
+mongoose.model('std_billsGuidance_lib', stdBillsGuidanceLib, 'std_billsGuidance_lib');
+

+ 54 - 0
modules/std_billsGuidance_lib/controllers/libController.js

@@ -0,0 +1,54 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+import BaseController from '../../common/base/base_controller';
+const _ = require('lodash');
+const billsGuidanceFacade = require('../facade/facades');
+let callback = function (req, res, err, msg, data) {
+    res.json({error: err, message: msg, data: data});
+};
+
+class BillsGuideLibController extends BaseController{
+    //获取清单指引库和该库引用的清单
+    async getLibWithBills(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let rst = await billsGuidanceFacade.getLibWithBills(data.libID);
+            callback(req, res, 0, '', rst);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
+
+    async getItemsByBills(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let items = await billsGuidanceFacade.getItemsBybills(data.guidanceLibID, data.billsID);
+            callback(req, res, 0, '', items);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
+
+    async updateItems(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let updateDatas = data.updateDatas;
+            await billsGuidanceFacade.updateItems(updateDatas);
+            callback(req, res, 0, '', null);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
+}
+
+export default BillsGuideLibController;

+ 27 - 0
modules/std_billsGuidance_lib/controllers/viewController.js

@@ -0,0 +1,27 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+import BaseController from "../../common/base/base_controller";
+
+class ViewsController extends BaseController{
+    redirectMain(req, res){
+        res.render('maintain/billsGuidance_lib/html/main.html',
+            {
+                userAccount: req.session.managerData.username
+            });
+    }
+    redirectGuidance(req, res){
+        res.render('maintain/billsGuidance_lib/html/zhiyin.html',
+            {
+                userAccount: req.session.managerData.username
+            });
+    }
+}
+
+export default ViewsController;

+ 136 - 0
modules/std_billsGuidance_lib/facade/facades.js

@@ -0,0 +1,136 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/6/1
+ * @version
+ */
+import mongoose from 'mongoose';
+import CompilationModel from "../../users/models/compilation_model";
+import moment from 'moment';
+const uuidV1 = require('uuid/v1');
+const billsLibModel = mongoose.model('std_bills_lib_list');
+const billsGuideLibModel = mongoose.model('std_billsGuidance_lib');
+const billsGuideItemsModel = mongoose.model('std_billsGuidance_items');
+const stdBillsLibModel = mongoose.model('std_bills_lib_list');
+const stdBillsModel = mongoose.model('std_bills_lib_bills');
+const stdBillsJobsModel = mongoose.model('std_bills_lib_jobContent');
+const stdRationModel = mongoose.model('std_ration_lib_ration_items');
+const _ = require('lodash');
+
+module.exports = {
+    getLibWithBills,
+    getItemsBybills,
+};
+
+async function getBillsGuideLibs(findData) {
+    return await billsGuideLibModel.find(findData);
+}
+
+
+async function getLibWithBills(libID){
+    let guidanceLib = await getBillsGuideLibs({ID: libID, deleted: false});
+    if(guidanceLib.length === 0){
+        throw '不存在此指引库!';
+    }
+    let billsLib = await stdBillsLibModel.findOne({billsLibId: guidanceLib[0].billsLibId, deleted: false});
+    if(!billsLib){
+        throw '引用的清单规则库不存在!';
+    }
+    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId, deleted: false}, '-_id code name ID NextSiblingID ParentID');
+    return {guidanceLib: guidanceLib[0], bills};
+}
+
+function getAttrs(field, datas){
+    let rst = [];
+    for(let data of datas){
+        if(data[field]){
+            rst.push(data[field]);
+        }
+    }
+    return rst;
+}
+
+//定额项目指所引用定额是否被删除
+function rationAllExist(rationItems, stdRationIdx) {
+    for(let item of rationItems){
+        if(!stdRationIdx[item.rationID]){
+            return false;
+        }
+    }
+    return true;
+}
+
+//将同层树结构转为顺序数组
+function chainToArr(nodes){
+    let rst = [];
+    let tempIdx = {};
+    let nodeIdx = {};
+    //建索引
+    for(let node of nodes){
+        tempIdx[node.ID] = {ID: node.ID, NextSiblingID: node.NextSiblingID, preSibling: null, nextSibling: null};
+        nodeIdx[node.ID] = node;
+    }
+    //建链
+    for(let i in tempIdx){
+        let temp = tempIdx[i];
+        if(temp.NextSiblingID != -1){
+            let next = tempIdx[temp.NextSiblingID];
+            temp.nextSibling = next;
+            next.preSibling = temp;
+        }
+    }
+    let firstNode = null;
+    for(let i in tempIdx){
+        if(!tempIdx[i].preSibling){
+            firstNode = tempIdx[i];
+            break;
+        }
+    }
+    //获得顺序队列
+    while(firstNode){
+        rst.push(nodeIdx[firstNode.ID]);
+        firstNode = firstNode.nextSibling;
+    }
+    return rst;
+}
+
+async function getItemsBybills(guidanceLibID, billsID){
+    const type = {job: 0, ration: 1};
+    let items = await billsGuideItemsModel.find({libID: guidanceLibID, billsID: billsID, deleted: false});
+    let rationItems = _.filter(items, {type: type.ration});
+    let rationIds = getAttrs('rationID', rationItems);
+    let stdRations = await stdRationModel.find({ID: {$in: rationIds}, $or: [{isDeleted: null}, {isDeleted: false}]});
+    let stdRationIndex = {};
+    for(let stdRation of stdRations){
+        stdRationIndex[stdRation.ID] = stdRation;
+    }
+    //判断定额完整性
+    if(!rationAllExist(rationItems, stdRationIndex)){
+        //建定额链, 排序后再清除不存在的定额,保证顺序正确性
+        rationItems = chainToArr(rationItems);
+        //清除已被删除的定额
+        let removeIds = [];
+        _.remove(rationItems, function (item) {
+            if(!stdRationIndex[item.rationID]){
+                removeIds.push(item.ID);
+                return true;
+            }
+            return false;
+        });
+        _.remove(items, function (item) {
+           return removeIds.includes(item.ID);
+        });
+        await billsGuideItemsModel.remove({ID: {$in: removeIds}});
+        //重组树结构
+        let bulkArr = [];
+        for(let i = 0, len = rationItems.length; i < len; i++){
+            rationItems[i].NextSiblingID = rationItems[i + 1] ? rationItems[i + 1].ID : -1;
+            bulkArr.push({updateOne: {filter: {ID: rationItems[i].ID}, update: {$set: {NextSiblingID: rationItems[i].NextSiblingID}}}});
+        }
+        await billsGuideItemsModel.bulkWrite(bulkArr);
+    }
+    return items;
+}

+ 20 - 0
modules/std_billsGuidance_lib/routes/routes.js

@@ -0,0 +1,20 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/5/29
+ * @version
+ */
+import express from 'express';
+import BillsGuideLibController from '../controllers/libController';
+const router = express.Router();
+const billsGuideLibController = new BillsGuideLibController();
+
+module.exports = function (app) {
+  router.post('/getLibWithBills', billsGuideLibController.getLibWithBills);
+  router.post('/getItemsByBills', billsGuideLibController.getItemsByBills);
+
+  app.use('/billsGuidance/api', router);
+};

+ 8 - 5
web/building_saas/complementary_ration_lib/js/main.js

@@ -16,11 +16,14 @@ let compleRationMain = {
                     );
                     );
                     var newHref = "/complementaryRation/ration?repository="+id;
                     var newHref = "/complementaryRation/ration?repository="+id;
                     $("#tempId td:first a").click(function () {
                     $("#tempId td:first a").click(function () {
-                        let newHref = "/complementaryRation/ration?repository="+id;
-                        let newTab = window.open('about:blank');
-                        CommonAjax.get(newHref, [], function () {
-                            newTab.location.href = newHref;
-                        });
+                        $('#comple-ration').modal('hide');
+                        setTimeout(function () {
+                            let newHref = "/complementaryRation/ration?repository="+id;
+                            let newTab = window.open('about:blank');
+                            CommonAjax.get(newHref, [], function () {
+                                newTab.location.href = newHref;
+                            });
+                        }, 200);
                     });
                     });
                     $("#tempId").attr("id", id);
                     $("#tempId").attr("id", id);
                 }
                 }

+ 3 - 0
web/building_saas/js/global.js

@@ -7,10 +7,13 @@ function autoFlashHeight(){
     // var feeRateToolsbarHeight = $(".toolsbar_feeRate").height();
     // var feeRateToolsbarHeight = $(".toolsbar_feeRate").height();
     let toolsBarHeightQ = $(".tools-bar-height-q").height();
     let toolsBarHeightQ = $(".tools-bar-height-q").height();
     let toolsBarHeightD = $(".tools-bar-height-d").height();
     let toolsBarHeightD = $(".tools-bar-height-d").height();
+    let toolsBarHeightZ = $(".tools-bar-height-z").height();
     //$(".main-data-side-q").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightQ-302);
     //$(".main-data-side-q").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightQ-302);
     $(".main-data-side-q").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightQ-$('#qd').find('.bottom-content').find('.p-0').height()-5);
     $(".main-data-side-q").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightQ-$('#qd').find('.bottom-content').find('.p-0').height()-5);
     //$(".main-data-side-d").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightD-302);
     //$(".main-data-side-d").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightD-302);
     $(".main-data-side-d").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightD-$('#stdSectionRations').height()-5);
     $(".main-data-side-d").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightD-$('#stdSectionRations').height()-5);
+    $(".main-data-side-zb").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightZ);
+    $(".main-data-side-zi").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightZ);
     $('.main-content').width($(window).width()-$('.main-nav').width()-$('.main-side').width()-5);
     $('.main-content').width($(window).width()-$('.main-nav').width()-$('.main-side').width()-5);
     $('#glj_tree_div .modal-content').width($(window).width() < 1020 + 20 ? $(window).width() - 20 : 1020);
     $('#glj_tree_div .modal-content').width($(window).width() < 1020 + 20 ? $(window).width() - 20 : 1020);
     //$("#main .main-data-top").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
     //$("#main .main-data-top").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);

+ 14 - 14
web/building_saas/main/html/main.html

@@ -86,9 +86,6 @@
                       <a href="javascript:void(0)" class="btn btn-sm" name="lockBills"  title="锁定清单"> <i class="fa fa-lock" aria-hidden="true"></i> 锁定清单</a>
                       <a href="javascript:void(0)" class="btn btn-sm" name="lockBills"  title="锁定清单"> <i class="fa fa-lock" aria-hidden="true"></i> 锁定清单</a>
                       <% } %>
                       <% } %>
                   </div>
                   </div>
-                  <div class="tools-btn">
-                      <a href="javacript:void(0);" data-toggle="modal" data-target="#column" class="btn btn-sm"><i class="fa fa-table" aria-hidden="true"></i> 列设置</a>
-                  </div>
                   <div class="side-tabs">
                   <div class="side-tabs">
                       <ul class="nav nav-tabs" role="tablist">
                       <ul class="nav nav-tabs" role="tablist">
                           <li class="nav-item">
                           <li class="nav-item">
@@ -263,17 +260,15 @@
                                                   <button class="btn btn-secondary btn-sm" type="button"><i class="fa fa-search" aria-hidden="true"></i></button>
                                                   <button class="btn btn-secondary btn-sm" type="button"><i class="fa fa-search" aria-hidden="true"></i></button>
                                               </span>
                                               </span>
                                           </div>
                                           </div>
-                                          <button class="btn btn-primary btn-sm mx-3" type="button">插入定额</button>
-                                          <button class="btn btn-primary btn-sm mx-3" type="button">插入清单</button>
+                                          <button id="guidanceInsertRation" class="btn btn-primary btn-sm mx-3" type="button">插入定额</button>
+                                          <button id="guidanceInsertBills" class="btn btn-primary btn-sm mx-3" type="button">插入清单</button>
                                       </div>
                                       </div>
                                   </div>
                                   </div>
-                                  <div class="main-data-side-z">
-                                      <table class="table table-bordered">
-                                          <tr>
-                                              <th></th><th>项目指引</th><th>选择</th>
-                                          </tr>
-                                          </tr>
-                                      </table>
+                                  <div class="row" style="margin-left: 1px;">
+                                      <div id="billsGuidance_bills" class="main-data-side-zb" style="width: 49%; float: left; margin: 0; padding: 0;">
+                                      </div>
+                                      <div id="billsGuidance_items" class="main-data-side-zi" style="width: 50%; float: left; margin: 0; padding: 0;">
+                                      </div>
                                   </div>
                                   </div>
                               </div>
                               </div>
                               <!--清单规则-->
                               <!--清单规则-->
@@ -584,6 +579,8 @@
                                                 </label>
                                                 </label>
                                             </div>
                                             </div>
                                         </fieldset>
                                         </fieldset>
+                                        <div id="col_setting_spread" style="height:300px;overflow:hidden">
+                                        </div>
                                     </div>
                                     </div>
                                 </div>
                                 </div>
                             </div>
                             </div>
@@ -662,7 +659,7 @@
         </div>
         </div>
     </div>    
     </div>    
     <!--弹出列设置-->
     <!--弹出列设置-->
-    <div class="modal fade" id="column" data-backdrop="static">
+  <!--  <div class="modal fade" id="column" data-backdrop="static">
         <div class="modal-dialog modal-lg" role="document" style="width: 350px;">
         <div class="modal-dialog modal-lg" role="document" style="width: 350px;">
             <div class="modal-content">
             <div class="modal-content">
                 <div class="modal-header">
                 <div class="modal-header">
@@ -678,7 +675,7 @@
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
-    </div>
+    </div>-->
     <!--工料机选择窗口-->
     <!--工料机选择窗口-->
     <div class="modal fade" id="glj_tree_div" data-backdrop="static">
     <div class="modal fade" id="glj_tree_div" data-backdrop="static">
         <div class="modal-dialog modal-lg" role="document" id="modalCon">
         <div class="modal-dialog modal-lg" role="document" id="modalCon">
@@ -1260,6 +1257,7 @@
         <script type="text/javascript" src="/web/building_saas/main/js/controllers/project_controller.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/controllers/project_controller.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/controllers/block_controller.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/controllers/block_controller.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/side_tools.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/side_tools.js"></script>
+        <script type="text/javascript" src="/web/building_saas/main/js/views/std_billsGuidance_lib.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/std_bills_lib.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/std_bills_lib.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/std_ration_lib.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/views/std_ration_lib.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/models/quantity_detail.js"></script>
         <script type="text/javascript" src="/web/building_saas/main/js/models/quantity_detail.js"></script>
@@ -1348,6 +1346,8 @@
 
 
 
 
             $(document).ready(function(){
             $(document).ready(function(){
+                console.log(1 - 1);
+                console.log(1 - 1);
                 //createTree();
                 //createTree();
               /*  document.onkeydown=keydown;
               /*  document.onkeydown=keydown;
                 function keydown(e){
                 function keydown(e){

+ 6 - 3
web/building_saas/main/js/views/calc_base_view.js

@@ -255,10 +255,13 @@ let calcBaseView = {
     //输入窗口控制
     //输入窗口控制
     inputControl: function () {
     inputControl: function () {
         let me = calcBaseView;
         let me = calcBaseView;
-        me.inputExpr.keydown(function (e) {
-            if(!me.arithmeticLegal(me.inputExpr.val() + e.key)){
-                return false;
+        me.inputExpr.on('input',function () {
+            if(!me.arithmeticLegal(me.inputExpr.val())){
+                if(me.preInputExpr){
+                    me.inputExpr.val(me.preInputExpr);
+                }
             }
             }
+            me.preInputExpr = me.inputExpr.val();
         });
         });
     },
     },
 
 

+ 53 - 15
web/building_saas/main/js/views/main_tree_col.js

@@ -399,29 +399,67 @@ let colSettingObj = {
     initSettingSpread: function () {
     initSettingSpread: function () {
         this.settingSpread = SheetDataHelper.createNewSpread($('#col_setting_spread')[0], {sheetCount: 1});
         this.settingSpread = SheetDataHelper.createNewSpread($('#col_setting_spread')[0], {sheetCount: 1});
         this.settingSpread.options.showScrollTip = GC.Spread.Sheets.ShowScrollTip.vertical;
         this.settingSpread.options.showScrollTip = GC.Spread.Sheets.ShowScrollTip.vertical;
+        this.settingSpread.bind(GC.Spread.Sheets.Events.ButtonClicked, function (sender, args) {
+            if(args.sheet.isEditing()){
+                args.sheet.endEdit(true);
+            }
+        });
         this.loadSetting(this.settingSpread.getActiveSheet(), projectObj.project.projSetting.main_tree_col);
         this.loadSetting(this.settingSpread.getActiveSheet(), projectObj.project.projSetting.main_tree_col);
+    },
+    dataChanged: function () {
+        let sheet = this.settingSpread.getActiveSheet();
+        for(let row = 0; row < sheet.getRowCount(); row++){
+            let orgData = projectObj.project.projSetting.main_tree_col.cols[row].visible;
+            let newData = sheet.getValue(row, 0);
+            if(orgData != newData){
+                return true;
+            }
+        }
+        return false;
+    },
+    updateColSetting: function () {
+        let sheet = this.settingSpread.getActiveSheet();
+         let mainSheet = projectObj.mainSpread.getActiveSheet();
+         for (let iRow = 0; iRow < sheet.getRowCount(); iRow++) {
+         projectObj.project.projSetting.main_tree_col.cols[iRow].visible = sheet.getValue(iRow, 0);
+         projectObj.project.projSetting.mainGridSetting.cols[iRow].visible = sheet.getValue(iRow, 0);
+         }
+         SheetDataHelper.massOperationSheet(mainSheet, function () {
+         SheetDataHelper.refreshColumnVisible(projectObj.project.projSetting.mainGridSetting, mainSheet);
+         //左右滚动条到最左边
+         mainSheet.showColumn(projectObj.project.projSetting.mainGridSetting.frozenCols, GC.Spread.Sheets.HorizontalPosition.left);
+         });
+         //refresh nodes to autoFitRow
+         projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots, true);
+         projectObj.project.pushNow('editColSetting', projectObj.project.projSetting.moduleName, {
+         projectID: projectObj.project.ID(),
+         main_tree_col: projectObj.project.projSetting.main_tree_col
+         });
     }
     }
 };
 };
 
 
-$('#column').on('shown.bs.modal', function () {
+$('#poj-set').on('shown.bs.modal', function (e) {
     if (!colSettingObj.settingSpread) {
     if (!colSettingObj.settingSpread) {
         colSettingObj.initSettingSpread();
         colSettingObj.initSettingSpread();
     }
     }
 });
 });
 
 
-$('#column').on('hide.bs.modal', function () {
-    let sheet = colSettingObj.settingSpread.getActiveSheet();
-    for (let iRow = 0; iRow < sheet.getRowCount(); iRow++) {
-        projectObj.project.projSetting.main_tree_col.cols[iRow].visible = sheet.getValue(iRow, 0);
-        projectObj.project.projSetting.mainGridSetting.cols[iRow].visible = sheet.getValue(iRow, 0);
+$('#poj-set').on('hidden.bs.modal', function (e) {
+    if (colSettingObj.settingSpread) {
+        //恢复
+        let sheet = colSettingObj.settingSpread.getActiveSheet();
+        SheetDataHelper.massOperationSheet(sheet, function () {
+            for(let row = 0; row < sheet.getRowCount(); row++){
+                let orgData = projectObj.project.projSetting.main_tree_col.cols[row].visible;
+                sheet.setValue(row, 0, orgData);
+            }
+        });
+    }
+});
+
+
+$('#tab_display_setting').on('shown.bs.tab', function () {
+    if(colSettingObj.settingSpread){
+        colSettingObj.settingSpread.refresh();
     }
     }
-    SheetDataHelper.massOperationSheet(projectObj.mainSpread.getActiveSheet(), function () {
-        SheetDataHelper.refreshColumnVisible(projectObj.project.projSetting.mainGridSetting, projectObj.mainSpread.getActiveSheet());
-    });
-    //refresh nodes to autoFitRow
-    projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots, true);
-    projectObj.project.pushNow('editColSetting', projectObj.project.projSetting.moduleName, {
-        projectID: projectObj.project.ID(),
-        main_tree_col: projectObj.project.projSetting.main_tree_col
-    });
 });
 });

+ 1 - 0
web/building_saas/main/js/views/project_info.js

@@ -31,6 +31,7 @@ var projectInfoObj = {
         CommonAjax.post('/pm/api/getProject', {"user_id": userID, "proj_id": scUrlUtil.GetQueryString('project')}, function (data) {
         CommonAjax.post('/pm/api/getProject', {"user_id": userID, "proj_id": scUrlUtil.GetQueryString('project')}, function (data) {
             if (data) {
             if (data) {
                 that.projectInfo = data;
                 that.projectInfo = data;
+                console.log(that.projectInfo);
                 //init decimal
                 //init decimal
                 setDecimal(decimalObj, data.property.decimal);
                 setDecimal(decimalObj, data.property.decimal);
                 billsQuanDecimal.datas = data.property.billsQuantityDecimal || [billsDecimalView.angleDecimal];
                 billsQuanDecimal.datas = data.property.billsQuantityDecimal || [billsDecimalView.angleDecimal];

+ 4 - 0
web/building_saas/main/js/views/project_view.js

@@ -1525,6 +1525,10 @@ $('#property_ok').click(function () {
     }
     }
     // 呈现选项
     // 呈现选项
     projDisplayView.updateChecking(properties);
     projDisplayView.updateChecking(properties);
+    //列设置(独立逻辑,只是通过项目属性确定按钮触发)
+    if(colSettingObj.dataChanged()){
+        colSettingObj.updateColSetting();
+    }
 
 
     if(calcOptions.updateChecking(properties)){
     if(calcOptions.updateChecking(properties)){
         reCalcRations = true;
         reCalcRations = true;

+ 6 - 1
web/building_saas/main/js/views/side_tools.js

@@ -14,7 +14,11 @@ sideResizeEles.nav = null;
 slideResize(sideResizeEles, {min: 250, max: $('#zaojiashu').width()-260}, 'width', function(){
 slideResize(sideResizeEles, {min: 250, max: $('#zaojiashu').width()-260}, 'width', function(){
     projectObj.refreshMainSpread();
     projectObj.refreshMainSpread();
     refreshSubSpread();
     refreshSubSpread();
-    if(sideResizeEles.id === 'stdRationTab'){
+    console.log(sideResizeEles.id);
+    if(sideResizeEles.id === 'stdBillsGuidanceTab'){
+        billsGuidance.refreshWorkBook();
+    }
+    else if(sideResizeEles.id === 'stdRationTab'){
         rationLibObj.refreshSpread();
         rationLibObj.refreshSpread();
     }
     }
     else{
     else{
@@ -75,6 +79,7 @@ var sideToolsObj = {
             tabPanel.hide();
             tabPanel.hide();
         }
         }
         autoFlashHeight();
         autoFlashHeight();
+        billsGuidance.refreshWorkBook();
         billsLibObj.refreshBillsSpread();
         billsLibObj.refreshBillsSpread();
         refreshSubSpread();
         refreshSubSpread();
         billsLibObj.refreshBillsRelaSpread();
         billsLibObj.refreshBillsRelaSpread();

+ 369 - 0
web/building_saas/main/js/views/std_billsGuidance_lib.js

@@ -7,3 +7,372 @@
  * @date 2018/6/11
  * @date 2018/6/11
  * @version
  * @version
  */
  */
+
+const billsGuidance = (function () {
+
+    const libSel = $('#stdBillsGuidanceLibSelect');
+    const bills = {
+        dom: $('#billsGuidance_bills'),
+        workBook: null,
+        cache: [],
+        tree: null,
+        controller: null,
+        treeSetting: {
+            treeCol: 0,
+            emptyRows: 0,
+            headRows: 1,
+            headRowHeight: [40],
+            defaultRowHeight: 21,
+            cols: [{
+                width: 200,
+                readOnly: true,
+                head: {
+                    titleNames: ["项目编码"],
+                    spanCols: [1],
+                    spanRows: [1],
+                    vAlign: [1],
+                    hAlign: [1],
+                    font: ["Arial"]
+                },
+                data: {
+                    field: "code",
+                    vAlign: 1,
+                    hAlign: 0,
+                    font: "Arial"
+                }
+            }, {
+                width: 200,
+                readOnly: true,
+                head: {
+                    titleNames: ["项目名称"],
+                    spanCols: [1],
+                    spanRows: [1],
+                    vAlign: [1],
+                    hAlign: [1],
+                    font: ["Arial"]
+                },
+                data: {
+                    field: "name",
+                    vAlign: 1,
+                    hAlign: 0,
+                    font: "Arial"
+                }
+            }]
+        },
+        headers: [
+            {name: '项目编码', dataCode: 'code', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'},
+            {name: '项目名称', dataCode: 'name', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'}
+        ],
+        events: {
+            SelectionChanging: function (sender, info) {
+                billsInitSel(info.newSelections[0].row);
+            }
+        }
+    };
+    //项目指引类型
+    const itemType = {
+        job: 0,
+        ration: 1
+    };
+    const guideItem = {
+        dom: $('#billsGuidance_items'),
+        workBook: null,
+        tree: null,
+        controller: null,
+        treeSetting: {
+            treeCol: 0,
+            emptyRows: 0,
+            headRows: 1,
+            headRowHeight: [40],
+            defaultRowHeight: 21,
+            cols: [{
+                width: 300,
+                readOnly: false,
+                head: {
+                    titleNames: ["项目指引"],
+                    spanCols: [1],
+                    spanRows: [1],
+                    vAlign: [1],
+                    hAlign: [1],
+                    font: ["Arial"]
+                },
+                data: {
+                    field: "name",
+                    vAlign: 1,
+                    hAlign: 0,
+                    font: "Arial"
+                }
+            },
+            {
+                width: 50,
+                readOnly: false,
+                head: {
+                    titleNames: ["选择"],
+                    spanCols: [1],
+                    spanRows: [1],
+                    vAlign: [1],
+                    hAlign: [1],
+                    font: ["Arial"]
+                },
+                data: {
+                    field: "select",
+                    vAlign: 1,
+                    hAlign: 1,
+                    font: "Arial"
+                }
+            }
+            ]
+        },
+        headers: [
+            {name: '项目指引', dataCode: 'name', width: 300, vAlign: 'center', hAlign: 'left', formatter: '@'},
+            {name: '选择', dataCode: 'name', width: 50, vAlign: 'center', hAlign: 'center', formatter: '@'},
+        ],
+        events: {
+            EditStarting: function (sender, args) {
+                if(guideItem.headers[args.col]['dataCode'] === 'name'){
+                    args.cancel = true;
+                }
+            },
+            ButtonClicked: function (sender, args) {
+                if(args.sheet.isEditing()){
+                    args.sheet.endEdit(true);
+                }
+            },
+        }
+    };
+    const options = {
+        workBook: {
+            tabStripVisible:  false,
+            allowContextMenu: false,
+            allowCopyPasteExcelStyle : false,
+            allowExtendPasteRange: false,
+            allowUserDragDrop : false,
+            allowUserDragFill: false,
+            scrollbarMaxAlign : true
+        },
+        sheet: {
+            protectionOptions: {allowResizeRows: true, allowResizeColumns: true},
+            clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
+        }
+    };
+    //渲染时方法,停止渲染
+    //@param {Object}sheet {Function}func @return {void}
+    function renderSheetFunc(sheet, func){
+        sheet.suspendEvent();
+        sheet.suspendPaint();
+        if(func){
+            func();
+        }
+        sheet.resumeEvent();
+        sheet.resumePaint();
+    }
+    //设置表选项
+    //@param {Object}workBook {Object}opts @return {void}
+    function setOptions (workBook, opts) {
+        for(let opt in opts.workBook){
+            workBook.options[opt] = opts.workBook[opt];
+        }
+        for(let opt in opts.sheet){
+            workBook.getActiveSheet().options[opt] = opts.sheet[opt];
+        }
+    }
+    //建表头
+    //@param {Object}sheet {Array}headers @return {void}
+    function buildHeader(sheet, headers) {
+        let fuc = function () {
+            sheet.setColumnCount(headers.length);
+            sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
+            for(let i = 0, len = headers.length; i < len; i++){
+                sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
+                sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
+                if(headers[i].formatter){
+                    sheet.setFormatter(-1, i, headers[i].formatter);
+                }
+                sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
+                sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
+            }
+        };
+        renderSheetFunc(sheet, fuc);
+    }
+    //表监听事件
+    //@param {Object}workBook @return {void}
+    function bindEvent(workBook, events) {
+        if(Object.keys(events).length === 0){
+            return;
+        }
+        const Events = GC.Spread.Sheets.Events;
+        let sheet = workBook.getActiveSheet();
+        for(let event in events){
+            workBook.bind(Events[event], events[event]);
+        }
+    }
+    //建表
+    //@param {Object}module @return {void}
+    function buildSheet(module) {
+        if(!module.workBook){
+            module.workBook = new GC.Spread.Sheets.Workbook(module.dom[0], {sheetCount: 1});
+            let sheet = module.workBook.getActiveSheet();
+            if(module === bills){
+                //默认初始可控制焦点在清单表中
+                module.workBook.focus();
+                sheet.options.isProtected = true;
+            }
+            if(module === guideItem){
+                sheet.options.isProtected = true;
+                sheet.getRange(-1, 1, -1, 1).locked(false);
+                sheet.getRange(-1, 0, -1, 1).locked(true);
+            }
+            setOptions(module.workBook, options);
+            buildHeader(module.workBook.getActiveSheet(), module.headers);
+            bindEvent(module.workBook, module.events);
+        }
+    }
+    //清空表数据
+    //@param {Object}sheet {Array}headers {Number}rowCount @return {void}
+    function cleanData(sheet, headers, rowCount){
+        renderSheetFunc(sheet, function () {
+            sheet.clear(-1, 0, -1, headers.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
+            if (rowCount > 0) {
+                sheet.setRowCount(rowCount);
+            }
+        });
+    }
+    //初始化各工作表
+    //@param {Array}modules @return {void}
+    function initWorkBooks(modules){
+        for(let module of modules){
+            buildSheet(module);
+        }
+    }
+    //初始化并输出树
+    //@param {Object}module {Object}sheet {Object}treeSetting {Array}datas
+    function initTree(module, sheet, treeSetting, datas){
+        module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
+        module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting);
+        module.tree.loadDatas(datas);
+        module.controller.showTreeData();
+    }
+    //项目指引表焦点控制
+    //@param {Number}row @return {void}
+    function guideItemInitSel(row){
+        let billsNode = bills.tree.selected;
+        let node = null;
+        if(billsNode && billsNode.guidance.tree){
+            node = billsNode.guidance.tree.items[row];
+            if(node){
+                billsNode.guidance.tree.selected = node;
+            }
+        }
+
+
+    }
+    //根据项目指引的类型设置单元格类型,定额类型的项目指引为复选框
+    //@param {Array}nodes @return {void}
+    function setItemCellType(nodes){
+        //设置单元格类型
+        const base = new GC.Spread.Sheets.CellTypes.Base();
+        const checkBox = new GC.Spread.Sheets.CellTypes.CheckBox();
+        const sheet = guideItem.workBook.getActiveSheet();
+        renderSheetFunc(sheet, function(){
+            for(let node of nodes){
+                sheet.setCellType(node.serialNo(), 1, node.data.type === itemType.ration ?  checkBox : base);
+            }
+        });
+    }
+    //清单表焦点控制
+    //@param {Number}row @return {void}
+    function billsInitSel(row){
+        let guideSheet = guideItem.workBook.getActiveSheet();
+        cleanData(guideSheet, guideItem.headers, -1);
+        let node = bills.tree.items[row];
+        if(!node){
+            return;
+        }
+        bills.tree.selected = node;
+        if(!node.guidance.tree){
+            CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: libSel.val(), billsID: node.getID()}, function (rstData) {
+                initTree(node.guidance, guideSheet, guideItem.treeSetting, rstData);
+                setItemCellType(node.guidance.tree.items);
+                //项目指引初始焦点
+                guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
+            });
+        }
+        else{
+            node.guidance.controller.showTreeData();
+            setItemCellType(node.guidance.tree.items);
+            //项目指引初始焦点
+            guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
+        }
+    }
+    //初始选择清单指引库
+    //@param {Number}libID @return {void}
+    function libInitSel(libID){
+        //获取清单
+        CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function(rstData){
+            initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills);
+            //每一棵项目指引树挂在清单节点上
+            for(let node of bills.tree.items){
+                node.guidance = {tree: null, controller: null};
+            }
+            //默认初始节点
+            billsInitSel(0);
+        });
+    }
+    //初始化清单指引库
+    //@param {Array}libDats @return {void}
+    function initLibs(libDatas){
+        libSel.empty();
+        for(let libData of libDatas){
+            let opt = `<option value="${libData.id}">${libData.name}</option>`;
+            libSel.append(opt);
+        }
+        //初始默认选择
+        libInitSel(libSel.select().val());
+    }
+    //初始化视图
+    //@param {void} @return {void}
+    function initViews(){
+        let modules = [bills, guideItem];
+        initWorkBooks(modules);
+
+    }
+    //各按钮监听事件
+    //@return {void}
+    function bindBtn(){
+        //打开清单指引库
+        $('#stdBillsGuidanceTab').click(function () {
+            if(libSel.children().length === 0){
+                initLibs(projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib);
+            }
+        });
+        //更改清单指引库
+        $('#stdBillsGuidanceLibSelect').change(function () {
+            libInitSel($(this).select().val());
+        });
+        //插入定额
+        $('#guidanceInsertRation').click(function () {
+
+        });
+        //插入清单
+        $('#guidanceInsertBills').click(function () {
+
+        });
+    }
+    //刷新表
+    //@return {void}
+    function refreshWorkBook(){
+        if(bills.workBook){
+            bills.workBook.refresh();
+        }
+        if(guideItem.workBook){
+            guideItem.workBook.refresh();
+        }
+    }
+
+    return {initViews, bindBtn, refreshWorkBook};
+})();
+
+$(document).ready(function(){
+    billsGuidance.initViews();
+    billsGuidance.bindBtn();
+});

+ 27 - 27
web/building_saas/pm/html/project-management.html

@@ -274,9 +274,9 @@
             <div class="modal-body">
             <div class="modal-body">
                 <form>
                 <form>
                     <div>
                     <div>
-                        <label>建设项目</label>
                         <div class="input-group">
                         <div class="input-group">
-                            <input type="text" class="form-control" placeholder="输入建设项目名称" id="poj-name" autocomplete="off">
+                            <label style="margin-top: 8px;">建设项目</label>
+                            <input style="margin-left: 5px; border-radius: .25rem;" type="text" class="form-control" placeholder="输入建设项目名称" id="poj-name" autocomplete="off">
                               <span class="input-group-btn">
                               <span class="input-group-btn">
                                 <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"></button>
                                 <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"></button>
                                 <div class="dropdown-menu dropdown-menu-right" style="width:468px" id="poj-name-list">
                                 <div class="dropdown-menu dropdown-menu-right" style="width:468px" id="poj-name-list">
@@ -286,12 +286,12 @@
                                 </div>
                                 </div>
                               </span>
                               </span>
                         </div>
                         </div>
-                        <span class="form-text text-info" id="poj-name-info" style="display: none;">新建 “汽车生产车间5”</span>
                     </div>
                     </div>
-                    <div>
-                        <label>单项工程</label>
+                    <span class="form-text text-info" id="poj-name-info" style="display: none;">新建 “汽车生产车间5”</span>
+                    <div style="margin-top: 15px;">
                         <div class="input-group">
                         <div class="input-group">
-                            <input type="text" class="form-control" placeholder="输入单项工程名称" id="eng-name" autocomplete="off">
+                            <label style="margin-top: 8px;">单项工程</label>
+                            <input style="margin-left: 5px; border-radius: .25rem;" type="text" class="form-control" placeholder="输入单项工程名称" id="eng-name" autocomplete="off">
                               <span class="input-group-btn">
                               <span class="input-group-btn">
                                 <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"></button>
                                 <button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"></button>
                                 <div class="dropdown-menu dropdown-menu-right" style="width:468px" id="eng-name-list">
                                 <div class="dropdown-menu dropdown-menu-right" style="width:468px" id="eng-name-list">
@@ -299,25 +299,25 @@
                                     <button class="dropdown-item" type="button">左4号生产车间</button>
                                     <button class="dropdown-item" type="button">左4号生产车间</button>
                                 </div>                              </span>
                                 </div>                              </span>
                         </div>
                         </div>
-                        <span class="form-text text-info" id="eng-name-info" style="display: none;">新建 “左2号生产车间2”</span>
                     </div>
                     </div>
+                    <span class="form-text text-info" id="eng-name-info" style="display: none;">新建 “左2号生产车间2”</span>
 
 
-                    <div>
-                        <label>单位工程</label>
-                        <input type="text" class="form-control" placeholder="输入单位工程名称" id="tender-name" autocomplete="off">
-                        <span class="form-text text-danger" id="tender-name-info" style="display: none;">已存在 “建筑工程1”</span>
+                    <div style="margin-top: 15px;" class="input-group">
+                        <label style="margin-top: 8px;">单位工程</label>
+                        <input style="margin-left: 5px; border-radius: .25rem;" type="text" class="form-control" placeholder="输入单位工程名称" id="tender-name" autocomplete="off">
                     </div>
                     </div>
-                    <div>
-                        <label>单价文件</label>
-                        <select class="form-control" id="unit-price"><option value="">新建单价文件</option></select>
+                    <span class="form-text text-danger" id="tender-name-info" style="display: none;">已存在 “建筑工程1”</span>
+                    <div style="margin-top: 15px;" class="input-group">
+                        <label style="margin-top: 8px;">单价文件</label>
+                        <select style="margin-left: 5px; border-radius: .25rem;" class="form-control" id="unit-price"><option value="">新建单价文件</option></select>
                     </div>
                     </div>
-                    <div>
-                        <label>费率文件</label>
-                        <select class="form-control" id="tender-fee-rate"><option value="">新建费率文件</option></select>
+                    <div style="margin-top: 15px;" class="input-group">
+                        <label style="margin-top: 8px;">费率文件</label>
+                        <select style="margin-left: 5px; border-radius: .25rem;" class="form-control" id="tender-fee-rate"><option value="">新建费率文件</option></select>
                     </div>
                     </div>
-                    <div>
+                    <div style="margin-top: 15px;" class="input-group">
                         <label>计价方式</label>
                         <label>计价方式</label>
-                        <div class="row">
+                        <div style="margin-left: 5px; border-radius: .25rem;"  class="row">
                             <label class="custom-control custom-radio" style="margin-left: 20px;">
                             <label class="custom-control custom-radio" style="margin-left: 20px;">
                                 <input name="valuation_type" id="radioBill" value="bill" type="radio" class="custom-control-input">
                                 <input name="valuation_type" id="radioBill" value="bill" type="radio" class="custom-control-input">
                                 <label class="custom-control-label" for="radioBill">清单计价</label>
                                 <label class="custom-control-label" for="radioBill">清单计价</label>
@@ -328,16 +328,16 @@
                             </label>-->
                             </label>-->
                         </div>
                         </div>
                     </div>
                     </div>
-                    <div>
-                        <label>计价规则</label>
-                        <select class="form-control" id="valuation"><option value="">请选择计价规则</option></select>
-                        <span class="form-text text-danger" id="valuation-info" style="display: none;">请选择计价规则</span>
+                    <div style="margin-top: 15px;" class="input-group">
+                        <label style="margin-top: 8px;">计价规则</label>
+                        <select style="margin-left: 5px; border-radius: .25rem;" class="form-control" id="valuation"><option value="">请选择计价规则</option></select>
                     </div>
                     </div>
-                    <div>
-                        <label>工程专业</label>
-                        <select class="form-control" id="tender-engineering"><option value="">请选择对应的工程专业</option></select>
-                        <span class="form-text text-danger" id="engineering-info" style="display: none;">请选择工程专业</span>
+                    <span class="form-text text-danger" id="valuation-info" style="display: none;">请选择计价规则</span>
+                    <div style="margin-top: 15px;" class="input-group">
+                        <label style="margin-top: 8px;">工程专业</label>
+                        <select style="margin-left: 5px; border-radius: .25rem;" class="form-control" id="tender-engineering"><option value="">请选择对应的工程专业</option></select>
                     </div>
                     </div>
+                    <span class="form-text text-danger" id="engineering-info" style="display: none;">请选择工程专业</span>
                 </form>
                 </form>
             </div>
             </div>
             <div class="modal-footer">
             <div class="modal-footer">

+ 2 - 2
web/building_saas/pm/js/pm_gc.js

@@ -633,10 +633,10 @@ function v_getMoBody(type, oprNode, nodes){
             html += ('</p>');
             html += ('</p>');
         }
         }
 
 
-        html += ('<p>点“确定”按钮,确认从回收站中恢复</p>');
+        html += ('<p>点“确定”按钮,确认从回收站中恢复</p>');
     }
     }
     else{
     else{
-        html += ('<p>点“确定”按钮,确认彻底删除数据</p>');
+        html += ('<p>点“确定”按钮,确认彻底删除数据</p>');
     }
     }
     return html;
     return html;
 }
 }

+ 2 - 0
web/building_saas/pm/js/pm_newMain.js

@@ -1715,6 +1715,7 @@ function setProjOptions(projs, selected){
                 $("#poj-name").val(projs[i].data.name);
                 $("#poj-name").val(projs[i].data.name);
                 setFileOptions(projs[i].data.ID);
                 setFileOptions(projs[i].data.ID);
                 setEngOptions(projs[i].data.ID);
                 setEngOptions(projs[i].data.ID);
+                $('#poj-name-info').hide();
             });
             });
             $("#poj-name-list").append(proj);
             $("#poj-name-list").append(proj);
         }
         }
@@ -1757,6 +1758,7 @@ function setEngOptions(projID){
                 eng.attr("type", "button");
                 eng.attr("type", "button");
                 eng.click(function () {
                 eng.click(function () {
                     $("#eng-name").val(engineerings[i].data.name);
                     $("#eng-name").val(engineerings[i].data.name);
+                    $('#eng-name-info').hide();
                 });
                 });
                 $("#eng-name-list").append(eng);
                 $("#eng-name-list").append(eng);
             }
             }