Browse Source

Merge branch 'master' of http://192.168.1.12:3000/SmartCost/ConstructionCost

zhangyin 7 years ago
parent
commit
92f61f0cbe
51 changed files with 1187 additions and 291 deletions
  1. 2 2
      modules/common/base/base_model.js
  2. 1 1
      modules/glj/models/unit_price_file_model.js
  3. 7 7
      modules/main/facade/labour_coe_facade.js
  4. 50 8
      modules/pm/controllers/pm_controller.js
  5. 17 14
      modules/pm/models/project_model.js
  6. 1 1
      modules/pm/models/project_property_template.js
  7. 1 0
      modules/pm/models/project_schema.js
  8. 1 0
      modules/pm/routes/pm_route.js
  9. 1 1
      modules/ration_glj/facade/ration_glj_facade.js
  10. 10 0
      modules/ration_repository/controllers/ration_controller.js
  11. 23 0
      modules/ration_repository/models/ration_item.js
  12. 1 0
      modules/ration_repository/routes/ration_front_end_routes.js
  13. 2 2
      public/web/rpt_value_define.js
  14. 2 2
      public/web/scMathUtil.js
  15. 5 1
      public/web/sheet/sheet_data_helper.js
  16. 13 0
      public/web/tree_sheet/tree_sheet_controller.js
  17. 4 1
      public/web/tree_sheet/tree_sheet_helper.js
  18. 3 3
      test/unit/reports/test_tpl_09_1.js
  19. 7 5
      web/building_saas/complementary_glj_lib/js/glj.js
  20. 12 1
      web/building_saas/glj/js/project_glj.js
  21. 13 4
      web/building_saas/glj/js/project_glj_spread.js
  22. 30 30
      web/building_saas/main/html/main.html
  23. 7 0
      web/building_saas/main/js/controllers/project_controller.js
  24. 6 4
      web/building_saas/main/js/main.js
  25. 9 11
      web/building_saas/main/js/models/calc_base.js
  26. 2 1
      web/building_saas/main/js/models/calc_program.js
  27. 5 5
      web/building_saas/main/js/models/fee_rate.js
  28. 1 1
      web/building_saas/main/js/models/main_consts.js
  29. 2 1
      web/building_saas/main/js/models/project.js
  30. 16 0
      web/building_saas/main/js/models/project_glj.js
  31. 105 22
      web/building_saas/main/js/models/ration_glj.js
  32. 5 4
      web/building_saas/main/js/views/calc_base_view.js
  33. 4 4
      web/building_saas/main/js/views/calc_program_manage.js
  34. 283 8
      web/building_saas/main/js/views/character_content_view.js
  35. 3 3
      web/building_saas/main/js/views/fee_rate_view.js
  36. 89 23
      web/building_saas/main/js/views/glj_view.js
  37. 10 6
      web/building_saas/main/js/views/main_tree_col.js
  38. 2 2
      web/building_saas/main/js/views/project_property_basicInfo.js
  39. 18 2
      web/building_saas/main/js/views/project_property_bills_quantity_decimal.js
  40. 16 8
      web/building_saas/main/js/views/project_property_decimal_view.js
  41. 8 5
      web/building_saas/main/js/views/project_property_display_view.js
  42. 11 3
      web/building_saas/main/js/views/project_property_labour_coe_view.js
  43. 11 6
      web/building_saas/main/js/views/project_property_projFeature.js
  44. 133 44
      web/building_saas/main/js/views/project_view.js
  45. 19 3
      web/building_saas/main/js/views/std_bills_lib.js
  46. 22 1
      web/building_saas/main/js/views/std_ration_lib.js
  47. 128 0
      web/building_saas/main/js/views/sub_view.js
  48. 5 7
      web/building_saas/pm/html/project-management.html
  49. 1 1
      web/building_saas/pm/js/pm_ajax.js
  50. 59 32
      web/building_saas/pm/js/pm_main.js
  51. 1 1
      web/common/html/header.html

+ 2 - 2
modules/common/base/base_model.js

