mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 04:08:43 +08:00 
			
		
		
		
	集成 Go-View 大屏设计器
This commit is contained in:
		@@ -0,0 +1 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.controller.admin.ajreport;
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.controller.admin.goview;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.map.MapUtil;
 | 
			
		||||
import cn.hutool.core.util.RandomUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.data.GoViewDataGetBySqlReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.data.GoViewDataRespVO;
 | 
			
		||||
import cn.iocoder.yudao.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.validation.Valid;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,77 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.controller.admin.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.convert.goview.GoViewProjectConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.report.dal.dataobject.goview.GoViewProjectDO;
 | 
			
		||||
import cn.iocoder.yudao.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.jdbc.core.JdbcTemplate;
 | 
			
		||||
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 cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 | 
			
		||||
import static cn.iocoder.yudao.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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
package cn.iocoder.yudao.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 语句", required = true, example = "SELECT * FROM user")
 | 
			
		||||
    @NotEmpty(message = "SQL 语句不能为空")
 | 
			
		||||
    private String sql;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package cn.iocoder.yudao.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 = "数据维度", required = true, example = "['product', 'data1', 'data2']")
 | 
			
		||||
    private List<String> dimensions;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "数据明细列表", required = true)
 | 
			
		||||
    private List<Map<String, Object>> source;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
package cn.iocoder.yudao.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 = "项目名称", required = true, example = "王五")
 | 
			
		||||
    @NotEmpty(message = "项目名称不能为空")
 | 
			
		||||
    private String name;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
package cn.iocoder.yudao.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 = "编号", required = true, example = "18993")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "项目名称", required = true, example = "王五")
 | 
			
		||||
    private String name;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "发布状态", required = true, 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 = "创建人编号", required = true, example = "1024")
 | 
			
		||||
    private String creator;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "创建时间", required = true)
 | 
			
		||||
    private LocalDateTime createTime;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.controller.admin.goview.vo.project;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.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 = "编号", required = true, example = "18993")
 | 
			
		||||
    @NotNull(message = "编号不能为空")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "项目名称", required = true, example = "王五")
 | 
			
		||||
    private String name;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "发布状态", required = true, 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;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 提供 RESTful API 给前端:
 | 
			
		||||
 * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目
 | 
			
		||||
 * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.controller;
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
/**
 | 
			
		||||
 * TODO 占位,后续删除
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.convert.ajreport;
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.convert.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
/**
 | 
			
		||||
 * TODO 芋艿:占位,待删除
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.dal.dataobject.ajreport;
 | 
			
		||||
@@ -0,0 +1,57 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.dal.dataobject.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.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 cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private Integer status;
 | 
			
		||||
    /**
 | 
			
		||||
     * 项目备注
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
/**
 | 
			
		||||
 * TODO 芋艿:占位,待删除
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.dal.mysql.ajreport;
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.dal.mysql.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 | 
			
		||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 | 
			
		||||
import cn.iocoder.yudao.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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,26 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.framework.jmreport.config;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
 | 
			
		||||
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
 | 
			
		||||
import cn.iocoder.yudao.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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,131 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.framework.jmreport.core.service;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
 | 
			
		||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
 | 
			
		||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 | 
			
		||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
 | 
			
		||||
import cn.iocoder.yudao.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);
 | 
			
		||||
 | 
			
		||||
        // 设置到 yudao 系统的 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,实现认证
 | 
			
		||||
        TenantContextHolder.setIgnore(true); // 忽略租户,保证可查询到 token 信息
 | 
			
		||||
        LoginUser user = null;
 | 
			
		||||
        try {
 | 
			
		||||
            OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token);
 | 
			
		||||
            if (accessToken == null) {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            user = new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
 | 
			
		||||
                    .setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes());
 | 
			
		||||
        } catch (ServiceException ignored) {
 | 
			
		||||
            // do nothing:如果报错,说明认证失败,则返回 false 即可
 | 
			
		||||
        }
 | 
			
		||||
        if (user == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        SecurityFrameworkUtils.setLoginUser(user, WebFrameworkUtils.getRequest());
 | 
			
		||||
 | 
			
		||||
        // ② 参考 TenantContextWebFilter 实现(Tenant 的上下文清理,交给 TenantContextWebFilter 完成)
 | 
			
		||||
        // 目的:基于 LoginUser 获得到的租户编号,设置到 Tenant 上下文,避免查询数据库时的报错
 | 
			
		||||
        TenantContextHolder.setIgnore(false);
 | 
			
		||||
        TenantContextHolder.setTenantId(user.getTenantId());
 | 
			
		||||
        return user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 占位,后续会基于 Filter 实现积木报表的认证等功能,替代 {@link cn.iocoder.yudao.module.report.framework.jmreport.core.service.JmReportTokenServiceImpl}
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.framework.jmreport.core.web;
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 属于 report 模块的 framework 封装
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.framework;
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.framework.security.config;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 | 
			
		||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Report 模块的 Security 配置
 | 
			
		||||
 */
 | 
			
		||||
