diff --git a/Yi.BBS.Vue3/.env.development b/Yi.BBS.Vue3/.env.development index 8229bdf9..9ea2ef99 100644 --- a/Yi.BBS.Vue3/.env.development +++ b/Yi.BBS.Vue3/.env.development @@ -1,2 +1,4 @@ +# 接口前缀 VITE_APP_BASEAPI="/api-dev" -VITE_APP_URL="http://localhost:19001/api/app" \ No newline at end of file +VITE_APP_URL="http://localhost:19001/api/app" +VITE_APP_ENV_NAME = "dev" \ No newline at end of file diff --git a/Yi.BBS.Vue3/.env.production b/Yi.BBS.Vue3/.env.production index a76814fb..d14259d7 100644 --- a/Yi.BBS.Vue3/.env.production +++ b/Yi.BBS.Vue3/.env.production @@ -1 +1,4 @@ -VITE_APP_BASEAPI="/prod-api" \ No newline at end of file +# 接口前缀 +VITE_APP_BASEAPI="/prod-api" + +VITE_APP_ENV_NAME = "production" \ No newline at end of file diff --git a/Yi.BBS.Vue3/src/apis/auth.js b/Yi.BBS.Vue3/src/apis/auth.js new file mode 100644 index 00000000..37e2524b --- /dev/null +++ b/Yi.BBS.Vue3/src/apis/auth.js @@ -0,0 +1,65 @@ +import request from "@/config/axios/service"; + +/** + * 用户登录 + * @param {*} data 账号密码 + */ +export function userLogin(data) { + return request({ + url: `/account/login`, + method: "post", + data, + }); +} + +/** + * 用户注册 + * @param {*} data 账号密码 + */ +export function userRegister(data) { + return request({ + url: `/account/register`, + method: "post", + data, + }); +} + +/** + * 获取用户详细信息 + */ +export function getUserDetailInfo() { + return request({ + url: `/account`, + method: "get", + }); +} + +/** + * 用户退出 + */ +export function userLogout() { + return request({ + url: `/account/logout`, + method: "post", + }); +} + +/** + * 获取验证码 + */ +export function getCodeImg() { + return request({ + url: `/account/captcha-image`, + method: "get", + }); +} +/** + * 获取短信验证码 + */ +export function getCodePhone(data) { + return request({ + url: `/account/captcha-phone`, + method: "post", + data, + }); +} diff --git a/Yi.BBS.Vue3/src/apis/configApi.js b/Yi.BBS.Vue3/src/apis/configApi.js index 79e7edf9..0b117e63 100644 --- a/Yi.BBS.Vue3/src/apis/configApi.js +++ b/Yi.BBS.Vue3/src/apis/configApi.js @@ -1,9 +1,9 @@ -import myaxios from '@/utils/request' +import request from "@/config/axios/service"; //获取配置 -export function getAll(){ - return myaxios({ - url: '/config', - method: 'get' - }) -}; \ No newline at end of file +export function getAll() { + return request({ + url: "/config", + method: "get", + }); +} diff --git a/Yi.BBS.Vue3/src/config/axios/ErrorCode.js b/Yi.BBS.Vue3/src/config/axios/ErrorCode.js new file mode 100644 index 00000000..f552fd6f --- /dev/null +++ b/Yi.BBS.Vue3/src/config/axios/ErrorCode.js @@ -0,0 +1,13 @@ +export default { + "000": "操作太频繁,请勿重复请求", + 401: "当前操作没有权限,请退出重试", + 403: "当前操作没有权限,请退出重试", + 404: "资源不存在", + 417: "未绑定登录账号,请使用密码登录后绑定", + 423: "演示环境不能操作,如需了解联系", + 426: "用户名不存在或密码错误", + 428: "验证码错误,请重新输入", + 429: "请求过频繁", + 479: "演示环境,没有权限操作", + default: "系统未知错误,请反馈给管理员", +}; diff --git a/Yi.BBS.Vue3/src/config/axios/config.js b/Yi.BBS.Vue3/src/config/axios/config.js new file mode 100644 index 00000000..bd677d55 --- /dev/null +++ b/Yi.BBS.Vue3/src/config/axios/config.js @@ -0,0 +1,34 @@ +const config = { + /** + * api请求基础路径 + */ + base_url: { + // 开发环境接口前缀 + dev: import.meta.env.VITE_APP_BASEAPI, + // 打包生产环境接口前缀 + pro: window.location.protocol + "//" + window.location.hostname + ":19001", + }, + + /** + * 接口请求前缀 + */ + pre_interface: import.meta.env.VITE_APP_BASEAPI, + + /** + * 接口成功返回状态码 + */ + result_code: "0000", + + /** + * 接口请求超时时间 + */ + request_timeout: 60000, + + /** + * 默认接口请求类型 + * 可选值:application/x-www-form-urlencoded multipart/form-data + */ + default_headers: "application/json", +}; + +export { config }; diff --git a/Yi.BBS.Vue3/src/config/axios/service.js b/Yi.BBS.Vue3/src/config/axios/service.js new file mode 100644 index 00000000..daed13fa --- /dev/null +++ b/Yi.BBS.Vue3/src/config/axios/service.js @@ -0,0 +1,89 @@ +import axios from "axios"; +import { ElMessage } from "element-plus"; +import { config } from "@/config/axios/config"; +import { Session } from "@/utils/storage"; +import useAuths from "@/hooks/useAuths"; + +const { getToken } = useAuths(); + +const { request_timeout } = config; +export const PATH_URL = import.meta.env.VITE_APP_BASEAPI; + +// 配置新建一个 axios 实例 +const service = axios.create({ + baseURL: PATH_URL, // api 的 base_url + timeout: request_timeout, // 请求超时时间 + headers: { "Content-Type": "application/json" }, + hideerror: false, //是否在底层显示错误信息 +}); + +// 添加请求拦截器 +service.interceptors.request.use( + (config) => { + // 在发送请求之前做些什么 token + const token = getToken(); + if (token) { + config.headers["Authorization"] = `Bearer ${token}`; + } + if (Session.get("tenantId")) { + config.headers["TenantId"] = Session.get("tenantId"); + } + return config; + }, + (error) => { + // 对请求错误做些什么 + return Promise.reject(error); + } +); + +// 添加响应拦截器 +service.interceptors.response.use( + (response) => { + return Promise.resolve(response); + }, + (error) => { + // 对响应错误做点什么 + if (error.message.indexOf("timeout") != -1) { + ElMessage({ + type: "danger", + message: "网络超时", + }); + } else if (error.message == "Network Error") { + ElMessage({ + type: "danger", + message: "网络连接错误", + }); + } else { + const res = error.response || {}; + const status = Number(res.status) || 200; + const message = res.data.error.message; + if (status === 401) { + ElMessage({ + type: "danger", + message, + }); + return; + } + if (status !== 200) { + if (status >= 500) { + ElMessage({ + type: "danger", + message: "网络开小差了,请稍后再试", + }); + return Promise.reject(new Error(message)); + } + // 避开找不到后端接口的提醒 + if (status !== 404) { + ElMessage({ + type: "danger", + message, + }); + } + } + } + return Promise.reject(new Error(error)); + } +); + +// 导出 axios 实例 +export default service; diff --git a/Yi.BBS.Vue3/src/hooks/useAuths.js b/Yi.BBS.Vue3/src/hooks/useAuths.js new file mode 100644 index 00000000..38552666 --- /dev/null +++ b/Yi.BBS.Vue3/src/hooks/useAuths.js @@ -0,0 +1,138 @@ +import { ElMessage, ElMessageBox } from "element-plus"; +import useUserStore from "@/stores/user"; +import router from "@/router"; +import { Session, Local } from "@/utils/storage"; +import { userLogin, getUserDetailInfo, userLogout } from "@/apis/auth"; + +const TokenKey = "AccessToken"; +export const AUTH_MENUS = "AUTH_MENUS"; +export const AUTH_USER = "AUTH_USER"; + +export default function useAuths(opt) { + const defaultOpt = { + loginUrl: "/login", // 登录页跳转url 默认: /login + loginReUrl: "", // 登录页登陆成功后带重定向redirect=的跳转url 默认为空 + homeUrl: "/index", // 主页跳转url 默认: /index + otherQuery: {}, // 成功登录后携带的(除redirect外)其他参数 + }; + + let option = { + ...defaultOpt, + ...opt, + }; + + // 获取token + const getToken = () => { + return Session.get(TokenKey); + }; + + // 存储token到cookies + const setToken = (token) => { + if (token == null) { + return false; + } + Session.set(TokenKey, token); + return true; + }; + + // 删除token + const removeToken = () => { + Session.remove(TokenKey); + return true; + }; + + // 退出登录 + const logoutFun = async () => { + let flag = true; + try { + await userLogout().then((res) => { + ElMessage({ + message: "退出成功", + type: "info", + duration: 2000, + }); + }); + } catch (error) { + flag = await ElMessageBox.confirm( + `退出登录失败,是否强制退出?`, + "提示", + { + confirmButtonText: "确 定", + cancelButtonText: "取 消", + type: "warning", + } + ) + .then(() => { + return true; + }) + .catch(() => { + //取消 + return false; + }); + } + if (flag) { + clearStorage(); + } + }; + + // 清空本地存储的信息 + const clearStorage = () => { + Session.clear(); + Local.clear(); + removeToken(); + window.location.reload(); + Session.set("vuex", null); + }; + + // 用户名密码登录 + const loginFun = async (params) => { + const res = await userLogin(params); + ElMessage({ + message: `您好${params.userName},登录成功!`, + type: "success", + }); + loginSuccess(res); + return res; + }; + + // 获取用户基本信息、角色、菜单权限 + const getUserInfo = async () => { + try { + let { data } = await getUserDetailInfo(); + // useUserStore + // store.dispatch("updateUserInfo", result); + return data; + } catch (error) { + return {}; + } + }; + + // 登录成功之后的操作 + const loginSuccess = async (res) => { + const { token } = res.data; + + setToken(token); + try { + // 存储用户信息 + await getUserInfo(); // 用户信息 + // 登录成功后 路由跳转 + router.replace({ + path: option.loginReUrl ? option.loginReUrl : option.homeUrl, + query: option.otherQuery, + }); + } catch (error) { + removeToken(); + return false; + } + }; + + return { + getToken, + setToken, + removeToken, + loginFun, + getUserInfo, + logoutFun, + clearStorage, + }; +} diff --git a/Yi.BBS.Vue3/src/permission.js b/Yi.BBS.Vue3/src/permission.js index aa0af493..01e51f38 100644 --- a/Yi.BBS.Vue3/src/permission.js +++ b/Yi.BBS.Vue3/src/permission.js @@ -1,65 +1,52 @@ -import router from './router' -import { ElMessage } from 'element-plus' -import NProgress from 'nprogress' -import 'nprogress/nprogress.css' -import { getToken } from '@/utils/auth' -import { isRelogin } from '@/utils/request' -import useUserStore from '@/stores/user' - +import router from "./router"; +import useAuths from "@/hooks/useAuths"; +import { ElMessage } from "element-plus"; +import NProgress from "nprogress"; +import "nprogress/nprogress.css"; +import useUserStore from "@/stores/user"; NProgress.configure({ showSpinner: false }); - -const whiteList = ['/login', '/auth-redirect', '/bind', '/register']; +const { getToken, logoutFun } = useAuths(); +const whiteList = ["/login", "/auth-redirect", "/bind", "/register"]; router.beforeEach((to, from, next) => { - NProgress.start() - if (getToken()) { - // to.meta.title && useSettingsStore().setTitle(to.meta.title) - /* has token*/ - if (to.path === '/login') { - next({ path: '/' }) - NProgress.done() + NProgress.start(); + const hasToken = getToken(); + if (hasToken) { + if (to.path === "/login") { + // 已经登陆跳转到首页 + next({ path: "/" }); + NProgress.done(); } else { - - if (useUserStore().roles.length === 0) - { - isRelogin.show = true + if (useUserStore().roles.length === 0) { // 判断当前用户是否已拉取完user_info信息 - useUserStore().getInfo().then(() => { - isRelogin.show = false - //这里不需要动态路由 - // usePermissionStore().generateRoutes().then(accessRoutes => { - // // 根据roles权限生成可访问的路由表 - // accessRoutes.forEach(route => { - // if (!isHttp(route.path)) { - // router.addRoute(route) // 动态添加可访问路由表 - // } - // }) - // next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 - // }) - next({ ...to, replace: true }) - }).catch(err => { - useUserStore().logOut().then(() => { - ElMessage.error(err) - next({ path: '/' }) + useUserStore() + .getInfo() + .then(() => { + next({ ...to, replace: true }); }) - }) + .catch((err) => { + logoutFun.then(() => { + ElMessage.error(err); + next({ path: "/" }); + }); + }); } else { - next() + next(); } } } else { // 没有token if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入 - next() + next(); } else { - next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 - NProgress.done() + next(`/login?redirect=${to.path}&unTourist=true`); // 否则全部重定向到登录页 + NProgress.done(); } } -}) +}); router.afterEach(() => { - NProgress.done() -}) + NProgress.done(); +}); diff --git a/Yi.BBS.Vue3/src/router/index.js b/Yi.BBS.Vue3/src/router/index.js index e5a40141..efd0a79d 100644 --- a/Yi.BBS.Vue3/src/router/index.js +++ b/Yi.BBS.Vue3/src/router/index.js @@ -1,76 +1,74 @@ -import { createRouter, createWebHistory } from 'vue-router' -import Layout from '../layout/Index.vue' -import NotFound from '../views/error/404.vue' -import LoginLayout from '../layout/LoginLayout.vue' +import { createRouter, createWebHistory } from "vue-router"; +import Layout from "../layout/Index.vue"; +import NotFound from "../views/error/404.vue"; +import LoginLayout from "../layout/LoginLayout.vue"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), scrollBehavior(to, from, savedPosition) { // 始终滚动到顶部 - return { top: 0 } + return { top: 0 }; }, routes: [ { - name:'test', - path: '/test', - component: () => import('../views/Test.vue') + name: "test", + path: "/test", + component: () => import("../views/Test.vue"), }, { - - path: '/loginLayout', - name: 'loginLayout', + path: "/loginLayout", + name: "loginLayout", component: LoginLayout, - redirect: '/login' , - children :[ + redirect: "/login", + children: [ { - name:'login', - path: '/login', - component: () => import('../views/Login.vue') + name: "login", + path: "/login", + component: () => import("../views/Login.vue"), }, { - name:'register', - path: '/register', - component: () => import('../views/Register.vue') + name: "register", + path: "/register", + component: () => import("../views/Register.vue"), }, - ] + ], }, { - path: '/', - name: 'layout', + path: "/", + name: "layout", component: Layout, - redirect: '/index' , - children :[ + redirect: "/index", + children: [ { - name:'index', - path: '/index', - component: () => import('../views/Index.vue') + name: "index", + path: "/index", + component: () => import("../views/Index.vue"), }, { - name:'article', - path: '/article/:discussId/:articleId?', - component: () => import('../views/Article.vue') + name: "article", + path: "/article/:discussId/:articleId?", + component: () => import("../views/Article.vue"), }, { - name:'discuss', - path: '/discuss/:plateId?', - component: () => import('../views/Discuss.vue') + name: "discuss", + path: "/discuss/:plateId?", + component: () => import("../views/Discuss.vue"), }, { //artType:discuss主题、article文章 //operType:create创建、update更新 - name:'editArt', - path:'/editArt', - component:()=>import('../views/EditArticle.vue') + name: "editArt", + path: "/editArt", + component: () => import("../views/EditArticle.vue"), }, { - name:'profile', - path:'/profile', - component:()=>import('../views/profile/Index.vue') - - } - ] + name: "profile", + path: "/profile", + component: () => import("../views/profile/Index.vue"), + }, + ], }, - { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }, - ] -}) + { path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound }, + ], +}); -export default router +export default router; diff --git a/Yi.BBS.Vue3/src/stores/user.js b/Yi.BBS.Vue3/src/stores/user.js index ea55f132..744a944b 100644 --- a/Yi.BBS.Vue3/src/stores/user.js +++ b/Yi.BBS.Vue3/src/stores/user.js @@ -1,98 +1,109 @@ -import { login, logout, getInfo,register } from '@/apis/accountApi' -import { getToken, setToken, removeToken } from '@/utils/auth' -import { defineStore } from 'pinia' -const useUserStore = defineStore('user', -{ - state: () => ({ - id:'', - token: getToken(), - name: '游客', - userName:'', - icon: null, - roles: [], - permissions: [] - }), - getters: { - }, - actions: { - // 登录 - login(userInfo) { - const userName = userInfo.userName.trim() - const password = userInfo.password - const code = userInfo.code - const uuid = userInfo.uuid - return new Promise((resolve, reject) => { - login(userName, password, code, uuid).then(response => { - const res=response.data; +import { login, logout, getInfo, register } from "@/apis/accountApi"; +import { getUserDetailInfo } from "@/apis/auth"; +import useAuths from "@/hooks/useAuths"; +import { defineStore } from "pinia"; + +const { getToken, setToken, removeToken } = useAuths(); + +const useUserStore = defineStore("user", { + state: () => ({ + id: "", + token: getToken(), + name: "游客", + userName: "", + icon: null, + roles: [], + permissions: [], + }), + getters: {}, + actions: { + // 登录 + login(userInfo) { + const userName = userInfo.userName.trim(); + const password = userInfo.password; + const code = userInfo.code; + const uuid = userInfo.uuid; + return new Promise((resolve, reject) => { + login(userName, password, code, uuid) + .then((response) => { + const res = response.data; setToken(res.token); this.token = res.token; resolve(response); - }).catch(error => { - reject(error) }) - }) - }, - // 获取用户信息 - getInfo() { - return new Promise((resolve, reject) => { - getInfo().then(response => { - const res=response.data; - const user = res.user - const avatar = (user.icon == "" || user.icon == null) ? "/src/assets/logo.ico" : import.meta.env.VITE_APP_BASEAPI + "/file/"+user.icon; - - if (res.roleCodes && res.roleCodes.length > 0) { // 验证返回的roles是否是一个非空数组 - this.roles = res.roleCodes - this.permissions = res.permissionCodes + .catch((error) => { + reject(error); + }); + }); + }, + // 获取用户信息 + getInfo() { + return new Promise((resolve, reject) => { + getUserDetailInfo() + .then((response) => { + const res = response.data; + const user = res.user; + const avatar = + user.icon == "" || user.icon == null + ? "/src/assets/logo.ico" + : import.meta.env.VITE_APP_BASEAPI + "/file/" + user.icon; + + if (res.roleCodes && res.roleCodes.length > 0) { + // 验证返回的roles是否是一个非空数组 + this.roles = res.roleCodes; + this.permissions = res.permissionCodes; // this.roles = ["admin"]; // this.permissions=["*:*:*"] - } else { - this.roles = ['ROLE_DEFAULT'] + this.roles = ["ROLE_DEFAULT"]; } // this.roles = ["admin"]; // this.permissions=["*:*:*"] - this.name = user.nick + this.name = user.nick; this.icon = avatar; - this.userName=user.userName; - this.id=user.id; - resolve(res) - }).catch(error => { - reject(error) + this.userName = user.userName; + this.id = user.id; + resolve(res); }) - }) - }, - // 退出系统 - logOut() { - return new Promise((resolve, reject) => { - logout().then(() => { - this.token = '' - this.roles = [] - this.permissions = [] - removeToken() - resolve() - }).catch(error => { - reject(error) + .catch((error) => { + reject(error); + }); + }); + }, + // 退出系统 + logOut() { + return new Promise((resolve, reject) => { + logout() + .then(() => { + this.token = ""; + this.roles = []; + this.permissions = []; + removeToken(); + resolve(); }) - }) - }, - // 注册 - register(userInfo) { - const userName = userInfo.userName.trim() - const password = userInfo.password.trim() - const phone = userInfo.phone; - const uuid = userInfo.uuid; - const code=userInfo.code; - return new Promise((resolve, reject) => { - register(userName,password,phone,code,uuid).then(response => { - resolve(response); - }).catch(error => { - reject(error) - }) - }) - }, - - }, -}) + .catch((error) => { + reject(error); + }); + }); + }, + // 注册 + register(userInfo) { + const userName = userInfo.userName.trim(); + const password = userInfo.password.trim(); + const phone = userInfo.phone; + const uuid = userInfo.uuid; + const code = userInfo.code; + return new Promise((resolve, reject) => { + register(userName, password, phone, code, uuid) + .then((response) => { + resolve(response); + }) + .catch((error) => { + reject(error); + }); + }); + }, + }, +}); export default useUserStore; - \ No newline at end of file diff --git a/Yi.BBS.Vue3/src/utils/file.js b/Yi.BBS.Vue3/src/utils/file.js new file mode 100644 index 00000000..5d65a68a --- /dev/null +++ b/Yi.BBS.Vue3/src/utils/file.js @@ -0,0 +1,140 @@ +/** + * 根据后缀判断文件类型 + * @param {string} fileName 文件后缀名 + * @returns + */ +export function matchType(fileName) { + // 后缀获取 + let suffix = ""; + // 获取类型结果 + let result = ""; + try { + let flieArr = fileName.split("."); + suffix = flieArr[flieArr.length - 1]; + } catch (err) { + suffix = ""; + } + // fileName无后缀返回 false + if (!suffix) { + result = false; + return result; + } + // 图片格式 + let imglist = ["png", "jpg", "jpeg", "bmp", "gif"]; + // 进行图片匹配 + result = imglist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "image"; + return result; + } + // 匹配txt + let txtlist = ["txt"]; + result = txtlist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "txt"; + return result; + } + // 匹配 excel + let excelist = ["xls", "xlsx"]; + result = excelist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "excel"; + return result; + } + // 匹配 word + let wordlist = ["doc", "docx"]; + result = wordlist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "word"; + return result; + } + // 匹配 pdf + let pdflist = ["pdf"]; + result = pdflist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "pdf"; + return result; + } + // 匹配 ppt + let pptlist = ["ppt"]; + result = pptlist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "ppt"; + return result; + } + // 匹配 视频 + let videolist = ["mp4", "m2v", "mkv"]; + result = videolist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "video"; + return result; + } + // 匹配 音频 + let radiolist = ["mp3", "wav", "wmv"]; + result = radiolist.some(function (item) { + return item == suffix; + }); + if (result) { + result = "radio"; + return result; + } + // 其他 文件类型 + result = "other"; + return result; +} + +/** + * url处理 + * @param {string} path url路径 + * @returns + */ +export function convertToUrl(path) { + // 替换反斜杠为正斜杠 + const normalizedPathWithSlashes = path.replace(/\\/g, "/"); + // 去掉开始的点号和反斜杠 + const removedDotsAndSlashes = normalizedPathWithSlashes.replace(/^\.\//, ""); + // 添加斜杠作为根路径 + const url = `/${removedDotsAndSlashes}`; + return url; +} + +/** + * 下载文件 + * + * @param {*} path 下载地址/下载请求地址。 + * @param {string} name 下载文件的名字(考虑到兼容性问题,最好加上后缀名 + */ +export const downLoadFile = (path, name) => { + const link = document.createElement("a"); + link.href = path; + link.download = name; + + if (isMobileDevice()) { + link.target = "_blank"; + link.rel = "noopener noreferrer"; + } + + link.style.display = "none"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +}; + +// 判断是否移动设备 +export function isMobileDevice() { + return /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent); +} diff --git a/Yi.BBS.Vue3/src/utils/storage.js b/Yi.BBS.Vue3/src/utils/storage.js new file mode 100644 index 00000000..fe57badc --- /dev/null +++ b/Yi.BBS.Vue3/src/utils/storage.js @@ -0,0 +1,53 @@ +/** + * window.localStorage 浏览器永久缓存 + * @method set 设置永久缓存 + * @method get 获取永久缓存 + * @method remove 移除永久缓存 + * @method clear 移除全部永久缓存 + */ +export const Local = { + // 设置永久缓存 + set(key, val) { + window.localStorage.setItem(key, JSON.stringify(val)); + }, + // 获取永久缓存 + get(key) { + let json = window.localStorage.getItem(key); + return JSON.parse(json); + }, + // 移除永久缓存 + remove(key) { + window.localStorage.removeItem(key); + }, + // 移除全部永久缓存 + clear() { + window.localStorage.clear(); + }, +}; + +/** + * window.sessionStorage 浏览器会话临时缓存 + * @method set 设置临时缓存 + * @method get 获取临时缓存 + * @method remove 移除临时缓存 + * @method clear 移除全部临时缓存 + */ +export const Session = { + // 设置临时缓存 + set(key, val) { + window.sessionStorage.setItem(key, JSON.stringify(val)); + }, + // 获取临时缓存 + get(key) { + let json = window.sessionStorage.getItem(key); + return JSON.parse(json); + }, + // 移除临时缓存 + remove(key) { + window.sessionStorage.removeItem(key); + }, + // 移除全部临时缓存 + clear() { + window.sessionStorage.clear(); + }, +}; diff --git a/Yi.BBS.Vue3/src/views/Login.vue b/Yi.BBS.Vue3/src/views/Login.vue index a39f813b..438bdfce 100644 --- a/Yi.BBS.Vue3/src/views/Login.vue +++ b/Yi.BBS.Vue3/src/views/Login.vue @@ -1,47 +1,50 @@