欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

若依(ruoyi)前后端分离项目集成积木报表,并解决积木大屏部署到服务器加载不出来的问题,目前整体使用感觉还是

来源: javaer 分享于  点击 43200 次 点评:213

若依(ruoyi)前后端分离项目集成积木报表,并解决积木大屏部署到服务器加载不出来的问题,目前整体使用感觉还是


若依(ruoyi)前后端分离项目集成积木报表

致敬:

1:若依开源项目(本文使用的是前后端分离版本:3.8.9)

        若依官网:https://www.ruoyi.vip/

2:积木开源项目

        积木报表官网:https://www.jimureport.com/

3:CSDN大神的文章(我是根据他的原文一步步配置的,前端配置有一些改动,如有版权问题,可随时联系本人删除)

        原文地址:https://blog.csdn.net/qq_55896432/article/details/145060090

背景:

写在前面:

搭建这个项目是因为自己想记录日常使用的一些数据(练琴统计,钢琴课程数量,花费等等这些),然后找了一些BI发现都不是很适合,目前积木是最适合的(开源且集成程度高),所以记录了一下整体的操作步骤。
目前整体使用感觉还是可以的,数据源数据集设置都很方便,必要的控件也都够用。

项目运行的前提条件:

能正常运行若依前后端分离版本就OK.

效果(部分截图)

手搓的首页

普通报表管理菜单

普通报表设计

数据源&数据集设置

大屏报表管理菜单

大屏设计

数据源&数据集设置

后端配置

ruoyi-common模块下pom.xml文件添加依赖

        <!-- 积木报表 -->
        <dependency>
            <groupId>org.jeecgframework.jimureport</groupId>
            <artifactId>jimureport-spring-boot-starter</artifactId>
            <version>1.9.2</version>
        </dependency>

        <!--积木BI大屏-->
        <dependency>
            <groupId>org.jeecgframework.jimureport</groupId>
            <artifactId>jimubi-spring-boot-starter</artifactId>
            <version>1.9.1</version>
        </dependency>

添加完重新加载maven

ruoyi-admin模块修改application.yml文件,新增积木报表相关配置

jeecg :
  # 权限配置
  permission:
    # 报表权限配置
    report:
      # 查询权限符号,配置此权限代表只能查看报表
      query: jeecg:report:query
      # 修改权限符号,配置此权限代表拥有报表所有权限
      edit: jeecg:report:edit
    # 大屏权限配置
    drag:
      # 查询权限符号,配置此权限代表只能查看大屏
      query: jeecg:drag:query
      # 修改权限符号,配置此权限代表拥有大屏所有权限
      edit: jeecg:drag:edit
  jmreport:
    #自定义项目前缀
    # 现在是开发环境下的前端访问前缀,部署项目时,需要切换到生成环境访问前缀
    customPrePath: /dev-api

注意:

1.目前报表和大屏分别设置两个类型的权限,其中query权限表示只能查看,edit权限表示用于一切权限。

2.customPrePath是用来配置前端访问后端的接口的前缀,当前是开发环境配置为/dev-api没问题。

3.项目发布时,一定将这个配置改为生产环境下访问前缀,如:/prod-api。

允许匿名访问ruoyi-framework模块下修改SecurityConfig.java文件

增加积木报表和大屏匿名访问权限。

, "/jmreport/**", "/drag/**"

新建积木报表相关配置类

在com.ruoyi.framework包下增加包report,在report包下新增config包,在cofig包下新增ReportConfig.java类,并在此类中添加以下代码。

package com.ruoyi.framework.report.config;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
@Component
public class ReportConfig {
 
    // 报表查询权限
    @Value("${jeecg.permission.report.query}")
    private String reportQueryPermission;
 
    // 报表修改权限
    @Value("${jeecg.permission.report.edit}")
    private String reportEditPermission;
 
    // 大屏查看权限
    @Value("${jeecg.permission.drag.query}")
    private String dragQueryPermission;
 
