first commit
This commit is contained in:
294
frontend/src/utils/api.ts
Normal file
294
frontend/src/utils/api.ts
Normal file
@@ -0,0 +1,294 @@
|
||||
import axios, { AxiosInstance, AxiosResponse } from 'axios'
|
||||
import { userAuth, adminAuth } from './auth'
|
||||
|
||||
// API基础配置
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api'
|
||||
|
||||
// 创建axios实例
|
||||
const api: AxiosInstance = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
// 请求拦截器 - 添加认证token
|
||||
api.interceptors.request.use(
|
||||
(config) => {
|
||||
// 优先使用管理员token,如果没有则使用用户token
|
||||
let token = adminAuth.getToken()
|
||||
if (!token) {
|
||||
token = userAuth.getToken()
|
||||
}
|
||||
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
} else {
|
||||
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截器 - 处理认证错误
|
||||
api.interceptors.response.use(
|
||||
(response: AxiosResponse) => {
|
||||
return response
|
||||
},
|
||||
(error) => {
|
||||
if (error.response?.status === 401) {
|
||||
// Token过期或无效,清除所有认证状态
|
||||
userAuth.logout()
|
||||
adminAuth.logout()
|
||||
|
||||
// 自动重定向到登录页面(如果不是已经在登录页面)
|
||||
if (window.location.pathname !== '/' && window.location.pathname !== '/login') {
|
||||
window.location.href = '/'
|
||||
}
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// 用户认证API
|
||||
export const authAPI = {
|
||||
// 用户注册
|
||||
async register(data: {
|
||||
username: string
|
||||
password: string
|
||||
confirmPassword: string
|
||||
}) {
|
||||
// 只发送后端需要的字段
|
||||
const requestData = {
|
||||
username: data.username,
|
||||
password: data.password,
|
||||
confirmPassword: data.confirmPassword
|
||||
}
|
||||
|
||||
const response = await api.post('/auth/register', requestData)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 用户登录
|
||||
async login(data: {
|
||||
username: string
|
||||
password: string
|
||||
}) {
|
||||
try {
|
||||
const response = await api.post('/auth/login', data)
|
||||
return response.data
|
||||
} catch (error: any) {
|
||||
throw error
|
||||
}
|
||||
},
|
||||
|
||||
// 邮箱验证
|
||||
async verifyEmail(token: string) {
|
||||
const response = await api.post('/auth/verify-email', { token })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 重新发送验证邮件
|
||||
async resendVerification(email: string) {
|
||||
const response = await api.post('/auth/resend-verification', { email })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 忘记密码
|
||||
async forgotPassword(email: string) {
|
||||
const response = await api.post('/auth/forgot-password', { email })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 重置密码
|
||||
async resetPassword(data: {
|
||||
token: string
|
||||
password: string
|
||||
}) {
|
||||
const response = await api.post('/auth/reset-password', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 设置TOTP
|
||||
async setupTOTP() {
|
||||
const response = await api.post('/auth/setup-totp')
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 验证TOTP
|
||||
async verifyTOTP(token: string) {
|
||||
const response = await api.post('/auth/verify-totp', { token })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
async getProfile() {
|
||||
const response = await api.get('/auth/me')
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 更新用户信息
|
||||
async updateProfile(data: {
|
||||
username?: string
|
||||
email?: string
|
||||
currentPassword?: string
|
||||
newPassword?: string
|
||||
}) {
|
||||
const response = await api.put('/auth/profile', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 用户登出
|
||||
async logout() {
|
||||
const response = await api.post('/auth/logout')
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取TOTP二维码
|
||||
async getTOTPQRCode() {
|
||||
const response = await api.get('/auth/totp/qr-code')
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 启用TOTP
|
||||
async enableTOTP(token: string) {
|
||||
const response = await api.post('/auth/totp/enable', { token })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 禁用TOTP
|
||||
async disableTOTP(password: string) {
|
||||
const response = await api.post('/auth/totp/disable', { password })
|
||||
return response.data
|
||||
}
|
||||
}
|
||||
|
||||
// 账号管理API
|
||||
export const accountAPI = {
|
||||
// 获取用户可用账号
|
||||
async getUserAccounts() {
|
||||
const response = await api.get('/accounts/user/assigned')
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取账号详情
|
||||
async getAccountDetails(accountId: string) {
|
||||
const response = await api.get(`/accounts/${accountId}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 登录到网站
|
||||
async loginToWebsite(accountId: string, userId: string) {
|
||||
const response = await api.post(`/accounts/${accountId}/login`, { userId })
|
||||
return response.data
|
||||
}
|
||||
}
|
||||
|
||||
// 管理员API
|
||||
export const adminAPI = {
|
||||
// 管理员登录
|
||||
async login(data: { username: string; password: string }) {
|
||||
const response = await api.post('/admin/login', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取用户列表
|
||||
async getUsers(params?: { page?: number; limit?: number; search?: string }) {
|
||||
const response = await api.get('/admin/users', { params })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 创建用户
|
||||
async createUser(data: {
|
||||
username: string
|
||||
password: string
|
||||
role: string
|
||||
}) {
|
||||
const response = await api.post('/admin/users', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 更新用户
|
||||
async updateUser(userId: string, data: any) {
|
||||
const response = await api.put(`/admin/users/${userId}`, data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 更新用户账号权限
|
||||
async updateUserAccounts(userId: string, accountIds: string[]) {
|
||||
const response = await api.put(`/admin/users/${userId}/accounts`, { accountIds })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 删除用户
|
||||
async deleteUser(userId: string) {
|
||||
const response = await api.delete(`/admin/users/${userId}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取统计数据
|
||||
async getStats() {
|
||||
console.log('发送获取统计数据请求...')
|
||||
const response = await api.get('/admin/stats')
|
||||
console.log('统计数据API响应:', response.data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取最近活动
|
||||
async getRecentActivities() {
|
||||
console.log('发送获取最近活动请求...')
|
||||
const response = await api.get('/admin/activities')
|
||||
console.log('最近活动API响应:', response.data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取账号列表
|
||||
async getAccounts(params?: { page?: number; limit?: number; search?: string; status?: string }) {
|
||||
const response = await api.get('/admin/accounts', { params })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 创建账号
|
||||
async createAccount(data: {
|
||||
website: string
|
||||
username: string
|
||||
token?: string
|
||||
isActive: boolean
|
||||
}) {
|
||||
const requestData = {
|
||||
website: data.website,
|
||||
accountName: data.username,
|
||||
token: data.token,
|
||||
isActive: data.isActive
|
||||
}
|
||||
const response = await api.post('/admin/accounts', requestData)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 更新账号
|
||||
async updateAccount(accountId: string, data: any) {
|
||||
const response = await api.put(`/admin/accounts/${accountId}`, data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 删除账号
|
||||
async deleteAccount(accountId: string) {
|
||||
const response = await api.delete(`/admin/accounts/${accountId}`)
|
||||
return response.data
|
||||
}
|
||||
}
|
||||
|
||||
// 路径API
|
||||
export const pathAPI = {
|
||||
// 获取路径
|
||||
async getPaths() {
|
||||
const response = await api.get('/paths')
|
||||
return response.data
|
||||
}
|
||||
}
|
||||
|
||||
export default api
|
||||
96
frontend/src/utils/auth.ts
Normal file
96
frontend/src/utils/auth.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
// 认证工具函数
|
||||
|
||||
// 用户认证相关
|
||||
export const userAuth = {
|
||||
// 检查用户是否已登录
|
||||
isLoggedIn(): boolean {
|
||||
return !!localStorage.getItem('userToken')
|
||||
},
|
||||
|
||||
// 获取用户token
|
||||
getToken(): string | null {
|
||||
return localStorage.getItem('userToken')
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
getUserInfo(): any {
|
||||
const userInfo = localStorage.getItem('userInfo')
|
||||
return userInfo ? JSON.parse(userInfo) : null
|
||||
},
|
||||
|
||||
// 设置用户登录状态
|
||||
setLogin(token: string, userInfo: any): void {
|
||||
localStorage.setItem('userToken', token)
|
||||
localStorage.setItem('userInfo', JSON.stringify(userInfo))
|
||||
},
|
||||
|
||||
// 清除用户登录状态
|
||||
logout(): void {
|
||||
localStorage.removeItem('userToken')
|
||||
localStorage.removeItem('userInfo')
|
||||
}
|
||||
}
|
||||
|
||||
// 管理员认证相关
|
||||
export const adminAuth = {
|
||||
// 检查管理员是否已登录
|
||||
isLoggedIn(): boolean {
|
||||
return !!localStorage.getItem('adminToken')
|
||||
},
|
||||
|
||||
// 获取管理员token
|
||||
getToken(): string | null {
|
||||
return localStorage.getItem('adminToken')
|
||||
},
|
||||
|
||||
// 获取管理员信息
|
||||
getAdminInfo(): any {
|
||||
try {
|
||||
const adminInfo = localStorage.getItem('adminUser')
|
||||
return adminInfo ? JSON.parse(adminInfo) : null
|
||||
} catch (error) {
|
||||
console.error('解析管理员信息失败:', error)
|
||||
// 清除可能损坏的数据
|
||||
localStorage.removeItem('adminUser')
|
||||
return null
|
||||
}
|
||||
},
|
||||
|
||||
// 设置管理员登录状态
|
||||
setLogin(token: string, adminInfo: any): void {
|
||||
try {
|
||||
if (!token || !adminInfo) {
|
||||
console.error('设置管理员登录状态失败:token 或 adminInfo 为空')
|
||||
return
|
||||
}
|
||||
|
||||
if (!adminInfo.username) {
|
||||
console.error('设置管理员登录状态失败:adminInfo 缺少 username 字段')
|
||||
return
|
||||
}
|
||||
|
||||
localStorage.setItem('adminToken', token)
|
||||
localStorage.setItem('adminUser', JSON.stringify(adminInfo))
|
||||
console.log('管理员登录状态设置成功:', { token, adminInfo })
|
||||
} catch (error) {
|
||||
console.error('设置管理员登录状态失败:', error)
|
||||
}
|
||||
},
|
||||
|
||||
// 清除管理员登录状态
|
||||
logout(): void {
|
||||
localStorage.removeItem('adminToken')
|
||||
localStorage.removeItem('adminUser')
|
||||
}
|
||||
}
|
||||
|
||||
// 验证管理员凭据
|
||||
export const validateAdminCredentials = (username: string, password: string): boolean => {
|
||||
// 这里可以扩展为从API验证
|
||||
const validCredentials = {
|
||||
username: 'admin',
|
||||
password: 'admin123'
|
||||
}
|
||||
|
||||
return username === validCredentials.username && password === validCredentials.password
|
||||
}
|
||||
Reference in New Issue
Block a user