Browse Source

增加登录

master
xyiege 3 weeks ago
parent
commit
ba1311ae59
  1. 12
      vue/afvue/src/components/nprogress.css
  2. 2
      vue/afvue/src/main.js
  3. 32
      vue/afvue/src/permission.js
  4. 171
      vue/afvue/src/stores/auth.js
  5. 31
      vue/afvue/src/stores/user.js
  6. 10
      vue/afvue/src/views/Login.vue

12
vue/afvue/src/components/NProgress/nprogress.less → vue/afvue/src/components/nprogress.css

@ -1,4 +1,3 @@
@import url('../index.less');
/* Make clicks pass-through */
#nprogress {
@ -6,8 +5,8 @@
}
#nprogress .bar {
background: @primary-color;
/* background: @primary-color; */
background-color: rgb(224, 89, 82);
position: fixed;
z-index: 1031;
top: 0;
@ -24,7 +23,8 @@
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color;
/* box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color; */
box-shadow: 0 0 10px rgb(224, 89, 82), 0 0 5px rgb(220, 215, 215);
opacity: 1.0;
-webkit-transform: rotate(3deg) translate(0px, -4px);
@ -47,8 +47,8 @@
box-sizing: border-box;
border: solid 2px transparent;
border-top-color: @primary-color;
border-left-color: @primary-color;
border-top-color: rgb(224, 89, 82);
border-left-color: rgb(224, 89, 82);
border-radius: 50%;
-webkit-animation: nprogress-spinner 400ms linear infinite;

2
vue/afvue/src/main.js

@ -3,6 +3,8 @@ import { createPinia, PiniaVuePlugin } from 'pinia'
import { VueAxios } from './utils/request'
import App from './App.vue'
import router from './router'
// 导入权限控制模块
import './permission'
import './assets/main.css'

32
vue/afvue/src/permission.js

@ -0,0 +1,32 @@
import router from './router'
import { userStStore } from './stores/user'
import NProgress from 'nprogress' // progress bar
import '@/components/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false }) // NProgress Configuration
// 登录页面
const loginRoutePath = '/login'
// 白名单
const whiteList = [loginRoutePath, '/404', '/401']
// 路由守卫
// router.beforeEach((to, from, next) => {
// NProgress.start() // start progress bar
// // 获取用户store实例
// const userStore = userStStore()
// console.log(userStore.token,"user token")
// // 检查token
// console.log("check token")
// })
// 路由守卫
router.afterEach((to, from) => {
NProgress.done() // finish progress bar
})

171
vue/afvue/src/stores/auth.js

@ -0,0 +1,171 @@
import { defineStore } from 'pinia'
import { api } from '@/api/axios' // 你的 API 配置
export const useAuthStore = defineStore('auth', {
state: () => ({
// 用户信息
user: null,
// 令牌
token: localStorage.getItem('token') || null,
// 登录状态
isLoggedIn: !!localStorage.getItem('token'),
// 加载状态
isLoading: false,
// 错误信息
error: null
}),
getters: {
// 用户基本信息
userInfo: (state) => state.user,
// 用户名
userName: (state) => state.user?.username || state.user?.name || '用户',
// 用户角色
userRole: (state) => state.user?.role || '',
// 是否有特定权限
hasPermission: (state) => (permission) => {
return state.user?.permissions?.includes(permission) || false
},
// 是否是管理员
isAdmin: (state) => state.user?.role === 'admin'
},
actions: {
/**
* 用户登录
*/
async login(credentials) {
this.isLoading = true
this.error = null
try {
const response = await api.post('/auth/login', credentials)
const { user, token } = response.data
// 保存用户信息和令牌
this.user = user
this.token = token
this.isLoggedIn = true
// 保存到 localStorage
localStorage.setItem('token', token)
localStorage.setItem('user', JSON.stringify(user))
// 设置 axios 默认授权头
api.defaults.headers.common['Authorization'] = `Bearer ${token}`
this.isLoading = false
return { success: true, user }
} catch (error) {
this.isLoading = false
this.error = error.response?.data?.message || '登录失败'
return { success: false, error: this.error }
}
},
/**
* 用户注册
*/
async register(userData) {
this.isLoading = true
this.error = null
try {
const response = await api.post('/auth/register', userData)
const { user, token } = response.data
// 自动登录
this.user = user
this.token = token
this.isLoggedIn = true
localStorage.setItem('token', token)
localStorage.setItem('user', JSON.stringify(user))
api.defaults.headers.common['Authorization'] = `Bearer ${token}`
this.isLoading = false
return { success: true, user }
} catch (error) {
this.isLoading = false
this.error = error.response?.data?.message || '注册失败'
return { success: false, error: this.error }
}
},
/**
* 用户退出登录
*/
logout() {
this.user = null
this.token = null
this.isLoggedIn = false
this.error = null
// 清除 localStorage
localStorage.removeItem('token')
localStorage.removeItem('user')
// 移除 axios 授权头
delete api.defaults.headers.common['Authorization']
// 可以在这里跳转到登录页
if (this.router) {
this.router.push('/login')
}
},
/**
* 检查登录状态页面刷新时调用
*/
async checkAuth() {
const token = localStorage.getItem('token')
const userData = localStorage.getItem('user')
if (token && userData) {
try {
// 验证 token 是否有效
const response = await api.get('/auth/me')
this.user = response.data.user
this.token = token
this.isLoggedIn = true
api.defaults.headers.common['Authorization'] = `Bearer ${token}`
} catch (error) {
// token 无效,清除状态
this.logout()
}
}
},
/**
* 更新用户信息
*/
async updateUser(userData) {
try {
const response = await api.put('/auth/profile', userData)
this.user = { ...this.user, ...response.data.user }
// 更新 localStorage
localStorage.setItem('user', JSON.stringify(this.user))
return { success: true, user: this.user }
} catch (error) {
this.error = error.response?.data?.message || '更新失败'
return { success: false, error: this.error }
}
},
/**
* 清除错误信息
*/
clearError() {
this.error = null
},
/**
* 设置路由实例用于退出登录后跳转
*/
setRouter(router) {
this.router = router
}
}
})

31
vue/afvue/src/stores/user.js

@ -0,0 +1,31 @@
import { defineStore } from 'pinia';
export const userStStore = defineStore('user', {
state: () => {
return {
token: null, // 存储用户token
user: null, // 存储用户对象
isLoggedIn: false // 用户登录状态
};
},
getters: {
getUser: (state) => state.user,
getIsLoggedIn: (state) => state.isLoggedIn,
token: (state) => state.token
},
actions: {
setUser(user) {
this.user = user;
this.isLoggedIn = true;
},
logout() {
this.token = null
this.user = null;
this.isLoggedIn = false;
},
setToken(token) {
// this.token = token;
console.log("set token")
}
},
});

10
vue/afvue/src/views/Login.vue

@ -22,6 +22,7 @@
import { login } from '@/api/scinfo'
import storage from 'store'
import router from '@/router'
import { useUserStore } from '@/stores/user'
export default {
name: 'Login',
@ -53,6 +54,15 @@ export default {
if (res && res.data && res.data.token) {
// tokenlocalStorage
storage.set('token', res.data.token)
// 使Pinia store
const userStore = useUserStore()
userStore.setUser({
username: this.username,
token: res.data.token,
...(res.data.userInfo || {})
})
//
router.push('/')
} else {

Loading…
Cancel
Save