feat:聊天信息支持 文件、图片、语音发送,增加一键启停脚本
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
| [admin/online.md](admin/online.md) | 在线监控 | ✅ Phase 2a | 在线用户列表、在线用户计数 |
|
||||
| [admin/contact.md](admin/contact.md) | 好友关系管理 | ✅ Phase 2a | 好友关系列表(分页)、管理员解除好友关系 |
|
||||
| [admin/group.md](admin/group.md) | 群聊管理 | ✅ Phase 2c | 群列表/详情、管理员解散群聊 |
|
||||
| [admin/message.md](admin/message.md) | 消息管理 | ✅ Phase 2d | 消息列表/详情/撤回/删除、消息统计(5 个 API) |
|
||||
| [admin/meeting.md](admin/meeting.md) | 会议管理 | 📋 后续 | 会议列表/详情、强制结束、会议统计 |
|
||||
| [admin/system.md](admin/system.md) | 系统管理 | 📋 待定 | 仪表盘数据、操作日志、系统配置 |
|
||||
|
||||
@@ -206,6 +207,7 @@ docs/api/
|
||||
│ ├── online.md # 在线监控 ✅ Phase 2a
|
||||
│ ├── contact.md # 好友关系管理 ✅ Phase 2a
|
||||
│ ├── group.md # 群聊管理(3 个 API) ✅ Phase 2c
|
||||
│ ├── message.md # 消息管理(5 个 API) ✅ Phase 2d
|
||||
│ ├── meeting.md # 会议管理 📋 后续
|
||||
│ └── system.md # 系统管理 📋 待定
|
||||
└── websocket.md # WebSocket 全量事件协议 ✅ Phase 2a/2b/2c
|
||||
|
||||
162
docs/api/admin/message.md
Normal file
162
docs/api/admin/message.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# 管理端消息管理 API
|
||||
|
||||
> **最后更新**:2026-03-03
|
||||
> **阶段**:Phase 2d
|
||||
|
||||
---
|
||||
|
||||
## 接口列表
|
||||
|
||||
| 方法 | 路径 | 描述 | 认证 |
|
||||
|------|------|------|------|
|
||||
| GET | /api/v1/admin/messages | 消息列表(分页+多条件筛选) | JWT + admin |
|
||||
| GET | /api/v1/admin/messages/:id | 消息详情 | JWT + admin |
|
||||
| DELETE | /api/v1/admin/messages/:id | 删除消息(软删除) | JWT + admin |
|
||||
| PUT | /api/v1/admin/messages/:id/recall | 撤回消息 | JWT + admin |
|
||||
| GET | /api/v1/admin/messages/stats | 消息统计 | JWT + admin |
|
||||
|
||||
---
|
||||
|
||||
## GET /api/v1/admin/messages
|
||||
|
||||
获取消息列表(分页+多条件筛选)。
|
||||
|
||||
### 请求参数(Query)
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| page | int | 否 | 页码(默认 1) |
|
||||
| page_size | int | 否 | 每页条数(默认 20,最大 100) |
|
||||
| keyword | string | 否 | 搜索关键词(模糊匹配消息内容) |
|
||||
| type | int | 否 | 消息类型:1=文本 / 2=图片 / 3=语音 / 5=文件 / 10=系统 |
|
||||
| sender_id | int64 | 否 | 发送者 ID |
|
||||
| conversation_id | int64 | 否 | 会话 ID |
|
||||
| status | int | 否 | 消息状态:1=正常 / 2=已撤回 / 3=已删除 |
|
||||
| start_time | string | 否 | 开始日期(YYYY-MM-DD) |
|
||||
| end_time | string | 否 | 结束日期(YYYY-MM-DD) |
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"total": 156,
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"conversation_id": 5,
|
||||
"sender_id": 10,
|
||||
"sender_nickname": "张三",
|
||||
"sender_avatar": "https://...",
|
||||
"type": 1,
|
||||
"type_label": "文本",
|
||||
"content": "你好",
|
||||
"extra": null,
|
||||
"status": 1,
|
||||
"status_label": "正常",
|
||||
"created_at": "2026-03-03 14:30:00"
|
||||
}
|
||||
],
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GET /api/v1/admin/messages/:id
|
||||
|
||||
获取消息详情。
|
||||
|
||||
### 响应
|
||||
|
||||
同列表中的单条消息对象。
|
||||
|
||||
---
|
||||
|
||||
## DELETE /api/v1/admin/messages/:id
|
||||
|
||||
删除消息(软删除,状态改为 3=已删除)。
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PUT /api/v1/admin/messages/:id/recall
|
||||
|
||||
管理员撤回消息。撤回后会通过 WebSocket 推送 `im.message.recalled` 事件给该会话的所有在线成员。
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
### WS 推送事件
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "im.message.recalled",
|
||||
"data": {
|
||||
"message_id": 123,
|
||||
"conversation_id": 5,
|
||||
"operator_id": 0,
|
||||
"sender_id": 10,
|
||||
"recall_text": "管理员撤回了一条消息"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GET /api/v1/admin/messages/stats
|
||||
|
||||
获取消息统计数据。
|
||||
|
||||
### 请求参数(Query)
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| days | int | 否 | 统计天数(默认 7,最大 90) |
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"total_count": 5680,
|
||||
"today_count": 120,
|
||||
"type_distribution": [
|
||||
{ "type": 1, "label": "文本", "count": 4500 },
|
||||
{ "type": 2, "label": "图片", "count": 800 }
|
||||
],
|
||||
"daily_trend": [
|
||||
{ "date": "2026-02-25", "count": 150 },
|
||||
{ "date": "2026-02-26", "count": 200 }
|
||||
],
|
||||
"active_users": [
|
||||
{ "user_id": 10, "nickname": "张三", "count": 500 }
|
||||
],
|
||||
"active_groups": [
|
||||
{ "group_id": 1, "name": "技术交流群", "count": 300 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -3,7 +3,7 @@
|
||||
> 通用规范(认证方式、响应格式、错误码)见 [README.md](../README.md)
|
||||
> 消息的实时收发(发送/撤回/标记已读/正在输入)通过 WebSocket 完成,见 [websocket.md](../websocket.md)
|
||||
> 本文档中的接口用于会话管理和消息历史查询等非实时操作。
|
||||
> **最后更新:** 2026-03-04(Fix T19 已读详情群昵称 + Fix T20 免打扰 API 补全)
|
||||
> **最后更新:** 2026-03-03(Phase 2d 文件上传 API 新增)
|
||||
|
||||
---
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
| GET | /api/v1/im/messages/search | 需认证 | 全局消息搜索 |
|
||||
| GET | /api/v1/im/unread | 需认证 | 获取全局未读消息总数 |
|
||||
| GET | /api/v1/im/messages/:id/reads | 需认证 | 获取消息已读详情 |
|
||||
| POST | /api/v1/upload/image | 需认证 | 图片上传(含缩略图生成)[Phase 2d] |
|
||||
| POST | /api/v1/upload/voice | 需认证 | 语音上传(含时长校验)[Phase 2d] |
|
||||
| POST | /api/v1/upload | 需认证 | 通用文件上传(最大 50MB)[Phase 2d] |
|
||||
|
||||
---
|
||||
|
||||
|
||||
704
docs/plans/2026-03-04-phase2d-design.md
Normal file
704
docs/plans/2026-03-04-phase2d-design.md
Normal file
@@ -0,0 +1,704 @@
|
||||
# Phase 2d 设计文档:消息类型扩展
|
||||
|
||||
> **状态:** ✅ 已完成
|
||||
> **分支:** `feature/phase2d-message-types`
|
||||
> **前置依赖:** Phase 2c 全部完成(群聊与已读回执)
|
||||
> **最后更新:** 2026-03-03
|
||||
|
||||
---
|
||||
|
||||
## 一、设计目标
|
||||
|
||||
基于 Phase 2b/2c 的单聊+群聊文本消息基础设施,扩展三种富媒体消息类型和管理端消息管理功能。
|
||||
|
||||
**核心交付物:**
|
||||
- 图片消息(type=2):前端压缩+多图发送(最多9张)、后端生成 JPEG 缩略图、聊天内缩略图展示+大图预览
|
||||
- 语音消息(type=3):微信风格按住录音/松手发送/上滑取消、最长60秒、时长波形条展示+播放
|
||||
- 文件消息(type=5):任意文件上传(最大50MB)、类型图标+大小展示、点击下载+在线预览(PDF/图片)
|
||||
- 文件上传服务增强:大小限制提升至50MB、图片专用上传(缩略图生成)、语音专用上传(格式+时长校验)
|
||||
- 管理端消息管理:消息列表(完整筛选搜索)+ 消息统计仪表板(趋势图+类型分布+活跃排行)+ 敏感消息删除/撤回
|
||||
|
||||
**不包含(留待后续阶段):**
|
||||
- 视频消息(type=4,录制/压缩/缩略图复杂度高)
|
||||
- 表情包 / 自定义贴纸
|
||||
- 消息转发 / 合并转发
|
||||
- 消息引用 / 回复
|
||||
|
||||
---
|
||||
|
||||
## 二、需求决策记录
|
||||
|
||||
### 2.1 消息类型决策
|
||||
|
||||
| 决策项 | 选择 | 理由 |
|
||||
|--------|------|------|
|
||||
| 消息类型范围 | 图片+语音+文件(无视频) | 视频录制/压缩/缩略图复杂度高,留后续阶段 |
|
||||
| 多图策略 | 单条消息包含多图(最多9张) | 微信风格,extra JSON 存图片列表 |
|
||||
| 图片缩略图 | 后端 Go 图片库生成 | 保证各端一致性,前端仅做发送前压缩 |
|
||||
| 图片格式 | 统一转 JPEG | 兼容性最好,体积适中 |
|
||||
| 图片压缩 | 前端发送前压缩(宽>1920px 等比缩放,质量80%) | 减少上传流量 |
|
||||
| 缩略图尺寸 | 宽度不超过 200px,等比缩放,JPEG quality 80 | 列表加载快,质量可接受 |
|
||||
|
||||
### 2.2 语音消息决策
|
||||
|
||||
| 决策项 | 选择 | 理由 |
|
||||
|--------|------|------|
|
||||
| 交互方式 | 微信风格:按住录音/松手发送/上滑取消 | 用户认知成本低 |
|
||||
| 录音时长 | 最长 60 秒 | 微信标准 |
|
||||
| 录音格式 | MP3 | 跨端兼容性最好 |
|
||||
| 录音技术 | uni-app `uni.getRecorderManager()` | uni-app 原生 API,多端兼容 |
|
||||
|
||||
### 2.3 文件消息决策
|
||||
|
||||
| 决策项 | 选择 | 理由 |
|
||||
|--------|------|------|
|
||||
| 大小限制 | 50MB(上调原 10MB) | 支持 PPT/中等大小文件 |
|
||||
| 文件能力 | 上传+类型图标+大小显示+下载+在线预览(PDF/图片) | 完整用户体验 |
|
||||
| 文件类型限制 | 不限制(后端仅做大小校验) | 通用文件传输场景 |
|
||||
|
||||
### 2.4 上传与发送流程决策
|
||||
|
||||
| 决策项 | 选择 | 理由 |
|
||||
|--------|------|------|
|
||||
| 上传流程 | 先上传后发送:前端 REST 上传 → 获取 URL → WS 发消息 | 简单可靠,解耦文件上传和消息发送 |
|
||||
| 上传接口 | 按类型分离:通用/图片/语音三个接口 | 图片需要缩略图、语音需要时长校验,逻辑各异 |
|
||||
|
||||
### 2.5 UI/UX 决策
|
||||
|
||||
| 决策项 | 选择 | 理由 |
|
||||
|--------|------|------|
|
||||
| 会话列表预览 | 方括号标记:`[图片]`、`[语音 12"]`、`[文件] report.pdf` | 微信风格,用户习惯 |
|
||||
| 图片展示 | 聊天内缩略图(网格)+ 点击大图预览(Swiper) | 标准 IM 体验 |
|
||||
| 语音展示 | 时长+波形条+播放按钮 | 微信风格 |
|
||||
| 文件展示 | 文件图标+文件名+大小+下载/预览按钮 | 清晰直观 |
|
||||
| 表情包/贴纸 | 不做 | 专注核心媒体消息 |
|
||||
|
||||
### 2.6 管理端决策
|
||||
|
||||
| 决策项 | 选择 | 理由 |
|
||||
|--------|------|------|
|
||||
| 搜索筛选 | 完整:关键词+类型+发送者+会话/群+时间+状态 | 满足运营需求 |
|
||||
| 统计维度 | 完整:趋势图+类型分布+活跃用户排行+群活跃度 | 数据运营可视化 |
|
||||
| 图表库 | ECharts | admin 项目基于 Vue 3 + Element Plus,ECharts 集成良好 |
|
||||
|
||||
---
|
||||
|
||||
## 三、架构设计
|
||||
|
||||
### 3.1 模块目录结构
|
||||
|
||||
```
|
||||
backend/go-service/
|
||||
├── app/
|
||||
│ ├── file/ # 文件上传模块(增强)
|
||||
│ │ ├── controller/
|
||||
│ │ │ └── file_controller.go # 新增 UploadImage / UploadVoice 接口
|
||||
│ │ ├── service/
|
||||
│ │ │ └── file_service.go # 新增 UploadWithThumbnail / UploadVoice 方法
|
||||
│ │ ├── router.go # 新增 /upload/image 和 /upload/voice 路由
|
||||
│ │ └── provider.go
|
||||
│ ├── im/ # 即时通讯模块(适配)
|
||||
│ │ ├── service/
|
||||
│ │ │ └── im_service.go # SendMessage 适配 extra + 预览文案
|
||||
│ │ └── handler/
|
||||
│ │ └── event_handler.go # im.message.send 适配 extra 字段
|
||||
│ ├── admin/ # 管理端(新增消息管理)
|
||||
│ │ ├── controller/
|
||||
│ │ │ └── message_manage_controller.go # [新增]
|
||||
│ │ ├── service/
|
||||
│ │ │ └── message_manage_service.go # [新增]
|
||||
│ │ ├── dao/
|
||||
│ │ │ └── message_manage_dao.go # [新增]
|
||||
│ │ └── router.go # 注册消息管理路由
|
||||
│ ├── dto/
|
||||
│ │ ├── im_dto.go # 扩展 SendMessageRequest + MessageDTO 的 extra
|
||||
│ │ └── admin_dto.go # 新增管理端消息 DTO
|
||||
│ └── constants/
|
||||
│ └── im.go # 消息类型常量注释更新(2/3/5 不再标注"预留")
|
||||
├── frontend/src/
|
||||
│ ├── api/
|
||||
│ │ └── file.js # [新增] 文件上传 API 封装
|
||||
│ ├── components/
|
||||
│ │ ├── msg/ # [新增] 消息类型组件
|
||||
│ │ │ ├── MsgText.vue # 文本消息组件
|
||||
│ │ │ ├── MsgImage.vue # 图片消息组件(网格+大图预览)
|
||||
│ │ │ ├── MsgVoice.vue # 语音消息组件(波形条+播放)
|
||||
│ │ │ └── MsgFile.vue # 文件消息组件(卡片+下载)
|
||||
│ │ └── chat/ # [新增] 聊天辅助组件
|
||||
│ │ ├── MorePanel.vue # "+"展开面板(图片/文件入口)
|
||||
│ │ ├── VoiceRecorder.vue # 语音录制组件
|
||||
│ │ └── ImagePreviewer.vue # 图片全屏预览
|
||||
│ ├── pages/
|
||||
│ │ ├── chat/conversation.vue # [修改] 引入消息组件+输入栏改造
|
||||
│ │ └── group/conversation.vue # [修改] 同上
|
||||
│ ├── store/
|
||||
│ │ └── chat.js # [修改] 扩展发送方法
|
||||
│ └── utils/
|
||||
│ └── file.js # [新增] 文件工具(压缩/格式判断/大小格式化)
|
||||
├── admin/src/
|
||||
│ ├── api/
|
||||
│ │ └── message.js # [新增] 管理端消息 API
|
||||
│ ├── views/
|
||||
│ │ └── message/ # [新增] 消息管理模块
|
||||
│ │ ├── list.vue # 消息列表(筛选+分页+操作)
|
||||
│ │ └── stats.vue # 消息统计仪表板
|
||||
│ └── router/
|
||||
│ └── index.js # 注册消息管理路由
|
||||
```
|
||||
|
||||
### 3.2 跨模块依赖关系
|
||||
|
||||
```
|
||||
file.FileService ← im.IMService (通过接口注入,暂不直接依赖)
|
||||
↓
|
||||
im.IMService → convDAO/msgDAO (存储消息 + extra)
|
||||
↓
|
||||
im.EventHandler → im.IMService (WS 事件调用)
|
||||
↓
|
||||
admin.MessageManageService → im.MessageDAO (查询消息)
|
||||
→ auth.UserDAO (查询发送者)
|
||||
```
|
||||
|
||||
消息发送流程中,**文件上传与消息发送是解耦的**:
|
||||
1. 前端通过 REST API 上传文件到 MinIO,获取 URL
|
||||
2. 前端通过 WS 发送消息,payload 中携带 `extra` 字段(含文件 URL)
|
||||
3. 后端 IM Service 直接存储,不再访问 file 模块
|
||||
|
||||
---
|
||||
|
||||
## 四、消息 extra 字段 JSON 结构设计
|
||||
|
||||
`im_messages.extra` 字段类型为 JSONB(已存在),按消息类型存储不同元数据。
|
||||
|
||||
### 4.1 图片消息(type=2)
|
||||
|
||||
```json
|
||||
{
|
||||
"images": [
|
||||
{
|
||||
"url": "http://localhost:9000/echochat/uploads/2026/03/05/abc.jpg",
|
||||
"thumbnail_url": "http://localhost:9000/echochat/uploads/2026/03/05/abc_thumb.jpg",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"size": 245760,
|
||||
"file_name": "photo.jpg"
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:9000/echochat/uploads/2026/03/05/def.jpg",
|
||||
"thumbnail_url": "http://localhost:9000/echochat/uploads/2026/03/05/def_thumb.jpg",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"size": 180000,
|
||||
"file_name": "photo2.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 语音消息(type=3)
|
||||
|
||||
```json
|
||||
{
|
||||
"voice": {
|
||||
"url": "http://localhost:9000/echochat/uploads/2026/03/05/voice_xxx.mp3",
|
||||
"duration": 12,
|
||||
"size": 48000,
|
||||
"file_name": "voice_20260305_120000.mp3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 文件消息(type=5)
|
||||
|
||||
```json
|
||||
{
|
||||
"file": {
|
||||
"url": "http://localhost:9000/echochat/uploads/2026/03/05/doc_xxx.pdf",
|
||||
"file_name": "年度报告.pdf",
|
||||
"size": 1048576,
|
||||
"mime_type": "application/pdf",
|
||||
"ext": ".pdf"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、API 设计
|
||||
|
||||
### 5.1 文件上传 REST API(扩展)
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|------|------|------|------|
|
||||
| POST | /api/v1/upload | 需认证 | 通用文件上传(最大50MB) |
|
||||
| POST | /api/v1/upload/image | 需认证 | 图片上传(压缩+生成缩略图,返回双 URL) |
|
||||
| POST | /api/v1/upload/voice | 需认证 | 语音上传(校验格式+时长<=60s) |
|
||||
|
||||
#### POST /api/v1/upload/image
|
||||
|
||||
**请求**:multipart/form-data,字段名 `file`
|
||||
|
||||
**成功响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"url": "http://localhost:9000/echochat/uploads/2026/03/05/xxx.jpg",
|
||||
"thumbnail_url": "http://localhost:9000/echochat/uploads/2026/03/05/xxx_thumb.jpg",
|
||||
"file_name": "photo.jpg",
|
||||
"size": 245760,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"mime_type": "image/jpeg"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/v1/upload/voice
|
||||
|
||||
**请求**:multipart/form-data,字段名 `file`
|
||||
|
||||
**成功响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"url": "http://localhost:9000/echochat/uploads/2026/03/05/voice_xxx.mp3",
|
||||
"file_name": "voice_20260305.mp3",
|
||||
"size": 48000,
|
||||
"duration": 12,
|
||||
"mime_type": "audio/mpeg"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 管理端消息管理 REST API(新增)
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|------|------|------|------|
|
||||
| GET | /api/v1/admin/messages | admin | 消息列表(分页+多条件筛选) |
|
||||
| GET | /api/v1/admin/messages/:id | admin | 消息详情(含发送者信息) |
|
||||
| DELETE | /api/v1/admin/messages/:id | admin | 删除消息 |
|
||||
| PUT | /api/v1/admin/messages/:id/recall | admin | 管理员撤回消息 |
|
||||
| GET | /api/v1/admin/messages/stats | admin | 消息统计数据 |
|
||||
|
||||
#### GET /api/v1/admin/messages
|
||||
|
||||
**查询参数**:
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| keyword | string | 搜索关键词(模糊匹配 content) |
|
||||
| type | int | 消息类型筛选(1/2/3/5/10) |
|
||||
| sender_id | int64 | 发送者 ID |
|
||||
| conversation_id | int64 | 会话 ID |
|
||||
| status | int | 消息状态(1=正常/2=已撤回/3=已删除) |
|
||||
| start_time | string | 开始时间(YYYY-MM-DD) |
|
||||
| end_time | string | 结束时间(YYYY-MM-DD) |
|
||||
| page | int | 页码(默认1) |
|
||||
| page_size | int | 每页条数(默认20) |
|
||||
|
||||
**成功响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"conversation_id": 5,
|
||||
"sender_id": 4,
|
||||
"sender_nickname": "张三",
|
||||
"sender_avatar": "",
|
||||
"type": 2,
|
||||
"type_label": "图片",
|
||||
"content": "",
|
||||
"extra": { "images": [...] },
|
||||
"status": 1,
|
||||
"status_label": "正常",
|
||||
"created_at": "2026-03-05 10:30:00"
|
||||
}
|
||||
],
|
||||
"total": 1000,
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /api/v1/admin/messages/stats
|
||||
|
||||
**查询参数**:
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| days | int | 统计天数(默认7,最大90) |
|
||||
|
||||
**成功响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"total_count": 12580,
|
||||
"today_count": 350,
|
||||
"type_distribution": [
|
||||
{ "type": 1, "label": "文本", "count": 10000 },
|
||||
{ "type": 2, "label": "图片", "count": 1500 },
|
||||
{ "type": 3, "label": "语音", "count": 500 },
|
||||
{ "type": 5, "label": "文件", "count": 300 },
|
||||
{ "type": 10, "label": "系统消息", "count": 280 }
|
||||
],
|
||||
"daily_trend": [
|
||||
{ "date": "2026-03-01", "count": 280 },
|
||||
{ "date": "2026-03-02", "count": 320 }
|
||||
],
|
||||
"active_users": [
|
||||
{ "user_id": 4, "nickname": "张三", "count": 120 }
|
||||
],
|
||||
"active_groups": [
|
||||
{ "group_id": 1, "name": "技术讨论群", "count": 500 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 WebSocket 事件变更
|
||||
|
||||
**`im.message.send` 请求扩展**:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "im.message.send",
|
||||
"data": {
|
||||
"conversation_id": 8,
|
||||
"type": 2,
|
||||
"content": "",
|
||||
"client_msg_id": "xxx",
|
||||
"extra": "{\"images\":[{\"url\":\"...\",\"thumbnail_url\":\"...\",\"width\":1920,\"height\":1080,\"size\":245760,\"file_name\":\"photo.jpg\"}]}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**`im.message.new` 推送扩展**:
|
||||
|
||||
推送数据增加 `extra` 字段(JSON string),前端解析后根据 `type` 渲染对应组件。
|
||||
|
||||
**`im.message.send.ack` 响应扩展**:
|
||||
|
||||
ACK 的 `data`(MessageDTO)增加 `extra` 字段。
|
||||
|
||||
---
|
||||
|
||||
## 六、核心业务流程
|
||||
|
||||
### 6.1 图片消息发送流程
|
||||
|
||||
1. 用户点击"+"面板中的"图片",调用 `uni.chooseImage` 选择图片(最多9张)
|
||||
2. 前端对每张图片进行压缩(宽>1920px 等比缩放,质量80%)
|
||||
3. 逐张调用 `POST /api/v1/upload/image` 上传
|
||||
4. 后端接收图片 → 生成 JPEG 缩略图(宽200px,quality 80)→ 原图+缩略图存 MinIO
|
||||
5. 返回 `{ url, thumbnail_url, width, height, size, file_name, mime_type }`
|
||||
6. 所有图片上传完成后,前端组装 `extra.images` 数组
|
||||
7. 通过 WS 发送 `im.message.send`:`type=2`,`content=""`,`extra` 为 JSON 字符串
|
||||
8. 后端存储消息,`UpdateLastMessage` 预览文案为 `[图片]` 或 `[图片x3]`
|
||||
9. 推送 `im.message.new` 给接收方,携带 `extra`
|
||||
|
||||
### 6.2 语音消息发送流程
|
||||
|
||||
1. 用户长按麦克风按钮,调用 `uni.getRecorderManager().start({ format: 'mp3', duration: 60000 })`
|
||||
2. 录音过程中显示录音动画(时长 + 波形),上滑显示"取消发送"
|
||||
3. 松手停止录音 → 录音回调返回临时文件路径
|
||||
4. 时长 < 1秒:提示"录音时间太短"并丢弃
|
||||
5. 调用 `POST /api/v1/upload/voice` 上传语音文件
|
||||
6. 后端校验格式和时长(<=60s)→ 存 MinIO → 返回 `{ url, duration, size, file_name }`
|
||||
7. 前端组装 `extra.voice` 对象
|
||||
8. 通过 WS 发送:`type=3`,`content=""`,`extra` 为 JSON 字符串
|
||||
9. 后端存储,预览文案 `[语音 12"]`
|
||||
|
||||
### 6.3 文件消息发送流程
|
||||
|
||||
1. 用户点击"+"面板中的"文件",调用 `uni.chooseFile` 或 `uni.chooseMessageFile`
|
||||
2. 校验文件大小(<=50MB)
|
||||
3. 调用 `POST /api/v1/upload` 通用上传接口
|
||||
4. 返回 `{ url, file_name, size }`
|
||||
5. 前端补充 `mime_type` 和 `ext`,组装 `extra.file` 对象
|
||||
6. 通过 WS 发送:`type=5`,`content=""`,`extra` 为 JSON 字符串
|
||||
7. 后端存储,预览文案 `[文件] report.pdf`
|
||||
|
||||
### 6.4 管理员撤回消息流程
|
||||
|
||||
1. 管理员在消息列表选中消息 → 点击"撤回"
|
||||
2. 调用 `PUT /api/v1/admin/messages/:id/recall`
|
||||
3. 后端将消息 status 改为 2(已撤回)
|
||||
4. 推送 `im.message.recalled` 给相关在线用户
|
||||
5. 会话最后消息预览更新为"管理员撤回了一条消息"
|
||||
|
||||
---
|
||||
|
||||
## 七、会话列表预览文案规则
|
||||
|
||||
在 `IMService` 中 `UpdateLastMessage` 时根据消息类型生成预览文案:
|
||||
|
||||
| type | content 字段用途 | last_msg_content 预览 |
|
||||
|------|-----------------|----------------------|
|
||||
| 1(文本) | 消息正文 | 消息正文(截断) |
|
||||
| 2(图片) | 空字符串 | `[图片]` / `[图片x3]`(多图标数量) |
|
||||
| 3(语音) | 空字符串 | `[语音 12"]`(duration 从 extra 解析) |
|
||||
| 5(文件) | 空字符串 | `[文件] report.pdf`(file_name 从 extra 解析) |
|
||||
| 10(系统) | 系统消息正文 | 系统消息正文 |
|
||||
|
||||
---
|
||||
|
||||
## 八、前端页面规划
|
||||
|
||||
### 8.1 新增组件(前台用户端)
|
||||
|
||||
| 组件 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| MsgText.vue | components/msg/ | 文本消息组件(从 conversation 提取) |
|
||||
| MsgImage.vue | components/msg/ | 图片消息:1张=大图,2-4张=2列网格,5-9张=3列网格;点击放大 |
|
||||
| MsgVoice.vue | components/msg/ | 语音消息:播放按钮+波形条+时长(宽度按时长缩放) |
|
||||
| MsgFile.vue | components/msg/ | 文件消息:文件图标+文件名+大小+下载/预览按钮 |
|
||||
| MorePanel.vue | components/chat/ | 输入栏"+"展开面板:图片、文件两个入口 |
|
||||
| VoiceRecorder.vue | components/chat/ | 语音录制:长按录音+上滑取消+时长显示+波形动画 |
|
||||
| ImagePreviewer.vue | components/chat/ | 图片全屏预览:Swiper 左右滑+双指缩放 |
|
||||
|
||||
### 8.2 修改页面(前台用户端)
|
||||
|
||||
| 页面 | 修改内容 |
|
||||
|------|----------|
|
||||
| pages/chat/conversation.vue | 消息列表按 type 渲染不同组件;输入栏增加"+"和麦克风按钮 |
|
||||
| pages/group/conversation.vue | 同上 |
|
||||
| store/chat.js | 扩展 sendMessage 支持 extra;新增 sendImageMessage/sendVoiceMessage/sendFileMessage |
|
||||
|
||||
### 8.3 新增页面(管理端)
|
||||
|
||||
| 页面 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| 消息列表 | views/message/list.vue | 多条件筛选+分页表格+撤回/删除操作 |
|
||||
| 消息统计 | views/message/stats.vue | ECharts 图表:趋势折线图+类型饼图+活跃排行柱状图 |
|
||||
|
||||
---
|
||||
|
||||
## 九、DTO 扩展规划
|
||||
|
||||
### 9.1 发送消息请求扩展
|
||||
|
||||
```go
|
||||
// SendMessageRequest 发送消息请求(WS 事件 im.message.send 的 data 字段)
|
||||
type SendMessageRequest struct {
|
||||
ConversationID int64 `json:"conversation_id"`
|
||||
TargetUserID int64 `json:"target_user_id"`
|
||||
Type int `json:"type"`
|
||||
Content string `json:"content"`
|
||||
ClientMsgID string `json:"client_msg_id"`
|
||||
AtUserIDs []int64 `json:"at_user_ids"`
|
||||
Extra string `json:"extra"` // [Phase 2d 新增] 扩展数据 JSON 字符串
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2 消息 DTO 扩展
|
||||
|
||||
```go
|
||||
// MessageDTO 消息传输对象(返回给前端)
|
||||
type MessageDTO struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID int64 `json:"conversation_id"`
|
||||
SenderID int64 `json:"sender_id"`
|
||||
Type int `json:"type"`
|
||||
Content string `json:"content"`
|
||||
Extra *string `json:"extra,omitempty"` // [Phase 2d 新增] 扩展数据 JSON
|
||||
Status int `json:"status"`
|
||||
ClientMsgID string `json:"client_msg_id"`
|
||||
AtUserIDs []int64 `json:"at_user_ids"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
```
|
||||
|
||||
### 9.3 文件上传结果 DTO 扩展
|
||||
|
||||
```go
|
||||
// ImageUploadResult 图片上传结果
|
||||
type ImageUploadResult struct {
|
||||
URL string `json:"url"`
|
||||
ThumbnailURL string `json:"thumbnail_url"`
|
||||
FileName string `json:"file_name"`
|
||||
Size int64 `json:"size"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
MimeType string `json:"mime_type"`
|
||||
}
|
||||
|
||||
// VoiceUploadResult 语音上传结果
|
||||
type VoiceUploadResult struct {
|
||||
URL string `json:"url"`
|
||||
FileName string `json:"file_name"`
|
||||
Size int64 `json:"size"`
|
||||
Duration int `json:"duration"`
|
||||
MimeType string `json:"mime_type"`
|
||||
}
|
||||
```
|
||||
|
||||
### 9.4 管理端消息 DTO
|
||||
|
||||
```go
|
||||
// AdminMessageListRequest 管理端消息列表查询
|
||||
type AdminMessageListRequest struct {
|
||||
Keyword string `form:"keyword"`
|
||||
Type *int `form:"type"`
|
||||
SenderID *int64 `form:"sender_id"`
|
||||
ConversationID *int64 `form:"conversation_id"`
|
||||
Status *int `form:"status"`
|
||||
StartTime string `form:"start_time"`
|
||||
EndTime string `form:"end_time"`
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
}
|
||||
|
||||
// AdminMessageDTO 管理端消息条目
|
||||
type AdminMessageDTO struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID int64 `json:"conversation_id"`
|
||||
SenderID int64 `json:"sender_id"`
|
||||
SenderNickname string `json:"sender_nickname"`
|
||||
SenderAvatar string `json:"sender_avatar"`
|
||||
Type int `json:"type"`
|
||||
TypeLabel string `json:"type_label"`
|
||||
Content string `json:"content"`
|
||||
Extra *string `json:"extra,omitempty"`
|
||||
Status int `json:"status"`
|
||||
StatusLabel string `json:"status_label"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
// AdminMessageStatsRequest 管理端消息统计请求
|
||||
type AdminMessageStatsRequest struct {
|
||||
Days int `form:"days"` // 统计天数(默认7,最大90)
|
||||
}
|
||||
|
||||
// AdminMessageStatsResponse 管理端消息统计响应
|
||||
type AdminMessageStatsResponse struct {
|
||||
TotalCount int64 `json:"total_count"`
|
||||
TodayCount int64 `json:"today_count"`
|
||||
TypeDistribution []TypeDistItem `json:"type_distribution"`
|
||||
DailyTrend []DailyTrendItem `json:"daily_trend"`
|
||||
ActiveUsers []ActiveUserItem `json:"active_users"`
|
||||
ActiveGroups []ActiveGroupItem `json:"active_groups"`
|
||||
}
|
||||
|
||||
type TypeDistItem struct {
|
||||
Type int `json:"type"`
|
||||
Label string `json:"label"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
type DailyTrendItem struct {
|
||||
Date string `json:"date"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
type ActiveUserItem struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Nickname string `json:"nickname"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
type ActiveGroupItem struct {
|
||||
GroupID int64 `json:"group_id"`
|
||||
Name string `json:"name"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、技术要点
|
||||
|
||||
### 10.1 Go 缩略图生成
|
||||
|
||||
- 依赖:`github.com/disintegration/imaging`
|
||||
- 流程:`imaging.Open(file)` → `imaging.Resize(img, 200, 0, imaging.Lanczos)` → `imaging.Encode(buf, thumb, imaging.JPEG, imaging.JPEGQuality(80))`
|
||||
- 缩略图文件名:原始 UUID + `_thumb` 后缀,如 `abc123_thumb.jpg`
|
||||
- 原图同时进行 JPEG 转码(如果不是 JPEG 格式)
|
||||
|
||||
### 10.2 前端图片压缩
|
||||
|
||||
- H5 平台使用 Canvas 压缩:创建 Canvas → drawImage → toBlob('image/jpeg', 0.8)
|
||||
- 小程序/App 平台使用 `uni.compressImage({ src, quality: 80 })`
|
||||
- 压缩策略:宽度>1920px 等比缩放至 1920px,质量 80%
|
||||
|
||||
### 10.3 语音录制
|
||||
|
||||
- uni-app RecorderManager API
|
||||
- `start({ format: 'mp3', duration: 60000, sampleRate: 44100, numberOfChannels: 1 })`
|
||||
- 监听 `onStop` 获取录音文件临时路径
|
||||
- 时长计算:回调中的 `duration` 字段(毫秒),前端转秒显示
|
||||
|
||||
### 10.4 语音播放
|
||||
|
||||
- uni-app InnerAudioContext API
|
||||
- `uni.createInnerAudioContext()` → `src = voiceUrl` → `play()`
|
||||
- 全局单例:同一时间只允许一个语音播放
|
||||
- 播放状态:空闲 → 加载中 → 播放中 → 播放完成
|
||||
|
||||
### 10.5 文件下载与预览
|
||||
|
||||
- 下载:`uni.downloadFile({ url })` → `uni.saveFile()` 或直接 `window.open(url)` (H5)
|
||||
- 预览:PDF 和图片通过 `uni.openDocument` 或浏览器新标签打开
|
||||
- 文件类型图标映射:根据扩展名匹配图标(PDF/Word/Excel/PPT/ZIP/图片/音频/通用)
|
||||
|
||||
### 10.6 管理端 ECharts 集成
|
||||
|
||||
- `npm install echarts` 安装
|
||||
- 使用 Vue 3 Composition API + `onMounted` 初始化
|
||||
- 响应式:`window.resize` 时 `chart.resize()`
|
||||
- 主题色与系统保持一致(Primary #2563EB)
|
||||
|
||||
---
|
||||
|
||||
## 十一、补充设计细节
|
||||
|
||||
### 11.1 消息内容安全
|
||||
|
||||
- 文件上传不做内容安全审查(留后续阶段)
|
||||
- 管理端提供人工审查和撤回能力
|
||||
- 上传文件类型不限制,但大小限制 50MB
|
||||
|
||||
### 11.2 多图布局规则
|
||||
|
||||
| 图片数量 | 布局 | 单图最大宽度 |
|
||||
|----------|------|-------------|
|
||||
| 1 张 | 自适应宽度(最大 500rpx) | 500rpx |
|
||||
| 2 张 | 2列1行 | 240rpx |
|
||||
| 3 张 | 3列1行 | 160rpx |
|
||||
| 4 张 | 2列2行 | 240rpx |
|
||||
| 5-6 张 | 3列2行 | 160rpx |
|
||||
| 7-9 张 | 3列3行 | 160rpx |
|
||||
|
||||
### 11.3 文件类型图标映射
|
||||
|
||||
| 扩展名 | 图标 | 颜色 |
|
||||
|--------|------|------|
|
||||
| .pdf | PDF 图标 | #E53E3E |
|
||||
| .doc/.docx | Word 图标 | #2B6CB0 |
|
||||
| .xls/.xlsx | Excel 图标 | #276749 |
|
||||
| .ppt/.pptx | PPT 图标 | #C05621 |
|
||||
| .zip/.rar/.7z | 压缩包图标 | #6B46C1 |
|
||||
| .jpg/.png/.gif | 图片图标 | #38A169 |
|
||||
| .mp3/.wav/.aac | 音频图标 | #D69E2E |
|
||||
| 其他 | 通用文件图标 | #718096 |
|
||||
|
||||
### 11.4 语音波形条设计
|
||||
|
||||
- 宽度:按时长线性缩放,最小 120rpx(1秒),最大 500rpx(60秒)
|
||||
- 高度:固定 60rpx
|
||||
- 波形:使用 CSS 模拟随机高度的竖条(5-6 个竖条)
|
||||
- 播放时:从左到右逐条变色动画
|
||||
435
docs/plans/2026-03-04-phase2d-implementation.plan.md
Normal file
435
docs/plans/2026-03-04-phase2d-implementation.plan.md
Normal file
@@ -0,0 +1,435 @@
|
||||
# Phase 2d 实施计划:消息类型扩展
|
||||
|
||||
> **状态:** ✅ 已完成
|
||||
> **设计文档:** [Phase 2d 设计文档](./2026-03-04-phase2d-design.md)
|
||||
> **分支:** `feature/phase2d-message-types`
|
||||
> **最后更新:** 2026-03-03
|
||||
|
||||
---
|
||||
|
||||
## 实施概览
|
||||
|
||||
共 14 个 Task,按依赖关系分为 4 个阶段:
|
||||
|
||||
| 阶段 | Task | 说明 |
|
||||
|------|------|------|
|
||||
| 后端基础层 | Task 1-4 | 上传增强 → DTO/常量 → IM 适配 → 管理端后端 |
|
||||
| 前端消息组件 | Task 5-9 | 组件体系 → 图片 → 语音 → 文件 → 输入栏 |
|
||||
| 管理端前端 | Task 10-12 | 列表页 → 统计页 → 路由/Store/API |
|
||||
| 收尾 | Task 13-14 | 群聊适配+测试 → 代码审查+文档 |
|
||||
|
||||
---
|
||||
|
||||
## Task 1:文件上传服务增强 ✅
|
||||
|
||||
**目标**:升级现有文件上传服务,支持 50MB 上传、图片缩略图生成、语音校验。
|
||||
|
||||
### 修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| backend/go-service/go.mod | 修改 | 添加 `github.com/disintegration/imaging` 依赖 |
|
||||
| backend/go-service/app/file/service/file_service.go | 修改 | 新增 `UploadWithThumbnail`、`UploadVoice` 方法;`UploadResult` 扩展字段 |
|
||||
| backend/go-service/app/file/controller/file_controller.go | 修改 | 新增 `UploadImage`、`UploadVoice` 处理器;`maxUploadSize` 提升至 50MB |
|
||||
| backend/go-service/app/file/router.go | 修改 | 新增 `/upload/image`、`/upload/voice` 路由 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `go get github.com/disintegration/imaging` 安装图片处理库
|
||||
2. 扩展 `UploadResult` 添加 `ThumbnailURL`、`Width`、`Height`、`Duration`、`MimeType` 可选字段
|
||||
3. 新增 `ImageUploadResult` 和 `VoiceUploadResult` 结构体
|
||||
4. 实现 `UploadWithThumbnail`:
|
||||
- 接收图片文件 → 解码获取宽高 → `imaging.Resize(img, 200, 0)` 生成缩略图
|
||||
- 缩略图转 JPEG(quality=80) → 上传原图+缩略图到 MinIO → 返回双 URL + 尺寸
|
||||
5. 实现 `UploadVoice`:
|
||||
- 接收语音文件 → 校验扩展名(.mp3/.wav/.aac/.m4a)→ 获取时长(从 header 或前端传参)
|
||||
- 上传到 MinIO → 返回 URL + duration + size
|
||||
6. Controller 新增 `UploadImage`、`UploadVoice` 处理器(含大小校验)
|
||||
7. `maxUploadSize` 从 `10 << 20` 改为 `50 << 20`
|
||||
8. 路由注册新接口
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] `POST /api/v1/upload` 支持 50MB 文件
|
||||
- [x] `POST /api/v1/upload/image` 返回 url + thumbnail_url + width + height
|
||||
- [x] `POST /api/v1/upload/voice` 返回 url + duration
|
||||
- [x] 缩略图宽度 200px,JPEG 格式
|
||||
|
||||
---
|
||||
|
||||
## Task 2:消息 extra 结构定义 + DTO 扩展 + 常量启用 ✅
|
||||
|
||||
**目标**:定义 extra JSON 结构的 Go 类型、扩展消息 DTO、更新常量注释。
|
||||
|
||||
### 修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| backend/go-service/app/dto/im_dto.go | 修改 | SendMessageRequest + MessageDTO 增加 Extra 字段 |
|
||||
| backend/go-service/app/dto/admin_dto.go | 修改 | 新增管理端消息相关 DTO |
|
||||
| backend/go-service/app/constants/im.go | 修改 | 消息类型常量注释去掉"预留"标注 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `SendMessageRequest` 增加 `Extra string` 字段
|
||||
2. `MessageDTO` 增加 `Extra *string` 字段(omitempty)
|
||||
3. `constants/im.go` 消息类型注释更新:去掉"预留"二字
|
||||
4. 在 `admin_dto.go` 中新增管理端消息 DTO 结构体
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] SendMessageRequest 和 MessageDTO 支持 extra 字段
|
||||
- [x] 管理端消息 DTO 定义完成
|
||||
- [x] 常量注释准确反映当前实现状态
|
||||
|
||||
---
|
||||
|
||||
## Task 3:IM Service 适配富媒体消息 ✅
|
||||
|
||||
**目标**:后端 IM 服务支持存储和推送富媒体消息。
|
||||
|
||||
### 修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| backend/go-service/app/im/service/im_service.go | 修改 | SendMessage 存储 extra;预览文案生成 |
|
||||
| backend/go-service/app/im/handler/event_handler.go | 修改 | im.message.send 解析 extra 字段 |
|
||||
| backend/go-service/app/im/dao/message_dao.go | 修改 | MessageDTO 转换包含 extra |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `EventHandler` 中 `im.message.send` 解析 `req.Extra` 并传给 Service
|
||||
2. `SendMessage` 中创建 Message 时设置 `Extra` 字段
|
||||
3. 新增 `generateLastMsgPreview(msgType int, content string, extra *string) string` 方法
|
||||
4. `UpdateLastMessage` 调用预览文案生成方法
|
||||
5. `buildMessagePushData` 返回的 MessageDTO 包含 extra
|
||||
6. 历史消息查询 `toMessageDTO` 中包含 extra 字段
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] type=2/3/5 消息能正常存储到数据库,extra 字段不为空
|
||||
- [x] 推送 im.message.new 包含 extra 数据
|
||||
- [x] 会话列表预览文案正确([图片]/[语音 12"]/[文件] xxx.pdf)
|
||||
- [x] 历史消息接口返回 extra 字段
|
||||
|
||||
---
|
||||
|
||||
## Task 4:管理端消息 DAO + Service + Controller ✅
|
||||
|
||||
**目标**:实现管理端完整的消息管理后端 API。
|
||||
|
||||
### 新增文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| backend/go-service/app/admin/dao/message_manage_dao.go | 新增 | 消息分页查询、统计聚合 |
|
||||
| backend/go-service/app/admin/service/message_manage_service.go | 新增 | 消息管理业务逻辑 |
|
||||
| backend/go-service/app/admin/controller/message_manage_controller.go | 新增 | REST API 处理器 |
|
||||
| backend/go-service/app/admin/router.go | 修改 | 注册消息管理路由 |
|
||||
| backend/go-service/app/provider/provider.go | 修改 | Wire 注入新依赖 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `message_manage_dao.go`:
|
||||
- `GetMessageList`:分页+多条件筛选(keyword/type/sender/conversation/status/time)
|
||||
- `GetMessageByID`:单条详情
|
||||
- `UpdateMessageStatus`:更新状态(撤回/删除)
|
||||
- `GetMessageStats`:统计聚合(总量/今日/类型分布/每日趋势/活跃用户/活跃群组)
|
||||
2. `message_manage_service.go`:
|
||||
- `GetMessageList` / `GetMessageDetail` / `DeleteMessage` / `RecallMessage` / `GetStats`
|
||||
- 撤回时推送 WS 事件给相关在线用户
|
||||
3. `message_manage_controller.go`:五个接口处理器
|
||||
4. Router 注册路由
|
||||
5. Wire provider 注册
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] `GET /api/v1/admin/messages` 支持完整筛选
|
||||
- [x] `GET /api/v1/admin/messages/:id` 返回详细信息
|
||||
- [x] `DELETE /api/v1/admin/messages/:id` 软删除
|
||||
- [x] `PUT /api/v1/admin/messages/:id/recall` 撤回+推送
|
||||
- [x] `GET /api/v1/admin/messages/stats` 返回统计数据
|
||||
|
||||
---
|
||||
|
||||
## Task 5:消息组件体系 + conversation 页改造 ✅
|
||||
|
||||
**目标**:建立消息类型组件体系,改造聊天页面按消息类型渲染不同组件。
|
||||
|
||||
### 新增/修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| frontend/src/components/msg/MsgText.vue | 新增 | 文本消息组件(从 conversation 抽取) |
|
||||
| frontend/src/components/msg/MsgImage.vue | 新增 | 图片消息组件(网格+预览,初始骨架) |
|
||||
| frontend/src/components/msg/MsgVoice.vue | 新增 | 语音消息组件(波形+播放,初始骨架) |
|
||||
| frontend/src/components/msg/MsgFile.vue | 新增 | 文件消息组件(卡片+下载,初始骨架) |
|
||||
| frontend/src/pages/chat/conversation.vue | 修改 | 引入组件体系,按 type 分支渲染 |
|
||||
| frontend/src/pages/group/conversation.vue | 修改 | 同上 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. 从现有 conversation.vue 中提取文本消息渲染逻辑到 `MsgText.vue`
|
||||
2. 创建 `MsgImage.vue`/`MsgVoice.vue`/`MsgFile.vue` 骨架组件(接收 msg prop,显示占位)
|
||||
3. conversation.vue 消息列表区域改为根据 `msg.type` 使用 `<component :is="">` 动态组件
|
||||
4. 确保文本消息渲染效果与改造前一致
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 文本消息渲染效果不变
|
||||
- [x] 4 个消息组件均已创建并可接收 msg prop
|
||||
- [x] conversation 页面按 type 分支渲染
|
||||
|
||||
---
|
||||
|
||||
## Task 6:图片消息完整流程 ✅
|
||||
|
||||
**目标**:实现图片消息从选取到展示的完整流程。
|
||||
|
||||
### 新增/修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| frontend/src/api/file.js | 新增 | 文件上传 API 封装 |
|
||||
| frontend/src/utils/file.js | 新增 | 文件工具函数 |
|
||||
| frontend/src/components/msg/MsgImage.vue | 修改 | 完整图片网格+大图预览 |
|
||||
| frontend/src/components/chat/ImagePreviewer.vue | 新增 | 全屏图片预览 |
|
||||
| frontend/src/store/chat.js | 修改 | 新增 sendImageMessage |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `api/file.js`:封装 `uploadImage(file)` 和 `uploadFile(file)` API 调用
|
||||
2. `utils/file.js`:图片压缩工具、文件大小格式化
|
||||
3. `MsgImage.vue`:完整实现多图网格布局 + 点击调起 ImagePreviewer
|
||||
4. `ImagePreviewer.vue`:全屏 Swiper 预览 + 左右滑 + 关闭
|
||||
5. `chat.js`:`sendImageMessage(conversationId, imageFiles)` → 压缩 → 逐张上传 → 组装 extra → WS 发送
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 图片选取+压缩+上传+发送全流程通畅
|
||||
- [x] 聊天界面正确展示图片缩略图(网格布局)
|
||||
- [x] 点击图片可全屏大图预览
|
||||
- [x] 多图(2-9张)布局正确
|
||||
|
||||
---
|
||||
|
||||
## Task 7:语音消息完整流程 ✅
|
||||
|
||||
**目标**:实现语音消息录制、发送、展示、播放完整流程。
|
||||
|
||||
### 新增/修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| frontend/src/components/chat/VoiceRecorder.vue | 新增 | 语音录制组件 |
|
||||
| frontend/src/components/msg/MsgVoice.vue | 修改 | 完整语音播放组件 |
|
||||
| frontend/src/store/chat.js | 修改 | 新增 sendVoiceMessage |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `VoiceRecorder.vue`:长按录音 UI + 上滑取消 + 时长显示 + 波形动画
|
||||
2. `MsgVoice.vue`:播放按钮 + 波形条 + 时长显示 + 播放进度动画
|
||||
3. 全局单例播放器:同时只有一个语音在播放
|
||||
4. `chat.js`:`sendVoiceMessage(conversationId, voiceTempPath, duration)` → 上传 → 发送
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 长按录音 + 松手发送 + 上滑取消
|
||||
- [x] 录音时长 < 1s 提示太短
|
||||
- [x] 录音时长 > 60s 自动停止
|
||||
- [x] 聊天界面显示语音条 + 时长
|
||||
- [x] 点击播放/暂停
|
||||
- [x] 同一时间只有一个语音播放
|
||||
|
||||
---
|
||||
|
||||
## Task 8:文件消息完整流程 ✅
|
||||
|
||||
**目标**:实现文件消息选取、上传、发送、展示、下载/预览完整流程。
|
||||
|
||||
### 新增/修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| frontend/src/components/msg/MsgFile.vue | 修改 | 完整文件卡片组件 |
|
||||
| frontend/src/store/chat.js | 修改 | 新增 sendFileMessage |
|
||||
| frontend/src/utils/file.js | 修改 | 文件类型图标映射 + 大小格式化 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `MsgFile.vue`:文件图标 + 文件名 + 大小 + 下载/预览按钮
|
||||
2. 文件类型图标映射(PDF/Word/Excel/PPT/压缩包/图片/音频/通用)
|
||||
3. 下载功能:H5 用 `window.open`,APP 用 `uni.downloadFile`
|
||||
4. 预览功能:PDF/图片支持在线预览
|
||||
5. `chat.js`:`sendFileMessage(conversationId, file)` → 校验大小 → 上传 → 发送
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 文件选择 + 大小校验(50MB)+ 上传 + 发送
|
||||
- [x] 聊天界面显示文件卡片(图标+名称+大小)
|
||||
- [x] 点击下载文件
|
||||
- [x] PDF/图片可在线预览
|
||||
|
||||
---
|
||||
|
||||
## Task 9:输入栏改造 ✅
|
||||
|
||||
**目标**:改造聊天输入栏,新增"+"面板和麦克风按钮。
|
||||
|
||||
### 新增/修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| frontend/src/components/chat/MorePanel.vue | 新增 | "+"展开面板 |
|
||||
| frontend/src/pages/chat/conversation.vue | 修改 | 输入栏集成"+"和麦克风 |
|
||||
| frontend/src/pages/group/conversation.vue | 修改 | 同上 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. `MorePanel.vue`:网格布局面板,包含"图片"和"文件"两个入口
|
||||
2. 输入栏右侧添加"+"按钮,点击展开/收起 MorePanel
|
||||
3. 输入栏左侧添加麦克风按钮,点击切换为语音录制模式
|
||||
4. 语音模式下隐藏文本输入框,显示 VoiceRecorder
|
||||
5. 统一发送流程:文本/图片/语音/文件各走对应的 store 方法
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] "+"按钮展开面板,包含图片和文件入口
|
||||
- [x] 麦克风按钮切换语音录制模式
|
||||
- [x] 各类型消息发送流程统一
|
||||
- [x] 单聊和群聊输入栏行为一致
|
||||
|
||||
---
|
||||
|
||||
## Task 10:管理端消息列表页 ✅
|
||||
|
||||
**目标**:实现管理端消息管理列表页面。
|
||||
|
||||
### 新增文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| admin/src/views/message/list.vue | 新增 | 消息列表页 |
|
||||
| admin/src/api/message.js | 新增 | 消息管理 API |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. 顶部筛选区:关键词搜索 + 类型下拉 + 发送者 + 时间范围 + 状态
|
||||
2. 表格列:ID / 发送者 / 类型 / 内容预览 / 状态 / 时间 / 操作
|
||||
3. 操作列:查看详情 / 撤回 / 删除
|
||||
4. 分页组件
|
||||
5. 消息详情弹窗:展示完整内容 + extra 渲染(图片缩略图 / 语音播放 / 文件链接)
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 完整筛选功能
|
||||
- [x] 分页正确
|
||||
- [x] 撤回和删除操作正常
|
||||
- [x] 消息详情弹窗内容完整
|
||||
|
||||
---
|
||||
|
||||
## Task 11:管理端消息统计页 ✅
|
||||
|
||||
**目标**:实现管理端消息统计仪表板。
|
||||
|
||||
### 新增文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| admin/src/views/message/stats.vue | 新增 | 消息统计仪表板 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. 顶部统计卡片:总消息数 + 今日消息数
|
||||
2. 消息趋势折线图(近 7/30 天切换)
|
||||
3. 消息类型分布饼图
|
||||
4. 活跃用户排行水平柱状图(Top 10)
|
||||
5. 活跃群组排行水平柱状图(Top 10)
|
||||
6. 图表主题色与系统一致(Primary #2563EB)
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 4 个统计图表正确渲染
|
||||
- [x] 7/30 天切换正常
|
||||
- [x] 数据与 stats API 返回一致
|
||||
- [x] 响应式布局
|
||||
|
||||
---
|
||||
|
||||
## Task 12:管理端路由 + Store + API ✅
|
||||
|
||||
**目标**:管理端消息管理模块基础设施。
|
||||
|
||||
### 修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| admin/src/router/index.js | 修改 | 注册消息管理路由 |
|
||||
| admin/src/api/message.js | 修改 | 完善 API 封装(如未在 Task 10 完成) |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. 路由配置:`/message/list` + `/message/stats`
|
||||
2. 侧边栏菜单:新增"消息管理"分组
|
||||
3. API 封装:确保所有管理端消息 API 已封装
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 侧边栏正确显示消息管理菜单
|
||||
- [x] 路由跳转正常
|
||||
- [x] API 封装完整
|
||||
|
||||
---
|
||||
|
||||
## Task 13:群聊适配 + 统一测试 ✅
|
||||
|
||||
**目标**:确保群聊页面与单聊页面的富媒体消息功能一致,统一测试。
|
||||
|
||||
### 修改文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| frontend/src/pages/group/conversation.vue | 修改 | 确认组件集成完整 |
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. 群聊 conversation.vue 确认所有消息组件和输入栏改造与单聊一致
|
||||
2. 测试单聊图片/语音/文件消息发送接收
|
||||
3. 测试群聊图片/语音/文件消息发送接收
|
||||
4. 测试会话列表预览文案
|
||||
5. 测试管理端消息列表和统计
|
||||
6. 修复发现的问题
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 单聊+群聊富媒体消息全流程正常
|
||||
- [x] 会话列表预览文案正确
|
||||
- [x] 管理端功能正常
|
||||
|
||||
---
|
||||
|
||||
## Task 14:代码审查 + Playwright 测试 + 文档更新 ✅
|
||||
|
||||
**目标**:最终质量保障和文档同步。
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. 使用 `code-reviewer` 子代理进行代码审查
|
||||
2. 使用 Playwright MCP 进行浏览器自动化测试
|
||||
3. 修复审查和测试中发现的问题
|
||||
4. 更新项目文档:
|
||||
- `docs/progress/CURRENT_STATUS.md`
|
||||
- `docs/plans/2026-03-04-phase2d-design.md`(状态更新)
|
||||
- `docs/plans/2026-03-04-phase2d-implementation.plan.md`(状态更新)
|
||||
- `docs/api/frontend/im.md`(新增上传 API)
|
||||
- `docs/api/admin/message.md`(新增管理端消息 API 文档)
|
||||
- `docs/architecture/system-architecture.md`(更新模块描述)
|
||||
- `.cursor/rules/project-context.mdc`(更新进度)
|
||||
5. Git commit + push
|
||||
|
||||
### 验收标准
|
||||
|
||||
- [x] 代码审查通过
|
||||
- [x] Playwright 测试通过
|
||||
- [x] 所有文档同步更新
|
||||
@@ -1,10 +1,49 @@
|
||||
# EchoChat 项目开发进度
|
||||
|
||||
> **最后更新**:2026-03-04(Phase 2c 浏览器测试 + UI/UX 优化 + Tab 切换刷新修复完成)
|
||||
> **当前阶段**:Phase 2c 全部完成(含 Playwright 浏览器测试 + 21 项用户反馈修复)
|
||||
> **当前分支**:`feature/phase2c-group-read-receipt`
|
||||
> **实施计划**:`docs/plans/2026-03-04-phase2c-implementation.plan.md`
|
||||
> **设计文档**:`docs/plans/2026-03-04-phase2c-design.md`
|
||||
> **最后更新**: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/`)
|
||||
|
||||
---
|
||||
|
||||
@@ -197,8 +236,20 @@ EchoChat/
|
||||
│ │ ├── join-requests.vue # 入群审批
|
||||
│ │ └── search.vue # 搜索群聊
|
||||
│ ├── pages/contact/ # [Phase 2a] 6 个页面
|
||||
│ ├── components/msg/ # [Phase 2d] 消息类型组件
|
||||
│ │ ├── MsgText.vue # 文本消息
|
||||
│ │ ├── MsgImage.vue # 图片消息(网格+预览)
|
||||
│ │ ├── MsgVoice.vue # 语音消息(播放+波形)
|
||||
│ │ └── MsgFile.vue # 文件消息(卡片+下载)
|
||||
│ ├── components/chat/ # [Phase 2d] 聊天辅助组件
|
||||
│ │ ├── MorePanel.vue # "+"展开面板
|
||||
│ │ └── VoiceRecorder.vue # 语音录制
|
||||
│ └── components/CustomTabBar.vue(含 badge)
|
||||
├── admin/ # 管理端(Vue 3 + Element Plus)
|
||||
│ └── src/views/
|
||||
│ ├── message/ # [Phase 2d] 消息管理
|
||||
│ │ ├── list.vue # 消息列表(多条件筛选+操作)
|
||||
│ │ └── stats.vue # 消息统计(ECharts 仪表板)
|
||||
├── deploy/
|
||||
├── design-system/
|
||||
└── docs/
|
||||
@@ -387,8 +438,96 @@ kill $(lsof -ti :8085) 2>/dev/null; sleep 2; cd backend/go-service && go run cmd
|
||||
- `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 完善
|
||||
- 消息转发功能
|
||||
- 视频消息支持
|
||||
|
||||
Reference in New Issue
Block a user