From 9f7f4aba7225f46ba597f98854df090c04678557 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Tue, 23 Jul 2024 11:23:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=9F=BA=E7=A1=80=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=EF=BC=9A=E6=9D=BF=E6=9D=90=E6=B1=87=E6=80=BB-?= =?UTF-8?q?=E6=8C=89=E6=9D=BF=E6=9D=90=E6=8A=A5=E8=A1=A8excel=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E5=AE=9E=E7=8E=B0=EF=BC=9Aexec=E5=BE=AE=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1rpc=E6=8E=A5=E5=8F=A3=E3=80=81report=E5=BE=AE=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1rpc=E6=8E=A5=E5=8F=A3=E5=AE=9E=E7=8E=B0=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/datasource/OrderDatasourceApi.java | 26 +++ .../datasource/OrderPlateDatasourceApi.java | 28 +++ .../executor/api/datasource/dto/OrderDTO.java | 78 ++++++++ .../api/datasource/dto/PlateGoodsRespDTO.java | 179 ++++++++++++++++++ .../cf-module-prod-executor-biz/pom.xml | 6 +- .../datasource/OrderDatasourceApiImpl.java | 32 ++++ .../OrderPlateDatasourceApiImpl.java | 34 ++++ .../rpc/config/RpcConfiguration.java | 3 +- cf-module-report/cf-module-report-api/pom.xml | 21 ++ .../api/template/ReportTemplateApi.java | 26 +++ .../dto/ReportTemplateGenerateReqDTO.java | 22 +++ .../module/report/enums/ApiConstants.java | 21 ++ .../report/enums/ErrorCodeConstants.java | 23 ++- cf-module-report/cf-module-report-biz/pom.xml | 29 +++ .../report/ReportServerApplication.java | 3 + .../dataset/vo/ReportDatasetSaveReqVO.java | 5 +- .../vo/ReportDatasourceSaveReqVO.java | 1 - .../template/ReportTemplateController.java | 29 ++- .../rpc/config/RpcConfiguration.java | 11 ++ .../bean/OrderSummaryBeanDatasource.java | 113 +++++++++++ .../config/CfReportSpringbeanRegistrar.java | 6 + .../template/ReportTemplateService.java | 13 +- .../template/ReportTemplateServiceImpl.java | 26 ++- .../lib/ureport-core-2.3.0-SNAPSHOT.jar | Bin 916178 -> 916116 bytes cf-module-report/pom.xml | 3 + 25 files changed, 716 insertions(+), 22 deletions(-) create mode 100644 cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApi.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApi.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/OrderDTO.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/PlateGoodsRespDTO.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApiImpl.java create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApiImpl.java create mode 100644 cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/ReportTemplateApi.java create mode 100644 cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/dto/ReportTemplateGenerateReqDTO.java create mode 100644 cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ApiConstants.java create mode 100644 cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/rpc/config/RpcConfiguration.java create mode 100644 cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApi.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApi.java new file mode 100644 index 000000000..c1b4c97e2 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApi.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.module.executor.api.datasource.dto.OrderDTO; +import com.cf.imes.module.executor.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * @author Gqr + * @since 2024/7/22 17:56 + */ +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 订单报表数据源") +public interface OrderDatasourceApi { + String PREFIX = ApiConstants.PREFIX + "/order"; + + @GetMapping(PREFIX +"/info") + @Operation(summary = "获取生产单信息") + @Parameter(name = "orderId", description = "生产单id", required = true, example = "1") + CommonResult getOrderInfo(@RequestParam("orderId") Long orderId); +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApi.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApi.java new file mode 100644 index 000000000..e482d683a --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApi.java @@ -0,0 +1,28 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.module.executor.api.datasource.dto.PlateGoodsRespDTO; +import com.cf.imes.module.executor.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +/** + * @author Gqr + * @since 2024/7/19 12:00 + */ +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 板材报表数据源") +public interface OrderPlateDatasourceApi { + String PREFIX = ApiConstants.PREFIX + "/order-plate"; + + @GetMapping(PREFIX + "/summary/byPlate") + @Operation(summary = "按板材汇总板材数据") + @Parameter(name = "orderId", description = "生产单id", required = true, example = "1") + CommonResult> selectPlateGoodsListSummary(@RequestParam("orderId") Long orderId); +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/OrderDTO.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/OrderDTO.java new file mode 100644 index 000000000..b7fa64aec --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/OrderDTO.java @@ -0,0 +1,78 @@ +package com.cf.imes.module.executor.api.datasource.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author Gqr + * @since 2024/7/22 17:54 + */ +@Schema(description = "管理后台 - 生产单表 RPC Response DTO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OrderDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 3574973837176279383L; + + @Schema(description = "生产单号") + private Long id; + + @Schema(description = "父单号") + private Long parentNo; + + @Schema(description = "源生产单号") + private String apiOrderId; + + @Schema(description = "生产单日期", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime orderDate; + + @Schema(description = "交付日期", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime deliveryDate; + + @Schema(description = "生产单类型,1主单 2子单", example = "1") + private Integer orderType; + + @Schema(description = "生产单排序号") + private Integer orderSort; + + @Schema(description = "CAD数据类型,1CAD 2WebCAD 3Excel", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer dataType; + + @Schema(description = "订单状态,订单状态,0空订单1新单2生产中3生产完成", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "自定义单号") + private String customOrderNo; + + @Schema(description = "客户", requiredMode = Schema.RequiredMode.REQUIRED) + private String customer; + + @Schema(description = "客户地址", requiredMode = Schema.RequiredMode.REQUIRED) + private String address; + + @Schema(description = "客户电话", requiredMode = Schema.RequiredMode.REQUIRED) + private String phoneNumber; + + @Schema(description = "经销商", requiredMode = Schema.RequiredMode.REQUIRED) + private String dealer; + + @Schema(description = "经销商电话", requiredMode = Schema.RequiredMode.REQUIRED) + private String dealerPhoneNumber; + + @Schema(description = "业务员") + private String salesman; + + @Schema(description = "拆单员") + private String splitter; + + @Schema(description = "备注", example = "你猜") + private String remark; +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/PlateGoodsRespDTO.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/PlateGoodsRespDTO.java new file mode 100644 index 000000000..d77ec4f3c --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/api/datasource/dto/PlateGoodsRespDTO.java @@ -0,0 +1,179 @@ +package com.cf.imes.module.executor.api.datasource.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "管理后台 - 板件对应板材信息 Response DTO") +public class PlateGoodsRespDTO { + + @Schema(description = "柜体号", example = "11087") + private Long bodyId; + + @Schema(description = "柜体名称", example = "11087") + private String bodyName; + + @Schema(description = "房间号", example = "11087") + private Long roomId; + + @Schema(description = "房间名称", example = "11087") + private String roomName; + + @Schema(description = "板id", example = "11087") + private Long id; + + @Schema(description = "板数量", example = "11087") + private Integer count = 1; + + @Schema(description = "生产单号", example = "11087") + private Long orderId; + + @Schema(description = "板名称", example = "晨丰") + private String name; + + @Schema(description = "自定义板编号,设计有板编号,则保留设计板编号;设计没有且在机台设置中设置了自定义板编号规则,则按规则自动生成") + private String plateNo; + + @Schema(description = "板类型,0 层板 1 立板 2 背板", example = "1") + private Integer type; + + @Schema(description = "商品 ID", example = "14195") + private String goodsId; + + @Schema(description = "商品名称", example = "西西") + private String goodsName; + + @Schema(description = "商品材质", example = "颗粒板") + private String material; + + @Schema(description = "商品颜色", example = "白色") + private String color; + + @Schema(description = "商品宽度", example = "14195") + private BigDecimal goodsWidth; + + @Schema(description = "商品高度", example = "14195") + private BigDecimal goodsHeight; + + @Schema(description = "商品厚度", example = "14195") + private BigDecimal goodsThickness; + + @Schema(description = "商品价格", example = "14195") + private BigDecimal price; + + @Schema(description = "商品品牌", example = "柏柏") + private String brand; + + @Schema(description = "商品规格", example = "14195*21") + private String spec; + + @Schema(description = "宽度") + private BigDecimal width; + + @Schema(description = "高度") + private BigDecimal height; + + @Schema(description = "厚度") + private BigDecimal thickness; + + @Schema(description = "拆单宽度") + private BigDecimal splitWidth; + + @Schema(description = "拆单高度") + private BigDecimal splitHeight; + + @Schema(description = "拆单厚度") + private BigDecimal splitThickness; + + @Schema(description = "左封边厚度") + private BigDecimal sealLeft; + + @Schema(description = "右封边厚度") + private BigDecimal sealRight; + + @Schema(description = "上封边厚度") + private BigDecimal sealUp; + + @Schema(description = "下封边厚度") + private BigDecimal sealDown; + + @Schema(description = "面积") + private BigDecimal area; + + @Schema(description = "纹路类型,0 正纹 1 可翻转 2 反纹") + private Integer texture; + + @Schema(description = "孔面类型,0 正面 1 反面 2 侧面") + private Integer holeFace; + + @Schema(description = "排孔类型,0 正纹 1 反面 2 随意面") + private Integer holeArrange; + + @Schema(description = "异型孔数量", example = "28477") + private Short unregularPointCount; + + @Schema(description = "正面孔数量", example = "20823") + private Short frontHoleCount; + + @Schema(description = "背面孔数量", example = "3441") + private Short backHoleCount; + + @Schema(description = "侧面孔数量", example = "25509") + private Short sideHoleCount; + + @Schema(description = "正面造型量", example = "31547") + private Short frontModelCount; + + @Schema(description = "背面造型量", example = "26725") + private Short backModelCount; + + @Schema(description = "是否门板") + private Boolean isDoor; + + @Schema(description = "开门类型,0 无 1 左 2 右 3 上 4 下", example = "2") + private Integer openDoorType; + + @Schema(description = "异型偏移 x") + private Double offsetX; + + @Schema(description = "异型偏移 y") + private Double offsetY; + + @Schema(description = "是否孤形对角") + private Boolean isArcAcross; + + @Schema(description = "是否异性") + private Boolean isSpecialShaped; + + @Schema(description = "是否造型") + private Boolean isSculpt; + + @Schema(description = "模块类型 ID", example = "12800") + private Long moduleTypeId; + + @Schema(description = "排单过滤类型,1 有挖穿造型 2 有挖穿孔 4 有二维刀路 8 可叠", example = "1") + private String filterType; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "是否作废") + private Boolean isCancel; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml index 5f090cde7..7f93d1641 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/pom.xml @@ -151,7 +151,11 @@ uk.co.jemos.podam podam - + + com.cf.imes + cf-module-report-api + ${revision} + diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApiImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApiImpl.java new file mode 100644 index 000000000..583533207 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderDatasourceApiImpl.java @@ -0,0 +1,32 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.organ.core.context.OrganContextHolder; +import com.cf.imes.module.executor.api.datasource.dto.OrderDTO; +import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; +import com.cf.imes.module.executor.dal.mysql.order.OrderMapper; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author Gqr + * @since 2024/7/22 17:57 + */ +@RestController // 提供 RESTful API 接口,给 Feign 调用 +@Validated +public class OrderDatasourceApiImpl implements OrderDatasourceApi { + + @Resource + private OrderMapper orderMapper; + + @Override + public CommonResult getOrderInfo(Long orderId) { + // 查询生产单 + OrderDO orderDO = orderMapper.selectOrderOne(orderId, OrganContextHolder.getOrganId()); + OrderDTO orderDTO = BeanUtils.toBean(orderDO, OrderDTO.class); + return CommonResult.success(orderDTO); + } +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApiImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApiImpl.java new file mode 100644 index 000000000..d27d79569 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/api/datasource/OrderPlateDatasourceApiImpl.java @@ -0,0 +1,34 @@ +package com.cf.imes.module.executor.api.datasource; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; +import com.cf.imes.module.executor.api.datasource.dto.PlateGoodsRespDTO; +import com.cf.imes.module.executor.controller.admin.plate.vo.PlateGoodsRespVO; +import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper; +import com.cf.imes.module.executor.enums.OrderDeletedEnum; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author Gqr + * @since 2024/7/19 14:26 + */ +@RestController // 提供 RESTful API 接口,给 Feign 调用 +@Validated +public class OrderPlateDatasourceApiImpl implements OrderPlateDatasourceApi { + @Resource + private PlateMapper plateMapper; + + + @Override + public CommonResult> selectPlateGoodsListSummary(Long orderId) { + // 查询分组统计 + Integer notDeletedStatus = OrderDeletedEnum.NOT_DELETED.getStatus(); + List plateGoodsRespVOS = plateMapper.selectPlateGoodsListSummary(orderId, SecurityFrameworkUtils.getLoginUser().getOrganId(), notDeletedStatus); + return CommonResult.success(BeanUtils.toBean(plateGoodsRespVOS, PlateGoodsRespDTO.class)); + } +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java index bed2ea5be..81998298b 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/framework/rpc/config/RpcConfiguration.java @@ -1,6 +1,7 @@ package com.cf.imes.module.executor.framework.rpc.config; import com.cf.imes.module.infra.api.file.FileApi; +import com.cf.imes.module.report.api.template.ReportTemplateApi; import com.cf.imes.module.system.api.application.ApplicationApi; import com.cf.imes.module.system.api.dataSource.DataSourceApi; import com.cf.imes.module.system.api.machine.MachineApi; @@ -16,6 +17,6 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @EnableFeignClients(clients = {AdminUserApi.class, MachineApi.class, DictDataApi.class, - FileApi.class, ProcessGroupApi.class, FileApi.class, DataSourceApi.class, ApplicationApi.class, ProcessApi.class}) + FileApi.class, ProcessGroupApi.class, FileApi.class, DataSourceApi.class, ApplicationApi.class, ProcessApi.class, ReportTemplateApi.class}) public class RpcConfiguration { } diff --git a/cf-module-report/cf-module-report-api/pom.xml b/cf-module-report/cf-module-report-api/pom.xml index bdcf4798e..78758b2bd 100644 --- a/cf-module-report/cf-module-report-api/pom.xml +++ b/cf-module-report/cf-module-report-api/pom.xml @@ -22,5 +22,26 @@ com.cf.imes cf-common + + + + org.springdoc + springdoc-openapi-ui + provided + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + true + diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/ReportTemplateApi.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/ReportTemplateApi.java new file mode 100644 index 000000000..da559c190 --- /dev/null +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/ReportTemplateApi.java @@ -0,0 +1,26 @@ +package com.cf.imes.module.report.api.template; + +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; +import com.cf.imes.module.report.enums.ApiConstants; +import feign.Response; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * 报表模板feign service + * + * @author Gqr + * @since 2024/7/19 11:31 + */ +@FeignClient(name = ApiConstants.NAME) // TODO 晨丰:fallbackFactory = +@Tag(name = "RPC 服务 - 报表模板") +public interface ReportTemplateApi { + String PREFIX = ApiConstants.PREFIX + "/template"; + + @PostMapping(value = PREFIX + "/excel") + @Operation(summary = "下载模板excel") + Response excel(@RequestBody ReportTemplateGenerateReqDTO reqDTO); +} diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/dto/ReportTemplateGenerateReqDTO.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/dto/ReportTemplateGenerateReqDTO.java new file mode 100644 index 000000000..0297253d4 --- /dev/null +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/api/template/dto/ReportTemplateGenerateReqDTO.java @@ -0,0 +1,22 @@ +package com.cf.imes.module.report.api.template.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Map; + +/** + * @author Gqr + * @since 2024/7/19 15:03 + */ +@Schema(description = "RPC 服务 - 报表模板生成 Request DTO") +@Data +public class ReportTemplateGenerateReqDTO { + @Schema(description = "模板id") + @NotNull(message = "模板id不能为空") + private Long templateId; + + @Schema(description = "参数集合") + private Map params; +} diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ApiConstants.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ApiConstants.java new file mode 100644 index 000000000..c6fb3a77f --- /dev/null +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ApiConstants.java @@ -0,0 +1,21 @@ +package com.cf.imes.module.report.enums; + +/** + * API 相关的枚举 + * + * @author 晨丰科技 + */ +public class ApiConstants { + + /** + * 服务名 + * + * 注意,需要保证和 spring.application.name 保持一致 + */ + public static final String NAME = "report-server"; + + public static final String PREFIX = "/admin-api/report"; + + public static final String VERSION = "1.0.0"; + +} diff --git a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java index 5085ebbea..540412f57 100644 --- a/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java +++ b/cf-module-report/cf-module-report-api/src/main/java/com/cf/imes/module/report/enums/ErrorCodeConstants.java @@ -5,18 +5,23 @@ import com.cf.imes.framework.common.exception.ErrorCode; /** * Report 错误码枚举类 - * + *

* report 系统,使用 1-003-000-000 段 */ public interface ErrorCodeConstants { - // ========== UREPORT 模块 1-003-001-000 ========== + // ========== UREPORT template模块 1-003-001-000 ========== ErrorCode TEMPLATE_NOT_EXISTS = new ErrorCode(1_003_001_001, "报表模板信息不存在"); - ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_001_002, "报表数据源不存在"); - ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_001_003, "报表数据源连接失败"); - ErrorCode DATASET_NOT_EXISTS = new ErrorCode(1_003_001_004, "报表数据集不存在"); - ErrorCode DATASET_SQL_INJECTION_RISK = new ErrorCode(1_003_001_005, "存在SQL注入风险"); - ErrorCode DATASET_SQL_REQUIRED = new ErrorCode(1_003_001_006, "SQL语句不能为空"); - ErrorCode DATASET_SQL_ILLEGAL = new ErrorCode(1_003_001_007, "SQL语句非法"); - ErrorCode DATASET_GET_FIELDS_ERROR = new ErrorCode(1_003_001_008, "获取表字段"); + ErrorCode TEMPLATE_GENERATE_EXCEL_ERROR = new ErrorCode(1_003_001_002, "模板excel生成异常"); + + // ========== UREPORT datasource模块 1-003-002-000 ========== + ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_002_001, "报表数据源不存在"); + ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_002_001, "报表数据源连接失败"); + + // ========== UREPORT dataset模块 1-003-003-000 ========== + ErrorCode DATASET_NOT_EXISTS = new ErrorCode(1_003_003_001, "报表数据集不存在"); + ErrorCode DATASET_SQL_INJECTION_RISK = new ErrorCode(1_003_003_002, "存在SQL注入风险"); + ErrorCode DATASET_SQL_REQUIRED = new ErrorCode(1_003_003_003, "SQL语句不能为空"); + ErrorCode DATASET_SQL_ILLEGAL = new ErrorCode(1_003_003_004, "SQL语句非法"); + ErrorCode DATASET_GET_FIELDS_ERROR = new ErrorCode(1_003_003_005, "获取表字段"); } diff --git a/cf-module-report/cf-module-report-biz/pom.xml b/cf-module-report/cf-module-report-biz/pom.xml index 84ad88f49..e52949f46 100644 --- a/cf-module-report/cf-module-report-biz/pom.xml +++ b/cf-module-report/cf-module-report-biz/pom.xml @@ -130,6 +130,35 @@ commons-text ${commons-text.version} + + + com.cf.imes + cf-module-prod-executor-api + ${revision} + + + + org.apache.poi + poi-ooxml-full + ${poi-ooxml-full.version} + + + org.apache.poi + poi-ooxml + + + org.apache.poi + poi-ooxml-lite + + + ${poi-ooxml.version} + + + com.itextpdf + itextpdf + ${itextpdf.version} + + diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java index bb7be9dd6..ebae14f18 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/ReportServerApplication.java @@ -1,7 +1,9 @@ package com.cf.imes.module.report; +import com.bstek.common.config.DataSourceConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; /** * 项目的启动类 @@ -9,6 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @author 晨丰 */ @SpringBootApplication +@Import({DataSourceConfig.class}) public class ReportServerApplication { public static void main(String[] args) { diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java index 882e94e09..12e14ef09 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java @@ -6,7 +6,6 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; @@ -32,12 +31,14 @@ public class ReportDatasetSaveReqVO implements Serializable { private String name; @Schema(description = "数据源id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "数据源id不能为空") private Long datasourceId; @Schema(description = "动态查询SQL") private String sql; + @Schema(description = "bean数据源方法名") + private String method; + @Schema(description = "参数列表") private List parameters = new ArrayList<>(); diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java index 883d9c02d..f0ad81190 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java @@ -31,7 +31,6 @@ public class ReportDatasourceSaveReqVO implements Serializable { private Long id; @Schema(description = "模板id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "模板id不能为空") private Long templateId; @Schema(description = "数据源名称", example = "测试库") diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java index 209a0cd3c..877aafd5d 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/ReportTemplateController.java @@ -1,9 +1,13 @@ package com.cf.imes.module.report.controller.admin.template; import com.bstek.designer.bean.ReportDefinitionWrapper; +import com.bstek.ureport.export.ExportUtils; +import com.bstek.ureport.export.ProducerEnum; import com.bstek.ureport.export.html.HtmlReport; +import com.bstek.ureport.model.Report; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplatePreviewPageParametersVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateRespVO; @@ -12,13 +16,17 @@ import com.cf.imes.module.report.service.template.ReportTemplateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.io.OutputStream; import java.util.List; import static com.cf.imes.framework.common.pojo.CommonResult.success; @@ -33,6 +41,7 @@ import static com.cf.imes.framework.common.pojo.CommonResult.success; @RestController @RequestMapping("/report") @Validated +@Slf4j public class ReportTemplateController { @Autowired private ReportTemplateService templateService; @@ -62,7 +71,7 @@ public class ReportTemplateController { } @GetMapping("/template/{id}") - @Operation(summary = "获得报表模板信息") + @Operation(summary = "获取报表模板信息") @Parameter(name = "id", description = "编号", required = true, example = "1") @PreAuthorize("@ss.hasPermission('report:template:query')") public CommonResult getReportTemplate(@PathVariable("id") Long id) { @@ -70,7 +79,7 @@ public class ReportTemplateController { } @GetMapping("/templates") - @Operation(summary = "获得报表模板信息列表") + @Operation(summary = "获取报表模板信息列表") @PreAuthorize("@ss.hasPermission('report:template:query')") public CommonResult> getTemplatePage(@RequestParam(value = "name", required = false) String name) { ReportTemplateReqVO reqVO = new ReportTemplateReqVO(name, null); @@ -83,4 +92,20 @@ public class ReportTemplateController { public CommonResult preview(@Valid @RequestBody ReportTemplatePreviewPageParametersVO pageParametersVO) { return success(templateService.preview(pageParametersVO)); } + + @PostMapping("/template/excel") + @Operation(summary = "模板导出") + @PreAuthorize("@ss.hasPermission('report:template:query')") + public void generateExcel(@RequestBody ReportTemplateGenerateReqDTO reqDTO, HttpServletResponse response) { + OutputStream out = null; + try { + Report report = templateService.generateReport(reqDTO); + out = response.getOutputStream(); + ExportUtils.export(out, report, ProducerEnum.EXCEL); + } catch (Exception ex) { + log.error("[generateExcel] 报表模板生成excel异常", ex); + } finally { + IOUtils.closeQuietly(out); + } + } } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/rpc/config/RpcConfiguration.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/rpc/config/RpcConfiguration.java new file mode 100644 index 000000000..03a4b3da0 --- /dev/null +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/rpc/config/RpcConfiguration.java @@ -0,0 +1,11 @@ +package com.cf.imes.module.report.framework.rpc.config; + +import com.cf.imes.module.executor.api.datasource.OrderDatasourceApi; +import com.cf.imes.module.executor.api.datasource.OrderPlateDatasourceApi; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +@EnableFeignClients(clients = {OrderPlateDatasourceApi.class, OrderDatasourceApi.class}) +public class RpcConfiguration { +} diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java new file mode 100644 index 000000000..005f58364 --- /dev/null +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/bean/OrderSummaryBeanDatasource.java @@ -0,0 +1,113 @@ +package com.cf.imes.module.report.framework.ureport.bean; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.module.executor.api.datasource.OrderDatasourceApi; +import com.cf.imes.module.executor.api.datasource.OrderPlateDatasourceApi; +import com.cf.imes.module.executor.api.datasource.dto.OrderDTO; +import com.cf.imes.module.executor.api.datasource.dto.PlateGoodsRespDTO; +import com.cf.imes.module.report.framework.ureport.annotation.CfReportSpringbeanDatasource; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Gqr + * @since 2024/7/19 14:41 + */ +@CfReportSpringbeanDatasource(value = "OrderSummaryBeanDatasource", name = "生产单导出统计数据源") +@Slf4j +public class OrderSummaryBeanDatasource { + + @Resource + private OrderPlateDatasourceApi orderPlateDatasourceApi; + + @Resource + private OrderDatasourceApi orderDatasourceApi; + + /** + * 生产单信息 + * + * @param dsName + * @param datasetName + * @param parameters + * @return + */ + public List> orderInfo(String dsName, String datasetName, Map parameters) { + List> resultList = new ArrayList<>(); + + Object orderId = parameters.get("orderId"); + if (ObjectUtil.isNull(orderId)) { + + return resultList; + } + + CommonResult commonResult = orderDatasourceApi.getOrderInfo(Long.parseLong(orderId.toString())); + OrderDTO orderDTO = commonResult.getData(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if (orderDTO != null) { + // 把orderInfo转map并put到resultList中 + resultList.add(new HashMap<>() {{ + // 构造报表所需结构 + put("orderId", orderDTO.getId()); + put("customOrderNo", orderDTO.getCustomOrderNo()); + put("dealer", orderDTO.getDealer()); + LocalDateTime orderDate = orderDTO.getOrderDate(); + put("orderDate", ObjectUtil.isNotNull(orderDate) ? formatter.format(orderDate) : null); + LocalDateTime deliveryDate = orderDTO.getDeliveryDate(); + put("deliveryDate", ObjectUtil.isNotNull(deliveryDate) ? formatter.format(deliveryDate) : null); + put("customer", orderDTO.getCustomer()); + put("phoneNumber", orderDTO.getPhoneNumber()); + }}); + } + return resultList; + } + + /** + * 板材汇总-按板材 + * + * @param dsName + * @param datasetName + * @param parameters + * @return + */ + public List> orderPlateSummaryByPlate(String dsName, String datasetName, Map parameters) { + List> resultList = new ArrayList<>(); + + Object orderId = parameters.get("orderId"); + // 查询统计信息 + CommonResult> commonResult = orderPlateDatasourceApi.selectPlateGoodsListSummary(Long.parseLong(orderId.toString())); + List plateGoodsRespDTOS = commonResult.getData(); + + if (CollUtil.isNotEmpty(plateGoodsRespDTOS)) { + plateGoodsRespDTOS.forEach(p -> { + resultList.add(new HashMap<>() {{ + BigDecimal area = p.getArea(); + Integer count = p.getCount(); + // 构造报表所需结构 + put("roomName", p.getRoomName()); + put("bodyName", p.getBodyName()); + put("thickness", p.getThickness()); + put("name", p.getName()); + put("height", p.getHeight()); + put("width", p.getWidth()); + put("count", count); + put("area", area); + put("openDoorType", p.getOpenDoorType()); + put("remark", p.getRemark()); + put("areaAll", area.multiply(BigDecimal.valueOf(count))); + }}); + }); + } + return resultList; + } +} diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java index 907477896..4854d7d04 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/framework/ureport/config/CfReportSpringbeanRegistrar.java @@ -35,10 +35,16 @@ public class CfReportSpringbeanRegistrar implements ImportBeanDefinitionRegistra AnnotatedBeanDefinition beanDef = (AnnotatedBeanDefinition) candidate; Map attributes = beanDef.getMetadata().getAnnotationAttributes(CfReportSpringbeanDatasource.class.getName()); if (attributes != null) { + // 校验注解上的value String value = (String) attributes.get("value"); if (!StringUtils.hasText(value)) { throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'value' attribute."); } + // 校验注解上的name + String name = (String) attributes.get("name"); + if (!StringUtils.hasText(name)) { + throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'name' attribute."); + } BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(candidate.getBeanClassName()); registry.registerBeanDefinition(value, builder.getBeanDefinition()); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java index dbf45136f..f7b652091 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateService.java @@ -2,6 +2,8 @@ package com.cf.imes.module.report.service.template; import com.bstek.designer.bean.ReportDefinitionWrapper; import com.bstek.ureport.export.html.HtmlReport; +import com.bstek.ureport.model.Report; +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplatePreviewPageParametersVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; @@ -56,7 +58,7 @@ public interface ReportTemplateService { ReportDefinitionWrapper getReportTemplateDefinition(Long id); /** - * 获得报表模板信息列表 + * 获取报表模板信息列表 * * @param pageReqVO 查询参数 * @return 报表模板信息列表 @@ -70,4 +72,13 @@ public interface ReportTemplateService { * @return */ HtmlReport preview(ReportTemplatePreviewPageParametersVO pageParametersVO); + + + /** + * 构造生成报表report对象 + * + * @param dto + * @return + */ + Report generateReport(ReportTemplateGenerateReqDTO dto); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java index c696a9e4f..e7b15fdce 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java @@ -26,6 +26,7 @@ import com.bstek.ureport.model.Report; import com.bstek.ureport.parser.ReportParser; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetReqVO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO; @@ -99,14 +100,14 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { private void analyzeDatasource(List datasource, Long templateId) { datasource.forEach(ds -> { // 更新/新增数据源 + Long datasourceId; if (ObjectUtil.isNotNull(ds.getId())) { + datasourceId = ds.getId(); datasourceService.updateDatasource(ds); } else { ds.setTemplateId(templateId); - datasourceService.createDatasource(ds); + datasourceId = datasourceService.createDatasource(ds); } - // 获取自增数据源主键 - Long datasourceId = ds.getId(); List datasets = ds.getDatasets(); List batchInsertDataset = new ArrayList<>(); List batchupdateDataset = new ArrayList<>(); @@ -239,7 +240,7 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { HtmlReport htmlReport = new HtmlReport(); // 转换ureport参数 - PreviewPageParameters pageParameters = BeanUtils.toBean(pageParametersVO,PreviewPageParameters.class); + PreviewPageParameters pageParameters = BeanUtils.toBean(pageParametersVO, PreviewPageParameters.class); PreviewParameters params = pageParameters.getParams(); // 解析xml @@ -270,7 +271,7 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { htmlReport.setChartDatas(report.getContext().getChartDataMap().values()); htmlReport.setContent(html); htmlReport.setStyle(reportDefinition.getStyle()); - SearchFormData searchFormData = reportDefinition.buildSearchFormData(report.getContext().getDatasetMap(),parameters); + SearchFormData searchFormData = reportDefinition.buildSearchFormData(report.getContext().getDatasetMap(), parameters); htmlReport.setSearchFormData(searchFormData); htmlReport.setReportAlign(report.getPaper().getHtmlReportAlign().name()); htmlReport.setBgImage(report.getPaper().getBgImage()); @@ -278,4 +279,19 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { htmlReport.setFloatImages(reportDefinition.getFloatImages()); return htmlReport; } + + @Override + public Report generateReport(ReportTemplateGenerateReqDTO reqDTO) { + // 查询模板 + ReportTemplateDO template = templateMapper.selectById(reqDTO.getTemplateId()); + String xmlContent = template.getContent(); + ReportRender reportRender = new ReportRender(); + // 解析xml + ReportDefinition reportDefinition = reportRender.getReportDefinition(xmlContent, CharsetUtil.UTF_8); + // 设置参数 + PreviewParameters previewParameters = new PreviewParameters(); + previewParameters.setQuery(reqDTO.getParams()); + + return reportRender.render(reportDefinition, previewParameters.getQuery()); + } } diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar index 7f66b483dac8d7dbfe2d12094ed26d27af5c539c..e3b1628bb38d00e03030d27ec92fe94d86f340d1 100644 GIT binary patch delta 36697 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 K{0VIGFaQAb>AaHw delta 36790 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.11.0 4.5.3 1.10.0 + 5.2.0 + 5.2.2 + 5.5.13