若依微服務版本整合積木報表

2023-06-26 18:01:35

一、專案結構

新建報表微服務模組,這是我的專案結構圖。

二、執行初始化資料指令碼

執行積木報表的初始化指令碼,建立相關表結構,github速度太慢,推薦使用 gitee地址。選擇你要建表的資料庫,我是跟業務庫放到了一起,執行完後會新增以下這幾張表。


三、pom中引入積木報表依賴

在頂級父pom中宣告積木報表的版本號:

<properties>
    <jeccg.jimureport.version>1.5.6</jeccg.jimureport.version>
</properties>

在報表微服務模組新增積木報表的依賴:

<!-- JimuReport -->
<dependency>
    <groupId>org.jeecgframework.jimureport</groupId>
    <artifactId>jimureport-spring-boot-starter</artifactId>
    <version>${jeccg.jimureport.version}</version>
</dependency>

四、啟動類新增積木掃描目錄

在報表微服務啟動類上新增積木報表掃描註解,@SpringBootApplication(exclude = {MongoAutoConfiguration.class},
scanBasePackages = {"org.jeecg.modules.jmreport", "com.iotings.report"}),下面是完整的啟動類程式碼塊:

package com.iotings.report;

import com.iotings.common.security.annotation.EnableCustomConfig;
import com.iotings.common.security.annotation.EnableRyFeignClients;
import com.iotings.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;

/**
 * @description: 報表中心模組
 * @author: wzlUp
 * @date: 2023/06/16 17:05
 * @motto: Done is better than perfect.
 */
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication(exclude = {MongoAutoConfiguration.class},
        scanBasePackages = {"org.jeecg.modules.jmreport", "com.iotings.report"})
public class IotingsReportApplication {

    public static void main(String[] args) {
        SpringApplication.run(IotingsReportApplication.class, args);
        System.out.println(
                "  .------------------------------------. \n" +
                " :     __                               :\n" +
                " :  =='_))  __-:!:-                     :\n" +
                " :    ,.' .'  ))-:!:-                   :\n" +
                " :   ((_,'  .'-:!:-  - Report Started - :\n" +
                " :  ~^~~~^~~^~~~^~                      :\n" +
                "  `------------------------------------' ");
    }
}

五、設定積木報表資料來源

使用程式碼方式進行資料來源的設定:

package com.iotings.report.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
 * @description: 資料來源設定類
 * @author: wzlUp
 * @date: 2023/06/25 16:17
 * @motto: Done is better than perfect.
 */
@Configuration
public class DataSourceConfig{
    /**
     *  1、bean的名稱必須為minidaoDataSource,否則不生效
     *  2、jeecg.minidao-datasource對應的是yml中的jeecg下的minidao-datasource,可自定義
     */
    @Bean(name="minidaoDataSource")
    @ConfigurationProperties(prefix = "jeecg.minidao-datasource")
    public DataSource dataSource(){
        return DataSourceBuilder.create().build();
    }
}

六、報表微服務設定

在 nacos 中新建 iotings-report-dev.yml 組態檔

以下是我的完整設定資料項:

# spring設定
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
  
#Minidao設定
minidao :
  base-package: org.jeecg.modules.jmreport.*  

