Browse Source

解决冲突

caiaolin 8 years ago
parent
commit
3456686844

+ 3 - 3
Dockerfile

@@ -4,10 +4,10 @@ COPY . ConstructionOperation
 
 WORKDIR ConstructionOperation
 
-RUN cnpm install 
+RUN mkdir tmp
+
+RUN cnpm install
 
 EXPOSE 6080
 
 ENTRYPOINT babel-node operation.js
-
-

+ 49 - 0
modules/reports/util/pdf/rpt_pdf_consts.js

@@ -0,0 +1,49 @@
+/**
+ * Created by zhang on 2017/8/14.
+ */
+module.exports={
+    JV:{
+        NODE_MAIN_INFO: "主信息",
+        NODE_PAGE_INFO: "打印页面_信息",
+        NODE_MARGINS: "页边距",
+
+        NODE_FONT_COLLECTION: "font_collection",
+        NODE_STYLE_COLLECTION: "style_collection",
+        NODE_CONTROL_COLLECTION: "control_collection",
+
+        BAND_PROP_MERGE_BAND: "MergeBand",
+
+        PROP_NAME: "Name",
+        PROP_VALUE: "Value",
+        PROP_FONT: "font",
+        PROP_CONTROL: "control",
+        PROP_STYLE: "style",
+        PROP_AREA: "area",
+        PROP_ID: "ID",
+        PROP_LEFT: "Left",
+        PROP_RIGHT: "Right",
+        PROP_TOP: "Top",
+        PROP_BOTTOM: "Bottom",
+
+        IDX_LEFT: 0,
+        IDX_TOP: 1,
+        IDX_RIGHT: 2,
+        IDX_BOTTOM: 3,
+
+        CONTROL_PROPS: ["Shrink", "ShowZero", "Horizon", "Vertical", "Wrap"],
+        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"],
+
+        OUTPUT_OFFSET: [2,1,2,3],
+        OFFSET_IDX_LEFT: 0,
+        OFFSET_IDX_RIGHT: 1,
+        OFFSET_IDX_TOP: 2,
+        OFFSET_IDX_BOTTOM: 3,
+
+        VERTICAL_ANGLE: "90",
+        ANTI_VERTICAL_ANGLE: "-90"
+    }
+}

+ 198 - 0
modules/reports/util/pdf/rpt_pdf_util.js

