报表基础模块:1、模拟前端保存、获取模板列表、查询模板详情接口对接及啊对应字段的调整;2、移除没用部分引用和代码(积木等);

This commit is contained in:
gaoqr
2024-07-11 16:00:22 +08:00
parent 129f919405
commit f75cf19fdc
48 changed files with 396 additions and 940 deletions
+1 -13
View File
@@ -14,8 +14,7 @@
<name>${project.artifactId}</name>
<description>
report 模块,主要实现数据可视化报表等功能
1. 基于「积木报表」实现,打印设计、报表设计、图形设计、大屏设计等。
report 模块,主要实现数据可视化报表等功能
</description>
<dependencies>
<!-- Spring Cloud 基础 -->
@@ -104,17 +103,6 @@
<artifactId>cf-spring-boot-starter-monitor</artifactId>
</dependency>
<!-- 积木报表-->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
</dependency>
<!-- 单独依赖升级版本,解决低版本validator失败问题 -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
@@ -1 +0,0 @@
package com.cf.imes.module.report.controller.admin.ajreport;
@@ -1,69 +0,0 @@
package com.cf.imes.module.report.controller.admin.goview;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.report.controller.admin.goview.vo.data.GoViewDataGetBySqlReqVO;
import com.cf.imes.module.report.controller.admin.goview.vo.data.GoViewDataRespVO;
import com.cf.imes.module.report.service.goview.GoViewDataService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import java.util.*;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - GoView 数据", description = "提供 SQL、HTTP 等数据查询的能力")
@RestController
@RequestMapping("/report/go-view/data")
@Validated
public class GoViewDataController {
@Resource
private GoViewDataService goViewDataService;
@RequestMapping("/get-by-sql")
@Operation(summary = "使用 SQL 查询数据")
@PreAuthorize("@ss.hasPermission('report:go-view-data:get-by-sql')")
@OperateLog(enable = false) // 不记录操作日志,因为不需要
public CommonResult<GoViewDataRespVO> getDataBySQL(@Valid @RequestBody GoViewDataGetBySqlReqVO reqVO) {
return success(goViewDataService.getDataBySQL(reqVO.getSql()));
}
@RequestMapping("/get-by-http")
@Operation(summary = "使用 HTTP 查询数据", description = "这个只是示例接口,实际应该每个查询,都要写一个接口")
@PreAuthorize("@ss.hasPermission('report:go-view-data:get-by-http')")
@OperateLog(enable = false) // 不记录操作日志,因为不需要
public CommonResult<GoViewDataRespVO> getDataByHttp(
@RequestParam(required = false) Map<String, String> params,
@RequestBody(required = false) String body) { // params、body 按照需要去接收,这里仅仅是示例
GoViewDataRespVO respVO = new GoViewDataRespVO();
// 1. 数据维度
respVO.setDimensions(Arrays.asList("日期", "PV", "UV")); // PV 是每天访问次数;UV 是每天访问人数
// 2. 明细数据列表
// 目前通过随机的方式生成。一般来说,这里你可以写逻辑来实现数据的返回
respVO.setSource(new LinkedList<>());
for (int i = 1; i <= 12; i++) {
String date = "2021-" + (i < 10 ? "0" + i : i);
Integer pv = RandomUtil.randomInt(1000, 10000);
Integer uv = RandomUtil.randomInt(100, 1000);
respVO.getSource().add(MapUtil.<String, Object>builder().put("日期", date)
.put("PV", pv).put("UV", uv).build());
}
return success(respVO);
}
}
@@ -1,76 +0,0 @@
package com.cf.imes.module.report.controller.admin.goview;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectRespVO;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
import com.cf.imes.module.report.convert.goview.GoViewProjectConvert;
import com.cf.imes.module.report.dal.dataobject.goview.GoViewProjectDO;
import com.cf.imes.module.report.service.goview.GoViewProjectService;
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.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - GoView 项目")
@RestController
@RequestMapping("/report/go-view/project")
@Validated
public class GoViewProjectController {
@Resource
private GoViewProjectService goViewProjectService;
@PostMapping("/create")
@Operation(summary = "创建项目")
@PreAuthorize("@ss.hasPermission('report:go-view-project:create')")
public CommonResult<Long> createProject(@Valid @RequestBody GoViewProjectCreateReqVO createReqVO) {
return success(goViewProjectService.createProject(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新项目")
@PreAuthorize("@ss.hasPermission('report:go-view-project:update')")
public CommonResult<Boolean> updateProject(@Valid @RequestBody GoViewProjectUpdateReqVO updateReqVO) {
goViewProjectService.updateProject(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除 GoView 项目")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('report:go-view-project:delete')")
public CommonResult<Boolean> deleteProject(@RequestParam("id") Long id) {
goViewProjectService.deleteProject(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得项目")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('report:go-view-project:query')")
public CommonResult<GoViewProjectRespVO> getProject(@RequestParam("id") Long id) {
GoViewProjectDO project = goViewProjectService.getProject(id);
return success(GoViewProjectConvert.INSTANCE.convert(project));
}
@GetMapping("/my-page")
@Operation(summary = "获得我的项目分页")
@PreAuthorize("@ss.hasPermission('report:go-view-project:query')")
public CommonResult<PageResult<GoViewProjectRespVO>> getMyProjectPage(@Valid PageParam pageVO) {
PageResult<GoViewProjectDO> pageResult = goViewProjectService.getMyProjectPage(
pageVO, getLoginUserId());
return success(GoViewProjectConvert.INSTANCE.convertPage(pageResult));
}
}
@@ -1,16 +0,0 @@
package com.cf.imes.module.report.controller.admin.goview.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
@Schema(description = "管理后台 - GoView 使用 SQL 查询数据 Request VO")
@Data
public class GoViewDataGetBySqlReqVO {
@Schema(description = "SQL 语句", requiredMode = Schema.RequiredMode.REQUIRED, example = "SELECT * FROM user")
@NotEmpty(message = "SQL 语句不能为空")
private String sql;
}
@@ -1,19 +0,0 @@
package com.cf.imes.module.report.controller.admin.goview.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Schema(description = "管理后台 - GoView 数据 Response VO")
@Data
public class GoViewDataRespVO {
@Schema(description = "数据维度", requiredMode = Schema.RequiredMode.REQUIRED, example = "['product', 'data1', 'data2']")
private List<String> dimensions;
@Schema(description = "数据明细列表", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Map<String, Object>> source;
}
@@ -1,15 +0,0 @@
package com.cf.imes.module.report.controller.admin.goview.vo.project;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - GoView 项目创建 Request VO")
@Data
public class GoViewProjectCreateReqVO {
@Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
@NotEmpty(message = "项目名称不能为空")
private String name;
}
@@ -1,36 +0,0 @@
package com.cf.imes.module.report.controller.admin.goview.vo.project;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - GoView 项目 Response VO")
@Data
public class GoViewProjectRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18993")
private Long id;
@Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
private String name;
@Schema(description = "发布状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "报表内容") // JSON 格式
private String content;
@Schema(description = "预览图片 URL", example = "https://www.iocoder.cn")
private String picUrl;
@Schema(description = "项目备注", example = "你猜")
private String remark;
@Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String creator;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -1,34 +0,0 @@
package com.cf.imes.module.report.controller.admin.goview.vo.project;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - GoView 项目更新 Request VO")
@Data
public class GoViewProjectUpdateReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18993")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
private String name;
@Schema(description = "发布状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(value = CommonStatusEnum.class, message = "发布状态必须是 {value}")
private Integer status;
@Schema(description = "报表内容") // JSON 格式
private String content;
@Schema(description = "预览图片 URL", example = "https://www.iocoder.cn")
private String picUrl;
@Schema(description = "项目备注", example = "你猜")
private String remark;
}
@@ -2,7 +2,6 @@ package com.cf.imes.module.report.controller.admin.template;
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.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.ReportTemplateSaveReqVO;
@@ -40,7 +39,6 @@ public class ReportTemplateController {
@Operation(summary = "创建报表模板信息")
@PreAuthorize("@ss.hasPermission('report:template:create')")
public CommonResult<Long> createTemplate(@Valid @RequestBody ReportTemplateSaveReqVO createReqVO) {
OrganContextHolder.setOrganId(1L);
return success(templateService.createReportTemplate(createReqVO));
}
@@ -73,9 +71,8 @@ public class ReportTemplateController {
@GetMapping("/templates")
@Operation(summary = "获得报表模板信息列表")
@PreAuthorize("@ss.hasPermission('report:template:query')")
public CommonResult<List<ReportTemplateRespVO>> getTemplatePage(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "type", required = false) Integer type) {
ReportTemplateReqVO reqVO = new ReportTemplateReqVO(name, type);
public CommonResult<List<ReportTemplateRespVO>> getTemplatePage(@RequestParam(value = "name", required = false) String name) {
ReportTemplateReqVO reqVO = new ReportTemplateReqVO(name, null);
return success(BeanUtils.toBean(templateService.getReportTemplateList(reqVO), ReportTemplateRespVO.class));
}
}
@@ -0,0 +1,26 @@
package com.cf.imes.module.report.controller.admin.template.vo;
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;
/**
* @author Gqr
* @since 2024/7/8 11:36
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReportDatasetFieldVO implements Serializable {
@Serial
private static final long serialVersionUID = 8325596134986873011L;
/**
* 字段名称
*/
@Schema(description = "字段名称")
private String name;
}
@@ -1,9 +1,13 @@
package com.cf.imes.module.report.controller.admin.template.vo;
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;
/**
* @author Gqr
* @since 2024/7/8 11:36
@@ -11,19 +15,24 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReportDatasetParameterVO {
public class ReportDatasetParameterVO implements Serializable {
@Serial
private static final long serialVersionUID = 2752387952196201725L;
/**
* 参数名称
*/
@Schema(description = "参数名称")
private String name;
/**
* 类型
*/
private Integer type;
@Schema(description = "参数类型")
private String type;
/**
* 默认值
*/
@Schema(description = "参数默认值")
private String defaultValue;
}
@@ -2,6 +2,7 @@ package com.cf.imes.module.report.controller.admin.template.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@@ -13,6 +14,7 @@ import lombok.ToString;
@Schema(description = "管理后台 - 报表数据集 Request VO")
@Data
@ToString(callSuper = true)
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReportDatasetReqVO {
@@ -27,11 +27,14 @@ public class ReportDatasetRespVO {
private Long datasourceId;
@Schema(description = "动态查询SQL")
private String dbSql;
@Schema(description = "参数列表")
private List<ReportDatasetParameterVO> params;
private String sql;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "参数列表")
private List<ReportDatasetParameterVO> parameters;
@Schema(description = "字段列表")
private List<ReportDatasetFieldVO> fields;
}
@@ -30,8 +30,11 @@ public class ReportDatasetSaveReqVO {
private Long datasourceId;
@Schema(description = "动态查询SQL")
private String dbSql;
private String sql;
@Schema(description = "参数列表")
private List<ReportDatasetParameterVO> params;
private List<ReportDatasetParameterVO> parameters;
@Schema(description = "字段列表")
private List<ReportDatasetFieldVO> fields;
}
@@ -2,6 +2,7 @@ package com.cf.imes.module.report.controller.admin.template.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@@ -13,15 +14,16 @@ import lombok.ToString;
@Schema(description = "管理后台 - 报表数据源 Request VO")
@Data
@ToString(callSuper = true)
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReportDatasourceReqVO {
@Schema(description = "模板id", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
private Long reportId;
private Long templateId;
@Schema(description = "数据源名称", example = "测试库")
private String name;
@Schema(description = "模板类型,0内置、1自定义", example = "0")
@Schema(description = "数据源类型,jdbc、buildin", example = "jdbc")
private Integer type;
}
@@ -5,7 +5,7 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author Gqr
@@ -26,24 +26,24 @@ public class ReportDatasourceRespVO {
@Schema(description = "数据源名称", example = "测试库")
private String name;
@Schema(description = "模板类型,0内置、1自定义", example = "0")
private Integer type;
@Schema(description = "数据源类型,jdbc、buildin", example = "jdbc")
private String type;
@Schema(description = "数据源驱动类",example = "com.mysql.cj.jdbc.Driver")
private String dbDriver;
private String driver;
@Schema(description = "数据源地址", example = "https://www.cf.com")
private String dbUrl;
private String url;
@Schema(description = "数据源用户名", example = "晨丰")
private String dbUsername;
private String username;
@Schema(description = "数据源密码", example = "晨丰")
private String dbPassword;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
private String password;
@Schema(description = "备注", example = "该模板仅供生产使用")
private String remark;
@Schema(description = "数据集")
private List<ReportDatasetRespVO> datasets;
}
@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author Gqr
@@ -23,26 +24,29 @@ public class ReportDatasourceSaveReqVO {
@Schema(description = "模板id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "模板id不能为空")
private Long reportId;
private Long templateId;
@Schema(description = "数据源名称", example = "测试库")
private String name;
@Schema(description = "模板类型,0内置、1自定义", example = "0")
private Integer type;
@Schema(description = "数据源类型,jdbc、buildin", example = "jdbc")
private String type;
@Schema(description = "数据源驱动类",example = "com.mysql.cj.jdbc.Driver")
private String dbDriver;
private String driver;
@Schema(description = "数据源地址", example = "https://www.cf.com")
private String dbUrl;
private String url;
@Schema(description = "数据源用户名", example = "晨丰")
private String dbUsername;
private String username;
@Schema(description = "数据源密码", example = "晨丰")
private String dbPassword;
private String password;
@Schema(description = "备注", example = "该模板仅供生产使用")
private String remark;
@Schema(description = "数据集")
private List<ReportDatasetSaveReqVO> datasets;
}
@@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author Gqr
@@ -23,7 +24,7 @@ public class ReportTemplateRespVO {
private String name;
@Schema(description = "报表模板")
private String template;
private String content;
@Schema(description = "模板类型,0内置、1自定义", example = "0")
private Long type;
@@ -33,4 +34,7 @@ public class ReportTemplateRespVO {
@Schema(description = "备注", example = "该模板仅供生产使用")
private String remark;
@Schema(description = "数据源")
private List<ReportDatasourceRespVO> datasource;
}
@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author Gqr
@@ -26,7 +27,10 @@ public class ReportTemplateSaveReqVO {
private String name;
@Schema(description = "报表模板")
private String template;
private String content;
@Schema(description = "数据源")
private List<ReportDatasourceSaveReqVO> datasource;
@Schema(description = "模板类型,0内置、1自定义", example = "1")
private Integer type;
@@ -1,4 +0,0 @@
/**
* TODO 占位,后续删除
*/
package com.cf.imes.module.report.convert.ajreport;
@@ -1,24 +0,0 @@
package com.cf.imes.module.report.convert.goview;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectRespVO;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
import com.cf.imes.module.report.dal.dataobject.goview.GoViewProjectDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface GoViewProjectConvert {
GoViewProjectConvert INSTANCE = Mappers.getMapper(GoViewProjectConvert.class);
GoViewProjectDO convert(GoViewProjectCreateReqVO bean);
GoViewProjectDO convert(GoViewProjectUpdateReqVO bean);
GoViewProjectRespVO convert(GoViewProjectDO bean);
PageResult<GoViewProjectRespVO> convertPage(PageResult<GoViewProjectDO> page);
}
@@ -1,4 +0,0 @@
/**
* TODO 芋艿:占位,待删除
*/
package com.cf.imes.module.report.dal.dataobject.ajreport;
@@ -1,57 +0,0 @@
package com.cf.imes.module.report.dal.dataobject.goview;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* GoView 项目表
*
* 每个大屏图标,对应一个项目
*
* @author 晨丰科技
*/
@TableName(value = "report_go_view_project", autoResultMap = true) // 由于 SQL Server 的 system_user 是关键字,所以使用 system_users
@KeySequence("report_go_view_project_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GoViewProjectDO extends BaseDO {
/**
* 编号,数据库自增
*/
@TableId
private Long id;
/**
* 项目名称
*/
private String name;
/**
* 预览图片 URL
*/
private String picUrl;
/**
* 报表内容
*
* JSON 配置,使用字符串存储
*/
private String content;
/**
* 发布状态
*
* 0 - 已发布
* 1 - 未发布
*
* 枚举 {@link com.cf.imes.framework.common.enums.CommonStatusEnum}
*/
private Integer status;
/**
* 项目备注
*/
private String remark;
}
@@ -5,9 +5,16 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import com.cf.imes.framework.mybatis.core.type.ObjectListTypeHandler;
import com.cf.imes.framework.mybatis.core.type.CompressObjectListTypeHandler;
import com.cf.imes.framework.mybatis.core.type.CompressStringTypeHandler;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetFieldVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetParameterVO;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.List;
@@ -42,10 +49,14 @@ public class ReportDatasetDO extends BaseDO {
/**
* 动态查询SQL
*/
private String dbSql;
@TableField(value = "db_sql", typeHandler = CompressStringTypeHandler.class)
private String sql;
/**
* 参数列表
*/
@TableField(typeHandler = ObjectListTypeHandler.class)
private List<ReportDatasetParameterVO> params;
@TableField(typeHandler = CompressObjectListTypeHandler.class)
private List<ReportDatasetParameterVO> parameters;
@TableField(typeHandler = CompressObjectListTypeHandler.class)
private List<ReportDatasetFieldVO> fields;
}
@@ -1,11 +1,14 @@
package com.cf.imes.module.report.dal.dataobject.template;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.util.List;
/**
* 报表数据源DO
*
@@ -29,35 +32,31 @@ public class ReportDatasourceDO extends BaseDO {
/**
* 模板id
*/
private Long reportId;
private Long templateId;
/**
* 数据源名称
*/
private String name;
/**
* 模板类型,0内置、1自定义
* 模板类型,jdbc、buildin
*/
private Long type;
/**
* 数据库类型
*/
private String dbType;
private String type;
/**
* 数据源驱动类
*/
private String dbDriver;
private String driver;
/**
* 数据源地址
*/
private String dbUrl;
private String url;
/**
* 数据源用户名
*/
private String dbUsername;
private String username;
/**
* 数据源密码
*/
private String dbPassword;
private String password;
/**
* 备注
*/
@@ -66,4 +65,10 @@ public class ReportDatasourceDO extends BaseDO {
* 组织id
*/
private Long organId;
/**
* 数据集
*/
@TableField(exist = false)
private List<ReportDatasetDO> datasets;
}
@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.*;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.util.List;
/**
* 报表模板信息DO
*
@@ -31,11 +33,11 @@ public class ReportTemplateDO extends BaseDO {
/**
* 报表模板
*/
private String template;
private String content;
/**
* 模板类型,0内置、1自定义
*/
private Long type;
private Integer type;
/**
* 备注
*/
@@ -45,4 +47,10 @@ public class ReportTemplateDO extends BaseDO {
* 组织id
*/
private Long organId;
/**
* 数据源
*/
@TableField(exist = false)
private List<ReportDatasourceDO> datasource;
}
@@ -1,4 +0,0 @@
/**
* TODO 芋艿:占位,待删除
*/
package com.cf.imes.module.report.dal.mysql.ajreport;
@@ -1,19 +0,0 @@
package com.cf.imes.module.report.dal.mysql.goview;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.report.dal.dataobject.goview.GoViewProjectDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface GoViewProjectMapper extends BaseMapperX<GoViewProjectDO> {
default PageResult<GoViewProjectDO> selectPage(PageParam reqVO, Long userId) {
return selectPage(reqVO, new LambdaQueryWrapperX<GoViewProjectDO>()
.eq(GoViewProjectDO::getCreator, userId)
.orderByDesc(GoViewProjectDO::getId));
}
}
@@ -1,25 +0,0 @@
package com.cf.imes.module.report.framework.jmreport.config;
import com.cf.imes.framework.security.config.SecurityProperties;
import com.cf.imes.module.system.api.oauth2.OAuth2TokenApi;
import com.cf.imes.module.report.framework.jmreport.core.service.JmReportTokenServiceImpl;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* 积木报表的配置类
*
* @author 晨丰科技
*/
@Configuration(proxyBeanMethods = false)
@ComponentScan(basePackages = "org.jeecg.modules.jmreport") // 扫描积木报表的包
public class JmReportConfiguration {
@Bean
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public JmReportTokenServiceI jmReportTokenService(OAuth2TokenApi oAuth2TokenApi, SecurityProperties securityProperties) {
return new JmReportTokenServiceImpl(oAuth2TokenApi, securityProperties);
}
}
@@ -1,149 +0,0 @@
package com.cf.imes.module.report.framework.jmreport.core.service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.util.servlet.ServletUtils;
import com.cf.imes.framework.security.config.SecurityProperties;
import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.web.core.util.WebFrameworkUtils;
import com.cf.imes.module.system.api.oauth2.OAuth2TokenApi;
import com.cf.imes.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import lombok.RequiredArgsConstructor;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.springframework.http.HttpHeaders;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* {@link JmReportTokenServiceI} 实现类,提供积木报表的 Token 校验、用户信息的查询等功能
*
* @author 随心
*/
@RequiredArgsConstructor
public class JmReportTokenServiceImpl implements JmReportTokenServiceI {
/**
* 积木 token head 头
*/
private static final String JM_TOKEN_HEADER = "X-Access-Token";
/**
* auth 相关格式
*/
private static final String AUTHORIZATION_FORMAT = SecurityFrameworkUtils.AUTHORIZATION_BEARER + " %s";
private final OAuth2TokenApi oauth2TokenApi;
private final SecurityProperties securityProperties;
/**
* 自定义 API 数据集appian自定义 Header,解决 Token 传递。
* 参考 <a href="http://report.jeecg.com/2222224">api数据集token机制详解</a> 文档
*
* @return 新 head
*/
@Override
public HttpHeaders customApiHeader() {
// 读取积木标标系统的 token
HttpServletRequest request = ServletUtils.getRequest();
String token = request.getHeader(JM_TOKEN_HEADER);
// 设置到 cf 系统的 token
HttpHeaders headers = new HttpHeaders();
headers.add(securityProperties.getTokenHeader(), String.format(AUTHORIZATION_FORMAT, token));
return headers;
}
/**
* 校验 Token 是否有效,即验证通过
*
* @param token JmReport 前端传递的 token
* @return 是否认证通过
*/
@Override
public Boolean verifyToken(String token) {
Long userId = SecurityFrameworkUtils.getLoginUserId();
if (!Objects.isNull(userId)) {
return true;
}
return buildLoginUserByToken(token) != null;
}
/**
* 获得用户编号
* <p>
* 虽然方法名获得的是 username,实际对应到项目中是用户编号
*
* @param token JmReport 前端传递的 token
* @return 用户编号
*/
@Override
public String getUsername(String token) {
Long userId = SecurityFrameworkUtils.getLoginUserId();
if (ObjectUtil.isNotNull(userId)) {
return String.valueOf(userId);
}
LoginUser user = buildLoginUserByToken(token);
return user == null ? null : String.valueOf(user.getId());
}
/**
* 基于 token 构建登录用户
*
* @param token token
* @return 返回 token 对应的用户信息
*/
private LoginUser buildLoginUserByToken(String token) {
if (StrUtil.isEmpty(token)) {
return null;
}
// TODO 如下的实现不算特别优雅,主要咱是不想搞的太复杂,所以参考对应的 Filter 先实现了
// ① 参考 TokenAuthenticationFilter 的认证逻辑(Security 的上下文清理,交给 Spring Security 完成)
// 目的:实现基于 JmReport 前端传递的 token,实现认证
OrganContextHolder.setIgnore(true); // 忽略租户,保证可查询到 token 信息
LoginUser user = null;
try {
OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token).getCheckedData();
if (accessToken == null) {
return null;
}
user = new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
.setOrganId(accessToken.getOrganId()).setScopes(accessToken.getScopes())
.setDataCode(accessToken.getDataCode()).setLarge(accessToken.getLarge())
.setNickname(accessToken.getNickname());
} catch (ServiceException ignored) {
// do nothing:如果报错,说明认证失败,则返回 false 即可
}
if (user == null) {
return null;
}
SecurityFrameworkUtils.setLoginUser(user, WebFrameworkUtils.getRequest());
// ② 参考 TenantContextWebFilter 实现(Tenant 的上下文清理,交给 TenantContextWebFilter 完成)
// 目的:基于 LoginUser 获得到的租户编号,设置到 Tenant 上下文,避免查询数据库时的报错
OrganContextHolder.setIgnore(false);
OrganContextHolder.setOrganId(user.getOrganId());
return user;
}
@Override
public String[] getRoles(String s) {
// 暂时不用实现,因为不用 JmReport 的角色
return null;
}
@Override
public String getTenantId() {
// 补充说明:不能直接通过 TenantContext 获取,因为 jimu 报表前端请求时,没有带上 tenant-id Header
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
if (loginUser == null) {
return null;
}
return StrUtil.toStringOrNull(loginUser.getOrganId());
}
}
@@ -1,4 +0,0 @@
/**
* 占位,后续会基于 Filter 实现积木报表的认证等功能,替代 {@link com.cf.imes.module.report.framework.jmreport.core.service.JmReportTokenServiceImpl}
*/
package com.cf.imes.module.report.framework.jmreport.core.web;
@@ -1,78 +0,0 @@
package com.cf.imes.module.report.service.ajreport;
import org.jeecg.modules.jmreport.api.data.IDataSetFactory;
import org.jeecg.modules.jmreport.desreport.model.JmPage;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author there
*/
@Service
public class DemoDataService implements IDataSetFactory {
/**
* 不分页时返回list
* @param map 参数 包括浏览器地址栏 和 查询条件
* @return
*/
@Override
public List<Map<String, Object>> createData(Map<String, Object> map) {
List<Map<String, Object>> ls = new ArrayList<>();
Map<String, Object> obj2 = new HashMap<>();
obj2.put("name", "张三");
obj2.put("age", "14");
ls.add(obj2);
Map<String, Object> obj3 = new HashMap<>();
obj3.put("name", "李四");
obj3.put("age", "15");
ls.add(obj3);
Map<String, Object> obj4 = new HashMap<>();
obj4.put("name", "王五");
obj4.put("age", "16");
ls.add(obj4);
return ls;
}
/**
* 分页时返回 JmPage 并且参数param里会传入pageNo, pageSize
* @param map 参数 包括浏览器地址栏 和 查询条件
* @return
*/
@Override
public JmPage createPageData(Map<String, Object> map) {
JmPage page = new JmPage();
List<Map<String, Object>> ls = new ArrayList<>();
int pageSize = Integer.parseInt(map.get("pageSize").toString());
Map<String, Object> obj2 = new HashMap<>();
obj2.put("name", "张三");
obj2.put("age", "14");
obj2.put("sex", "1");
ls.add(obj2);
Map<String, Object> obj3 = new HashMap<>();
obj3.put("name", "李四");
obj3.put("age", "15");
obj2.put("sex", "2");
ls.add(obj3);
Map<String, Object> obj4 = new HashMap<>();
obj4.put("name", "王五");
obj4.put("age", "16");
obj2.put("sex", "2");
ls.add(obj4);
//以下参数均需设置
page.setPageSize(pageSize);
page.setTotal(20);
page.setRecords(ls);
return page;
}
}
@@ -1,4 +0,0 @@
/**
* TODO 芋艿:占位,待删除
*/
package com.cf.imes.module.report.service.ajreport;
@@ -1,20 +0,0 @@
package com.cf.imes.module.report.service.goview;
import com.cf.imes.module.report.controller.admin.goview.vo.data.GoViewDataRespVO;
/**
* GoView 数据 Service 接口
*
* @author 晨丰科技
*/
public interface GoViewDataService {
/**
* 使用 SQL 查询数据
*
* @param sql SQL 语句
* @return 数据
*/
GoViewDataRespVO getDataBySQL(String sql);
}
@@ -1,55 +0,0 @@
package com.cf.imes.module.report.service.goview;
import com.cf.imes.module.report.controller.admin.goview.vo.data.GoViewDataRespVO;
import com.google.common.collect.Maps;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Map;
/**
* GoView 数据 Service 实现类
*
* 补充说明:
* 1. 目前默认使用 jdbcTemplate 查询项目配置的数据源。如果你想查询其它数据源,可以新建对应数据源的 jdbcTemplate 来实现。
* 2. 默认数据源是 MySQL 关系数据源,可能数据量比较大的情况下,会比较慢,可以考虑后续使用 Click House 等等。
*
* @author 晨丰科技
*/
@Service
@Validated
public class GoViewDataServiceImpl implements GoViewDataService {
@Resource
private JdbcTemplate jdbcTemplate;
@Override
public GoViewDataRespVO getDataBySQL(String sql) {
// 1. 执行查询
SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql);
// 2. 构建返回结果
GoViewDataRespVO respVO = new GoViewDataRespVO();
// 2.1 解析元数据
SqlRowSetMetaData metaData = sqlRowSet.getMetaData();
String[] columnNames = metaData.getColumnNames();
respVO.setDimensions(Arrays.asList(columnNames));
// 2.2 解析数据明细
respVO.setSource(new LinkedList<>()); // 由于数据量不确认,使用 LinkedList 虽然内存占用大一点,但是不存在扩容复制的问题
while (sqlRowSet.next()) {
Map<String, Object> data = Maps.newHashMapWithExpectedSize(columnNames.length);
for (String columnName : columnNames) {
data.put(columnName, sqlRowSet.getObject(columnName));
}
respVO.getSource().add(data);
}
return respVO;
}
}
@@ -1,57 +0,0 @@
package com.cf.imes.module.report.service.goview;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
import com.cf.imes.module.report.dal.dataobject.goview.GoViewProjectDO;
import javax.validation.Valid;
/**
* GoView 项目 Service 接口
*
* @author 晨丰科技
*/
public interface GoViewProjectService {
/**
* 创建项目
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createProject(@Valid GoViewProjectCreateReqVO createReqVO);
/**
* 更新项目
*
* @param updateReqVO 更新信息
*/
void updateProject(@Valid GoViewProjectUpdateReqVO updateReqVO);
/**
* 删除项目
*
* @param id 编号
*/
void deleteProject(Long id);
/**
* 获得项目
*
* @param id 编号
* @return 项目
*/
GoViewProjectDO getProject(Long id);
/**
* 获得我的项目分页
*
* @param pageReqVO 分页查询
* @param userId 用户编号
* @return GoView 项目分页
*/
PageResult<GoViewProjectDO> getMyProjectPage(PageParam pageReqVO, Long userId);
}
@@ -1,74 +0,0 @@
package com.cf.imes.module.report.service.goview;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
import com.cf.imes.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
import com.cf.imes.module.report.convert.goview.GoViewProjectConvert;
import com.cf.imes.module.report.dal.dataobject.goview.GoViewProjectDO;
import com.cf.imes.module.report.dal.mysql.goview.GoViewProjectMapper;
import com.cf.imes.module.report.enums.ErrorCodeConstants;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
* GoView 项目 Service 实现类
*
* @author 晨丰科技
*/
@Service
@Validated
public class GoViewProjectServiceImpl implements GoViewProjectService {
@Resource
private GoViewProjectMapper goViewProjectMapper;
@Override
public Long createProject(GoViewProjectCreateReqVO createReqVO) {
// 插入
GoViewProjectDO goViewProject = GoViewProjectConvert.INSTANCE.convert(createReqVO)
.setStatus(CommonStatusEnum.DISABLE.getStatus());
goViewProjectMapper.insert(goViewProject);
// 返回
return goViewProject.getId();
}
@Override
public void updateProject(GoViewProjectUpdateReqVO updateReqVO) {
// 校验存在
validateProjectExists(updateReqVO.getId());
// 更新
GoViewProjectDO updateObj = GoViewProjectConvert.INSTANCE.convert(updateReqVO);
goViewProjectMapper.updateById(updateObj);
}
@Override
public void deleteProject(Long id) {
// 校验存在
validateProjectExists(id);
// 删除
goViewProjectMapper.deleteById(id);
}
private void validateProjectExists(Long id) {
if (goViewProjectMapper.selectById(id) == null) {
throw exception(ErrorCodeConstants.GO_VIEW_PROJECT_NOT_EXISTS);
}
}
@Override
public GoViewProjectDO getProject(Long id) {
return goViewProjectMapper.selectById(id);
}
@Override
public PageResult<GoViewProjectDO> getMyProjectPage(PageParam pageReqVO, Long userId) {
return goViewProjectMapper.selectPage(pageReqVO, userId);
}
}
@@ -22,6 +22,12 @@ public interface ReportDatasetService {
*/
Long createDataset(@Valid ReportDatasetSaveReqVO createReqVO);
/**
* 批量创建报表数据集
* @param createReqVOList
*/
void batchCreateDataset(@Valid List<ReportDatasetSaveReqVO> createReqVOList);
/**
* 更新报表数据集
*
@@ -29,6 +35,13 @@ public interface ReportDatasetService {
*/
void updateDataset(@Valid ReportDatasetSaveReqVO updateReqVO);
/**
* 批量更新报表数据集
* @param createReqVOList
*/
void batchUpdateDataset(@Valid List<ReportDatasetSaveReqVO> createReqVOList);
/**
* 删除报表数据集
*
@@ -1,5 +1,6 @@
package com.cf.imes.module.report.service.template;
import cn.hutool.core.collection.CollUtil;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetReqVO;
@@ -36,6 +37,14 @@ public class ReportDatasetServiceImpl implements ReportDatasetService {
return dataset.getId();
}
@Override
public void batchCreateDataset(List<ReportDatasetSaveReqVO> createReqVOList) {
List<ReportDatasetDO> reportDatasetDOS = BeanUtils.toBean(createReqVOList, ReportDatasetDO.class);
if (CollUtil.isNotEmpty(reportDatasetDOS)) {
datasetMapper.insertBatch(reportDatasetDOS);
}
}
@Override
public void updateDataset(ReportDatasetSaveReqVO updateReqVO) {
// 校验存在
@@ -45,6 +54,14 @@ public class ReportDatasetServiceImpl implements ReportDatasetService {
datasetMapper.updateById(updateObj);
}
@Override
public void batchUpdateDataset(List<ReportDatasetSaveReqVO> createReqVOList) {
List<ReportDatasetDO> reportDatasetDOS = BeanUtils.toBean(createReqVOList, ReportDatasetDO.class);
if (CollUtil.isNotEmpty(reportDatasetDOS)) {
datasetMapper.updateBatch(reportDatasetDOS);
}
}
@Override
public void deleteDataset(Long id) {
// 校验存在
@@ -47,8 +47,8 @@ public interface ReportDatasourceService {
/**
* 获取模板下的数据源列表
*
* @param pageReqVO 分页查询
* @param reqVO 查询参数
* @return 报表数据源分页
*/
List<ReportDatasourceDO> getTemplateDatasourceList(ReportDatasourceReqVO pageReqVO);
List<ReportDatasourceDO> getTemplateDatasourceList(ReportDatasourceReqVO reqVO);
}
@@ -72,7 +72,7 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService {
@Override
public List<ReportDatasourceDO> getTemplateDatasourceList(ReportDatasourceReqVO reqVO) {
return datasourceMapper.selectList(new LambdaQueryWrapperX<ReportDatasourceDO>()
.eqIfPresent(ReportDatasourceDO::getReportId, reqVO.getReportId())
.eqIfPresent(ReportDatasourceDO::getTemplateId, reqVO.getTemplateId())
.likeIfPresent(ReportDatasourceDO::getName, reqVO.getName())
.eqIfPresent(ReportDatasourceDO::getType, reqVO.getType())
.orderByDesc(ReportDatasourceDO::getCreateTime));
@@ -1,18 +1,28 @@
package com.cf.imes.module.report.service.template;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.URLUtil;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetReqVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetSaveReqVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasourceReqVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasourceSaveReqVO;
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.dal.dataobject.template.ReportDatasetDO;
import com.cf.imes.module.report.dal.dataobject.template.ReportDatasourceDO;
import com.cf.imes.module.report.dal.dataobject.template.ReportTemplateDO;
import com.cf.imes.module.report.dal.mysql.template.ReportTemplateMapper;
import com.cf.imes.module.report.enums.ErrorCodeConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -29,31 +39,87 @@ public class ReportTemplateServiceImpl implements ReportTemplateService {
@Resource
private ReportTemplateMapper templateMapper;
@Resource
private ReportDatasourceService datasourceService;
@Resource
private ReportDatasetService datasetService;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createReportTemplate(ReportTemplateSaveReqVO createReqVO) {
String templateContent = URLUtil.decode(createReqVO.getTemplate());
if(StringUtils.isNotEmpty(templateContent)) {
// todo template压缩待完善
createReqVO.setTemplate(templateContent);
// url解码xml
String content = createReqVO.getContent();
if (StringUtils.isNotEmpty(content)) {
createReqVO.setContent(URLUtil.decode(content));
}
// 插入
// 新增模板
ReportTemplateDO template = BeanUtils.toBean(createReqVO, ReportTemplateDO.class);
templateMapper.insert(template);
Long templateId = template.getId();
// 解析数据源
analyzeDatasource(createReqVO.getDatasource(), templateId);
// 返回主键
return template.getId();
return templateId;
}
/**
* 解析数据源集合并入库
*
* @param datasource 数据源列表
* @param templateId 模板id
*/
private void analyzeDatasource(List<ReportDatasourceSaveReqVO> datasource, Long templateId) {
datasource.forEach(ds -> {
// 更新/新增数据源
if (ObjectUtil.isNotNull(ds.getId())) {
datasourceService.updateDatasource(ds);
} else {
ds.setTemplateId(templateId);
datasourceService.createDatasource(ds);
}
// 获取自增数据源主键
Long datasourceId = ds.getId();
List<ReportDatasetSaveReqVO> datasets = ds.getDatasets();
List<ReportDatasetSaveReqVO> batchInsertDataset = new ArrayList<>();
List<ReportDatasetSaveReqVO> batchupdateDataset = new ArrayList<>();
datasets.forEach(dataset -> {
// 更新/新增数据集
if (ObjectUtil.isNotNull(dataset.getId())) {
batchupdateDataset.add(dataset);
} else {
dataset.setDatasourceId(datasourceId);
batchInsertDataset.add(dataset);
}
});
// 批量插入数据集
if (CollUtil.isNotEmpty(batchInsertDataset)) {
datasetService.batchCreateDataset(batchInsertDataset);
}
// 批量更新数据集
if (CollUtil.isNotEmpty(batchupdateDataset)) {
datasetService.batchUpdateDataset(batchupdateDataset);
}
});
}
@Override
public void updateReportTemplate(ReportTemplateSaveReqVO updateReqVO) {
Long templateId = updateReqVO.getId();
// 校验存在
validateTemplateExists(updateReqVO.getId());
String templateContent = updateReqVO.getTemplate();
if (StringUtils.isNotEmpty(templateContent)) {
// todo template压缩待完善
validateTemplateExists(templateId);
// url解码xml
String content = updateReqVO.getContent();
if (StringUtils.isNotEmpty(content)) {
updateReqVO.setContent(URLUtil.decode(content));
}
// 更新
// 更新模板
ReportTemplateDO updateObj = BeanUtils.toBean(updateReqVO, ReportTemplateDO.class);
templateMapper.updateById(updateObj);
// 更新数据源
analyzeDatasource(updateReqVO.getDatasource(), templateId);
}
@Override
@@ -77,7 +143,19 @@ public class ReportTemplateServiceImpl implements ReportTemplateService {
@Override
public ReportTemplateDO getReportTemplate(Long id) {
return templateMapper.selectById(id);
// 查询模板
ReportTemplateDO template = templateMapper.selectById(id);
if (ObjectUtil.isNotNull(template)) {
// 查询数据源
List<ReportDatasourceDO> datasourceList = datasourceService.getTemplateDatasourceList(ReportDatasourceReqVO.builder().templateId(template.getId()).build());
datasourceList.forEach(ds -> {
// 查询数据集
List<ReportDatasetDO> datasetList = datasetService.getDatasetList(ReportDatasetReqVO.builder().datasourceId(ds.getId()).build());
ds.setDatasets(datasetList);
});
template.setDatasource(datasourceList);
}
return template;
}
@Override
@@ -85,6 +163,8 @@ public class ReportTemplateServiceImpl implements ReportTemplateService {
return templateMapper.selectList(new LambdaQueryWrapperX<ReportTemplateDO>()
.likeIfPresent(ReportTemplateDO::getName, reqVO.getName())
.eqIfPresent(ReportTemplateDO::getType, reqVO.getType())
.orderByDesc(ReportTemplateDO::getCreateTime));
.orderByDesc(ReportTemplateDO::getCreateTime)
// 不返回content xml,点击具体的模板中返回xml
.select(ReportTemplateDO::getId, ReportTemplateDO::getName, ReportTemplateDO::getCreateTime, ReportTemplateDO::getRemark));
}
}
@@ -2,6 +2,7 @@ package com.cf.imes.module.report.service.template;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.test.core.util.RandomUtils;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetFieldVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetParameterVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasetSaveReqVO;
import com.cf.imes.module.report.controller.admin.template.vo.ReportDatasourceSaveReqVO;
@@ -27,7 +28,7 @@ public abstract class ReportCommonServiceImplTest {
return ReportTemplateSaveReqVO.builder()
.id(id)
.name("单元测试模板")
.template(JsonUtil.zipString(TEMPLATE))
.content(JsonUtil.zipString(TEMPLATE))
.type(ReportTemplateTypeEnum.SYSTEM.getType())
.remark(RandomUtils.randomString())
.build();
@@ -38,29 +39,35 @@ public abstract class ReportCommonServiceImplTest {
return ReportDatasourceSaveReqVO.builder()
.id(id)
.name("单元测试数据源")
.reportId(reportId)
.type(ReportTemplateTypeEnum.SYSTEM.getType())
.dbDriver("com.mysql.cj.jdbc.Driver")
.dbUrl("jdbc:mysql://192.168.1.205:3307/imes_base?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true")
.dbUsername("root")
.dbPassword("root")
.templateId(reportId)
.type("jdbc")
.driver("com.mysql.cj.jdbc.Driver")
.url("jdbc:mysql://192.168.1.205:3307/imes_base?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true")
.username("root")
.password("root")
.remark(RandomUtils.randomString())
.build();
}
protected ReportDatasetSaveReqVO prepareDatasetReqVO(Long id, Long datasourceId) {
ReportDatasetParameterVO idvo = new ReportDatasetParameterVO("id", 1, "1");
ReportDatasetParameterVO appidvo = new ReportDatasetParameterVO("app_id", 2, "CF7526AD51");
ReportDatasetParameterVO idvo = new ReportDatasetParameterVO("id", "Integer", "1");
ReportDatasetParameterVO appidvo = new ReportDatasetParameterVO("app_id", "String", "CF7526AD51");
List<ReportDatasetParameterVO> params = new ArrayList<>() {{
add(idvo);
add(appidvo);
}};
ReportDatasetFieldVO idfield = new ReportDatasetFieldVO("id");
List<ReportDatasetFieldVO> fields = new ArrayList<>() {{
add(idfield);
}};
return ReportDatasetSaveReqVO.builder()
.id(id)
.name("单元测试数据集")
.dbSql("select * from application where id = \"${param(\"id\")}\" and app_id = \"${param(\"app_id\")}\"")
.sql("select * from application where id = \"${param(\"id\")}\" and app_id = \"${param(\"app_id\")}\"")
.datasourceId(datasourceId)
.params(params)
.parameters(params)
.fields(fields)
.build();
}
}
@@ -66,7 +66,7 @@ public class ReportDatasourceServiceImplTest extends ReportCommonServiceImplTest
// 列表查询参数准备
ReportDatasourceReqVO reqVO = new ReportDatasourceReqVO();
reqVO.setReportId(templateId);
reqVO.setTemplateId(templateId);
reqVO.setType(ReportTemplateTypeEnum.SYSTEM.getType());
reqVO.setName(updateReqVO.getName());
List<ReportDatasourceDO> templateDatasourceList = reportDatasourceService.getTemplateDatasourceList(reqVO);
@@ -33,7 +33,7 @@ public class ReportTemplateServiceImplTest extends ReportCommonServiceImplTest {
setOrganId();
// 准备参数
ReportTemplateSaveReqVO createReqVO = prepareTemplateReqVO(null);
System.out.println("template压缩后大小:" + createReqVO.getTemplate().length());
System.out.println("template压缩后大小:" + createReqVO.getContent().length());
// 插入
Long templateId = reportTemplateService.createReportTemplate(createReqVO);
// 断言
@@ -41,7 +41,7 @@ public class ReportTemplateServiceImplTest extends ReportCommonServiceImplTest {
// 校验是否插入
ReportTemplateDO template = reportTemplateService.getReportTemplate(templateId);
assertNotNull(template);
String templateUnZip = template.getTemplate();
String templateUnZip = template.getContent();
System.out.println("从库中读取template大小:" + templateUnZip.length());
// 校验解压内容是否正确
assertEquals(JsonUtil.unzipString(templateUnZip),TEMPLATE);
@@ -54,7 +54,7 @@ public class ReportTemplateServiceImplTest extends ReportCommonServiceImplTest {
setOrganId();
// 准备参数
ReportTemplateSaveReqVO createReqVO = prepareTemplateReqVO(null);
System.out.println("template压缩后大小:" + createReqVO.getTemplate().length());
System.out.println("template压缩后大小:" + createReqVO.getContent().length());
// 插入
Long templateId = reportTemplateService.createReportTemplate(createReqVO);
@@ -65,6 +65,7 @@ public class ReportTemplateServiceImplTest extends ReportCommonServiceImplTest {
reportTemplateService.updateReportTemplate(updateReqVO);
// 校验是否更新正确
ReportTemplateDO template = reportTemplateService.getReportTemplate(updateReqVO.getId()); // 获取最新的
assertNotNull(template);
isPojoEquals(template,updateReqVO);
// 删除
reportTemplateService.deleteReportTemplate(templateId);