router.js 8.21 KB
/*
 * @Date: 2022-05-26 13:57:28
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-09-25 18:29:36
 * @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 { Loading } from "vant";
import Cookies from 'js-cookie';
import { showUnfinishedFormDialog, resetDialogState } from '@/utils/dialogControl.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 = (to) => {
  // 如果已经在周期选择页面,不需要再检查
  if (to.path === '/cycle-selection') {
    return Promise.resolve(false);
  }

  // 只有在page_type=add或者没有page_type参数时才进行周期判断
  if (to.query.page_type && to.query.page_type !== 'add') {
    return Promise.resolve(false);
  }

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

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

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

  // 如果URL中包含x_cycle参数,跳过周期检查
  if (to.query.x_cycle) {
    return Promise.resolve(false);
  }

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

router.beforeEach((to, from, next) => {
  // 当访问不同的表单时(code参数不同),重置弹框状态
  if (to.query.code && from.query.code && to.query.code !== from.query.code) {
    resetDialogState();
  }

  // 使用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 {
    // 先进行同步检查,避免异步问题
    // 如果已经在周期选择页面,直接通过
    if (to.path === '/cycle-selection') {
      next();
      return;
    }

    // 如果用户已经选择过周期,直接通过
    if (to.query.cycle_selected === '1') {
      next();
      return;
    }

    // 如果不是新增状态或预览模式,直接通过
    if ((to.query.page_type && to.query.page_type !== 'add') || to.query.model === 'preview') {
      next();
      return;
    }

    // 如果URL中包含x_cycle参数,跳过周期检查
    if (to.query.x_cycle) {
      next();
      return;
    }

    // 如果没有表单代码,直接通过
    if (!to.query.code) {
      next();
      return;
    }

    // 检查是否从授权页面返回,如果是首次访问且可能需要授权,则跳过周期检查
    const isFromAuth = from.path === '/auth';
    const skipCycleCheck = sessionStorage.getItem('skip_cycle_check_for_auth');

    // 如果不是从授权页面返回,且设置了跳过标识,则先清除标识并跳过周期检查
    if (!isFromAuth && skipCycleCheck === 'true') {
      sessionStorage.removeItem('skip_cycle_check_for_auth');
      // 直接执行表单检查逻辑,跳过周期检查
      if (to.query.page_type === 'add' || to.query.page_type === undefined) {
        const existingCookie = Cookies.get(to.query.code);
        // 在x_project功能下屏蔽未完成表单功能
        if (existingCookie && to.query.force_back !== '1' && !to.query.x_project) {
          showUnfinishedFormDialog(
            () => {
              // 用户选择继续,跳转到目标页面
              next();
            },
            () => {
              // 用户选择删除,删除cookie并跳转
              Cookies.remove(to.query.code);
              next();
            },
            to.query.code
          );
        } else {
          next();
        }
      } else {
        next();
      }
      return;
    }

    // 异步检查周期选择
    checkCycleSelection(to).then(needsCycleSelection => {
      if (needsCycleSelection) {
        // 保存目标路由到sessionStorage
        const targetRoute = {
          path: to.path,
          query: to.query,
          params: to.params
        };

        // 调试信息:检查保存的路由对象
        console.log('保存到sessionStorage的目标路由:', targetRoute);
        console.log('目标路由查询参数:', targetRoute.query);
        console.log('目标路由code参数:', targetRoute.query.code);

        sessionStorage.setItem('cycle_target_route', JSON.stringify(targetRoute));
        // 直接跳转,不使用next
        router.push({
          path: '/cycle-selection',
          query: to.query // 保留所有原始查询参数
        });
        return; // 有周期选择需求时,直接返回,不执行后续表单检查
      }

      // 只有在不需要周期选择时,才执行表单检查逻辑
      if (to.query.page_type === 'add' || to.query.page_type === undefined) {
        const existingCookie = Cookies.get(to.query.code);
        // 在x_project功能下屏蔽未完成表单功能
        if (existingCookie && to.query.force_back !== '1' && !to.query.x_project) {
          showUnfinishedFormDialog(
            () => {
              // 用户选择继续,跳转到目标页面
              next();
            },
            () => {
              // 用户选择删除,删除cookie并跳转
              Cookies.remove(to.query.code);
              next();
            },
            to.query.code
          );
        } else {
          next();
        }
      } else {
        next();
      }
    }).catch(error => {
      console.error('周期选择检查失败:', error);
      // 检查失败时,继续执行表单检查逻辑
      if (to.query.page_type === 'add' || to.query.page_type === undefined) {
        const existingCookie = Cookies.get(to.query.code);
        // 在x_project功能下屏蔽未完成表单功能
        if (existingCookie && to.query.force_back !== '1' && !to.query.x_project) {
          showConfirmDialog({
            title: '温馨提示',
            message: '您还未完成的表单,是否继续?',
            confirmButtonColor: styleColor.baseColor,
            cancelButtonText: '删除',
            closeOnPopstate: false,
          })
            .then(() => {
              next();
            })
            .catch(() => {
              Cookies.remove(to.query.code);
              next();
            });
        } else {
          next();
        }
      } else {
        next();
      }
    });
  }
})

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

export default router;