diff --git a/mock/module/user.ts b/mock/module/user.ts index f8e9af0..3398027 100644 --- a/mock/module/user.ts +++ b/mock/module/user.ts @@ -1,17 +1,36 @@ import Mock from 'mockjs'; -import { resultSuccess } from '../utils'; +import { resultSuccess, resultFailed } from '../utils'; const Random = Mock.Random; const token = () => Random.string('upper', 32, 32); -const userInfo = { - userId: 1, - userName: 'iamsee', - realName: '管理员大人', - avatar: 'https://z3.ax1x.com/2021/10/29/5jnWgf.jpg', - role: "super", -}; +const userData = [ + { + userId: 1, + userName: 'super', + password: '123456', + nickName: '超级管理员大人', + avatar: 'https://z3.ax1x.com/2021/10/29/5jnWgf.jpg', + role: 'super', + }, + { + userId: 2, + userName: 'admin', + password: '123456', + nickName: '管理员大人', + avatar: 'https://z3.ax1x.com/2021/10/29/5jnWgf.jpg', + role: 'admin', + }, + { + userId: 3, + userName: 'user', + password: '123456', + nickName: '用户大人', + avatar: 'https://z3.ax1x.com/2021/10/29/5jnWgf.jpg', + role: 'user', + }, +]; const userRoutes = [ { name: 'dashboard', @@ -312,7 +331,7 @@ const userRoutes = [ icon: 'icon-park-outline:wrong-user', }, }, - ] + ], }, { name: 'error', @@ -322,7 +341,6 @@ const userRoutes = [ title: '异常页', requiresAuth: true, icon: 'icon-park-outline:error-computer', - }, children: [ { @@ -425,15 +443,32 @@ const userRoutes = [ export default [ { url: '/mock/login', - timeout: 1000, method: 'post', - response: () => { - return resultSuccess({ token: token(), refreshToken: token() }); + response: (options: any) => { + const { userName = undefined, password = undefined } = options.body; + + if (!userName || !password) { + return resultFailed(null, '账号密码不全'); + } + + const userInfo = userData.find((item) => item.userName === userName && item.password === password); + + if (userInfo) { + return { + code: 200, + message: 'ok', + data: { + userId: userInfo.userId, + token: token(), + refreshToken: token(), + }, + }; + } + return resultFailed(null, '账号密码错误'); }, }, { url: '/mock/updateToken', - timeout: 1000, method: 'post', response: () => { return resultSuccess({ token: token(), refreshToken: token() }); @@ -441,15 +476,21 @@ export default [ }, { url: '/mock/getUserInfo', - timeout: 1000, method: 'get', - response: () => { - return resultSuccess(userInfo); + response: (options: any) => { + const { userId = undefined } = options.query; + if (!userId) { + return resultFailed(null, '未传入用户id!'); + } + const userInfo = userData.find((item) => item.userId == userId); + if (userInfo) { + return resultSuccess(userInfo); + } + return resultFailed(null, '未找到用户信息,请检查提交参数'); }, }, { url: '/mock/getUserRoutes', - timeout: 1000, method: 'post', response: () => { return resultSuccess(userRoutes); diff --git a/mock/utils.ts b/mock/utils.ts index 3f52471..174e22b 100644 --- a/mock/utils.ts +++ b/mock/utils.ts @@ -1,16 +1,16 @@ import Mock from 'mockjs'; -export function resultSuccess(data: any, { msg = 'success' } = {}) { +export function resultSuccess(data: any, msg?:string ) { return Mock.mock({ code: 200, data, - msg, + msg: msg || 'success', }); } -export function resultFailed(data: any, { msg = 'failed' } = {}) { +export function resultFailed(data: any, msg?: string ) { return Mock.mock({ - code: 400, + code: 500, data, - msg, + msg: msg || 'failed', }); } diff --git a/src/directive/index.ts b/src/directive/index.ts new file mode 100644 index 0000000..3e606a0 --- /dev/null +++ b/src/directive/index.ts @@ -0,0 +1,6 @@ +import type { App } from 'vue'; +import { setupPermission } from './permission' + +export function setupDirectives(app: App) { + setupPermission(app); +} diff --git a/src/directive/permission.ts b/src/directive/permission.ts new file mode 100644 index 0000000..96ecd83 --- /dev/null +++ b/src/directive/permission.ts @@ -0,0 +1,26 @@ +import type { App, Directive } from 'vue'; +import { usePermission } from '@/hooks'; + + +export function setupPermission(app: App) { + const { hasPermission } = usePermission(); + + function updatapermission(el: HTMLElement, permission: Auth.RoleType | Auth.RoleType[]) { + if (!permission) { + throw new Error(`v-permissson Directive with no explicit role attached`); + } + if (!hasPermission(permission)) { + el.parentElement?.removeChild(el); + } + } + + const permissionDirective: Directive = { + mounted(el, binding) { + updatapermission(el, binding.value) + }, + updated(el, binding) { + updatapermission(el, binding.value) + } + } + app.directive('permission', permissionDirective) +} \ No newline at end of file diff --git a/src/hooks/useSystem.ts b/src/hooks/useSystem.ts index 0b99a91..adb2c81 100644 --- a/src/hooks/useSystem.ts +++ b/src/hooks/useSystem.ts @@ -34,6 +34,7 @@ export function usePermission() { if (!permission) return true + if (!authStore.userInfo) return false const { role } = authStore.userInfo let has = role === 'super'; diff --git a/src/layouts/components/header/UserCenter.vue b/src/layouts/components/header/UserCenter.vue index e1a8983..0ec174d 100644 --- a/src/layouts/components/header/UserCenter.vue +++ b/src/layouts/components/header/UserCenter.vue @@ -10,7 +10,7 @@ size="large" :src="userInfo?.avatar" /> - {{ userInfo?.realName }} + {{ userInfo?.nickName }} @@ -42,7 +42,15 @@ const { userInfo, resetAuthStore } = useAuthStore(); ]; const handleSelect = (key: string | number) => { if (key === 'loginOut') { - resetAuthStore(); + window.$dialog.info({ + title: '退出登录', + content: '确认退出当前账号?', + positiveText: '确定', + negativeText: '取消', + onPositiveClick: () => { + resetAuthStore(); + }, + }) } if (key === 'userCenter') { router.push('/userCenter') diff --git a/src/main.ts b/src/main.ts index 4bb5d4f..f312d8e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,7 +4,8 @@ import AppLoading from './components/common/appLoading.vue'; import { setupRouter } from './router'; import { setupAssets } from './plugins'; import { setupStore } from './store'; - +import { setupDirectives } from './directive' + async function setupApp() { // 引入静态资源 setupAssets(); @@ -16,6 +17,8 @@ async function setupApp() { const app = createApp(App); // 安装pinia全局状态库 setupStore(app); + // 安装自定义指令 + setupDirectives(app) // 安装router await setupRouter(app); // 挂载 diff --git a/src/service/api/login.ts b/src/service/api/login.ts index 7bbc34a..823f044 100644 --- a/src/service/api/login.ts +++ b/src/service/api/login.ts @@ -11,8 +11,8 @@ export function fetchLogin(params: Ilogin) { export function fetchUpdateToken(params: any) { return mockRequest.post('/updateToken', params); } -export function fetchUserInfo() { - return mockRequest.get('/getUserInfo'); +export function fetchUserInfo(params:any) { + return mockRequest.get('/getUserInfo',{params}); } export function fetchUserRoutes(params: { userId: number }) { return mockRequest.post('/getUserRoutes', params); diff --git a/src/store/modules/auth.ts b/src/store/modules/auth.ts index d50305a..dbc6e4a 100644 --- a/src/store/modules/auth.ts +++ b/src/store/modules/auth.ts @@ -6,11 +6,19 @@ import { unref } from 'vue'; import { useRouteStore } from './route'; import { local } from '@/utils'; +const emptyInfo: Auth.UserInfo = { + userId: 0, + userName: '', + nickName: '', + avatar: '', + role: 'user', +}; export const useAuthStore = defineStore('auth-store', { state: () => { return { - userInfo: local.get('userInfo'), - token: local.get('token'), + userInfo: local.get('userInfo') || emptyInfo, + token: local.get('token') || '', + refreshToken: local.get('refreshToken') || '', loginLoading: false, }; }, @@ -44,7 +52,11 @@ export const useAuthStore = defineStore('auth-store', { /* 用户登录 */ async login(userName: string, password: string) { this.loginLoading = true; - const { data } = await fetchLogin({ userName, password }); + const { error, data } = await fetchLogin({ userName, password }); + if (error) { + this.loginLoading = false; + return; + } // 处理登录信息 await this.handleAfterLogin(data); @@ -69,41 +81,37 @@ export const useAuthStore = defineStore('auth-store', { // 触发用户提示 window.$notification?.success({ title: '登录成功!', - content: `欢迎回来😊,${this.userInfo?.realName}!`, + content: `欢迎回来😊,${this.userInfo.nickName}!`, duration: 3000, }); return; } // 如果不成功则重置存储 this.resetAuthStore(); - // 登录失败提示 - window.$notification?.error({ - title: '登录失败!', - content: `验证失败,请检查账号密码`, - duration: 3000, - }); }, /* 缓存用户信息 */ async catchUserInfo(userToken: ApiAuth.loginToken) { let catchSuccess = false; - // 先存储token - const { token, refreshToken } = userToken; - local.set('token', token); - local.set('refreshToken', refreshToken,) - - // 请求/存储用户信息 - const { data } = await fetchUserInfo(); - if (data) { - local.set('userInfo', data); + const { token, refreshToken, userId } = userToken; + const { error, data } = await fetchUserInfo({ userId }); + if (error) { + return catchSuccess; } - // 再将token和userInfo初始化 - this.userInfo = data; + // 先存储token + local.set('token', token); + local.set('refreshToken', refreshToken); this.token = token; - + this.refreshToken = refreshToken; + // 请求/存储用户信息 + local.set('userInfo', data); + this.userInfo = data; catchSuccess = true; return catchSuccess; }, + toggleUserRole(role: Auth.RoleType) { + this.login(role, '123456'); + }, }, }); diff --git a/src/typings/api.d.ts b/src/typings/api.d.ts index 883d372..0438007 100644 --- a/src/typings/api.d.ts +++ b/src/typings/api.d.ts @@ -6,9 +6,10 @@ declare namespace ApiAuth { type UserInfo = Auth.UserInfo; /* 登录token字段 */ interface loginToken { - token: string; - refreshToken: string; - } + token: string; + refreshToken: string; + userId: number; + } } declare namespace CommonList { /* 返回的性别类型 */ diff --git a/src/typings/business.d.ts b/src/typings/business.d.ts index c9d95a3..5dc3355 100644 --- a/src/typings/business.d.ts +++ b/src/typings/business.d.ts @@ -8,7 +8,7 @@ declare namespace Auth { /** 用户名 */ userName: string; /* 用户称呼 */ - realName: string; + nickName: string; /* 用户头像 */ avatar: string; /** 用户角色类型 */ diff --git a/src/typings/storage.d.ts b/src/typings/storage.d.ts index 6b6286f..0721172 100644 --- a/src/typings/storage.d.ts +++ b/src/typings/storage.d.ts @@ -5,9 +5,10 @@ declare namespace Storage { } interface Local { - userInfo: Auth.UserInfo - token: string - refreshToken: string - tabsRoutes: string - } + userInfo: Auth.UserInfo; + token: string; + refreshToken: string; + tabsRoutes: string; + login_account:any; + } } \ No newline at end of file diff --git a/src/views/dashboard/workbench/index.vue b/src/views/dashboard/workbench/index.vue index 338bad2..e7853d8 100644 --- a/src/views/dashboard/workbench/index.vue +++ b/src/views/dashboard/workbench/index.vue @@ -14,7 +14,7 @@ />

- 您好,{{ userInfo?.realName }},今天又是充满活力的一天! + 您好,{{ userInfo?.nickName }},今天又是充满活力的一天!

今日多云转晴,20℃ - 25℃! diff --git a/src/views/login/components/Login/index.vue b/src/views/login/components/Login/index.vue index a72c151..8fed9f5 100644 --- a/src/views/login/components/Login/index.vue +++ b/src/views/login/components/Login/index.vue @@ -134,8 +134,8 @@ const rules = { }, }; const formValue = ref({ - account: 'admin', - pwd: '000000', + account: 'super', + pwd: '123456', code: '1234', }); const isRemember = ref(false); diff --git a/src/views/permission/permission/index.vue b/src/views/permission/permission/index.vue index 02e0b1d..571e0b5 100644 --- a/src/views/permission/permission/index.vue +++ b/src/views/permission/permission/index.vue @@ -2,13 +2,50 @@

权限示例: 当前权限:{{ role }} + + + {{ item }} + + + v-permission 指令用法 + + + 仅super可见 + + + admin可见 + + + + usePermission 函数用法 + + + super可见 + + + admin可见 + + + admin和user可见 + +
diff --git a/src/views/userCenter/index.vue b/src/views/userCenter/index.vue index c91ed41..db5cb07 100644 --- a/src/views/userCenter/index.vue +++ b/src/views/userCenter/index.vue @@ -24,7 +24,7 @@ {{ userInfo?.userName }} - {{ userInfo?.realName }} + {{ userInfo?.nickName }} {{ userInfo?.role }}