caixiaofeng 9 hónapja
szülő
commit
cb6f7d397f
19 módosított fájl, 650 hozzáadás és 26 törlés
  1. 6 4
      flow-report/flow-report-entity/src/main/java/com/flow/entity/ReportTemplate.java
  2. 27 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/Autofilter.java
  3. 12 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/Cells.java
  4. 27 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/Col.java
  5. 19 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetBorder.java
  6. 35 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetCell.java
  7. 197 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetCellStyle.java
  8. 48 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetFont.java
  9. 13 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetRow.java
  10. 103 0
      flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SpreadSheet.java
  11. 12 0
      flow-report/pom.xml
  12. 5 1
      flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowInstanceService.java
  13. 19 0
      flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowModelService.java
  14. 26 5
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowInstanceServiceImpl.java
  15. 65 12
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowModelServiceImpl.java
  16. 8 1
      flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowInstanceController.java
  17. 20 2
      flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowModelController.java
  18. 2 1
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/settings/PrintConfig.java
  19. 6 0
      flow-workflow/pom.xml

+ 6 - 4
flow-report/flow-report-entity/src/main/java/com/flow/entity/ReportTemplate.java

@@ -3,13 +3,13 @@ import com.baomidou.mybatisplus.annotation.SqlCondition;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.flow.common.mybatis.entity.BaseEntity;
-import com.zaxxer.hikari.HikariDataSource;
+import com.flow.model.spreadsheet.SpreadSheet;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
-import javax.sql.DataSource;
-
 @Data
 @EqualsAndHashCode(callSuper = true)
 @TableName("report_template")
@@ -17,6 +17,8 @@ public class ReportTemplate extends BaseEntity {
     private String code;
     @TableField(condition = SqlCondition.LIKE)
     private String name;
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long businessId;
     @TableField(typeHandler = JacksonTypeHandler.class)
-    private Object data;
+    private SpreadSheet data;
 }

+ 27 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/Autofilter.java

@@ -0,0 +1,27 @@
+package com.flow.model.spreadsheet;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class Autofilter {
+    private String ref;
+    private List<Object> filters;
+    private Object sort;
+    protected Map<String, Object> other = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getOther() {
+        return other;
+    }
+
+    @JsonAnySetter
+    public void setOther(String name, Object value) {
+        this.other.put(name, value);
+    }
+}

+ 12 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/Cells.java

@@ -0,0 +1,12 @@
+package com.flow.model.spreadsheet;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Cells {
+    private Map<String, SheetCell> cell;
+}

+ 27 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/Col.java

@@ -0,0 +1,27 @@
+package com.flow.model.spreadsheet;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Col {
+    private Integer width;
+
+    protected Map<String, Object> other = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getOther() {
+        return other;
+    }
+
+    @JsonAnySetter
+    public void setOther(String name, Object value) {
+        this.other.put(name, value);
+    }
+}

+ 19 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetBorder.java

@@ -0,0 +1,19 @@
+package com.flow.model.spreadsheet;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@AllArgsConstructor
+@NoArgsConstructor
+public class SheetBorder {
+    private List<String> top;
+    private List<String> bottom;
+    private List<String> left;
+    private List<String> right;
+}

+ 35 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetCell.java

@@ -0,0 +1,35 @@
+package com.flow.model.spreadsheet;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class SheetCell {
+    // 值
+    private String text;
+    // 样式
+    private Integer style;
+    // 是否可打印
+    private Boolean printable;
+    // 合并
+    private List<Integer> merge;
+    protected Map<String, Object> other = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getOther() {
+        return other;
+    }
+
+    @JsonAnySetter
+    public void setOther(String name, Object value) {
+        this.other.put(name, value);
+    }
+
+}

+ 197 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetCellStyle.java

