瀏覽代碼

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

zhongzewei 6 年之前
父節點
當前提交
22270d39bb

+ 12 - 1
modules/all_models/rpt_template.js

@@ -27,6 +27,17 @@ let RptTemplateSchema = new Schema({
     "计算式_集合": Array
 });
 
-let Template = mongoose.model("rpt_templates", RptTemplateSchema, "rpt_templates");
+let RptTplExtCodeSchema = new Schema({
+    "Name": String,
+    "Type": String,
+    "Description": String,
+    "Template": String,
+    "items": Array
+});
+
+mongoose.model("rpt_templates", RptTemplateSchema, "rpt_templates");
+mongoose.model("rpt_ext_code_tpl", RptTplExtCodeSchema, "rpt_ext_code_tpl");
+
+//rpt_ext_code_tpl
 
 // export {Template as default};

+ 12 - 2
modules/reports/controllers/rpt_tpl_controller.js

@@ -9,6 +9,7 @@ import counter from "../../../public/counter/counter";
 
 let RptTplModel = mongoose.model('rpt_templates');
 let TreeNodeModel = mongoose.model('rpt_tpl_tree');
+let rptExtCodeModel = mongoose.model('rpt_ext_code_tpl');
 
 let rptCustCfgFacade = require("../facade/rpt_cust_cfg_facade");
 
@@ -22,7 +23,7 @@ let callback = function(req, res, err, message, data){
 };
 
 let mExport = {
-    getCustomerCfg(req, res) {
+    getCustomerCfg: function(req, res) {
         let params = JSON.parse(req.body.params),
             userId = params.userId,
             me = this;
@@ -82,7 +83,7 @@ let mExport = {
             }
         })
     },
-    getDftTemplates(req, res) {
+    getDftTemplates: function(req, res) {
         let filter = {"userId": "-100", "$or": [{"isDeleted": null}, {"isDeleted": false} ]};
         TreeNodeModel.find(filter, '-_id', function(err, data){
             if (err) {
@@ -92,6 +93,15 @@ let mExport = {
             }
         });
     },
+    getExtCodeTpl: function(req, res) {
+        rptExtCodeModel.find({}).exec().then(function(rstCodeTpl) {
+            if (rstCodeTpl) {
+                callback(req,res, false, "", rstCodeTpl);
+            } else {
+                callback(req, res, 'The report template was not found!', null);
+            }
+        })
+    },
     getCompilationList(req, res) {
         let compilationModel = new CompilationModel();
         let compilationList = compilationModel.getCompilationList();

+ 7 - 1
modules/reports/facade/rpt_template_facade.js

@@ -3,12 +3,18 @@
  */
 import mongoose from "mongoose";
 let rpt_tpl_mdl = mongoose.model("rpt_templates");
+let rpt_tpl_ext_code_mdl = mongoose.model("rpt_ext_code_tpl");
 
 module.exports = {
-    getRptTemplate: getRptTemplate
+    getRptTemplate: getRptTemplate,
+    getExtCodeTpl: getExtCodeTpl
 };
 
 async function getRptTemplate(tplId) {
     //console.log('templateId: ' + parseInt(tplId));
     return await  rpt_tpl_mdl.findOne({"ID": parseInt(tplId)}, '-_id');
 }
+
+async function getExtCodeTpl() {
+    return await  rpt_tpl_ext_code_mdl.find({});
+}

+ 1 - 0
modules/reports/routes/rpt_tpl_router.js

@@ -36,6 +36,7 @@ module.exports = function (app) {
     rptTplRouter.post('/getCompilationList', reportTplController.getCompilationList);
     rptTplRouter.post('/getCustomizeCfg', reportTplController.getCustomerCfg);
     rptTplRouter.post('/saveCustomerCfg', reportTplController.saveCustomerCfg);
+    rptTplRouter.post('/getExtCodeTpl', reportTplController.getExtCodeTpl);
 
     rptTplRouter.post('/getUserRptCfg', reportCfgController.getReportUserCfg);
     rptTplRouter.post('/getMappingFields', reportCfgController.getAllMappingFields);

+ 3 - 0
modules/reports/rpt_component/helper/jpc_helper_field.js

@@ -29,6 +29,7 @@ let JpcFieldHelper = {
         return rst;
     },
     resetFormat: function (tab_field, map_field, customizeCfg) {
+        let rst = false;
         if (map_field && map_field[JV.PROP_PRECISION] && map_field[JV.PROP_PRECISION].type === "fixed") {
             let formatStrs = ["#."], ffStr = (customizeCfg && customizeCfg.fillZero)?"0":"#";
             for (let idx = 0; idx < parseInt(map_field[JV.PROP_FIXED_PRECISION_AMT]); idx++) {
@@ -40,7 +41,9 @@ let JpcFieldHelper = {
                 tab_field[JV.PROP_FORMAT] = formatStrs.join("");
             }
             map_field[JV.PROP_FORMAT] = tab_field[JV.PROP_FORMAT]; //这里顺手把format也赋给map_field,后期统计用得着
+            rst = true;
         }
+        return rst;
     },
     resetFlexibleFormat: function (tab_field, ref_field_data, flexiblePrecisionRefObj, valueIdx, customizeCfg) {
         let precisionAmt = 2;

+ 13 - 9
modules/reports/rpt_component/jpc_flow_tab.js

@@ -749,9 +749,9 @@ JpcFlowTabSrv.prototype.createNew = function(){
             // 2.2 Column tab
             tabRstLst.push(me.outputColumn(rptTpl, dataObj, page, segIdx, bands, unitFactor, 0));
             // 2.3 Sum Seg
-            tabRstLst.push(me.outputSegSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT));
+            tabRstLst.push(me.outputSegSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT, customizeCfg));
             // 2.4 Sum Page
-            tabRstLst.push(me.outputPageSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT));
+            tabRstLst.push(me.outputPageSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT, customizeCfg));
             // 2.5 Group
             // 2.6 Discrete
             tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[FLOW_NODE_STR][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[page - 1], segIdx, 1, 0, $CURRENT_RPT, customizeCfg));
@@ -783,9 +783,9 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 // 2.2 Column tab
                 tabRstLst.push(me.outputColumn(rptTpl, dataObj, actualPage, segIdx, bands, unitFactor, pi));
                 // 2.3 Sum Seg
-                tabRstLst.push(me.outputSegSum(rptTpl, dataObj, actualPage, segIdx, bands, unitFactor, controls, $CURRENT_RPT));
+                tabRstLst.push(me.outputSegSum(rptTpl, dataObj, actualPage, segIdx, bands, unitFactor, controls, $CURRENT_RPT, customizeCfg));
                 // 2.4 Sum Page
-                tabRstLst.push(me.outputPageSum(rptTpl, dataObj, actualPage, segIdx, bands, unitFactor, controls, $CURRENT_RPT));
+                tabRstLst.push(me.outputPageSum(rptTpl, dataObj, actualPage, segIdx, bands, unitFactor, controls, $CURRENT_RPT, customizeCfg));
                 // 2.5 Group
                 // 2.6 Discrete
                 if (pi === 0) {
@@ -1023,7 +1023,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         }
         return rst;
     };
-    JpcFlowTabResult.outputSegSum = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT) {
+    JpcFlowTabResult.outputSegSum = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT, customizeCfg) {
         let me = this, rst = [];
         let FLOW_NODE_STR = me.isEx?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
         let tab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_SEG_SUM];
