Browse Source

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

TonyKang 7 years atrás
parent
commit
a11828cc81
48 changed files with 982 additions and 284 deletions
  1. 2 2
      modules/common/base/base_model.js
  2. 4 1
      modules/glj/controllers/glj_controller.js
  3. 1 1
      modules/glj/models/unit_price_file_model.js
  4. 22 1
      modules/main/controllers/ration_controller.js
  5. 7 7
      modules/main/facade/labour_coe_facade.js
  6. 12 2
      modules/main/models/ration.js
  7. 2 1
      modules/main/routes/ration_route.js
  8. 42 1
      modules/pm/controllers/pm_controller.js
  9. 6 3
      modules/pm/models/project_model.js
  10. 1 1
      modules/pm/models/project_property_template.js
  11. 1 0
      modules/pm/routes/pm_route.js
  12. 38 5
      modules/ration_glj/facade/ration_glj_facade.js
  13. 31 14
      modules/ration_glj/models/ration_glj_temp.js
  14. 10 0
      modules/ration_repository/controllers/ration_controller.js
  15. 23 0
      modules/ration_repository/models/ration_item.js
  16. 1 0
      modules/ration_repository/routes/ration_front_end_routes.js
  17. 64 7
      public/web/scMathUtil.js
  18. 5 1
      public/web/sheet/sheet_data_helper.js
  19. 4 1
      public/web/tree_sheet/tree_sheet_helper.js
  20. 3 3
      web/building_saas/complementary_glj_lib/js/glj.js
  21. 10 2
      web/building_saas/glj/js/project_glj_spread.js
  22. 5 5
      web/building_saas/main/html/main.html
  23. 6 4
      web/building_saas/main/js/main.js
  24. 9 11
      web/building_saas/main/js/models/calc_base.js
  25. 12 1
      web/building_saas/main/js/models/calc_program.js
  26. 5 5
      web/building_saas/main/js/models/fee_rate.js
  27. 0 6
      web/building_saas/main/js/models/main_consts.js
  28. 2 1
      web/building_saas/main/js/models/project.js
  29. 8 3
      web/building_saas/main/js/models/project_glj.js
  30. 134 15
      web/building_saas/main/js/models/ration_glj.js
  31. 5 4
      web/building_saas/main/js/views/calc_base_view.js
  32. 4 4
      web/building_saas/main/js/views/calc_program_manage.js
  33. 113 19
      web/building_saas/main/js/views/character_content_view.js
  34. 3 3
      web/building_saas/main/js/views/fee_rate_view.js
  35. 77 19
      web/building_saas/main/js/views/glj_view.js
  36. 13 8
      web/building_saas/main/js/views/main_tree_col.js
  37. 2 2
      web/building_saas/main/js/views/project_property_basicInfo.js
  38. 16 8
      web/building_saas/main/js/views/project_property_decimal_view.js
  39. 8 5
      web/building_saas/main/js/views/project_property_display_view.js
  40. 11 3
      web/building_saas/main/js/views/project_property_labour_coe_view.js
  41. 11 6
      web/building_saas/main/js/views/project_property_projFeature.js
  42. 121 48
      web/building_saas/main/js/views/project_view.js
  43. 18 3
      web/building_saas/main/js/views/std_bills_lib.js
  44. 22 1
      web/building_saas/main/js/views/std_ration_lib.js
  45. 71 26
      web/building_saas/main/js/views/sub_view.js
  46. 2 5
      web/building_saas/pm/html/project-management.html
  47. 14 15
      web/building_saas/pm/js/pm_main.js
  48. 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不能实例化,只能继承使用。');
-        }
+        }*/
     }
 
     /**

+ 4 - 1
modules/glj/controllers/glj_controller.js

@@ -13,6 +13,7 @@ import MixRatioModel from "../models/mix_ratio_model";
 import UnitPriceFileModel from "../models/unit_price_file_model";
 let logger = require("../../../logs/log_helper").logger;
 let consts = require('../../main/models/project_consts');
+let glj_type_util = require('../../../public/cache/std_glj_type_util');
 
 const ProjectModel = require('../../pm/models/project_model').project;
 class GLJController extends BaseController {
@@ -595,12 +596,14 @@ async function getGLJListByProjectID(projectId){
         responseData.data.mixRatioConnectData = mixRatioConnectData;
         responseData.data.mixRatioMap = mixRationMap;
         responseData.data.usedTenderList = usedTenderList;
+        let gljTypeMap = glj_type_util.getStdGljTypeCacheObj().innerGljTypeObj;
         responseData.data.constData = {
             materialIdList: gljListModel.materialIdList,
             ownCompositionTypes: gljListModel.ownCompositionTypes,
             roomId: unitPriceFileId,
             GLJTypeConst: JSON.stringify(GLJTypeConst),
-            usedUnitPriceInfo: usedUnitPriceInfo
+            usedUnitPriceInfo: usedUnitPriceInfo,
+            gljTypeMap:gljTypeMap
         };
     } catch (error) {
         console.log(error);

+ 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;

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

@@ -2,6 +2,8 @@
  * Created by jimiz on 2017/4/9.
  */
 var rationData = require('../models/ration');
+var ration_glj_facade = require('../../ration_glj/facade/ration_glj_facade');
+let logger = require("../../../logs/log_helper").logger;
 
 //统一回调函数
 var callback = function(req, res, err, message, data){
@@ -39,6 +41,25 @@ module.exports = {
                 callback(req, res, err, message, null);
             }
         });