@@ -0,0 +1,197 @@
+package com.flow.model.spreadsheet;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+import lombok.SneakyThrows;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class SheetCellStyle {
+    private SheetBorder border;
+    private String align;
+    private SheetFont font;
+    private String bgcolor;
+    private Boolean textwrap;
+    private String color;
+    private Boolean underline;
+    private Boolean strike;
+    private String valign;
+    private String format;
+    protected Map<String, Object> other = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getOther() {
+        return other;
+    }
+
+    @JsonAnySetter
+    public void setOther(String name, Object value) {
+        this.other.put(name, value);
+    }
+
+    @SneakyThrows
+    public CellStyle toStyle(SXSSFWorkbook workbook) {
+        XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle();
+        XSSFFont textFont = Objects.nonNull(this.font) ?
+                this.font.toFont(workbook) :
+                (XSSFFont) workbook.createFont();
+        cellStyle.setFont(textFont);
+        // 背景色
+        if (StringUtils.isNotBlank(this.bgcolor)) {
+            XSSFColor bgColor = new XSSFColor(java.awt.Color.decode(this.bgcolor), null);
+            cellStyle.setFillForegroundColor(bgColor);
+            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        }
+        // 文字颜色
+        if (StringUtils.isNotBlank(this.color)) {
+            XSSFColor xssfColor = new XSSFColor(java.awt.Color.decode(this.color), null);
+            textFont.setColor(xssfColor);
+            cellStyle.setFont(textFont);
+        }
+        // 自动换行
+        if (Objects.nonNull(this.textwrap)) {
+            cellStyle.setWrapText(textwrap);
+        }
+        // 对齐方式
+        if (StringUtils.isNotBlank(this.align)) {
+            switch (this.align) {
+                case "left":
+                    cellStyle.setAlignment(HorizontalAlignment.LEFT);
+                    break;
+                case "center":
+                    cellStyle.setAlignment(HorizontalAlignment.CENTER);
+                    break;
+                case "right":
+                    cellStyle.setAlignment(HorizontalAlignment.RIGHT);
+                    break;
+                default:
+                    break;
+            }
+        }
+        // 下划线
+        if (Objects.nonNull(this.underline)) {
+            textFont.setUnderline(this.underline ? Font.U_SINGLE : Font.U_NONE);
+        }
+        // 删除线
+        if (Objects.nonNull(this.strike)) {
+            textFont.setStrikeout(this.strike);
+        }
+        // 对齐方式
+        if (StringUtils.isNotBlank(this.valign)) {
+            switch (this.valign) {
+                case "top":
+                    cellStyle.setVerticalAlignment(VerticalAlignment.TOP);
+                    break;
+                case "middle":
+                    cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+                    break;
+                case "bottom":
+                    cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
+                    break;
+                default:
+                    break;
+            }
+        }
+        // 格式
+        if (StringUtils.isNotBlank(this.format)) {
+            switch (this.format) {
+                case "number":
+                    DataFormat format = workbook.createDataFormat();
+                    cellStyle.setDataFormat(format.getFormat("#,##0.00"));
+                    break;
+                case "percent":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("0.00%"));
+                    break;
+                case "text":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("@"));
+                    break;
+                case "rmb":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("¥#,##0.00"));
+                    break;
+                case "usd":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("$#,##0.00"));
+                    break;
+                case "eur":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("€#,##0.00"));
+                    break;
+                case "date":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("dd/mm/yyyy"));
+                    break;
+                case "datetime":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("dd/mm/yyyy hh:mm:ss"));
+                    break;
+                case "duration":
+                    cellStyle.setDataFormat(workbook.createDataFormat().getFormat("hh:mm:ss"));
+                    break;
+                default:
+                    break;
+            }
+        }
+        // 边框
+        if (Objects.nonNull(this.border)) {
+            List<String> top = this.border.getTop();
+            if (Objects.nonNull(top)) {
+                BorderStyle style = this.toBorderStyle(top.get(0));
+                cellStyle.setBorderTop(style);
+                XSSFColor xssfColor = new XSSFColor(java.awt.Color.decode(top.get(1)), null);
+                cellStyle.setTopBorderColor(xssfColor);
+            }
+            List<String> bottom = this.border.getBottom();
+            if (Objects.nonNull(bottom)) {
+                BorderStyle style = this.toBorderStyle(bottom.get(0));
+                cellStyle.setBorderBottom(style);
+                XSSFColor xssfColor = new XSSFColor(java.awt.Color.decode(bottom.get(1)), null);
+                cellStyle.setBottomBorderColor(xssfColor);
+            }
+            List<String> left = this.border.getLeft();
+            if (Objects.nonNull(left)) {
+                BorderStyle style = this.toBorderStyle(left.get(0));
+                cellStyle.setBorderLeft(style);
+                XSSFColor xssfColor = new XSSFColor(java.awt.Color.decode(left.get(1)), null);
+                cellStyle.setLeftBorderColor(xssfColor);
+            }
+            List<String> right = this.border.getRight();
+            if (Objects.nonNull(right)) {
+                BorderStyle style = this.toBorderStyle(right.get(0));
+                cellStyle.setBorderRight(style);
+                XSSFColor xssfColor = new XSSFColor(java.awt.Color.decode(right.get(1)), null);
+                cellStyle.setRightBorderColor(xssfColor);
+            }
+        }
+        return cellStyle;
+    }
+
+    /**
+     * 边框样式
+     *
+     * @param borderStyle
+     * @return
+     */
+    private BorderStyle toBorderStyle(String borderStyle) {
+        switch (borderStyle) {
+            case "dotted":
+                return BorderStyle.DOTTED;
+            case "thin":
+                return BorderStyle.THIN;
+            case "medium":
+                return BorderStyle.MEDIUM;
+            case "thick":
+                return BorderStyle.THICK;
+            default:
+                return BorderStyle.NONE;
+        }
+    }
+}

