diff --git a/admin-system/API接口文档.md b/admin-system/API接口文档.md new file mode 100644 index 0000000..ef9ec23 --- /dev/null +++ b/admin-system/API接口文档.md @@ -0,0 +1,372 @@ +# 爱鉴花后台管理系统 API 接口文档 + +## 概述 +本文档描述了爱鉴花后台管理系统的 RESTful API 接口规范,基于 OpenAPI 3.0 标准。 + +## 基础信息 +- **Base URL**: `http://localhost:3200/api/v1` +- **认证方式**: Bearer Token (JWT) +- **响应格式**: JSON + +## 通用响应格式 +```json +{ + "code": 200, + "message": "操作成功", + "data": {} +} +``` + +## 错误码说明 +| 错误码 | 说明 | +|--------|------| +| 200 | 成功 | +| 400 | 请求参数错误 | +| 401 | 未授权访问 | +| 403 | 权限不足 | +| 404 | 资源不存在 | +| 409 | 资源冲突 | +| 500 | 服务器内部错误 | + +## 用户管理接口 + +### 1. 获取用户列表 + +**接口摘要**: 获取用户列表(需要管理员权限) + +**请求方法**: `GET` +**请求路径**: `/users` + +**请求参数**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| page | integer | 否 | 页码,默认1 | +| limit | integer | 否 | 每页数量,默认10 | +| keyword | string | 否 | 搜索关键词(用户名/手机号/邮箱) | +| user_type | string | 否 | 用户类型(farmer/buyer/admin) | + +**请求示例**: +```http +GET /api/v1/users?page=1&limit=10&keyword=test&user_type=farmer +Authorization: Bearer +``` + +**响应示例 (200)**: +```json +{ + "code": 200, + "message": "获取成功", + "data": { + "users": [ + { + "id": 1, + "username": "testuser", + "phone": "13800138000", + "email": "test@example.com", + "user_type": "farmer", + "avatar_url": null, + "created_at": "2023-12-01 10:00:00", + "last_login": "2023-12-15 15:30:00" + } + ], + "pagination": { + "page": 1, + "limit": 10, + "total": 100, + "pages": 10 + } + } +} +``` + +### 2. 创建用户 + +**接口摘要**: 创建新用户(需要管理员权限) + +**请求方法**: `POST` +**请求路径**: `/users` + +**请求体**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| username | string | 是 | 用户名 | +| phone | string | 是 | 手机号 | +| email | string | 是 | 邮箱地址 | +| user_type | string | 是 | 用户类型(farmer/buyer/admin) | +| password | string | 是 | 密码(最少6位) | +| real_name | string | 否 | 真实姓名 | +| avatar_url | string | 否 | 头像URL | + +**请求示例**: +```http +POST /api/v1/users +Authorization: Bearer +Content-Type: application/json + +{ + "username": "newuser", + "phone": "13900139000", + "email": "newuser@example.com", + "user_type": "buyer", + "password": "123456", + "real_name": "张三", + "avatar_url": null +} +``` + +**响应示例 (201)**: +```json +{ + "code": 201, + "message": "用户创建成功", + "data": { + "id": 2, + "username": "newuser", + "phone": "13900139000", + "email": "newuser@example.com", + "user_type": "buyer", + "avatar_url": null, + "real_name": "张三" + } +} +``` + +**错误响应示例 (409)**: +```json +{ + "code": 409, + "message": "用户名已存在", + "data": null +} +``` + +### 3. 获取用户详情 + +**接口摘要**: 获取指定用户的详细信息 + +**请求方法**: `GET` +**请求路径**: `/users/{id}` + +**路径参数**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | integer | 是 | 用户ID | + +**请求示例**: +```http +GET /api/v1/users/1 +Authorization: Bearer +``` + +**响应示例 (200)**: +```json +{ + "code": 200, + "message": "获取成功", + "data": { + "id": 1, + "username": "testuser", + "phone": "13800138000", + "email": "test@example.com", + "user_type": "farmer", + "avatar_url": null, + "real_name": "测试用户", + "created_at": "2023-12-01 10:00:00", + "last_login": "2023-12-15 15:30:00" + } +} +``` + +### 4. 更新用户信息 + +**接口摘要**: 更新用户信息 + +**请求方法**: `PUT` +**请求路径**: `/users/{id}` + +**路径参数**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | integer | 是 | 用户ID | + +**请求体**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| username | string | 否 | 用户名 | +| phone | string | 否 | 手机号 | +| email | string | 否 | 邮箱地址 | +| user_type | string | 否 | 用户类型 | +| real_name | string | 否 | 真实姓名 | +| avatar_url | string | 否 | 头像URL | + +**请求示例**: +```http +PUT /api/v1/users/1 +Authorization: Bearer +Content-Type: application/json + +{ + "username": "updateduser", + "phone": "13800138001", + "email": "updated@example.com", + "user_type": "admin", + "real_name": "更新用户" +} +``` + +**响应示例 (200)**: +```json +{ + "code": 200, + "message": "更新成功", + "data": { + "id": 1, + "username": "updateduser", + "phone": "13800138001", + "email": "updated@example.com", + "user_type": "admin", + "avatar_url": null, + "real_name": "更新用户" + } +} +``` + +### 5. 删除用户 + +**接口摘要**: 删除用户(软删除,需要管理员权限) + +**请求方法**: `DELETE` +**请求路径**: `/users/{id}` + +**路径参数**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | integer | 是 | 用户ID | + +**请求示例**: +```http +DELETE /api/v1/users/1 +Authorization: Bearer +``` + +**响应示例 (200)**: +```json +{ + "code": 200, + "message": "删除成功", + "data": null +} +``` + +### 6. 修改密码 + +**接口摘要**: 修改用户密码 + +**请求方法**: `PUT` +**请求路径**: `/users/{id}/password` + +**路径参数**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| id | integer | 是 | 用户ID | + +**请求体**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| old_password | string | 是 | 原密码 | +| new_password | string | 是 | 新密码(最少6位) | + +**请求示例**: +```http +PUT /api/v1/users/1/password +Authorization: Bearer +Content-Type: application/json + +{ + "old_password": "oldpassword123", + "new_password": "newpassword456" +} +``` + +**响应示例 (200)**: +```json +{ + "code": 200, + "message": "密码修改成功", + "data": null +} +``` + +## 认证接口 + +### 1. 用户登录 + +**接口摘要**: 用户登录获取访问令牌 + +**请求方法**: `POST` +**请求路径**: `/auth/login` + +**请求体**: +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| username | string | 是 | 用户名 | +| password | string | 是 | 密码 | + +**请求示例**: +```http +POST /api/v1/auth/login +Content-Type: application/json + +{ + "username": "admin", + "password": "admin123" +} +``` + +**响应示例 (200)**: +```json +{ + "code": 200, + "message": "登录成功", + "data": { + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": 1, + "username": "admin", + "user_type": "admin" + } + } +} +``` + +### 2. 获取当前用户信息 + +**接口摘要**: 获取当前登录用户信息 + +**请求方法**: `GET` +**请求路径**: `/users/me` + +**请求示例**: +```http +GET /api/v1/users/me +Authorization: Bearer +``` + +**响应示例 (200)**: +```json +{ + "code": 200, + "message": "获取成功", + "data": { + "id": 1, + "username": "admin", + "phone": "13800138000", + "email": "admin@example.com", + "user_type": "admin", + "avatar_url": null, + "real_name": "管理员", + "created_at": "2023-12-01 10:00:00", + "last_login": "2023-12-15 15:30:00" + } +} +``` \ No newline at end of file diff --git a/admin-system/src/utils/api.js b/admin-system/src/utils/api.js index 2cfbdd7..ea1baca 100644 --- a/admin-system/src/utils/api.js +++ b/admin-system/src/utils/api.js @@ -72,6 +72,9 @@ export const userAPI = { // 获取用户详情 getUser: (id) => api.get(`/users/${id}`), + // 创建用户 + createUser: (data) => api.post('/users', data), + // 更新用户信息 updateUser: (id, data) => api.put(`/users/${id}`, data), diff --git a/admin-system/src/views/Settings.vue b/admin-system/src/views/Settings.vue index 2db9c3f..70810a8 100644 --- a/admin-system/src/views/Settings.vue +++ b/admin-system/src/views/Settings.vue @@ -302,6 +302,7 @@ + @@ -333,6 +334,7 @@ + @@ -365,6 +367,7 @@ + @@ -400,6 +403,7 @@ + diff --git a/admin-system/src/views/Users.vue b/admin-system/src/views/Users.vue index 4b7f30f..8f5748b 100644 --- a/admin-system/src/views/Users.vue +++ b/admin-system/src/views/Users.vue @@ -274,14 +274,20 @@ export default { if (editForm.id) { // 更新用户 response = await userAPI.updateUser(editForm.id, { + username: editForm.username, + phone: editForm.phone, email: editForm.email, user_type: editForm.user_type }) } else { - // 创建用户(这里简化处理,实际应该调用注册接口) - ElMessage.warning('演示版本,暂不支持创建用户') - dialogVisible.value = false - return + // 创建用户 + response = await userAPI.createUser({ + username: editForm.username, + phone: editForm.phone, + email: editForm.email, + user_type: editForm.user_type, + password: editForm.password + }) } if (response.code === 200) { diff --git a/admin-system/开发计划.md b/admin-system/开发计划.md index ae1e4a0..1594312 100644 --- a/admin-system/开发计划.md +++ b/admin-system/开发计划.md @@ -1,32 +1,103 @@ # 爱鉴花后台管理系统开发计划 -## 第一阶段:基础框架搭建(1-2周) -- 项目初始化 -- 页面结构设计 -- 基础组件开发 -- 路由配置 +## 📊 当前开发状态 +**已完成功能:** +- ✅ 项目基础框架搭建(Vue3 + Element Plus) +- ✅ 用户登录认证系统 +- ✅ 路由权限控制 +- ✅ 用户管理模块(列表查看、搜索、分页) +- ✅ 基础API接口集成 -## 第二阶段:核心功能开发(3-6周) -- 用户管理模块 -- 商品管理模块 -- 订单管理模块 +**开发中功能:** +- 🔄 用户管理完整功能(编辑、删除、新增) +- 🔄 商品管理模块 +- 🔄 订单管理模块 -## 第三阶段:数据统计功能开发(7-10周) -- 数据统计模块 -- 图表展示 -- 报表导出 +## 🗓️ 详细开发计划 -## 第四阶段:系统设置功能开发(11-12周) -- 系统参数配置 -- 权限管理 -- 日志查看 +### 第一阶段:基础框架搭建(已完成) +**时间:** 第1-2周 +**完成内容:** +- [x] Vue3 + Element Plus 项目初始化 +- [x] 路由系统配置(登录验证、权限控制) +- [x] 统一API请求封装(axios拦截器) +- [x] 环境配置文件设置 +- [x] 基础布局组件开发 -## 第五阶段:测试和优化(13-14周) -- 功能测试 -- 性能优化 -- 用户体验优化 +### 第二阶段:核心功能开发(进行中) +**时间:** 第3-8周 +**用户管理模块(第3-4周):** +- [x] 用户列表展示(表格、搜索、分页) +- [x] 用户信息编辑功能(弹窗表单) +- [x] 用户删除功能(软删除) +- [ ] 用户状态管理(启用/禁用) +- [ ] 用户权限分配界面 +- [ ] 批量操作功能 -## 第六阶段:部署和维护(15-16周) -- 部署上线 -- 系统监控 -- 持续优化 \ No newline at end of file +**商品管理模块(第5-6周):** +- [ ] 商品列表展示(分类、搜索、筛选) +- [ ] 商品添加/编辑功能 +- [ ] 商品上下架管理 +- [ ] 商品库存管理 +- [ ] 商品分类管理 +- [ ] 商品图片上传 + +**订单管理模块(第7-8周):** +- [ ] 订单列表展示(状态筛选) +- [ ] 订单详情查看 +- [ ] 订单状态更新 +- [ ] 订单导出功能 +- [ ] 订单统计面板 + +### 第三阶段:数据统计功能开发 +**时间:** 第9-10周 +**数据可视化模块:** +- [ ] 用户数据统计图表(ECharts集成) +- [ ] 销售数据统计分析 +- [ ] 识别数据统计展示 +- [ ] 实时数据监控面板 +- [ ] 数据报表导出功能 +- [ ] 自定义统计时间段 + +### 第四阶段:系统设置功能开发 +**时间:** 第11-12周 +**系统管理模块:** +- [ ] 系统参数配置界面 +- [ ] 角色权限管理系统 +- [ ] 操作日志查看功能 +- [ ] 数据备份/恢复功能 +- [ ] 系统健康状态监控 + +### 第五阶段:测试和优化 +**时间:** 第13-14周 +**质量保障:** +- [ ] 单元测试覆盖(Jest + Vue Test Utils) +- [ ] 集成测试用例编写 +- [ ] 性能优化(代码分割、懒加载) +- [ ] 用户体验优化(响应式设计) +- [ ] 浏览器兼容性测试 + +### 第六阶段:部署和维护 +**时间:** 第15-16周 +**生产环境:** +- [ ] Docker容器化部署 +- [ ] CI/CD流水线配置 +- [ ] 生产环境监控告警 +- [ ] 日志管理系统集成 +- [ ] 定期维护计划制定 + +## 🎯 技术栈说明 +- **前端框架:** Vue 3.3.4 + Composition API +- **UI组件库:** Element Plus 2.3.12 +- **路由管理:** Vue Router 4.2.4 +- **状态管理:** Vuex 4.0.2 +- **HTTP客户端:** Axios 1.4.0 +- **图表库:** ECharts 6.0.0 +- **构建工具:** Vue CLI 5.0.8 + +## 📋 开发规范 +- 代码遵循ESLint + Prettier规范 +- 组件采用Composition API写法 +- API接口统一错误处理 +- 响应式设计支持移动端 +- 定期代码审查和重构 \ No newline at end of file diff --git a/backend/routes/users.js b/backend/routes/users.js index 71b376f..d78e2aa 100644 --- a/backend/routes/users.js +++ b/backend/routes/users.js @@ -56,6 +56,113 @@ router.get('/', adminRequired, asyncHandler(async (req, res) => { }); })); +/** + * 创建用户(管理员权限) + */ +router.post('/', adminRequired, asyncHandler(async (req, res) => { + const { username, phone, email, user_type, password, real_name, avatar_url } = req.body; + + // 验证必填字段 + if (!username || !phone || !email || !user_type || !password) { + return res.status(400).json({ + code: 400, + message: '用户名、手机号、邮箱、用户类型和密码为必填项', + data: null + }); + } + + // 验证邮箱格式 + if (!validator.isEmail(email)) { + return res.status(400).json({ + code: 400, + message: '邮箱格式不正确', + data: null + }); + } + + // 验证手机号格式 + if (!validator.isMobilePhone(phone, 'zh-CN')) { + return res.status(400).json({ + code: 400, + message: '手机号格式不正确', + data: null + }); + } + + // 验证密码长度 + if (password.length < 6) { + return res.status(400).json({ + code: 400, + message: '密码长度不能少于6位', + data: null + }); + } + + // 检查用户名是否已存在 + const existingUsername = await dbConnector.query( + 'SELECT id FROM users WHERE username = ?', + [username] + ); + + if (existingUsername.length > 0) { + return res.status(409).json({ + code: 409, + message: '用户名已存在', + data: null + }); + } + + // 检查邮箱是否已存在 + const existingEmail = await dbConnector.query( + 'SELECT id FROM users WHERE email = ?', + [email] + ); + + if (existingEmail.length > 0) { + return res.status(409).json({ + code: 409, + message: '邮箱已存在', + data: null + }); + } + + // 检查手机号是否已存在 + const existingPhone = await dbConnector.query( + 'SELECT id FROM users WHERE phone = ?', + [phone] + ); + + if (existingPhone.length > 0) { + return res.status(409).json({ + code: 409, + message: '手机号已存在', + data: null + }); + } + + // 加密密码 + const hashedPassword = await bcrypt.hash(password, 12); + + // 插入用户数据 + const result = await dbConnector.query( + `INSERT INTO users (username, phone, email, user_type, password_hash, real_name, avatar_url) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + [username, phone, email, user_type, hashedPassword, real_name || null, avatar_url || null] + ); + + // 获取新创建的用户信息 + const newUser = await dbConnector.query( + 'SELECT id, username, phone, email, user_type, avatar_url, real_name FROM users WHERE id = ?', + [result.insertId] + ); + + res.status(201).json({ + code: 201, + message: '用户创建成功', + data: newUser[0] + }); +})); + /** * 获取用户详情 */ @@ -89,7 +196,7 @@ router.get('/:id', asyncHandler(async (req, res) => { */ router.put('/:id', asyncHandler(async (req, res) => { const { id } = req.params; - const { email, real_name, avatar_url } = req.body; + const { username, phone, email, user_type, real_name, avatar_url } = req.body; // 检查用户是否存在 const existingUser = await dbConnector.query( @@ -114,6 +221,31 @@ router.put('/:id', asyncHandler(async (req, res) => { }); } + // 验证手机号格式 + if (phone && !validator.isMobilePhone(phone, 'zh-CN')) { + return res.status(400).json({ + code: 400, + message: '手机号格式不正确', + data: null + }); + } + + // 检查用户名是否已被其他用户使用 + if (username) { + const usernameUser = await dbConnector.query( + 'SELECT id FROM users WHERE username = ? AND id != ?', + [username, id] + ); + + if (usernameUser.length > 0) { + return res.status(409).json({ + code: 409, + message: '用户名已被其他用户使用', + data: null + }); + } + } + // 检查邮箱是否已被其他用户使用 if (email) { const emailUser = await dbConnector.query( @@ -134,11 +266,26 @@ router.put('/:id', asyncHandler(async (req, res) => { const updateFields = []; const updateValues = []; + if (username !== undefined) { + updateFields.push('username = ?'); + updateValues.push(username); + } + + if (phone !== undefined) { + updateFields.push('phone = ?'); + updateValues.push(phone); + } + if (email !== undefined) { updateFields.push('email = ?'); updateValues.push(email); } + if (user_type !== undefined) { + updateFields.push('user_type = ?'); + updateValues.push(user_type); + } + if (real_name !== undefined) { updateFields.push('real_name = ?'); updateValues.push(real_name);