@@ -0,0 +1,198 @@
+/**
+ * Created by zhang on 2017/8/14.
+ */
+
+const prf_cons = require('./rpt_pdf_consts');
+var pdf = require('pdfkit');
+var fs = require('fs');
+let reportO = require('./reportOj');
+
+let JV = prf_cons.JV;
+export_pdf_file();
+function export_pdf_file (data) {
+    let offsetX= 10;
+    let offsetY=10;
+    var doc = new pdf({autoFirstPage: false});
+    doc.pipe(fs.createWriteStream('导出.pdf'));
+    let pageObj = reportO.reportObj;
+   // doc.rect(5,5,1190,890).lineWidth(1).strokeColor('black').stroke();//边框
+
+    if (pageObj && pageObj.items.length > 0 ) {
+        for(let i=0;i<pageObj.items.length;i++){
+            doc.addPage({size:[1200,900]});
+            var page = pageObj.items[i],
+                fonts = pageObj[JV.NODE_FONT_COLLECTION],
+                styles = pageObj[JV.NODE_STYLE_COLLECTION],
+                controls = pageObj[JV.NODE_CONTROL_COLLECTION],
+                mergedBand = pageObj[JV.BAND_PROP_MERGE_BAND];
+
+            for (var j = 0; j < page.cells.length; j++) {
+                var cell = page.cells[j];
+                private_drawCell(cell, fonts, styles, controls, mergedBand);
+            }
+        }
+    }
+    doc.end();
+
+
+    function private_drawCell(cell, fonts, styles, controls, mergedBand) {
+        doc.save();
+        //doc.translate(0.5,0.5);
+        var style = styles[cell[JV.PROP_STYLE]];
+        if (style) {
+            private_drawLine(cell, doc, style, JV.PROP_TOP, [JV.PROP_LEFT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_TOP], mergedBand, styles);
+            private_drawLine(cell, doc, style, JV.PROP_RIGHT, [JV.PROP_RIGHT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_BOTTOM], mergedBand, styles);
+            private_drawLine(cell, doc, style, JV.PROP_BOTTOM, [JV.PROP_RIGHT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_BOTTOM], mergedBand, styles);
+            private_drawLine(cell, doc, style, JV.PROP_LEFT, [JV.PROP_LEFT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_TOP], mergedBand, styles);
+        }
+        private_drawCellText(cell, fonts, controls);
+        doc.restore();
+
+    }
+
+    function private_drawLine(cell, doc, style, styleBorderDest, startP, destP, mergedBand, styles) {
+        //doc.beginPath();
+        var destStyle = style;
+        if (mergedBand) {
+            if (mergedBand[styleBorderDest] == cell[JV.PROP_AREA][styleBorderDest]) {
+                destStyle = styles[mergedBand[JV.PROP_STYLE][JV.PROP_ID]];
+            }
+        }
+        doc.moveTo(cell[JV.PROP_AREA][startP[0]] + offsetX, cell[JV.PROP_AREA][startP[1]] + offsetY);
+        if (destStyle[styleBorderDest] && destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT] != 0) {
+            doc.lineWidth(1.0 * destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT]);
+            doc.lineTo(cell[JV.PROP_AREA][destP[0]] + offsetX, cell[JV.PROP_AREA][destP[1]] + offsetY);
+            doc.strokeColor(destStyle[styleBorderDest][JV.PROP_COLOR]);
+        }
+        doc.stroke();
+    }
+    function private_drawCellText(cell, fonts, controls) {
+        if (cell[JV.PROP_VALUE]) {
+            var values = ("" + cell[JV.PROP_VALUE]).split('|');
+            var font = fonts[cell[JV.PROP_FONT]];
+            var control = controls[cell[JV.PROP_CONTROL]];
+            var height = cell[JV.PROP_AREA][JV.PROP_BOTTOM] - cell[JV.PROP_AREA][JV.PROP_TOP];
+            var 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];
+            for (var i = 0; i < values.length; i++) {
+                area[JV.IDX_TOP] = cell[JV.PROP_AREA][JV.PROP_TOP] + i * (height / values.length) + offsetY;
+                area[JV.IDX_BOTTOM] = cell[JV.PROP_AREA][JV.PROP_TOP] + (i + 1) * (height / values.length) + offsetY;
+                private_drawText(values[i], area, font, control);
+            }
+        }
+    }
+
+    function private_drawText(val, area, font, control) {
+        var dftFontHeight = 12;
+        var output = [];
+        if (font) {
+            dftFontHeight = 1 * font[JV.FONT_PROPS[1]];
+            var dftOthers = "";
+            var dftFontBold = font[JV.FONT_PROPS[3]];
+            if (dftFontBold && dftFontBold == 'T') {
+                doc.font('simsunB.ttf');
+            }else {
+                doc.font('Smart.ttf');
+            }
+         /*   var dftFontItalic = font[JV.FONT_PROPS[4]]; 没有找到中文斜体的字库,暂不支持
+            if (dftFontItalic && dftFontItalic == 'T') {
+                dftOthers = dftOthers + "italic ";
+            }*/
+           // ctx.font = dftOthers + dftFontHeight + "px " + font[JV.PROP_NAME];
+            doc.fontSize(dftFontHeight);
+        }
+        var 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);
+        }
+        var w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+        if (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;
+                }
+            }
+        }
+
+        var rotateOptions;
+        if (font.FontAngle != "0") {
+            if (control){
+                rotateOptions=private_setupAreaRotateOption(area,w,control.Vertical,dftFontHeight, output);
+            }else {
+                rotateOptions=private_setupAreaRotateOption(area,w,"bottom",dftFontHeight, output);
+            }
+            doc.rotate(font.FontAngle,rotateOptions);
+        }
+        doc.text(val,output[0], output[1],options);
+        doc.restore();
+    }
+
+    function private_setupAreaH(area, type, fontAngle, dftFontHeight, outputPoint,options) {
+        var lType = type;
+        if (type != "left" && type != "right" && type != "center") lType = "left";
+        options.align=lType;
+        outputPoint[0]=1 * area[JV.IDX_LEFT]+ JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+    }
+
+    function private_setupAreaV(area, type, fontAngle, dftFontHeight, outputPoint) {
+        var lType = type;
+        if (type != "top" && type != "bottom" && type != "center") lType = "top";
+         switch (lType) {
+             case "top":
+                 outputPoint[1] = 1 * area[JV.IDX_TOP] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                 break;
+             case "bottom":
+                 outputPoint[1] = 1 * area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM]-dftFontHeight;
+                 break;
+             case "center":
+                 outputPoint[1] = 1 * area[JV.IDX_TOP] + (1 * area[JV.IDX_BOTTOM]-1 * area[JV.IDX_TOP]- dftFontHeight) / 2;
+                 break;
+         }
+    }
+
+    function private_setupAreaRotateOption(area,w, type="top",dftFontHeight,outputPoint){
+        var x = (area[JV.IDX_RIGHT] - area[JV.IDX_LEFT])/2+area[JV.IDX_LEFT];
+        var y =(area[JV.IDX_BOTTOM] - area[JV.IDX_TOP])/2+ area[JV.IDX_TOP];
+        var rotateOptions = {origin:[x,y]};
+        var h = area[JV.IDX_RIGHT] - area[JV.IDX_LEFT];
+        outputPoint[0]=x-w/2+JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
+        var lType = type;
+        switch (lType) {
+            case "top":
+                outputPoint[1] = y- h/2+ JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
+                break;
+            case "bottom":
+                outputPoint[1] = y+ h/2-JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM]-dftFontHeight;
+                break;
+            case "center":
+                outputPoint[1] = y+dftFontHeight/2;
+                break;
+        }
+        return rotateOptions;
+    }
+
+}
+
+
+
+
+
+
+
+
+

