diff --git a/README.md b/README.md
index a6e6160..bacd184 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,68 @@
# resource-manage
## Project setup
+
```
npm install
```
### Compiles and hot-reloads for development
+
```
npm run serve
```
### Compiles and minifies for production
+
```
npm run build
```
### Lints and fixes files
+
```
npm run lint
```
### Customize configuration
+
See [Configuration Reference](https://cli.vuejs.org/config/).
+
+## 部分业务逻辑
+
+### 登录流程
+
+```mermaid
+graph TD;
+ A[前置路由守卫] --> B{ query.token 是否存在?}
+
+ %% TAPD 登录流程
+ B -->|是| C[清除本地 token]
+ C --> D[调用 fetchToken]
+ D --> E{获取 token 成功?}
+ E -->|是| F[保存 token 到 localStorage
重定向并移除 URL token 参数]
+ E -->|否| G[处理登录失败]
+
+ %% 无 token 流程
+ B -->|否| H{检查 Vuex 和 localStorage
是否有 token?}
+ H -->|都没有| I[显示 token 错误
中断导航]
+
+ %% 恢复 token 流程
+ H -->|localStorage 有 Vuex 没有| J[恢复 token 到 Vuex]
+ J --> L
+
+ %% 加载路由流程
+ H -->|Vuex 有| L{检查动态路由是否为空?}
+ L -->|是| M[获取路由资源]
+ M --> N[生成动态路由]
+ N --> O{是否为管理员?}
+ O -->|是| P[添加系统设置路由]
+ O -->|否| Q[继续导航]
+ P --> Q
+ L -->|否| Q
+
+ %% 登录失败处理
+ G --> R{是否不在白名单?}
+ R -->|是| S[跳转到登录失败页面
中断导航]
+ R -->|否| T[提示点击TAPD导航栏刷新
中断导航]
+```
diff --git a/src/index/router/index.js b/src/index/router/index.js
index ca0b22d..f9f4bd1 100644
--- a/src/index/router/index.js
+++ b/src/index/router/index.js
@@ -3,7 +3,7 @@ import VueRouter from "vue-router";
import store from "@/index/store";
import { generateIndexRouter } from "./generateIndexRouter";
import systemSettings from './systemSettings'
-// import { accessTokenError } from "@/index/utils/errorModal";
+import { accessTokenError } from "@/index/utils/errorModal";
// hack router push callback
const originalPush = VueRouter.prototype.push;
@@ -34,130 +34,86 @@ const router = new VueRouter({
let dynamicRoutes = [];
-router.beforeEach(async(to, from, next)=>{
- // 1. 从tapd进来, 重定向路由参数带token
- // if(to.query.token){
- // // 1.1 先删除本地存储
- // Vue.ls.remove('token')
- // // 1.2 设置token
- // const tmp_token = to.query.token
- // let formData = new FormData()
- // formData.append("tmp_token", tmp_token)
- // await store.dispatch('user/getToken', formData)
- // if(store.state.user.token){
- // // 1.2.1 能拿到正式token,保存token
- // Vue.ls.set('token',store.state.user.token)
- // // 跳转,去掉路由参数
- // next({ path: to.path })
- // }else{
- // // 1.2.2 拿不到token
- // // 1.2.2.1 判断是不是因为没有添加进白名单
- // if(store.state.user.loginFailed){
- // next({path: '/loginFailed'})
- // }else{
- // // 1.2.2.2 判断是否已弹提示
- // if(!Vue.prototype.$closeModalFun){
- // Vue.prototype.$closeModalFun = accessTokenError('获取token失败,请点击左边导航栏应用“资源管理”重试。')
- // }
- // next(false)
- // }
- // }
- // }else{
- // 2. 不是从tapd进来
- // 2.1 检查token
- // if(!store.state.user.token && !store.state.user.loginFailed){
- // const token = Vue.ls.get('token')
- // if(token){
- // store.commit('user/changeToken', token)
- // }else {
- // if(!Vue.prototype.$closeModalFun){
- // Vue.prototype.$closeModalFun = accessTokenError('获取token失败,请点击左边导航栏应用“资源管理”重试。')
- // }
- // // 拿不到token, 弹窗并停止
- // next(false)
- // }
- // }
- store.commit('user/changeToken', '123456')
- // 2.2 没有路由, 生成路由
- if ( store.state.user.token && dynamicRoutes.length === 0) {
- // 获取用户信息
- await store.dispatch('user/getUserInfo')
- store
- .dispatch("user/getRoutesResource")
- .then((routesResource) => {
- dynamicRoutes = generateIndexRouter(routesResource)
- router.addRoutes(dynamicRoutes)
- // 是管理员, 添加设置页面路由
- if(store.state.user.isAdmin){
- router.addRoutes([systemSettings]);
- }
- })
- .catch((err) => {
- Vue.prototype.$error("请求用户资源失败");
- console.log(err)
- next(false)
- })
+router.beforeEach(async (to, from, next) => {
+ const { token: queryToken } = to.query;
+ const userState = store.state.user;
+ // const storageToken = Vue.ls.get("token");
+ const storageToken = Vue.ls.get("token")||'123test'; // 离线状态测试用
+
+ // 1. 从 TAPD 入口进来, 更新token并重定向
+ if (queryToken) return handleTapdLogin(queryToken, to, next);
+
+ // 2. Vuex 和本地存储都没有 token,处理登录失败情况, 结束导航
+ if (!userState.token && !storageToken) return handleNoToken(next);
+
+ // 3. Vuex 没有 token,但 localStorage 有,恢复 token
+ if (!userState.token && storageToken) restoreToken(storageToken);
+
+ // 4. Vuex 有 token,但还没有动态路由,获取用户资源, 生成动态路由
+ if (userState.token && dynamicRoutes.length === 0) loadRoutes(userState.isAdmin, next);
+
+ // 5. 放行
+ next();
+});
+
+/** 处理从 TAPD 入口进来的情况 */
+async function handleTapdLogin(queryToken, to, next) {
+ Vue.ls.remove("token"); // 清除本地 token
+
+ if (await fetchToken(queryToken)) {
+ Vue.ls.set("token", store.state.user.token);
+ return next({ path: to.path, query: {} }); // 移除 URL 中的 token 参数
+ }
+
+ return handleLoginFailure(next);
+}
+
+/** 通过临时 token 获取正式 token */
+async function fetchToken(tmpToken) {
+ const formData = new FormData();
+ formData.append("tmp_token", tmpToken);
+ await store.dispatch("user/getToken", formData);
+ return Boolean(store.state.user.token);
+}
+
+/** 处理没有 token 的情况 */
+function handleNoToken(next) {
+ showTokenError();
+ next(false);
+}
+
+/** 从 localStorage 恢复 token */
+function restoreToken(token) {
+ store.commit("user/changeToken", token);
+}
+
+/** 生成并加载动态路由 */
+async function loadRoutes(isAdmin, next) {
+ try {
+ const routesResource = await store.dispatch("user/getRoutesResource");
+ dynamicRoutes = generateIndexRouter(routesResource);
+ router.addRoutes(dynamicRoutes);
+
+ if (isAdmin) {
+ router.addRoutes([systemSettings]);
}
- // 2.4 已有路由
- next()
- // }
+ } catch (err) {
+ Vue.prototype.$error("请求用户资源失败");
+ console.error(err);
+ next(false);
+ }
+}
+/** 处理登录失败情况 */
+function handleLoginFailure(next) {
+ return store.state.user.loginFailed ? next({ path: "/loginFailed" }) : showTokenError(next);
+}
- // if(!store.state.token){
- // // if(false){
- // const CURRENT_USER = localStorage.getItem('uid') || to.query["CURRENT-USER"];
- // // debugger
- // store.commit('saveUid', CURRENT_USER);
- // localStorage.setItem('uid', CURRENT_USER);
-
- // const token = localStorage.getItem('token');
- // if(token){
- // store.commit('changeToken', token);
- // localStorage.removeItem('token');
- // next({ path: to.path });
- // }else{
- // const tmp_token = to.query.token;
- // if (tmp_token) {
- // let formData = new FormData();
- // formData.append("tmp_token", tmp_token);
- // await store.dispatch('getToken', formData);
- // if(store.state.token){
- // // localStorage.setItem('token',store.state.token);
- // next({ path: to.path });
- // }else{
- // if(!Vue.prototype.$closeModalFun){
- // Vue.prototype.$closeModalFun = accessTokenError('获取token失败,请点击左边导航栏应用“资源管理”重试。');
- // }
- // next(false);
- // }
- // }else{
- // if(!Vue.prototype.$closeModalFun){
- // Vue.prototype.$closeModalFun = accessTokenError('获取临时token失败,请点击左边导航栏应用“资源管理”重试。');
- // }
- // next(false);
- // }
- // }
- // }else{
- // if (dynamicRoutes.length === 0) {
- // store
- // .dispatch("user/getRoutesResource")
- // .then((routesResource) => {
- // dynamicRoutes = generateIndexRouter(routesResource);
- // router.addRoutes(dynamicRoutes);
- // if(store.state.isAdmin){
- // router.addRoutes([systemSettings]);
- // }
- // next({ path: to.path, query: to.query });
- // })
- // .catch((err) => {
- // Vue.prototype.$error("请求用户资源失败");
- // console.log(err);
- // next(false);
- // });
- // } else {
- // next();
- // }
- // }
-})
+/** 显示 token 相关的错误提示 */
+function showTokenError() {
+ if (!Vue.prototype.$closeModalFun) {
+ Vue.prototype.$closeModalFun = accessTokenError("获取 token 失败,请点击左边导航栏应用“资源管理”重试。");
+ }
+}
export default router;