فهرست منبع

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

zhongzewei 7 سال پیش
والد
کامیت
340a479227

+ 0 - 24
modules/reports/rpt_component/helper/jpc_helper_common.js

@@ -74,30 +74,6 @@ let JpcCommonHelper = {
         }
         return arrDPI;
     },
-    // getBrowerScreenDPI: function() {
-    //     let me = this, arrDPI = [];
-    //     if (!me.commonConstant.resolution) {
-    //         if (window) {
-    //             if (window.screen.deviceXDPI != undefined) {
-    //                 arrDPI.push(window.screen.deviceXDPI);
-    //                 arrDPI.push(window.screen.deviceYDPI);
-    //             } else {
-    //                 let tmpNode = document.createElement("DIV");
-    //                 tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
-    //                 document.body.appendChild(tmpNode);
-    //                 arrDPI.push(parseInt(tmpNode.offsetWidth));
-    //                 arrDPI.push(parseInt(tmpNode.offsetHeight));
-    //                 tmpNode.parentNode.removeChild(tmpNode);
-    //             }
-    //         } else {
-    //             arrDPI = [96,96];
-    //         }
-    //         me.commonConstant.resolution = arrDPI;
-    //     } else {
-    //         arrDPI = me.commonConstant.resolution;
-    //     }
-    //     return arrDPI;
-    // },
     getUnitFactor: function(rptTpl) {
         let me = this;
         return me.translateUnit(rptTpl[JV.NODE_MAIN_INFO][JV.PROP_UNITS]);

+ 94 - 0
modules/reports/util/rpt_svg_util.js

@@ -0,0 +1,94 @@
+/**
+ * Created by Tony on 2018/6/27.
+ * 报表直接打印需要
+ */
+
+let JV = require('../rpt_component/jpc_value_define');
+const SCREEN_DPI = [96,96];
+
+module.exports = {
+    exportSvgStr: function (pagesData, callback) {
+        let styles = pagesData[JV.NODE_STYLE_COLLECTION],
+            fonts = pagesData[JV.NODE_FONT_COLLECTION],
+            controls = pagesData[JV.NODE_CONTROL_COLLECTION]
+        ;
+        for (let page of pagesData.items) {
+            let svgPageArr = [], pixelSize = getPixelSize(pagesData);
+            svgPageArr.push("<svg width='" + pixelSize[0] + "' height='" + pixelSize[1] + "'>");
+            for (let cell of page.cells) {
+                svgPageArr.push(buildCellSvg(cell, fonts, styles, controls, page[JV.PROP_PAGE_MERGE_BORDER]));
+            }
+            svgPageArr.push("</svg>");
+        }
+    }
+}
+
+function buildCellSvg(cell, fonts, styles, controls, mergeBorder) {
+    let rst = [];
+    let style = styles[cell[JV.PROP_STYLE]];
+    if (style) {
+        if (style[JV.PROP_LEFT] && parseFloat(style[JV.PROP_LEFT][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_RIGHT] && parseFloat(style[JV.PROP_RIGHT][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_TOP] && parseFloat(style[JV.PROP_TOP][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_TOP] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_BOTTOM] && parseFloat(style[JV.PROP_BOTTOM][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + cell[JV.PROP_AREA][JV.PROP_LEFT] + "' y1='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' x2='" + cell[JV.PROP_AREA][JV.PROP_RIGHT] + "' y2='" + cell[JV.PROP_AREA][JV.PROP_BOTTOM] +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+    }
+    let font = cell[JV.PROP_FONT];
+    if (typeof font === 'string') {
+        font = fonts[cell[JV.PROP_FONT]];
+    }
+    let fontsize = parseInt(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]]);
+    let left = parseInt(cell[JV.PROP_AREA][JV.PROP_LEFT]),
+        right = parseInt(cell[JV.PROP_AREA][JV.PROP_RIGHT]),
+        top = parseInt(cell[JV.PROP_AREA][JV.PROP_TOP]),
+        bottom = parseInt(cell[JV.PROP_AREA][JV.PROP_BOTTOM]),
+        x = left, y = top,
+        text_anchor = "start"
+    ;
+    let control = controls[cell[JV.PROP_CONTROL]];
+    if (control) {
+        if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "left") {
+            text_anchor = "start";
+            x = left + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "right") {
+            text_anchor = "end";
+            x = right - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "center") {
+            text_anchor = "middle";
+            x = Math.round((left + right) / 2);
+        }
+        if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "top") {
+            y = top + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "bottom") {
+            y = bottom - fontsize - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "center") {
+            y = Math.round((top + bottom + fontsize) / 2 );
+        }
+    }
+    rst.push("<text style='fill:black;font-size:" + fontsize + "pt' x='" + x +"' y='" + y + "'>" + cell[JV.PROP_VALUE] + "</text>");
+    return rst.join();
+}
+
+function getPixelSize(pagesData) {
+    let rst = [793,1122];
+    if (pagesData[JV.NODE_PAGE_INFO] && pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE]) {
+        rst[0] = Math.round(SCREEN_DPI[0] * pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][0]);
+        rst[1] = Math.round(SCREEN_DPI[1] * pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][1]);
+    }
+    return rst;
+}