+    },
+    insertGLJAsRation:insertGLJAsRation
+};
+
+async function insertGLJAsRation(req, res){
+    let result={
+        error:0
     }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await ration_glj_facade.insertGLJAsRation(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(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) {

+ 12 - 2
modules/main/models/ration.js

@@ -37,6 +37,7 @@ let rationSchema = new Schema({
     name: String,
     unit: String,
     quantity: String,
+    contain:String,//含量
     programID: Number,
     marketUnitFee: String,
     marketTotalFee: String,
@@ -51,13 +52,22 @@ let rationSchema = new Schema({
     caption: String,
     isFromDetail:{type: Number,default:0},       // 1 true 2 false
     adjustState: String,
-    content: String,
     rationProjName: String,
     comments: String,                           // 说明
     flags: [subSchema.flagsSchema],             // 标记字段
     rationAssList: [rationAssItemSchema],
     content: String,                            // 工作内容
-    ruleText: String                            // 计算规则
+    ruleText: String,                            // 计算规则
+
+    //工料机特有属性
+    projectGLJID:Number,  //项目工料机ID
+    GLJID:Number,//工料机库ID
+    original_code:String, //原始编码
+    specs:String,//规格型号
+    shortName:String,//缩写
+    customQuantity:String,//自定义消耗
+    from:{type: String,default:'std'}//std, cpt  来自标准工料机库、补充工料机库
+
 });
 
 let ration = db.model("ration", rationSchema, "ration");

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

@@ -6,10 +6,11 @@ let express = require('express');
 module.exports = function (app) {
     let rationRouter = express.Router();
     let rationController = require('../controllers/ration_controller');
-
     rationRouter.post('/getData', rationController.getData);
     rationRouter.post('/getItemTemplate', rationController.getItemTemplate);
     rationRouter.post('/allocIDs', rationController.allocIDs);
+    rationRouter.post('/insertGLJAsRation', rationController.insertGLJAsRation);
+
 
     app.use('/ration', rationRouter);
 };

+ 42 - 1
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){
@@ -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;
@@ -202,7 +243,7 @@ module.exports = {
 
     getGCDatas: async function(request, response) {
         let userID = request.session.sessionUser.ssoId;
-        let compilatoinId = req.session.sessionCompilation._id;
+        let compilatoinId = request.session.sessionCompilation._id;
         let rst = [];
         let _projs = Object.create(null), _engs = Object.create(null), prefix = 'ID_';
         try{

+ 6 - 3
modules/pm/models/project_model.js

@@ -72,7 +72,8 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, compilationId,
             }
             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();
@@ -136,7 +137,8 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, compilationId,
                         updateAll(err);
                     }
                 });
-            } else if (data.updateType === 'delete') {
+            }
+            else if (data.updateType === 'delete') {
                 deleteInfo = {};
                 deleteInfo['deleted'] = true;
                 deleteInfo['deleteDateTime'] = new Date();
@@ -190,7 +192,8 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, compilationId,
                 catch (error){
                     callback(1, error, null);
                 }
-            } else {
+            }
+            else {
                 hasError = true;
                 callback(1, '提交数据错误.', null);
             }

+ 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/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}]}'}

+ 38 - 5
modules/ration_glj/facade/ration_glj_facade.js

@@ -22,6 +22,8 @@ import stdgljutil  from "../../../public/cache/std_glj_type_util";
 import EngineeringLibModel from "../../users/models/engineering_lib_model";
 import GljDao from "../../complementary_glj_lib/models/gljModel";
 import {complementaryGljModel, stdGljModel, gljClassModel} from "../../complementary_glj_lib/models/schemas";
+import  projCounter from '../../main/models/proj_counter_model';
+
 
 
 module.exports={
@@ -35,7 +37,8 @@ module.exports={
     replaceGLJ:replaceGLJ,
     mReplaceGLJ:mReplaceGLJ,
     updateRationGLJByEdit:updateRationGLJByEdit,
-    getGLJClass:getGLJClass
+    getGLJClass:getGLJClass,
+    insertGLJAsRation:insertGLJAsRation
 }
 
 let operationMap={
@@ -138,7 +141,7 @@ function get_lib_glj_info(ration_glj) {
                     }
                 });
             }else {
-                cb(null,null);
+                cb(null,result);
             }
         })
     }