@@ -22,9 +22,9 @@ class BaseModel {
      * @return {void}
      */
     constructor() {
-        if (new.target === BaseModel) {
+/*        if (new.target === BaseModel) {
             throw new Error('BaseModel不能实例化,只能继承使用。');
-        }
+        }*/
     }
 
     /**

+ 1 - 1
modules/glj/models/unit_price_file_model.js

@@ -120,7 +120,7 @@ class UnitPriceFileModel extends BaseModel {
             return result;
         }
 
-        let condition = {project_id: {$in: idList}};
+        let condition = {project_id: {$in: idList},deleteInfo:null};
         result = await this.findDataByCondition(condition, null, false);
 
         return result;

+ 7 - 7
modules/main/facade/labour_coe_facade.js

@@ -87,22 +87,22 @@ function getData(projectID, callback) {
 // needUpdateDatas: [{ID: 5, value: 2.87}, {ID: 13, value: 2.91}]
 function save (data, callback) {
     let updateArr = [];
-    let datas = JSON.parse(data);
+    // let datas = JSON.parse(data);
 
-    if (datas.libID){
+    if (data.libID){
         let ItemObj = {
             updateOne: {
-                filter: {projectID: datas.projectID},
-                update: { 'libID': datas.projectID, 'libName': datas.libName }
+                filter: {projectID: data.projectID},
+                update: { 'libID': data.projectID, 'libName': data.libName }
             }
         };
         updateArr.push(ItemObj);
     };
 
-    for (let Item of datas.newItemArr) {
+    for (let Item of data.newItemArr) {
          let ItemObj = {
              updateOne: {
-                 filter: {projectID: datas.projectID, 'coes.ID': Item.ID},
+                 filter: {projectID: data.projectID, 'coes.ID': Item.ID},
                  update: { 'coes.$.coe': Item.coe }
              }
          };
@@ -111,7 +111,7 @@ function save (data, callback) {
     // console.log(JSON.stringify(updateArr));
     projectLabourCoesModel.bulkWrite(updateArr)
         .then(function(){
-            logger.info(`Project LabourCoe saved successful : ${datas.projectID}`);
+            logger.info(`Project LabourCoe saved successful : ${data.projectID}`);
             callback(0, '', null);
         })
         .catch(function (err) {

+ 50 - 8
modules/pm/controllers/pm_controller.js

@@ -3,11 +3,15 @@
  */
 import UnitPriceFileModel from "../../glj/models/unit_price_file_model";
 let ProjectsData = require('../models/project_model').project;
+let labourCoe = require('../../main/facade/labour_coe_facade');
 let projType = require('../models/project_model').projType;
 let fileType = require('../models/project_model').fileType;
 const engineering = require("../../common/const/engineering");
 let EngineeringLibModel = require("../../users/models/engineering_lib_model");
 let fee_rate_facade = require("../../fee_rates/facade/fee_rates_facade");
+let billsModel = require('../../main/models/bills').model;
+let rationsModel = require('../../main/models/ration').model;
+let projectModel = require("../models/project_schema");
 
 //统一回调函数
 let callback = function(req, res, err, message, data){
@@ -40,7 +44,7 @@ module.exports = {
         });
     },
     getProjects: function(req, res){
-        ProjectsData.getUserProjects(req.session.sessionUser.ssoId, function(err, message, projects){
+        ProjectsData.getUserProjects(req.session.sessionUser.ssoId, req.session.sessionCompilation._id, function(err, message, projects){
             if (projects) {
                 callback(req, res, err, message, projects);
             } else {
@@ -50,7 +54,7 @@ module.exports = {
     },
     updateProjects: async function (req, res) {
         let data = JSON.parse(req.body.data);
-        await ProjectsData.updateUserProjects(req.session.sessionUser.ssoId, data.updateData, function (err, message, data) {
+        await ProjectsData.updateUserProjects(req.session.sessionUser.ssoId, req.session.sessionCompilation._id, data.updateData, function (err, message, data) {
             if (err === 0) {
                 callback(req, res, err, message, data);
             } else {
@@ -58,6 +62,43 @@ module.exports = {
             }
         });
     },
+    // CSL, 2017-12-14 该方法用于项目属性:提交保存混合型数据,这些数据来自不同的表,包括projects.property、ration、bills、labour_coes.
+    updateMixDatas: function(req, res){
+        let callBackInner = function (err, message, data) {
+            if (err === 0) {
+                res.json({error: err, message: message, data: data});
+            } else {
+                res.json({error: err, message: message, data: null});
+            }
+        };
+
+        let datas = JSON.parse(req.body.data).mixDataArr;
+
+        // 项目属性
+        if (Object.keys(datas.properties).length > 0){
+            projectModel.update({ID: datas.projectID}, datas.properties, callBackInner);
+        };
+
+        // 人工系数
+        if (datas.labourCoes.updateData){
+            datas.labourCoes.updateData.projectID = datas.projectID;
+            labourCoe.save(datas.labourCoes.updateData, callBackInner);
+        };
+
+        // 清单:每文档doc只存储一条清单,每条清单都必须定位一次文档,无法合并处理
+        if (datas.bills.length > 0){
+            for (let bill of datas.bills){
+                billsModel.update({projectID: datas.projectID, ID: bill.ID, deleteInfo: null}, bill, callBackInner);
+            };
+        };
+
+        // 定额:每文档doc只存储一条定额,每条定额都必须定位一次文档,无法合并处理
+        if (datas.rations.length > 0){
+            for (let ration of datas.rations){
+                rationsModel.update({projectID: datas.projectID, ID: ration.ID, deleteInfo: null}, ration, callBackInner);
+            };
+        };
+    },
     updateFiles: async function(req, res){
         let data = JSON.parse(req.body.data);
         let updateDatas = data.updateDatas;
@@ -77,7 +118,7 @@ module.exports = {
     },
     rename: function (req, res) {
         let data = JSON.parse(req.body.data);
-        ProjectsData.rename(req.session.sessionUser.ssoId, data, function (err, message) {
+        ProjectsData.rename(req.session.sessionUser.ssoId, req.session.sessionCompilation._id, data, function (err, message) {
             callback(req, res, err, message, null);
         });
     },
@@ -135,7 +176,7 @@ module.exports = {
         let renderData = {
             userAccount: request.session.userAccount,
             userID: request.session.sessionUser.ssoId,
-            compilationData: sessionCompilation,
+            compilationData: JSON.stringify(sessionCompilation),
             billValuation: JSON.stringify(billValuation),
             rationValuation: JSON.stringify(rationValuation),
             engineeringList: JSON.stringify(engineering.List)
@@ -202,6 +243,7 @@ module.exports = {
 
     getGCDatas: async function(request, response) {
         let userID = request.session.sessionUser.ssoId;
+        let compilatoinId = request.session.sessionCompilation._id;
         let rst = [];
         let _projs = Object.create(null), _engs = Object.create(null), prefix = 'ID_';
         try{
@@ -212,7 +254,7 @@ module.exports = {
                 let gc_uf = gc_unitPriceFiles[i];
                 let theProj = _projs[prefix + gc_uf.root_project_id] || null;
                 if(!theProj){
-                    let tempProj = await ProjectsData.getProjectsByIds([gc_uf.root_project_id]);
+                    let tempProj = await ProjectsData.getProjectsByIds(userID, compilatoinId, [gc_uf.root_project_id]);
                     if(tempProj.length > 0 && tempProj[0].projType !== projType.folder){
                         theProj = _projs[prefix + gc_uf.root_project_id] = tempProj[0]._doc;
                         buildProj(theProj);
@@ -226,7 +268,7 @@ module.exports = {
                 let gc_ff = gc_feeRateFiles[i];
                 let theProj = _projs[prefix + gc_ff.rootProjectID] || null;
                 if(!theProj){
-                    let tempProj = await ProjectsData.getProjectsByIds([gc_ff.rootProjectID]);
+                    let tempProj = await ProjectsData.getProjectsByIds(userID, compilatoinId, [gc_ff.rootProjectID]);
                     if(tempProj.length > 0 && tempProj[0].projType !== projType.folder){
                         theProj = _projs[prefix + gc_ff.rootProjectID] = tempProj[0]._doc;
                         buildProj(theProj);
@@ -241,7 +283,7 @@ module.exports = {
                     let gc_t = gc_tenderFiles[i];
                     let theEng = _engs[prefix + gc_t.ParentID] || null;
                     if(!theEng){
-                        let tempEngs = await ProjectsData.getProjectsByIds([gc_t.ParentID]);
+                        let tempEngs = await ProjectsData.getProjectsByIds(userID, compilatoinId, [gc_t.ParentID]);
                         if(tempEngs.length > 0 && tempEngs[0].projType === projType.engineering){
                             theEng = _engs[prefix + gc_t.ParentID] = tempEngs[0]._doc;
                             theEng.children = [];
@@ -251,7 +293,7 @@ module.exports = {
                         theEng.children.push(gc_t);
                         let theProj = _projs[prefix + theEng.ParentID] || null;
                         if(!theProj){
-                            let tempProj = await ProjectsData.getProjectsByIds([theEng.ParentID]);
+                            let tempProj = await ProjectsData.getProjectsByIds(userID, compilatoinId, [theEng.ParentID]);
                             if(tempProj.length > 0 && tempProj[0].projType === projType.project){
                                 theProj = _projs[prefix + theEng.ParentID] = tempProj[0]._doc;
                                 buildProj(theProj);

+ 17 - 14
modules/pm/models/project_model.js

@@ -30,8 +30,8 @@ let fileType = {
 
 let ProjectsDAO = function(){};
 
-ProjectsDAO.prototype.getUserProjects = function(userId, callback){
-    Projects.find({'$or': [{'userID': userId, 'deleteInfo': null}, {'userID': userId, 'deleteInfo.deleted': {'$in': [null, false]}}]}, '-_id', function(err, templates){
+ProjectsDAO.prototype.getUserProjects = function(userId, compilation, callback){
+    Projects.find({'$or': [{'userID': userId, 'compilation': compilation, 'deleteInfo': null}, {'userID': userId, 'compilation': compilation, 'deleteInfo.deleted': {'$in': [null, false]}}]}, '-_id', function(err, templates){
         if (err) {
             callback(1, 'Error', null);
         } else {
@@ -50,7 +50,7 @@ ProjectsDAO.prototype.getUserProject = function (userId, ProjId, callback) {
     });
 }
 
-ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callback){
+ProjectsDAO.prototype.updateUserProjects = async function(userId, compilationId, datas, callback){
     let data, project, updateLength = 0, hasError = false, deleteInfo = null, i, newProject;
     let updateAll = function (err) {
             if (!err){
@@ -72,8 +72,10 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
             }
             if (data.updateType === 'update') {
                 Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll);
-            } else if (data.updateType === 'new') {
+            }
+            else if (data.updateType === 'new') {
                 data.updateData['userID'] = userId;
+                data.updateData['compilation'] = compilationId;
                 data.updateData['createDateTime'] = new Date();
                 // 如果没有选中单价文件则新增单价文件
                 if (data.updateData.projType === projectType.tender && data.updateData.property !== null &&
@@ -112,7 +114,7 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                 }
                 newProject = new Projects(data.updateData);
                 // 查找同级是否存在同名数据
-                let exist = await this.isExist(data.updateData.name, data.updateData.ParentID);
+                let exist = await this.isExist(userId, compilationId, data.updateData.name, data.updateData.ParentID);
                 if (exist) {
                     callback(1, '同级目录已存在相同名称数据.', null);
                     return;
@@ -135,7 +137,8 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                         updateAll(err);
                     }
                 });
-            } else if (data.updateType === 'delete') {
+            }
+            else if (data.updateType === 'delete') {
                 deleteInfo = {};
                 deleteInfo['deleted'] = true;
                 deleteInfo['deleteDateTime'] = new Date();
@@ -189,7 +192,8 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                 catch (error){
                     callback(1, error, null);
                 }
-            } else {
+            }
+            else {
                 hasError = true;
                 callback(1, '提交数据错误.', null);
             }
@@ -270,7 +274,7 @@ ProjectsDAO.prototype.copyUserProjects = function (userId, datas, callback) {
     }
 };
 
-ProjectsDAO.prototype.rename = async function (userId, data, callback){
+ProjectsDAO.prototype.rename = async function (userId, compilationId, data, callback){
     try {
         if (data.id === undefined || data.id === '') {
             throw '数据错误!';
@@ -280,7 +284,7 @@ ProjectsDAO.prototype.rename = async function (userId, data, callback){
         }
         data.newName = data.newName.trim();
         // 查找同级是否存在同名数据
-        let exist = await this.isExist(data.newName, data.parentID);
+        let exist = await this.isExist(userId, compilationId, data.newName, data.parentID);
         if (exist) {
             throw '同级目录已存在相同名称数据';
         }
@@ -333,8 +337,8 @@ ProjectsDAO.prototype.getProject = function (key, callback) {
     }
 };
 
-ProjectsDAO.prototype.getProjectsByIds = async function (ids){
-    return await Projects.find({ID: {$in: ids}});
+ProjectsDAO.prototype.getProjectsByIds = async function (userId, compilationId, ids){
+    return await Projects.find({userID: userId, compilation: compilationId, ID: {$in: ids}});
 };
 
 ProjectsDAO.prototype.getGCFiles = async function (fileType, userID){
@@ -470,12 +474,12 @@ ProjectsDAO.prototype.recGC = async function(userID, datas, callback){
  * @param {Object} data
  * @return {Boolean}
  */
-ProjectsDAO.prototype.isExist = async function(name, parentID) {
+ProjectsDAO.prototype.isExist = async function(userId, compilationId, name, parentID) {
     parentID = parseInt(parentID);
     if (name === '' || isNaN(parentID)) {
         return true;
     }
-    let condition = {ParentID: parentID, name: name, "$or":[{deleteInfo: null}, {"deleteInfo.deleted": false}]};
+    let condition = {userID: userId, compilation: compilationId, ParentID: parentID, name: name, "$or":[{deleteInfo: null}, {"deleteInfo.deleted": false}]};
     let count = await Projects.count(condition);
     return count > 0;
 };
@@ -583,7 +587,6 @@ ProjectsDAO.prototype.changeUnitPriceFileInfo = async function(projectId, change
     return result.ok === 1;
 };
 
-
 module.exports ={
     project: new ProjectsDAO(),
     projType: projectType,

+ 1 - 1
modules/pm/models/project_property_template.js

@@ -13,7 +13,7 @@ const defaultDecimal = {
 };
 const displaySetting = {
     autoHeight:true,
-    disPlayMainMateria:true
+    disPlayMainMaterial:true
 }
 
 /*

+ 1 - 0
modules/pm/models/project_schema.js

@@ -16,6 +16,7 @@ let ProjectSchema = new Schema({
     "projType": String,
     "recentDateTime": Date,
     "createDateTime": Date,
+    "compilation": String,
     "deleteInfo": deleteSchema,
     'fullFolder': Array,
     "property": {

+ 1 - 0
modules/pm/routes/pm_route.js

@@ -31,6 +31,7 @@ module.exports = function (app) {
      data.updateData.updateType: 1 of ['new', 'update', 'delete']
      */
     pmRouter.post('/updateProjects', pmController.updateProjects);
+    pmRouter.post('/updateMixDatas', pmController.updateMixDatas);
 
     /*
      req.body = {data: '{user_id: user_id, updateData: [{updateType, updateData}]}'}

+ 1 - 1
modules/ration_glj/facade/ration_glj_facade.js

@@ -138,7 +138,7 @@ function get_lib_glj_info(ration_glj) {
                     }
                 });
             }else {
-                cb(null,null);
+                cb(null,result);
             }
         })
     }

+ 10 - 0
modules/ration_repository/controllers/ration_controller.js

@@ -18,6 +18,16 @@ module.exports = {
             }
         });
     },
+    getRationGljItemsBySection: async function(req, res){
+        var sectionId = req.body.sectionID;
+        rationItem.getRationGljItemsBySection(sectionId, function(err, message, rst){
+            if (err) {
+                callback(req, res, err, message, null);
+            } else {
+                callback(req, res, err, message, rst);
+            }
+        });
+    },
     mixUpdateRationItems: function(req, res){
         var sectionId = req.body.sectionID,
             rationLibId = req.body.rationLibId,

+ 23 - 0
modules/ration_repository/models/ration_item.js

@@ -43,6 +43,7 @@ var rationItemSchema = mongoose.Schema({
 });
 var rationItemModel = db.model("std_ration_lib_ration_items",rationItemSchema, "std_ration_lib_ration_items")
 var counter = require('../../../public/counter/counter');
+import stdGljListModel from '../../common/std/schemas/std_ration_lib_glj_list';
 
 var rationItemDAO = function(){};
 
@@ -52,6 +53,28 @@ rationItemDAO.prototype.getRationItemsBySection = function(sectionId,callback){
         else callback(false,"Get items successfully", data);
     })
 };
+rationItemDAO.prototype.getRationGljItemsBySection = async function(sectionId,callback){
+    try{
+        let rationItems = await rationItemModel.find({"sectionId": sectionId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]}, null, {sort: {code: 1}});
+        for(let i = 0, len = rationItems.length; i < len; i++){
+            let hint = '';
+            let ration = rationItems[i];
+            for(let j = 0, jLen = ration.rationGljList.length; j < jLen; j++){
+                let rationGlj = ration.rationGljList[j];
+                let glj = await stdGljListModel.find({ID: rationGlj.gljId, $or: [{isDeleted: null}, {isDeleted: false} ]}, '-_id code name unit');
+                if(glj.length > 0){
+                    let unitHint = '' + glj[0].code + ' ' + glj[0].name + '' + glj[0].unit + ' ' + rationGlj.consumeAmt + '</br>';
+                    hint += unitHint;
+                }
+            }
+            ration._doc.hint = hint;
+        }
+        callback(false,"Get items successfully", rationItems);
+    }
+    catch (err){
+        callback(true, "Fail to get items", "")
+    }
+};
 rationItemDAO.prototype.mixUpdateRationItems = function(rationLibId, sectionId, updateItems, addItems, rIds, callback){
     var me = this;
     if (updateItems.length == 0 && rIds.length == 0) {

+ 1 - 0
modules/ration_repository/routes/ration_front_end_routes.js

@@ -21,6 +21,7 @@ module.exports = function (app) {
     apiRouter.post("/getRationTree",rationChapterTreeController.getRationChapterTree);
 
     apiRouter.post("/getRationItems",rationController.getRationItemsBySection);
+    apiRouter.post("/getRationGljItems",rationController.getRationGljItemsBySection);
 
     apiRouter.post("/getGljTree",repositoryGljController.getGljTree);
     apiRouter.post("/getGljItems",repositoryGljController.getGljItems);

+ 2 - 2
public/web/rpt_value_define.js

@@ -213,8 +213,8 @@ const JV = {
     LAYOUT_FULFILL: 4,
 
     OUTPUT_ALIGN: {
-        H: ["Left", "Center", "Right"],
-        V: ["Top", "Center", "Bottom"]
+        H: ["left", "center", "right"],
+        V: ["top", "center", "bottom"]
     },
 
     CAL_TYPE:["percentage","abstract"],

+ 2 - 2
public/web/scMathUtil.js

@@ -19,11 +19,11 @@ let scMathUtil = {
         let iLength = result.length;
         // 因为数值被转为整数计算,当目标位数在小数点后,且数值小于0,需要补齐前面的位数
         if (iLength < -digit){
-            result = zeroString(-digit) + result;
+            result = this.zeroString(-digit) + result;
         }
         // 当目标位数在小数点前,需要补齐后面的位数
         else if ((digit > 0) && (iLength < digit)){
-            result = result + zeroString(digit);
+            result = result + this.zeroString(digit);
         }
         iLength = result.length;
         // 获得小数点前的数字

+ 5 - 1
public/web/sheet/sheet_data_helper.js

@@ -134,6 +134,10 @@ var SheetDataHelper = {
         };
         TipCellType.prototype.processMouseEnter = function (hitinfo) {
             let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
+            let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
+            if(tag !== undefined && tag){
+                text = tag;
+            }
             if (setting.pos && text && text !== '') {
                 if (!this._toolTipElement) {
                     let div = $('#autoTip')[0];
@@ -150,7 +154,7 @@ var SheetDataHelper = {
                         document.body.insertBefore(div, null);
                     }
                     this._toolTipElement = div;
-                    $(this._toolTipElement).text(text).css("top", setting.pos.y + hitinfo.y + 15).css("left", setting.pos.x + hitinfo.x + 15);
+                    $(this._toolTipElement).html(text).css("top", setting.pos.y + hitinfo.y + 15).css("left", setting.pos.x + hitinfo.x + 15);
                     $(this._toolTipElement).show("fast");
                 }
             }

+ 13 - 0
public/web/tree_sheet/tree_sheet_controller.js

@@ -54,6 +54,19 @@ var TREE_SHEET_CONTROLLER = {
                 }
             }
         };
+        controller.prototype.deleteNode = function (node,next) {
+            var that = this;
+            if (node){
+                var row = node.serialNo();
+                if (this.tree.delete(node)) {
+                    TREE_SHEET_HELPER.massOperationSheet(this.sheet, function () {
+                        that.sheet.deleteRows(row,1);
+                        next?that.setTreeSelected(that.tree.items[row]):"";
+                    });
+                }
+            }
+
+        };
         controller.prototype.upLevel = function () {
             var that = this;
             if (this.tree.selected) {

+ 4 - 1
public/web/tree_sheet/tree_sheet_helper.js

@@ -223,7 +223,6 @@ var TREE_SHEET_HELPER = {
             }
             let node = tree.items[options.row];
             let showTreeLine = true;
-
             if (!node) { return; }
 
             let centerX = Math.floor(x) + node.depth() * indent + indent / 2;
@@ -317,6 +316,10 @@ var TREE_SHEET_HELPER = {
         };
         TipCellType.prototype.processMouseEnter = function (hitinfo) {
             let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
+            let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
+            if(tag !== undefined && tag) {
+                text = tag;
+            }
             if (setting.pos && text && text !== '') {
                 if (!this._toolTipElement) {
                     let div = $('#autoTip')[0];

+ 3 - 3
test/unit/reports/test_tpl_09_1.js

@@ -40,8 +40,8 @@ let demoRptId = 226, pagesize = "A4";
 
 let userId_Leng = 1142; //小冷User Id
 // demoPrjId = 720; //QA: DW3
-demoPrjId = 838; //QA:
-/*/
+demoPrjId = 1296; //QA:
+//*/
 let userId_Dft = userId_Leng;
 /*/
 let userId_Dft = 76075;
@@ -120,8 +120,8 @@ test('测试 - 测试模板啦: ', function (t) {
         rptTplDataFacade.prepareProjectData(userId_Dft, demoPrjId, filter, function (err, msg, rawDataObj) {
             if (!err) {
                 try {
-                    let tplData = rptDataUtil.assembleData(rawDataObj);
                     // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject.js");
+                    let tplData = rptDataUtil.assembleData(rawDataObj);
                     //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;

+ 7 - 5
web/building_saas/complementary_glj_lib/js/glj.js

@@ -45,7 +45,7 @@ let repositoryGljObj = {
             {headerName:"名称",headerWidth:280,dataCode:"name", dataType: "String", hAlign: "left", vAlign: "center"},
             {headerName:"规格型号",headerWidth:180,dataCode:"specs", dataType: "String", hAlign: "left", vAlign: "center"},
             {headerName:"单位",headerWidth:120,dataCode:"unit", dataType: "String", hAlign: "center", vAlign: "center"},
-            {headerName:"基价单价",headerWidth:120,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
+            {headerName:"定额价",headerWidth:120,dataCode:"basePrice", dataType: "Number", formatter: "0.00", hAlign: "right", vAlign: "center"},
             {headerName:"类型",headerWidth:120,dataCode:"gljType", dataType: "String", hAlign: "center", vAlign: "center"},
             {headerName:"是否新增",headerWidth:80,dataCode:"isComplementary", hAlign: "center", vAlign: "center"}
         ],
@@ -147,8 +147,7 @@ let repositoryGljObj = {
             }
             sheetOpr.cleanData(me.workBook.getSheet(0), me.setting, -1);
             sheetOpr.showData(me.workBook.getSheet(0), me.setting, cacheSection, me.distTypeTree);
-            sheetCommonObj.setStaticCombo(me.workBook.getActiveSheet(), 0, 5, cacheSection.length, me.distTypeTree.comboDatas, false, 'text');
-            sheetCommonObj.setDynamicCombo(me.workBook.getActiveSheet(), cacheSection.length, 5, me.workBook.getActiveSheet().getRowCount() - cacheSection.length, me.distTypeTree.comboDatas, false, 'text');
+            sheetCommonObj.setDynamicCombo(me.workBook.getActiveSheet(), 0, 5, me.workBook.getActiveSheet().getRowCount(), me.distTypeTree.comboDatas, false, 'text');
 
             cacheSection = null;
         }
@@ -165,6 +164,7 @@ let repositoryGljObj = {
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.SelectionChanged, me.onSelectionChanged);
         me.workBook.bind(GC.Spread.Sheets.Events.ButtonClicked, me.onButtonClicked);//复选框点击事件
     },
+
     getCurrentComponent: function (gljComponent) {
         let me = repositoryGljObj, rst = [];
         for(let i = 0; i < gljComponent.length; i++){
@@ -493,7 +493,7 @@ let repositoryGljObj = {
                 }
             }
         }
-        if(me.gljCurTypeId !== 732){
+        if(!me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]){
             rObj.gljClass = me.gljCurTypeId;
         }
         if(updateArr.length >0 || addArr.length >0){
@@ -741,7 +741,9 @@ let repositoryGljObj = {
 
         }
         pasteObj.basePrice = !isNaN(parseFloat(pasteObj.basePrice)) && (pasteObj.basePrice && typeof pasteObj.basePrice !== 'undefined') ? parseFloat(pasteObj.basePrice) : 0;
-        pasteObj.gljClass = me.gljCurTypeId;
+        if(!me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]){
+            pasteObj.gljClass = me.gljCurTypeId;
+        }
         return true;
     },
     canPasted: function (info) {

+ 12 - 1
web/building_saas/glj/js/project_glj.js

@@ -229,6 +229,7 @@ function init() {
             // 赋值
             jsonData = data.gljList !== undefined && data.gljList.length > 0 ? data.gljList : [];
             jsonData= filterProjectGLJ(jsonData);
+            jsonData = sortProjectGLJ(jsonData);
             mixRatioConnectData = data.mixRatioConnectData !== undefined ? data.mixRatioConnectData : mixRatioConnectData;
             mixRatioMap = data.mixRatioMap !== undefined ? data.mixRatioMap : mixRatioMap;
             host = data.constData.hostname !== undefined ? data.constData.hostname : '';
@@ -341,7 +342,9 @@ function successTrigger(field, info) {
             break;
     }
     // 重新加载数据到缓存
-    projectObj.project.projectGLJ.loadData();
+    projectObj.project.projectGLJ.loadData(function () {
+        projectObj.project.projectGLJ.loadCacheData();
+    });
 
     // 更新定额工料机
     gljOprObj.refreshView();
@@ -387,3 +390,11 @@ function filterProjectGLJ(jsonData) {
     return jsonData;
 }
 
+function sortProjectGLJ(jsonData) {
+    if (jsonData.length > 0){
+        jsonData = _.sortByAll(jsonData,[function (item) {
+            return item.unit_price.type+"";
+        },'code']);
+    }
+    return jsonData
+}

+ 13 - 4
web/building_saas/glj/js/project_glj_spread.js

@@ -60,7 +60,7 @@ ProjectGLJSpread.prototype.init = function () {
             ,width:60
         },
         {name: '供货方式', field: 'supply', visible: true, cellType: selectBox,width:80},
-        {name: '甲供数量', field: 'supply_quantity', visible: true,width:100},
+        {name: '甲供数量', field: 'supply_quantity',validator:'number', visible: true,width:100},
         {name: '交货方式', field: 'delivery', visible: true,width:90},
         {name: '送达地点', field: 'delivery_address', visible: true,width:100},
         {
@@ -106,6 +106,7 @@ ProjectGLJSpread.prototype.init = function () {
     this.sheetObj.setStyle(-1, basePriceColumn, rightStyleSetting);
     this.sheetObj.setStyle(-1, adjustPriceColumn, rightStyleSetting);
     this.sheetObj.setStyle(-1, marketPriceColumn, rightStyleSetting);
+    this.sheetObj.setStyle(-1, supplyColumn, rightStyleSetting);
 
     // 设置可编辑列
     this.sheetObj.setColumnEditable(marketPriceColumn);
@@ -175,7 +176,7 @@ ProjectGLJSpread.prototype.updateProjectGLJField = function(info, callback) {
     // 校验数据
     let value = info.newValue;
     if (!projectGLJSheet.checkData(column, value)) {
-        alert('数据格式错误,请重新输入!');
+        alert('输入的数据类型不对,请重新输入!');
         activeSheet.setValue(row, column, info.oldValue);
         return false;
     }
@@ -204,6 +205,9 @@ ProjectGLJSpread.prototype.updateProjectGLJField = function(info, callback) {
         value = this.supplyType.indexOf(value);
         extend.supply_quantity = this.getSupplyQuantity(value, activeSheet, info);
     }
+    if(field === 'supply_quantity'){//修改数量需做4舍5入
+        value= value.toDecimal(getDecimal('glj.quantity'));
+    }
 
     extend = Object.keys(extend).length > 0 ?  JSON.stringify(extend) : '';
     $.ajax({
@@ -229,6 +233,9 @@ ProjectGLJSpread.prototype.updateProjectGLJField = function(info, callback) {
                 if (parentMarketPrice !== null) {
                     info.parentMarketPrice = parentMarketPrice;
                 }
+                if(field !== 'supply'){ //供货方式需做转换才能直接设置值, 这里设置值是为了早点更新数据,等getdata返回数据再刷新的话会有比较大的延时
+                    activeSheet.setValue(row, column, value);
+                }
                 callback(field, info);
             }
         }
@@ -356,10 +363,11 @@ ProjectGLJSpread.prototype.compositionCalculate = function(row) {
                 continue;
             }
             let rowConsumption = consumption[index] === undefined ? 0 : consumption[index];
+            let decimal = getDecimal("glj.unitPrice");
             // 计算价格
-            let rowMarketPrice = (marketPrice * rowConsumption).toDecimal(2);
+            let rowMarketPrice = (marketPrice * rowConsumption).toDecimal(decimal);
             parentMarketPrice[active] = parentMarketPrice[active] === undefined ?
-                rowMarketPrice : (parentMarketPrice[active] + rowMarketPrice).toDecimal(2);
+                rowMarketPrice : (parentMarketPrice[active] + rowMarketPrice).toDecimal(decimal);
 
         }
 
@@ -465,6 +473,7 @@ ProjectGLJSpread.prototype.getSupplyQuantity = function(supplyType, activeSheet,
     let quantity = activeSheet.getValue(info.row, quantityColumn);
     // 自行采购和甲定乙供则把甲供数量设置为0,其余情况则设置为当前总消耗量
     let supplyQuantity = supplyType === 0 || supplyType === 3 ? 0 : quantity;
+    supplyQuantity = parseFloat(supplyQuantity);
 
     return supplyQuantity;
 };

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

@@ -124,62 +124,62 @@
                                           </div>
                                           <div class="main-data-bottom ovf-hidden" style="width: 33%; float: left;" id="itemSpread">
                                           </div>
-                                          <div id="add-rule" style="width: 33%;float: left;background: #EFEFEF; height: 100%;display: none;">
+                                          <div id="add-rule" style="width: 33%;float: left;background: #EFEFEF; height: 100%;display: none; padding-left: 8px;">
                                               <p style="text-align: center">添加规则</p>
                                               <p>
                                                   <label class="title">添加位置:</label>
-                                                  <select name="" id="add-position">
-                                                      <option value="">添加到项目特征列</option>
-                                                      <option value="">添加到清单名称列</option>
-                                                      <option value="">添加到工作内容列</option>
-                                                      <option value="">分别添加到对应列</option>
+                                                  <select id="add-position">
+                                                      <option value="1" selected="selected">添加到项目特征列</option>
+                                                      <option value="2">添加到清单名称列</option>
+                                                      <option value="3">添加到工作内容列</option>
+                                                      <option value="4">分别添加到对应列</option>
                                                   </select>
                                               </p>
                                               <p>
                                                   <label class="title">添加内容:</label>
-                                                  <select name="" id="add-content">
+                                                  <select id="add-content">
                                                       <option value="">无</option>
-                                                      <option value="">项目特征+工作内容</option>
-                                                      <option value="">工作内容+项目特征</option>
-                                                      <option value="">项目特征</option>
-                                                      <option value="">工作内容</option>
-                                                      <option value="">定额子目</option>
+                                                      <option value="1" selected="selected">项目特征+工作内容</option>
+                                                      <option value="2">工作内容+项目特征</option>
+                                                      <option value="3">项目特征</option>
+                                                      <option value="4">工作内容</option>
+                                                      <option value="5">定额子目</option>
                                                   </select>
                                               </p>
                                               <p>
                                                   <label class="title">显示格式:</label>
-                                                  <select name="" id="format">
-                                                      <option value="">换行分隔</option>
-                                                      <option value="">逗号分隔</option>
-                                                      <option value="">括号分隔</option>
+                                                  <select id="display-format">
+                                                      <option value="1" selected="selected">换行分隔</option>
+                                                      <option value="2">逗号分隔</option>
+                                                      <option value="3">括号分隔</option>
                                                   </select>
                                               </p>
                                               <p>
                                                   <label class="title">特征生成方式:</label>
-                                                  <select name="" id="">
-                                                      <option value="">特征值</option>
-                                                      <option value="">特征:特征值</option>
+                                                  <select id="character-format">
+                                                      <option value="1">特征值</option>
+                                                      <option value="2" selected="selected">特征:特征值</option>
                                                   </select>
                                               </p>
                                               <p>
                                                   <label class="title">子目生成方式:</label>
-                                                  <select name="" id="">
-                                                      <option value="">编号+定额名称</option>
-                                                      <option value="">序号+定额名称</option>
+                                                  <select id="child-display-format" disabled="disabled">
+                                                      <option value="1" selected="selected">编号+定额名称</option>
+                                                      <option value="2">序号+定额名称</option>
                                                   </select>
                                               </p>
                                               <p>
                                                   <label class="title">序号格式:</label>
-                                                  <select name="" id="">
+                                                  <select id="serial-type">
                                                       <option value="">无</option>
-                                                      <option value="">1.</option>
-                                                      <option value="">a.</option>
-                                                      <option value="">A.</option>
+                                                      <option value="1" selected="selected">1.</option>
+                                                      <option value="2">a.</option>
+                                                      <option value="3">A.</option>
                                                   </select>
                                               </p>
                                               <p style="text-align: center">
-                                                  <button class="btn btn-primary btn-sm" type="button">应用到选中清单</button>
-                                                  <button class="btn btn-primary btn-sm" type="button">应用到所有清单</button>
+                                                  <button class="btn btn-primary btn-sm" type="button" id="use-to-current">应用到选中清单</button>
+                                                  <button class="btn btn-primary btn-sm" type="button" id="use-to-all">应用到所有清单</button>
                                               </p>
                                           </div>
                                       </div>
@@ -448,13 +448,13 @@
                                         <fieldset class="form-group">
                                             <div class="form-check">
                                                 <label class="form-check-label">
-                                                    <input class="form-check-input" id="autoHeight" value="1" type="checkbox">
+                                                    <input class="form-check-input" id="autoHeight" type="checkbox">
                                                     造价书表格自动调整行高
                                                 </label>
                                             </div>
                                             <div class="form-check">
                                                 <label class="form-check-label">
-                                                    <input class="form-check-input" id="disPlayMainMaterial" value="1" type="checkbox">
+                                                    <input class="form-check-input" id="disPlayMainMaterial" type="checkbox">
                                                     定额下显示主材、设备
                                                 </label>
                                             </div>

+ 7 - 0
web/building_saas/main/js/controllers/project_controller.js

@@ -14,6 +14,13 @@ ProjectController = {
             sc.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
         });
     },
+    syncDisplayNewRationGljNode:function (sc,newNode) {
+        TREE_SHEET_HELPER.massOperationSheet(sc.sheet, function () {
+            sc.sheet.addRows(newNode.serialNo(), 1);
+            TREE_SHEET_HELPER.refreshTreeNodeData(sc.setting, sc.sheet, [newNode], false);
+            sc.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+        });
+    },
     addBills: function (project, sheetController, std) {
         if (!project || !sheetController) { return null; }
 

+ 6 - 4
web/building_saas/main/js/main.js

@@ -7,7 +7,7 @@ $(function () {
     loadSize("main", function() {
         refreshSubSpread();
     });
-
+    $("#header-menu").removeAttr('style');
     projectInfoObj.showProjectInfo();
     projectObj.checkMainSpread();
     projectObj.loadProjectData();
@@ -79,12 +79,12 @@ function slideResize(rootElement, callback) {
             // 判断拖动范围不能超出
             topChangeHeight = topContentHeight + moveHeight;
             topChangeHeight = topChangeHeight < 170 ? 170 : topChangeHeight;
-            topChangeHeight = topChangeHeight > 700 ? 700 : topChangeHeight;
+            topChangeHeight = topChangeHeight > 700 ? 709 : topChangeHeight;
             topContentEle.children(".main-data-top").height(topChangeHeight);
 
             bottomChangeHeight = bottomContentHeight - moveHeight;
             bottomChangeHeight = bottomChangeHeight < 170 ? 170 : bottomChangeHeight;
-            bottomChangeHeight = bottomChangeHeight > 700 ? 700 : bottomChangeHeight;
+            bottomChangeHeight = bottomChangeHeight > 700 ? 709 : bottomChangeHeight;
             bottomContentEle.children().find(".main-data-bottom").height(bottomChangeHeight - navHeight);
         }
     });
@@ -96,6 +96,8 @@ function slideResize(rootElement, callback) {
             drag = false;
             // 存入本地缓存
             const id = rootElement.attr('id');
+            topChangeHeight = topChangeHeight >= 700 ? 709 : topChangeHeight;
+            bottomChangeHeight = bottomChangeHeight >= 700 ? 709 : bottomChangeHeight;
             setLocalCache('topHeight:' + id, topChangeHeight);
             setLocalCache('bottomHeight:' + id, bottomChangeHeight);
         }
@@ -123,6 +125,6 @@ function loadSize(tag, callback) {
     bottomHeight = parseFloat(bottomHeight);
     $("#"+ tag +" .main-data-top").height(topHeight);
     $("#"+ tag +" .main-data-bottom").height(bottomHeight - navHeight);
-    $("#"+ tag +" .bottom-content").height(bottomHeight);
+    // $("#"+ tag +" .bottom-content").height(bottomHeight);
     callback();
 }

+ 9 - 11
web/building_saas/main/js/models/calc_base.js

@@ -52,7 +52,7 @@ let cbTools = {
         return this.isDef(v) && !isNaN(v) && v !== Infinity;
     },
     isFlag: function (v) {
-        return this.isDef(v.flagsIndex) && this.isDef(v.flagsIndex.fixed);
+        return this.isDef(v) && this.isDef(v.flagsIndex) && this.isDef(v.flagsIndex.fixed);
     },
     returnV: function (v, r) {
         if(this.isDef(v)){
@@ -277,7 +277,7 @@ let baseFigureTemplate = {
         return 0;
     },
     'FBFXGCLQDJJZJGCF': function () {
-        return this['FBFXDEJJRGF']() + this['FBFXDEJJCLF']() + this['FBFXDEJJJXF']();
+        return (this['FBFXDEJJRGF']() + this['FBFXDEJJCLF']() + this['FBFXDEJJJXF']()).toDecimal(decimalObj.bills.totalPrice);
     },
     'CSXMF': function () {
         let bill = calcBase.fixedBills[calcBase.fixedFlag.MEASURE]['bill'];
@@ -292,7 +292,7 @@ let baseFigureTemplate = {
         return bill.feesIndex.common.totalFee || 0;
     },
     'ZZCSXMDEJJZJGCF': function () {
-        return this['ZZCSXMDEJJRGF']() + this['ZZCSXMDEJJCLF']() + this['ZZCSXMDEJJJXF']()
+        return (this['ZZCSXMDEJJRGF']() + this['ZZCSXMDEJJCLF']() + this['ZZCSXMDEJJJXF']()).toDecimal(decimalObj.bills.totalPrice);
     },
     'ZZCSXMDEJJRGF': function () {
         let bill = calcBase.fixedBills[calcBase.fixedFlag.CONSTRUCTION_ORGANIZATION]['bill'];
@@ -364,7 +364,7 @@ let baseFigureTemplate = {
         return 0;
     },
     'JSCSXMQDDEJJZJGCF': function () {
-        return this['JSCSXMDEJJRGF']() + this['JSCSXMDEJJCLF']() + this['JSCSXMDEJJJXF']();
+        return (this['JSCSXMDEJJRGF']() + this['JSCSXMDEJJCLF']() + this['JSCSXMDEJJJXF']()).toDecimal(decimalObj.bills.totalPrice);
     },
     'QTXMF': function () {
         let bill = calcBase.fixedBills[calcBase.fixedFlag.OTHER]['bill'];
@@ -500,11 +500,6 @@ let cbAnalyzer = {
             return null;
         }
         return null;
-    },
-
-    isCN: function(v){
-        let regex = /[\u4e00-\u9fa5]/g;
-        return (regex.test(v));
     }
 };
 
@@ -579,6 +574,9 @@ let calcBase = {
     getBaseByClass: function (node) {
         return cbTools.getFigure(node);
     },
+    getBaseBill: function (node) {
+        return cbTools.getBaseBill(node);
+    },
     calculate: function (node) {
         let me = calcBase,
             $CBA = cbAnalyzer,
@@ -607,7 +605,7 @@ let calcBase = {
             me.project.calcProgram.saveNode(node);
         }
         catch (err){
-            alert(err);
+            alert('表达式不正确');
         }
-    },
+    }
 };

+ 2 - 1
web/building_saas/main/js/models/calc_program.js

@@ -954,7 +954,8 @@ class CalcProgram {
         };
 
         calcNodes(me.project.mainTree.roots);
-        me.saveNodes(needSaveNodes);
+        // me.saveNodes(needSaveNodes);   保存要与计算分离,否则实际应用场景中,会产生多次通讯。
+        return needSaveNodes;
     };
 
     // 重新计算叶子清单下的所有子结点:如定额、工料机定额等(calculate算法基于定额、工料机定额的计算结果是正确的,实际上有时它们的计算结果并不是最新的)

+ 5 - 5
web/building_saas/main/js/models/fee_rate.js

@@ -243,7 +243,7 @@ var FeeRate = {
                 })
             }
             project.calcProgram.compileAllTemps();
-            rationPM.refreshDetailSheet();
+            calcProgramManage.refreshDetailSheet();
         }
         FeeRate.prototype.refreshCalProgramByRateID=function (rateID,value) {
             var templates = project.calcProgram.datas.templates;
@@ -255,7 +255,7 @@ var FeeRate = {
                 })
             }
             project.calcProgram.compileAllTemps();
-            rationPM.refreshDetailSheet();
+            calcProgramManage.refreshDetailSheet();
         };
         FeeRate.prototype.refreshBillsByRateID=function(rateID,value){
             var nodes = _.filter(projectObj.project.mainTree.items,function (n) {
@@ -379,12 +379,12 @@ var FeeRate = {
                 editInfo.calcItem.feeRate=value;
                 editInfo.calcItem.feeRateID=null;
                 var data={'projectID': projectObj.project.ID(),'templatesID': editInfo.template.ID,'calcItem': editInfo.calcItem};
-                rationPM.saveCalcItem(data,function (result) {
+                calcProgramManage.saveCalcItem(data,function (result) {
                     project.calcProgram.compileAllTemps();
-                    rationPM.refreshDetailSheet();
+                    calcProgramManage.refreshDetailSheet();
                 })
             }else {
-                rationPM.refreshDetailSheet();
+                calcProgramManage.refreshDetailSheet();
             }
         };
         FeeRate.prototype.updateFeeRateByCalc=function (rate,value) {

+ 1 - 1
web/building_saas/main/js/models/main_consts.js

@@ -34,7 +34,7 @@ const gljType = {
     COMMERCIAL_MORTAR: 206,
     // ==============材料类型=================
     // ==============机械类型=================
-    // 普通机械
+    // 机械台班
     GENERAL_MACHINE: 301,
     // 机械组成物
     MACHINE_COMPOSITION: 302,

+ 2 - 1
web/building_saas/main/js/models/project.js

@@ -142,7 +142,8 @@ var PROJECT = {
                     newNode.source = br[i];
                     newNode.sourceType = that.Ration.getSourceType();
                     newNode.data = br[i];
-                    if(projectInfoObj.projectInfo.property.displaySetting.disPlayMainMateria==true){
+                    if(projectInfoObj.projectInfo.property.displaySetting !== undefined &&
+                        projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial==true){
                         loadRationGLJNode(newNode);
                     }
                 }

+ 16 - 0
web/building_saas/main/js/models/project_glj.js

@@ -140,6 +140,7 @@ ProjectGLJ.prototype.loadCacheData = function() {
     }
     jsonData = data.gljList !== undefined && data.gljList.length > 0 ? data.gljList : [];
     jsonData=filterProjectGLJ(jsonData);
+    jsonData = sortProjectGLJ(jsonData);
     projectGLJSheet.setData(jsonData);
     projectGLJSpread.specialColumn(jsonData);
 };
@@ -170,6 +171,8 @@ ProjectGLJ.prototype.updateBasePriceFromRG=function(recode,updateField,newval){
             me.refreshProjectGLJPrice(data);
             me.refreshRationGLJPrice(glj);
             gljOprObj.showRationGLJSheetData();
+            me.refreshTreeNodePriceIfNeed(glj);
+            
             $.bootstrapLoading.end();
         }
         $.bootstrapLoading.start();
@@ -180,6 +183,18 @@ ProjectGLJ.prototype.updateBasePriceFromRG=function(recode,updateField,newval){
         gljOprObj.showRationGLJSheetData();
     }
 }
+ProjectGLJ.prototype.refreshTreeNodePriceIfNeed = function (data) {
+    if((data.unit_price.type = gljType.MAIN_MATERIAL||data.unit_price.type==gljType.EQUIPMENT)&&projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial==true){
+        var nodes = _.filter(projectObj.project.mainTree.items,function (tem) {
+            if(tem.sourceType==ModuleNames.ration_glj&&tem.data.projectGLJID ==data.id){
+                tem.data.marketUnitFee = data.unit_price.market_price;
+                return true;
+            }
+        })
+        projectObj.mainController.refreshTreeNode(nodes);
+
+    }
+}
 
 ProjectGLJ.prototype.refreshRationGLJPrice=function (glj) {
     for(let ration_glj of gljOprObj.sheetData){
@@ -209,6 +224,7 @@ ProjectGLJ.prototype.refreshProjectGLJPrice=function(data){
                 glj.unit_price.market_price = d.market_price;
                 this.setAdjustPrice(glj);
                 this.refreshRationGLJPrice(glj);
+                this.refreshTreeNodePriceIfNeed(glj);
             }
         }
     }

+ 105 - 22
web/building_saas/main/js/models/ration_glj.js

@@ -86,34 +86,36 @@ var ration_glj = {
 
         // 提交数据后返回数据处理
         ration_glj.prototype.doAfterUpdate = function(err, data){
+            var me = this;
             if(!err){
                 if(data.updateTpye=='ut_update'){
-                    this.refreshAfterUpdate(data);
+                    me.refreshAfterUpdate(data);
                 }else if(data.updateTpye=='ut_delete'){
-                    this.refreshAfterDelete(data);
+                    me.refreshAfterDelete(data);
                 } else {
-                    this.refreshAfterSave(data);
+                    me.refreshAfterSave(data);
                 }
-                projectObj.project.projectGLJ.loadData();
             }
+            projectObj.project.projectGLJ.loadData();
         };
         ration_glj.prototype.refreshAfterSave=function(data){
+            let me = projectObj.project.ration_glj;
             let neRecodes=[];
             if(data){
                // neRecodes=data.newRecords;//原来是显示和缓存分开的,后来发现会导致数据不一致的问题所以改成统一的了,这里也只是会作为显示。
                 neRecodes = data.showDatas;
                 gljOprObj.sheetData=neRecodes;
             }
-            if(projectObj.project.ration_glj.datas&&Array.isArray(projectObj.project.ration_glj.datas)){
+            if(me.datas&&Array.isArray(me.datas)){
                 if(data){
-                    projectObj.project.ration_glj.datas = projectObj.project.ration_glj.datas.concat(neRecodes);
+                    me.datas = me.datas.concat(neRecodes);
                 }
             }else {
-                projectObj.project.ration_glj.datas = neRecodes;
+                me.datas = neRecodes;
             }
             gljOprObj.showRationGLJSheetData(true);
             //add to mainTree;
-
+            me.addToMainTree(neRecodes);
             let node = project.mainTree.selected;
             project.calcProgram.calculate(node);
             project.calcProgram.saveNode(node);
@@ -121,6 +123,33 @@ var ration_glj = {
                 calcProgramObj.showData(node, false);
             };
         };
+        ration_glj.prototype.addToMainTree = function (datas) {
+            datas = sortRationGLJ(datas);
+            for(let data of datas){
+                if(this.needShowToTree(data)){
+                    this.transferToNodeData(data);
+                    let parentNode = _.find(projectObj.project.mainTree.items,function (n) {//找父节点
+                        return n.sourceType==ModuleNames.ration &&n.data.ID==data.rationID;
+                    });
+                    if(parentNode){
+                        let nextNodeID=null;
+                        if(parentNode.children.length>0){
+                            for(let br of parentNode.children){
+                                if(compareRationGLJ(data,br.data)){//如果有兄弟节点则找到添加位置。
+                                    nextNodeID = br.getID();
+                                }
+                            }
+                        }
+                        nextNodeID = nextNodeID?nextNodeID:parentNode.tree.rootID();
+                        let newNode = projectObj.project.mainTree.insert(parentNode.getID(),nextNodeID);
+                        newNode.source = data;
+                        newNode.sourceType = this.getSourceType();
+                        newNode.data = data;
+                        ProjectController.syncDisplayNewRationGljNode(projectObj.mainController,newNode);
+                    }
+                }
+            }
+        };
         ration_glj.prototype.refreshAfterUpdate=function(data){
             var me = this;
             if(data.quantityRefresh){
@@ -146,14 +175,29 @@ var ration_glj = {
             return glj_list[glj_index].rationID;
         };
         ration_glj.prototype.refreshAfterDelete=function(data){
-            var glj_list = projectObj.project.ration_glj.datas;
-            _.remove(glj_list,data.query);
+            var me = projectObj.project.ration_glj;
+            var glj_list = me.datas;
+            var oldData = _.remove(glj_list,data.query);
             _.remove(gljOprObj.sheetData,data.query);
             gljOprObj.showRationGLJSheetData();
             projectObj.project.projectGLJ.loadData();
+            var rationNode = null;
+            var next = null;
             var selected = projectObj.project.mainTree.selected;
-            selected.data.adjustState=data.adjustState;
-            projectObj.mainController.refreshTreeNode([selected]);
+            if(selected.sourceType==ModuleNames.ration){ //如果选中的是定额,说明是右键删除工料机操作,如果选中的是定额工料机,则说明是在造价书主界面中点击了删除按钮
+                rationNode= selected;
+            }else if(selected.sourceType==ModuleNames.ration_glj){
+                rationNode = selected.parent;
+                next = true;
+            }
+            rationNode.data.adjustState=data.adjustState;
+            projectObj.mainController.refreshTreeNode([rationNode]);
+            for(let o of oldData){
+                if(this.needShowToTree(o)){
+                    let node = me.findTreeNodeByID(o.ID);  //找到对应的树节点
+                    projectObj.mainController.deleteNode(node,next);
+                }
+            }
         };
         // CSL,2017.05.09
         ration_glj.prototype.modifyQuantity = function (data, newQuantity) {
@@ -286,20 +330,25 @@ var ration_glj = {
             var callback=function (data) {
                 let initShow = false;//是否需要表格初始化显示
                 if(updateField=='customQuantity'){
-                    console.log(data);
                     me.refreshAfterQuantityUpdate(data,node);
                 }else {
                     var doc = data.doc;
                     for(var key in doc){
                         recode[key] = doc[key];
                     }
-                    console.log(data);
                     if(data.hasOwnProperty('adjustState')){//更新定额调整状态
                         me.updateRationAdjustState(data.adjustState,recode.rationID,node);
                     }
                     if(recode.subList&&recode.subList.length>0){
                         initShow = true;
                     }
+                    if(node){//如果不是在造价书页面直接编辑,则不用刷新
+                        if(updateField=="type"&&!(newval == gljType.MAIN_MATERIAL||newval==gljType.EQUIPMENT)){//如果改变类型后不是主材或设备,则在造价书树中移除
+                            projectObj.mainController.deleteNode(node,true);
+                        }else {
+                            me.refreshTreeNodeIfNeeded(recode);
+                        }
+                    }
                 }
                 if(initShow==false){//不需要初始化,只需耍新当前显示就可以了
                     gljOprObj.showRationGLJSheetData();
@@ -343,7 +392,7 @@ var ration_glj = {
             })
             if(node){
                 node.data.adjustState=adjustState;
-                nodes.push(node)
+                nodes.push(node);
             }
             if(rnode){
                 nodes.push(rnode);
@@ -360,7 +409,10 @@ var ration_glj = {
           var allGLJ=gljOprObj.AllRecode;
             GLJSelection.sort();
           _.forEach(GLJSelection,function (g) {
-              var glj=_.find(allGLJ,{'code':g});
+              var glj=_.find(allGLJ,function (item) {
+                var i_key = gljOprObj.getIndex(item,['code','name','specs','unit','gljType']);
+                return i_key ==g;
+              });
               var ration_glj ={
                   projectID:ration.projectID,
                   GLJID:glj.ID,
@@ -382,7 +434,7 @@ var ration_glj = {
               }
               if(glj.hasOwnProperty("compilationId")){
                   ration_glj.from="cpt";
-                  if(glj.code.indexOf('-')!=-1){//这条工料机是用户通过修改称、规格、型号等保存到补充工料机库的
+                  if(glj.code.indexOf('-')!=-1){//这条工料机是用户通过修改称、规格、型号等保存到补充工料机库的
                       ration_glj.original_code = glj.code.split('-')[0];//取-前的编号作为原始编号
                   }
               }
@@ -396,8 +448,11 @@ var ration_glj = {
         };
         ration_glj.prototype.replaceGLJ=function (selectCode,oldData,callback) {
             var allGLJ=gljOprObj.AllRecode;
-            var glj=_.find(allGLJ,{'code':selectCode});
-            if(selectCode==oldData.code){
+            var glj=_.find(allGLJ,function (item) {
+                var i_key = gljOprObj.getIndex(item,['code','name','specs','unit','gljType']);
+                return i_key ==selectCode;
+            });
+            if(selectCode==gljOprObj.getIndex(oldData,['code','name','specs','unit','type'])){
                 return callback(null);
             }
             if(oldData.createType!='replace'){
@@ -429,8 +484,11 @@ var ration_glj = {
 
         ration_glj.prototype.mReplaceGLJ=function (selectCode,oldData,callback) {
             var allGLJ=gljOprObj.AllRecode;
-            var glj=_.find(allGLJ,{'code':selectCode});
-            if(selectCode==oldData.code){
+            var glj=_.find(allGLJ,function (item) {
+                var i_key = gljOprObj.getIndex(item,['code','name','specs','unit','gljType']);
+                return i_key ==selectCode;
+            });
+            if(selectCode== gljOprObj.getIndex(oldData,['code','name','specs','unit','type'])){
                 return callback(null);
             }
             var query={
@@ -480,6 +538,7 @@ var ration_glj = {
            var gljList = _.filter(this.datas,function (n) {
               return n.rationID == rationID&&(n.type==gljType.MAIN_MATERIAL||n.type==gljType.EQUIPMENT)
            });
+           gljList = sortRationGLJ(gljList);
            return gljOprObj.combineWithProjectGlj(gljList);
         };
         ration_glj.prototype.transferToNodeData = function (data) {
@@ -493,7 +552,13 @@ var ration_glj = {
                 return;
             }
             if(fieldName=="marketUnitFee"){
-
+                var decimal =getDecimal("glj.unitPrice");
+                var newval = number_util.checkNumberValue(value,decimal);
+                if(newval){
+                    fieldName="marketPrice";
+                    projectObj.project.projectGLJ.updatePriceFromRG(node.data,fieldName,newval);
+                    return;
+                }
             }else {
                 if(value!==undefined&&value!==null){
                     if(fieldName=="subType"){
@@ -507,6 +572,24 @@ var ration_glj = {
            // node.data.subType = value;
             projectObj.mainController.refreshTreeNode([node]);
         };
+        ration_glj.prototype.refreshTreeNodeIfNeeded=function (data) {
+            if(this.needShowToTree(data)){
+                this.transferToNodeData(data);
+                gljOprObj.refreshTreeNode({"type":ModuleNames.ration_glj,"ID":data.ID});
+            }
+        };
+        ration_glj.prototype.needShowToTree=function(data){
+            if((data.type == gljType.MAIN_MATERIAL||data.type==gljType.EQUIPMENT)&&projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial==true){
+                return true
+            }
+            return false
+        };
+        ration_glj.prototype.findTreeNodeByID = function (ID) {
+            let node = _.find(projectObj.project.mainTree.items,function (n) {//找到对应的树节点
+                return n.sourceType==ModuleNames.ration_glj &&n.data.ID==ID;
+            });
+            return node;
+        }
         return new ration_glj(project);
     }
 };

+ 5 - 4
web/building_saas/main/js/views/calc_base_view.js

@@ -14,7 +14,7 @@ let calcBaseView = {
     setting:{
         header: [
             {name: '计算基础名称', dataCode: 'base', width: 280, vAlign: 'center', hAlign: 'left'},
-            {name: '金额', dataCode: 'price', width: 120, vAlign: 'center', hAlign: 'left'}
+            {name: '金额', dataCode: 'price', width: 120, vAlign: 'center', hAlign: 'right'}
         ],
         options: {
             tabStripVisible:  false,
@@ -84,7 +84,7 @@ let calcBaseView = {
             sheet.setFormatter(-1, 1, '@');
             for(let col = 0, cLen = cols.length; col < cLen; col++){
                 sheet.getRange(-1, col, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[cols[col]['hAlign']]);
-                sheet.getRange(-1, col, -1, 1).hAlign(GC.Spread.Sheets.VerticalAlign[cols[col]['vAlign']]);
+                sheet.getRange(-1, col, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[cols[col]['vAlign']]);
                 for(let row = 0, rLen = datas.length; row < rLen; row++){
                     sheet.setValue(row, col, datas[row][cols[col]['dataCode']]);
                 }
@@ -210,8 +210,9 @@ let calcBaseView = {
         CalcBaseCellType.prototype = new ns.CellTypes.Text();
         CalcBaseCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
             if(value!=null){
-                // ctx.fillText(value,x+3+ctx.measureText(value).width,y+h-3);
-                ctx.fillText(value,x+w,y+h-3);
+               // ctx.fillText(value,x+3+ctx.measureText(value).width,y+h-3);
+               // ctx.fillText(value,x+w-3,y+h-3);
+                GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
             }
             if(calcBaseView.editingCell){
                 if(calcBaseView.editingCell.row==options.row&&calcBaseView.editingCell.col==options.col){

+ 4 - 4
web/building_saas/main/js/views/calc_program_manage.js

@@ -2,7 +2,7 @@
  * Created by CSL on 2017-08-03.
  * 计算程序管理。
  */
-let rationPM = {
+let calcProgramManage = {
     datas: [],
     mainSpread: null,
     detailSpread: null,
@@ -68,7 +68,7 @@ let rationPM = {
         sheetCommonObj.showData(dSheet, me.detailSetting, me.datas[0].calcItems);
     },
     onMainEnterCell: function(sender, args) {
-        var me = rationPM;
+        var me = calcProgramManage;
         var row = args.sheet.getActiveRowIndex();
 
         me.detailSpread.suspendPaint();
@@ -79,7 +79,7 @@ let rationPM = {
         me.detailSpread.resumePaint();
     },
     onEditEnded: function(sender, args) {
-        var me = rationPM;
+        var me = calcProgramManage;
         if(me.detailSetting.header[args.col].dataCode=='feeRate'){
             var editInfo= me.getSelectionInfo();
             projectObj.project.FeeRate.updateFeeRateFromCalc(args.editingText,editInfo);
@@ -126,7 +126,7 @@ let rationPM = {
 $(document).ready(function(){
     $('#tab_calc_program_manage').on('shown.bs.tab', function (e) {
         $(e.relatedTarget.hash).removeClass('active');
-        rationPM.buildSheet();
+        calcProgramManage.buildSheet();
     });
 });
 

+ 283 - 8
web/building_saas/main/js/views/character_content_view.js

@@ -741,15 +741,290 @@ let pageCCOprObj = {
         };
         CommonAjax.post(url, postData, function (rstData) {
             //更新节点数据
-            let selectedNode = projectObj.mainController.tree.selected;
-            selectedNode.data[updateObj.field] = updateObj.updateArr;
-            selectedNode.data[txtObj.field] = txtObj.text;
-            me.showData(oprObj.workBook.getSheet(0), oprObj.setting, oprObj.currentCache);//刷新特征及内容Spread
             if(updateCol){
-                let activeCell = projectObj.mainSpread.getActiveSheet().getSelections()[0];
-                projectObj.mainSpread.getActiveSheet().setValue(activeCell.row, updateCol, txtObj.text + ''); //刷新输出显示
-                projectObj.mainSpread.getActiveSheet().autoFitRow(activeCell.row);
+                if (!oprObj.hasOwnProperty("getID")) {
+                    // 已当前选中行更新数据
+                    let selectedNode = projectObj.mainController.tree.selected;
+                    selectedNode.data[updateObj.field] = updateObj.updateArr;
+                    selectedNode.data[txtObj.field] = txtObj.text;
+                    me.showData(oprObj.workBook.getSheet(0), oprObj.setting, oprObj.currentCache);//刷新特征及内容Spread
+
+                    let activeCell = projectObj.mainSpread.getActiveSheet().getSelections()[0];
+                    projectObj.mainSpread.getActiveSheet().setValue(activeCell.row, updateCol, txtObj.text + ''); //刷新输出显示
+                    projectObj.mainSpread.getActiveSheet().autoFitRow(activeCell.row);
+                } else {
+                    // 以节点更新数据
+                    const row = oprObj.getID() - 1;
+                    projectObj.mainSpread.getActiveSheet().setValue(row, updateCol, txtObj.text + ''); //刷新输出显示
+                    projectObj.mainSpread.getActiveSheet().autoFitRow(row);
+                }
             }
         });
-    }
+    },
+    /**
+     * 根据配置设置清单项目特征
+     *
+     * @param {Object} node - 选中的node节点
+     * @param {Object} setting - 设置
+     * @return {void}
+     */
+    setCharacterBySetting: function(node, setting) {
+        let contentArray = [];
+        // 特征部分
+        const itemCharacter = node.data.itemCharacter;
+        // 内容数据
+        const itemJob = node.data.jobContent;
+
+        if (itemCharacter === undefined || itemCharacter.length <= 0 || itemJob === undefined || itemJob.length <= 0) {
+            return;
+        }
+        // 保存的条件数据
+        const findSet = { ID: node.data.ID, projectID: node.data.projectID };
+        const baseData = { findSet, itemJob, itemCharacter };
+        let characterArray = [];
+        for (const tmp of itemCharacter) {
+            if (tmp.eigenvalue === undefined || tmp.eigenvalue.length <= 0 || !tmp.isChecked) {
+                continue;
+            }
+            // 获取选中的特征值
+            let selectedEigen = '';
+            for (const eigen of tmp.eigenvalue) {
+                if (eigen.isSelected) {
+                    selectedEigen = eigen.value;
+                }
+            }
+            // 匹配设置的序号格式
+            const serialNo = this.formatSerialNumber(setting.serialType, tmp.serialNo);
+            let characterString = '';
+            // 特征生成方式
+            switch (setting.characterFormat) {
+                case '1':
+                    // 特征值
+                    characterString = serialNo + selectedEigen;
+                    break;
+                case '2':
+                    // 特征:特征值
+                    characterString = serialNo + tmp.character + ': ' + selectedEigen;
+                    break;
+            }
+            characterArray.push(characterString);
+        }
+
+        // 内容部分
+        let jobArray = [];
+        for (const tmp of itemJob) {
+            if (!tmp.isChecked) {
+                continue;
+            }
+            // 匹配设置的序号格式
+            const serialNo = this.formatSerialNumber(setting.serialType, tmp.serialNo);
+            jobArray.push(serialNo + tmp.content)
+        }
+
+        // 组合数据
+        let content = '';
+        const jobContent = jobArray.join("\r\n");
+        const characterContent = characterArray.join("\r\n");
+        let nodeNameList = node.data.name.split("\n");
+        const nameContent = nodeNameList[0] !== undefined ? nodeNameList[0] : '';
+        // 存入对象,生成数据时用
+        let defaultContentInfo = {
+            jobContent,
+            characterContent,
+            nameContent
+        };
+        switch (setting.addContent) {
+            case "1":
+                // 项目特征+工作内容
+                contentArray.push('[项目特征]');
+                contentArray.push.apply(contentArray, characterArray);
+                contentArray.push('[工作内容]');
+                contentArray.push.apply(contentArray, jobArray);
+                break;
+            case "2":
+                // 工作内容+项目特征
+                contentArray.push('[工作内容]');
+                contentArray.push.apply(contentArray, jobArray);
+                contentArray.push('[项目特征]');
+                contentArray.push.apply(contentArray, characterArray);
+                break;
+            case "3":
+                // 项目特征
+                contentArray.push.apply(contentArray, characterArray);
+                break;
+            case "4":
+                // 工作内容
+                contentArray.push.apply(contentArray, jobArray);
+                break;
+            case "5":
+                // 定额子目
+                const rationChapter = this.getRationChapter(node, setting);
+                contentArray.push.apply(contentArray, rationChapter);
+                break;
+            case "":
+                // 无
+                break;
+        }
+        // 显示格式
+        switch (setting.displayFormat) {
+            case "1":
+                // 换行分隔
+                content = contentArray.join("\r\n");
+                break;
+            case "2":
+                // 逗号分隔
+                content = contentArray.join(',');
+                break;
+            case "3":
+                // 括号分隔
+                content = '(' + contentArray.join(',') + ')';
+                break;
+        }
+        // 还原数据
+        this.restoreData(node, setting.position, baseData, defaultContentInfo);
+        // 添加到对应位置
+        let saveObj = {};
+        switch (setting.position) {
+            case "1":
+                // 添加到项目特征列
+                saveObj = {field: 'itemCharacterText', text: content};
+                // 更新到数据库
+                pageCCOprObj.updateCharacterContent(findSet, {field: 'itemCharacter', updateArr: itemCharacter},
+                    saveObj, node);
+                break;
+            case "2":
+                // 添加到清单名称列
+                const column = this.mainActiveCell.col !== undefined ? this.mainActiveCell.col : -1;
+                let colSetting = projectObj.mainController.setting.cols[column];
+                if (colSetting !== undefined) {
+                    content = node.data.name + "\r\n" + content;
+                    projectObj.project.Bills.updateField(node.source, 'name', content, true);
+                    projectObj.mainController.refreshTreeNode([node], false);
+                }
+                break;
+            case "3":
+                // 添加到工作内容列
+                saveObj =  {field: 'jobContentText', text: content};
+                // 更新到数据库
+                pageCCOprObj.updateCharacterContent(findSet, {field: 'jobContent', updateArr: itemJob},
+                    saveObj, node);
+                break;
+            case "4":
+                // 分别添加到对应列
+                if (Object.keys(defaultContentInfo).length <= 0) {
+                    return;
+                }
+                // 名称
+                projectObj.project.Bills.updateField(node.source, 'name', defaultContentInfo.nameContent, true);
+                projectObj.mainController.refreshTreeNode([node], false);
+                // 特征
+                saveObj = {field: 'itemCharacterText', text: defaultContentInfo.characterContent};
+                pageCCOprObj.updateCharacterContent(findSet, {field: 'itemCharacter', updateArr: itemCharacter},
+                    saveObj, node);
+                // 内容
+                saveObj = {field: 'jobContentText', text: defaultContentInfo.jobContent};
+                pageCCOprObj.updateCharacterContent(findSet, {field: 'jobContent', updateArr: itemJob},
+                    saveObj, node);
+                break;
+        }
+
+    },
+    /**
+     * 格式化序号格式
+     *
+     * @param {Number} type - 格式化的类型
+     * @param {String} serialNo - 待格式化的序号
+     * @return {String} - 返回格式化后的字符
+     */
+    formatSerialNumber: function(type, serialNo) {
+        const letter = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
+            's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
+        switch (type) {
+            case '1':
+                // 数字
+                serialNo = serialNo + '. ';
+                break;
+            case '2':
+                // 英文字母(小写)
+                serialNo = letter[serialNo - 1] !== undefined ? letter[serialNo - 1] + '. ' : '';
+                break;
+            case '3':
+                // 英文字母(大写)
+                serialNo = letter[serialNo - 1] !== undefined ? letter[serialNo - 1].toUpperCase() + '. ' : '';
+                break;
+        }
+        return serialNo;
+    },
+    /**
+     * 查找选中的树节点中定额子目数据
+     *
+     * @param {Object} selectNode - 选中的节点
+     * @param {Object} setting - 设置
+     * @return {Array} - 返回定额子目数组
+     */
+    getRationChapter: function(selectNode, setting) {
+        let result = [];
+        if (selectNode.children === undefined || selectNode.children.length <= 0) {
+            return result;
+        }
+        // 查找对应的定额数据
+        let count = 1;
+        for (const tmp of selectNode.children) {
+            if (tmp.sourceType !== 'ration') {
+                continue;
+            }
+            const serialNo = this.formatSerialNumber(setting.serialType, count.toString());
+            result.push(serialNo +  tmp.data.code + ':' + tmp.data.name);
+            count++;
+        }
+
+        return result;
+    },
+
+    /**
+     * 还原数据
+     *
+     * @param {Object} node - 节点数据
+     * @param {String} setType - 当前设置的项
+     * @param {Object} baseData - 需要用到的基础数据
+     * @param {Object} defaultContentInfo - 默认数据
+     * @return {void}
+     */
+    restoreData: function(node, setType, baseData, defaultContentInfo) {
+        if (baseData.findSet === undefined ||
+        baseData.itemJob === undefined || baseData.itemCharacter === undefined) {
+            return;
+        }
+
+        switch (setType) {
+            case "1":
+                // 添加到项目特征列
+                // 把其他字段还原回原来数据
+                // 还原名称
+                projectObj.project.Bills.updateField(node.source, 'name', defaultContentInfo.nameContent, true);
+                projectObj.mainController.refreshTreeNode([node], false);
+                // 还原工作内容
+                pageCCOprObj.updateCharacterContent(baseData.findSet, {field: 'jobContent', updateArr: baseData.itemJob},
+                    {field: 'jobContentText', text: defaultContentInfo.jobContent}, node);
+                break;
+            case "2":
+                // 添加到清单名称
+                // 还原特征
+                pageCCOprObj.updateCharacterContent(baseData.findSet, {field: 'itemCharacter', updateArr: baseData.itemCharacter},
+                    {field: 'itemCharacterText', text: defaultContentInfo.characterContent}, node);
+                // 还原工作内容
+                pageCCOprObj.updateCharacterContent(baseData.findSet, {field: 'jobContent', updateArr: baseData.itemJob},
+                    {field: 'jobContentText', text: defaultContentInfo.jobContent}, node);
+                break;
+            case "3":
+                // 添加到工作内容列
+                // 还原名称
+                projectObj.project.Bills.updateField(node.source, 'name', defaultContentInfo.nameContent, true);
+                projectObj.mainController.refreshTreeNode([node], false);
+                // 还原特征
+                pageCCOprObj.updateCharacterContent(baseData.findSet, {field: 'itemCharacter', updateArr: baseData.itemCharacter},
+                    {field: 'jobContentText', text: defaultContentInfo.characterContent}, node);
+                break;
+        }
+    },
 }

+ 3 - 3
web/building_saas/main/js/views/fee_rate_view.js

@@ -660,14 +660,14 @@ var feeRateObject={
     },
     submitFeeRateFromCalc:function () {
         var rate = feeRateObject.feeRateSelection;
-        var calInfo = rationPM.getSelectionInfo();
+        var calInfo = calcProgramManage.getSelectionInfo();
         calInfo.calcItem.feeRateID=rate.ID;
         calInfo.calcItem.feeRate=null;
         var data={'projectID': projectObj.project.ID(),'templatesID': calInfo.template.ID,'calcItem': calInfo.calcItem};
-        rationPM.saveCalcItem(data,function (result) {
+        calcProgramManage.saveCalcItem(data,function (result) {
             calInfo.calcItem.feeRate=rate.rate;
             projectObj.project.calcProgram.compileAllTemps();
-            rationPM.refreshDetailSheet();
+            calcProgramManage.refreshDetailSheet();
             $("#fee_rate_tree").modal('hide');
         });
         console.log(calInfo);

+ 89 - 23
web/building_saas/main/js/views/glj_view.js

@@ -22,7 +22,7 @@ var gljOprObj = {
         header: [
             {headerName: "编码", headerWidth: 100, dataCode: "code", dataType: "String", formatter: "@"},
             {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
-            {headerName: "规格型号", headerWidth: 120, dataCode: "specs", dataType: "String", hAlign: "left"},
+            {headerName: "规格型号", headerWidth: 90, dataCode: "specs", dataType: "String", hAlign: "left"},
             {headerName: "单位", headerWidth: 45, dataCode: "unit", dataType: "String", hAlign: "center"},
             {headerName: "类型", headerWidth: 45, dataCode: "shortName", dataType: "String", hAlign: "center"},
             {headerName: "定额消耗", headerWidth: 80, dataCode: "rationItemQuantity", dataType: "Number", hAlign: "right",decimalField:"glj.quantity"},    // dataType: "Number", formatter: "0.00"
@@ -559,7 +559,7 @@ var gljOprObj = {
         this.sheet.setRowCount(0);
         //console.log(+new Date())
         //this.sheet.getRange(0,-1,this.sheet.getRowCount(),-1).visible(true); //这个方法导致加载缓慢
-        this.sheetData=_.sortBy(this.sheetData,'type');
+        this.sheetData=sortRationGLJ(this.sheetData);
         this.sumQuantity();//计算总消耗量
         this.addMixRatioToShow();//显示组成物信息
         this.initRationTree(init);
@@ -751,7 +751,7 @@ var gljOprObj = {
         var newval;
         if(updateField=='marketPrice'||updateField=='customQuantity'||updateField=='basePrice'){
             if(args.editingText==null){
-                newval="";
+                updateField=='marketPrice'||updateField=='customQuantity'?newval=0:newval="";
             }else {
                 var decimal = updateField=='customQuantity'?getDecimal("glj.quantity"):getDecimal("glj.unitPrice");
                 newval = number_util.checkNumberValue(args.editingText,decimal);
@@ -792,6 +792,7 @@ var gljOprObj = {
             isValidate = me.checkingActualValue(recode,newval)
         }
         if(isValidate){
+            newval = scMathUtil.roundTo(newval,-2);
             projectObj.project.ration_ass.updateActualValue(me.assSheetData,args.row,newval)
         }else {
             newval = recode.actualValue;
@@ -856,7 +857,7 @@ var gljOprObj = {
         }else {
             me.gljLibSheetData=me[val];
         }
-        if($('#actionType').val()!='add'){
+        if($('#actionType').val()=='replace'||$('#actionType').val()=='m_replace'){
             me.filterLibGLJByType();
         }
         if(me.gljCurTypeId==undefined){
@@ -871,36 +872,44 @@ var gljOprObj = {
         }
     },
     setGLJSelection:function (args,newVal) {
-        if($('#actionType').val()=='add'){
+        if($('#actionType').val()=='add'||$('#actionType').val()=='insert'){
             this.addGLJsSelection(args,newVal);
         }else {
             this.replaceGLJSelection(args,newVal);
         }
     },
     addGLJsSelection:function (args,newVal) {
+         var con_key = this.getIndex(this.gljLibSheetData[args.row],['code','name','specs','unit','gljType'])
         if(newVal==1){
-            this.GLJSelection.push(this.gljLibSheetData[args.row].code);
+            this.GLJSelection.push(con_key);
             this.gljLibSheetData[args.row].select=1;
         }else if(newVal==0){
-            _.pull(this.GLJSelection,this.gljLibSheetData[args.row].code);
+            _.pull(this.GLJSelection,con_key);
             this.gljLibSheetData[args.row].select=0;
         }
     },
     replaceGLJSelection:function (args,newVal) {
+        var me =this;
         var oldSelection=this.GLJSelection[0];
         if(newVal==0){
             args.sheet.getCell(args.row, args.col).value(1);
             return;
         }
-        this.GLJSelection=[this.gljLibSheetData[args.row].code];
+        this.GLJSelection=[me.getIndex(this.gljLibSheetData[args.row],['code','name','specs','unit','gljType'])];
         this.gljLibSheetData[args.row].select=1;
-        var oindex = _.findIndex(this.gljLibSheetData,{'code':oldSelection});
+        var oindex = _.findIndex(this.gljLibSheetData,function (item) {
+            var i_key = me.getIndex(item,['code','name','specs','unit','gljType']);
+            return oldSelection==i_key;
+        });
         if(oindex!=-1){
             args.sheet.getCell(oindex, args.col).value(0);
             this.gljLibSheetData[oindex].select=0;
         }else {
-            var oldData = _.find(gljOprObj.AllRecode,{'code':oldSelection})
-            oldData.select=0;
+            var oldData = _.find(gljOprObj.AllRecode,function (item) {
+                var i_key = me.getIndex(item,['code','name','specs','unit','gljType']);
+                return oldSelection==i_key;
+            });
+            oldData?oldData.select=0:"";
         }
     },
     filterLibGLJByType:function () {
@@ -941,11 +950,20 @@ var gljOprObj = {
         });
         return distTypeTree;
     },
+    doInsertGLJ:function () {
+        var selected = projectObj.project.mainTree.selected;
+        var project= projectObj.project;
+        console.log(gljOprObj.GLJSelection);
+    },
     doAddGLJ:function () {
         var selected = projectObj.project.mainTree.selected;
         var project= projectObj.project;
         gljOprObj.GLJSelection= _.filter(gljOprObj.GLJSelection,function (n) {
-            return _.find(gljOprObj.sheetData,{'code':n})?false:true;
+            var rg = _.find(gljOprObj.sheetData,function (item) {
+                var i_key = gljOprObj.getIndex(item,['code','name','specs','unit','type']);
+                 return n==i_key
+            })
+            return rg?false:true;
         })
         if(gljOprObj.GLJSelection.length>0&&selected&&selected.sourceType==ModuleNames.ration){
             $("#glj_tree_div").modal('hide');
@@ -954,8 +972,9 @@ var gljOprObj = {
                     selected.data.adjustState=result.adjustState;
                     //project.ration_glj.datas = project.ration_glj.datas.concat(result.newRecodes);//显示和缓存统一,这样的话就不用更新两个位置了
                     project.ration_glj.datas = project.ration_glj.datas.concat(result.showData);
-                    gljOprObj.sheetData = gljOprObj.sheetData.concat(result.showData)
+                    gljOprObj.sheetData = gljOprObj.sheetData.concat(result.showData);
                     gljOprObj.showRationGLJSheetData();
+                    project.ration_glj.addToMainTree(result.showData);
                     project.projectGLJ.loadData();
                     projectObj.mainController.refreshTreeNode([selected]);
                     $.bootstrapLoading.end();
@@ -978,11 +997,22 @@ var gljOprObj = {
                 //result.adjustState;
                 var data =result.data;
                 var index = _.findIndex(gljOprObj.sheetData,{'ID':data.ID});
+                var nodes = [selected];
                 gljOprObj.sheetData[index]=data;
                 gljOprObj.showRationGLJSheetData();
+                if(project.ration_glj.needShowToTree(data)){//当替换的是主材或设备时,刷新对应的树节点
+                    var  node =  project.ration_glj.findTreeNodeByID(data.ID);
+                    if(node){
+                        project.ration_glj.transferToNodeData(data);
+                        node.source = data;
+                        node.data = data;
+                    }
+                    node?nodes.push(node):"";
+                }
+                //project.ration_glj.addToMainTree(data);
                 project.projectGLJ.loadData();
                 selected.data.adjustState=result.adjustState;
-                projectObj.mainController.refreshTreeNode([selected]);
+                projectObj.mainController.refreshTreeNode(nodes);
             }
             $.bootstrapLoading.end();
         })
@@ -997,15 +1027,21 @@ var gljOprObj = {
             var data=result.data;
             var stateList= result.stateList;
             var n_index = me.getIndex(data.query,['code','name','specs','unit','type']);
+            var nodes=[];
             _.forEach(project.ration_glj.datas,function (t) {
                 var t_index =me.getIndex(t,['code','name','specs','unit','type']);
                 if(n_index==t_index){
                     me.updateProperty(t,data.doc);
+                    if(project.ration_glj.needShowToTree(t)){//如果是造价书中的树节点,则也须刷新
+                        project.ration_glj.transferToNodeData(t);
+                        var node = project.ration_glj.findTreeNodeByID(t.ID);
+                        nodes.push(node);
+                    }
                 }
             })
             me.showRationGLJSheetData();
             project.projectGLJ.loadData();
-            me.refreshStateAfterMreplace(stateList);
+            me.refreshStateAfterMreplace(stateList,nodes);
             $.bootstrapLoading.end();
         })
     },
@@ -1014,7 +1050,7 @@ var gljOprObj = {
             obj[key] = n;
         });
     },
-    refreshStateAfterMreplace:function (stateList) {
+    refreshStateAfterMreplace:function (stateList,gljNodes) {
         var nodes=[];
         _.forEach(stateList,function (s) {
           var node = _.find(projectObj.project.mainTree.items,function (n) {
@@ -1025,6 +1061,7 @@ var gljOprObj = {
               nodes.push(node);
           }
         });
+        gljNodes.length>0?nodes = nodes.concat(gljNodes):"";
         projectObj.mainController.refreshTreeNode(nodes);
     },
     refreshView:function () {
@@ -1053,7 +1090,6 @@ var gljOprObj = {
             nodes.push(node);
         }
     }
-
     projectObj.mainController.refreshTreeNode(nodes);
 
     },
@@ -1162,7 +1198,11 @@ var gljOprObj = {
             }
         };
         return new TreeNodeCellType()
+    },
+    marketPriceReadOnly:function(node){
+        return node.data.type==gljType.CONCRETE||node.data.type==gljType.MORTAR||node.data.type==gljType.MIX_RATIO||node.data.type==gljType.GENERAL_MACHINE||node.data.isEstimate==1
     }
+
 }
 
 $(function(){
@@ -1176,16 +1216,21 @@ $(function(){
         }
         gljOprObj.gljLibSheetData =gljOprObj.AllRecode;
         var selected=null;
-        if($('#actionType').val()=='add'){
+        if($('#actionType').val()=='add'||$('#actionType').val()=='insert'){
             gljOprObj.GLJSelection=[];
         }else {
              selected=gljOprObj.sheetData[gljContextMenu.selectedRow];
-            gljOprObj.GLJSelection=[selected.code];
+             var connect_key = gljOprObj.getIndex(selected,['code','name','specs','unit','type'])
+            gljOprObj.GLJSelection=[connect_key];
             gljOprObj.filterLibGLJByType();
         }
 
         if(selected!=null){
-            var r = _.find(gljOprObj.gljLibSheetData,{'code':selected.code});
+            var s_key = gljOprObj.getIndex(selected,['code','name','specs','unit','gljType']);
+            var r = _.find(gljOprObj.gljLibSheetData,function (item) {
+                var item_key = gljOprObj.getIndex(item,['code','name','specs','unit','type']);
+                return s_key == item_key;
+            });
             r?r.select=1:"";
         }
         gljOprObj.showLibGLJSheetData();
@@ -1207,11 +1252,13 @@ $(function(){
         if(gljOprObj.GLJSelection.length<1){
             return;
         }
-        if($('#actionType').val()=='add'){
+        if($('#actionType').val()=='insert'){  //造价书页面中插入定额类型的工料机
+            gljOprObj.doInsertGLJ();
+        }else if($('#actionType').val()=='add'){ //添加工料机
             gljOprObj.doAddGLJ();
-        }else if($('#actionType').val()=='replace'){
+        }else if($('#actionType').val()=='replace'){//替换工料机
             gljOprObj.doReplaceGLJ();
-        }else if($('#actionType').val()=='m_replace'){
+        }else if($('#actionType').val()=='m_replace'){//批量替换工料机
             gljOprObj.doMReplaceGLJ();
         }
     })
@@ -1295,4 +1342,23 @@ function getFormatter(decimal) {
         pre += "0"
     }
     return pre;
+}
+
+function sortRationGLJ(list) {
+    list= _.sortByAll(list,[function (item) {
+        return item.type+"";
+    },"code"])
+    return list;
+}
+
+function compareRationGLJ(a,b) {
+    if((a.type+"")<(b.type+"")){
+        return true
+    }
+    if((a.type+"")==(b.type+"")){
+        if (a.code<b.code){
+            return true
+        }
+    }
+    return false;
 }

+ 10 - 6
web/building_saas/main/js/views/main_tree_col.js

@@ -116,14 +116,18 @@ let MainTreeCol = {
         },
         forQuantity:function (node) {
             return MainTreeCol.readOnly.glj(node)||MainTreeCol.readOnly.billsParent(node)
+        },
+        forMarketPrice:function (node) {
+            return MainTreeCol.readOnly.bills(node)||(MainTreeCol.readOnly.ration(node)&&node.data.type == rationType.ration)||gljOprObj.marketPriceReadOnly(node);
         }
     },
     cellType: {
         unit: function () {
-            let combo = new GC.Spread.Sheets.CellTypes.ComboBox();
-            combo.itemHeight(10).items(['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',
+            //let combo = new GC.Spread.Sheets.CellTypes.ComboBox();
+            let dynamicCombo = sheetCommonObj.getDynamicCombo();
+            dynamicCombo.itemHeight(10).items(['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',
                 '根', '组', '系统', '台', '套', '株', '丛', '缸', '支', '只', '块', '座', '对', '份', '樘', '攒', '榀']);
-            return combo;
+            return dynamicCombo;
         },
 
         units: function () {
@@ -153,12 +157,12 @@ let MainTreeCol = {
         // CSL, 2017-11-28
         subType: function (node) {
             if (node.data.type == rationType.volumePrice || node.data.type == rationType.gljRation||node.sourceType === projectObj.project.ration_glj.getSourceType()){
-                let VPType = new GC.Spread.Sheets.CellTypes.ComboBox();
+                let VPType = sheetCommonObj.getDynamicCombo();;
 
                 if (node.data.type == rationType.volumePrice)
-                    VPType.items(["人工","材料","机械","主材","设备"])
+                    VPType.itemHeight(5).items(["人工","材料","机械","主材","设备"])
                 else if (node.data.type == rationType.gljRation||node.sourceType === projectObj.project.ration_glj.getSourceType())
-                    VPType.items(["材料","主材","设备"]);
+                    VPType.itemHeight(3).items(["材料","主材","设备"]);
 
                 return VPType;
             };

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

@@ -265,12 +265,12 @@ let basicInfoView = {
             if(datas[i].hasOwnProperty('items')){
                 let collapsed = false;
                 if(init){
-                    datas[i].collapsed=true;
+                    datas[i].collapsed=false;
                     collapsed = true;
                 }else {
                     collapsed = datas[i].collapsed == undefined ? true : datas[i].collapsed;
                 }
-                sheet.getRange(i+1, -1, datas[i].items.length, -1).visible(!collapsed);
+                //sheet.getRange(i+1, -1, datas[i].items.length, -1).visible(!collapsed);
             }
         }
     },

+ 18 - 2
web/building_saas/main/js/views/project_property_bills_quantity_decimal.js

@@ -248,7 +248,7 @@ let billsDecimalView = {
     },
 
     isValidDecimal: function (v) {
-        return this.isData(v) && !isNaN(v) && parseInt(v) % 1 === 0 && parseInt(v) >= this.default.min && parseInt(v) <= this.default.max;
+        return this.isData(v) && !isNaN(v) && parseInt(v) == v && parseInt(v) >= this.default.min && parseInt(v) <= this.default.max;
     },
 
     hasUnit: function (all, v) {
@@ -260,6 +260,21 @@ let billsDecimalView = {
         return false;
     },
 
+    copyObj: function(obj){
+        let newObj = {};
+        for(let attr in obj){
+            newObj[attr] = obj[attr];
+        }
+        return newObj;
+    },
+
+    initDatas: function (datas) {
+        this.cache = [];
+        for(let i = 0, len = datas.length; i < len; i++){
+            this.cache.push(this.copyObj(datas[i]));
+        }
+    },
+
     rowHasData: function (sheet, row) {
         let v = sheet.getValue(row, 0);
         if(v && v.toString().trim().length > 0) {
@@ -317,7 +332,8 @@ $(document).ready(function () {
     $('#poj-set').on('shown.bs.modal', function (e) {
         //init Spread
         if(billsDecimalView.isDef(billsQuanDecimal.datas)){
-            billsDecimalView.cache = billsDecimalView.cache.concat(billsQuanDecimal.datas);
+            //billsDecimalView.cache = billsDecimalView.cache.concat(billsQuanDecimal.datas);
+            billsDecimalView.initDatas(billsQuanDecimal.datas);
         }
         if(billsDecimalView.cache.length === 0){
             billsDecimalView.cache.push(billsDecimalView.angleDecimal);

+ 16 - 8
web/building_saas/main/js/views/project_property_decimal_view.js

@@ -178,20 +178,28 @@ function v_initPanel(data){
 function e_validIn(inputs){
     for(let i = 0, len = inputs.length; i < len; i++){
         let orgV = $(inputs[i]).val();
-        $(inputs[i]).keydown(function () {
-            let v = $(this).val();
-            if(v.trim().length > 0 && isValidDigit(v)){
-                orgV = v;
-            }
-        });
-        $(inputs[i]).keyup(function () {
+        $(inputs[i]).bind('input', function () {
             let v = $(this).val();
+            let inputName = $(this).attr('name');
             if(v.trim().length === 0 || !isValidDigit(v)){
                 alert('小数位数范围在0-6!');
                 $(this).val(orgV);
             }
             else{
-                //let newV = parseInt(v);
+                orgV = v;
+                //清单单价、合价 与定额单价、合价同步
+                if(inputName === 'bills-unitPrice'){
+                    $("input[name='ration-unitPrice']").val(v);
+                }
+                else if(inputName === 'bills-totalPrice'){
+                    $("input[name='ration-totalPrice']").val(v);
+                }
+                else if(inputName === 'ration-unitPrice'){
+                    $("input[name='bills-unitPrice']").val(v);
+                }
+                else if(inputName === 'ration-totalPrice'){
+                    $("input[name='bills-totalPrice']").val(v);
+                }
             }
         });
     }

+ 8 - 5
web/building_saas/main/js/views/project_property_display_view.js

@@ -12,6 +12,9 @@ let projDisplayView = {
  },
 
     needUpdate: function(autoHeight, disPlayMainMaterial) {
+        if(this.datas==null){
+            return;
+        }
         return autoHeight !== this.datas.autoHeight || disPlayMainMaterial !== this.datas.disPlayMainMaterial;
     },
 
@@ -20,13 +23,13 @@ let projDisplayView = {
             return;
         }
         var autoHeight = $('#autoHeight').prop('checked');
-        var disPlayMainMateria = $('#disPlayMainMateria').prop('checked');
-        if(this.datas.autoHeight!==autoHeight||this.datas.disPlayMainMateria!==disPlayMainMateria){
+        var disPlayMainMaterial = $('#disPlayMainMaterial').prop('checked');
+        if(this.datas.autoHeight!==autoHeight||this.datas.disPlayMainMaterial!==disPlayMainMaterial){
             this.datas.autoHeight=autoHeight;
-            this.datas.disPlayMainMateria=disPlayMainMateria;
+            this.datas.disPlayMainMaterial=disPlayMainMaterial;
+            // let updateData = {sourceType: 'properties', updateType: 'update', updateData: {ID: projectID, 'property.displaySetting':this.datas}};
+            properties['property.displaySetting'] = this.datas;
         }
-        let updateData = {updateType: 'update', updateData: {ID: projectID, 'property.displaySetting':this.datas}};
-        properties.push(updateData);
     }
 };
 

+ 11 - 3
web/building_saas/main/js/views/project_property_labour_coe_view.js

@@ -131,7 +131,15 @@ let labourCoeView = {
         me.loadData(datas);
     },
 
-    save(){
+    refresh(data){
+        let me = this;
+        projectObj.project.labourCoe.refreshData(data);
+        me.needUpdateDatas.splice(0, me.needUpdateDatas.length);
+        $("#std_labour_coe_files").val('');
+        calcProgramManage.buildSheet();
+    }
+
+/*  save(){
         let me = this;
         if (me.needUpdateDatas.length > 0){
             let projectID = projectInfoObj.projectInfo.ID;
@@ -143,11 +151,11 @@ let labourCoeView = {
                 me.needUpdateDatas.splice(0, me.needUpdateDatas.length);
                 projectObj.project.calcProgram.compileAllTemps();
                 projectObj.project.calcProgram.calcAllNodes(calcAllType.catRations);
-                rationPM.buildSheet();
                 $("#std_labour_coe_files").val('');
+                calcProgramManage.buildSheet();
             });
         }
-    }
+    }*/
 };
 
 $(document).ready(function(){

+ 11 - 6
web/building_saas/main/js/views/project_property_projFeature.js

@@ -48,10 +48,10 @@ let projFeatureView = {
     },
 
     setCombo: function (sheet, row, items) {
-        let combo = new GC.Spread.Sheets.CellTypes.ComboBox();
-        combo.items(items);
-        combo.editable(false);
-        sheet.getCell(row, 1).cellType(combo);
+        let dynamicCombo = sheetCommonObj.getDynamicCombo();
+        dynamicCombo.items(items);
+        dynamicCombo.editable(false);
+        sheet.getCell(row, 1).cellType(dynamicCombo);
     },
 
     getComboItemsByRow: function (row) {
@@ -91,6 +91,7 @@ let projFeatureView = {
         let sheet = workBook.getActiveSheet();
         sheet.bind(_events.EditStarting, this.onEditStarting);
         sheet.bind(_events.EditEnded, this.onEditEnded);
+        sheet.bind(_events.EnterCell, this.onEnterCell);
         sheet.bind(_events.ClipboardPasting, this.onClipboardPasting);
         sheet.bind(_events.ClipboardPasted, this.onClipboardPasted);
     },
@@ -142,6 +143,10 @@ let projFeatureView = {
         }
     },
 
+    onEnterCell: function (sender, args) {
+        args.sheet.repaint();
+    },
+
     onClipboardPasting: function (sender, args) {
         let me = projFeatureView;
         if(me.setting.locked.cols.indexOf(args.cellRange.col) !== -1){
@@ -260,12 +265,12 @@ let projFeatureView = {
             if(datas[i].hasOwnProperty('items')){
                 let collapsed = false;
                 if(init){
-                    datas[i].collapsed=true;
+                    datas[i].collapsed=false;
                     collapsed = true;
                 }else {
                     collapsed = datas[i].collapsed == undefined ? true : datas[i].collapsed;
                 }
-                sheet.getRange(i+1, -1, datas[i].items.length, -1).visible(!collapsed);
+                //sheet.getRange(i+1, -1, datas[i].items.length, -1).visible(!collapsed);
             }
         }
     },

+ 133 - 44
web/building_saas/main/js/views/project_view.js

@@ -335,6 +335,16 @@ var projectObj = {
             projectObj.mainController.refreshTreeNode([node], false);
         }
     },
+    mainSpreadLeaveCell: function (sender, info) {
+        let colSetting = projectObj.mainController.setting.cols[info.col];
+        projectObj.lastCol = colSetting;
+    },
+    mainSpreadEnterCell: function (sender, info) {
+        let colSetting = projectObj.mainController.setting.cols[info.col];
+        if(colSetting.data.field === 'unit' || projectObj.lastCol.data.field === 'unit'||colSetting.data.field ==='subType'|| projectObj.lastCol.data.field === 'subType'){
+            info.sheet.repaint();
+        }
+    },
     mainSpreadEditEnded: function (sender, info) {
         let project = projectObj.project;
         let node = project.mainTree.items[info.row];
@@ -343,6 +353,12 @@ var projectObj = {
         // 检查输入类型等
         let value = projectObj.checkSpreadEditingText(info.editingText, colSetting);
         projectObj.updateCellValue(node, value, colSetting);
+
+        // 自动行高
+        const autoHeight = project.property.displaySetting.autoHeight;
+        if (autoHeight) {
+            projectObj.mainSpread.getActiveSheet().autoFitRow(info.row);
+        }
     },
     mainSpreadRangeChanged: function (sender, info) {
         let project = projectObj.project, setting = projectObj.mainController.setting;
@@ -383,7 +399,8 @@ var projectObj = {
                 that.project.projSetting.mainGridSetting = JSON.parse(str);
                 that.project.projSetting.mainGridSetting.frozenCols = 4;
                 TREE_SHEET_HELPER.initSetting($('#billsSpread')[0], that.project.projSetting.mainGridSetting);
-                const autoHeight = that.project.property.displaySetting.autoHeight;
+                const autoHeight = that.project.property.displaySetting !== undefined ?
+                    that.project.property.displaySetting.autoHeight : false;
                 that.project.projSetting.mainGridSetting.cols.forEach(function (col) {
                     // for test.  后端没有绑定,暂时写死用于测试。
 /*                    if (col.data.field == '' && col.head.titleNames[0] == "取费专业") {
@@ -415,11 +432,11 @@ var projectObj = {
                     if (col.data.field === 'name' || col.data.field === 'itemCharacterText' ||
                         col.data.field === 'jobContentText' || col.data.field === 'adjustState') {
                         if (!autoHeight) {
-                            col.data.wordWrap = false;
                             col.showHint = true;
+                            col.data.wordWrap = false;
                         } else {
-                            col.data.wordWrap = true;
                             col.showHint = false;
+                            col.data.wordWrap = true;
                         }
                     }
 
@@ -438,6 +455,8 @@ var projectObj = {
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.beforeTreeSelectedChange, that.beforeMainTreeSelectedChange);
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, that.treeSelectedChanged);
 
+                that.mainSpread.bind(GC.Spread.Sheets.Events.LeaveCell, that.mainSpreadLeaveCell);
+                that.mainSpread.bind(GC.Spread.Sheets.Events.EnterCell, that.mainSpreadEnterCell);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.EditEnded, that.mainSpreadEditEnded);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.RangeChanged, that.mainSpreadRangeChanged);
                 that.loadMainSpreadContextMenu();
@@ -503,6 +522,18 @@ var projectObj = {
                         ProjectController.addRation(project, controller, rationType.volumePrice);
                     }
                 },
+                "insertGLJ": {
+                    name: "插入工料机",
+                    icon: 'fa-sign-in',
+                    disabled: function () {
+                        var selected = project.mainTree.selected;
+                        var readOnly = MainTreeCol.readOnly;
+                        return readOnly.billsParent(selected)||(readOnly.bills(selected)&&!readOnly.calcBaseType(selected));
+                    },
+                    callback: function (key, opt) {
+                        getGLJData('insert');// ProjectController.addRation(project, controller, rationType.volumePrice);
+                    }
+                },
                 "spr1": '--------',
                 "delete": {
                     name: '删除',
@@ -529,8 +560,8 @@ var projectObj = {
                 "calculateAll_RationContent": {
                     name: '造价计算',
                     callback: function () {
-                        // projectObj.calculateAll();
-                        project.calcProgram.calcAllNodes();
+                        let changedNodes = project.calcProgram.calcAllNodes();
+                        project.calcProgram.saveNodes(changedNodes);
                     }
                 }
             }
@@ -597,6 +628,8 @@ $('#delete').click(function () {
         } else if (selected.sourceType === project.Ration.getSourceType()) {
             project.Ration.delete(selected.source);
             controller.delete();
+        }else if(selected.sourceType==ModuleNames.ration_glj){
+            project.ration_glj.updataOrdelete(selected.source);
         };
         projectObj.converseCalculateBills(parent);
     }
@@ -659,75 +692,131 @@ $('#poj-set').on('show.bs.modal', function () {
     if (projectObj.project) {
         // let mode = projectObj.project.projSetting.billsCalcMode;
         // let settingConst = projectObj.project.projSetting.settingConst;
-        let mode = projectObj.project.property.billsCalcMode ? projectObj.project.property.billsCalcMode : leafBillGetFeeType.rationContent;
-        setCalcFlag($('#rationContent'), leafBillGetFeeType.rationContent, mode);
-        setCalcFlag($('#rationPriceConverse'), leafBillGetFeeType.rationPriceConverse, mode);
-        setCalcFlag($('#rationPrice'), leafBillGetFeeType.rationPrice, mode);
-        setCalcFlag($('#billsPrice'), leafBillGetFeeType.billsPrice, mode);
+        let ft = projectObj.project.property.billsCalcMode ? projectObj.project.property.billsCalcMode : leafBillGetFeeType.rationContent;
+        setCalcFlag($('#rationContent'), leafBillGetFeeType.rationContent, ft);
+        setCalcFlag($('#rationPriceConverse'), leafBillGetFeeType.rationPriceConverse, ft);
+        setCalcFlag($('#rationPrice'), leafBillGetFeeType.rationPrice, ft);
+        setCalcFlag($('#billsPrice'), leafBillGetFeeType.billsPrice, ft);
 
         // mode = projectObj.project.projSetting.zanguCalcType;
-        mode = projectObj.project.property.zanguCalcMode ? projectObj.project.property.zanguCalcMode : zanguCalcType.common;
-        setCalcFlag($('#zangu_common'), zanguCalcType.common, mode);
-        setCalcFlag($('#zangu_gatherMaterial'), zanguCalcType.gatherMaterial, mode);
+        let zg = projectObj.project.property.zanguCalcMode ? projectObj.project.property.zanguCalcMode : zanguCalcType.common;
+        setCalcFlag($('#zangu_common'), zanguCalcType.common, zg);
+        setCalcFlag($('#zangu_gatherMaterial'), zanguCalcType.gatherMaterial, zg);
     }
 });
 $('#property_ok').click(function () {
-    let properties = [], projectID = parseInt(scUrlUtil.GetQueryString('project'));
-    let project = projectObj.project, reCalc= false;
+    let project = projectObj.project,
+        projectID = project.ID(),
+
+        properties = {},
+        labourCoes = {},
+        rations = [],
+        bills = [],
+
+        mixDatas = {
+            projectID: projectID,
+            updateType: 'update',
+            properties: properties,
+            labourCoes: labourCoes,
+            rations: rations,
+            bills: bills
+        },
+
+        reCalcBills= false,
+        reCalcRations= false;
+
     let b = parseInt($("input[name='calcFlag']:checked").val());
     if (b !== project.property.billsCalcMode) {
-        let data1 = {updateType: 'update', updateData: {ID: projectID, 'property.billsCalcMode': b}};
-        properties.push(data1);
+        properties['property.billsCalcMode'] = b;
         project.property.billsCalcMode = b;
-        reCalc = true;
+        reCalcBills = true;
     };
 
     let zg = parseInt($("input[name='zangu']:checked").val());
     if (zg !== project.property.zanguCalcMode) {
-        let data2 = {updateType: 'update', updateData: {ID: projectID, 'property.zanguCalcMode': zg}};
-        properties.push(data2);
+        properties['property.zanguCalcMode'] = zg;
         project.property.zanguCalcMode = zg;
-        reCalc = true;
+        reCalcBills = true;
     };
 
-    if (labourCoeView.needSave()){
-        labourCoeView.save();
-        reCalc = true;
-    }
-
-    if (reCalc) {
-        project.calcProgram.calcAllNodes(calcAllType.catBills);
-    }
     //基本信息
     if(basicInfoView.toUpdate(basicInfoView.orgDatas, basicInfoView.datas)){
-        let updateData = {updateType: 'update', updateData: {ID: projectID, 'property.basicInformation': basicInfoView.toSaveDatas(basicInfoView.datas)}};
-        properties.push(updateData);
+        properties['property.basicInformation'] = basicInfoView.toSaveDatas(basicInfoView.datas);
     }
     //工程特征
     if(projFeatureView.toUpdate(projFeatureView.orgDatas, projFeatureView.datas)){
-        let updateData = {updateType: 'update', updateData: {ID: projectID, 'property.projectFeature': projFeatureView.toSaveDatas(projFeatureView.datas)}};
-        properties.push(updateData);
+        properties['property.projectFeature'] = projFeatureView.toSaveDatas(projFeatureView.datas);
     }
     //清单工程量精度
     let newBillsDecimalDatas = billsDecimalView.toBillsDecimalDatas(billsDecimalView.cache);
     if(billsDecimalView.toUpdate(billsQuanDecimal.datas, newBillsDecimalDatas)){
-        let updateData = {updateType: 'update', updateData: {ID: projectID, 'property.billsQuantityDecimal': newBillsDecimalDatas}};
-        properties.push(updateData);
+        reCalcBills = true;
+        properties['property.billsQuantityDecimal'] = newBillsDecimalDatas;
     }
     //小数位数
-    //获取更新的数据
     let updateDecimal = m_getDecimalData($('input', '#poj-settings-decimal'));
     if(toUpdateDecimal(decimalObj, updateDecimal)){
-        let updateData = {updateType: 'update', updateData: {ID: projectID, 'property.decimal': updateDecimal}};
-        properties.push(updateData);
+        reCalcRations = true;
+        reCalcBills = true;
+        properties['property.decimal'] = updateDecimal;
+    };
+    // 呈现选项
+    projDisplayView.updateChecking(projectID, properties);
+
+    // 人工系数
+    if (labourCoeView.needSave()){
+        reCalcRations = true;
+        reCalcBills = true;
+        project.calcProgram.compileAllTemps();
+
+        let libID = $("#std_labour_coe_files").children("option:selected").val();
+        let libName = $("#std_labour_coe_files").children("option:selected").text();
+
+        labourCoes.updateData = {libID: libID, libName: libName, newItemArr: labourCoeView.needUpdateDatas};
+    };
+
+    // 重新计算树节点
+    let changedNodes = [];
+    if (reCalcRations)    // 定额动,全部计算。
+        changedNodes = project.calcProgram.calcAllNodes(calcAllType.catAll)
+    else if (reCalcBills)  // 清单动,可以只计算清单。
+        changedNodes = project.calcProgram.calcAllNodes(calcAllType.catBills);
+    if (changedNodes.length > 0) {
+        for (let node of changedNodes){
+            let data = {
+                // projectID: projectID,
+                ID: node.data.ID,
+                quantity: node.data.quantity,
+                calcBase: node.data.calcBase,
+                calcBaseValue: node.data.calcBaseValue,
+                marketUnitFee: node.data.marketUnitFee,
+                marketTotalFee: node.data.marketTotalFee,
+                fees: node.data.fees,
+                feeRate: node.data.feeRate,
+                feeRateID: node.data.feeRateID
+            };
+            if (node.sourceType == 'ration'){
+                rations.push(data);
+            }
+            else if (node.sourceType == 'bills'){
+                bills.push(data);
+            };
+        };
+    };
+
+    console.log(mixDatas);
+    function hasMixData() {
+        return Object.keys(mixDatas.properties).length > 0 ||
+            mixDatas.labourCoes.updateData || mixDatas.rations.length > 0 || mixDatas.bills.length > 0;
     }
- // 呈现选项
-    projDisplayView.updateChecking(projectID,properties);
 
-    console.log(properties);
-    if(properties.length > 0){
-        CommonAjax.post('/pm/api/updateProjects', {user_id: userID, updateData: properties}, function (rstData) {
-            window.location.href = '/main?project=' + projectID;
+    if(hasMixData){
+        CommonAjax.post('/pm/api/updateMixDatas', {user_id: userID, mixDataArr: mixDatas}, function (rstData) {
+/*            if (changedNodes.length > 0) {
+                for (let node of changedNodes){delete node.changed};
+            };
+            if (mixDatas.labourCoes.updateData) labourCoeView.refresh(mixDatas.labourCoes.updateData);*/
+            // window.location.href = '/main?project=' + projectID;
         });
     }
 });

+ 19 - 3
web/building_saas/main/js/views/std_bills_lib.js

@@ -46,6 +46,19 @@ var billsLibObj = {
             sheet.resumePaint();
         }
     },
+    setTagForHint: function (datas) {
+        let sheet = this.stdBillsSpread.getActiveSheet();
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        for(let i = 0, len = sheet.getRowCount(); i < len; i++){
+            sheet.setTag(i, 2, '');
+        }
+        for(let i = 0, len = datas.length; i < len; i++){
+            sheet.setTag(i, 2, datas[i].ruleText ? datas[i].ruleText : '');
+        }
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
     loadStdBillsLib: function () {
         let i, select = $('#stdBillsLibSelect');
         select.empty();
@@ -153,9 +166,11 @@ var billsLibObj = {
             stdBills = datas;
             stdBillsTree.loadDatas(stdBills);
             stdBillsTreeController.showTreeData();
+            billsLibObj.setTagForHint(datas);
             showBillsRela(stdBillsTree.firstNode());
 
             stdBillsTreeController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, showBillsRela);
+            that.stdBillsSpread.unbind(GC.Spread.Sheets.Events.CellDoubleClick);
             that.stdBillsSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, function (sender, args) {
                 let selectNode = stdBillsTree.items[args.row];
                 if (stdBillsTree.items[args.row].children.length === 0) {
@@ -248,7 +263,7 @@ var billsLibObj = {
                 "font":"Arial"
             }
         }, {
-            "width":150,
+            "width":220,
             "readOnly": true,
             "head":{
                 "titleNames":["项目名称"],
@@ -267,6 +282,7 @@ var billsLibObj = {
         }, {
             "width":50,
             "readOnly": true,
+            "showHint": true,
             "head":{
                 "titleNames":["计量单位"],
                 "spanCols":[1],
@@ -282,7 +298,7 @@ var billsLibObj = {
                 "hAlign":1,
                 "font":"Arial"
             }
-        }, {
+        }/*, {
             "width":100,
             "readOnly": true,
             "showHint": true,
@@ -300,7 +316,7 @@ var billsLibObj = {
                 "hAlign":0,
                 "font":"Arial"
             }
-        }]
+        }*/]
     },
     jobsSetting: {
         "emptyRows":0,

+ 22 - 1
web/building_saas/main/js/views/std_ration_lib.js

@@ -8,6 +8,9 @@ var rationLibObj = {
     rationChapterSpread: null,
     sectionRationsSpread: null,
     rationChapterTreeController: null,
+    refreshSettingForHint: function () {
+        TREE_SHEET_HELPER.initSetting($('#stdSectionRations')[0], rationLibObj.sectionRationsSetting);
+    },
     checkSpread: function () {
         if (!this.rationChapterSpread) {
             this.rationChapterSpread = SheetDataHelper.createNewSpread($('#stdRationChapter')[0]);
@@ -16,6 +19,7 @@ var rationLibObj = {
             this.sectionRationsSpread = SheetDataHelper.createNewSpread($('#stdSectionRations')[0]);
 
             this.sectionRationsSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, this.onRationSpreadCellDoubleClick);
+            this.refreshSettingForHint();
         }
     },
     refreshSpread: function () {
@@ -63,13 +67,27 @@ var rationLibObj = {
             showRationChapterTree([]);
         });
     },
+    setTagForHint: function (datas) {
+        let sheet = this.sectionRationsSpread.getActiveSheet();
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        for(let i = 0, len = sheet.getRowCount(); i < len; i++){
+            sheet.setTag(i, 1, '');
+        }
+        for(let i = 0, len = datas.length; i < len; i++){
+            sheet.setTag(i, 1, datas[i].hint ? datas[i].hint : '');
+        }
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
     loadSectionRations: function (sectionID) {
         var showDatas = function (datas, setting) {
             SheetDataHelper.loadSheetHeader(setting, rationLibObj.sectionRationsSpread.getActiveSheet());
             SheetDataHelper.loadSheetData(setting, rationLibObj.sectionRationsSpread.getActiveSheet(), datas);
+            rationLibObj.setTagForHint(datas);
         };
         if (sectionID) {
-            CommonAjax.postRationLib('/rationRepository/api/getRationItems', {userId: userID, sectionID: sectionID}, function (datas) {
+            CommonAjax.postRationLib('/rationRepository/api/getRationGljItems', {userId: userID, sectionID: sectionID}, function (datas) {
                 showDatas(datas, rationLibObj.sectionRationsSetting);
             }, function () {
                 showDatas([], rationLibObj.sectionRationsSetting);
@@ -174,6 +192,7 @@ var rationLibObj = {
         }, {
             "width":220,
             "readOnly": true,
+            "showHint": true,
             "head":{
                 "titleNames":["名称"],
                 "spanCols":[1],
@@ -225,6 +244,8 @@ var rationLibObj = {
         }]
     }
 };
+
+addEventOnResize(rationLibObj.refreshSettingForHint);
 $('#stdRationTab').bind('click', function () {
     refreshSubSpread();//subSpread、jobSpread、itemSpread显示问题
     var select = $('#stdRationLibSelect');

+ 128 - 0
web/building_saas/main/js/views/sub_view.js

@@ -114,6 +114,134 @@ $("#linkTZJNR").click(function () {
     gljOprObj.activeTab='#linkTZJNR';
 });
 
+// 应用到选中清单
+let isSaving = false;
+$("#use-to-current").click(function() {
+    if (isSaving) {
+        return false;
+    }
+    const setting = getAddRuleSetting();
+    isSaving = true;
+    const self = $(this);
+    self.attr('disabled', 'disabled');
+    let selectedNode = projectObj.mainController.tree.selected;
+    pageCCOprObj.setCharacterBySetting(selectedNode, setting);
+    // 防止连续点击1秒后才能再次发起请求
+    setTimeout(function() {
+        isSaving = false;
+        self.removeAttr('disabled');
+    }, 1000);
+});
+// 应用到所有的清单
+$("#use-to-all").click(function() {
+    let treeNode = projectObj.mainController.tree;
+    const setting = getAddRuleSetting();
+    if (treeNode.items === undefined || treeNode.items.length <= 0) {
+        return false;
+    }
+    for (const item of treeNode.items) {
+        if (item.data.jobContent === undefined || item.data.jobContent.length <= 0 ||
+        item.data.itemCharacter === undefined || item.data.itemCharacter.length <= 0) {
+            continue;
+        }
+        pageCCOprObj.setCharacterBySetting(item, setting);
+    }
+});
+
+// 添加位置选择
+$("#add-position").change(function() {
+    const selected = $(this).children(":selected").val();
+    const addContentEle = $("#add-content");
+    const displayFormatEle = $("#display-format");
+    const characterFormatEle = $("#character-format");
+    switch (selected) {
+        case '4':
+            // 分别添加到对应列
+            // 当“添加位置”是“分别添加到对应列”,则“添加内容”恢复默认“无”,且灰显;“显示格式”恢复默认“换行分隔”,且灰显。
+            addContentEle.val('');
+            addContentEle.attr('disabled', 'disabled');
+            displayFormatEle.val(1);
+            displayFormatEle.attr('disabled', 'disabled');
+            characterFormatEle.val(2);
+            characterFormatEle.attr('disabled', 'disabled');
+            break;
+        default:
+            addContentEle.removeAttr('disabled');
+            displayFormatEle.removeAttr('disabled');
+            characterFormatEle.removeAttr('disabled');
+            break;
+    }
+});
+// 添加内容选择
+$("#add-content").change(function() {
+    const selected = $(this).children(":selected").val();
+    const characterFormatEle = $("#character-format");
+    const childDisplayFormatEle = $("#child-display-format");
+    const serialTypeEle = $("#serial-type");
+
+    switch (selected) {
+        case '5':
+            // 当“添加内容”是“定额子目”或“工作内容”,则“特征生成方式”灰显,不需选择;否则有效可选。
+            characterFormatEle.attr('disabled', 'disabled');
+            characterFormatEle.val(2);
+            // 当“添加内容”是“定额子目”,则“子目生成方式”有效可选;否则灰显,不需选择。
+            childDisplayFormatEle.removeAttr('disabled');
+            serialTypeEle.val('');
+            serialTypeEle.attr('disabled', 'disabled');
+            break;
+        case '4':
+            // 当“添加内容”是“定额子目”或“工作内容”,则“特征生成方式”灰显,不需选择;否则有效可选。
+            characterFormatEle.attr('disabled', 'disabled');
+            characterFormatEle.val(2);
+        default:
+            serialTypeEle.removeAttr('disabled');
+            childDisplayFormatEle.attr('disabled', 'disabled');
+            break;
+    }
+});
+
+// 子目生成方式选择事件
+$("#child-display-format").change(function() {
+    const selected = $(this).children(":selected").val();
+    const serialTypeEle = $("#serial-type");
+    // 如果是编号+定额名称则序号格式不能选择
+    if (selected === '1') {
+        // 默认选中数字显示模式
+        serialTypeEle.val("");
+        serialTypeEle.attr('disabled', 'disabled');
+    } else {
+        serialTypeEle.removeAttr('disabled');
+    }
+});
+
+/**
+ * 获取添加规则的设置
+ *
+ * @return {Object} - 返回设置内容
+ */
+function getAddRuleSetting() {
+    // 添加位置
+    const position = $("#add-position").val();
+    // 添加内容
+    const addContent = $("#add-content").val();
+    // 显示格式
+    const displayFormat = $("#display-format").val();
+    // 特征生成方式
+    const characterFormat = $("#character-format").val();
+
+    // 序号格式
+    const serialType = $("#serial-type").val();
+    const setting = {
+        serialType,
+        characterFormat,
+        addContent,
+        position,
+        displayFormat,
+    };
+
+    return setting;
+}
+
 function activeSubSheetIs(idx){
     let rst = subSpread.getActiveSheetIndex() == idx;
     return rst;

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

@@ -26,9 +26,6 @@
         #summary-engineering,#summary-project{
             display: none;
         }
-        #header-menu{
-            display: none;
-        }
     </style>
 </head>
 
@@ -83,7 +80,7 @@
                                     <div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
                                         <a href="javascript:void(0);"  id="add-project-btn" class="dropdown-item"><i class="fa fa-cubes"></i>新建建设项目</a>
                                         <a href="javascript:void(0);"  id="add-engineering-btn" class="dropdown-item disabled"><i class="fa fa-cube"></i> 新建单项工程</a>
-                                        <a href="javascript:void(0);"  id="add-folder-btn" class="dropdown-item"><i class="fa fa-folder-o"></i>新建文件夹</a>
+                                        <a href="javascript:void(0);"  id="add-folder-btn" class="dropdown-item"><i class="fa fa-folder-o"></i> 新建文件夹</a>
                                     </div>
                                 </div>
                                 <a href="javascript:void(0);" class="btn btn-sm" id="rename-btn">重命名</a>
@@ -233,7 +230,7 @@
     <div class="modal-dialog" role="document">
         <div class="modal-content">
             <div class="modal-header">
-                <h5 class="modal-title">新建 <i class="fa fa-cubes"></i> 建设项目</h5>
+                <h5 class="modal-title"><i class="fa fa-cubes"></i> 新建建设项目</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                     <span aria-hidden="true">&times;</span>
                 </button>
@@ -284,7 +281,7 @@
     <div class="modal-dialog" role="document">
         <div class="modal-content">
             <div class="modal-header">
-                <h5 class="modal-title">新建 <i class="fa fa-sticky-note-o"></i> 单位工程</h5>
+                <h5 class="modal-title"><i class="fa fa-sticky-note-o"></i>新建单位工程</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                     <span aria-hidden="true">&times;</span>
                 </button>
@@ -369,7 +366,7 @@
     <div class="modal-dialog" role="document">
         <div class="modal-content">
             <div class="modal-header">
-                <h5 class="modal-title">新建文件夹</h5>
+                <h5 class="modal-title"><i class="fa fa-folder-o"></i>新建文件夹</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                     <span aria-hidden="true">&times;</span>
                 </button>
@@ -522,5 +519,6 @@
     let billValuation = '<%- billValuation %>';
     let rationValuation = '<%- rationValuation %>';
     let engineeringList = '<%- engineeringList %>';
+    let compilationData = JSON.parse('<%- compilationData %>');
 </script>
 </html>

+ 1 - 1
web/building_saas/pm/js/pm_ajax.js

@@ -6,7 +6,7 @@ var GetAllProjectData = function (callback) {
     $.ajax({
         type:"POST",
         url: '/pm/api/getProjects',
-        data: {'data': JSON.stringify({"user_id": userID})},
+        data: {'data': JSON.stringify({"user_id": userID, "compilation": compilationData._id})},
         dataType: 'json',
         cache: false,
         timeout: 50000,

+ 59 - 32
web/building_saas/pm/js/pm_main.js

@@ -13,7 +13,6 @@ let feeRateData = [];
 let isSaving = false;
 let projectProperty = [];
 let fileDelObj = null;
-let selectedInfo = {project: null, engineering: null};//新建单位工程,建设项目和单项工程下拉选择
 let projectType = {
     folder: 'Folder',
     tender: 'Tender',
@@ -96,45 +95,44 @@ let ProjTreeSetting = {
             }
         },
         {
-            head: '计价方式',
+            head: '工程造价',
             data: 'valuationType',
             width: '10%',
             event: {
                 getText: function (html, node, text) {
                     if(node.data.projType === projectType.tender){
-                        let typeText = node.data.property.valuationType === 'bill'? '清单计价' : '定额计价';
-                        html.push(typeText);
+                        html.push('0');
                     }
                 }
             }
         },
         {
-            head: '计价规则',
-            data: 'valuationName',
-            width: '10%',
+            head: '单价文件',
+            data: 'unitPriceFile',
+            width: '15%',
             event: {
                 getText: function (html, node, text) {
                     if(node.data.projType === projectType.tender){
-                        let valuationText = node.data.property.valuationName;
-                        html.push(valuationText);
+                        let unitPriceText = node.data.property.unitPriceFile ? node.data.property.unitPriceFile.name : '';
+                        html.push(unitPriceText);
                     }
                 }
             }
         },
         {
-            head: '工程专业',
-            data: 'engineeringName',
-            width: '10%',
+            head: '费率文件',
+            data: 'feeFile',
+            width: '15%',
             event: {
                 getText: function (html, node, text) {
                     if(node.data.projType === projectType.tender){
-                        let engineeringText = node.data.property.engineeringName;
-                        html.push(engineeringText);
+                        let feeFileText = node.data.property.feeFile ? node.data.property.feeFile.name : '';
+                        html.push(feeFileText);
                     }
                 }
             }
         },
-        {
+        /*{
             head: '最近使用',
             data: 'lastDateTime',
             width: '10%',
@@ -145,7 +143,7 @@ let ProjTreeSetting = {
                     }
                 }
             }
-        },
+        },*/
         {
             head: '创建日期',
             data: 'createDateTime',
@@ -358,10 +356,16 @@ $(document).ready(function() {
 
     // 新增单位工程弹层改变
     $('#add-tender-dialog').on('show.bs.modal', function() {
+        //clear info
+        $('#poj-name-info').hide();
+        $('#eng-name-info').hide();
+        $('#tender-name-info').hide();
+        $('#tender-name').val('');
         //获取建设项目
         let selected = Tree.selected();
         let projs = getProjs(selected);
         setProjOptions(projs);
+       $($("input[name='valuation_type']")[0]).click();
     });
 
     // 新增单位工程
@@ -949,24 +953,41 @@ function existName(name , nodes){
 function getProjs(selected){
     let rst = [];
     let temp;
+    let firstNode;
     if(!selected){
         temp = Tree._root.children;
+        firstNode = temp[0];
     }
     else if(selected.data.projType === projectType.folder){
         temp = selected.children;
+        firstNode = temp[0];
     }
     else if(selected.data.projType === projectType.project){
         temp = selected.parent.children;
+        firstNode = temp[0];
     }
     else if(selected.data.projType === projectType.engineering || selected.data.projType === projectType.tender){
         let proj = selected.parent.data.projType === projectType.project ? selected.parent : selected.parent.parent;
         temp = proj.parent.children;
+        firstNode = proj;
     }
     for(let i = 0, len = temp.length; i < len; i++){
         if(temp[i].data.projType === projectType.project){
             rst.push(temp[i]);
         }
     }
+    //firstNode to first place
+    let index = null;
+    for(let i = 0, len = rst.length; i < len; i++){
+        if(rst[i].data.ID === firstNode.data.ID){
+            index = i;
+            break;
+        }
+    }
+    if(index){
+        rst.splice(index, 1);
+        rst.splice(0, 0, firstNode);
+    }
     return rst;
 }
 
@@ -981,6 +1002,7 @@ function setFileOptions(projID){
     }
     else {
         getUnitFile(projID, function (response) {
+            $("#unit-price").children("option:not(':first')").remove();
             if (response.data.length <= 0) {
                 return false;
             }
@@ -988,17 +1010,16 @@ function setFileOptions(projID){
             for(let tmp of response.data) {
                 unitFileHtml += '<option value="'+ tmp.id +'">'+ tmp.name +'</option>';
             }
-            $("#unit-price").children("option:not(':first')").remove();
             $("#unit-price").children("option").first().after(unitFileHtml);
         });
         // 获取费率文件数据
         getFeeRateFile(projID, function (response) {
-            if (response.data.length <= 0) {
-                return false;
-            }
             let first = $("#tender-fee-rate").children("option").first();
             $("#tender-fee-rate").empty();
             $("#tender-fee-rate").append(first);
+            if (response.data.length <= 0) {
+                return false;
+            }
             for(let tmp of response.data) {
                 let option =  $("<option>").val(tmp.ID).text(tmp.name);
                 $("#tender-fee-rate").append(option);
@@ -1011,12 +1032,8 @@ function setFileOptions(projID){
 function setProjOptions(projs){
     $("#poj-name-list").empty();
     $("#poj-name").val("");
-    selectedInfo.project = null;
     if(projs.length > 0){
         $("#poj-name").val(projs[0].data.name);
-        selectedInfo.project = Object.create(null);
-        selectedInfo.project.ID = projs[0].data.ID;
-        selectedInfo.project.name = projs[0].data.name;
         setFileOptions(projs[0].data.ID);
         setEngOptions(projs[0].data.ID);
         for(let i = 0, len = projs.length; i < len; i++){
@@ -1024,8 +1041,6 @@ function setProjOptions(projs){
             proj.addClass("dropdown-item");
             proj.attr("type", "button");
             proj.click(function () {
-                selectedInfo.project.ID = projs[i].data.ID;
-                selectedInfo.project.name = projs[i].data.name;
                 $("#poj-name").val(projs[i].data.name);
                 setFileOptions(projs[i].data.ID);
                 setEngOptions(projs[i].data.ID);
@@ -1043,21 +1058,33 @@ function setEngOptions(projID){
     let proj = Tree.findNode(projID) || null;
     $("#eng-name-list").empty();
     $("#eng-name").val("");
-    selectedInfo.engineering = null;
     if(proj){
         let engineerings = proj.children;
+        //set selected engineering to first place
+        let selected = Tree.selected();
+        let firstNode = null;
+        if(selected && (selected.data.projType === projectType.engineering || selected.data.projType === projectType.tender)){
+            firstNode = selected.data.projType === projectType.engineering ? selected : selected.parent;
+        }
+        if(firstNode){
+            let index = null;
+            for(let i = 0, len = engineerings.length; i < len; i++){
+                if(firstNode.data.ID === engineerings[i].data.ID){
+                    index = i;
+                }
+            }
+            if(index){
+                engineerings.splice(index, 1);
+                engineerings.splice(0, 0, firstNode);
+            }
+        }
         if(engineerings.length > 0){
             $("#eng-name").val(engineerings[0].data.name);
-            selectedInfo.engineering = Object.create(null);
-            selectedInfo.engineering.ID = engineerings[0].data.ID;
-            selectedInfo.engineering.name = engineerings[0].data.name;
             for(let i = 0, len = engineerings.length; i < len; i++){
                 let eng = $("<button>").val(engineerings[i].data.ID).text(engineerings[i].data.name);
                 eng.addClass("dropdown-item");
                 eng.attr("type", "button");
                 eng.click(function () {
-                    selectedInfo.engineering.ID = engineerings[i].data.ID;
-                    selectedInfo.engineering.name = engineerings[i].data.name;
                     $("#eng-name").val(engineerings[i].data.name);
                 });
                 $("#eng-name-list").append(eng);

+ 1 - 1
web/common/html/header.html

@@ -1,6 +1,6 @@
 <nav class="navbar navbar-expand-lg p-0 d-flex">
     <a class="header-logo px-2" href="/pm" style="text-decoration: none;">纵横云造价</a>
-    <ul class="nav navbar-nav px-1" id="header-menu">
+    <ul class="nav navbar-nav px-1" id="header-menu" style="display: none;">
         <li class="nav-item">
             <a class="nav-link" href="#" aria-expanded="false" data-toggle="modal" data-target="#poj-set"><i class="fa fa-cube"></i> 项目属性</a>
         </li>