+ 48 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetFont.java

@@ -0,0 +1,48 @@
+package com.flow.model.spreadsheet;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class SheetFont {
+    private Boolean bold;
+    private Boolean italic;
+    private Integer size;
+
+    protected Map<String, Object> other = new HashMap<>();
+
+    @JsonAnyGetter
+    public Map<String, Object> getOther() {
+        return other;
+    }
+
+    @JsonAnySetter
+    public void setOther(String name, Object value) {
+        this.other.put(name, value);
+    }
+
+    public XSSFFont toFont(SXSSFWorkbook workbook) {
+        XSSFFont font = (XSSFFont) workbook.createFont();
+        if (Objects.nonNull(this.bold)) {
+            font.setBold(this.bold);
+        }
+        if (Objects.nonNull(this.size)) {
+            font.setFontHeightInPoints(size.shortValue());
+        }
+        if (Objects.nonNull(this.italic)) {
+            font.setItalic(this.italic);
+        }
+        return font;
+    }
+}

+ 13 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SheetRow.java

@@ -0,0 +1,13 @@
+package com.flow.model.spreadsheet;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class SheetRow {
+    private Map<Integer, SheetCell> cells;
+    private Integer height;
+}

+ 103 - 0
flow-report/flow-report-entity/src/main/java/com/flow/model/spreadsheet/SpreadSheet.java