@@ -551,8 +554,8 @@ function getGLJSearchInfo(ration_glj) {
         shortName:ration_glj.shortName,
         specs: ration_glj.specs,
         unit: ration_glj.unit,
-        type: ration_glj.type,
-        type_of_work: ration_glj.type,
+        type:ration_glj.subType?ration_glj.subType:ration_glj.type,//如果有subType,则是通过插入定额级的工料机进来的
+        type_of_work: ration_glj.subType?ration_glj.subType:ration_glj.type,
         base_price: ration_glj.basePrice,
         market_price: ration_glj.basePrice,
         repositoryId:ration_glj.repositoryId,
@@ -574,7 +577,7 @@ async function addGLJ(rgList) {
        g.marketPrice=result.unit_price.market_price;
        g.adjustPrice=result.unit_price.base_price;
        g.basePrice=result.unit_price.base_price;
-       g.isAdd=result.unit_price.is_add,
+       g.isAdd=result.unit_price.is_add;
        g.projectGLJID=result.id;
        g.isEstimate=result.is_evaluate;
        g.ID=uuidV1();
@@ -710,6 +713,36 @@ async function getGLJClass(info,data) {
    return result;
 }
 
+async function insertGLJAsRation(data) {
+    let gljList = data.gljList;
+    //先更新counter
+    let counter = await projCounter.model.findOneAndUpdate({projectID:data.projectID},{ration:data.rationCount},{new:true});
+    console.log(counter);
+    if(data.hasOwnProperty("selectedSerialNo")){ //如果需要,更新序列号。
+        let query={
+            projectID:data.projectID,
+            billsItemID:data.billsItemID,
+            serialNo:{$gt: data.selectedSerialNo}
+        }
+        await ration.update(query,{$inc:{serialNo:gljList.length}},{multi: true});
+    }
+
+    for(let glj of gljList){
+        let p_glj = getGLJSearchInfo(glj);
+        let projectGljModel = new GLJListModel();
+        let result = await projectGljModel.addList(p_glj);//逐条添加到项目工料机
+        glj.marketPrice=result.unit_price.market_price;
+        glj.adjustPrice=result.unit_price.base_price;
+        glj.basePrice=result.unit_price.base_price;
+        glj.isAdd=result.unit_price.is_add;
+        glj.projectGLJID=result.id;
+        glj.isEstimate=result.is_evaluate;
+    }
+    await ration.insertMany(gljList);
+    console.log(gljList);
+    return gljList;
+}
+
 async function changAdjustState(data,rationList) {
     let stateList=[];
     for(let r of rationList){

+ 31 - 14
modules/ration_glj/models/ration_glj_temp.js

@@ -40,30 +40,47 @@ var rationAssItemSchema = mongoose.Schema({
 
 
 let rationSchema = new Schema({
+    // 公用属性部分
     ID: Number,
     projectID: Number,
     billsItemID: Number,
     serialNo: Number,
-    libID: Number,
     code: String,
     name: String,
-    maskName: String,
-    caption: String,
     unit: String,
-    quantity: String, // Decimal
-    isFromDetail:{type: Number,default:0},//1 true 2 false
+    quantity: String,
+    contain:String,//含量
     programID: Number,
-    adjustState: String,
-    content: String,
-    rationProjName: String,
-    comments: String,
-    // 费用字段
+    marketUnitFee: String,
+    marketTotalFee: String,
     fees: [subSchema.feesSchema],
-    // 标记字段
-    flags: [subSchema.flagsSchema],
     deleteInfo: deleteSchema,
-    rationAssList: [rationAssItemSchema]
-});
+    type: Number,                               // 1 定额、2 量价、3 工料机定额
+    subType: Number,                            // 子类型:1人工、201材料、301机械、4主材、5设备
+
+    // 定额特有属性:
+    libID: Number,
+    maskName: String,
+    caption: String,
+    isFromDetail:{type: Number,default:0},       // 1 true 2 false
+    adjustState: String,
+    rationProjName: String,
+    comments: String,                           // 说明
+    flags: [subSchema.flagsSchema],             // 标记字段
+    rationAssList: [rationAssItemSchema],
+    content: String,                            // 工作内容
+    ruleText: String,                            // 计算规则
+
+    //工料机特有属性
+    projectGLJID:Number,  //项目工料机ID
+    GLJID:Number,//工料机库ID
+    original_code:String, //原始编码
+    specs:String,//规格型号
+    shortName:String,//缩写
+    customQuantity:String,//自定义消耗
+    from:{type: String,default:'std'}//std, cpt  来自标准工料机库、补充工料机库
+
+},{versionKey:false});
 
 mongoose.model("ration", rationSchema, "ration");
 

+ 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);

+ 64 - 7
public/web/scMathUtil.js

@@ -1,5 +1,7 @@
 /**
  * Created by jimiz on 2017/3/28.
+ * 经验证:10000次四舍五入,用num.toFixed为15毫秒,用roundTo为47毫秒,速度低一些,但可以接受
+ * 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
  */
 
 let scMathUtil = {
@@ -31,8 +33,69 @@ let scMathUtil = {
         // 拼出完整结果
         return Number(sign + r1 + '.' + r2);
     },
+    // 原来直接用num.toString(2),如果小数段最后位数是0,会被舍掉,导致进位计算bug
+    // 改为自己计算二进制,固定为53位。
+    // 经验证速度没有差别
+    // 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
     floatToBin: function(num) {
-        return num.toString(2);
+        let sign = '';
+        let dNum = num;
+        // 符号位
+        if (num < 0) {
+            sign = '-';
+            dNum = -num;
+        };
+        // 解析整数段
+        let iNum = Math.floor(dNum);
+        let iFactor;
+        let sResult1 = '';
+        // 计算二进制整数段
+        while (iNum > 0){
+            iFactor = iNum % 2;
+            iNum = Math.floor(iNum / 2);
+            sResult1 = iFactor + sResult1;
+        }
+        // 判断是否有整数段
+        let bIntZero = sResult1 === '';
+        if (bIntZero){
+            sResult1 = '0';
+        }
+        // 解析小数段
+        let fNum = dNum - Math.floor(dNum);
+        let sResult2 = '';
+        if (fNum > 0){
+            // 双精度浮点数,尾数总长52位,因为第一位总是1,存储时已经被隐藏,所以有效位数为53位
+            const floatLength = 53;
+
+            let iLength;
+            // js的bug,浮点数直接取小数可能不能获得精确值,只有转成字符串,截取字符串中的小数段
+            let sNum = dNum.toString(10);
+            let iDot = sNum.indexOf('.');
+            sNum = '0' + sNum.substring(iDot, sNum.length);
+            fNum = Number(sNum);
+            // 有整数段,则小数位数为全部位数-整数位数
+            if (!bIntZero){
+                iLength = floatLength - sResult1.length;
+            }
+            else{
+                iLength = floatLength;
+            }
+            // 计算二进制小数段
+            while (iLength > 0){
+                fNum = fNum * 2;
+                iFactor = Math.floor(fNum);
+                fNum = fNum % 1;
+                sResult2 = sResult2 + iFactor;
+                if (iFactor > 0){
+                    bIntZero = false;
+                }
+                if (bIntZero && (iFactor === 0)){
+                    continue;
+                }
+                iLength--;
+            }
+        }
+        return sign + sResult1 + '.' + sResult2;
     },
     binToFloat: function(bin) {
         let result = 0;
@@ -74,13 +137,7 @@ let scMathUtil = {
         let result = bin;
         let iDot = bin.indexOf('.');
         if (iDot < 0){return result};
-        // 二进制浮点数带小数位数最大长度
-        let floatLength = 53;
         let iLength = bin.length;
-        // 长度小于53说明该二进制数尾数长度小于Double类型限制,未被截断,无需进位
-        if (iLength < floatLength) {
-            return result;
-        }
         iLength = bin.length;
         for (let i = iLength - 1; i > iDot; i--){
             let num = Number(bin[i]);

+ 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");
                 }
             }

+ 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
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++){

+ 10 - 2
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);
             }
         }
@@ -466,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;
 };

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

@@ -124,7 +124,7 @@
                                           </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>
@@ -170,7 +170,7 @@
                                               </p>
                                               <p>
                                                   <label class="title">序号格式:</label>
-                                                  <select id="serial-type" disabled="disabled">
+                                                  <select id="serial-type">
                                                       <option value="">无</option>
                                                       <option value="1" selected="selected">1.</option>
                                                       <option value="2">a.</option>
@@ -179,7 +179,7 @@
                                               </p>
                                               <p style="text-align: center">
                                                   <button class="btn btn-primary btn-sm" type="button" id="use-to-current">应用到选中清单</button>
-                                                  <button class="btn btn-primary btn-sm" type="button">应用到所有清单</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>

+ 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('表达式不正确');
         }