+ 25 - 9
public/web/common_util.js

@@ -13,25 +13,41 @@ String.prototype.hasSubStr = function (str) {
     return this.toLowerCase().indexOf(str.toLowerCase()) > -1;
 };
 
+// 判断字符串是否是数字形式的字符串
+String.prototype.isNumberStr = function () {
+    return this == +this;
+};
+
 // 树结点计算时,取费会出现值为NaN的情况,导致往父节点汇总(递归相加)会出现错误。
 function parseFloatPlus(value){
     let rst = parseFloat(value);
     return  isNaN(rst) ? 0 : rst;
 };
 
-// 将arr2合并到arr1,并去重复。
-function mergeArr(arr1, arr2){
-    if (arr2.length > 0){
-        for (let e of arr2){
-            if (!arr1.includes(e)) arr1.push(e);
+// 数组合并,并去重复。
+Array.prototype.merge = function (arr) {
+    if (arr.length > 0){
+        for (let e of arr){
+            if (!this.includes(e)) this.push(e);
         };
     }
 };
 
-// 判断 sub 是否是 arr 的子数组。
-function isSubArr(sub, arr){
-    for(var i = 0, len = sub.length; i < len; i++){
-        if(arr.indexOf(sub[i]) == -1) return false;
+// 数组是否包含另一个数组。
+Array.prototype.hasSubArr = function (subArr){
+    for(var i = 0, len = subArr.length; i < len; i++){
+        if(this.indexOf(subArr[i]) == -1) return false;
     }
     return true;
 };
+
+function seqString(num,length){
+    var numstr = num.toString();
+    var l=numstr.length;
+    if (numstr.length>=length) {return numstr;}
+
+    for(var  i = 0 ;i<length - l;i++){
+        numstr = "0" + numstr;
+    }
+    return numstr;
+}

+ 5 - 0
public/web/rpt_value_define.js

@@ -197,6 +197,11 @@ const JV = {
     PAGE_STATUS: ["EveryPage","FirstPage", "LastPage", "SegmentStart", "SegmentEnd", "Group", "CrossRowEnd", "CrossColEnd"],
 
     CONTROL_PROPS: ["Shrink", "ShowZero", "Horizon", "Vertical", "Wrap"],
+    CONTROL_PROP_IDX_SHRINK: 0,
+    CONTROL_PROP_IDX_SHOW_ZERO: 1,
+    CONTROL_PROP_IDX_HORIZON: 2,
+    CONTROL_PROP_IDX_VERTICAL: 3,
+    CONTROL_PROP_IDX_WRAP: 4,
     BORDER_STYLE_PROPS: ["LineWeight", "DashStyle", "Color"],
     PROP_LINE_WEIGHT: "LineWeight",
     PROP_DASH_STYLE: "DashStyle",

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

@@ -1140,7 +1140,7 @@
                 </div>
                 <div class="modal-footer">
                     <button class="btn btn-primary" id="select_position_confirm">确定</button>
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                 </div>
             </div>
         </div>

+ 16 - 5
web/building_saas/main/js/models/calc_program.js

@@ -953,8 +953,18 @@ let analyzer = {
         return template.calcItems[idx];
     },
     isCycleCalc: function (expression, ID, template) {     // 这里判断expression,是ID引用: @5+@6
-        if (expression.includes(`@${ID}`))
-            return true;
+        let atID = `@${ID}`;
+        // 避免部分匹配,如:@10匹配@1
+        let idx = expression.indexOf(atID);
+        if (idx >= 0){
+            let nextPos = idx + atID.length;
+            if (nextPos >= expression.length)
+                return true;
+
+            let char = expression.charAt(nextPos);
+            if (!char.isNumberStr())
+                return true;
+        };
 
         let atIDs = analyzer.getAtIDArr(expression);
         for (let atID of atIDs) {
@@ -971,6 +981,7 @@ let analyzer = {
             try {
                 expr = expr.replace(/\[[\u4E00-\u9FA5]+\]/gi, '0');
                 expr = expr.replace(/@\d+/gi, '0');
+                expr = expr.replace(/L/gi, '0');
                 if (expr.includes('00'))
                     return false;
 
@@ -1852,11 +1863,11 @@ class CalcProgram {
                 leafBills.push(leafBill);
         };
 
-        mergeArr(billNodes, leafBills);
+        billNodes.merge(leafBills);
 
         for (let bill of billNodes){
             let changeBills = me.calculate(bill, true, false, tender);
-            mergeArr(allChangedNodes, changeBills);
+            allChangedNodes.merge(changeBills);
         };
 
         me.calcFormulaNodes(allChangedNodes, tender);
@@ -1898,7 +1909,7 @@ class CalcProgram {
             };
 
             let curChangeds = me.calculate(treeNode, true, true, tender);
-            mergeArr(changedNodes, curChangeds);
+            changedNodes.merge(curChangeds);
             me.saveNodes(changedNodes);
         };
     };

+ 30 - 15
web/building_saas/main/js/models/installation_fee.js

@@ -276,14 +276,15 @@ var installation_fee = {
                 userID: userID
             };
             let oldITypeRations = _.cloneDeep(project.Ration.getAllInstallTypeRation())//取所有旧的安装增加费定额-没有用的要删除
-            let oldRationMap = {}, deleteRationNodes = [], deleteBillsNodes = [];
+            let oldRationMap = {}, deleteRationNodes = [], deleteBillsNodes = [],reCalBillIDS = [];
             let isChange = newBills.length>0;//记录数据是否发生了改变;
-            for(let o of oldITypeRations){//过滤出要删除的定额
+            for(let o of oldITypeRations){//过滤出要删除的定额 - 同时对应的父项也要重新更新计算
                 if(rationKeyMap[o.installationKey]==undefined){
                     updateData.ration.delete.push(o);
                     let d_node =  project.mainTree.getNodeByID(o.ID);
                     if(d_node){
                         deleteRationNodes.push(d_node);
+                        reCalBillIDS.push(o.billsItemID);
                         isChange = true;
                     }
                 }
@@ -302,8 +303,8 @@ var installation_fee = {
                 }
             }
 
-            for(let tem_bx of BXs){//过滤要删除的补项
-                if(usedBXMap[tem_bx.ParentID]==undefined){
+            for(let tem_bx of BXs){//过滤要删除的 自动生成的补项
+                if(tem_bx.code.startsWith('BAZF')&& usedBXMap[tem_bx.ParentID]==undefined){
                     updateData.bills.delete.push(tem_bx);
                     let b_node =  project.mainTree.getNodeByID(tem_bx.ID);
                     if(b_node){
@@ -331,9 +332,16 @@ var installation_fee = {
                         calRations =  addNewNodes(updateData);
                     });
                     for(let u of updateData.ration.update){
-                        let unode =   projectObj.project.mainTree.findNode(u.ID);
+                        let unode =  projectObj.project.mainTree.findNode(u.ID);
                          unode?calRations.push(unode):'';
                     }
+                    if(reCalBillIDS.length > 0){
+                        reCalBillIDS = _.uniq(reCalBillIDS);
+                        for(let bID of reCalBillIDS){
+                            let bnode =  projectObj.project.mainTree.findNode(bID);
+                            bnode?calRations.push(bnode):''; //现在计算程序支持同时传入清单和定额了,所以能放一起
+                        }
+                    }
                     setTreeSelection(selectedNode);
                     let endTime =  +new Date();
                     console.log(`计算安装增加费时间——${endTime - startTime}`);
@@ -493,13 +501,13 @@ var installation_fee = {
                             projectID: parseInt(project.ID()),
                             ParentID:billID_key,
                             NextSiblingID:-1,
-                            code : 'BAZF',
                             name:'安装增加费',
                             unit:'元',
                             quantity:'1',
                             type:billType.BX
                         };
                         BXNodeData.ID =  uuid.v1();
+                        BXNodeData.code = getBXCode("BAZF",usedBXMap);
                         FBMap[billID_key] = BXNodeData;
                         newBills.push(BXNodeData);
                     }
@@ -519,6 +527,22 @@ var installation_fee = {
                 }
             }
 
+            function getBXCode(code,BXMap) {//自动生成物补项编号加001、002等后缀
+                let codes = [];
+                let i = 1;
+                let newCode = '';
+                for(let key in BXMap){
+                    codes.push(BXMap[key].code);
+                }
+                while (true){
+                    newCode = code + seqString(i,3);
+                    if(codes.indexOf(newCode)==-1){
+                        break;
+                    }
+                    i++;
+                }
+               return newCode;
+            }
 
             function allInOne(item,rule,rations,newBills,pre_key,rationKeyMap) {//统一设置
                 let billData = getBillNodeData(item,rule,newBills);//取对应的清单或生成一个新的清单数据
@@ -562,8 +586,6 @@ var installation_fee = {
                 newRationData = setNewRationProperty(newRationData,nextID,rule);
                 return newRationData;
             }
-
-
             function getBillNodeData(item,rule,newBills) {
                 let billData = null;
                 let billID = null;
@@ -590,7 +612,6 @@ var installation_fee = {
             function getBillsByID(billID){
                 return _.find(allBillsDatas,{"ID":billID});
             }
-
             function getBillsByCode(code){
                 return _.find(allBillsDatas, function(b) {
                     if(b.code&&b.code.indexOf(code)!=-1){
@@ -600,8 +621,6 @@ var installation_fee = {
                     }
                 })
             }
-
-
             function calcQuantity(rule,ration) {//计算单条定额的三个消耗量
                 let gljDecimal = getDecimal('glj.quantity');
                 let labourQuantity = 0, materialQuantity = 0, machineQuantity = 0;
@@ -718,10 +737,6 @@ var installation_fee = {
             });
         };
 
-
-
-
-
         installation_fee.prototype.resetToDefault = function (callback) {
             let me = this;
             let installFees = [];

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

@@ -100,7 +100,7 @@ const CP_Col_Width = {          // 多处计算程序界面的列宽统一设置
     feeRate: 60,
     displayFieldName: 120,
     statement: 380,
-    memo: 110,
+    memo: 120,
     unitFee: 90,
     totalFee: 90
 };

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

@@ -838,7 +838,7 @@ ProjectGLJ.prototype.isEstimateType = function(type){
 
 ProjectGLJ.prototype.getShortNameByID = function (ID) {
     let gljTypeMap = this.datas.constData.gljTypeMap;
-    return gljTypeMap["typeId" + ID].shortName;
+    return gljTypeMap["typeId" + ID]?gljTypeMap["typeId" + ID].shortName:'';
 };
 
 ProjectGLJ.prototype.calcQuantity  = function (init=false){

+ 2 - 2
web/building_saas/main/js/models/quantity_detail.js

@@ -626,7 +626,6 @@ var quantity_detail = {
             }else {
                 me.updateRationQuantity(value,node,null,editingText);
             }
-            gljOprObj.refreshView();
         };
 
 
@@ -698,6 +697,7 @@ var quantity_detail = {
             if(gljNodes.length>0){
                 projectObj.mainController.refreshTreeNode(gljNodes);
             }
+            gljOprObj.refreshView();
         };
         quantity_detail.prototype.updateRationQuantity=function(value,node,quantityEXP,editingText){
             node.data.quantityEXP = quantityEXP?quantityEXP:editingText;
@@ -723,7 +723,7 @@ var quantity_detail = {
                 }
             });
             projectObj.mainController.refreshTreeNode(node.children);//刷新子工料机总消耗量
-            gljOprObj.showRationGLJSheetData();
+            gljOprObj.refreshView();
         };
         quantity_detail.prototype.getDecimal=function (node) {
             var decimal = 3;

+ 17 - 14
web/building_saas/main/js/views/calc_program_manage.js

@@ -373,21 +373,24 @@ let calcProgramManage = {
                             return;
                         };
 
-                        template.calcItems.splice(idx, 1);
-                        let data = {
-                            'projectID': projectObj.project.ID(),
-                            'ID': template.ID,
-                            'calcItems': template.calcItems
+                        hintBox.infoBox('系统提示', `确定要删除计算规则“${item.name}”吗?`, 2, cbYes);
+                        function cbYes() {
+                            template.calcItems.splice(idx, 1);
+                            let data = {
+                                'projectID': projectObj.project.ID(),
+                                'ID': template.ID,
+                                'calcItems': template.calcItems
+                            };
+                            calcProgramManage.updateTemplate(data, function (rst) {
+                                if (rst){
+                                    projectObj.project.calcProgram.compileTemplate(template);
+                                    calcProgramManage.refreshDetailSheet();
+                                    let relationNodes = calcTools.getNodesByProgramID(template.ID);
+                                    projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
+                                    $.bootstrapLoading.end();
+                                }
+                            });
                         };
-                        calcProgramManage.updateTemplate(data, function (rst) {
-                            if (rst){
-                                projectObj.project.calcProgram.compileTemplate(template);
-                                calcProgramManage.refreshDetailSheet();
-                                let relationNodes = calcTools.getNodesByProgramID(template.ID);
-                                projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
-                            }
-                        });
-                        $.bootstrapLoading.end();
                     }
                 }
             }

+ 1 - 0
web/building_saas/main/js/views/glj_view.js

@@ -730,6 +730,7 @@ var gljOprObj = {
         var projectGljs = projectGLJData.gljList;
         var mixRatioMap = projectGLJData.mixRatioMap;
         if (ration_gljs && ration_gljs.length > 0 && projectGljs && projectGljs.length > 0) {
+
             for (var i = 0; i < ration_gljs.length; i++) {
                 var glj = _.find(projectGljs, {'id': ration_gljs[i].projectGLJID});
                 if (glj) {

+ 13 - 5
web/building_saas/main/js/views/installation_fee_view.js

@@ -331,6 +331,8 @@ let installationFeeObj={
         if(this.feeItemSpread == null){
             this.initInstallationFeeSpread();
         }else {
+            this.feeItemSpread.refresh();
+            this.feeDetailSpread.refresh();
             let sel_f = this.feeItemSheet.getSelections()[0];
             let sel_d = this.feeDetailSheet.getSelections()[0];
             this.showFeeItemData();
@@ -648,11 +650,15 @@ let installationFeeObj={
                recode:me.positionData[args.row]
            }
         }else {
-            if(args.row==me.positionSelectedObject.row){//如果是在已选中的记录中再点一次选中复框,则去掉选中记录
-                me.positionSelectedObject = null;
+            if(me.positionData[args.row].ID == me.positionSelectedObject.recode.ID){//行相同的时候有两种情况,一种是没有做过滤的情况,行相等就说明是要去掉选中记录。
+                // 另外一种有可能是过滤后刚好和初始的选中位置显示的时候相等,这里其实是不同的记录,所以行相等的时候用ID判断是不是来的记录才准确
+                    me.positionSelectedObject = null;  //如果是在已选中的记录中再点一次选中复框,则去掉选中记录
             }else {//切换选中记录
-                //去掉之前选中位置的打勾
-                args.sheet.getCell(me.positionSelectedObject.row, me.positionSelectedObject.col).value(0);
+                //去掉之前选中位置的打勾 - 要先查找原先的位置,因为过滤功能的原因,有可能选中的与当前的行数已经不一样了
+                let oldIndex = _.findIndex(me.positionData,{'ID':me.positionSelectedObject.recode.ID});
+                if(oldIndex != -1){
+                    args.sheet.getCell(oldIndex, me.positionSelectedObject.col).value(0);
+                }
                 me.positionSelectedObject ={
                     row : args.row,
                     col: args.col,
@@ -1364,7 +1370,9 @@ $(function () {
     });
     $('#calc_position').on('shown.bs.modal',function () {
         installationFeeObj.positionSelectedObject = null;
-        if (!installationFeeObj.positionSpread) {
+        if (installationFeeObj.positionSpread) {
+            installationFeeObj.positionSpread.refresh();
+        }else {
             installationFeeObj.initPositionSpread();
         }
         installationFeeObj.loadSelectionNodes();

+ 61 - 15
web/building_saas/report/html/rpt_print.html

@@ -13,21 +13,34 @@
         page-break-before: auto;
         page-break-after: auto;
     }
-</style><script type="text/javascript" src="/web/building_saas/report/js/jpc_output_value_define.js"></script>
+</style>
+<style type="text/css">
+    svg{
+        width: 1122px;
+        height: 1122px;
+    }
+</style>
+<script type="text/javascript" src="/web/building_saas/report/js/jpc_output_value_define.js"></script>
 <body onload="loading()" onbeforeunload="closing()">
 </body>
 <script src="/lib/jquery/jquery-3.2.1.min.js"></script>
 <script type="text/javascript" src="/web/building_saas/report/js/jpc_output.js"></script>
+<script type="text/javascript" src="/web/building_saas/report/js/rpt_print.js"></script>
 <SCRIPT type="text/javascript">
     let canvasArr = [];
     function loading() {
         if (sessionStorage.currentPageData) {
             let pageData = JSON.parse(sessionStorage.currentPageData);
+//            let scaleFactor = parseInt(sessionStorage.scaleFactor);
+            let scaleFactor = 1;
             $(document).attr("title", pageData[JV.NODE_PAGE_INFO][JV.NODE_MAIN_INFO_RPT_NAME]);
-            let pageHeight = 793, pageWidth = 1122;
+            let orgHeight = 793, orgWidth = 1122;
+            let pageHeight = orgHeight * scaleFactor, pageWidth = orgWidth * scaleFactor;
             if (sessionStorage.pageSize === 'A3') {
-                pageHeight = 1122;
-                pageWidth = 793 * 2;
+                pageHeight = orgWidth * scaleFactor;
+                pageWidth = orgHeight * 2 * scaleFactor;
+                orgHeight = 1122;
+                orgWidth = 793 * 2;
             } else if (sessionStorage.pageSize === '自定义') {
                 //自定义
             }
@@ -35,21 +48,54 @@
                 let tmpInt = pageHeight;
                 pageHeight = pageWidth;
                 pageWidth = tmpInt;
+
+                tmpInt = orgWidth;
+                orgWidth = orgHeight;
+                orgHeight = tmpInt;
             }
+//            for (let i = 0; i < pageData.items.length; i++) {
+//                let div = $('<div class="pageBreak"><canvas width="' + pageWidth + '" height="' + pageHeight + '"></canvas></div>');
+//                $("body").append(div);
+//            }
+//            $(document.body).find("div").each(function(index,element){
+//                $(element).find("canvas").each(function(cIdx,elementCanvas){
+//                    canvasArr.push(elementCanvas);
+//                });
+//            });
+//            JpcCanvasOutput.scaleFactor = scaleFactor;
+//            JpcCanvasOutput.resetFonts(pageData[JV.NODE_FONT_COLLECTION]);
+//            for (let i = 0; i < canvasArr.length; i++) {
+//                JpcCanvasOutput.offsetX = -30;
+//                JpcCanvasOutput.offsetY = -30;
+//                JpcCanvasOutput.drawToCanvas(pageData, canvasArr[i], i+1);
+//            }
+
+//            let imgDataArr = [];
+//            for (let canvas of canvasArr) {
+//                imgDataArr.push(canvas.toDataURL());
+//            }
+//            let imgIdx = 0;
+//            $(document.body).find("div").each(function(index,element){
+//                let img = document.createElement('img');
+//                img.src = imgDataArr[imgIdx];
+//                img.height = orgHeight;
+//                img.width = orgWidth;
+//                imgIdx++;
+//                element.appendChild(img);
+//                $(element).find("canvas").each(function(cIdx,elementCanvas){
+//                    elementCanvas.style.display = "none";
+//                });
+//            });
+
+            let svgArr = rptPrintHelper.buildSvgArr(pageData, -30, -30);
             for (let i = 0; i < pageData.items.length; i++) {
-                let div = $('<div class="pageBreak"><canvas width="' + pageWidth + '" height="' + pageHeight + '"></canvas></div>');
+                let div = $('<div class="pageBreak"></div>');
+//                console.log()
+//                div.append(svgArr[i]);
+                div.append($(svgArr[i].join("")));
                 $("body").append(div);
             }
-            $(document.body).find("div").each(function(index,element){
-                $(element).find("canvas").each(function(cIdx,elementCanvas){
-                    canvasArr.push(elementCanvas);
-                });
-            });
-            for (let i = 0; i < canvasArr.length; i++) {
-                JpcCanvasOutput.offsetX = -10;
-                JpcCanvasOutput.offsetY = -20;
-                JpcCanvasOutput.drawToCanvas(pageData, canvasArr[i], i+1);
-            }
+
             window.print();
             //document.execCommand("print");
         } else {

+ 25 - 1
web/building_saas/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,6 +12,14 @@ 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");
@@ -252,6 +261,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],
@@ -266,9 +286,13 @@ 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);
+                if (me.scaleFactor !== 1) {
+                    private_resetCellFont(cell);
+                    private_resetArea(cell[JV.PROP_AREA]);
+                }
                 private_drawCell(cell, fonts, styles, controls, newPageMergeBand);
             }
         }

+ 13 - 0
web/building_saas/report/js/jpc_output_value_define.js

@@ -34,11 +34,24 @@ let JV = {
     IDX_BOTTOM: 3,
 
     CONTROL_PROPS: ["Shrink", "ShowZero", "Horizon", "Vertical", "Wrap"],
+    CONTROL_PROP_IDX_SHRINK: 0,
+    CONTROL_PROP_IDX_SHOW_ZERO: 1,
+    CONTROL_PROP_IDX_HORIZON: 2,
+    CONTROL_PROP_IDX_VERTICAL: 3,
+    CONTROL_PROP_IDX_WRAP: 4,
     BORDER_STYLE_PROPS: ["LineWeight", "DashStyle", "Color"],
     PROP_LINE_WEIGHT: "LineWeight",
     PROP_DASH_STYLE: "DashStyle",
     PROP_COLOR: "Color",
     FONT_PROPS: ["Name", "FontHeight", "FontColor", "FontBold", "FontItalic", "FontUnderline", "FontStrikeOut", "FontAngle"],
+    FONT_PROP_IDX_NAME: 0,
+    FONT_PROP_IDX_HEIGHT: 1,
+    FONT_PROP_IDX_COLOR: 2,
+    FONT_PROP_IDX_BOLD: 3,
+    FONT_PROP_IDX_ITALIC: 4,
+    FONT_PROP_IDX_UNDERLINE: 5,
+    FONT_PROP_IDX_STRIKEOUT: 6,
+    FONT_PROP_IDX_ANGLE: 7,
 
     OUTPUT_OFFSET: [2,2,1,3],
     OFFSET_IDX_LEFT: 0,

+ 98 - 1
web/building_saas/report/js/rpt_print.js

@@ -9,6 +9,7 @@ let rptPrintHelper = {
             sessionStorage.currentPageData = JSON.stringify(zTreeOprObj.currentRptPageRst);
             sessionStorage.pageSize = rptControlObj.getCurrentPageSize();
             sessionStorage.orientation = rptControlObj.getCurrentOrientation();
+            sessionStorage.scaleFactor = 1;
             window.open('/rpt_print');
         } else {
             sessionStorage.currentPageData = null;
@@ -16,5 +17,101 @@ let rptPrintHelper = {
     },
     print: function () {
         //
+    },
+    buildSvgArr: function (pagesData, offsetX, offsetY) {
+        let styles = pagesData[JV.NODE_STYLE_COLLECTION],
+            fonts = pagesData[JV.NODE_FONT_COLLECTION],
+            controls = pagesData[JV.NODE_CONTROL_COLLECTION]
+        ;
+        let rst = [];
+        for (let page of pagesData.items) {
+            let svgPageArr = [], pixelSize = getPixelSize(pagesData);
+            svgPageArr.push("<svg width='" + pixelSize[0] + "' height='" + pixelSize[1] + "'>");
+            for (let cell of page.cells) {
+                svgPageArr.push(buildCellSvg(cell, fonts, styles, controls, page[JV.PROP_PAGE_MERGE_BORDER], pagesData[JV.BAND_PROP_MERGE_BAND], offsetX, offsetY));
+            }
+            svgPageArr.push("</svg>");
+            rst.push(svgPageArr);
+        }
+        return rst;
+    }
+};
+
+function buildCellSvg(cell, fonts, styles, controls, pageMergeBorder, rptMergeBorder, offsetX, offsetY) {
+    let rst = [];
+    let style = styles[cell[JV.PROP_STYLE]];
+    let mergeBandStyle = null;
+    if (rptMergeBorder) {
+        mergeBandStyle = styles[rptMergeBorder[JV.PROP_STYLE]];
+    }
+    let left = parseInt(cell[JV.PROP_AREA][JV.PROP_LEFT]) + offsetX + 0.5,
+        right = parseInt(cell[JV.PROP_AREA][JV.PROP_RIGHT]) + offsetX + 0.5,
+        top = parseInt(cell[JV.PROP_AREA][JV.PROP_TOP]) + offsetY + 0.5,
+        bottom = parseInt(cell[JV.PROP_AREA][JV.PROP_BOTTOM]) + offsetY + 0.5,
+        x = left, y = top,
+        text_anchor = "start"
+    ;
+    if (style) {
+        if (style[JV.PROP_LEFT] && parseFloat(style[JV.PROP_LEFT][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + left + "' y1='" + top +
+                "' x2='" + left + "' y2='" + bottom +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_RIGHT] && parseFloat(style[JV.PROP_RIGHT][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + right + "' y1='" + top +
+                "' x2='" + right + "' y2='" + bottom +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_TOP] && parseFloat(style[JV.PROP_TOP][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + left + "' y1='" + top +
+                "' x2='" + right + "' y2='" + top +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+        if (style[JV.PROP_BOTTOM] && parseFloat(style[JV.PROP_BOTTOM][JV.PROP_LINE_WEIGHT]) > 0) {
+            rst.push("<line x1='" + left + "' y1='" + bottom +
+                "' x2='" + right + "' y2='" + bottom +
+                "' style='stroke:rgb(0,0,0);stroke-width:1'/>")
+        }
+    }
+    let font = cell[JV.PROP_FONT];
+    if (typeof font === 'string') {
+        font = fonts[cell[JV.PROP_FONT]];
+    }
+    let fontsize = Math.round(parseInt(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]]) * 3 / 4);
+    let fontWeight = (font[JV.FONT_PROPS[JV.FONT_PROP_IDX_BOLD]] === 'T')?"bold":"normal";
+    let control = controls[cell[JV.PROP_CONTROL]];
+    if (control) {
+        if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "left") {
+            text_anchor = "start";
+            x = left + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "right") {
+            text_anchor = "end";
+            x = right - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_HORIZON]] === "center") {
+            text_anchor = "middle";
+            x = Math.round((left + right) / 2);
+        }
+        if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "top") {
+            y = top + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "bottom") {
+            y = bottom - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM];
+        } else if (control[JV.CONTROL_PROPS[JV.CONTROL_PROP_IDX_VERTICAL]] === "center") {
+            y = Math.round((top + bottom + fontsize) / 2 );
+        }
+    }
+    rst.push("<text style='fill:black;font-family:" + font[JV.PROP_NAME] +
+        ";font-weight:" + fontWeight +
+        ";font-size:" + fontsize + "pt' x='" +
+        x +"' y='" + y + "' text-anchor='" + text_anchor + "'>" + cell[JV.PROP_VALUE] + "</text>");
+    return rst.join("");
+}
+
+function getPixelSize(pagesData) {
+    let rst = [793,1122];
+    let SCREEN_DPI = [96,96];
+    if (pagesData[JV.NODE_PAGE_INFO] && pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE]) {
+        rst[0] = Math.round(SCREEN_DPI[0] * pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][0]);
+        rst[1] = Math.round(SCREEN_DPI[1] * pagesData[JV.NODE_PAGE_INFO][JV.NODE_PAGE_SIZE][1]);
     }
-};
+    return rst;
+}