浏览代码

!3 0.9.2
Merge pull request !3 from Raod/dev

Raod 4 年之前
父节点
当前提交
b31bd6fe6c
共有 61 个文件被更改,包括 3752 次插入216 次删除
  1. 14 1
      README.md
  2. 25 8
      doc/docs/guide/dashboard.md
  3. 二进制
      doc/docs/picture/dashboard/img_17.png
  4. 2 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java
  5. 47 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/enums/DeleteFlagEnum.java
  6. 47 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/enums/EnableFlagEnum.java
  7. 19 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java
  8. 1 1
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java
  9. 1 3
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasettransform/service/impl/JsTransformServiceImpl.java
  10. 16 11
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/report/controller/ReportController.java
  11. 69 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/ReportShareController.java
  12. 56 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/dto/ReportShareDto.java
  13. 16 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/param/ReportShareParam.java
  14. 15 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/ReportShareMapper.java
  15. 43 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/dao/entity/ReportShare.java
  16. 27 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/ReportShareService.java
  17. 107 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImpl.java
  18. 152 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/util/AESUtil.java
  19. 23 1
      report-core/src/main/java/com/anjiplus/template/gaea/business/util/DateUtil.java
  20. 58 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/util/JwtUtil.java
  21. 44 0
      report-core/src/main/java/com/anjiplus/template/gaea/business/util/UuidUtil.java
  22. 1 1
      report-core/src/main/resources/bootstrap.yml
  23. 86 0
      report-core/src/main/resources/db/migration/V1.0.10__create_report_share.sql
  24. 3 0
      report-core/src/main/resources/db/migration/V1.0.9__update_dict.sql
  25. 2 0
      report-core/src/main/resources/i18n/messages_en_US.properties
  26. 1 0
      report-core/src/main/resources/i18n/messages_zh_CN.properties
  27. 26 0
      report-core/src/main/resources/mapper/ReportShareMapper.xml
  28. 48 0
      report-core/src/test/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImplTest.java
  29. 4 0
      report-ui/src/api/bigscreen.js
  30. 50 0
      report-ui/src/api/reportShare.js
  31. 49 3
      report-ui/src/assets/iconfont/demo_index.html
  32. 11 3
      report-ui/src/assets/iconfont/iconfont.css
  33. 0 0
      report-ui/src/assets/iconfont/iconfont.js
  34. 14 0
      report-ui/src/assets/iconfont/iconfont.json
  35. 二进制
      report-ui/src/assets/iconfont/iconfont.ttf
  36. 二进制
      report-ui/src/assets/iconfont/iconfont.woff
  37. 二进制
      report-ui/src/assets/iconfont/iconfont.woff2
  38. 54 0
      report-ui/src/mixins/queryform.js
  39. 15 9
      report-ui/src/permission.js
  40. 2 1
      report-ui/src/router/index.js
  41. 3 1
      report-ui/src/store/modules/user.js
  42. 10 0
      report-ui/src/utils/auth.js
  43. 1 1
      report-ui/src/utils/request.js
  44. 2 1
      report-ui/src/views/dict/dict-item.vue
  45. 38 11
      report-ui/src/views/file-management/index.vue
  46. 143 136
      report-ui/src/views/login.vue
  47. 50 0
      report-ui/src/views/report/aj/index.vue
  48. 7 3
      report-ui/src/views/report/bigscreen/designer/form/dynamicComponents.vue
  49. 1 0
      report-ui/src/views/report/bigscreen/designer/form/dynamicForm.vue
  50. 2 4
      report-ui/src/views/report/bigscreen/designer/index.vue
  51. 1341 0
      report-ui/src/views/report/bigscreen/designer/tools.js
  52. 411 0
      report-ui/src/views/report/bigscreen/designer/widget/bar/widgetBarStackChart.vue
  53. 1 2
      report-ui/src/views/report/bigscreen/designer/widget/bar/widgetGradientColorBarchart.vue
  54. 443 0
      report-ui/src/views/report/bigscreen/designer/widget/line/widgetLineStackChart.vue
  55. 6 1
      report-ui/src/views/report/bigscreen/designer/widget/temp.vue
  56. 6 1
      report-ui/src/views/report/bigscreen/designer/widget/widget.vue
  57. 4 1
      report-ui/src/views/report/bigscreen/index.vue
  58. 0 2
      report-ui/src/views/report/bigscreen/viewer/index.vue
  59. 102 4
      report-ui/src/views/report/report/components/share.vue
  60. 28 1
      report-ui/src/views/report/report/index.vue
  61. 5 5
      report-ui/src/views/report/resultset/components/EditDataSet.vue

+ 14 - 1
README.md