jeecg:
  minidao-datasource:
    jdbc-url: jdbc:mysql://127.0.0.1:3306/ry-cloud?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2b8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      # 連線池最大連線數
      maximum-pool-size: 400
      # 空閒時保持最小連線數
      minimum-idle: 20
      # 空閒連線存活時間
      idle-timeout: 30000
      # 連線超時時間
      connection-timeout: 1800000
      #池中連線最長生命週期
      max-lifetime: 1800000
  jmreport:
    #資料字典是否進行saas資料隔離(限制只能看自己的字典)
    saas: false
    #是否 禁用匯出PDF和圖片的按鈕 預設為false
    exportDisabled: false
    #是否自動儲存
    autoSave: false
    #自動儲存間隔時間毫秒
    interval: 20000
    # 列索引
    col: 300
    #自定義專案字首
    customPrePath: /report
    # 自定義API介面的字首 #{api_base_path}的值
    # apiBasePath: http://10.10.0.138:83/
    #預覽分頁自定義
    pageSize:
      - 10
      - 20
      - 50
      - 100
    #列印紙張自定義
    printPaper:
      - title: 標籤列印
        size:
          - 140
          - 100        
    #介面超時設定(毫秒)
    connect-timeout: 1800000
    #Excel匯出模式(fast/快、primary/精緻模式,預設fast)
    export-excel-pattern: fast
    #Excel匯出資料每個sheet的行數,每個sheet最大1048576行
    page-size-number: 1048576
    #excel樣式超過多少行顯示預設樣式(只在fast模式下有效)
    excel-style-row: 1048576
    #預覽頁面的工具條 是否顯示 預設true
    viewToolbar: true
    #設計頁面表格的線是否顯示 預設true
    line: true
    #sql資料來源不寫字典下拉框顯示條數 版本1.4.2之後被放棄
    select-show-total: 10  

# mybatis設定
mybatis:
    # 搜尋指定包別名
    typeAliasesPackage: com.iotings.report
    # 設定mapper的掃描,找到所有的mapper.xml對映檔案
    mapperLocations: classpath:mapper/**/*.xml

# knife4j設定
knife4j:
  enable: true
#   basic:
#     enable: true
#     username: iotings
#     password: iotings2023

# swagger設定
swagger:
  version: 1.0.0
  title: 報表中心介面檔案
  basePackage: com.iotings.report
  termsOfServiceUrl: iotings-center
  description: 報表中心繫統介面的說明檔案
  contact:
    name: xxx

注意事項:

  • customPrePath路徑設定:需要跟閘道器的斷言【predicates】報表關鍵字保持一致,否則無法進行正確的路由

七、閘道器微服務設定

在 iotings-gateway-dev.yml 組態檔中新增報表微服務的路由:

routes:
    # 報表中心服務
    - id: iotings-report
      uri: lb://iotings-report
      predicates:
        - Path=/report/**
      filters:
        - StripPrefix=1

在 iotings-gateway-dev.yml 組態檔中新增積木報表的安全設定和不校驗白名單:

# 安全設定
security:
  # 驗證碼
  captcha:
    enabled: true
    type: math
  # 防止XSS攻擊
  xss:
    enabled: true
    excludeUrls:
      - /system/notice
      - /report/jmreport/**
  # 不校驗白名單
  ignore:
    whites:
      - /auth/logout
      - /auth/login
      - /auth/register
      - /*/v2/api-docs
      - /csrf
      - /message/websocket/**
      - /report/**

八、擴充套件:Token許可權控制

package com.iotings.report.service.impl;

import com.iotings.common.core.utils.DateUtils;
import com.iotings.common.core.utils.StringUtils;
import com.iotings.common.security.service.TokenService;
import com.iotings.common.security.utils.SecurityUtils;
import com.iotings.system.api.model.LoginUser;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 自定義報表鑑權(如果不進行自定義, 則所有請求不做許可權控制)
 * @author: wzlUp
 * @date: 2023/06/25 16:37
 * @motto: Done is better than perfect.
 */
@Component
public class JimuReportTokenServiceImpl implements JmReportTokenServiceI {

    @Autowired
    private TokenService tokenService;

    /**
     * 通過請求獲取Token
     */
    @Override
    public String getToken(HttpServletRequest request) {
        String token = request.getParameter("token");
        String jmToken = request.getHeader("token");
        if (token == null || token.length() == 0) {
            token = jmToken;
        }
        LoginUser loginUser = tokenService.getLoginUser(token);
        if (loginUser != null) {
            return token;
        }
        return "";
    }

    /**
     * 獲取登入人使用者名稱
     */
    @Override
    public String getUsername(String s) {
        LoginUser loginUser = tokenService.getLoginUser(s);
        return loginUser.getUsername();
    }

