fix 登录页和home页路由调整
This commit is contained in:
parent
862661c426
commit
f25f506ca8
@ -98,42 +98,46 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
if (to.meta.title) NProgress.start()
|
if (to.meta.title) NProgress.start()
|
||||||
const storesUseUserInfo = useUserInfo(pinia)
|
const storesUseUserInfo = useUserInfo(pinia)
|
||||||
const token = storesUseUserInfo.getToken()
|
const token = storesUseUserInfo.getToken()
|
||||||
if (to.meta.isPublic && !token) {
|
|
||||||
|
// 如果是公共页面,直接通过,不需要检查token和路由列表
|
||||||
|
if (to.meta.isPublic) {
|
||||||
next()
|
next()
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
next(`/login?redirect=${to.path}¶ms=${JSON.stringify(to.query ? to.query : to.params)}`)
|
||||||
|
storesUseUserInfo.removeTokenInfo()
|
||||||
|
Session.clear()
|
||||||
|
NProgress.done()
|
||||||
|
} else if (token && to.path === '/login') {
|
||||||
|
console.log('🔄 [路由守卫] 已登录用户访问登录页面,重定向到系统入口页面')
|
||||||
|
next('/system-entrance')
|
||||||
|
NProgress.done()
|
||||||
} else {
|
} else {
|
||||||
if (!token) {
|
const storesRoute = useRoute(pinia)
|
||||||
next(`/login?redirect=${to.path}¶ms=${JSON.stringify(to.query ? to.query : to.params)}`)
|
storesRoute.setRouteTo({ to: { path: to.path, params: JSON.stringify(to.query ? to.query : to.params) } })
|
||||||
storesUseUserInfo.removeTokenInfo()
|
const storesRoutesList = useRoutesList(pinia)
|
||||||
Session.clear()
|
const { routesList } = storeToRefs(storesRoutesList)
|
||||||
NProgress.done()
|
if (routesList.value.length === 0) {
|
||||||
} else if (token && to.path === '/login') {
|
if (isRequestRoutes) {
|
||||||
next('/')
|
// 后端控制路由:路由数据初始化,防止刷新时丢失
|
||||||
NProgress.done()
|
const isNoPower = await initBackEndControlRoutes()
|
||||||
} else {
|
if (isNoPower) {
|
||||||
const storesRoute = useRoute(pinia)
|
ElMessage.warning('抱歉,您没有分配权限,请联系管理员')
|
||||||
storesRoute.setRouteTo({ to: { path: to.path, params: JSON.stringify(to.query ? to.query : to.params) } })
|
storesUseUserInfo.removeTokenInfo()
|
||||||
const storesRoutesList = useRoutesList(pinia)
|
Session.clear()
|
||||||
const { routesList } = storeToRefs(storesRoutesList)
|
|
||||||
if (routesList.value.length === 0) {
|
|
||||||
if (isRequestRoutes) {
|
|
||||||
// 后端控制路由:路由数据初始化,防止刷新时丢失
|
|
||||||
const isNoPower = await initBackEndControlRoutes()
|
|
||||||
if (isNoPower) {
|
|
||||||
ElMessage.warning('抱歉,您没有分配权限,请联系管理员')
|
|
||||||
storesUseUserInfo.removeTokenInfo()
|
|
||||||
Session.clear()
|
|
||||||
}
|
|
||||||
// 解决刷新时,一直跳 404 页面问题,关联问题 No match found for location with path 'xxx'
|
|
||||||
// to.query 防止页面刷新时,普通路由带参数时,参数丢失。动态路由(xxx/:id/:name")isDynamic 无需处理
|
|
||||||
next({ path: to.path, query: to.query })
|
|
||||||
} else {
|
|
||||||
await initFrontEndControlRoutes()
|
|
||||||
next({ path: to.path, query: to.query })
|
|
||||||
}
|
}
|
||||||
|
// 解决刷新时,一直跳 404 页面问题,关联问题 No match found for location with path 'xxx'
|
||||||
|
// to.query 防止页面刷新时,普通路由带参数时,参数丢失。动态路由(xxx/:id/:name")isDynamic 无需处理
|
||||||
|
next({ path: to.path, query: to.query })
|
||||||
} else {
|
} else {
|
||||||
next()
|
await initFrontEndControlRoutes()
|
||||||
|
next({ path: to.path, query: to.query })
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -143,6 +143,15 @@ export const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
isPublic: true,
|
isPublic: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/system-entrance',
|
||||||
|
name: 'system-entrance',
|
||||||
|
component: () => import('/@/views/system-entrance/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '系统入口',
|
||||||
|
isPublic: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 提示:写在这里的为全屏界面,不建议写在这里
|
* 提示:写在这里的为全屏界面,不建议写在这里
|
||||||
* 请写在 `dynamicRoutes` 路由数组中
|
* 请写在 `dynamicRoutes` 路由数组中
|
||||||
|
@ -217,6 +217,10 @@ const onSignIn = async () => {
|
|||||||
}
|
}
|
||||||
// 登录成功后的跳转
|
// 登录成功后的跳转
|
||||||
const signInSuccess = (isNoPower: boolean | undefined) => {
|
const signInSuccess = (isNoPower: boolean | undefined) => {
|
||||||
|
console.log('🚀 [登录成功] signInSuccess 被调用')
|
||||||
|
console.log('🚀 [登录成功] isNoPower:', isNoPower)
|
||||||
|
console.log('🚀 [登录成功] route.query:', route.query)
|
||||||
|
|
||||||
if (isNoPower) {
|
if (isNoPower) {
|
||||||
ElMessage.warning('抱歉,您没有分配权限,请联系管理员')
|
ElMessage.warning('抱歉,您没有分配权限,请联系管理员')
|
||||||
useUserInfo().removeTokenInfo()
|
useUserInfo().removeTokenInfo()
|
||||||
@ -224,15 +228,17 @@ const signInSuccess = (isNoPower: boolean | undefined) => {
|
|||||||
} else {
|
} else {
|
||||||
// 初始化登录成功时间问候语
|
// 初始化登录成功时间问候语
|
||||||
let currentTimeInfo = currentTime.value
|
let currentTimeInfo = currentTime.value
|
||||||
// 登录成功,跳到转首页
|
// 登录成功,跳到系统入口页面
|
||||||
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
||||||
if (route.query?.redirect) {
|
if (route.query?.redirect && route.query.redirect !== '/') {
|
||||||
|
console.log('🚀 [登录成功] 有redirect参数且不是首页,跳转到:', route.query.redirect)
|
||||||
router.push({
|
router.push({
|
||||||
path: <string>route.query?.redirect,
|
path: <string>route.query?.redirect,
|
||||||
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
router.push('/')
|
console.log('🚀 [登录成功] 无redirect参数或redirect是首页,跳转到系统入口页面: /system-entrance')
|
||||||
|
router.push('/system-entrance')
|
||||||
}
|
}
|
||||||
// 登录成功提示
|
// 登录成功提示
|
||||||
const signInText = t('message.signInText')
|
const signInText = t('message.signInText')
|
||||||
|
@ -135,15 +135,15 @@ const signInSuccess = (isNoPower: boolean | undefined) => {
|
|||||||
} else {
|
} else {
|
||||||
// 初始化登录成功时间问候语
|
// 初始化登录成功时间问候语
|
||||||
let currentTimeInfo = currentTime.value
|
let currentTimeInfo = currentTime.value
|
||||||
// 登录成功,跳到转首页
|
// 登录成功,跳到系统入口页面
|
||||||
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
||||||
if (route.query?.redirect) {
|
if (route.query?.redirect && route.query.redirect !== '/') {
|
||||||
router.push({
|
router.push({
|
||||||
path: <string>route.query?.redirect,
|
path: <string>route.query?.redirect,
|
||||||
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
router.push('/')
|
router.push('/system-entrance')
|
||||||
}
|
}
|
||||||
// 登录成功提示
|
// 登录成功提示
|
||||||
const signInText = t('message.signInText')
|
const signInText = t('message.signInText')
|
||||||
|
@ -138,15 +138,15 @@ const signInSuccess = (isNoPower: boolean | undefined) => {
|
|||||||
} else {
|
} else {
|
||||||
// 初始化登录成功时间问候语
|
// 初始化登录成功时间问候语
|
||||||
let currentTimeInfo = currentTime.value
|
let currentTimeInfo = currentTime.value
|
||||||
// 登录成功,跳到转首页
|
// 登录成功,跳到系统入口页面
|
||||||
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
||||||
if (route.query?.redirect) {
|
if (route.query?.redirect && route.query.redirect !== '/') {
|
||||||
router.push({
|
router.push({
|
||||||
path: <string>route.query?.redirect,
|
path: <string>route.query?.redirect,
|
||||||
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
router.push('/')
|
router.push('/system-entrance')
|
||||||
}
|
}
|
||||||
// 登录成功提示
|
// 登录成功提示
|
||||||
const signInText = t('message.signInText')
|
const signInText = t('message.signInText')
|
||||||
|
@ -114,20 +114,21 @@ const onSignIn = async () => {
|
|||||||
// 登录成功后的跳转
|
// 登录成功后的跳转
|
||||||
const signInSuccess = (isNoPower: boolean | undefined) => {
|
const signInSuccess = (isNoPower: boolean | undefined) => {
|
||||||
if (isNoPower) {
|
if (isNoPower) {
|
||||||
ElMessage.warning('抱歉,您没有登录权限')
|
ElMessage.warning('抱歉,您没有分配权限,请联系管理员')
|
||||||
|
useUserInfo().removeTokenInfo()
|
||||||
Session.clear()
|
Session.clear()
|
||||||
} else {
|
} else {
|
||||||
// 初始化登录成功时间问候语
|
// 初始化登录成功时间问候语
|
||||||
let currentTimeInfo = currentTime.value
|
let currentTimeInfo = currentTime.value
|
||||||
// 登录成功,跳到转首页
|
// 登录成功,跳到系统入口页面
|
||||||
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
||||||
if (route.query?.redirect) {
|
if (route.query?.redirect && route.query.redirect !== '/') {
|
||||||
router.push({
|
router.push({
|
||||||
path: <string>route.query?.redirect,
|
path: <string>route.query?.redirect,
|
||||||
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
router.push('/')
|
router.push('/system-entrance')
|
||||||
}
|
}
|
||||||
// 登录成功提示
|
// 登录成功提示
|
||||||
const signInText = t('message.signInText')
|
const signInText = t('message.signInText')
|
||||||
|
481
src/views/system-entrance/index.vue
Normal file
481
src/views/system-entrance/index.vue
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
<template>
|
||||||
|
<div class="system-entrance-page">
|
||||||
|
<!-- Logo区域 -->
|
||||||
|
<div class="logo-section">
|
||||||
|
<div class="logo-container">
|
||||||
|
<img src="/@/assets/logo-mini.png" alt="WuXi Biologics" class="company-logo" />
|
||||||
|
<div class="logo-text">
|
||||||
|
<span class="company-name">WuXi Biologics</span>
|
||||||
|
<span class="company-subtitle">Global Solution Provider</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 欢迎标题 -->
|
||||||
|
<div class="welcome-title">
|
||||||
|
<h1>欢迎来到系统入口</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 功能模块卡片 -->
|
||||||
|
<div class="modules-grid">
|
||||||
|
<!-- 调试信息 -->
|
||||||
|
<div v-if="state.columnsAsideList.length === 0" class="debug-info">
|
||||||
|
<div v-if="!storesUserInfo.getToken()">
|
||||||
|
<p>👤 您尚未登录</p>
|
||||||
|
<p>请先<router-link to="/login" class="login-link">点击这里登录</router-link>,然后再访问系统功能</p>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="state.isInitializing">
|
||||||
|
<p>🔄 正在初始化系统路由数据...</p>
|
||||||
|
<p>请稍候,系统正在准备菜单数据</p>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<p>⚡ 系统需要初始化路由数据</p>
|
||||||
|
<p>请<router-link to="/" class="login-link">点击这里进入主页</router-link>完成系统初始化,然后返回此页面</p>
|
||||||
|
<p style="margin-top: 15px; font-size: 12px; color: #666;">
|
||||||
|
或者刷新页面重新尝试加载路由数据
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 动态路由模块 -->
|
||||||
|
<div
|
||||||
|
v-for="(v, k) in state.columnsAsideList"
|
||||||
|
:key="`route-${k}`"
|
||||||
|
class="module-card"
|
||||||
|
@click="onColumnsAsideMenuClick(v)"
|
||||||
|
>
|
||||||
|
<div class="module-icon">
|
||||||
|
<svg class="icon-svg" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="currentColor" :d="getModuleIcon(k)"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="module-title">{{ getModuleTitle(v) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="SystemEntrancePage">
|
||||||
|
import { reactive, onMounted, computed, watch } from 'vue'
|
||||||
|
import { useRoute, useRouter, RouteRecordRaw } from 'vue-router'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { useRoutesList } from '/@/stores/routesList'
|
||||||
|
import { useThemeConfig } from '/@/stores/themeConfig'
|
||||||
|
import { useUserInfo } from '/@/stores/userInfo'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import mittBus from '/@/utils/mitt'
|
||||||
|
import { treeToList, listToTree, filterList } from '/@/utils/tree'
|
||||||
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
import { initBackEndControlRoutes } from '/@/router/backEnd'
|
||||||
|
import { initFrontEndControlRoutes } from '/@/router/frontEnd'
|
||||||
|
import { NextLoading } from '/@/utils/loading'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const stores = useRoutesList()
|
||||||
|
const storesThemeConfig = useThemeConfig()
|
||||||
|
const storesUserInfo = useUserInfo()
|
||||||
|
const { routesList } = storeToRefs(stores)
|
||||||
|
const { themeConfig } = storeToRefs(storesThemeConfig)
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
columnsAsideList: [] as RouteItem[],
|
||||||
|
isInitializing: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取模块图标
|
||||||
|
const getModuleIcon = (index: number): string => {
|
||||||
|
// 预定义的图标数组
|
||||||
|
const iconPaths = [
|
||||||
|
'M512 85.333333c235.648 0 426.666667 191.018667 426.666667 426.666667s-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333z m0 64C311.168 149.333333 149.333333 311.168 149.333333 512s161.834667 362.666667 362.666667 362.666667 362.666667-161.834667 362.666667-362.666667S712.832 149.333333 512 149.333333z m-32 149.333334v277.333333l170.666667 170.666667-45.254667 45.254666L469.333333 656V298.666667h74.666667z',
|
||||||
|
'M469.333333 170.666667c23.564267 0 42.666667 19.102933 42.666667 42.666666v128c0 23.564267-19.102933 42.666667-42.666667 42.666667s-42.666667-19.102933-42.666667-42.666667V213.333333c0-23.564267 19.102933-42.666667 42.666667-42.666667z m0 469.333333c23.564267 0 42.666667 19.102933 42.666667 42.666667v128c0 23.564267-19.102933 42.666667-42.666667 42.666667s-42.666667-19.102933-42.666667-42.666667V682.666667c0-23.564267 19.102933-42.666667 42.666667-42.666667z',
|
||||||
|
'M170.666667 85.333333h682.666666c47.128533 0 85.333333 38.204800 85.333334 85.333334v682.666666c0 47.128533-38.204800 85.333333-85.333334 85.333334H170.666667c-47.128533 0-85.333333-38.204800-85.333334-85.333334V170.666667c0-47.128533 38.204800-85.333333 85.333334-85.333334z m0 64c-11.776 0-21.333333 9.557333-21.333334 21.333334v682.666666c0 11.776 9.557333 21.333333 21.333334 21.333334h682.666666c11.776 0 21.333333-9.557333 21.333334-21.333334V170.666667c0-11.776-9.557333-21.333333-21.333334-21.333334H170.666667z',
|
||||||
|
'M512 618.666667c58.88 0 106.666667-47.786667 106.666667-106.666667s-47.786667-106.666667-106.666667-106.666667-106.666667 47.786667-106.666667 106.666667 47.786667 106.666667 106.666667 106.666667z m0 64c-94.293333 0-170.666667-76.373333-170.666667-170.666667s76.373333-170.666667 170.666667-170.666667 170.666667 76.373333 170.666667 170.666667-76.373333 170.666667-170.666667 170.666667z'
|
||||||
|
]
|
||||||
|
return iconPaths[index % iconPaths.length]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取模块标题
|
||||||
|
const getModuleTitle = (moduleItem: RouteItem): string => {
|
||||||
|
return moduleItem.meta?.title || '未命名模块'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路由过滤递归函数(完全按照 columnsAside.vue)
|
||||||
|
const filterRoutesFun = <T extends RouteItem>(arr: T[]): T[] => {
|
||||||
|
return arr
|
||||||
|
.filter((item: T) => !item.meta?.isHide)
|
||||||
|
.map((item: T) => {
|
||||||
|
item = Object.assign({}, item)
|
||||||
|
if (item.children) item.children = filterRoutesFun(item.children)
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置/过滤路由(完全按照 columnsAside.vue)
|
||||||
|
const setFilterRoutes = () => {
|
||||||
|
state.columnsAsideList = filterRoutesFun(routesList.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主动初始化路由数据
|
||||||
|
const initializeRoutes = async () => {
|
||||||
|
if (state.isInitializing) return
|
||||||
|
|
||||||
|
const token = storesUserInfo.getToken()
|
||||||
|
if (!token) return
|
||||||
|
|
||||||
|
state.isInitializing = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (themeConfig.value.isRequestRoutes) {
|
||||||
|
await initBackEndControlRoutes()
|
||||||
|
} else {
|
||||||
|
await initFrontEndControlRoutes()
|
||||||
|
}
|
||||||
|
// 确保停止加载动画
|
||||||
|
NextLoading.done()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('路由初始化失败:', error)
|
||||||
|
// 即使出错也要停止加载动画
|
||||||
|
NextLoading.done()
|
||||||
|
} finally {
|
||||||
|
state.isInitializing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单高亮点击事件(完全按照 columnsAside.vue 的方式)
|
||||||
|
const onColumnsAsideMenuClick = async (v: RouteItem) => {
|
||||||
|
let { path, redirect } = v
|
||||||
|
|
||||||
|
if (redirect) {
|
||||||
|
if (route.path.startsWith(redirect)) {
|
||||||
|
mittBus.emit('setSendColumnsChildren', setSendChildren(redirect))
|
||||||
|
} else {
|
||||||
|
router.push(redirect)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (v.children && v.children.length > 0) {
|
||||||
|
const resData: MittMenu = setSendChildren(path)
|
||||||
|
if (Object.keys(resData).length <= 0) return false
|
||||||
|
mittBus.emit('setSendColumnsChildren', resData)
|
||||||
|
router.push('/')
|
||||||
|
themeConfig.value.isCollapse = false
|
||||||
|
} else {
|
||||||
|
router.push(path)
|
||||||
|
themeConfig.value.isCollapse = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 一个路由设置自动收起菜单(按照 columnsAside.vue 的逻辑)
|
||||||
|
!v.children || v.children.length < 1 ? (themeConfig.value.isCollapse = true) : (themeConfig.value.isCollapse = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 传送当前子级数据到菜单中(完全按照 columnsAside.vue 的方式)
|
||||||
|
const setSendChildren = (path: string) => {
|
||||||
|
const currentPathSplit = path.split('/')
|
||||||
|
let rootPath = `/${currentPathSplit[1]}`
|
||||||
|
|
||||||
|
// 判断是否能够找到根节点
|
||||||
|
if (!state.columnsAsideList.find((v) => v.path === rootPath)) {
|
||||||
|
// 不存在则使用顶级的分类
|
||||||
|
let routeTree = listToTree(
|
||||||
|
filterList(treeToList(cloneDeep(state.columnsAsideList)), path, {
|
||||||
|
filterWhere: (item: any, filterword: string) => {
|
||||||
|
return item.path?.toLocaleLowerCase() === filterword
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// 找到根节点则使用根节点
|
||||||
|
if (routeTree.length > 0 && routeTree[0]?.path) {
|
||||||
|
rootPath = routeTree[0].path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentData: MittMenu = { children: [] }
|
||||||
|
state.columnsAsideList.map((v: RouteItem, k: number) => {
|
||||||
|
if (v.path === rootPath) {
|
||||||
|
v['k'] = k
|
||||||
|
currentData['item'] = { ...v }
|
||||||
|
currentData['children'] = [{ ...v }]
|
||||||
|
if (v.children) currentData['children'] = v.children
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return currentData
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面加载时(完全按照 columnsAside.vue)
|
||||||
|
onMounted(() => {
|
||||||
|
setFilterRoutes()
|
||||||
|
|
||||||
|
// 如果路由数据为空且用户已登录,主动初始化
|
||||||
|
if (routesList.value.length === 0 && storesUserInfo.getToken()) {
|
||||||
|
initializeRoutes()
|
||||||
|
} else {
|
||||||
|
// 如果不需要初始化,也要确保停止可能存在的加载动画
|
||||||
|
NextLoading.done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听路由列表变化(关键:确保路由数据更新时重新过滤)
|
||||||
|
watch(
|
||||||
|
() => routesList.value,
|
||||||
|
() => {
|
||||||
|
setFilterRoutes()
|
||||||
|
// 当路由数据加载完成时,确保停止加载动画
|
||||||
|
if (routesList.value.length > 0) {
|
||||||
|
NextLoading.done()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: false }
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.system-entrance-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
padding: 40px 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.logo-section {
|
||||||
|
margin-bottom: 60px;
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
|
||||||
|
.company-logo {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.company-name {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-subtitle {
|
||||||
|
font-size: 16px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-title {
|
||||||
|
margin-bottom: 80px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 42px;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 300;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
text-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modules-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 50px;
|
||||||
|
max-width: 900px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.debug-info {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-link {
|
||||||
|
color: #667eea;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #5a6fd8;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-card {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 50px 40px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
min-height: 240px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-15px) scale(1.02);
|
||||||
|
box-shadow: 0 25px 60px rgba(0, 0, 0, 0.25);
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
|
||||||
|
.module-icon .icon-svg {
|
||||||
|
color: #667eea;
|
||||||
|
transform: scale(1.15) rotateY(10deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-title {
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-icon {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.icon-svg {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
color: #555;
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-title {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.4;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.modules-grid {
|
||||||
|
max-width: 600px;
|
||||||
|
gap: 40px;
|
||||||
|
|
||||||
|
.module-card {
|
||||||
|
padding: 40px 30px;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 30px 20px;
|
||||||
|
|
||||||
|
.logo-section {
|
||||||
|
margin-bottom: 50px;
|
||||||
|
|
||||||
|
.logo-container {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.company-logo {
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.company-name {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-title {
|
||||||
|
margin-bottom: 60px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modules-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 30px;
|
||||||
|
max-width: 400px;
|
||||||
|
|
||||||
|
.module-card {
|
||||||
|
padding: 35px 25px;
|
||||||
|
min-height: 180px;
|
||||||
|
|
||||||
|
.module-icon {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.icon-svg {
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-title {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
padding: 20px 15px;
|
||||||
|
|
||||||
|
.welcome-title h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modules-grid {
|
||||||
|
max-width: 320px;
|
||||||
|
|
||||||
|
.module-card {
|
||||||
|
padding: 30px 20px;
|
||||||
|
min-height: 160px;
|
||||||
|
|
||||||
|
.module-icon .icon-svg {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-title {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user