index.js 4.08 KB
/*
 * @Date: 2025-10-30 10:29:15
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-11-12 15:48:17
 * @FilePath: /stdj_h5/src/router/index.js
 * @Description: 文件描述
 */
import { createRouter, createWebHashHistory } from 'vue-router'
import { useLoadingStore } from '@/stores/loading.js'
import Cookies from 'js-cookie'

const routes = [
  {
    path: '/',
    name: 'Splash',
    component: () => import('../views/Splash.vue')
  },
  {
    path: '/home',
    name: 'Home',
    component: () => import('../views/Home.vue')
  },
  {
    path: '/masters',
    name: '三師七證',
    component: () => import('../views/Masters.vue')
  },
  {
    path: '/masters/:id',
    name: '三師七證详情',
    component: () => import('../views/MastersDetail.vue')
  },
  {
    path: '/yinlishi',
    name: '引礼师',
    component: () => import('../views/YinLiShi.vue')
  },
  {
    path: '/yinlishi/:id',
    name: '引礼师详情',
    component: () => import('../views/YinLiShiDetail.vue')
  },
  {
    path: '/news/:id',
    name: 'NewsDetail',
    component: () => import('../views/NewsDetail.vue')
  },
  {
    path: '/students',
    name: '戒子',
    component: () => import('../views/Students.vue')
  },
  {
    path: '/studentInfo',
    name: '戒子详情',
    component: () => import('../views/StudentInfo.vue')
  },
  {
    path: '/login',
    name: '登录',
    component: () => import('../views/Login.vue')
  },
  {
    path: '/jz_login',
    name: '登录-戒子',
    component: () => import('../views/LoginID.vue')
  },
  {
    path: '/volunteers',
    name: '义工',
    component: () => import('../views/Volunteers.vue')
  },
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: () => import('../views/NotFound.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory('/index.html'),
  routes,
  /**
   * 路由切换时的滚动行为
   * 说明:不使用平滑滚动,进入新页面时立即滚动到顶部,确保用户无感知的快速回到初始位置。
   */
  scrollBehavior(to, from, savedPosition) {
        if (savedPosition) {
            return savedPosition
        }
        return { left: 0, top: 0 }
  }
})

// 路由守卫
router.beforeEach((to, from, next) => {
    // 设置页面标题
    if (to.meta.title) {
        document.title = to.meta.title
    }

    // 开启全局loading用于覆盖路由懒加载白屏
    /**
     * 开启路由级加载指示
     * @description 进入任意页面前先展示全局loading,避免异步组件/资源加载期间出现白屏
     */
    try {
        const loading = useLoadingStore()
        loading.start()
    } catch (e) {
        // 兜底:忽略异常,保证路由流程继续
        void e
    }

    /**
     * 访问控制:除首页('/')与登录页外,其余页面均需登录
     */
    const token_cookie = Cookies.get('token-stdj')
    const is_login = token_cookie !== undefined

    // 白名单:无需登录校验的路径
    const white_list = ['/', '/jz_login']
    const need_auth = !white_list.includes(to.path)

    if (need_auth && !is_login) {
        // 在重定向前关闭或重置上一跳的loading,避免计数残留
        try {
            const loading = useLoadingStore()
            loading.reset()
        } catch (e) {
            void e
        }
        next({ name: '登录-戒子', query: { redirect: to.fullPath } })
        return
    }

    next()
})

// 路由解析完成(异步组件与守卫均已完成)后关闭loading
/**
 * 关闭路由级加载指示
 * @description 在组件解析完成后关闭一次全局loading,剩余由接口加载计数继续控制
 */
router.beforeResolve(() => {
    try {
        const loading = useLoadingStore()
        loading.end()
    } catch (e) {
        // 兜底:忽略异常,保证路由流程继续
        void e
    }
})

// 路由错误时重置loading,避免蒙版残留
router.onError(() => {
    try {
        const loading = useLoadingStore()
        loading.reset()
    } catch (e) {
        // 兜底:忽略异常,保证路由流程继续
        void e
    }
})

export default router