Files
competition-website/src/stores/auth.js
WorkBuddy e8f0195b61 chore: 前端首次基线提交
运行必须源码:src/、public/、index.html、package.json 及构建配置。
已忽略运行非必须:node_modules/、dist/、.env*。
2026-08-17 12:25:42 +08:00

157 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import * as authApi from '@/api/auth'
// ==================== 认证状态管理 ====================
export const useAuthStore = defineStore('auth', () => {
// ==================== 状态 ====================
// 当前用户信息
const currentUser = ref(
JSON.parse(localStorage.getItem('user') || 'null')
)
// 认证令牌
const token = ref(localStorage.getItem('token') || '')
// ==================== 计算属性(Getters) ====================
// 是否已登录
const isLoggedIn = computed(() => !!token.value)
// 是否为管理员
const isAdmin = computed(() => {
if (!currentUser.value) return false
return (
currentUser.value.role === 'admin' ||
currentUser.value.isAdmin === true
)
})
// 用户名称(优先显示姓名,其次用户名)
const userName = computed(() => {
if (!currentUser.value) return ''
return currentUser.value.name || currentUser.value.username || ''
})
// 用户所属组别
const userGroup = computed(() => {
return currentUser.value?.group || ''
})
// ==================== 私有辅助方法 ====================
/**
* 持久化存储 token 和用户信息到 localStorage
*/
function persistAuth(tokenValue, userData) {
token.value = tokenValue
currentUser.value = userData
localStorage.setItem('token', tokenValue)
localStorage.setItem('user', JSON.stringify(userData))
}
/**
* 清除本地存储的认证信息
*/
function clearAuth() {
token.value = ''
currentUser.value = null
localStorage.removeItem('token')
localStorage.removeItem('user')
}
// ==================== 操作方法(Actions) ====================
/**
* 参赛者登录(身份证号 + 密码)
* @param {string} idNumber - 身份证号
* @param {string} password - 密码
* @returns {Promise<object>} 用户信息
*/
async function login(phone, password) {
const result = await authApi.login(phone, password)
// 后端应返回 { token, user }
persistAuth(result.token, result.user)
return result.user
}
/**
* 管理员登录
* @param {string} username - 管理员用户名
* @param {string} password - 密码
* @returns {Promise<object>} 管理员信息
*/
async function adminLogin(username, password) {
const result = await authApi.adminLogin(username, password)
// 后端应返回 { token, user }
persistAuth(result.token, result.user)
return result.user
}
/**
* 激活账号(设置密码)
* @param {object} data - { phone, password, smsCode }
* @returns {Promise}
*/
async function activate(data) {
const result = await authApi.activate(data)
// 激活成功后自动登录
if (result.token && result.user) {
persistAuth(result.token, result.user)
}
return result
}
/**
* 退出登录
*/
async function logout() {
try {
// 尝试通知后端登出
await authApi.logout()
} catch (e) {
// 即使后端请求失败,也清除本地状态
console.warn('登出请求失败,仍将清除本地状态', e)
}
clearAuth()
// 跳转到登录页
window.location.href = '/login'
}
/**
* 从服务端获取最新用户信息
* @returns {Promise<object>} 用户信息
*/
async function fetchCurrentUser() {
const user = await authApi.getCurrentUser()
currentUser.value = user
localStorage.setItem('user', JSON.stringify(user))
return user
}
// ==================== 导出 ====================
return {
// 状态
currentUser,
token,
// 计算属性
isLoggedIn,
isAdmin,
userName,
userGroup,
// 操作
login,
adminLogin,
activate,
logout,
fetchCurrentUser,
// 工具方法
clearAuth,
persistAuth,
}
})