router.js 4.41 KB
/*
 * @Date: 2022-05-26 13:57:28
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-09-08 15:52:35
 * @FilePath: /data-table/src/router.js
 * @Description: 文件描述
 */
import { createRouter, createWebHashHistory } from 'vue-router';
import RootRoute from './route.js';
import asyncRoutesArr from "./mock/routes"
import generateRoutes from './utils/generateRoute'
import { showConfirmDialog, Loading } from "vant";
import Cookies from 'js-cookie';
import { styleColor } from "@/constant.js";
import { getCycleListAPI } from '@/api/cycle';

// TAG: 路由配置表
/**
 * 把项目独有的路由配置到相应的路径,默认路由文件只放公用部分
 * 但是 vue 文件内容还是要事先准备好
 */
const modules = import.meta.globEager('@/router/routes/modules/**/*.js'); // Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块
const routeModuleList = [];

Object.keys(modules).forEach((key) => {
  const mod = modules[key].default || {};
  const modList = Array.isArray(mod) ? [...mod] : [mod];
  routeModuleList.push(...modList);
});

// 创建路由实例并传递 `routes` 配置
const router = createRouter({
  history: createWebHashHistory('/index.html'),
  routes: [...RootRoute, ...routeModuleList]
});

// TAG: 动态生成路由
/**
 * generateRoute 负责把后台返回数据拼接成项目需要的路由结构,动态添加到路由表里面
 */
/**
 * 检查是否需要周期选择
 * @param {Object} to 目标路由
 * @returns {Promise<boolean>} 是否需要周期选择
 */
const checkCycleSelection = async (to) => {
  // 如果已经在周期选择页面,不需要再检查
  if (to.path === '/cycle-selection') {
    return false;
  }

  // 如果没有表单代码,不需要周期选择
  if (!to.query.code) {
    return false;
  }

  // 如果用户已经选择过周期,不需要再选择
  if (to.query.cycle_selected === '1') {
    return false;
  }

  // 如果是预览模式,不需要周期选择
  if (to.query.model === 'preview') {
    return false;
  }

  try {
    const { data } = await getCycleListAPI({ form_code: to.query.code });
    // 如果需要周期选择且有周期列表
    return data.is_cycle && data.cycle_list && data.cycle_list.length > 0;
  } catch (error) {
    console.error('检查周期选择失败:', error);
    return false;
  }
};

router.beforeEach(async (to, from, next) => {
  // 使用404为中转页面,避免动态路由没有渲染出来,控制台报警告问题
  if (to.path == '/404' && to.redirectedFrom != undefined) {
    // 模拟异步操作
    setTimeout(() => {
      if (!asyncRoutesArr.length) return; // 没有动态路由避免报错
      const arr = generateRoutes(asyncRoutesArr); // 在路由守卫处生成,避免有子路由时刷新白屏问题。
      arr.forEach(item => {
        router.addRoute(item) // 新增路由
      })
      // 重写被404覆盖路由信息
      next({ ...to.redirectedFrom, replace: true });
    }, 1000);
  } else {
    // 检查是否需要周期选择
    const needsCycleSelection = await checkCycleSelection(to);
    if (needsCycleSelection) {
      // 保存目标路由到sessionStorage
      sessionStorage.setItem('cycle_target_route', JSON.stringify({
        path: to.path,
        query: to.query,
        params: to.params
      }));
      // 跳转到周期选择页面
      next({
        path: '/cycle-selection',
        query: { code: to.query.code }
      });
      return;
    }

    if (to.query.page_type === 'add' || to.query.page_type === undefined) { // 表单为新增状态, 检查是否有未完成的表单信息
      const existingCookie = Cookies.get(to.query.code);
      if (existingCookie && to.query.force_back !== '1') {
        // TAG: 只能在进入路由之前判断,不然很多组件数据不渲染
        showConfirmDialog({
          title: '温馨提示',
          message: '您还未完成的表单,是否继续?',
          confirmButtonColor: styleColor.baseColor,
          cancelButtonText: '删除',
          closeOnPopstate: false,
        })
          .then(() => { // 通过后把数据绑定上去
            next();
          })
          .catch(() => { // 删除cookie
            Cookies.remove(to.query.code);
            next();
          });
      } else {
        next();
      }
    } else {
      next()
    }
  }
})

router.afterEach(() => {
  // console.warn(to);
  // console.warn(wx);
  // share(to)
})

export default router;