@@ -1040,7 +1040,8 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     if (!JpcFieldHelper.resetSumFormat(ref_tab_fields, tab_fields[i])) {
                         if (!JpcFieldHelper.resetSumFormat(ref_tab_fields_ex, tab_fields[i])) {
                             let map_data_field = JE.F(tab_fields[i][JV.PROP_FIELD_ID], $CURRENT_RPT);
-                            tab_fields[i][JV.PROP_FORMAT] = map_data_field[JV.PROP_FORMAT];
+                            JpcFieldHelper.resetFormat(tab_fields[i], map_data_field, customizeCfg)
+                            //如果都找不到,就得靠自己的Format属性了
                         }
                     }
                     let sumVal = 0;
@@ -1057,7 +1058,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         }
         return rst;
     };
-    JpcFlowTabResult.outputPageSum = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT) {
+    JpcFlowTabResult.outputPageSum = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT, customizeCfg) {
         let me = this, rst = [];
         let FLOW_NODE_STR = me.isEx?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
         let tab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_PAGE_SUM];
@@ -1072,8 +1073,11 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 let tab_fields = me.page_sum_tab_fields;
                 for (let i = 0; i < tab_fields.length; i++) {
                     if (!JpcFieldHelper.resetSumFormat(ref_tab_fields, tab_fields[i])) {
-                        JpcFieldHelper.resetSumFormat(ref_tab_fields_ex, tab_fields[i]);
-                        //如果都找不到,说明是离散的指标,那么就得靠tab_fields[i]本身的Format来处理格式了
+                        if (!JpcFieldHelper.resetSumFormat(ref_tab_fields_ex, tab_fields[i])) {
+                            let map_data_field = JE.F(tab_fields[i][JV.PROP_FIELD_ID], $CURRENT_RPT);
+                            JpcFieldHelper.resetFormat(tab_fields[i], map_data_field, customizeCfg)
+                            //如果都找不到,就得靠自己的Format属性了
+                        }
                     }
                     let cellItem = JpcCommonOutputHelper.createCommonOutput(tab_fields[i], me.pageSumValLst[page - 1][i], controls);
                     cellItem[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_fields[i][JV.PROP_AREA], band, unitFactor, 1, 0, 1, 0, me.multiCols, 0, true, false);

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

@@ -289,7 +289,7 @@ class Rpt_Data_Extractor {
                         break;
                     case JV.PROP_HANDLE_TYPE_SUM:
                         // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/insertedRawDataData10.jsp");
-                        summaryData(srcData, preHandle, rawDataObj.prjData);
+                        summaryData(srcData, preHandle, rawDataObj.prjData, rawDataObj.prj);
                         // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/insertedRawDataData11.jsp");
                         break;
                     case JV.PROP_HANDLE_TYPE_ADD_DUMMY:
@@ -371,9 +371,24 @@ function getModuleDataByKey(prjData, key) {
     return rst;
 }
 
-function summaryData(sourceData, handleCfg, prjData){
+function summaryData(sourceData, handleCfg, prjData, prjMain){
     let rstArr = [], tempRstArr = [];
     let curParentPrjData = {};
+    let precision = 6;
+    if (handleCfg[JV.PROP_HANDLE_TYPE_PRECISION]) {
+        if (isNaN(parseInt(handleCfg[JV.PROP_HANDLE_TYPE_PRECISION]))) {
+            let properties = handleCfg[JV.PROP_HANDLE_TYPE_PRECISION].split('.');
+            let currentProperty = prjMain[properties[0]];
+            for (let idx = 1; idx < properties.length; idx++) {
+                currentProperty = currentProperty[properties[idx]];
+            }
+            if (!isNaN(parseInt(currentProperty))) {
+                precision = parseInt(currentProperty);
+            }
+        } else {
+            precision = parseInt(handleCfg[JV.PROP_HANDLE_TYPE_PRECISION]);
+        }
+    }
     for (let item of getActDataArr(sourceData)) {
         if (item._doc) {
             tempRstArr.push(item._doc);
@@ -399,10 +414,10 @@ function summaryData(sourceData, handleCfg, prjData){
                                     dtlItem[sumKey] = parseFloat(dtlItem[sumKey]) - parseFloat(data[calcAheadObj["calc_property"]]);
                                     break;
                                 case "*":
-                                    dtlItem[sumKey] = dtlItem[sumKey] * parseFloat(data[calcAheadObj["calc_property"]]).toFixed(4);
+                                    dtlItem[sumKey] = dtlItem[sumKey] * parseFloat(data[calcAheadObj["calc_property"]]);
                                     break;
                                 case "/":
-                                    dtlItem[sumKey] = dtlItem[sumKey] / parseFloat(data[calcAheadObj["calc_property"]]).toFixed(4);
+                                    dtlItem[sumKey] = dtlItem[sumKey] / parseFloat(data[calcAheadObj["calc_property"]]);
                                     break;
                                 default:
                                     break;
@@ -445,7 +460,7 @@ function summaryData(sourceData, handleCfg, prjData){
             for (let sumKey of handleCfg[JV.PROP_SUM_SUM_KEYS]) {
                 if (dtl[sumKey]) {
                     // sumObj[grpKey][sumKey] += dtl[sumKey];
-                    sumObj[grpKey][sumKey] = parseFloat(sumObj[grpKey][sumKey]) + parseFloat(dtl[sumKey]);
+                    sumObj[grpKey][sumKey] = parseFloat(parseFloat(sumObj[grpKey][sumKey]).toFixed(precision)) + parseFloat(parseFloat(dtl[sumKey]).toFixed(precision));
                 }
             }
         }

+ 94 - 24
modules/reports/util/rpt_pdf_util.js

@@ -152,33 +152,21 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
         }
         doc.font(fontFile);
         let options={};
-        if (control) {
-            private_setupAreaH(area, control.Horizon, font.FontAngle, dftFontHeight, output,options);
-            private_setupAreaV(area, control.Vertical, font.FontAngle, dftFontHeight, output);
-        } else {
-            private_setupAreaH(area, "left", font.FontAngle, dftFontHeight, output,options);
-            private_setupAreaV(area, "bottom", font.FontAngle, dftFontHeight, output);
-        }
+        let inner_setupControl = function (inArea, inFontHeight, inOutput) {
+            if (control) {
+                private_setupAreaH(inArea, control.Horizon, font.FontAngle, inFontHeight, inOutput, options);
+                private_setupAreaV(inArea, control.Vertical, font.FontAngle, inFontHeight, inOutput);
+            } else {
+                private_setupAreaH(inArea, "left", parseInt(font.FontAngle), inFontHeight, inOutput, options);
+                private_setupAreaV(inArea, "bottom", parseInt(font.FontAngle), inFontHeight, inOutput);
+            }
+        };
+        inner_setupControl(area, dftFontHeight, output);
         let w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
         if (parseInt(font.FontAngle) !== 0) {
             w = area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] - area[JV.IDX_TOP] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
         }
-        // doc.save();
-        //doc.translate(output[0], output[1]);
-        if (w >= doc.widthOfString(val)) {
-            options.width = w;
-            options.height = dftFontHeight;
-        } else {
-            while (true) {
-                dftFontHeight--;
-                doc.fontSize(dftFontHeight);
-                if (w >= doc.widthOfString(val) || dftFontHeight < 6) {
-                    options.width = w;
-                    options.height = dftFontHeight;
-                    break;
-                }
-            }
-        }
+
         function private_drawUnderline() {
             //A. 暂不支持角度; B. PDF输出时,坐标没有translate
             let ctx = doc;
@@ -230,7 +218,61 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
             }
             doc.rotate(font.FontAngle,rotateOptions);
         }
-        doc.text(val,output[0], output[1], options);
+        if (w >= doc.widthOfString(val) || (control && control.Shrink !== 'T')) {
+            options.width = w;
+            options.height = dftFontHeight;
+            doc.text(val,output[0], output[1], options);
+            doc.font(__dirname + '/pdf_base_files/simhei_bold_italic.ttf');
+        } else {
+            while (true) {
+                //*/
+                let lines = Math.floor((area[JV.IDX_BOTTOM] - area[JV.IDX_TOP]) / (dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP] + 4));
+                lines = (lines === 0)?1:lines;
+                let actLines = private_splitString(val, w, doc);
+                if (actLines.length > lines && dftFontHeight >= 6) {
+                    dftFontHeight--;
+                    doc.fontSize(dftFontHeight);
+                    options.width = w;
+                    options.height = dftFontHeight;
+                    doc.text(val,output[0], output[1], options);
+                } else {
+                    let aH = dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP] + 4;
+                    if ((aH * actLines.length) < (area[JV.IDX_BOTTOM] - area[JV.IDX_TOP]) && (control && control.Vertical !== 'top')) {
+                        if (control.Vertical === 'bottom') {
+                            area[JV.IDX_TOP] = area[JV.IDX_BOTTOM] - (aH * actLines.length);
+                        } else {
+                            area[JV.IDX_TOP] = (area[JV.IDX_TOP] + area[JV.IDX_BOTTOM]) / 2 - (aH * actLines.length) / 2
+                            area[JV.IDX_BOTTOM] = area[JV.IDX_TOP] + (aH * actLines.length);
+                        }
+                    }
+                    let newArea = [], baseTop = area[JV.IDX_TOP];
+                    for (let ai = 0; ai < area.length; ai++) {
+                        newArea[ai] = area[ai];
+                    }
+                    options.width = w;
+                    options.height = dftFontHeight;
+                    for (let lIdx = 0; lIdx < actLines.length; lIdx++) {
+                        newArea[JV.IDX_TOP] = Math.round(aH * lIdx + baseTop);
+                        newArea[JV.IDX_BOTTOM] = Math.round(aH * (lIdx + 1) + baseTop);
+                        inner_setupControl(newArea, dftFontHeight, output);
+                        doc.text(actLines[lIdx], output[0], output[1], options);
+                    }
+                    break;
+                }
+                /*/
+                dftFontHeight--;
+                doc.fontSize(dftFontHeight);
+                if (w >= doc.widthOfString(val) || dftFontHeight < 6) {
+                    options.width = w;
+                    options.height = dftFontHeight;
+                    doc.text(val,output[0], output[1], options);
+                    doc.font(__dirname + '/pdf_base_files/simhei_bold_italic.ttf');
+                    break;
+                }
+                //*/
+            }
+        }
+        // doc.text(val,output[0], output[1], options);
         doc.font(__dirname + '/pdf_base_files/simhei_bold_italic.ttf');
         // doc.restore();
     }
@@ -258,6 +300,34 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
         }
     }
 
