25 changed files with 2 additions and 4674 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
@ -1,63 +0,0 @@ |
|||||
{ |
|
||||
"Version": 1, |
|
||||
"WorkspaceRootPath": "D:\\Test\\Build_God\\Build_God_Admin_Frontend\\Frontend\\", |
|
||||
"Documents": [], |
|
||||
"DocumentGroupContainers": [ |
|
||||
{ |
|
||||
"Orientation": 0, |
|
||||
"VerticalTabListWidth": 256, |
|
||||
"DocumentGroups": [ |
|
||||
{ |
|
||||
"DockedWidth": 200, |
|
||||
"SelectedChildIndex": -1, |
|
||||
"Children": [ |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:136:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:135:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:134:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:133:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:132:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:131:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:130:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:131:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}" |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
@ -1,59 +0,0 @@ |
|||||
{ |
|
||||
"Version": 1, |
|
||||
"WorkspaceRootPath": "D:\\Test\\Build_God\\Build_God_Admin_Frontend\\Frontend\\", |
|
||||
"Documents": [], |
|
||||
"DocumentGroupContainers": [ |
|
||||
{ |
|
||||
"Orientation": 0, |
|
||||
"VerticalTabListWidth": 256, |
|
||||
"DocumentGroups": [ |
|
||||
{ |
|
||||
"DockedWidth": 200, |
|
||||
"SelectedChildIndex": -1, |
|
||||
"Children": [ |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:136:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:135:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:134:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:133:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:132:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:131:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:130:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
|
||||
}, |
|
||||
{ |
|
||||
"$type": "Bookmark", |
|
||||
"Name": "ST:131:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
@ -1,3 +0,0 @@ |
|||||
{ |
|
||||
"CurrentProjectSetting": null |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
{ |
|
||||
"ExpandedNodes": [ |
|
||||
"" |
|
||||
], |
|
||||
"PreviewInSolutionExplorer": false |
|
||||
} |
|
||||
Binary file not shown.
@ -1,173 +0,0 @@ |
|||||
# 后台管理系统 |
|
||||
|
|
||||
一个基于 Vue 3 + TypeScript + Vite 的现代化后台管理系统框架。 |
|
||||
|
|
||||
## 🎨 特性 |
|
||||
|
|
||||
- ✨ **暗黑主题设计** - 黑白双色优雅设计,舒适的深色主题 |
|
||||
- 🔐 **认证系统** - 完整的登录/登出功能 |
|
||||
- 📊 **仪表板** - 数据统计和概览 |
|
||||
- 👥 **用户管理** - CRUD 操作示例 |
|
||||
- 📦 **产品管理** - 完整的产品管理模块 |
|
||||
- 📋 **订单管理** - 订单管理系统 |
|
||||
- ⚙️ **系统设置** - 系统配置管理 |
|
||||
- 🎯 **响应式布局** - 完美适配各种屏幕尺寸 |
|
||||
|
|
||||
## 🚀 快速开始 |
|
||||
|
|
||||
### 安装依赖 |
|
||||
|
|
||||
```bash |
|
||||
npm install |
|
||||
``` |
|
||||
|
|
||||
### 开发模式 |
|
||||
|
|
||||
```bash |
|
||||
npm run dev |
|
||||
``` |
|
||||
|
|
||||
访问 `http://localhost:5173` 查看应用 |
|
||||
|
|
||||
### 生产构建 |
|
||||
|
|
||||
```bash |
|
||||
npm run build |
|
||||
``` |
|
||||
|
|
||||
### 类型检查 |
|
||||
|
|
||||
```bash |
|
||||
npm run type-check |
|
||||
``` |
|
||||
|
|
||||
### 预览构建结果 |
|
||||
|
|
||||
```bash |
|
||||
npm run preview |
|
||||
``` |
|
||||
|
|
||||
## 📁 项目结构 |
|
||||
|
|
||||
``` |
|
||||
src/ |
|
||||
├── assets/ # 静态资源和样式 |
|
||||
├── components/ # 可复用组件 |
|
||||
│ ├── Header.vue # 顶部导航栏 |
|
||||
│ └── Sidebar.vue # 侧边栏菜单 |
|
||||
├── router/ # 路由配置 |
|
||||
├── stores/ # Pinia 状态管理 |
|
||||
│ ├── auth.ts # 认证状态 |
|
||||
│ └── counter.ts # 计数器示例 |
|
||||
├── views/ # 页面组件 |
|
||||
│ ├── LoginView.vue # 登录页面 |
|
||||
│ ├── AdminLayout.vue # 后台布局 |
|
||||
│ └── admin/ # 后台管理页面 |
|
||||
│ ├── DashboardView.vue # 仪表板 |
|
||||
│ ├── UsersView.vue # 用户管理 |
|
||||
│ ├── ProductsView.vue # 产品管理 |
|
||||
│ ├── OrdersView.vue # 订单管理 |
|
||||
│ └── SettingsView.vue # 系统设置 |
|
||||
└── main.ts # 应用入口 |
|
||||
``` |
|
||||
|
|
||||
## 🔑 认证信息 |
|
||||
|
|
||||
### 测试账号 |
|
||||
|
|
||||
- **用户名**: `admin` |
|
||||
- **密码**: `123456` |
|
||||
|
|
||||
> 注:当前使用本地模拟认证,实际项目需要连接真实 API 服务器 |
|
||||
|
|
||||
## 🎯 功能模块 |
|
||||
|
|
||||
### 仪表板 (Dashboard) |
|
||||
- 数据统计卡片 |
|
||||
- 最近订单表格 |
|
||||
- 统计数据可视化 |
|
||||
|
|
||||
### 用户管理 |
|
||||
- 用户列表展示 |
|
||||
- 搜索功能 |
|
||||
- 新增用户 |
|
||||
- 编辑用户信息 |
|
||||
- 删除用户 |
|
||||
- 状态管理(启用/禁用) |
|
||||
|
|
||||
### 产品管理 |
|
||||
- 产品列表管理 |
|
||||
- 产品搜索和过滤 |
|
||||
- 新增产品 |
|
||||
- 编辑产品 |
|
||||
- 删除产品 |
|
||||
- 库存管理 |
|
||||
- 产品分类 |
|
||||
|
|
||||
### 订单管理 |
|
||||
- 订单列表展示 |
|
||||
- 订单搜索和过滤 |
|
||||
- 订单状态管理 |
|
||||
- 新增/编辑/删除订单 |
|
||||
- 支付方式记录 |
|
||||
|
|
||||
### 系统设置 |
|
||||
- 基本设置 |
|
||||
- 安全设置 |
|
||||
- 备份配置 |
|
||||
- 文件上传设置 |
|
||||
|
|
||||
## 🎨 主题配置 |
|
||||
|
|
||||
系统使用黑白双色暗黑主题: |
|
||||
|
|
||||
- **主色调**: `#667eea` (紫蓝色) |
|
||||
- **背景色**: `#0a0e27` (深蓝黑) |
|
||||
- **卡片色**: `#1f2937` (深灰) |
|
||||
- **文字色**: `#e5e7eb` (浅灰) |
|
||||
|
|
||||
## 📦 技术栈 |
|
||||
|
|
||||
- **Vue 3** - 渐进式 JavaScript 框架 |
|
||||
- **TypeScript** - JavaScript 超集 |
|
||||
- **Vite** - 下一代前端构建工具 |
|
||||
- **Vue Router** - 官方路由库 |
|
||||
- **Pinia** - Vue 3 状态管理 |
|
||||
- **Element Plus** - UI 组件库 |
|
||||
- **Axios** - HTTP 客户端库 |
|
||||
|
|
||||
## 🔒 路由保护 |
|
||||
|
|
||||
系统包含路由导航守卫,确保: |
|
||||
- 未登录用户无法访问后台页面 |
|
||||
- 已登录用户不能重复进入登录页 |
|
||||
- 自动重定向到登录页 |
|
||||
|
|
||||
## 💾 数据持久化 |
|
||||
|
|
||||
认证信息保存在 `localStorage` 中: |
|
||||
- `auth_token` - 用户令牌 |
|
||||
- `user` - 用户信息 |
|
||||
|
|
||||
## 🛠 开发建议 |
|
||||
|
|
||||
1. **状态管理**: 使用 Pinia store 管理全局状态 |
|
||||
2. **API 集成**: 将模拟数据替换为真实 API 调用 |
|
||||
3. **表单验证**: 为表单添加完善的验证规则 |
|
||||
4. **错误处理**: 添加全局错误处理和日志记录 |
|
||||
5. **权限管理**: 根据用户角色实现权限控制 |
|
||||
|
|
||||
## 📝 注意事项 |
|
||||
|
|
||||
- 当前使用本地状态管理,实际项目需要后端 API 支持 |
|
||||
- 表单数据为演示用途,需要根据实际需求修改 |
|
||||
- 样式可根据公司品牌进行定制 |
|
||||
- 建议在生产环境中启用权限检查和数据验证 |
|
||||
|
|
||||
## 🤝 贡献 |
|
||||
|
|
||||
欢迎提交 Issue 和 Pull Request |
|
||||
|
|
||||
## 📄 许可证 |
|
||||
|
|
||||
MIT |
|
||||
@ -1,434 +0,0 @@ |
|||||
# ✨ API 集成完成!完整总结 |
|
||||
|
|
||||
## 🎉 已为你完成的工作 |
|
||||
|
|
||||
### 1. ✅ Axios 配置文件 (`src/api/index.ts`) |
|
||||
|
|
||||
完整的 HTTP 客户端配置,包括: |
|
||||
|
|
||||
```typescript |
|
||||
✓ axios 实例创建 |
|
||||
✓ 请求拦截器 - 自动添加 Authorization header |
|
||||
✓ 响应拦截器 - 自动解析响应、处理错误 |
|
||||
✓ Token 过期处理 - 自动清除并跳转登录 |
|
||||
✓ 环境变量支持 - 开发/生产不同 API 地址 |
|
||||
``` |
|
||||
|
|
||||
### 2. ✅ API 服务层 (`src/api/auth.ts`) |
|
||||
|
|
||||
完整的登录 API 接口定义,包括: |
|
||||
|
|
||||
```typescript |
|
||||
✓ 类型定义 (TypeScript) |
|
||||
✓ loginApi() - 登录接口 |
|
||||
✓ logoutApi() - 登出接口 |
|
||||
✓ getUserInfoApi() - 获取用户信息 |
|
||||
✓ refreshTokenApi() - 刷新 token |
|
||||
✓ 详细的 JSDoc 注释 |
|
||||
``` |
|
||||
|
|
||||
### 3. ✅ 认证 Store 更新 (`src/stores/auth.ts`) |
|
||||
|
|
||||
集成后端 API 的状态管理: |
|
||||
|
|
||||
```typescript |
|
||||
✓ async login() - 调用真实 API |
|
||||
✓ async logout() - 调用登出 API |
|
||||
✓ setUser() - 更新用户信息 |
|
||||
✓ localStorage 持久化 |
|
||||
✓ 错误处理 |
|
||||
``` |
|
||||
|
|
||||
### 4. ✅ 登录页面更新 (`src/views/LoginView.vue`) |
|
||||
|
|
||||
支持异步 API 调用的登录页面: |
|
||||
|
|
||||
```typescript |
|
||||
✓ async handleLogin() |
|
||||
✓ 加载状态管理 |
|
||||
✓ 错误处理和提示 |
|
||||
✓ 回车键提交 |
|
||||
✓ 完整的错误消息 |
|
||||
``` |
|
||||
|
|
||||
### 5. ✅ 环境配置文件 |
|
||||
|
|
||||
``` |
|
||||
✓ .env.development - 开发环境 API 地址 |
|
||||
✓ .env.production - 生产环境 API 地址 |
|
||||
✓ .env.local - 本地覆盖配置 |
|
||||
``` |
|
||||
|
|
||||
### 6. ✅ 完整的文档 |
|
||||
|
|
||||
``` |
|
||||
✓ API_INTEGRATION_GUIDE.md - 详细集成指南 |
|
||||
✓ BACKEND_API_EXAMPLE.md - 后端实现参考 (Node.js/Python) |
|
||||
✓ API_INTEGRATION_COMPLETE.md - 完整工作流程说明 |
|
||||
✓ API_QUICK_REFERENCE.md - 快速参考卡片 |
|
||||
``` |
|
||||
|
|
||||
## 📂 项目结构 |
|
||||
|
|
||||
``` |
|
||||
src/ |
|
||||
├── api/ |
|
||||
│ ├── index.ts ← axios 实例 + 拦截器 |
|
||||
│ └── auth.ts ← 登录 API 接口定义 ← 可在这里添加更多 API |
|
||||
├── stores/ |
|
||||
│ ├── auth.ts ← 认证状态管理(已与 API 集成) |
|
||||
│ └── counter.ts |
|
||||
├── views/ |
|
||||
│ ├── LoginView.vue ← 登录页面(已支持异步 API) |
|
||||
│ ├── AdminLayout.vue |
|
||||
│ └── admin/ |
|
||||
│ ├── DashboardView.vue |
|
||||
│ ├── UsersView.vue |
|
||||
│ ├── ProductsView.vue |
|
||||
│ ├── OrdersView.vue |
|
||||
│ └── SettingsView.vue |
|
||||
├── components/ |
|
||||
│ ├── Header.vue |
|
||||
│ ├── Sidebar.vue |
|
||||
│ └── ... |
|
||||
├── router/ |
|
||||
│ └── index.ts |
|
||||
├── main.ts |
|
||||
└── App.vue |
|
||||
|
|
||||
root/ |
|
||||
├── .env.development ← 开发环境配置 |
|
||||
├── .env.production ← 生产环境配置 |
|
||||
├── .env.local ← 本地覆盖 |
|
||||
├── API_INTEGRATION_GUIDE.md ← 详细教程 |
|
||||
├── BACKEND_API_EXAMPLE.md ← 后端代码示例 |
|
||||
├── API_INTEGRATION_COMPLETE.md ← 完整说明 |
|
||||
└── API_QUICK_REFERENCE.md ← 快速参考 |
|
||||
``` |
|
||||
|
|
||||
## 🔄 完整工作流 |
|
||||
|
|
||||
### 前端流程 |
|
||||
|
|
||||
``` |
|
||||
1️⃣ 用户在登录页输入用户名和密码 |
|
||||
└─> username.value = 'admin' |
|
||||
└─> password.value = '123456' |
|
||||
|
|
||||
2️⃣ 点击"登录"按钮 |
|
||||
└─> handleLogin() 被调用 |
|
||||
|
|
||||
3️⃣ 登录方法开始 |
|
||||
└─> loading.value = true |
|
||||
└─> authStore.login(username, password) 被调用 |
|
||||
|
|
||||
4️⃣ Store 中的登录方法 |
|
||||
└─> loginApi({ username, password }) 被调用 |
|
||||
└─> 返回 Promise |
|
||||
|
|
||||
5️⃣ API 函数 |
|
||||
└─> http.post('/auth/login', { username, password }) |
|
||||
└─> 返回 Promise |
|
||||
|
|
||||
6️⃣ Axios 请求拦截器 |
|
||||
└─> 检查 localStorage 中是否有 auth_token |
|
||||
└─> 如果有,添加 Authorization: Bearer <token> |
|
||||
└─> 发送 HTTP 请求 |
|
||||
|
|
||||
7️⃣ HTTP 请求发送到后端 |
|
||||
└─> POST http://localhost:3000/api/auth/login |
|
||||
└─> Content-Type: application/json |
|
||||
└─> Body: { "username": "admin", "password": "123456" } |
|
||||
|
|
||||
8️⃣ 后端处理请求 |
|
||||
└─> 验证用户名和密码 |
|
||||
└─> 生成 JWT token |
|
||||
└─> 返回 JSON 响应 |
|
||||
|
|
||||
9️⃣ Axios 响应拦截器 |
|
||||
└─> 检查响应状态码 |
|
||||
└─> 如果 401,清除 token 并跳转登录 |
|
||||
└─> 提取 response.data 并返回 |
|
||||
|
|
||||
🔟 Store 接收响应 |
|
||||
└─> 检查 response.code === 200 |
|
||||
└─> 保存 token 和 user 到 localStorage |
|
||||
└─> 返回 true |
|
||||
|
|
||||
1️⃣1️⃣ 组件接收结果 |
|
||||
└─> 显示"登录成功"提示 |
|
||||
└─> 路由跳转到 /admin/dashboard |
|
||||
|
|
||||
✨ 完成!用户已登录 |
|
||||
``` |
|
||||
|
|
||||
## 💻 后端需要做什么 |
|
||||
|
|
||||
### 最小实现示例 (Node.js Express) |
|
||||
|
|
||||
```javascript |
|
||||
app.post('/api/auth/login', (req, res) => { |
|
||||
const { username, password } = req.body |
|
||||
|
|
||||
// 验证用户 |
|
||||
if (username === 'admin' && password === '123456') { |
|
||||
// 生成 token (使用 JWT) |
|
||||
const token = jwt.sign({ id: 1, username }, 'secret') |
|
||||
|
|
||||
// 返回正确格式的响应 |
|
||||
res.json({ |
|
||||
code: 200, |
|
||||
message: '登录成功', |
|
||||
data: { |
|
||||
token, |
|
||||
user: { |
|
||||
id: '1', |
|
||||
username: 'admin', |
|
||||
email: 'admin@example.com', |
|
||||
role: 'admin' |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
} else { |
|
||||
res.status(401).json({ |
|
||||
code: 401, |
|
||||
message: '用户名或密码错误' |
|
||||
}) |
|
||||
} |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
### 响应格式必须严格遵守 |
|
||||
|
|
||||
✅ **必须返回** |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "jwt_token_here", |
|
||||
"user": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
❌ **不要这样返回** |
|
||||
```json |
|
||||
{ |
|
||||
"token": "...", // ❌ 缺少 code 和 message |
|
||||
"user": {...} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 🚀 立即开始 |
|
||||
|
|
||||
### 第 1 步:准备后端服务 |
|
||||
|
|
||||
```bash |
|
||||
# 方案 A: 使用提供的 Node.js 示例 |
|
||||
# 参考 BACKEND_API_EXAMPLE.md 创建 server.js |
|
||||
node server.js |
|
||||
|
|
||||
# 方案 B: 使用你自己的后端 |
|
||||
# 确保实现了 POST /api/auth/login 接口 |
|
||||
# 返回上述格式的 JSON |
|
||||
``` |
|
||||
|
|
||||
### 第 2 步:配置前端 API 地址 |
|
||||
|
|
||||
编辑 `.env.development`(可选,因为已配置默认值): |
|
||||
|
|
||||
``` |
|
||||
VITE_API_URL=http://localhost:3000/api |
|
||||
``` |
|
||||
|
|
||||
### 第 3 步:启动前端开发服务器 |
|
||||
|
|
||||
```bash |
|
||||
npm run dev |
|
||||
``` |
|
||||
|
|
||||
### 第 4 步:测试登录 |
|
||||
|
|
||||
1. 访问 http://localhost:5173 |
|
||||
2. 输入用户名和密码 |
|
||||
3. 点击登录 |
|
||||
4. 应该看到"登录成功"提示并跳转到仪表板 |
|
||||
|
|
||||
### 第 5 步:验证请求 |
|
||||
|
|
||||
1. 打开浏览器开发者工具 (F12) |
|
||||
2. 点击 Network 标签 |
|
||||
3. 再次登录 |
|
||||
4. 看到 POST /api/auth/login 请求 |
|
||||
5. 点击查看请求和响应的详细信息 |
|
||||
|
|
||||
## 📝 代码使用示例 |
|
||||
|
|
||||
### 在登录页使用 |
|
||||
|
|
||||
```typescript |
|
||||
// LoginView.vue |
|
||||
import { useAuthStore } from '@/stores/auth' |
|
||||
|
|
||||
const authStore = useAuthStore() |
|
||||
const success = await authStore.login('admin', '123456') |
|
||||
``` |
|
||||
|
|
||||
### 在其他组件中获取用户信息 |
|
||||
|
|
||||
```typescript |
|
||||
import { useAuthStore } from '@/stores/auth' |
|
||||
|
|
||||
const authStore = useAuthStore() |
|
||||
console.log(authStore.user) // 用户信息 |
|
||||
console.log(authStore.token) // JWT token |
|
||||
console.log(authStore.isAuthenticated) // 是否已登录 |
|
||||
``` |
|
||||
|
|
||||
### 创建新的 API 接口 |
|
||||
|
|
||||
```typescript |
|
||||
// src/api/users.ts |
|
||||
import http from './index' |
|
||||
|
|
||||
export const getUsersApi = () => http.get('/users') |
|
||||
export const createUserApi = (data) => http.post('/users', data) |
|
||||
export const updateUserApi = (id, data) => http.put(`/users/${id}`, data) |
|
||||
export const deleteUserApi = (id) => http.delete(`/users/${id}`) |
|
||||
|
|
||||
// 在组件中使用 |
|
||||
import { getUsersApi } from '@/api/users' |
|
||||
const response = await getUsersApi() |
|
||||
``` |
|
||||
|
|
||||
## ✅ 完成清单 |
|
||||
|
|
||||
### 前端完成 |
|
||||
- [x] Axios 配置 |
|
||||
- [x] 请求/响应拦截器 |
|
||||
- [x] API 服务层 |
|
||||
- [x] 认证 Store |
|
||||
- [x] 登录页面 |
|
||||
- [x] 类型定义 |
|
||||
- [x] 环境配置 |
|
||||
- [x] 完整文档 |
|
||||
|
|
||||
### 等待后端完成 |
|
||||
- [ ] 实现 POST /api/auth/login 接口 |
|
||||
- [ ] 返回正确的 JSON 格式 |
|
||||
- [ ] 配置 CORS 允许前端请求 |
|
||||
- [ ] 其他业务接口 (可选) |
|
||||
|
|
||||
## 🎓 后续学习 |
|
||||
|
|
||||
### 添加其他 API |
|
||||
|
|
||||
参考登录 API,在 `src/api/` 中创建新文件: |
|
||||
|
|
||||
``` |
|
||||
src/api/ |
|
||||
├── index.ts # axios 实例 |
|
||||
├── auth.ts # ✓ 已完成 |
|
||||
├── users.ts # 待添加 |
|
||||
├── products.ts # 待添加 |
|
||||
├── orders.ts # 待添加 |
|
||||
└── ... |
|
||||
``` |
|
||||
|
|
||||
### 完整的 CRUD 示例 (用户管理) |
|
||||
|
|
||||
```typescript |
|
||||
// src/api/users.ts |
|
||||
import http from './index' |
|
||||
|
|
||||
export interface User { |
|
||||
id: number |
|
||||
username: string |
|
||||
email: string |
|
||||
} |
|
||||
|
|
||||
// 查 - Read |
|
||||
export const getUsersApi = (page = 1, limit = 10) => |
|
||||
http.get('/users', { params: { page, limit } }) |
|
||||
|
|
||||
// 增 - Create |
|
||||
export const createUserApi = (data: User) => |
|
||||
http.post('/users', data) |
|
||||
|
|
||||
// 改 - Update |
|
||||
export const updateUserApi = (id: number, data: Partial<User>) => |
|
||||
http.put(`/users/${id}`, data) |
|
||||
|
|
||||
// 删 - Delete |
|
||||
export const deleteUserApi = (id: number) => |
|
||||
http.delete(`/users/${id}`) |
|
||||
``` |
|
||||
|
|
||||
## 🔍 调试技巧 |
|
||||
|
|
||||
### 查看请求和响应 |
|
||||
|
|
||||
```typescript |
|
||||
// 在 api/index.ts 中添加日志 |
|
||||
instance.interceptors.request.use((config) => { |
|
||||
console.log('📤 发送请求:', config.method?.toUpperCase(), config.url) |
|
||||
console.log('数据:', config.data) |
|
||||
return config |
|
||||
}) |
|
||||
|
|
||||
instance.interceptors.response.use((response) => { |
|
||||
console.log('📥 收到响应:', response) |
|
||||
return response |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
### 检查 localStorage |
|
||||
|
|
||||
```typescript |
|
||||
// 在浏览器控制台执行 |
|
||||
localStorage.getItem('auth_token') // 查看 token |
|
||||
localStorage.getItem('user') // 查看用户信息 |
|
||||
``` |
|
||||
|
|
||||
### 测试 API 接口 |
|
||||
|
|
||||
```bash |
|
||||
# 使用 curl |
|
||||
curl -X POST http://localhost:3000/api/auth/login \ |
|
||||
-H "Content-Type: application/json" \ |
|
||||
-d '{"username":"admin","password":"123456"}' |
|
||||
|
|
||||
# 或使用 Postman/Insomnia GUI 工具 |
|
||||
``` |
|
||||
|
|
||||
## 🎉 总结 |
|
||||
|
|
||||
你现在拥有: |
|
||||
|
|
||||
✅ **完整的前端 API 架构** - 随时可以调用后端接口 |
|
||||
✅ **登录示例** - 展示了完整的请求/响应流程 |
|
||||
✅ **可扩展的 API 服务层** - 轻松添加更多接口 |
|
||||
✅ **完整的文档** - 学习和参考资料 |
|
||||
✅ **后端代码示例** - Node.js 和 Python 实现 |
|
||||
|
|
||||
现在你需要做的只是: |
|
||||
1. 实现后端登录接口 |
|
||||
2. 启动后端和前端 |
|
||||
3. 测试登录功能 |
|
||||
|
|
||||
其他所有的 CRUD 操作都可以按照登录示例的方式进行! |
|
||||
|
|
||||
祝你开发愉快!🚀 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
📚 **相关文档** |
|
||||
- [详细 API 集成指南](./API_INTEGRATION_GUIDE.md) |
|
||||
- [后端实现参考](./BACKEND_API_EXAMPLE.md) |
|
||||
- [快速参考卡片](./API_QUICK_REFERENCE.md) |
|
||||
@ -1,507 +0,0 @@ |
|||||
# API 集成完整指南 |
|
||||
|
|
||||
你好!现在项目已经完全配置好了 axios 和 API 层。以下是完整的说明。 |
|
||||
|
|
||||
## 🎯 快速概览 |
|
||||
|
|
||||
### 已为你完成的工作 |
|
||||
|
|
||||
✅ **Axios 配置** - 完整的 HTTP 客户端配置 |
|
||||
✅ **API 服务层** - 登录 API 接口定义 |
|
||||
✅ **认证 Store** - 与后端 API 集成的状态管理 |
|
||||
✅ **登录页面** - 支持异步 API 调用 |
|
||||
✅ **环境配置** - 开发和生产环境变量 |
|
||||
✅ **详细文档** - API 集成指南和后端示例 |
|
||||
|
|
||||
## 📁 项目结构 |
|
||||
|
|
||||
``` |
|
||||
src/ |
|
||||
├── api/ |
|
||||
│ ├── index.ts ← axios 实例(请求/响应拦截器) |
|
||||
│ └── auth.ts ← 登录 API 接口(可扩展) |
|
||||
├── stores/ |
|
||||
│ └── auth.ts ← 认证状态(调用 API) |
|
||||
├── views/ |
|
||||
│ └── LoginView.vue ← 登录页面(异步登录) |
|
||||
└── ... |
|
||||
|
|
||||
root/ |
|
||||
├── .env.development ← 开发环境配置 |
|
||||
├── .env.production ← 生产环境配置 |
|
||||
├── API_INTEGRATION_GUIDE.md ← API 集成详细指南 |
|
||||
├── BACKEND_API_EXAMPLE.md ← 后端实现参考 |
|
||||
└── ... |
|
||||
``` |
|
||||
|
|
||||
## 🔄 工作流程 |
|
||||
|
|
||||
### 1️⃣ 用户登录流程 |
|
||||
|
|
||||
``` |
|
||||
用户输入用户名和密码 |
|
||||
↓ |
|
||||
点击"登录"按钮 |
|
||||
↓ |
|
||||
LoginView.vue 调用 authStore.login(username, password) |
|
||||
↓ |
|
||||
authStore 调用 loginApi({ username, password }) |
|
||||
↓ |
|
||||
axios 发送 POST /api/auth/login 请求 |
|
||||
↓ |
|
||||
axios 拦截器处理: |
|
||||
- 添加 Authorization 头 |
|
||||
- 处理错误响应 |
|
||||
↓ |
|
||||
后端返回 JSON 响应 |
|
||||
↓ |
|
||||
前端解析 response.data(自动由拦截器处理) |
|
||||
↓ |
|
||||
保存 token 和 user 到 localStorage |
|
||||
↓ |
|
||||
路由跳转到仪表板 |
|
||||
``` |
|
||||
|
|
||||
### 2️⃣ 后续请求流程 |
|
||||
|
|
||||
``` |
|
||||
任何组件需要调用 API |
|
||||
↓ |
|
||||
导入 API 函数(如 getUsersApi) |
|
||||
↓ |
|
||||
await getUsersApi() |
|
||||
↓ |
|
||||
axios 请求拦截器自动添加 Authorization: Bearer <token> |
|
||||
↓ |
|
||||
后端验证 token |
|
||||
↓ |
|
||||
后端返回数据 |
|
||||
↓ |
|
||||
axios 响应拦截器处理(提取 data) |
|
||||
↓ |
|
||||
组件接收数据 |
|
||||
``` |
|
||||
|
|
||||
## 💻 代码实现细节 |
|
||||
|
|
||||
### axios 实例 (`src/api/index.ts`) |
|
||||
|
|
||||
```typescript |
|
||||
import axios from 'axios' |
|
||||
|
|
||||
const instance = axios.create({ |
|
||||
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api', |
|
||||
timeout: 10000 |
|
||||
}) |
|
||||
|
|
||||
// 请求拦截器 - 自动添加 token |
|
||||
instance.interceptors.request.use((config) => { |
|
||||
const token = localStorage.getItem('auth_token') |
|
||||
if (token) { |
|
||||
config.headers.Authorization = `Bearer ${token}` |
|
||||
} |
|
||||
return config |
|
||||
}) |
|
||||
|
|
||||
// 响应拦截器 - 处理错误和 token 过期 |
|
||||
instance.interceptors.response.use( |
|
||||
(response) => response.data, // ← 返回 response.data |
|
||||
(error) => { |
|
||||
if (error.response?.status === 401) { |
|
||||
// token 过期,清除并跳转 |
|
||||
localStorage.removeItem('auth_token') |
|
||||
window.location.href = '/login' |
|
||||
} |
|
||||
return Promise.reject(error) |
|
||||
} |
|
||||
) |
|
||||
|
|
||||
export default instance |
|
||||
``` |
|
||||
|
|
||||
**关键点:** |
|
||||
1. 所有请求自动添加 `Authorization: Bearer <token>` |
|
||||
2. 所有响应自动提取 `response.data` |
|
||||
3. 401 错误自动清除 token 并跳转 |
|
||||
|
|
||||
### API 接口定义 (`src/api/auth.ts`) |
|
||||
|
|
||||
```typescript |
|
||||
import http from './index' |
|
||||
|
|
||||
export interface LoginRequest { |
|
||||
username: string |
|
||||
password: string |
|
||||
} |
|
||||
|
|
||||
export interface LoginResponse { |
|
||||
code: number |
|
||||
message: string |
|
||||
data: { |
|
||||
token: string |
|
||||
user: User |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export const loginApi = (credentials: LoginRequest): Promise<LoginResponse> => { |
|
||||
return http.post('/auth/login', credentials) |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**使用方式:** |
|
||||
```typescript |
|
||||
const response = await loginApi({ username: 'admin', password: '123456' }) |
|
||||
// response.code === 200 |
|
||||
// response.data.token |
|
||||
// response.data.user |
|
||||
``` |
|
||||
|
|
||||
### 认证 Store (`src/stores/auth.ts`) |
|
||||
|
|
||||
```typescript |
|
||||
export const useAuthStore = defineStore('auth', () => { |
|
||||
const login = async (username: string, password: string): Promise<boolean> => { |
|
||||
try { |
|
||||
const response = await loginApi({ username, password }) |
|
||||
|
|
||||
if (response.code === 200 && response.data) { |
|
||||
token.value = response.data.token |
|
||||
user.value = response.data.user |
|
||||
localStorage.setItem('auth_token', token.value) |
|
||||
return true |
|
||||
} |
|
||||
} catch (error) { |
|
||||
console.error('登录失败:', error) |
|
||||
return false |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return { login, logout, user, token, isAuthenticated } |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
### 登录页面 (`src/views/LoginView.vue`) |
|
||||
|
|
||||
```typescript |
|
||||
const handleLogin = async () => { |
|
||||
loading.value = true |
|
||||
try { |
|
||||
// 调用异步登录 |
|
||||
const success = await authStore.login(username.value, password.value) |
|
||||
if (success) { |
|
||||
ElMessage.success('登录成功') |
|
||||
router.push('/admin/dashboard') |
|
||||
} else { |
|
||||
ElMessage.error('登录失败') |
|
||||
} |
|
||||
} catch (error: any) { |
|
||||
ElMessage.error(error?.message || '登录出错') |
|
||||
} finally { |
|
||||
loading.value = false |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 🛠 后端 API 需要返回什么? |
|
||||
|
|
||||
### 登录接口 |
|
||||
|
|
||||
**端点:** `POST /api/auth/login` |
|
||||
|
|
||||
**请求:** |
|
||||
```json |
|
||||
{ |
|
||||
"username": "admin", |
|
||||
"password": "123456" |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**响应格式(必须严格按照):** |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", |
|
||||
"user": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**关键点:** |
|
||||
- `code` 必须是 200 表示成功 |
|
||||
- `data.token` 是 JWT token,后续请求在 `Authorization: Bearer <token>` 中使用 |
|
||||
- `data.user` 必须包含至少 `id, username, email, role` 字段 |
|
||||
|
|
||||
## 📝 添加更多 API 接口 |
|
||||
|
|
||||
### 例子:用户列表 API |
|
||||
|
|
||||
1. **在 `src/api/` 中创建 `users.ts`:** |
|
||||
|
|
||||
```typescript |
|
||||
import http from './index' |
|
||||
|
|
||||
export interface User { |
|
||||
id: number |
|
||||
username: string |
|
||||
email: string |
|
||||
role: string |
|
||||
} |
|
||||
|
|
||||
export interface UsersResponse { |
|
||||
code: number |
|
||||
message: string |
|
||||
data: { |
|
||||
items: User[] |
|
||||
total: number |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 获取用户列表 |
|
||||
export const getUsersApi = ( |
|
||||
page: number = 1, |
|
||||
limit: number = 10 |
|
||||
): Promise<UsersResponse> => { |
|
||||
return http.get('/users', { |
|
||||
params: { page, limit } |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 创建用户 |
|
||||
export const createUserApi = (data: User): Promise<any> => { |
|
||||
return http.post('/users', data) |
|
||||
} |
|
||||
|
|
||||
// 更新用户 |
|
||||
export const updateUserApi = (id: number, data: Partial<User>): Promise<any> => { |
|
||||
return http.put(`/users/${id}`, data) |
|
||||
} |
|
||||
|
|
||||
// 删除用户 |
|
||||
export const deleteUserApi = (id: number): Promise<any> => { |
|
||||
return http.delete(`/users/${id}`) |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
2. **在组件中使用:** |
|
||||
|
|
||||
```typescript |
|
||||
import { getUsersApi } from '@/api/users' |
|
||||
|
|
||||
const users = ref([]) |
|
||||
const loading = ref(false) |
|
||||
|
|
||||
const fetchUsers = async () => { |
|
||||
loading.value = true |
|
||||
try { |
|
||||
const response = await getUsersApi(1, 10) |
|
||||
if (response.code === 200) { |
|
||||
users.value = response.data.items |
|
||||
} |
|
||||
} catch (error) { |
|
||||
ElMessage.error('获取用户列表失败') |
|
||||
} finally { |
|
||||
loading.value = false |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
onMounted(() => { |
|
||||
fetchUsers() |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
## 🌐 环境配置 |
|
||||
|
|
||||
### 开发环境 (`.env.development`) |
|
||||
|
|
||||
``` |
|
||||
VITE_API_URL=http://localhost:3000/api |
|
||||
``` |
|
||||
|
|
||||
### 生产环境 (`.env.production`) |
|
||||
|
|
||||
``` |
|
||||
VITE_API_URL=https://api.example.com/api |
|
||||
``` |
|
||||
|
|
||||
### 在代码中使用 |
|
||||
|
|
||||
```typescript |
|
||||
const baseURL = import.meta.env.VITE_API_URL |
|
||||
console.log(baseURL) // 自动根据环境选择 |
|
||||
|
|
||||
// 或直接在 axios 配置中 |
|
||||
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api' |
|
||||
``` |
|
||||
|
|
||||
## 🧪 测试步骤 |
|
||||
|
|
||||
### 1. 启动后端服务 |
|
||||
|
|
||||
```bash |
|
||||
# Node.js Express 示例 |
|
||||
node server.js |
|
||||
|
|
||||
# 或 Python Flask 示例 |
|
||||
python app.py |
|
||||
|
|
||||
# 或你自己的后端服务 |
|
||||
``` |
|
||||
|
|
||||
### 2. 验证后端在运行 |
|
||||
|
|
||||
访问 `http://localhost:3000/api/auth/login` (应该看到 404 或错误,说明服务在运行) |
|
||||
|
|
||||
### 3. 使用 cURL 测试登录 |
|
||||
|
|
||||
```bash |
|
||||
curl -X POST http://localhost:3000/api/auth/login \ |
|
||||
-H "Content-Type: application/json" \ |
|
||||
-d '{"username":"admin","password":"123456"}' |
|
||||
``` |
|
||||
|
|
||||
应该返回: |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "...", |
|
||||
"user": {...} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### 4. 启动前端 |
|
||||
|
|
||||
```bash |
|
||||
npm run dev |
|
||||
``` |
|
||||
|
|
||||
### 5. 在前端登录 |
|
||||
|
|
||||
- 访问 http://localhost:5173 |
|
||||
- 输入用户名和密码 |
|
||||
- 点击登录 |
|
||||
- 如果成功,应该跳转到仪表板 |
|
||||
|
|
||||
### 6. 检查浏览器开发者工具 |
|
||||
|
|
||||
- **Network 标签:** 查看请求和响应 |
|
||||
- **Application 标签:** 查看 localStorage 中的 `auth_token` |
|
||||
- **Console 标签:** 查看是否有错误 |
|
||||
|
|
||||
## 🔒 安全建议 |
|
||||
|
|
||||
1. **始终使用 HTTPS** (生产环境) |
|
||||
2. **密码必须加密存储** (使用 bcrypt 等) |
|
||||
3. **使用 JWT 令牌** 而不是 session |
|
||||
4. **设置合理的 token 过期时间** (如 7 天) |
|
||||
5. **实现 token 刷新机制** (可选但推荐) |
|
||||
6. **验证 CORS 配置** 只允许特定域名 |
|
||||
7. **记录所有登录尝试** 用于审计 |
|
||||
8. **使用速率限制** 防止暴力破解 |
|
||||
|
|
||||
## 常见问题 |
|
||||
|
|
||||
### Q: 如何在其他组件中获取当前用户? |
|
||||
|
|
||||
```typescript |
|
||||
import { useAuthStore } from '@/stores/auth' |
|
||||
|
|
||||
const authStore = useAuthStore() |
|
||||
console.log(authStore.user) // 当前用户 |
|
||||
console.log(authStore.token) // 当前 token |
|
||||
``` |
|
||||
|
|
||||
### Q: 如何处理 token 刷新? |
|
||||
|
|
||||
参考 `src/api/auth.ts` 中已定义的 `refreshTokenApi` 函数,在响应拦截器中实现 token 刷新逻辑。 |
|
||||
|
|
||||
### Q: 如何在请求中添加其他头信息? |
|
||||
|
|
||||
```typescript |
|
||||
// 在 src/api/index.ts 中修改请求拦截器 |
|
||||
instance.interceptors.request.use((config) => { |
|
||||
const token = localStorage.getItem('auth_token') |
|
||||
if (token) { |
|
||||
config.headers.Authorization = `Bearer ${token}` |
|
||||
} |
|
||||
// 添加其他头 |
|
||||
config.headers['X-Custom-Header'] = 'value' |
|
||||
return config |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
### Q: 如何处理超时错误? |
|
||||
|
|
||||
```typescript |
|
||||
const login = async () => { |
|
||||
try { |
|
||||
await authStore.login(username, password) |
|
||||
} catch (error: any) { |
|
||||
if (error.code === 'ECONNABORTED') { |
|
||||
ElMessage.error('请求超时,请检查网络') |
|
||||
} else { |
|
||||
ElMessage.error(error.message) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### Q: 前后端如何联调? |
|
||||
|
|
||||
1. 后端启动在 http://localhost:3000 |
|
||||
2. 前端启动在 http://localhost:5173 |
|
||||
3. 确保 `.env.development` 中 `VITE_API_URL=http://localhost:3000/api` |
|
||||
4. 后端需要配置 CORS 允许 http://localhost:5173 访问 |
|
||||
|
|
||||
### Q: CORS 错误怎么解决? |
|
||||
|
|
||||
后端需要配置 CORS: |
|
||||
|
|
||||
**Express 示例:** |
|
||||
```javascript |
|
||||
const cors = require('cors') |
|
||||
app.use(cors({ |
|
||||
origin: 'http://localhost:5173', |
|
||||
credentials: true |
|
||||
})) |
|
||||
``` |
|
||||
|
|
||||
**Flask 示例:** |
|
||||
```python |
|
||||
from flask_cors import CORS |
|
||||
CORS(app, resources={r"/api/*": {"origins": "http://localhost:5173"}}) |
|
||||
``` |
|
||||
|
|
||||
## 📚 相关文档 |
|
||||
|
|
||||
- [API 集成详细指南](./API_INTEGRATION_GUIDE.md) - 完整的 API 使用说明 |
|
||||
- [后端 API 实现参考](./BACKEND_API_EXAMPLE.md) - Node.js/Python 后端示例代码 |
|
||||
- [项目总结](./PROJECT_SUMMARY.md) - 整个项目的概览 |
|
||||
|
|
||||
## 🎉 总结 |
|
||||
|
|
||||
你现在有: |
|
||||
|
|
||||
✅ 完整的 axios 配置(请求/响应拦截器) |
|
||||
✅ API 服务层架构 |
|
||||
✅ 登录示例(已与后端集成) |
|
||||
✅ 完整的类型定义 (TypeScript) |
|
||||
✅ 环境变量配置 |
|
||||
✅ 详细的文档和后端示例 |
|
||||
|
|
||||
**下一步:** |
|
||||
1. 启动你的后端服务,确保监听 3000 端口 |
|
||||
2. 实现后端的 `/api/auth/login` 接口,返回上述格式的 JSON |
|
||||
3. 运行 `npm run dev` 启动前端 |
|
||||
4. 测试登录功能 |
|
||||
|
|
||||
有任何问题,请参考文档或查看相关代码注释!🚀 |
|
||||
@ -1,399 +0,0 @@ |
|||||
# API 集成指南 |
|
||||
|
|
||||
## 概述 |
|
||||
|
|
||||
项目已完整配置 axios,包括请求拦截器、响应拦截器和 API 服务层。 |
|
||||
|
|
||||
## 文件结构 |
|
||||
|
|
||||
``` |
|
||||
src/api/ |
|
||||
├── index.ts # axios 实例配置(请求/响应拦截器) |
|
||||
└── auth.ts # 登录相关 API 接口定义 |
|
||||
``` |
|
||||
|
|
||||
## 核心概念 |
|
||||
|
|
||||
### 1. axios 实例配置 (`src/api/index.ts`) |
|
||||
|
|
||||
```typescript |
|
||||
// 创建 axios 实例 |
|
||||
const instance = axios.create({ |
|
||||
baseURL: 'http://localhost:3000/api', // 从环境变量读取 |
|
||||
timeout: 10000 |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
**请求拦截器**:自动在请求头添加 Authorization token |
|
||||
```typescript |
|
||||
instance.interceptors.request.use((config) => { |
|
||||
const token = localStorage.getItem('auth_token') |
|
||||
if (token) { |
|
||||
config.headers.Authorization = `Bearer ${token}` |
|
||||
} |
|
||||
return config |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
**响应拦截器**:统一处理错误和 token 过期 |
|
||||
```typescript |
|
||||
instance.interceptors.response.use( |
|
||||
(response) => response.data, // 成功时返回 data |
|
||||
(error) => { |
|
||||
if (error.response?.status === 401) { |
|
||||
// Token 过期,清除登录状态并跳转到登录页 |
|
||||
} |
|
||||
} |
|
||||
) |
|
||||
``` |
|
||||
|
|
||||
### 2. API 服务层 (`src/api/auth.ts`) |
|
||||
|
|
||||
定义所有 API 接口和类型: |
|
||||
|
|
||||
```typescript |
|
||||
// 定义请求/响应类型 |
|
||||
export interface LoginRequest { |
|
||||
username: string |
|
||||
password: string |
|
||||
} |
|
||||
|
|
||||
export interface LoginResponse { |
|
||||
code: number |
|
||||
message: string |
|
||||
data: { |
|
||||
token: string |
|
||||
user: User |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 定义 API 接口 |
|
||||
export const loginApi = (credentials: LoginRequest): Promise<LoginResponse> => { |
|
||||
return http.post('/auth/login', credentials) |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### 3. 状态管理 (`src/stores/auth.ts`) |
|
||||
|
|
||||
在 Pinia store 中调用 API: |
|
||||
|
|
||||
```typescript |
|
||||
const login = async (username: string, password: string): Promise<boolean> => { |
|
||||
try { |
|
||||
const response = await loginApi({ username, password }) |
|
||||
|
|
||||
if (response.code === 200 && response.data) { |
|
||||
token.value = response.data.token |
|
||||
user.value = response.data.user |
|
||||
|
|
||||
// 保存到本地存储 |
|
||||
localStorage.setItem('auth_token', token.value) |
|
||||
localStorage.setItem('user', JSON.stringify(user.value)) |
|
||||
|
|
||||
return true |
|
||||
} |
|
||||
} catch (error) { |
|
||||
console.error('登录失败:', error) |
|
||||
return false |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 登录流程详解 |
|
||||
|
|
||||
### 前端请求流程 |
|
||||
|
|
||||
``` |
|
||||
1. 用户在登录页输入用户名和密码 |
|
||||
↓ |
|
||||
2. 点击"登录"按钮调用 handleLogin() |
|
||||
↓ |
|
||||
3. authStore.login(username, password) 被调用 |
|
||||
↓ |
|
||||
4. loginApi({ username, password }) 发送 HTTP 请求 |
|
||||
↓ |
|
||||
5. axios 拦截器处理(添加 headers 等) |
|
||||
↓ |
|
||||
6. 发送 POST /auth/login 请求到后端 |
|
||||
``` |
|
||||
|
|
||||
### 后端需要返回的数据格式 |
|
||||
|
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", |
|
||||
"user": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**字段说明:** |
|
||||
- `code`: HTTP 状态码(200 表示成功) |
|
||||
- `message`: 返回消息 |
|
||||
- `data.token`: JWT token,用于后续请求认证 |
|
||||
- `data.user`: 用户信息对象 |
|
||||
- `id`: 用户 ID |
|
||||
- `username`: 用户名 |
|
||||
- `email`: 邮箱 |
|
||||
- `role`: 用户角色(admin 或 user) |
|
||||
|
|
||||
## 环境配置 |
|
||||
|
|
||||
### `.env.development` (开发环境) |
|
||||
``` |
|
||||
VITE_API_URL=http://localhost:3000/api |
|
||||
``` |
|
||||
|
|
||||
### `.env.production` (生产环境) |
|
||||
``` |
|
||||
VITE_API_URL=https://api.example.com/api |
|
||||
``` |
|
||||
|
|
||||
### 在代码中获取环境变量 |
|
||||
|
|
||||
```typescript |
|
||||
const baseURL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api' |
|
||||
``` |
|
||||
|
|
||||
## 使用示例 |
|
||||
|
|
||||
### 1. 调用登录 API |
|
||||
|
|
||||
```typescript |
|
||||
import { loginApi } from '@/api/auth' |
|
||||
|
|
||||
const response = await loginApi({ |
|
||||
username: 'admin', |
|
||||
password: '123456' |
|
||||
}) |
|
||||
|
|
||||
if (response.code === 200) { |
|
||||
console.log('登录成功,用户信息:', response.data.user) |
|
||||
console.log('Token:', response.data.token) |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### 2. 在组件中使用 store |
|
||||
|
|
||||
```vue |
|
||||
<script setup lang="ts"> |
|
||||
import { useAuthStore } from '@/stores/auth' |
|
||||
|
|
||||
const authStore = useAuthStore() |
|
||||
|
|
||||
const login = async () => { |
|
||||
const success = await authStore.login('admin', '123456') |
|
||||
if (success) { |
|
||||
// 登录成功,跳转 |
|
||||
router.push('/admin/dashboard') |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
``` |
|
||||
|
|
||||
### 3. 创建新的 API 接口 |
|
||||
|
|
||||
在 `src/api/` 中创建新文件,如 `users.ts`: |
|
||||
|
|
||||
```typescript |
|
||||
import http from './index' |
|
||||
|
|
||||
export interface User { |
|
||||
id: number |
|
||||
username: string |
|
||||
email: string |
|
||||
role: string |
|
||||
} |
|
||||
|
|
||||
// 获取用户列表 |
|
||||
export const getUsersApi = (page: number, limit: number) => { |
|
||||
return http.get('/users', { |
|
||||
params: { page, limit } |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 创建用户 |
|
||||
export const createUserApi = (data: User) => { |
|
||||
return http.post('/users', data) |
|
||||
} |
|
||||
|
|
||||
// 更新用户 |
|
||||
export const updateUserApi = (id: number, data: Partial<User>) => { |
|
||||
return http.put(`/users/${id}`, data) |
|
||||
} |
|
||||
|
|
||||
// 删除用户 |
|
||||
export const deleteUserApi = (id: number) => { |
|
||||
return http.delete(`/users/${id}`) |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 错误处理 |
|
||||
|
|
||||
### 全局错误处理 |
|
||||
|
|
||||
axios 响应拦截器已处理以下情况: |
|
||||
|
|
||||
| 状态码 | 处理方式 | |
|
||||
|-------|--------| |
|
||||
| 401 | Token 过期,清除登录状态,跳转到登录页 | |
|
||||
| 其他 4xx/5xx | 返回错误信息 | |
|
||||
| 网络错误 | 返回"网络错误"提示 | |
|
||||
|
|
||||
### 在组件中处理错误 |
|
||||
|
|
||||
```typescript |
|
||||
try { |
|
||||
const response = await loginApi({ username, password }) |
|
||||
// 处理成功 |
|
||||
} catch (error: any) { |
|
||||
ElMessage.error(error?.message || '登录失败') |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 请求示例 |
|
||||
|
|
||||
### POST 请求 (登录) |
|
||||
|
|
||||
```typescript |
|
||||
// 请求 |
|
||||
POST /api/auth/login |
|
||||
Content-Type: application/json |
|
||||
Authorization: Bearer <token> |
|
||||
|
|
||||
{ |
|
||||
"username": "admin", |
|
||||
"password": "123456" |
|
||||
} |
|
||||
|
|
||||
// 响应 |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "...", |
|
||||
"user": { ... } |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### GET 请求 (获取列表) |
|
||||
|
|
||||
```typescript |
|
||||
// 请求 |
|
||||
GET /api/users?page=1&limit=10 |
|
||||
Authorization: Bearer <token> |
|
||||
|
|
||||
// 响应 |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "成功", |
|
||||
"data": { |
|
||||
"items": [...], |
|
||||
"total": 100 |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### PUT 请求 (更新) |
|
||||
|
|
||||
```typescript |
|
||||
// 请求 |
|
||||
PUT /api/users/1 |
|
||||
Content-Type: application/json |
|
||||
Authorization: Bearer <token> |
|
||||
|
|
||||
{ |
|
||||
"username": "new_name", |
|
||||
"email": "new@email.com" |
|
||||
} |
|
||||
|
|
||||
// 响应 |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "更新成功", |
|
||||
"data": { ... } |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 常见问题 |
|
||||
|
|
||||
### Q: Token 过期怎么处理? |
|
||||
|
|
||||
A: 后端返回 401 时,拦截器会自动清除 token 并跳转到登录页。 |
|
||||
|
|
||||
### Q: 如何添加其他请求头? |
|
||||
|
|
||||
A: 修改 `src/api/index.ts` 中的拦截器: |
|
||||
|
|
||||
```typescript |
|
||||
instance.interceptors.request.use((config) => { |
|
||||
config.headers['Custom-Header'] = 'value' |
|
||||
return config |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
### Q: 如何处理超时? |
|
||||
|
|
||||
A: 已在 axios 配置中设置 `timeout: 10000`(10秒)。修改 `src/api/index.ts` 中的 `timeout` 值。 |
|
||||
|
|
||||
### Q: 如何调用 API 时显示加载状态? |
|
||||
|
|
||||
A: 在组件中使用 `loading` ref: |
|
||||
|
|
||||
```typescript |
|
||||
const loading = ref(false) |
|
||||
loading.value = true |
|
||||
try { |
|
||||
const response = await loginApi(...) |
|
||||
} finally { |
|
||||
loading.value = false |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 集成后端步骤 |
|
||||
|
|
||||
1. **启动后端服务** |
|
||||
```bash |
|
||||
# 后端服务应该运行在 http://localhost:3000 |
|
||||
``` |
|
||||
|
|
||||
2. **更新 API 地址** (如果不同) |
|
||||
``` |
|
||||
修改 .env.development 中的 VITE_API_URL |
|
||||
``` |
|
||||
|
|
||||
3. **确保后端返回正确格式** |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "...", |
|
||||
"data": { ... } |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
4. **测试登录流程** |
|
||||
- 访问 http://localhost:5173 |
|
||||
- 输入用户名和密码 |
|
||||
- 查看浏览器控制台的网络请求 |
|
||||
|
|
||||
5. **检查 Token 存储** |
|
||||
- 打开浏览器开发者工具 → Application → LocalStorage |
|
||||
- 应该看到 `auth_token` 和 `user` 字段 |
|
||||
|
|
||||
## 下一步 |
|
||||
|
|
||||
- [ ] 集成后端登录接口 |
|
||||
- [ ] 添加用户列表 API (`src/api/users.ts`) |
|
||||
- [ ] 添加产品 API (`src/api/products.ts`) |
|
||||
- [ ] 添加订单 API (`src/api/orders.ts`) |
|
||||
- [ ] 实现 token 刷新机制 |
|
||||
- [ ] 添加错误日志上报 |
|
||||
@ -1,306 +0,0 @@ |
|||||
# API 快速参考卡片 |
|
||||
|
|
||||
## 📋 一页纸速查表 |
|
||||
|
|
||||
### 项目文件对应关系 |
|
||||
|
|
||||
| 文件 | 作用 | 修改频率 | |
|
||||
|-----|------|--------| |
|
||||
| `src/api/index.ts` | axios 配置 + 拦截器 | 很少 | |
|
||||
| `src/api/auth.ts` | API 接口定义 | 经常 | |
|
||||
| `src/stores/auth.ts` | 认证状态管理 | 偶尔 | |
|
||||
| `src/views/LoginView.vue` | 登录页面 | 偶尔 | |
|
||||
| `.env.development` | 开发环境 API 地址 | 很少 | |
|
||||
| `.env.production` | 生产环境 API 地址 | 很少 | |
|
||||
|
|
||||
### 工作流程简图 |
|
||||
|
|
||||
``` |
|
||||
前端组件 |
|
||||
↓ |
|
||||
import { loginApi } from '@/api/auth' |
|
||||
↓ |
|
||||
await loginApi({ username, password }) |
|
||||
↓ |
|
||||
axios instance (请求拦截器添加 token) |
|
||||
↓ |
|
||||
POST /api/auth/login |
|
||||
↓ |
|
||||
后端返回 JSON |
|
||||
↓ |
|
||||
axios instance (响应拦截器提取 data) |
|
||||
↓ |
|
||||
return response.data |
|
||||
↓ |
|
||||
前端接收数据 |
|
||||
``` |
|
||||
|
|
||||
### 常用代码片段 |
|
||||
|
|
||||
**1. 登录** |
|
||||
```typescript |
|
||||
import { useAuthStore } from '@/stores/auth' |
|
||||
|
|
||||
const authStore = useAuthStore() |
|
||||
const success = await authStore.login('admin', '123456') |
|
||||
``` |
|
||||
|
|
||||
**2. 获取当前用户** |
|
||||
```typescript |
|
||||
const authStore = useAuthStore() |
|
||||
console.log(authStore.user) |
|
||||
console.log(authStore.token) |
|
||||
``` |
|
||||
|
|
||||
**3. 登出** |
|
||||
```typescript |
|
||||
const authStore = useAuthStore() |
|
||||
await authStore.logout() |
|
||||
``` |
|
||||
|
|
||||
**4. 创建新 API 接口** |
|
||||
```typescript |
|
||||
// src/api/users.ts |
|
||||
import http from './index' |
|
||||
|
|
||||
export const getUsersApi = () => { |
|
||||
return http.get('/users') |
|
||||
} |
|
||||
|
|
||||
// 组件中使用 |
|
||||
import { getUsersApi } from '@/api/users' |
|
||||
const response = await getUsersApi() |
|
||||
``` |
|
||||
|
|
||||
### 后端需要的东西 |
|
||||
|
|
||||
**登录接口** |
|
||||
``` |
|
||||
POST /api/auth/login |
|
||||
|
|
||||
请求: |
|
||||
{ |
|
||||
"username": "admin", |
|
||||
"password": "123456" |
|
||||
} |
|
||||
|
|
||||
响应: |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "jwt_token_here", |
|
||||
"user": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**所有其他接口** |
|
||||
``` |
|
||||
Authorization: Bearer <token> (自动添加) |
|
||||
|
|
||||
返回格式: |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "...", |
|
||||
"data": {...} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### 调试技巧 |
|
||||
|
|
||||
**1. 查看网络请求** |
|
||||
- 打开浏览器开发者工具 (F12) |
|
||||
- 点击 Network 标签 |
|
||||
- 登录看看 POST /api/auth/login 的请求和响应 |
|
||||
|
|
||||
**2. 查看存储的 token** |
|
||||
- 打开浏览器开发者工具 (F12) |
|
||||
- 点击 Application 标签 |
|
||||
- 找到 LocalStorage |
|
||||
- 查看 `auth_token` 和 `user` |
|
||||
|
|
||||
**3. 打印错误** |
|
||||
```typescript |
|
||||
try { |
|
||||
await loginApi(...) |
|
||||
} catch (error) { |
|
||||
console.log(error) // 查看具体错误 |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### 环境变量配置 |
|
||||
|
|
||||
**开发环境** (`.env.development`) |
|
||||
``` |
|
||||
VITE_API_URL=http://localhost:3000/api |
|
||||
``` |
|
||||
|
|
||||
**生产环境** (`.env.production`) |
|
||||
``` |
|
||||
VITE_API_URL=https://api.yourdomain.com/api |
|
||||
``` |
|
||||
|
|
||||
**在代码中使用** |
|
||||
```typescript |
|
||||
console.log(import.meta.env.VITE_API_URL) |
|
||||
``` |
|
||||
|
|
||||
### 常见错误解决 |
|
||||
|
|
||||
| 错误 | 原因 | 解决 | |
|
||||
|-----|------|------| |
|
||||
| CORS error | 跨域问题 | 后端配置 CORS | |
|
||||
| 401 | token 过期 | 自动清除,跳转登录 | |
|
||||
| 404 | 接口不存在 | 检查后端路由 | |
|
||||
| 500 | 服务器错误 | 检查后端日志 | |
|
||||
| 网络错误 | 后端未启动 | 启动后端服务 | |
|
||||
|
|
||||
### 完整登录示例 |
|
||||
|
|
||||
```typescript |
|
||||
<script setup lang="ts"> |
|
||||
import { ref } from 'vue' |
|
||||
import { useRouter } from 'vue-router' |
|
||||
import { useAuthStore } from '@/stores/auth' |
|
||||
import { ElMessage } from 'element-plus' |
|
||||
|
|
||||
const router = useRouter() |
|
||||
const authStore = useAuthStore() |
|
||||
const username = ref('admin') |
|
||||
const password = ref('123456') |
|
||||
const loading = ref(false) |
|
||||
|
|
||||
const handleLogin = async () => { |
|
||||
loading.value = true |
|
||||
try { |
|
||||
// 调用异步登录 |
|
||||
const success = await authStore.login(username.value, password.value) |
|
||||
if (success) { |
|
||||
ElMessage.success('登录成功') |
|
||||
router.push('/admin/dashboard') |
|
||||
} else { |
|
||||
ElMessage.error('登录失败') |
|
||||
} |
|
||||
} catch (error: any) { |
|
||||
ElMessage.error(error?.message || '登录错误') |
|
||||
} finally { |
|
||||
loading.value = false |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<template> |
|
||||
<input v-model="username" type="text" placeholder="用户名" /> |
|
||||
<input v-model="password" type="password" placeholder="密码" /> |
|
||||
<button @click="handleLogin" :disabled="loading"> |
|
||||
{{ loading ? '登录中...' : '登录' }} |
|
||||
</button> |
|
||||
</template> |
|
||||
``` |
|
||||
|
|
||||
### API 调用模板 |
|
||||
|
|
||||
```typescript |
|
||||
// 1. 创建接口文件 src/api/xxx.ts |
|
||||
import http from './index' |
|
||||
|
|
||||
export interface XXXRequest { |
|
||||
// 请求参数 |
|
||||
} |
|
||||
|
|
||||
export interface XXXResponse { |
|
||||
code: number |
|
||||
message: string |
|
||||
data: { |
|
||||
// 响应数据 |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export const xxxApi = (params: XXXRequest): Promise<XXXResponse> => { |
|
||||
return http.post('/xxx', params) |
|
||||
} |
|
||||
|
|
||||
// 2. 在组件中使用 |
|
||||
import { xxxApi } from '@/api/xxx' |
|
||||
|
|
||||
const response = await xxxApi({ /* 参数 */ }) |
|
||||
if (response.code === 200) { |
|
||||
// 成功处理 |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### HTTP 方法速查 |
|
||||
|
|
||||
```typescript |
|
||||
// GET 请求 |
|
||||
http.get('/users') |
|
||||
http.get('/users?page=1&limit=10') |
|
||||
http.get('/users', { params: { page: 1 } }) |
|
||||
|
|
||||
// POST 请求 |
|
||||
http.post('/users', { name: 'John' }) |
|
||||
|
|
||||
// PUT 请求 |
|
||||
http.put('/users/1', { name: 'Jane' }) |
|
||||
|
|
||||
// DELETE 请求 |
|
||||
http.delete('/users/1') |
|
||||
|
|
||||
// PATCH 请求 |
|
||||
http.patch('/users/1', { name: 'Bob' }) |
|
||||
``` |
|
||||
|
|
||||
### token 在请求中的流程 |
|
||||
|
|
||||
``` |
|
||||
1. 用户登录 → token 保存到 localStorage |
|
||||
2. 请求拦截器检查 localStorage 中的 token |
|
||||
3. 如果有 token,添加到请求头:Authorization: Bearer <token> |
|
||||
4. 后端验证 token |
|
||||
5. 后端返回数据或 401 错误 |
|
||||
6. 响应拦截器检查状态码 |
|
||||
7. 如果 401,清除 token 并跳转登录页 |
|
||||
``` |
|
||||
|
|
||||
### 测试后端接口的命令 |
|
||||
|
|
||||
```bash |
|
||||
# 测试登录 |
|
||||
curl -X POST http://localhost:3000/api/auth/login \ |
|
||||
-H "Content-Type: application/json" \ |
|
||||
-d '{"username":"admin","password":"123456"}' |
|
||||
|
|
||||
# 获取响应中的 token |
|
||||
# 复制 token 值 |
|
||||
|
|
||||
# 测试其他接口(需要 token) |
|
||||
curl -X GET http://localhost:3000/api/users \ |
|
||||
-H "Authorization: Bearer YOUR_TOKEN_HERE" |
|
||||
``` |
|
||||
|
|
||||
## 🚀 快速启动清单 |
|
||||
|
|
||||
- [ ] 后端启动在 http://localhost:3000 |
|
||||
- [ ] 后端实现 POST /api/auth/login 接口 |
|
||||
- [ ] 后端返回正确的 JSON 格式 |
|
||||
- [ ] 前端运行 `npm run dev` |
|
||||
- [ ] 前端 .env.development 中 VITE_API_URL 指向后端 |
|
||||
- [ ] 打开浏览器访问 http://localhost:5173 |
|
||||
- [ ] 输入用户名和密码登录 |
|
||||
- [ ] 查看浏览器 Network 标签验证请求 |
|
||||
- [ ] 检查 localStorage 中是否保存了 token |
|
||||
- [ ] 登录成功后跳转到仪表板 |
|
||||
|
|
||||
## 📞 获取帮助 |
|
||||
|
|
||||
1. 查看 `API_INTEGRATION_GUIDE.md` - 详细教程 |
|
||||
2. 查看 `BACKEND_API_EXAMPLE.md` - 后端代码示例 |
|
||||
3. 查看组件代码注释 |
|
||||
4. 打开浏览器开发者工具查看错误 |
|
||||
5. 检查后端日志 |
|
||||
@ -1,401 +0,0 @@ |
|||||
# 后端 API 实现参考 |
|
||||
|
|
||||
这是一个使用 Node.js + Express 的简单后端示例,展示如何实现登录接口。 |
|
||||
|
|
||||
## 快速开始 (Node.js + Express) |
|
||||
|
|
||||
### 1. 初始化项目 |
|
||||
|
|
||||
```bash |
|
||||
mkdir admin-backend |
|
||||
cd admin-backend |
|
||||
npm init -y |
|
||||
npm install express cors jsonwebtoken bcryptjs dotenv |
|
||||
npm install -D nodemon typescript ts-node |
|
||||
``` |
|
||||
|
|
||||
### 2. 创建 `server.js` |
|
||||
|
|
||||
```javascript |
|
||||
const express = require('express') |
|
||||
const cors = require('cors') |
|
||||
const jwt = require('jsonwebtoken') |
|
||||
require('dotenv').config() |
|
||||
|
|
||||
const app = express() |
|
||||
const PORT = process.env.PORT || 3000 |
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key' |
|
||||
|
|
||||
// 中间件 |
|
||||
app.use(cors()) |
|
||||
app.use(express.json()) |
|
||||
|
|
||||
// 模拟用户数据 |
|
||||
const users = [ |
|
||||
{ |
|
||||
id: '1', |
|
||||
username: 'admin', |
|
||||
password: '123456', // 实际应该加密存储 |
|
||||
email: 'admin@example.com', |
|
||||
role: 'admin' |
|
||||
}, |
|
||||
{ |
|
||||
id: '2', |
|
||||
username: 'user', |
|
||||
password: '123456', |
|
||||
email: 'user@example.com', |
|
||||
role: 'user' |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
// 登录接口 |
|
||||
app.post('/api/auth/login', (req, res) => { |
|
||||
const { username, password } = req.body |
|
||||
|
|
||||
// 验证输入 |
|
||||
if (!username || !password) { |
|
||||
return res.status(400).json({ |
|
||||
code: 400, |
|
||||
message: '用户名和密码不能为空' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 查找用户 |
|
||||
const user = users.find(u => u.username === username && u.password === password) |
|
||||
|
|
||||
if (!user) { |
|
||||
return res.status(401).json({ |
|
||||
code: 401, |
|
||||
message: '用户名或密码错误' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 生成 JWT token |
|
||||
const token = jwt.sign( |
|
||||
{ id: user.id, username: user.username, role: user.role }, |
|
||||
JWT_SECRET, |
|
||||
{ expiresIn: '7d' } |
|
||||
) |
|
||||
|
|
||||
// 返回成功响应 |
|
||||
res.json({ |
|
||||
code: 200, |
|
||||
message: '登录成功', |
|
||||
data: { |
|
||||
token, |
|
||||
user: { |
|
||||
id: user.id, |
|
||||
username: user.username, |
|
||||
email: user.email, |
|
||||
role: user.role |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
// 登出接口 |
|
||||
app.post('/api/auth/logout', (req, res) => { |
|
||||
res.json({ |
|
||||
code: 200, |
|
||||
message: '登出成功' |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
// 获取用户信息接口 (需要认证) |
|
||||
app.get('/api/auth/userinfo', authenticateToken, (req, res) => { |
|
||||
const user = users.find(u => u.id === req.user.id) |
|
||||
|
|
||||
if (!user) { |
|
||||
return res.status(404).json({ |
|
||||
code: 404, |
|
||||
message: '用户不存在' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
res.json({ |
|
||||
code: 200, |
|
||||
message: '获取成功', |
|
||||
data: { |
|
||||
id: user.id, |
|
||||
username: user.username, |
|
||||
email: user.email, |
|
||||
role: user.role |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
// Token 验证中间件 |
|
||||
function authenticateToken(req, res, next) { |
|
||||
const authHeader = req.headers['authorization'] |
|
||||
const token = authHeader && authHeader.split(' ')[1] // Bearer <token> |
|
||||
|
|
||||
if (!token) { |
|
||||
return res.status(401).json({ |
|
||||
code: 401, |
|
||||
message: 'Token 缺失' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
jwt.verify(token, JWT_SECRET, (err, user) => { |
|
||||
if (err) { |
|
||||
return res.status(401).json({ |
|
||||
code: 401, |
|
||||
message: 'Token 无效或已过期' |
|
||||
}) |
|
||||
} |
|
||||
req.user = user |
|
||||
next() |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 启动服务器 |
|
||||
app.listen(PORT, () => { |
|
||||
console.log(\`✅ 服务器运行在 http://localhost:\${PORT}\`) |
|
||||
console.log(\`📝 API 文档: http://localhost:\${PORT}/api/docs\`) |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
### 3. 创建 `.env` |
|
||||
|
|
||||
```env |
|
||||
PORT=3000 |
|
||||
JWT_SECRET=your-super-secret-key-change-in-production |
|
||||
NODE_ENV=development |
|
||||
``` |
|
||||
|
|
||||
### 4. 运行服务器 |
|
||||
|
|
||||
```bash |
|
||||
node server.js |
|
||||
# 或使用 nodemon 自动重启 |
|
||||
npx nodemon server.js |
|
||||
``` |
|
||||
|
|
||||
## API 端点说明 |
|
||||
|
|
||||
### 登录接口 |
|
||||
|
|
||||
**请求** |
|
||||
``` |
|
||||
POST /api/auth/login |
|
||||
Content-Type: application/json |
|
||||
|
|
||||
{ |
|
||||
"username": "admin", |
|
||||
"password": "123456" |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**成功响应 (200)** |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", |
|
||||
"user": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**错误响应 (401)** |
|
||||
```json |
|
||||
{ |
|
||||
"code": 401, |
|
||||
"message": "用户名或密码错误" |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### 获取用户信息接口 |
|
||||
|
|
||||
**请求** |
|
||||
``` |
|
||||
GET /api/auth/userinfo |
|
||||
Authorization: Bearer <token> |
|
||||
``` |
|
||||
|
|
||||
**成功响应** |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "获取成功", |
|
||||
"data": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 使用 cURL 测试 |
|
||||
|
|
||||
```bash |
|
||||
# 登录 |
|
||||
curl -X POST http://localhost:3000/api/auth/login \ |
|
||||
-H "Content-Type: application/json" \ |
|
||||
-d '{"username":"admin","password":"123456"}' |
|
||||
|
|
||||
# 获取用户信息 |
|
||||
curl -X GET http://localhost:3000/api/auth/userinfo \ |
|
||||
-H "Authorization: Bearer YOUR_TOKEN_HERE" |
|
||||
``` |
|
||||
|
|
||||
## 使用 Postman 测试 |
|
||||
|
|
||||
1. 打开 Postman |
|
||||
2. 创建 POST 请求到 `http://localhost:3000/api/auth/login` |
|
||||
3. 在 Body → raw → JSON 中输入: |
|
||||
```json |
|
||||
{ |
|
||||
"username": "admin", |
|
||||
"password": "123456" |
|
||||
} |
|
||||
``` |
|
||||
4. 点击 Send |
|
||||
5. 复制响应中的 token |
|
||||
|
|
||||
## Python Flask 示例 |
|
||||
|
|
||||
```python |
|
||||
from flask import Flask, request, jsonify |
|
||||
from flask_cors import CORS |
|
||||
from functools import wraps |
|
||||
import jwt |
|
||||
from datetime import datetime, timedelta |
|
||||
|
|
||||
app = Flask(__name__) |
|
||||
CORS(app) |
|
||||
app.config['JSON_AS_ASCII'] = False |
|
||||
SECRET_KEY = 'your-secret-key' |
|
||||
|
|
||||
# 模拟用户数据 |
|
||||
USERS = [ |
|
||||
{'id': '1', 'username': 'admin', 'password': '123456', 'email': 'admin@example.com', 'role': 'admin'}, |
|
||||
{'id': '2', 'username': 'user', 'password': '123456', 'email': 'user@example.com', 'role': 'user'} |
|
||||
] |
|
||||
|
|
||||
def token_required(f): |
|
||||
@wraps(f) |
|
||||
def decorated(*args, **kwargs): |
|
||||
token = request.headers.get('Authorization', '').replace('Bearer ', '') |
|
||||
if not token: |
|
||||
return jsonify({'code': 401, 'message': 'Token 缺失'}), 401 |
|
||||
try: |
|
||||
data = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) |
|
||||
request.user_id = data['id'] |
|
||||
except: |
|
||||
return jsonify({'code': 401, 'message': 'Token 无效'}), 401 |
|
||||
return f(*args, **kwargs) |
|
||||
return decorated |
|
||||
|
|
||||
@app.route('/api/auth/login', methods=['POST']) |
|
||||
def login(): |
|
||||
data = request.json |
|
||||
username = data.get('username') |
|
||||
password = data.get('password') |
|
||||
|
|
||||
if not username or not password: |
|
||||
return jsonify({'code': 400, 'message': '用户名和密码不能为空'}), 400 |
|
||||
|
|
||||
user = next((u for u in USERS if u['username'] == username and u['password'] == password), None) |
|
||||
|
|
||||
if not user: |
|
||||
return jsonify({'code': 401, 'message': '用户名或密码错误'}), 401 |
|
||||
|
|
||||
token = jwt.encode( |
|
||||
{'id': user['id'], 'username': user['username']}, |
|
||||
SECRET_KEY, |
|
||||
algorithm='HS256' |
|
||||
) |
|
||||
|
|
||||
return jsonify({ |
|
||||
'code': 200, |
|
||||
'message': '登录成功', |
|
||||
'data': { |
|
||||
'token': token, |
|
||||
'user': { |
|
||||
'id': user['id'], |
|
||||
'username': user['username'], |
|
||||
'email': user['email'], |
|
||||
'role': user['role'] |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
@app.route('/api/auth/userinfo', methods=['GET']) |
|
||||
@token_required |
|
||||
def get_userinfo(): |
|
||||
user = next((u for u in USERS if u['id'] == request.user_id), None) |
|
||||
if not user: |
|
||||
return jsonify({'code': 404, 'message': '用户不存在'}), 404 |
|
||||
|
|
||||
return jsonify({ |
|
||||
'code': 200, |
|
||||
'message': '获取成功', |
|
||||
'data': { |
|
||||
'id': user['id'], |
|
||||
'username': user['username'], |
|
||||
'email': user['email'], |
|
||||
'role': user['role'] |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
app.run(debug=True, port=3000) |
|
||||
``` |
|
||||
|
|
||||
## Java Spring Boot 示例 |
|
||||
|
|
||||
```java |
|
||||
@RestController |
|
||||
@RequestMapping("/api/auth") |
|
||||
@CrossOrigin(origins = "*") |
|
||||
public class AuthController { |
|
||||
|
|
||||
@PostMapping("/login") |
|
||||
public ResponseEntity<?> login(@RequestBody LoginRequest request) { |
|
||||
// 验证用户 |
|
||||
User user = authenticateUser(request.getUsername(), request.getPassword()); |
|
||||
|
|
||||
if (user == null) { |
|
||||
return ResponseEntity.status(401).body(new ApiResponse(401, "用户名或密码错误")); |
|
||||
} |
|
||||
|
|
||||
// 生成 JWT token |
|
||||
String token = JwtUtils.generateToken(user); |
|
||||
|
|
||||
return ResponseEntity.ok(new ApiResponse(200, "登录成功", |
|
||||
new LoginResponse(token, user))); |
|
||||
} |
|
||||
|
|
||||
@GetMapping("/userinfo") |
|
||||
@PreAuthorize("isAuthenticated()") |
|
||||
public ResponseEntity<?> getUserInfo() { |
|
||||
User user = getCurrentUser(); |
|
||||
return ResponseEntity.ok(new ApiResponse(200, "获取成功", user)); |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
## 注意事项 |
|
||||
|
|
||||
1. **密码加密**:在生产环境中,必须加密存储密码(使用 bcrypt 等) |
|
||||
2. **HTTPS**:生产环境必须使用 HTTPS |
|
||||
3. **CORS**:根据前端域名配置 CORS |
|
||||
4. **Token 有效期**:建议设置合理的过期时间(如 7 天) |
|
||||
5. **错误处理**:返回统一的错误格式 |
|
||||
6. **日志记录**:记录所有登录尝试 |
|
||||
7. **速率限制**:防止暴力破解 |
|
||||
|
|
||||
## 与前端集成 |
|
||||
|
|
||||
1. 启动后端服务:`node server.js` |
|
||||
2. 启动前端开发服务:`npm run dev` |
|
||||
3. 前端会自动从 `http://localhost:3000/api` 调用后端接口 |
|
||||
4. 在登录页输入 `admin / 123456` 进行测试 |
|
||||
@ -1,501 +0,0 @@ |
|||||
# 🎉 后台管理系统 - 项目完成总结 |
|
||||
|
|
||||
## ✨ 项目概述 |
|
||||
|
|
||||
一个现代化的 Vue 3 + TypeScript 后台管理系统框架,具有完整的登录认证、用户管理、产品管理、订单管理等功能模块,采用优雅的暗黑主题设计。 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎨 设计主题 |
|
||||
|
|
||||
### 颜色方案(黑白双色暗黑风格) |
|
||||
```css |
|
||||
主色调:#667eea (紫蓝色) - 用于强调和交互元素 |
|
||||
副色调:#764ba2 (深紫) - 用于渐变和悬停效果 |
|
||||
|
|
||||
背景色:#0a0e27 (深蓝黑) - 主要背景 |
|
||||
卡片色:#1f2937 (深灰) - 内容卡片背景 |
|
||||
边框色:#374151 (浅深灰) - 边框分割线 |
|
||||
文字色:#e5e7eb (浅灰) - 主文本 |
|
||||
辅文字:#9ca3af (中灰) - 辅助文本 |
|
||||
|
|
||||
成功:#22c55e (绿色) |
|
||||
警告:#f59e0b (橙色) |
|
||||
错误:#ef4444 (红色) |
|
||||
信息:#3b82f6 (蓝色) |
|
||||
``` |
|
||||
|
|
||||
### 设计风格 |
|
||||
- ✅ 极简现代设计 |
|
||||
- ✅ 深色护眼主题 |
|
||||
- ✅ 圆角柔和设计 |
|
||||
- ✅ 平滑过渡动画 |
|
||||
- ✅ 响应式布局 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📁 完整的文件清单 |
|
||||
|
|
||||
### 核心文件 |
|
||||
``` |
|
||||
✅ src/main.ts - 应用入口,集成 Element Plus |
|
||||
✅ src/App.vue - 根组件,简化为路由容器 |
|
||||
✅ src/router/index.ts - 路由配置(含导航守卫) |
|
||||
✅ src/assets/main.css - 暗黑主题全局样式 |
|
||||
``` |
|
||||
|
|
||||
### 状态管理 |
|
||||
``` |
|
||||
✅ src/stores/auth.ts - 用户认证状态管理 |
|
||||
- 登录/登出功能 |
|
||||
- 用户信息管理 |
|
||||
- Token 管理 |
|
||||
- localStorage 持久化 |
|
||||
``` |
|
||||
|
|
||||
### 页面组件 |
|
||||
``` |
|
||||
✅ src/views/LoginView.vue - 登录页面 |
|
||||
- 用户名/密码输入 |
|
||||
- 表单验证 |
|
||||
- 记住登录状态 |
|
||||
|
|
||||
✅ src/views/AdminLayout.vue - 后台主布局 |
|
||||
- 侧边栏 + 内容区域布局 |
|
||||
- 顶部导航栏 |
|
||||
- 退出登录功能 |
|
||||
|
|
||||
✅ src/views/admin/DashboardView.vue - 仪表板 |
|
||||
- 数据统计卡片 |
|
||||
- 最近订单表格 |
|
||||
- 数据概览展示 |
|
||||
|
|
||||
✅ src/views/admin/UsersView.vue - 用户管理 |
|
||||
- 用户列表展示 |
|
||||
- 搜索功能 |
|
||||
- 新增用户 |
|
||||
- 编辑用户 |
|
||||
- 删除用户 |
|
||||
- 状态管理 |
|
||||
|
|
||||
✅ src/views/admin/ProductsView.vue - 产品管理 |
|
||||
- 产品列表管理 |
|
||||
- 搜索过滤 |
|
||||
- 新增产品 |
|
||||
- 编辑产品 |
|
||||
- 删除产品 |
|
||||
- 库存管理 |
|
||||
- 价格管理 |
|
||||
|
|
||||
✅ src/views/admin/OrdersView.vue - 订单管理 |
|
||||
- 订单列表展示 |
|
||||
- 高级过滤 |
|
||||
- 订单搜索 |
|
||||
- 新增订单 |
|
||||
- 编辑订单 |
|
||||
- 删除订单 |
|
||||
- 状态跟踪 |
|
||||
|
|
||||
✅ src/views/admin/SettingsView.vue - 系统设置 |
|
||||
- 基本设置 |
|
||||
- 安全设置 |
|
||||
- 备份配置 |
|
||||
- 文件类型管理 |
|
||||
``` |
|
||||
|
|
||||
### 可复用组件 |
|
||||
``` |
|
||||
✅ src/components/Header.vue - 顶部导航栏 |
|
||||
- 菜单切换按钮 |
|
||||
- 用户信息展示 |
|
||||
- 退出登录按钮 |
|
||||
|
|
||||
✅ src/components/Sidebar.vue - 侧边栏菜单 |
|
||||
- 可折叠菜单 |
|
||||
- 图标 + 文字标签 |
|
||||
- 当前路由高亮 |
|
||||
- 菜单项导航 |
|
||||
``` |
|
||||
|
|
||||
### 文档文件 |
|
||||
``` |
|
||||
✅ ADMIN_SYSTEM_README.md - 项目完整文档 |
|
||||
✅ QUICK_START.md - 快速开始指南 |
|
||||
✅ PROJECT_SUMMARY.md - 本文件 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎯 功能清单 |
|
||||
|
|
||||
### 已实现的功能 |
|
||||
|
|
||||
#### 1. 认证系统 ✅ |
|
||||
- [x] 登录页面(用户名/密码) |
|
||||
- [x] 登录状态验证 |
|
||||
- [x] 自动登录(localStorage 记忆) |
|
||||
- [x] 登出功能 |
|
||||
- [x] 路由保护守卫 |
|
||||
- [x] 登录失败提示 |
|
||||
|
|
||||
#### 2. 仪表板 ✅ |
|
||||
- [x] 数据统计卡片(4 个指标) |
|
||||
- [x] 统计数据展示 |
|
||||
- [x] 最近订单表格 |
|
||||
- [x] 欢迎信息 |
|
||||
|
|
||||
#### 3. 用户管理(CRUD 完整示例)✅ |
|
||||
- [x] 用户列表展示 |
|
||||
- [x] 搜索功能(用户名/邮箱) |
|
||||
- [x] 新增用户对话框 |
|
||||
- [x] 编辑用户信息 |
|
||||
- [x] 删除用户 |
|
||||
- [x] 状态管理(启用/禁用) |
|
||||
- [x] 角色管理(管理员/普通用户) |
|
||||
- [x] 创建时间记录 |
|
||||
|
|
||||
#### 4. 产品管理(CRUD 完整示例)✅ |
|
||||
- [x] 产品列表展示 |
|
||||
- [x] 搜索功能(名称/SKU) |
|
||||
- [x] 新增产品 |
|
||||
- [x] 编辑产品信息 |
|
||||
- [x] 删除产品 |
|
||||
- [x] 库存管理 |
|
||||
- [x] 价格管理 |
|
||||
- [x] 分类管理 |
|
||||
- [x] 上架/下架状态 |
|
||||
- [x] 库存警告显示 |
|
||||
|
|
||||
#### 5. 订单管理(CRUD 完整示例)✅ |
|
||||
- [x] 订单列表展示 |
|
||||
- [x] 搜索功能(订单号/客户名) |
|
||||
- [x] 状态过滤 |
|
||||
- [x] 新增订单 |
|
||||
- [x] 编辑订单 |
|
||||
- [x] 删除订单 |
|
||||
- [x] 支付方式管理 |
|
||||
- [x] 订单状态追踪 |
|
||||
- [x] 金额管理 |
|
||||
|
|
||||
#### 6. 系统设置 ✅ |
|
||||
- [x] 基本设置表单 |
|
||||
- [x] 安全设置 |
|
||||
- [x] 备份配置 |
|
||||
- [x] 文件上传设置 |
|
||||
- [x] 文件类型管理 |
|
||||
- [x] 设置保存功能 |
|
||||
|
|
||||
#### 7. UI 组件 ✅ |
|
||||
- [x] 侧边栏菜单(可折叠) |
|
||||
- [x] 顶部导航栏 |
|
||||
- [x] 对话框表单 |
|
||||
- [x] 数据表格 |
|
||||
- [x] 搜索输入 |
|
||||
- [x] 状态标签 |
|
||||
- [x] 按钮组件 |
|
||||
- [x] 表单输入 |
|
||||
|
|
||||
#### 8. 交互功能 ✅ |
|
||||
- [x] 弹出确认对话框 |
|
||||
- [x] 提示消息提醒 |
|
||||
- [x] 加载状态显示 |
|
||||
- [x] 表单验证 |
|
||||
- [x] 回车键提交 |
|
||||
- [x] 菜单切换动画 |
|
||||
|
|
||||
#### 9. 路由系统 ✅ |
|
||||
- [x] 登录路由 |
|
||||
- [x] 后台管理路由 |
|
||||
- [x] 路由懒加载 |
|
||||
- [x] 导航守卫(认证检查) |
|
||||
- [x] 自动重定向 |
|
||||
- [x] 404 处理 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🚀 技术架构 |
|
||||
|
|
||||
### 技术栈 |
|
||||
``` |
|
||||
Frontend: |
|
||||
- Vue 3.5.27 前端框架 |
|
||||
- TypeScript 5.9.3 类型安全 |
|
||||
- Vite 7.3.1 构建工具 |
|
||||
- Vue Router 4.6.4 路由管理 |
|
||||
- Pinia 3.0.4 状态管理 |
|
||||
- Element Plus 2.7.0 UI 组件库 |
|
||||
- Axios HTTP 请求 |
|
||||
``` |
|
||||
|
|
||||
### 架构特点 |
|
||||
``` |
|
||||
1. 组件化设计 |
|
||||
- 可复用组件模式 |
|
||||
- 父子组件通信 |
|
||||
- Emits 事件机制 |
|
||||
|
|
||||
2. 状态管理 |
|
||||
- Pinia 集中管理状态 |
|
||||
- localStorage 持久化 |
|
||||
- 单一数据源 |
|
||||
|
|
||||
3. 路由管理 |
|
||||
- 嵌套路由结构 |
|
||||
- 导航守卫保护 |
|
||||
- 懒加载优化 |
|
||||
|
|
||||
4. 样式系统 |
|
||||
- Scoped CSS |
|
||||
- CSS 变量(可扩展) |
|
||||
- 响应式设计 |
|
||||
|
|
||||
5. 类型安全 |
|
||||
- 完整的 TypeScript 支持 |
|
||||
- 接口定义 |
|
||||
- 类型检查 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📊 数据流 |
|
||||
|
|
||||
### 登录流程 |
|
||||
``` |
|
||||
用户输入 → 表单验证 → authStore.login() |
|
||||
→ localStorage 保存 → 路由重定向 → 仪表板 |
|
||||
``` |
|
||||
|
|
||||
### 页面导航 |
|
||||
``` |
|
||||
点击菜单 → Router.push() → 导航守卫检查 |
|
||||
→ 页面组件加载 → 内容展示 |
|
||||
``` |
|
||||
|
|
||||
### 数据操作 |
|
||||
``` |
|
||||
表单提交 → 数据验证 → ref 状态更新 |
|
||||
→ UI 重新渲染 → 操作反馈 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎨 样式系统 |
|
||||
|
|
||||
### 响应式设计 |
|
||||
```css |
|
||||
✅ 桌面端:完整布局 |
|
||||
✅ 平板端:侧边栏可收缩 |
|
||||
✅ 手机端:响应式卡片布局 |
|
||||
``` |
|
||||
|
|
||||
### 颜色管理 |
|
||||
```css |
|
||||
主题颜色统一使用: |
|
||||
- 主调:#667eea(可自定义) |
|
||||
- 背景:#0a0e27(可自定义) |
|
||||
- 卡片:#1f2937(可自定义) |
|
||||
- 文本:#e5e7eb(可自定义) |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🔐 安全特性 |
|
||||
|
|
||||
### 已实现 |
|
||||
``` |
|
||||
✅ 路由认证守卫 |
|
||||
✅ 登录状态管理 |
|
||||
✅ 表单数据验证 |
|
||||
✅ 错误提示处理 |
|
||||
✅ Token 管理 |
|
||||
``` |
|
||||
|
|
||||
### 建议增强 |
|
||||
``` |
|
||||
⚠️ HTTPS 传输 |
|
||||
⚠️ API 签名验证 |
|
||||
⚠️ CSRF 令牌 |
|
||||
⚠️ XSS 防护 |
|
||||
⚠️ 权限细粒度控制 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📈 性能优化 |
|
||||
|
|
||||
### 已优化项 |
|
||||
``` |
|
||||
✅ 路由懒加载 |
|
||||
✅ 组件动态导入 |
|
||||
✅ 事件委托 |
|
||||
✅ 防抖处理 |
|
||||
``` |
|
||||
|
|
||||
### 可优化项 |
|
||||
``` |
|
||||
⚠️ 虚拟滚动(大列表) |
|
||||
⚠️ 分页加载 |
|
||||
⚠️ 图片懒加载 |
|
||||
⚠️ 缓存策略 |
|
||||
⚠️ 代码分割优化 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎓 学习路径 |
|
||||
|
|
||||
### 初级开发者 |
|
||||
1. 理解 Vue 3 基础 |
|
||||
2. 学习组件通信 |
|
||||
3. 理解 Pinia 状态管理 |
|
||||
4. 学习 Vue Router 路由 |
|
||||
|
|
||||
### 中级开发者 |
|
||||
1. API 集成 |
|
||||
2. 表单验证和处理 |
|
||||
3. 错误处理 |
|
||||
4. 权限管理 |
|
||||
|
|
||||
### 高级开发者 |
|
||||
1. 性能优化 |
|
||||
2. 安全加固 |
|
||||
3. 自动化测试 |
|
||||
4. 部署流程 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📋 使用说明 |
|
||||
|
|
||||
### 快速启动 |
|
||||
```bash |
|
||||
# 1. 安装依赖 |
|
||||
npm install |
|
||||
|
|
||||
# 2. 开发模式 |
|
||||
npm run dev |
|
||||
|
|
||||
# 3. 访问 |
|
||||
http://localhost:5173 |
|
||||
|
|
||||
# 4. 登录信息 |
|
||||
用户名: admin |
|
||||
密码: 123456 |
|
||||
``` |
|
||||
|
|
||||
### 生产构建 |
|
||||
```bash |
|
||||
# 构建 |
|
||||
npm run build |
|
||||
|
|
||||
# 预览 |
|
||||
npm run preview |
|
||||
|
|
||||
# 类型检查 |
|
||||
npm run type-check |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🛠 后续开发计划 |
|
||||
|
|
||||
### Phase 1: 基础功能(当前 ✅) |
|
||||
- [x] 登录认证 |
|
||||
- [x] CRUD 模块 |
|
||||
- [x] 主题设计 |
|
||||
|
|
||||
### Phase 2: 功能扩展(推荐) |
|
||||
- [ ] API 后端集成 |
|
||||
- [ ] 权限管理系统 |
|
||||
- [ ] 审计日志 |
|
||||
- [ ] 批量操作 |
|
||||
- [ ] 导出功能 |
|
||||
|
|
||||
### Phase 3: 用户体验(优化) |
|
||||
- [ ] 深浅主题切换 |
|
||||
- [ ] 国际化多语言 |
|
||||
- [ ] 快捷键支持 |
|
||||
- [ ] 高级搜索 |
|
||||
- [ ] 自定义仪表板 |
|
||||
|
|
||||
### Phase 4: 系统优化(性能) |
|
||||
- [ ] 性能监控 |
|
||||
- [ ] 错误追踪 |
|
||||
- [ ] 用户行为分析 |
|
||||
- [ ] 缓存策略 |
|
||||
- [ ] CDN 配置 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 💡 开发建议 |
|
||||
|
|
||||
### 代码组织 |
|
||||
``` |
|
||||
建议创建 src/api 文件夹管理所有 API 调用 |
|
||||
建议创建 src/services 文件夹存放业务逻辑 |
|
||||
建议创建 src/types 文件夹存放类型定义 |
|
||||
建议创建 src/utils 文件夹存放工具函数 |
|
||||
``` |
|
||||
|
|
||||
### 命名规范 |
|
||||
``` |
|
||||
✅ 组件文件:PascalCase(如 UserForm.vue) |
|
||||
✅ 页面文件:PascalCase + View 后缀(如 UsersView.vue) |
|
||||
✅ Store 文件:camelCase + Store 后缀(如 authStore.ts) |
|
||||
✅ 类名:PascalCase |
|
||||
✅ 变量/函数:camelCase |
|
||||
✅ 常量:UPPER_CASE |
|
||||
``` |
|
||||
|
|
||||
### Git 管理 |
|
||||
```bash |
|
||||
# 建议分支结构 |
|
||||
main - 生产环境 |
|
||||
develop - 开发环境 |
|
||||
feature/* - 功能分支 |
|
||||
bugfix/* - 修复分支 |
|
||||
hotfix/* - 紧急修复 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎉 项目成果总结 |
|
||||
|
|
||||
✅ **完整的后台管理系统框架** |
|
||||
- 5 个功能模块(仪表板、用户、产品、订单、设置) |
|
||||
- 2 个可复用组件(导航栏、侧边栏) |
|
||||
- 完整的 CRUD 示例 |
|
||||
|
|
||||
✅ **专业的暗黑主题设计** |
|
||||
- 黑白双色优雅设计 |
|
||||
- 响应式布局 |
|
||||
- 平滑动画效果 |
|
||||
|
|
||||
✅ **完善的路由和认证系统** |
|
||||
- 登录/登出功能 |
|
||||
- 路由保护守卫 |
|
||||
- localStorage 持久化 |
|
||||
|
|
||||
✅ **生产级代码质量** |
|
||||
- TypeScript 类型安全 |
|
||||
- 完整的错误处理 |
|
||||
- 用户友好的提示反馈 |
|
||||
|
|
||||
✅ **详细的文档和注释** |
|
||||
- 项目完整文档 |
|
||||
- 快速开始指南 |
|
||||
- 代码注释清晰 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📞 联系方式 |
|
||||
|
|
||||
如有任何问题或建议,欢迎反馈。 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
**项目创建时间**: 2026-02-02 |
|
||||
**框架版本**: Vue 3.5.27 + TypeScript 5.9.3 |
|
||||
**主题**: 暗黑风格(黑白双色) |
|
||||
**状态**: ✅ 已完成且可直接使用 |
|
||||
|
|
||||
祝你开发愉快!🚀 |
|
||||
@ -1,170 +0,0 @@ |
|||||
# 快速开始指南 |
|
||||
|
|
||||
## 系统已搭建完成 ✅ |
|
||||
|
|
||||
你的后台管理系统框架已经完全搭建好!以下是完成的内容: |
|
||||
|
|
||||
## 📦 已安装的依赖 |
|
||||
|
|
||||
- ✅ Vue 3 |
|
||||
- ✅ TypeScript |
|
||||
- ✅ Vue Router |
|
||||
- ✅ Pinia (状态管理) |
|
||||
- ✅ Element Plus (UI 库) |
|
||||
- ✅ Axios (HTTP 请求) |
|
||||
- ✅ Vite (构建工具) |
|
||||
|
|
||||
## 🏗️ 已创建的文件结构 |
|
||||
|
|
||||
### 状态管理 |
|
||||
- `src/stores/auth.ts` - 认证状态管理(用户登录/登出) |
|
||||
|
|
||||
### 页面组件 |
|
||||
- `src/views/LoginView.vue` - 登录页面 |
|
||||
- `src/views/AdminLayout.vue` - 后台主布局 |
|
||||
- `src/views/admin/DashboardView.vue` - 仪表板 |
|
||||
- `src/views/admin/UsersView.vue` - 用户管理(CRUD 示例) |
|
||||
- `src/views/admin/ProductsView.vue` - 产品管理(CRUD 示例) |
|
||||
- `src/views/admin/OrdersView.vue` - 订单管理(CRUD 示例) |
|
||||
- `src/views/admin/SettingsView.vue` - 系统设置 |
|
||||
|
|
||||
### 可复用组件 |
|
||||
- `src/components/Header.vue` - 顶部导航栏 |
|
||||
- `src/components/Sidebar.vue` - 侧边栏菜单 |
|
||||
|
|
||||
### 配置文件 |
|
||||
- `src/router/index.ts` - 路由配置(包含导航守卫) |
|
||||
- `src/main.ts` - 应用入口 |
|
||||
- `src/App.vue` - 根组件 |
|
||||
- `src/assets/main.css` - 暗黑主题样式 |
|
||||
|
|
||||
## 🎨 设计特点 |
|
||||
|
|
||||
### 暗黑主题配置 |
|
||||
- 主色调:紫蓝色 (#667eea) |
|
||||
- 背景:深蓝黑 (#0a0e27) |
|
||||
- 卡片:深灰 (#1f2937) |
|
||||
- 文本:浅灰 (#e5e7eb) |
|
||||
|
|
||||
### UI 特性 |
|
||||
- 侧边栏可折叠 |
|
||||
- 响应式设计 |
|
||||
- 平滑过渡动画 |
|
||||
- 深色主题优化 |
|
||||
|
|
||||
## 🚀 运行项目 |
|
||||
|
|
||||
### 开发环境 |
|
||||
```bash |
|
||||
npm run dev |
|
||||
``` |
|
||||
访问 http://localhost:5173 |
|
||||
|
|
||||
### 生产构建 |
|
||||
```bash |
|
||||
npm run build |
|
||||
``` |
|
||||
|
|
||||
### 类型检查 |
|
||||
```bash |
|
||||
npm run type-check |
|
||||
``` |
|
||||
|
|
||||
## 🔐 登录信息 |
|
||||
|
|
||||
- **用户名**: admin |
|
||||
- **密码**: 123456 |
|
||||
|
|
||||
## 📋 功能清单 |
|
||||
|
|
||||
✅ 登录/登出功能 |
|
||||
✅ 仪表板(数据统计) |
|
||||
✅ 用户管理(增删改查) |
|
||||
✅ 产品管理(增删改查) |
|
||||
✅ 订单管理(增删改查) |
|
||||
✅ 系统设置 |
|
||||
✅ 侧边栏导航 |
|
||||
✅ 顶部导航栏 |
|
||||
✅ 路由保护 |
|
||||
✅ 响应式布局 |
|
||||
|
|
||||
## 🎯 后续开发步骤 |
|
||||
|
|
||||
1. **后端 API 集成** |
|
||||
- 替换 mock 数据为真实 API 调用 |
|
||||
- 使用 axios 进行 HTTP 请求 |
|
||||
- 添加错误处理和加载状态 |
|
||||
|
|
||||
2. **权限管理** |
|
||||
- 根据用户角色显示/隐藏菜单项 |
|
||||
- 实现页面级权限控制 |
|
||||
- 添加操作级权限检查 |
|
||||
|
|
||||
3. **数据验证** |
|
||||
- 为所有表单添加输入验证 |
|
||||
- 实现客户端表单验证规则 |
|
||||
- 添加服务端验证提示 |
|
||||
|
|
||||
4. **功能扩展** |
|
||||
- 添加更多管理模块 |
|
||||
- 实现导出/导入功能 |
|
||||
- 添加批量操作功能 |
|
||||
- 实现高级过滤和搜索 |
|
||||
|
|
||||
5. **性能优化** |
|
||||
- 实现虚拟滚动 |
|
||||
- 添加分页功能 |
|
||||
- 优化图片加载 |
|
||||
- 实现懒加载 |
|
||||
|
|
||||
6. **用户体验** |
|
||||
- 添加更多交互反馈 |
|
||||
- 实现快捷键支持 |
|
||||
- 添加深色/浅色主题切换 |
|
||||
- 实现国际化多语言 |
|
||||
|
|
||||
## 📚 文件修改说明 |
|
||||
|
|
||||
### 关键文件 |
|
||||
|
|
||||
1. **src/router/index.ts** |
|
||||
- 完全重写了路由配置 |
|
||||
- 添加了导航守卫(认证检查) |
|
||||
- 配置了后台管理模块路由 |
|
||||
|
|
||||
2. **src/main.ts** |
|
||||
- 集成了 Element Plus |
|
||||
- 初始化认证状态 |
|
||||
|
|
||||
3. **src/App.vue** |
|
||||
- 简化为只展示路由视图 |
|
||||
|
|
||||
4. **src/assets/main.css** |
|
||||
- 更新为暗黑主题样式 |
|
||||
|
|
||||
## 💡 开发建议 |
|
||||
|
|
||||
1. 所有 CRUD 页面都有完整的搜索、编辑、删除功能示例 |
|
||||
2. 使用 Pinia store 管理全局状态 |
|
||||
3. 表单验证可以使用 Element Plus 的表单验证功能 |
|
||||
4. API 调用使用 axios 库,可创建 `src/api` 文件夹管理所有 API |
|
||||
5. 创建 `src/services` 文件夹存放业务逻辑 |
|
||||
|
|
||||
## 🔗 项目结构优化建议 |
|
||||
|
|
||||
``` |
|
||||
src/ |
|
||||
├── api/ # API 接口管理 |
|
||||
│ ├── users.ts |
|
||||
│ ├── products.ts |
|
||||
│ ├── orders.ts |
|
||||
│ └── index.ts |
|
||||
├── services/ # 业务逻辑服务 |
|
||||
├── types/ # TypeScript 类型定义 |
|
||||
├── utils/ # 工具函数 |
|
||||
├── hooks/ # 自定义 Hooks |
|
||||
├── directives/ # 自定义指令 |
|
||||
└── ... |
|
||||
``` |
|
||||
|
|
||||
祝你开发愉快!如有任何问题,随时联系我。 |
|
||||
@ -1,235 +0,0 @@ |
|||||
# 🎯 Axios API 集成 - 一句话总结 |
|
||||
|
|
||||
## 你问的问题 |
|
||||
|
|
||||
> 是不是少了axios相关的东西?调用后台接口,后台接口会传递json数据上来,我应该怎么做?你只用做一个登录示例就可以了。 |
|
||||
|
|
||||
## 答案 |
|
||||
|
|
||||
✅ **已为你完成!** 完整的 axios 配置和登录 API 示例已创建。 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📂 新增文件 |
|
||||
|
|
||||
### API 层(前端代码) |
|
||||
|
|
||||
``` |
|
||||
src/api/ |
|
||||
├── index.ts ← axios 实例 + 拦截器 |
|
||||
│ • baseURL 自动添加 API 前缀 |
|
||||
│ • 请求拦截器自动添加 token |
|
||||
│ • 响应拦截器自动处理错误 |
|
||||
│ |
|
||||
└── auth.ts ← 登录 API |
|
||||
• loginApi(username, password) - 调用 POST /api/auth/login |
|
||||
• logoutApi() |
|
||||
• getUserInfoApi() |
|
||||
• 完整的 TypeScript 类型定义 |
|
||||
``` |
|
||||
|
|
||||
### 环境配置 |
|
||||
|
|
||||
``` |
|
||||
.env.development ← API 地址:http://localhost:3000/api |
|
||||
.env.production ← API 地址:https://api.example.com/api |
|
||||
.env.local ← 本地覆盖 |
|
||||
``` |
|
||||
|
|
||||
### 文档 |
|
||||
|
|
||||
``` |
|
||||
WHAT_TO_DO_NEXT.md ← 👈 你接下来该做什么(先读这个) |
|
||||
API_IMPLEMENTATION_COMPLETE.md ← 完整总结 |
|
||||
API_INTEGRATION_GUIDE.md ← 详细教程 |
|
||||
BACKEND_API_EXAMPLE.md ← 后端代码示例 |
|
||||
API_QUICK_REFERENCE.md ← 快速参考 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🔄 工作流程 |
|
||||
|
|
||||
### 简单版本 |
|
||||
|
|
||||
``` |
|
||||
用户登录 |
|
||||
↓ |
|
||||
await authStore.login(username, password) |
|
||||
↓ |
|
||||
loginApi(credentials) |
|
||||
↓ |
|
||||
http.post('/auth/login', credentials) |
|
||||
↓ |
|
||||
axios 拦截器处理 |
|
||||
↓ |
|
||||
POST http://localhost:3000/api/auth/login |
|
||||
↓ |
|
||||
后端返回 JSON |
|
||||
↓ |
|
||||
axios 拦截器提取 response.data |
|
||||
↓ |
|
||||
前端收到数据 |
|
||||
↓ |
|
||||
保存 token 和 user 到 localStorage |
|
||||
↓ |
|
||||
登录成功! |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 💻 后端返回的 JSON 格式 |
|
||||
|
|
||||
你的后端需要返回这样的格式: |
|
||||
|
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", |
|
||||
"user": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
**关键点:** |
|
||||
- `code` 必须是 200 表示成功 |
|
||||
- `data.token` 是 JWT,后续请求会自动在 `Authorization: Bearer <token>` 中发送 |
|
||||
- `data.user` 包含用户信息 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🚀 立即测试 |
|
||||
|
|
||||
### 选项 1:使用提供的后端示例 |
|
||||
|
|
||||
```bash |
|
||||
# 创建后端项目 |
|
||||
mkdir admin-backend && cd admin-backend |
|
||||
npm init -y && npm install express cors jsonwebtoken |
|
||||
|
|
||||
# 复制 BACKEND_API_EXAMPLE.md 中的代码到 server.js |
|
||||
# 然后运行 |
|
||||
node server.js |
|
||||
|
|
||||
# 在另一个终端启动前端 |
|
||||
npm run dev |
|
||||
|
|
||||
# 访问 http://localhost:5173 |
|
||||
# 输入 admin / 123456 登录 |
|
||||
``` |
|
||||
|
|
||||
### 选项 2:集成你自己的后端 |
|
||||
|
|
||||
1. 实现 `POST /api/auth/login` 接口 |
|
||||
2. 返回上述格式的 JSON |
|
||||
3. 配置 CORS |
|
||||
4. 启动后端 |
|
||||
5. 运行 `npm run dev` |
|
||||
6. 测试登录 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📝 代码示例 |
|
||||
|
|
||||
### 在组件中使用(已更新) |
|
||||
|
|
||||
```typescript |
|
||||
import { useAuthStore } from '@/stores/auth' |
|
||||
|
|
||||
const authStore = useAuthStore() |
|
||||
|
|
||||
// 登录 |
|
||||
const success = await authStore.login('admin', '123456') |
|
||||
if (success) { |
|
||||
console.log('登录成功!') |
|
||||
} |
|
||||
|
|
||||
// 获取当前用户 |
|
||||
console.log(authStore.user) |
|
||||
console.log(authStore.token) |
|
||||
|
|
||||
// 登出 |
|
||||
await authStore.logout() |
|
||||
``` |
|
||||
|
|
||||
### 添加新的 API(参考登录示例) |
|
||||
|
|
||||
```typescript |
|
||||
// src/api/users.ts |
|
||||
import http from './index' |
|
||||
|
|
||||
export const getUsersApi = () => { |
|
||||
return http.get('/users') |
|
||||
} |
|
||||
|
|
||||
export const createUserApi = (data) => { |
|
||||
return http.post('/users', data) |
|
||||
} |
|
||||
|
|
||||
// 在组件中使用 |
|
||||
const response = await getUsersApi() |
|
||||
if (response.code === 200) { |
|
||||
console.log(response.data) |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## ✅ 检查清单 |
|
||||
|
|
||||
### 前端(✅ 已完成) |
|
||||
|
|
||||
- [x] Axios 配置 |
|
||||
- [x] 拦截器设置 |
|
||||
- [x] API 服务层 |
|
||||
- [x] 登录示例 |
|
||||
- [x] TypeScript 类型 |
|
||||
- [x] 环境配置 |
|
||||
|
|
||||
### 你需要做(⏳ 待实施) |
|
||||
|
|
||||
- [ ] 实现后端登录接口 |
|
||||
- [ ] 配置 CORS |
|
||||
- [ ] 启动后端 |
|
||||
- [ ] 测试集成 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📚 快速参考 |
|
||||
|
|
||||
| 需求 | 文件 | 说明 | |
|
||||
|------|------|------| |
|
||||
| 快速上手 | `WHAT_TO_DO_NEXT.md` | 下一步该做什么 | |
|
||||
| 详细教程 | `API_INTEGRATION_GUIDE.md` | 完整 API 使用指南 | |
|
||||
| 后端参考 | `BACKEND_API_EXAMPLE.md` | Node.js/Python 实现 | |
|
||||
| 代码参考 | `API_QUICK_REFERENCE.md` | 快速代码片段 | |
|
||||
| 原理说明 | `API_IMPLEMENTATION_COMPLETE.md` | 完整工作流程 | |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎉 总结 |
|
||||
|
|
||||
``` |
|
||||
✅ 前端:完整的 API 层 + 登录示例 |
|
||||
⏳ 你的工作:实现后端 API + 配置 CORS + 测试 |
|
||||
|
|
||||
预计时间:15 分钟 |
|
||||
结果:功能完整的登录系统 |
|
||||
``` |
|
||||
|
|
||||
**现在就开始吧!** 🚀 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
**相关文档快速链接:** |
|
||||
- 👉 [接下来该做什么](./WHAT_TO_DO_NEXT.md) |
|
||||
- 📖 [详细集成指南](./API_INTEGRATION_GUIDE.md) |
|
||||
- 💻 [后端代码示例](./BACKEND_API_EXAMPLE.md) |
|
||||
- ⚡ [快速参考](./API_QUICK_REFERENCE.md) |
|
||||
@ -1,390 +0,0 @@ |
|||||
# 🎯 API 集成总结 - 你该做什么 |
|
||||
|
|
||||
## ✅ 已经为你完成的 |
|
||||
|
|
||||
### 1. 前端 API 架构 |
|
||||
|
|
||||
``` |
|
||||
src/api/ |
|
||||
├── index.ts - axios 实例 + 拦截器(请求时自动添加 token) |
|
||||
└── auth.ts - 登录相关 API 定义 |
|
||||
``` |
|
||||
|
|
||||
### 2. 更新的文件 |
|
||||
|
|
||||
``` |
|
||||
src/stores/auth.ts - 已更新为调用真实 API |
|
||||
src/views/LoginView.vue - 已更新为异步登录 |
|
||||
``` |
|
||||
|
|
||||
### 3. 环境配置 |
|
||||
|
|
||||
``` |
|
||||
.env.development - API 地址:http://localhost:3000/api |
|
||||
.env.production - API 地址:https://api.example.com/api (修改为你的) |
|
||||
.env.local - 本地覆盖配置 |
|
||||
``` |
|
||||
|
|
||||
### 4. 完整的文档 |
|
||||
|
|
||||
``` |
|
||||
API_IMPLEMENTATION_COMPLETE.md - 最完整的总结(推荐先读这个) |
|
||||
API_INTEGRATION_GUIDE.md - 详细 API 使用指南 |
|
||||
BACKEND_API_EXAMPLE.md - 后端代码示例(Node.js/Python) |
|
||||
API_QUICK_REFERENCE.md - 快速参考卡片 |
|
||||
``` |
|
||||
|
|
||||
## 🚀 你现在需要做什么 |
|
||||
|
|
||||
### 方案 A:使用我提供的后端示例 |
|
||||
|
|
||||
**第 1 步:创建后端项目** |
|
||||
|
|
||||
```bash |
|
||||
mkdir admin-backend |
|
||||
cd admin-backend |
|
||||
npm init -y |
|
||||
npm install express cors jsonwebtoken |
|
||||
``` |
|
||||
|
|
||||
**第 2 步:创建 `server.js`** |
|
||||
|
|
||||
参考 `BACKEND_API_EXAMPLE.md` 中的 Node.js 示例代码,复制到 `server.js` |
|
||||
|
|
||||
**第 3 步:启动后端** |
|
||||
|
|
||||
```bash |
|
||||
node server.js |
|
||||
``` |
|
||||
|
|
||||
你会看到: |
|
||||
``` |
|
||||
✅ 服务器运行在 http://localhost:3000 |
|
||||
``` |
|
||||
|
|
||||
**第 4 步:启动前端** |
|
||||
|
|
||||
在另一个终端: |
|
||||
|
|
||||
```bash |
|
||||
npm run dev |
|
||||
``` |
|
||||
|
|
||||
**第 5 步:测试** |
|
||||
|
|
||||
1. 访问 http://localhost:5173 |
|
||||
2. 输入 `admin / 123456` |
|
||||
3. 点击登录 |
|
||||
4. 应该看到"登录成功"并跳转到仪表板 ✨ |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
### 方案 B:使用你自己的后端 |
|
||||
|
|
||||
**需要做什么:** |
|
||||
|
|
||||
1. **实现登录接口** |
|
||||
|
|
||||
端点:`POST /api/auth/login` |
|
||||
|
|
||||
请求: |
|
||||
```json |
|
||||
{ |
|
||||
"username": "admin", |
|
||||
"password": "123456" |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
响应: |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, |
|
||||
"message": "登录成功", |
|
||||
"data": { |
|
||||
"token": "jwt_token_here", |
|
||||
"user": { |
|
||||
"id": "1", |
|
||||
"username": "admin", |
|
||||
"email": "admin@example.com", |
|
||||
"role": "admin" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
2. **配置 CORS** |
|
||||
|
|
||||
允许前端跨域请求: |
|
||||
``` |
|
||||
Access-Control-Allow-Origin: http://localhost:5173 |
|
||||
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS |
|
||||
Access-Control-Allow-Headers: Content-Type, Authorization |
|
||||
``` |
|
||||
|
|
||||
3. **启动后端服务** |
|
||||
|
|
||||
确保监听 `3000` 端口(或修改 `.env.development` 中的地址) |
|
||||
|
|
||||
4. **启动前端** |
|
||||
|
|
||||
```bash |
|
||||
npm run dev |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🔧 常见问题 |
|
||||
|
|
||||
### Q: 前端提示"网络错误" |
|
||||
|
|
||||
**解决方案:** |
|
||||
1. 检查后端是否启动:`http://localhost:3000` |
|
||||
2. 检查 `.env.development` 中的 API 地址是否正确 |
|
||||
3. 查看浏览器开发者工具的 Network 标签查看请求 |
|
||||
|
|
||||
### Q: 前端提示"CORS error" |
|
||||
|
|
||||
**解决方案:** |
|
||||
- 后端必须配置 CORS,允许来自 `http://localhost:5173` 的请求 |
|
||||
|
|
||||
**Express 示例:** |
|
||||
```javascript |
|
||||
const cors = require('cors') |
|
||||
app.use(cors({ |
|
||||
origin: 'http://localhost:5173', |
|
||||
credentials: true |
|
||||
})) |
|
||||
``` |
|
||||
|
|
||||
### Q: 登录提示"401 未授权" |
|
||||
|
|
||||
**解决方案:** |
|
||||
- 检查后端返回的 `code` 是否为 200 |
|
||||
- 检查用户名和密码是否匹配 |
|
||||
- 查看后端日志 |
|
||||
|
|
||||
### Q: 登录后页面不跳转 |
|
||||
|
|
||||
**解决方案:** |
|
||||
1. 检查浏览器控制台是否有 JavaScript 错误 |
|
||||
2. 检查是否成功保存到 localStorage(打开开发者工具 → Application → LocalStorage) |
|
||||
3. 查看 Network 标签验证响应数据格式是否正确 |
|
||||
|
|
||||
### Q: 如何修改 API 地址? |
|
||||
|
|
||||
**开发环境:** |
|
||||
编辑 `.env.development`: |
|
||||
``` |
|
||||
VITE_API_URL=http://你的后端地址:3000/api |
|
||||
``` |
|
||||
|
|
||||
**生产环境:** |
|
||||
编辑 `.env.production`: |
|
||||
``` |
|
||||
VITE_API_URL=https://你的生产API地址/api |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📚 后续开发 |
|
||||
|
|
||||
### 添加更多 API 接口 |
|
||||
|
|
||||
参考 `src/api/auth.ts`,在 `src/api/` 中创建新文件: |
|
||||
|
|
||||
```typescript |
|
||||
// src/api/users.ts |
|
||||
import http from './index' |
|
||||
|
|
||||
export const getUsersApi = () => { |
|
||||
return http.get('/users') |
|
||||
} |
|
||||
|
|
||||
export const createUserApi = (data) => { |
|
||||
return http.post('/users', data) |
|
||||
} |
|
||||
|
|
||||
export const updateUserApi = (id, data) => { |
|
||||
return http.put(`/users/${id}`, data) |
|
||||
} |
|
||||
|
|
||||
export const deleteUserApi = (id) => { |
|
||||
return http.delete(`/users/${id}`) |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### 在组件中使用 |
|
||||
|
|
||||
```typescript |
|
||||
import { getUsersApi } from '@/api/users' |
|
||||
|
|
||||
const users = ref([]) |
|
||||
const loading = ref(false) |
|
||||
|
|
||||
const fetchUsers = async () => { |
|
||||
loading.value = true |
|
||||
try { |
|
||||
const response = await getUsersApi() |
|
||||
if (response.code === 200) { |
|
||||
users.value = response.data.items |
|
||||
} |
|
||||
} catch (error) { |
|
||||
ElMessage.error('获取失败') |
|
||||
} finally { |
|
||||
loading.value = false |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
onMounted(() => { |
|
||||
fetchUsers() |
|
||||
}) |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🧪 测试步骤 |
|
||||
|
|
||||
### 1. 测试后端接口(使用 curl) |
|
||||
|
|
||||
```bash |
|
||||
# 登录 |
|
||||
curl -X POST http://localhost:3000/api/auth/login \ |
|
||||
-H "Content-Type: application/json" \ |
|
||||
-d '{"username":"admin","password":"123456"}' |
|
||||
|
|
||||
# 应该返回 |
|
||||
# { |
|
||||
# "code": 200, |
|
||||
# "message": "登录成功", |
|
||||
# "data": { |
|
||||
# "token": "...", |
|
||||
# "user": {...} |
|
||||
# } |
|
||||
# } |
|
||||
``` |
|
||||
|
|
||||
### 2. 测试前端集成 |
|
||||
|
|
||||
1. 启动后端:`node server.js` |
|
||||
2. 启动前端:`npm run dev` |
|
||||
3. 打开 http://localhost:5173 |
|
||||
4. 输入用户名和密码 |
|
||||
5. 点击登录 |
|
||||
6. 查看浏览器开发者工具: |
|
||||
- **Network** 标签:查看请求/响应 |
|
||||
- **Application** 标签:查看 localStorage 中的 token |
|
||||
- **Console** 标签:查看任何错误信息 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📋 文件说明 |
|
||||
|
|
||||
| 文件 | 说明 | 何时修改 | |
|
||||
|-----|------|--------| |
|
||||
| `src/api/index.ts` | Axios 配置和拦截器 | 很少 | |
|
||||
| `src/api/auth.ts` | API 接口定义 | 添加新接口时 | |
|
||||
| `src/stores/auth.ts` | 认证状态管理 | 很少 | |
|
||||
| `src/views/LoginView.vue` | 登录页面 | 很少 | |
|
||||
| `.env.development` | 开发环境 API 地址 | 改变后端地址时 | |
|
||||
| `.env.production` | 生产环境 API 地址 | 部署到生产前 | |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎓 学习资源 |
|
||||
|
|
||||
1. **快速参考** - 看 `API_QUICK_REFERENCE.md` |
|
||||
2. **详细指南** - 看 `API_INTEGRATION_GUIDE.md` |
|
||||
3. **后端示例** - 看 `BACKEND_API_EXAMPLE.md` |
|
||||
4. **完整说明** - 看 `API_IMPLEMENTATION_COMPLETE.md` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## ✅ 完成清单 |
|
||||
|
|
||||
### 前端部分(✅ 已完成) |
|
||||
|
|
||||
- [x] Axios 配置 |
|
||||
- [x] 请求拦截器 |
|
||||
- [x] 响应拦截器 |
|
||||
- [x] API 服务层 |
|
||||
- [x] 认证 Store |
|
||||
- [x] 登录页面 |
|
||||
- [x] 环境配置 |
|
||||
- [x] 文档 |
|
||||
- [x] 类型定义 |
|
||||
|
|
||||
### 你需要完成的(⏳ 待实施) |
|
||||
|
|
||||
- [ ] 后端登录接口 |
|
||||
- [ ] 后端 CORS 配置 |
|
||||
- [ ] 后端数据库存储 |
|
||||
- [ ] 其他业务接口 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🚀 快速开始 |
|
||||
|
|
||||
### 最快的方式(使用示例后端) |
|
||||
|
|
||||
```bash |
|
||||
# 终端 1 - 启动后端 |
|
||||
cd admin-backend |
|
||||
node server.js |
|
||||
|
|
||||
# 终端 2 - 启动前端 |
|
||||
npm run dev |
|
||||
|
|
||||
# 打开浏览器访问 http://localhost:5173 |
|
||||
# 输入 admin / 123456 登录 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 💡 核心概念 |
|
||||
|
|
||||
### 请求流程 |
|
||||
``` |
|
||||
前端 → 添加 token → 发送 HTTP 请求 → 后端 ← 验证 token ← 返回数据 |
|
||||
``` |
|
||||
|
|
||||
### 响应格式 |
|
||||
```json |
|
||||
{ |
|
||||
"code": 200, // HTTP 状态码 |
|
||||
"message": "...", // 消息 |
|
||||
"data": {...} // 实际数据 |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
### Token 管理 |
|
||||
``` |
|
||||
登录时保存 → 每个请求自动添加 → 验证失败自动清除 → 跳转登录 |
|
||||
``` |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 📞 如果遇到问题 |
|
||||
|
|
||||
1. 查看浏览器控制台错误信息 |
|
||||
2. 查看后端日志 |
|
||||
3. 使用 curl 测试后端接口 |
|
||||
4. 查看相关文档 |
|
||||
5. 检查文件名和 API 路径是否正确 |
|
||||
|
|
||||
--- |
|
||||
|
|
||||
## 🎉 总结 |
|
||||
|
|
||||
你现在有: |
|
||||
|
|
||||
✅ 完整的前端 API 架构(可直接使用) |
|
||||
✅ 登录示例代码(参考如何集成) |
|
||||
✅ 后端代码示例(参考如何实现) |
|
||||
✅ 详细的文档(学习和参考) |
|
||||
|
|
||||
**只需 3 步即可让系统运行:** |
|
||||
1. 实现后端登录接口 |
|
||||
2. 启动后端和前端 |
|
||||
3. 在登录页测试 |
|
||||
|
|
||||
准备好了吗?让我们开始吧!🚀 |
|
||||
Loading…
Reference in new issue