@@ -110,14 +110,18 @@ bin/start.bat Windows修改第4行的JAVA_HOME后,双击启动
 启动后访问
 http://serverip:9095
 ```
+源码编译部署和发行版部署可参考在线文档 <br>
+https://report.anji-plus.com/report-doc/guide/quicklyDevelop.html
 
 ## 谁在使用
 
-希望你们的logo出现在此,[请点此Issue进行登记](https://gitee.com/anji-plus/report/issues/I3ZXT4) <br>
+希望你们的logo出现在此,[请点此Issue进行登记](https://gitee.com/anji-plus/report/issues/I3ZXT4) ,我们将优先进行技术支持 <br>
 
 <a href='http://www.anji-plus.com/'> <img src="https://report.anji-plus.com/file/download/d287d4d3-d30b-4850-9bac-a6c991409251" width = "130" height = "50" align=left/> </a>
 <a href='https://www.yunstech.cn/'><img src="https://www.yunstech.cn/images/logo.png" width = "130" height = "50" /> </a>
 <a href='http://www.fgkb.net/'><img src="https://report.anji-plus.com/file/download/9ee5b709-5033-4cd5-a784-ebd2877fd373" width = "130" height = "50" /> </a>
+<a href='https://www.gykjweb.com/'><img src="https://report.anji-plus.com/file/download/d13b03f5-0c20-4878-9a79-f3c76b44bfd9" width = "130" height = "130" /> </a>
+
 
 ## 近期计划
 
@@ -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) <br>**

+ 25 - 8
doc/docs/guide/dashboard.md

@@ -35,40 +35,57 @@
 **存在问题,还在开发中**<br>
 
 ### 柱状图
-目前**柱状图-渐变色**图形右侧功能区还在开发调整中 <br>
+柱状图数据集对应字典值需要选择一个“X轴”、“柱状”,只需要2个字段 <br>
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
+
 
 ### 柱状堆叠图
-开发中 <br>
+动态的数据集对应字典值需要选择一个“X轴”、“Y轴”、“柱状”,也就是说需要3个字段,不明白可以看看静态数据 <br>
+![img.17](../picture/dashboard/img_17.png)
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
 
-### 折线图
+### 折线堆叠图 
+动态的数据集对应字典值需要选择一个“X轴”、“Y轴”、“折线”,也就是说需要3个字段,不明白可以看看静态数据 <br>
+![img.17](../picture/dashboard/img_17.png)
 **如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
+
+### 折线图
+折线图数据集对应字典值需要选择一个“X轴”、“折线”,只需要2个字段 <br>
 ![img_8.png](../picture/dashboard/img_8.png)
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
 
 ### 柱线图
-**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
+柱线图数据集对应字典值需要选择一个“X轴”、“柱状”、“折线”,需要3个字段 <br>
 ![img9](../picture/dashboard/img_9.png)
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
 
 ### 饼图
-**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
+饼图的数据集选择的时候,只能选择饼图对应的字典,即“Name”、“Value”,不明白可以参考静态数据 <br>
 ![img10](../picture/dashboard/img_10.png) <br>
 ![img11](../picture/dashboard/img_11.png) <br>
 ![img12](../picture/dashboard/img_12.png) <br>
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
 
 ### 漏斗图
-**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
+和饼图一样 <br>
 ![img13](../picture/dashboard/img_13.png) <br>
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
 
 ### 仪表盘
-**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
+数据集只能有一个字段,且字典选择“文本数字” <br>
 ![img14](../picture/dashboard/img_14.png) <br>
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
 
 ### 中国地图
 **注**:气泡地图已支持动态数据,中国地图(迁徙图)暂不支持动态数据
+气泡地图动态数据集,和饼图一样,对应字典值需要选择一个“Name”、“Value”,且name的字段值要和echarts图表里面的值能对应上,可参考静态数据 <br>
 ![img15](../picture/dashboard/img_15.png) <br>
 
+
 ### 百分百图
-**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
+数据集只能有一个字段,且字典选择“文本数字” <br>
 ![img16](../picture/dashboard/img_16.png) <br>
+**如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues) <br>**
 
 ### 热力图
 **开发中** <br>

二进制
doc/docs/picture/dashboard/img_17.png


+ 2 - 0
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";
+
 }

+ 47 - 0
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();
+    }
+
+
+}

+ 47 - 0
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();
+    }
+
+
+}

+ 19 - 0
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)) {

+ 1 - 1
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;

+ 1 - 3
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<JSONObject>) invocable.invokeFunction("dataTransform", data);
             }
 
         } catch (Exception ex) {

+ 16 - 11
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<ReportParam, Report, ReportDto> {
 
+    @Autowired
+    private ReportShareService reportShareService;
+
     @Autowired
     private ReportService reportService;
 
@@ -47,15 +50,17 @@ public class ReportController extends GaeaBaseController<ReportParam, Report, Re
     }
 
     @DeleteMapping("/delReport")
-    @Permission(
-            code = "delete",
-            name = "删除"
-    )
-    @GaeaAuditLog(
-            pageTitle = "删除"
-    )
+    @Permission(code = "delete", name = "删除")
+    @GaeaAuditLog(pageTitle = "删除")
     public ResponseBean delReport(@RequestBody ReportDto reportDto) {
         reportService.delReport(reportDto);
         return ResponseBean.builder().build();
     }
+
+    @PostMapping("/share")
+    @Permission(code = "share", name = "分享")
+    @GaeaAuditLog(pageTitle = "分享")
+    public ResponseBean share(@Validated @RequestBody ReportShareDto dto) {
+        return ResponseBean.builder().data(reportShareService.insertShare(dto)).build();
+    }
 }

+ 69 - 0
report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/ReportShareController.java

@@ -0,0 +1,69 @@
+
+package com.anjiplus.template.gaea.business.modules.reportshare.controller;
+
+import com.anji.plus.gaea.annotation.AccessKey;
+import com.anji.plus.gaea.annotation.Permission;
+import com.anji.plus.gaea.bean.ResponseBean;
+import com.anji.plus.gaea.curd.controller.GaeaBaseController;
+import com.anji.plus.gaea.curd.service.GaeaBaseService;
+import com.anji.plus.gaea.utils.GaeaBeanUtils;
+import com.anji.plus.gaea.utils.GaeaUtils;
+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;
+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.*;
+
+/**
+ * @author Raod
+ * @desc 报表分享 controller
+ * @date 2021-08-18 13:37:26.663
+ **/
+@RestController
+@Api(tags = "报表分享管理")
+@RequestMapping("/reportShare")
+@Permission(code = "reportShareManage", name = "报表分享管理")
+public class ReportShareController extends GaeaBaseController<ReportShareParam, ReportShare, ReportShareDto> {
+
+    @Autowired
+    private ReportShareService reportShareService;
+
+    @Override
+    public GaeaBaseService<ReportShareParam, ReportShare> 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();
+    }
+
+}

+ 56 - 0
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;
+
+}

+ 16 - 0
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{
+}

+ 15 - 0
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<ReportShare> {
+
+
+}

+ 43 - 0
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;
+
+
+}

+ 27 - 0
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<ReportShareParam, ReportShare> {
+
+    /***
+     * 查询详情
+     *
+     * @param id
+     * @return
+     */
+    ReportShare getDetail(Long id);
+
+    ReportShareDto insertShare(ReportShareDto dto);
+
+    ReportShare detailByCode(String shareCode);
+}

+ 107 - 0
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<ReportShare> 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<ReportShare> 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()));
+    }
+}

+ 152 - 0
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);
+    }
+
+}

+ 23 - 1
report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/util/DateUtil.java → 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);
+    }
 }

+ 58 - 0
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<String, Claim> 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();
+    }
+
+}

+ 44 - 0
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());
+        }
+    }
+}

+ 1 - 1
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:

+ 86 - 0
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);
+

+ 3 - 0
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);

+ 2 - 0
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

+ 1 - 0
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

+ 26 - 0
report-core/src/main/resources/mapper/ReportShareMapper.xml

@@ -0,0 +1,26 @@
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.anjiplus.template.gaea.business.modules.reportshare.dao.ReportShareMapper">
+
+    <resultMap type="com.anjiplus.template.gaea.business.modules.reportshare.dao.entity.ReportShare" id="ReportShareMap">
+        <!--jdbcType="{column.columnType}"-->
+        <result property="id" column="id"  />
+        <result property="shareCode" column="share_code"  />
+        <result property="shareValidType" column="share_valid_type"  />
+        <result property="shareValidTime" column="share_valid_time"  />
+        <result property="shareUrl" column="share_url"  />
+        <result property="reportCode" column="report_code"  />
+        <result property="enableFlag" column="enable_flag"  />
+        <result property="deleteFlag" column="delete_flag"  />
+        <result property="createBy" column="create_by"  />
+        <result property="createTime" column="create_time"  />
+        <result property="updateBy" column="update_by"  />
+        <result property="updateTime" column="update_time"  />
+        <result property="version" column="version"  />
+
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        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
+    </sql>
+
+</mapper>

+ 48 - 0
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);
+
+
+
+    }
+
+}

+ 4 - 0
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,
   })
 }

+ 50 - 0
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 }

+ 49 - 3
report-ui/src/assets/iconfont/demo_index.html

@@ -54,6 +54,18 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe621;</span>
+                <div class="name">堆叠图</div>
+                <div class="code-name">&amp;#xe621;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe61f;</span>
+                <div class="name">堆叠图</div>
+                <div class="code-name">&amp;#xe61f;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe645;</span>
                 <div class="name">文件</div>
@@ -750,9 +762,9 @@
 <pre><code class="language-css"
 >@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');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -778,6 +790,24 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont iconbianzu23"></span>
+            <div class="name">
+              堆叠图
+            </div>
+            <div class="code-name">.iconbianzu23
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont iconduidietu"></span>
+            <div class="name">
+              堆叠图
+            </div>
+            <div class="code-name">.iconduidietu
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont iconfill_folder"></span>
             <div class="name">
@@ -1822,6 +1852,22 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconbianzu23"></use>
+                </svg>
+                <div class="name">堆叠图</div>
+                <div class="code-name">#iconbianzu23</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#iconduidietu"></use>
+                </svg>
+                <div class="name">堆叠图</div>
+                <div class="code-name">#iconduidietu</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#iconfill_folder"></use>

+ 11 - 3
report-ui/src/assets/iconfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 1513211 */
-  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 {
@@ -13,6 +13,14 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.iconbianzu23:before {
+  content: "\e621";
+}
+
+.iconduidietu:before {
+  content: "\e61f";
+}
+
 .iconfill_folder:before {
   content: "\e645";
 }

文件差异内容过多而无法显示
+ 0 - 0
report-ui/src/assets/iconfont/iconfont.js


+ 14 - 0
report-ui/src/assets/iconfont/iconfont.json

@@ -5,6 +5,20 @@
   "css_prefix_text": "icon",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "18888301",
+      "name": "堆叠图",
+      "font_class": "bianzu23",
+      "unicode": "e621",
+      "unicode_decimal": 58913
+    },
+    {
+      "icon_id": "23457042",
+      "name": "堆叠图",
+      "font_class": "duidietu",
+      "unicode": "e61f",
+      "unicode_decimal": 58911
+    },
     {
       "icon_id": "5472881",
       "name": "文件",

二进制
report-ui/src/assets/iconfont/iconfont.ttf


二进制
report-ui/src/assets/iconfont/iconfont.woff


二进制
report-ui/src/assets/iconfont/iconfont.woff2


+ 54 - 0
report-ui/src/mixins/queryform.js

@@ -109,6 +109,7 @@ export default {
       // widget-gauge 仪表盘
       // widget-text 文本框
       // widge-table 表格(数据不要转)
+      // widget-stackchart 堆叠图
       const chartType = params.chartType
       if (
         chartType == "widget-barchart" ||
@@ -125,6 +126,8 @@ export default {
         return this.gaugeFn(params.chartProperties, data);
       } else if (chartType == "widget-text") {
         return this.widgettext(params.chartProperties, data)
+      } else if (chartType == "widget-stackchart") {
+        return this.stackChartFn(params.chartProperties, data)
       } else {
         return data
       }
@@ -157,6 +160,39 @@ export default {
       ananysicData["series"] = series;
       return ananysicData;
     },
+    //堆叠图
+    stackChartFn(chartProperties, data) {
+      const ananysicData = {};
+      const series = [];
+      //全部字段字典值
+      const types = Object.values(chartProperties)
+      //x轴字段、y轴字段名
+      const xAxisField = Object.keys(chartProperties)[types.indexOf('xAxis')]
+      const yAxisField = Object.keys(chartProperties)[types.indexOf('yAxis')]
+      //x轴数值去重,y轴去重
+      const xAxisList = this.setUnique(data.map(item => item[xAxisField]))
+      const yAxisList = this.setUnique(data.map(item => item[yAxisField]))
+      const dataGroup = this.setGroupBy(data, yAxisField)
+
+      for (const key in chartProperties) {
+        if (chartProperties[key] !== 'yAxis' && !chartProperties[key].startsWith('xAxis')) {
+          Object.keys(dataGroup).forEach(item => {
+            const data = new Array(yAxisList.length).fill(0)
+            dataGroup[item].forEach(res => {
+              data[xAxisList.indexOf(res[xAxisField])]= res[key]
+            })
+            series.push({
+              name: yAxisList[item],
+              type: chartProperties[key],
+              data,
+            })
+          })
+        }
+      }
+      ananysicData["xAxis"] = xAxisList;
+      ananysicData["series"] = series;
+      return ananysicData;
+    },
     // 饼图、漏斗图
     piechartFn(chartProperties, data) {
       const ananysicData = [];
@@ -208,6 +244,24 @@ export default {
       }
       return ananysicData;
     },
+    setUnique(arr) {
+      let newArr = [];
+      arr.forEach(item => {
+        return newArr.includes(item) ? '' : newArr.push(item);
+      });
+      return newArr;
+    },
+    setGroupBy(array, name) {
+      const groups = {}
+      array.forEach(function (o) {
+        const group = JSON.stringify(o[name])
+        groups[group] = groups[group] || []
+        groups[group].push(o)
+      })
+      return Object.keys(groups).map(function (group) {
+        return groups[group]
+      })
+    },
   },
   watch: {
     'selectInput.keyname'(newVal, oldVal) {

+ 15 - 9
report-ui/src/permission.js

@@ -4,14 +4,14 @@ import NProgress from 'nprogress' // Progress 进度条
 import 'nprogress/nprogress.css'// Progress 进度条样式
 import { getToken, getAccessUser } from "@/utils/auth";
 export default router
-var whiteList = ['/login']
+var whiteList = ['/login', '/aj/**', '/bigscreen/viewer']
 //  判断是否需要登录权限 以及是否登录
 router.beforeEach((to, from, next) => {
-  
+
   NProgress.start()
-  var token = getToken(); 
+  var token = getToken();
   var gaeaUser = getAccessUser();
-  // 如果有token 
+  // 如果有token
   if (token) {
     if (to.path == '/login') {
       next('/index')
@@ -20,13 +20,19 @@ router.beforeEach((to, from, next) => {
       next()
     }
   }else {
-    // 如果没有token  
-    if ((token == null || token == '' || token ==undefined || gaeaUser == {}) && (to.meta != null && to.meta.requireAuth == true)) { // 在免登录白名单,直接进入
-      next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
-      NProgress.done()
-    } else {
+    console.log(to.path)
+    if (whiteList.includes(to.path)) {
       next()
+    }else {
+      // 如果没有token
+      if ((token == null || token == '' || token ==undefined || gaeaUser == {}) && (to.meta != null && to.meta.requireAuth == true)) {// 在免登录白名单,直接进入
+        next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页
+        NProgress.done();
+      } else {
+        next();
+      }
     }
+
   }
 })
 

+ 2 - 1
report-ui/src/router/index.js

@@ -27,6 +27,7 @@ import Layout from '../views/layout/Layout'
 **/
 export const constantRouterMap = [
   { path: '/login', component: () => import('@/views/login'), hidden: true },
+  { path: '/aj/**', component: () => import('@/views/report/aj'), hidden: true },
   {
     path: '/index', component: Layout, name: 'index', meta: { title: '首页', icon: 'iconhome2' },
     children: [
@@ -56,7 +57,7 @@ export const constantRouterMap = [
     children: [
       { path: 'file', name: 'file', component: () => import('@/views/file-management/index'), meta: { title: '文件管理', icon: 'iconfill_folder', keepAlive: true, requireAuth: true, permission: 'fileManage'} },
       { path: 'dict', name: 'dict', component: () => import('@/views/dict/index'), meta: { title: '数据字典', icon: 'iconzidian', keepAlive: true, requireAuth: true, permission: 'dictManage'} },
-      { path: 'dictItem', name: 'dictItem', component: () => import('@/views/dict/dict-item'), meta: { title: '字典项', icon: 'iconzidianxiang', keepAlive: true, requireAuth: true, permission: 'dictItemManage'} },
+      { path: 'dictItem', name: 'dictItem', component: () => import('@/views/dict/dict-item'), hidden: true, meta: { title: '字典项', icon: 'iconzidianxiang', keepAlive: true, requireAuth: true, permission: 'dictItemManage'} },
     ]
   },
   { path: '/bigscreen/viewer', component: () => import('@/views/report/bigscreen/viewer'), hidden: true, meta: { requireAuth: true }},

+ 3 - 1
report-ui/src/store/modules/user.js

@@ -1,5 +1,5 @@
 import { login, logout } from '@/api/login'
-import { setToken, delToken, setAccessUser, delAccessUser } from '@/utils/auth'
+import {setToken, delToken, setAccessUser, delAccessUser, delShareToken} from '@/utils/auth'
 
 const user = {
   state: {
@@ -51,6 +51,7 @@ const user = {
           commit('SET_TOKEN', '')
           commit('SET_ACCESSUSER', {})
           delToken()
+          delShareToken()
           delAccessUser()
           resolve()
         }).catch(error => {
@@ -65,6 +66,7 @@ const user = {
         commit('SET_TOKEN', '')
         commit('SET_ACCESSUSER', {})
         delToken()
+        delShareToken()
         delAccessUser()
         resolve()
       })

+ 10 - 0
report-ui/src/utils/auth.js

@@ -1,17 +1,27 @@
 import { getStorageItem, setStorageItem, delStorageItem } from '@/utils/storage'
 
 const TokenKey = 'token'
+const ShareTokenKey = 'shareToken'
 const AccessUserKey = 'gaeaUser'
 
 export function getToken() {
   return getStorageItem(TokenKey)
 }
+export function getShareToken() {
+  return getStorageItem(ShareTokenKey) == null ? '' : getStorageItem(ShareTokenKey);
+}
 export function setToken(token) {
   return setStorageItem(TokenKey, token)
 }
+export function setShareToken(shareToken) {
+  return setStorageItem(ShareTokenKey, shareToken)
+}
 export function delToken() {
   return delStorageItem(TokenKey)
 }
+export function delShareToken() {
+  return delStorageItem(ShareTokenKey)
+}
 
 export function getAccessUser() {
   return getStorageItem(AccessUserKey)

+ 1 - 1
report-ui/src/utils/request.js

@@ -49,7 +49,7 @@ service.interceptors.response.use(
         type: 'error',
         duration: 5 * 1000
       })
-      return Promise.reject('error')
+      return response.data
     } else {
       return response.data
     }

+ 2 - 1
report-ui/src/views/dict/dict-item.vue

@@ -177,7 +177,8 @@ export default {
             rules: [
               { required: true, message: "状态不能为空", trigger: "blur" }
             ],
-            disabled: false
+            disabled: false,
+            defaultValue: 1
           },
           {
             label: "排序", // 排序

+ 38 - 11
report-ui/src/views/file-management/index.vue

@@ -1,19 +1,22 @@
 <template>
   <anji-crud ref="listPage" :option="crudOption">
     <template v-slot:buttonLeftOnTable>
-      <el-upload class="el-upload" :action="uploadUrl" :headers="headers" :on-success="handleUpload" :on-error="handleUpload" :show-file-list="false" :limit="1">
+      <el-upload class="el-upload" ref="upload" :action="uploadUrl" :headers="headers" :on-success="handleUpload"
+                 :on-error="handleError" :show-file-list="false" :limit="1">
         <el-button type="primary" icon="el-icon" v-permission="'fileManage:upload'">文件上传</el-button>
       </el-upload>
     </template>
 
     <template slot="rowButton" slot-scope="props">
+      <el-button type="text" @click="copyUrlPath(props)">复制url</el-button>
       <el-button type="text" @click="customButtom(props)">下载</el-button>
     </template>
   </anji-crud>
 </template>
 <script>
-import { fileList, fileAdd, fileDel, fileUpdate, fileDetail } from '@/api/file'
-import { getToken } from '@/utils/auth'
+import {fileList, fileAdd, fileDel, fileUpdate, fileDetail} from '@/api/file'
+import {getToken} from '@/utils/auth'
+
 export default {
   name: 'File',
   components: {
@@ -95,7 +98,7 @@ export default {
             editField: 'fileId',
             tableHide: true, // 表格中不显示
             inputType: 'input',
-            rules: [{ min: 1, max: 64, message: '不超过64个字符', trigger: 'blur' }],
+            rules: [{min: 1, max: 64, message: '不超过64个字符', trigger: 'blur'}],
             disabled: false,
           },
           {
@@ -104,7 +107,7 @@ export default {
             field: 'fileType',
             editField: 'fileType',
             inputType: 'input',
-            rules: [{ min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur' }],
+            rules: [{min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur'}],
             disabled: false,
           },
           {
@@ -113,7 +116,7 @@ export default {
             field: 'filePath',
             editField: 'filePath',
             inputType: 'input',
-            rules: [{ min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur' }],
+            rules: [{min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur'}],
             disabled: false,
           },
           {
@@ -122,7 +125,7 @@ export default {
             field: 'urlPath',
             editField: 'urlPath',
             inputType: 'input',
-            rules: [{ min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur' }],
+            rules: [{min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur'}],
             disabled: false,
           },
           {
@@ -131,7 +134,7 @@ export default {
             field: 'fileInstruction',
             editField: 'fileInstruction',
             inputType: 'input',
-            rules: [{ min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur' }],
+            rules: [{min: 1, max: 1024, message: '不超过1024个字符', trigger: 'blur'}],
             disabled: false,
           },
           {
@@ -162,21 +165,45 @@ export default {
     },
   },
 
-  created() {},
+  created() {
+  },
   methods: {
     // 上传成功的回调
-    handleUpload(response) {
+    handleUpload(response, file, fileList) {
       console.log(this)
       // 触发查询按钮
       this.$refs.listPage.handleQueryForm()
+      //清除el-upload组件中的文件
+      this.$refs.upload.clearFiles()
+    },
+    handleError() {
+      this.$message({
+        message: '上传失败!',
+        type: 'error',
+      })
     },
-    handleError() {},
     async downloadFile(row) {
       window.open(row.urlPath)
     },
     customButtom(val) {
       this.downloadFile(val.msg)
     },
+    copyUrlPath(val) {
+      this.copyToClip(val.msg.urlPath)
+      this.$message({
+        message: '已将url路径复制至剪切板!',
+        type: 'success',
+      })
+    },
+    copyToClip(content, message) {
+      var aux = document.createElement("input");
+      aux.setAttribute("value", content);
+      document.body.appendChild(aux);
+      aux.select();
+      document.execCommand("copy");
+      document.body.removeChild(aux);
+    },
+
   },
 }
 </script>

+ 143 - 136
report-ui/src/views/login.vue

@@ -8,20 +8,19 @@
   <div class="login_container">
     <!-- 顶部logo -->
     <div class="login_title">
-      <img src="@/assets/images/home-logo.png"
-           alt="logo" />
+      <img src="@/assets/images/home-logo.png" alt="logo" />
     </div>
     <div class="login_contant">
-      <img src="@/assets/images/login.png"
-           alt="image"
-           class="login_img" />
-      <el-form ref="loginForm"
-               :model="loginForm"
-               :rules="loginRules"
-               class="login_form"
-               autocomplete="on"
-               label-position="left"
-               @keyup.enter.native="handleLogin">
+      <img src="@/assets/images/login.png" alt="image" class="login_img" />
+      <el-form
+        ref="loginForm"
+        :model="loginForm"
+        :rules="loginRules"
+        class="login_form"
+        autocomplete="on"
+        label-position="left"
+        @keyup.enter.native="handleLogin"
+      >
         <div class="title_container">
           <h3 class="title">
             HELLO,
@@ -37,41 +36,48 @@
           <div>
             <p>用户名</p>
             <el-form-item prop="loginName">
-              <el-input ref="loginName"
-                        v-model="loginForm.loginName"
-                        placeholder="用户名"
-                        name="loginName"
-                        type="text"
-                        tabindex="1"
-                        autocomplete="on"
-                        @focus="setTop('0')"
-                        @change="getPsw" />
+              <el-input
+                ref="loginName"
+                v-model="loginForm.loginName"
+                placeholder="用户名"
+                name="loginName"
+                type="text"
+                tabindex="1"
+                autocomplete="on"
+                @focus="setTop('0')"
+                @change="getPsw"
+              />
             </el-form-item>
           </div>
           <div>
             <p>密码</p>
-            <input name="password"
-                   type="password"
-                   autocomplete="off"
-                   class="take" />
-            <el-tooltip v-model="capsTooltip"
-                        content="Caps lock is On"
-                        placement="right"
-                        manual>
+            <input
+              name="password"
+              type="password"
+              autocomplete="off"
+              class="take"
+            />
+            <el-tooltip
+              v-model="capsTooltip"
+              content="Caps lock is On"
+              placement="right"
+              manual
+            >
               <el-form-item prop="password">
-                <el-input :key="passwordType"
-                          ref="password"
-                          v-model="loginForm.password"
-                          :type="passwordType"
-                          placeholder="用户密码"
-                          name="password"
-                          tabindex="2"
-                          autocomplete="on"
-                          @blur="capsTooltip = false"
-                          @focus="setTop('50')"
-                          @keyup.native="checkCapslock" />
-                <span class="show_pwd"
-                      @click="showPwd">
+                <el-input
+                  :key="passwordType"
+                  ref="password"
+                  v-model="loginForm.password"
+                  :type="passwordType"
+                  placeholder="用户密码"
+                  name="password"
+                  tabindex="2"
+                  autocomplete="on"
+                  @blur="capsTooltip = false"
+                  @focus="setTop('50')"
+                  @keyup.native="checkCapslock"
+                />
+                <span class="show_pwd" @click="showPwd">
                   <i class="el-icon-view" />
                 </span>
               </el-form-item>
@@ -80,180 +86,181 @@
         </div>
         <div class="control">
           <div class="remember">
-            <input v-model="rememberPsw"
-                   type="checkbox" />
+            <input v-model="rememberPsw" type="checkbox" />
             <p>记住密码</p>
           </div>
         </div>
-        <el-button :loading="loading"
-                   type="primary"
-                   class="login_btn"
-                   @click.native.prevent="handleLogin">登录</el-button>
+        <el-button
+          :loading="loading"
+          type="primary"
+          class="login_btn"
+          @click.native.prevent="handleLogin"
+          >登录</el-button
+        >
       </el-form>
     </div>
     <!--  验证码  -->
-    <Verify v-if="needCaptcha"
-            ref="verify"
-            :captcha-type="'blockPuzzle'"
-            :img-size="{ width: '400px', height: '200px' }"
-            @success="verifylogin" />
+    <Verify
+      v-if="needCaptcha"
+      ref="verify"
+      :captcha-type="'blockPuzzle'"
+      :img-size="{ width: '400px', height: '200px' }"
+      @success="verifylogin"
+    />
   </div>
 </template>
 
 <script>
-import Verify from '@/components/verifition/Verify'
-import cookies from 'js-cookie'
-import { Decrypt, Encrypt } from '@/utils/index'
-import { login } from '@/api/login'
-import { transPsw } from '@/utils/encrypted'
+import Verify from "@/components/verifition/Verify";
+import cookies from "js-cookie";
+import { Decrypt, Encrypt } from "@/utils/index";
+import { login } from "@/api/login";
+import { transPsw } from "@/utils/encrypted";
 import { setToken, setAccessUser } from "@/utils/auth";
 export default {
-  name: 'Login',
+  name: "Login",
   components: {
-    Verify,
+    Verify
   },
-  data () {
+  data() {
     return {
-      activeTop: '-50%', // 色条滑块控制
+      activeTop: "-50%", // 色条滑块控制
       rememberPsw: false, // 记住密码选择框
       loginForm: {
-        loginName: '',
-        password: '',
-        verifyCode: '',
+        loginName: "",
+        password: "",
+        verifyCode: ""
       }, // 登录表单
       loginRules: {
-        loginName: [{ required: true, message: '用户名必填', trigger: 'blur' }],
-        password: [
-          { required: true, message: '用户密码必填', trigger: 'blur' },
-        ],
+        loginName: [{ required: true, message: "用户名必填", trigger: "blur" }],
+        password: [{ required: true, message: "用户密码必填", trigger: "blur" }]
       }, // 登录表单验证
-      passwordType: 'password', // 用来控制查看密码操作时的输入框类型
+      passwordType: "password", // 用来控制查看密码操作时的输入框类型
       capsTooltip: false, // 键盘大写是否打开
       loading: false, // 登录loding
       redirect: undefined, // 记录重定向地址
       otherQuery: {}, // 记录重定向地址中的参数
-      needCaptcha: false,
-    }
+      needCaptcha: false
+    };
   },
   watch: {
     $route: {
       // 监听路由获取上个路由(from)的地址和参数
-      handler: function (route) {
-        const query = route.query
+      handler: function(route) {
+        const query = route.query;
         if (query) {
-          this.redirect = query.redirect
-          this.otherQuery = this.getOtherQuery(query)
+          this.redirect = query.redirect;
+          this.otherQuery = this.getOtherQuery(query);
         }
       },
-      immediate: true,
-    },
+      immediate: true
+    }
   },
-  mounted () {
+  mounted() {
     // 获取焦点
-    if (this.loginForm.loginName === '') {
-      this.$refs.loginName.focus()
-    } else if (this.loginForm.password === '') {
-      this.$refs.password.focus()
+    if (this.loginForm.loginName === "") {
+      this.$refs.loginName.focus();
+    } else if (this.loginForm.password === "") {
+      this.$refs.password.focus();
     }
   },
   methods: {
     // 获取存储的密码并解密
-    getPsw () {
-      const cookVal = cookies.get(`u_${this.loginForm.loginName}`)
-      this.loginForm.password = cookVal && Decrypt(cookVal)
+    getPsw() {
+      const cookVal = cookies.get(`u_${this.loginForm.loginName}`);
+      this.loginForm.password = cookVal && Decrypt(cookVal);
     },
     // 滑动条块的top控制
-    setTop (val) {
-      this.activeTop = val
+    setTop(val) {
+      this.activeTop = val;
     },
     // 检测大写锁定键是否开启
-    checkCapslock (e) {
-      const { key } = e
-      this.capsTooltip = key && key.length === 1 && key >= 'A' && key <= 'Z'
+    checkCapslock(e) {
+      const { key } = e;
+      this.capsTooltip = key && key.length === 1 && key >= "A" && key <= "Z";
     },
     // 查看密码
-    showPwd () {
-      if (this.passwordType === 'password') {
-        this.passwordType = ''
+    showPwd() {
+      if (this.passwordType === "password") {
+        this.passwordType = "";
       } else {
-        this.passwordType = 'password'
+        this.passwordType = "password";
       }
       this.$nextTick(() => {
-        this.$refs.password.focus()
-      })
+        this.$refs.password.focus();
+      });
     },
     // 滑动验证码
-    useVerify () {
-      this.$refs.loginForm.validate((valid) => {
+    useVerify() {
+      this.$refs.loginForm.validate(valid => {
         if (valid) {
-          this.$refs.verify.show()
+          this.$refs.verify.show();
         } else {
-          return false
+          return false;
         }
-      })
+      });
     },
     // 验证成功的回调
-    verifylogin (params) {
-      this.loginForm.verifyCode = params.captchaVerification
+    verifylogin(params) {
+      this.loginForm.verifyCode = params.captchaVerification;
       if (this.loginForm.verifyCode) {
-        this.loginApi()
+        this.loginApi();
       }
     },
     // 登录操作
-    handleLogin () {
-      this.$refs.loginForm.validate((valid) => {
+    handleLogin() {
+      this.$refs.loginForm.validate(valid => {
         if (valid) {
-          this.loading = true
+          this.loading = true;
           // 登录失败次数过多需要展示滑动验证码
           if (this.needCaptcha) {
-            this.useVerify()
-            return
+            this.useVerify();
+            return;
           }
-          this.loginApi()
+          this.loginApi();
         } else {
-          return false
+          return false;
         }
-      })
+      });
     },
-    async loginApi () {
+    async loginApi() {
       let obj = {
         loginName: this.loginForm.loginName,
         password: transPsw(this.loginForm.password),
-        verifyCode: '',
-      }
-      const { code, data } = await login(obj)
-      console.log(data)
-      this.loading = false
-      if (code != '200') return
-      setToken(data.token)
-      setAccessUser(data)
+        verifyCode: ""
+      };
+      const { code, data } = await login(obj);
+      this.loading = false;
+      if (code != "200") return;
+      setToken(data.token);
+      setAccessUser(data);
       // 选中记住密码时 把密码存到cookie里,时效15天
       this.rememberPsw &&
         cookies.set(
           `u_${this.loginForm.loginName}`,
           Encrypt(this.loginForm.password),
           { expires: 15 }
-        )
+        );
       if (data && data.captcha) {
-        this.needCaptcha = true
+        this.needCaptcha = true;
       } else {
-        this.needCaptcha = false
+        this.needCaptcha = false;
         this.$router.push({
-          path: this.redirect || '/index',
-          query: this.otherQuery,
-        })
+          path: this.redirect || "/index",
+          query: this.otherQuery
+        });
       }
     },
-    getOtherQuery (query) {
+    getOtherQuery(query) {
       return Object.keys(query).reduce((acc, cur) => {
-        if (cur !== 'redirect') {
-          acc[cur] = query[cur]
+        if (cur !== "redirect") {
+          acc[cur] = query[cur];
         }
-        return acc
-      }, {})
-    },
-  },
-}
+        return acc;
+      }, {});
+    }
+  }
+};
 </script>
 
 <style lang="scss">

+ 50 - 0
report-ui/src/views/report/aj/index.vue

@@ -0,0 +1,50 @@
+<!--
+ * @Author: lide1202@hotmail.com
+ * @Date: 2021-3-13 11:04:24
+ * @Last Modified by:   lide1202@hotmail.com
+ * @Last Modified time: 2021-3-13 11:04:24
+ !-->
+<template>
+<div>
+
+</div>
+</template>
+<script>
+import { reportShareDetailByCode} from '@/api/reportShare'
+import { setShareToken } from '@/utils/auth'
+export default {
+  name: "Report",
+  components: {
+  },
+  data() {
+    return {
+
+    };
+  },
+
+  created() {
+    this.handleOpen()
+  },
+  methods: {
+    async handleOpen() {
+      const url = window.location.href
+      const shareCode = url.substring(url.lastIndexOf("/") + 1);
+      console.log(shareCode)
+
+      const {code, data} = await reportShareDetailByCode(shareCode)
+      if (code != '200') return
+      setShareToken(data.shareToken)
+      //将shareToken缓存在浏览器
+      //跳转至大屏预览页面
+      this.$router.push({
+        path: '/bigscreen/viewer',
+        query: {
+          reportCode: data.reportCode
+        },
+      })
+
+    },
+
+  }
+};
+</script>

+ 7 - 3
report-ui/src/views/report/bigscreen/designer/form/dynamicComponents.vue

@@ -5,7 +5,7 @@
         <el-select
           size="mini"
           v-model="dataSetValue"
-          clearable
+          filterable
           placeholder="请选择"
           @change="selectDataSet"
         >
@@ -27,7 +27,7 @@
       <el-form-item v-for="item in setParamList" :key="item" :label="item">
         <Dictionary
           v-model="params"
-          :dict-key="'CHART_PROPERTIES'"
+          :dict-key="getDictKey()"
           @input="selectParams($event, item)"
         />
       </el-form-item>
@@ -57,6 +57,7 @@ export default {
   },
   props: {
     chartType: String,
+    dictKey: String,
     props: ["formData"]
   },
   data() {
@@ -66,7 +67,7 @@ export default {
       userNameList: [], // 用户
       setParamList: [], // 对应的不同的图形数据参数
       params: {},
-      chartProperties: {}
+      chartProperties: {},
     };
   },
   computed: {
@@ -113,6 +114,9 @@ export default {
     },
     selectParams(val, key) {
       this.chartProperties[key] = val;
+    },
+    getDictKey(){
+      return this.dictKey == null ? 'CHART_PROPERTIES' : this.dictKey
     }
   }
 };

+ 1 - 0
report-ui/src/views/report/bigscreen/designer/form/dynamicForm.vue

@@ -137,6 +137,7 @@
             v-if="item.type == 'dycustComponents' && inputShow[item.name]"
             v-model="formData[item.name]"
             :chart-type="item.chartType"
+            :dict-key='item.dictKey'
             @change="changed($event, item.name)"
           />
           <dynamic-add-table

+ 2 - 4
report-ui/src/views/report/bigscreen/designer/index.vue

@@ -87,7 +87,7 @@
             <i class="iconfont iconyulan" @click="viewScreen"></i>
           </el-tooltip>
         </span>
-        <span class="btn border-left">
+        <!-- <span class="btn border-left">
           <ul class="nav">
             <li>
               <i class="el-icon-brush"></i><i class="el-icon-arrow-down"></i>
@@ -116,7 +116,7 @@
               </ul>
             </li>
           </ul>
-        </span>
+        </span> -->
       </div>
       <div
         class="workbench-container"
@@ -170,8 +170,6 @@
           </div>
         </vue-ruler-tool>
       </div>
-      <!-- 如果是二次开发商业使用必须带上这个技术支持 -->
-      <div class="bottom-text">技术支持: 安吉加加信息技术有限公司</div>
     </div>
 
     <div class="layout-right" :style="{ width: widthLeftForOptions + 'px' }">

+ 1341 - 0
report-ui/src/views/report/bigscreen/designer/tools.js

@@ -192,6 +192,7 @@ const widgetTools = [
           relactiveDom: 'dataType',
           relactiveDomValue: 'dynamicData',
           chartType: 'widget-text',
+          dictKey: 'TEXT_PROPERTIES',
           value: '',
         }
       ],
@@ -360,6 +361,7 @@ const widgetTools = [
           relactiveDom: 'dataType',
           relactiveDomValue: 'dynamicData',
           chartType: 'widget-text',
+          dictKey: 'TEXT_PROPERTIES',
           value: '',
         }
       ],
@@ -1142,6 +1144,7 @@ const widgetTools = [
           relactiveDom: 'dataType',
           relactiveDomValue: 'dynamicData',
           chartType: 'widget-table',
+          dictKey: 'TEXT_PROPERTIES', //表格的暂不起作用
           value: '',
         },
       ],
@@ -1833,6 +1836,7 @@ const widgetTools = [
           relactiveDom: 'dataType',
           relactiveDomValue: 'dynamicData',
           chartType: 'widget-barchart',
+          dictKey: 'BAR_PROPERTIES',
           value: '',
         },
       ],
@@ -2250,6 +2254,26 @@ const widgetTools = [
               },
             ],
           },
+          {
+            name: '提示语设置',
+            list: [
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'tipsFontSize',
+                required: false,
+                placeholder: '',
+                value: 16
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'lineColor',
+                required: false,
+                placeholder: '',
+              },
+            ],
+          },
           {
             name: '坐标轴边距设置',
             list: [
@@ -2371,6 +2395,7 @@ const widgetTools = [
           relactiveDom: 'dataType',
           relactiveDomValue: 'dynamicData',
           chartType: 'widget-barchart',
+          dictKey: 'BAR_PROPERTIES',
           value: '',
         },
       ],
@@ -3013,6 +3038,7 @@ const widgetTools = [
           placeholder: 'px',
           relactiveDom: 'dataType',
           chartType: 'widget-linechart',
+          dictKey: 'LINE_PROPERTIES',
           relactiveDomValue: 'dynamicData',
         },
       ],
@@ -3638,6 +3664,7 @@ const widgetTools = [
           placeholder: 'px',
           relactiveDom: 'dataType',
           chartType: 'widget-barlinechart',
+          dictKey: 'BAR_LINE_PROPERTIES',
           relactiveDomValue: 'dynamicData',
         },
       ],
@@ -4032,6 +4059,7 @@ const widgetTools = [
           relactiveDom: 'dataType',
           chartType: 'widget-piechart',
           relactiveDomValue: 'dynamicData',
+          dictKey: 'PIE_PROPERTIES',
           value: '',
         },
       ],
@@ -4406,6 +4434,7 @@ const widgetTools = [
           relactiveDom: 'dataType',
           chartType: 'widget-funnel',
           relactiveDomValue: 'dynamicData',
+          dictKey: 'PIE_PROPERTIES',
           value: '',
         },
       ],
@@ -4558,6 +4587,7 @@ const widgetTools = [
           placeholder: 'px',
           relactiveDom: 'dataType',
           chartType: 'widget-gauge',
+          dictKey: 'TEXT_PROPERTIES',
           relactiveDomValue: 'dynamicData',
           value: '',
         },
@@ -5005,6 +5035,7 @@ const widgetTools = [
           placeholder: 'px',
           relactiveDom: 'dataType',
           chartType: 'widget-piechart',
+          dictKey: 'PIE_PROPERTIES',
           relactiveDomValue: 'dynamicData',
           value: '',
         },
@@ -5251,6 +5282,7 @@ const widgetTools = [
           placeholder: 'px',
           relactiveDom: 'dataType',
           chartType: 'widget-piechart',
+          dictKey: 'TEXT_PROPERTIES',
           relactiveDomValue: 'dynamicData',
           value: '',
         },
@@ -5625,6 +5657,7 @@ const widgetTools = [
           placeholder: 'px',
           relactiveDom: 'dataType',
           chartType: 'widget-piechart',
+          dictKey: 'MAP_PROPERTIES',
           relactiveDomValue: 'dynamicData',
           value: '',
         },
@@ -5665,6 +5698,1314 @@ const widgetTools = [
       ]
     }
   },
+  {
+    code: 'widgetBarStackChart',
+    type: 'chart',
+    label: '柱状堆叠图',
+    icon: 'iconbianzu23',
+    options: {
+      // 配置
+      setup: [
+        {
+          type: 'el-input-text',
+          label: '图层名称',
+          name: 'layerName',
+          required: false,
+          placeholder: '',
+          value: '柱状堆叠图',
+        },
+        {
+          type: 'el-switch',
+          label: '竖展示',
+          name: 'verticalShow',
+          required: false,
+          placeholder: '',
+          value: false,
+        },
+        {
+          type: 'vue-color',
+          label: '背景颜色',
+          name: 'background',
+          required: false,
+          placeholder: '',
+          value: ''
+        },
+        {
+          type: 'el-select',
+          label: '堆叠样式',
+          name: 'stackStyle',
+          required: false,
+          placeholder: '',
+          selectOptions: [
+            {code: 'leftRight', name: '左右堆叠'},
+            {code: 'upDown', name: '上下堆叠'},
+          ],
+          value: 'leftRight'
+        },
+        [
+          {
+            name: '柱体设置',
+            list: [
+              {
+                type: 'el-slider',
+                label: '最大宽度',
+                name: 'maxWidth',
+                required: false,
+                placeholder: '',
+                value: 20,
+              },
+              {
+                type: 'el-slider',
+                label: '圆角',
+                name: 'radius',
+                require: false,
+                placeholder: '',
+                value: 5,
+              },
+            ],
+          },
+          {
+            name: '标题设置',
+            list: [
+              {
+                type: 'el-switch',
+                label: '标题',
+                name: 'isNoTitle',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-input-text',
+                label: '标题',
+                name: 'titleText',
+                required: false,
+                placeholder: '',
+                value: '',
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'textColor',
+                required: false,
+                placeholder: '',
+                value: '#FFD700'
+              },
+              {
+                type: 'el-select',
+                label: '字体粗细',
+                name: 'textFontWeight',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'normal', name: '正常'},
+                  {code: 'bold', name: '粗体'},
+                  {code: 'bolder', name: '特粗体'},
+                  {code: 'lighter', name: '细体'}
+                ],
+                value: 'normal'
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'textFontSize',
+                required: false,
+                placeholder: '',
+                value: 20
+              },
+              {
+                type: 'el-select',
+                label: '字体位置',
+                name: 'textAlign',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'center', name: '居中'},
+                  {code: 'left', name: '左对齐'},
+                  {code: 'right', name: '右对齐'},
+                ],
+                value: 'center'
+              },
+              {
+                type: 'el-input-text',
+                label: '副标题',
+                name: 'subText',
+                required: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'subTextColor',
+                required: false,
+                placeholder: '',
+                value: 'rgba(30, 144, 255, 1)'
+              },
+              {
+                type: 'el-select',
+                label: '字体粗细',
+                name: 'subTextFontWeight',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'normal', name: '正常'},
+                  {code: 'bold', name: '粗体'},
+                  {code: 'bolder', name: '特粗体'},
+                  {code: 'lighter', name: '细体'}
+                ],
+                value: 'normal'
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'subTextFontSize',
+                required: false,
+                placeholder: '',
+                value: 20
+              },
+            ],
+          },
+          {
+            name: 'X轴设置',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'hideX',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-input-text',
+                label: 'X轴别名',
+                name: 'xName',
+                required: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '别名颜色',
+                name: 'xNameColor',
+                required: false,
+                placeholder: '',
+                value: '#fff'
+              },
+              {
+                type: 'el-input-number',
+                label: '别名字号',
+                name: 'xNameFontSize',
+                required: false,
+                placeholder: '',
+                value: 14
+              },
+              {
+                type: 'el-switch',
+                label: '轴反转',
+                name: 'reversalX',
+                required: false,
+                placeholder: '',
+                value: false
+              },
+              {
+                type: 'el-slider',
+                label: '文字角度',
+                name: 'textAngleX',
+                required: false,
+                placeholder: '',
+                value: 0
+              },
+              {
+                type: 'el-input-number',
+                label: '文字间隔',
+                name: 'textInterval',
+                required: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '文字颜色',
+                name: 'Xcolor',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '文字字号',
+                name: 'fontSizeX',
+                required: false,
+                placeholder: '',
+                value: 14,
+              },
+              {
+                type: 'vue-color',
+                label: '轴颜色',
+                name: 'lineColorX',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-switch',
+                label: '分割线显示',
+                name: 'isShowSplitLineX',
+                require: false,
+                placeholder: '',
+                value: false,
+              },
+              {
+                type: 'vue-color',
+                label: '分割线颜色',
+                name: 'splitLineColorX',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+
+              }
+            ],
+          },
+          {
+            name: 'Y轴设置',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'isShowY',
+                require: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-input-text',
+                label: 'Y轴别名',
+                name: 'textNameY',
+                require: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '别名颜色',
+                name: 'NameColorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '别名字号',
+                name: 'NameFontSizeY',
+                required: false,
+                placeholder: '',
+                value: 14,
+              },
+              {
+                type: 'el-switch',
+                label: '轴反转',
+                name: 'reversalY',
+                required: false,
+                placeholder: '',
+                value: false
+              },
+              {
+                type: 'el-slider',
+                label: '文字角度',
+                name: 'textAngleY',
+                required: false,
+                placeholder: '',
+                value: 0
+              },
+              {
+                type: 'vue-color',
+                label: '文字颜色',
+                name: 'colorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '文字字号',
+                name: 'fontSizeY',
+                required: false,
+                placeholder: '',
+                value: 14,
+              },
+              {
+                type: 'vue-color',
+                label: '轴颜色',
+                name: 'lineColorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              }, {
+                type: 'el-switch',
+                label: '分割线显示',
+                name: 'isShowSplitLineY',
+                require: false,
+                placeholder: '',
+                value: false,
+              }, {
+                type: 'vue-color',
+                label: '分割线颜色',
+                name: 'splitLineColorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+
+              }
+            ],
+          },
+          {
+            name: '数值设定',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'isShow',
+                required: false,
+                placeholder: '',
+                value: false
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'fontSize',
+                required: false,
+                placeholder: '',
+                value: 14
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'subTextColor',
+                required: false,
+                placeholder: '',
+                value: '#fff'
+              },
+              {
+                type: 'el-select',
+                label: '字体粗细',
+                name: 'fontWeight',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'normal', name: '正常'},
+                  {code: 'bold', name: '粗体'},
+                  {code: 'bolder', name: '特粗体'},
+                  {code: 'lighter', name: '细体'}
+                ],
+                value: 'normal'
+              },
+            ],
+          },
+          {
+            name: '提示语设置',
+            list: [
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'tipsFontSize',
+                required: false,
+                placeholder: '',
+                value: 16
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'lineColor',
+                required: false,
+                placeholder: '',
+              },
+            ],
+          },
+          {
+            name: '坐标轴边距设置',
+            list: [
+              {
+                type: 'el-slider',
+                label: '左边距(像素)',
+                name: 'marginLeft',
+                required: false,
+                placeholder: '',
+                value: 10,
+              }, {
+                type: 'el-slider',
+                label: '顶边距(像素)',
+                name: 'marginTop',
+                required: false,
+                placeholder: '',
+                value: 50,
+              }, {
+                type: 'el-slider',
+                label: '右边距(像素)',
+                name: 'marginRight',
+                required: false,
+                placeholder: '',
+                value: 40,
+              }, {
+                type: 'el-slider',
+                label: '底边距(像素)',
+                name: 'marginBottom',
+                required: false,
+                placeholder: '',
+                value: 10,
+              },
+            ],
+          },
+          {
+            name: '图例操作',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'isShowLegend',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'lengedColor',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'lengedFontSize',
+                required: false,
+                placeholder: '',
+                value: 16,
+              },
+              {
+                type: 'el-input-number',
+                label: '图例宽度',
+                name: 'lengedWidth',
+                required: false,
+                placeholder: '',
+                value: 15,
+              },
+              {
+                type: 'el-select',
+                label: '横向位置',
+                name: 'lateralPosition',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'center', name: '居中'},
+                  {code: 'left', name: '左对齐'},
+                  {code: 'right', name: '右对齐'},
+                ],
+                value: 'center'
+              },
+              {
+                type: 'el-select',
+                label: '纵向位置',
+                name: 'longitudinalPosition',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'top', name: '顶部'},
+                  {code: 'bottom', name: '底部'},
+                ],
+                value: 'top'
+              },
+              {
+                type: 'el-select',
+                label: '布局前置',
+                name: 'layoutFront',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'vertical', name: '竖排'},
+                  {code: 'horizontal', name: '横排'},
+                ],
+                value: 'horizontal'
+              },
+            ],
+          },
+          {
+            name: '自定义配色',
+            list: [
+              {
+                type: 'customColor',
+                label: '',
+                name: 'customColor',
+                required: false,
+                value: [{color: '#ff7f50'}, {color: '#87cefa'}, {color: '#da70d6'}, {color: '#32cd32'}, {color: '#6495ed'}],
+              },
+            ],
+          },
+        ],
+      ],
+      // 数据
+      data: [
+        {
+          type: 'el-radio-group',
+          label: '数据类型',
+          name: 'dataType',
+          require: false,
+          placeholder: '',
+          selectValue: true,
+          selectOptions: [
+            {
+              code: 'staticData',
+              name: '静态数据',
+            },
+            {
+              code: 'dynamicData',
+              name: '动态数据',
+            },
+          ],
+          value: 'staticData',
+        },
+        {
+          type: 'el-input-number',
+          label: '刷新时间(毫秒)',
+          name: 'refreshTime',
+          relactiveDom: 'dataType',
+          relactiveDomValue: 'dynamicData',
+          value: 5000
+        },
+        {
+          type: 'el-button',
+          label: '静态数据',
+          name: 'staticData',
+          required: false,
+          placeholder: 'px',
+          relactiveDom: 'dataType',
+          relactiveDomValue: 'staticData',
+          value: [
+            {"axis":"2021-07-25","name":"A","data":"12"},
+            {"axis":"2021-07-25","name":"B","data":"20"},
+            {"axis":"2021-07-26","name":"B","data":"5"},
+            {"axis":"2021-07-26","name":"C","data":"20"},
+            {"axis":"2021-07-27","name":"A","data":"15"},
+            {"axis":"2021-07-27","name":"B","data":"30"},
+            {"axis":"2021-07-27","name":"C","data":"5"}
+          ],
+        },
+        {
+          type: 'dycustComponents',
+          label: '',
+          name: 'dynamicData',
+          required: false,
+          placeholder: 'px',
+          relactiveDom: 'dataType',
+          relactiveDomValue: 'dynamicData',
+          chartType: 'widget-stackchart',
+          dictKey: 'STACK_PROPERTIES',
+          value: '',
+        },
+      ],
+      // 坐标
+      position: [
+        {
+          type: 'el-input-number',
+          label: '左边距',
+          name: 'left',
+          required: false,
+          placeholder: 'px',
+          value: 0,
+        },
+        {
+          type: 'el-input-number',
+          label: '上边距',
+          name: 'top',
+          required: false,
+          placeholder: 'px',
+          value: 0,
+        },
+        {
+          type: 'el-input-number',
+          label: '宽度',
+          name: 'width',
+          required: false,
+          placeholder: '该容器在1920px大屏中的宽度',
+          value: 400,
+        },
+        {
+          type: 'el-input-number',
+          label: '高度',
+          name: 'height',
+          required: false,
+          placeholder: '该容器在1080px大屏中的高度',
+          value: 200,
+        },
+      ],
+    },
+  },
+  {
+    code: 'widgetLineStackChart',
+    type: 'chart',
+    label: '折线堆叠图',
+    icon: 'iconduidietu',
+    options: {
+      // 配置
+      setup: [
+        {
+          type: 'el-input-text',
+          label: '图层名称',
+          name: 'layerName',
+          required: false,
+          placeholder: '',
+          value: '折线堆叠图',
+        },
+        {
+          type: 'el-switch',
+          label: '竖展示',
+          name: 'verticalShow',
+          required: false,
+          placeholder: '',
+          value: false,
+        },
+        {
+          type: 'vue-color',
+          label: '背景颜色',
+          name: 'background',
+          required: false,
+          placeholder: '',
+          value: ''
+        },
+        [
+          {
+            name: '折线设置',
+            list: [
+              {
+                type: 'el-switch',
+                label: '标记点',
+                name: 'markPoint',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-slider',
+                label: '点大小',
+                name: 'pointSize',
+                required: false,
+                placeholder: '',
+                value: 10,
+              },
+              {
+                type: 'el-switch',
+                label: '平滑曲线',
+                name: 'smoothCurve',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-switch',
+                label: '面积堆积',
+                name: 'area',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-slider',
+                label: '面积厚度',
+                name: 'areaThickness',
+                required: false,
+                placeholder: '',
+                value: 5,
+              },
+              {
+                type: 'el-slider',
+                label: '线条宽度',
+                name: 'lineWidth',
+                required: false,
+                placeholder: '',
+                value: 4,
+              },
+            ],
+          },
+          {
+            name: '标题设置',
+            list: [
+              {
+                type: 'el-switch',
+                label: '标题',
+                name: 'isNoTitle',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-input-text',
+                label: '标题',
+                name: 'titleText',
+                required: false,
+                placeholder: '',
+                value: '',
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'textColor',
+                required: false,
+                placeholder: '',
+                value: '#FFD700'
+              },
+              {
+                type: 'el-select',
+                label: '字体粗细',
+                name: 'textFontWeight',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'normal', name: '正常'},
+                  {code: 'bold', name: '粗体'},
+                  {code: 'bolder', name: '特粗体'},
+                  {code: 'lighter', name: '细体'}
+                ],
+                value: 'normal'
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'textFontSize',
+                required: false,
+                placeholder: '',
+                value: 20
+              },
+              {
+                type: 'el-select',
+                label: '字体位置',
+                name: 'textAlign',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'center', name: '居中'},
+                  {code: 'left', name: '左对齐'},
+                  {code: 'right', name: '右对齐'},
+                ],
+                value: 'center'
+              },
+              {
+                type: 'el-input-text',
+                label: '副标题',
+                name: 'subText',
+                required: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'subTextColor',
+                required: false,
+                placeholder: '',
+                value: 'rgba(30, 144, 255, 1)'
+              },
+              {
+                type: 'el-select',
+                label: '字体粗细',
+                name: 'subTextFontWeight',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'normal', name: '正常'},
+                  {code: 'bold', name: '粗体'},
+                  {code: 'bolder', name: '特粗体'},
+                  {code: 'lighter', name: '细体'}
+                ],
+                value: 'normal'
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'subTextFontSize',
+                required: false,
+                placeholder: '',
+                value: 20
+              },
+            ],
+          },
+          {
+            name: 'X轴设置',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'hideX',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-input-text',
+                label: 'X轴别名',
+                name: 'xName',
+                required: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '别名颜色',
+                name: 'xNameColor',
+                required: false,
+                placeholder: '',
+                value: '#fff'
+              },
+              {
+                type: 'el-input-number',
+                label: '别名字号',
+                name: 'xNameFontSize',
+                required: false,
+                placeholder: '',
+                value: 14
+              },
+              {
+                type: 'el-switch',
+                label: '轴反转',
+                name: 'reversalX',
+                required: false,
+                placeholder: '',
+                value: false
+              },
+              {
+                type: 'el-slider',
+                label: '文字角度',
+                name: 'textAngleX',
+                required: false,
+                placeholder: '',
+                value: 0
+              },
+              {
+                type: 'el-input-number',
+                label: '文字间隔',
+                name: 'textInterval',
+                required: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '文字颜色',
+                name: 'Xcolor',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '文字字号',
+                name: 'fontSizeX',
+                required: false,
+                placeholder: '',
+                value: 14,
+              },
+              {
+                type: 'vue-color',
+                label: '轴颜色',
+                name: 'lineColorX',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-switch',
+                label: '分割线显示',
+                name: 'isShowSplitLineX',
+                require: false,
+                placeholder: '',
+                value: false,
+              },
+              {
+                type: 'vue-color',
+                label: '分割线颜色',
+                name: 'splitLineColorX',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+
+              }
+            ],
+          },
+          {
+            name: 'Y轴设置',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'isShowY',
+                require: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'el-input-text',
+                label: 'Y轴别名',
+                name: 'textNameY',
+                require: false,
+                placeholder: '',
+                value: ''
+              },
+              {
+                type: 'vue-color',
+                label: '别名颜色',
+                name: 'NameColorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '别名字号',
+                name: 'NameFontSizeY',
+                required: false,
+                placeholder: '',
+                value: 14,
+              },
+              {
+                type: 'el-switch',
+                label: '轴反转',
+                name: 'reversalY',
+                required: false,
+                placeholder: '',
+                value: false
+              },
+              {
+                type: 'el-slider',
+                label: '文字角度',
+                name: 'textAngleY',
+                required: false,
+                placeholder: '',
+                value: 0
+              },
+              {
+                type: 'vue-color',
+                label: '文字颜色',
+                name: 'colorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '文字字号',
+                name: 'fontSizeY',
+                required: false,
+                placeholder: '',
+                value: 14,
+              },
+              {
+                type: 'vue-color',
+                label: '轴颜色',
+                name: 'lineColorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              }, {
+                type: 'el-switch',
+                label: '分割线显示',
+                name: 'isShowSplitLineY',
+                require: false,
+                placeholder: '',
+                value: false,
+              }, {
+                type: 'vue-color',
+                label: '分割线颜色',
+                name: 'splitLineColorY',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+
+              }
+            ],
+          },
+          {
+            name: '数值设定',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'isShow',
+                required: false,
+                placeholder: '',
+                value: false
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'fontSize',
+                required: false,
+                placeholder: '',
+                value: 14
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'subTextColor',
+                required: false,
+                placeholder: '',
+                value: '#fff'
+              },
+              {
+                type: 'el-select',
+                label: '字体粗细',
+                name: 'fontWeight',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'normal', name: '正常'},
+                  {code: 'bold', name: '粗体'},
+                  {code: 'bolder', name: '特粗体'},
+                  {code: 'lighter', name: '细体'}
+                ],
+                value: 'normal'
+              },
+            ],
+          },
+          {
+            name: '提示语设置',
+            list: [
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'tipsFontSize',
+                required: false,
+                placeholder: '',
+                value: 16
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'lineColor',
+                required: false,
+                placeholder: '',
+              },
+            ],
+          },
+          {
+            name: '坐标轴边距设置',
+            list: [
+              {
+                type: 'el-slider',
+                label: '左边距(像素)',
+                name: 'marginLeft',
+                required: false,
+                placeholder: '',
+                value: 10,
+              }, {
+                type: 'el-slider',
+                label: '顶边距(像素)',
+                name: 'marginTop',
+                required: false,
+                placeholder: '',
+                value: 50,
+              }, {
+                type: 'el-slider',
+                label: '右边距(像素)',
+                name: 'marginRight',
+                required: false,
+                placeholder: '',
+                value: 40,
+              }, {
+                type: 'el-slider',
+                label: '底边距(像素)',
+                name: 'marginBottom',
+                required: false,
+                placeholder: '',
+                value: 10,
+              },
+            ],
+          },
+          {
+            name: '图例操作',
+            list: [
+              {
+                type: 'el-switch',
+                label: '显示',
+                name: 'isShowLegend',
+                required: false,
+                placeholder: '',
+                value: true,
+              },
+              {
+                type: 'vue-color',
+                label: '字体颜色',
+                name: 'lengedColor',
+                required: false,
+                placeholder: '',
+                value: '#fff',
+              },
+              {
+                type: 'el-input-number',
+                label: '字体大小',
+                name: 'lengedFontSize',
+                required: false,
+                placeholder: '',
+                value: 16,
+              },
+              {
+                type: 'el-input-number',
+                label: '图例宽度',
+                name: 'lengedWidth',
+                required: false,
+                placeholder: '',
+                value: 15,
+              },
+              {
+                type: 'el-select',
+                label: '横向位置',
+                name: 'lateralPosition',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'center', name: '居中'},
+                  {code: 'left', name: '左对齐'},
+                  {code: 'right', name: '右对齐'},
+                ],
+                value: 'center'
+              },
+              {
+                type: 'el-select',
+                label: '纵向位置',
+                name: 'longitudinalPosition',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'top', name: '顶部'},
+                  {code: 'bottom', name: '底部'},
+                ],
+                value: 'top'
+              },
+              {
+                type: 'el-select',
+                label: '布局前置',
+                name: 'layoutFront',
+                required: false,
+                placeholder: '',
+                selectOptions: [
+                  {code: 'vertical', name: '竖排'},
+                  {code: 'horizontal', name: '横排'},
+                ],
+                value: 'horizontal'
+              },
+            ],
+          },
+          {
+            name: '自定义配色',
+            list: [
+              {
+                type: 'customColor',
+                label: '',
+                name: 'customColor',
+                required: false,
+                value: [{color: '#ff7f50'}, {color: '#87cefa'}, {color: '#da70d6'}, {color: '#32cd32'}, {color: '#6495ed'}],
+              },
+            ],
+          },
+        ],
+      ],
+      // 数据
+      data: [
+        {
+          type: 'el-radio-group',
+          label: '数据类型',
+          name: 'dataType',
+          require: false,
+          placeholder: '',
+          selectValue: true,
+          selectOptions: [
+            {
+              code: 'staticData',
+              name: '静态数据',
+            },
+            {
+              code: 'dynamicData',
+              name: '动态数据',
+            },
+          ],
+          value: 'staticData',
+        },
+        {
+          type: 'el-input-number',
+          label: '刷新时间(毫秒)',
+          name: 'refreshTime',
+          relactiveDom: 'dataType',
+          relactiveDomValue: 'dynamicData',
+          value: 5000
+        },
+        {
+          type: 'el-button',
+          label: '静态数据',
+          name: 'staticData',
+          required: false,
+          placeholder: 'px',
+          relactiveDom: 'dataType',
+          relactiveDomValue: 'staticData',
+          value: [
+            {"axis":"2021-07-25","name":"A","data":"12"},
+            {"axis":"2021-07-25","name":"B","data":"20"},
+            {"axis":"2021-07-26","name":"B","data":"5"},
+            {"axis":"2021-07-26","name":"C","data":"20"},
+            {"axis":"2021-07-27","name":"A","data":"15"},
+            {"axis":"2021-07-27","name":"B","data":"30"},
+            {"axis":"2021-07-27","name":"C","data":"5"}
+          ],
+        },
+        {
+          type: 'dycustComponents',
+          label: '',
+          name: 'dynamicData',
+          required: false,
+          placeholder: 'px',
+          relactiveDom: 'dataType',
+          relactiveDomValue: 'dynamicData',
+          chartType: 'widget-stackchart',
+          dictKey: 'STACK_PROPERTIES',
+          value: '',
+        },
+      ],
+      // 坐标
+      position: [
+        {
+          type: 'el-input-number',
+          label: '左边距',
+          name: 'left',
+          required: false,
+          placeholder: 'px',
+          value: 0,
+        },
+        {
+          type: 'el-input-number',
+          label: '上边距',
+          name: 'top',
+          required: false,
+          placeholder: 'px',
+          value: 0,
+        },
+        {
+          type: 'el-input-number',
+          label: '宽度',
+          name: 'width',
+          required: false,
+          placeholder: '该容器在1920px大屏中的宽度',
+          value: 400,
+        },
+        {
+          type: 'el-input-number',
+          label: '高度',
+          name: 'height',
+          required: false,
+          placeholder: '该容器在1080px大屏中的高度',
+          value: 200,
+        },
+      ],
+    },
+  },
 ]
 
 const getToolByCode = function (code) {

+ 411 - 0
report-ui/src/views/report/bigscreen/designer/widget/bar/widgetBarStackChart.vue

@@ -0,0 +1,411 @@
+<template>
+  <div :style="styleObj">
+    <v-chart :options="options" autoresize/>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "WidgetBarStackchart",
+  components: {},
+  props: {
+    value: Object,
+    ispreview: Boolean
+  },
+  data() {
+    return {
+      options: {
+        grid: {},
+        legend: {
+          textStyle: {
+            color: "#fff"
+          }
+        },
+        xAxis: {
+          type: "category",
+          data: [],
+          axisLabel: {
+            show: true,
+            textStyle: {
+              color: "#fff"
+            }
+          }
+        },
+        yAxis: {
+          type: "value",
+          data: [],
+          axisLabel: {
+            show: true,
+            textStyle: {
+              color: "#fff"
+            }
+          }
+        },
+        series: [
+          {
+            data: [],
+            name: '',
+            type: "bar",
+            barGap: "0%",
+            itemStyle: {
+              barBorderRadius: null
+            }
+          }
+        ]
+      },
+      optionsStyle: {}, // 样式
+      optionsData: {}, // 数据
+      optionsSetup: {},
+      flagInter: null
+    };
+  },
+  computed: {
+    styleObj() {
+      return {
+        position: this.ispreview ? "absolute" : "static",
+        width: this.optionsStyle.width + "px",
+        height: this.optionsStyle.height + "px",
+        left: this.optionsStyle.left + "px",
+        top: this.optionsStyle.top + "px",
+        background: this.optionsSetup.background
+      };
+    }
+  },
+  watch: {
+    value: {
+      handler(val) {
+        this.optionsStyle = val.position;
+        this.optionsData = val.data;
+        this.optionsCollapse = val.setup;
+        this.optionsSetup = val.setup;
+        this.editorOptions();
+      },
+      deep: true
+    }
+  },
+  mounted() {
+    this.optionsStyle = this.value.position;
+    this.optionsData = this.value.data;
+    this.optionsCollapse = this.value.setup;
+    this.optionsSetup = this.value.setup;
+    this.editorOptions();
+  },
+  methods: {
+    // 修改图标options属性
+    editorOptions() {
+      this.setOptionsTitle();
+      this.setOptionsX();
+      this.setOptionsY();
+      this.setOptionsTooltip();
+      this.setOptionsMargin();
+      this.setOptionsLegend();
+      this.setOptionsData();
+    },
+    // 标题修改
+    setOptionsTitle() {
+      const optionsSetup = this.optionsSetup;
+      const title = {};
+      title.text = optionsSetup.titleText;
+      title.show = optionsSetup.isNoTitle;
+      title.left = optionsSetup.textAlign;
+      title.textStyle = {
+        color: optionsSetup.textColor,
+        fontSize: optionsSetup.textFontSize,
+        fontWeight: optionsSetup.textFontWeight
+      };
+      title.subtext = optionsSetup.subText;
+      title.subtextStyle = {
+        color: optionsSetup.subTextColor,
+        fontWeight: optionsSetup.subTextFontWeight,
+        fontSize: optionsSetup.subTextFontSize
+      };
+      this.options.title = title;
+    },
+    // X轴设置
+    setOptionsX() {
+      const optionsSetup = this.optionsSetup;
+      const xAxis = {
+        type: "category",
+        show: optionsSetup.hideX, // 坐标轴是否显示
+        name: optionsSetup.xName, // 坐标轴名称
+        nameTextStyle: {
+          color: optionsSetup.xNameColor,
+          fontSize: optionsSetup.xNameFontSize
+        },
+        nameRotate: optionsSetup.textAngleX, // 文字角度
+        inverse: optionsSetup.reversalX, // 轴反转
+        axisLabel: {
+          show: true,
+          interval: optionsSetup.textInterval, // 文字角度
+          rotate: optionsSetup.textAngle, // 文字角度
+          textStyle: {
+            color: optionsSetup.Xcolor, // x轴 坐标文字颜色
+            fontSize: optionsSetup.fontSizeX
+          }
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: optionsSetup.lineColorX
+          }
+        },
+        splitLine: {
+          show: optionsSetup.isShowSplitLineX,
+          lineStyle: {
+            color: optionsSetup.splitLineColorX
+          }
+        }
+      };
+      this.options.xAxis = xAxis;
+    },
+    // Y轴设置
+    setOptionsY() {
+      const optionsSetup = this.optionsSetup;
+      const yAxis = {
+        type: "value",
+        show: optionsSetup.isShowY, // 坐标轴是否显示
+        name: optionsSetup.textNameY, // 坐标轴名称
+        nameTextStyle: {
+          color: optionsSetup.NameColorY,
+          fontSize: optionsSetup.NameFontSizeY
+        },
+        inverse: optionsSetup.reversalY, // y轴反转
+        axisLabel: {
+          show: true,
+          rotate: optionsSetup.textAngleY,// 文字角度
+          textStyle: {
+            color: optionsSetup.colorY, // y轴 坐标文字颜色
+            fontSize: optionsSetup.fontSizeY
+          }
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: optionsSetup.lineColorY
+          }
+        },
+        splitLine: {
+          show: optionsSetup.isShowSplitLineY,
+          lineStyle: {
+            color: optionsSetup.splitLineColorY
+          }
+        }
+      };
+      this.options.yAxis = yAxis;
+    },
+    // tooltip 提示语设置,鼠标放置显示
+    setOptionsTooltip() {
+      const optionsSetup = this.optionsSetup;
+      const tooltip = {
+        trigger: "item",
+        show: true,
+        textStyle: {
+          color: optionsSetup.lineColor,
+          fontSize: optionsSetup.tipsFontSize
+        }
+      };
+      this.options.tooltip = tooltip;
+    },
+    // 边距设置
+    setOptionsMargin() {
+      const optionsSetup = this.optionsSetup;
+      const grid = {
+        left: optionsSetup.marginLeft,
+        right: optionsSetup.marginRight,
+        bottom: optionsSetup.marginBottom,
+        top: optionsSetup.marginTop,
+        containLabel: true
+      };
+      this.options.grid = grid;
+    },
+    // 图例操作 legend
+    setOptionsLegend() {
+      const optionsSetup = this.optionsSetup;
+      const legend = this.options.legend;
+      legend.show = optionsSetup.isShowLegend;
+      legend.left = optionsSetup.lateralPosition;
+      legend.top = optionsSetup.longitudinalPosition == "top" ? 0 : "auto";
+      legend.bottom =
+        optionsSetup.longitudinalPosition == "bottom" ? 0 : "auto";
+      legend.orient = optionsSetup.layoutFront;
+      legend.textStyle = {
+        color: optionsSetup.lengedColor,
+        fontSize: optionsSetup.lengedFontSize
+      };
+      legend.itemWidth = optionsSetup.lengedWidth;
+    },
+    // 数据解析
+    setOptionsData() {
+      const optionsSetup = this.optionsSetup;
+      const optionsData = this.optionsData; // 数据类型 静态 or 动态
+      optionsData.dataType == "staticData"
+        ? this.staticDataFn(optionsData.staticData, optionsSetup)
+        : this.dynamicDataFn(
+        optionsData.dynamicData,
+        optionsData.refreshTime,
+        optionsSetup
+        );
+    },
+    //去重
+    setUnique(arr) {
+      let newArr = [];
+      arr.forEach(item => {
+        return newArr.includes(item) ? '' : newArr.push(item);
+      });
+      return newArr;
+    },
+    //获取堆叠样式
+    getStackStyle() {
+      const optionsSetup = this.optionsSetup;
+      let style = ""
+      if (optionsSetup.stackStyle == "upDown") {
+        style = "total"
+      }
+      return style
+    },
+    //静态数据
+    staticDataFn(val) {
+      const optionsSetup = this.optionsSetup;
+      //颜色
+      const customColor = optionsSetup.customColor;
+      const arrColor = [];
+      for (let i = 0; i < customColor.length; i++) {
+        arrColor.push(customColor[i].color);
+      }
+      //数据
+      const series = [];
+      let xAxisList = []
+      let yAxisList = []
+      for (const i in val) {
+        xAxisList[i] = val[i].axis
+        yAxisList[i] = val[i].name
+      }
+      xAxisList = this.setUnique(xAxisList) // x轴 0725 0726 0727
+      yAxisList = this.setUnique(yAxisList) // y轴 A B C
+      for (const i in yAxisList) {
+        const data = new Array(yAxisList.length).fill(0)
+        for (const j in xAxisList) {
+          for (const k in val) {
+            if (val[k].name == yAxisList[i]) { // a = a
+              if (val[k].axis == xAxisList[j]) { // 0725
+                data[j] = val[k].data
+              }
+            }
+          }
+        }
+        series.push({
+          name: yAxisList[i],
+          type: "bar",
+          data: data,
+          barGap: "0%",
+          stack: this.getStackStyle(),
+          barWidth: optionsSetup.maxWidth,
+          label: {
+            show: optionsSetup.isShow,
+            position: "top",
+            distance: 10,
+            fontSize: optionsSetup.fontSize,
+            color: optionsSetup.subTextColor,
+            fontWeight: optionsSetup.fontWeight
+          },
+          //颜色,圆角属性
+          itemStyle: {
+            normal: {
+              color: arrColor[i],
+              barBorderRadius: optionsSetup.radius,
+            }
+          }
+        })
+      }
+      this.options.series = series
+      if (optionsSetup.verticalShow) {
+        this.options.xAxis.data = [];
+        this.options.yAxis.data = xAxisList;
+        this.options.xAxis.type = "value";
+        this.options.yAxis.type = "category";
+      } else {
+        this.options.xAxis.data = xAxisList;
+        this.options.yAxis.data = [];
+        this.options.xAxis.type = "category";
+        this.options.yAxis.type = "value";
+      }
+    },
+    // 动态数据
+    dynamicDataFn(val, refreshTime, optionsSetup) {
+      if (!val) return;
+      if (this.ispreview) {
+        this.getEchartData(val, optionsSetup);
+        this.flagInter = setInterval(() => {
+          this.getEchartData(val, optionsSetup);
+        }, refreshTime);
+      } else {
+        this.getEchartData(val, optionsSetup);
+      }
+    },
+    getEchartData(val, optionsSetup) {
+      const data = this.queryEchartsData(val);
+      data.then(res => {
+        this.renderingFn(optionsSetup, res);
+      });
+    },
+    renderingFn(optionsSetup, val) {
+      //颜色
+      const customColor = optionsSetup.customColor;
+      const arrColor = [];
+      for (let i = 0; i < customColor.length; i++) {
+        arrColor.push(customColor[i].color);
+      }
+      // x轴
+      if (optionsSetup.verticalShow) {
+        this.options.xAxis.data = [];
+        this.options.yAxis.data = val.xAxis;
+        this.options.xAxis.type = "value";
+        this.options.yAxis.type = "category";
+      } else {
+        this.options.xAxis.data = val.xAxis;
+        this.options.yAxis.data = [];
+        this.options.xAxis.type = "category";
+        this.options.yAxis.type = "value";
+      }
+      const series = [];
+      for (const i in val.series) {
+        if (val.series[i].type == "bar") {
+          series.push({
+            name: val.series[i].name,
+            type: "bar",
+            data: val.series[i].data,
+            barGap: "0%",
+            stack: this.getStackStyle(),
+            barWidth: optionsSetup.maxWidth,
+            label: {
+              show: optionsSetup.isShow,
+              position: "top",
+              distance: 10,
+              fontSize: optionsSetup.fontSize,
+              color: optionsSetup.subTextColor,
+              fontWeight: optionsSetup.fontWeight
+            },
+            //颜色,圆角属性
+            itemStyle: {
+              normal: {
+                color: arrColor[i],
+                barBorderRadius: optionsSetup.radius,
+              }
+            }
+          })
+        }
+      }
+      this.options.series = series
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.echarts {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+
+</style>

+ 1 - 2
report-ui/src/views/report/bigscreen/designer/widget/bar/widgetGradientColorBarchart.vue

@@ -283,12 +283,11 @@ export default {
             fontWeight: optionsCollapse.fontWeight
           };
           series[key].barWidth = optionsCollapse.maxWidth;
-          //series[key].barMinHeight = optionsCollapse.minHeight;
         }
       }
       this.options.series = series;
     },
-    // tooltip 设置
+    // tooltip 提示语设置
     setOptionsTooltip() {
       const optionsCollapse = this.optionsSetup;
       const tooltip = {

+ 443 - 0
report-ui/src/views/report/bigscreen/designer/widget/line/widgetLineStackChart.vue

@@ -0,0 +1,443 @@
+<template>
+  <div :style="styleObj">
+    <v-chart :options="options" autoresize/>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "WidgetBarStackchart",
+  components: {},
+  props: {
+    value: Object,
+    ispreview: Boolean
+  },
+  data() {
+    return {
+      options: {
+        grid: {},
+        legend: {
+          textStyle: {
+            color: "#fff"
+          }
+        },
+        xAxis: {
+          type: "category",
+          data: [],
+          axisLabel: {
+            show: true,
+            textStyle: {
+              color: "#fff"
+            }
+          }
+        },
+        yAxis: {
+          type: "value",
+          data: [],
+          axisLabel: {
+            show: true,
+            textStyle: {
+              color: "#fff"
+            }
+          }
+        },
+        series: [
+          {
+            data: [],
+            name: '',
+            type: "line",
+            barGap: "0%",
+            itemStyle: {
+              barBorderRadius: null
+            }
+          }
+        ]
+      },
+      optionsStyle: {}, // 样式
+      optionsData: {}, // 数据
+      optionsSetup: {},
+      flagInter: null
+    };
+  },
+  computed: {
+    styleObj() {
+      return {
+        position: this.ispreview ? "absolute" : "static",
+        width: this.optionsStyle.width + "px",
+        height: this.optionsStyle.height + "px",
+        left: this.optionsStyle.left + "px",
+        top: this.optionsStyle.top + "px",
+        background: this.optionsSetup.background
+      };
+    }
+  },
+  watch: {
+    value: {
+      handler(val) {
+        this.optionsStyle = val.position;
+        this.optionsData = val.data;
+        this.optionsCollapse = val.setup;
+        this.optionsSetup = val.setup;
+        this.editorOptions();
+      },
+      deep: true
+    }
+  },
+  mounted() {
+    this.optionsStyle = this.value.position;
+    this.optionsData = this.value.data;
+    this.optionsCollapse = this.value.setup;
+    this.optionsSetup = this.value.setup;
+    this.editorOptions();
+  },
+  methods: {
+    // 修改图标options属性
+    editorOptions() {
+      this.setOptionsTitle();
+      this.setOptionsX();
+      this.setOptionsY();
+      this.setOptionsTooltip();
+      this.setOptionsMargin();
+      this.setOptionsLegend();
+      this.setOptionsData();
+    },
+    // 标题修改
+    setOptionsTitle() {
+      const optionsSetup = this.optionsSetup;
+      const title = {};
+      title.text = optionsSetup.titleText;
+      title.show = optionsSetup.isNoTitle;
+      title.left = optionsSetup.textAlign;
+      title.textStyle = {
+        color: optionsSetup.textColor,
+        fontSize: optionsSetup.textFontSize,
+        fontWeight: optionsSetup.textFontWeight
+      };
+      title.subtext = optionsSetup.subText;
+      title.subtextStyle = {
+        color: optionsSetup.subTextColor,
+        fontWeight: optionsSetup.subTextFontWeight,
+        fontSize: optionsSetup.subTextFontSize
+      };
+      this.options.title = title;
+    },
+    // X轴设置
+    setOptionsX() {
+      const optionsSetup = this.optionsSetup;
+      const xAxis = {
+        type: "category",
+        show: optionsSetup.hideX, // 坐标轴是否显示
+        name: optionsSetup.xName, // 坐标轴名称
+        nameTextStyle: {
+          color: optionsSetup.xNameColor,
+          fontSize: optionsSetup.xNameFontSize
+        },
+        nameRotate: optionsSetup.textAngleX, // 文字角度
+        inverse: optionsSetup.reversalX, // 轴反转
+        axisLabel: {
+          show: true,
+          interval: optionsSetup.textInterval, // 文字角度
+          rotate: optionsSetup.textAngle, // 文字角度
+          textStyle: {
+            color: optionsSetup.Xcolor, // x轴 坐标文字颜色
+            fontSize: optionsSetup.fontSizeX
+          }
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: optionsSetup.lineColorX
+          }
+        },
+        splitLine: {
+          show: optionsSetup.isShowSplitLineX,
+          lineStyle: {
+            color: optionsSetup.splitLineColorX
+          }
+        }
+      };
+      this.options.xAxis = xAxis;
+    },
+    // Y轴设置
+    setOptionsY() {
+      const optionsSetup = this.optionsSetup;
+      const yAxis = {
+        type: "value",
+        show: optionsSetup.isShowY, // 坐标轴是否显示
+        name: optionsSetup.textNameY, // 坐标轴名称
+        nameTextStyle: {
+          color: optionsSetup.NameColorY,
+          fontSize: optionsSetup.NameFontSizeY
+        },
+        inverse: optionsSetup.reversalY, // y轴反转
+        axisLabel: {
+          show: true,
+          rotate: optionsSetup.textAngleY,// 文字角度
+          textStyle: {
+            color: optionsSetup.colorY, // y轴 坐标文字颜色
+            fontSize: optionsSetup.fontSizeY
+          }
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: optionsSetup.lineColorY
+          }
+        },
+        splitLine: {
+          show: optionsSetup.isShowSplitLineY,
+          lineStyle: {
+            color: optionsSetup.splitLineColorY
+          }
+        }
+      };
+      this.options.yAxis = yAxis;
+    },
+    // 获取面积
+    getOptionArea() {
+      const optionsSetup = this.optionsSetup;
+      let areaStyle = [];
+      if (optionsSetup.area) {
+        areaStyle = {
+          opacity: optionsSetup.areaThickness / 100
+        }
+      } else {
+        areaStyle = {
+          opacity: 0
+        }
+      }
+      return areaStyle
+    },
+    // tooltip 提示语设置,鼠标放置显示
+    setOptionsTooltip() {
+      const optionsSetup = this.optionsSetup;
+      const tooltip = {
+        trigger: "item",
+        show: true,
+        textStyle: {
+          color: optionsSetup.lineColor,
+          fontSize: optionsSetup.tipsFontSize
+        }
+      };
+      this.options.tooltip = tooltip;
+    },
+    // 边距设置
+    setOptionsMargin() {
+      const optionsSetup = this.optionsSetup;
+      const grid = {
+        left: optionsSetup.marginLeft,
+        right: optionsSetup.marginRight,
+        bottom: optionsSetup.marginBottom,
+        top: optionsSetup.marginTop,
+        containLabel: true
+      };
+      this.options.grid = grid;
+    },
+    // 图例操作 legend
+    setOptionsLegend() {
+      const optionsSetup = this.optionsSetup;
+      const legend = this.options.legend;
+      legend.show = optionsSetup.isShowLegend;
+      legend.left = optionsSetup.lateralPosition;
+      legend.top = optionsSetup.longitudinalPosition == "top" ? 0 : "auto";
+      legend.bottom =
+        optionsSetup.longitudinalPosition == "bottom" ? 0 : "auto";
+      legend.orient = optionsSetup.layoutFront;
+      legend.textStyle = {
+        color: optionsSetup.lengedColor,
+        fontSize: optionsSetup.lengedFontSize
+      };
+      legend.itemWidth = optionsSetup.lengedWidth;
+    },
+    // 图例颜色修改
+    setOptionsColor() {
+      const optionsCollapse = this.optionsSetup;
+      const customColor = optionsCollapse.customColor;
+      if (!customColor) return;
+      const arrColor = [];
+      for (let i = 0; i < customColor.length; i++) {
+        arrColor.push(customColor[i].color);
+      }
+      this.options.color = arrColor;
+      this.options = Object.assign({}, this.options);
+    },
+    // 数据解析
+    setOptionsData() {
+      const optionsSetup = this.optionsSetup;
+      const optionsData = this.optionsData; // 数据类型 静态 or 动态
+      optionsData.dataType == "staticData"
+        ? this.staticDataFn(optionsData.staticData, optionsSetup)
+        : this.dynamicDataFn(
+        optionsData.dynamicData,
+        optionsData.refreshTime,
+        optionsSetup
+        );
+    },
+    //去重
+    setUnique(arr) {
+      let newArr = [];
+      arr.forEach(item => {
+        return newArr.includes(item) ? '' : newArr.push(item);
+      });
+      return newArr;
+    },
+    //静态数据
+    staticDataFn(val) {
+      const optionsSetup = this.optionsSetup;
+      //颜色
+      const customColor = optionsSetup.customColor;
+      const arrColor = [];
+      for (let i = 0; i < customColor.length; i++) {
+        arrColor.push(customColor[i].color);
+      }
+      //数据
+      const series = [];
+      let xAxisList = []
+      let yAxisList = []
+      for (const i in val) {
+        xAxisList[i] = val[i].axis
+        yAxisList[i] = val[i].name
+      }
+      xAxisList = this.setUnique(xAxisList) // x轴 0725 0726 0727
+      yAxisList = this.setUnique(yAxisList) // y轴 A B C
+      for (const i in yAxisList) {
+        const data = new Array(yAxisList.length).fill(0)
+        for (const j in xAxisList) {
+          for (const k in val) {
+            if (val[k].name == yAxisList[i]) { // a = a
+              if (val[k].axis == xAxisList[j]) { // 0725
+                data[j] = val[k].data
+              }
+            }
+          }
+        }
+        series.push({
+          name: yAxisList[i],
+          type: "line",
+          data: data,
+          width: optionsSetup.lineWidth,
+          symbol: 'circle',
+          showSymbol: optionsSetup.markPoint,
+          symbolSize: optionsSetup.pointSize,
+          symbolColor: arrColor[i],
+          smooth: optionsSetup.smoothCurve,
+          // 线条
+          lineStyle: {
+            color: arrColor[i],
+            width: optionsSetup.lineWidth
+          },
+          //点
+          itemStyle: {
+            color: arrColor[i],
+          },
+          areaStyle: this.getOptionArea(),
+          //标题部分
+          label: {
+            show: optionsSetup.isShow,
+            position: "top",
+            distance: 10,
+            fontSize: optionsSetup.fontSize,
+            color: optionsSetup.subTextColor,
+            fontWeight: optionsSetup.fontWeight
+          },
+        })
+      }
+      this.options.series = series
+      if (optionsSetup.verticalShow) {
+        this.options.xAxis.data = [];
+        this.options.yAxis.data = xAxisList;
+        this.options.xAxis.type = "value";
+        this.options.yAxis.type = "category";
+      } else {
+        this.options.xAxis.data = xAxisList;
+        this.options.yAxis.data = [];
+        this.options.xAxis.type = "category";
+        this.options.yAxis.type = "value";
+      }
+    },
+    // 动态数据
+    dynamicDataFn(val, refreshTime, optionsSetup) {
+      if (!val) return;
+      if (this.ispreview) {
+        this.getEchartData(val, optionsSetup);
+        this.flagInter = setInterval(() => {
+          this.getEchartData(val, optionsSetup);
+        }, refreshTime);
+      } else {
+        this.getEchartData(val, optionsSetup);
+      }
+    },
+    getEchartData(val, optionsSetup) {
+      const data = this.queryEchartsData(val);
+      data.then(res => {
+        this.renderingFn(optionsSetup, res);
+      });
+    },
+    renderingFn(optionsSetup, val) {
+      //颜色
+      const customColor = optionsSetup.customColor;
+      const arrColor = [];
+      for (let i = 0; i < customColor.length; i++) {
+        arrColor.push(customColor[i].color);
+      }
+      // x轴
+      if (optionsSetup.verticalShow) {
+        this.options.xAxis.data = [];
+        this.options.yAxis.data = val.xAxis;
+        this.options.xAxis.type = "value";
+        this.options.yAxis.type = "category";
+      } else {
+        this.options.xAxis.data = val.xAxis;
+        this.options.yAxis.data = [];
+        this.options.xAxis.type = "category";
+        this.options.yAxis.type = "value";
+      }
+      const series = [];
+      for (const i in val.series) {
+        if (val.series[i].type == "line") {
+          series.push({
+            name: val.series[i].name,
+            type: "line",
+            data: val.series[i].data,
+            width: optionsSetup.lineWidth,
+            symbol: 'circle',
+            showSymbol: optionsSetup.markPoint,
+            symbolSize: optionsSetup.pointSize,
+            symbolColor: arrColor[i],
+            smooth: optionsSetup.smoothCurve,
+            // 线条
+            lineStyle: {
+              color: arrColor[i],
+              width: optionsSetup.lineWidth
+            },
+            //点
+            itemStyle: {
+              color: arrColor[i],
+            },
+            areaStyle: this.getOptionArea(),
+            // 标题部分
+            label: {
+              show: optionsSetup.isShow,
+              position: "top",
+              distance: 10,
+              fontSize: optionsSetup.fontSize,
+              color: optionsSetup.subTextColor,
+              fontWeight: optionsSetup.fontWeight
+            },
+          })
+        }
+      }
+      this.options.series = series
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.echarts {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+
+</style>

+ 6 - 1
report-ui/src/views/report/bigscreen/designer/widget/temp.vue

@@ -31,6 +31,9 @@ import widgetTable from "./widgetTable.vue";
 import widgetMap from "./widgetMap.vue";
 import widgetPiePercentageChart from "./pie/widgetPiePercentageChart";
 import widgetAirBubbleMap from "./map/widgetAirBubbleMap";
+import widgetBarStackChart from "./bar/widgetBarStackChart";
+import widgetLineStackChart from "./line/widgetLineStackChart";
+
 export default {
   name: "WidgetTemp",
   components: {
@@ -53,7 +56,9 @@ export default {
     widgetTable,
     widgetMap,
     widgetPiePercentageChart,
-    widgetAirBubbleMap
+    widgetAirBubbleMap,
+    widgetBarStackChart,
+    widgetLineStackChart
   },
   model: {
     prop: "value",

+ 6 - 1
report-ui/src/views/report/bigscreen/designer/widget/widget.vue

@@ -41,6 +41,9 @@ import widgetTable from "./widgetTable.vue";
 import widgetMap from "./widgetMap.vue";
 import widgetPiePercentageChart from "./pie/widgetPiePercentageChart";
 import widgetAirBubbleMap from "./map/widgetAirBubbleMap";
+import widgetBarStackChart from "./bar/widgetBarStackChart";
+import widgetLineStackChart from "./line/widgetLineStackChart";
+
 export default {
   name: "Widget",
   components: {
@@ -63,7 +66,9 @@ export default {
     widgetTable,
     widgetMap,
     widgetPiePercentageChart,
-    widgetAirBubbleMap
+    widgetAirBubbleMap,
+    widgetBarStackChart,
+    widgetLineStackChart
   },
   model: {
     prop: "value",

+ 4 - 1
report-ui/src/views/report/bigscreen/index.vue

@@ -99,6 +99,7 @@
     <Share
       :visib="visibleForShareDialog"
       :reportCode="reportCodeForShareDialog"
+      :reportName="reportNameForShareDialog"
       @handleClose="visibleForShareDialog = false"
     />
   </div>
@@ -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) {

+ 0 - 2
report-ui/src/views/report/bigscreen/viewer/index.vue

@@ -14,8 +14,6 @@
         :type="widget.type"
       />
     </div>
-    <!-- 如果是二次开发商业使用必须带上这个技术支持 -->
-    <div class="bottom-text">技术支持: 安吉加加信息技术有限公司</div>
   </div>
 </template>
 

+ 102 - 4
report-ui/src/views/report/report/components/share.vue

@@ -1,14 +1,45 @@
 <template>
-  <el-dialog class="tree_dialog" title="报表分享" width="60%" :close-on-click-modal="false" center :visible.sync="visib" :before-close="closeDialog">
+  <el-dialog class="tree_dialog" :title="titleBuild()" width="60%" :close-on-click-modal="false" center :visible.sync="visib" :before-close="closeDialog">
+    <div v-if="shareLinkFlag1">
+      <el-form ref="userForm" :model="dialogForm" :rules="rules" size="small" label-width="100px">
+        <el-row :gutter="10">
+          <el-col :xs="24" :sm="20" :md="6" :lg="6" :xl="6">
+            <el-form-item label="有效期" prop="shareValidType">
+              <el-select v-model.trim="dialogForm.shareValidType" placeholder="请选择" clearable @change="selectChange">
+                <el-option v-for="item in shareValidTypeOptions" :key="item.id" :label="item.text" :value="item.id" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <el-button type="primary" plain @click="createShare">创建链接</el-button>
+    </div>
+    <div v-else>
+      <el-row :gutter="10">
+      <el-col :xs="24" :sm="20" :md="20" :lg="20" :xl="16">
+        <el-input v-model="reportShareUrl" :disabled="true"/>
+      </el-col>
+      </el-row>
+      <el-row :gutter="10">
+        <el-button type="primary" plain @click="copyShare">复制链接</el-button>
+      </el-row>
+
+    </div>
+
     <div slot="footer" style="text-align: center">
-      {{reportCode}}
-      <el-button type="primary" plain @click="saveReportShare">保存</el-button>
+
+<!--      <el-button type="primary" plain @click="saveReportShare">保存</el-button>-->
       <el-button type="danger" plain @click="closeDialog">取消</el-button>
     </div>
   </el-dialog>
 </template>
 <script>
+
+import { reportShareAdd } from '@/api/reportShare'
+import { getDictList } from '@/api/dict-data' // 获取数据字典
+import Dictionary from '@/components/Dictionary/index'
 export default {
+  components: { Dictionary },
   props: {
     visib: {
       required: true,
@@ -22,20 +53,87 @@ export default {
         return ''
       },
     },
+    reportName: {
+      required: true,
+      type: String,
+      default: () => {
+        return ''
+      },
+    },
   },
   data() {
     return {
-    }
+      title: '报表分享',
+      reportShareUrl:'',
+      shareValidTypeOptions: [], // 有效期类型
+      dialogForm: {
+        shareValidType: 0,
+        reportCode: '',
+        shareUrl: '',
+        shareCode: '',
+      },
+      shareLinkFlag1: true,
+      rules: {
+        shareValidType: [
+          {required: true, message: '有效期必选', trigger: 'change'},
+        ],
+      },
+    };
   },
   watch: {
     visib(val) {
       if (val) {
         // 弹窗弹出时需要执行的逻辑
+        this.getSystem()
       }
     },
   },
   created() {},
   methods: {
+    titleBuild(){
+      return '【' +this.reportName + '】' + '报表分享-' + this.reportCode
+    },
+    selectChange(val) {
+      this.dialogForm.shareValidType = val
+    },
+    // 获取数据字典
+    async getSystem() {
+      this.shareLinkFlag1 = true
+      const { code, data } = await getDictList('SHARE_VAILD')
+      if (code != '200') return
+      this.shareValidTypeOptions = data
+      this.dialogForm.shareValidType = this.shareValidTypeOptions[0].id
+    },
+    async createShare() {
+      this.dialogForm.reportCode = this.reportCode
+      this.dialogForm.shareUrl = window.location.href
+      console.log(this.dialogForm)
+      const {code, data} = await reportShareAdd(this.dialogForm)
+      if (code != '200') return
+      console.log(data)
+      this.shareLinkFlag1 = false
+      this.$message({
+        message: '创建链接成功!',
+        type: 'success',
+      })
+      this.reportShareUrl = data.shareUrl
+    },
+
+    copyShare(){
+      this.copyToClip(this.reportShareUrl)
+      this.$message({
+        message: '复制链接成功!',
+        type: 'success',
+      })
+    },
+    copyToClip(content, message) {
+      var aux = document.createElement("input");
+      aux.setAttribute("value", content);
+      document.body.appendChild(aux);
+      aux.select();
+      document.execCommand("copy");
+      document.body.removeChild(aux);
+    },
 
     async saveReportShare() {
       var params = {

+ 28 - 1
report-ui/src/views/report/report/index.vue

@@ -19,6 +19,21 @@
         v-permission="'bigScreenManage:design'"
         >设计</el-button
       >
+      <el-button
+        type="text"
+        @click="shareReport(props.msg)"
+        v-permission="'bigScreenManage:share'"
+      >分享</el-button
+      >
+    </template>
+
+    <template v-slot:pageSection>
+      <Share
+        :visib="visibleForShareDialog"
+        :reportCode="reportCodeForShareDialog"
+        :reportName="reportNameForShareDialog"
+        @handleClose="visibleForShareDialog = false"
+      />
     </template>
   </anji-crud>
 </template>
@@ -30,13 +45,19 @@ import {
   reportUpdate,
   reportDetail
 } from "@/api/reportmanage";
+import Share from "@/views/report/report/components/share";
 export default {
   name: "Report",
   components: {
-    anjiCrud: require("@/components/AnjiPlus/anji-crud/anji-crud").default
+    anjiCrud: require("@/components/AnjiPlus/anji-crud/anji-crud").default,
+    Share
   },
   data() {
     return {
+      // 分享
+      visibleForShareDialog: false,
+      reportCodeForShareDialog: "",
+      reportNameForShareDialog: "",
       crudOption: {
         // 使用菜单做为页面标题
         title: "报表管理",
@@ -233,6 +254,12 @@ export default {
         }
       });
       window.open(routeUrl.href, "_blank");
+    },
+    //分享
+    shareReport(val){
+      this.reportCodeForShareDialog = val.reportCode;
+      this.reportNameForShareDialog = val.reportName;
+      this.visibleForShareDialog = true;
     }
   }
 };

+ 5 - 5
report-ui/src/views/report/resultset/components/EditDataSet.vue

@@ -161,11 +161,11 @@
                       </template>
                     </el-table-column>
                   </el-table>
-                  <el-checkbox
-                    v-model="isShowPagination"
-                    @change="changePagination"
-                    >加入分页参数
-                  </el-checkbox>
+<!--                  <el-checkbox-->
+<!--                    v-model="isShowPagination"-->
+<!--                    @change="changePagination"-->
+<!--                    >加入分页参数-->
+<!--                  </el-checkbox>-->
                 </el-tab-pane>
                 <el-tab-pane label="数据转换" name="second">
                   <template>

部分文件因为文件数量过多而无法显示