diff --git a/.eslintrc.js b/.eslintrc.js
index 737bdb9..4316764 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -35,5 +35,6 @@ module.exports = {
'no-debugger': 'off', // 关闭debugger警告
'vue/multi-word-component-names': 0, // 关闭文件名多单词
// 'import/no-unresolved': ['error', { ignore: ['~icons/*'] }],
+ "@typescript-eslint/no-explicit-any": ["off"]
},
};
diff --git a/mock/module/user.ts b/mock/module/user.ts
index 47b1c24..6195bd7 100644
--- a/mock/module/user.ts
+++ b/mock/module/user.ts
@@ -1,23 +1,17 @@
import Mock from 'mockjs';
-function resultSuccess(data: any, { msg = 'success' } = {}) {
- return Mock.mock({
- code: 200,
- data,
- msg,
- });
-}
+import { resultSuccess } from '../utils';
const Random = Mock.Random;
const token = Random.string('upper', 32, 32);
-const adminInfo = {
+const userInfo = {
userId: '1',
- username: 'admin',
- realName: 'Admin',
- avatar: Random.image(),
- desc: 'manager',
- password: Random.string('upper', 4, 16),
+ userName: 'admin',
+ realName: '管理员大人',
+ avatar: 'https://z3.ax1x.com/2021/10/29/5jnWgf.jpg',
+ role: 'admin',
+ password: '123456',
token,
permissions: [
{
@@ -28,18 +22,6 @@ const adminInfo = {
label: '监控页',
value: 'dashboard_monitor',
},
- {
- label: '工作台',
- value: 'dashboard_workplace',
- },
- {
- label: '基础列表',
- value: 'basic_list',
- },
- {
- label: '基础列表删除',
- value: 'basic_list_delete',
- },
],
};
@@ -49,17 +31,7 @@ export default [
timeout: 1000,
method: 'post',
response: () => {
- return resultSuccess({ token });
- },
- },
- {
- url: '/mock/admin_info',
- timeout: 1000,
- method: 'get',
- response: () => {
- // const token = getRequestToken(request);
- // if (!token) return resultError('Invalid token');
- return resultSuccess(adminInfo);
+ return resultSuccess(userInfo);
},
},
];
diff --git a/mock/utils.ts b/mock/utils.ts
new file mode 100644
index 0000000..3f52471
--- /dev/null
+++ b/mock/utils.ts
@@ -0,0 +1,16 @@
+import Mock from 'mockjs';
+
+export function resultSuccess(data: any, { msg = 'success' } = {}) {
+ return Mock.mock({
+ code: 200,
+ data,
+ msg,
+ });
+}
+export function resultFailed(data: any, { msg = 'failed' } = {}) {
+ return Mock.mock({
+ code: 400,
+ data,
+ msg,
+ });
+}
diff --git a/src/enum/common.ts b/src/enum/common.ts
new file mode 100644
index 0000000..09adeed
--- /dev/null
+++ b/src/enum/common.ts
@@ -0,0 +1,5 @@
+/* 缓存的Key值 */
+export enum EnumStorageKey {
+ userInfo = '__USER_INFO__',
+ token = '__TOKEN__',
+}
diff --git a/src/enum/index.ts b/src/enum/index.ts
new file mode 100644
index 0000000..d0b9323
--- /dev/null
+++ b/src/enum/index.ts
@@ -0,0 +1 @@
+export * from './common';
diff --git a/src/layouts/BasicLayout/index.vue b/src/layouts/BasicLayout/index.vue
index 4fe32b2..6ad0a0b 100644
--- a/src/layouts/BasicLayout/index.vue
+++ b/src/layouts/BasicLayout/index.vue
@@ -4,7 +4,7 @@
-
+
@@ -30,7 +30,7 @@
-
+
{{ appStore.footerText }}
diff --git a/src/layouts/components/header/UserCenter.vue b/src/layouts/components/header/UserCenter.vue
index 4bd94d9..d3d1dc6 100644
--- a/src/layouts/components/header/UserCenter.vue
+++ b/src/layouts/components/header/UserCenter.vue
@@ -1,5 +1,5 @@
-
+
{{ authStore.name }}
diff --git a/src/router/guard/index.ts b/src/router/guard/index.ts
index 87b8184..6f2371f 100644
--- a/src/router/guard/index.ts
+++ b/src/router/guard/index.ts
@@ -1,7 +1,22 @@
import type { Router } from 'vue-router';
+import { getToken } from '@/utils/auth';
+
+// const authStore = useAuthStore();
export function setupRouterGuard(router: Router) {
- router.beforeEach((_to, _from, next) => {
+ const isLogin = Boolean(getToken());
+
+ router.beforeEach((to, _from, next) => {
+ // 登录鉴权
+ if (!isLogin) {
+ if (to.name === 'login') {
+ next();
+ } else {
+ const redirect = to.fullPath;
+ next({ path: '/login', query: { redirect } });
+ }
+ return false;
+ }
next();
});
// router.afterEach((_to) => {});
diff --git a/src/router/index.ts b/src/router/index.ts
index 137b9bc..8ef29d8 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -41,7 +41,7 @@ const routes: RouteRecordRaw[] = [
},
{
path: '/login',
- name: 'Login',
+ name: 'login',
component: () => import('@/views/login/index.vue'), // 注意这里要带上 文件后缀.vue
},
{
diff --git a/src/service/api/index.ts b/src/service/api/index.ts
deleted file mode 100644
index 6cc1e6e..0000000
--- a/src/service/api/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './login';
diff --git a/src/service/api/login.ts b/src/service/api/login.ts
index 0dff09a..dff010c 100644
--- a/src/service/api/login.ts
+++ b/src/service/api/login.ts
@@ -1,30 +1,9 @@
-import { request } from '../http';
import { mockRequest } from '../http';
-interface Itest {
- data: string;
+interface Ilogin {
+ userName: string;
+ password: string;
}
-/* get方法测试 */
-export function fetachGet() {
- return request.get('/getAPI');
-}
-/* post方法测试 */
-export function fetachPost(params: Itest) {
- return request.post('/postAPI', params);
-}
-/* delete方法测试 */
-export function fetachDelete() {
- return request.Delete('/deleteAPI');
-}
-/* put方法测试 */
-export function fetachPut(params: Itest) {
- return request.put('/putAPI', params);
-}
-/* patch方法测试 */
-export function fetachPatch(params: Itest) {
- return request.patch('/patchAPI', params);
-}
-/* mock方法测试 */
-export function fetchMock() {
- return mockRequest.post('/login');
+export function fetchLogin(params: Ilogin) {
+ return mockRequest.post('/login', params);
}
diff --git a/src/service/api/test.ts b/src/service/api/test.ts
new file mode 100644
index 0000000..0dff09a
--- /dev/null
+++ b/src/service/api/test.ts
@@ -0,0 +1,30 @@
+import { request } from '../http';
+import { mockRequest } from '../http';
+
+interface Itest {
+ data: string;
+}
+/* get方法测试 */
+export function fetachGet() {
+ return request.get('/getAPI');
+}
+/* post方法测试 */
+export function fetachPost(params: Itest) {
+ return request.post('/postAPI', params);
+}
+/* delete方法测试 */
+export function fetachDelete() {
+ return request.Delete('/deleteAPI');
+}
+/* put方法测试 */
+export function fetachPut(params: Itest) {
+ return request.put('/putAPI', params);
+}
+/* patch方法测试 */
+export function fetachPatch(params: Itest) {
+ return request.patch('/patchAPI', params);
+}
+/* mock方法测试 */
+export function fetchMock() {
+ return mockRequest.post('/login');
+}
diff --git a/src/service/index.ts b/src/service/index.ts
new file mode 100644
index 0000000..3734566
--- /dev/null
+++ b/src/service/index.ts
@@ -0,0 +1,2 @@
+export * from './api/test';
+export * from './api/login';
diff --git a/src/store/modules/auth.ts b/src/store/modules/auth.ts
index df667f9..bd32a4b 100644
--- a/src/store/modules/auth.ts
+++ b/src/store/modules/auth.ts
@@ -1,9 +1,55 @@
import { defineStore } from 'pinia';
+import { fetchLogin } from '@/service';
+import { setUserInfo, getUserInfo, getToken, setToken } from '@/utils/auth';
+import { router } from '@/router';
export const useAuthStore = defineStore('auth-store', {
state: () => {
return {
- name: '张三',
+ userInfo: getUserInfo(),
+ token: getToken(),
+ loginLoading: false,
};
},
+ getters: {
+ /** 是否登录 */
+ isLogin(state) {
+ return Boolean(state.token);
+ },
+ },
+ actions: {
+ /* 用户登录 */
+ async login(userName: string, password: string) {
+ this.loginLoading = true;
+ const data = await fetchLogin({ userName, password });
+
+ // 处理登录信息
+ this.handleAfterLogin(data as any);
+
+ this.loginLoading = false;
+ },
+ handleAfterLogin(data: Auth.UserInfo) {
+ // 存储用户信息
+ setUserInfo(data);
+ setToken(data.token);
+ this.userInfo = data;
+ this.token = data.token;
+
+ // 触发用户提示
+ window.$notification?.success({
+ title: '登录成功!',
+ content: `欢迎回来,${this.userInfo.realName}!`,
+ duration: 3000,
+ });
+
+ // 进行跳转
+ const route = router.currentRoute;
+ const { query } = route.value;
+ if (query?.redirect) {
+ router.push(query.redirect as string);
+ } else {
+ router.push('/');
+ }
+ },
+ },
});
diff --git a/src/types/api.d.ts b/src/types/api.d.ts
new file mode 100644
index 0000000..710fd28
--- /dev/null
+++ b/src/types/api.d.ts
@@ -0,0 +1,7 @@
+/* 接口类型数据 */
+
+/** 后端返回的用户相关类型 */
+declare namespace ApiAuth {
+ /** 返回的用户信息 */
+ type UserInfo = Auth.UserInfo;
+}
diff --git a/src/types/business.d.ts b/src/types/business.d.ts
new file mode 100644
index 0000000..a06d2ee
--- /dev/null
+++ b/src/types/business.d.ts
@@ -0,0 +1,31 @@
+/** 用户相关模块 */
+declare namespace Auth {
+ /**
+ * 用户角色类型(前端静态路由用角色类型进行路由权限的控制)
+ * - super: 超级管理员(该权限具有所有路由数据)
+ * - admin: 管理员
+ * - user: 用户
+ * - custom: 自定义角色
+ */
+ // type RoleType = keyof typeof import('@/enum').EnumUserRole;
+
+ /** 用户信息 */
+ interface UserInfo {
+ /** 用户id */
+ userId: string;
+ /** 用户名 */
+ userName: string;
+ /* 用户称呼 */
+ realName: string;
+ /* 用户头像 */
+ avatar: string;
+ /** 用户角色类型 */
+ role: RoleType;
+ /* 密码 */
+ password: string;
+ /* token */
+ token: string;
+ /* 权限路由 */
+ permissions: [];
+ }
+}
diff --git a/src/utils/auth.ts b/src/utils/auth.ts
new file mode 100644
index 0000000..7dcd2af
--- /dev/null
+++ b/src/utils/auth.ts
@@ -0,0 +1,34 @@
+import { setLocal, getLocal, removeLocal } from './storage';
+import { EnumStorageKey } from '@/enum';
+
+/* 获取当前token */
+export function getToken() {
+ return getLocal(EnumStorageKey.token);
+}
+/* 设置token */
+export function setToken(data: string) {
+ setLocal(EnumStorageKey.token, data);
+}
+/* 移除token */
+export function removeToken() {
+ removeLocal(EnumStorageKey.token);
+}
+
+/* 获取用户详情 */
+export function getUserInfo() {
+ return getLocal(EnumStorageKey.userInfo);
+}
+/* 设置用户详情 */
+export function setUserInfo(data: any) {
+ setLocal(EnumStorageKey.userInfo, data);
+}
+/* 移除用户详情 */
+export function removeUserInfo() {
+ removeLocal(EnumStorageKey.userInfo);
+}
+
+/** 去除用户相关缓存 */
+export function clearAuthStorage() {
+ removeToken();
+ removeUserInfo();
+}
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
index cfe55e7..52933d3 100644
--- a/src/views/login/index.vue
+++ b/src/views/login/index.vue
@@ -1,12 +1,12 @@
-
-
+
+
-
+
-
+
Ench Admin
高效、简约、可能对你有点帮助
@@ -52,7 +52,7 @@
记住我
忘记密码?
-
登录
+
登录
其他登录
@@ -63,16 +63,15 @@
diff --git a/src/views/test/test1.vue b/src/views/test/test1.vue
index bd8c39f..ffe3771 100644
--- a/src/views/test/test1.vue
+++ b/src/views/test/test1.vue
@@ -15,7 +15,7 @@