-    },
+    }
 };

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

@@ -917,6 +917,12 @@ class CalcProgram {
                     feeRate: node.data.feeRate,
                     feeRateID: node.data.feeRateID
                 };
+                if(node.sourceType==ModuleNames.ration&&node.data.type==rationType.gljRation){//定额类型的工料机做特殊处理
+                    data.code=node.data.code;
+                    data.projectGLJID = node.data.projectGLJID;
+                    delete data.marketUnitFee;
+                }
+
                 let newData = {'updateType': 'ut_update', 'updateData': data};
                 me.project.push(node.sourceType, [newData]);
             }
@@ -954,7 +960,8 @@ class CalcProgram {
         };
 
         calcNodes(me.project.mainTree.roots);
-        me.saveNodes(needSaveNodes);
+        // me.saveNodes(needSaveNodes);   保存要与计算分离,否则实际应用场景中,会产生多次通讯。
+        return needSaveNodes;
     };
 
     // 重新计算叶子清单下的所有子结点:如定额、工料机定额等(calculate算法基于定额、工料机定额的计算结果是正确的,实际上有时它们的计算结果并不是最新的)
@@ -970,4 +977,8 @@ class CalcProgram {
             me.saveNodes(needSaveNodes);
         };
     };
+    calcRationsAndSave(nodes){//计算批量替换工料机后受影响的定额,同时将结果打包保存
+
+    };
+
 }

+ 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) {

+ 0 - 6
web/building_saas/main/js/models/main_consts.js

@@ -108,12 +108,6 @@ const volumePriceMaps = {
     5: "量设"
 };
 
-const gljTypeMap = {
-   201:'材',
-   4:'主',
-   5:'设'
-}
-
 
 const rationType = {
     ration: 1,

+ 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);
                     }
                 }

+ 8 - 3
web/building_saas/main/js/models/project_glj.js

@@ -172,7 +172,8 @@ ProjectGLJ.prototype.updateBasePriceFromRG=function(recode,updateField,newval){
             me.refreshRationGLJPrice(glj);
             gljOprObj.showRationGLJSheetData();
             me.refreshTreeNodePriceIfNeed(glj);
-            
+            //触发计算
+            projectObj.project.ration_glj.reCalcWhenGLJChange(recode);
             $.bootstrapLoading.end();
         }
         $.bootstrapLoading.start();
@@ -184,7 +185,7 @@ ProjectGLJ.prototype.updateBasePriceFromRG=function(recode,updateField,newval){
     }
 }
 ProjectGLJ.prototype.refreshTreeNodePriceIfNeed = function (data) {
-    if((data.unit_price.type = gljType.MAIN_MATERIAL||data.type==gljType.EQUIPMENT)&&projectInfoObj.projectInfo.property.displaySetting.disPlayMainMateria==true){
+    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;
@@ -258,5 +259,9 @@ ProjectGLJ.prototype.getAdjustPrice = function (glj) {
     }else {
         return glj.unit_price.base_price
     }
+}
 
-}
+ProjectGLJ.prototype.getShortNameByID = function (ID) {
+    let gljTypeMap = this.datas.constData.gljTypeMap;
+    return gljTypeMap["typeId"+ID].shortName;
+}

+ 134 - 15
web/building_saas/main/js/models/ration_glj.js

