Merge branch 'abp' of https://gitee.com/ccnetcore/Yi into abp
This commit is contained in:
@@ -1,2 +1,4 @@
|
||||
# 接口前缀
|
||||
VITE_APP_BASEAPI="/api-dev"
|
||||
VITE_APP_URL="http://localhost:19001/api/app"
|
||||
VITE_APP_URL="http://localhost:19001/api/app"
|
||||
VITE_APP_ENV_NAME = "dev"
|
||||
@@ -1 +1,4 @@
|
||||
VITE_APP_BASEAPI="/prod-api"
|
||||
# 接口前缀
|
||||
VITE_APP_BASEAPI="/prod-api"
|
||||
|
||||
VITE_APP_ENV_NAME = "production"
|
||||
65
Yi.BBS.Vue3/src/apis/auth.js
Normal file
65
Yi.BBS.Vue3/src/apis/auth.js
Normal file
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import myaxios from '@/utils/request'
|
||||
import request from "@/config/axios/service";
|
||||
|
||||
//获取配置
|
||||
export function getAll(){
|
||||
return myaxios({
|
||||
url: '/config',
|
||||
method: 'get'
|
||||
})
|
||||
};
|
||||
export function getAll() {
|
||||
return request({
|
||||
url: "/config",
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
|
||||
13
Yi.BBS.Vue3/src/config/axios/ErrorCode.js
Normal file
13
Yi.BBS.Vue3/src/config/axios/ErrorCode.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export default {
|
||||
"000": "操作太频繁,请勿重复请求",
|
||||
401: "当前操作没有权限,请退出重试",
|
||||
403: "当前操作没有权限,请退出重试",
|
||||
404: "资源不存在",
|
||||
417: "未绑定登录账号,请使用密码登录后绑定",
|
||||
423: "演示环境不能操作,如需了解联系",
|
||||
426: "用户名不存在或密码错误",
|
||||
428: "验证码错误,请重新输入",
|
||||
429: "请求过频繁",
|
||||
479: "演示环境,没有权限操作",
|
||||
default: "系统未知错误,请反馈给管理员",
|
||||
};
|
||||
34
Yi.BBS.Vue3/src/config/axios/config.js
Normal file
34
Yi.BBS.Vue3/src/config/axios/config.js
Normal file
@@ -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 };
|
||||
89
Yi.BBS.Vue3/src/config/axios/service.js
Normal file
89
Yi.BBS.Vue3/src/config/axios/service.js
Normal file
@@ -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;
|
||||
138
Yi.BBS.Vue3/src/hooks/useAuths.js
Normal file
138
Yi.BBS.Vue3/src/hooks/useAuths.js
Normal file
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
140
Yi.BBS.Vue3/src/utils/file.js
Normal file
140
Yi.BBS.Vue3/src/utils/file.js
Normal file
@@ -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);
|
||||
}
|
||||
53
Yi.BBS.Vue3/src/utils/storage.js
Normal file
53
Yi.BBS.Vue3/src/utils/storage.js
Normal file
@@ -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();
|
||||
},
|
||||
};
|
||||
@@ -1,47 +1,50 @@
|
||||
<template>
|
||||
<div class="login-wrapper">
|
||||
<h1>{{configStore.name}}-登录</h1>
|
||||
<div class="login-form">
|
||||
|
||||
<el-form ref="loginFormRef" v-model="loginForm" :rules="rules" >
|
||||
|
||||
<div class="username form-item">
|
||||
<el-form-item prop="userName">
|
||||
<span>使用账号</span>
|
||||
<input type="text" class="input-item" v-model="loginForm.userName">
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="password form-item">
|
||||
<el-form-item prop="password">
|
||||
<span>密码</span>
|
||||
<input type="password" class="input-item" v-model="loginForm.password">
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<RouterLink to="/register" > 没有账号?前往注册</RouterLink>
|
||||
<button class="login-btn" @click="login">登 录</button>
|
||||
<button class="login-btn" @click="guestlogin">游客临时登录</button>
|
||||
<div class="login-wrapper">
|
||||
<h1>{{ configStore.name }}-登录</h1>
|
||||
<div class="login-form">
|
||||
<el-form ref="loginFormRef" :model="loginForm" :rules="rules">
|
||||
<div class="username form-item">
|
||||
<el-form-item prop="userName">
|
||||
<span>使用账号</span>
|
||||
<input
|
||||
type="text"
|
||||
class="input-item"
|
||||
v-model="loginForm.userName"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="divider">
|
||||
<span class="line"></span>
|
||||
<span class="divider-text">其他方式登录</span>
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
|
||||
<div class="other-login-wrapper">
|
||||
<div class="other-login-item">
|
||||
<img src="@/assets/login_images/QQ.png" alt="">
|
||||
</div>
|
||||
<div class="other-login-item">
|
||||
<img src="@/assets/login_images/WeChat.png" alt="">
|
||||
</div>
|
||||
<div class="password form-item">
|
||||
<el-form-item prop="password">
|
||||
<span>密码</span>
|
||||
<input
|
||||
type="password"
|
||||
class="input-item"
|
||||
v-model="loginForm.password"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<RouterLink to="/register"> 没有账号?前往注册</RouterLink>
|
||||
<button class="login-btn" @click="login(loginFormRef)">登 录</button>
|
||||
<button class="login-btn" @click="guestlogin">游客临时登录</button>
|
||||
</div>
|
||||
<!-- <h2> 登录-欢迎</h2>
|
||||
|
||||
<div class="divider">
|
||||
<span class="line"></span>
|
||||
<span class="divider-text">其他方式登录</span>
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
|
||||
<div class="other-login-wrapper">
|
||||
<div class="other-login-item">
|
||||
<img src="@/assets/login_images/QQ.png" alt="" />
|
||||
</div>
|
||||
<div class="other-login-item">
|
||||
<img src="@/assets/login_images/WeChat.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <h2> 登录-欢迎</h2>
|
||||
<el-input v-model="loginForm.userName" placeholder="用户名" />
|
||||
<el-input v-model="loginForm.password" placeholder="密码" show-password />
|
||||
<el-button class="login-btn" type="primary" @click="login">登录</el-button>
|
||||
@@ -49,53 +52,51 @@
|
||||
<el-button class="login-btn" type="primary" @click="guestlogin">游客临时登录</el-button> -->
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import useUserStore from '@/stores/user.js'
|
||||
import { ref, reactive } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import useUserStore from "@/stores/user.js";
|
||||
import useConfigStore from "@/stores/config";
|
||||
const configStore= useConfigStore();
|
||||
import useAuths from "@/hooks/useAuths";
|
||||
const configStore = useConfigStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const { loginFun } = useAuths();
|
||||
|
||||
const loginFormRef = ref();
|
||||
const rules = reactive({
|
||||
userName: [
|
||||
{ required: true, message: '请输入账号名', trigger: 'blur' },
|
||||
{ min: 3, message: '至少大于等于3位', trigger: 'blur' },
|
||||
],
|
||||
password:[
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 3, message: '至少大于等于6位', trigger: 'blur' },
|
||||
|
||||
]})
|
||||
userName: [{ required: true, message: "请输入账号名", trigger: "blur" }],
|
||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||
});
|
||||
const loginForm = reactive({
|
||||
userName: "cc",
|
||||
password: "123456",
|
||||
uuid: "",
|
||||
code: ""
|
||||
})
|
||||
userName: "cc",
|
||||
password: "123456",
|
||||
uuid: "",
|
||||
code: "",
|
||||
});
|
||||
const guestlogin = async () => {
|
||||
loginForm.userName = "guest";
|
||||
loginForm.password = "123456"
|
||||
await userStore.login(loginForm);
|
||||
const redirect = route.query?.redirect ?? '/index'
|
||||
router.push(redirect)
|
||||
}
|
||||
const login = async () => {
|
||||
const response = await userStore.login(loginForm).catch((e) => {
|
||||
loginForm.password = "";
|
||||
});
|
||||
if (response!=undefined) {
|
||||
loginForm.userName = "guest";
|
||||
loginForm.password = "123456";
|
||||
await userStore.login(loginForm);
|
||||
const redirect = route.query?.redirect ?? "/index";
|
||||
router.push(redirect);
|
||||
};
|
||||
const login = async (formEl) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
loginFun(loginForm);
|
||||
} catch (error) {
|
||||
ElMessage({
|
||||
message: `您好${loginForm.userName},登录成功!`,
|
||||
type: 'success',
|
||||
})
|
||||
|
||||
const redirect = route.query?.redirect ?? '/index'
|
||||
router.push(redirect)
|
||||
|
||||
message: error.message,
|
||||
type: "error",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style src="@/assets/styles/login.scss" scoped></style>
|
||||
|
||||
Reference in New Issue
Block a user