Переглянути джерело

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

Conflicts:
	web/building_saas/main/js/views/main_tree_col.js
chenshilong 7 роки тому
батько
коміт
e7449a2c8e

+ 3 - 3
modules/ration_glj/facade/glj_calculate_facade.js

@@ -20,7 +20,7 @@ module.exports={
 //辅助定额调整、替换工料机、标准附注条件调整、添加工料机、自定义消耗量(包括删除工料机)、自定义乘系数、市场单价调整
 let stateSeq ={
     ass:1,
-    replase:2,
+    replace:2,
     coe:3,
     add:4,
     cusQuantity:5,
@@ -139,8 +139,8 @@ function calculateAss(quantity,assList,glj) {
 
 function generateAdjustState(glj,coeList,adjustState,index,quantity) {
    //替换工料机 and 添加工料机
-    if(glj._doc.createType=='replace'){
-        adjustState.push({index:stateSeq.replase,content:glj.rcode+'换'+glj.code});
+    if(glj._doc.createType=='replace'&&glj.rcode!=glj.code){
+        adjustState.push({index:stateSeq.replace,content:glj.rcode+'换'+glj.code});
     }else if(glj._doc.createType=='add'){
         adjustState.push({index:stateSeq.add,content:'添'+glj.code+'量'+parseFloat(quantity)});
     }

+ 29 - 25
modules/reports/rpt_component/helper/jpc_helper_common_output.js

@@ -2,7 +2,7 @@ let JV = require('../jpc_value_define');
 let JpcFieldHelper = require('./jpc_helper_field');
 
 let JpcCommonOutputHelper = {
-    createCommonOutputWithoutDecorate: function (node, value, controls) {
+    createCommonOutputWithoutDecorate: function (node, value) {
         let rst = {};
         //1. font/style/control
         rst[JV.PROP_FONT] = node[[JV.PROP_FONT]];
@@ -10,20 +10,11 @@ let JpcCommonOutputHelper = {
         rst[JV.PROP_STYLE] = node[[JV.PROP_STYLE]];
         //2. value
         rst[JV.PROP_VALUE] = value;
-        if (node[JV.PROP_FORMAT]) {
-            if (!(isNaN(parseFloat(rst[JV.PROP_VALUE])))) {
-                let dotIdx = node[JV.PROP_FORMAT].indexOf(".");
-                if (dotIdx >= 0) {
-                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(node[JV.PROP_FORMAT].length - dotIdx - 1);
-                } else {
-                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(0);
-                }
-            }
-        }
-        if (node[JV.PROP_PREFIX] && rst[JV.PROP_VALUE] != null) {
+        innerFormat(node[JV.PROP_FORMAT], rst);
+        if (node[JV.PROP_PREFIX] && rst[JV.PROP_VALUE] !== null) {
             rst[JV.PROP_VALUE] = node[JV.PROP_PREFIX] + rst[JV.PROP_VALUE];
         }
-        if (node[JV.PROP_SUFFIX] && rst[JV.PROP_VALUE] != null) {
+        if (node[JV.PROP_SUFFIX] && rst[JV.PROP_VALUE] !== null) {
             rst[JV.PROP_VALUE] = rst[JV.PROP_VALUE] + node[JV.PROP_SUFFIX];
         }
         return rst;
@@ -37,24 +28,37 @@ let JpcCommonOutputHelper = {
         //2. value
         rst[JV.PROP_VALUE] = value;
         JpcFieldHelper.decorateValue(rst, controls);
-        if (node[JV.PROP_FORMAT]) {
-            if (!(isNaN(parseFloat(rst[JV.PROP_VALUE])))) {
-                let dotIdx = node[JV.PROP_FORMAT].indexOf(".");
-                if (dotIdx >= 0) {
-                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(node[JV.PROP_FORMAT].length - dotIdx - 1);
-                } else {
-                    rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(0);
-                }
-            }
-        }
-        if (node[JV.PROP_PREFIX] && rst[JV.PROP_VALUE] != null && rst[JV.PROP_VALUE] != "") {
+        innerFormat(node[JV.PROP_FORMAT], rst);
+        if (node[JV.PROP_PREFIX] && rst[JV.PROP_VALUE] !== null && rst[JV.PROP_VALUE] !== "") {
             rst[JV.PROP_VALUE] = node[JV.PROP_PREFIX] + rst[JV.PROP_VALUE];
         }
-        if (node[JV.PROP_SUFFIX] && rst[JV.PROP_VALUE] != null && rst[JV.PROP_VALUE] != "") {
+        if (node[JV.PROP_SUFFIX] && rst[JV.PROP_VALUE] !== null && rst[JV.PROP_VALUE] !== "") {
             rst[JV.PROP_VALUE] = rst[JV.PROP_VALUE] + node[JV.PROP_SUFFIX];
         }
         return rst;
     }
+};
+
+function innerFormat(formatStr, rst) {
+    if (formatStr) {
+        if (!(isNaN(parseFloat(rst[JV.PROP_VALUE])))) {
+            let dotIdx = formatStr.indexOf(".");
+            if (dotIdx >= 0) {
+                rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(formatStr.length - dotIdx - 1);
+            } else {
+                rst[JV.PROP_VALUE] = parseFloat(rst[JV.PROP_VALUE]).toFixed(0);
+            }
+            let commaIdx = formatStr.indexOf(",");
+            if (commaIdx >= 0) {
+                rst[JV.PROP_VALUE] = comdify(rst[JV.PROP_VALUE].toString());
+            }
+        }
+    }
+}
+
+function comdify(numStr){
+    let re = /\d{1,3}(?=(\d{3})+$)/g;
+    return numStr.replace(/^(\d+)((\.\d+)?)$/,function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
 }
 
 module.exports = JpcCommonOutputHelper;

+ 1 - 0
modules/reports/rpt_component/jpc_bill_tab.js

@@ -1,4 +1,5 @@
 let JV = require('./jpc_value_define');
+let JE = require('./jpc_rte');
 let JpcFieldHelper = require('./helper/jpc_helper_field');
 let JpcBandHelper = require('./helper/jpc_helper_band');
 let JpcCommonHelper = require('./helper/jpc_helper_common');

+ 2 - 1
modules/reports/rpt_component/jpc_rte.js

@@ -1,9 +1,10 @@
 /**
  * Created by Tony on 2016/12/28.
  */
-
+let strUtil = require('../../../public/stringUtil');
 let JV = require('./jpc_value_define');
 let JE = {
+    $STR_UTIL: strUtil,
     F: function(fID, $CURRENT_RPT) {
         let rst = null;
         if ($CURRENT_RPT && ($CURRENT_RPT.fields[JV.NODE_DETAIL_FIELDS][JV.PROP_ID + "_" + fID])) {

+ 13 - 5
public/stringUtil.js

@@ -149,6 +149,10 @@ module.exports = {
         let regExp = new RegExp(FindText, "gm");
         return targetStr.replace(regExp, RepText);
     },
+    comdify: function(numStr){
+        let re = /\d{1,3}(?=(\d{3})+$)/g;
+        return numStr.replace(/^(\d+)((\.\d+)?)$/,function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
+    },
     convertToCaptionNum: function(num, isCurrency, isTraditionalCap) {
         let me = this, rst = "";
         if (/^\d*(\.\d*)?$/.test(num)) {
@@ -187,12 +191,16 @@ module.exports = {
                 //小数部分处理
                 if (numSplitArr.length > 1) {
                     len = numSplitArr[1].length;
-                    if (isCurrency && len > 2) len = 2;
-                    let fractionStr = [];
-                    for (let idx = 0; idx < len; idx++) {
-                        fractionStr.push(capChars[ parseInt(numSplitArr[1].charAt(idx))]+ (isCurrency?((idx === 0)?"角":"分"):""));
+                    if (parseInt(numSplitArr[1]) === 0) {
+                        rst = rst + (isCurrency?"元整":"");
+                    } else {
+                        if (isCurrency && len > 2) len = 2;
+                        let fractionStr = [];
+                        for (let idx = 0; idx < len; idx++) {
+                            fractionStr.push(capChars[ parseInt(numSplitArr[1].charAt(idx))]+ (isCurrency?((idx === 0)?"角":"分"):""));
+                        }
+                        rst = rst + (isCurrency?"元":"点") + fractionStr.join("");
                     }
-                    rst = rst + (isCurrency?"元":"点") + fractionStr.join("");
                 } else {
                     rst = rst + (isCurrency?"元整":"");
                 }

+ 43 - 5
test/demo/stringTest.js

@@ -55,9 +55,47 @@ var strUtil = require('../../public/stringUtil');
 //     t.end();
 // })
 
-test('test typeof', function(t){
-    t.equal(typeof(true), "boolean");
-    t.equal((typeof("abc")).toUpperCase(), "STRING");
-    t.equal(typeof(1), "number");
+// test('test typeof', function(t){
+//     t.equal(typeof(true), "boolean");
+//     t.equal((typeof("abc")).toUpperCase(), "STRING");
+//     t.equal(typeof(1), "number");
+//     t.end();
+// })
+
+test('test 千分位', function(t){
+    let num = 123.01;
+    t.equal( strUtil.comdify(num.toString()), "123.01");
+    num = 123456.01;
+    t.equal( strUtil.comdify(num.toString()), "123,456.01");
+    num = 1234567.01;
+    t.equal( strUtil.comdify(num.toString()), "1,234,567.01");
+    num = 1234567;
+    t.equal( strUtil.comdify(String(num)), "1,234,567");
+    t.end();
+})
+
+
+test('test number to Chinese', function(t){
+    t.equal(strUtil.convertToCaptionNum(0, false, false), '零');
+    t.equal(strUtil.convertToCaptionNum(0, true, false), '零元整');
+    t.equal(strUtil.convertToCaptionNum(0.68, true, false), '零元六角八分');
+    t.equal(strUtil.convertToCaptionNum(0.68, true, true), '零元陆角捌分');
+    t.equal(strUtil.convertToCaptionNum(10, false, false), '一十');
+    t.equal(strUtil.convertToCaptionNum(10, false, true), '壹拾');
+    t.equal(strUtil.convertToCaptionNum(11, false, false), '一十一');
+    t.equal(strUtil.convertToCaptionNum(11, false, true), '壹拾壹');
+    t.equal(strUtil.convertToCaptionNum(12, false, false), '一十二');
+    t.equal(strUtil.convertToCaptionNum(12, false, true), '壹拾贰');
+    t.equal(strUtil.convertToCaptionNum(21, false, false), '二十一');
+    t.equal(strUtil.convertToCaptionNum(21, false, true), '贰拾壹');
+
+    t.equal(strUtil.convertToCaptionNum(0.123456789, false, false), '零点一二三四五六七八九');
+    t.equal(strUtil.convertToCaptionNum(10.123456789, false, false), '一十点一二三四五六七八九');
+
+    t.equal(strUtil.convertToCaptionNum(123456789.15, false, false), '一亿二千三百四十五万六千七百八十九点一五');
+    t.equal(strUtil.convertToCaptionNum(123456789.15, false, true), '壹億贰仟叁佰肆拾伍萬陆仟柒佰捌拾玖点壹伍');
+    t.equal(strUtil.convertToCaptionNum(123456789.15, true, false), '一亿二千三百四十五万六千七百八十九元一角五分');
+    t.equal(strUtil.convertToCaptionNum(123456789.15, true, true), '壹億贰仟叁佰肆拾伍萬陆仟柒佰捌拾玖元壹角伍分');
+
     t.end();
-})
+})

+ 41 - 41
web/building_saas/glj/js/project_glj.js

@@ -19,7 +19,7 @@ let GLJTypeConst = [];
 // spreadjs载入数据所需
 let jsonData = [];
 let mixRatioConnectData = [];
-let mixRatioMap={};
+let mixRatioMap = {};
 // 单价文件相关
 let usedUnitPriceInfo = {};
 let usedTenderList = [];
@@ -32,7 +32,7 @@ $(document).ready(function () {
         init();
     });
 
-    slideResize($("#glj-main"), function() {
+    slideResize($("#glj-main"), function () {
         projectGLJSpread.sheetObj.spread.refresh();
     });
 
@@ -40,7 +40,7 @@ $(document).ready(function () {
     $('#change-dj').on('shown.bs.modal', function () {
         // 获取当前建设项数据
         let projectName = projectInfoObj.projectInfo.fullFolder !== undefined &&
-            projectInfoObj.projectInfo.fullFolder.length > 0 ? projectInfoObj.projectInfo.fullFolder[0] : '';
+        projectInfoObj.projectInfo.fullFolder.length > 0 ? projectInfoObj.projectInfo.fullFolder[0] : '';
         $("#current-project-name").text(projectName);
 
         // 获取切换单价文件相关数据
@@ -49,7 +49,7 @@ $(document).ready(function () {
             type: 'post',
             data: {project_id: scUrlUtil.GetQueryString('project')},
             dataType: 'json',
-            success: function(response) {
+            success: function (response) {
                 if (response.err === 1) {
                     alert('数据传输错误!');
                     return false;
@@ -58,9 +58,9 @@ $(document).ready(function () {
                 // 本项目中的单价文件
                 if (data.self.length > 0) {
                     let selfFileHtml = '';
-                    for(let tmp of data.self) {
+                    for (let tmp of data.self) {
                         let select = usedUnitPriceInfo === tmp.id ? ' selected="selected"' : '';
-                        selfFileHtml += '<option'+ select +' value="'+ tmp.id +'">'+ tmp.name +'</option>';
+                        selfFileHtml += '<option' + select + ' value="' + tmp.id + '">' + tmp.name + '</option>';
                     }
                     $("#self-file").html(selfFileHtml);
                 }
@@ -69,14 +69,14 @@ $(document).ready(function () {
                 if (data.other.length > 0) {
                     let otherProjectHtml = '';
                     let otherFileHtml = '';
-                    for(let tmp of data.other) {
-                        otherProjectHtml += '<option value="'+ tmp.ID +'">'+ tmp.name +'</option>';
+                    for (let tmp of data.other) {
+                        otherProjectHtml += '<option value="' + tmp.ID + '">' + tmp.name + '</option>';
                         otherFileData[tmp.ID] = tmp.unitPriceList;
                         if (otherFileHtml !== '') {
                             continue;
                         }
-                        for(let unitPrice of tmp.unitPriceList) {
-                            otherFileHtml += '<option value="'+ unitPrice.id +'">'+ unitPrice.name +'</option>';
+                        for (let unitPrice of tmp.unitPriceList) {
+                            otherFileHtml += '<option value="' + unitPrice.id + '">' + unitPrice.name + '</option>';
                         }
                     }
                     $("#other-project").html(otherProjectHtml);
@@ -87,13 +87,13 @@ $(document).ready(function () {
     });
 
     // 单价文件另存为弹框
-    $("#file-save-as-dialog").on('shown.bs.modal', function() {
+    $("#file-save-as-dialog").on('shown.bs.modal', function () {
         // 获取当前建设项数据
         $("#save-as-name").val(usedUnitPriceInfo.name + '(复件)');
     });
 
     // 单价文件另存为操作
-    $("#save-as-confirm").click(function() {
+    $("#save-as-confirm").click(function () {
         let name = $("#save-as-name").val();
         if (name === '') {
             $("#save-as-tips").text('请填写单价文件名称').show();
@@ -108,13 +108,13 @@ $(document).ready(function () {
             type: 'post',
             data: {name: name, project_id: scUrlUtil.GetQueryString('project')},
             dataType: 'json',
-            error: function() {
+            error: function () {
                 isChanging = false;
             },
-            beforeSend: function() {
+            beforeSend: function () {
                 isChanging = true;
             },
-            success: function(response) {
+            success: function (response) {
                 isChanging = false;
                 if (response.err === 1) {
                     let msg = response.msg !== undefined && response.msg !== '' ? response.msg : '另存为失败!';
@@ -128,20 +128,20 @@ $(document).ready(function () {
     });
 
     // 从其他建设项目中复制 选择建设项目
-    $("#other-project").change(function() {
+    $("#other-project").change(function () {
         let projectId = $(this).val();
         if (otherFileData[projectId] === undefined) {
             return false;
         }
         let otherFileHtml = '';
-        for(let unitPrice of otherFileData[projectId]) {
-            otherFileHtml += '<option value="'+ unitPrice.id +'">'+ unitPrice.name +'</option>';
+        for (let unitPrice of otherFileData[projectId]) {
+            otherFileHtml += '<option value="' + unitPrice.id + '">' + unitPrice.name + '</option>';
         }
         $("#other-file").html(otherFileHtml);
     });
 
     // 单价文件选项切换
-    $("input[name='change-type']").change(function() {
+    $("input[name='change-type']").change(function () {
         let type = $(this).val();
         type = parseInt(type);
         $("#change-dj .option").hide();
@@ -153,7 +153,7 @@ $(document).ready(function () {
     });
 
     // 单价文件切换确认
-    $("#change-file-confirm").click(function() {
+    $("#change-file-confirm").click(function () {
         if (isChanging) {
             return false;
         }
@@ -173,14 +173,14 @@ $(document).ready(function () {
             url: '/glj/change-file',
             type: 'post',
             data: {project_id: scUrlUtil.GetQueryString('project'), change_id: changeUnitPriceId, type: type},
-            error: function() {
+            error: function () {
                 isChanging = false;
                 $.bootstrapLoading.end();
             },
-            beforeSend: function() {
+            beforeSend: function () {
                 isChanging = true;
             },
-            success: function(response) {
+            success: function (response) {
                 isChanging = false;
                 if (response.err === 1) {
                     let msg = response.msg !== undefined ? response.msg : '未知错误';
@@ -200,19 +200,19 @@ $(document).ready(function () {
     });
 
     // 是否主动更改数据
-    $("#message").on('click', '#load-data', function() {
+    $("#message").on('click', '#load-data', function () {
         $("#message").html('正在加载...');
         // 重新加载数据到缓存
-        projectObj.project.projectGLJ.loadData(function() {
+        projectObj.project.projectGLJ.loadData(function () {
             projectObj.project.projectGLJ.loadCacheData();
             $("#notify").slideUp('fast');
         });
     });
 
     $('#pop-dj').popover({
-            placement:"bottom",
-            html:true,
-            trigger:"hover | focus",
+            placement: "bottom",
+            html: true,
+            trigger: "hover | focus",
             content: getUsedTenderInfo
         }
     );
@@ -224,11 +224,11 @@ $(document).ready(function () {
  * @return {void|boolean}
  */
 function init() {
-    projectObj.project.projectGLJ.loadData(function(data) {
+    projectObj.project.projectGLJ.loadData(function (data) {
         if (jsonData.length <= 0) {
             // 赋值
             jsonData = data.gljList !== undefined && data.gljList.length > 0 ? data.gljList : [];
-            jsonData= filterProjectGLJ(jsonData);
+            jsonData = filterProjectGLJ(jsonData);
             jsonData = sortProjectGLJ(jsonData);
             mixRatioConnectData = data.mixRatioConnectData !== undefined ? data.mixRatioConnectData : mixRatioConnectData;
             mixRatioMap = data.mixRatioMap !== undefined ? data.mixRatioMap : mixRatioMap;
@@ -291,7 +291,7 @@ function spreadInit() {
         }
     });
 
-    loadSize("glj-main", function() {
+    loadSize("glj-main", function () {
         projectGLJSpread.sheetObj.spread.refresh();
     });
 }
@@ -306,7 +306,7 @@ function spreadInit() {
 function unitPriceFileInit() {
     let projectGLJ = projectObj.project.projectGLJ;
     let data = projectGLJ.datas;
-     usedTenderList = data.usedTenderList !== undefined ? data.usedTenderList : [];
+    usedTenderList = data.usedTenderList !== undefined ? data.usedTenderList : [];
     usedUnitPriceInfo = data.constData.usedUnitPriceInfo !== undefined ?
         data.constData.usedUnitPriceInfo : {};
     $("#used-name").text(usedUnitPriceInfo.name);
@@ -315,7 +315,7 @@ function unitPriceFileInit() {
 }
 
 function getUsedTenderInfo() {
-   return usedTenderList.join("<br>");
+    return usedTenderList.join("<br>");
 }
 
 /**
@@ -357,7 +357,7 @@ function successTrigger(field, info) {
  */
 function socketInit() {
     if (socket === null) {
-        socket = io('http://'+ host +':3300');
+        socket = io('http://' + host + ':3300');
         socket.on('connect', function () {
             socket.emit('join', roomId);
             console.log('单价文件同步连接成功');
@@ -365,7 +365,7 @@ function socketInit() {
     }
 
     // 接收到改变
-    socket.on('dataChange', function(data) {
+    socket.on('dataChange', function (data) {
         data = JSON.parse(data);
         if (data.newValue === undefined) {
             return false;
@@ -380,8 +380,8 @@ function filterProjectGLJ(jsonData) {
     if (jsonData.length > 0) {
         // 不显示消耗量为0的数据
         let tmpData = [];
-        for(let data of jsonData) {
-            if (data.quantity !== 0&&data.quantity !=='0') {
+        for (let data of jsonData) {
+            if (data.quantity !== 0 && data.quantity !== '0') {
                 tmpData.push(data);
             }
         }
@@ -391,10 +391,10 @@ function filterProjectGLJ(jsonData) {
 }
 
 function sortProjectGLJ(jsonData) {
-    if (jsonData.length > 0){
-        jsonData = _.sortByAll(jsonData,[function (item) {
-            return item.unit_price.type+"";
-        },'code']);
+    if (jsonData.length > 0) {
+        jsonData = _.sortByAll(jsonData, [function (item) {
+            return item.unit_price.type + "";
+        }, 'code']);
     }
     return jsonData
 }

Різницю між файлами не показано, бо вона завелика
+ 358 - 338
web/building_saas/main/js/models/ration_glj.js


Різницю між файлами не показано, бо вона завелика
+ 786 - 650
web/building_saas/main/js/views/glj_view.js


+ 56 - 40
web/building_saas/main/js/views/main_tree_col.js

@@ -7,21 +7,27 @@ let MainTreeCol = {
         subType: function (node) {
             if (node.sourceType === projectObj.project.Bills.getSourceType()) {
                 return '';
-            // CSL, 2017-11-29
+                // CSL, 2017-11-29
             } else if (node.sourceType === projectObj.project.Ration.getSourceType()) {
                 if (node.data.type == 1 || node.data.type == undefined)    // 兼容旧定额
                     return '定'
-                else if (node.data.type == 2){    // 量价
+                else if (node.data.type == 2) {    // 量价
                     return volumePriceMaps[node.data.subType];
                 }
-                else if (node.data.type == 3){    // 工料机定额
-                    return  projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
+                else if (node.data.type == 3) {    // 工料机定额
+                    return projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
                 }
             } else if (node.sourceType === projectObj.project.ration_glj.getSourceType()) {
                 return projectObj.project.projectGLJ.getShortNameByID(node.data.subType);//工料机名字缩写
             }
         },
-
+        quantity:function (node) {
+          if(node.sourceType === projectObj.project.ration_glj.getSourceType()){
+              return gljOprObj.getTotalQuantity(node.data);
+          }else {
+              return node.data["quantity"];
+          }
+        },
         // CSL, 2017-11-28
         calcProgramName: function (node) {
             let programID = node.data.programID;
@@ -31,8 +37,8 @@ let MainTreeCol = {
     },
     readOnly: {
         // CSL, 2017-11-28
-        subType: function (node){
-            return (node.data.type != 2 && node.data.type != 3&&!MainTreeCol.readOnly.glj(node))||(node.data.type==rationType.gljRation&&MainTreeCol.readOnly.non_editSubType(node));
+        subType: function (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,31 +47,33 @@ let MainTreeCol = {
             ) return false
             else return true;
         },
-        non_editSubType:function (node) {
-           return node.data.subType!=201&&node.data.subType!=4&&node.data.subType!=5
+        non_editSubType: function (node) {
+            return node.data.subType != 201 && node.data.subType != 4 && node.data.subType != 5
         },
-        commonUnitFee: function(node){
+        commonUnitFee: function (node) {
             return !projectObj.project.calcProgram.isNullBill(node);
         },
         //根据节点、父节点类型判断是否可用计算基数
         calcBaseType: function (node) {
-            function isDef (v) {
+            function isDef(v) {
                 return v !== undefined && v !== null;
             }
-            function isFlag (v) {
+
+            function isFlag(v) {
                 return this.isDef(v.flagsIndex) && this.isDef(v.flagsIndex.fixed);
             }
+
             let calcBase = projectObj.project.calcBase;
             let parent = node.parent;
-            if(isFlag(node.data) && (node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.SUB_ENGINERRING
-                || node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.CONSTRUCTION_TECH)){
+            if (isFlag(node.data) && (node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.SUB_ENGINERRING
+                || node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.CONSTRUCTION_TECH)) {
                 return true;
             }
-            else if(isFlag(node.data) && node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.CONSTRUCTION_ORGANIZATION){
+            else if (isFlag(node.data) && node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.CONSTRUCTION_ORGANIZATION) {
                 return false;
             }
             else {
-                if(!parent){
+                if (!parent) {
                     return false;
                 }
                 else {
@@ -102,7 +110,7 @@ let MainTreeCol = {
         },
         forCalcBase: function (node) {
             // to do according to billsParentType
-            return MainTreeCol.readOnly.billsParent(node) || MainTreeCol.readOnly.non_bills(node)||MainTreeCol.readOnly.leafBillsWithDetail(node) ||MainTreeCol.readOnly.calcBaseType(node);
+            return MainTreeCol.readOnly.billsParent(node) || MainTreeCol.readOnly.non_bills(node) || MainTreeCol.readOnly.leafBillsWithDetail(node) || MainTreeCol.readOnly.calcBaseType(node);
         },
         forUnitFee: function (node) {
             return MainTreeCol.readOnly.ration(node) || MainTreeCol.readOnly.billsParent(node) || MainTreeCol.readOnly.leafBillsWithDetail(node);
@@ -110,17 +118,17 @@ let MainTreeCol = {
         forTotalFee: function (node) {
             return MainTreeCol.readOnly.non_bills(node) || MainTreeCol.readOnly.billsParent(node) || (MainTreeCol.readOnly.leafBillsWithDetail(node));
         },
-        forQuantifyDetail:function (node) {
-            return !(node.sourceType==ModuleNames.ration||!MainTreeCol.readOnly.billsParent(node));
+        forQuantifyDetail: function (node) {
+            return !(node.sourceType == ModuleNames.ration || !MainTreeCol.readOnly.billsParent(node));
         },
-        forFeeRate:function (node) {
-            return MainTreeCol.readOnly.non_bills(node)||MainTreeCol.readOnly.billsParent(node)||MainTreeCol.readOnly.leafBillsWithDetail(node)
+        forFeeRate: function (node) {
+            return MainTreeCol.readOnly.non_bills(node) || MainTreeCol.readOnly.billsParent(node) || MainTreeCol.readOnly.leafBillsWithDetail(node)
         },
-        forQuantity:function (node) {
-            return MainTreeCol.readOnly.glj(node)||MainTreeCol.readOnly.billsParent(node)
+        forQuantity: function (node) {
+            return MainTreeCol.readOnly.glj(node) || MainTreeCol.readOnly.billsParent(node)
         },
-        forMarketPrice:function (node) {
-            return MainTreeCol.readOnly.bills(node)||(MainTreeCol.readOnly.ration(node)&&node.data.type == rationType.ration)||gljOprObj.marketPriceReadOnly(node);
+        forMarketPrice: function (node) {
+            return MainTreeCol.readOnly.bills(node) || (MainTreeCol.readOnly.ration(node) && node.data.type == rationType.ration) || gljOprObj.marketPriceReadOnly(node);
         }
     },
     cellType: {
@@ -159,21 +167,23 @@ 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 = sheetCommonObj.getDynamicCombo();
+            if (node.data.type == rationType.volumePrice || node.data.type == rationType.gljRation || node.sourceType === projectObj.project.ration_glj.getSourceType()) {
+                let VPType = sheetCommonObj.getDynamicCombo();;
+                ;
 
                 if (node.data.type == rationType.volumePrice)
-                    VPType.itemHeight(5).items(["人工","材料","机械","主材","设备"])
-                else if (node.data.type == rationType.gljRation||node.sourceType === projectObj.project.ration_glj.getSourceType())
-                    if(!MainTreeCol.readOnly.non_editSubType(node)){
-                        VPType.itemHeight(3).items(["材料","主材","设备"]);
-                    }else {
+                    VPType.itemHeight(5).items(["人工", "材料", "机械", "主材", "设备"])
+                else if (node.data.type == rationType.gljRation || node.sourceType === projectObj.project.ration_glj.getSourceType())
+                    if (!MainTreeCol.readOnly.non_editSubType(node)) {
+                        VPType.itemHeight(3).items(["材料", "主材", "设备"]);
+                    } else {
                         return null;
                     }
                 return VPType;
-            };
+            }
+            ;
         },
-     },
+    },
     getEvent: function (eventName) {
         let names = eventName.split('.');
         let event = this;
@@ -207,9 +217,10 @@ let MainTreeCol = {
                     return '0.000000';
                 default:
                     return '0.00';
-            };
+            }
+            ;
         }
-        else{
+        else {
             switch (digit) {
                 case 1:
                     return '0.#';
@@ -225,7 +236,8 @@ let MainTreeCol = {
                     return '0.######';
                 default:
                     return '0.##';
-            };
+            }
+            ;
         }
     }
 };
@@ -252,11 +264,12 @@ let colSettingObj = {
                     sheet.addSpan(index, iCol, col.head.spanRows[i], col.head.spanCols[i], GC.Spread.Sheets.SheetArea.rowHeader);
                 }
                 iCol += col.head.spanRows[i];
-            };
+            }
+            ;
             let colWidth = sheet.getColumnWidth(index, GC.Spread.Sheets.SheetArea.rowHeader);
             colWidth = colWidth > col.width ? colWidth : col.width;
             sheet.setColumnWidth(index, colWidth, GC.Spread.Sheets.SheetArea.rowHeader);
-            cell = sheet.getCell(index, 0).value(col.visible);            
+            cell = sheet.getCell(index, 0).value(col.visible);
             sheet.autoFitRow(index);
         });
     },
@@ -280,5 +293,8 @@ $('#column').on('hide.bs.modal', function () {
         projectObj.project.projSetting.mainGridSetting.cols[iRow].visible = sheet.getValue(iRow, 0);
     }
     SheetDataHelper.refreshColumnVisible(projectObj.project.projSetting.mainGridSetting, projectObj.mainSpread.getActiveSheet());
-    projectObj.project.pushNow('editColSetting', projectObj.project.projSetting.moduleName, {projectID: projectObj.project.ID(), main_tree_col: projectObj.project.projSetting.main_tree_col});
+    projectObj.project.pushNow('editColSetting', projectObj.project.projSetting.moduleName, {
+        projectID: projectObj.project.ID(),
+        main_tree_col: projectObj.project.projSetting.main_tree_col
+    });
 });

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

@@ -465,6 +465,7 @@ var projectObj = {
                 that.mainSpread.bind(GC.Spread.Sheets.Events.EnterCell, that.mainSpreadEnterCell);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.EditEnded, that.mainSpreadEditEnded);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.RangeChanged, that.mainSpreadRangeChanged);
+                that.mainSpread.bind(GC.Spread.Sheets.Events.SelectionChanged, that.amountAreaNumber);
                 that.loadMainSpreadContextMenu();
                 that.loadFocusLocation();
             }
@@ -611,7 +612,95 @@ var projectObj = {
             this.mainController.setTreeSelected(this.mainController.tree.items[row]);//触发树节点选中事件
         }
     },
+    // 选中区域合计数字
+    amountAreaNumber: function(e, info) {
+        if (info.newSelections === undefined || info.newSelections.length <= 0) {
+            return false;
+        }
+        const selectedArea = info.newSelections[0];
+        const sheet = info.sheet;
+        if (selectedArea.colCount <= 1 && selectedArea.rowCount <= 1) {
+            return false;
+        }
+        // 获取鼠标位置
+        let x = window.event.clientX;
+        let y = window.event.clientY;
+
+        // 匹配数字或小数
+        const regular = /^([0-9]+[.]{1}[0-9]+)$|^([1-9]{1}\d+)$/;
+        // 小数点最高位数
+        let max = 0;
+        let total = 0;
+        for (let col = selectedArea.col; col < (selectedArea.colCount + selectedArea.col); col++) {
+            for (let row = selectedArea.row; row < (selectedArea.rowCount + selectedArea.row); row++) {
+                const value = sheet.getCell(row, col).value();
+                if (!regular.test(value)) {
+                    continue;
+                }
+                // 获取当前数据小数位数
+                let pointPosition = value.toString().indexOf(".");
+                pointPosition = pointPosition < 0 ? pointPosition : pointPosition + 1;
+                const current = pointPosition > 0 ? value.toString().substring(pointPosition, value.toString().length).length : 0;
+                max = current > max ? current : max;
+                total += parseFloat(value);
+            }
+        }
+        // 如果不为0则悬浮显示
+        if (total > 0) {
+            const div = $('<div id="total-tips"><p>合计: <input type="text" id="total" readonly="readonly" style="border: none;"/></p><p><a href="javascript:void(0);">复制</a></p></div>');
+            div.css({
+                position: "absolute",
+                border: "1px #C0C0C0 solid",
+                background: "#fff",
+                boxShadow: "1px 2px 5px rgba(0,0,0,0.4)",
+            });
+            div.children("p").css({
+                textAlign: "center",
+                padding: 8,
+                marginBottom: 2,
+            });
+            div.children("p").first().css({
+                borderBottom: "1px #C0C0C0 solid"
+            });
+            const totalString = total.toFixed(max);
+            // input长度
+            const inputWidth = totalString.length * 8;
+            // 计算是否会超出显示范围
+            const baseWidth = 48;
+            const baseHeight = 81;
+            const canvasWidth = $("#billsSpreadvp_vp").width();
+            const canvasHeight = $("#billsSpreadvp_vp").height();
+            x = x + baseWidth + inputWidth > canvasWidth ? x - baseWidth - inputWidth : x;
+            y = y + baseHeight > canvasHeight ? y - baseHeight : y;
+            div.css({
+                left: x,
+                top: y,
+            });
+
+            div.children().children("#total").width(inputWidth).val(totalString);
+            $("body").append(div);
+            // 用于判断是否要关闭窗体
+            setTimeout(function() {
+                isTotalShowing = true;
+            }, 200);
+        };
+    }
 };
+// 点击合计框中的复制
+$("body").on("click", "#total-tips a", function() {
+    const totalElement = $(this).parent().siblings("p").find("#total");
+    totalElement.select();
+    document.execCommand("Copy");
+    $(this).text("已复制");
+});
+// 合计框点击其他位置关闭
+let isTotalShowing = false;
+$("body").on("click",  function(e) {
+    if (isTotalShowing && !$(e.target).is("#total-tips") && !$(e.target).is("#total-tips p") && !$(e.target).is("#total-tips p a")) {
+        $("#total-tips").remove();
+        isTotalShowing = false;
+    }
+});
 
 $('#insert').click(function () {
     var controller = projectObj.mainController, project = projectObj.project;