Forráskód Böngészése

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhangweicheng 7 éve
szülő
commit
f2eeb71a01

+ 5 - 2
config/gulpConfig.js

@@ -27,15 +27,18 @@ module.exports = {
     ],
     pm_css:[
         'lib/ztree/css/zTreeStyle.css',
-        'lib/spreadjs/sheets/css/gc.spread.sheets.sc.css'
+        'lib/spreadjs/sheets/css/gc.spread.sheets.sc.css',
+        'lib/jquery-contextmenu/jquery.contextMenu.css'
     ],
     pm_jspaths:[
         'public/web/date_util.js',
         'public/web/tree_sheet/tree_sheet_helper.js',
+        'public/web/sheet/sheet_data_helper.js',
         'public/web/common_ajax.js',
         'lib/JSExpressionEval_src/Date.js',
         'web/building_saas/pm/js/**/*.js',
-        'lib/ztree/*.js'
+        'lib/ztree/*.js',
+        'lib/jquery-contextmenu/jquery.contextMenu.min.js'
     ],
     main_css:[
         'lib/ztree/css/zTreeStyle.css',

+ 2 - 2
lib/jquery-ui/jquery-ui.css

@@ -1063,7 +1063,7 @@ a.ui-button:active,
 	width: 16px;
 	height: 16px;
 }
-.ui-icon,
+/*.ui-icon,
 .ui-widget-content .ui-icon {
 	background-image: url("images/ui-icons_444444_256x240.png");
 }
@@ -1090,7 +1090,7 @@ a.ui-button:active,
 }
 .ui-button .ui-icon {
 	background-image: url("images/ui-icons_777777_256x240.png");
-}
+}*/
 
 /* positioning */
 .ui-icon-blank { background-position: 16px 16px; }

+ 13 - 3
modules/complementary_ration_lib/models/searchModel.js

