Explorar o código

BUG #1759 - 自动换行处理(UI + PDF)

TonyKang %!s(int64=6) %!d(string=hai) anos
pai
achega
628dcb08fb

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

+ 3 - 2
test/unit/reports/test_rpt_test_template.js

@@ -32,7 +32,7 @@ let demoPrjId = - 1;
 // let demoRptId = 361; //封1
 // let demoRptId = 279; //表04
 // let demoRptId = 261; //封3
-let demoRptId = 458; //09
+// let demoRptId = 458; //09
 // let demoRptId = 451; //09-1
 // let demoRptId = 452; //04
 // let demoRptId = 612; //09-3
@@ -41,6 +41,7 @@ let demoRptId = 458; //09
 // let demoRptId = 389; //10
 // let demoRptId = 280; //11-1 暂列金
 // let demoRptId = 2260; //测试基本信息
+let demoRptId = 479; //12
 let pagesize = "A4";
 //288: 11-2表(新)
 //279: 04
@@ -82,7 +83,7 @@ test('测试 - 测试模板啦: ', function (t) {
         rptTplDataFacade.prepareProjectData(userId_Dft, demoPrjId, filter, function (err, msg, rawDataObj) {
             if (!err) {
                 try {
-                    fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject_测试模板.jsp");
+                    // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject_测试模板.jsp");
                     let tplData = rptDataUtil.assembleData(rawDataObj);
                     // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataAfterCacl_测试模板.jsp");
                     // fsUtil.writeObjToFile(tplData, "D:/GitHome/ConstructionCost/tmp/rptTplAssembledData_测试模板.jsp");

+ 66 - 12
web/building_saas/report/js/jpc_output.js

@@ -86,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 = [];
@@ -102,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];
@@ -164,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;
                     }
                 }