From ee77d5c917e56bebf6576b67ebdc3e74fbc29a46 Mon Sep 17 00:00:00 2001 From: snape <81641493@qq.com> Date: Tue, 26 Mar 2024 13:47:24 +0800 Subject: [PATCH] =?UTF-8?q?refactor(login):=20=E9=80=82=E9=85=8D=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E7=99=BB=E5=BD=95=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- .env.development | 2 +- build/plugins.ts | 14 ++++---- index.html | 4 +-- public/platform-config.json | 4 +-- src/api/routes.ts | 6 +++- src/api/user.ts | 28 +++------------- src/api/utils.ts | 1 + src/layout/components/sidebar/logo.vue | 2 +- src/router/index.ts | 2 +- src/router/modules/error.ts | 2 +- src/router/utils.ts | 3 +- src/store/modules/user.ts | 25 +++----------- src/utils/auth.ts | 46 ++++++-------------------- src/utils/http/index.ts | 30 +++-------------- src/views/login/index.vue | 11 ++++-- vite.config.ts | 9 ++++- 17 files changed, 64 insertions(+), 127 deletions(-) create mode 100644 src/api/utils.ts diff --git a/.env b/.env index 09344c1..13d15ca 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ # 平台本地运行端口号 -VITE_PORT = 8848 +VITE_PORT = 10086 # 是否隐藏首页 隐藏 true 不隐藏 false (勿删除,VITE_HIDE_HOME只需在.env文件配置) VITE_HIDE_HOME = false diff --git a/.env.development b/.env.development index 90d1146..ef6304e 100644 --- a/.env.development +++ b/.env.development @@ -1,5 +1,5 @@ # 平台本地运行端口号 -VITE_PORT = 8848 +VITE_PORT = 10086 # 开发环境读取配置文件路径 VITE_PUBLIC_PATH = / diff --git a/build/plugins.ts b/build/plugins.ts index 1f86de5..97357c8 100644 --- a/build/plugins.ts +++ b/build/plugins.ts @@ -10,7 +10,7 @@ import { visualizer } from "rollup-plugin-visualizer"; import removeConsole from "vite-plugin-remove-console"; import { themePreprocessorPlugin } from "@pureadmin/theme"; import { genScssMultipleScopeVars } from "../src/layout/theme"; -import { vitePluginFakeServer } from "vite-plugin-fake-server"; +// import { vitePluginFakeServer } from "vite-plugin-fake-server"; export function getPluginsList( VITE_CDN: boolean, @@ -29,12 +29,12 @@ export function getPluginsList( */ removeNoMatch(), // mock支持 - vitePluginFakeServer({ - logger: false, - include: "mock", - infixName: false, - enableProd: true - }), + // vitePluginFakeServer({ + // logger: false, + // include: "mock", + // infixName: false, + // enableProd: true + // }), // 自定义主题 themePreprocessorPlugin({ scss: { diff --git a/index.html b/index.html index f7f6135..bca2383 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - - + + diff --git a/public/platform-config.json b/public/platform-config.json index 87dca8d..60cf652 100644 --- a/public/platform-config.json +++ b/public/platform-config.json @@ -1,6 +1,6 @@ { - "Version": "5.2.0", - "Title": "PureAdmin", + "Version": "1.0.1", + "Title": "电力配餐后台管理系统", "FixedHeader": true, "HiddenSideBar": false, "MultiTagsCache": false, diff --git a/src/api/routes.ts b/src/api/routes.ts index 501ea3c..baaa283 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -1,4 +1,5 @@ import { http } from "@/utils/http"; +import { baseUrlApi } from "@/api/utils"; type Result = { success: boolean; @@ -6,5 +7,8 @@ type Result = { }; export const getAsyncRoutes = () => { - return http.request("get", "/get-async-routes"); + return http.request( + "get", + baseUrlApi("api/v1/user/manage/getRoutes") + ); }; diff --git a/src/api/user.ts b/src/api/user.ts index 66a797c..524933a 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -1,4 +1,5 @@ import { http } from "@/utils/http"; +import { baseUrlApi } from "@/api/utils"; export type UserResult = { success: boolean; @@ -8,32 +9,13 @@ export type UserResult = { /** 当前登陆用户的角色 */ roles: Array; /** `token` */ - accessToken: string; - /** 用于调用刷新`accessToken`的接口时所需的`token` */ - refreshToken: string; - /** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx') */ - expires: Date; - }; -}; - -export type RefreshTokenResult = { - success: boolean; - data: { - /** `token` */ - accessToken: string; - /** 用于调用刷新`accessToken`的接口时所需的`token` */ - refreshToken: string; - /** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx') */ - expires: Date; + access_token: string; }; }; /** 登录 */ export const getLogin = (data?: object) => { - return http.request("post", "/login", { data }); -}; - -/** 刷新token */ -export const refreshTokenApi = (data?: object) => { - return http.request("post", "/refresh-token", { data }); + return http.request("post", baseUrlApi("api/v1/auth/login"), { + data + }); }; diff --git a/src/api/utils.ts b/src/api/utils.ts new file mode 100644 index 0000000..1bd0b1e --- /dev/null +++ b/src/api/utils.ts @@ -0,0 +1 @@ +export const baseUrlApi = (url: string) => `/dev-api/${url}`; diff --git a/src/layout/components/sidebar/logo.vue b/src/layout/components/sidebar/logo.vue index e02f5cc..c8a7069 100644 --- a/src/layout/components/sidebar/logo.vue +++ b/src/layout/components/sidebar/logo.vue @@ -29,7 +29,7 @@ const { title, getLogo } = useNav(); class="sidebar-logo-link" :to="getTopMenu()?.path ?? '/'" > - logo + {{ title }} diff --git a/src/router/index.ts b/src/router/index.ts index d3fb5bf..1eb7b3c 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -113,7 +113,7 @@ router.beforeEach((to: ToRouteType, _from, next) => { handleAliveRoute(to); } } - const userInfo = storageLocal().getItem>(userKey); + const userInfo = storageLocal().getItem(userKey); NProgress.start(); const externalLink = isUrl(to?.name as string); if (!externalLink) { diff --git a/src/router/modules/error.ts b/src/router/modules/error.ts index e2a1b1f..c336492 100644 --- a/src/router/modules/error.ts +++ b/src/router/modules/error.ts @@ -3,7 +3,7 @@ export default { redirect: "/error/403", meta: { icon: "ri:information-line", - // showLink: false, + showLink: false, title: "异常页面", rank: 9 }, diff --git a/src/router/utils.ts b/src/router/utils.ts index 1b80ac6..cee2470 100644 --- a/src/router/utils.ts +++ b/src/router/utils.ts @@ -83,8 +83,7 @@ function isOneOfArray(a: Array, b: Array) { /** 从localStorage里取出当前登陆用户的角色roles,过滤无权限的菜单 */ function filterNoPermissionTree(data: RouteComponent[]) { - const currentRoles = - storageLocal().getItem>(userKey)?.roles ?? []; + const currentRoles = storageLocal().getItem(userKey)?.roles ?? []; const newTree = cloneDeep(data).filter((v: any) => isOneOfArray(v.meta?.roles, currentRoles) ); diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 00a0f71..30d2399 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,8 +4,8 @@ import type { userType } from "./types"; import { routerArrays } from "@/layout/types"; import { router, resetRouter } from "@/router"; import { storageLocal } from "@pureadmin/utils"; -import { getLogin, refreshTokenApi } from "@/api/user"; -import type { UserResult, RefreshTokenResult } from "@/api/user"; +import { getLogin } from "@/api/user"; +import type { UserResult } from "@/api/user"; import { useMultiTagsStoreHook } from "@/store/modules/multiTags"; import { type DataInfo, setToken, removeToken, userKey } from "@/utils/auth"; @@ -13,9 +13,9 @@ export const useUserStore = defineStore({ id: "pure-user", state: (): userType => ({ // 用户名 - username: storageLocal().getItem>(userKey)?.username ?? "", + username: storageLocal().getItem(userKey)?.username ?? "", // 页面级别权限 - roles: storageLocal().getItem>(userKey)?.roles ?? [], + roles: storageLocal().getItem(userKey)?.roles ?? [], // 是否勾选了登录页的免登录 isRemembered: false, // 登录页的免登录存储几天,默认7天 @@ -39,7 +39,7 @@ export const useUserStore = defineStore({ this.loginDay = Number(value); }, /** 登入 */ - async loginByUsername(data) { + async loginByUsername(data: object) { return new Promise((resolve, reject) => { getLogin(data) .then(data => { @@ -61,21 +61,6 @@ export const useUserStore = defineStore({ useMultiTagsStoreHook().handleTags("equal", [...routerArrays]); resetRouter(); router.push("/login"); - }, - /** 刷新`token` */ - async handRefreshToken(data) { - return new Promise((resolve, reject) => { - refreshTokenApi(data) - .then(data => { - if (data) { - setToken(data.data); - resolve(data); - } - }) - .catch(error => { - reject(error); - }); - }); } } }); diff --git a/src/utils/auth.ts b/src/utils/auth.ts index ccefcf2..18ffca3 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -2,13 +2,9 @@ import Cookies from "js-cookie"; import { storageLocal } from "@pureadmin/utils"; import { useUserStoreHook } from "@/store/modules/user"; -export interface DataInfo { +export interface DataInfo { /** token */ - accessToken: string; - /** `accessToken`的过期时间(时间戳) */ - expires: T; - /** 用于调用刷新accessToken的接口时所需的token */ - refreshToken: string; + access_token: string; /** 用户名 */ username?: string; /** 当前登陆用户的角色 */ @@ -16,7 +12,7 @@ export interface DataInfo { } export const userKey = "user-info"; -export const TokenKey = "authorized-token"; +export const TokenKey = "Authorization"; /** * 通过`multiple-tabs`是否在`cookie`中,判断用户是否已经登录系统, * 从而支持多标签页打开已经登录的系统后无需再登录。 @@ -26,7 +22,7 @@ export const TokenKey = "authorized-token"; export const multipleTabsKey = "multiple-tabs"; /** 获取`token` */ -export function getToken(): DataInfo { +export function getToken(): DataInfo { // 此处与`TokenKey`相同,此写法解决初始化时`Cookies`中不存在`TokenKey`报错 return Cookies.get(TokenKey) ? JSON.parse(Cookies.get(TokenKey)) @@ -39,35 +35,17 @@ export function getToken(): DataInfo { * 将`accessToken`、`expires`这两条信息放在key值为authorized-token的cookie里(过期自动销毁) * 将`username`、`roles`、`refreshToken`、`expires`这四条信息放在key值为`user-info`的localStorage里(利用`multipleTabsKey`当浏览器完全关闭后自动销毁) */ -export function setToken(data: DataInfo) { - let expires = 0; - const { accessToken, refreshToken } = data; - const { isRemembered, loginDay } = useUserStoreHook(); - expires = new Date(data.expires).getTime(); // 如果后端直接设置时间戳,将此处代码改为expires = data.expires,然后把上面的DataInfo改成DataInfo即可 - const cookieString = JSON.stringify({ accessToken, expires }); +export function setToken(data: DataInfo) { + const { access_token } = data; + const cookieString = JSON.stringify({ access_token }); + Cookies.set(TokenKey, cookieString); - expires > 0 - ? Cookies.set(TokenKey, cookieString, { - expires: (expires - Date.now()) / 86400000 - }) - : Cookies.set(TokenKey, cookieString); - - Cookies.set( - multipleTabsKey, - "true", - isRemembered - ? { - expires: loginDay - } - : {} - ); + Cookies.set(multipleTabsKey, "true"); function setUserKey(username: string, roles: Array) { useUserStoreHook().SET_USERNAME(username); useUserStoreHook().SET_ROLES(roles); storageLocal().setItem(userKey, { - refreshToken, - expires, username, roles }); @@ -77,10 +55,8 @@ export function setToken(data: DataInfo) { const { username, roles } = data; setUserKey(username, roles); } else { - const username = - storageLocal().getItem>(userKey)?.username ?? ""; - const roles = - storageLocal().getItem>(userKey)?.roles ?? []; + const username = storageLocal().getItem(userKey)?.username ?? ""; + const roles = storageLocal().getItem(userKey)?.roles ?? []; setUserKey(username, roles); } } diff --git a/src/utils/http/index.ts b/src/utils/http/index.ts index 5f40e69..aa784c1 100644 --- a/src/utils/http/index.ts +++ b/src/utils/http/index.ts @@ -12,7 +12,6 @@ import type { import { stringify } from "qs"; import NProgress from "../progress"; import { getToken, formatToken } from "@/utils/auth"; -import { useUserStoreHook } from "@/store/modules/user"; // 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1 const defaultConfig: AxiosRequestConfig = { @@ -79,31 +78,10 @@ class PureHttp { : new Promise(resolve => { const data = getToken(); if (data) { - const now = new Date().getTime(); - const expired = parseInt(data.expires) - now <= 0; - if (expired) { - if (!PureHttp.isRefreshing) { - PureHttp.isRefreshing = true; - // token过期刷新 - useUserStoreHook() - .handRefreshToken({ refreshToken: data.refreshToken }) - .then(res => { - const token = res.data.accessToken; - config.headers["Authorization"] = formatToken(token); - PureHttp.requests.forEach(cb => cb(token)); - PureHttp.requests = []; - }) - .finally(() => { - PureHttp.isRefreshing = false; - }); - } - resolve(PureHttp.retryOriginalRequest(config)); - } else { - config.headers["Authorization"] = formatToken( - data.accessToken - ); - resolve(config); - } + config.headers["Authorization"] = formatToken( + data.access_token + ); + resolve(config); } else { resolve(config); } diff --git a/src/views/login/index.vue b/src/views/login/index.vue index b25fd5a..3d2b24d 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -33,8 +33,9 @@ dataThemeChange(); const { title } = useNav(); const ruleForm = reactive({ - username: "admin", - password: "admin123" + grantType: "WEB", + username: "", + password: "" }); const onLogin = async (formEl: FormInstance | undefined) => { @@ -43,7 +44,11 @@ const onLogin = async (formEl: FormInstance | undefined) => { await formEl.validate((valid, fields) => { if (valid) { useUserStoreHook() - .loginByUsername({ username: ruleForm.username, password: "admin123" }) + .loginByUsername({ + grantType: ruleForm.grantType, + username: ruleForm.username, + password: ruleForm.password + }) .then(res => { if (res.success) { // 获取后端路由 diff --git a/vite.config.ts b/vite.config.ts index f7e2f28..b1ea29a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -24,7 +24,14 @@ export default ({ mode }: ConfigEnv): UserConfigExport => { port: VITE_PORT, host: "0.0.0.0", // 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy - proxy: {}, + proxy: { + "/dev-api": { + // 这里填写后端地址 + target: "http://192.168.1.33:8000", + changeOrigin: true, + rewrite: path => path.replace(/^\/dev-api/, "") + } + }, // 预热文件以提前转换和缓存结果,降低启动期间的初始页面加载时长并防止转换瀑布 warmup: { clientFiles: ["./index.html", "./src/{views,components}/*"]