zhibo/Zhibo/zhibo-h/新增接口文档.md

584 lines
14 KiB
Markdown
Raw Normal View History

2025-12-29 15:12:12 +08:00
# 新增接口文档
> **创建时间**: 2024-12-29
> **版本**: v1.0
> **状态**: ✅ 已完成
---
## 📋 接口概览
本次开发完成了4个待开发接口
| 序号 | 接口路径 | 方法 | 功能 | 状态 |
|------|---------|------|------|------|
| 1 | `/api/upload/work/video` | POST | 视频上传 | ✅ 已完成 |
| 2 | `/api/upload/chat/voice` | POST | 语音上传 | ✅ 已完成 |
| 3 | `/api/rooms/{roomId}/viewers` | GET | 观众列表 | ✅ 已完成 |
| 4 | `/api/rooms/{roomId}/gift` | POST | 赠送礼物 | ✅ 已完成 |
---
## 1⃣ 视频上传接口
### 基本信息
- **接口路径**: `POST /api/upload/work/video`
- **功能描述**: 上传作品视频文件
- **需要登录**: 否(公开接口)
- **限流**: 无
### 请求参数
**Content-Type**: `multipart/form-data`
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| multipart | File | 是 | 视频文件 | video.mp4 |
| model | String | 否 | 模块名称 | works默认 |
| pid | Integer | 否 | 分类ID | 0默认 |
### 文件限制
- **支持格式**: MP4, MOV, AVI, FLV
- **文件大小**: 最大 500MB
- **存储路径**: `video/{model}/yyyy/MM/dd/`
### 响应示例
```json
{
"code": 200,
"message": "操作成功",
"data": {
"fileName": "my_video.mp4",
"fileSize": 52428800,
"extName": "mp4",
"url": "video/public/works/2024/12/29/abc123.mp4",
"type": "video/mp4"
}
}
```
### 错误码
| 错误码 | 说明 |
|--------|------|
| 400 | 视频格式不支持 |
| 400 | 文件大小超过限制 |
| 500 | 上传失败 |
### 使用示例
```javascript
// JavaScript示例
const formData = new FormData();
formData.append('multipart', videoFile);
formData.append('model', 'works');
formData.append('pid', 0);
fetch('/api/upload/work/video', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => console.log(data));
```
---
## 2⃣ 语音上传接口
### 基本信息
- **接口路径**: `POST /api/upload/chat/voice`
- **功能描述**: 上传语音消息文件
- **需要登录**: 否(公开接口)
- **限流**: 无
### 请求参数
**Content-Type**: `multipart/form-data`
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| multipart | File | 是 | 语音文件 | voice.mp3 |
| model | String | 否 | 模块名称 | chat默认 |
| pid | Integer | 否 | 分类ID | 0默认 |
### 文件限制
- **支持格式**: MP3, AAC, WAV, M4A
- **文件大小**: 最大 10MB
- **存储路径**: `voice/{model}/yyyy/MM/dd/`
### 响应示例
```json
{
"code": 200,
"message": "操作成功",
"data": {
"fileName": "voice_message.mp3",
"fileSize": 1048576,
"extName": "mp3",
"url": "voice/public/chat/2024/12/29/xyz789.mp3",
"type": "audio/mp3"
}
}
```
### 错误码
| 错误码 | 说明 |
|--------|------|
| 400 | 语音格式不支持 |
| 400 | 文件大小超过限制 |
| 500 | 上传失败 |
### 使用示例
```javascript
// JavaScript示例
const formData = new FormData();
formData.append('multipart', voiceFile);
formData.append('model', 'chat');
formData.append('pid', 0);
fetch('/api/upload/chat/voice', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => console.log(data));
```
---
## 3⃣ 观众列表接口
### 基本信息
- **接口路径**: `GET /api/rooms/{roomId}/viewers`
- **功能描述**: 获取直播间在线观众列表
- **需要登录**: 否(公开接口)
- **限流**: 无
### 请求参数
**URL参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| roomId | Integer | 是 | 直播间ID | 123 |
**Query参数**:
| 参数名 | 类型 | 必填 | 说明 | 默认值 |
|--------|------|------|------|--------|
| limit | Integer | 否 | 返回数量限制 | 50 |
### 响应示例
```json
{
"code": 200,
"message": "操作成功",
"data": [
{
"userId": 1001,
"nickname": "用户1001",
"avatar": "https://example.com/avatar/1001.jpg",
"level": 5,
"isVip": true,
"enterTime": 1703836800000,
"isOnline": true,
"clientId": "user_1001_1703836800000"
},
{
"userId": null,
"nickname": "游客",
"avatar": "",
"level": 0,
"isVip": false,
"enterTime": 1703836900000,
"isOnline": true,
"clientId": "guest_abc123_1703836900000"
}
]
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| userId | Integer | 用户ID游客为null |
| nickname | String | 用户昵称 |
| avatar | String | 用户头像URL |
| level | Integer | 用户等级 |
| isVip | Boolean | 是否VIP |
| enterTime | Long | 进入时间(时间戳) |
| isOnline | Boolean | 是否在线 |
| clientId | String | 客户端唯一标识 |
### 错误码
| 错误码 | 说明 |
|--------|------|
| 400 | 房间ID不能为空 |
| 500 | 获取观众列表失败 |
### 使用示例
```javascript
// JavaScript示例
fetch('/api/rooms/123/viewers?limit=50')
.then(response => response.json())
.then(data => {
console.log('在线观众:', data.data);
});
```
---
## 4⃣ 赠送礼物接口
### 基本信息
- **接口路径**: `POST /api/rooms/{roomId}/gift`
- **功能描述**: 在直播间赠送礼物给主播
- **需要登录**: ✅ 是需要Token
- **限流**: 建议添加(防止刷礼物)
### 请求参数
**URL参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| roomId | Integer | 是 | 直播间ID | 123 |
**Body参数** (JSON):
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| giftId | Integer | 是 | 礼物ID | 1 |
| giftCount | Integer | 是 | 礼物数量≥1 | 1 |
| receiverId | Integer | 是 | 接收者用户ID主播ID | 100 |
### 请求示例
```json
{
"giftId": 1,
"giftCount": 5,
"receiverId": 100
}
```
### 响应示例
```json
{
"code": 200,
"message": "操作成功",
"data": {
"recordId": 1001,
"giftName": "玫瑰花",
"giftCount": 5,
"totalDiamond": 50.00,
"remainingDiamond": 450.00,
"intimacy": 50,
"sendTime": 1703836800000
}
}
```
### 响应字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| recordId | Long | 礼物记录ID |
| giftName | String | 礼物名称 |
| giftCount | Integer | 礼物数量 |
| totalDiamond | BigDecimal | 消耗钻石总数 |
| remainingDiamond | BigDecimal | 剩余钻石数 |
| intimacy | Integer | 增加的亲密度 |
| sendTime | Long | 赠送时间(时间戳) |
### 业务逻辑
1. **验证礼物**: 检查礼物是否存在且启用
2. **验证用户**: 检查赠送者和接收者是否存在
3. **计算总价**: 单价 × 数量
4. **检查余额**: 验证赠送者钻石余额是否充足
5. **扣除钻石**: 从赠送者账户扣除钻石
6. **增加收益**: 给接收者主播增加钻石70%分成)
7. **创建记录**: 保存礼物赠送记录
8. **返回结果**: 返回赠送详情
### 错误码
| 错误码 | 说明 |
|--------|------|
| 400 | 房间ID不能为空 |
| 400 | 礼物ID不能为空 |
| 400 | 礼物数量至少为1 |
| 400 | 接收者用户ID不能为空 |
| 400 | 不能给自己赠送礼物 |
| 404 | 礼物不存在 |
| 404 | 用户不存在 |
| 404 | 接收者不存在 |
| 404 | 直播间不存在 |
| 400 | 礼物已下架 |
| 400 | 钻石余额不足 |
| 401 | 请先登录 |
| 500 | 扣除钻石失败 |
| 500 | 赠送礼物失败 |
### 使用示例
```javascript
// JavaScript示例
fetch('/api/rooms/123/gift', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN'
},
body: JSON.stringify({
giftId: 1,
giftCount: 5,
receiverId: 100
})
})
.then(response => response.json())
.then(data => {
if (data.code === 200) {
console.log('赠送成功:', data.data);
} else {
console.error('赠送失败:', data.message);
}
});
```
---
## 📦 数据库表结构
### eb_gift_record - 礼物赠送记录表
```sql
CREATE TABLE `eb_gift_record` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`room_id` INT NOT NULL COMMENT '直播间ID',
`gift_id` INT NOT NULL COMMENT '礼物ID',
`gift_name` VARCHAR(100) COMMENT '礼物名称',
`gift_image` VARCHAR(255) COMMENT '礼物图片',
`sender_id` INT NOT NULL COMMENT '赠送者用户ID',
`sender_nickname` VARCHAR(50) COMMENT '赠送者昵称',
`sender_avatar` VARCHAR(255) COMMENT '赠送者头像',
`receiver_id` INT NOT NULL COMMENT '接收者用户ID主播',
`receiver_nickname` VARCHAR(50) COMMENT '接收者昵称',
`gift_count` INT NOT NULL DEFAULT 1 COMMENT '礼物数量',
`diamond_price` DECIMAL(10,2) DEFAULT 0.00 COMMENT '单价(钻石)',
`total_diamond` DECIMAL(10,2) DEFAULT 0.00 COMMENT '总价(钻石)',
`intimacy` INT DEFAULT 0 COMMENT '增加的亲密度',
`is_deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除 0=未删除 1=已删除',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`ext_field1` VARCHAR(100) COMMENT '扩展字段1特效类型',
`ext_field2` INT COMMENT '扩展字段2连击次数',
`ext_field3` VARCHAR(50) COMMENT '扩展字段3活动标识',
`ext_field4` BIGINT COMMENT '扩展字段4关联订单ID',
`ext_field5` TEXT COMMENT '扩展字段5JSON扩展数据',
PRIMARY KEY (`id`),
INDEX `idx_room_id` (`room_id`),
INDEX `idx_sender_id` (`sender_id`),
INDEX `idx_receiver_id` (`receiver_id`),
INDEX `idx_gift_id` (`gift_id`),
INDEX `idx_create_time` (`create_time`),
INDEX `idx_is_deleted` (`is_deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='礼物赠送记录表';
```
---
## 🔧 技术实现
### 1. 文件上传实现
**核心类**:
- `UploadService` - 上传服务接口
- `UploadServiceImpl` - 上传服务实现
- `UserUploadController` - 前端上传控制器
**技术特点**:
- 支持多种文件格式验证
- 文件大小限制
- 自动生成唯一文件名
- 按日期分目录存储
- 支持本地存储和云存储七牛云、OSS、COS等
### 2. 观众列表实现
**核心类**:
- `LiveRoomOnlineService` - 在线服务接口
- `LiveRoomOnlineServiceImpl` - 在线服务实现
- `LiveRoomController` - 直播间控制器
- `LiveRoomOnlineUser` - 观众信息实体
**技术特点**:
- 基于WebSocket实时连接
- 使用ConcurrentHashMap保证线程安全
- 支持用户去重同一用户多标签页只计1人
- 实时更新在线状态
### 3. 礼物赠送实现
**核心类**:
- `GiftRecordService` - 礼物记录服务接口
- `GiftRecordServiceImpl` - 礼物记录服务实现
- `GiftRecord` - 礼物记录实体
- `SendGiftRequest` - 赠送请求对象
- `SendGiftResponse` - 赠送响应对象
**技术特点**:
- 使用事务保证数据一致性
- 余额检查和扣除
- 主播收益分成70%
- 完整的错误处理
- 礼物记录持久化
---
## 🧪 测试建议
### 1. 视频上传测试
```bash
# 测试正常上传
curl -X POST http://localhost:8080/api/upload/work/video \
-F "multipart=@test_video.mp4" \
-F "model=works" \
-F "pid=0"
# 测试大文件(应该失败)
curl -X POST http://localhost:8080/api/upload/work/video \
-F "multipart=@large_video.mp4"
# 测试错误格式(应该失败)
curl -X POST http://localhost:8080/api/upload/work/video \
-F "multipart=@test.txt"
```
### 2. 语音上传测试
```bash
# 测试正常上传
curl -X POST http://localhost:8080/api/upload/chat/voice \
-F "multipart=@test_voice.mp3" \
-F "model=chat" \
-F "pid=0"
```
### 3. 观众列表测试
```bash
# 获取观众列表
curl -X GET "http://localhost:8080/api/rooms/123/viewers?limit=50"
```
### 4. 赠送礼物测试
```bash
# 赠送礼物
curl -X POST http://localhost:8080/api/rooms/123/gift \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"giftId": 1,
"giftCount": 5,
"receiverId": 100
}'
```
---
## 📝 注意事项
### 1. 安全性
- ✅ 视频和语音上传接口建议添加登录验证
- ✅ 赠送礼物接口已添加登录验证
- ⚠️ 建议添加限流防刷(特别是礼物接口)
- ⚠️ 建议添加文件内容安全检查
### 2. 性能优化
- 视频上传建议使用分片上传
- 大文件上传建议使用云存储
- 观众列表建议添加缓存
- 礼物记录建议异步处理
### 3. 扩展性
- 所有实体类都预留了5个扩展字段
- 支持后续功能扩展
- 使用JPA自动建表便于维护
---
## 📊 接口统计
### 完成情况
| 模块 | 接口数量 | 完成度 |
|------|---------|--------|
| 文件上传 | 2 | ✅ 100% |
| 直播间功能 | 2 | ✅ 100% |
| **总计** | **4** | **✅ 100%** |
### 新增文件
| 类型 | 文件数量 | 说明 |
|------|---------|------|
| 实体类 | 2 | GiftRecord, LiveRoomOnlineUser扩展 |
| 请求对象 | 1 | SendGiftRequest |
| 响应对象 | 2 | SendGiftResponse, LiveRoomViewerResponse |
| DAO层 | 2 | GiftRecordDao, GiftRecordDao.xml |
| Service层 | 2 | GiftRecordService, GiftRecordServiceImpl |
| Controller层 | 2 | LiveRoomController扩展, UserUploadController扩展 |
| **总计** | **11** | - |
---
## 🎯 后续优化建议
### 短期优化1-2周
1. **添加限流**: 使用@RateLimit注解保护接口
2. **添加日志**: 完善操作日志记录
3. **添加监控**: 接入监控系统
4. **性能测试**: 压力测试和优化
### 中期优化1个月
1. **分片上传**: 实现大文件分片上传
2. **云存储**: 集成七牛云/OSS/COS
3. **CDN加速**: 视频和语音文件CDN加速
4. **缓存优化**: Redis缓存观众列表
### 长期优化3个月
1. **实时推送**: WebSocket推送礼物动画
2. **数据分析**: 礼物消费统计和分析
3. **活动系统**: 礼物活动和促销
4. **AI审核**: 视频和语音内容审核
---
**文档版本**: v1.0
**最后更新**: 2024-12-29
**维护人员**: Kiro AI Assistant