Przeglądaj źródła

Merge branch 'master' of http://192.168.1.41:3000/maixinrong/Calculation

laiguoran 5 lat temu
rodzic
commit
ce1e417221

+ 53 - 0
app/controller/template_controller.js

@@ -0,0 +1,53 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const path = require('path');
+const fs = require('fs');
+
+module.exports = app => {
+
+    class TemplateController extends app.BaseController {
+        /**
+         * 下载 各种模板
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async download(ctx) {
+            const file = ctx.params.file;
+            if (file) {
+                try {
+                    let fileName;
+                    switch (file) {
+                        case '导入分项清单EXCEL格式.xls':
+                            fileName = path.join(this.app.baseDir, 'app', 'public', 'files', 'template', 'ledger', '导入分项清单EXCEL格式.xls');
+                            break;
+                        case '导入工程量清单EXCEL格式.xls':
+                            fileName = path.join(this.app.baseDir, 'app', 'public', 'files', 'template', 'ledger', '导入工程量清单EXCEL格式.xls');
+                            break;
+                        default:
+                            throw '参数错误'
+                    }
+                    ctx.body = await fs.readFileSync(fileName);
+                } catch (err) {
+                    this.log(err);
+                    if (err.stack) {
+                        ctx.body = '您下载的示例文件不存在';
+                    } else {
+                        ctx.body = err;
+                    }
+                }
+            } else {
+                ctx.body = '参数错误';
+            }
+        }
+    }
+
+    return TemplateController;
+};

+ 2 - 2
app/public/css/main.css

@@ -41,6 +41,7 @@ font-size: .875rem;
 }
 .form-check,.form-check-label{
   cursor: pointer;
+  line-height: 22px;
 }
 .input-group-text .group-checkbox[type="checkbox"],.input-group-text .group-checkbox[type="radio"]{
   margin-top: .3rem;
@@ -253,7 +254,6 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 .panel-content .content-wrap{
   margin:0 15px 15px;
   position: relative;
-  background-color: #d2d5da
 }
 .panel-sidebar+.panel-content{
   padding: 65px 0 0 200px;
@@ -322,7 +322,7 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 .side-menu .nav-link{
   line-height: 16px;
   font-size: 14px;
-  color:#666;
+  color:#007bff;
 }
 .side-menu .nav-link:hover{
   background:#dcdee3;

BIN
app/public/files/template/ledger/导入工程量清单EXCEL格式.xls


+ 43 - 64
app/public/js/ledger.js

@@ -1135,7 +1135,49 @@ $(document).ready(function() {
                         return readOnly;
                     },
                     callback: function (key, opt) {
-                        $('#upload-ledger').modal('show');
+                        importExcel.doImport({
+                            template: {
+                                hint: '0号台账',
+                                url: '/template/导入分项清单EXCEL格式.xls',
+                            },
+                            callback: function (sheet) {
+                                postDataCompress(window.location.pathname + '/upload-excel', sheet, function (result) {
+                                    ledgerTree.loadDatas(result.bills);
+                                    treeCalc.calculateAll(ledgerTree);
+                                    SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
+                                    pos.loadDatas(result.pos);
+                                    posOperationObj.loadCurPosData();
+                                }, null);
+                            }
+                        });
+                        //$('#upload-ledger').modal('show');
+                    }
+                },
+                'importGclBills2Xmj': {
+                    name: '导入工程量清单至项目节',
+                    icon: 'fa-file-excel-o',
+                    disabled: function (key, opt) {
+                        const node = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
+                        return readOnly
+                            || (node.children && node.children.length > 0)
+                            || (!_.isNil(node.b_code) && node.b_code !== '');
+                    },
+                    callback: function (key, opt) {
+                        importExcel.doImport({
+                            template: {
+                                hint: '工程量清单',
+                                url: '/template/导入工程量清单EXCEL格式.xls',
+                            },
+                            callback: function (sheet) {
+                                postDataCompress(window.location.pathname + '/upload-excel', sheet, function (result) {
+                                    ledgerTree.loadDatas(result.bills);
+                                    treeCalc.calculateAll(ledgerTree);
+                                    SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
+                                    pos.loadDatas(result.pos);
+                                    posOperationObj.loadCurPosData();
+                                }, null);
+                            }
+                        });
                     }
                 },
                 'exportExcel': {
@@ -2206,69 +2248,6 @@ $(document).ready(function() {
             }
         });
     });
-    // 选择excel文件后,加载全部sheet
-    $('#upload-ledger-file').change(function () {
-        if (this.files.length === 0) {
-            $('#upload-ledger-sheets').html('').hide();
-            return;
-        }$('#upload-ledger-sheets').hide();
-        try {
-            $('#select-excel-loading').show();
-            xlsxUtils.import(this.files[0], (excelData) => {
-                if (excelData.SheetNames.length > 0) {
-                    const html = [];
-                    html.push('<hr></hr>');
-                    html.push('<h6>选择导入的工作表</h6>');
-                    for (const iName in excelData.SheetNames) {
-                        const name = excelData.SheetNames[iName];
-                        html.push('<div class="card p-2 mb-2">');
-                        html.push('<div class="form-check">');
-                        html.push('<input class="form-check-input" type="radio" name="sheetName" id="excel-sheet' + iName + '"', (iName == 0 ? ' checked=""' : ''), ' value="' + name + '"',  '>');
-                        html.push('<label class="form-check-label" for="excel-sheet' + iName + '">', name, '</label>');
-                        html.push('</div>');
-                        html.push('</div>');
-                    }
-                    $('#upload-ledger-sheets').html(html.join('')).show();
-                    $('.mb-2.p-2').mouseenter(function () {
-                        $(this).addClass('border-primary');
-                    });
-                    $('.mb-2.p-2').mouseleave(function () {
-                        $(this).removeClass('border-primary');
-                    })
-                } else {
-                    toastr.info('选择的Excel无有效数据,请重新选择');
-                    $('#upload-ledger-sheets').hide();
-                }
-                $('#select-excel-loading').hide();
-            });
-        } catch(err) {
-            $('#select-excel-loading').hide();
-            toastr.error('加载excel异常,请刷新当前页面');
-            $('#upload-ledger-sheets').hide();
-        }
-    });
-    // 上传excel内容,并导入
-    $('#upload-ledger-ok').click(function () {
-        const sheetName = $('input[name=sheetName]:checked').val();
-        if (sheetName) {
-            const sheet = {
-                rows: xlsxUtils.getSheetByName(sheetName, {header: 1}),
-                merge: xlsxUtils._wb.Sheets[sheetName]["!merges"]
-            };
-            postDataCompress(window.location.pathname + '/upload-excel', sheet, function (result) {
-                ledgerTree.loadDatas(result.bills);
-                treeCalc.calculateAll(ledgerTree);
-                SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
-                pos.loadDatas(result.pos);
-                posOperationObj.loadCurPosData();
-                $('#upload-ledger').modal('hide');
-            }, null);
-        }
-    });
-    $('#upload-ledger').bind('hidden.bs.modal', function () {
-        $('#upload-ledger-file').val('');
-        $('#upload-ledger-sheets').html('');
-    });
 
     $('#hideSp').click(function () {
         $('#sp-list2').modal('hide');

+ 7 - 5
app/public/report/js/rpt_signature.js

@@ -281,8 +281,9 @@ let rptSignatureHelper = {
                 }
             }
         }
-        ROLE_REL_LIST = [];
-        ROLE_REL_LIST = ROLE_REL_LIST.concat(rptSignatureHelper.originalRoleRelList);
+        // ROLE_REL_LIST = [];
+        // ROLE_REL_LIST = ROLE_REL_LIST.concat(rptSignatureHelper.originalRoleRelList);
+        ROLE_REL_LIST = JSON.parse(JSON.stringify(rptSignatureHelper.originalRoleRelList));
         zTreeOprObj.showPage(zTreeOprObj.currentPage, zTreeOprObj.canvas);
     },
     resetSignDate: function() {
@@ -341,12 +342,13 @@ let rptSignatureHelper = {
         params.tender_id = TENDER_ID;
         params.rpt_id = zTreeOprObj.currentNode.refId;
         params.rel_content = ROLE_REL_LIST;
-        rptSignatureHelper.originalRoleRelList = [];
-        rptSignatureHelper.originalRoleRelList = rptSignatureHelper.originalRoleRelList.concat(ROLE_REL_LIST);
+        // rptSignatureHelper.originalRoleRelList = [];
+        // rptSignatureHelper.originalRoleRelList = rptSignatureHelper.originalRoleRelList.concat(ROLE_REL_LIST);
+        rptSignatureHelper.originalRoleRelList = JSON.parse(JSON.stringify(ROLE_REL_LIST));
         CommonAjax.postXsrfEx("/tender/report_api/updateRoleRelationship", params, 10000, true, getCookie('csrfToken'),
             function(result){
                 console.log(result);
-                if (result.data && result.data.insertId >= 0) {
+                if (result.data && result.data.insertId > 0) {
                     CURRENT_ROLE_REL_ID = result.data.insertId;
                 }
             }, function(err){

+ 2 - 2
app/reports/rpt_component/helper/jpc_helper_common.js

@@ -142,7 +142,7 @@ const JpcCommonHelper = {
         }
         return rst;
     },
-    getStringLinesInArea: function(area, strVal, pdfDoc, chnW, otherW) {
+    getStringLinesInArea: function(area, strVal, chnW, otherW) {
         // 备注: 因后台的pdf kit判断字符串长度与前端的不一样,需要做些调整,不一次性地判断字符串长度。
         //      分2种字符:中文与非中文,按照各种字符的数量分别乘以相关一个字符的宽度再累计。
         //      另判断行数还不能直接用总长度除以宽度来计算,因每一行都会有不同的余量,所以得一行行走过来判断。
@@ -167,7 +167,7 @@ const JpcCommonHelper = {
         return rst;
         // 备注: 其实是想用canvas的,但node canvas装起来麻烦,暂时用PDF Kit来顶用一下,以后有更好的再换
     },
-    splitString: function(area, strVal, pdfDoc, chnW, otherW) {
+    splitString: function(area, strVal, chnW, otherW) {
         const rst = [];
         if (strVal) {
             const areaWidth = area[JV.PROP_RIGHT] - area[JV.PROP_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT] - 1;

+ 515 - 0
app/reports/rpt_component/helper/jpc_helper_font_width.js

@@ -0,0 +1,515 @@
+'use strict';
+
+/**
+ * Created by Tony on 2019/12/12.
+ */
+
+const fontWidthMap = {
+    '宋体': {
+        '宽': {
+            '_6': 6,
+            '_7': 7,
+            '_8': 8,
+            '_9': 9,
+            '_10': 10,
+            '_11': 11,
+            '_12': 12,
+            '_13': 13,
+            '_14': 14,
+            '_15': 15,
+            '_16': 16,
+            '_17': 17,
+            '_18': 18,
+            '_19': 19,
+            '_20': 20,
+            '_21': 21,
+            '_22': 22,
+            '_23': 23,
+            '_24': 24,
+            '_25': 25,
+            '_26': 26,
+            '_27': 27,
+            '_28': 28,
+            '_29': 29,
+            '_30': 30,
+            '_31': 31,
+            '_32': 32,
+            '_33': 33,
+            '_34': 34,
+            '_35': 35,
+            '_36': 36,
+            '_37': 37,
+            '_38': 38,
+            '_39': 39,
+            '_40': 40,
+            '_41': 41,
+            '_42': 42,
+            '_43': 43,
+            '_44': 44,
+            '_45': 45,
+            '_46': 46,
+            '_47': 47,
+            '_48': 48,
+            '_49': 49,
+            '_50': 50,
+            '_51': 51,
+            '_52': 52,
+            '_53': 53,
+            '_54': 54,
+            '_55': 55,
+            '_56': 56,
+            '_57': 57,
+            '_58': 58,
+            '_59': 59,
+            '_60': 60,
+            '_61': 61,
+            '_62': 62,
+            '_63': 63,
+            '_64': 64
+        },
+        '窄': {
+            '_6': 3,
+            '_7': 3.5,
+            '_8': 4,
+            '_9': 4.5,
+            '_10': 5,
+            '_11': 5.5,
+            '_12': 6,
+            '_13': 6.5,
+            '_14': 7,
+            '_15': 7.5,
+            '_16': 8,
+            '_17': 8.5,
+            '_18': 9,
+            '_19': 9.5,
+            '_20': 10,
+            '_21': 10.5,
+            '_22': 11,
+            '_23': 11.5,
+            '_24': 12,
+            '_25': 12.5,
+            '_26': 13,
+            '_27': 13.5,
+            '_28': 14,
+            '_29': 14.5,
+            '_30': 15,
+            '_31': 15.5,
+            '_32': 16,
+            '_33': 16.5,
+            '_34': 17,
+            '_35': 17.5,
+            '_36': 18,
+            '_37': 18.5,
+            '_38': 19,
+            '_39': 19.5,
+            '_40': 20,
+            '_41': 20.5,
+            '_42': 21,
+            '_43': 21.5,
+            '_44': 22,
+            '_45': 22.5,
+            '_46': 23,
+            '_47': 23.5,
+            '_48': 24,
+            '_49': 24.5,
+            '_50': 25,
+            '_51': 25.5,
+            '_52': 26,
+            '_53': 26.5,
+            '_54': 27,
+            '_55': 27.5,
+            '_56': 28,
+            '_57': 28.5,
+            '_58': 29,
+            '_59': 29.5,
+            '_60': 30,
+            '_61': 30.5,
+            '_62': 31,
+            '_63': 31.5,
+            '_64': 32
+        }
+    },
+    '黑体': {
+        '宽': {
+            '_6': 6,
+            '_7': 7,
+            '_8': 8,
+            '_9': 9,
+            '_10': 10,
+            '_11': 11,
+            '_12': 12,
+            '_13': 13,
+            '_14': 14,
+            '_15': 15,
+            '_16': 16,
+            '_17': 17,
+            '_18': 18,
+            '_19': 19,
+            '_20': 20,
+            '_21': 21,
+            '_22': 22,
+            '_23': 23,
+            '_24': 24,
+            '_25': 25,
+            '_26': 26,
+            '_27': 27,
+            '_28': 28,
+            '_29': 29,
+            '_30': 30,
+            '_31': 31,
+            '_32': 32,
+            '_33': 33,
+            '_34': 34,
+            '_35': 35,
+            '_36': 36,
+            '_37': 37,
+            '_38': 38,
+            '_39': 39,
+            '_40': 40,
+            '_41': 41,
+            '_42': 42,
+            '_43': 43,
+            '_44': 44,
+            '_45': 45,
+            '_46': 46,
+            '_47': 47,
+            '_48': 48,
+            '_49': 49,
+            '_50': 50,
+            '_51': 51,
+            '_52': 52,
+            '_53': 53,
+            '_54': 54,
+            '_55': 55,
+            '_56': 56,
+            '_57': 57,
+            '_58': 58,
+            '_59': 59,
+            '_60': 60,
+            '_61': 61,
+            '_62': 62,
+            '_63': 63,
+            '_64': 64
+        },
+        '窄': {
+            '_6': 3,
+            '_7': 3.5,
+            '_8': 4,
+            '_9': 4.5,
+            '_10': 5,
+            '_11': 5.5,
+            '_12': 6,
+            '_13': 6.5,
+            '_14': 7,
+            '_15': 7.5,
+            '_16': 8,
+            '_17': 8.5,
+            '_18': 9,
+            '_19': 9.5,
+            '_20': 10,
+            '_21': 10.5,
+            '_22': 11,
+            '_23': 11.5,
+            '_24': 12,
+            '_25': 12.5,
+            '_26': 13,
+            '_27': 13.5,
+            '_28': 14,
+            '_29': 14.5,
+            '_30': 15,
+            '_31': 15.5,
+            '_32': 16,
+            '_33': 16.5,
+            '_34': 17,
+            '_35': 17.5,
+            '_36': 18,
+            '_37': 18.5,
+            '_38': 19,
+            '_39': 19.5,
+            '_40': 20,
+            '_41': 20.5,
+            '_42': 21,
+            '_43': 21.5,
+            '_44': 22,
+            '_45': 22.5,
+            '_46': 23,
+            '_47': 23.5,
+            '_48': 24,
+            '_49': 24.5,
+            '_50': 25,
+            '_51': 25.5,
+            '_52': 26,
+            '_53': 26.5,
+            '_54': 27,
+            '_55': 27.5,
+            '_56': 28,
+            '_57': 28.5,
+            '_58': 29,
+            '_59': 29.5,
+            '_60': 30,
+            '_61': 30.5,
+            '_62': 31,
+            '_63': 31.5,
+            '_64': 32
+        }
+    },
+    '楷体': {
+        '宽': {
+            '_6': 6,
+            '_7': 7,
+            '_8': 8,
+            '_9': 9,
+            '_10': 10,
+            '_11': 11,
+            '_12': 12,
+            '_13': 13,
+            '_14': 14,
+            '_15': 15,
+            '_16': 16,
+            '_17': 17,
+            '_18': 18,
+            '_19': 19,
+            '_20': 20,
+            '_21': 21,
+            '_22': 22,
+            '_23': 23,
+            '_24': 24,
+            '_25': 25,
+            '_26': 26,
+            '_27': 27,
+            '_28': 28,
+            '_29': 29,
+            '_30': 30,
+            '_31': 31,
+            '_32': 32,
+            '_33': 33,
+            '_34': 34,
+            '_35': 35,
+            '_36': 36,
+            '_37': 37,
+            '_38': 38,
+            '_39': 39,
+            '_40': 40,
+            '_41': 41,
+            '_42': 42,
+            '_43': 43,
+            '_44': 44,
+            '_45': 45,
+            '_46': 46,
+            '_47': 47,
+            '_48': 48,
+            '_49': 49,
+            '_50': 50,
+            '_51': 51,
+            '_52': 52,
+            '_53': 53,
+            '_54': 54,
+            '_55': 55,
+            '_56': 56,
+            '_57': 57,
+            '_58': 58,
+            '_59': 59,
+            '_60': 60,
+            '_61': 61,
+            '_62': 62,
+            '_63': 63,
+            '_64': 64
+        },
+        '窄': {
+            '_6': 3,
+            '_7': 3.5,
+            '_8': 4,
+            '_9': 4.5,
+            '_10': 5,
+            '_11': 5.5,
+            '_12': 6,
+            '_13': 6.5,
+            '_14': 7,
+            '_15': 7.5,
+            '_16': 8,
+            '_17': 8.5,
+            '_18': 9,
+            '_19': 9.5,
+            '_20': 10,
+            '_21': 10.5,
+            '_22': 11,
+            '_23': 11.5,
+            '_24': 12,
+            '_25': 12.5,
+            '_26': 13,
+            '_27': 13.5,
+            '_28': 14,
+            '_29': 14.5,
+            '_30': 15,
+            '_31': 15.5,
+            '_32': 16,
+            '_33': 16.5,
+            '_34': 17,
+            '_35': 17.5,
+            '_36': 18,
+            '_37': 18.5,
+            '_38': 19,
+            '_39': 19.5,
+            '_40': 20,
+            '_41': 20.5,
+            '_42': 21,
+            '_43': 21.5,
+            '_44': 22,
+            '_45': 22.5,
+            '_46': 23,
+            '_47': 23.5,
+            '_48': 24,
+            '_49': 24.5,
+            '_50': 25,
+            '_51': 25.5,
+            '_52': 26,
+            '_53': 26.5,
+            '_54': 27,
+            '_55': 27.5,
+            '_56': 28,
+            '_57': 28.5,
+            '_58': 29,
+            '_59': 29.5,
+            '_60': 30,
+            '_61': 30.5,
+            '_62': 31,
+            '_63': 31.5,
+            '_64': 32
+        }
+    },
+    'Arial': {
+        '宽': {
+            '_6': 6,
+            '_7': 7,
+            '_8': 8,
+            '_9': 9,
+            '_10': 10,
+            '_11': 11,
+            '_12': 12,
+            '_13': 13,
+            '_14': 14,
+            '_15': 15,
+            '_16': 16,
+            '_17': 17,
+            '_18': 18,
+            '_19': 19,
+            '_20': 20,
+            '_21': 21,
+            '_22': 22,
+            '_23': 23,
+            '_24': 24,
+            '_25': 25,
+            '_26': 26,
+            '_27': 27,
+            '_28': 28,
+            '_29': 29,
+            '_30': 30,
+            '_31': 31,
+            '_32': 32,
+            '_33': 33,
+            '_34': 34,
+            '_35': 35,
+            '_36': 36,
+            '_37': 37,
+            '_38': 38,
+            '_39': 39,
+            '_40': 40,
+            '_41': 41,
+            '_42': 42,
+            '_43': 43,
+            '_44': 44,
+            '_45': 45,
+            '_46': 46,
+            '_47': 47,
+            '_48': 48,
+            '_49': 49,
+            '_50': 50,
+            '_51': 51,
+            '_52': 52,
+            '_53': 53,
+            '_54': 54,
+            '_55': 55,
+            '_56': 56,
+            '_57': 57,
+            '_58': 58,
+            '_59': 59,
+            '_60': 60,
+            '_61': 61,
+            '_62': 62,
+            '_63': 63,
+            '_64': 64
+        },
+        '窄': {
+            '_6': 3.3399999141693115,
+            '_7': 3.8899998664855957,
+            '_8': 4.449999809265137,
+            '_9': 5.009999752044678,
+            '_10': 5.559999942779541,
+            '_11': 6.119999885559082,
+            '_12': 6.670000076293945,
+            '_13': 7.230000019073486,
+            '_14': 7.789999961853027,
+            '_15': 8.34000015258789,
+            '_16': 8.899999618530273,
+            '_17': 9.449999809265136,
+            '_18': 10.010000228881836,
+            '_19': 10.569999694824218,
+            '_20': 11.119999885559082,
+            '_21': 11.679999351501464,
+            '_22': 12.239999771118164,
+            '_23': 12.789999961853027,
+            '_24': 13.34999942779541,
+            '_25': 13.899999618530273,
+            '_26': 14.460000038146972,
+            '_27': 15.019999504089355,
+            '_28': 15.569999694824218,
+            '_29': 16.1299991607666,
+            '_30': 16.68000030517578,
+            '_31': 17.239999771118164,
+            '_32': 17.799999237060547,
+            '_33': 18.350000381469726,
+            '_34': 18.90999984741211,
+            '_35': 19.469999313354492,
+            '_36': 20.020000457763672,
+            '_37': 20.579999923706054,
+            '_38': 21.1299991607666,
+            '_39': 21.689998626708984,
+            '_40': 22.25,
+            '_41': 22.799999237060547,
+            '_42': 23.35999870300293,
+            '_43': 23.90999984741211,
+            '_44': 24.469999313354492,
+            '_45': 25.029998779296875,
+            '_46': 25.579999923706054,
+            '_47': 26.139999389648437,
+            '_48': 26.69999885559082,
+            '_49': 27.25,
+            '_50': 27.809999465942383,
+            '_51': 28.35999870300293,
+            '_52': 28.920000076293945,
+            '_53': 29.479999542236328,
+            '_54': 30.029998779296875,
+            '_55': 30.59000015258789,
+            '_56': 31.139999389648437,
+            '_57': 31.69999885559082,
+            '_58': 32.2599983215332,
+            '_59': 32.80999755859375,
+            '_60': 33.369998931884766,
+            '_61': 33.93000030517578,
+            '_62': 34.47999954223633,
+            '_63': 35.040000915527344,
+            '_64': 35.59000015258789
+        }
+    },
+    getFontWidth: function(fontName, fontHeight, typeStr) {
+        let rst = 12;
+        if (fontWidthMap[fontName]) {
+            rst = fontWidthMap[fontName][typeStr]['_' + fontHeight];
+        } else {
+            rst = fontWidthMap['宋体'][typeStr]['_' + fontHeight];
+        }
+        return rst;
+    },
+};
+
+module.exports = fontWidthMap;

+ 4 - 0
app/reports/rpt_component/jpc_ex.js

@@ -280,6 +280,8 @@ JpcExSrv.prototype.createNew = function() {
             if (pageMergeBorder) {
                 rstPage[JV.PROP_PAGE_MERGE_BORDER] = pageMergeBorder;
             }
+            rstPage[JV.PROP_SIGNATURE_CELLS] = [];
+            rstPage[JV.PROP_SIGNATURE_DATE_CELLS] = [];
             rst.items.push(rstPage);
             // 2.
             if (bands[JV.BAND_PROP_MERGE_BAND]) {
@@ -393,6 +395,8 @@ JpcExSrv.prototype.createNew = function() {
                     rst[JV.PROP_PAGE_MERGE_BORDER] = pageMergeBorder;
                 }
             }
+        } else {
+            console.log('no page result was found!');
         }
         return rst;
     };

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

@@ -11,10 +11,9 @@ const JpcDiscreteHelper = require('./helper/jpc_helper_discrete');
 const JpcTextHelper = require('./helper/jpc_helper_text');
 const JpcCommonOutputHelper = require('./helper/jpc_helper_common_output');
 const JpcAreaHelper = require('./helper/jpc_helper_area');
-const PDFKit = require('pdfkit');
-const fontUtil = require('../util/rpt_font_util');
 const fsUtil = require('../public/fsUtil');
 const strUtil = require('../public/stringUtil');
+const fontWidthMap = require('./helper/jpc_helper_font_width');
 
 
 const JpcFlowTabSrv = function() {};
@@ -358,7 +357,6 @@ JpcFlowTabSrv.prototype.createNew = function() {
             const reg2 = new RegExp('\r\n', 'g');
             const reg3 = new RegExp('\n', 'g');
             const reg4 = new RegExp('\r', 'g');
-            const doc = new PDFKit({ autoFirstPage: false });
             const fonts = defProperties.fonts;
             const fontCache = {};
             const private_get_font = function(fontKey) {
@@ -410,21 +408,19 @@ JpcFlowTabSrv.prototype.createNew = function() {
                         const values = value.split('|');
                         if (values.length > rst) rst = values.length;
                         const font = private_get_font(tab_field[JV.PROP_FONT]);
+                        let chkFontName = '宋体';
+                        let chkFontHeight = 12;
                         if (font) {
-                            const fontFile = __dirname.slice(0, __dirname.length - 14) + '/util/pdf_base_files/' + fontUtil.getActualFont(font[JV.FONT_PROPS[0]], (font[JV.FONT_PROPS[3]] === 'T'), (font[JV.FONT_PROPS[4]] === 'T')) + '.ttf';
-                            doc.font(fontFile);
-                            doc.fontSize(parseInt(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]]));
-                        } else {
-                            doc.font(__dirname.slice(0, __dirname.length - 14) + '/util/pdf_base_files/Smart.ttf');
-                            doc.fontSize(12);
+                            chkFontName = font[JV.FONT_PROPS[0]];
+                            chkFontHeight = font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]];
                         }
                         let hasSplitStr = false;
                         let splitStrArr = [];
                         let accAmt = 0;
