浏览代码

Merge branch '1.0.0_online' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost into 1.0.0_online

zhangweicheng 6 年之前
父节点
当前提交
5932245f2f

+ 1 - 0
config/gulpConfig.js

@@ -153,6 +153,7 @@ module.exports = {
         'web/building_saas/main/js/views/zmhs_view.js',
         'web/building_saas/main/js/views/mbzm_view.js',
         'web/building_saas/main/js/views/tender_price_view.js',
+        'web/building_saas/main/js/views/billsElf.js',
         'web/building_saas/main/js/views/sub_view.js',
         'web/building_saas/main/js/views/fee_rate_view.js',
         'web/building_saas/main/js/views/quantity_edit_view.js',

+ 1 - 0
modules/all_models/ration.js

@@ -52,6 +52,7 @@ let rationSchema = new Schema({
     isSubcontract: Boolean,                     // 是否分包
     installationKey:String,                   //用来记录安装增加费的关联字段
     // 定额特有属性:
+    stdID: Number,                            //来自的标准定额ID
     libID: Number,
     maskName: String,
     caption: String,

+ 2 - 0
modules/main/facade/ration_facade.js

@@ -122,6 +122,7 @@ async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入
         newData.caption = std.caption;
         newData.unit = std.unit;
         newData.libID = std.rationRepId;
+        newData.stdID = std.ID;
         newData.content = std.jobContent;
         newData.annotation = std.annotation;
         if (std.chapter) {
@@ -480,6 +481,7 @@ async function  updateRation(std,defaultLibID,rationID,billsItemID,projectID,cal
     ration.unit = std.unit;
     if (std.type === 'std') {
         ration.libID = std.rationRepId;
+        ration.stdID = std.ID;
     }
     ration.content = std.jobContent;
     ration.adjustState = '';

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

@@ -37,6 +37,17 @@ class BillsGuideLibController extends BaseController{
             callback(req, res, 1, err, null);
         }
     }
+    //根据清单编号获取项目指引
+    async getItemsByCode(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let items = await billsGuidanceFacade.getItemsByCode(data.guidanceLibID, data.code);
+            callback(req, res, 0, '', items);
+        }
+        catch(err){
+            callback(req, res, 1, err, null);
+        }
+    }
 
     async updateItems(req, res){
         try{

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

@@ -23,6 +23,7 @@ const _ = require('lodash');
 module.exports = {
     getLibWithBills,
     getItemsBybills,
+    getItemsByCode,
 };
 
 async function getBillsGuideLibs(findData) {
@@ -133,4 +134,18 @@ async function getItemsBybills(guidanceLibID, billsID){
         await billsGuideItemsModel.bulkWrite(bulkArr);
     }
     return items;
+}
+
+async function getItemsByCode(guidanceLibID, code){
+    let rst = [];
+    let guidanceLib = await billsGuideLibModel.findOne({ID: guidanceLibID});
+    if (!guidanceLib) {
+        return rst;
+    }
+    let stdBills = await stdBillsModel.findOne({code: code, billsLibId: guidanceLib.billsLibId});
+    if (!stdBills) {
+        return rst;
+    }
+    let items = await getItemsBybills(guidanceLibID, stdBills.ID);
+    return items;
 }

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

@@ -15,6 +15,7 @@ const billsGuideLibController = new BillsGuideLibController();
 module.exports = function (app) {
   router.post('/getLibWithBills', billsGuideLibController.getLibWithBills);
   router.post('/getItemsByBills', billsGuideLibController.getItemsByBills);
+  router.post('/getItemsByCode', billsGuideLibController.getItemsByCode);
 
   app.use('/billsGuidance/api', router);
 };

二进制
web/building_saas/css/animated_favicon1.gif


二进制
web/building_saas/css/favicon.ico


二进制
web/building_saas/css/logo.png


+ 1 - 1
web/building_saas/js/global.js

@@ -12,7 +12,7 @@ function autoFlashHeight(){
     $(".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-$('#stdSectionRations').height()-5);
-    $(".main-data-side-zb").height(($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightZ) - $('#billsGuidance_items').height() - $('#zyTools').height() - 12);
+    $(".main-data-side-zb").height(($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightZ));
     /*$(".main-data-side-zi").height($(window).height()-headerHeight-toolsbarHeight- toolsBarHeightZ - $(".main-data-side-zb").height());*/
     $('.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);

+ 46 - 13
web/building_saas/main/html/main.html

@@ -88,7 +88,7 @@
                     <span class="btn btn-light btn-sm" id="importSpan" data-toggle="tooltip" data-original-title="导入" data-placement="bottom">
                         <a class="dropdown-toggle" href="#" data-toggle="dropdown"><i class="fa fa-cloud-upload"></i></a>
                         <div class="dropdown-menu">
-                            <a id="uploadLj" class="dropdown-item" href="#import" data-toggle="modal" data-target="#import">导入09表Excel清单</a>
+                            <a id="uploadLj" class="dropdown-item" href="#import" data-toggle="modal" data-target="#import">导入表Excel清单</a>
                             <a id="uploadGld" class="dropdown-item" href="#import" data-toggle="modal" data-target="#import">导入广联达算量Excel清单</a>
                         </div>
                     </span>
@@ -98,7 +98,30 @@
                     <a href="javascript:void(0)"  class="btn btn-light btn-sm" id="downLevel" data-toggle="tooltip" data-placement="bottom" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
                       <a href="javascript:void(0)" class="btn btn-light btn-sm" id="upMove" data-toggle="tooltip" data-placement="bottom" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
                       <a href="javascript:void(0)" class="btn btn-light btn-sm" id="downMove" data-toggle="tooltip" data-placement="bottom" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
-                    <span class="btn btn-light btn-sm">
+                      <div class="btn-group ml-2">
+                          <a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">更多</a>
+                          <div class="dropdown-menu dropright">
+                              <a href="" data-toggle="dropdown" class="dropdown-item dropdown-toggle"><i class="fa fa-list-ol"></i> 显示至...</a>
+                              <div class="dropdown-menu dropdown-menu-left" style="min-width: 6.5rem">
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);" id="displayDXFY">大项费用</a>
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);"  id="displayFB1">一级分部</a>
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);" id="displayFB2">二级分部</a>
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);" id="displayFB3">三级分部</a>
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);"  id="displayFB4">四级分部</a>
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);"  id="displayFX">分项</a>
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);" id="displayZM">子目</a>
+                                  <a class="dropdown-item btn-sm" href="javascript:void(0);"  id="displayZD">最底层</a>
+                              </div>
+                              <a href="javascript:void(0);" id="ZLFB_btn" class="dropdown-item" data-placement="bottom"><i class="fa fa-retweet" aria-hidden="true"></i> 整理分部</a>
+                              <% if (projectData.property.lockBills == true) { %>
+                              <a href="javascript:void(0)"  class="dropdown-item" name="lockBills"> <i class="fa fa-unlock-alt" aria-hidden="true"></i> 解锁清单</a>
+                              <% } else { %>
+                              <a href="javascript:void(0)"  class="dropdown-item" name="lockBills"> <i class="fa fa-lock" aria-hidden="true"></i> 锁定清单</a>
+                              <% } %>
+                              <a id="switchTznr" href="javascript:void(0);"  class="dropdown-item"><i class="fa fa-eye" aria-hidden="true"></i> 显示特征</a>
+                          </div>
+                      </div>
+                 <!--   <span class="btn btn-light btn-sm">
                       <a href="" data-toggle="dropdown"><span data-placement="bottom"><i class="fa fa-list-ol"></i></span> 显示至...</a>
                       <div class="dropdown-menu dropdown-menu-left" style="min-width: 6.5rem">
                       <a class="dropdown-item" href="javascript:void(0);" id="displayDXFY">大项费用</a>
@@ -117,7 +140,7 @@
                       <% } else { %>
                       <a href="javascript:void(0)"  class="btn btn-light btn-sm" name="lockBills"> <i class="fa fa-lock" aria-hidden="true"></i> 锁定清单</a>
                       <% } %>
-                      <a id="switchTznr" href="javascript:void(0);"  class="btn btn-light btn-sm"><i class="fa fa-eye" aria-hidden="true"></i> 显示特征</a>
+                      <a id="switchTznr" href="javascript:void(0);"  class="btn btn-light btn-sm"><i class="fa fa-eye" aria-hidden="true"></i> 显示特征</a>-->
                   </div>
                   <div class="side-tabs">
                       <ul class="nav nav-tabs" role="tablist">
@@ -125,13 +148,13 @@
                               <a class="nav-link px-3 right-nav-link"  href="javascript:void(0)" id = 'locateTab' relaPanel="#locate">查找定位</a>
                           </li>-->
                           <li class="nav-item">
-                              <a class="nav-link px-3 right-nav-link" href="javascript:void(0)" id = 'stdBillsGuidanceTab' relaPanel="#zy">清单指引</a>
+                              <a class="nav-link px-1 right-nav-link" href="javascript:void(0)" id = 'stdBillsGuidanceTab' relaPanel="#zy">清单规则</a>
                           </li>
                          <!-- <li class="nav-item">
                               <a class="nav-link px-3" href="javascript:void(0)" id = 'stdBillsTab' relaPanel="#qd">清单规则</a>
                           </li>-->
                           <li class="nav-item" id = "li_stdRationTab">
-                              <a class="nav-link px-3 right-nav-link" href="javascript:void(0)" id="stdRationTab" relaPanel="#de">定额库</a>
+                              <a class="nav-link px-1 right-nav-link" href="javascript:void(0)" id="stdRationTab" relaPanel="#de">定额库</a>
                           </li>
                           <li class="nav-item dropdown">
                               <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">更多</a>
@@ -154,12 +177,15 @@
                   <div class="row">
                       <!--col-lg-12 p-0-->
                       <div class="main-content" style="width: 100%; display: inline-block" id="main">
-                          <div class="top-content">
+                          <div class="top-content" id="top_div" style="overflow:hidden;">
                               <div class="main-data-top" id="billsSpread"></div>
                           </div>
                           <div class="resize"></div>
                           <div class="bottom-content" id="bottom_div">
                               <ul class="nav nav-tabs" role="tablist">
+                                  <li class="nav-item" id="QDJL_div">
+                                      <a class="nav-link sub-item" id="linkQDJL" data-toggle="tab" href="#subSpread" role="tab">清单精灵</a>
+                                  </li>
                                   <li class="nav-item" id="GLJ_div">
                                       <a class="nav-link sub-item active" id="linkGLJ" data-toggle="tab" href="#subSpread" role="tab">人材机</a>
                                   </li>
@@ -352,6 +378,18 @@
                                               </div>
                                           </div>
                                       </div>
+                                      <div class="container-fluid" id="qdjl" role="tabpanel">
+                                          <div class="row p-0" style="background: #efefef">
+                                              <div class="col-10 p-0">
+                                                  <div class="main-data-bottom ovf-hidden" id="elfItems">
+                                                  </div>
+                                              </div>
+                                              <div class="col-2 p-1">
+                                                  <p class="mt-3"><a id="elfInsertRation" href="javascript:void(0);" class="btn btn-sm btn-primary">插入定额</a></p>
+                                                  <p><a id="elfInsertSingle" href="javascript:void(0)" class="btn btn-sm btn-primary">插入单条</a></p>
+                                              </div>
+                                          </div>
+                                      </div>
                                   </div>
                               </div>
                           </div>
@@ -457,7 +495,7 @@
                                       <div class="main-data-side-zb" id="billsGuidance_bills">
                                       </div>
                                   </div>
-                                  <div class="resize" id="zyResize" style="background: #F1F1F1"></div>
+                             <!--     <div class="resize" id="zyResize" style="background: #F1F1F1"></div>
                                   <div class="p-0 row" id="zyTools" style="background: #F1F1F1">
                                       <div class="col">
                                           <button id="guidanceInsertBills" class="btn btn-primary btn-sm" style="height: 25px; line-height: 1px;" type="button">插入清单</button>