@@ -0,0 +1,103 @@
+package com.flow.model.spreadsheet;
+
+import lombok.Data;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.RegionUtil;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+@Data
+public class SpreadSheet {
+    // 名称
+    private String name;
+    // 冻结
+    private String freeze;
+    // 自动过滤
+    private Autofilter autofilter;
+    // 列
+    private Map<Integer, Col> cols;
+    // 合并
+    private List<String> merges;
+    // 样式
+    private List<SheetCellStyle> styles;
+    // 校验
+    private List<Object> validations;
+    // 行
+    private Map<Integer, SheetRow> rows;
+    // 行数
+    private Integer rowLen;
+    // 列数
+    private Integer colLen;
+
+    public SXSSFWorkbook toExcel() {
+        SXSSFWorkbook workbook = new SXSSFWorkbook();
+        SXSSFSheet sheet = workbook.createSheet(this.name);
+        sheet.setDefaultColumnWidth((100 - 5) / 7);
+        sheet.setDefaultRowHeightInPoints(25 * 0.75f);
+        // 行列
+        for (Map.Entry<Integer, SheetRow> entry : this.rows.entrySet()) {
+            Row row = sheet.createRow(entry.getKey());
+            SheetRow sheetRow = entry.getValue();
+            Integer height = sheetRow.getHeight();
+            if (Objects.nonNull(height)) {
+                row.setHeightInPoints(height);
+            }
+            Map<Integer, SheetCell> cells = sheetRow.getCells();
+            for (Map.Entry<Integer, SheetCell> cellEntry : cells.entrySet()) {
+                SheetCell poiSheetCell = cellEntry.getValue();
+                Cell cell = row.createCell(cellEntry.getKey());
+                cell.setCellValue(poiSheetCell.getText());
+                Integer styleIndex = poiSheetCell.getStyle();
+                if (Objects.nonNull(styleIndex)) {
+                    SheetCellStyle sheetCellStyle = this.styles.get(styleIndex);
+                    CellStyle cellStyle = sheetCellStyle.toStyle(workbook);
+                    cell.setCellStyle(cellStyle);
+                }
+            }
+        }
+        // 合并区域
+        for (String merge : this.merges) {
+            CellRangeAddress cra = CellRangeAddress.valueOf(merge);
+            sheet.addMergedRegion(cra);
+            Cell cell = sheet.getRow(cra.getFirstRow()).getCell(cra.getFirstColumn());
+            if (Objects.nonNull(cell)) {
+                CellStyle cellStyle = cell.getCellStyle();
+                // 左边边框
+                BorderStyle borderLeft = cellStyle.getBorderLeft();
+                short leftBorderColor = cellStyle.getLeftBorderColor();
+                if (borderLeft != BorderStyle.NONE) {
+                    RegionUtil.setBorderLeft(borderLeft, cra, sheet);
+                    RegionUtil.setLeftBorderColor(leftBorderColor, cra, sheet);
+                }
+                // 右边边框
+                BorderStyle borderRight = cellStyle.getBorderRight();
+                short rightBorderColor = cellStyle.getRightBorderColor();
+                if (borderRight != BorderStyle.NONE) {
+                    RegionUtil.setBorderRight(borderRight, cra, sheet);
+                    RegionUtil.setRightBorderColor(rightBorderColor, cra, sheet);
+                }
+                // 上边边框
+                BorderStyle borderTop = cellStyle.getBorderTop();
+                short topBorderColor = cellStyle.getTopBorderColor();
+                if (borderTop != BorderStyle.NONE) {
+                    RegionUtil.setBorderTop(borderTop, cra, sheet);
+                    RegionUtil.setTopBorderColor(topBorderColor, cra, sheet);
+                }
+                // 下边边框
+                BorderStyle borderBottom = cellStyle.getBorderBottom();
+                short bottomBorderColor = cellStyle.getBottomBorderColor();
+                if (borderBottom != BorderStyle.NONE) {
+                    RegionUtil.setBorderBottom(borderBottom, cra, sheet);
+                    RegionUtil.setBottomBorderColor(bottomBorderColor, cra, sheet);
+                }
+            }
+        }
+        return workbook;
+    }
+
+}

+ 12 - 0
flow-report/pom.xml

@@ -38,6 +38,18 @@
             <artifactId>flow-common-mybatis-starter</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
+        <!-- Apache POI Core -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>5.2.3</version>
+        </dependency>
+        <!-- Apache POI for Excel -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>5.2.3</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 5 - 1
flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowInstanceService.java

@@ -1,11 +1,13 @@
 package com.flow.service;
 
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.flow.common.core.model.PageResult;
 import com.flow.common.mybatis.service.BaseService;
 import com.flow.entity.FlowInstance;
 import com.flow.model.FlowInstanceQuery;
 import com.flow.model.FormInfo;
+import com.flow.model.spreadsheet.SpreadSheet;
 
 import java.util.List;
 import java.util.Map;
@@ -62,5 +64,7 @@ public interface FlowInstanceService extends BaseService<FlowInstance> {
      * @param instanceId
      * @return
      */
-    String getPrintData(String instanceId);
+    SpreadSheet getPrintData(String instanceId) throws JsonProcessingException;
+
+    Boolean getPrintExist(String instanceId);
 }

+ 19 - 0
flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowModelService.java

@@ -4,8 +4,10 @@ import com.flow.common.mybatis.service.BaseService;
 import com.flow.entity.DatasetField;
 import com.flow.entity.FlowDefine;
 import com.flow.entity.FlowModel;
+import com.flow.model.spreadsheet.SpreadSheet;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.util.List;
 import java.util.Set;
 