    //大屏修改权限
    @Value("${jeecg.permission.drag.edit}")
    private String dragEditPermission;
 
    public String getReportQueryPermission() {
        return reportQueryPermission;
    }
 
    public void setReportQueryPermission(String reportQueryPermission) {
        this.reportQueryPermission = reportQueryPermission;
    }
 
    public String getReportEditPermission() {
        return reportEditPermission;
    }
 
    public void setReportEditPermission(String reportEditPermission) {
        this.reportEditPermission = reportEditPermission;
    }
 
    public String getDragQueryPermission() {
        return dragQueryPermission;
    }
 
    public void setDragQueryPermission(String dragQueryPermission) {
        this.dragQueryPermission = dragQueryPermission;
    }
 
    public String getDragEditPermission() {
        return dragEditPermission;
    }
 
    public void setDragEditPermission(String dragEditPermission) {
        this.dragEditPermission = dragEditPermission;
    }
}

重写若依框架getLoginUser()方法

打开web.service包下的TokenService.java文件,将自带的getLoginUser方法注释掉

新增代码

    /***************************积木报表修改,注释掉了原来的getLoginUser*******************************/
    // 修改
    public LoginUser getLoginUser(HttpServletRequest request) {
        // 获取请求携带的令牌
        String token = getToken(request);
        return getLoginUser(token);

    }


    public LoginUser getLoginUser(String token) {
        if (StringUtils.isNotEmpty(token)) {
            try {
                Claims claims = parseToken(token);
                // 解析对应的权限以及用户信息
                String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
                String userKey = getTokenKey(uuid);
                LoginUser user = redisCache.getCacheObject(userKey);
                return user;
            } catch (Exception e) {
                log.error("获取用户信息异常'{}'", e.getMessage());
            }
        }
        return null;

    }

    /***************************积木报表修改,注释掉了原来的getLoginUser*******************************/

在report包下新增service包下,在service包下新增ReportTokenService.java类,并且在此类中添加以下代码

package com.ruoyi.framework.report.service;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.report.config.ReportConfig;
import com.ruoyi.framework.web.service.TokenService;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;


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


@Component
public class ReportTokenService implements JmReportTokenServiceI {

    // 若依框架token
    @Value("${token.header}")
    private String ryHeader;

    // 积木报表token
    private String jmHeader = "X-Access-Token";

    @Autowired
    private ReportConfig reportConfig;

    @Autowired
    private TokenService tokenService;


    @Override
    public String getUsername(String s) {
        LoginUser loginUser = tokenService.getLoginUser(s);
        return loginUser.getUsername();
    }

    @Override
    public String[] getRoles(String s) {
        LoginUser loginUser = tokenService.getLoginUser(s);
        SysUser user = loginUser.getUser();
        List<SysRole> roles = user.getRoles();
        String[] roleNameArray = roles.stream().map(SysRole::getRoleName).toArray(String[]::new);
        return roleNameArray;
    }