@@ -467,12 +505,6 @@
                                   </div>
                                   <div class="bottom-content">
                                       <div class="main-data-side-zi" id="billsGuidance_items"></div>
-                                  </div>
-                                  <!--<div class="row" style="margin-left: 1px;">
-                                      <div id="billsGuidance_bills" class="main-data-side-zb" style="width: 53%; float: left; margin: 0; padding: 0;">
-                                      </div>
-                                      <div id="billsGuidance_items" class="main-data-side-zi" style="width: 46%; float: left; margin: 0; padding: 0;">
-                                      </div>
                                   </div>-->
                               </div>
                               <!--清单规则-->
@@ -1880,6 +1912,7 @@
     <script type="text/javascript" src="/web/building_saas/main/js/views/zmhs_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/mbzm_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/tender_price_view.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/views/billsElf.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/sub_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/fee_rate_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/quantity_edit_view.js"></script>

+ 768 - 0
web/building_saas/main/js/views/billsElf.js

@@ -0,0 +1,768 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/11/25
+ * @version
+ */
+
+/*
+* 造价书下方清单精灵
+* */
+//选项单选多选状态(按住alt为多选) 单选:0 多选:1
+let billsGuidanceSelMode = 0;
+
+const BillsElf = (function() {
+    //清单精灵树挂载的地方,selected:当前选中的清单,mapping:以前九位清单编码为索引, 'xxx' : {elf: {datas, tree, controller}}
+    let bills = {selected: null, mapping: {}};
+    const itemType = {
+        job: 0,
+        ration: 1
+    };
+    const elfItem = {
+        dom: $('#elfItems'),
+        workBook: null,
+        tree: null,
+        controller: null,
+        treeSetting: {
+            treeCol: 0,
+            emptyRows: 0,
+            headRows: 1,
+            headRowHeight: [40],
+            defaultRowHeight: 21,
+            cols: [
+                {
+                    width: 250,
+                    readOnly: true,
+                    head: {
+                        titleNames: ["施工工序"],
+                        spanCols: [1],
+                        spanRows: [1],
+                        vAlign: [1],
+                        hAlign: [1],
+                        font: ["Arial"]
+                    },
+                    data: {
+                        field: "name",
+                        vAlign: 1,
+                        hAlign: 0,
+                        font: "Arial"
+                    }
+                },
+                {
+                    width: 250,
+                    readOnly: false,
+                    head: {
+                        titleNames: ["选项"],
+                        spanCols: [1],
+                        spanRows: [1],
+                        vAlign: [1],
+                        hAlign: [1],
+                        font: ["Arial"]
+                    },
+                    data: {
+                        field: "options",
+                        vAlign: 1,
+                        hAlign: 0,
+                        font: "Arial"
+                    }
+                }
+            ]
+        },
+        headers: [
+            {name: '施工工序', dataCode: 'name', width: 250, rateWidth: 0.5, vAlign: 'center', hAlign: 'center', formatter: '@'},
+            {name: '选项', dataCode: 'options', width: 250, rateWidth: 0.5,  vAlign: 'center', hAlign: 'left', formatter: '@'},
+        ],
+        rowHeaderWidth:25,
+        events: {
+            SelectionChanging: function (sender, info) {
+                elfItemInitSel(info.newSelections[0].row);
+            },
+            CellClick: function (sender, args) {
+                if(elfItem.headers[args.col]['dataCode'] === 'options' && args.sheetArea === 3){
+                    if(!args.sheet.getCell(args.row, args.col).locked() && !args.sheet.isEditing()){
+                        args.sheet.startEdit();
+                    }
+                }
+            },
+            ClipboardPasting: function (sender, info) {
+                info.cancel = 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, 30, GC.Spread.Sheets.SheetArea.colHeader);
+            sheet.setColumnWidth(0, sheet.getParent() === bills.workBook ? 15 : 25, GC.Spread.Sheets.SheetArea.rowHeader);
+            if(sheet.getParent() === elfItem.workBook || sheet.getParent() === guideItem.workBook){
+                sheet.setRowHeight(0, 20, 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;
+        for(let event in events){
+            workBook.bind(Events[event], events[event]);
+        }
+    }
+    //根据宽度比例设置列宽
+    //@param {Object}workBook {Number}workBookWidth {Array}headers @return {void}
+    function setColumnWidthByRate() {
+        let workBook = elfItem.workBook,
+            workBookWidth = ($(window).width() - $('.main').find('.main-nav').width() - $('.main-side').width()) * 5 / 6,
+            headers = elfItem.headers;
+        if(workBook){
+            workBookWidth -= 60;
+            const sheet = workBook.getActiveSheet();
+            sheet.suspendEvent();
+            sheet.suspendPaint();
+            for(let col = 0; col < headers.length; col++){
+                if(headers[col]['rateWidth'] !== undefined && headers[col]['rateWidth'] !== null && headers[col]['rateWidth'] !== ''){
+                    let width = workBookWidth * headers[col]['rateWidth'];
+                    if(headers[col]['dataCode'] === 'options'){
+                        width = width;
+                    }
+                    sheet.setColumnWidth(col, width, GC.Spread.Sheets.SheetArea.colHeader)
+                }
+                else {
+                    if(headers[col]['headerWidth'] !== undefined && headers[col]['headerWidth'] !== null && headers[col]['headerWidth'] !== ''){
+                        sheet.setColumnWidth(col, headers[col]['headerWidth'], GC.Spread.Sheets.SheetArea.colHeader)
+                    }
+                }
+            }
+            sheet.resumeEvent();
+            sheet.resumePaint();
+        }
+    }
+    //建表
+    //@param {Object}module @return {void}
+    function buildSheet() {
+        if(!elfItem.workBook){
+            elfItem.workBook = new GC.Spread.Sheets.Workbook(elfItem.dom[0], {sheetCount: 1});
+            sheetCommonObj.spreadDefaultStyle(elfItem.workBook);
+            let sheet = elfItem.workBook.getActiveSheet();
+            sheet.options.isProtected = true;
+            sheet.getRange(-1, 0, -1, 1).locked(true);
+            sheet.getRange(-1, 1, -1, 1).locked(false);
+            if(elfItem.rowHeaderWidth) {
+                sheet.setColumnWidth(0, elfItem.rowHeaderWidth, GC.Spread.Sheets.SheetArea.rowHeader);
+            }
+            setOptions(elfItem.workBook, options);
+            buildHeader(elfItem.workBook.getActiveSheet(), elfItem.headers);
+            setColumnWidthByRate(elfItem.workBook, $('#elfItems').width(), elfItem.headers);
+            bindEvent(elfItem.workBook, elfItem.events);
+        }
+    }
+    //刷新表
+    //@return {void}
+    function refreshWorkBook(){
+        if (elfItem.workBook) {
+            elfItem.workBook.refresh();
+        }
+    }
+    //清空表数据
+    //@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);
+            } else {
+                sheet.setRowCount(0);
+            }
+        });
+    }
+    //初始化并输出树
+    //@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, false);
+        module.tree.loadDatas(datas);
+        module.controller.showTreeData();
+    }
+    //清单精灵表焦点控制
+    //@param {Number}row @return {void}
+    function elfItemInitSel(row){
+        let billsNode = bills.selected;
+        let node = null;
+        if(billsNode && billsNode.elf.tree){
+            node = billsNode.elf.tree.items[row];
+            if(node){
+                billsNode.elf.tree.selected = node;
+            }
+        }
+        refreshInsertSingle();
+    }
+    //清单焦点变换-清单精灵操作,获取清单前九位编码的标准清单清单精灵选项
+    //@param {String}code @return {void}
+    function billsSelElf(code) {
+        let elfSheet = elfItem.workBook.getActiveSheet();
+        cleanData(elfSheet, elfItem.headers, -1);
+        if (!code || code === '') {
+            $('#elfInsertRation').addClass('disabled');
+            $('#elfInsertSingle').addClass('disabled');
+            return;
+        }
+        let nineCode = code.substr(0, 9);
+        //查看此清单映射是否存在此编码映射数据,不存在,则新建映射
+        if (!bills.mapping[nineCode]) {
+            bills.mapping[nineCode] = {elf: {datas: [], tree: null, controller: null}};
+        }
+        let node = bills.mapping[nineCode];
+        bills.selected = node;
+        if(!node.elf.tree){
+            let guidanceLibID;
+            if (projectInfoObj.projectInfo.engineeringInfo && projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib) {
+                guidanceLibID = projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib[0] ? projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib[0].id : null;
+            }
+            CommonAjax.post('/billsGuidance/api/getItemsByCode', {guidanceLibID: guidanceLibID, code: nineCode}, function (rstData) {
+                //定额数据删除编号信息
+                for(let rData of rstData){
+                    if(rData.type === itemType.ration){
+                        let nameArr = rData.name.split(' ');
+                        if(nameArr.length > 0){
+                            nameArr.splice(0, 1);
+                            rData.name = nameArr.join(' ');
+                        }
+                    }
+                }
+                node.elf.datas = rstData;
+                //第一层节点数据
+                let firstLevelDatas = _.filter(rstData, function (data) {
+                    return data.ParentID == -1;
+                });
+                //第一层初始数据的选项显示
+                for(let fData of firstLevelDatas){
+                    let options = getOptions(fData, rstData);
+                    fData.options = options.length > 0 ? options[0].name : '';
+                    //下挂的选项
+                    fData.optionsData = options && options.length > 0 ? _.cloneDeep(options) : [];
+                    fData.optionChecked = options && options.length > 0 ? [_.cloneDeep(options[0])] : [];
+                }
+                renderSheetFunc(elfSheet, function () {
+                    initTree(node.elf, elfSheet, elfItem.treeSetting, firstLevelDatas);
+                    //初始选择选项
+                    let initOptsOpr = [];
+                    for(let elfNode of node.elf.tree.items){
+                        if(elfNode.data.optionsData.length > 0){
+                            initOptsOpr.push({node: elfNode, data: elfNode.data.optionsData[0]});
+                        }
+                    }
+                    for(let opr of initOptsOpr){
+                        insertNodeByData(opr.node, opr.data);
+                    }
+                    TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.elf.tree.items, false);
+                    setOptionsCellType(node.elf.tree.items);
+                    //项目指引初始焦点
+                    elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0);
+                    refreshInsertRation();
+                });
+            });
+        }
+        else{
+            renderSheetFunc(elfSheet, function () {
+                node.elf.controller.showTreeData();
+                setOptionsCellType(node.elf.tree.items);
+                //项目指引初始焦点
+                elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0);
+                refreshInsertRation();
+            });
+        }
+    }
+    //获取选项的深度
+    //@param {Object}opt {Array}options(当前清单所有选项) @return {Array}
+    function getOptionDepth(opt, options) {
+        let parent = _.find(options, {ID: opt.ParentID});
+        let depth = 0;
+        while (parent){
+            depth++;
+            parent = _.find(options, {ID: parent.ParentID});
+        }
+        return depth;
+    }
+    //获取施工工序含有的选项(即当前施工工序的子项),获取的顺序按照NextSiblingID排序
+    //@param {Object}process {Array}datas @return {Array}
+    function getOptions(process, datas) {
+        let rst = [];
+        if(!process || !process.ID){
+            return [];
+        }
+        let options = _.filter(datas, function (data) {
+            return data.ParentID == process.ID;
+        });
+        if(options.length === 0){
+            return [];
+        }
+        //根据NextSiblingID排序
+        let IDMapping = {};
+        for(let opt of options){
+            IDMapping[opt.ID] = {self: opt, next: null, pre: null};
+        }
+        for(let opt of options){
+            let next = IDMapping[opt.NextSiblingID] ? IDMapping[opt.NextSiblingID] : null;
+            if(next){
+                next.pre = IDMapping[opt.ID];
+                IDMapping[opt.ID]['next'] = next;
+            }
+        }
+        let first = null,
+            rank = 0;
+        for(let ID in IDMapping){
+            let obj = IDMapping[ID];
+            if(!obj.pre){
+                first = obj;
+            }
+        }
+        while(first){
+            rank++;
+            first.self.rank = rank;
+            rst.push(first.self);
+            first = first.next;
+        }
+
+        return rst;
+    }
+    //设置清单精灵选项单元格
+    //@param {Array}nodes @return {void}
+    function setOptionsCellType(nodes) {
+        let elfSheet = elfItem.workBook.getActiveSheet();
+        for(let node of nodes){
+            if(node.data.optionsData && node.data.optionsData.length > 0){
+                elfSheet.getCell(node.serialNo(), 1).locked(false).cellType(getOptionsCellType());
+            }
+            else {
+                elfSheet.getCell(node.serialNo(), 1).locked(true).cellType(new GC.Spread.Sheets.CellTypes.Base());
+            }
+        }
+    }
+    //递归插入节点:原始项目指引数据奇数层为需要插入的节点,偶数层为下拉选项
+    //@param {Object}node(当前操作的节点) {Object}data(选项) @return {void}
+    function insertNodeByData(node, data) {
+        let elfSheet = elfItem.workBook.getActiveSheet();
+        let sameDepthNodes = node.children;
+        let insertNextSiblingID = -1,
+            insertParentID = node.data.ID;
+        //当前操作节点的选项
+        let nodeOpts = getOptions(node.data, bills.selected.elf.datas);
+        let subOpts = getOptions(data, bills.selected.elf.datas);
+        let dataDepth = getOptionDepth(data, bills.selected.elf.datas);
+        if(subOpts.length >0 && subOpts[0].type !== itemType.ration){
+            if((dataDepth + 1) % 2 === 0){
+                //排序后的数据
+                let dataWithRank = _.find(nodeOpts, {ID: data.ID});
+                //确定插入位置
+                for(let subOpt of subOpts){
+                    for(let subNode of sameDepthNodes){
+                        //同层节点原本选项数据
+                        let subNodeOptData = _.find(bills.selected.elf.datas, {ID: subNode.data.ID});
+                        //同层节点原本父选项数据
+                        let subNodeOptParent = _.find(bills.selected.elf.datas, {ID: subNodeOptData.ParentID});
+                        let subNodeOptParentWithRank = _.find(nodeOpts, {ID: subNodeOptParent.ID});
+                        //父项顺序决定插入位置
+                        if(dataWithRank.rank < subNodeOptParentWithRank.rank){
+                            insertNextSiblingID = subNode.data.ID;
+                            break;
+                        }
+                        //父项顺序相同,根据子项顺序决定插入位置
+                        else if(dataWithRank.rank = subNodeOptParentWithRank.rank){
+                            if(subOpt.rank < subNode.data.rank){
+                                insertNextSiblingID = subNode.data.ID;
+                                break;
+                            }
+                        }
+                    }
+                    let sub2Opts = getOptions(subOpt, bills.selected.elf.datas);
+                    subOpt.options = sub2Opts.length > 0 ? sub2Opts[0].name : '';
+                    let cloneOpt = _.cloneDeep(subOpt);//不改变原本的数据,比如ParentID
+                    cloneOpt.optionChecked = sub2Opts.length > 0 ? [_.cloneDeep(sub2Opts[0])] : [];
+                    cloneOpt.optionsData = sub2Opts.length > 0 ? _.cloneDeep(sub2Opts) : [];
+                    let newNode = node.tree.insertByData(cloneOpt, insertParentID, insertNextSiblingID);
+                    elfSheet.addRows(newNode.serialNo(), 1);
+                    node.tree.selected = newNode;
+                    elfSheet.setSelection(newNode.serialNo(), elfSheet.getSelections()[0].col, 1, 1);
+                    if(sub2Opts.length > 0 && sub2Opts[0].type !== itemType.ration){
+                        insertNodeByData(newNode, sub2Opts[0]);
+                    }
+                }
+            }
+            else {
+                insertNodeByData(node, subOpts[0]);
+            }
+        }
+    }
+    //获取选项下拉多选单元格
+    //@param {void} @return {void}
+    function getOptionsCellType() {
+        let me = this;
+        let elfSheet= elfItem.workBook.getActiveSheet();
+        function OptionsCellType() {
+            this.isEscKey=false;
+            this.displayText='';
+        }
+        function setOptionsDiv($editor, node, cellRect, cellStyle, top) {
+            if(!node){
+                return '';
+            }
+            let height = cellRect.height;
+            let options = getOptions(node.data, bills.selected.elf.datas);
+            top = options.length - 2 > 4 ? top - 4 * height : top - (options.length - 2) * height - 5;
+            let $editInput = $(`<div style="height: ${height}px; background: ${cellStyle.backColor};overflow: hidden; white-space: nowrap; text-overflow: ellipsis">${node.data.options}</div>`),
+                $optDiv = $(`<div style="position: fixed; width: ${cellRect.width}px; top: ${top}px;background: ${cellStyle.backColor};border: 1px solid; overflow: auto; height: ${options.length > 6 ? height*6 : height*options.length+5}px; font-size: 0.9rem;"></div>`);
+            for(let opt of options){
+                let $opt = $(`<div title="${opt.name ? opt.name : ''}" class="elf-options" style="height: ${height}px;overflow: hidden; white-space: nowrap; text-overflow: ellipsis"></div>`),
+                    $optInput = $(`<input rank="${opt.rank}" value="${opt.ID}" style="margin-left: 5px; vertical-align: middle" type="checkbox" 
+                    ${node.data.optionChecked && _.find(node.data.optionChecked, {ID: opt.ID}) ? 'checked' : ''}>`);
+                $opt.text(`${opt.name ? opt.name : ''}`);
+                $opt.prepend($optInput);
+                $optDiv.append($opt);
+                //选项复选框点击监听
+                $opt.click(function () {
+                    //单选
+                    if(billsGuidanceSelMode === 0){
+                        let $allInput = $optDiv.find('input');
+                        for(let input of $allInput){
+                            $(input).prop('checked', false);
+                        }
+                        $($optInput).prop('checked', 'checked');
+                        elfItem.workBook.getSheet(0).endEdit();
+                    } else {//多选
+
+                    }
+                });
+            }
+            $editor.append($editInput);
+            $editor.append($optDiv);
+        }
+        //选择后处理
+        function doAfterSel(node) {
+            let checkedSels = $('.elf-options').find('input:checked');
+            let checkedNameArr = [],
+                optionChecked= [];
+            for(let checkSel of checkedSels){
+                let opt = _.cloneDeep(_.find(bills.selected.elf.datas, {ID: $(checkSel).val()}));
+                opt.rank = $(checkSel).attr('rank');
+                checkedNameArr.push(opt.name);
+                optionChecked.push(opt);
+            }
+            this.displayText = checkedNameArr.length > 0 ? checkedNameArr.join(';') : '';
+            node.data.options = this.displayText;
+            node.data.optionChecked = optionChecked;
+            //删除节点
+            let deleteNodes = getDeleteNodes(node, optionChecked);
+            for(let dNode of deleteNodes){
+                elfSheet.deleteRows(dNode.serialNo(), dNode.posterityCount() + 1);
+                node.tree.delete(dNode);
+            }
+            //插入节点
+            for(let perCheked of optionChecked){
+                let exist = false;
+                let subOpts = getOptions(perCheked, bills.selected.elf.datas);
+                for(let subNode of node.children){
+                    for(let subOpt of subOpts){
+                        if(subNode.data.ID === subOpt.ID){
+                            exist = true;
+                            break;
+                        }
+                    }
+                }
+                //不重复且不为定额时插入
+                if(!exist && perCheked.type !== itemType.ration){
+                    insertNodeByData(node, perCheked);//这里递归,默认第一个
+                }
+            }
+            TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.tree.items, false);
+            setOptionsCellType(node.tree.items);
+            refreshInsertRation();
+            refreshInsertSingle();
+        }
+        //获取删除节点
+        function getDeleteNodes(node, optionChecked) {
+            let rst = [];
+            for(let subNode of node.children){
+                let exist = false;
+                for(let perChecked of optionChecked){
+                    let subOpts = getOptions(perChecked, bills.selected.elf.datas);
+                    for(let subOpt of subOpts){
+                        if(subNode.data.ID === subOpt.ID){
+                            exist = true;
+                            break;
+                        }
+                    }
+                }
+                if(!exist){
+                    rst.push(subNode);
+                }
+            }
+            return rst;
+        }
+        OptionsCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();
+
+        OptionsCellType.prototype.createEditorElement = function (context) {
+            let element = document.createElement("div");//这里创建的,会自动销毁
+            return element
+        };
+        OptionsCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
+            if (editorContext) {
+                let $editor = $(editorContext);
+                $editor.css("position", "fixed");
+                $editor.css("background", "white");
+                $editor.css("width", cellRect.width);
+                $editor.attr("gcUIElement", "gcEditingInput");
+                let top = $('.header').height() + $('#zaojiashu').find('.toolsbar').height() + $('#top_div').height();
+                let activeCellTop = $editor.parent().parent().css('top');
+                activeCellTop = parseFloat(activeCellTop.replace('px', ''));
+                let node = bills.selected.elf.tree.items[elfSheet.getActiveRowIndex()];
+                setOptionsDiv($editor, node, cellRect, cellStyle, top + activeCellTop);
+                this.isEscKey = false;
+            }
+        }
+        OptionsCellType.prototype.deactivateEditor = function (editorContext, context) {
+
+        };
+        OptionsCellType.prototype.setEditorValue = function (editor, value, context) {
+            this.displayText = value;
+        };
+        OptionsCellType.prototype.getEditorValue = function (editor, context) {
+            let me = this;
+            let node = bills.selected.elf.tree.items[elfSheet.getActiveRowIndex()];
+            if(this.isEscKey !=true){
+                renderSheetFunc(elfSheet, function () {
+                    doAfterSel.call(me, node);
+                });
+            }
+            this.isEscKey = false;
+            return this.displayText;
+        };
+        OptionsCellType.prototype.updateEditor = function (editorContext, cellStyle, cellRect, context) {
+
+        };
+        OptionsCellType.prototype.isReservedKey = function (e, context) {
+            //cell type handle tab key by itself
+            this.isEscKey = e.keyCode === GC.Spread.Commands.Key.esc;
+            return false;
+        };
+        /* OptionsCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+         if(style.backColor){
+         ctx.fillStyle = style.backColor;
+         ctx.fillRect(x, y, w, h);
+         ctx.save();
+         }
+         //边长
+         const l = 7;
+         let leftPointX = x + w - 15,
+         rightPointX = leftPointX + l,
+         middlePointX = (leftPointX + rightPointX)/2;
+         const cos30 = Math.cos(2*Math.PI * 30 / 360);
+         let hL = l * cos30;
+         let beginY = y + h/2 - hL;
+         ctx.beginPath();
+         ctx.moveTo(leftPointX, beginY);
+         ctx.lineTo(rightPointX, beginY);
+         ctx.lineTo(middlePointX, beginY + hL);
+         ctx.fillStyle = 'black';
+         ctx.fill();
+         ctx.save();
+         };*/
+        // override getHitInfo to allow cell type get mouse messages
+        OptionsCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea
+            };
+        };
+        return new OptionsCellType();
+    }
+    //获取清单精灵生成的定额数据(跳过重复,不允许重复插入)
+    //@return {Array}
+    function getInsertElfRationData(){
+        let rst = [];
+        if(!bills.selected || !bills.selected.elf){
+            return rst;
+        }
+        let tree = bills.selected.elf.tree;
+        if(!tree){
+            return rst;
+        }
+        let mainSelected = projectObj.project.mainTree.selected;
+        let mainSelRationNodes = _.filter(mainSelected.children, function (c) {
+            return c.data && c.data.type === rationType.ration;
+        });
+        //原本清单存在此定额
+        function existTheRation(rationID) {
+            let r = _.find(mainSelRationNodes, function (node) {
+                return node.data && node.data.stdID && node.data.stdID == rationID;
+            });
+            return r;
+        }
+        //造价书当前选中清单下的定额
+        for(let node of tree.items){
+            for(let perChecked of node.data.optionChecked){
+                //选项直接是定额
+                if(perChecked.type === itemType.ration && !existTheRation(perChecked.rationID)){
+                    rst.push({itemQuery: {userID: userID, ID: perChecked.rationID}, rationType: rationType.ration});
+                }
+                //选项下子选项是定额
+                else {
+                    let rationOpts = getOptions(perChecked, bills.selected.elf.datas);
+                    for(let ration of rationOpts){
+                        if(ration.type === itemType.ration && !existTheRation(ration.rationID)){
+                            rst.push({itemQuery: {userID: userID, ID: ration.rationID}, rationType: rationType.ration});
+                        }
+                    }
+                }
+            }
+        }
+        return rst;
+    }
+    //获取清单精灵插入单条定额的数据
+    //@return {Array}
+    function getInsertElfSingleRation() {
+        let rst = [];
+        if (!bills.selected || !bills.selected.elf) {
+            return rst;
+        }
+        let tree = bills.selected.elf.tree;
+        if (!tree) {
+            return rst;
+        }
+        let elfSelected = tree.selected;
+        if (!elfSelected || !elfSelected.data.optionChecked || !elfSelected.data.optionChecked[0]) {
+            return rst;
+        }
+        let mainSelected = projectObj.project.mainTree.selected;
+        let mainSelRationNodes = _.filter(mainSelected.children, function (c) {
+            return c.data && c.data.type === rationType.ration;
+        });
+        //原本清单存在此定额
+        function existTheRation(rationID) {
+            let r = _.find(mainSelRationNodes, function (node) {
+                return node.data && node.data.stdID && node.data.stdID == rationID;
+            });
+            return r;
+        }
+        //选中的节点第一个选项时定额选项或第一个选项下的子选项时定额选项
+        let firstOptionChecked = elfSelected.data.optionChecked[0];
+        if (firstOptionChecked.type === itemType.ration && !existTheRation(firstOptionChecked.rationID)) {
+            rst.push({itemQuery: {userID: userID, ID: firstOptionChecked.rationID}, rationType: rationType.ration});
+        } else {
+            let rationOpts = getOptions(firstOptionChecked, bills.selected.elf.datas);
+            for(let ration of rationOpts){
+                if(ration.type === itemType.ration && !existTheRation(ration.rationID)){
+                    rst.push({itemQuery: {userID: userID, ID: ration.rationID}, rationType: rationType.ration});
+                    break;
+                }
+            }
+        }
+        return rst;
+    }
+    //插入定额
+    //@return {void}
+    function insertRations(addRationDatas){
+        if(addRationDatas.length > 0){
+            projectObj.project.Ration.addMultiRation(addRationDatas, function () {
+                refreshInsertRation();
+                projectObj.setActiveCell('quantity', true);
+            });
+        }
+    }
+    //更新插入定额按钮有效性
+    function refreshInsertRation(){
+        if (!projectReadOnly) {
+            if (getInsertElfRationData().length > 0) {
+                $('#elfInsertRation').removeClass('disabled');
+            } else {
+                $('#elfInsertRation').addClass('disabled');
+            }
+        }
+    }
+    //更新插入单条按钮有效性
+    function refreshInsertSingle() {
+        if (!projectReadOnly) {
+            if (getInsertElfSingleRation().length > 0) {
+                $('#elfInsertSingle').removeClass('disabled');
+            } else {
+                $('#elfInsertSingle').addClass('disabled');
+            }
+        }
+    }
+    //各监听事件
+    //@return {void}
+    function bindListener(){
+        //插入定额
+        $('#elfInsertRation').click(function () {
+            let addRationDatas =  getInsertElfRationData();
+            insertRations(addRationDatas);
+        });
+        //插入单条
+        $('#elfInsertSingle').click(function () {
+            let addRationDatas = getInsertElfSingleRation();
+            insertRations(addRationDatas);
+        })
+    }
+    return {buildSheet, refreshWorkBook, billsSelElf, setColumnWidthByRate, bindListener};
+})();
+
+$(document).ready(function () {
+    BillsElf.bindListener();
+});