@@ -71,4 +73,21 @@ public interface FlowModelService extends BaseService<FlowModel> {
      * @return
      */
     List<DatasetField> getReportField(String modelId);
+
+    /**
+     * 保存打印模板
+     * @param spreadSheet
+     * @param modelId
+     * @return
+     */
+    SpreadSheet savePrint(SpreadSheet spreadSheet, String modelId);
+
+    /**
+     * 获取打印模板
+     * @param modelId
+     * @return
+     */
+    SpreadSheet getPrint(String modelId);
+
+    void exportExcel(String modelId) throws UnsupportedEncodingException;
 }

+ 26 - 5
flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowInstanceServiceImpl.java

@@ -2,6 +2,8 @@ package com.flow.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.flow.common.core.exception.BaseException;
 import com.flow.common.core.model.PageResult;
 import com.flow.common.core.util.StrUtil;
@@ -17,6 +19,7 @@ import com.flow.enums.NotifyEnum;
 import com.flow.enums.ProcessStatus;
 import com.flow.model.FlowInstanceQuery;
 import com.flow.model.FormInfo;
+import com.flow.model.spreadsheet.SpreadSheet;
 import com.flow.service.*;
 import org.flowable.engine.HistoryService;
 import org.flowable.engine.RuntimeService;
@@ -52,6 +55,8 @@ public class FlowInstanceServiceImpl extends BaseServiceImpl<FlowInstanceDao, Fl
     private UserService userService;
     @Autowired
     private HistoryService historyService;
+    @Autowired
+    private ObjectMapper objectMapper;
 
     @Override
     public PageResult<FlowInstance> list(FlowInstanceQuery flowInstanceQuery) {
@@ -187,7 +192,7 @@ public class FlowInstanceServiceImpl extends BaseServiceImpl<FlowInstanceDao, Fl
     }
 
     @Override
-    public String getPrintData(String instanceId) {
+    public SpreadSheet getPrintData(String instanceId) throws JsonProcessingException {
         FlowInstance instance = flowInstanceDao.getInstance(instanceId);
         String definitionId = instance.getDefinitionId();
         FlowDefine define = flowDefineService.getDefine(definitionId);
@@ -196,12 +201,12 @@ public class FlowInstanceServiceImpl extends BaseServiceImpl<FlowInstanceDao, Fl
         }
         Settings settings = define.getSettings();
         if (Objects.isNull(settings)) {
-            return "";
+            return null;
         }
         PrintConfig printConfig = settings.getPrint();
         Boolean enable = printConfig.getEnable();
         if (Objects.isNull(enable) || !enable) {
-            return "";
+            // return null;
         }
         Map<String, Object> variables = this.getVariables(instanceId);
         User user = userService.getByUsername(instance.getStartUserId());
@@ -219,7 +224,23 @@ public class FlowInstanceServiceImpl extends BaseServiceImpl<FlowInstanceDao, Fl
         String _currentTime_ = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
         variables.put("_currentTime_", _currentTime_);
         variables.put("_status_", instance.getStatus().getDescription());
-        String template = printConfig.getTemplate();
-        return StrUtil.format(template, variables);
+        SpreadSheet spreadSheet = printConfig.getTemplate();
+        String json = objectMapper.writeValueAsString(spreadSheet);
+        String format = StrUtil.format(json, variables);
+        spreadSheet = objectMapper.readValue(format, SpreadSheet.class);
+        return spreadSheet;
+    }
+
+    @Override
+    public Boolean getPrintExist(String instanceId) {
+        FlowInstance instance = flowInstanceDao.getInstance(instanceId);
+        String definitionId = instance.getDefinitionId();
+        FlowDefine define = flowDefineService.getDefine(definitionId);
+        if (Objects.isNull(define)) {
+            throw new BaseException("流程不存在");
+        }
+        Settings settings = define.getSettings();
+        PrintConfig printConfig = settings.getPrint();
+        return printConfig.getEnable();
     }
 }

+ 65 - 12
flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowModelServiceImpl.java

@@ -5,15 +5,18 @@ import com.flow.common.core.exception.BaseException;
 import com.flow.common.mybatis.constant.SqlConstant;
 import com.flow.common.mybatis.service.impl.BaseServiceImpl;
 import com.flow.dao.FlowModelDao;
-import com.flow.entity.DatasetField;
-import com.flow.entity.FlowDefine;
-import com.flow.entity.FlowModel;
-import com.flow.entity.FormModel;
+import com.flow.entity.*;
 import com.flow.entity.form.Field;
