Files
admin_core/demo-project/登录功能修复说明.md
张成 845658f193 1
2025-10-08 18:53:38 +08:00

278 lines
6.9 KiB
Markdown
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.
# 登录功能修复说明
## 🔧 修复的问题
### 问题描述
登录时出现错误:`Cannot read properties of undefined (reading 'message')`
### 根本原因
登录接口返回的数据结构与代码中期望的不一致。
## 📊 数据结构分析
### 后端返回的数据结构
```json
{
"code": 0,
"message": "请求成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"name": "zc",
"password": "d3df61764ee9a26091f714b88958caef",
"roleId": 6,
"create_time": "2022-10-24 05:45:40",
"last_modify_time": "2025-09-12 06:48:54"
},
"authorityMenus": "[1,142,121,143,144,145,124,147,120,123,125,132,133,126,136,137,138,139,151,152,153,154,149,150,156,157,158,122,159,5,11,12,13,67,68,15]"
}
}
```
### HTTP 工具类的处理流程
1. **axios 响应拦截器**`src/utils/http.js` 第 55-69 行)
```javascript
instance.interceptors.response.use(
response => {
if (response.status === 200) {
if (response.data && response.data.code === 0) {
return response // 返回整个 response 对象
} else {
// code 不为 0拒绝
return Promise.reject(response.data.message)
}
}
}
)
```
2. **http.post 方法**`src/utils/http.js` 第 176-191 行)
```javascript
async post(url, param, config) {
let instance = this.getHttpInstance(config)
let promise = new Promise((resolve, reject) => {
instance.post(url, param).then(response => {
resolve(response.data) // 返回 response.data
})
})
return promise
}
```
3. **最终在 user.js 中得到的数据结构**
```javascript
let res = await userServerInstance.login(userFrom)
// res 的结构是:
// {
// code: 0,
// message: "请求成功",
// data: { token, user, authorityMenus }
// }
```
## ✅ 修复方案
### 1. 修复 `src/store/user.js` 中的 `handleLogin` 方法
**修复前:**
```javascript
let res = await userServerInstance.login(userFrom)
let token = res.data.token // ❌ 错误res.data 是整个数据对象
let user = res.data.user
```
**修复后:**
```javascript
let res = await userServerInstance.login(userFrom)
// 检查返回数据结构
if (res.code !== 0) {
throw new Error(res.message || '登录失败')
}
// 实际数据在 res.data 中
let token = res.data.token // ✅ 正确
let user = res.data.user // ✅ 正确
let authorityMenus = res.data.authorityMenus // ✅ 正确
```
### 2. 修复 `src/store/user.js` 中的 `setAuthorityMenus` 方法
**修复前:**
```javascript
let res = await userServerInstance.authorityMenus()
let authorityMenus = res.data // ❌ 可能不正确
```
**修复后:**
```javascript
let res = await userServerInstance.authorityMenus()
// res 的结构是 { code, message, data }
if (res && res.code === 0 && res.data) {
menus = res.data // ✅ 正确获取数据
}
```
### 3. 增强错误处理
在 `src/views/login/login.vue` 中:
```javascript
async handleSubmit({ userName, password }) {
try {
let userFrom = { name: userName, password: password }
await this.handleLogin({
userFrom,
Main,
ParentView,
Page404
})
this.$Message.success('登录成功!')
window.location.reload()
} catch (error) {
console.error('登录失败:', error)
// 处理不同类型的错误
let errorMsg = '登录失败,请检查用户名和密码'
if (error) {
if (typeof error === 'string') {
errorMsg = error
} else if (error.message) {
errorMsg = error.message
} else if (error.data && error.data.message) {
errorMsg = error.data.message
}
}
this.$Message.error(errorMsg)
}
}
```
## 🎯 登录流程
### 完整的登录流程
1. **用户输入用户名和密码**
- 组件:`src/components/login-form/login-form.vue`
- 触发事件:`on-success-valid`
2. **登录页面处理**
- 组件:`src/views/login/login.vue`
- 调用:`handleLogin` action
3. **Vuex Action 处理**
- 文件:`src/store/user.js`
- 方法:`handleLogin`
- 步骤:
1. 调用登录接口
2. 保存 token 和用户名
3. 处理权限菜单
4. 生成路由
4. **HTTP 请求**
- 文件:`src/api/system/userServer.js`
- 接口:`POST /sys_user/login`
- 参数:`{ name, password }`
5. **登录成功后**
- 显示成功提示
- 刷新页面
- 自动跳转到首页
## 📝 测试步骤
### 1. 启动项目
```bash
cd demo-project
npm run dev
```
### 2. 打开浏览器
访问:`http://localhost:8080`
### 3. 输入登录信息
- 用户名:`zc`(或其他有效用户名)
- 密码:对应的密码
### 4. 查看控制台日志
应该能看到以下日志:
```
登录接口返回: { code: 0, message: "请求成功", data: {...} }
处理权限菜单: [1,142,121,...]
生成的主菜单: { path: '/', children: [...] }
✅ Demo 项目启动成功!
```
### 5. 验证登录成功
- ✅ 显示"登录成功!"提示
- ✅ 页面刷新
- ✅ 跳转到系统首页
- ✅ 显示用户名和菜单
## 🐛 调试技巧
### 查看登录请求
1. 打开浏览器开发者工具F12
2. 切换到 Network 标签
3. 输入用户名密码,点击登录
4. 查看 `/sys_user/login` 请求
5. 检查 Response 数据结构
### 查看 Vuex 状态
1. 安装 Vue DevTools 浏览器插件
2. 打开 Vue DevTools
3. 切换到 Vuex 标签
4. 查看 `user` 模块的状态:
- `token`:应该有值
- `userName`:应该是登录的用户名
- `authorityMenus`:应该是权限菜单数组
### 查看 localStorage
1. 打开浏览器开发者工具F12
2. 切换到 Application 标签
3. 展开 Local Storage
4. 查看存储的数据:
- `demo_token`token 值
- `userName`:用户名
- `authorityMenus`:权限菜单 JSON 字符串
## ⚠️ 注意事项
### 1. authorityMenus 的数据格式
后端返回的 `authorityMenus` 是一个 **字符串**
```json
"authorityMenus": "[1,142,121,143,...]"
```
代码会自动解析这个字符串为数组。
### 2. 权限菜单的处理
- 登录接口返回的 `authorityMenus` 是菜单 ID 数组
- 需要根据这些 ID 从菜单配置中生成实际的路由
- 使用 `uiTool.getRoutes()` 方法生成路由
### 3. Token 的使用
- Token 保存在 Vuex store 和 localStorage 中
- 每次 HTTP 请求都会自动带上 token在请求头 `admin-token` 中)
- Token 失效时会自动跳转到登录页
## 🎉 修复完成
现在登录功能应该可以正常工作了!
### 验证清单
- ✅ 登录接口正确调用
- ✅ Token 正确保存
- ✅ 用户信息正确保存
- ✅ 权限菜单正确处理
- ✅ 登录成功后正确跳转
- ✅ 错误处理完善
如果还有问题,请查看浏览器控制台的错误信息和网络请求详情。