    @Override
    public Boolean verifyToken(String s) {
        LoginUser loginUser = tokenService.getLoginUser(s);
        if (StringUtils.isNotNull(loginUser)){
            tokenService.refreshToken(loginUser);
            SysUser user = loginUser.getUser();

            // 超级管理员放权
            if (StringUtils.isNotNull(user) && user.isAdmin()) {
                return true;
            } else {
                Set<String> permissions = loginUser.getPermissions();
                if (StringUtils.isNotNull(permissions) && (permissions.contains(reportConfig.getReportQueryPermission()) || permissions.contains(reportConfig.getReportEditPermission()) || permissions.contains(reportConfig.getDragQueryPermission()) || permissions.contains(reportConfig.getDragEditPermission()))) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public String getToken(HttpServletRequest request) {
        String token = request.getParameter("token");
        if (StringUtils.isNull(token)) {
            token = request.getHeader(jmHeader);
        }
        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
        {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

    @Override
    public Map<String, Object> getUserInfo(String token) {
        token = token.replace(Constants.TOKEN_PREFIX, "");
        LoginUser loginUser = tokenService.getLoginUser(token);
        Map<String, Object> map = new HashMap<>();
        map.put(SYS_USER_CODE, loginUser.getUserId());
        map.put(SYS_ORG_CODE, loginUser.getDeptId());
        return map;
    }

    @Override
    public HttpHeaders customApiHeader() {
        HttpHeaders headers = new HttpHeaders();
        headers.add(ryHeader, Constants.TOKEN_PREFIX + getToken());
        headers.add(jmHeader, getToken());
        return headers;
    }
}

贴一下原作者的注意事项:

配置拦截器

在report包下新增interceptor包,在interceptor包下新增ReportInterceptor.java类,并且在此类中添加以下代码

package com.ruoyi.framework.report.interceptor;
 
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.report.config.ReportConfig;
import com.ruoyi.framework.report.service.ReportTokenService;
import com.ruoyi.framework.web.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
 
@Component
public class ReportInterceptor implements HandlerInterceptor {
 
    @Autowired
    private TokenService tokenService;
 
    @Autowired
    private ReportConfig reportConfig;
 
    @Autowired
    private ReportTokenService reportTokenService;
 
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 
        String token = reportTokenService.getToken(request);
        LoginUser loginUser = tokenService.getLoginUser(token);
//        String uri = request.getRequestURI();
//        System.out.println(uri);
 
        if (StringUtils.isNotNull(loginUser)) {
            SysUser user = loginUser.getUser();
 
            // 超级管理员放权
            if (StringUtils.isNotNull(user) && user.isAdmin()) {
                return true;
            } else {
                //获取权限集合
                Set<String> permissions = loginUser.getPermissions();
                //如果拥有设计器的权限,则无需view权限,也可以通过校验
                if (StringUtils.isNotNull(permissions)) {
                    String uri = request.getRequestURI();
 
                    // 如果访问报表
                    if (uri.contains("/jmreport/")) {
                        // 如果有操作权限,直接放行
                        if (permissions.contains(reportConfig.getReportEditPermission())) {
                            return true;
                        } else {
                            // 设置查询报表的路径,没有带报表编码的路径
                            Set<String> queryReportSet = new HashSet<>();
                            queryReportSet.add("/jmreport/getQueryInfo");
                            queryReportSet.add("/jmreport/show");
 
                            // 设置查询报表的路径,带报表编码的路径
                            ArrayList<String> queryReportList = new ArrayList<>();
                            queryReportList.add("/jmreport/view/");
                            queryReportList.add("/jmreport/addViewCount/");
                            queryReportList.add("/jmreport/checkParam/");
 
                            // 如果有查询权限
                            if (permissions.contains(reportConfig.getReportQueryPermission())) {
 
                                // 如果是没有报表编码的路径,放行
                                if (queryReportSet.contains(uri)) {
                                    return true;
                                } else {
 
                                    // 如果是带报表编码的路径,放行
                                    for (int i = 0; i < queryReportList.size(); i++) {
                                        String s = queryReportList.get(i);
                                        if (uri.contains(s)) {
                                            return true;
                                        }
                                    }
 
                                }
 
                            }
                        }
 
                        //如果访问大屏
                    } else if (uri.contains("/drag/")) {
 
                        // 如果有操作权限,直接放行
                        if (permissions.contains(reportConfig.getDragEditPermission())) {
                            return true;
                        } else {
                            // 设置查询大屏的路径,完全路径
                            Set<String> queryDragSet = new HashSet<>();
                            queryDragSet.add("/drag/page/queryById");
                            queryDragSet.add("/drag/page/addVisitsNumber");
 
 
                            // 设置查询大屏的路径,带有包含部分路径
                            ArrayList<String> queryDragList = new ArrayList<>();
                            queryDragList.add("/drag/share/view/");
                            queryDragList.add("/drag/mock/json/");
 
                            // 如果有查询权限,并且访问的查询接口,放行
                            if (permissions.contains(reportConfig.getDragQueryPermission()) && queryDragSet.contains(uri)) {
                                return true;
                            }
                        }
                        // 拦截非报表和大屏路径处理,正确配置,不会出现此情况。
                    } else {
                        return true;
                    }
 
                }
            }
        }
        AjaxResult ajaxResult = AjaxResult.error(403, "当前操作没有权限");
        ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult));
        return false;
    }
}

原作者说的注意事项:

打开config包下的ResourcesConfig.java文件,注入ReportInterceptor拦截器,并且注册拦截器和设置拦截规则

修改addInterceptors()方法

  /**
     * 自定义拦截规则
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**")
                // 积木报表新增:不拦截静态资源
                .excludePathPatterns("/*.**, /**/*.html, /**/*.css, /**/*.js, /**/*.png, /**/*.jpg, /**/*.woff, /**/*.woff2, /**/*.ttf,  /**/*.svg, /**/*.ico, /**/*.map" )
        ;
    }

如果出现未设置的静态资源,需要自己进行设置。

实现数据格式转换器

在report包下新增adapter包,在adapter包下,新增ReportDataConvertAdapter.java文件,并且在此类中添加以下代码

package com.ruoyi.framework.report.adapter;
 
import com.alibaba.fastjson.JSONObject;
import org.jeecg.modules.jmreport.desreport.render.handler.convert.ApiDataConvertAdapter;
import org.springframework.stereotype.Component;
 
@Component("reportDataConvertAdapter")
public class ReportDataConvertAdapter implements ApiDataConvertAdapter {
    @Override
    public String getData(JSONObject jsonObject) {
 
        if(jsonObject.containsKey("data")){
            String data = jsonObject.getString("data");
            return data;
        }else if(jsonObject.containsKey("rows")){
            return jsonObject.getString("rows");
        }else {
            return jsonObject.toJSONString();
        }
    }
}
 

去官网拿积木的数据结构,在数据库执行

官网地址:

https://github.com/jeecgboot/jimureport/blob/master/db/jimureport.mysql5.7.create.sql

再贴个云盘地址吧(最好去官网拿最新版本)

https://www.alipan.com/s/PqaE77FUK28

前端配置

新建jeecg文件夹,并且jeecg文件夹下,新增request.js文件,并且在此文件中添加以下代码

import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams } from "@/utils/ruoyi";
import cache from '@/plugins/cache'