+import com.flow.entity.settings.PrintConfig;
+import com.flow.entity.settings.Settings;
+import com.flow.model.spreadsheet.SpreadSheet;
 import com.flow.service.FlowDefineService;
 import com.flow.service.FlowModelHistoryService;
 import com.flow.service.FlowModelService;
+import com.flow.service.ReportTemplateService;
 import com.google.common.collect.Lists;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.flowable.bpmn.converter.BpmnXMLConverter;
 import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.engine.RepositoryService;
@@ -30,6 +33,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -44,6 +48,8 @@ public class FlowModelServiceImpl extends BaseServiceImpl<FlowModelDao, FlowMode
     private RepositoryService repositoryService;
     @Autowired
     private FlowDefineService flowDefineService;
+    @Autowired
+    private ReportTemplateService reportTemplateService;
 
     @Override
     public List<FlowModel> list(FlowModel flowModel) {
@@ -107,6 +113,11 @@ public class FlowModelServiceImpl extends BaseServiceImpl<FlowModelDao, FlowMode
     public FlowModel create(FlowModel flowModel) {
         flowModel.setCode(String.format("flow-%s", IdWorker.getIdStr()));
         flowModelDao.insert(flowModel);
+        // 打印模板
+        ReportTemplate template = new ReportTemplate();
+        template.setBusinessId(flowModel.getId());
+        template.setCode(flowModel.getCode());
+        template.setName(flowModel.getName());
         return flowModel;
     }
 
@@ -185,18 +196,60 @@ public class FlowModelServiceImpl extends BaseServiceImpl<FlowModelDao, FlowMode
         Map<String, Field> fieldMap = formModel.allFieldsAsMap();
         List<DatasetField> list = fieldMap.values().stream().map(field -> new DatasetField(
                 field.getLabel(),
-                field.getId()
+                String.format("${%s}", field.getId())
         )).collect(Collectors.toList());
-        list.add(new DatasetField("发起人", "_initiator_"));
-        list.add(new DatasetField("编号", "_code_"));
-        list.add(new DatasetField("标题", "_title_"));
-        list.add(new DatasetField("状态", "_status_"));
-        list.add(new DatasetField("发起时间", "_startTime_"));
-        list.add(new DatasetField("结束时间", "_endTime_"));
-        list.add(new DatasetField("打印时间", "_currentTime_"));
+        list.add(new DatasetField("发起人", "${_initiator_}"));
+        list.add(new DatasetField("编号", "${_code_}"));
+        list.add(new DatasetField("标题", "${_title_}"));
+        list.add(new DatasetField("状态", "${_status_}"));
+        list.add(new DatasetField("发起时间", "${_startTime_}"));
+        list.add(new DatasetField("结束时间", "${_endTime_}"));
+        list.add(new DatasetField("打印时间", "${_currentTime_}"));
         DatasetField datasetField = new DatasetField();
+        datasetField.setField(String.format("${%s}", modelId));
         datasetField.setLabel(flowModel.getName());
         datasetField.setChildren(list);
         return Lists.newArrayList(datasetField);
     }
+
+    @Override
+    public SpreadSheet savePrint(SpreadSheet spreadSheet, String modelId) {
+        FlowModel flowModel = flowModelDao.selectById(modelId);
+        if (Objects.isNull(flowModel)) {
+            throw new BaseException("流程模型不存在");
+        }
+        Settings settings = flowModel.getSettings();
+        PrintConfig printConfig = settings.getPrint();
+        printConfig.setTemplate(spreadSheet);
+        flowModel.setSettings(settings);
+        flowModelDao.updateById(flowModel);
+        return spreadSheet;
+    }
+
+    @Override
+    public SpreadSheet getPrint(String modelId) {
+        FlowModel flowModel = flowModelDao.selectById(modelId);
+        Settings settings = flowModel.getSettings();
+        PrintConfig printConfig = settings.getPrint();
+        return printConfig.getTemplate();
+    }
+
+    @Override
+    public void exportExcel(String modelId) throws UnsupportedEncodingException {
+        SpreadSheet spreadSheet = this.getPrint(modelId);
+        SXSSFWorkbook excel = spreadSheet.toExcel();
+        // 响应前端
+        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+        response.setContentType("application/vnd.ms-excel");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(spreadSheet.getName() + ".xlsx", "UTF-8"));
+        try {
+            ServletOutputStream outputStream = response.getOutputStream();
+            excel.write(outputStream);
+            outputStream.flush();
+            outputStream.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }

