关于jeecgboot在header中添加全局参数的构想

首先是先考虑要实现的功能

1、通过考试时间的选择,进行当前考试的级联回显

2、当前考试的数据由考试管理里面的数据所得

3、其实是登录项目后的回显

功能考虑完成之后就要进行全局的布局设置

1、设置一个数据存储器进行对考试ID、考试名称及开始时间和结束时间的一个存储


import { defineStore } from 'pinia';
export interface batchState {
  batchInfoList: string;
  batchId: string;
  batchFlag: boolean;
  batchName: string;
  batchFalg: boolean
  startTime: string;
  endTime: string;
}

export const usebatchStore = defineStore({
  id: 'app-batch',
  state: (): batchState => ({
    batchInfoList: "",
    batchId: '',
    batchFlag: true,
    batchName: '',
    batchFalg: false,
    startTime: "2000-01-01 00:00",
    endTime: "2099-12-31 23:59",
  }),
  actions: {
    // 对set方法进行参数校验,确保传入的是字符串类型
    setBatchInfoList(count: string): void {
      if (typeof count !== 'string') {
        console.error('很抱歉,setBatchInfoList传入的值不是字符串类型,请检查!');
        return;
      }
      this.batchInfoList = count
    },
    setBatchId(count: string): void {
      if (typeof count !== 'string') {
        console.error('很抱歉,setBatchId传入的值不是字符串类型,请检查!');
        return;
      }
      this.batchId = count;
    },
    setBatchName(count: string): void {
      if (typeof count !== 'string') {
        console.error('很抱歉,setBatchName传入的值不是字符串类型,请检查!');
        return;
      }
      this.batchName = count;
    },
    setStartTime(count: string): void {
      if (typeof count !== 'string') {
        console.error('很抱歉,setStartTime,请检查!');
        return;
      }
      this.startTime = count;
    },
    setEndTime(count: string): void {
      if (typeof count !== 'string') {
        console.error('很抱歉,setEndTime传入的值不是字符串类型,请检查!');
        return;
      }
      this.endTime = count;
    },
  },
  persist: {
    enabled: true,
    strategies: [
      {
        storage: localStorage,
      }
    ]
  }

});

2、对事件登录后回显、选择时间回显以及切换当前考试选项的一个回显的事件封装

/**
 * 获取当前考试
 */
export async function handleUpdateExamListToLocalStorage(val?: any, examName?: any, examId?: any) {
  const usebatch = usebatchStore();
  try {
    const res = await GetList();
    // 判断返回数据类型,确保安全存储
    if (typeof res === 'object' && res !== null) {
      // 序列化对象或数组为字符串
      const resString = JSON.stringify(res);
      // 检查数据大小,以防超过localStorage限制
      if (resString.length <= 5 * 1024 * 1024) {
        // 假设单个key的value上限为5MB
        usebatch.setBatchInfoList(resString);
      } else {
        console.error('很抱歉,当前考试数据过大,无法存储到localStorage');
      }
      if (val === 'login') {
        usebatch.setBatchName("");
        usebatch.setBatchId("");
      } else if (val === 'save') {
        JSON.parse(usebatch.batchInfoList).forEach((element) => {
          if (element.value == usebatch.batchId) {
            usebatch.setBatchName(element.content);
          }
        });
      } else if (val === 'change') {
        usebatch.setBatchName(examName);
        usebatch.setBatchId(examId);
      }
    } else {
      console.error('很抱歉,当前考试返回的不是对象且为空,无法存储到localStorage');
    }
  } catch (error) {
    // 异常处理
    console.error('获取批次异常:', error);
  }
}

3、在获取考试信息处理的前提是先获取数据库里面的考试数据,故封装了一个请求

/**
 * 查询考试数据
 */
enum Api {
  GetList = '/exam/getExamList',
}
export const GetList = () => {
  const usebatch = usebatchStore();
  let params={
    startTime:dayjs(usebatch.startTime).format('YYYY-MM-DD HH:mm'),
    endTime:dayjs(usebatch.endTime).format('YYYY-MM-DD HH:mm')
  }
  return defHttp.post({ url: Api.GetList,params }, { joinParamsToUrl: true })
};

4、差点忘记了,还封装了一个时间计算函数(获取当前时间的前/后x天的日期)

// 定义一天的毫秒数常量,用于日期计算
const MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
// 定义JavaScript支持的最大日期常量,用于防止时间戳溢出
const MAX_DATE = new Date(2099, 0, 19);

/**
 * 格式化日期函数
 * @param {Date} date - 需要格式化的日期对象
 * @return {string} 格式化后的日期字符串,格式为 'YYYY-MM-DD'
 */