+ 90 - 0
web/building_saas/main/js/views/block_lib.js

@@ -101,6 +101,7 @@ var blockLibObj = {
         me.mainSheet.name('blockLibSheet');
         sheetCommonObj.spreadDefaultStyle(me.mainSpread);
         // me.mainSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, this.onCellDoubleClick);
+        me.mainSpread.bind(GC.Spread.Sheets.Events.EnterCell, me.onEnterCell);
 
         var showblockTree = function (datas) {
             me.mainTree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: false});
@@ -134,6 +135,8 @@ var blockLibObj = {
         sheetCommonObj.spreadDefaultStyle(me.rationSpread);
         me.rationSheet.setColumnWidth(0, 20, GC.Spread.Sheets.SheetArea.rowHeader);
 
+        me.loadTreeContextMenu();
+
         $.bootstrapLoading.end();
     },
     loadDetailDatas: function (node){
@@ -410,6 +413,12 @@ var blockLibObj = {
         };
         return nodes;
     },
+    curIsBlock: function () {
+        return this.mainTree.selected.data.type == 2;
+    },
+    curIsCategory: function () {
+        return this.mainTree.selected.data.type == 1;
+    },
     refreshSpread: function (){
         if (this.mainSpread)
             this.mainSpread.refresh();
@@ -439,6 +448,87 @@ var blockLibObj = {
             sheet.setValue(0, 3, billData.feesIndex.common.unitFee);
         sheet.resumeEvent();
         sheet.resumePaint();
+    },
+    loadTreeContextMenu: function (){
+        let me = this;
+        $.contextMenu({
+            selector: '#div_block_tree',
+            build: function ($trigger, e) {
+                SheetDataHelper.safeRightClickSelection($trigger, e, me.mainSpread);
+                me.onEnterCell();
+            },
+            items: {
+                "oneToOneClone": {
+                    name: '一对一克隆',
+                    icon: "fa-battery-empty",
+                    disabled: function () {
+
+                    },
+                    visible: function(key, opt){
+                        return me.curIsBlock();
+                    },
+                    callback: function (key, opt) {
+
+                    }
+                },
+                "oneToMoreClone": {
+                    name: '一对多克隆',
+                    icon: "fa-battery-half",
+                    disabled: function () {
+
+                    },
+                    visible: function(key, opt){
+                        return me.curIsBlock();
+                    },
+                    callback: function (key, opt) {
+
+                    }
+                },
+                "moreToMoreClone": {
+                    name: '多对多克隆',
+                    icon: "fa-battery-full",
+                    disabled: function () {
+
+                    },
+                    visible: function(key, opt){
+                        return me.curIsCategory();
+                    },
+                    callback: function (key, opt) {
+
+                    }
+                },
+                "delete": {
+                    name: '删除',
+                    icon: "delete",
+                    disabled: function () {
+
+                    },
+                    visible: function(key, opt){
+                        return true;
+                    },
+                    callback: function (key, opt) {
+
+                    }
+                },
+                "moveBlock": {
+                    name: '移动模板',
+                    icon: "cut",
+                    disabled: function () {
+
+                    },
+                    visible: function(key, opt){
+                        return me.curIsBlock();
+                    },
+                    callback: function (key, opt) {
+
+                    }
+                }
+            }
+        });
+    },
+    onEnterCell: function (sender, args) {
+        let me = blockLibObj;
+        me.mainTree.selected = me.mainTree.items[me.mainSheet.getActiveRowIndex()];
     }
 };
 