+    function private_splitString(strVal, areaWidth, doc) {
+        let rst = [];
+        if (strVal) {
+            let preSIdx = 0, txtWidth = 0;
+            let currentW = 0;
+            let chnW = doc.widthOfString('一'), otherW = doc.widthOfString('_');
+            for (let sIdx = 0; sIdx < strVal.length; sIdx++) {
+                currentW = (strVal.charCodeAt(sIdx) > 127)?chnW:otherW;
+                txtWidth += currentW;
+                if (txtWidth > areaWidth) {
+                    if (preSIdx < sIdx) {
+                        rst.push(strVal.substr(preSIdx, sIdx - preSIdx));
+                        preSIdx = sIdx;
+                    } else {
+                        rst.push(strVal.substr(preSIdx, 1));
+                        preSIdx = sIdx + 1;
+                    }
+                    txtWidth = currentW;
+                }
+                if (sIdx === strVal.length - 1) {
+                    rst.push(strVal.substr(preSIdx, strVal.length - preSIdx));
+                }
+            }
+        }
+        if (rst.length === 0) rst.push(''); //什么都没有,也得整个空串
+        return rst;
+    }
+
     function private_setupAreaRotateOption(area,w, type="top",dftFontHeight,outputPoint){
         let x = (area[JV.IDX_RIGHT] - area[JV.IDX_LEFT])/2+area[JV.IDX_LEFT];
         let y =(area[JV.IDX_BOTTOM] - area[JV.IDX_TOP])/2+ area[JV.IDX_TOP];

+ 1 - 0
public/web/rpt_value_define.js

@@ -68,6 +68,7 @@ const JV = {
     PROP_HANDLE_TYPE_ADJUST: "数据调整",
     PROP_HANDLE_TYPE_BILLS_DATA_MOVE: "量材数据转移",
     PROP_HANDLE_TYPE_COMPONENT_REPLACEMENT: "组成物替换",
+    PROP_HANDLE_TYPE_PRECISION: "合计精度",
 
     PROP_ADJUST_COLLECTION: "数据调整集",
     PROP_ADJUST_ACTION: "action",

+ 10 - 39
web/maintain/report/html/rpt_tpl_dtl_calc.html

@@ -1,44 +1,11 @@
 <div class="tab-pane" id="rpttplformula" role="tabpanel">
     <!--
-    <div class="main-data">
-        <div class="p-3">
-            <label>计算式</label>
-            <div class="tab-content">
-                <ul id="rpt_tpl_formulas" class="ztree"></ul>
-            </div>
-        </div>
-        <div class="p-3" id="exprDetail">
-            <div class="row">
-                <div class="form-group col-md-5">
-                    <select class="form-control" id="exprTemplatesSelect"></select>
-                </div>
-                <div class="form-group col-md-1">
-                    <button class="btn btn-primary" id="expr_tpl_select_btn" onclick="calculationTreeOprObj.setTemplateExpression(this)">套用</button>
-                </div>
-            </div>
-            <div class="row">
-                <div class="form-group col-md-3">
-                    <label>计算式执行点</label>
-                    <select class="form-control" id="exprRunType" onchange="calculationTreeOprObj.changeRunType(this)"></select>
-                </div>
-                <div class="form-group col-md-4">
-                    <label>格式串(format)</label>
-                    <input class="form-control" id="exprFormat" value="" onkeyup="calculationTreeOprObj.changeFormat(this)">
-                </div>
-            </div>
-            <div class="form-group">
-                <textarea rows="20" cols="50" style="width: 100%; height: 100%; overflow: auto; work-break: break-all;" id="exprContent" onkeyup="calculationTreeOprObj.changeExpression(this)"></textarea>
-            </div>
-        </div>
-    </div>
-    -->
-    <!--
     -->
     <div class="main">
         <div class="content">
             <div class="container-fluid">
                 <div class="row">
-                    <div class="main-side col-lg-6 p-3">
+                    <div class="main-side col-lg-5 p-3">
                         <div class="row">
                             <div class="form-group col-md-12">
                                 <label>计算式</label>
@@ -48,15 +15,19 @@
                             </div>
                         </div>
                         <div class="row">
-                            <div class="form-group col-md-5">
-                                <select class="form-control" id="exprTemplatesSelect"></select>
+                            <div class="sub-button p-0">
+                                <button class="btn btn-primary" id="ext_code_tpl_select_btn" onclick="calculationTreeOprObj.setExtCodeTemplate(this)">套用</button>
+                                <button class="btn btn-primary" id="ext_code_tpl_add_btn" onclick="calculationTreeOprObj.addExtCodeTemplate(this)">Copy</button>
                             </div>
-                            <div class="form-group col-md-1">
-                                <button class="btn btn-primary" id="expr_tpl_select_btn" onclick="calculationTreeOprObj.setTemplateExpression(this)">套用</button>
+                        </div>
+                        <div style="height: 10px"></div>
+                        <div class="main-content">
+                            <div>
+                                <ul id="rpt_ext_code_tpl" class="ztree"></ul>
                             </div>
                         </div>
                     </div>
-                    <div class="main-content col-lg-6 p-0">
+                    <div class="main-content col-lg-7 p-0">
                         <div class="p-3" id="exprDetail">
                             <div class="row">
                                 <div class="form-group col-md-3">

+ 30 - 0
web/maintain/report/js/cfg_const.js

@@ -228,6 +228,36 @@ let caculationSetting = {
     }
 };
 
+let extCodeSetting = {
+    view: {
+        showIcon: true,
+        expandSpeed: "",
+        selectedMulti: false
+    },
+    edit: {
+        enable: false,
+        showRemoveBtn: false,
+        showRenameBtn: false
+    },
+    data: {
+        keep: {
+            parent:true,
+            leaf:true
+        },
+        key: {
+            children: 'items',
+            name: "Name",
+            title: "Description"
+        },
+        simpleData: {
+            enable: true
+        }
+    },
+    callback:{
+        onClick: calculationTreeOprObj.onExtCodeTreeClick
+    }
+};
+
 let rptDataInfoSetting = {
     view: {
         showIcon: true,

+ 99 - 59
web/maintain/report/js/jpc_output.js

@@ -4,6 +4,7 @@
 let JpcCanvasOutput = {
     offsetX: 10,
     offsetY: 10,
+    scaleFactor: 1,
     cleanCanvas: function (canvas) {
         let ctx = canvas.getContext("2d");
         ctx.save();
@@ -11,9 +12,18 @@ let JpcCanvasOutput = {
         ctx.clearRect(0,0, canvas.width, canvas.height);
         ctx.restore();
     },
+    resetFonts: function(rptFonts) {
+        let me = JpcCanvasOutput;
+        if (me.scaleFactor !== 1) {
+            for (let key in rptFonts) {
+                rptFonts[key]["FontHeight"] = me.scaleFactor * rptFonts[key]["FontHeight"];
+            }
+        }
+    },
     drawToCanvas : function(pageObj, canvas, pageIdx) {
         let me = this;
         let ctx = canvas.getContext("2d");
+        let floatReg = /^(-?\d+)(\.\d+)?$/;
 
         function private_setupAreaH(area, type, fontAngle, dftFontHeight, outputPoint) {
             let lType = type;
@@ -76,6 +86,33 @@ let JpcCanvasOutput = {
                     break;
             }
         }
+        function private_splitString(strVal, areaWidth, ctx) {
+            let rst = [];
+            if (strVal) {
+                let preSIdx = 0, txtWidth = 0;
+                let currentW = 0;
+                let chnW = ctx.measureText('一').width, otherW = ctx.measureText('_').width;
+                for (let sIdx = 0; sIdx < strVal.length; sIdx++) {
+                    currentW = (strVal.charCodeAt(sIdx) > 127)?chnW:otherW;
+                    txtWidth += currentW;
+                    if (txtWidth > areaWidth) {
+                        if (preSIdx < sIdx) {
+                            rst.push(strVal.substr(preSIdx, sIdx - preSIdx));
+                            preSIdx = sIdx;
+                        } else {
+                            rst.push(strVal.substr(preSIdx, 1));
+                            preSIdx = sIdx + 1;
+                        }
+                        txtWidth = currentW;
+                    }
+                    if (sIdx === strVal.length - 1) {
+                        rst.push(strVal.substr(preSIdx, strVal.length - preSIdx));
+                    }
+                }
+            }
+            if (rst.length === 0) rst.push(''); //什么都没有,也得整个空串
+            return rst;
+        }
         function private_drawText(val, area, font, control) {
             let dftFontHeight = 12;
             let output = [];
@@ -92,13 +129,16 @@ let JpcCanvasOutput = {
                 }
                 ctx.font = dftOthers + dftFontHeight + "px " + font[JV.PROP_NAME];
             }
-            if (control) {
-                private_setupAreaH(area, control.Horizon, parseInt(font.FontAngle), dftFontHeight, output);
-                private_setupAreaV(area, control.Vertical, parseInt(font.FontAngle), font.Name, dftFontHeight, output);
-            } else {
-                private_setupAreaH(area, "left", parseInt(font.FontAngle), dftFontHeight, output);
-                private_setupAreaV(area, "bottom", parseInt(font.FontAngle), font.Name, dftFontHeight, output);
-            }
+            let inner_setupControl = function (inArea, inFontHeight, inOutput) {
+                if (control) {
+                    private_setupAreaH(inArea, control.Horizon, parseInt(font.FontAngle), inFontHeight, inOutput);
+                    private_setupAreaV(inArea, control.Vertical, parseInt(font.FontAngle), font.Name, inFontHeight, inOutput);
+                } else {
+                    private_setupAreaH(inArea, "left", parseInt(font.FontAngle), inFontHeight, inOutput);
+                    private_setupAreaV(inArea, "bottom", parseInt(font.FontAngle), font.Name, inFontHeight, inOutput);
+                }
+            };
+            inner_setupControl(area, dftFontHeight, output);
             let w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
             if ( parseInt(font.FontAngle) !== 0) {
                 w = area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] - area[JV.IDX_TOP] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
@@ -154,14 +194,38 @@ let JpcCanvasOutput = {
             } else if (font.FontAngle === JV.ANTI_VERTICAL_ANGLE) {
                 ctx.rotate(-Math.PI/2);
             }
-            if (w >= ctx.measureText(val).width) {
+            if (w >= ctx.measureText(val).width || (control && control.Shrink !== 'T') ) {
                 ctx.fillText(val, 0, 0);
             } else {
                 while (true) {
-                    dftFontHeight--;
-                    ctx.font = "" + dftFontHeight + "px " + font[JV.PROP_NAME];
-                    if (w >=  ctx.measureText(val).width || dftFontHeight < 6) {
-                        ctx.fillText(val, 0, 0);
+                    let lines = Math.floor((area[JV.IDX_BOTTOM] - area[JV.IDX_TOP]) / (dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP] + 4));
+                    lines = (lines === 0)?1:lines;
+                    let actLines = private_splitString(val, w, ctx);
+                    if (actLines.length > lines && dftFontHeight >= 6) {
+                        dftFontHeight--;
+                        ctx.font = "" + dftFontHeight + "px " + font[JV.PROP_NAME];
+                    } else {
+                        let aH = dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP] + 4;
+                        if ((aH * actLines.length) < (area[JV.IDX_BOTTOM] - area[JV.IDX_TOP]) && (control && control.Vertical !== 'top')) {
+                            if (control.Vertical === 'bottom') {
+                                area[JV.IDX_TOP] = area[JV.IDX_BOTTOM] - (aH * actLines.length);
+                            } else {
+                                area[JV.IDX_TOP] = (area[JV.IDX_TOP] + area[JV.IDX_BOTTOM]) / 2 - (aH * actLines.length) / 2
+                                area[JV.IDX_BOTTOM] = area[JV.IDX_TOP] + (aH * actLines.length);
+                            }
+                        }
+                        let newArea = [], baseTop = area[JV.IDX_TOP];
+                        for (let ai = 0; ai < area.length; ai++) {
+                            newArea[ai] = area[ai];
+                        }
+                        for (let lIdx = 0; lIdx < actLines.length; lIdx++) {
+                            newArea[JV.IDX_TOP] = Math.round(aH * lIdx + baseTop);
+                            newArea[JV.IDX_BOTTOM] = Math.round(aH * (lIdx + 1) + baseTop);
+                            ctx.translate(-output[0], -output[1]);
+                            inner_setupControl(newArea, dftFontHeight, output);
+                            ctx.translate(output[0], output[1]);
+                            ctx.fillText(actLines[lIdx], 0, 0);
+                        }
                         break;
                     }
                 }
@@ -169,7 +233,7 @@ let JpcCanvasOutput = {
             ctx.restore();
         }
         function private_drawCellText(cell, fonts, controls) {
-            if (cell[JV.PROP_VALUE]) {
+            if (cell[JV.PROP_VALUE] !== null && cell[JV.PROP_VALUE] !== undefined) {
                 let values = ("" + cell[JV.PROP_VALUE]).split('|');
                 let font = null;
                 if (typeof cell[JV.PROP_FONT] === "string") {
@@ -185,7 +249,11 @@ let JpcCanvasOutput = {
                     control = cell[JV.PROP_CONTROL];
                 }
                 if (control.ShowZero === "F") {
-                    if (parseFloat(cell[JV.PROP_VALUE]) === 0.0) {
+                    if (typeof cell[JV.PROP_VALUE] === "string") {
+                        if (floatReg.test(cell[JV.PROP_VALUE]) && parseFloat(cell[JV.PROP_VALUE]) === 0.0) {
+                            values = [""];
+                        }
+                    } else if (parseFloat(cell[JV.PROP_VALUE]) === 0.0) {
                         values = [""];
                     }
                 }
@@ -247,6 +315,17 @@ let JpcCanvasOutput = {
             }
             return rst;
         }
+        function private_resetArea(area) {
+            area[JV.PROP_LEFT] = me.scaleFactor * area[JV.PROP_LEFT];
+            area[JV.PROP_RIGHT] = me.scaleFactor * area[JV.PROP_RIGHT];
+            area[JV.PROP_TOP] = me.scaleFactor * area[JV.PROP_TOP];
+            area[JV.PROP_BOTTOM] = me.scaleFactor * area[JV.PROP_BOTTOM];
+        }
+        function private_resetCellFont(cell) {
+            if (typeof cell.font !== "string") {
+                cell.font["FontHeight"] = me.scaleFactor * cell.font["FontHeight"];
+            }
+        }
 
         if (pageObj && pageObj.items.length > 0 && canvas && pageObj.items.length >= pageIdx) {
             let page = pageObj.items[pageIdx - 1],
@@ -261,37 +340,14 @@ let JpcCanvasOutput = {
                 newPageMergeBand[JV.PROP_TOP] = page[JV.PROP_PAGE_MERGE_BORDER][JV.PROP_TOP];
                 newPageMergeBand[JV.PROP_BOTTOM] = page[JV.PROP_PAGE_MERGE_BORDER][JV.PROP_BOTTOM];
             }
+            private_resetArea(newPageMergeBand);
             for (let j = 0; j < page.cells.length; j++) {
                 let cell = page.cells[j];
-                // private_drawCell(cell, fonts, styles, controls, mergedBand);
-                private_drawCell(cell, fonts, styles, controls, newPageMergeBand);
-            }
-        }
-    },
-    highlightConflictArea: function (pageObj, pageIdx) {
-        if (pageObj && pageObj.items.length > 0 && pageObj.items.length >= pageIdx) {
-            let private_create_conflict_line = function () {
-                return {"LineWeight": "1", "DashStyle": "SOLID", "Color": "RED"};
-            };
-            let page = pageObj.items[pageIdx - 1],
-                styleConflict = {"Left": private_create_conflict_line(), "Right": private_create_conflict_line(), "Top": private_create_conflict_line(), "Bottom": private_create_conflict_line()}
-            ;
-            pageObj[JV.NODE_STYLE_COLLECTION]["ConflictCell"] = styleConflict;
-            let conflictIds = [];
-            for (let j = 0; j < page.cells.length; j++) {
-                if (conflictIds.indexOf(j) < 0) {
-                    let cell1 = page.cells[j];
-                    for (let k = j + 1; k < page.cells.length; k++) {
-                        let cell2 = page.cells[k];
-                        //判断area是否有交叉
-                        if (areaConflict(cell1[JV.PROP_AREA], cell2[JV.PROP_AREA])) {
-                            conflictIds.push(j);
-                            conflictIds.push(k);
-                            cell1[JV.PROP_STYLE] = "ConflictCell";
-                            cell2[JV.PROP_STYLE] = "ConflictCell";
-                        }
-                    }
+                if (me.scaleFactor !== 1) {
+                    private_resetCellFont(cell);
+                    private_resetArea(cell[JV.PROP_AREA]);
                 }
+                private_drawCell(cell, fonts, styles, controls, newPageMergeBand);
             }
         }
     },
@@ -322,20 +378,4 @@ let JpcCanvasOutput = {
         rst[1] = Math.round(resolution[0] * rst[1]);
         return rst;
     }
-};
-
-function areaConflict(area1,area2) {
-    let maxX,maxY,minX,minY,
-        w1 = area1[JV.PROP_RIGHT] - area1[JV.PROP_LEFT],
-        w2 = area2[JV.PROP_RIGHT] - area2[JV.PROP_LEFT],
-        h1 = area1[JV.PROP_BOTTOM] - area1[JV.PROP_TOP],
-        h2 = area2[JV.PROP_BOTTOM] - area2[JV.PROP_TOP]
-    ;
-    //1. 求2个矩形的最小外包矩形
-    minX = (area1[JV.PROP_LEFT] <= area2[JV.PROP_LEFT]) ? area1[JV.PROP_LEFT] : area2[JV.PROP_LEFT];
-    minY = (area1[JV.PROP_TOP] <= area2[JV.PROP_TOP]) ? area1[JV.PROP_TOP] : area2[JV.PROP_TOP];
-    maxX = (area1[JV.PROP_RIGHT] >= area2[JV.PROP_RIGHT]) ? area1[JV.PROP_RIGHT] : area2[JV.PROP_RIGHT];
-    maxY = (area1[JV.PROP_BOTTOM] >= area2[JV.PROP_BOTTOM]) ? area1[JV.PROP_BOTTOM] : area2[JV.PROP_BOTTOM];
-    //2. 判断外包矩形与高与宽是否小于俩矩形的高与宽之和(这里的边界条件是小于,等于的话不算;而且是高与宽都得符合条件!)
-    return (maxX - minX < w1 + w2 && maxY - minY < h1 + h2);
-}
+};

文件差異過大導致無法顯示
+ 28 - 18
web/maintain/report/js/rpt_tpl_calculation.js


+ 1 - 1
web/maintain/report/js/rpt_tpl_main.js

@@ -22,8 +22,8 @@ let rptTplObj = {
         selectableFiledTreeOprObj.iniTree();
         preview_util.drawBorder($("#tplCanvas")[0]);
         calculationTreeOprObj.buildRunType();
-        calculationTreeOprObj.buildExprTemplates();
         preHandleObj.buildTypeData();
+        calculationTreeOprObj.iniExtCodeTpl();
     }
 };