+ 1 - 0
modules/users/controllers/compilation_controller.js

@@ -147,6 +147,7 @@ class CompilationController extends BaseController {
             billList: JSON.stringify(billList),
             rationList: JSON.stringify(rationList),
             gljList: JSON.stringify(gljList),
+            mainTreeCol: JSON.stringify(valuationData.main_tree_col),
             engineeringList: EngineeringList,
             selectedCompilation: selectedCompilation,
             valuationData: valuationData,

+ 1 - 0
modules/users/models/compilation_model.js

@@ -125,6 +125,7 @@ class CompilationModel extends BaseModel {
         updateData[sectionString + ".$.glj_lib"] = data.glj_lib;
         updateData[sectionString + ".$.name"] = data.name;
         updateData[sectionString + ".$.engineering"] = data.engineering;
+        updateData[sectionString + ".$.main_tree_col"] = JSON.parse(data.main_tree_col);
 
         let result = await this.db.update(condition, updateData);
 

+ 11 - 0
modules/users/models/schemas/compilation.js

@@ -40,6 +40,17 @@ let childrenSchema = new Schema({
     // 类型
     type: {
         type: Number
+    },
+    // 列设置
+    main_tree_col: {
+        type: Schema.Types.Mixed,
+        default: {
+            "emptyRows":3,
+            "headRows":0,
+            "treeCol": 0,
+            "headRowHeight":[],
+            "cols":[]
+        }
     }
 });
 let modelSchema = {

+ 1 - 1
operation.js

@@ -1,7 +1,7 @@
 let express = require('express');
 
 let config = require("./config/config.js");
-config.setToQaDb();
+config.setToLocalDb();
 let dbm = require("./config/db/db_manager");
 
 let path = require('path');

+ 22 - 18
public/web/sheet/sheet_data_helper.js

@@ -40,25 +40,29 @@ var SheetDataHelper = {
         return spread;
     },
     loadSheetHeader: function (setting, sheet) {
-        sheet.setColumnCount(setting.cols.length);
         sheet.setRowCount(setting.headRows, GC.Spread.Sheets.SheetArea.colHeader);
-        setting.headRowHeight.forEach(function (rowHeight, index) {
-            sheet.setRowHeight(index, rowHeight, GC.Spread.Sheets.SheetArea.colHeader);
-        })
-        setting.cols.forEach(function (col, index) {
-            var i, iRow = 0, cell;
-            for (i = 0; i < col.head.spanCols.length; i++) {
-                if (col.head.spanCols[i] !== 0) {
-                    cell = sheet.getCell(iRow, index, GC.Spread.Sheets.SheetArea.colHeader);
-                    cell.value(col.head.titleNames[i]).font(col.head.font).hAlign(col.head.hAlign[i]).vAlign(col.head.vAlign[i]);
-                }
-                if (col.head.spanCols[i] > 1 || col.head.spanRows[i] > 1) {
-                    sheet.addSpan(iRow, index, col.head.spanRows[i], col.head.spanCols[i], GC.Spread.Sheets.SheetArea.colHeader);
-                }
-                iRow += col.head.spanRows[i];
-            };
-            sheet.setColumnWidth(index, col.width);
-        });
+        if (setting.headRowHeight) {
+            setting.headRowHeight.forEach(function (rowHeight, index) {
+                sheet.setRowHeight(index, rowHeight, GC.Spread.Sheets.SheetArea.colHeader);
+            });
+        }
+        if (setting.cols) {
+            sheet.setColumnCount(setting.cols.length);
+            setting.cols.forEach(function (col, index) {
+                var i, iRow = 0, cell;
+                for (i = 0; i < col.head.spanCols.length; i++) {
+                    if (col.head.spanCols[i] !== 0) {
+                        cell = sheet.getCell(iRow, index, GC.Spread.Sheets.SheetArea.colHeader);
+                        cell.value(col.head.titleNames[i]).font(col.head.font).hAlign(col.head.hAlign[i]).vAlign(col.head.vAlign[i]);
+                    }
+                    if (col.head.spanCols[i] > 1 || col.head.spanRows[i] > 1) {
+                        sheet.addSpan(iRow, index, col.head.spanRows[i], col.head.spanCols[i], GC.Spread.Sheets.SheetArea.colHeader);
+                    }
+                    iRow += col.head.spanRows[i];
+                };
+                sheet.setColumnWidth(index, col.width);
+            });
+        }
     },
     protectdSheet: function (sheet) {
         var option = {

+ 323 - 0
web/users/js/col_setting.js

@@ -0,0 +1,323 @@
+/**
+ * Created by Mai on 2017/8/14.
+ */
+
+let ColSettingObj = {
+    colSetting: null,
+    DEFAULT_TITLE_STYLE: null,
+    DEFAULT_DATA_STYLE: null,
+    cellType: {
+        getText: null,
+        readOnly: null
+    },
+    Rows: {data: 0, filedName: 0, getText: 1, width: 2, readOnly: 3},
+    columnValueChanged: function (e, info) {
+        let that = ColSettingObj;
+        info.colList.forEach(function (iCol) {
+            info.sheet.setValue(that.colSetting.headRows + that.Rows.width, iCol, info.sheet.getColumnWidth(iCol), GC.Spread.Sheets.SheetArea.viewport);
+        });
+    },
+    valueChanged: function (e, info) {
+        let that = ColSettingObj;
+        if (info.row === that.colSetting.headRows + that.Rows.width) {
+            info.sheet.setColumnWidth(info.col, info.newValue, GC.Spread.Sheets.SheetArea.viewport);
+        }
+    },
+    selectionChanged: function (e, info) {
+        let that = ColSettingObj, sel = info.newSelections[0];
+        if (sel.row <= that.colSetting.headRows) {
+            $('.btn-toolbar').removeClass('disabled');
+            $('#font').val(info.sheet.getCell(sel.row, sel.col, GC.Spread.Sheets.SheetArea.viewport).font());
+        } else {
+            $('.btn-toolbar').addClass('disabled');
+        }
+    },
+    getCellStyle: function (font, hAlign, vAlign) {
+        var style = new GC.Spread.Sheets.Style();
+        style.font = font;
+        style.hAlign = hAlign;
+        style.vAlign = vAlign;
+        style.wordWrap = true;
+        return style;
+    },
+    initCellType: function () {
+        this.cellType.readOnly = new GC.Spread.Sheets.CellTypes.ComboBox();
+        this.cellType.readOnly.items([true, false,
+            'readOnly.bills', 'readOnly.ration', 'readOnly.volumePrice',
+            'readOnly.non_bills', 'readOnly.non_ration', 'readOnly.non_volumePrice',
+            'readOnly.billsParent', 'readOnly.forCalcBase'
+        ]);
+
+        this.cellType.getText = new GC.Spread.Sheets.CellTypes.ComboBox();
+        this.cellType.getText.items(['getText.type']);
+    },
+    initSheet: function (sheet, setting) {
+        sheet.setColumnCount(2, GC.Spread.Sheets.SheetArea.rowHeader);
+        sheet.setColumnWidth(0, 80, GC.Spread.Sheets.SheetArea.rowHeader);
+        sheet.setColumnWidth(1, 70, GC.Spread.Sheets.SheetArea.rowHeader);
+        sheet.setRowCount(setting.headRows + this.Rows.readOnly + 1);
+
+        sheet.setText(setting.headRows + this.Rows.data, 0, 'Data', GC.Spread.Sheets.SheetArea.rowHeader);
+        sheet.setStyle(setting.headRows + this.Rows.data, -1, this.DEFAULT_DATA_STYLE);
+        sheet.addSpan(setting.headRows + this.Rows.data, 0, 2, 1, GC.Spread.Sheets.SheetArea.rowHeader);
+
+        sheet.setText(setting.headRows + this.Rows.filedName, 1, 'FieldName', GC.Spread.Sheets.SheetArea.rowHeader);
+        sheet.setText(setting.headRows + this.Rows.getText, 1, 'getText', GC.Spread.Sheets.SheetArea.rowHeader);
+
+        sheet.setText(setting.headRows + this.Rows.width, 0, 'width', GC.Spread.Sheets.SheetArea.rowHeader);
+        sheet.addSpan(setting.headRows + this.Rows.width, 0, 1, 2, GC.Spread.Sheets.SheetArea.rowHeader);
+
+        sheet.setText(setting.headRows + this.Rows.readOnly, 0, 'ReadOnly', GC.Spread.Sheets.SheetArea.rowHeader);
+        sheet.addSpan(setting.headRows + this.Rows.readOnly, 0, 1, 2, GC.Spread.Sheets.SheetArea.rowHeader);
+    },
+    initColSetting: function (setting) {
+        this.DEFAULT_TITLE_STYLE = this.getCellStyle('Arial', GC.Spread.Sheets.HorizontalAlign.center, GC.Spread.Sheets.VerticalAlign.center);
+        this.DEFAULT_DATA_STYLE = this.getCellStyle('Arial', GC.Spread.Sheets.HorizontalAlign.left, GC.Spread.Sheets.VerticalAlign.center);
+        this.initCellType();
+
+        $('#empty-rows').val(setting.emptyRows);
+        $('#col-count').val(setting.cols ? setting.cols.length : 0);
+        $('#header-row-count').val(setting.headRows);
+
+        colEditSpread = new GC.Spread.Sheets.Workbook($('#colEditSpread')[0], {sheetCount: 1});
+        colEditSpread.options.tabStripVisible = false;
+        colEditSpread.bind(GC.Spread.Sheets.Events.ColumnWidthChanged, this.columnValueChanged);
+        colEditSpread.bind(GC.Spread.Sheets.Events.ValueChanged, this.valueChanged);
+        colEditSpread.bind(GC.Spread.Sheets.Events.SelectionChanged, this.selectionChanged);
+
+        this.initSheet(colEditSpread.getActiveSheet(), setting);
+        this.setColCount(this.colSetting.cols.length);
+        this.setHeaderRowCount(this.colSetting.headRows);
+
+        if (setting.cols) {
+            let sheet = colEditSpread.getActiveSheet(), iRow;
+            for (let iCol = 0; iCol < setting.cols.length; iCol++) {
+                let col = setting.cols[iCol], iRow = 0;
+                // header
+                for (let i in col.head.spanCols) {
+                    if (col.head.spanCols[i] !== 0) {
+                        let cell = sheet.getCell(iRow, iCol, GC.Spread.Sheets.SheetArea.viewport);
+                        cell.value(col.head.titleNames[i]).font(col.head.font[i]).hAlign(col.head.hAlign[i]).vAlign(col.head.vAlign[i]);
+                    }
+                    if (col.head.spanCols[i] > 1 || col.head.spanRows[i] > 1) {
+                        sheet.addSpan(iRow, iCol, col.head.spanRows[i], col.head.spanCols[i], GC.Spread.Sheets.SheetArea.viewport);
+                    }
+                    iRow += col.head.spanRows[i];
+                };
+                // data
+                // field
+                let cell = sheet.getCell(this.colSetting.headRows + this.Rows.data, iCol, GC.Spread.Sheets.SheetArea.viewport);
+                cell.value(col.data.field).font(col.data.font).hAlign(col.head.hAlign).vAlign(col.data.vAlign);
+                // getText
+                cell = sheet.getCell(this.colSetting.headRows + this.Rows.getText, iCol, GC.Spread.Sheets.SheetArea.viewport);
+                cell.cellType(this.cellType.getText).value(col.data.getText).hAlign(GC.Spread.Sheets.HorizontalAlign.right);
+                // 列宽
+                sheet.setColumnWidth(iCol, col.width);
+                sheet.setValue(this.colSetting.headRows + this.Rows.width, iCol, sheet.getColumnWidth(iCol), GC.Spread.Sheets.SheetArea.viewport);
+                // readonly
+                cell = sheet.getCell(this.colSetting.headRows + this.Rows.readOnly, iCol, GC.Spread.Sheets.SheetArea.viewport);
+                cell.cellType(this.cellType.readOnly).value(col.readOnly).hAlign(GC.Spread.Sheets.HorizontalAlign.right);
+            }
+        }
+        let cell = info.sheet.getCell(0, 0, GC.Spread.Sheets.SheetArea.viewport);
+        if (cell) {
+            $('#font').val(cell.font());
+        }
+    },
+    setColCount: function (count) {
+        let sheet = colEditSpread.getActiveSheet();
+        sheet.setColumnCount(count);
+        for (let iCol = 0; iCol < sheet.getColumnCount(); iCol++) {
+            sheet.setValue(this.colSetting.headRows + this.Rows.width, iCol, sheet.getColumnWidth(iCol), GC.Spread.Sheets.SheetArea.viewport);
+            sheet.getCell(this.colSetting.headRows + this.Rows.readOnly, iCol, GC.Spread.Sheets.SheetArea.viewport).cellType(this.cellType.readOnly);
+            sheet.setValue(this.colSetting.headRows + this.Rows.readOnly, iCol, false, GC.Spread.Sheets.SheetArea.viewport);
+        }
+    },
+    setHeaderRowCount: function (count) {
+        let sheet = colEditSpread.getActiveSheet(), orgCount = this.colSetting.headRows;
+        if (count < orgCount) {
+            sheet.deleteRows(count, orgCount - count);
+        } else if (count > orgCount) {
+            sheet.addRows(orgCount, count - orgCount);
+            sheet.addSpan(0, 0, count, 1, GC.Spread.Sheets.SheetArea.rowHeader);
+            for (let iRow = orgCount; iRow < count; iRow++) {
+                sheet.setStyle(iRow, -1, this.DEFAULT_TITLE_STYLE);
+            }
+        }
+    },
+    getActualCellRange: function (cellRange, rowCount, columnCount) {
+        if (cellRange.row == -1 && cellRange.col == -1) {
+            return new spreadNS.Range(0, 0, rowCount, columnCount);
+        }
+        else if (cellRange.row == -1) {
+            return new spreadNS.Range(0, cellRange.col, rowCount, cellRange.colCount);
+        }
+        else if (cellRange.col == -1) {
+            return new spreadNS.Range(cellRange.row, 0, cellRange.rowCount, columnCount);
+        }
+
+        return cellRange;
+    },
+    // 批量操作Spread选择的单元格
+    controlSelectCells: function (spread, control) {
+        let sheet = colEditSpread.getActiveSheet();
+        let sel = sheet.getSelections(), i, j;
+
+        sel = this.getActualCellRange(sel[sel.length - 1], sheet.getRowCount(), sheet.getColumnCount());
+        for (i = 0; i < sel.rowCount; i++) {
+            for (j = 0; j < sel.colCount; j++) {
+                control(sheet.getCell(sel.row + i, sel.col + j));
+            }
+        }
+    },
+    generateColSetting: function () {
+        let setting = {}, sheet = colEditSpread.getActiveSheet();
+        setting.emptyRows = parseInt($('#empty-rows').val());
+        setting.headRows = parseInt($('#header-row-count').val());
+        if ($('#is-tree').checked) {
+            setting.treeCol = parseInt($('#treeCol').val());
+        }
+        setting.headRowHeight = [];
+        for (let iRow = 0; iRow < setting.headRows; iRow++) {
+            setting.headRowHeight.push(sheet.getRowHeight(iRow, GC.Spread.Sheets.SheetArea.viewport));
+        };
+        setting.cols = [];
+        for (let iCol = 0; iCol < sheet.getColumnCount(); iCol++) {
+            let col = {};
+            col.width = sheet.getColumnWidth(iCol);
+            col.readOnly = sheet.getValue(setting.headRows + this.Rows.readOnly, iCol) || false;
+
+            col.head = {};
+            col.head.titleNames = [];
+            col.head.spanCols = [];
+            col.head.spanRows = [];
+            col.head.vAlign = [];
+            col.head.hAlign = [];
+            col.head.font = [];
+            for (let iRow = 0; iRow < setting.headRows; iRow++) {
+                let cell = sheet.getCell(iRow, iCol);
+                col.head.titleNames.push(cell.text());
+                let span = sheet.getSpan(iRow, iCol);
+                if (span) {
+                    if (span.col === iCol && span.row === iRow) {
+                        col.head.spanCols.push(span.colCount);
+                        col.head.spanRows.push(span.rowCount);
+                    } else {
+                        col.head.spanCols.push(0);
+                        col.head.spanRows.push(1);
+                    }
+                } else {
+                    col.head.spanCols.push(1);
+                    col.head.spanRows.push(1);
+                }
+                col.head.vAlign.push(cell.vAlign());
+                col.head.hAlign.push(cell.hAlign());
+                col.head.font.push(cell.font());
+            }
+
+            col.data = {};
+            let cell = sheet.getCell(setting.headRows, iCol);
+            col.data.field = cell.text();
+            col.data.vAlign = cell.vAlign();
+            col.data.hAlign = cell.hAlign();
+            col.data.font = cell.font();
+            // getText
+            cell = sheet.getCell(setting.headRows + this.Rows.getText, iCol);
+            if (cell.text() !== '') {
+                col.data.getText = cell.text();
+            }
+            setting.cols.push(col);
+        }
+        return setting;
+    }
+};
+
+$('#set-column').on('shown.bs.modal', function () {
+    if (!colEditSpread) {
+        ColSettingObj.colSetting = JSON.parse(mainTreeCol);
+        ColSettingObj.initColSetting(ColSettingObj.colSetting);
+    }
+});
+$('#col-count').change(function () {
+    ColSettingObj.setColCount(parseInt($(this).val()));
+});
+$('#header-row-count').change(function () {
+    ColSettingObj.setHeaderRowCount(parseInt($(this).val()));
+    ColSettingObj.colSetting.headRows = parseInt($(this).val());
+});
+$('#merge').click(function () {
+    let sheet = colEditSpread.getActiveSheet();
+    let sel = sheet.getSelections();
+
+    if (sel.length > 0) {
+        sel = ColSettingObj.getActualCellRange(sel[sel.length - 1], sheet.getRowCount(), sheet.getColumnCount());
+        if (sel.row + sel.rowCount > ColSettingObj.colSetting.headRows) {
+            alert('仅HeaderTitle部分可以合并单元格');
+        } else {
+            sheet.addSpan(sel.row, sel.col, sel.rowCount, sel.colCount);
+            //sheet.setTag(sel.row, sel.col, 1);
+        }
+    }
+});
+$('#unmerge').click(function () {
+    let sheet = colEditSpread.getActiveSheet();
+    let sel = sheet.getSelections();
+
+    if (sel.length > 0) {
+        sel = ColSettingObj.getActualCellRange(sel[sel.length - 1], sheet.getRowCount(), sheet.getColumnCount());
+        sheet.suspendPaint();
+        for (var i = 0; i < sel.rowCount; i++) {
+            for (var j = 0; j < sel.colCount; j++) {
+                sheet.removeSpan(i + sel.row, j + sel.col);
+            }
+        }
+        sheet.resumePaint();
+    }
+});
+$('#save-col-setting').click(function () {
+    ColSettingObj.colSetting = ColSettingObj.generateColSetting();
+    mainTreeCol = JSON.stringify(ColSettingObj.colSetting);
+    $('input:hidden[name="main_tree_col"]').val(mainTreeCol);
+    $('#set-column').modal('hide');
+    SheetDataHelper.loadSheetHeader(ColSettingObj.colSetting, colSpread.getActiveSheet());
+});
+
+$('#h-left').click(function () {
+    ColSettingObj.controlSelectCells(colEditSpread, function (cell) {
+        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.left);
+    });
+});
+$('#h-center').click(function () {
+    ColSettingObj.controlSelectCells(colEditSpread, function (cell) {
+        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
+    });
+});
+
+$('#h-right').click(function () {
+    ColSettingObj.controlSelectCells(colEditSpread, function (cell) {
+        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.right);
+    });
+});
+
+$('#v-top').click(function () {
+    ColSettingObj.controlSelectCells(colEditSpread, function (cell) {
+        cell.vAlign(GC.Spread.Sheets.VerticalAlign.top);
+    });
+});
+$('#v-center').click(function () {
+    ColSettingObj.controlSelectCells(colEditSpread, function (cell) {
+        cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
+    });
+});
+$('#v-bottom').click(function () {
+    ColSettingObj.controlSelectCells(colEditSpread, function (cell) {
+        cell.vAlign(GC.Spread.Sheets.VerticalAlign.bottom);
+    });
+});
+
+$('#set-font').click(function () {
+    var sFont = $('#font').val();
+    ColSettingObj.controlSelectCells(colEditSpread, function (cell) {
+        cell.font(sFont);
+    });
+});

+ 4 - 0
web/users/js/compilation.js

@@ -249,6 +249,10 @@ function initCompilation() {
     if (billListData.length <= 0 || rationLibData.length <= 0 || gljLibData.length <= 0) {
         return false;
     }
+    // 初始化 造价书列设置
+    colSpread = SheetDataHelper.createNewSpread($('#main-tree-col')[0]);
+    SheetDataHelper.loadSheetHeader(JSON.parse(mainTreeCol), colSpread.getActiveSheet());
+
     // 标准清单
     let html = '';
     for(let tmp of billListData) {

+ 6 - 2
web/users/views/compilation/add.html

@@ -103,8 +103,8 @@
                     </div>
                     <div class="col-md-8">
                         <legend>造价书列设置<a href="javascript:void(0)" data-toggle="modal" data-target="#set-column" class="btn btn-primary btn-sm pull-right">设置</a></legend>
-                        <div>
-                            S JS预览在此
+                        <input type="hidden" name="main_tree_col" value="<%= mainTreeCol %>">
+                        <div id="main-tree-col">
                         </div>
                     </div>
                 </div>
@@ -118,6 +118,10 @@
     let billList = '<%- billList %>';
     let rationList = '<%- rationList %>';
     let gljList = '<%- gljList %>';
+    let mainTreeCol = '<%- mainTreeCol %>';
+    let colSpread = null;
+    let colEditSpread = null;
 </script>
+<script type="text/javascript" src="/public/web/sheet/sheet_data_helper.js"></script>
 <script type="text/javascript" src="/web/users/js/compilation.js"></script>
 <%include ../compilation/modal.html %>

+ 18 - 18
web/users/views/compilation/modal.html

@@ -85,25 +85,25 @@
                     <div class="col-md-3">
                         <div class="input-group">
                             <span class="input-group-addon" id="basic-addon1">空行</span>
-                            <input type="number" class="form-control input-sm" value="3">
+                            <input type="number" class="form-control input-sm" value="3" id="empty-rows">
                         </div>
                     </div>
                     <div class="col-md-3">
                         <div class="input-group">
                             <span class="input-group-addon" id="basic-addon1">数据绑定列数</span>
-                            <input type="number" class="form-control input-sm" value="4">
+                            <input type="number" class="form-control input-sm" value="4" id="col-count">
                         </div>
                     </div>
                     <div class="col-md-3">
                         <div class="input-group">
                             <span class="input-group-addon" id="basic-addon1">表头行数</span>
-                            <input type="number" class="form-control input-sm" value="1">
+                            <input type="number" class="form-control input-sm" value="1" id="header-row-count">
                         </div>
                     </div>
                     <div class="col-md-3">
                         <div class="checkbox">
                             <label>
-                                <input type="checkbox"> 是否包含树结构
+                                <input type="checkbox" id="is-tree"> 是否包含树结构
                             </label>
                         </div>
                     </div>
@@ -111,38 +111,38 @@
                 <div class="">
                     <div class="btn-toolbar" role="toolbar">
                         <div class="btn-group" role="group" >
-                            <a href="#" class="btn btn-default btn-sm">合并</a>
-                            <a href="#" class="btn btn-default btn-sm">拆分</a>
+                            <a href="#" class="btn btn-default btn-sm" id="merge">合并</a>
+                            <a href="#" class="btn btn-default btn-sm" id="unmerge">拆分</a>
                         </div>
                         <div class="btn-group" role="group">
-                            <a href="#" class="btn btn-default btn-sm">左对齐</a>
-                            <a href="#" class="btn btn-default btn-sm">居中</a>
-                            <a href="#" class="btn btn-default btn-sm">右对齐</a>
+                            <a href="#" class="btn btn-default btn-sm" id="h-left">左对齐</a>
+                            <a href="#" class="btn btn-default btn-sm" id="h-center">居中</a>
+                            <a href="#" class="btn btn-default btn-sm" id="h-right">右对齐</a>
                         </div>
                         <div class="btn-group" role="group">
-                            <a href="#" class="btn btn-default btn-sm">上对齐</a>
-                            <a href="#" class="btn btn-default btn-sm">垂直居中</a>
-                            <a href="#" class="btn btn-default btn-sm">下对齐</a>
+                            <a href="#" class="btn btn-default btn-sm" id="v-top">上对齐</a>
+                            <a href="#" class="btn btn-default btn-sm" id="v-center">垂直居中</a>
+                            <a href="#" class="btn btn-default btn-sm" id="v-bottom">下对齐</a>
                         </div>
                         <div class="btn-group" role="group">
                             <div class="input-group">
                                 <span class="input-group-addon" id="basic-addon1">字体</span>
-                                <input type="text" class="form-control input-sm" >
+                                <input type="text" class="form-control input-sm" id="font">
                                 <div class="input-group-btn">
-                                    <a href="#" class="btn btn-default btn-sm">设置</a>
+                                    <a href="#" class="btn btn-default btn-sm" id="set-font">设置</a>
                                 </div>
                             </div>
                         </div>
                     </div>
                 </div>
-                <div>
-                    S JS在此
+                <div id="colEditSpread">
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary">确定</button>
+                <button type="button" class="btn btn-primary" id="save-col-setting">确定</button>
             </div>
         </div>
     </div>
-</div>
+</div>
+<script type="text/javascript" src="/web/users/js/col_setting.js"></script>

+ 4 - 0
web/users/views/layout/layout.html

@@ -9,6 +9,7 @@
     <meta name=copyright content="smartcost.com.cn">
     <link rel="stylesheet" href="/web/users/css/bootstrap.min.css">
     <link rel="stylesheet" href="/web/users/css/style.css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.excel2013lightGray.10.0.1.css" type="text/css">
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/web/users/js/lib/bootstrap.min.js"></script>
     <script src="/web/users/js/global.js"></script>
@@ -16,6 +17,9 @@
     <script src="/web/users/js/lib/validate.extend.js"></script>
     <script src="/web/users/js/lib/messages_zh.js"></script>
     <script src="/web/users/js/lib/bootstrap-paginator.js"></script>
+    <!-- spreadJs -->
+    <script type="text/javascript" src="/lib/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
+    <script>GC.Spread.Sheets.LicenseKey = "559432293813965#A0y3iTOzEDOzkjMyMDN9UTNiojIklkI1pjIEJCLi4TPB9mM5AFNTd4cvZ7SaJUVy3CWKtWYXx4VVhjMpp7dYNGdx2ia9sEVlZGOTh7NRlTUwkWR9wEV4gmbjBDZ4ElR8N7cGdHVvEWVBtCOwIGW0ZmeYVWVr3mI0IyUiwCMzETN8kzNzYTM0IicfJye&Qf35VfiEzRwEkI0IyQiwiIwEjL6ByUKBCZhVmcwNlI0IiTis7W0ICZyBlIsIyNyMzM5ADI5ADNwcTMwIjI0ICdyNkIsIibj9SbvNmL4N7bjRnch56ciojIz5GRiwiI8+Y9sWY9QmZ0Jyp96uL9v6L0wap9biY9qiq95q197Wr9g+89iojIh94Wiqi";</script>
 </head>
 <body>
 <div class="header">