EchoChat 项目开发进度
最后更新:2026-04-20(Phase 2d 富媒体消息缺陷修复,Playwright 全流程验证通过)
当前阶段:Phase 2d 全部完成 + Bug 修复 4 项(图片上传端口/MinIO 策略/MsgImage 布局/文件名保留)
当前分支:feature/phase2d-message-types
实施计划:docs/plans/2026-03-04-phase2d-implementation.plan.md
设计文档:docs/plans/2026-03-04-phase2d-design.md
本次修复报告:test-report-phase2d-bugfix.md
🔧 2026-04-20 Bug 修复清单
| # |
根因 |
修复 |
文件 |
| B1 |
文件上传 BASE_URL 硬编码为 :8080(与实际 :8085 不符)导致 ERR_CONNECTION_REFUSED |
改为复用 @/utils/request 中的统一 BASE_URL |
frontend/src/api/file.js |
| B2 |
MinIO bucket 默认 private,图片 URL 匿名访问返回 403 |
启动时自动设置 bucket public-read 策略(仅 s3:GetObject) |
backend/go-service/pkg/storage/minio.go |
| B3 |
MsgImage flex 布局塌陷,<uni-image> 宽度为 0 |
.grid-single/2col/3col 增加显式宽高和 display:block |
frontend/src/components/msg/MsgImage.vue |
| B4 |
H5 下 URL.createObjectURL(file) 丢失文件名,显示为 file-1776xxx |
前端发送消息时优先使用用户选择的 file.name |
frontend/src/pages/{chat,group}/conversation.vue |
验证结果:Playwright MCP 全流程通过(图片/文件上传、缩略图渲染、大图预览、管理端消息详情)。详见 test-report-phase2d-bugfix.md。
🛠️ 2026-04-20 工程化脚本改造(开发者体验)
引入社区通用的 setup / start 职责分离 模式(参考 Rails bin/setup + bin/dev、Django 模板、Next.js 企业模板):
| 脚本 |
定位 |
使用频率 |
scripts/dev-setup.sh |
首次环境初始化:Docker 检查 + 容器拉起 + 重试式健康检查(pg/redis/minio) |
首次 clone / 重建卷 |
scripts/start.sh |
日常启动:Docker 中间件 + Go 后端 + 前台 + 管理端全量拉起,端口占用自动跳过 |
每天多次 |
scripts/stop.sh |
日常停止:优雅终止应用层(先 TERM 后 KILL 兜底),默认保留容器,支持 --all 全关 |
每天多次 |
scripts/status.sh |
状态查看:三应用端口 + 三容器状态一览 |
排障随时 |
核心特性:
- 端口占用自动跳过:
lsof 检测,已占用则 WARN 跳过,不重复启动
- PID + 日志分离:PID 写入
.run/*.pid,stdout 写入 .run/logs/*.log(已加入 .gitignore)
- MinIO 健康等待:
dev-setup.sh 新增 /minio/health/live 重试检查,补齐原脚本遗漏
- 单项启停:
./scripts/start.sh backend|frontend|admin|docker
涉及文件:
- 新增
scripts/start.sh、scripts/stop.sh、scripts/status.sh
- 改造
scripts/dev-setup.sh(新增 MinIO 检查 + 头部使用时机注释)
- 更新
README.md(置顶一键脚本章节,阐述首次/日常使用顺序)
- 更新
.gitignore(忽略 .run/)
一、Phase 2b Task 完成状态
| Task |
描述 |
状态 |
备注 |
| Task 0 |
IM Model + 数据库迁移 + 常量 |
✅ 完成 |
3 张表 + init.sql + AutoMigrate |
| Task 1 |
WS 事件路由表机制 |
✅ 完成 |
Hub.RegisterEvent/DispatchEvent |
| Task 2 |
IM DAO 层 |
✅ 完成 |
ConversationDAO + MessageDAO |
| Task 3 |
IM Service 核心业务 + DTO |
✅ 完成 |
9 个业务方法 + 接口注入 |
| Task 4 |
WS 事件处理器 + 离线推送 |
✅ 完成 |
4 个事件 + OfflinePusher |
| Task 5 |
REST Controller + Router + Wire |
✅ 完成 |
7 个 REST API + 完整 Wire 集成 |
| Task 6 |
前台 Store + API + WS 事件 |
✅ 完成 |
chat.js Store + API + TabBar badge |
| Task 7 |
会话列表页 + 聊天对话页 |
✅ 完成 |
2 个核心页面 |
| Task 8 |
设置页 + 搜索页 + 联系人改造 |
✅ 完成 |
2 个辅助页面 + 发消息跳转 |
| Task 9 |
文档更新 + 代码审查 |
✅ 完成 |
进度/架构文档同步 |
| UI 改造 |
ui-ux-pro-max 规范改造 |
✅ 完成 |
uni-icons 替换 emoji + 设计规范文件 |
| 代码审查修复 |
后端 7 项修复 |
✅ 完成 |
P0×2 + P1×3 + 推送补全×2 |
| 用户测试修复 |
8 项 Bug 修复 |
✅ 完成 |
好友申请/接受、在线状态、UI 布局等 |
代码审查修复详情
| # |
优先级 |
修复内容 |
| Fix 1 |
P0 |
ClearHistory 改为个人视图操作(ClearBeforeMsgID),不再删除双方消息 |
| Fix 2 |
P0 |
Redis 未读数负数保护(Lua 脚本原子递减,下限为 0) |
| Fix 3 |
P1 |
GetConversationList N+1 查询优化(LEFT JOIN 一次获取 peerID) |
| Fix 4 |
P1 |
消息搜索改用 GIN 全文索引(to_tsvector/plainto_tsquery 替代 LIKE) |
| Fix 5 |
P1 |
撤回消息后更新会话预览(last_msg_content = "XX 撤回了一条消息") |
| Fix 6 |
- |
im.message.new 推送补充 sender_name、sender_avatar |
| Fix 7 |
- |
im.message.recalled 推送补充 sender_id |
用户测试修复详情
| # |
修复内容 |
| Fix 8 |
好友申请拒绝后重新申请失败 — FriendshipDAO 新增 ReactivateRejectedRequest 方法 |
| Fix 9 |
好友接受申请失败(反向记录 UNIQUE 冲突)— AcceptRequest 先查后改,避免重复插入 |
| Fix 10 |
Redis 在线状态残留 — OnlineService 启动时清理旧在线数据(cleanStaleOnlineData) |
| Fix 11 |
WS 断开时在线状态未清理 — 修正 onDisconnect 判断条件(closedByHub && isOnline) |
| Fix 12 |
前端 WS 连接未全局初始化 — App.vue onLaunch/onShow + login.vue 登录后建立连接 |
| Fix 13 |
后台管理端好友关系页用户 A 列名称错误 — 修正字段绑定 row.user_username |
| Fix 14 |
前台好友在线状态初始值缺失 — ContactService 注入 OnlineChecker,GetFriendList 返回 is_online |
| Fix 15 |
聊天页消息过多时输入框被挤出 — scroll-view 添加 height:0 + min-height:0 约束 |
二、Phase 2b 新增功能
即时通讯(IM)
- 消息收发:WebSocket 全双工通讯,im.message.send → ACK + 推送
- 三态确认:sending → sent/ACK → failed
- 消息撤回:2 分钟内可撤回,推送 im.message.recalled
- 正在输入:im.typing 事件,3 秒超时自动清除
- 离线消息:WebSocket 重连后服务端主动推送未读会话摘要
会话管理
- 自动创建:首次发消息时自动创建单聊会话
- 会话列表:置顶优先 → 最后消息时间降序,LEFT JOIN 一次获取 peerID(N+1 优化)
- 会话操作:置顶/取消、软删除(不影响对方)、清空聊天记录(个人视图 ClearBeforeMsgID)
- 未读管理:DB unread_count + Redis STRING 全局未读数(Lua 脚本负数保护),TabBar badge 显示
WebSocket 事件路由表
- Hub.RegisterEvent:业务模块注册事件处理器
- Hub.DispatchEvent:消息分发到匹配的处理器
- 事件清单:im.message.send / im.message.recall / im.conversation.read / im.typing
REST API(7 个)
| 方法 |
路径 |
描述 |
| GET |
/api/v1/im/conversations |
会话列表 |
| GET |
/api/v1/im/messages |
历史消息(游标分页) |
| PUT |
/api/v1/im/conversations/:id/pin |
置顶/取消 |
| DELETE |
/api/v1/im/conversations/:id |
删除会话 |
| DELETE |
/api/v1/im/conversations/:id/messages |
清空记录 |
| GET |
/api/v1/im/messages/search |
全局搜索 |
| GET |
/api/v1/im/unread |
全局未读数 |
前端页面(4 个)
pages/chat/index.vue — 会话列表(TabBar 页面)
pages/chat/conversation.vue — 聊天对话页
pages/chat/settings.vue — 聊天设置页
pages/chat/search.vue — 消息搜索页
数据库表(3 张)
im_conversations — 会话表(含冗余 last_msg_* 字段)
im_conversation_members — 会话成员表(个人视图:置顶/未读/软删除)
im_messages — 消息表(游标分页索引 + GIN 全文搜索索引)
三、Phase 2a 完成总结
| Task |
描述 |
状态 |
备注 |
| Task 0-12 |
WebSocket + 联系人 + 管理端 |
✅ 全部完成 |
13 个 Task + 8 项 Bug 修复 |
- WebSocket 实时通讯(Hub + Client + PubSub)
- 联系人管理 17 个 API
- 在线状态管理(Redis SET + TTL)
- 管理端扩展(在线监控 + 好友管理)
四、Phase 1 完成总结
| Task |
描述 |
状态 |
| Task 1-11 |
基础设施 + 认证 + 用户管理 |
✅ 全部完成 |
- Go 后端 15+ API、JWT 有状态认证、RBAC 角色权限
- 前台 uni-app 登录/注册/TabBar/个人中心
- 管理端 Vue 3 登录/仪表盘/用户列表/详情
- Docker Compose 一键启动
五、关键技术决策记录
后端(Go)
- 框架组合:Gin + GORM + Wire + Zap + Viper
- JWT 策略:有状态 JWT,Token 按 clientType 隔离存储在 Redis
- WebSocket:
gorilla/websocket + Redis Pub/Sub 跨实例路由
- WS 事件路由:Hub.eventHandlers map[string]EventHandler + RegisterEvent/DispatchEvent
- IM 跨模块:FriendChecker + UserInfoGetter 接口注入(contact → im)
- IM 推送:OfflineMessagePusher 接口注入(im → ws)
- 在线状态:混合方案(Redis SET + STRING TTL + Pub/Sub 推送)
- 角色等级:
auth_roles.level(1=超管, 10=管理员, 100=普通用户)
前台用户端(frontend/)
- 框架:uni-app 3.0(Vue 3.4.21)
- 状态管理:Pinia 2.1.7 + pinia-plugin-persistedstate@3
- WebSocket:
uni.connectSocket(小程序)/ WebSocket(H5)
- IM Store:chat.js(会话列表 + 消息缓存 + 三态确认 + 全局未读)
- 设计系统:ui-ux-pro-max 规范,MASTER.md + 页面覆盖规范
- 图标方案:@dcloudio/uni-ui uni-icons(easycom 自动引入,跨平台兼容)
- 预处理器:sass(uni-icons SCSS 依赖)
后台管理端(admin/)
- 框架:Vue 3.5+ + Vite 7.x + Element Plus
- HTTP 客户端:Axios
- 存储隔离:localStorage key 前缀
admin_
六、目录结构概览
七、开发测试指南
服务管理命令
建议开 4 个终端窗口,分别运行各服务。终止方式统一为 Ctrl + C 或 kill 命令。
基础设施(Docker Compose)
| 服务 |
地址 |
单独启动 |
单独停止 |
| PostgreSQL |
localhost:5432 |
docker compose -f docker-compose.dev.yml up -d postgres |
docker compose -f docker-compose.dev.yml stop postgres |
| Redis |
localhost:6379 |
docker compose -f docker-compose.dev.yml up -d redis |
docker compose -f docker-compose.dev.yml stop redis |
| MinIO API |
localhost:9000 |
docker compose -f docker-compose.dev.yml up -d minio |
docker compose -f docker-compose.dev.yml stop minio |
| MinIO 控制台 |
localhost:9001 |
(同上) |
(同上) |
应用服务
Go 后端快速重启(一行命令)
测试账号
| 账号 |
密码 |
角色 |
用途 |
super_admin |
admin123456 |
super_admin |
系统预置唯一超管 |
admin_test |
admin123456 |
user + admin |
管理端登录推荐 |
testuser1 |
test123456 |
user + admin |
前台登录测试 |
testuser |
test123456 |
user |
前台登录测试 |
Phase 2b 可测试功能
- 会话列表:发消息自动创建会话 → 列表排序 → 置顶 → 长按删除
- 聊天:发送文本 → 三态确认 → 撤回(2分钟内)→ 正在输入提示
- 离线消息:断开重连 → 自动推送未读摘要 → TabBar badge 更新
- 消息搜索:全局关键词搜索 → 跳转到对应会话
- 联系人入口:好友详情页 → 发消息 → 跳转聊天页
八、Phase 2c — 群聊与已读回执
状态: ✅ 已完成
设计文档: docs/plans/2026-03-04-phase2c-design.md
实施计划: docs/plans/2026-03-04-phase2c-implementation.plan.md
分支: feature/phase2c-group-read-receipt
功能范围
| 模块 |
内容 |
| 群聊管理 |
建群/加入/退出/解散/搜索/三级角色/禁言/全体禁言/群公告/群昵称/免打扰 |
| 群消息 |
复用 im.message.* 事件 + @某人/@所有人 + 管理员撤回(无时限)+ 系统消息 |
| 已读回执 |
单聊会话级(last_read_msg_id)+ 群聊消息级(im_message_reads 表)+ 实时推送 |
| MinIO |
Docker 容器 + Go SDK + 通用上传 API(群头像) |
| 管理端 |
群列表/群详情/解散群 |
| 前端 |
9 个新页面 + 群聊 Store + 会话列表 Tab 改造 |
Task 完成状态
| Task |
描述 |
状态 |
| Task 0 |
MinIO Docker + SDK + 通用上传 API |
✅ 完成 |
| Task 1 |
数据库迁移 + Model + 常量 |
✅ 完成 |
| Task 2 |
Group DAO 层 |
✅ 完成 |
| Task 3 |
Group Service 业务逻辑 + WS 推送 |
✅ 完成 |
| Task 4 |
Group Controller + Router + Wire |
✅ 完成 |
| Task 5 |
IM Service 扩展(群消息/@提醒/管理员撤回) |
✅ 完成 |
| Task 6 |
已读回执后端(单聊 + 群聊) |
✅ 完成 |
| Task 7 |
代码审查修复(Critical 4 项 + Important 4 项) |
✅ 完成 |
| Task 8 |
前端已读回执 UI(单聊标记 + 群聊计数 + 详情页) |
✅ 完成 |
| Task 9 |
前端群聊 Store + API 封装 + WS 事件监听 |
✅ 完成 |
| Task 10 |
群聊核心页面(Tab 切换 + 群聊对话页 + 创建群聊页) |
✅ 完成 |
| Task 11 |
群聊管理页面(群设置 + 成员管理 + 邀请入群) |
✅ 完成 |
| Task 12 |
群聊辅助功能(入群审批 + 搜索群聊) |
✅ 完成 |
| Task 13 |
管理端群组管理 + 文档更新 |
✅ 完成 |
| 代码审查修复 |
14 项修复(Critical×5 + Important×4 + Minor×2 + Suggestion×3) |
✅ 完成 |
| Playwright 测试 + 用户反馈修复 |
浏览器端到端测试 + 21 项修复(搜索/UI/交互/功能增强) |
✅ 完成 |
用户测试修复详情(Phase 2c)
| # |
修复内容 |
| Fix T1 |
create.vue 创建群后跳转使用 result.id(原 result.group_id 字段不存在) |
| Fix T2 |
conversation/settings/members/join-requests 用 user_nickname 替代 username(对齐 DTO) |
| Fix T3 |
管理端群组详情弹窗 UI 全面重设计(卡片+头像+分区布局+成员mini头像) |
| Fix T4 |
群搜索结果已在群内的显示「已加入」标签,不再显示「申请加入」按钮 |
| Fix T5 |
group_dao.go SearchGroups 改用 ILIKE 模糊匹配(原 to_tsvector 不支持混合词搜索) |
| Fix T6 |
conversation.vue 增加 groupId=0 时从 chatStore 回退查找 group_id |
| Fix T7 |
create.vue 最低选择人数从 2 改为 1(支持 2 人群聊) |
| Fix T8 |
create.vue 支持搜索非好友用户并加入群聊(全站用户搜索 + 非好友标签) |
| Fix T9 |
invite.vue 支持搜索非好友用户并邀请入群(同 create.vue 改造) |
| Fix T10 |
admin/list.vue 成员表用 username 替代 user_nickname(对齐 admin DTO) |
| Fix T11 |
群聊已读回执优化:无人已读时显示「0人已读」(含点击跳转已读详情功能) |
| Fix T12 |
新好友聊天页 conversationId=0 时「加载更多」点击报错(hasMore 增加 ID 校验) |
| Fix T13 |
联系人 TabBar 添加好友申请未读数 badge(与消息 Tab 一致的交互体验) |
| Fix T14 |
App.vue 启动时预加载好友申请数,确保 badge 立即可见 |
| Fix T15 |
单聊已读回执:后端 MarkRead 缺失 im.message.read.ack 推送(补全对方已读通知链路) |
| Fix T16 |
群成员列表页为所有角色添加身份标识(群主/管理员/成员) |
| Fix T17 |
全局修复 e?.data?.message → e?.message(8 个页面 18 处,确保后端错误信息正确展示) |
| Fix T18 |
members.vue 管理操作弹窗改为自定义组件(头像+角色+图标操作列表),替代 uni.showActionSheet;三个点按钮从 @longpress 改为 @tap |
| Fix T19 |
已读详情页展示群内昵称:后端 DTO 新增 group_nickname 字段 + DAO 批量查询群昵称 + 前端主显群昵称/副显真实昵称 |
| Fix T20 |
消息免打扰 API 补全:后端缺失 DAO/Service/Controller/Router 完整链路(PUT /api/v1/im/conversations/:id/dnd) |
| Fix T21 |
联系人 Tab 页切换回来后数据不刷新:onMounted → 增加 onShow 生命周期钩子自动重新获取好友列表和待处理申请数 |
代码审查修复详情(Phase 2c)
| # |
优先级 |
修复内容 |
| Fix C1 |
Critical |
conversation.vue 角色类型不匹配:字符串改为 GROUP_ROLE 数字常量 |
| Fix C2 |
Critical |
settings.vue 群公告字段名 announcement 改为 notice(对齐后端 DTO) |
| Fix C3 |
Critical |
chat.js sendMessage 未传递 at_user_ids 到 WS payload |
| Fix C4 |
Critical |
create.vue 创建成功后导航错误:改为 /pages/group/conversation + 正确参数 |
| Fix C5 |
Critical |
admin/provider.go Wire Set 未注册 GroupManageService/Controller |
| Fix I1 |
Important |
store/group.js searchGroups 添加 append 参数解决分页加载竞态 |
| Fix I2 |
Important |
settings.vue 改为 fetchMembers() 刷新数据,不直接修改 computed 引用 |
| Fix I3 |
Important |
新增 constants/group.js 前端角色常量定义,消除魔数 |
| Fix I4 |
Important |
group_manage_service.go 列表查询 N+1 优化:批量查询用户名和成员数 |
| Fix M1 |
Minor |
file.js JSON.parse 添加 try/catch 异常保护 |
| Fix M2 |
Minor |
conversation.vue isSelf 移除冗余临时状态条件 |
| Fix S1 |
Suggestion |
群聊对话页新增禁言状态检测和输入栏禁用提示 |
| Fix S2 |
Suggestion |
join-requests.vue 注册 WS group.join.request 事件实时刷新 |
| Fix S3 |
Suggestion |
read-detail.vue 获取失败时添加 uni.showToast 用户提示 |
Phase 2c 新增内容
后端新增模块
- file/ — 文件上传(MinIO SDK + 通用上传 API)
- group/ — 群聊管理(Controller + Service + DAO + Model + Router)
- 18 个群管理 REST API + 11 个 WS 群事件推送
- im/ 扩展 — 群消息发送/撤回 + @提醒 + 单聊/群聊已读回执
- admin/ 扩展 — 群组列表 + 群组详情 + 解散群聊
前端新增页面(9 个)
| 页面 |
路径 |
功能 |
| 群聊对话页 |
pages/group/conversation.vue |
群消息收发 + @选择器 + 已读计数 |
| 创建群聊页 |
pages/group/create.vue |
好友/非好友多选 + 全站用户搜索 + 群名称输入 |
| 群设置页 |
pages/group/settings.vue |
群信息修改 + 成员概览 + 退出/解散 |
| 群成员页 |
pages/group/members.vue |
成员列表 + 全角色标识(群主/管理员/成员)+ 自定义操作弹窗 + 角色管理 + 禁言操作 |
| 邀请入群页 |
pages/group/invite.vue |
好友/非好友多选 + 全站用户搜索 + 排除已在群内成员 |
| 入群审批页 |
pages/group/join-requests.vue |
申请列表 + 通过/拒绝操作 |
| 搜索群聊页 |
pages/group/search.vue |
关键词搜索 + 申请加入 + 已加入状态显示 |
| 已读详情页 |
pages/chat/read-detail.vue |
已读/未读成员列表(群聊消息级)+ 群昵称优先展示 + 真实昵称副行 |
| 会话列表改造 |
pages/chat/index.vue |
Tab 切换(全部/单聊/群聊)+ @标记 + 免打扰标识 |
管理端新增
| 页面 |
路径 |
功能 |
| 群组列表 |
views/group/list.vue |
搜索 + 分页 + 详情弹窗 + 解散群聊 |
数据库新增/变更
im_groups — 群信息表(新增)
im_group_join_requests — 入群申请表(新增)
im_message_reads — 群消息已读表(新增)
im_conversation_members — 扩展字段(role, nickname, is_muted, is_do_not_disturb, joined_at, at_me_count)
im_messages — 扩展字段(at_user_ids BIGINT[])
九、Phase 2d — 消息类型扩展
状态: ✅ 已完成
设计文档: docs/plans/2026-03-04-phase2d-design.md
实施计划: docs/plans/2026-03-04-phase2d-implementation.plan.md
分支: feature/phase2d-message-types
功能范围
| 模块 |
内容 |
| 文件上传增强 |
50MB 上传上限、图片缩略图(200px JPEG)、语音校验(mp3/wav/aac/m4a, 最长 60s) |
| 富媒体消息 |
图片(多图网格 + 大图预览)、语音(录制+播放+波形)、文件(卡片+下载+预览) |
| IM Service |
extra JSON 存储、会话列表预览文案([图片x3]/[语音 12"]/[文件] xxx.pdf) |
| 前端组件 |
MsgText/MsgImage/MsgVoice/MsgFile + MorePanel + VoiceRecorder |
| 管理端 |
消息列表(多条件筛选+撤回+删除+详情)+ 消息统计仪表板(ECharts 四图表) |
Task 完成状态
| Task |
描述 |
状态 |
| Task 1 |
文件上传服务增强(50MB + 缩略图 + 语音校验) |
✅ 完成 |
| Task 2 |
消息 extra 结构定义 + DTO 扩展 + 常量启用 |
✅ 完成 |
| Task 3 |
IM Service 适配富媒体消息 |
✅ 完成 |
| Task 4 |
管理端消息 DAO + Service + Controller |
✅ 完成 |
| Task 5 |
消息组件体系 + conversation 页改造 |
✅ 完成 |
| Task 6 |
图片消息完整流程 |
✅ 完成 |
| Task 7 |
语音消息完整流程 |
✅ 完成 |
| Task 8 |
文件消息完整流程 |
✅ 完成 |
| Task 9 |
输入栏改造 |
✅ 完成 |
| Task 10 |
管理端消息列表页 |
✅ 完成 |
| Task 11 |
管理端消息统计页 |
✅ 完成 |
| Task 12 |
管理端路由 + Store + API |
✅ 完成 |
| Task 13 |
群聊适配 + 编译验证 |
✅ 完成 |
| Task 14 |
代码审查 + 文档更新 |
✅ 完成 |
| 代码审查修复 |
C1: im_groups 表名修复 + C2: 管理端撤回 WS 推送补全 |
✅ 完成 |
后端新增/修改
文件上传 API
| 方法 |
路径 |
说明 |
| POST |
/api/v1/upload/image |
图片上传(含缩略图生成) |
| POST |
/api/v1/upload/voice |
语音上传(含时长校验) |
管理端消息 API
| 方法 |
路径 |
说明 |
| GET |
/api/v1/admin/messages |
消息列表(分页+多条件筛选) |
| GET |
/api/v1/admin/messages/:id |
消息详情 |
| DELETE |
/api/v1/admin/messages/:id |
删除消息(软删除) |
| PUT |
/api/v1/admin/messages/:id/recall |
撤回消息(+WS 推送) |
| GET |
/api/v1/admin/messages/stats |
消息统计 |
前端新增组件
| 组件 |
路径 |
功能 |
| MsgText.vue |
components/msg/ |
文本消息渲染 |
| MsgImage.vue |
components/msg/ |
图片网格 + 大图预览 |
| MsgVoice.vue |
components/msg/ |
语音播放 + 波形 + 时长 |
| MsgFile.vue |
components/msg/ |
文件卡片 + 下载 + 预览 |
| MorePanel.vue |
components/chat/ |
"+"展开面板 |
| VoiceRecorder.vue |
components/chat/ |
长按录音 |
管理端新增页面
| 页面 |
路径 |
功能 |
| 消息列表 |
views/message/list.vue |
多条件筛选 + 操作 + 详情弹窗 |
| 消息统计 |
views/message/stats.vue |
趋势折线图 + 类型饼图 + 活跃排行 |
Playwright 端到端测试(2026-04-17)
| 测试项 |
结果 |
说明 |
| 前台单聊输入栏改造 |
✅ 通过 |
语音切换 + MorePanel 展开正常 |
| 前台群聊输入栏改造 |
✅ 通过 |
与单聊一致的改造结构 |
| 管理端消息列表展示 |
✅ 通过 |
表格、分页、操作按钮正常 |
| 管理端筛选功能 |
✅ 通过 |
关键词/类型/发送者ID/重置全部正常 |
| 管理端撤回/删除操作 |
✅ 通过 |
确认弹窗 + 状态变更 + 按钮联动正常 |
| 管理端消息详情弹窗 |
✅ 通过 |
发送者信息 + 元数据 + 内容展示正常 |
| 管理端消息统计图表 |
✅ 通过 |
ECharts 线图/饼图/条形图渲染正常 |
详细报告:test-report-phase2d.md
留待后续阶段
- 群头像上传 UI 完善
- 消息转发功能
- 视频消息支持