-                        const chnW = doc.widthOfString('一');
-                        const otherW = doc.widthOfString('_');
+                        const chnW = fontWidthMap.getFontWidth(chkFontName, chkFontHeight, '宽');
+                        const otherW = fontWidthMap.getFontWidth(chkFontName, chkFontHeight, '窄');
                         for (let i = 0; i < values.length; i++) {
-                            const amt = JpcCommonHelper.getStringLinesInArea(area, values[i], doc, chnW, otherW);
+                            const amt = JpcCommonHelper.getStringLinesInArea(area, values[i], chnW, otherW);
                             accAmt += amt;
                             if (amt > 1) {
                                 hasSplitStr = true;
@@ -439,7 +435,7 @@ JpcFlowTabSrv.prototype.createNew = function() {
                                 if (splitStrArr.indexOf(i) < 0) {
                                     newValArr.push(values[i]);
                                 } else {
-                                    newValArr = newValArr.concat(JpcCommonHelper.splitString(area, values[i], doc, chnW, otherW));
+                                    newValArr = newValArr.concat(JpcCommonHelper.splitString(area, values[i], chnW, otherW));
                                 }
                             }
                             JpcFieldHelper.setValue(data_field, theRecIdx, newValArr.join('|'));

+ 19 - 15
app/reports/util/rpt_svg_util.js

@@ -4,10 +4,11 @@
  */
 
 let JV = require('../rpt_component/jpc_value_define');
-let pdf = require('pdfkit');
+// let pdf = require('pdfkit');
 let jpcCmnHelper = require('../rpt_component/helper/jpc_helper_common');
 let SCREEN_DPI = jpcCmnHelper.getScreenDPI();
-let fontUtil = require('./rpt_font_util');
+// let fontUtil = require('./rpt_font_util');
+let fontWidthMap = require('../rpt_component/helper/jpc_helper_font_width');
 
 module.exports = {
     exportSvgStr: function (pagesData, offsetX, offsetY) {
@@ -16,7 +17,7 @@ module.exports = {
             fonts = pagesData[JV.NODE_FONT_COLLECTION],
             controls = pagesData[JV.NODE_CONTROL_COLLECTION]
         ;
-        let pdf_doc = new pdf({autoFirstPage: false});
+        // let pdf_doc = new pdf({autoFirstPage: false});
         for (let idx = 0; idx < pagesData.items.length; idx++) {
             let page = pagesData.items[idx];
             let svgPageArr = [], pixelSize = getPixelSize(pagesData);
@@ -24,7 +25,7 @@ module.exports = {
             let adjustY = 0.5 * ((idx + 1) % 2);
             // let cnt = 0;
             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, adjustY, pdf_doc));
+                svgPageArr.push(buildCellSvg(cell, fonts, styles, controls, page[JV.PROP_PAGE_MERGE_BORDER], pagesData[JV.BAND_PROP_MERGE_BAND], offsetX, offsetY, adjustY));
                 // cnt++;
                 // console.log(cnt);
             }
@@ -55,7 +56,7 @@ function getActualBorderStyle(cell, styles, mergeBorderStyle, pageBorderArea, bo
     return rst;
 }
 
-function buildCellSvg(cell, fonts, styles, controls, pageMergeBorder, rptMergeBorder, offsetX, offsetY, adjustY, pdf_doc) {
+function buildCellSvg(cell, fonts, styles, controls, pageMergeBorder, rptMergeBorder, offsetX, offsetY, adjustY) {
     let rst = [];
     let style = styles[cell[JV.PROP_STYLE]];
     let mergeBandStyle = null;
@@ -101,18 +102,18 @@ function buildCellSvg(cell, fonts, styles, controls, pageMergeBorder, rptMergeBo
                 "' style='stroke:rgb(0,0,0);stroke-width:" + bottomBS[JV.PROP_LINE_WEIGHT] +"'/>")
         }
     }
-    buildText(rst, cell, font, controls[cell[JV.PROP_CONTROL]], offsetX, offsetY, adjustY, pdf_doc);
+    buildText(rst, cell, font, controls[cell[JV.PROP_CONTROL]], offsetX, offsetY, adjustY);
 
     return rst.join("");
 }
 
-function buildText(destRst, cell, font, control, offsetX, offsetY, adjustY, pdf_doc) {
+function buildText(destRst, cell, font, control, offsetX, offsetY, adjustY) {
     let orgFontHeight = parseInt(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]]);
     let fontWeight = (font[JV.FONT_PROPS[JV.FONT_PROP_IDX_BOLD]] === 'T')?"bold":"normal";
     let fontStyle = (font[JV.FONT_PROPS[JV.FONT_PROP_IDX_ITALIC]] === 'T')?"italic":"normal";
     let dftFontBold = font[JV.FONT_PROPS[3]];
     let dftFontItalic = font[JV.FONT_PROPS[4]];
-    let fontFile = __dirname + '/pdf_base_files/' + fontUtil.getActualFont(font[JV.FONT_PROPS[0]], (dftFontBold === 'T'), (dftFontItalic === 'T')) + '.ttf';
+    // let fontFile = __dirname + '/pdf_base_files/' + fontUtil.getActualFont(font[JV.FONT_PROPS[0]], (dftFontBold === 'T'), (dftFontItalic === 'T')) + '.ttf';
     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 + adjustY,
@@ -148,9 +149,10 @@ function buildText(destRst, cell, font, control, offsetX, offsetY, adjustY, pdf_
     let area = [cell[JV.PROP_AREA][JV.PROP_LEFT] + offsetX, cell[JV.PROP_AREA][JV.PROP_TOP] + offsetY, cell[JV.PROP_AREA][JV.PROP_RIGHT] + offsetX, cell[JV.PROP_AREA][JV.PROP_BOTTOM] + offsetY];
     let inner_draw_text = function (textValue) {
         let dftFontHeight = orgFontHeight;
-        pdf_doc.font(fontFile);
-        pdf_doc.fontSize(dftFontHeight);
-        let actLines = private_splitString(textValue, (area[JV.PROP_RIGHT] - area[JV.PROP_LEFT]), pdf_doc);
+        // pdf_doc.font(fontFile);
+        // pdf_doc.fontSize(dftFontHeight);
+        // let actLines = private_splitString(textValue, (area[JV.PROP_RIGHT] - area[JV.PROP_LEFT]), pdf_doc);
+        let actLines = private_splitStringEx(textValue, (area[JV.PROP_RIGHT] - area[JV.PROP_LEFT]), font[JV.FONT_PROPS[0]], dftFontHeight);
         function inner_build_text(innerTxt, innerArea) {
             let innerDftFontHeight = (dftFontHeight * 3 / 4); //SVG的字体与canvas的字体大小的切换, 不用考虑取整
             if (control) {
@@ -177,10 +179,11 @@ function buildText(destRst, cell, font, control, offsetX, offsetY, adjustY, pdf_
             while (true) {
                 if (dftFontHeight > 6) {
                     dftFontHeight--;
-                    pdf_doc.fontSize(dftFontHeight);
+                    // pdf_doc.fontSize(dftFontHeight);
                     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;
-                    actLines = private_splitString(textValue, (area[JV.PROP_RIGHT] - area[JV.PROP_LEFT]), pdf_doc);
+                    // actLines = private_splitString(textValue, (area[JV.PROP_RIGHT] - area[JV.PROP_LEFT]), pdf_doc);
+                    let actLines = private_splitStringEx(textValue, (area[JV.PROP_RIGHT] - area[JV.PROP_LEFT]), font[JV.FONT_PROPS[0]], dftFontHeight);
                     if (lines >= actLines.length) {
                         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')) {
@@ -250,12 +253,13 @@ function buildText(destRst, cell, font, control, offsetX, offsetY, adjustY, pdf_
     //*/
 }
 
-function private_splitString(strVal, areaWidth, doc) {
+function private_splitStringEx(strVal, areaWidth, chkFontName, chkFontHeight) {
     let rst = [];
     if (strVal) {
         let preSIdx = 0, txtWidth = 0;
         let currentW = 0;
-        let chnW = doc.widthOfString('一'), otherW = doc.widthOfString('_');
+        // let chnW = doc.widthOfString('一'), otherW = doc.widthOfString('_');
+        let chnW = fontWidthMap.getFontWidth(chkFontName, chkFontHeight, '宽'), otherW = fontWidthMap.getFontWidth(chkFontName, chkFontHeight, '窄');
         for (let sIdx = 0; sIdx < strVal.length; sIdx++) {
             currentW = (strVal.charCodeAt(sIdx) > 127)?chnW:otherW;
             txtWidth += currentW;

+ 3 - 0
app/router.js

@@ -255,4 +255,7 @@ module.exports = app => {
 
     // 查询
     app.post('/search/user', sessionAuth, 'projectController.searchAccount');
+
+    // 示例
+    app.get('/template/:file', sessionAuth, 'templateController.download');
 };

+ 2 - 1
app/view/ledger/explode_modal.ejs

@@ -401,4 +401,5 @@
     </div>
 </div>
 <% } %>
-<% include ../shares/merge_peg_modal.ejs %>
+<% include ../shares/merge_peg_modal.ejs %>
+<% include ../shares/import_excel_modal.ejs %>

+ 100 - 0
app/view/shares/import_excel_modal.ejs

@@ -0,0 +1,100 @@
+<!--导入清单Excel-->
+<div class="modal fade" id="import-excel" data-backdrop="static" enctype="multipart/form-data">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">导入</h5>
+            </div>
+            <div class="modal-body">
+                <p id="import-template">请上传符合 <b id="import-type-hint">0号台帐</b> 格式的 .xls和.xlsx 文件,<a id="download-template" href="/tender/<%- ctx.tender.id %>/ledger/download/导入分项清单EXCEL格式.xls">下载示例</a>。</p>
+                <div class="form-group">
+                    <label for="exampleFormControlFile1">选择文件</label><i class="fa fa-spinner fa-pulse fa-lg fa-fw text-primary" id="select-excel-loading" style="display: none;"></i>
+                    <input type="file" class="form-control-file" id="import-excel-file" accept="*.xls">
+                </div>
+                <div id="excel-sheets" style="display: none;">
+                    <hr></hr>
+                    <h6>选择导入的工作表</h6>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary btn-sm" id="import-excel-ok">确认上传</button>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const importExcel = (function () {
+        // 选择excel文件后,加载全部sheet
+        $('#import-excel-file').change(function () {
+            if (this.files.length === 0) {
+                $('#excel-sheets').html('').hide();
+                return;
+            }
+            $('#excel-sheets').hide();
+            try {
+                $('#select-excel-loading').show();
+                xlsxUtils.import(this.files[0], (excelData) => {
+                    if (excelData.SheetNames.length > 0) {
+                        const html = [];
+                        html.push('<hr></hr>');
+                        html.push('<h6>选择导入的工作表</h6>');
+                        for (const iName in excelData.SheetNames) {
+                            const name = excelData.SheetNames[iName];
+                            html.push('<div class="card p-2 mb-2">');
+                            html.push('<div class="form-check">');
+                            html.push('<input class="form-check-input" type="radio" name="sheetName" id="excel-sheet' + iName + '"', (iName == 0 ? ' checked=""' : ''), ' value="' + name + '"',  '>');
+                            html.push('<label class="form-check-label" for="excel-sheet' + iName + '">', name, '</label>');
+                            html.push('</div>');
+                            html.push('</div>');
+                        }
+                        $('#excel-sheets').html(html.join('')).show();
+                        $('.mb-2.p-2').mouseenter(function () {
+                            $(this).addClass('border-primary');
+                        });
+                        $('.mb-2.p-2').mouseleave(function () {
+                            $(this).removeClass('border-primary');
+                        })
+                    } else {
+                        toastr.info('选择的Excel无有效数据,请重新选择');
+                        $('#excel-sheets').hide();
+                    }
+                    $('#select-excel-loading').hide();
+                });
+            } catch(err) {
+                $('#select-excel-loading').hide();
+                toastr.error('加载excel异常,请刷新当前页面');
+                $('#excel-sheets').hide();
+            }
+        });
+        // 清除上一次数据
+        $('#upload-ledger').bind('hidden.bs.modal', function () {
+            $('#import-excel-file').val('');
+            $('#excel-sheets').html('');
+        });
+
+        const doImport = function (setting) {
+            // 上传excel内容,并导入
+            $('#import-excel-ok').click(function () {
+                const sheetName = $('input[name=sheetName]:checked').val();
+                if (sheetName) {
+                    const sheet = {
+                        rows: xlsxUtils.getSheetByName(sheetName, {header: 1}),
+                        merge: xlsxUtils._wb.Sheets[sheetName]["!merges"]
+                    };
+                    setting.callback(sheet);
+                    $('#import-excel').modal('hide');
+                }
+            });
+            if (setting.template) {
+                $('#import-template').show();
+                $('#import-type-hint').html(setting.template.hint);
+                $('#download-template').attr('href', setting.template.url);
+            } else {
+                $('#import-template').hide();
+            }
+            $('#import-excel').modal('show');
+        }
+        return { doImport };
+    })();
+</script>

+ 1 - 1
app/view/shares/merge_peg_modal.ejs

@@ -9,7 +9,7 @@
                 <div class="mb-2" style="height: 25px; line-height: 25px">
                     <div class="d-inline-block mr-3">
                         <div class="form-check">
-                            <input class="form-check-input" type="checkbox" value="" id="mp-with-pos">
+                            <input class="form-check-input" type="checkbox" valu e="" id="mp-with-pos">
                             <label class="form-check-label" for="defaultCheck1">
                                 合并位置
                             </label>