    /**
     * Token校驗
     */
    @Override
    public Boolean verifyToken(String s) {
        if (s != null && s.length() > 0) {
            LoginUser loginUser = tokenService.getLoginUser(s);
            return loginUser != null;
        }
        return false;
    }


    /**
     *  自定義請求頭
     */
    @Override
    public HttpHeaders customApiHeader() {
        HttpHeaders header = new HttpHeaders();
        header.add("X-Access-Token", SecurityUtils.getToken());
        return header;
    }

    /**
     * 獲取多租戶id
     * @return tenantId
     */
    public String getTenantId() {
        String token = SecurityUtils.getCurrentRequestInfo().getParameter("token");
        String header = SecurityUtils.getCurrentRequestInfo().getHeader("X-Access-Token");
        LoginUser loginUser = null;
        if (StringUtils.isNotBlank(token)) {
            loginUser = tokenService.getLoginUser(token);
        } else if (StringUtils.isNotBlank(header)) {
            loginUser = tokenService.getLoginUser(header);
        } else {
            //都不具備則不能存取
            return "NO";
        }
        //具備admin或者管理員許可權才可存取所有報表
        if (SecurityUtils.isAdmin(loginUser.getUserid())
                || loginUser.getRoles().contains("it")
                || loginUser.getRoles().contains("manger")) {
            return "";
        }
        return loginUser.getUsername();
    }

    @Override
    public Map<String, Object> getUserInfo(String token) {
        // 將所有資訊存放至map 解析sql會根據map的鍵值解析,可自定義其他值
        Map<String, Object> map = new HashMap<>(20);
        LoginUser loginUser = tokenService.getLoginUser(token);
        map.put("sysUserCode", loginUser.getUsername());
        //設定當前日期(年月日)
        map.put("sysData", DateUtils.getDate());
        //設定昨天日期(年月日)
        map.put("sysYesterDay", DateUtils.getYesterday());
        //設定當前登入使用者暱稱
        map.put("sysUserName", loginUser.getSysUser().getNickName());
        //設定當前登入使用者部門ID
        map.put("deptId", loginUser.getSysUser().getDeptId());
        //設定當前登入使用者描述
//        map.put("describe", loginUser.getSysUser().getDept().getDescribes());
        map.put("describe", loginUser.getSysUser().getDept().getRemark());
        return map;
    }
}

九、前端頁面設定

在前端頁面中新建 jimureport 資料夾,新建以下vue檔案

1、jimu.vue

<template>
  <i-frame :src="openUrl" id="jimuReportFrame"></i-frame>
</template>
<script>
  import { getToken } from '@/utils/auth'
  import iFrame from '@/components/iFrame/index'
  export default {
    name: "Jimu",
    components: {iFrame},
    data() {
      return {
        // 這裡寫暴露的統一的閘道器地址
        openUrl: "http://127.0.0.1:8080/report/jmreport/list?token=" + getToken(),
      };
    },
    mounted: function() {

    }
  };
</script>

2、view.vue

<template>
  <i-frame :src="openUrl"/>
</template>

<script>
import {getToken} from '@/utils/auth'
import iFrame from "@/components/iFrame/index";

export default {
  name: 'jimuview',
  components: {iFrame},
  props: {
    reportID: {
      type: [String],
      required: false,
      default: ''
    },
  },
  data() {
    return {
      serverUrl: 'http://127.0.0.1:8080',
      openUrl: '',
    }
  },
  created() {
    if (this.reportID.length != 0) {
      this.openUrl = this.serverUrl + '/report/jmreport/view/' + this.reportID + '?token=' +  getToken()
    } else {
      this.openUrl = this.serverUrl + '/report/jmreport/view/' + this.$route.path.substring(this.$route.path.lastIndexOf("/") + 1) + '?token=' + getToken()
    }
    console.log(this.openUrl)
  }
}
</script>

<style scoped>

</style>

十、設定報表選單

先新建一個主類目,我是建立了一個二級選單,這個可以自定義,隨意設定

新增二級目錄

十一、整合效果展示

整合後的頁面

模板案例頁面

報表的設計頁面

預覽頁面

十二、參考資料