Browse Source

报表分享

Raod 4 năm trước cách đây
mục cha
commit
0465d8d3e2

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

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

@@ -3,6 +3,7 @@ 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.annotation.log.GaeaAuditLog;
 import com.anji.plus.gaea.bean.ResponseBean;
 import com.anji.plus.gaea.curd.controller.GaeaBaseController;
 import com.anji.plus.gaea.curd.service.GaeaBaseService;
@@ -14,16 +15,14 @@ import com.anjiplus.template.gaea.business.modules.reportshare.dao.entity.Report
 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.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-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.*;
 
 /**
-* @desc 报表分享 controller
-* @author Raod
-* @date 2021-08-18 13:37:26.663
-**/
+ * @author Raod
+ * @desc 报表分享 controller
+ * @date 2021-08-18 13:37:26.663
+ **/
 @RestController
 @Api(tags = "报表分享管理")
 @RequestMapping("/reportShare")
@@ -63,4 +62,23 @@ public class ReportShareController extends GaeaBaseController<ReportShareParam,
         return responseBean;
     }
 
+    @GetMapping({"/detailByCode"})
+    @Permission(code = "detail", name = "明细")
+    public ResponseBean detailByCode(@RequestParam("shareCode") String shareCode) {
+        return ResponseBean.builder().data(reportShareService.detailByCode(shareCode)).build();
+    }
+
+    @PostMapping
+    @Permission(
+            code = "insert",
+            name = "新增"
+    )
+    @GaeaAuditLog(
+            pageTitle = "新增"
+    )
+    @Override
+    public ResponseBean insert(@Validated @RequestBody ReportShareDto dto) {
+        return ResponseBean.builder().data(reportShareService.insertShare(dto)).build();
+    }
+
 }

+ 6 - 0
report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/controller/dto/ReportShareDto.java

@@ -5,6 +5,9 @@ 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;
 
 /**
@@ -21,6 +24,7 @@ public class ReportShareDto extends GaeaBaseDTO implements Serializable {
 
     /** 分享有效期类型,DIC_NAME=SHARE_VAILD */
     @ApiModelProperty(value = "分享有效期类型,DIC_NAME=SHARE_VAILD")
+    @NotNull(message = "6002")
     private Integer shareValidType;
 
     /** 分享有效期 */
@@ -29,10 +33,12 @@ public class ReportShareDto extends GaeaBaseDTO implements Serializable {
 
     /** 分享url */
     @ApiModelProperty(value = "分享url")
+    @NotEmpty(message = "6002")
     private String shareUrl;
 
     /** 报表编码 */
     @ApiModelProperty(value = "报表编码")
+    @NotEmpty(message = "6002")
     private String reportCode;
 
     /** 0--已禁用 1--已启用  DIC_NAME=ENABLE_FLAG */

+ 4 - 0
report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/ReportShareService.java

@@ -2,6 +2,7 @@
 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;
 
@@ -20,4 +21,7 @@ public interface ReportShareService extends GaeaBaseService<ReportShareParam, Re
      */
     ReportShare getDetail(Long id);
 
+    ReportShare insertShare(ReportShareDto dto);
+
+    ReportShare detailByCode(String shareCode);
 }

+ 32 - 5
report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportshare/service/impl/ReportShareServiceImpl.java

@@ -4,16 +4,18 @@ 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.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.MD5Util;
-import org.apache.commons.lang3.StringUtils;
+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;
 
-import java.util.Date;
 import java.util.UUID;
 
 /**
@@ -24,6 +26,13 @@ import java.util.UUID;
 @Service
 public class ReportShareServiceImpl implements ReportShareService {
 
+    /**
+     * 默认跳转路由为aj的页面
+     */
+    private static final String SHARE_FLAG = "#/aj/";
+
+    private static final String SHARE_URL = "#";
+
     @Autowired
     private ReportShareMapper reportShareMapper;
 
@@ -38,6 +47,22 @@ public class ReportShareServiceImpl implements ReportShareService {
         return reportShare;
     }
 
+    @Override
+    public ReportShare insertShare(ReportShareDto dto) {
+        ReportShare entity = new ReportShare();
+        BeanUtils.copyProperties(dto, entity);
+        insert(entity);
+        return entity;
+    }
+
+    @Override
+    public ReportShare detailByCode(String shareCode) {
+        LambdaQueryWrapper<ReportShare> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(ReportShare::getShareCode, shareCode);
+        wrapper.eq(ReportShare::getEnableFlag, EnableFlagEnum.ENABLE.getCodeDesc());
+        return selectOne(wrapper);
+    }
+
     @Override
     public void processBeforeOperation(ReportShare entity, BaseOperationEnum operationEnum) throws BusinessException {
         switch (operationEnum) {
@@ -48,9 +73,11 @@ public class ReportShareServiceImpl implements ReportShareService {
                 //http://127.0.0.1:9095/reportDashboard/getData
                 String shareCode = UUID.randomUUID().toString();
                 entity.setShareCode(shareCode);
-                if (StringUtils.isNotBlank(entity.getShareUrl())) {
+                if (entity.getShareUrl().contains(SHARE_URL)) {
                     String prefix = entity.getShareUrl().substring(0, entity.getShareUrl().indexOf("#"));
-                    entity.setShareUrl(prefix + "#/bigscreen/viewer?reportCode=" + entity.getReportCode());
+                    entity.setShareUrl(prefix + SHARE_FLAG + shareCode);
+                } else {
+                    entity.setShareUrl(entity.getShareUrl() + SHARE_FLAG + shareCode);
                 }
                 entity.setShareValidTime(DateUtil.getFutureDateTmdHms(entity.getShareValidType()));
                 break;

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

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

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

@@ -1,14 +1,32 @@
 <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="title" width="60%" :close-on-click-modal="false" center :visible.sync="visib" :before-close="closeDialog">
+    <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>
+    {{reportShareUrl}}
     <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 +40,65 @@ export default {
         return ''
       },
     },
+    reportName: {
+      required: true,
+      type: String,
+      default: () => {
+        return ''
+      },
+    },
   },
   data() {
     return {
-    }
+      title: '报表分享-' + this.reportName + '【' +this.reportCode + '】',
+      reportShareUrl:'',
+      shareValidTypeOptions: [], // 有效期类型
+      dialogForm: {
+        shareValidType: 0,
+        reportCode: '',
+        shareUrl: '',
+        shareCode: '',
+      },
+      rules: {
+        shareValidType: [
+          {required: true, message: '有效期必选', trigger: 'change'},
+        ],
+      },
+    };
   },
   watch: {
     visib(val) {
       if (val) {
         // 弹窗弹出时需要执行的逻辑
+        this.getSystem()
       }
     },
   },
   created() {},
   methods: {
+    selectChange(val) {
+      this.dialogForm.shareValidType = val
+    },
+    // 获取数据字典
+    async getSystem() {
+      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.$message({
+        message: '创建链接成功!',
+        type: 'success',
+      })
+      this.reportShareUrl = data.shareUrl
+    },
 
     async saveReportShare() {
       var params = {