前后端登录注册连接成功
Change-Id: Ib5f9282fe7217b3363e542ce5c4e1c0d32619dcb
diff --git a/src/api/auth.js b/src/api/auth.js
new file mode 100644
index 0000000..a3c672a
--- /dev/null
+++ b/src/api/auth.js
@@ -0,0 +1,62 @@
+import request from './request'
+
+export const authApi = {
+ /**
+ * 用户登录
+ */
+ async login(loginData) {
+ console.log('📤 发送登录数据:', loginData)
+
+ const requestData = {
+ user: loginData.user,
+ password: loginData.password
+ }
+
+ return request({
+ url: '/api/auth/login', // 需要 /api 前缀
+ method: 'post',
+ data: requestData
+ })
+ },
+
+ /**
+ * 用户注册
+ */
+ async register(registerData) {
+ console.log('📤 发送注册数据:', registerData)
+
+ const requestData = {
+ username: registerData.username,
+ email: registerData.email,
+ password: registerData.password
+ }
+
+ return request({
+ url: '/api/auth/register', // 需要 /api 前缀
+ method: 'post',
+ data: requestData
+ })
+ },
+
+ /**
+ * 用户登出
+ */
+ logout() {
+ return request({
+ url: '/api/auth/logout', // 需要 /api 前缀
+ method: 'post'
+ })
+ },
+
+ /**
+ * 获取登录状态
+ */
+ getStatus() {
+ return request({
+ url: '/api/auth/status', // 需要 /api 前缀
+ method: 'get'
+ })
+ }
+}
+
+export default authApi
\ No newline at end of file
diff --git a/src/api/index.js b/src/api/index.js
new file mode 100644
index 0000000..6a72540
--- /dev/null
+++ b/src/api/index.js
@@ -0,0 +1,219 @@
+export { authApi } from './auth'
+export { userApi } from './user'
+
+// 默认导出request实例,方便其他地方使用
+export { default as request } from './request'
+
+// ===========================================
+
+// src/store/modules/auth.js - 认证状态管理
+import { authApi } from '@/api/auth'
+import { ElMessage } from 'element-plus'
+
+const state = {
+ // 登录状态
+ isLoggedIn: false,
+ // 用户信息
+ userInfo: null,
+ // Token信息
+ token: null,
+ // 登录加载状态
+ loginLoading: false
+}
+
+const getters = {
+ // 是否已登录
+ isAuthenticated: state => state.isLoggedIn,
+ // 获取用户信息
+ userInfo: state => state.userInfo,
+ // 获取用户名
+ username: state => state.userInfo?.user?.username || '',
+ // 获取用户头像
+ avatar: state => state.userInfo?.user?.avatar || '',
+ // 获取用户组信息
+ userGroup: state => state.userInfo?.user?.group || null,
+ // 登录加载状态
+ loginLoading: state => state.loginLoading
+}
+
+const mutations = {
+ // 设置登录状态
+ SET_LOGIN_STATUS(state, status) {
+ state.isLoggedIn = status
+ },
+
+ // 设置用户信息
+ SET_USER_INFO(state, userInfo) {
+ state.userInfo = userInfo
+ },
+
+ // 设置Token
+ SET_TOKEN(state, token) {
+ state.token = token
+ },
+
+ // 设置登录加载状态
+ SET_LOGIN_LOADING(state, loading) {
+ state.loginLoading = loading
+ },
+
+ // 清除用户数据
+ CLEAR_USER_DATA(state) {
+ state.isLoggedIn = false
+ state.userInfo = null
+ state.token = null
+ state.loginLoading = false
+ }
+}
+
+const actions = {
+ // 用户登录
+ async login({ commit }, loginData) {
+ try {
+ commit('SET_LOGIN_LOADING', true)
+
+ const response = await authApi.login(loginData)
+
+ if (response) {
+ // 保存Token
+ const tokenInfo = response.token
+ if (tokenInfo && tokenInfo.tokenValue) {
+ localStorage.setItem('token', tokenInfo.tokenValue)
+ localStorage.setItem('tokenInfo', JSON.stringify(tokenInfo))
+ commit('SET_TOKEN', tokenInfo)
+ }
+
+ // 保存用户信息
+ localStorage.setItem('userInfo', JSON.stringify(response))
+ localStorage.setItem('isLoggedIn', 'true')
+
+ commit('SET_USER_INFO', response)
+ commit('SET_LOGIN_STATUS', true)
+
+ ElMessage.success('登录成功!')
+ return response
+ }
+ } catch (error) {
+ console.error('登录失败:', error)
+ throw error
+ } finally {
+ commit('SET_LOGIN_LOADING', false)
+ }
+ },
+
+ // 用户注册
+ async register({ commit }, registerData) {
+ try {
+ commit('SET_LOGIN_LOADING', true)
+
+ const response = await authApi.register(registerData)
+
+ if (response) {
+ // 注册成功后自动登录
+ const tokenInfo = response.token
+ if (tokenInfo && tokenInfo.tokenValue) {
+ localStorage.setItem('token', tokenInfo.tokenValue)
+ localStorage.setItem('tokenInfo', JSON.stringify(tokenInfo))
+ commit('SET_TOKEN', tokenInfo)
+ }
+
+ localStorage.setItem('userInfo', JSON.stringify(response))
+ localStorage.setItem('isLoggedIn', 'true')
+
+ commit('SET_USER_INFO', response)
+ commit('SET_LOGIN_STATUS', true)
+
+ ElMessage.success('注册成功!')
+ return response
+ }
+ } catch (error) {
+ console.error('注册失败:', error)
+ throw error
+ } finally {
+ commit('SET_LOGIN_LOADING', false)
+ }
+ },
+
+ // 用户登出
+ async logout({ commit }) {
+ try {
+ await authApi.logout()
+ } catch (error) {
+ console.error('登出请求失败:', error)
+ // 即使登出请求失败,也要清除本地数据
+ } finally {
+ // 清除本地存储
+ localStorage.removeItem('token')
+ localStorage.removeItem('tokenInfo')
+ localStorage.removeItem('userInfo')
+ localStorage.removeItem('isLoggedIn')
+
+ // 清除状态
+ commit('CLEAR_USER_DATA')
+
+ ElMessage.success('已退出登录')
+ }
+ },
+
+ // 检查登录状态
+ async checkLoginStatus({ commit }) {
+ try {
+ const response = await authApi.getStatus()
+
+ if (response && response.isLoggedIn && response.user) {
+ // 更新用户信息
+ localStorage.setItem('userInfo', JSON.stringify(response.user))
+ localStorage.setItem('isLoggedIn', 'true')
+
+ commit('SET_USER_INFO', response.user)
+ commit('SET_LOGIN_STATUS', true)
+
+ return true
+ } else {
+ // 登录状态无效,清除本地数据
+ commit('CLEAR_USER_DATA')
+ localStorage.removeItem('token')
+ localStorage.removeItem('tokenInfo')
+ localStorage.removeItem('userInfo')
+ localStorage.removeItem('isLoggedIn')
+
+ return false
+ }
+ } catch (error) {
+ console.error('检查登录状态失败:', error)
+ commit('CLEAR_USER_DATA')
+ return false
+ }
+ },
+
+ // 从本地存储恢复登录状态
+ restoreLoginState({ commit }) {
+ const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true'
+ const userInfo = localStorage.getItem('userInfo')
+ const tokenInfo = localStorage.getItem('tokenInfo')
+
+ if (isLoggedIn && userInfo) {
+ try {
+ const parsedUserInfo = JSON.parse(userInfo)
+ const parsedTokenInfo = tokenInfo ? JSON.parse(tokenInfo) : null
+
+ commit('SET_USER_INFO', parsedUserInfo)
+ commit('SET_TOKEN', parsedTokenInfo)
+ commit('SET_LOGIN_STATUS', true)
+
+ console.log('✅ 已从本地存储恢复登录状态')
+ } catch (error) {
+ console.error('❌ 恢复登录状态失败:', error)
+ commit('CLEAR_USER_DATA')
+ }
+ }
+ }
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ mutations,
+ actions
+}
\ No newline at end of file
diff --git a/src/api/request.js b/src/api/request.js
new file mode 100644
index 0000000..dd5aade
--- /dev/null
+++ b/src/api/request.js
@@ -0,0 +1,76 @@
+import axios from 'axios'
+import { ElMessage } from 'element-plus'
+import router from '@/router'
+
+const request = axios.create({
+ // 关键:不要设置baseURL,或者设置为空字符串
+ // 这样请求会发送到当前域名(8080),然后被代理转发到8081
+ baseURL: '',
+ timeout: 10000,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+})
+
+request.interceptors.request.use(
+ config => {
+ const token = localStorage.getItem('token')
+ if (token) {
+ config.headers.Authorization = `Bearer ${token}`
+ }
+
+ console.log('🚀 发送请求:', config.method?.toUpperCase(), config.url)
+ console.log('📤 请求数据:', config.data)
+
+ return config
+ },
+ error => {
+ console.error('❌ 请求错误:', error)
+ return Promise.reject(error)
+ }
+)
+
+request.interceptors.response.use(
+ response => {
+ console.log('✅ 响应成功:', response.status, response.data)
+ return response.data
+ },
+ error => {
+ console.error('❌ 响应错误:', error)
+
+ if (error.response) {
+ const { status, data } = error.response
+
+ switch (status) {
+ case 401:
+ localStorage.removeItem('token')
+ localStorage.removeItem('isLoggedIn')
+ localStorage.removeItem('userInfo')
+ ElMessage.error('登录已过期,请重新登录')
+ router.push('/login')
+ break
+ case 403:
+ ElMessage.error('权限不足')
+ break
+ case 404:
+ ElMessage.error('API接口不存在')
+ console.error('❌ 请求的URL:', error.config.url)
+ break
+ case 500:
+ ElMessage.error('服务器内部错误')
+ break
+ default:
+ const errorMessage = data?.message || `请求失败 (${status})`
+ ElMessage.error(errorMessage)
+ }
+ } else if (error.request) {
+ ElMessage.error('无法连接到服务器,请检查网络')
+ } else {
+ ElMessage.error('请求配置错误')
+ }
+
+ return Promise.reject(error)
+ }
+)
+
+export default request
\ No newline at end of file
diff --git a/src/api/user.js b/src/api/user.js
new file mode 100644
index 0000000..2cfb40c
--- /dev/null
+++ b/src/api/user.js
@@ -0,0 +1,115 @@
+import request from './request'
+
+export const userApi = {
+ /**
+ * 获取当前用户信息
+ * @returns {Promise<Object>} 用户信息
+ */
+ getCurrentUser() {
+ return request({
+ url: '/user/profile',
+ method: 'get'
+ })
+ },
+
+ /**
+ * 更新用户资料
+ * @param {Object} profileData - 用户资料数据
+ * @returns {Promise<Object>} 更新响应
+ */
+ updateProfile(profileData) {
+ return request({
+ url: '/user/profile',
+ method: 'put',
+ data: profileData
+ })
+ },
+
+ /**
+ * 修改密码
+ * @param {Object} passwordData - 密码数据
+ * @param {string} passwordData.currentPassword - 当前密码
+ * @param {string} passwordData.newPassword - 新密码
+ * @returns {Promise<Object>} 修改响应
+ */
+ changePassword(passwordData) {
+ return request({
+ url: '/user/password',
+ method: 'put',
+ data: passwordData
+ })
+ },
+
+ /**
+ * 上传头像
+ * @param {FormData} formData - 包含头像文件的FormData
+ * @returns {Promise<Object>} 上传响应
+ */
+ uploadAvatar(formData) {
+ return request({
+ url: '/user/avatar',
+ method: 'post',
+ data: formData,
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+ },
+
+ /**
+ * 获取用户统计信息
+ * @returns {Promise<Object>} 统计信息
+ */
+ getUserStats() {
+ return request({
+ url: '/user/stats',
+ method: 'get'
+ })
+ },
+
+ /**
+ * 获取用户活动记录
+ * @param {Object} params - 查询参数
+ * @param {string} params.type - 活动类型
+ * @param {number} params.page - 页码
+ * @param {number} params.size - 每页大小
+ * @returns {Promise<Object>} 活动记录
+ */
+ getUserActivities(params = {}) {
+ return request({
+ url: '/user/activities',
+ method: 'get',
+ params
+ })
+ },
+
+ /**
+ * 获取用户上传的种子
+ * @param {Object} params - 查询参数
+ * @param {number} params.page - 页码
+ * @param {number} params.size - 每页大小
+ * @returns {Promise<Object>} 种子列表
+ */
+ getUserTorrents(params = {}) {
+ return request({
+ url: '/user/torrents',
+ method: 'get',
+ params
+ })
+ },
+
+ /**
+ * 获取登录历史
+ * @param {Object} params - 查询参数
+ * @param {number} params.page - 页码
+ * @param {number} params.size - 每页大小
+ * @returns {Promise<Object>} 登录历史
+ */
+ getLoginHistory(params = {}) {
+ return request({
+ url: '/user/login-history',
+ method: 'get',
+ params
+ })
+ }
+}