diff --git a/README.md b/README.md index 80aeb545..c282b849 100644 --- a/README.md +++ b/README.md @@ -110,14 +110,18 @@ bin/start.bat Windows修改第4行的JAVA_HOME后,双击启动 启动后访问 http://serverip:9095 ``` +源码编译部署和发行版部署可参考在线文档
+https://report.anji-plus.com/report-doc/guide/quicklyDevelop.html ## 谁在使用 -希望你们的logo出现在此,[请点此Issue进行登记](https://gitee.com/anji-plus/report/issues/I3ZXT4)
+希望你们的logo出现在此,[请点此Issue进行登记](https://gitee.com/anji-plus/report/issues/I3ZXT4) ,我们将优先进行技术支持
+ + ## 近期计划 @@ -128,6 +132,15 @@ http://serverip:9095 - 基础图表增加 - 现有图表功能修复/增加 +## 版本问题 +已知以下版本存在兼容性问题 +- Node.js V16 +- Jdk 11 +- Mysql 8.0 +- Windows 11 + +AJ-Report 使用Druid,版本为1.2.6,如果你觉得你配置都是正常但是数据源测试不过,请尝试降低Druid版本 + ## 技术支持 **如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** diff --git a/doc/docs/guide/dashboard.md b/doc/docs/guide/dashboard.md index 6494fc6c..54842dbf 100644 --- a/doc/docs/guide/dashboard.md +++ b/doc/docs/guide/dashboard.md @@ -35,40 +35,57 @@ **存在问题,还在开发中**
### 柱状图 -目前**柱状图-渐变色**图形右侧功能区还在开发调整中
+柱状图数据集对应字典值需要选择一个“X轴”、“柱状”,只需要2个字段
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** + ### 柱状堆叠图 -开发中
+动态的数据集对应字典值需要选择一个“X轴”、“Y轴”、“柱状”,也就是说需要3个字段,不明白可以看看静态数据
+![img.17](../picture/dashboard/img_17.png) +**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** -### 折线图 +### 折线堆叠图 +动态的数据集对应字典值需要选择一个“X轴”、“Y轴”、“折线”,也就是说需要3个字段,不明白可以看看静态数据
+![img.17](../picture/dashboard/img_17.png) **如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** + +### 折线图 +折线图数据集对应字典值需要选择一个“X轴”、“折线”,只需要2个字段
![img_8.png](../picture/dashboard/img_8.png) +**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** ### 柱线图 -**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** +柱线图数据集对应字典值需要选择一个“X轴”、“柱状”、“折线”,需要3个字段
![img9](../picture/dashboard/img_9.png) +**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** ### 饼图 -**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** +饼图的数据集选择的时候,只能选择饼图对应的字典,即“Name”、“Value”,不明白可以参考静态数据
![img10](../picture/dashboard/img_10.png)
![img11](../picture/dashboard/img_11.png)
![img12](../picture/dashboard/img_12.png)
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** ### 漏斗图 -**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** +和饼图一样
![img13](../picture/dashboard/img_13.png)
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** ### 仪表盘 -**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** +数据集只能有一个字段,且字典选择“文本数字”
![img14](../picture/dashboard/img_14.png)
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** ### 中国地图 **注**:气泡地图已支持动态数据,中国地图(迁徙图)暂不支持动态数据 +气泡地图动态数据集,和饼图一样,对应字典值需要选择一个“Name”、“Value”,且name的字段值要和echarts图表里面的值能对应上,可参考静态数据
![img15](../picture/dashboard/img_15.png)
+ ### 百分百图 -**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** +数据集只能有一个字段,且字典选择“文本数字”
![img16](../picture/dashboard/img_16.png)
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** ### 热力图 **开发中**
diff --git a/doc/docs/picture/dashboard/img_17.png b/doc/docs/picture/dashboard/img_17.png new file mode 100644 index 00000000..7f0db579 Binary files /dev/null and b/doc/docs/picture/dashboard/img_17.png differ diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java index 8359a3fa..94494b03 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java @@ -132,4 +132,6 @@ public interface ResponseCode { String SOURCE_CODE_ISEXIST = "4009"; String CLASS_NOT_FOUND = "4010"; + String REPORT_SHARE_LINK_INVALID = "report.share.link.invalid"; + } diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/enums/DeleteFlagEnum.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/enums/DeleteFlagEnum.java new file mode 100644 index 00000000..a883408d --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/enums/DeleteFlagEnum.java @@ -0,0 +1,47 @@ +package com.anjiplus.template.gaea.business.enums; +public enum DeleteFlagEnum { + DELETED(1,"已删除"), + UNDELETED(0,"未删除"), + ; + + private int codeValue; + private String codeDesc; + + private DeleteFlagEnum(int codeValue, String codeDesc) { + this.codeValue = codeValue; + this.codeDesc = codeDesc; + } + + public int getCodeValue(){ return this.codeValue;} + + public String getCodeDesc(){ return this.codeDesc;} + + //根据codeValue获取枚举 + public static DeleteFlagEnum parseFromCodeValue(int codeValue){ + for (DeleteFlagEnum e : DeleteFlagEnum.values()){ + if(e.codeValue == codeValue){ return e;} + } + return null; + } + + //根据codeValue获取描述 + public static String getCodeDescByCodeValue(int codeValue){ + DeleteFlagEnum enumItem = parseFromCodeValue(codeValue); + return enumItem == null ? "" : enumItem.getCodeDesc(); + } + + //验证codeValue是否有效 + public static boolean validateCodeValue(int codeValue){ return parseFromCodeValue(codeValue)!=null;} + + //列出所有值字符串 + public static String getString(){ + StringBuffer buffer = new StringBuffer(); + for (DeleteFlagEnum e : DeleteFlagEnum.values()){ + buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", "); + } + buffer.deleteCharAt(buffer.lastIndexOf(",")); + return buffer.toString().trim(); + } + + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/enums/EnableFlagEnum.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/enums/EnableFlagEnum.java new file mode 100644 index 00000000..5d4b207b --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/enums/EnableFlagEnum.java @@ -0,0 +1,47 @@ +package com.anjiplus.template.gaea.business.enums; +public enum EnableFlagEnum { + ENABLE(1,"启用"), + DISABLE(0,"禁用"), + ; + + private int codeValue; + private String codeDesc; + + private EnableFlagEnum(int codeValue, String codeDesc) { + this.codeValue = codeValue; + this.codeDesc = codeDesc; + } + + public int getCodeValue(){ return this.codeValue;} + + public String getCodeDesc(){ return this.codeDesc;} + + //根据codeValue获取枚举 + public static EnableFlagEnum parseFromCodeValue(int codeValue){ + for (EnableFlagEnum e : EnableFlagEnum.values()){ + if(e.codeValue == codeValue){ return e;} + } + return null; + } + + //根据codeValue获取描述 + public static String getCodeDescByCodeBalue(int codeValue){ + EnableFlagEnum enumItem = parseFromCodeValue(codeValue); + return enumItem == null ? "" : enumItem.getCodeDesc(); + } + + //验证codeValue是否有效 + public static boolean validateCodeValue(int codeValue){ return parseFromCodeValue(codeValue)!=null;} + + //列出所有值字符串 + public static String getString(){ + StringBuffer buffer = new StringBuffer(); + for (EnableFlagEnum e : EnableFlagEnum.values()){ + buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", "); + } + buffer.deleteCharAt(buffer.lastIndexOf(",")); + return buffer.toString().trim(); + } + + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java index a21eff4f..bea91d96 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java @@ -6,6 +6,7 @@ import com.anji.plus.gaea.bean.ResponseBean; import com.anji.plus.gaea.cache.CacheHelper; import com.anji.plus.gaea.utils.JwtBean; import com.anjiplus.template.gaea.business.constant.BusinessConstant; +import com.anjiplus.template.gaea.business.util.JwtUtil; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -68,6 +69,24 @@ public class TokenFilter implements Filter { return; } + //针对大屏分享,优先处理 + String shareToken = request.getHeader("Share-Token"); + if (StringUtils.isNotBlank(shareToken)) { + //两个接口需要处理 + // /reportDashboard/getData + // /reportDashboard/{reportCode} + String reportCode = JwtUtil.getReportCode(shareToken); + if (!uri.endsWith("/getData") && !uri.contains(reportCode)) { + ResponseBean responseBean = ResponseBean.builder().code("50014") + .message("分享链接已过期").build(); + response.getWriter().print(JSONObject.toJSONString(responseBean)); + return; + } + filterChain.doFilter(request, response); + return; + } + + //获取token String token = request.getHeader("Authorization"); if (StringUtils.isBlank(token)) { diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java index 7a41a7fa..3a8cdab9 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java @@ -13,7 +13,7 @@ import com.anjiplus.template.gaea.business.modules.dashboard.controller.dto.Repo import com.anjiplus.template.gaea.business.modules.dashboard.dao.ReportDashboardMapper; import com.anjiplus.template.gaea.business.modules.dashboard.service.ChartStrategy; import com.anjiplus.template.gaea.business.modules.dashboard.service.ReportDashboardService; -import com.anjiplus.template.gaea.business.modules.dashboard.util.DateUtil; +import com.anjiplus.template.gaea.business.util.DateUtil; import com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto.ReportDashboardWidgetDto; import com.anjiplus.template.gaea.business.modules.dashboardwidget.controller.dto.ReportDashboardWidgetValueDto; import com.anjiplus.template.gaea.business.modules.dashboard.dao.entity.ReportDashboard; diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasettransform/service/impl/JsTransformServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasettransform/service/impl/JsTransformServiceImpl.java index 22945676..082a2796 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasettransform/service/impl/JsTransformServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasettransform/service/impl/JsTransformServiceImpl.java @@ -54,9 +54,7 @@ public class JsTransformServiceImpl implements TransformStrategy { engine.eval(js); if(engine instanceof Invocable){ Invocable invocable = (Invocable) engine; - Object exec = invocable.invokeFunction("dataTransform", data); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.convertValue(exec, List.class); + return (List) invocable.invokeFunction("dataTransform", data); } } catch (Exception ex) { diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/report/controller/ReportController.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/report/controller/ReportController.java index ed667273..93745458 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/report/controller/ReportController.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/report/controller/ReportController.java @@ -9,12 +9,12 @@ import com.anjiplus.template.gaea.business.modules.report.controller.dto.ReportD import com.anjiplus.template.gaea.business.modules.report.controller.param.ReportParam; import com.anjiplus.template.gaea.business.modules.report.dao.entity.Report; import com.anjiplus.template.gaea.business.modules.report.service.ReportService; +import com.anjiplus.template.gaea.business.modules.reportshare.controller.dto.ReportShareDto; +import com.anjiplus.template.gaea.business.modules.reportshare.service.ReportShareService; import io.swagger.annotations.Api; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; /** * TODO @@ -28,6 +28,9 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/report") public class ReportController extends GaeaBaseController { + @Autowired + private ReportShareService reportShareService; + @Autowired private ReportService reportService; @@ -47,15 +50,17 @@ public class ReportController extends GaeaBaseController { + + @Autowired + private ReportShareService reportShareService; + + @Override + public GaeaBaseService getService() { + return reportShareService; + } + + @Override + public ReportShare getEntity() { + return new ReportShare(); + } + + @Override + public ReportShareDto getDTO() { + return new ReportShareDto(); + } + + + @GetMapping({"/{id}"}) + @AccessKey + @Override + @Permission(code = "detail", name = "明细") + public ResponseBean detail(@PathVariable("id") Long id) { + this.logger.info("{}根据ID查询服务开始,id为:{}", this.getClass().getSimpleName(), id); + ReportShare result = reportShareService.getDetail(id); + ReportShareDto dto = this.getDTO(); + GaeaBeanUtils.copyAndFormatter(result, dto); + ResponseBean responseBean = this.responseSuccessWithData(this.resultDtoHandle(dto)); + this.logger.info("{}根据ID查询结束,结果:{}", this.getClass().getSimpleName(), GaeaUtils.toJSONString(responseBean)); + return responseBean; + } + + @GetMapping({"/detailByCode"}) + @Permission(code = "detail", name = "明细") + public ResponseBean detailByCode(@RequestParam("shareCode") String shareCode) { + return ResponseBean.builder().data(reportShareService.detailByCode(shareCode)).build(); + } + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/dto/ReportShareDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/dto/ReportShareDto.java new file mode 100644 index 00000000..0b139d01 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/dto/ReportShareDto.java @@ -0,0 +1,56 @@ + +package com.anjiplus.template.gaea.business.modules.reportshare.controller.dto; + +import java.io.Serializable; +import com.anji.plus.gaea.curd.dto.GaeaBaseDTO; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** +* +* @description 报表分享 dto +* @author Raod +* @date 2021-08-18 13:37:26.663 +**/ +@Data +public class ReportShareDto extends GaeaBaseDTO implements Serializable { + /** 分享编码,系统生成,默认UUID */ + @ApiModelProperty(value = "分享编码,系统生成,默认UUID") + private String shareCode; + + /** 分享有效期类型,DIC_NAME=SHARE_VAILD */ + @ApiModelProperty(value = "分享有效期类型,DIC_NAME=SHARE_VAILD") + @NotNull(message = "6002") + private Integer shareValidType; + + /** 分享有效期 */ + @ApiModelProperty(value = "分享有效期") + private Date shareValidTime; + + /** 分享token */ + @ApiModelProperty(value = "分享token") + private String shareToken; + + /** 分享url */ + @ApiModelProperty(value = "分享url") + @NotEmpty(message = "6002") + private String shareUrl; + + /** 报表编码 */ + @ApiModelProperty(value = "报表编码") + @NotEmpty(message = "6002") + private String reportCode; + + /** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */ + @ApiModelProperty(value = "0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG") + private Integer enableFlag; + + /** 0--未删除 1--已删除 DIC_NAME=DELETE_FLAG */ + @ApiModelProperty(value = "0--未删除 1--已删除 DIC_NAME=DELETE_FLAG") + private Integer deleteFlag; + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/param/ReportShareParam.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/param/ReportShareParam.java new file mode 100644 index 00000000..293f8b02 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/param/ReportShareParam.java @@ -0,0 +1,16 @@ +/**/ +package com.anjiplus.template.gaea.business.modules.reportshare.controller.param; + +import com.anji.plus.gaea.curd.params.PageParam; +import lombok.Data; + +import java.io.Serializable; + +/** +* @desc ReportShare 报表分享查询输入类 +* @author Raod +* @date 2021-08-18 13:37:26.663 +**/ +@Data +public class ReportShareParam extends PageParam implements Serializable{ +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/ReportShareMapper.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/ReportShareMapper.java new file mode 100644 index 00000000..852490fe --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/ReportShareMapper.java @@ -0,0 +1,15 @@ +package com.anjiplus.template.gaea.business.modules.reportshare.dao; + +import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper; +import com.anjiplus.template.gaea.business.modules.reportshare.dao.entity.ReportShare; +import org.apache.ibatis.annotations.Mapper; +/** +* ReportShare Mapper +* @author Raod +* @date 2021-08-18 13:37:26.663 +**/ +@Mapper +public interface ReportShareMapper extends GaeaBaseMapper { + + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/entity/ReportShare.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/entity/ReportShare.java new file mode 100644 index 00000000..59bd466d --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/entity/ReportShare.java @@ -0,0 +1,43 @@ + +package com.anjiplus.template.gaea.business.modules.reportshare.dao.entity; + +import lombok.Data; +import io.swagger.annotations.ApiModelProperty; +import com.anji.plus.gaea.curd.entity.GaeaBaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import javax.validation.constraints.*; +import java.util.Date; +/** +* @description 报表分享 entity +* @author Raod +* @date 2021-08-18 13:37:26.663 +**/ +@TableName(value="gaea_report_share") +@Data +public class ReportShare extends GaeaBaseEntity { + /** 分享编码,系统生成,默认UUID */ + private String shareCode; + + /** 分享有效期类型,DIC_NAME=SHARE_VAILD */ + private Integer shareValidType; + + /** 分享有效期 */ + private Date shareValidTime; + + /** 分享token */ + private String shareToken; + + /** 分享url */ + private String shareUrl; + + /** 报表编码 */ + private String reportCode; + + /** 0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG */ + private Integer enableFlag; + + /** 0--未删除 1--已删除 DIC_NAME=DELETE_FLAG */ + private Integer deleteFlag; + + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/ReportShareService.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/ReportShareService.java new file mode 100644 index 00000000..e3613cba --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/ReportShareService.java @@ -0,0 +1,27 @@ + +package com.anjiplus.template.gaea.business.modules.reportshare.service; + +import com.anji.plus.gaea.curd.service.GaeaBaseService; +import com.anjiplus.template.gaea.business.modules.reportshare.controller.dto.ReportShareDto; +import com.anjiplus.template.gaea.business.modules.reportshare.controller.param.ReportShareParam; +import com.anjiplus.template.gaea.business.modules.reportshare.dao.entity.ReportShare; + +/** +* @desc ReportShare 报表分享服务接口 +* @author Raod +* @date 2021-08-18 13:37:26.663 +**/ +public interface ReportShareService extends GaeaBaseService { + + /*** + * 查询详情 + * + * @param id + * @return + */ + ReportShare getDetail(Long id); + + ReportShareDto insertShare(ReportShareDto dto); + + ReportShare detailByCode(String shareCode); +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImpl.java new file mode 100644 index 00000000..60e165c8 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImpl.java @@ -0,0 +1,107 @@ + +package com.anjiplus.template.gaea.business.modules.reportshare.service.impl; + +import com.anji.plus.gaea.constant.BaseOperationEnum; +import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper; +import com.anji.plus.gaea.exception.BusinessException; +import com.anji.plus.gaea.exception.BusinessExceptionBuilder; +import com.anjiplus.template.gaea.business.code.ResponseCode; +import com.anjiplus.template.gaea.business.enums.EnableFlagEnum; +import com.anjiplus.template.gaea.business.modules.reportshare.controller.dto.ReportShareDto; +import com.anjiplus.template.gaea.business.modules.reportshare.dao.ReportShareMapper; +import com.anjiplus.template.gaea.business.modules.reportshare.dao.entity.ReportShare; +import com.anjiplus.template.gaea.business.modules.reportshare.service.ReportShareService; +import com.anjiplus.template.gaea.business.util.DateUtil; +import com.anjiplus.template.gaea.business.util.JwtUtil; +import com.anjiplus.template.gaea.business.util.UuidUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** +* @desc ReportShare 报表分享服务实现 +* @author Raod +* @date 2021-08-18 13:37:26.663 +**/ +@Service +public class ReportShareServiceImpl implements ReportShareService { + + /** + * 默认跳转路由为aj的页面 + */ + private static final String SHARE_FLAG = "#/aj/"; + + private static final String SHARE_URL = "#"; + + @Autowired + private ReportShareMapper reportShareMapper; + + @Override + public GaeaBaseMapper getMapper() { + return reportShareMapper; + } + + @Override + public ReportShare getDetail(Long id) { + ReportShare reportShare = this.selectOne(id); + return reportShare; + } + + @Override + public ReportShareDto insertShare(ReportShareDto dto) { + ReportShareDto reportShareDto = new ReportShareDto(); + ReportShare entity = new ReportShare(); + BeanUtils.copyProperties(dto, entity); + insert(entity); + //将分享链接返回 + reportShareDto.setShareUrl(entity.getShareUrl()); + return reportShareDto; + } + + @Override + public ReportShare detailByCode(String shareCode) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(ReportShare::getShareCode, shareCode); + wrapper.eq(ReportShare::getEnableFlag, EnableFlagEnum.ENABLE.getCodeValue()); + ReportShare reportShare = selectOne(wrapper); + if (null == reportShare) { + throw BusinessExceptionBuilder.build(ResponseCode.REPORT_SHARE_LINK_INVALID); + } + return reportShare; + } + + @Override + public void processBeforeOperation(ReportShare entity, BaseOperationEnum operationEnum) throws BusinessException { + switch (operationEnum) { + case INSERT: + init(entity); + break; + default: + + break; + } + } + + /** + * 新增初始化 + * @param entity + */ + private void init(ReportShare entity) { + //前端地址 window.location.href https://report.anji-plus.com/index.html#/report/bigscreen + //截取#之前的内容 + //http://localhost:9528/#/bigscreen/viewer?reportCode=bigScreen2 + //http://127.0.0.1:9095/reportDashboard/getData + String shareCode = UuidUtil.generateShortUuid(); + entity.setShareCode(shareCode); + if (entity.getShareUrl().contains(SHARE_URL)) { + String prefix = entity.getShareUrl().substring(0, entity.getShareUrl().indexOf("#")); + entity.setShareUrl(prefix + SHARE_FLAG + shareCode); + } else { + entity.setShareUrl(entity.getShareUrl() + SHARE_FLAG + shareCode); + } + entity.setShareValidTime(DateUtil.getFutureDateTmdHms(entity.getShareValidType())); + entity.setShareToken(JwtUtil.createToken(entity.getReportCode(), shareCode, entity.getShareValidTime())); + } +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/AESUtil.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/AESUtil.java new file mode 100644 index 00000000..9a488dd5 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/AESUtil.java @@ -0,0 +1,152 @@ +/* + *Copyright © 2018 anji-plus + *安吉加加信息技术有限公司 + *http://www.anji-plus.com + *All rights reserved. + */ +package com.anjiplus.template.gaea.business.util; + + +import org.apache.commons.lang3.StringUtils; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.spec.SecretKeySpec; +import java.math.BigInteger; +import java.util.Base64; + + +public class AESUtil { + //算法 + private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding"; + + private static final String AES_KEY = "AnjiPLUSAjReport"; + + + /** + * 获取随机key + * + * @return + */ + public static String getKey() { + return AES_KEY; + } + + + /** + * 将byte[]转为各种进制的字符串 + * + * @param bytes byte[] + * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制 + * @return 转换后的字符串 + */ + public static String binary(byte[] bytes, int radix) { + return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数 + } + + /** + * base 64 encode + * + * @param bytes 待编码的byte[] + * @return 编码后的base 64 code + */ + public static String base64Encode(byte[] bytes) { + //return Base64.encodeBase64String(bytes); + return Base64.getEncoder().encodeToString(bytes); + } + + /** + * base 64 decode + * + * @param base64Code 待解码的base 64 code + * @return 解码后的byte[] + * @throws Exception + */ + public static byte[] base64Decode(String base64Code) throws Exception { + Base64.Decoder decoder = Base64.getDecoder(); + return StringUtils.isEmpty(base64Code) ? null : decoder.decode(base64Code); + } + + + /** + * AES加密 + * + * @param content 待加密的内容 + * @param encryptKey 加密密钥 + * @return 加密后的byte[] + * @throws Exception + */ + public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception { + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + kgen.init(128); + Cipher cipher = Cipher.getInstance(ALGORITHMSTR); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES")); + + return cipher.doFinal(content.getBytes("utf-8")); + } + + + /** + * AES加密为base 64 code + * + * @param content 待加密的内容 + * @param encryptKey 加密密钥 + * @return 加密后的base 64 code + * @throws Exception + */ + public static String aesEncrypt(String content, String encryptKey) throws Exception { + if (StringUtils.isBlank(encryptKey)) { + return content; + } + return base64Encode(aesEncryptToBytes(content, encryptKey)); + } + + /** + * AES解密 + * + * @param encryptBytes 待解密的byte[] + * @param decryptKey 解密密钥 + * @return 解密后的String + * @throws Exception + */ + public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception { + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + kgen.init(128); + + Cipher cipher = Cipher.getInstance(ALGORITHMSTR); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES")); + byte[] decryptBytes = cipher.doFinal(encryptBytes); + return new String(decryptBytes); + } + + + /** + * 将base 64 code AES解密 + * + * @param encryptStr 待解密的base 64 code + * @param decryptKey 解密密钥 + * @return 解密后的string + * @throws Exception + */ + public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception { + if (StringUtils.isBlank(decryptKey)) { + return encryptStr; + } + return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey); + } + + /** + * 测试 + */ + public static void main(String[] args) throws Exception { + String randomString = getKey(); + String content = "report"; + System.out.println("加密前:" + content); + System.out.println("加密密钥和解密密钥:" + randomString); + String encrypt = aesEncrypt(content, randomString); + System.out.println("加密后:" + encrypt); + String decrypt = aesDecrypt(encrypt, randomString); + System.out.println("解密后:" + decrypt); + } + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/util/DateUtil.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/DateUtil.java similarity index 64% rename from report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/util/DateUtil.java rename to report-core/src/main/java/com/anjiplus/template/gaea/business/util/DateUtil.java index 3f8403bf..a8e40ea4 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/util/DateUtil.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/DateUtil.java @@ -1,7 +1,8 @@ -package com.anjiplus.template.gaea.business.modules.dashboard.util; +package com.anjiplus.template.gaea.business.util; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Date; /** @@ -44,4 +45,25 @@ public class DateUtil { return null; } } + + /** + * 获取未来第几天的日期 + * + * @param day + * @return + */ + public static Date getFutureDateTmdHms(int day) { + if (day <= 0) { + //默认2099年 + return parse("2099-01-01", defaultDatePattern); + } + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + day); + return calendar.getTime(); + } + + public static void main(String[] args) { + Date futureDateTmdHms = getFutureDateTmdHms(7); + System.out.println(futureDateTmdHms); + } } diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/JwtUtil.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/JwtUtil.java new file mode 100644 index 00000000..c2867eb6 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/JwtUtil.java @@ -0,0 +1,58 @@ +package com.anjiplus.template.gaea.business.util; + +import com.anji.plus.gaea.exception.BusinessExceptionBuilder; +import com.anjiplus.template.gaea.business.code.ResponseCode; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.util.Date; +import java.util.Map; + +/** + * Created by raodeming on 2021/8/18. + */ +public class JwtUtil { + + private static final String JWT_SECRET = "aj-report"; + + public static String createToken(String reportCode, String shareCode, Date expires) { + String token = JWT.create() + .withIssuedAt(new Date()) + .withExpiresAt(expires) + .withClaim("reportCode", reportCode) + .withClaim("shareCode", shareCode) + .sign(Algorithm.HMAC256(JWT_SECRET)); + return token; + } + + + public static Map getClaim(String token) { + try { + JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(JWT_SECRET)).build(); + DecodedJWT decodedJwt = jwtVerifier.verify(token); + return decodedJwt.getClaims(); + } catch (Exception e) { + throw BusinessExceptionBuilder.build(ResponseCode.REPORT_SHARE_LINK_INVALID, e.getMessage()); + } + } + + public static String getReportCode(String token) { + Claim claim = getClaim(token).get("reportCode"); + if (null == claim) { + throw BusinessExceptionBuilder.build(ResponseCode.REPORT_SHARE_LINK_INVALID); + } + return claim.asString(); + } + + public static String getShareCode(String token) { + Claim claim = getClaim(token).get("shareCode"); + if (null == claim) { + throw BusinessExceptionBuilder.build(ResponseCode.REPORT_SHARE_LINK_INVALID); + } + return claim.asString(); + } + +} diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/UuidUtil.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/UuidUtil.java new file mode 100644 index 00000000..b152ea75 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/UuidUtil.java @@ -0,0 +1,44 @@ +package com.anjiplus.template.gaea.business.util; + +import java.util.UUID; + +/** + * Created by raodeming on 2021/8/19. + */ +public class UuidUtil { + + public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", + "W", "X", "Y", "Z" }; + + + /** + * 8位短id + * @return + */ + public static String generateShortUuid() { + StringBuilder builder = new StringBuilder(); + String uuid = UUID.randomUUID().toString().replace("-", ""); + for (int i = 0; i < 8; i++) { + String str = uuid.substring(i * 4, i * 4 + 4); + int x = Integer.parseInt(str, 16); + builder.append(chars[x % 0x3E]); + } + return builder.toString(); + + } + + + public static String generateUuid() { + return UUID.randomUUID().toString().replace("-", ""); + } + + public static void main(String[] args) { + for (int i = 0; i < 100; i++) { + System.out.println(generateShortUuid()); + } + } +} diff --git a/report-core/src/main/resources/bootstrap.yml b/report-core/src/main/resources/bootstrap.yml index e3dd9190..e4157d82 100644 --- a/report-core/src/main/resources/bootstrap.yml +++ b/report-core/src/main/resources/bootstrap.yml @@ -73,7 +73,7 @@ customer: downloadPath: http://10.108.26.197:9095/file/download # 跳过token验证和权限验证的url清单 - skip-authenticate-urls: /gaeaDict/all, /login, /static, /file/download/, /index.html, /favicon.ico + skip-authenticate-urls: /gaeaDict/all, /login, /static, /file/download/, /index.html, /favicon.ico, /reportShare/detailByCode user: ##新增用户默认密码 default: diff --git a/report-core/src/main/resources/db/migration/V1.0.10__create_report_share.sql b/report-core/src/main/resources/db/migration/V1.0.10__create_report_share.sql new file mode 100644 index 00000000..f848dbda --- /dev/null +++ b/report-core/src/main/resources/db/migration/V1.0.10__create_report_share.sql @@ -0,0 +1,86 @@ +use +aj_report; + +CREATE TABLE `gaea_report_share` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `share_code` varchar(50) DEFAULT NULL COMMENT '分享编码,系统生成,默认UUID', + `share_valid_type` int(2) DEFAULT NULL COMMENT '分享有效期类型,DIC_NAME=SHARE_VAILD', + `share_valid_time` datetime DEFAULT NULL COMMENT '分享有效期', + `share_token` varchar(255) DEFAULT NULL COMMENT '分享token', + `share_url` varchar(100) DEFAULT NULL COMMENT '分享url', + `report_code` varchar(50) DEFAULT NULL COMMENT '报表编码', + `enable_flag` int(1) DEFAULT '1' COMMENT '0--已禁用 1--已启用 DIC_NAME=ENABLE_FLAG', + `delete_flag` int(1) DEFAULT '0' COMMENT '0--未删除 1--已删除 DIC_NAME=DELETE_FLAG', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(255) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `version` int(8) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE KEY `UNIQUE_SHARE_CODE` (`share_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报表分享'; + + +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '分享有效期', 'SHARE_VAILD', '报表分享', 'admin', '2021-08-18 13:29:19', 'admin', '2021-08-18 13:29:24', 1); +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '柱状图属性', 'BAR_PROPERTIES', '柱状图属性', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1); +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '折线图属性', 'LINE_PROPERTIES', '折线图属性', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1); +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '柱线图属性', 'BAR_LINE_PROPERTIES', '柱线图属性', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1); +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '饼图属性', 'PIE_PROPERTIES', '饼图、漏斗图', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1); +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '单文本图属性', 'TEXT_PROPERTIES', '仪表盘、百分比、文本框、滚动文本', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1); +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '堆叠图属性', 'STACK_PROPERTIES', '堆叠图属性', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1); +INSERT INTO `aj_report`.`gaea_dict`(`id`, `dict_name`, `dict_code`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , '地图属性', 'MAP_PROPERTIES', '地图属性', 'admin', '2021-04-29 10:28:15', 'admin', '2021-06-23 10:47:20', 1); + + + +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'SHARE_VAILD', '永久有效', '0', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-18 13:30:21', 'admin', '2021-08-18 13:30:21', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default, 'SHARE_VAILD', '1天', '1', NULL, 1, 'zh', NULL, 2, 'admin', '2021-08-18 13:30:39', 'admin', '2021-08-18 13:30:39', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default, 'SHARE_VAILD', '7天', '7', NULL, 1, 'zh', NULL, 3, 'admin', '2021-08-18 13:30:51', 'admin', '2021-08-18 13:30:56', 2); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default, 'SHARE_VAILD', '30天', '30', NULL, 1, 'zh', NULL, 4, 'admin', '2021-08-18 13:31:11', 'admin', '2021-08-18 13:31:11', 1); + +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_PROPERTIES', 'x轴字段', 'xAxis', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:19:35', 'admin', '2021-08-20 10:19:35', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_PROPERTIES', '柱状', 'bar', NULL, 1, 'zh', NULL, 2, 'admin', '2021-08-20 10:19:56', 'admin', '2021-08-20 10:19:56', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'LINE_PROPERTIES', 'x轴字段', 'xAxis', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:27:39', 'admin', '2021-08-20 10:27:39', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'LINE_PROPERTIES', '折线', 'line', NULL, 1, 'zh', NULL, 2, 'admin', '2021-08-20 10:27:49', 'admin', '2021-08-20 10:27:49', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_LINE_PROPERTIES', 'x轴字段', 'xAxis', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:31:51', 'admin', '2021-08-20 10:31:51', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_LINE_PROPERTIES', 'x轴时间轴-时', 'xAxis-hour', NULL, 1, 'zh', NULL, 2, 'admin', '2021-08-20 10:32:11', 'admin', '2021-08-20 10:32:11', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_LINE_PROPERTIES', 'x轴时间轴-天', 'xAxis-day', NULL, 1, 'zh', NULL, 3, 'admin', '2021-08-20 10:32:25', 'admin', '2021-08-20 10:32:25', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_LINE_PROPERTIES', 'x轴时间轴-月', 'xAxis-month', NULL, 1, 'zh', NULL, 4, 'admin', '2021-08-20 10:32:38', 'admin', '2021-08-20 10:32:38', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_LINE_PROPERTIES', '时间轴-年', 'xAxis-year', NULL, 1, 'zh', NULL, 5, 'admin', '2021-08-20 10:32:52', 'admin', '2021-08-20 10:32:52', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_LINE_PROPERTIES', '柱状', 'bar', NULL, 1, 'zh', NULL, 6, 'admin', '2021-08-20 10:33:02', 'admin', '2021-08-20 10:33:02', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'BAR_LINE_PROPERTIES', '折线', 'line', NULL, 1, 'zh', NULL, 7, 'admin', '2021-08-20 10:33:11', 'admin', '2021-08-20 10:33:11', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'PIE_PROPERTIES', '名称name', 'name', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:35:27', 'admin', '2021-08-20 10:35:27', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'PIE_PROPERTIES', '数值value', 'value', NULL, 1, 'zh', NULL, 2, 'admin', '2021-08-20 10:35:38', 'admin', '2021-08-20 10:35:38', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'TEXT_PROPERTIES', '文本数字', 'text', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:36:04', 'admin', '2021-08-20 10:36:04', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', 'x轴字段', 'xAxis', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:31:51', 'admin', '2021-08-20 10:31:51', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', 'x轴时间轴-时', 'xAxis-hour', NULL, 1, 'zh', NULL, 2, 'admin', '2021-08-20 10:32:11', 'admin', '2021-08-20 10:32:11', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', 'x轴时间轴-天', 'xAxis-day', NULL, 1, 'zh', NULL, 3, 'admin', '2021-08-20 10:32:25', 'admin', '2021-08-20 10:32:25', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', 'x轴时间轴-月', 'xAxis-month', NULL, 1, 'zh', NULL, 4, 'admin', '2021-08-20 10:32:38', 'admin', '2021-08-20 10:32:38', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', '时间轴-年', 'xAxis-year', NULL, 1, 'zh', NULL, 5, 'admin', '2021-08-20 10:32:52', 'admin', '2021-08-20 10:32:52', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', 'y轴字段', 'yAxis', NULL, 1, 'zh', NULL, 6, 'admin', '2021-08-20 10:32:52', 'admin', '2021-08-20 10:32:52', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', '柱状', 'bar', NULL, 1, 'zh', NULL, 7, 'admin', '2021-08-20 10:33:02', 'admin', '2021-08-20 10:33:02', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'STACK_PROPERTIES', '折线', 'line', NULL, 1, 'zh', NULL, 8, 'admin', '2021-08-20 10:33:11', 'admin', '2021-08-20 10:33:11', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'MAP_PROPERTIES', '名称name', 'name', NULL, 1, 'zh', NULL, 1, 'admin', '2021-08-20 10:41:00', 'admin', '2021-08-20 10:41:00', 1); +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (default , 'MAP_PROPERTIES', '数值value', 'value', NULL, 1, 'zh', NULL, 2, 'admin', '2021-08-20 10:41:11', 'admin', '2021-08-20 10:41:11', 1); +INSERT INTO `aj_report`.`gaea_report_data_set`(`set_code`, `set_name`, `set_desc`, `source_code`, `dyn_sentence`, `case_result`, `enable_flag`, `delete_flag`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES ('barstack_ajreport', '柱状堆叠数据', '', 'mysql_ajreport', 'select time,type,nums from aj_report_barstack', '[{\"time\":\"2021-07-27\",\"type\":\"A\",\"nums\":12},{\"time\":\"2021-07-27\",\"type\":\"B\",\"nums\":20},{\"time\":\"2021-07-27\",\"type\":\"C\",\"nums\":11},{\"time\":\"2021-07-26\",\"type\":\"A\",\"nums\":11},{\"time\":\"2021-07-26\",\"type\":\"B\",\"nums\":30},{\"time\":\"2021-07-25\",\"type\":\"B\",\"nums\":20},{\"time\":\"2021-07-25\",\"type\":\"C\",\"nums\":15}]', 1, 0, 'admin', '2021-07-27 19:50:52', 'admin', '2021-08-16 14:08:51', 7); + +use +aj_report_init; +CREATE TABLE `aj_report_barstack` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `time` date DEFAULT NULL, + `type` varchar(255) DEFAULT NULL, + `nums` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +/*堆叠图数据*/ +INSERT INTO `aj_report_init`.`aj_report_barstack`(`id`, `time`, `type`, `nums`) VALUES (1, '2021-07-27', 'A', 12); +INSERT INTO `aj_report_init`.`aj_report_barstack`(`id`, `time`, `type`, `nums`) VALUES (2, '2021-07-27', 'B', 20); +INSERT INTO `aj_report_init`.`aj_report_barstack`(`id`, `time`, `type`, `nums`) VALUES (3, '2021-07-27', 'C', 11); +INSERT INTO `aj_report_init`.`aj_report_barstack`(`id`, `time`, `type`, `nums`) VALUES (4, '2021-07-26', 'A', 11); +INSERT INTO `aj_report_init`.`aj_report_barstack`(`id`, `time`, `type`, `nums`) VALUES (5, '2021-07-26', 'B', 30); +INSERT INTO `aj_report_init`.`aj_report_barstack`(`id`, `time`, `type`, `nums`) VALUES (6, '2021-07-25', 'B', 20); +INSERT INTO `aj_report_init`.`aj_report_barstack`(`id`, `time`, `type`, `nums`) VALUES (7, '2021-07-25', 'C', 15); + diff --git a/report-core/src/main/resources/db/migration/V1.0.9__update_dict.sql b/report-core/src/main/resources/db/migration/V1.0.9__update_dict.sql new file mode 100644 index 00000000..15076a90 --- /dev/null +++ b/report-core/src/main/resources/db/migration/V1.0.9__update_dict.sql @@ -0,0 +1,3 @@ +UPDATE `aj_report`.`gaea_dict_item` SET `dict_code` = 'CHART_PROPERTIES', `item_name` = 'x轴字段', `item_value` = 'xAxis', `item_extend` = NULL, `enabled` = 1, `locale` = 'zh', `remark` = NULL, `sort` = 1, `create_by` = 'admin', `create_time` = now(), `update_by` = 'admin', `update_time` = now(), `version` = 1 WHERE `id` = 260; + +INSERT INTO `aj_report`.`gaea_dict_item`(`id`, `dict_code`, `item_name`, `item_value`, `item_extend`, `enabled`, `locale`, `remark`, `sort`, `create_by`, `create_time`, `update_by`, `update_time`, `version`) VALUES (288, 'CHART_PROPERTIES', 'y轴字段', 'yAxis', NULL, 1, 'zh', NULL, 11, 'admin', '2021-07-05 15:33:59', 'admin', '2021-07-05 15:33:59', 1); diff --git a/report-core/src/main/resources/i18n/messages_en_US.properties b/report-core/src/main/resources/i18n/messages_en_US.properties index e0ac3965..4219c464 100644 --- a/report-core/src/main/resources/i18n/messages_en_US.properties +++ b/report-core/src/main/resources/i18n/messages_en_US.properties @@ -47,3 +47,5 @@ Component.load.check.error={0} Component not load 4008=The set code does not allow duplication 4009=The source code does not allow duplication 4010=Can't auto find match driver class + +report.share.link.invalid=report share link invalid diff --git a/report-core/src/main/resources/i18n/messages_zh_CN.properties b/report-core/src/main/resources/i18n/messages_zh_CN.properties index 36ac0a42..c25afa66 100644 --- a/report-core/src/main/resources/i18n/messages_zh_CN.properties +++ b/report-core/src/main/resources/i18n/messages_zh_CN.properties @@ -52,3 +52,4 @@ Component.load.check.error={0}\u7EC4\u4EF6\u672A\u52A0\u8F7D 7001=\u89E3\u6790\u5931\u8D25 +report.share.link.invalid=\u5206\u4EAB\u94FE\u63A5\u5DF2\u5931\u6548 diff --git a/report-core/src/main/resources/mapper/ReportShareMapper.xml b/report-core/src/main/resources/mapper/ReportShareMapper.xml new file mode 100644 index 00000000..b26b7923 --- /dev/null +++ b/report-core/src/main/resources/mapper/ReportShareMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + id,share_code,share_valid_type,share_valid_time,share_url,report_code,enable_flag,delete_flag,create_by,create_time,update_by,update_time,version + + + diff --git a/report-core/src/test/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImplTest.java b/report-core/src/test/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImplTest.java new file mode 100644 index 00000000..41f9a4c6 --- /dev/null +++ b/report-core/src/test/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImplTest.java @@ -0,0 +1,48 @@ +package com.anjiplus.template.gaea.business.modules.reportshare.service.impl; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.junit.jupiter.api.Test; + +import java.util.Date; + +/** + * Created by raodeming on 2021/8/18. + */ +public class ReportShareServiceImplTest { + + @Test + public void jwtTest() throws InterruptedException { + + long l = System.currentTimeMillis(); + + + String sign = JWT.create() + .withIssuedAt(new Date()) + .withExpiresAt(new Date(l + 5000)) + .withClaim("reportCode", "report") + .withClaim("shareCode", "1234567") + .sign(Algorithm.HMAC256("111")); + + + System.out.println(sign); + + Thread.sleep(8000L); + + DecodedJWT verify = JWT.require(Algorithm.HMAC256("111")).build().verify(sign); + + Date expiresAt = verify.getExpiresAt(); + String reportCode = verify.getClaim("reportCode").asString(); + String shareCode = verify.getClaim("shareCode").asString(); + + + System.out.println(expiresAt); + System.out.println(reportCode); + System.out.println(shareCode); + + + + } + +} diff --git a/report-ui/src/api/bigscreen.js b/report-ui/src/api/bigscreen.js index 06347b6e..79217efb 100644 --- a/report-ui/src/api/bigscreen.js +++ b/report-ui/src/api/bigscreen.js @@ -1,4 +1,5 @@ import request from '@/utils/request' +import { getShareToken, getToken } from "@/utils/auth"; // 保存大屏设计 export function insertDashboard(data) { @@ -13,6 +14,7 @@ export function insertDashboard(data) { export function detailDashboard(data) { return request({ url: 'reportDashboard/' + data, + headers: { 'Share-Token': getShareToken(), 'Authorization': getToken() }, method: 'get', }) } @@ -22,6 +24,7 @@ export function queryAllDataSet(data) { return request({ url: 'dataSet/queryAllDataSet', method: 'get', + }) } @@ -38,6 +41,7 @@ export function getData(data) { return request({ url: 'reportDashboard/getData', method: 'post', + headers: { 'Share-Token': getShareToken(), 'Authorization': getToken() }, data, }) } diff --git a/report-ui/src/api/reportShare.js b/report-ui/src/api/reportShare.js new file mode 100644 index 00000000..9967c31f --- /dev/null +++ b/report-ui/src/api/reportShare.js @@ -0,0 +1,50 @@ +import request from '@/utils/request' + +export function reportShareList(params) { + return request({ + url: 'reportShare/pageList', + method: 'GET', + params, + }) +} + +export function reportShareAdd(data) { + return request({ + url: 'report/share', + method: 'post', + data + }) +} + +export function reportShareDeleteBatch(data) { +return request({ +url: 'reportShare/delete/batch', +method: 'post', +data +}) +} + +export function reportShareUpdate(data) { + return request({ + url: 'reportShare', + method: 'put', data, + }) +} + +export function reportShareDetail(data) { + return request({ + url: 'reportShare/' + data.id, + method: 'get', + params: { accessKey: data.accessKey } + }) +} + +export function reportShareDetailByCode(data) { + return request({ + url: 'reportShare/detailByCode', + method: 'get', + params: { shareCode: data } + }) +} + +export default { reportShareList, reportShareAdd, reportShareDeleteBatch, reportShareUpdate, reportShareDetail } diff --git a/report-ui/src/assets/iconfont/demo_index.html b/report-ui/src/assets/iconfont/demo_index.html index f335efb5..f92c2da9 100644 --- a/report-ui/src/assets/iconfont/demo_index.html +++ b/report-ui/src/assets/iconfont/demo_index.html @@ -54,6 +54,18 @@
    +
  • + +
    堆叠图
    +
    &#xe621;
    +
  • + +
  • + +
    堆叠图
    +
    &#xe61f;
    +
  • +
  • 文件
    @@ -750,9 +762,9 @@
    @font-face {
       font-family: 'iconfont';
    -  src: url('iconfont.woff2?t=1628064452460') format('woff2'),
    -       url('iconfont.woff?t=1628064452460') format('woff'),
    -       url('iconfont.ttf?t=1628064452460') format('truetype');
    +  src: url('iconfont.woff2?t=1629425895962') format('woff2'),
    +       url('iconfont.woff?t=1629425895962') format('woff'),
    +       url('iconfont.ttf?t=1629425895962') format('truetype');
     }
     

    第二步:定义使用 iconfont 的样式

    @@ -778,6 +790,24 @@
      +
    • + +
      + 堆叠图 +
      +
      .iconbianzu23 +
      +
    • + +
    • + +
      + 堆叠图 +
      +
      .iconduidietu +
      +
    • +
    • @@ -1822,6 +1852,22 @@
        +
      • + +
        堆叠图
        +
        #iconbianzu23
        +
      • + +
      • + +
        堆叠图
        +
        #iconduidietu
        +
      • +
      • @@ -127,7 +128,8 @@ export default { }, // 分享 visibleForShareDialog: false, - reportCodeForShareDialog: "" + reportCodeForShareDialog: "", + reportNameForShareDialog: "" }; }, mounted() {}, @@ -172,6 +174,7 @@ export default { // 分享 share(val) { this.reportCodeForShareDialog = val.reportCode; + this.reportNameForShareDialog = val.reportName; this.visibleForShareDialog = true; }, openDesign(val) { diff --git a/report-ui/src/views/report/bigscreen/viewer/index.vue b/report-ui/src/views/report/bigscreen/viewer/index.vue index 10bd6642..1e75bd80 100644 --- a/report-ui/src/views/report/bigscreen/viewer/index.vue +++ b/report-ui/src/views/report/bigscreen/viewer/index.vue @@ -14,8 +14,6 @@ :type="widget.type" />
      - -
      技术支持: 安吉加加信息技术有限公司
      diff --git a/report-ui/src/views/report/report/components/share.vue b/report-ui/src/views/report/report/components/share.vue index 8bbff3ec..f61335b3 100644 --- a/report-ui/src/views/report/report/components/share.vue +++ b/report-ui/src/views/report/report/components/share.vue @@ -1,14 +1,45 @@