// 是否显示重新登录
export let isRelogin = { show: false };

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 超时
  timeout: 10000
})

// request拦截器
service.interceptors.request.use(config => {
  // 是否需要设置 token
  const isToken = (config.headers || {}).isToken === false
  // 是否需要防止数据重复提交
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  if (getToken() && !isToken) {
    config.headers['X-Access-Token'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
  }
  // get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?' + tansParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }
  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
    const requestObj = {
      url: config.url,
      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
      time: new Date().getTime()
    }
    const sessionObj = cache.session.getJSON('sessionObj')
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.session.setJSON('sessionObj', requestObj)
    } else {
      const s_url = sessionObj.url;                  // 请求地址
      const s_data = sessionObj.data;                // 请求数据
      const s_time = sessionObj.time;                // 请求时间
      const interval = 1000;                         // 间隔时间(ms),小于此时间视为重复提交
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        const message = '数据正在处理,请勿重复提交';
        console.warn(`[${s_url}]: ` + message)
        return Promise.reject(new Error(message))
      } else {
        cache.session.setJSON('sessionObj', requestObj)
      }
    }
  }
  return config
}, error => {
  console.log(error)
  Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
    // 未设置状态码则默认成功状态
    const code = res.data.code || 200;
    // 获取错误信息
    const msg = errorCode[code] || res.data.msg || res.data.message || errorCode['default']

    // 二进制数据则直接返回
    if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {
      return res
    }
    if (code === 401) {
      if (!isRelogin.show) {
        isRelogin.show = true;
        MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
          isRelogin.show = false;
          store.dispatch('LogOut').then(() => {
            location.href = '/index';
          })
        }).catch(() => {
          isRelogin.show = false;
        });
      }
      return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
    } else if (code === 500) {
      Message({ message: msg, type: 'error' })
      return Promise.reject(new Error(msg))
    } else if (code === 601) {
      Message({ message: msg, type: 'warning' })
      return Promise.reject('error')
    } else if (code !== 200) {
      Notification.error({ title: msg })
      return Promise.reject('error')
    } else {
      return res.data
    }
  },
  error => {
    console.log('err' + error)
    let { message } = error;
    if (message == "Network Error") {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    Message({ message: message, type: 'error', duration: 5 * 1000 })
    return Promise.reject(error)
  }
)