@@ -175,7 +175,8 @@ var ration_glj = {
             return glj_list[glj_index].rationID;
         };
         ration_glj.prototype.refreshAfterDelete=function(data){
-            var glj_list = projectObj.project.ration_glj.datas;
+            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();
@@ -193,9 +194,7 @@ var ration_glj = {
             projectObj.mainController.refreshTreeNode([rationNode]);
             for(let o of oldData){
                 if(this.needShowToTree(o)){
-                    let node = _.find(projectObj.project.mainTree.items,function (n) {//找到对应的树节点
-                        return n.sourceType==ModuleNames.ration_glj &&n.data.ID==o.ID;
-                    });
+                    let node = me.findGLJNodeByID(o.ID);  //找到对应的树节点
                     projectObj.mainController.deleteNode(node,next);
                 }
             }
@@ -354,6 +353,7 @@ var ration_glj = {
                 if(initShow==false){//不需要初始化,只需耍新当前显示就可以了
                     gljOprObj.showRationGLJSheetData();
                 }
+                me.reCalcWhenGLJChange(recode);//触发计算定额以及父节点
                 projectObj.project.projectGLJ.loadData(function () {//等项目工料机加载完成后再给用户编辑
                     if(initShow==true){
                         gljOprObj.refreshView();
@@ -373,7 +373,7 @@ var ration_glj = {
             var doc = {};
             doc[updateField]=newval;
             if(updateField=="type"){
-                doc.shortName = gljTypeMap[newval];
+                doc.shortName =  projectObj.project.projectGLJ.getShortNameByID[newval];
             }
             CommonAjax.post("/rationGlj/updateRationGLJByEdit",{query:query,doc:doc,priceInfo:priceInfo},callback,function (err) {
                 $.bootstrapLoading.end();
@@ -405,12 +405,109 @@ var ration_glj = {
                 cb(data);
             })
         };
+        ration_glj.prototype.insertGLJAsRation = function (GLJSelection,selected,callback) {
+            let gljList = [];
+            let allGLJ=gljOprObj.AllRecode;
+            let billsItemID = null;
+            let serialNo=0;
+            let selectedSerialNo=null;
+            let nextNodeID=null;
+            let parentNodeID=null;
+            let children = [];
+            if(selected.sourceType === project.Bills.getSourceType()){
+                billsItemID = selected.data.ID;
+                parentNodeID = selected.getID();
+                nextNodeID = selected.tree.rootID();
+            }else {
+                billsItemID = selected.data.billsItemID;
+                serialNo = selected.data.serialNo;
+                selectedSerialNo=selected.data.serialNo;
+                nextNodeID= selected.getNextSiblingID();
+                parentNodeID=selected.getParentID();
+            }
+            children = project.Ration.getBillsSortRation(billsItemID);
+            serialNo==0?serialNo=children.length:"";
+            for(let con_key of GLJSelection){
+                var glj=_.find(allGLJ,function (item) {
+                    let i_key = gljOprObj.getIndex(item,['code','name','specs','unit','gljType']);
+                    return i_key ==con_key;
+                });
+                if(glj){
+                    serialNo+=1;
+                    let new_glj = {
+                        ID:project.Ration.getNewRationID(),
+                        projectID:parseInt(project.ID()),
+                        billsItemID:billsItemID,
+                        type:rationType.gljRation,
+                        code : glj.code,
+                        name :glj.name,
+                        quantity:0,
+                        unit:glj.unit,
+                        specs:glj.specs,
+                        subType:glj.gljType,
+                        basePrice:glj.basePrice,
+                        original_code:glj.code,
+                        shortName:glj.shortName,
+                        serialNo:serialNo,
+                        GLJID:glj.ID,
+                        adjCoe:glj.adjCoe,
+                        repositoryId:glj.repositoryId
+                    }
+                    if(glj.hasOwnProperty("compilationId")){
+                        new_glj.from="cpt";
+                        if(glj.code.indexOf('-')!=-1){//这条工料机是用户通过修改名称、规格、型号等保存到补充工料机库的
+                            new_glj.original_code = glj.code.split('-')[0];//取-前的编号作为原始编号
+                        }
+                    }
+                    gljList.push(new_glj);
+                }
+            }
+            if(gljList.length==0){
+                return;
+            }
+            let postData = {
+                gljList:gljList,
+                projectID:parseInt(project.ID()),
+                billsItemID:billsItemID,
+                rationCount:project.Ration.maxRationID()
+            }
+            selectedSerialNo==null?"":postData.selectedSerialNo = selectedSerialNo;
+            $.bootstrapLoading.start();
+            CommonAjax.post("/ration/insertGLJAsRation",postData,function (data) {
+                console.log(data);
+                 // 更新兄弟节点的序列号
+                if(selectedSerialNo!=null&&selectedSerialNo<children.length){
+                    for(let i = selectedSerialNo;i<children.length;i++){
+                        children[i].serialNo+=gljList.length;
+                    }
+                }
+                for(let r_glj of data){
+                    r_glj.marketUnitFee = r_glj.marketPrice;
+                    r_glj.quantity =r_glj.quantity+"";
+                    project.Ration.datas.push(r_glj);
+                    let newNode = project.mainTree.insert(parentNodeID,nextNodeID);
+                    newNode.source = r_glj;
+                    newNode.sourceType = project.Ration.getSourceType();
+                    newNode.data = r_glj;
+                    ProjectController.syncDisplayNewNode(projectObj.mainController, newNode);
+                }
+                callback();
+                $.bootstrapLoading.end();
+            },function () {
+                $.bootstrapLoading.end();
+            });
+
+
+        };
         ration_glj.prototype.addGLJByLib=function (GLJSelection,ration,callback) {
           var gljList=[];
           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,
@@ -446,8 +543,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'){
@@ -479,8 +579,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={
@@ -538,8 +641,6 @@ var ration_glj = {
             data.marketUnitFee = data.marketPrice;
         };
         ration_glj.prototype.updateFromMainSpread=function (value,node,fieldName) {
-            console.log(fieldName);
-            console.log(value);
             if(node.data[fieldName]===value){
                 return;
             }
@@ -570,13 +671,31 @@ var ration_glj = {
                 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.disPlayMainMateria==true){
+            if((data.type == gljType.MAIN_MATERIAL||data.type==gljType.EQUIPMENT)&&projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial==true){
                 return true
             }
             return false
-        }
+        };
+        ration_glj.prototype.findGLJNodeByID = function (ID) {
+            let node = _.find(projectObj.project.mainTree.items,function (n) {//找到对应的树节点
+                return n.sourceType==ModuleNames.ration_glj &&n.data.ID==ID;
+            });
+            return node;
+        };
+        ration_glj.prototype.findRationNodeByID = function (ID) {
+            let node = _.find(projectObj.project.mainTree.items,function (n) {//找到对应定额的树节点
+                return n.sourceType==ModuleNames.ration &&n.data.ID==ID;
+            });
+            return node;
+        };
+        ration_glj.prototype.reCalcWhenGLJChange = function (ration_glj) {//当改变定额工料机时,重新计算定额以及期父节点
+            let node = this.findRationNodeByID(ration_glj.rationID);
+            if(node){
+                project.calcProgram.calculate(node);
+                project.calcProgram.saveNode(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();
     });
 });
 

+ 113 - 19
web/building_saas/main/js/views/character_content_view.js

@@ -741,14 +741,23 @@ 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);
+                }
             }
         });
     },
@@ -769,10 +778,12 @@ let pageCCOprObj = {
         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) {
+            if (tmp.eigenvalue === undefined || tmp.eigenvalue.length <= 0 || !tmp.isChecked) {
                 continue;
             }
             // 获取选中的特征值
@@ -793,7 +804,7 @@ let pageCCOprObj = {
                     break;
                 case '2':
                     // 特征:特征值
-                    characterString = serialNo + tmp.character + ':' + selectedEigen;
+                    characterString = serialNo + tmp.character + ': ' + selectedEigen;
                     break;
             }
             characterArray.push(characterString);
@@ -802,6 +813,9 @@ let pageCCOprObj = {
         // 内容部分
         let jobArray = [];
         for (const tmp of itemJob) {
+            if (!tmp.isChecked) {
+                continue;
+            }
             // 匹配设置的序号格式
             const serialNo = this.formatSerialNumber(setting.serialType, tmp.serialNo);
             jobArray.push(serialNo + tmp.content)
@@ -809,6 +823,16 @@ let pageCCOprObj = {
 
         // 组合数据
         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":
                 // 项目特征+工作内容
@@ -837,6 +861,9 @@ let pageCCOprObj = {
                 const rationChapter = this.getRationChapter(node, setting);
                 contentArray.push.apply(contentArray, rationChapter);
                 break;
+            case "":
+                // 无
+                break;
         }
         // 显示格式
         switch (setting.displayFormat) {
@@ -853,6 +880,8 @@ let pageCCOprObj = {
                 content = '(' + contentArray.join(',') + ')';
                 break;
         }
+        // 还原数据
+        this.restoreData(node, setting.position, baseData, defaultContentInfo);
         // 添加到对应位置
         let saveObj = {};
         switch (setting.position) {
@@ -860,24 +889,42 @@ let pageCCOprObj = {
                 // 添加到项目特征列
                 saveObj = {field: 'itemCharacterText', text: content};
                 // 更新到数据库
-                pageCCOprObj.updateCharacterContent(pageCCOprObj.currentFindSet,
-                    {field: 'itemCharacter', updateArr: itemCharacter}, saveObj, characterOprObj);
+                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]);
+                    projectObj.mainController.refreshTreeNode([node], false);
                 }
                 break;
             case "3":
                 // 添加到工作内容列
                 saveObj =  {field: 'jobContentText', text: content};
                 // 更新到数据库
-                pageCCOprObj.updateCharacterContent(pageCCOprObj.currentFindSet,
-                    {field: 'jobContent', updateArr: itemJob}, saveObj, contentOprObj);
+                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;
         }
 
@@ -895,15 +942,15 @@ let pageCCOprObj = {
         switch (type) {
             case '1':
                 // 数字
-                serialNo = serialNo + '.';
+                serialNo = serialNo + '. ';
                 break;
             case '2':
                 // 英文字母(小写)
-                serialNo = letter[serialNo - 1] !== undefined ? letter[serialNo - 1] + '.' : '';
+                serialNo = letter[serialNo - 1] !== undefined ? letter[serialNo - 1] + '. ' : '';
                 break;
             case '3':
                 // 英文字母(大写)
-                serialNo = letter[serialNo - 1] !== undefined ? letter[serialNo - 1].toUpperCase() + '.' : '';
+                serialNo = letter[serialNo - 1] !== undefined ? letter[serialNo - 1].toUpperCase() + '. ' : '';
                 break;
         }
         return serialNo;
@@ -927,10 +974,57 @@ let pageCCOprObj = {
                 continue;
             }
             const serialNo = this.formatSerialNumber(setting.serialType, count.toString());
-            result.push(serialNo + tmp.data.code + ':' + tmp.data.name);
+            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);

+ 77 - 19
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"
@@ -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,27 @@ var gljOprObj = {
         });
         return distTypeTree;
     },
+    doInsertGLJ:function () {
+        var selected = projectObj.project.mainTree.selected;
+        var project= projectObj.project;
+        if(gljOprObj.GLJSelection.length<=0){
+            return;
+        }
+       $("#glj_tree_div").modal('hide');
+        project.ration_glj.insertGLJAsRation(gljOprObj.GLJSelection,selected,function (result) {
+            project.projectGLJ.loadData();
+            gljOprObj.showRationGLJSheetData();
+        })
+    },
     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');
@@ -958,6 +983,8 @@ var gljOprObj = {
                     gljOprObj.showRationGLJSheetData();
                     project.ration_glj.addToMainTree(result.showData);
                     project.projectGLJ.loadData();
+                    project.calcProgram.calculate(selected);
+                    project.calcProgram.saveNode(selected);
                     projectObj.mainController.refreshTreeNode([selected]);
                     $.bootstrapLoading.end();
                 }
@@ -979,11 +1006,24 @@ 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.findGLJNodeByID(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);
+                project.calcProgram.calculate(selected);
+                project.calcProgram.saveNode(selected);
             }
             $.bootstrapLoading.end();
         })