+ 8 - 1
flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowInstanceController.java

@@ -1,11 +1,13 @@
 package com.flow.controller;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.flow.common.core.model.PageResult;
 import com.flow.common.core.model.Result;
 import com.flow.common.oauth2.utils.SecurityContextUtil;
 import com.flow.entity.FlowInstance;
 import com.flow.model.FlowInstanceQuery;
 import com.flow.model.FormInfo;
+import com.flow.model.spreadsheet.SpreadSheet;
 import com.flow.service.FlowInstanceService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -54,7 +56,12 @@ public class FlowInstanceController {
     }
 
     @GetMapping("/print/{instanceId}")
-    public Result<String> getPrintData(@PathVariable String instanceId) {
+    public Result<SpreadSheet> getPrintData(@PathVariable String instanceId) throws JsonProcessingException {
         return Result.successData(flowInstanceService.getPrintData(instanceId));
     }
+
+    @GetMapping("/print/exist/{instanceId}")
+    public Result<Boolean> getPrintExist(@PathVariable String instanceId) throws JsonProcessingException {
+        return Result.successData(flowInstanceService.getPrintExist(instanceId));
+    }
 }

+ 20 - 2
flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowModelController.java

@@ -4,6 +4,7 @@ import com.flow.common.core.model.Result;
 import com.flow.entity.DatasetField;
 import com.flow.entity.FlowDefine;
 import com.flow.entity.FlowModel;
+import com.flow.model.spreadsheet.SpreadSheet;
 import com.flow.service.FlowModelService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -46,7 +47,7 @@ public class FlowModelController {
         return Result.success();
     }
 
-    @CrossOrigin(origins = "*",maxAge = 3600)
+    @CrossOrigin(origins = "*", maxAge = 3600)
     @PostMapping("/download")
     public void downloadXml(@RequestBody FlowModel flowModel) throws IOException {
         flowModelService.downloadXml(flowModel);
@@ -59,7 +60,8 @@ public class FlowModelController {
 
     @GetMapping("/{modelId}")
     public Result<FlowModel> getModel(@PathVariable Long modelId) {
-        return Result.success(flowModelService.getModel(modelId));
+        FlowModel model = flowModelService.getModel(modelId);
+        return Result.success(model);
     }
 
     @GetMapping("/report/{modelId}")
@@ -67,4 +69,20 @@ public class FlowModelController {
         List<DatasetField> list = flowModelService.getReportField(modelId);
         return Result.success(list);
     }
+
+    @PostMapping("/report/save/{modelId}")
+    public Result<?> savePrint(@PathVariable String modelId,@RequestBody SpreadSheet spreadSheet) {
+        return Result.success(flowModelService.savePrint(spreadSheet,modelId));
+    }
+
+    @GetMapping("/report/print/{modelId}")
+    public Result<SpreadSheet> getPrint(@PathVariable String modelId) {
+        SpreadSheet spreadSheet = flowModelService.getPrint(modelId);
+        return Result.success(spreadSheet);
+    }
+
+    @PostMapping("/report/excel/{modelId}")
+    public void exportExcel(@PathVariable String modelId) throws IOException {
+        flowModelService.exportExcel(modelId);
+    }
 }

+ 2 - 1
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/settings/PrintConfig.java

@@ -1,9 +1,10 @@
 package com.flow.entity.settings;
 
+import com.flow.model.spreadsheet.SpreadSheet;
 import lombok.Data;
 
 @Data
 public class PrintConfig {
     private Boolean enable;
-    private String template;
+    private SpreadSheet template;
 }

+ 6 - 0
flow-workflow/pom.xml

@@ -59,6 +59,12 @@
             <artifactId>flow-common-redis-starter</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
+        <!--report-->
+        <dependency>
+            <groupId>com.flow</groupId>
+            <artifactId>flow-report-api</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
         <!--system-->
         <dependency>
             <groupId>com.flow</groupId>