export const format = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
};

/**
 * 计算从今天起指定天数后的日期
 * @param {number} days - 从今天起的天数,0表示今天,1表示明天,以此类推
 * @return {string} 格式化后的目标日期字符串,格式为 'YYYY-MM-DD'
 * @throws {Error} 如果输入类型非数字、值不在有效范围内或目标日期超过最大支持日期,则抛出错误
 */
export const getDaysFromNow = (days) => {
  // 类型检查,确保输入是数字类型
  if (typeof days !== 'number') {
    throw new Error('Invalid input type for days. Expected number.');
  }

  const today = new Date();
  const targetDate = new Date(today.getTime() + days * MILLISECONDS_IN_DAY);

  // 时间戳溢出检查,确保目标日期在最大支持日期范围内
  if (targetDate > MAX_DATE) {
    throw new Error('Target date exceeds maximum supported date.');
  }

  // 返回格式化后的目标日期字符串
  return format(targetDate);
};

最后就开始分项进行事件处理

1、登录后进行数据处理,(默认时间区间为前后七天)。代码如下:

usebatch.setStartTime(getDaysFromNow(-7)+ " 00:00")
usebatch.setEndTime(getDaysFromNow(7)+ " 23:59")
Timevalue.value=[dayjs(usebatch.startTime, dateFormat),dayjs(usebatch.endTime, dateFormat)]
handleUpdateExamListToLocalStorage("login");

2、选择时间后触发更新函数,代码如下:

const handleTimeChange = () => {
        usebatch.setStartTime(dayjs(Timevalue.value[0],).format('YYYY-MM-DD HH:mm'))
        usebatch.setEndTime(dayjs(Timevalue.value[1],).format('YYYY-MM-DD HH:mm'))
        handleUpdateExamListToLocalStorage("login",);
      };

3、选择当前考试的切换函数,代码如下:

const handleChange = (value: any, res: any) => {
        handleUpdateExamListToLocalStorage("change", res.content, value);
        message.success('切换批次成功,1s后刷新页面');
        setTimeout(() => {
          window.location.reload();
        }, 1000);
      };

4、也是最后一项,就是在考试管理编辑的数据正是当前考试的数据的时候,要对选项的名字进行同步,代码如下:

if (values.id == usebatch.batchId) {
       await handleUpdateExamListToLocalStorage('save');
      }