@@ -998,15 +1038,22 @@ 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.findGLJNodeByID(t.ID);
+                        nodes.push(node);
+                    }
                 }
             })
             me.showRationGLJSheetData();
             project.projectGLJ.loadData();
-            me.refreshStateAfterMreplace(stateList);
+            var rationNodes= me.refreshStateAfterMreplace(stateList,nodes);
+            project.calcProgram.calcRationsAndSave(rationNodes);
             $.bootstrapLoading.end();
         })
     },
@@ -1015,8 +1062,9 @@ var gljOprObj = {
             obj[key] = n;
         });
     },
-    refreshStateAfterMreplace:function (stateList) {
+    refreshStateAfterMreplace:function (stateList,gljNodes) {
         var nodes=[];
+        var rationNodes=[];
         _.forEach(stateList,function (s) {
           var node = _.find(projectObj.project.mainTree.items,function (n) {
               return n.sourceType==ModuleNames.ration&&n.data.ID==s.rationID;
@@ -1024,9 +1072,12 @@ var gljOprObj = {
           if(node){
               node.data.adjustState=s.adjustState;
               nodes.push(node);
+              rationNode.push(node);
           }
         });
+        gljNodes.length>0?nodes = nodes.concat(gljNodes):"";
         projectObj.mainController.refreshTreeNode(nodes);
+        return rationNodes;
     },
     refreshView:function () {
         this.showRationGLJData();
@@ -1180,16 +1231,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();
@@ -1211,11 +1267,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();
         }
     })

+ 13 - 8
web/building_saas/main/js/views/main_tree_col.js

@@ -15,10 +15,10 @@ let MainTreeCol = {
                     return volumePriceMaps[node.data.subType];
                 }
                 else if (node.data.type == 3){    // 工料机定额
-                    return '工料机';     // 这里明细值等张伟城确定
+                    return  projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
                 }
             } else if (node.sourceType === projectObj.project.ration_glj.getSourceType()) {
-                return gljTypeMap[node.data.subType];
+                return projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
             }
         },
 
