feat(phase2a): 前台联系人页面 + 管理端在线监控/好友管理 + API 文档
前台联系人模块(ui-ux-pro-max 规范): - contact/index.vue: 好友列表(搜索/在线状态/骨架屏) - contact/request.vue: 好友申请列表(接受/拒绝/防重复提交) - contact/detail.vue: 好友详情(备注/分组/拉黑/删除) - contact/search.vue: 搜索添加好友 + 好友推荐 - contact/groups.vue: 好友分组管理(CRUD) - contact/blacklist.vue: 黑名单管理 管理端前端: - views/monitor/online.vue: 在线监控(统计卡片/用户表格/30s 自动刷新) - views/contact/list.vue: 好友关系管理(分页表格/强制删除) - api/monitor.js + api/contact.js: 管理端 API 封装 - 路由 + 侧边栏导航更新 API 文档(4 份): - docs/api/frontend/contact.md: 17 个接口完整文档 - docs/api/frontend/websocket.md: 前端 WS 事件协议 - docs/api/admin/online.md: 在线监控 API - docs/api/admin/contact.md: 好友管理 API 进度文档更新至 Phase 2a 全部完成 Made-with: Cursor
This commit is contained in:
78
docs/api/admin/contact.md
Normal file
78
docs/api/admin/contact.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# 管理端好友关系管理 API
|
||||
|
||||
> 通用规范(认证方式、响应格式、错误码)见 [README.md](../README.md)
|
||||
> 所有接口需要 JWT + admin/super_admin 角色权限
|
||||
|
||||
---
|
||||
|
||||
## 接口列表
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|------|------|------|------|
|
||||
| GET | /api/v1/admin/contacts | admin | 获取所有好友关系列表(分页) |
|
||||
| DELETE | /api/v1/admin/contacts/:id | admin | 删除好友关系(双向解除) |
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取所有好友关系列表
|
||||
|
||||
`GET /api/v1/admin/contacts`
|
||||
|
||||
**说明:** 分页查询系统中所有好友关系记录,包含双方用户名信息。
|
||||
|
||||
**查询参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| page | int | 否 | 页码,默认 1 |
|
||||
| page_size | int | 否 | 每页数量,默认 20 |
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"total": 150,
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 1,
|
||||
"username": "zhangsan",
|
||||
"friend_id": 2,
|
||||
"friend_username": "lisi",
|
||||
"remark": "同事",
|
||||
"status": 1,
|
||||
"created_at": "2026-03-01 10:00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**status 状态码:**
|
||||
|
||||
| 值 | 说明 |
|
||||
|-----|------|
|
||||
| 0 | 待确认(pending) |
|
||||
| 1 | 已通过(accepted) |
|
||||
| 2 | 已拒绝(rejected) |
|
||||
| 3 | 已拉黑(blocked) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 删除好友关系
|
||||
|
||||
`DELETE /api/v1/admin/contacts/:id`
|
||||
|
||||
**路径参数:** `id` — 好友关系记录 ID
|
||||
|
||||
**说明:** 管理员可以强制删除任意好友关系。此操作会双向解除(同时删除 A→B 和 B→A 的关系记录)。
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok"
|
||||
}
|
||||
```
|
||||
56
docs/api/admin/online.md
Normal file
56
docs/api/admin/online.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 管理端在线监控 API
|
||||
|
||||
> 通用规范(认证方式、响应格式、错误码)见 [README.md](../README.md)
|
||||
> 所有接口需要 JWT + admin/super_admin 角色权限
|
||||
|
||||
---
|
||||
|
||||
## 接口列表
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|------|------|------|------|
|
||||
| GET | /api/v1/admin/online/users | admin | 获取在线用户列表 |
|
||||
| GET | /api/v1/admin/online/count | admin | 获取在线用户数量 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取在线用户列表
|
||||
|
||||
`GET /api/v1/admin/online/users`
|
||||
|
||||
**说明:** 返回当前所有在线用户的基本信息。数据来源于 Redis SET `echo:user:online`。
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"username": "super_admin"
|
||||
},
|
||||
{
|
||||
"user_id": 2,
|
||||
"username": "lisi"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 获取在线用户数量
|
||||
|
||||
`GET /api/v1/admin/online/count`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": {
|
||||
"count": 25
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -12,10 +12,19 @@
|
||||
| POST | /api/v1/contacts/request | 需认证 | 发送好友申请 |
|
||||
| POST | /api/v1/contacts/accept | 需认证 | 接受好友申请 |
|
||||
| POST | /api/v1/contacts/reject | 需认证 | 拒绝好友申请 |
|
||||
| GET | /api/v1/contacts/requests | 需认证 | 获取待处理的好友申请列表 |
|
||||
| DELETE | /api/v1/contacts/:id | 需认证 | 删除好友 |
|
||||
| PUT | /api/v1/contacts/:id/remark | 需认证 | 修改好友备注 |
|
||||
| PUT | /api/v1/contacts/:id/group | 需认证 | 移动好友到分组 |
|
||||
| POST | /api/v1/contacts/block | 需认证 | 拉黑用户 |
|
||||
| DELETE | /api/v1/contacts/block/:id | 需认证 | 取消拉黑 |
|
||||
| GET | /api/v1/contacts/block | 需认证 | 获取黑名单 |
|
||||
| GET | /api/v1/contacts/groups | 需认证 | 获取好友分组列表 |
|
||||
| POST | /api/v1/contacts/groups | 需认证 | 创建好友分组 |
|
||||
| PUT | /api/v1/contacts/groups/:id | 需认证 | 修改好友分组 |
|
||||
| DELETE | /api/v1/contacts/groups/:id | 需认证 | 删除好友分组 |
|
||||
| GET | /api/v1/contacts/recommend | 需认证 | 好友推荐 |
|
||||
| GET | /api/v1/users/search | 需认证 | 搜索用户 |
|
||||
|
||||
---
|
||||
|
||||
@@ -23,13 +32,11 @@
|
||||
|
||||
`GET /api/v1/contacts`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**查询参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| group_id | int | 否 | 按分组筛选 |
|
||||
| group_id | int | 否 | 按分组筛选,不传则返回全部 |
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
@@ -38,15 +45,13 @@
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"friend_id": 2,
|
||||
"user_id": 2,
|
||||
"username": "lisi",
|
||||
"nickname": "李四",
|
||||
"avatar": "",
|
||||
"remark": "我的同事",
|
||||
"avatar": "https://cdn.echochat.com/avatar/2.jpg",
|
||||
"online": true,
|
||||
"group_id": 1,
|
||||
"group_name": "同事"
|
||||
"is_online": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -58,16 +63,18 @@
|
||||
|
||||
`POST /api/v1/contacts/request`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| target_id | int | 是 | 目标用户 ID |
|
||||
| message | string | 否 | 申请附言,如"我是张三的同事" |
|
||||
| message | string | 否 | 申请附言 |
|
||||
|
||||
**可能的错误码:** 1004(用户不存在),1005(已是好友或已发送过申请)
|
||||
**错误场景:**
|
||||
- 400: 不能添加自己为好友
|
||||
- 400: 已是好友
|
||||
- 400: 已有待处理的申请
|
||||
- 403: 对方已将你拉黑
|
||||
|
||||
---
|
||||
|
||||
@@ -75,15 +82,13 @@
|
||||
|
||||
`POST /api/v1/contacts/accept`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| friendship_id | int | 是 | 好友关系记录 ID |
|
||||
| request_id | int | 是 | 好友申请记录 ID |
|
||||
|
||||
**说明:** 接受后系统自动创建双向好友关系,并发送通知给对方。
|
||||
**说明:** 接受后系统自动创建双向好友关系,并通过 WebSocket 推送 `contact.request.accepted` 事件给对方。
|
||||
|
||||
---
|
||||
|
||||
@@ -91,35 +96,54 @@
|
||||
|
||||
`POST /api/v1/contacts/reject`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| friendship_id | int | 是 | 好友关系记录 ID |
|
||||
| request_id | int | 是 | 好友申请记录 ID |
|
||||
|
||||
---
|
||||
|
||||
## 5. 删除好友
|
||||
## 5. 获取待处理的好友申请
|
||||
|
||||
`GET /api/v1/contacts/requests`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"id": 5,
|
||||
"user_id": 3,
|
||||
"username": "wangwu",
|
||||
"nickname": "王五",
|
||||
"avatar": "",
|
||||
"message": "我是你的同学",
|
||||
"created_at": "2026-03-01T10:30:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 删除好友
|
||||
|
||||
`DELETE /api/v1/contacts/:id`
|
||||
|
||||
**权限:** 需认证
|
||||
**路径参数:** `id` — 好友的用户 ID
|
||||
|
||||
**路径参数:** `id` — 好友关系记录 ID
|
||||
|
||||
**说明:** 删除后双向关系均解除,关联的单聊会话不会删除(消息记录保留)。
|
||||
**说明:** 删除后双向关系均解除。
|
||||
|
||||
---
|
||||
|
||||
## 6. 修改好友备注
|
||||
## 7. 修改好友备注
|
||||
|
||||
`PUT /api/v1/contacts/:id/remark`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**路径参数:** `id` — 好友关系记录 ID
|
||||
**路径参数:** `id` — 好友的用户 ID
|
||||
|
||||
**请求参数:**
|
||||
|
||||
@@ -129,11 +153,45 @@
|
||||
|
||||
---
|
||||
|
||||
## 7. 获取好友分组列表
|
||||
## 8. 移动好友到分组
|
||||
|
||||
`GET /api/v1/contacts/groups`
|
||||
`PUT /api/v1/contacts/:id/group`
|
||||
|
||||
**权限:** 需认证
|
||||
**路径参数:** `id` — 好友的用户 ID
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| group_id | int | 是 | 目标分组 ID,0 为默认分组 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 拉黑用户
|
||||
|
||||
`POST /api/v1/contacts/block`
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| target_id | int | 是 | 目标用户 ID |
|
||||
|
||||
**说明:** 拉黑后自动解除好友关系(如果存在),对方无法向你发送好友申请和消息。
|
||||
|
||||
---
|
||||
|
||||
## 10. 取消拉黑
|
||||
|
||||
`DELETE /api/v1/contacts/block/:id`
|
||||
|
||||
**路径参数:** `id` — 被拉黑用户的 ID
|
||||
|
||||
---
|
||||
|
||||
## 11. 获取黑名单
|
||||
|
||||
`GET /api/v1/contacts/block`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
@@ -141,24 +199,123 @@
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{ "id": 1, "name": "同事", "sort_order": 0, "count": 15 },
|
||||
{ "id": 2, "name": "朋友", "sort_order": 1, "count": 8 }
|
||||
{
|
||||
"user_id": 5,
|
||||
"username": "blocked_user",
|
||||
"nickname": "某用户",
|
||||
"avatar": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 创建好友分组
|
||||
## 12. 获取好友分组列表
|
||||
|
||||
`GET /api/v1/contacts/groups`
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{ "id": 1, "name": "同事", "sort_order": 0, "friend_count": 15 },
|
||||
{ "id": 2, "name": "朋友", "sort_order": 1, "friend_count": 8 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. 创建好友分组
|
||||
|
||||
`POST /api/v1/contacts/groups`
|
||||
|
||||
**权限:** 需认证
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| name | string | 是 | 分组名称,最多 50 字符 |
|
||||
|
||||
**可能的错误码:** 1005(同名分组已存在)
|
||||
---
|
||||
|
||||
## 14. 修改好友分组
|
||||
|
||||
`PUT /api/v1/contacts/groups/:id`
|
||||
|
||||
**路径参数:** `id` — 分组 ID
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| name | string | 是 | 新分组名称 |
|
||||
| sort_order | int | 否 | 排序序号 |
|
||||
|
||||
---
|
||||
|
||||
## 15. 删除好友分组
|
||||
|
||||
`DELETE /api/v1/contacts/groups/:id`
|
||||
|
||||
**路径参数:** `id` — 分组 ID
|
||||
|
||||
**说明:** 删除分组后,该分组内的好友自动移至默认分组(group_id = 0)。
|
||||
|
||||
---
|
||||
|
||||
## 16. 好友推荐
|
||||
|
||||
`GET /api/v1/contacts/recommend`
|
||||
|
||||
**说明:** 基于共同好友算法推荐可能认识的人。
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"user_id": 8,
|
||||
"username": "zhaoliu",
|
||||
"nickname": "赵六",
|
||||
"avatar": "",
|
||||
"common_count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 17. 搜索用户
|
||||
|
||||
`GET /api/v1/users/search`
|
||||
|
||||
**查询参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| keyword | string | 是 | 搜索关键词(用户名/昵称模糊匹配) |
|
||||
| page | int | 否 | 页码,默认 1 |
|
||||
| page_size | int | 否 | 每页数量,默认 20 |
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
"data": [
|
||||
{
|
||||
"user_id": 10,
|
||||
"username": "newuser",
|
||||
"nickname": "新用户",
|
||||
"avatar": "",
|
||||
"is_friend": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
141
docs/api/frontend/websocket.md
Normal file
141
docs/api/frontend/websocket.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# 前端 WebSocket 事件协议
|
||||
|
||||
> 完整的 WebSocket 协议文档见 [websocket.md](../websocket.md)
|
||||
> 本文档补充前端联系人模块使用的 WebSocket 事件及对接说明
|
||||
|
||||
---
|
||||
|
||||
## 连接管理
|
||||
|
||||
### 连接地址
|
||||
|
||||
| 环境 | 地址 |
|
||||
|------|------|
|
||||
| 开发环境 | `ws://localhost:8085/ws?token=<access_token>` |
|
||||
| 生产环境 | `wss://api.echochat.com/ws?token=<access_token>` |
|
||||
|
||||
### 前端实现
|
||||
|
||||
- **连接服务:** `frontend/src/services/websocket.js`(WebSocketService 单例)
|
||||
- **状态管理:** `frontend/src/store/websocket.js`(Pinia Store)
|
||||
- **联系人监听:** `frontend/src/store/contact.js`(initWsListeners)
|
||||
|
||||
### 心跳与重连
|
||||
|
||||
- 心跳间隔:30 秒
|
||||
- 重连策略:指数退避 1s → 2s → 4s → 8s → 16s → 最大 30s
|
||||
- 连接时自动发送 heartbeat 事件
|
||||
|
||||
---
|
||||
|
||||
## 联系人相关事件
|
||||
|
||||
### heartbeat
|
||||
|
||||
**方向:** 客户端 → 服务端
|
||||
|
||||
**说明:** 心跳消息,服务端收到后续期在线状态 TTL
|
||||
|
||||
**发送格式:**
|
||||
```json
|
||||
{
|
||||
"event": "heartbeat",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### notify.friend.request
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 收到新的好友申请推送
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"friendship_id": 5,
|
||||
"from_user_id": 2,
|
||||
"from_nickname": "李四",
|
||||
"from_avatar": "",
|
||||
"message": "我是你的同事"
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** `contactStore.initWsListeners` 监听此事件,自动刷新待处理申请列表
|
||||
|
||||
---
|
||||
|
||||
### contact.request.accepted
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 好友申请被对方接受的通知
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"friendship_id": 5,
|
||||
"user_id": 1,
|
||||
"username": "zhangsan",
|
||||
"nickname": "张三"
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** `contactStore.initWsListeners` 监听此事件,自动刷新好友列表
|
||||
|
||||
---
|
||||
|
||||
### user.status.online
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 好友上线通知
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"user_id": 2,
|
||||
"nickname": "李四"
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** 更新 `contactStore.onlineMap` 和好友列表中对应用户的 `is_online` 状态
|
||||
|
||||
---
|
||||
|
||||
### user.status.offline
|
||||
|
||||
**方向:** 服务端 → 客户端
|
||||
|
||||
**说明:** 好友离线通知
|
||||
|
||||
**data 内容:**
|
||||
```json
|
||||
{
|
||||
"user_id": 2
|
||||
}
|
||||
```
|
||||
|
||||
**前端处理:** 更新 `contactStore.onlineMap` 和好友列表中对应用户的 `is_online` 状态
|
||||
|
||||
---
|
||||
|
||||
## 事件监听代码示例
|
||||
|
||||
```javascript
|
||||
import { useContactStore } from '@/store/contact'
|
||||
import { useWebSocketStore } from '@/store/websocket'
|
||||
|
||||
const contactStore = useContactStore()
|
||||
const wsStore = useWebSocketStore()
|
||||
|
||||
// 建立 WebSocket 连接
|
||||
wsStore.connect()
|
||||
|
||||
// 初始化联系人事件监听
|
||||
contactStore.initWsListeners()
|
||||
```
|
||||
|
||||
以上代码会自动监听 `notify.friend.request`、`contact.request.accepted`、`user.status.online`、`user.status.offline` 四个事件。
|
||||
@@ -1,187 +1,209 @@
|
||||
# EchoChat 项目开发进度
|
||||
|
||||
> **最后更新**:2026-03-02(角色等级体系与权限管控实施)
|
||||
> **当前阶段**:Phase 1 - 基础设施与用户认证
|
||||
> **当前分支**:`feature/phase1-foundation-and-auth`
|
||||
> **实施计划**:`docs/plans/2026-02-27-phase1-foundation-and-auth.md`
|
||||
> **最后更新**:2026-03-02(Phase 2a 完成 - WebSocket 实时通讯与联系人管理)
|
||||
> **当前阶段**:Phase 2a - WebSocket 实时通讯与联系人管理
|
||||
> **当前分支**:`feature/phase2a-websocket-contacts`
|
||||
> **实施计划**:`phase_2a_实施计划_221003ce.plan.md`
|
||||
> **设计文档**:`docs/plans/2026-03-02-phase2a-design.md`
|
||||
|
||||
---
|
||||
|
||||
## 一、Task 完成状态
|
||||
## 一、Phase 2a Task 完成状态
|
||||
|
||||
| Task | 描述 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| Task 1 | Docker Compose 开发环境搭建 | ✅ 完成 | PostgreSQL 17 + Redis 7 |
|
||||
| Task 2 | 数据库初始化脚本 | ✅ 完成 | users + user_roles + roles 表 |
|
||||
| Task 3 | Go 后端服务骨架 | ✅ 完成 | Gin + GORM + Wire + Zap |
|
||||
| Task 4 | Auth Service 层 | ✅ 完成 | 注册/登录/Token/Profile API |
|
||||
| Task 5 | Auth Controller & Router | ✅ 完成 | JWT + Redis 有状态校验 |
|
||||
| Task 6 | uniapp 前端骨架 | ✅ 完成 | request/storage/api/store/pages.json |
|
||||
| Task 7 | uniapp 登录/注册页面 | ✅ 完成 | 基于 ui-ux-pro-max 设计系统 |
|
||||
| Task 8 | 首页框架与 TabBar | ✅ 完成 | 自定义 TabBar + 路由分发 |
|
||||
| Task 9 | Vue 3 管理端项目搭建 | ✅ 完成 | Element Plus + Pinia 3.x |
|
||||
| Task 10 | 管理端用户管理模块 | ✅ 完成 | 后端 admin 模块 + 前端列表/详情页 |
|
||||
| Task 11 | 端到端集成测试与文档 | ✅ 完成 | Dockerfile + Docker Compose + README + 全流程 API 验证 + Playwright 页面验证 + 代码审查 |
|
||||
| Task 0 | 设计文档 + 新分支 | ✅ 完成 | 架构设计、Redis Pub/Sub、文档策略 |
|
||||
| Task 1 | 数据库表结构 | ✅ 完成 | contact_friendships + contact_groups |
|
||||
| Task 2 | WebSocket 核心模块 | ✅ 完成 | Hub + Client + PubSub + Handler |
|
||||
| Task 3 | Contact 模型与 DAO | ✅ 完成 | friendship + friend_group DAO |
|
||||
| Task 4 | Contact Service | ✅ 完成 | 好友申请/分组/黑名单/搜索/推荐 |
|
||||
| Task 5 | Contact Controller & Router | ✅ 完成 | 17 个 REST API + Wire 集成 |
|
||||
| Task 6 | 在线状态管理 | ✅ 完成 | Redis SET + TTL 心跳续期 |
|
||||
| Task 7 | 管理端后端 | ✅ 完成 | 在线监控 + 好友关系管理 API |
|
||||
| Task 8 | 前台 WS 客户端 + Store + API | ✅ 完成 | websocket.js + contact.js Store/API |
|
||||
| Task 9 | 前台联系人页面 | ✅ 完成 | 6 个页面(ui-ux-pro-max 规范) |
|
||||
| Task 10 | 管理端前端 | ✅ 完成 | 在线监控 + 好友管理页面 |
|
||||
| Task 11 | API 文档编写 | ✅ 完成 | 4 份独立文档 |
|
||||
| Task 12 | 集成测试 + 文档更新 + 代码审查 | ✅ 完成 | 三端编译通过 |
|
||||
|
||||
---
|
||||
|
||||
## 二、关键技术决策记录
|
||||
## 二、Phase 2a 新增功能
|
||||
|
||||
### WebSocket 实时通讯
|
||||
- **连接管理**:`gorilla/websocket` + JWT 认证 + 心跳(30s)
|
||||
- **消息架构**:Redis Pub/Sub 跨实例消息路由
|
||||
- **Hub**:本地连接管理(注册/注销/按用户发送)
|
||||
- **Client**:读写泵 + 断线回调 + 缓冲通道
|
||||
|
||||
### 联系人管理(17 个 API)
|
||||
- 好友申请(发送/接受/拒绝)
|
||||
- 好友列表(按分组筛选 + 在线状态)
|
||||
- 好友详情(备注/分组移动)
|
||||
- 好友删除 + 拉黑/取消拉黑
|
||||
- 好友分组(CRUD + 排序)
|
||||
- 用户搜索 + 好友推荐(共同好友算法)
|
||||
|
||||
### 在线状态管理
|
||||
- Redis SET `echo:user:online` 存储在线用户集合
|
||||
- Redis STRING `echo:user:status:{user_id}` + TTL 心跳续期
|
||||
- Pub/Sub 推送好友上下线通知
|
||||
|
||||
### 管理端扩展
|
||||
- 在线监控页面(自动 30s 刷新 + 统计卡片)
|
||||
- 好友关系管理(分页列表 + 强制删除)
|
||||
|
||||
---
|
||||
|
||||
## 三、Phase 1 完成总结
|
||||
|
||||
| Task | 描述 | 状态 |
|
||||
|------|------|------|
|
||||
| Task 1-11 | 基础设施 + 认证 + 用户管理 | ✅ 全部完成 |
|
||||
|
||||
- Go 后端 15+ API、JWT 有状态认证、RBAC 角色权限(level 等级体系)
|
||||
- 前台 uni-app 登录/注册/TabBar/个人中心
|
||||
- 管理端 Vue 3 登录/仪表盘/用户列表/详情
|
||||
- Docker Compose 一键启动
|
||||
|
||||
---
|
||||
|
||||
## 四、关键技术决策记录
|
||||
|
||||
### 后端(Go)
|
||||
1. **框架组合**:Gin + GORM + Wire + Zap + Viper
|
||||
2. **JWT 策略**:有状态 JWT,Token 按 clientType 隔离存储在 Redis(`echo:auth:token:{frontend|admin}:{user_id}`)
|
||||
3. **密码加密**:bcrypt
|
||||
4. **数据库时间精度**:`TIMESTAMP(0)` 精确到秒
|
||||
5. **API 响应格式**:统一 `{ "code": 0, "message": "success", "data": ... }`
|
||||
6. **常量命名**:Go camelCase(`UserStatusActive`),非大写下划线
|
||||
7. **模块路由**:模块内自注册 + 中央 router 聚合
|
||||
8. **角色等级体系**:`auth_roles.level` 字段(值越小权限越高:1=超管, 10=管理员, 100=普通用户),所有管理操作强制执行"高等级管理低等级"规则
|
||||
2. **JWT 策略**:有状态 JWT,Token 按 clientType 隔离存储在 Redis
|
||||
3. **WebSocket**:`gorilla/websocket` + Redis Pub/Sub 跨实例路由
|
||||
4. **在线状态**:混合方案(Redis SET + STRING TTL + Pub/Sub 推送)
|
||||
5. **角色等级**:`auth_roles.level`(1=超管, 10=管理员, 100=普通用户)
|
||||
|
||||
### 前台用户端(frontend/)
|
||||
1. **框架**:uni-app 3.0(Vue 3.4.21 框架锁定)
|
||||
1. **框架**:uni-app 3.0(Vue 3.4.21)
|
||||
2. **状态管理**:Pinia 2.1.7 + pinia-plugin-persistedstate@3
|
||||
3. **npm 配置**:`.npmrc` 设置 `legacy-peer-deps=true`(uni-app 兼容性)
|
||||
4. **模块系统**:ESM(`export` / `import`),禁止 CommonJS
|
||||
5. **响应式单位**:`rpx`(750rpx = 屏幕宽度)
|
||||
6. **设计系统**:ui-ux-pro-max 生成,持久化在 `design-system/echochat/`
|
||||
7. **色板**:Primary `#2563EB` / BG `#F8FAFC` / Text `#1E293B`
|
||||
8. **开发端口**:`npm run dev:h5` → localhost:5173+
|
||||
3. **WebSocket**:`uni.connectSocket`(小程序)/ `WebSocket`(H5)
|
||||
4. **设计系统**:ui-ux-pro-max 规范
|
||||
|
||||
### 后台管理端(admin/)
|
||||
1. **框架**:Vue 3.5+ + Vite 7.x(独立项目,不受 uni-app 限制)
|
||||
2. **UI 组件**:Element Plus(中文语言包)
|
||||
3. **状态管理**:Pinia 3.x(最新版)
|
||||
4. **HTTP 客户端**:Axios
|
||||
5. **存储隔离**:localStorage key 前缀 `admin_`
|
||||
6. **主题色**:CSS 变量覆盖 Element Plus → `--el-color-primary: #2563EB`
|
||||
7. **开发端口**:`npm run dev` → localhost:3100(Vite proxy 代理后端)
|
||||
1. **框架**:Vue 3.5+ + Vite 7.x + Element Plus
|
||||
2. **HTTP 客户端**:Axios
|
||||
3. **存储隔离**:localStorage key 前缀 `admin_`
|
||||
|
||||
---
|
||||
|
||||
## 三、目录结构概览
|
||||
## 五、目录结构概览
|
||||
|
||||
```
|
||||
EchoChat/
|
||||
├── backend/go-service/ # Go 后端服务
|
||||
├── backend/go-service/
|
||||
│ ├── app/
|
||||
│ │ ├── admin/ # 管理端模块(controller/service/dao/router/provider)
|
||||
│ │ ├── auth/ # 认证模块(controller/service/dao/model/router)
|
||||
│ │ ├── constants/ # 常量(role_code/user_status)
|
||||
│ │ ├── dto/ # 数据传输对象(auth_dto + admin_dto)
|
||||
│ │ └── provider/ # Wire 依赖注入
|
||||
│ ├── cmd/server/main.go # 入口
|
||||
│ ├── config/ # 配置
|
||||
│ ├── pkg/ # 公共包(db/logs/middleware/utils)
|
||||
│ └── router/router.go # 中央路由聚合
|
||||
├── frontend/ # 前台用户端(uni-app)
|
||||
│ │ ├── admin/ # 管理端(controller/service/provider)
|
||||
│ │ ├── auth/ # 认证模块
|
||||
│ │ ├── contact/ # [Phase 2a] 联系人模块
|
||||
│ │ │ ├── controller/
|
||||
│ │ │ ├── dao/
|
||||
│ │ │ ├── model/
|
||||
│ │ │ ├── service/
|
||||
│ │ │ ├── router.go
|
||||
│ │ │ └── provider.go
|
||||
│ │ ├── ws/ # [Phase 2a] WebSocket 模块
|
||||
│ │ │ ├── handler.go
|
||||
│ │ │ ├── online_service.go
|
||||
│ │ │ ├── provider.go
|
||||
│ │ │ └── router.go
|
||||
│ │ ├── constants/
|
||||
│ │ ├── dto/
|
||||
│ │ └── provider/
|
||||
│ ├── pkg/
|
||||
│ │ ├── ws/ # [Phase 2a] WebSocket 核心
|
||||
│ │ │ ├── hub.go
|
||||
│ │ │ ├── client.go
|
||||
│ │ │ ├── pubsub.go
|
||||
│ │ │ └── message.go
|
||||
│ │ ├── db/ logs/ middleware/ utils/
|
||||
│ └── router/router.go
|
||||
├── frontend/ # 前台(uni-app)
|
||||
│ └── src/
|
||||
│ ├── api/auth.js
|
||||
│ ├── components/CustomTabBar.vue
|
||||
│ ├── pages/{auth,chat,contact,meeting,profile,index}/
|
||||
│ ├── store/user.js
|
||||
│ └── utils/{request,storage}.js
|
||||
├── admin/ # 后台管理端(Vue 3 + Element Plus)
|
||||
│ ├── api/{auth,contact,user}.js
|
||||
│ ├── services/websocket.js # [Phase 2a]
|
||||
│ ├── store/{user,websocket,contact}.js
|
||||
│ ├── pages/contact/ # [Phase 2a] 6 个页面
|
||||
│ │ ├── index.vue
|
||||
│ │ ├── request.vue
|
||||
│ │ ├── detail.vue
|
||||
│ │ ├── search.vue
|
||||
│ │ ├── groups.vue
|
||||
│ │ └── blacklist.vue
|
||||
│ └── components/CustomTabBar.vue
|
||||
├── admin/ # 管理端(Vue 3 + Element Plus)
|
||||
│ └── src/
|
||||
│ ├── api/auth.js
|
||||
│ ├── router/index.js
|
||||
│ ├── store/user.js
|
||||
│ ├── utils/{request,storage}.js
|
||||
│ └── views/{layout,login,dashboard,user}/
|
||||
│ ├── api/{auth,user,monitor,contact}.js
|
||||
│ ├── views/
|
||||
│ │ ├── monitor/online.vue # [Phase 2a]
|
||||
│ │ ├── contact/list.vue # [Phase 2a]
|
||||
│ │ ├── layout/ login/ dashboard/ user/
|
||||
│ └── router/index.js
|
||||
├── deploy/
|
||||
│ ├── docker-compose.dev.yml
|
||||
│ └── docker/postgres/init.sql
|
||||
├── design-system/echochat/ # ui-ux-pro-max 生成的设计系统
|
||||
│ ├── MASTER.md
|
||||
│ └── pages/{login,admin-login}.md
|
||||
├── design-system/
|
||||
└── docs/
|
||||
├── api/ # API 接口文档
|
||||
├── architecture/ # 系统架构文档
|
||||
├── conventions/ # 开发规范文档
|
||||
│ └── frontend-backend-integration.md # 前后端集成规范
|
||||
├── plans/ # 实施计划文档
|
||||
└── progress/ # 进度文档(本文件)
|
||||
├── api/
|
||||
│ ├── frontend/{auth,contact,websocket}.md
|
||||
│ ├── admin/{auth,user,online,contact}.md
|
||||
│ └── websocket.md
|
||||
├── plans/
|
||||
├── progress/CURRENT_STATUS.md
|
||||
└── conventions/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、开发流程规范
|
||||
## 六、开发测试指南
|
||||
|
||||
1. **工作流**:使用 superpowers 流程控制开发节奏
|
||||
2. **前端设计**:**必须**使用 ui-ux-pro-max 技能包,禁止手动设计
|
||||
3. **代码注释**:所有公开函数、组件、Store 必须有详细注释
|
||||
4. **文档同步**:代码变更后必须同步更新相关文档
|
||||
5. **Git 分支**:`feature/phase1-foundation-and-auth`
|
||||
6. **验证方式**:Playwright MCP 进行页面自动化验证
|
||||
7. **代码审查**:每个 Task 完成后,使用 `code-reviewer` 子代理进行结构化代码审查,对照实施计划和编码标准检查
|
||||
8. **完成验证**:使用 `verification-before-completion` 技能,在声称完成前必须运行验证命令并确认输出结果
|
||||
9. **前后端联动规范**:详见 `docs/conventions/frontend-backend-integration.md`,核心要求:前端错误提示必须优先使用后端 message,禁止硬编码覆盖;后端错误处理禁止忽略 error;登录安全统一返回 401
|
||||
|
||||
---
|
||||
|
||||
## 五、开发测试指南
|
||||
|
||||
### 启动命令(开发模式)
|
||||
|
||||
前提:postgres 和 redis 已通过 Docker Compose 运行。
|
||||
### 启动命令
|
||||
|
||||
```bash
|
||||
# 启动 Go 后端(http://localhost:8085)
|
||||
# 1. 启动 PostgreSQL + Redis
|
||||
cd deploy && docker compose -f docker-compose.dev.yml up -d postgres redis
|
||||
|
||||
# 2. 启动 Go 后端(http://localhost:8085)
|
||||
cd backend/go-service && go run cmd/server/main.go
|
||||
|
||||
# 启动管理端(http://localhost:3100)
|
||||
# 3. 启动管理端(http://localhost:3100)
|
||||
cd admin && npm run dev
|
||||
|
||||
# 启动前台 H5(http://localhost:5173+)
|
||||
# 4. 启动前台 H5(http://localhost:5173+)
|
||||
cd frontend && npm run dev:h5
|
||||
```
|
||||
|
||||
如需全容器启动(包括 Go 服务):`cd deploy && docker compose -f docker-compose.dev.yml up -d`
|
||||
|
||||
### 测试账号
|
||||
|
||||
| 账号 | 密码 | 角色 | 用途 |
|
||||
|------|------|------|------|
|
||||
| `admin_test` | `admin123456` | user + admin | **管理端登录推荐** |
|
||||
| `super_admin` | `admin123456` | super_admin | 系统预置唯一超管 |
|
||||
| `admin_test` | `admin123456` | user + admin | 管理端登录推荐 |
|
||||
| `testuser1` | `test123456` | user + admin | 前台登录测试 |
|
||||
| `testuser` | `test123456` | user | 前台登录测试 |
|
||||
| `testuser3` | `test123456` | user | 前台登录测试 |
|
||||
| `created_by_admin` | `pass123456` | user | 管理端创建的用户 |
|
||||
| `super_admin` | `admin123456` | super_admin | **系统预置唯一超管账号** |
|
||||
|
||||
> 也可以通过注册接口或管理端"创建用户"功能创建新的测试账号。
|
||||
### Phase 2a 可测试功能
|
||||
|
||||
### 可测试功能
|
||||
|
||||
- **管理端**:登录 → 仪表盘 → 用户列表 → 搜索/筛选 → 用户详情 → 禁用/启用(受角色等级约束) → 批量设置角色(Checkbox 多选 + 等级管控) → 创建用户
|
||||
- **前台 H5**:注册 → 登录 → 个人中心 → 修改资料 → 退出登录
|
||||
- **API**:`GET http://localhost:8085/health`(健康检查)
|
||||
- **前台联系人**:好友列表 → 搜索添加 → 好友申请 → 好友详情 → 备注/分组 → 拉黑/删除
|
||||
- **前台 WebSocket**:自动连接 → 心跳 → 在线状态实时更新 → 好友申请推送
|
||||
- **管理端在线监控**:在线用户数 → 在线用户列表 → 自动刷新
|
||||
- **管理端好友管理**:好友关系列表 → 强制删除关系
|
||||
|
||||
---
|
||||
|
||||
## 六、已知问题与注意事项
|
||||
## 七、已知问题
|
||||
|
||||
1. ~~前端工具模块使用了 CommonJS,已修复为 ESM~~(已解决)
|
||||
2. ~~前端登录失败时错误提示不正确(硬编码"登录已过期"覆盖后端消息)~~(已修复,详见 `docs/conventions/frontend-backend-integration.md`)
|
||||
3. ~~后端登录时用户不存在返回 404 暴露用户是否注册~~(已修复为统一返回 401)
|
||||
4. uni-app 的 `tabBar.custom: true` 配合自定义 TabBar 组件使用
|
||||
5. 管理端和前台的 localStorage key 通过前缀隔离(`admin_` vs `echo_`)
|
||||
6. Go 依赖版本需匹配 Go 1.23.12,不要随意升级 Go 工具链
|
||||
7. `.gitignore` 已配置忽略:`.cursor/`、`.vite/`、`node_modules/`、`dist/`、`*.png`(根目录截图)、`logs/` 等
|
||||
1. uni-app 的 `tabBar.custom: true` 配合自定义 TabBar 组件使用
|
||||
2. Go 依赖版本需匹配 Go 1.23.12
|
||||
3. 管理端 Element Plus 全量导入导致打包体积较大(后续可改为按需导入)
|
||||
|
||||
---
|
||||
|
||||
## 六、Phase 1 完成总结
|
||||
## 八、下一阶段规划
|
||||
|
||||
### Phase 1 阶段成果
|
||||
- **11 个 Task 全部完成**,端到端验证通过
|
||||
- **Go 后端**:15 个 API 端点,JWT 有状态认证,RBAC 角色权限
|
||||
- **前台 uni-app**:登录/注册/TabBar/个人中心
|
||||
- **管理端 Vue 3**:登录/仪表盘/用户列表/用户详情
|
||||
- **基础设施**:Docker Compose 一键启动(PostgreSQL + Redis + Go 服务)
|
||||
- **代码审查**:code-reviewer 审查通过,已修复 panic 风险、错误处理等问题
|
||||
|
||||
### 下一阶段:Phase 2 - 即时通讯
|
||||
- 待制定实施计划
|
||||
- WebSocket 长连接 + 消息系统
|
||||
- 联系人/好友管理
|
||||
### Phase 2b - 即时通讯消息系统
|
||||
- 会话管理(单聊/群聊)
|
||||
- 消息收发 + 离线消息
|
||||
- 消息通知
|
||||
- 已读回执
|
||||
|
||||
Reference in New Issue
Block a user