<think> 我们正在将SurveyKing的在线演示地址(https://s.surveyking.cn/)集成到JeecgBoot的菜单中。用户遇到的问题是:在JeecgBoot系统中登录后,访问该菜单项时一直停留在SurveyKing的登录页。 根据之前的讨论,问题可能源于: 1. 会话冲突:JeecgBoot和SurveyKing的会话(Cookie)相互覆盖。 2. 跨域问题:如果两个系统不在同一个域下,浏览器会阻止跨域请求携带Cookie,导致无法保持登录状态。 3. 嵌入方式:如果使用iframe嵌入,可能会受到浏览器的安全策略限制(如X-Frame-Options)。 解决方案回顾: 1. 使用反向代理将SurveyKing的地址代理到与JeecgBoot同域的路径下,从而避免跨域问题。 2. 在JeecgBoot的菜单配置中,使用代理后的地址(同域)而不是直接使用https://s.surveyking.cn/。 具体步骤: 由于JeecgBoot是一个Spring Boot为基础的系统,我们可以使用Nginx反向代理或者直接在Spring Boot中配置代理。这里我们以Nginx为例。 步骤一:配置Nginx反向代理 假设JeecgBoot运行在域名`yourdomain.com`上,我们希望通过`https://yourdomain.com/surveyking`来访问SurveyKing。 在Nginx配置文件中添加如下配置: ```nginx location /surveyking/ { proxy_pass https://s.surveyking.cn/; # 注意末尾的斜杠,确保路径正确传递 proxy_set_header Host s.surveyking.cn; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 以下两行解决跨域传递Cookie问题 proxy_cookie_domain s.surveyking.cn yourdomain.com; proxy_cookie_path / /surveyking/; } ``` 然后重启Nginx。 步骤二:在JeecgBoot菜单配置中使用代理地址 1. 登录JeecgBoot后台。 2. 进入菜单管理,添加菜单项: - 菜单名称:调查问卷(自定义) - 菜单类型:菜单类型选择“外部链接” - 路径/地址:填写`/surveyking`(注意:这里是相对路径,因为我们已经通过反向代理将`/surveyking`映射到SurveyKing的地址) 或者填写完整的URL(如果JeecgBoot要求填写完整URL,则填写`https://yourdomain.com/surveyking`,注意替换域名) - 其他菜单属性按需配置。 步骤三:测试 配置完成后,用户登录JeecgBoot后点击菜单项,应该可以直接进入SurveyKing而不需要再登录。 注意: 1. 如果SurveyKing本身需要独立登录,那么还需要考虑如何实现单点登录(SSO)。但根据用户描述,SurveyKing的在线演示地址是公开的,可能不需要登录(或者允许匿名访问)。如果确实需要独立登录,可能需要更复杂的集成(如OAuth2.0)。 2. 如果使用反向代理后,页面内的资源路径错误,可能需要调整SurveyKing的静态资源路径,或者使用Nginx的sub_filter模块替换资源中的路径。 替代方案:如果不想使用Nginx,也可以考虑在JeecgBoot中通过Controller进行代理转发,但这样会增加JeecgBoot的负担,不如Nginx高效。 总结: 通过反向代理将SurveyKing的地址代理到与JeecgBoot同域下,然后在菜单中配置代理后的地址,即可解决跨域和会话冲突问题。 §§相关问题§§ 1. 如何在Nginx中配置反向代理并解决Cookie跨域问题? 2. 如何在JeecgBoot中配置外部链接菜单? 3. 如何实现JeecgBoot与SurveyKing的单点登录集成? </think> 将 SurveyKing 集成到 JeecgBoot 菜单中,需通过以下步骤配置(含代码示例): --- ### 一、在 JeecgBoot添加外部链接菜单 #### 1. 修改菜单配置文件 在 `src/main/resources/jeecg/sys-menu.yml` 添加外部链接配置: ```yaml - name: 问卷系统 path: /surveyking component: IFrame redirect: '' meta: title: 问卷系统 icon: link internalOrExternal: true # 关键标记:外部链接 url: https://s.surveyking.cn/ ``` #### 2. 配置路由守卫(解决登录页循环) 在 `src/router/index.js` 添加路由处理逻辑: ```javascript // 添加路由守卫 router.beforeEach((to, from, next) => { if (to.meta.internalOrExternal) { // 外部链接直接加载iframe window.open(to.meta.url, '_blank') next(false) // 阻止vue-router跳转 } else { next() // 正常内部路由 } }) ``` --- ### 二、反向代理配置(解决跨域问题) #### 1. Nginx 配置(推荐) ```nginx location /surveyking/ { proxy_pass https://s.surveyking.cn/; proxy_set_header Host s.surveyking.cn; proxy_cookie_domain s.surveyking.cn $host; # 统一Cookie域 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 关键:解除iframe嵌入限制 proxy_hide_header X-Frame-Options; add_header Content-Security-Policy "frame-ancestors 'self' yourdomain.com;"; } ``` #### 2. Spring Boot 代理配置(备选) 在 `application.yml` 添加: ```yaml jeecg: shiro: exclude-urls: /surveyking/** # 跳过权限验证 zuul: routes: surveyking: path: /surveyking/** url: https://s.surveyking.cn sensitive-headers: Cookie,Set-Cookie # 传递认证头 ``` --- ### 三、单点登录集成(可选) 若需打通登录态,在 JeecgBoot 登录后添加 Token 传递: ```java // 在登录成功处理器中添加 @RequestMapping("/login") public void loginSuccess(HttpServletRequest request) { String token = JwtUtil.sign(userInfo); // 生成JWT String surveyUrl = "https://s.surveyking.cn?token=" + token; request.getSession().setAttribute("SURVEYKING_URL", surveyUrl); } ``` 前端修改菜单链接为动态获取: ```vue <template> <a :href="surveykingUrl" target="_blank">问卷系统</a> </template> <script> export default { computed: { surveykingUrl() { return this.$store.state.user.surveykingUrl // 从Vuex获取动态URL } } } </script> ``` --- ### 四、注意事项 1. **安全策略调整** - 禁用 SurveyKing 的 `X-Frame-Options`(若自建部署)[^3] - 在 `application.properties` 添加: ```properties server.servlet.session.cookie.same-site=none server.servlet.session.cookie.secure=true ``` 2. **菜单权限控制** 在 JeecgBoot 角色管理中对「问卷系统」菜单授权: ```sql INSERT INTO sys_permission (id, name, url) VALUES ('surveyking_menu', '问卷系统', '/surveyking'); ``` 3. **部署验证** - 访问 `https://your-domain.com/surveyking` 应显示 SurveyKing 界面 - 检查浏览器控制台确保无 `Refused to display in a frame` 错误 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值