@@ -32,7 +32,7 @@ let MainTreeCol = {
     readOnly: {
         // CSL, 2017-11-28
         subType: function (node){
-            return (node.data.type != 2 && node.data.type != 3&&!MainTreeCol.readOnly.glj(node));
+            return (node.data.type != 2 && node.data.type != 3&&!MainTreeCol.readOnly.glj(node))||(node.data.type==rationType.gljRation&&MainTreeCol.readOnly.non_editSubType(node));
         },
         calcProgramName: function (node) {
             if (
@@ -41,7 +41,9 @@ let MainTreeCol = {
             ) return false
             else return true;
         },
-
+        non_editSubType:function (node) {
+           return node.data.subType!=201&&node.data.subType!=4&&node.data.subType!=5
+        },
         commonUnitFee: function(node){
             return !projectObj.project.calcProgram.isNullBill(node);
         },
@@ -157,13 +159,16 @@ 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(["材料","主材","设备"]);
-
+                    if(!MainTreeCol.readOnly.non_editSubType(node)){
+                        VPType.itemHeight(3).items(["材料","主材","设备"]);
+                    }else {
+                        return null;
+                    }
                 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);
             }
         }
     },

+ 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);
             }
         }
     },

+ 121 - 48
web/building_saas/main/js/views/project_view.js