+ 3 - 2
web/building_saas/main/js/views/importBills.js

@@ -32,7 +32,7 @@ const importBills = (function(){
         serialNo: ['序号'],
         code: ['编码', '项目编码'],
         name: ['名称', '项目名称'],
-        itemCharacterText: ['特征', '项目特征'],
+        itemCharacterText: ['特征', '项目特征', '项目特征描述'],
         unit: ['单位', '计量单位'],
         quantity: ['工程量', '项目工程量'],
         money: ['金额'],
@@ -166,7 +166,8 @@ const importBills = (function(){
                 colMapping.name = colIdx;
             }
             //项目特征
-            else if(colMapping.itemCharacterText === undefined && (_deESC(cellData) === colText.itemCharacterText[0] || _deESC(cellData) === colText.itemCharacterText[1])){
+            else if(colMapping.itemCharacterText === undefined && (_deESC(cellData) === colText.itemCharacterText[0] || _deESC(cellData) === colText.itemCharacterText[1]
+                ||  _deESC(cellData) === colText.itemCharacterText[2])){
                 colMapping.itemCharacterText = colIdx;
             }
             //单位

+ 2 - 2
web/building_saas/main/js/views/project_info.js

@@ -32,9 +32,9 @@ var projectInfoObj = {
                 if(!data.engineeringInfo.billsGuidance_lib || data.engineeringInfo.billsGuidance_lib.length === 0){
                     $('#stdBillsGuidanceTab').addClass('disabled');
                 }
-                else {
+              /*  else {
                     $('#stdBillsGuidanceTab').text(data.engineeringInfo.billsGuidance_lib[0].type === 1 ? '清单指引' : '清单精灵');
-                }
+                }*/
 
                 //init decimal
                 setDecimal(decimalObj, data.property.decimal);

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

@@ -2963,6 +2963,9 @@ function disableTools(){
     $('#property_default').addClass('disabled');
     //项目属性确定
     $('#property_ok').addClass('disabled');
+    //清单精灵
+    $('#elfInsertRation').addClass('disabled');
+    $('#elfInsertSingle').addClass('disabled');
     //特征及内容
     $('#add-rule').find('select').prop('disabled', 'disabled');
     $('#use-to-current').addClass('disabled');

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

@@ -6,6 +6,7 @@ $(window).resize(function() {
     billsGuidance.setColumnWidthByRate(billsGuidance.elfItem.workBook, $('#zy').width(), billsGuidance.elfItem.headers);
     billsGuidance.refreshWorkBook();
     rationLibObj.refreshSpread();
+    BillsElf.setColumnWidthByRate();
 });
 //造价书与清单定额库左右拖动
 let sideResizeEles = {};
@@ -21,6 +22,7 @@ slideResize(sideResizeEles, {min: 250, max: $('#zaojiashu').width()-260}, 'width
     adaptiveTzjnrWidth();
     MaterialController.showReplaceDiv();
     pageCCOprObj.resizeWidth();
+    BillsElf.setColumnWidthByRate();
     projectObj.refreshMainSpread();
     refreshSubSpread();
     if(sideResizeEles.id === 'stdBillsGuidanceTab'){
@@ -40,7 +42,7 @@ slideResize(sideResizeEles, {min: 250, max: $('#zaojiashu').width()-260}, 'width
     }
 });
 
-//清单指引上下拖动
+/*//清单指引上下拖动
 let billsGuidanceLibResizeEles = {};
 billsGuidanceLibResizeEles.id = '#zy';
 billsGuidanceLibResizeEles.resize = $('#zyResize');
@@ -51,7 +53,7 @@ billsGuidanceLibResizeEles.farSpread = $('#billsGuidance_items');
 billsGuidanceLibResizeEles.nav = null;
 slideResize(billsGuidanceLibResizeEles, {min: 147, max: 680}, 'height', function() {
     billsGuidance.refreshWorkBook();
-});
+});*/
 
 //定额库上下拖动
 let rationLibResizeEles = {};
@@ -100,15 +102,10 @@ var sideToolsObj = {
         if (show) {
             sideResizeEles.nearElement.css('width', '66.666667%');
             sideResizeEles.farElement.css('width', '33.333333%');
-
             $('.main-side .tab-pane').hide();
             id === 'locateTab'?tabPanel.show(locateObject.onshow):tabPanel.show();//locateTab要等div显示后才执行刷新操作
             loadSize(sideResizeEles, 'width', function(){
-                if(id === 'stdBillsGuidanceTab'){//清单指引
-                    loadSize(billsGuidanceLibResizeEles, 'height', function(){
-                    });
-                }
-                else if(id === 'stdRationTab'){//定额库
+                if(id === 'stdRationTab'){//定额库
                     loadSize(rationLibResizeEles, 'height', function(){
                     });
                 }
@@ -123,7 +120,6 @@ var sideToolsObj = {
                     });
                 }
             });
-
         } else {
             sideResizeEles.nearElement.css('width', '100%');
             sideResizeEles.farElement.css('width', '0%');
@@ -135,6 +131,7 @@ var sideToolsObj = {
         pageCCOprObj.resizeWidth();
         billsGuidance.refreshWorkBook();
         billsLibObj.refreshBillsSpread();
+        BillsElf.setColumnWidthByRate();
         refreshSubSpread();
         billsLibObj.refreshBillsRelaSpread();
         rationLibObj.refreshSpread();//subSpread、jobSpread、itemSpread显示问题

+ 1 - 588
web/building_saas/main/js/views/std_billsGuidance_lib.js

@@ -10,14 +10,11 @@
 
 //清单指引/精灵获取完清单数据后的回调函数
 let doAfterLoadGuidance = null;
-//选项单选多选状态(按住alt为多选) 单选:0 多选:1
-let billsGuidanceSelMode = 0;
 
 const billsGuidance = (function () {
     let currentLib = null;
     //库类型
     const libType = {'guidance': 1, 'elf': 2}; //清单指引、清单精灵
-    const libTypeText = {1: '清单指引', 2: '清单精灵'};
     const libSel = $('#stdBillsGuidanceLibSelect');
     //工作内容
     let stdBillsJobData = [];
@@ -100,9 +97,6 @@ const billsGuidance = (function () {
         ],
         rowHeaderWidth:25,
         events: {
-            SelectionChanging: function (sender, info) {
-                billsInitSel(info.newSelections[0].row);
-            },
             CellDoubleClick: function (sender, args) {
                 if(!bills.tree){
                     return;
@@ -536,418 +530,6 @@ const billsGuidance = (function () {
             }
         });
     }
-    //清单表焦点控制
-    //@param {Number}row @return {void}
-    function billsInitSel(row){
-        if(currentLib.type && currentLib.type === libType.elf){
-            billsSelElf(row);
-        }else {
-            billsSelGuidance(row);
-        }
-    }
-    //清单焦点变换-清单指引操作
-    //@param {Number}row @return {void}
-    function billsSelGuidance(row){
-        let guideSheet = guideItem.workBook.getActiveSheet();
-        cleanData(guideSheet, guideItem.headers, -1);
-        if(!bills.tree){
-            return;
-        }
-        let node = bills.tree.items[row];
-        if(!node){
-            return;
-        }
-        bills.tree.selected = node;
-        refreshInsertRation();
-        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}row @return {void}
-    function billsSelElf(row) {
-        let elfSheet = elfItem.workBook.getActiveSheet();
-        cleanData(elfSheet, elfItem.headers, -1);
-        if(!bills.tree){
-            return;
-        }
-        let node = bills.tree.items[row];
-        if(!node){
-            return;
-        }
-        bills.tree.selected = node;
-        if(!node.elf.tree){
-            CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: libSel.val(), billsID: node.getID()}, function (rstData) {
-                //定额数据删除编号信息
-                for(let rData of rstData){
-                    if(rData.type === itemType.ration){
-                        let nameArr = rData.name.split(' ');
-                        if(nameArr.length > 0){
-                            nameArr.splice(0, 1);
-                            rData.name = nameArr.join(' ');
-                        }
-                    }
-                }
-                node.elf.datas = rstData;
-                //第一层节点数据
-                let firstLevelDatas = _.filter(rstData, function (data) {
-                    return data.ParentID == -1;
-                });
-                //第一层初始数据的选项显示
-                for(let fData of firstLevelDatas){
-                    let options = getOptions(fData, rstData);
-                    fData.options = options.length > 0 ? options[0].name : '';
-                    //下挂的选项
-                    fData.optionsData = options && options.length > 0 ? _.cloneDeep(options) : [];
-                    fData.optionChecked = options && options.length > 0 ? [_.cloneDeep(options[0])] : [];
-                }
-                renderSheetFunc(elfSheet, function () {
-                    initTree(node.elf, elfSheet, elfItem.treeSetting, firstLevelDatas);
-                    //初始选择选项
-                    let initOptsOpr = [];
-                    for(let elfNode of node.elf.tree.items){
-                        if(elfNode.data.optionsData.length > 0){
-                            initOptsOpr.push({node: elfNode, data: elfNode.data.optionsData[0]});
-                        }
-                    }
-                    for(let opr of initOptsOpr){
-                        insertNodeByData(opr.node, opr.data);
-                    }
-                    TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.elf.tree.items, false);
-                    setOptionsCellType(node.elf.tree.items);
-                    //项目指引初始焦点
-                    elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0);
-                    refreshInsertRation();
-                });
-            });
-        }
-        else{
-            renderSheetFunc(elfSheet, function () {
-                node.elf.controller.showTreeData();
-                setOptionsCellType(node.elf.tree.items);
-                //项目指引初始焦点
-                elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0);
-                refreshInsertRation();
-            });
-        }
-    }
-    //获取选项的深度
-    //@param {Object}opt {Array}options(当前清单所有选项) @return {Array}
-    function getOptionDepth(opt, options) {
-        let parent = _.find(options, {ID: opt.ParentID});
-        let depth = 0;
-        while (parent){
-            depth++;
-            parent = _.find(options, {ID: parent.ParentID});
-        }
-        return depth;
-    }
-    //获取施工工序含有的选项(即当前施工工序的子项),获取的顺序按照NextSiblingID排序
-    //@param {Object}process {Array}datas @return {Array}
-    function getOptions(process, datas) {
-        let rst = [];
-        if(!process || !process.ID){
-            return [];
-        }
-        let options = _.filter(datas, function (data) {
-            return data.ParentID == process.ID;
-        });
-        if(options.length === 0){
-            return [];
-        }
-        //根据NextSiblingID排序
-        let IDMapping = {};
-        for(let opt of options){
-            IDMapping[opt.ID] = {self: opt, next: null, pre: null};
-        }
-        for(let opt of options){
-            let next = IDMapping[opt.NextSiblingID] ? IDMapping[opt.NextSiblingID] : null;
-            if(next){
-                next.pre = IDMapping[opt.ID];
-                IDMapping[opt.ID]['next'] = next;
-            }
-        }
-        let first = null,
-            rank = 0;
-        for(let ID in IDMapping){
-            let obj = IDMapping[ID];
-            if(!obj.pre){
-                first = obj;
-            }
-        }
-        while(first){
-            rank++;
-            first.self.rank = rank;
-            rst.push(first.self);
-            first = first.next;
-        }
-
-        return rst;
-    }
-    //设置清单精灵选项单元格
-    //@param {Array}nodes @return {void}
-    function setOptionsCellType(nodes) {
-        let elfSheet = elfItem.workBook.getActiveSheet();
-        for(let node of nodes){
-            if(node.data.optionsData && node.data.optionsData.length > 0){
-                elfSheet.getCell(node.serialNo(), 1).locked(false).cellType(getOptionsCellType());
-            }
-            else {
-                elfSheet.getCell(node.serialNo(), 1).locked(true).cellType(new GC.Spread.Sheets.CellTypes.Base());
-            }
-        }
-    }
-    //递归插入节点:原始项目指引数据奇数层为需要插入的节点,偶数层为下拉选项
-    //@param {Object}node(当前操作的节点) {Object}data(选项) @return {void}
-    function insertNodeByData(node, data) {
-        let elfSheet = elfItem.workBook.getActiveSheet();
-        let sameDepthNodes = node.children;
-        let insertNextSiblingID = -1,
-            insertParentID = node.data.ID;
-        //当前操作节点的选项
-        let nodeOpts = getOptions(node.data, bills.tree.selected.elf.datas);
-        let subOpts = getOptions(data, bills.tree.selected.elf.datas);
-        let dataDepth = getOptionDepth(data, bills.tree.selected.elf.datas);
-        if(subOpts.length >0 && subOpts[0].type !== itemType.ration){
-            if((dataDepth + 1) % 2 === 0){
-                //排序后的数据
-                let dataWithRank = _.find(nodeOpts, {ID: data.ID});
-                //确定插入位置
-                for(let subOpt of subOpts){
-                    for(let subNode of sameDepthNodes){
-                        //同层节点原本选项数据
-                        let subNodeOptData = _.find(bills.tree.selected.elf.datas, {ID: subNode.data.ID});
-                        //同层节点原本父选项数据
-                        let subNodeOptParent = _.find(bills.tree.selected.elf.datas, {ID: subNodeOptData.ParentID});
-                        let subNodeOptParentWithRank = _.find(nodeOpts, {ID: subNodeOptParent.ID});
-                        //父项顺序决定插入位置
-                        if(dataWithRank.rank < subNodeOptParentWithRank.rank){
-                            insertNextSiblingID = subNode.data.ID;
-                            break;
-                        }
-                        //父项顺序相同,根据子项顺序决定插入位置
-                        else if(dataWithRank.rank = subNodeOptParentWithRank.rank){
-                            if(subOpt.rank < subNode.data.rank){
-                                insertNextSiblingID = subNode.data.ID;
-                                break;
-                            }
-                        }
-                    }
-                    let sub2Opts = getOptions(subOpt, bills.tree.selected.elf.datas);
-                    subOpt.options = sub2Opts.length > 0 ? sub2Opts[0].name : '';
-                    let cloneOpt = _.cloneDeep(subOpt);//不改变原本的数据,比如ParentID
-                    cloneOpt.optionChecked = sub2Opts.length > 0 ? [_.cloneDeep(sub2Opts[0])] : [];
-                    cloneOpt.optionsData = sub2Opts.length > 0 ? _.cloneDeep(sub2Opts) : [];
-                    let newNode = node.tree.insertByData(cloneOpt, insertParentID, insertNextSiblingID);
-                    elfSheet.addRows(newNode.serialNo(), 1);
-                    node.tree.selected = newNode;
-                    elfSheet.setSelection(newNode.serialNo(), elfSheet.getSelections()[0].col, 1, 1);
-                    if(sub2Opts.length > 0 && sub2Opts[0].type !== itemType.ration){
-                        insertNodeByData(newNode, sub2Opts[0]);
-                    }
-                }
-            }
-            else {
-                insertNodeByData(node, subOpts[0]);
-            }
-        }
-    }
-    //获取选项下拉多选单元格
-    //@param {void} @return {void}
-    function getOptionsCellType() {
-        let me = this;
-        let elfSheet= elfItem.workBook.getActiveSheet();
-        function OptionsCellType() {
-            this.isEscKey=false;
-            this.displayText='';
-        }
-        function setOptionsDiv($editor, node, cellRect, cellStyle, top) {
-            if(!node){
-                return '';
-            }
-            let height = cellRect.height;
-            top = top.replace('px', '');
-            let options = getOptions(node.data, bills.tree.selected.elf.datas);
-            top = options.length - 2 > 4 ? top - 4 * height : top - (options.length - 2) * height - 5;
-            let $editInput = $(`<div style="height: ${height}px; background: ${cellStyle.backColor};overflow: hidden; white-space: nowrap; text-overflow: ellipsis">${node.data.options}</div>`),
-                $optDiv = $(`<div style="position: fixed; width: ${cellRect.width}px; top: ${top}px;background: ${cellStyle.backColor};border: 1px solid; overflow: auto; height: ${options.length > 6 ? height*6 : height*options.length+5}px; font-size: 0.9rem;"></div>`);
-            for(let opt of options){
-                let $opt = $(`<div title="${opt.name ? opt.name : ''}" class="elf-options" style="height: ${height}px;overflow: hidden; white-space: nowrap; text-overflow: ellipsis"></div>`),
-                    $optInput = $(`<input rank="${opt.rank}" value="${opt.ID}" style="margin-left: 5px; vertical-align: middle" type="checkbox" 
-                    ${node.data.optionChecked && _.find(node.data.optionChecked, {ID: opt.ID}) ? 'checked' : ''}>`);
-                $opt.text(`${opt.name ? opt.name : ''}`);
-                $opt.prepend($optInput);
-                $optDiv.append($opt);
-                //选项复选框点击监听
-                $opt.click(function () {
-                    //单选
-                    if(billsGuidanceSelMode === 0){
-                        let $allInput = $optDiv.find('input');
-                        for(let input of $allInput){
-                            $(input).prop('checked', false);
-                        }
-                        $($optInput).prop('checked', 'checked');
-                        elfItem.workBook.getSheet(0).endEdit();
-                    } else {//多选
-
-                    }
-                });
-            }
-            $editor.append($editInput);
-            $editor.append($optDiv);
-        }
-        //选择后处理
-        function doAfterSel(node) {
-            let checkedSels = $('.elf-options').find('input:checked');
-            let checkedNameArr = [],
-                optionChecked= [];
-            for(let checkSel of checkedSels){
-                let opt = _.cloneDeep(_.find(bills.tree.selected.elf.datas, {ID: $(checkSel).val()}));
-                opt.rank = $(checkSel).attr('rank');
-                checkedNameArr.push(opt.name);
-                optionChecked.push(opt);
-            }
-            this.displayText = checkedNameArr.length > 0 ? checkedNameArr.join(';') : '';
-            node.data.options = this.displayText;
-            node.data.optionChecked = optionChecked;
-            //删除节点
-            let deleteNodes = getDeleteNodes(node, optionChecked);
-            for(let dNode of deleteNodes){
-                elfSheet.deleteRows(dNode.serialNo(), dNode.posterityCount() + 1);
-                node.tree.delete(dNode);
-            }
-            //插入节点
-            for(let perCheked of optionChecked){
-                let exist = false;
-                let subOpts = getOptions(perCheked, bills.tree.selected.elf.datas);
-                for(let subNode of node.children){
-                    for(let subOpt of subOpts){
-                        if(subNode.data.ID === subOpt.ID){
-                            exist = true;
-                            break;
-                        }
-                    }
-                }
-                //不重复且不为定额时插入
-                if(!exist && perCheked.type !== itemType.ration){
-                    insertNodeByData(node, perCheked);//这里递归,默认第一个
-                }
-            }
-            TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.tree.items, false);
-            setOptionsCellType(node.tree.items);
-            refreshInsertRation();
-        }
-        //获取删除节点
-        function getDeleteNodes(node, optionChecked) {
-            let rst = [];
-            for(let subNode of node.children){
-                let exist = false;
-                for(let perChecked of optionChecked){
-                    let subOpts = getOptions(perChecked, bills.tree.selected.elf.datas);
-                    for(let subOpt of subOpts){
-                        if(subNode.data.ID === subOpt.ID){
-                            exist = true;
-                            break;
-                        }
-                    }
-                }
-                if(!exist){
-                    rst.push(subNode);
-                }
-            }
-            return rst;
-        }
-        OptionsCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();
-
-        OptionsCellType.prototype.createEditorElement = function (context) {
-            let element = document.createElement("div");//这里创建的,会自动销毁
-            return element
-        };
-        OptionsCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
-            if (editorContext) {
-                let $editor = $(editorContext);
-                $editor.css("position", "fixed");
-                $editor.css("background", "white");
-                $editor.css("width", cellRect.width);
-                $editor.attr("gcUIElement", "gcEditingInput");
-                let activeCellTop = $editor.parent().parent().css('top');
-                let node = bills.tree.selected.elf.tree.items[elfSheet.getActiveRowIndex()];
-                setOptionsDiv($editor, node, cellRect, cellStyle, activeCellTop);
-                this.isEscKey = false;
-            }
-        }
-        OptionsCellType.prototype.deactivateEditor = function (editorContext, context) {
-
-        };
-        OptionsCellType.prototype.setEditorValue = function (editor, value, context) {
-            this.displayText = value;
-        };
-        OptionsCellType.prototype.getEditorValue = function (editor, context) {
-            let me = this;
-            let node = bills.tree.selected.elf.tree.items[elfSheet.getActiveRowIndex()];
-            if(this.isEscKey !=true){
-                renderSheetFunc(elfSheet, function () {
-                    doAfterSel.call(me, node);
-                });
-            }
-            this.isEscKey = false;
-            return this.displayText;
-        };
-        OptionsCellType.prototype.updateEditor = function (editorContext, cellStyle, cellRect, context) {
-
-        };
-        OptionsCellType.prototype.isReservedKey = function (e, context) {
-            //cell type handle tab key by itself
-            this.isEscKey = e.keyCode === GC.Spread.Commands.Key.esc;
-            return false;
-        };
-       /* OptionsCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
-            if(style.backColor){
-                ctx.fillStyle = style.backColor;
-                ctx.fillRect(x, y, w, h);
-                ctx.save();
-            }
-            //边长
-            const l = 7;
-            let leftPointX = x + w - 15,
-                rightPointX = leftPointX + l,
-                middlePointX = (leftPointX + rightPointX)/2;
-            const cos30 = Math.cos(2*Math.PI * 30 / 360);
-            let hL = l * cos30;
-            let beginY = y + h/2 - hL;
-            ctx.beginPath();
-            ctx.moveTo(leftPointX, beginY);
-            ctx.lineTo(rightPointX, beginY);
-            ctx.lineTo(middlePointX, beginY + hL);
-            ctx.fillStyle = 'black';
-            ctx.fill();
-            ctx.save();
-        };*/
-        // override getHitInfo to allow cell type get mouse messages
-        OptionsCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
-            return {
-                x: x,
-                y: y,
-                row: context.row,
-                col: context.col,
-                cellStyle: cellStyle,
-                cellRect: cellRect,
-                sheetArea: context.sheetArea
-            };
-        };
-        return new OptionsCellType();
-    }
     //初始化清单的工作内容和项目特征
     //@param {Number}billsLibId {Function}callback @return {void}
     function initJobAndCharacter(billsLibId, callback){
@@ -998,7 +580,6 @@ const billsGuidance = (function () {
         let sheet = bills.workBook.getActiveSheet();
         let locateRow = locateBills ? locateBills.serialNo() : 0;
         sheet.setActiveCell(locateRow, 0);
-        billsInitSel(locateRow);
         sheet.showRow(locateRow, GC.Spread.Sheets.VerticalPosition.center);
     }
     //清单设置悬浮提示信息
@@ -1084,25 +665,6 @@ const billsGuidance = (function () {
             initViews();
             let callback = function () {
                 initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills);
-                //清单精灵
-                if(rstData.guidanceLib.type && rstData.guidanceLib.type == libType.elf){
-                    $('#stdBillsGuidanceTab').text('清单精灵');
-                    //每一个清单节点下挂载一棵清单精灵树
-                    for(let node of bills.tree.items){
-                        node.elf = {tree: null, controller: null, datas: []}; //挂载全部数据,数据不一定全成为树节点
-                    }
-                }
-                //清单指引
-                else {
-                    $('#stdBillsGuidanceTab').text('清单指引');
-                    //每一棵项目指引树挂在清单节点上
-                    for(let node of bills.tree.items){
-                        node.guidance = {tree: null, controller: null};
-                    }
-                }
-                //setTagForHint(bills.tree.items);
-                //默认初始节点
-                billsInitSel(0);
                 if(doAfterLoadGuidance){
                     doAfterLoadGuidance();
                 }
@@ -1151,105 +713,6 @@ const billsGuidance = (function () {
         initWorkBooks(modules);
 
     }
-    //获取选中的行
-    //@return {Array}
-    function getCheckedRows(){
-        let rst = [];
-        let itemSheet = guideItem.workBook.getActiveSheet();
-        for(let row = 0; row < itemSheet.getRowCount(); row++){
-            let rowV = itemSheet.getValue(row, 0);
-            if(rowV){
-                rst.push(row);
-            }
-        }
-        return rst;
-    }
-    //获取清单精灵生成的定额数据
-    //@return {Array}
-    function getInsertElfRationData(){
-        let rst = [];
-        if(!bills.tree.selected){
-            return [];
-        }
-        if(!bills.tree.selected.elf){
-            return [];
-    }
-        let tree = bills.tree.selected.elf.tree;
-        if(!tree){
-            return [];
-        }
-        for(let node of tree.items){
-            for(let perChecked of node.data.optionChecked){
-                //选项直接是定额
-                if(perChecked.type === itemType.ration){
-                    rst.push({itemQuery: {userID: userID, ID: perChecked.rationID}, rationType: rationType.ration});
-                }
-                //选项下子选项是定额
-                else {
-                    let rationOpts = getOptions(perChecked, bills.tree.selected.elf.datas);
-                    for(let ration of rationOpts){
-                        if(ration.type === itemType.ration){
-                            rst.push({itemQuery: {userID: userID, ID: ration.rationID}, rationType: rationType.ration});
-                        }
-                    }
-                }
-            }
-        }
-        return rst;
-    }
-    //获取选中的定额数据
-    //@param {Array}rows @return {Array}
-    function getInsertRationData(rows){
-        let rst = [];
-        for(let row of rows){
-            let node = bills.tree.selected.guidance.tree.items[row];
-            if(node && node.data.type === itemType.ration){
-                rst.push({itemQuery: {userID: userID, ID: node.data.rationID}, rationType: rationType.ration});
-            }
-        }
-        return rst;
-    }
-    //插入定额
-    //@return {void}
-    function insertRations(addRationDatas){
-        if(addRationDatas.length > 0){
-            projectObj.project.Ration.addMultiRation(addRationDatas, function () {
-                //恢复
-                if(!currentLib.type || currentLib.type === libType.guidance){
-                    let sheet = guideItem.workBook.getActiveSheet();
-                    renderSheetFunc(sheet, function () {
-                        for(let row = 0; row < sheet.getRowCount(); row++){
-                            if(sheet.getValue(row, 0)){
-                                sheet.setValue(row, 0, false);
-                            }
-                        }
-                    });
-                }
-                refreshInsertRation();
-                projectObj.setActiveCell('quantity', true);
-            });
-        }
-    }
-    //更新插入定额按钮有效性
-    function refreshInsertRation(){
-        if(currentLib.type && currentLib.type === libType.elf){
-            if(getInsertElfRationData().length > 0){
-                $('#guidanceInsertRation').removeClass('disabled');
-            }
-            else {
-                $('#guidanceInsertRation').addClass('disabled');
-            }
-        }
-        else {
-            //勾选了定额,插入定额按钮才有效
-            if(getCheckedRows().length > 0){
-                $('#guidanceInsertRation').removeClass('disabled');
-            }
-            else {
-                $('#guidanceInsertRation').addClass('disabled');
-            }
-        }
-    }
     //展开至搜索出来点的节点
     //@param {Array}nodes @return {void}
     function expandSearchNodes(nodes){
@@ -1289,41 +752,6 @@ const billsGuidance = (function () {
             //清除展开收起状态sessionStorage
             sessionStorage.removeItem('stdBillsGuidanceExpState');
         });
-        //插入定额
-        $('#guidanceInsertRation').click(function () {
-            let addRationDatas = currentLib.type && currentLib.type === libType.elf ? getInsertElfRationData() : getInsertRationData(getCheckedRows());
-            insertRations(addRationDatas);
-        });
-        //插入清单
-        $('#guidanceInsertBills').click(function () {
-            //插入清单
-            if(!bills.tree || !bills.tree.selected){
-                return;
-            }
-            if(bills.tree.selected.children.length === 0){
-                let insert = billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, bills.tree.selected);
-                /*if(insert){
-                    //插入选中的定额
-                    let addRationDatas = currentLib.type && currentLib.type === libType.elf ? getInsertElfRationData() : getInsertRationData(getCheckedRows());
-                    insertRations(addRationDatas);
-                }*/
-            }
-        });
-        //插入清单和定额
-        $('#guidanceInsertBillsAndRation').click(function () {
-            //插入清单
-            if(!bills.tree || !bills.tree.selected){
-                return;
-            }
-            if(bills.tree.selected.children.length === 0){
-                let insert = billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, bills.tree.selected);
-                if(insert){
-                    //插入选中的定额
-                    let addRationDatas = currentLib.type && currentLib.type === libType.elf ? getInsertElfRationData() : getInsertRationData(getCheckedRows());
-                    insertRations(addRationDatas);
-                }
-            }
-        });
         //搜索
         $('#stdBillsGuidanceSearch>div>button').click(function () {
             if(!bills.tree){
@@ -1355,8 +783,6 @@ const billsGuidance = (function () {
                 renderSheetFunc(billsSheet, function () {
                     bills.controller.setTreeSelected(result[0]);
                     billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
-                    billsInitSel(result[0].serialNo());
-
                     for (let node of result) {
                         billsSheet.getRange(node.serialNo(), -1, 1, -1).backColor('lemonChiffon');
                     }
@@ -1371,12 +797,10 @@ const billsGuidance = (function () {
                     if (resultIndex === result.length - 1) {
                         bills.controller.setTreeSelected(result[0]);
                         billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
-                        billsInitSel(result[0].serialNo());
                         billsSheet.showRow(result[0].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
                     } else {
                         bills.controller.setTreeSelected(result[resultIndex + 1]);
                         billsSheet.setSelection(result[resultIndex + 1].serialNo(), sel[0].col, 1, 1);
-                        billsInitSel(result[resultIndex + 1].serialNo());
                         billsSheet.showRow(result[resultIndex + 1].serialNo(), GC.Spread.Sheets.VerticalPosition.bottom);
                     }
                 });
@@ -1400,17 +824,6 @@ const billsGuidance = (function () {
             billsLibObj.clearHighLight(bills.workBook);
             refreshWorkBook();
         });
-        //监听alt建,确定选项单选多选状态
-       /* $('#billsGuidance_items').keydown(function(e){
-            if(e.keyCode === 18){
-                billsGuidanceSelMode = 1;
-            }
-        });
-        $('#billsGuidance_items').keyup(function(e){
-            if(e.keyCode === 18){
-                billsGuidanceSelMode = 0;
-            }
-        });*/
     }
     //刷新表
     //@return {void}
@@ -1426,7 +839,7 @@ const billsGuidance = (function () {
         }
     }
 
-    return {initViews, bindBtn, refreshWorkBook, refreshInsertRation, setColumnWidthByRate, locateAtBills, bills, elfItem};
+    return {initViews, bindBtn, refreshWorkBook, setColumnWidthByRate, locateAtBills, bills, elfItem};
 })();
 
 $(document).ready(function(){

+ 18 - 1
web/building_saas/main/js/views/sub_view.js

@@ -11,6 +11,8 @@ let subSpread = null;
 let subObj = {
     TZJNRrePercent:null,
     initSubSpread:function () {
+        //清单精灵
+        BillsElf.buildSheet();
         contentOprObj.buildSheet($("#jobSpread")[0]);
         //sheetCommonObj.bindEscKey(contentOprObj.workBook, [{sheet: contentOprObj.workBook.getSheet(0), editStarting: contentOprObj.onEditStart, editEnded: contentOprObj.onEditEnded}]);
         sheetCommonObj.spreadDefaultStyle(contentOprObj.workBook);
@@ -74,7 +76,8 @@ let subObj = {
             $("#MBZM_div").show();
             installationFeeObj.engineeringTypeChecking();//检查是否安装工程
             $("#TZJNR_div").hide();
-            $(gljOprObj.rationTab).click();
+  			$('#QDJL_div').hide();
+            $("#linkGLJ").addClass();            $(gljOprObj.rationTab).click();
 
         }else {
             $("#GLJ_div").hide();
@@ -82,6 +85,7 @@ let subObj = {
             $("#MBZM_div").hide();
             $("#AZZJF_div").hide();
             $("#TZJNR_div").show();
+            $('#QDJL_div').show();
             $(gljOprObj.billsTab).click();
         }
         projectObj.mainSpread.focus();
@@ -202,6 +206,18 @@ function adaptiveTzjnrWidth() {
     pageCCOprObj.resizeWidth();
     refreshSubSpread();
 }
+//清单精灵
+$('#linkQDJL').click(function () {
+    gljOprObj.activeTab='#linkQDJL';
+    $("#subItems").children().hide();
+    $('#qdjl').show();
+    let selectedNode = projectObj.mainController.tree.selected;
+    BillsElf.billsSelElf(selectedNode.data.code);
+    refreshSubSpread();
+    gljOprObj.setNodeShowTab();
+    BillsElf.refreshWorkBook();
+
+});
 //特征及内容
 $("#linkTZJNR").click(function () {
     gljOprObj.activeTab='#linkTZJNR';
@@ -533,6 +549,7 @@ function refreshSubSpread(){
     } else{
         if(subSpread) subSpread.refresh();
         if(MaterialController.spread) MaterialController.spread.refresh();
+        BillsElf.refreshWorkBook();
     }
     if($('#linkZMHS').hasClass('active')) zmhs_obj.refresh();
     if($('#linkMBZM').hasClass('active')) mbzm_obj.refresh();

+ 56 - 5
web/building_saas/pm/html/project-management.html

@@ -31,6 +31,12 @@
         #summary-engineering,#summary-project{
             display: none;
         }
+        #shareToInfo {
+            display:block;
+            height:200px;
+            overflow-y:auto;
+            -webkit-overflow-scrolling: touch;
+        }
     </style>
 </head>
 
@@ -631,6 +637,51 @@
 </div>
 <!--弹出分享-->
 <div class="modal fade" id="share" data-backdrop="static">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">分享给...</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <!--添加分享-->
+                <div class="form-group">
+                    <div class="input-group input-group-sm">
+                        <input id="sharePhone" type="text" class="form-control" placeholder="输入 手机号 添加分享">
+                       <!-- <div class="input-group-append">
+                            <button class="btn btn-primary" type="button" id="button-addon2">添加分享</button>
+                        </div>-->
+                    </div>
+                </div>
+                <table class="table table-sm" id="shareFindDiv">
+                    <tbody style="display: block">
+                    <tr><th style="width: 112px;">姓名</th><th style="width: 165px;">公司</th><th style="width: 136px;">手机</th><th style="width: 160px;">邮箱</th><th style="width: 90px;">允许拷贝</th><th style="width: 90px;">添加分享</th></tr>
+                    <tr><td id="user_name">张三</td><td id="user_company">XX公司</td><td id="user_mobile">12345678900</td><td id="user_email"></td><td><input id="allowCopy" type="checkbox"></td><td><a id="share-confirm" href="javascript:void(0)" class="btn btn-sm btn-primary">添加分享</a></td></tr>
+                    </tbody>
+                </table>
+                <p id="share-info" class="text-danger">不存在手机号 15812777651 的用户</p>
+                <!--已分享数据-->
+                <legend>已分享</legend>
+                <table class="table table-sm">
+                    <tbody id="shareToInfo">
+                    <tr><th>姓名</th><th>公司</th><th>手机</th><th>邮箱</th><th width="90">允许拷贝</th><th width="90">取消分享</th></tr>
+                    <tr><td>张三</td><td>XX公司</td><td>12345678900</td><td></td><td><input type="checkbox"></td><td><input type="checkbox"></td></tr>
+                    <tr><td>王五</td><td>XX公司</td><td>12345678900</td><td></td><td><input type="checkbox"></td><td><input type="checkbox"></td></tr>
+                    </tbody>
+                </table>
+            </div>
+            <div class="modal-footer">
+                <!--分享人可以取消-->
+                <button id="shareToConfirm" type="button" class="btn btn-primary" data-dismiss="modal">确定</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!--弹出分享-->
+<!--<div class="modal fade" id="share" data-backdrop="static">
     <div class="modal-dialog" role="document">
         <div class="modal-content">
             <div class="modal-header">
@@ -660,7 +711,7 @@
                             <div class="form-check mb-2">
                                 <input type="checkbox" class="form-check-input" id="allowCopy">
                                 <label class="form-check-label" for="allowCopy">允许该用户拷贝该工程</label>
-                                <!--打勾后出现提示-->
+                                &lt;!&ndash;打勾后出现提示&ndash;&gt;
                                 <div id="allowCopyHint" class="form-text text-danger"><i class="fa fa-exclamation-triangle"></i> 该用户可以把你的项目拷贝成为他的数据,请谨慎勾选。 </div>
                             </div>
                             <a id="addShareUser" class="btn btn-sm btn-primary" href="javascript:void(0);"><i class="fa fa-plus"></i> 添加</a>
@@ -679,9 +730,9 @@
             </div>
         </div>
     </div>
-</div>
+</div>-->
 <!--弹出分享给交互-->
-<div class="modal fade" id="shareTo" data-backdrop="static">
+<!--<div class="modal fade" id="shareTo" data-backdrop="static">
     <div class="modal-dialog" role="document">
         <div class="modal-content" style="width: 750px;">
             <div class="modal-header">
@@ -691,7 +742,7 @@
                 </button>
             </div>
             <div class="modal-body modal-fixed-height">
-                <!--     <p>勾选需要恢复的文件,点“确定”按钮,确认从回收站中恢复。</p>-->
+                &lt;!&ndash;     <p>勾选需要恢复的文件,点“确定”按钮,确认从回收站中恢复。</p>&ndash;&gt;
                 <table class="table table-hover table-sm mb-5">
                     <thead>
                     <tr style="display: block;">
@@ -721,7 +772,7 @@
             </div>
         </div>
     </div>
-</div>
+</div>-->
 <!-- JS. -->
 <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js"></script>
 <script>GC.Spread.Sheets.LicenseKey = '<%- LicenseKey %>';</script>

+ 59 - 124
web/building_saas/pm/js/pm_newMain.js

@@ -35,9 +35,6 @@ let taxTypeMap = {
 * */
 let regions = [];
 
-//分享用户列表
-let shareUsers = [];
-
 function isDef(v) {
     return typeof v !== 'undefined' && v !== null;
 }
@@ -308,9 +305,11 @@ const projTreeObj = {
                         //return !(selectedItem && selectedItem.data.projType === projectType.tender);
                     },
                     callback: function (key, opt) {
+                        let selected = projTreeObj.tree.selected;
                         $('#sharePhone').val('');
                         $('#share-info').hide();
-                        $('#share').find('.card').hide();
+                        $('#shareFindDiv').hide();
+                        setShareToModal(selected);
                         $('#share').modal('show');
                         //默认允许拷贝
                         $('#allowCopy').prop('checked', true);
@@ -320,7 +319,7 @@ const projTreeObj = {
                         }, 200);
                     }
                 },
-                'cancelShare': {
+               /* 'cancelShare': {
                     name: '取消分享',
                     icon: 'fa-ban',
                     disabled: function () {
@@ -332,7 +331,7 @@ const projTreeObj = {
                         setShareToModal(selected);
                         $('#shareTo').modal('show');
                     }
-                },
+                },*/
                 "spr3": '--------',
                 "manageFiles": {
                     name: "管理相关文件",
@@ -1902,7 +1901,7 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
             let updateProjs = GetUpdateData(pre, parent, next, projName, null, projID, {updateType: 'new', projectType: projectType.project});
             let updateEng = {updateType: 'new', updateData: {ID: engID, ParentID: projID, NextSiblingID: -1, name: engName, projType: projectType.engineering}};
             property.rootProjectID = projID;
-            let updateTender = {updateType: 'new', updateData: {ID: tenderID, ParentID: engID, NextSiblingID: -1, name: tenderName, projType: projectType.tender, property: property}};
+            let updateTender = {updateType: 'new', updateData: {ID: tenderID, ParentID: engID, NextSiblingID: -1, shareInfo: [], name: tenderName, projType: projectType.tender, property: property}};
             updateDatas = updateDatas.concat(updateProjs);
             updateDatas.push(updateEng);
             updateDatas.push(updateTender);
@@ -1937,7 +1936,7 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
             let next = null;
             let updateEng = {updateType: 'new', updateData: {ID: engID, ParentID: tempProj.data.ID, NextSiblingID: -1, name: engName, projType: projectType.engineering}};
             property.rootProjectID = tempProj.data.ID;
-            let updateTender = {updateType: 'new', updateData: {ID: tenderID, ParentID: engID, NextSiblingID: -1, name: tenderName, projType: projectType.tender, property: property}};
+            let updateTender = {updateType: 'new', updateData: {ID: tenderID, ParentID: engID, NextSiblingID: -1,  shareInfo: [], name: tenderName, projType: projectType.tender, property: property}};
             if(selected && selected.data.projType === projectType.engineering && selected.parent === tempProj){
                 pre = selected;
                 next = selected.nextSibling;
@@ -1973,7 +1972,7 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
             let tenderID = IDs.lowID;
             let pre = tempEng.lastChild();
             property.rootProjectID = tempProj.data.ID;
-            let updateTender = {updateType: 'new', updateData: {ID: tenderID, ParentID: tempEng.id(), NextSiblingID: -1, name: tenderName, projType: projectType.tender, property: property}};
+            let updateTender = {updateType: 'new', updateData: {ID: tenderID, ParentID: tempEng.id(), NextSiblingID: -1,  shareInfo: [], name: tenderName, projType: projectType.tender, property: property}};
             updateDatas.push(updateTender);
             if(pre){
                 updateDatas.push({updateType: 'update', updateData: {ID: pre.id(), NextSiblingID: tenderID}});
@@ -3321,9 +3320,11 @@ function shareTender(){
     canShare = false;
     let phone = $('#sharePhone').val();
     const hintInfo = $('#share-info');
-    const userInfo = $('#share').find('.card');
+    const userInfo = $('#shareFindDiv');
     const addUser = $('#addShareUser');
     const copyInput = $('#allowCopy');
+    const shareConfirm = $('#share-confirm');
+    shareConfirm.addClass('disabled');
     //可分享才可添加用户
     addUser.addClass('disabled');
     if (hintInfo.is(':visible')) {
@@ -3354,10 +3355,8 @@ function shareTender(){
             setDangerInfo(hintInfo, '', false);
             $('#user_name').text(userData.real_name ? userData.real_name : '');
             $('#user_company').text(userData.company ? userData.company : '');
-            let mobileHtml = `<i class="fa fa-tablet"> ${userData.mobile ? userData.mobile : ''}</i>`;
-            $('#user_mobile').html(mobileHtml);
-            let emailHtml = `<i class="fa fa-envelope-o"> ${userData.email ? userData.email : ''}</i>`;
-            $('#user_email').html(emailHtml);
+            $('#user_mobile').text(userData.mobile ? userData.mobile : '');
+            $('#user_email').text(userData.email ? userData.email : '');
             //默认可拷贝
             copyInput.prop('checked', true);
             userInfo.show();
@@ -3370,6 +3369,7 @@ function shareTender(){
                     }
                 }
                 addUser.removeClass('disabled');
+                shareConfirm.removeClass('disabled');
                 canShare = true;
             });
         }
@@ -3381,127 +3381,46 @@ $('#sharePhone').on('keyup',function () {
     });
 });
 
-//设置确认分享用户列表
-//@param {String}name {String}phone @return {void}
-function setUsersShareDiv(projName, users) {
-    //每行的数据
-    const perLineCount = 2;
-    let $users = $('#shareUsers');
-    //三行后限制死高度
-    if (Math.ceil(users.length / perLineCount) > 2) {
-        $users.height(180);
-    } else {
-        $users.height('');
-    }
-    $users.empty();
-    let $projInfo = $(`<p>确认分享 <b>${projName}</b> 给</p>`);
-    $users.append($projInfo);
-    let $preP = null,
-        $preH4 = null;
-    for (let i = 0; i < users.length; i++) {
-        let user = users[i];
-        let $span = $(`<span class="badge badge-light mr-3" style="padding: 0">${user.name}(${user.phone})</span>`),
-            $a = $(`<a href="javascript:void(0);" userID="${user.userID}" class="text-danger" title="移除分享"></a>`),
-            $i = $('<i class="fa fa-remove"></i>');
-        bindRemoveShare($a);
-        $a.append($i);
-        $span.append($a);
-        //另起一行
-        if (i % 2 === 0) {
-           $preP = $('<p>');
-           $preH4 = $('<h4>');
-           $preH4.append($span);
-           $preP.append($preH4);
-           $users.append($preP);
-        } else {//行内新增元素
-            $preH4.append($span);
-            $preP.append($preH4);
-        }
-    }
-    if (users.length > 0) {
-        $users.show();
-    }
-    //移除分享列表
-    function bindRemoveShare(a){
-        a.click(function () {
-            let theUserID = a.attr('userID');
-            //清除shareUsers数组相关数据
-            _.remove(shareUsers, {userID: theUserID});
-            a.parent().remove();
-            //如果行内只剩一个数据,则删除数据及行
-            if (a.parent().parent().children().length === 0) {
-                a.parent().parent().remove();
-            }
-            //如果所用用户数据只剩这一条,删除用户数据则隐藏分享用户列表容器
-            if (shareUsers.length === 0) {
-                $('#shareUsers').hide();
-            }
-        });
-    }
-
-}
-//添加分享用户
-$('#addShareUser').click(function () {
-    //输入有效手机号的用户
-    if (shareUserID) {
-        const hintInfo = $('#share-info');
-        if (_.find(shareUsers, {userID: shareUserID})) {
-            setDangerInfo(hintInfo, '已添加此用户');
-            return;
-        }
-        let allowCopy = $('#allowCopy').prop('checked'),
-            name = $('#user_name').text(),
-            phone = $('#user_mobile').text();
-        shareUsers.push({userID: shareUserID, name: name, phone: phone, allowCopy: allowCopy});
-        let selected = projTreeObj.tree.selected;
-        setUsersShareDiv(selected.data.name, shareUsers);
-        if (hintInfo.is(':visible')) {
-            hintInfo.hide();
-        }
-        //搜索的用户信息
-        $('#share').find('.card').hide();
-        $('#sharePhone').val('');
-        $('#sharePhone').focus();
-        shareUserID = null;
-    }
-});
-$('#share').on('hidden.bs.modal', function () {
-    $('#shareUsers').hide();
-    shareUsers = []
-});
 //确认分享
 $('#share-confirm').click(function(){
     const hintInfo = $('#share-info');
-    if (shareUsers.length === 0) {
-        setDangerInfo(hintInfo, '请添加分享');
-        return;
-    }
-    $('#shareUsers').hide();
-    $('#share-confirm').addClass('disabled');
     $.bootstrapLoading.start();
-    let allowCopy = $('#allowCopy').prop('checked');
-    let shareData = [];
-    for (let userData of shareUsers) {
-        shareData.push({userID: userData.userID, allowCopy: userData.allowCopy});
-    }
+    const perHeight = 30;
+    let allowCopy = $('#allowCopy').prop('checked'),
+        userName = $('#user_name').text() || '',
+        userCompany = $('#user_company').text() || '',
+        userMobile = $('#user_mobile').text() || '',
+        userEmail = $('#user_email').text() || '';
+    let shareData = [{userID: shareUserID, allowCopy: allowCopy}];
     //分享
     CommonAjax.post('/pm/api/share', {user_id: userID, type: shareType.create,  projectID: shareSeleted.data.ID, shareData: shareData}, function (rstData) {
+        //更新已分享table
+        let $tr = $(`<tr>
+                        <td style="width: 112px">${userName}</td>
+                        <td style="width: 165px">${userCompany}</td>
+                        <td style="width: 136px">${userMobile}</td>
+                        <td style="width: 136px">${userEmail}</td>
+                        <td style="width: 90px;"><input value="allowCopy" ${allowCopy ? 'checked' : ''} type="checkbox"></td>
+                        <td style="width: 90px;"><input value="cancelShare" type="checkbox"></td>
+                     </tr>`);
+        let tbodyTotalHeight = $('#shareToInfo').height() + perHeight > 200 ? 200 : $('#shareToInfo').height() + perHeight;
+        $('#shareToInfo').height(tbodyTotalHeight);
+        $('#shareToInfo').append($tr);
         //更新缓存
-        if (shareSeleted.data.shareInfo.length === 0) {
+       // if (shareSeleted.data.shareInfo.length === 0) {
             shareSeleted.data.shareInfo = shareSeleted.data.shareInfo.concat(shareData);
             let sheet = projTreeObj.workBook.getSheet(0);
             projTreeObj.renderSheetFuc(sheet, function () {
                 sheet.invalidateLayout();
                 sheet.repaint();
             });
-        }
+       // }
         $.bootstrapLoading.end();
-        $('#share-confirm').removeClass('disabled');
-        $('#share').modal('hide');
+        $('#shareFindDiv').hide();
+        $('#share-confirm').addClass('disabled');
     }, function () {
         $.bootstrapLoading.end();
         $('#share-confirm').removeClass('disabled');
-        $('#share').modal('hide');
     });
 });
 //允许拷贝
@@ -3527,6 +3446,7 @@ $('#shareToConfirm').click(function () {
 //设置分享给界面数据
 //@param {Object}selected @return {void}
 function setShareToModal(selected){
+    const perHeight = 30; //每条分享给数据的高度
     $('#shareToInfo').empty();
     if(!selected){
         return;
@@ -3547,17 +3467,29 @@ function setShareToModal(selected){
             }
         }
         let infoArr = [];
+        //居中style="width: 90px;text-align: center"
+        let theadHtml = `<tr>
+                                          <th style="width: 112px;">姓名</th>
+                                          <th style="width: 165px;">公司</th>
+                                          <th style="width: 136px;">手机</th>
+                                          <th style="width: 136px;">邮箱</th>
+                                          <th style="width: 90px;">允许拷贝</th>
+                                          <th style="width: 90px;">取消分享</th>
+                               </tr>`;
+        infoArr.push(theadHtml);
         for(let user of selected.data.shareInfo){
             let infoHtml = `<tr>
-                                          <td style="width: 106px;">${user.name}</td>
-                                          <td style="width: 146px;">${user.company}</td>
-                                          <td style="width: 146px;">${user.mobile}</td>
-                                          <td style="width: 156px;">${user.email}</td>
-                                          <td style="width: 70px;text-align: center"><input value="allowCopy" ${user.allowCopy ? 'checked' : ''} type="checkbox"></td>
-                                          <td style="width: 70px;text-align: center"><input value="cancelShare" type="checkbox"></td>
+                                          <td style="width: 112px;">${user.name}</td>
+                                          <td style="width: 165px;">${user.company}</td>
+                                          <td style="width: 136px;">${user.mobile}</td>
+                                          <td style="width: 160px;">${user.email}</td>
+                                          <td style="width: 90px;"><input value="allowCopy" ${user.allowCopy ? 'checked' : ''} type="checkbox"></td>
+                                          <td style="width: 90px;"><input value="cancelShare" type="checkbox"></td>
                                </tr>`;
             infoArr.push(infoHtml);
         }
+        let tbodyTotalHeight = infoArr.length * perHeight + 5 > 200 ? 200 : infoArr.length * perHeight + 5;
+        $('#shareToInfo').height(tbodyTotalHeight);
         let infoHtml = infoArr.join('');
         $('#shareToInfo').html(infoHtml);
     });
@@ -3569,6 +3501,9 @@ function updateShareInfo(selected){
         return;
     }
     let usersTr = $('#shareToInfo').find('tr');
+    if (usersTr && usersTr.length > 0) {
+        usersTr = usersTr.slice(1);
+    }
     let newShareInfo = [];
     for(let i = 0; i < usersTr.length; i++){
         let userTr = usersTr[i];

二进制
web/dest/css/logo.png