export default service

在jeecg文件夹下,新增report.js文件,并且在此文件中添加以下代码

import request from "@/api/jeecg/request";
let jmreportUrl = "/jmreport";
import { getToken } from "@/utils/auth";
let paramObj = {
  token: "Bearer " + getToken()
}
// 获取填报报表
export function listReport(queryParams) {
  let params = {
    ...paramObj,
    ...queryParams
  }
  return request({
    url: jmreportUrl + "/excelQuery",
    method: 'get',
    params: params
  })
}

// 获取填报报表列表
export function listFillReport(queryParams) {
  paramObj["reportType"] = "1011126161407836160";
  let params = {
    ...paramObj,
    ...queryParams
  }
  return request({
    url: jmreportUrl + "/excelQuery",
    method: 'get',
    params: params
  })
}

在src/view文件夹下新增jeecg文件夹,在jeecg文件夹下新增report文件夹,在report文件夹下新增index.vue文件,并且在此文件中添加以下代码

<template>
  <div>
    <i-frame :src="reportUrl"></i-frame>
  </div>
</template>
<script>
import { getToken } from "@/utils/auth";
import iFrame from "@/components/iFrame/index";
export default {
  name: "PyJeecgReport",
  components: { iFrame },
  data() {
    return {
      reportUrl: process.env.VUE_APP_BASE_API + "/jmreport/list?token=Bearer " + getToken()
    }
  }
}
</script>

在report文件夹下新增view文件夹,在view文件夹下新增index.vue文件,并且在此文件中添加以下代码。

<template>
  <div>
    <i-frame :src="reportUrl"></i-frame>
  </div>
</template>
<script>
import { getToken } from "@/utils/auth";
import iFrame from "@/components/iFrame/index";
export default {
  name: "PyJeecgReportView",
  components: { iFrame },
  data() {
    return {
      reportUrl: ""
    }
  },
  created() {
    let query = this.$route.query;
    let code = undefined;
    let paramsString = "";
    if (query) {
      for (const key in query) {
        if (Object.hasOwnProperty.call(query, key)) {
          const param = query[key];
          if (key == "code") {
            code = param;
          } else {
            if (paramsString != "") {
              paramsString += paramsString + "&" + key + "=" + param;
            } else {
              paramsString = "&" + key + "=" + param;
            }
          }

        }
      }
    }

    if (code) {
      this.reportUrl = process.env.VUE_APP_BASE_API + "/jmreport/view/" + code + "?token=Bearer " + getToken() + paramsString;

    } else {
      this.$modal.msgError("报表编码(code)为空,无法打开报表");
    }
  }
}
</script>

在jeecg文件夹下新增drag文件夹,在drag文件夹下新增index.vue文件,并且在此文件中添加以下代码

<template>
  <div>
    <i-frame :src="dragUrl"></i-frame>
  </div>
</template>
<script>
import { getToken } from "@/utils/auth";
import iFrame from "@/components/iFrame/index";
export default {
  name: "PyJeecgDrag",
  components: { iFrame },
  data() {
    return {
      dragUrl: process.env.VUE_APP_BASE_API + "/drag/list?token=Bearer " + getToken()
    }
  }
}
</script>