@@ -10,16 +10,26 @@ let stdSectionTreeModel = require ('../../ration_repository/models/ration_sectio
 let stdRationModel = require ('../../ration_repository/models/ration_item').Model;
 
 class SearchDao{
-    async getRationItem(userId, rationRepIds, code, callback){
+    async getRationItem(userId, rationRepIds, code, ID, callback){
         let ration = null;
         try{
-            let stdRation = await stdRationModel.findOne({rationRepId: {$in: rationRepIds}, code: code, $or: [{isDeleted: null}, {isDeleted: false}]});
+            let stdQuery = {rationRepId: {$in: rationRepIds}, code: code, $or: [{isDeleted: null}, {isDeleted: false}]};
+            if(ID){
+                stdQuery = {ID: ID, $or: [{isDeleted: null}, {isDeleted: false}]};
+            }
+            //let stdRation = await stdRationModel.findOne({rationRepId: {$in: rationRepIds}, code: code, $or: [{isDeleted: null}, {isDeleted: false}]});
+            let stdRation = await stdRationModel.findOne(stdQuery);
             if(isDef(stdRation)){
                 ration = stdRation._doc;
                 ration.type = 'std';
             }
             else{
-                let compleRation = await compleRationModel.findOne({userId: userId, rationRepId: {$in: rationRepIds}, code: code, deleteInfo: null});
+                let compleQuery = {userId: userId, rationRepId: {$in: rationRepIds}, code: code, deleteInfo: null};
+                if(ID){
+                    compleQuery = {ID: ID, deleteInfo: null};
+                }
+                //let compleRation = await compleRationModel.findOne({userId: userId, rationRepId: {$in: rationRepIds}, code: code, deleteInfo: null});
+                let compleRation = await compleRationModel.findOne(compleQuery);
                 if(isDef(compleRation)){
                     ration = compleRation._doc;
                     ration.type = 'complementary';

+ 23 - 1
modules/main/controllers/ration_controller.js

@@ -45,7 +45,8 @@ module.exports = {
     },
     insertGLJAsRation:insertGLJAsRation,
     replaceRations:replaceRations,
-    addNewRation:addNewRation
+    addNewRation:addNewRation,
+    addMultiRation: addMultiRation
 };
 
 async function addNewRation(req,res) {
@@ -67,6 +68,27 @@ async function addNewRation(req,res) {
     res.json(result);
 }
 
+async function addMultiRation(req,res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        if(typeof data === 'object'){
+            data = JSON.stringify(data);
+        }
+        data = JSON.parse(data);
+        console.log(`data`);
+        console.log(data);
+        result.data = await ration_facade.addMultiRation(data.newDatas);
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
 async function replaceRations(req,res) {
     let result={
         error:0

+ 15 - 4
modules/main/facade/ration_facade.js

@@ -23,7 +23,8 @@ let projectModel = mongoose.model('projects');
 
 module.exports = {
     replaceRations: replaceRations,
-    addNewRation:addNewRation
+    addNewRation:addNewRation,
+    addMultiRation: addMultiRation
 };
 async function addNewRation(data) {
     let query = data.itemQuery;
@@ -31,8 +32,8 @@ async function addNewRation(data) {
     let startTime = +new Date();
     if(query){
         let searchDao = new SearchDao();
-        stdRation = await searchDao.getRationItem(query.userID,[query.rationRepId],query.code);
-        data.newData.code = query.code;
+        stdRation = await searchDao.getRationItem(query.userID,[query.rationRepId],query.code, query.ID);
+        //data.newData.code = query.code;
     }
     let stdRationTime = +new Date();
     console.log("取std定额时间-------------------------------"+(stdRationTime - startTime));
@@ -49,6 +50,15 @@ async function addNewRation(data) {
     }
 }
 
+async function addMultiRation(datas) {
+    let rst = [];
+    for(let data of datas){
+        let r = await addNewRation(data);
+        rst.push(r);
+    }
+    return rst;
+}
+
 async function  updateSerialNo(serialNoUpdate){
     let tasks=[];
     for(let data of serialNoUpdate){
@@ -72,6 +82,7 @@ async function  updateSerialNo(serialNoUpdate){
 async function insertNewRation(newData,firstLibID,std,calQuantity) {//插入新的定额
     let startTime = +new Date();
     if(std){
+        newData.code = std.code;
         newData.name = std.name;
         newData.caption = std.caption;
         newData.unit = std.unit;
@@ -109,7 +120,7 @@ async function replaceRations(userID,data) {
     let searchDao = new SearchDao();
     let recodes = [];
     for(let recode of data.nodeInfo){
-        let stdRation = await searchDao.getRationItem(userID,data.libIDs,recode.newCode);
+        let stdRation = await searchDao.getRationItem(userID,data.libIDs,recode.newCode, null);
         let newRecode = await replaceRation(recode,stdRation,data.firstLibID,data.projectID,data.calQuantity);
         if(newRecode){
             recodes.push(newRecode);

+ 1 - 0
modules/main/routes/ration_route.js

@@ -12,6 +12,7 @@ module.exports = function (app) {
     rationRouter.post('/insertGLJAsRation', rationController.insertGLJAsRation);
     rationRouter.post('/replaceRations', rationController.replaceRations);
     rationRouter.post('/addNewRation', rationController.addNewRation);
+    rationRouter.post('/addMultiRation', rationController.addMultiRation);
 
     app.use('/ration', rationRouter);
 };

+ 45 - 20
modules/reports/util/rpt_construct_data_util.js

@@ -437,9 +437,9 @@ function filterData(sourceData, handleCfg, prjData) {
                     rst = compVal.indexOf(src) >= 0;
                 } else {
                     //string,需要转类型
-                    let newCv = JSON.parse(compVal);
-                    if (newCv instanceof Array) {
-                        rst = newCv.indexOf(src) >= 0;
+                    let newInCv = JSON.parse(compVal);
+                    if (newInCv instanceof Array) {
+                        rst = newInCv.indexOf(src) >= 0;
                     } else {
                         rst = false;
                     }
@@ -450,9 +450,9 @@ function filterData(sourceData, handleCfg, prjData) {
                     rst = compVal.indexOf(src) < 0;
                 } else {
                     //string,需要转类型
-                    let newCv = JSON.parse(compVal);
-                    if (newCv instanceof Array) {
-                        rst = newCv.indexOf(src) < 0;
+                    let newNotInCv = JSON.parse(compVal);
+                    if (newNotInCv instanceof Array) {
+                        rst = (newNotInCv.indexOf(src) < 0);
                     } else {
                         rst = true;
                     }
@@ -465,12 +465,25 @@ function filterData(sourceData, handleCfg, prjData) {
     };
     let private_chkArrVal = function(arr, key, compVal, compStr){
         let rst = false;
-        for (let arrItem of arr) {
-            if (arrItem[key]) {
-                rst = private_chkVal(arrItem[key], compVal, compStr);
+        if (arr.length > 0) {
+            for (let arrItem of arr) {
+                if (arrItem[key]) {
+                    rst = private_chkVal(arrItem[key], compVal, compStr);
+                }
+                if (rst) {
+                    break;
+                }
             }
-            if (rst) {
-                break;
+        } else {
+            //在某些判断条件下(含有'非'判断),如arr没有数组项,默认结果反而是true
+            switch (compStr) {
+                case "!=" :
+                case "!==" :
+                case "not in":
+                    rst = true;
+                    break;
+                default:
+                    break;
             }
         }
         return rst;
@@ -560,11 +573,27 @@ function filterData(sourceData, handleCfg, prjData) {
             }
             startIdx++;
             if (!compRst) {
-                break; //不符合条件的数据则退出(这里的判断条件是and关系)
+                break; //不符合条件的数据则退出(这里的判断条件是and关系)
             }
         }
         return compRst;
     };
+    let private_sub_filter_compare = function (dtlItem, subFilters) {
+        let cmpRst = false;
+        for (let dtlCfg of subFilters) {
+            cmpRst = private_filter_compare(dtlItem, dtlCfg);
+            if (cmpRst) {
+                if (dtlCfg[JV.PROP_OTHER_SUB_FILTER] && dtlCfg[JV.PROP_OTHER_SUB_FILTER].length > 0) {
+                    cmpRst = private_sub_filter_compare(dtlItem, dtlCfg[JV.PROP_OTHER_SUB_FILTER]);
+                    if (cmpRst) break;
+                } else {
+                    break;
+                }
+            }
+        }
+        return cmpRst;
+    };
+
     for (let item of tempRstArr) {
         if (private_filter_compare(item, handleCfg)) {
             rstArr.push(item);
@@ -573,19 +602,15 @@ function filterData(sourceData, handleCfg, prjData) {
     if (handleCfg[JV.PROP_OTHER_SUB_FILTER] && handleCfg[JV.PROP_OTHER_SUB_FILTER].length > 0) {
         let newRstArr = [];
         for (let dtlItem of rstArr) {
-            let cmpRst = false;
-            for (let dtlCfg of handleCfg[JV.PROP_OTHER_SUB_FILTER]) {
-                cmpRst = private_filter_compare(dtlItem, dtlCfg);
-                if (cmpRst) {
-                    newRstArr.push(dtlItem);
-                    break;
-                }
+            let cmpRst = private_sub_filter_compare(dtlItem, handleCfg[JV.PROP_OTHER_SUB_FILTER]);
+            if (cmpRst) {
+                newRstArr.push(dtlItem);
             }
         }
         rstArr = newRstArr;
     }
     replaceActDataArr(sourceData, rstArr);
-    // fsUtil.writeObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/filteredRst.js");
+    // fsUtil.writeObjToFile(sourceData.data, "D:/GitHome/ConstructionCost/tmp/filteredRst.jsp");
 }
 
 function adjustData(sourceData, adjustCfg) {

+ 1 - 1
modules/std_billsGuidance_lib/facade/facades.js

@@ -39,7 +39,7 @@ async function getLibWithBills(libID){
     if(!billsLib){
         throw '引用的清单规则库不存在!';
     }
-    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId, deleted: false}, '-_id code name ID NextSiblingID ParentID');
+    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId, deleted: false});
     return {guidanceLib: guidanceLib[0], bills};
 }
 

+ 5 - 2
modules/users/models/user_model.js

@@ -17,14 +17,17 @@ class UserModel extends BaseModel {
      *
      * @var {object}
      */
-    province = ['广东省', '北京市'];
+    province = ['北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', '上海', '江苏', '浙江', '安徽',
+        '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '广西', '海南', '重庆', '四川', '贵州', '云南', '西藏',
+        '陕西', '甘肃', '青海', '宁夏', '新疆', '台湾', '香港', '澳门',];
 
     /**
      * 企业类型
      *
      * @var
      */
-    companyType = ['设计', '施工'];
+    companyType = ['建设单位', '设计单位',  '施工单位', '监理单位', '审核单位', '咨询公司', '招标代理', '住建部', '财政', '审计',
+        '造价管理站', '学校', '个人', '其他'];
 
     /**
      * 企业类型

+ 3 - 0
public/web/PerfectLoad.js

@@ -4,6 +4,9 @@
 
 jQuery.bootstrapLoading = {
     start: function (options) {
+        if($('#loadingPage').is(':visible')){
+            return;
+        }
         var defaults = {
             opacity: 0.5,
             //loading页面透明度

+ 21 - 4
public/web/treeDataHelper.js

@@ -1,7 +1,8 @@
 /**
  * Created by Tony on 2017/1/23.
  */
-const NODE_ID = "ID", P_ID = "ParentID", NEXT_ID = "NextSiblingID", ADHOC_PRE_ID="Previous_ID", CHILDREN_NODE = "items", SUB_ID = "sub_ids", EMPTY_ID_VAL = -1, TREE_LEVEL = 'treeLevel';
+const NODE_ID = "ID", P_ID = "ParentID", NEXT_ID = "NextSiblingID", ADHOC_PRE_ID="Previous_ID", CHILDREN_NODE = "items", SUB_ID = "sub_ids",
+      EMPTY_ID_VAL = -1, TREE_LEVEL = 'treeLevel', TOP_BILL_ID = "topBillID";
 
 let tree_Data_Helper = {
     buildTreeNodeDirectly: function(data, addLevel) {
@@ -16,7 +17,7 @@ let tree_Data_Helper = {
             }
             return tmpNodeRst;
         };
-        let private_buildNodeData = function(parentItem, idArr, treeLevel) {
+        let private_buildNodeData = function(parentItem, idArr, treeLevel, tbID) {
             let iter = [], nextNode = private_getStartNode(idArr);
             while (nextNode !== null && nextNode !== undefined ) {
                 if (parentItem) {
@@ -25,11 +26,27 @@ let tree_Data_Helper = {
                     rst.push(nextNode);
                 }
                 iter.push(nextNode);
+                nextNode[TOP_BILL_ID] = tbID;
+                if (parentItem === null) {
+                    nextNode[TOP_BILL_ID] = nextNode[NODE_ID];
+                    if (nextNode.flags && nextNode.flags.length > 0) {
+                        for (let flag of nextNode.flags) {
+                            if (flag.fieldName === "fixed") {
+                                nextNode[TOP_BILL_ID] = flag.flag;
+                                break;
+                            }
+                        }
+                    }
+                }
                 if (addLevel) nextNode[TREE_LEVEL] = treeLevel;
                 nextNode = tmpNodes[prefix + nextNode[NEXT_ID]];
             }
             for (let i = 0; i < iter.length; i++) {
-                private_buildNodeData(iter[i], iter[i][SUB_ID], (treeLevel + 1));
+                let rtbID = tbID;
+                if (parentItem === null) {
+                    rtbID = iter[i][TOP_BILL_ID];
+                }
+                private_buildNodeData(iter[i], iter[i][SUB_ID], (treeLevel + 1), rtbID);
             }
         };
 
@@ -52,7 +69,7 @@ let tree_Data_Helper = {
                 tmpNodes[prefix + data[i][P_ID]][SUB_ID].push(data[i][NODE_ID]);
             }
         }
-        private_buildNodeData(null, topArr, 0);
+        private_buildNodeData(null, topArr, 0, -1);
         //try to release and return
         tmpNodes = null;
         topArr.length = 0;

+ 3 - 0
public/web/tree_sheet/tree_sheet_helper.js

@@ -333,6 +333,9 @@ var TREE_SHEET_HELPER = {
                 else if(sheetName === 'stdRationLib_chapter'){
                     sessionStorage.setItem('stdRationLibExpState', rationLibObj.tree.getExpState(rationLibObj.tree.items));
                 }
+                else if(sheetName === 'stdBillsGuidance_bills'){
+                    sessionStorage.setItem('stdBillsGuidanceExpState', billsGuidance.bills.tree.getExpState(billsGuidance.bills.tree.items));
+                }
                 TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
                     let iCount = node.posterityCount(), i, child;
                     for (i = 0; i < iCount; i++) {

+ 5 - 3
test/unit/reports/test_rpt_test_template.js

@@ -26,7 +26,9 @@ cfgCacheUtil.setupDftCache();
 let fsUtil = require("../../../public/fsUtil");
 
 let demoPrjId = - 1;
-let demoRptId = 275, pagesize = "A4"; //11-2表(新)
+let demoRptId = 279, pagesize = "A4";
+//288: 11-2表(新)
+//279: 04
 
 // let userId_Leng = "59cdf14a0034a1000ba52b97"; //小冷User Id 换成_id了 QQ号
 let userId_Leng = "5acac1e885bf55000bd055ba"; //小冷User Id2
@@ -62,8 +64,8 @@ test('测试 - 测试模板啦: ', function (t) {
                 try {
                     // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject_测试模板.jsp");
                     let tplData = rptDataUtil.assembleData(rawDataObj);
-                    // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataAfterCacl_测试模板.jsp");
-                    // fsUtil.writeObjToFile(tplData, "D:/GitHome/ConstructionCost/tmp/rptTplAssembledData_测试模板.jsp");
+                    fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataAfterCacl_测试模板.jsp");
+                    fsUtil.writeObjToFile(tplData, "D:/GitHome/ConstructionCost/tmp/rptTplAssembledData_测试模板.jsp");
                     //it's time to build the report!!!
                     let printCom = JpcEx.createNew();
                     rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE] = pagesize;

+ 10 - 2
web/building_saas/main/html/main.html

@@ -263,11 +263,19 @@
                                           <button id="guidanceInsertRation" class="btn btn-primary btn-sm mx-3" type="button">插入定额</button>
                                           <button id="guidanceInsertBills" class="btn btn-primary btn-sm mx-3" type="button">插入清单</button>
                                       </div>
+                                      <!--搜索结果窗体-->
+                                      <div class="side-search-box col-12 p-2" id="billsGuidanceSearchResult" style="display: none;">
+                                          <div class="d-flex justify-content-between">
+                                              <span id = 'billsGuidanceSearchResultCount'>搜索结果:5</span>
+                                              <a class="btn btn-secondary btn-sm" href="javascript:void(0);" id="nextBillsGuidance">查找下一条</a>
+                                              <a title="关闭搜索" class="btn btn-link btn-sm" href="javascript:void(0);" id="closeSearchBillsGuidance"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                                          </div>
+                                      </div>
                                   </div>
                                   <div class="row" style="margin-left: 1px;">
-                                      <div id="billsGuidance_bills" class="main-data-side-zb" style="width: 49%; float: left; margin: 0; padding: 0;">
+                                      <div 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: 50%; float: left; margin: 0; padding: 0;">
+                                      <div id="billsGuidance_items" class="main-data-side-zi" style="width: 46%; float: left; margin: 0; padding: 0;">
                                       </div>
                                   </div>
                               </div>

+ 107 - 0
web/building_saas/main/js/models/ration.js

@@ -434,6 +434,113 @@ var Ration = {
                 }
             })
         };
+        ration.prototype.addMultiRation = function (items, callback) {
+            let me = this;
+            let project = projectObj.project, sheetController = projectObj.mainController;
+            let engineering = projectInfoObj.projectInfo.property.engineering;
+            let selected = project.mainTree.selected, newSource = null, newNode = null,pre=null,br=null;
+            let billItemID = null,serialNo=1,nextID=null;
+            let needInstall = false;
+            let newDatas = [];
+            if (selected === null) { return; }
+            if (selected.sourceType === project.Bills.getSourceType() && selected.depth() > 0) {
+                if (selected.source.children.length > 0) {
+                    alert('当前清单已有清单子项,不能套用定额。');
+                } else if (selected.data.calcBase&&selected.data.calcBase!="") {
+                    alert('当前有基数计算不能插入定额/量价/工料机。');
+                } else {
+                    if(selected.data.type === billType.FB){
+                        return;
+                    }
+                    billItemID = selected.source.getID();
+                    nextID = selected.tree.rootID();
+                    br = this.getBillsSortRation(billItemID);
+                    serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1
+                }
+            } else if (selected.sourceType === project.Ration.getSourceType()) {
+                billItemID = selected.getParentID();
+                br = this.getBillsSortRation(billItemID);
+                serialNo = selected.data.serialNo+1;
+                nextID = selected.getNextSiblingID();
+                pre = selected.source;
+            };
+            if(billItemID){
+                let calQuantity = optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan');
+                if(engineering==engineeringType.BUILD_IN) {//如果是安装工程,要看需不需要生成安装增加费
+                    let billsNode = project.mainTree.getNodeByID(billItemID);
+                    needInstall = project.Bills.isFBFX(billsNode);//在分部分项插入的定额才需要定额安装增加费
+                }
+                for(let i = 0; i < items.length; i++){
+                    let newData = me.getTempRationData(me.getNewRationID(), billItemID, serialNo, items[i].rationType);
+                    serialNo++;
+                    let brUpdate = [];
+                    //更新兄弟节点的序列号
+                    if (i ===0 && pre) {
+                        let preIndex = br.indexOf(pre), i;
+                        for (i = preIndex + 1; i < br.length; i++) {
+                            br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo + items.length - 1 : br[i].serialNo + items.length;
+                            brUpdate.push({projectID:newData.projectID,ID:br[i].ID,serialNo:br[i].serialNo});
+                        }
+                    }
+                    newDatas.push({itemQuery: items[i].itemQuery, newData: newData, firstLibID: rationLibObj.getFirstStdRationLibID(), calQuantity: calQuantity, brUpdate: brUpdate, needInstall: needInstall})
+                }
+                let showLoding = true;
+                $.bootstrapLoading.start();
+                //保证由于异步的关系loading界面被隐藏,比如清单指引插入清单定额时,endUpdate中提前隐藏了loading
+                let interval =setInterval(function () {
+                    if(!$('#loadingPage').is(':visible') && showLoding){
+                        $.bootstrapLoading.start();
+                        clearInterval(interval);
+                    }
+                    else{
+                        clearInterval(interval);
+                    }
+                }, 100);
+                CommonAjax.post("/ration/addMultiRation",{newDatas: newDatas},function (rstData) {
+                    let newNodes = [];
+                    //更新缓存
+                    for(let data of rstData){
+                        me.datas.push(data.ration);
+                        project.ration_glj.addDatasToList(data.ration_gljs);
+                        project.ration_coe.addDatasToList(data.ration_coes);
+                        project.ration_installation.addDatasToList(data.ration_installs);
+
+                        //插入树节点
+                        newSource = data.ration;
+                        newNode = project.mainTree.insert(billItemID, nextID, newSource.ID);
+                        newNodes.push(newNode);
+                        nextID = project.mainTree.selected.getNextSiblingID();
+                        newNode.source = newSource;
+                        newNode.sourceType = project.Ration.getSourceType();
+                        newNode.data = newSource;
+                        ProjectController.syncDisplayNewNode(sheetController, newNode);
+                    }
+                    project.projectGLJ.loadData(function () {
+                        for(let data of rstData){
+                            project.ration_glj.addToMainTree(data.ration_gljs);
+                        }
+                        projectObj.mainController.refreshTreeNode(newNodes, false);
+                        if(project.Bills.isFBFX(newNodes[0])) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
+                            project.installation_fee.calcInstallationFee(function (isChange,rations) {
+                                if(isChange){
+                                    rations = rations.concat(newNodes);
+                                    project.calcProgram.calcRationsAndSave(rations);
+                                }else {
+                                    project.calcProgram.calcRationsAndSave(newNodes);
+                                }
+                            });
+                        }else {
+                            project.calcProgram.calcNodesAndSave(newNodes);
+                        }
+                        if(callback){
+                            callback();
+                        }
+                        showLoding = false;
+                        $.bootstrapLoading.end();
+                    });
+                })
+            }
+        };
         ration.prototype.addNewRation = function (itemQuery,rationType) {
             let me = this;
             let project = projectObj.project, sheetController = projectObj.mainController;

+ 236 - 7
web/building_saas/main/js/views/std_billsGuidance_lib.js

@@ -11,6 +11,10 @@
 const billsGuidance = (function () {
 
     const libSel = $('#stdBillsGuidanceLibSelect');
+    //工作内容
+    let stdBillsJobData = [];
+    //项目特征
+    let stdBillsFeatureData = [];
     const bills = {
         dom: $('#billsGuidance_bills'),
         workBook: null,
@@ -66,6 +70,35 @@ const billsGuidance = (function () {
         events: {
             SelectionChanging: function (sender, info) {
                 billsInitSel(info.newSelections[0].row);
+            },
+            CellDoubleClick: function (sender, args) {
+                let node = bills.tree.items[args.row];
+                if(!node){
+                    return;
+                }
+                if(node.children.length === 0){
+                    //插入清单
+                    let insert = billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, node);
+                    if(insert){
+                        //插入选中的定额
+                        let addRationDatas = getInsertRationData(getCheckedRows());
+                        insertRations(addRationDatas);
+                    }
+                }
+                else {
+                    node.setExpanded(!node.expanded);
+                    //设置展开收起状态
+                    sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
+                    renderSheetFunc(args.sheet, function () {
+                        let iCount = node.posterityCount(), i, child;
+                        for (i = 0; i < iCount; i++) {
+                            child = bills.tree.items[args.row + i + 1];
+                            args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
+                        }
+                        args.sheet.invalidateLayout();
+                    });
+                    args.sheet.repaint();
+                }
             }
         }
     };
@@ -125,7 +158,7 @@ const billsGuidance = (function () {
         },
         headers: [
             {name: '项目指引', dataCode: 'name', width: 300, vAlign: 'center', hAlign: 'left', formatter: '@'},
-            {name: '选择', dataCode: 'name', width: 50, vAlign: 'center', hAlign: 'center', formatter: '@'},
+            {name: '选择', dataCode: 'select', width: 50, vAlign: 'center', hAlign: 'center', formatter: '@'},
         ],
         events: {
             EditStarting: function (sender, args) {
@@ -138,6 +171,32 @@ const billsGuidance = (function () {
                     args.sheet.endEdit(true);
                 }
             },
+            CellDoubleClick: function (sender, args) {
+                if(!bills.tree.selected){
+                    return;
+                }
+                let node = bills.tree.selected.guidance.tree.selected;
+                if(!node){
+                    return;
+                }
+                if(node.children.length === 0){
+                    if(guideItem.headers[args.col]['dataCode'] === 'name'){
+                        insertRations(getInsertRationData([args.row]));
+                    }
+                }
+                else {
+                    node.setExpanded(!node.expanded);
+                    renderSheetFunc(args.sheet, function () {
+                        let iCount = node.posterityCount(), i, child;
+                        for (i = 0; i < iCount; i++) {
+                            child = bills.tree.selected.guidance.tree.items[args.row + i + 1];
+                            args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea);
+                        }
+                        args.sheet.invalidateLayout();
+                    });
+                    args.sheet.repaint();
+                }
+            }
         }
     };
     const options = {
@@ -201,7 +260,6 @@ const billsGuidance = (function () {
             return;
         }
         const Events = GC.Spread.Sheets.Events;
-        let sheet = workBook.getActiveSheet();
         for(let event in events){
             workBook.bind(Events[event], events[event]);
         }
@@ -216,6 +274,7 @@ const billsGuidance = (function () {
                 //默认初始可控制焦点在清单表中
                 module.workBook.focus();
                 sheet.options.isProtected = true;
+                sheet.name('stdBillsGuidance_bills');
             }
             if(module === guideItem){
                 sheet.options.isProtected = true;
@@ -250,6 +309,9 @@ const billsGuidance = (function () {
         module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
         module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting);
         module.tree.loadDatas(datas);
+        if(module === bills){
+            initExpandStat();
+        }
         module.controller.showTreeData();
     }
     //项目指引表焦点控制
@@ -263,8 +325,6 @@ const billsGuidance = (function () {
                 billsNode.guidance.tree.selected = node;
             }
         }
-
-
     }
     //根据项目指引的类型设置单元格类型,定额类型的项目指引为复选框
     //@param {Array}nodes @return {void}
@@ -304,11 +364,36 @@ const billsGuidance = (function () {
             guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
         }
     }
+    //初始化清单的工作内容和项目特征
+    //@param {Number}billsLibId @return {void}
+    function initJobAndCharacter(billsLibId){
+        CommonAjax.post('/stdBillsEditor/getJobContent', {userId: userID, billsLibId: billsLibId}, function (datas) {
+            stdBillsJobData = datas;
+        });
+        CommonAjax.post('/stdBillsEditor/getItemCharacter', {userId: userID, billsLibId: billsLibId}, function (datas) {
+            stdBillsFeatureData = datas;
+        });
+    }
+    //初始化清单展开收起状态
+    //@return {void}
+    function initExpandStat(){
+        //读取展开收起状态
+        let currentExpState = sessionStorage.getItem('stdBillsGuidanceExpState');
+        if(currentExpState){
+            bills.tree.setExpandedByState(bills.tree.items, currentExpState);
+        }
+        //非叶子节点默认收起
+        else{
+            bills.tree.setRootExpanded(bills.tree.roots, false);
+        }
+    }
     //初始选择清单指引库
     //@param {Number}libID @return {void}
     function libInitSel(libID){
         //获取清单
         CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function(rstData){
+            //获取清单库中的工作内容和项目特征
+            initJobAndCharacter(rstData.guidanceLib.billsLibId);
             initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills);
             //每一棵项目指引树挂在清单节点上
             for(let node of bills.tree.items){
@@ -322,8 +407,12 @@ const billsGuidance = (function () {
     //@param {Array}libDats @return {void}
     function initLibs(libDatas){
         libSel.empty();
+        let selectedLib = sessionStorage.getItem('stdBillsGuidance');
         for(let libData of libDatas){
-            let opt = `<option value="${libData.id}">${libData.name}</option>`;
+            let opt = $('<option>').val(libData.id).text(libData.name);
+            if(selectedLib && libData.id == selectedLib){
+                opt.attr('selected', 'selected');
+            }
             libSel.append(opt);
         }
         //初始默认选择
@@ -336,6 +425,67 @@ 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, 1);
+            if(rowV){
+                rst.push(row);
+            }
+        }
+        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 () {
+                //恢复
+                let sheet = guideItem.workBook.getActiveSheet();
+                renderSheetFunc(sheet, function () {
+                    for(let row = 0; row < sheet.getRowCount(); row++){
+                        if(sheet.getValue(row, 1)){
+                            sheet.setValue(row, 1, false);
+                        }
+                    }
+                });
+            });
+        }
+    }
+    //展开至搜索出来点的节点
+    //@param {Array}nodes @return {void}
+    function expandSearchNodes(nodes){
+        let that = this;
+        let billsSheet = bills.workBook.getActiveSheet();
+        renderSheetFunc(billsSheet, function () {
+            function expParentNode(node){
+                if(node.parent && !node.parent.expanded){
+                    node.parent.setExpanded(true);
+                    expParentNode(node.parent);
+                }
+            }
+            for(let node of nodes){
+                expParentNode(node);
+            }
+            TREE_SHEET_HELPER.refreshTreeNodeData(bills.treeSetting, billsSheet, bills.tree.roots, true);
+            TREE_SHEET_HELPER.refreshNodesVisible(bills.tree.roots, billsSheet, true);
+        });
+    }
     //各按钮监听事件
     //@return {void}
     function bindBtn(){
@@ -347,15 +497,94 @@ const billsGuidance = (function () {
         });
         //更改清单指引库
         $('#stdBillsGuidanceLibSelect').change(function () {
+            //关闭搜索窗口
+            $('#billsGuidanceSearchResult').hide();
+            billsLibObj.clearHighLight(bills.workBook);
             libInitSel($(this).select().val());
+            //记住选项
+            sessionStorage.setItem('stdBillsGuidance', $(this).select().val());
+            //清除展开收起状态sessionStorage
+            sessionStorage.removeItem('stdBillsGuidanceExpState');
         });
         //插入定额
         $('#guidanceInsertRation').click(function () {
-
+            let addRationDatas = getInsertRationData(getCheckedRows());
+            insertRations(addRationDatas);
         });
         //插入清单
         $('#guidanceInsertBills').click(function () {
+            //插入清单
+            if(!bills.tree.selected){
+                return;
+            }
+            if(bills.tree.selected.children.length === 0){
+                let insert = billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, bills.tree.selected);
+                if(insert){
+                    //插入选中的定额
+                    let addRationDatas = getInsertRationData(getCheckedRows());
+                    insertRations(addRationDatas);
+                }
+            }
+        });
+        //搜索
+        $('#stdBillsGuidanceSearch>span>button').click(function () {
+            let billsSheet = bills.workBook.getActiveSheet();
+            billsLibObj.clearHighLight(bills.workBook);
+            let keyword = $('#stdBillsGuidanceSearch>input').val();
+            if (!keyword || keyword === '') {
+                $('#billsGuidanceSearchResult').hide();
+                return;
+            }
 
+            let result = bills.tree.items.filter(function (item) {
+                let codeIs = item.data.code ? item.data.code.indexOf(keyword) !== -1 : false;
+                let nameIs = item.data.name ? item.data.name.indexOf(keyword) !== -1 : false;
+                return codeIs || nameIs;
+            });
+            result.sort(function (x, y) {
+                return x.serialNo() - y.serialNo();
+            });
+            if (result.length !== 0) {
+                //展开搜索出来的节点
+                expandSearchNodes(result);
+                //设置记住展开
+                sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items));
+
+                let sel = billsSheet.getSelections();
+                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');
+                }
+
+                $('#nextBillsGuidance').show();
+                $('#nextBillsGuidance').unbind('click');
+                $('#nextBillsGuidance').bind('click', function () {
+                    let cur = bills.tree.selected, resultIndex = result.indexOf(cur), sel = billsSheet.getSelections();
+                    if (resultIndex === result.length - 1) {
+                        bills.controller.setTreeSelected(result[0]);
+                        billsSheet.setSelection(result[0].serialNo(), sel[0].col, 1, 1);
+                        billsInitSel(result[0].serialNo());
+                    } else {
+                        bills.controller.setTreeSelected(result[resultIndex + 1]);
+                        billsSheet.setSelection(result[resultIndex + 1].serialNo(), sel[0].col, 1, 1);
+                        billsInitSel(result[resultIndex + 1].serialNo());
+                    }
+                });
+            } else {
+                billsLibObj.clearHighLight(bills.workBook);
+                $('#nextBillsGuidance').hide();
+            }
+            $('#billsGuidanceSearchResultCount').text('搜索结果:' + result.length);
+            $('#billsGuidanceSearchResult').show();
+        });
+        // 关闭搜索结果
+        $('#closeSearchBillsGuidance').click(function () {
+            $('#billsGuidanceSearchResult').hide();
+            billsLibObj.clearHighLight(bills.workBook);
+            refreshWorkBook();
         });
     }
     //刷新表
@@ -369,7 +598,7 @@ const billsGuidance = (function () {
         }
     }
 
-    return {initViews, bindBtn, refreshWorkBook};
+    return {initViews, bindBtn, refreshWorkBook, bills};
 })();
 
 $(document).ready(function(){

+ 71 - 67
web/building_saas/main/js/views/std_bills_lib.js

@@ -76,6 +76,73 @@ var billsLibObj = {
             billsLibObj.loadStdBills(select.val());
         }
     },
+     sortJobsAndFeatures: function (arr) {
+        arr.sort(function (a, b) {
+            let rst = 0;
+            if(a.serialNo > b.serialNo) rst = 1;
+            else if(a.serialNo < b.serialNo) rst = -1;
+            return rst;
+        });
+    },
+     findData: function (value, field, Array) {
+        var i = 0;
+        for (i = 0; i < Array.length; i++) {
+            if (value[field] == Array[i][field]) {
+                return Array[i];
+            }
+        }
+        return null;
+    },
+    getBillsJobs: function (stdBillsJobData, node) {
+        var jobs = [], i, jobData = null;
+        if (stdBillsJobData && node && node.data.jobs) {
+            for (i = 0; i < node.data.jobs.length; i++) {
+                jobData = this.findData(node.data.jobs[i], 'id', stdBillsJobData);
+                if (jobData) {
+                    jobData.serialNo = node.data.jobs[i].serialNo;
+                    jobs.push(jobData);
+                }
+            }
+        }
+        this.sortJobsAndFeatures(jobs);
+        return jobs;
+    },
+    getBillsFeatures: function (stdBillsFeatureData, node) {
+        var features = [], i, featureData = null;
+        if (stdBillsFeatureData && node && node.data.items) {
+            for (i = 0; i < node.data.items.length; i++) {
+                featureData = this.findData(node.data.items[i], 'id', stdBillsFeatureData);
+                if (featureData) {
+                    featureData.serialNo = node.data.items[i].serialNo;
+                    features.push(featureData);
+                }
+            }
+        }
+        this.sortJobsAndFeatures(features);
+        return features;
+    },
+    insertBills: function (stdBillsJobData, stdBillsFeatureData, node) {
+        if(projectInfoObj.projectInfo.property.lockBills == true){
+            return false;
+        }
+        //特征及内容转化
+        pageCCOprObj.setItemContentNode(node, this.getBillsJobs(stdBillsJobData, node), this.getBillsFeatures(stdBillsFeatureData, node), node.data.name);
+        if (/\//.test(node.data.unit)) {
+            let existB = projectObj.project.Bills.sameStdCodeBillsData(node.data.code);
+            if (existB) {
+                let std = JSON.parse(JSON.stringify(node.data));
+                std.unit = existB.unit;
+                ProjectController.addBills(projectObj.project, projectObj.mainController, std);
+            } else {
+                ConfirmModal.stdBillsUnit.check(node.data, function (std) {
+                    ProjectController.addBills(projectObj.project, projectObj.mainController, std);
+                });
+            }
+        } else {
+            ProjectController.addBills(projectObj.project, projectObj.mainController, node.data);
+        }
+        return true;
+    },
     loadStdBills: function (stdBillsLibID) {
         var that = this;
         var stdBillsJobData, stdBillsFeatureData, stdBills;
@@ -84,51 +151,6 @@ var billsLibObj = {
         }
         that.stdBillsTree  = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
         var stdBillsTreeController = TREE_SHEET_CONTROLLER.createNew(that.stdBillsTree, billsLibObj.stdBillsSpread.getActiveSheet(), billsLibObj.stdBillsTreeSetting);
-        var findData = function (value, field, Array) {
-            var i = 0;
-            for (i = 0; i < Array.length; i++) {
-                if (value[field] == Array[i][field]) {
-                    return Array[i];
-                }
-            }
-            return null;
-        };
-        let sortJobsAndFeatures = function (arr) {
-            arr.sort(function (a, b) {
-                let rst = 0;
-                if(a.serialNo > b.serialNo) rst = 1;
-                else if(a.serialNo < b.serialNo) rst = -1;
-                return rst;
-            });
-        };
-        var getBillsJobs = function (node) {
-            var jobs = [], i, jobData = null;
-            if (stdBillsJobData && node && node.data.jobs) {
-                for (i = 0; i < node.data.jobs.length; i++) {
-                    jobData = findData(node.data.jobs[i], 'id', stdBillsJobData);
-                    if (jobData) {
-                        jobData.serialNo = node.data.jobs[i].serialNo;
-                        jobs.push(jobData);
-                    }
-                }
-            }
-            sortJobsAndFeatures(jobs);
-            return jobs;
-        };
-        var getBillsFeatures = function (node) {
-            var features = [], i, featureData = null;
-            if (stdBillsFeatureData && node && node.data.items) {
-                for (i = 0; i < node.data.items.length; i++) {
-                    featureData = findData(node.data.items[i], 'id', stdBillsFeatureData);
-                    if (featureData) {
-                        featureData.serialNo = node.data.items[i].serialNo;
-                        features.push(featureData);
-                    }
-                }
-            }
-            sortJobsAndFeatures(features);
-            return features;
-        };
         var showJobs = function (jobs) {
             SheetDataHelper.loadSheetHeader(billsLibObj.jobsSetting, billsLibObj.stdBillsJobSpread.getActiveSheet());
             SheetDataHelper.loadSheetData(billsLibObj.jobsSetting, billsLibObj.stdBillsJobSpread.getActiveSheet(), jobs);
@@ -142,9 +164,9 @@ var billsLibObj = {
             $('#stdBillsRemarkTab').hide();
             billsLibObj.refreshBillsRelaSpread();
             billsLibObj.checkBillsRelaSpread();
-            sortJobsAndFeatures(getBillsJobs(node));
-            showJobs(getBillsJobs(node));
-            showFeatures(getBillsFeatures(node));
+            billsLibObj.sortJobsAndFeatures(billsLibObj.getBillsJobs(node));
+            showJobs(billsLibObj.getBillsJobs(node));
+            showFeatures(billsLibObj.getBillsFeatures(node));
         };
         var showBillsRemark = function (node) {
             $('#stdBillsJobTab').hide();
@@ -190,25 +212,7 @@ var billsLibObj = {
                 let selectNode = that.stdBillsTree.items[args.row];
                 let name = selectNode.data.name;
                 if (that.stdBillsTree.items[args.row].children.length === 0) {
-                    if(projectInfoObj.projectInfo.property.lockBills == true){
-                        return;
-                    }
-                    //特征及内容转化
-                    pageCCOprObj.setItemContentNode(that.stdBillsTree.items[args.row], getBillsJobs(that.stdBillsTree.items[args.row]), getBillsFeatures(that.stdBillsTree.items[args.row]), name);
-                    if (/\//.test(selectNode.data.unit)) {
-                        let existB = projectObj.project.Bills.sameStdCodeBillsData(selectNode.data.code);
-                        if (existB) {
-                            let std = JSON.parse(JSON.stringify(selectNode.data));
-                            std.unit = existB.unit;
-                            ProjectController.addBills(projectObj.project, projectObj.mainController, std);
-                        } else {
-                            ConfirmModal.stdBillsUnit.check(selectNode.data, function (std) {
-                                ProjectController.addBills(projectObj.project, projectObj.mainController, std);
-                            });
-                        }
-                    } else {
-                        ProjectController.addBills(projectObj.project, projectObj.mainController, selectNode.data);
-                    }
+                    billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, selectNode);
                 }
                 else{
                     let me = billsLibObj;

+ 6 - 3
web/building_saas/pm/html/project-management.html

@@ -13,6 +13,7 @@
     <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.sc.css">
     <!--zTree-->
     <link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
+    <link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css">
     <!-- endinject -->
 
     <script>
@@ -87,7 +88,7 @@
                 <div class="tab-content">
                     <div class="tab-pane active" id="pm_all" role="tabpanel">
                         <div class="toolsbar">
-                            <div class="tools-btn btn-group align-top">
+                            <!--<div class="tools-btn btn-group align-top">
                                 <a href="javascript:void(0);"  id="add-tender-btn" class="btn btn-sm"><i class="fa fa-sticky-note-o"></i>新建单位工程</a>
                                 <div class="btn-group" role="group">
                                     <a href="javascript:void(0);" class="btn btn-sm dropdown-toggle" data-toggle="dropdown"></a>
@@ -99,11 +100,11 @@
                                 </div>
                                 <a href="javascript:void(0);" class="btn btn-sm" id="rename-btn">重命名</a>
                                 <a href="javascript:void(0);" class="btn btn-sm" id="del-btn">删除</a>
-                               <!-- <a href="javascript:void(0);" class="btn btn-sm" id="move-to-btn">移动到...</a>-->
+                               &lt;!&ndash; <a href="javascript:void(0);" class="btn btn-sm" id="move-to-btn">移动到...</a>&ndash;&gt;
                                 <a href="javascript:void(0);" class="btn btn-sm" id="copy-to-btn">复制到...</a>
                                 <a href="" class="btn btn-sm" id="share-btn">共享</a>
                                 <a href="" class="btn btn-sm" id="cooperate-btn">协同</a>
-                            </div>
+                            </div>-->
                             <legend class="m-0 pb-1">全部</legend>
                         </div>
                         <div class="poj-list" id="projSpread">
@@ -495,6 +496,7 @@
 <script src="/public/web/date_util.js"></script>
 <script src="/web/building_saas/pm/js/pm_tree.js"></script>
 <script src="/public/web/tree_sheet/tree_sheet_helper.js"></script>
+<script src="/public/web/sheet/sheet_data_helper.js"></script>
 <script type="text/javascript" src="/public/web/common_ajax.js"></script>
 <script src="/lib/JSExpressionEval_src/Date.js"></script>
 <script src="/web/building_saas/pm/js/pm_ajax.js"></script>
@@ -503,6 +505,7 @@
 <!-- zTree -->
 <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
 <script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>
+<script src="/lib/jquery-contextmenu/jquery.contextMenu.min.js"></script>
 <!-- endinject -->
 
 </body>

+ 11 - 10
web/building_saas/pm/js/pm_gc.js

@@ -17,15 +17,15 @@ const gcTreeObj = {
             autoUpdate: false
         },
         header: [
-            {name: '工程列表', dataCode: 'name', width: 800, vAlign: 'center', hAlign: 'left'},
-            {name: '删除日期', dataCode: 'deleteDateTime', width: 170, vAlign: 'center', hAlign: 'left'},
-            {name: '创建日期', dataCode: 'createDateTime', width: 170, vAlign: 'center', hAlign: 'left'},
-            {name: '恢复', dataCode: 'recovery', width: 100, vAlign: 'center', hAlign: 'left'},
-            {name: '彻底删除', dataCode: 'delete', width: 100, vAlign: 'center', hAlign: 'left'},
-            {name: '单价文件', dataCode: 'unitPriceFile', width: 100, vAlign: 'center', hAlign: 'left'},
-            {name: '单价文件-清除', dataCode: 'unitPriceFile_delete', width: 100, vAlign: 'center', hAlign: 'left'},
-            {name: '费率文件', dataCode: 'feeRateFile', width: 100, vAlign: 'center', hAlign: 'left'},
-            {name: '费率文件-清除', dataCode: 'feeRateFile_delete', width: 100, vAlign: 'center', hAlign: 'left'}
+            {name: '工程列表', dataCode: 'name', width: 0.5, vAlign: 'center', hAlign: 'left'},
+            {name: '删除日期', dataCode: 'deleteDateTime', width: 0.1, vAlign: 'center', hAlign: 'left'},
+            {name: '创建日期', dataCode: 'createDateTime', width: 0.1, vAlign: 'center', hAlign: 'left'},
+            {name: '恢复', dataCode: 'recovery', width: 0.05, vAlign: 'center', hAlign: 'left'},
+            {name: '彻底删除', dataCode: 'delete', width: 0.05, vAlign: 'center', hAlign: 'left'},
+            {name: '单价文件', dataCode: 'unitPriceFile', width: 0.05, vAlign: 'center', hAlign: 'left'},
+            {name: '单价文件-清除', dataCode: 'unitPriceFile_delete', width: 0.05, vAlign: 'center', hAlign: 'left'},
+            {name: '费率文件', dataCode: 'feeRateFile', width: 0.05, vAlign: 'center', hAlign: 'left'},
+            {name: '费率文件-清除', dataCode: 'feeRateFile_delete', width: 0.05, vAlign: 'center', hAlign: 'left'}
         ],
         //恢复和彻底删除字体色
         style: {
@@ -68,10 +68,11 @@ const gcTreeObj = {
                 allowResizeRows: true,
                 allowResizeColumns: true
             };
+            let workBookWidth = getWorkBookWidth();
             sheet.setColumnCount(headers.length);
             sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
             for(let i = 0, len = headers.length; i < len; i++){
-                sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
+                sheet.setColumnWidth(i, workBookWidth * headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
                 if(headers[i].dataCode === 'unitPriceFile' || headers[i].dataCode === 'feeRateFile'){
                     //合并列
                     sheet.addSpan(0, i, 1, 2, GC.Spread.Sheets.SheetArea.colHeader);

+ 187 - 21
web/building_saas/pm/js/pm_newMain.js

@@ -39,11 +39,11 @@ const projTreeObj = {
             autoUpdate: false
         },
         header: [
-            {name: '工程列表', dataCode: 'name', width: 800, vAlign: 'center', hAlign: 'left'},
-            {name: '工程造价', dataCode: 'engineeringCost', width: 170, vAlign: 'center', hAlign: 'right'},
-            {name: '单价文件', dataCode: 'unitPriceFile', width: 250, vAlign: 'center', hAlign: 'left'},
-            {name: '费率文件', dataCode: 'feeRateFile', width: 250, vAlign: 'center', hAlign: 'left'},
-            {name: '创建日期', dataCode: 'createDateTime', width: 90, vAlign: 'center', hAlign: 'center'}
+            {name: '工程列表', dataCode: 'name', width: 0.48, vAlign: 'center', hAlign: 'left'},
+            {name: '工程造价', dataCode: 'engineeringCost', width: 0.13, vAlign: 'center', hAlign: 'right'},
+            {name: '单价文件', dataCode: 'unitPriceFile', width: 0.15, vAlign: 'center', hAlign: 'left'},
+            {name: '费率文件', dataCode: 'feeRateFile', width: 0.15, vAlign: 'center', hAlign: 'left'},
+            {name: '创建日期', dataCode: 'createDateTime', width: 0.09, vAlign: 'center', hAlign: 'center'}
         ],
         //选中行颜色
         style: {
@@ -110,9 +110,11 @@ const projTreeObj = {
             };
             sheet.setColumnCount(headers.length);
             sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
+            let workBookWidth = getWorkBookWidth();
             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);
+                let width = workBookWidth * headers[i].width;
+                sheet.setColumnWidth(i, width, GC.Spread.Sheets.SheetArea.colHeader);
             }
         };
         me.renderSheetFuc(sheet, fuc);
@@ -124,9 +126,147 @@ const projTreeObj = {
             this.setOptions(newWorkBook, setting.options);
             this.buildHeader(newWorkBook.getActiveSheet(), setting.header);
             this.bindEvent(newWorkBook);
+            this.loadContextMenu()
         }
         return newWorkBook;
     },
+    loadContextMenu: function () {
+        let me = this;
+        $.contextMenu({
+            selector: '#projSpread',
+            build: function ($trigger, e) {
+                let target = SheetDataHelper.safeRightClickSelection($trigger, e, me.workBook);
+                me.initSelection({row: target.row, rowCount: 1}, me.preSelection ? me.preSelection : null, me.workBook.getActiveSheet());
+                return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                "addFolder": {
+                    name: "新建文件夹",
+                    icon: 'fa-folder-o',
+                    disabled: function () {
+                        return false;
+                    },
+                    callback: function (key, opt) {
+                        $("#add-folder-dialog").modal("show");
+                        setTimeout(function () {
+                            $('#folder-name')[0].focus();
+                        }, 300);
+                    }
+                },
+                "addProject": {
+                    name: "新建建设项目",
+                    icon: 'fa-cubes',
+                    disabled: function () {
+                        return false;
+                    },
+                    callback: function (key, opt) {
+                        $('#add-project-dialog').modal('show');
+                        setTimeout(function () {
+                            $('#project-name')[0].focus();
+                        }, 300);
+                    }
+                },
+                "addEngineering": {
+                    name: "新建单项工程",
+                    icon: 'fa-cube',
+                    disabled: function () {
+                        let node = me.tree.selected;
+                        if(node && node.data.projType !== projectType.folder){
+                            return false;
+                        }
+                        return true;
+                    },
+                    callback: function (key, opt) {
+                        let selectedItem = me.tree.selected;
+                        try {
+                            if(selectedItem !== null  && selectedItem.data.projType !== projectType.folder){
+                                $("#add-engineering-dialog").modal("show");
+                                setTimeout(function () {
+                                    $('#engineering-name')[0].focus();
+                                }, 300);
+                            }
+
+                        } catch (error) {
+                            alert(error);
+                        }
+                    }
+                },
+                "addTender": {
+                    name: "新建单位工程",
+                    icon: 'fa-sticky-note-o',
+                    disabled: function () {
+                        return false;
+                    },
+                    callback: function (key, opt) {
+                        //弹出新建单位工程之前,判断当前使用版本,且当前使用单位工程数是否已到最大值
+                        let selectedItem = me.tree.selected;
+                        $("#add-tender-dialog").modal("show");
+                    }
+                },
+                "spr1": '--------',
+                "rename": {
+                    name: "重命名",
+                    icon: 'fa-edit',
+                    disabled: function () {
+                        return !me.tree.selected;
+                    },
+                    callback: function (key, opt) {
+                        $('#rename-name').val(projTreeObj.tree.selected.data.name ? projTreeObj.tree.selected.data.name : '');
+                        $('#rename-dialog').modal('show');
+                        setTimeout(function () {
+                            $('#rename-name')[0].focus();
+                        }, 300);
+                    }
+                },
+                "delete": {
+                    name: "删除",
+                    icon: 'fa-remove',
+                    disabled: function () {
+                        let node = me.tree.selected;
+                        return !node || (node.data.projType === projectType.folder && node.children.length > 0);
+                    },
+                    callback: function (key, opt) {
+                        if (projTreeObj.tree && projTreeObj.tree.selected) {
+                            $('#del').modal('show');
+                        }
+                    }
+                },
+                "copyTo": {
+                    name: "复制到",
+                    icon: 'fa-copy',
+                    disabled: function () {
+                        let node = me.tree.selected;
+                        return !(node && node.data.projType === projectType.tender);
+                    },
+                    callback: function (key, opt) {
+                        let selectedItem = projTreeObj.tree.selected;
+                        try {
+                            let selectedType = selectedItem !== null && selectedItem.data !== undefined ?
+                                selectedItem.data.projType : '';
+                            if (selectedType !== projectType.tender) {
+                                throw '请选择单位工程进行复制';
+                            }
+                        } catch (error) {
+                            alert(error);
+                            return false;
+                        }
+                        $('#copy-to-dialog').modal('show');
+                    }
+                },
+                "spr2": '--------',
+                "share": {
+                    name: "分享",
+                    icon: 'fa-share',
+                    disabled: function () {
+                        return true;
+                    },
+                    callback: function (key, opt) {
+
+                    }
+                },
+            }
+        });
+    },
     getSelStyle: function (backColor) {
         let style = new GC.Spread.Sheets.Style();
         style.backColor = backColor;
@@ -152,6 +292,7 @@ const projTreeObj = {
     initSelection: function (newSel, oldSel = null,sheet) {
         let me = this;
         let node = me.tree.items[newSel.row];
+        node = node ? node : null;
         //恢复底色
         if(oldSel){
             me.setSelStyle(oldSel, me.setting.style.defalutBackColor,sheet);
@@ -839,6 +980,13 @@ const projTreeObj = {
 };
 
 $(document).ready(function() {
+    //列宽随着屏幕改变
+    $(window).resize(function () {
+        autoPmWdith(projTreeObj.workBook, projTreeObj.setting.header);
+        autoPmWdith(gcTreeObj.workBook, gcTreeObj.setting.header);
+
+    });
+
     init();
     $('#tab_pm_all').on('show.bs.tab', function () {
         if(gcTreeObj.workBook){
@@ -883,13 +1031,13 @@ $(document).ready(function() {
     bindModalsHidden($('#add-project-dialog'), $('#add-engineering-dialog'), $('#add-folder-dialog'), $('#rename-dialog'));
 
     // 新增建设项目点击
-    $('#add-project-btn').click(function () {
+    /*$('#add-project-btn').click(function () {
         let selectedItem = projTreeObj.tree.selected;
         $('#add-project-dialog').modal('show');
         setTimeout(function () {
             $('#project-name')[0].focus();
         }, 300);
-    });
+    });*/
 
     // 新增建设项目操作
     $('#addProjOk').click(function () {
@@ -920,7 +1068,7 @@ $(document).ready(function() {
     });
 
     // 新增单项项目点击
-    $("#add-engineering-btn").click(function() {
+   /* $("#add-engineering-btn").click(function() {
         let selectedItem = projTreeObj.tree.selected;
         try {
             if(selectedItem !== null  && selectedItem.data.projType !== projectType.folder){
@@ -933,7 +1081,7 @@ $(document).ready(function() {
         } catch (error) {
             alert(error);
         }
-    });
+    });*/
 
     // 新增单项工程操作
     $("#add-engineering-confirm").click(function() {
@@ -941,11 +1089,11 @@ $(document).ready(function() {
     });
 
     // 新增单位工程点击
-    $("#add-tender-btn").click(function() {
+    /*$("#add-tender-btn").click(function() {
         //弹出新建单位工程之前,判断当前使用版本,且当前使用单位工程数是否已到最大值
         let selectedItem = projTreeObj.tree.selected;
         $("#add-tender-dialog").modal("show");
-    });
+    });*/
 
     //新建单位工程-建设项目提示
     $('#poj-name').change(function () {
@@ -1041,12 +1189,12 @@ $(document).ready(function() {
     });
 
     // 新增文件夹按钮点击
-    $("#add-folder-btn").click(function() {
+    /*$("#add-folder-btn").click(function() {
         $("#add-folder-dialog").modal("show");
         setTimeout(function () {
             $('#folder-name')[0].focus();
         }, 300);
-    });
+    });*/
 
     // 新增文件夹操作
     $("#add-folder-confirm").click(function() {
@@ -1054,11 +1202,11 @@ $(document).ready(function() {
     });
 
     // 删除按钮点击
-    $('#del-btn').click(function() {
+   /* $('#del-btn').click(function() {
         if (projTreeObj.tree && projTreeObj.tree.selected) {
             $('#del').modal('show');
         }
-    });
+    });*/
 
     // 删除时文字替换
     $('#del').on('show.bs.modal', function() {
@@ -1120,7 +1268,7 @@ $(document).ready(function() {
     });
 
     // 重命名按钮点击
-    $('#rename-btn').click(function() {
+    /*$('#rename-btn').click(function() {
         if (!projTreeObj.tree) {
             return false;
         }
@@ -1133,7 +1281,7 @@ $(document).ready(function() {
         setTimeout(function () {
             $('#rename-name')[0].focus();
         }, 300);
-    });
+    });*/
 
     // 重命名操作
     $("#rename-confirm").click(function() {
@@ -1160,7 +1308,7 @@ $(document).ready(function() {
 
 
     // 复制到按钮点击
-    $('#copy-to-btn').click(function () {
+    /*$('#copy-to-btn').click(function () {
         let selectedItem = projTreeObj.tree.selected;
         try {
             let selectedType = selectedItem !== null && selectedItem.data !== undefined ?
@@ -1173,7 +1321,7 @@ $(document).ready(function() {
             return false;
         }
         $('#copy-to-dialog').modal('show');
-    });
+    });*/
     // 复制到弹层替换
   /*  $('#copy-to-dialog').on('show.bs.modal', function () {
         copytoZTree = ConvertTreeToZtree(projTreeObj.tree, $('#treeDemo2'), null);
@@ -1246,6 +1394,24 @@ $(document).ready(function() {
     });
 });
 
+//获取工作表总宽度
+function getWorkBookWidth(){
+    return workBookWidth = $(window).width() - $('.pm-side').width() - 90;
+}
+
+//根据当前工作表的宽度更改比例
+function autoPmWdith(workBook, headers){
+    if(workBook){
+        const sheet = workBook.getActiveSheet();
+        projTreeObj.renderSheetFuc(sheet, function () {
+            let workBookWidth = getWorkBookWidth();
+            for(let col = 0; col < headers.length; col++){
+                sheet.setColumnWidth(col, workBookWidth * headers[col]['width'], GC.Spread.Sheets.SheetArea.colHeader)
+            }
+        });
+    }
+}
+
 /**
  * 初始化数据
  *
@@ -1984,7 +2150,7 @@ function AddFolder() {
         $('#folder-name').val('');
         setDangerInfo($('#folder-name-info'), '', false);
     };
-    if (selectedItem !== null) {
+    if (selectedItem) {
         // 判断是否超过3层
         if(!withinTreble(selectedItem)){
             alert("文件夹不能超过3层");

+ 8 - 6
web/building_saas/report/html/rpt_main.html

@@ -62,13 +62,15 @@
                     <div class="panel">
                         <div class="panel-body">
                             <div class="input-group input-group-sm" role="group">
-                            <span class="input-group-btn">
-                              <button type="button" class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="上一页" onclick="rptControlObj.prePage(this)"><i class="fa fa-chevron-left"></i></button>
-                            </span>
-                                <input class="form-control" id="rpt_page_num" value="" style="width:60px"  data-toggle="tooltip" data-placement="bottom" title="输入页码按回车键,快速跳转">
                                 <span class="input-group-btn">
-                              <button type="button" class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="下一页" onclick="rptControlObj.nextPage(this)"><i class="fa fa-chevron-right"></i></button>
-                            </span>
+                                    <button type="button" class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="首页" onclick="rptControlObj.firstPage(this)"><i class="fa fa-chevron-left"></i><i class="fa fa-chevron-left"></i></button>
+                                    <button type="button" class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="上一页" onclick="rptControlObj.prePage(this)"><i class="fa fa-chevron-left"></i></button>
+                                </span>
+                                <input class="form-control" id="rpt_page_num" value="" onKeydown="rptControlObj.onKeydown(event, this)" style="width:60px"  data-toggle="tooltip" data-placement="bottom" title="输入页码按回车键,快速跳转">
+                                <span class="input-group-btn">
+                                    <button type="button" class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="下一页" onclick="rptControlObj.nextPage(this)"><i class="fa fa-chevron-right"></i></button>
+                                    <button type="button" class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="尾页" onclick="rptControlObj.lastPage(this)"><i class="fa fa-chevron-right"></i><i class="fa fa-chevron-right"></i></button>
+                                </span>
                             </div>
                         </div>
                         <div class="panel-foot text-muted">

+ 33 - 0
web/building_saas/report/js/rpt_main.js

@@ -302,6 +302,10 @@ let rptControlObj = {
             window.location = url;//这里不能使用get方法跳转,否则下载不成功
         }
     },
+    firstPage: function(dom) {
+        let canvas = document.getElementById("rptCanvas");
+        zTreeOprObj.showPage(1, canvas);
+    },
     prePage: function(dom) {
         let canvas = document.getElementById("rptCanvas");
         zTreeOprObj.showPage(zTreeOprObj.currentPage - 1, canvas);
@@ -310,6 +314,35 @@ let rptControlObj = {
         let canvas = document.getElementById("rptCanvas");
         zTreeOprObj.showPage(zTreeOprObj.currentPage + 1, canvas);
     },
+    lastPage: function(dom) {
+        let me = zTreeOprObj;
+        let canvas = document.getElementById("rptCanvas");
+        zTreeOprObj.showPage(me.maxPages, canvas);
+    },
+    onKeydown: function (event, dom) {
+        let me = zTreeOprObj, keyPressed = null;
+        if (window.event) {
+            keyPressed = window.event.keyCode; // IE/Chrome
+        } else {
+            keyPressed = event.which; // Firefox
+        }
+        if (keyPressed == 13) {
+            let pageNum = 1;
+            try {
+                pageNum = parseInt(dom.value);
+            } catch (e) {
+                pageNum = 1;
+            }
+            let canvas = document.getElementById("rptCanvas");
+            if (pageNum < 1) {
+                pageNum = 1;
+            } else if (pageNum > me.maxPages) {
+                pageNum = me.maxPages;
+            }
+            zTreeOprObj.showPage(pageNum, canvas);
+            return false;
+        }
+    },
     changeMargin: function(marginPropStr, marginDom) {
         zTreeOprObj.reportPageCfg.margins[marginPropStr] = marginDom.value;
     },