@Configuration("reportSecurityConfiguration")
 | 
			
		||||
public class SecurityConfiguration {
 | 
			
		||||
 | 
			
		||||
    @Bean("reportAuthorizeRequestsCustomizer")
 | 
			
		||||
    public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
 | 
			
		||||
        return new AuthorizeRequestsCustomizer() {
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
 | 
			
		||||
                //积木报表
 | 
			
		||||
                registry.antMatchers("/jmreport/**").permitAll();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 占位
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.framework.security.core;
 | 
			
		||||
@@ -0,0 +1,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * ureport2:https://github.com/youseries/ureport
 | 
			
		||||
 *
 | 
			
		||||
 * ureport2 和 jimurepot 是相同类型的产品,不过停更了,最好发布时间是 2018 年。
 | 
			
		||||
 * 它们之间的功能对比,可见 https://juejin.cn/post/6939836480269320200 地址
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.framework.ureport;
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
/**
 | 
			
		||||
 * report 模块,主要实现数据可视化报表等功能:
 | 
			
		||||
 * 1. 基于「积木报表」实现,打印设计、报表设计、图形设计、大屏设计等。URL 前缀是 /jmreport,表名前缀是 jimu_
 | 
			
		||||
 *
 | 
			
		||||
 * 由于「积木报表」的大屏设计器需要收费,后续会自研,对应的是:
 | 
			
		||||
 * 1. Controller URL:以 /report/ 开头,避免和其它 Module 冲突
 | 
			
		||||
 * 2. DataObject 表名:以 report_ 开头,方便在数据库中区分
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report;
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
/**
 | 
			
		||||
 * TODO 芋艿:占位,待删除
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.report.service.ajreport;
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.service.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.data.GoViewDataRespVO;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * GoView 数据 Service 接口
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
public interface GoViewDataService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 使用 SQL 查询数据
 | 
			
		||||
     *
 | 
			
		||||
     * @param sql SQL 语句
 | 
			
		||||
     * @return 数据
 | 
			
		||||
     */
 | 
			
		||||
    GoViewDataRespVO getDataBySQL(String sql);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,55 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.service.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,57 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.service.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,74 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.service.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.convert.goview.GoViewProjectConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.report.dal.dataobject.goview.GoViewProjectDO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.dal.mysql.goview.GoViewProjectMapper;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
			
		||||
import static cn.iocoder.yudao.module.report.enums.ErrorCodeConstants.GO_VIEW_PROJECT_NOT_EXISTS;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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(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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,58 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.service.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.data.GoViewDataRespVO;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.springframework.boot.test.mock.mockito.MockBean;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
import org.springframework.jdbc.core.JdbcTemplate;
 | 
			
		||||
import org.springframework.jdbc.support.rowset.SqlRowSet;
 | 
			
		||||
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
import static org.junit.jupiter.api.Assertions.assertEquals;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
import static org.mockito.Mockito.when;
 | 
			
		||||
 | 
			
		||||
@Import(GoViewDataServiceImpl.class)
 | 
			
		||||
public class GoViewDataServiceImplTest extends BaseDbUnitTest {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private GoViewDataServiceImpl goViewDataService;
 | 
			
		||||
 | 
			
		||||
    @MockBean
 | 
			
		||||
    private JdbcTemplate jdbcTemplate;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetDataBySQL() {
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        String sql = "SELECT id, name FROM system_users";
 | 
			
		||||
        // mock 方法
 | 
			
		||||
        SqlRowSet sqlRowSet = mock(SqlRowSet.class);
 | 
			
		||||
        when(jdbcTemplate.queryForRowSet(eq(sql))).thenReturn(sqlRowSet);
 | 
			
		||||
        // mock 元数据
 | 
			
		||||
        SqlRowSetMetaData metaData = mock(SqlRowSetMetaData.class);
 | 
			
		||||
        when(sqlRowSet.getMetaData()).thenReturn(metaData);
 | 
			
		||||
        when(metaData.getColumnNames()).thenReturn(new String[]{"id", "name"});
 | 
			
		||||
        // mock 数据明细
 | 
			
		||||
        when(sqlRowSet.next()).thenReturn(true).thenReturn(true).thenReturn(false);
 | 
			
		||||
        when(sqlRowSet.getObject("id")).thenReturn(1L).thenReturn(2L);
 | 
			
		||||
        when(sqlRowSet.getObject("name")).thenReturn("芋道源码").thenReturn("芋道");
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        GoViewDataRespVO dataBySQL = goViewDataService.getDataBySQL(sql);
 | 
			
		||||
        // 断言
 | 
			
		||||
        assertEquals(Arrays.asList("id", "name"), dataBySQL.getDimensions());
 | 
			
		||||
        assertEquals(2, dataBySQL.getDimensions().size());
 | 
			
		||||
        assertEquals(2, dataBySQL.getSource().get(0).size());
 | 
			
		||||
        assertEquals(1L, dataBySQL.getSource().get(0).get("id"));
 | 
			
		||||
        assertEquals("芋道源码", dataBySQL.getSource().get(0).get("name"));
 | 
			
		||||
        assertEquals(2, dataBySQL.getSource().get(1).size());
 | 
			
		||||
        assertEquals(2L, dataBySQL.getSource().get(1).get("id"));
 | 
			
		||||
        assertEquals("芋道", dataBySQL.getSource().get(1).get("name"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,135 @@
 | 
			
		||||
package cn.iocoder.yudao.module.report.service.goview;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.controller.admin.goview.vo.project.GoViewProjectUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.dal.dataobject.goview.GoViewProjectDO;
 | 
			
		||||
import cn.iocoder.yudao.module.report.dal.mysql.goview.GoViewProjectMapper;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
 | 
			
		||||
import static cn.iocoder.yudao.module.report.enums.ErrorCodeConstants.GO_VIEW_PROJECT_NOT_EXISTS;
 | 
			
		||||
import static org.junit.jupiter.api.Assertions.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link GoViewProjectServiceImpl} 的单元测试类
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Import(GoViewProjectServiceImpl.class)
 | 
			
		||||
public class GoViewProjectServiceImplTest extends BaseDbUnitTest {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private GoViewProjectServiceImpl goViewProjectService;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private GoViewProjectMapper goViewProjectMapper;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateProject_success() {
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        GoViewProjectCreateReqVO reqVO = randomPojo(GoViewProjectCreateReqVO.class);
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        Long goViewProjectId = goViewProjectService.createProject(reqVO);
 | 
			
		||||
        // 断言
 | 
			
		||||
        assertNotNull(goViewProjectId);
 | 
			
		||||
        // 校验记录的属性是否正确
 | 
			
		||||
        GoViewProjectDO goViewProject = goViewProjectMapper.selectById(goViewProjectId);
 | 
			
		||||
        assertPojoEquals(reqVO, goViewProject);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpdateProject_success() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        GoViewProjectDO dbGoViewProject = randomPojo(GoViewProjectDO.class);
 | 
			
		||||
        goViewProjectMapper.insert(dbGoViewProject);// @Sql: 先插入出一条存在的数据
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        GoViewProjectUpdateReqVO reqVO = randomPojo(GoViewProjectUpdateReqVO.class, o -> {
 | 
			
		||||
            o.setId(dbGoViewProject.getId()); // 设置更新的 ID
 | 
			
		||||
            o.setStatus(randomCommonStatus());
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        goViewProjectService.updateProject(reqVO);
 | 
			
		||||
        // 校验是否更新正确
 | 
			
		||||
        GoViewProjectDO goViewProject = goViewProjectMapper.selectById(reqVO.getId()); // 获取最新的
 | 
			
		||||
        assertPojoEquals(reqVO, goViewProject);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpdateProject_notExists() {
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        GoViewProjectUpdateReqVO reqVO = randomPojo(GoViewProjectUpdateReqVO.class);
 | 
			
		||||
 | 
			
		||||
        // 调用, 并断言异常
 | 
			
		||||
        assertServiceException(() -> goViewProjectService.updateProject(reqVO), GO_VIEW_PROJECT_NOT_EXISTS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDeleteProject_success() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        GoViewProjectDO dbGoViewProject = randomPojo(GoViewProjectDO.class);
 | 
			
		||||
        goViewProjectMapper.insert(dbGoViewProject);// @Sql: 先插入出一条存在的数据
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        Long id = dbGoViewProject.getId();
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        goViewProjectService.deleteProject(id);
 | 
			
		||||
        // 校验数据不存在了
 | 
			
		||||
        assertNull(goViewProjectMapper.selectById(id));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDeleteProject_notExists() {
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        Long id = randomLongId();
 | 
			
		||||
 | 
			
		||||
        // 调用, 并断言异常
 | 
			
		||||
        assertServiceException(() -> goViewProjectService.deleteProject(id), GO_VIEW_PROJECT_NOT_EXISTS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetProject() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        GoViewProjectDO dbGoViewProject = randomPojo(GoViewProjectDO.class);
 | 
			
		||||
        goViewProjectMapper.insert(dbGoViewProject);// @Sql: 先插入出一条存在的数据
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        Long id = dbGoViewProject.getId();
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        GoViewProjectDO goViewProject = goViewProjectService.getProject(id);
 | 
			
		||||
        // 断言
 | 
			
		||||
        assertPojoEquals(dbGoViewProject, goViewProject);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetMyGoViewProjectPage() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        GoViewProjectDO dbGoViewProject = randomPojo(GoViewProjectDO.class, o -> { // 等会查询到
 | 
			
		||||
            o.setCreator("1");
 | 
			
		||||
        });
 | 
			
		||||
        goViewProjectMapper.insert(dbGoViewProject);
 | 
			
		||||
        // 测试 userId 不匹配
 | 
			
		||||
        goViewProjectMapper.insert(cloneIgnoreId(dbGoViewProject, o -> o.setCreator("2")));
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        PageParam reqVO = new PageParam();
 | 
			
		||||
        Long userId = 1L;
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        PageResult<GoViewProjectDO> pageResult = goViewProjectService.getMyProjectPage(reqVO, userId);
 | 
			
		||||
        // 断言
 | 
			
		||||
        assertEquals(1, pageResult.getTotal());
 | 
			
		||||
        assertEquals(1, pageResult.getList().size());
 | 
			
		||||
        assertPojoEquals(dbGoViewProject, pageResult.getList().get(0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,55 @@
 | 
			
		||||
spring:
 | 
			
		||||
  main:
 | 
			
		||||
    lazy-initialization: true # 开启懒加载,加快速度
 | 
			
		||||
    banner-mode: off # 单元测试,禁用 Banner
 | 
			
		||||
 | 
			
		||||
--- #################### 数据库相关配置 ####################
 | 
			
		||||
 | 
			
		||||
spring:
 | 
			
		||||
  # 数据源配置项
 | 
			
		||||
  datasource:
 | 
			
		||||
    name: ruoyi-vue-pro
 | 
			
		||||
    url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
 | 
			
		||||
    driver-class-name: org.h2.Driver
 | 
			
		||||
    username: sa
 | 
			
		||||
    password:
 | 
			
		||||
    druid:
 | 
			
		||||
      async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
 | 
			
		||||
      initial-size: 1 # 单元测试,配置为 1,提升启动速度
 | 
			
		||||
  sql:
 | 
			
		||||
    init:
 | 
			
		||||
      schema-locations: classpath:/sql/create_tables.sql
 | 
			
		||||
 | 
			
		||||
  # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
 | 
			
		||||
  redis:
 | 
			
		||||
    host: 127.0.0.1 # 地址
 | 
			
		||||
    port: 16379 # 端口(单元测试,使用 16379 端口)
 | 
			
		||||
    database: 0 # 数据库索引
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
mybatis:
 | 
			
		||||
  lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
 | 
			
		||||
 | 
			
		||||
--- #################### 定时任务相关配置 ####################
 | 
			
		||||
 | 
			
		||||
--- #################### 配置中心相关配置 ####################
 | 
			
		||||
 | 
			
		||||
--- #################### 服务保障相关配置 ####################
 | 
			
		||||
 | 
			
		||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
 | 
			
		||||
 | 
			
		||||
# Resilience4j 配置项
 | 
			
		||||
 | 
			
		||||
--- #################### 监控相关配置 ####################
 | 
			
		||||
 | 
			
		||||
--- #################### 芋道相关配置 ####################
 | 
			
		||||
 | 
			
		||||
# 芋道配置项,设置当前项目所有自定义的配置
 | 
			
		||||
yudao:
 | 
			
		||||
  info:
 | 
			
		||||
    base-package: cn.iocoder.yudao.module
 | 
			
		||||
  captcha:
 | 
			
		||||
    timeout: 5m
 | 
			
		||||
    width: 160
 | 
			
		||||
    height: 60
 | 
			
		||||
    enable: true
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
<configuration>
 | 
			
		||||
    <!-- 引用 Spring Boot 的 logback 基础配置 -->
 | 
			
		||||
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
 | 
			
		||||
</configuration>
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
DELETE FROM "report_go_view_project";
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
CREATE TABLE IF NOT EXISTS "report_go_view_project" (
 | 
			
		||||
    "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
 | 
			
		||||
    "name" varchar NOT NULL,
 | 
			
		||||
    "pic_url" varchar,
 | 
			
		||||
    "content" varchar,
 | 
			
		||||
    "status" varchar NOT NULL,
 | 
			
		||||
    "remark" varchar,
 | 
			
		||||
    "creator" varchar DEFAULT '',
 | 
			
		||||
    "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
    "updater" varchar DEFAULT '',
 | 
			
		||||
    "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 | 
			
		||||
    "deleted" bit NOT NULL DEFAULT FALSE,
 | 
			
		||||
    PRIMARY KEY ("id")
 | 
			
		||||
) COMMENT 'GoView 项目表';
 | 
			
		||||
		Reference in New Issue
	
	Block a user