在drag文件夹下新增view文件夹,在view文件夹下新增index.vue文件,并且在此文件中添加以下代码。

<template>
  <div>
    <i-frame :src="dragUrl"></i-frame>
  </div>
</template>
<script>
import { getToken } from "@/utils/auth";
import iFrame from "@/components/iFrame/index";
export default {
  name: "PyJeecgDragView",
  components: { iFrame },
  data() {
    return {
      dragUrl: ""
    }
  },
  created() {
    let query = this.$route.query;
    let code = undefined;
    let paramsString = "";
    if (query) {
      for (const key in query) {
        if (Object.hasOwnProperty.call(query, key)) {
          const param = query[key];
          if (key == "code") {
            code = param;
          } else {
            if (paramsString != "") {
              paramsString += paramsString + "&" + key + "=" + param;
            } else {
              paramsString = "&" + key + "=" + param;
            }
          }

        }
      }
    }

    if (code) {
      this.dragUrl = process.env.VUE_APP_BASE_API + "/drag/share/view/" + code + "?token=Bearer " + getToken() + paramsString;

    } else {
      this.$modal.msgError("大屏编码(code)为空,无法打开大屏");
    }
  }
}
</script>

执行创建菜单的SQL

-- 主目录
INSERT INTO `lucas`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `route_name`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1083, '报表管理', 0, 7, 'jeecg', NULL, NULL, '', 1, 0, 'M', '0', '0', NULL, 'chart', 'admin', '2025-03-27 01:49:40', '', NULL, '');


-- 基础报表菜单
INSERT INTO `lucas`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `route_name`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1084, '报表管理', 1083, 0, 'report', 'jeecg/report/index', NULL, '', 1, 0, 'C', '0', '0', 'jeecg:report:edit', 'druid', 'admin', '2025-03-27 01:51:44', 'admin', '2025-03-27 05:12:06', '');


-- 大屏报表菜单
INSERT INTO `lucas`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `route_name`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1085, '大屏管理', 1083, 1, 'drag', 'jeecg/drag/index', NULL, '', 1, 0, 'C', '0', '0', 'jeecg:drag:edit', 'druid', 'admin', '2025-03-27 01:53:17', 'admin', '2025-03-27 05:12:13', '');


-- 基础报表查看菜单
INSERT INTO `lucas`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `route_name`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1086, '报表查看', 1083, 2, 'report/view', 'jeecg/report/view/index', NULL, '', 1, 0, 'C', '1', '0', 'jeecg:report:query', 'eye-open', 'admin', '2025-03-27 01:54:41', 'admin', '2025-03-27 05:12:19', '');


-- 大屏报表查看菜单
INSERT INTO `lucas`.`sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `route_name`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1087, '大屏查看', 1083, 3, 'drag/view', 'jeecg/drag/view/index', NULL, '', 1, 0, 'C', '1', '0', 'jeecg:drag:query', 'eye-open', 'admin', '2025-03-27 01:55:46', 'admin', '2025-03-27 05:12:24', '');

修改Nginx配置

部署到服务器发现大屏报表一直加载不出来,本地打开没问题,就像这种:

然后看了下请求,发现大屏的几个接口没加对应的prod-api的前缀,怀疑接口其实是没获取到数据的。

所以就想了想nginx要加大屏报表对应的配置,于是修改nginx配置文件:在nginx.conf加上下面这些配置(proxy_pass那里换成对应的后端接口地址)


	location /drag/ {
		proxy_set_header Host $http_host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://localhost:8080/drag/;
		proxy_http_version 1.1;
		proxy_set_header Upgrade websocket;
		proxy_set_header Connection Upgrade;
	}

完成之后重启nginx服务:

	systemctl restart nginx.service

然后就发现后端请求数据有了,问题解决

相关栏目:

用户点评