Files
EchoChat/docs/progress/CURRENT_STATUS.md
bujinyuan 2c59500e27 fix(phase2a): 代码审查修复 - 8项关键/重要问题
安全修复:
- WebSocket Token 增加 Redis 有效性校验(已登出用户无法建立 WS)

功能修复:
- GetRecommendFriends 改为批量查询,正确返回用户名/昵称/头像
- 上下线通知:OnlineService 通过接口注入获取好友列表推送状态变更
- 管理端在线用户 API 补充用户名信息

代码质量:
- 所有 json.Marshal/Redis 错误增加检查与日志
- ContactController 13 个 endpoint 统一走 handleError 业务错误映射
- 管理端 Controller 补全包注释、函数注释和结构化日志
- 前端 5 个联系人页面 avatar 工具函数抽取到 utils/avatar.js

Made-with: Cursor
2026-03-02 18:48:28 +08:00

250 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# EchoChat 项目开发进度
> **最后更新**2026-03-02Phase 2a 代码审查全面修复 + Phase 2b 架构建议)
> **当前阶段**Phase 2a 已完成Phase 2b 待设计
> **当前分支**`feature/phase2a-websocket-contacts`
> **实施计划**`phase_2a_实施计划_221003ce.plan.md`
> **设计文档**`docs/plans/2026-03-02-phase2a-design.md`
> **Phase 2b 架构备忘**`docs/plans/2026-03-02-phase2b-architecture-notes.md`
---
## 一、Phase 2a Task 完成状态
| Task | 描述 | 状态 | 备注 |
|------|------|------|------|
| 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 策略**:有状态 JWTToken 按 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.0Vue 3.4.21
2. **状态管理**Pinia 2.1.7 + pinia-plugin-persistedstate@3
3. **WebSocket**`uni.connectSocket`(小程序)/ `WebSocket`H5
4. **设计系统**ui-ux-pro-max 规范
### 后台管理端admin/
1. **框架**Vue 3.5+ + Vite 7.x + Element Plus
2. **HTTP 客户端**Axios
3. **存储隔离**localStorage key 前缀 `admin_`
---
## 五、目录结构概览
```
EchoChat/
├── backend/go-service/
│ ├── 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,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,user,monitor,contact}.js
│ ├── views/
│ │ ├── monitor/online.vue # [Phase 2a]
│ │ ├── contact/list.vue # [Phase 2a]
│ │ ├── layout/ login/ dashboard/ user/
│ └── router/index.js
├── deploy/
├── design-system/
└── docs/
├── api/
│ ├── frontend/{auth,contact,websocket}.md
│ ├── admin/{auth,user,online,contact}.md
│ └── websocket.md
├── plans/
├── progress/CURRENT_STATUS.md
└── conventions/
```
---
## 六、开发测试指南
### 启动命令
```bash
# 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
# 3. 启动管理端http://localhost:3100
cd admin && npm run dev
# 4. 启动前台 H5http://localhost:5173+
cd frontend && npm run dev:h5
```
### 测试账号
| 账号 | 密码 | 角色 | 用途 |
|------|------|------|------|
| `super_admin` | `admin123456` | super_admin | 系统预置唯一超管 |
| `admin_test` | `admin123456` | user + admin | 管理端登录推荐 |
| `testuser1` | `test123456` | user + admin | 前台登录测试 |
| `testuser` | `test123456` | user | 前台登录测试 |
### Phase 2a 可测试功能
- **前台联系人**:好友列表 → 搜索添加 → 好友申请 → 好友详情 → 备注/分组 → 拉黑/删除
- **前台 WebSocket**:自动连接 → 心跳 → 在线状态实时更新 → 好友申请推送
- **管理端在线监控**:在线用户数 → 在线用户列表 → 自动刷新
- **管理端好友管理**:好友关系列表 → 强制删除关系
---
## 七、已知问题
1. uni-app 的 `tabBar.custom: true` 配合自定义 TabBar 组件使用
2. Go 依赖版本需匹配 Go 1.23.12
3. 管理端 Element Plus 全量导入导致打包体积较大(后续可改为按需导入)
---
## 八、Phase 2a 后期 Bug 修复记录2026-03-02
### 修复 1: GetRecommendFriends 返回空数据
- **问题**:对每个候选人调用 `SearchUsers` 并忽略结果,返回的 DTO 只有 ID 字段
- **修复**FriendshipDAO 新增 `GetUsersByIDs` 批量查询方法Service 层收集所有候选人 ID 后一次查询,正确填充 Username/Nickname/Avatar
- **改进**:排序算法从手动冒泡改为 `sort.Slice`
### 修复 2: 上下线好友通知未实现
- **问题**`UserOnline`/`UserOffline` 没有调用已有的 `NotifyFriendsStatusChange` 方法
- **修复**OnlineService 新增 `FriendIDsGetter` 接口依赖(由 FriendshipDAO 隐式实现),在上线/下线时获取好友列表并推送状态变更通知
- **架构**:使用接口注入避免 ws 包直接依赖 contact 包
### 修复 3: 管理端在线用户 API 缺少用户名
- **问题**`GetOnlineUsers` 只返回 `[]int64`,管理端无法展示用户名
- **修复**OnlineManageService 注入 `*gorm.DB`,返回 `[]OnlineUserInfo`(含 user_id + username查询 auth_users 表补充信息
### 修复 4: WebSocket Token 未校验 Redis 状态I2
- **问题**`ws.handler.Upgrade` 只校验 JWT 签名和过期时间,未检查 Token 是否仍在 Redis 中有效(已登出用户仍可建立 WS 连接)
- **修复**:新增 `TokenValidator` 接口,由 `AuthService` 实现;`Upgrade` 流程增加 Redis Token 校验步骤
- **架构**:使用接口注入避免 ws 包直接依赖 auth 包
### 修复 5: HeartbeatRenew Redis 错误未检查M6
- **问题**`HeartbeatRenew``rdb.Expire` 调用结果被忽略
- **修复**:增加错误检查与日志记录
### 修复 6: json.Marshal 错误未处理M2
- **问题**`handler.go` 心跳/默认响应的 `MarshalResponse``online_service.go``json.Marshal` 错误被忽略
- **修复**:所有 Marshal 调用增加错误检查,失败时记录日志并提前返回
### 修复 7: Controller 统一错误处理I8
- **问题**`contact_controller.go` 中多数 endpoint 使用硬编码的 `utils.ResponseError`,未经过 `handleError` 业务错误映射
- **修复**:所有 13 个 endpoint 统一走 `handleError`确保已知业务错误404/400/403被正确返回
### 修复 8: 管理端 Controller 注释与日志规范化M1
- **问题**`online_controller.go``contact_manage_controller.go` 缺少包注释、函数注释和 `funcName` 日志模式
- **修复**:补全所有注释,增加 `funcName` + `logs.Error/Info` 结构化日志
---
## 九、下一阶段规划
### Phase 2b - 即时通讯消息系统
- 会话管理(单聊/群聊)
- 消息收发 + 离线消息
- 消息通知
- 已读回执