报表基础模块:板材汇总-按板材报表excel导出实现:exec微服务rpc接口、report微服务rpc接口实现;

This commit is contained in:
gaoqr
2024-07-23 11:23:41 +08:00
parent d9999377c9
commit 9f7f4aba72
25 changed files with 716 additions and 22 deletions
@@ -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<OrderDTO> getOrderInfo(@RequestParam("orderId") Long orderId);
}
@@ -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<List<PlateGoodsRespDTO>> selectPlateGoodsListSummary(@RequestParam("orderId") Long orderId);
}
@@ -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;
}
@@ -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;
}
@@ -151,7 +151,11 @@
<groupId>uk.co.jemos.podam</groupId> <groupId>uk.co.jemos.podam</groupId>
<artifactId>podam</artifactId> <artifactId>podam</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.cf.imes</groupId>
<artifactId>cf-module-report-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- JSON --> <!-- JSON -->
<dependency> <dependency>
@@ -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<OrderDTO> getOrderInfo(Long orderId) {
// 查询生产单
OrderDO orderDO = orderMapper.selectOrderOne(orderId, OrganContextHolder.getOrganId());
OrderDTO orderDTO = BeanUtils.toBean(orderDO, OrderDTO.class);
return CommonResult.success(orderDTO);
}
}
@@ -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<List<PlateGoodsRespDTO>> selectPlateGoodsListSummary(Long orderId) {
// 查询分组统计
Integer notDeletedStatus = OrderDeletedEnum.NOT_DELETED.getStatus();
List<PlateGoodsRespVO> plateGoodsRespVOS = plateMapper.selectPlateGoodsListSummary(orderId, SecurityFrameworkUtils.getLoginUser().getOrganId(), notDeletedStatus);
return CommonResult.success(BeanUtils.toBean(plateGoodsRespVOS, PlateGoodsRespDTO.class));
}
}
@@ -1,6 +1,7 @@
package com.cf.imes.module.executor.framework.rpc.config; package com.cf.imes.module.executor.framework.rpc.config;
import com.cf.imes.module.infra.api.file.FileApi; 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.application.ApplicationApi;
import com.cf.imes.module.system.api.dataSource.DataSourceApi; import com.cf.imes.module.system.api.dataSource.DataSourceApi;
import com.cf.imes.module.system.api.machine.MachineApi; import com.cf.imes.module.system.api.machine.MachineApi;
@@ -16,6 +17,6 @@ import org.springframework.context.annotation.Configuration;
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EnableFeignClients(clients = {AdminUserApi.class, MachineApi.class, DictDataApi.class, @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 { public class RpcConfiguration {
} }
@@ -22,5 +22,26 @@
<groupId>com.cf.imes</groupId> <groupId>com.cf.imes</groupId>
<artifactId>cf-common</artifactId> <artifactId>cf-common</artifactId>
</dependency> </dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<scope>provided</scope>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
</project> </project>
@@ -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);
}
@@ -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<String, Object> params;
}
@@ -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";
}
@@ -5,18 +5,23 @@ import com.cf.imes.framework.common.exception.ErrorCode;
/** /**
* Report 错误码枚举类 * Report 错误码枚举类
* * <p>
* report 系统,使用 1-003-000-000 段 * report 系统,使用 1-003-000-000 段
*/ */
public interface ErrorCodeConstants { 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 TEMPLATE_NOT_EXISTS = new ErrorCode(1_003_001_001, "报表模板信息不存在");
ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_001_002, "报表数据源不存在"); ErrorCode TEMPLATE_GENERATE_EXCEL_ERROR = new ErrorCode(1_003_001_002, "模板excel生成异常");
ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_001_003, "报表数据源连接失败");
ErrorCode DATASET_NOT_EXISTS = new ErrorCode(1_003_001_004, "报表数据集不存在"); // ========== UREPORT datasource模块 1-003-002-000 ==========
ErrorCode DATASET_SQL_INJECTION_RISK = new ErrorCode(1_003_001_005, "存在SQL注入风险"); ErrorCode DATASOURCE_NOT_EXISTS = new ErrorCode(1_003_002_001, "报表数据源不存在");
ErrorCode DATASET_SQL_REQUIRED = new ErrorCode(1_003_001_006, "SQL语句不能为空"); ErrorCode DATASOURCE_CONNECT_FAIL = new ErrorCode(1_003_002_001, "报表数据源连接失败");
ErrorCode DATASET_SQL_ILLEGAL = new ErrorCode(1_003_001_007, "SQL语句非法");
ErrorCode DATASET_GET_FIELDS_ERROR = new ErrorCode(1_003_001_008, "获取表字段"); // ========== 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, "获取表字段");
} }
@@ -130,6 +130,35 @@
<artifactId>commons-text</artifactId> <artifactId>commons-text</artifactId>
<version>${commons-text.version}</version> <version>${commons-text.version}</version>
</dependency> </dependency>
<!-- executor feign 远程调用-->
<dependency>
<groupId>com.cf.imes</groupId>
<artifactId>cf-module-prod-executor-api</artifactId>
<version>${revision}</version>
</dependency>
<!--ureport-core 相关start-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId>
<version>${poi-ooxml-full.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-lite</artifactId>
</exclusion>
</exclusions>
<version>${poi-ooxml.version}</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>${itextpdf.version}</version>
</dependency>
<!--ureport-core 相关end-->
</dependencies> </dependencies>
<build> <build>
<!-- 设置构建的 jar 包名 --> <!-- 设置构建的 jar 包名 -->
@@ -1,7 +1,9 @@
package com.cf.imes.module.report; package com.cf.imes.module.report;
import com.bstek.common.config.DataSourceConfig;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
/** /**
* 项目的启动类 * 项目的启动类
@@ -9,6 +11,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @author 晨丰 * @author 晨丰
*/ */
@SpringBootApplication @SpringBootApplication
@Import({DataSourceConfig.class})
public class ReportServerApplication { public class ReportServerApplication {
public static void main(String[] args) { public static void main(String[] args) {
@@ -6,7 +6,6 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
@@ -32,12 +31,14 @@ public class ReportDatasetSaveReqVO implements Serializable {
private String name; private String name;
@Schema(description = "数据源id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "数据源id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "数据源id不能为空")
private Long datasourceId; private Long datasourceId;
@Schema(description = "动态查询SQL") @Schema(description = "动态查询SQL")
private String sql; private String sql;
@Schema(description = "bean数据源方法名")
private String method;
@Schema(description = "参数列表") @Schema(description = "参数列表")
private List<ReportDatasetParameterVO> parameters = new ArrayList<>(); private List<ReportDatasetParameterVO> parameters = new ArrayList<>();
@@ -31,7 +31,6 @@ public class ReportDatasourceSaveReqVO implements Serializable {
private Long id; private Long id;
@Schema(description = "模板id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "模板id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "模板id不能为空")
private Long templateId; private Long templateId;
@Schema(description = "数据源名称", example = "测试库") @Schema(description = "数据源名称", example = "测试库")
@@ -1,9 +1,13 @@
package com.cf.imes.module.report.controller.admin.template; package com.cf.imes.module.report.controller.admin.template;
import com.bstek.designer.bean.ReportDefinitionWrapper; 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.export.html.HtmlReport;
import com.bstek.ureport.model.Report;
import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.util.object.BeanUtils; 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.ReportTemplatePreviewPageParametersVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateRespVO; 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.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; 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.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.OutputStream;
import java.util.List; import java.util.List;
import static com.cf.imes.framework.common.pojo.CommonResult.success; 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 @RestController
@RequestMapping("/report") @RequestMapping("/report")
@Validated @Validated
@Slf4j
public class ReportTemplateController { public class ReportTemplateController {
@Autowired @Autowired
private ReportTemplateService templateService; private ReportTemplateService templateService;
@@ -62,7 +71,7 @@ public class ReportTemplateController {
} }
@GetMapping("/template/{id}") @GetMapping("/template/{id}")
@Operation(summary = "报表模板信息") @Operation(summary = "报表模板信息")
@Parameter(name = "id", description = "编号", required = true, example = "1") @Parameter(name = "id", description = "编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('report:template:query')") @PreAuthorize("@ss.hasPermission('report:template:query')")
public CommonResult<ReportDefinitionWrapper> getReportTemplate(@PathVariable("id") Long id) { public CommonResult<ReportDefinitionWrapper> getReportTemplate(@PathVariable("id") Long id) {
@@ -70,7 +79,7 @@ public class ReportTemplateController {
} }
@GetMapping("/templates") @GetMapping("/templates")
@Operation(summary = "报表模板信息列表") @Operation(summary = "报表模板信息列表")
@PreAuthorize("@ss.hasPermission('report:template:query')") @PreAuthorize("@ss.hasPermission('report:template:query')")
public CommonResult<List<ReportTemplateRespVO>> getTemplatePage(@RequestParam(value = "name", required = false) String name) { public CommonResult<List<ReportTemplateRespVO>> getTemplatePage(@RequestParam(value = "name", required = false) String name) {
ReportTemplateReqVO reqVO = new ReportTemplateReqVO(name, null); ReportTemplateReqVO reqVO = new ReportTemplateReqVO(name, null);
@@ -83,4 +92,20 @@ public class ReportTemplateController {
public CommonResult<HtmlReport> preview(@Valid @RequestBody ReportTemplatePreviewPageParametersVO pageParametersVO) { public CommonResult<HtmlReport> preview(@Valid @RequestBody ReportTemplatePreviewPageParametersVO pageParametersVO) {
return success(templateService.preview(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);
}
}
} }
@@ -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 {
}
@@ -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<Map<String, Object>> orderInfo(String dsName, String datasetName, Map<String, Object> parameters) {
List<Map<String, Object>> resultList = new ArrayList<>();
Object orderId = parameters.get("orderId");
if (ObjectUtil.isNull(orderId)) {
return resultList;
}
CommonResult<OrderDTO> 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<Map<String, Object>> orderPlateSummaryByPlate(String dsName, String datasetName, Map<String, Object> parameters) {
List<Map<String, Object>> resultList = new ArrayList<>();
Object orderId = parameters.get("orderId");
// 查询统计信息
CommonResult<List<PlateGoodsRespDTO>> commonResult = orderPlateDatasourceApi.selectPlateGoodsListSummary(Long.parseLong(orderId.toString()));
List<PlateGoodsRespDTO> 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;
}
}
@@ -35,10 +35,16 @@ public class CfReportSpringbeanRegistrar implements ImportBeanDefinitionRegistra
AnnotatedBeanDefinition beanDef = (AnnotatedBeanDefinition) candidate; AnnotatedBeanDefinition beanDef = (AnnotatedBeanDefinition) candidate;
Map<String, Object> attributes = beanDef.getMetadata().getAnnotationAttributes(CfReportSpringbeanDatasource.class.getName()); Map<String, Object> attributes = beanDef.getMetadata().getAnnotationAttributes(CfReportSpringbeanDatasource.class.getName());
if (attributes != null) { if (attributes != null) {
// 校验注解上的value
String value = (String) attributes.get("value"); String value = (String) attributes.get("value");
if (!StringUtils.hasText(value)) { if (!StringUtils.hasText(value)) {
throw new IllegalArgumentException("@CfReportSpringbean requires a non-empty 'value' attribute."); 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()); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(candidate.getBeanClassName());
registry.registerBeanDefinition(value, builder.getBeanDefinition()); registry.registerBeanDefinition(value, builder.getBeanDefinition());
} }
@@ -2,6 +2,8 @@ package com.cf.imes.module.report.service.template;
import com.bstek.designer.bean.ReportDefinitionWrapper; import com.bstek.designer.bean.ReportDefinitionWrapper;
import com.bstek.ureport.export.html.HtmlReport; 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.ReportTemplatePreviewPageParametersVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO;
@@ -56,7 +58,7 @@ public interface ReportTemplateService {
ReportDefinitionWrapper getReportTemplateDefinition(Long id); ReportDefinitionWrapper getReportTemplateDefinition(Long id);
/** /**
* 获报表模板信息列表 * 获报表模板信息列表
* *
* @param pageReqVO 查询参数 * @param pageReqVO 查询参数
* @return 报表模板信息列表 * @return 报表模板信息列表
@@ -70,4 +72,13 @@ public interface ReportTemplateService {
* @return * @return
*/ */
HtmlReport preview(ReportTemplatePreviewPageParametersVO pageParametersVO); HtmlReport preview(ReportTemplatePreviewPageParametersVO pageParametersVO);
/**
* 构造生成报表report对象
*
* @param dto
* @return
*/
Report generateReport(ReportTemplateGenerateReqDTO dto);
} }
@@ -26,6 +26,7 @@ import com.bstek.ureport.model.Report;
import com.bstek.ureport.parser.ReportParser; import com.bstek.ureport.parser.ReportParser;
import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; 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.ReportDatasetReqVO;
import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveReqVO; import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveReqVO;
import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO; import com.cf.imes.module.report.controller.admin.datasource.vo.ReportDatasourceReqVO;
@@ -99,14 +100,14 @@ public class ReportTemplateServiceImpl implements ReportTemplateService {
private void analyzeDatasource(List<ReportDatasourceSaveReqVO> datasource, Long templateId) { private void analyzeDatasource(List<ReportDatasourceSaveReqVO> datasource, Long templateId) {
datasource.forEach(ds -> { datasource.forEach(ds -> {
// 更新/新增数据源 // 更新/新增数据源
Long datasourceId;
if (ObjectUtil.isNotNull(ds.getId())) { if (ObjectUtil.isNotNull(ds.getId())) {
datasourceId = ds.getId();
datasourceService.updateDatasource(ds); datasourceService.updateDatasource(ds);
} else { } else {
ds.setTemplateId(templateId); ds.setTemplateId(templateId);
datasourceService.createDatasource(ds); datasourceId = datasourceService.createDatasource(ds);
} }
// 获取自增数据源主键
Long datasourceId = ds.getId();
List<ReportDatasetSaveReqVO> datasets = ds.getDatasets(); List<ReportDatasetSaveReqVO> datasets = ds.getDatasets();
List<ReportDatasetSaveReqVO> batchInsertDataset = new ArrayList<>(); List<ReportDatasetSaveReqVO> batchInsertDataset = new ArrayList<>();
List<ReportDatasetSaveReqVO> batchupdateDataset = new ArrayList<>(); List<ReportDatasetSaveReqVO> batchupdateDataset = new ArrayList<>();
@@ -278,4 +279,19 @@ public class ReportTemplateServiceImpl implements ReportTemplateService {
htmlReport.setFloatImages(reportDefinition.getFloatImages()); htmlReport.setFloatImages(reportDefinition.getFloatImages());
return htmlReport; 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());
}
} }
+3
View File
@@ -26,5 +26,8 @@
<commons-io.version>2.11.0</commons-io.version> <commons-io.version>2.11.0</commons-io.version>
<antlr4.version>4.5.3</antlr4.version> <antlr4.version>4.5.3</antlr4.version>
<commons-text.version>1.10.0</commons-text.version> <commons-text.version>1.10.0</commons-text.version>
<poi-ooxml-full.version>5.2.0</poi-ooxml-full.version>
<poi-ooxml.version>5.2.2</poi-ooxml.version>
<itextpdf.version>5.5.13</itextpdf.version>
</properties> </properties>
</project> </project>