@@ -268,7 +268,9 @@ var projectObj = {
         let project = projectObj.project, fieldName = colSetting.data.field;
         if(node.sourceType==project.ration_glj.getSourceType()){
             project.ration_glj.updateFromMainSpread(value,node,fieldName);
-        }else if (value !== calcFees.getFee(node.data, fieldName)) {
+        }if(node.sourceType==ModuleNames.ration&&node.data.type==rationType.gljRation){
+            console.log("hehe");
+        } else if (value !== calcFees.getFee(node.data, fieldName)) {
             if (fieldName === 'code') {
                 projectObj.updateCode(node, value);
             }
@@ -341,7 +343,7 @@ var projectObj = {
     },
     mainSpreadEnterCell: function (sender, info) {
         let colSetting = projectObj.mainController.setting.cols[info.col];
-        if(colSetting.data.field === 'unit' || projectObj.lastCol.data.field === 'unit'){
+        if(colSetting.data.field === 'unit' || projectObj.lastCol.data.field === 'unit'||colSetting.data.field ==='subType'|| projectObj.lastCol.data.field === 'subType'){
             info.sheet.repaint();
         }
     },
@@ -357,7 +359,7 @@ var projectObj = {
         // 自动行高
         const autoHeight = project.property.displaySetting.autoHeight;
         if (autoHeight) {
-            this.mainSpread.getActiveSheet().autoFitRow(info.row);
+            projectObj.mainSpread.getActiveSheet().autoFitRow(info.row);
         }
     },
     mainSpreadRangeChanged: function (sender, info) {
@@ -399,7 +401,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] == "取费专业") {
@@ -432,18 +435,20 @@ var projectObj = {
                         col.data.field === 'jobContentText' || col.data.field === 'adjustState') {
                         if (!autoHeight) {
                             col.showHint = true;
+                            col.data.wordWrap = false;
                         } else {
                             col.showHint = false;
+                            col.data.wordWrap = true;
                         }
                     }
 
                     // for test digit. CSLAAAAA
                     if (col.data.field.hasSubStr("totalFee"))
-                       col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.totalPrice, true)
+                       col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.totalPrice, false)
                     else if (col.data.field.hasSubStr("unitFee"))
-                        col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.unitPrice, true)
+                        col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.unitPrice, false)
                     else if (col.data.field == "quantity")
-                        col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.quantity, true);
+                        col.data.formatter = MainTreeCol.getNumberFormatter(decimalObj.ration.quantity, false);
                 });
 
                 that.mainController = TREE_SHEET_CONTROLLER.createNew(that.project.mainTree, that.mainSpread.getActiveSheet(), that.project.projSetting.mainGridSetting);
@@ -519,6 +524,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.forCalcBase(selected))||readOnly.glj(selected);
+                    },
+                    callback: function (key, opt) {
+                        getGLJData('insert');// ProjectController.addRation(project, controller, rationType.volumePrice);
+                    }
+                },
                 "spr1": '--------',
                 "delete": {
                     name: '删除',
@@ -545,8 +562,8 @@ var projectObj = {
                 "calculateAll_RationContent": {
                     name: '造价计算',
                     callback: function () {
-                        // projectObj.calculateAll();
-                        project.calcProgram.calcAllNodes();
+                        let changedNodes = project.calcProgram.calcAllNodes();
+                        project.calcProgram.saveNodes(changedNodes);
                     }
                 }
             }
@@ -677,75 +694,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;
         });
     }
 });

+ 18 - 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,6 +166,7 @@ var billsLibObj = {
             stdBills = datas;
             stdBillsTree.loadDatas(stdBills);
             stdBillsTreeController.showTreeData();
+            billsLibObj.setTagForHint(datas);
             showBillsRela(stdBillsTree.firstNode());
 
             stdBillsTreeController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, showBillsRela);
@@ -249,7 +263,7 @@ var billsLibObj = {
                 "font":"Arial"
             }
         }, {
-            "width":150,
+            "width":220,
             "readOnly": true,
             "head":{
                 "titleNames":["项目名称"],
@@ -268,6 +282,7 @@ var billsLibObj = {
         }, {
             "width":50,
             "readOnly": true,
+            "showHint": true,
             "head":{
                 "titleNames":["计量单位"],
                 "spanCols":[1],
@@ -283,7 +298,7 @@ var billsLibObj = {
                 "hAlign":1,
                 "font":"Arial"
             }
-        }, {
+        }/*, {
             "width":100,
             "readOnly": true,
             "showHint": true,
@@ -301,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');

+ 71 - 26
web/building_saas/main/js/views/sub_view.js

@@ -115,46 +115,60 @@ $("#linkTZJNR").click(function () {
 });
 
 // 应用到选中清单
+let isSaving = false;
 $("#use-to-current").click(function() {
-    // 添加位置
-    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,
-    };
+    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(2);
+            displayFormatEle.val(1);
             displayFormatEle.attr('disabled', 'disabled');
-            console.log('hello');
+            characterFormatEle.val(2);
+            characterFormatEle.attr('disabled', 'disabled');
             break;
         default:
             addContentEle.removeAttr('disabled');
             displayFormatEle.removeAttr('disabled');
+            characterFormatEle.removeAttr('disabled');
             break;
     }
 });
@@ -163,21 +177,24 @@ $("#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 '4':
-            // 当“添加内容”是“定额子目”或“工作内容”,则“特征生成方式”灰显,不需选择;否则有效可选。
-            characterFormatEle.attr('disabled', 'disabled');
-            characterFormatEle.val(2);
-            break;
         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;
     }
@@ -190,13 +207,41 @@ $("#child-display-format").change(function() {
     // 如果是编号+定额名称则序号格式不能选择
     if (selected === '1') {
         // 默认选中数字显示模式
-        serialTypeEle.val(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;

+ 2 - 5
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>
@@ -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>

+ 14 - 15
web/building_saas/pm/js/pm_main.js

@@ -95,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%',
@@ -144,7 +143,7 @@ let ProjTreeSetting = {
                     }
                 }
             }
-        },
+        },*/
         {
             head: '创建日期',
             data: 'createDateTime',

+ 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>