docs: 更新项目文档,完善需求和技术细节

This commit is contained in:
ylweng
2025-09-01 02:58:34 +08:00
parent ad20888cd4
commit 40460f78d2
6 changed files with 633 additions and 30 deletions

View File

@@ -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 <token>
```
**响应示例 (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 <token>
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 <token>
```
**响应示例 (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 <token>
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 <token>
```
**响应示例 (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 <token>
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 <token>
```
**响应示例 (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"
}
}
```

View File

@@ -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),

View File

@@ -302,6 +302,7 @@
</el-form-item>
</el-form>
</el-card>
</el-tab-pane>
<!-- 商品设置 -->
<el-tab-pane label="商品设置" name="product">
@@ -333,6 +334,7 @@
</el-form-item>
</el-form>
</el-card>
</el-tab-pane>
<!-- 订单设置 -->
<el-tab-pane label="订单设置" name="order">
@@ -365,6 +367,7 @@
</el-form-item>
</el-form>
</el-card>
</el-tab-pane>
<!-- AI识别设置 -->
<el-tab-pane label="AI识别设置" name="ai">
@@ -400,6 +403,7 @@
</el-form-item>
</el-form>
</el-card>
</el-tab-pane>
<!-- 系统维护 -->
<el-tab-pane label="系统维护" name="maintenance">

View File

@@ -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) {

View File

@@ -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周
- 部署上线
- 系统监控
- 持续优化
**商品管理模块(第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接口统一错误处理
- 响应式设计支持移动端
- 定期代码审查和重构

View File

@@ -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);