火箭功能完善
This commit is contained in:
parent
4746377fc6
commit
e279ad51db
622
ROCKET_REQUIREMENT_DOC.md
Normal file
622
ROCKET_REQUIREMENT_DOC.md
Normal file
@ -0,0 +1,622 @@
|
||||
# 🚀 语聊房火箭系统 - 完整需求文档
|
||||
|
||||
---
|
||||
|
||||
## 📋 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
|-----|------|
|
||||
| **文档名称** | 语聊房火箭系统需求文档 |
|
||||
| **版本** | v1.0 |
|
||||
| **创建日期** | 2025-01-15 |
|
||||
| **所属项目** | Likei Services |
|
||||
| **所属模块** | rc-service-other |
|
||||
| **项目路径** | D:\workspace\likei-services\rc-service\rc-service-other |
|
||||
|
||||
---
|
||||
|
||||
## 1. 业务需求
|
||||
|
||||
### 1.1 功能概述
|
||||
|
||||
语聊房火箭是一个房间级互动玩法,用户通过送礼积累火箭能量,达到阈值后自动发射并分发奖励。
|
||||
|
||||
### 1.2 核心规则
|
||||
|
||||
#### 能量积累规则
|
||||
- **基础规则**:1金币礼物 = 1火箭能量点
|
||||
- **幸运加成**:幸运礼物额外增加4%能量
|
||||
- **实时累积**:每次送礼立即增加能量
|
||||
|
||||
#### 火箭等级系统
|
||||
| 等级 | 能量阈值 | 说明 |
|
||||
|-----|---------|------|
|
||||
| Lv1 | 150,000 | 一级火箭 |
|
||||
| Lv2 | 500,000 | 二级火箭 |
|
||||
| Lv3 | 1,000,000 | 三级火箭 |
|
||||
|
||||
#### 发射机制
|
||||
- 能量达到阈值自动触发发射
|
||||
- 发射后进入"领取中"状态
|
||||
- 领取有效期:1分钟
|
||||
|
||||
#### 奖励领取规则
|
||||
- 房间内所有用户可领取
|
||||
- 贡献者和普通用户奖励不同(配置待定)
|
||||
- 每人限领一次
|
||||
- 过期后自动重置
|
||||
|
||||
#### 每日重置
|
||||
- 每天00:00重置火箭状态
|
||||
- 历史记录保存到MongoDB
|
||||
|
||||
---
|
||||
|
||||
## 2. 技术架构
|
||||
|
||||
### 2.1 技术栈
|
||||
|
||||
| 组件 | 技术 |
|
||||
|-----|------|
|
||||
| **语言** | Java 17+ |
|
||||
| **框架** | Spring Boot |
|
||||
| **数据库** | MySQL + MongoDB |
|
||||
| **缓存** | Redis |
|
||||
| **架构模式** | DDD + CQRS |
|
||||
|
||||
### 2.2 数据库设计
|
||||
|
||||
#### MongoDB 集合
|
||||
|
||||
**room_rocket_status** - 火箭实时状态
|
||||
```javascript
|
||||
{
|
||||
"_id": ObjectId,
|
||||
"room_id": NumberLong,
|
||||
"date": "2025-01-15",
|
||||
"level": 1, // 1/2/3
|
||||
"current_energy": NumberLong(85000),
|
||||
"max_energy": NumberLong(150000),
|
||||
"status": 1, // 1:CHARGING 2:LAUNCHED 3:CLAIMING
|
||||
"contributors": [
|
||||
{
|
||||
"user_id": NumberLong,
|
||||
"user_name": "张三",
|
||||
"user_avatar": "https://...",
|
||||
"energy": NumberLong(50000),
|
||||
"contribution_rate": 58.82,
|
||||
"gift_count": 125,
|
||||
"first_contribute_time": ISODate,
|
||||
"last_contribute_time": ISODate
|
||||
}
|
||||
],
|
||||
"launch_time": ISODate,
|
||||
"claim_expire_time": ISODate,
|
||||
"claim_count": 0,
|
||||
"created_at": ISODate,
|
||||
"updated_at": ISODate
|
||||
}
|
||||
|
||||
// 索引
|
||||
db.room_rocket_status.createIndex({"room_id": 1, "date": 1}, {unique: true})
|
||||
db.room_rocket_status.createIndex({"status": 1})
|
||||
```
|
||||
|
||||
#### MySQL 表
|
||||
|
||||
**rocket_config** - 火箭配置表
|
||||
```sql
|
||||
CREATE TABLE `rocket_config` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`level` TINYINT UNSIGNED NOT NULL COMMENT '等级 1/2/3',
|
||||
`max_energy` BIGINT UNSIGNED NOT NULL COMMENT '最大能量值',
|
||||
`reward_config` JSON DEFAULT NULL COMMENT '奖励配置(预留)',
|
||||
`status` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_level` (`level`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `rocket_config` (`level`, `max_energy`) VALUES
|
||||
(1, 150000),
|
||||
(2, 500000),
|
||||
(3, 1000000);
|
||||
```
|
||||
|
||||
**rocket_reward_claim_log** - 奖励领取记录表
|
||||
```sql
|
||||
CREATE TABLE `rocket_reward_claim_log` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`rocket_history_id` VARCHAR(32) NOT NULL COMMENT 'MongoDB _id',
|
||||
`room_id` BIGINT UNSIGNED NOT NULL,
|
||||
`user_id` BIGINT UNSIGNED NOT NULL,
|
||||
`is_contributor` TINYINT UNSIGNED NOT NULL COMMENT '是否贡献者',
|
||||
`reward_type` VARCHAR(32) NOT NULL COMMENT 'GOLD/DIAMOND/PROP',
|
||||
`reward_amount` BIGINT UNSIGNED NOT NULL,
|
||||
`claimed_at` DATETIME NOT NULL,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_rocket_user` (`rocket_history_id`, `user_id`),
|
||||
KEY `idx_room_id` (`room_id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
```
|
||||
|
||||
### 2.3 Redis 缓存设计
|
||||
|
||||
| Key | 类型 | TTL | 用途 |
|
||||
|-----|------|-----|------|
|
||||
| ROCKET:STATUS:{roomId} | String(JSON) | 24h | 状态缓存 |
|
||||
| ROCKET:LOCK:{roomId} | String | 5s | 分布式锁 |
|
||||
| ROCKET:CLAIMED:{historyId} | Set | 2min | 已领取用户 |
|
||||
| ROCKET:CONFIG:{level} | String(JSON) | 1h | 配置缓存 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心流程
|
||||
|
||||
### 3.1 能量积累流程
|
||||
|
||||
```
|
||||
用户送礼 → GiftSendEvent
|
||||
↓
|
||||
RocketEnergyAddCmdExe
|
||||
↓
|
||||
1. 获取分布式锁 (Redis)
|
||||
2. 查询火箭状态 (MongoDB)
|
||||
3. 计算能量值 (普通/幸运)
|
||||
4. 更新能量和贡献者
|
||||
5. 检查等级提升
|
||||
6. 保存状态
|
||||
7. 判断是否达到发射条件
|
||||
├─ 是 → 触发发射
|
||||
└─ 否 → 推送能量更新
|
||||
```
|
||||
|
||||
### 3.2 火箭发射流程
|
||||
|
||||
```
|
||||
能量达到阈值
|
||||
↓
|
||||
RocketLaunchCmdExe
|
||||
↓
|
||||
1. 获取分布式锁
|
||||
2. 校验状态和能量
|
||||
3. 发射火箭 (status → LAUNCHED)
|
||||
4. 设置领取过期时间 (+1分钟)
|
||||
5. 进入领取状态 (status → CLAIMING)
|
||||
6. 保存状态
|
||||
7. 推送发射动画 (TODO: WebSocket)
|
||||
8. 保存历史记录 (TODO)
|
||||
```
|
||||
|
||||
### 3.3 奖励领取流程
|
||||
|
||||
```
|
||||
用户点击领取
|
||||
↓
|
||||
RocketRewardClaimCmdExe
|
||||
↓
|
||||
1. 获取分布式锁
|
||||
2. 校验领取资格
|
||||
├─ 状态是否为CLAIMING
|
||||
├─ 是否过期
|
||||
└─ 是否重复领取
|
||||
3. 判断是否贡献者
|
||||
4. 计算奖励金额 (TODO: 配置)
|
||||
5. 调用钱包服务发放 (TODO)
|
||||
6. 记录领取日志 (MySQL)
|
||||
7. 更新领取人数
|
||||
8. 返回奖励详情
|
||||
```
|
||||
|
||||
### 3.4 每日重置流程
|
||||
|
||||
```
|
||||
定时任务 00:00
|
||||
↓
|
||||
RocketDailyResetTask
|
||||
↓
|
||||
1. 查询所有CHARGING状态火箭
|
||||
2. 保存历史记录 (TODO)
|
||||
3. 重置火箭状态
|
||||
├─ level = 1
|
||||
├─ current_energy = 0
|
||||
├─ contributors = []
|
||||
└─ date = 今天
|
||||
4. 清除Redis缓存
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. API 接口设计
|
||||
|
||||
### 4.1 查询火箭状态
|
||||
|
||||
**接口**: `GET /api/rocket/status`
|
||||
|
||||
**请求参数**:
|
||||
```json
|
||||
{
|
||||
"roomId": 123456,
|
||||
"currentUserId": 789 // 可选
|
||||
}
|
||||
```
|
||||
|
||||
**响应数据**:
|
||||
```json
|
||||
{
|
||||
"roomId": 123456,
|
||||
"date": "2025-01-15",
|
||||
"level": 2,
|
||||
"levelName": "二级火箭",
|
||||
"currentEnergy": 350000,
|
||||
"maxEnergy": 500000,
|
||||
"energyPercent": 70.00,
|
||||
"status": "CHARGING",
|
||||
"statusDesc": "充能中",
|
||||
"topContributors": [
|
||||
{
|
||||
"userId": 789,
|
||||
"userName": "张三",
|
||||
"userAvatar": "https://...",
|
||||
"energy": 200000,
|
||||
"contributionRate": 57.14,
|
||||
"rank": 1,
|
||||
"giftCount": 500
|
||||
}
|
||||
],
|
||||
"totalContributors": 25,
|
||||
"claimCount": 0,
|
||||
"canClaim": false,
|
||||
"hasClaimed": false,
|
||||
"myContribution": 200000,
|
||||
"myContributionRate": 57.14
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 领取奖励
|
||||
|
||||
**接口**: `POST /api/rocket/claim`
|
||||
|
||||
**请求参数**:
|
||||
```json
|
||||
{
|
||||
"roomId": 123456,
|
||||
"userId": 789,
|
||||
"rocketHistoryId": "507f1f77bcf86cd799439011"
|
||||
}
|
||||
```
|
||||
|
||||
**响应数据**:
|
||||
```json
|
||||
{
|
||||
"rewardType": "GOLD",
|
||||
"rewardAmount": 1000,
|
||||
"isContributor": true,
|
||||
"contributionEnergy": 200000,
|
||||
"contributionRate": 57.14,
|
||||
"message": "恭喜您获得贡献者奖励!"
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 手动触发发射 (测试用)
|
||||
|
||||
**接口**: `POST /api/rocket/manual-launch`
|
||||
|
||||
**请求参数**:
|
||||
```
|
||||
roomId=123456
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 已实现文件清单
|
||||
|
||||
### 5.1 Domain 层
|
||||
```
|
||||
✅ RocketLevel.java - 等级枚举
|
||||
✅ RocketStatusEnum.java - 状态枚举
|
||||
✅ RocketContributor.java - 贡献者值对象
|
||||
✅ RocketStatus.java - 火箭状态领域对象
|
||||
✅ RocketStatusGateway.java - Gateway接口
|
||||
```
|
||||
|
||||
### 5.2 Infrastructure 层
|
||||
```
|
||||
✅ RocketKeys.java - Redis Key枚举
|
||||
✅ RocketStatusDocument.java - MongoDB文档
|
||||
✅ RocketStatusRepository.java - MongoDB Repository
|
||||
✅ RocketStatusGatewayImpl.java - Gateway实现
|
||||
```
|
||||
|
||||
### 5.3 Client 层
|
||||
```
|
||||
✅ RocketEnergyAddCmd.java - 能量增加命令
|
||||
✅ RocketRewardClaimCmd.java - 奖励领取命令
|
||||
✅ RocketStatusQueryCmd.java - 状态查询命令
|
||||
✅ RocketStatusCO.java - 状态客户端对象
|
||||
✅ RocketContributorCO.java - 贡献者客户端对象
|
||||
✅ RocketRewardCO.java - 奖励客户端对象
|
||||
✅ RocketService.java - 服务接口
|
||||
```
|
||||
|
||||
### 5.4 Application 层
|
||||
```
|
||||
✅ RocketEnergyAddCmdExe.java - 能量增加执行器
|
||||
✅ RocketLaunchCmdExe.java - 火箭发射执行器
|
||||
✅ RocketStatusQryExe.java - 状态查询执行器
|
||||
✅ RocketRewardClaimCmdExe.java - 奖励领取执行器
|
||||
✅ RocketServiceImpl.java - 服务实现
|
||||
✅ RocketDailyResetTask.java - 每日重置任务
|
||||
✅ RocketClaimExpireTask.java - 过期检查任务
|
||||
```
|
||||
|
||||
### 5.5 Adapter 层
|
||||
```
|
||||
✅ RocketRestController.java - REST控制器
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 待实现功能清单
|
||||
|
||||
### 6.1 高优先级 (P0)
|
||||
|
||||
#### 1. 礼物事件监听
|
||||
**文件**: `GiftSendRocketListener.java`
|
||||
**位置**: `other-application/src/.../app/listener/`
|
||||
**功能**: 监听送礼事件,自动触发能量增加
|
||||
```java
|
||||
@EventListener
|
||||
public void onGiftSend(GiftSendEvent event) {
|
||||
RocketEnergyAddCmd cmd = new RocketEnergyAddCmd();
|
||||
cmd.setRoomId(event.getRoomId());
|
||||
cmd.setUserId(event.getUserId());
|
||||
cmd.setGiftGoldValue(event.getGiftGoldValue());
|
||||
cmd.setIsLucky(event.getIsLuckyGift());
|
||||
cmd.setBizNo("GIFT_" + event.getGiftOrderId());
|
||||
rocketService.addEnergy(cmd);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. MySQL 表创建
|
||||
**执行SQL**:
|
||||
- `rocket_config` 配置表
|
||||
- `rocket_reward_claim_log` 领取记录表
|
||||
|
||||
#### 3. MongoDB 索引创建
|
||||
```javascript
|
||||
db.room_rocket_status.createIndex(
|
||||
{"room_id": 1, "date": 1},
|
||||
{unique: true, name: "uk_room_date"}
|
||||
)
|
||||
db.room_rocket_status.createIndex(
|
||||
{"status": 1},
|
||||
{name: "idx_status"}
|
||||
)
|
||||
```
|
||||
|
||||
#### 4. 奖励发放集成
|
||||
**需要**: 调用 `wallet-inner-api`
|
||||
**实现**: 在 `RocketRewardClaimCmdExe` 中补充
|
||||
```java
|
||||
// 注入 Feign Client
|
||||
@Autowired
|
||||
private WalletGoldClient walletGoldClient;
|
||||
|
||||
// 发放奖励
|
||||
String bizNo = "ROCKET_" + rocketHistoryId + "_" + userId;
|
||||
WalletReceiptReqDTO req = new WalletReceiptReqDTO();
|
||||
req.setUserId(userId);
|
||||
req.setAmount(rewardAmount);
|
||||
req.setBizType(WalletBizType.ROCKET_REWARD);
|
||||
req.setBizNo(bizNo);
|
||||
walletGoldClient.income(req);
|
||||
```
|
||||
|
||||
#### 5. 领取防重实现
|
||||
**实现**: MySQL唯一索引 + Redis检查
|
||||
```java
|
||||
// 查询MySQL
|
||||
boolean hasClaimed = rocketRewardLogGateway.existsByRocketAndUser(
|
||||
rocketHistoryId, userId
|
||||
);
|
||||
if (hasClaimed) {
|
||||
throw new RuntimeException("您已经领取过奖励了");
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 中优先级 (P1)
|
||||
|
||||
#### 6. 历史记录保存
|
||||
**文件**: `RocketHistoryDocument.java` + `RocketHistoryRepository.java`
|
||||
**功能**: 发射后保存完整历史
|
||||
|
||||
#### 7. WebSocket 推送
|
||||
**功能**:
|
||||
- 能量更新推送
|
||||
- 发射动画推送
|
||||
- 领取通知推送
|
||||
|
||||
#### 8. 奖励配置管理
|
||||
**功能**: 后台配置各等级奖励规则
|
||||
|
||||
#### 9. 排行榜查询
|
||||
**文件**: `RocketRankingQryExe.java`
|
||||
**功能**: 查询贡献排行榜
|
||||
|
||||
### 6.3 低优先级 (P2)
|
||||
|
||||
#### 10. 管理后台接口
|
||||
**功能**:
|
||||
- 配置管理
|
||||
- 数据统计
|
||||
- 手动重置
|
||||
|
||||
#### 11. 数据统计报表
|
||||
**功能**: 发射次数、领取人数等统计
|
||||
|
||||
#### 12. 监控告警
|
||||
**功能**: 关键指标监控、异常告警
|
||||
|
||||
---
|
||||
|
||||
## 7. 测试用例
|
||||
|
||||
### 7.1 单元测试
|
||||
|
||||
```java
|
||||
@Test
|
||||
public void testEnergyAdd_Normal() {
|
||||
// 正常送礼增加能量
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnergyAdd_Lucky() {
|
||||
// 幸运礼物增加能量
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRocketLaunch_AutoTrigger() {
|
||||
// 能量满自动发射
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRewardClaim_Contributor() {
|
||||
// 贡献者领取奖励
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRewardClaim_Duplicate() {
|
||||
// 重复领取防重
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 集成测试场景
|
||||
|
||||
1. **完整流程**: 送礼 → 发射 → 领取
|
||||
2. **并发送礼**: 100人同时送礼
|
||||
3. **分布式锁**: 高并发下的锁测试
|
||||
4. **过期重置**: 领取过期自动重置
|
||||
|
||||
---
|
||||
|
||||
## 8. 部署说明
|
||||
|
||||
### 8.1 环境要求
|
||||
|
||||
- MongoDB 4.4+
|
||||
- MySQL 8.0+
|
||||
- Redis 6.0+
|
||||
|
||||
### 8.2 配置示例
|
||||
|
||||
```yaml
|
||||
# application.yml
|
||||
spring:
|
||||
data:
|
||||
mongodb:
|
||||
uri: mongodb://localhost:27017/likei
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/likei
|
||||
username: root
|
||||
password: password
|
||||
|
||||
rocket:
|
||||
enabled: true
|
||||
lucky-bonus-rate: 0.04
|
||||
claim-expire-seconds: 60
|
||||
```
|
||||
|
||||
### 8.3 启动顺序
|
||||
|
||||
1. 启动 MongoDB
|
||||
2. 启动 MySQL
|
||||
3. 启动 Redis
|
||||
4. 执行数据库初始化脚本
|
||||
5. 启动应用
|
||||
|
||||
---
|
||||
|
||||
## 9. 注意事项
|
||||
|
||||
### 9.1 幂等性
|
||||
- 能量增加使用 `bizNo` 防重
|
||||
- 奖励领取使用 MySQL 唯一索引防重
|
||||
|
||||
### 9.2 并发控制
|
||||
- 使用 Redis 分布式锁
|
||||
- 锁粒度:房间级别
|
||||
|
||||
### 9.3 数据一致性
|
||||
- MongoDB 保存实时状态
|
||||
- MySQL 保存领取记录
|
||||
- 通过业务逻辑保证一致性
|
||||
|
||||
### 9.4 性能优化
|
||||
- 热点房间使用 Redis 缓存
|
||||
- 批量查询贡献者
|
||||
- 异步推送消息
|
||||
|
||||
---
|
||||
d
|
||||
## 10. 联系方式
|
||||
|
||||
**技术支持**: system
|
||||
**文档维护**: Leo
|
||||
**最后更新**: 2025-01-15
|
||||
|
||||
---
|
||||
|
||||
## 附录:快速上手指南
|
||||
|
||||
### A. 快速测试流程
|
||||
|
||||
1. **初始化数据库**
|
||||
```sql
|
||||
-- 执行 MySQL 建表语句
|
||||
-- 插入火箭配置数据
|
||||
```
|
||||
|
||||
2. **创建 MongoDB 索引**
|
||||
```javascript
|
||||
use likei
|
||||
db.room_rocket_status.createIndex({"room_id": 1, "date": 1}, {unique: true})
|
||||
```
|
||||
|
||||
3. **启动应用**
|
||||
```bash
|
||||
cd other-start
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
4. **测试接口**
|
||||
```bash
|
||||
# 查询状态
|
||||
curl "http://localhost:8080/api/rocket/status?roomId=123456"
|
||||
|
||||
# 手动发射 (测试用)
|
||||
curl -X POST "http://localhost:8080/api/rocket/manual-launch?roomId=123456"
|
||||
|
||||
# 领取奖励
|
||||
curl -X POST "http://localhost:8080/api/rocket/claim" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"roomId":123456,"userId":789,"rocketHistoryId":"xxx"}'
|
||||
```
|
||||
|
||||
### B. 常见问题
|
||||
|
||||
**Q: 如何手动触发能量增加?**
|
||||
A: 调用 `RocketService.addEnergy(cmd)` 或监听送礼事件
|
||||
|
||||
**Q: 如何查看当前火箭状态?**
|
||||
A: 访问 MongoDB `room_rocket_status` 集合或调用查询接口
|
||||
|
||||
**Q: 如何重置火箭?**
|
||||
A: 等待每日00:00自动重置,或手动调用重置方法
|
||||
|
||||
---
|
||||
|
||||
**祝开发顺利!🚀**
|
||||
48
rc-service/rc-service-other/docs/sql/rocket_init.sql
Normal file
48
rc-service/rc-service-other/docs/sql/rocket_init.sql
Normal file
@ -0,0 +1,48 @@
|
||||
-- ============================================
|
||||
-- 火箭系统数据库初始化脚本
|
||||
-- ============================================
|
||||
|
||||
-- 1. 创建火箭配置表
|
||||
CREATE TABLE IF NOT EXISTS `rocket_config` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`level` TINYINT UNSIGNED NOT NULL COMMENT '火箭等级 1/2/3',
|
||||
`max_energy` BIGINT UNSIGNED NOT NULL COMMENT '最大能量值',
|
||||
`reward_config` JSON DEFAULT NULL COMMENT '奖励配置(JSON,预留)',
|
||||
`contributor_reward_rate` DECIMAL(5,2) DEFAULT NULL COMMENT '贡献者奖励比例%',
|
||||
`normal_reward_config` JSON DEFAULT NULL COMMENT '普通用户奖励配置(JSON,预留)',
|
||||
`status` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态 1:启用 0:禁用',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_level` (`level`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='火箭配置表';
|
||||
|
||||
-- 2. 插入初始配置数据
|
||||
INSERT INTO `rocket_config` (`level`, `max_energy`, `status`) VALUES
|
||||
(1, 150000, 1),
|
||||
(2, 500000, 1),
|
||||
(3, 1000000, 1)
|
||||
ON DUPLICATE KEY UPDATE `max_energy` = VALUES(`max_energy`);
|
||||
|
||||
-- 3. 创建奖励领取记录表
|
||||
CREATE TABLE IF NOT EXISTS `rocket_reward_claim_log` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`rocket_history_id` VARCHAR(32) NOT NULL COMMENT '火箭历史记录ID(MongoDB _id)',
|
||||
`room_id` BIGINT UNSIGNED NOT NULL COMMENT '房间ID',
|
||||
`user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
|
||||
`rocket_level` TINYINT UNSIGNED NOT NULL COMMENT '火箭等级',
|
||||
`is_contributor` TINYINT UNSIGNED NOT NULL COMMENT '是否贡献者 1:是 0:否',
|
||||
`contribution_energy` BIGINT UNSIGNED DEFAULT 0 COMMENT '贡献能量值',
|
||||
`contribution_rate` DECIMAL(8,4) DEFAULT 0.0000 COMMENT '贡献率%',
|
||||
`reward_type` VARCHAR(32) NOT NULL COMMENT '奖励类型 GOLD/DIAMOND/PROP',
|
||||
`reward_item_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '奖励物品ID',
|
||||
`reward_amount` BIGINT UNSIGNED NOT NULL COMMENT '奖励数量',
|
||||
`wallet_biz_no` VARCHAR(64) DEFAULT NULL COMMENT '钱包业务单号',
|
||||
`claimed_at` DATETIME NOT NULL COMMENT '领取时间',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_rocket_user` (`rocket_history_id`, `user_id`),
|
||||
KEY `idx_room_id` (`room_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_claimed_at` (`claimed_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='火箭奖励领取记录表';
|
||||
82
rc-service/rc-service-other/docs/sql/rocket_mongo_init.js
Normal file
82
rc-service/rc-service-other/docs/sql/rocket_mongo_init.js
Normal file
@ -0,0 +1,82 @@
|
||||
// ============================================
|
||||
// 火箭系统MongoDB索引初始化脚本
|
||||
// 执行方式: mongosh < rocket_mongo_init.js
|
||||
// ============================================
|
||||
|
||||
// 切换到likei数据库 (根据实际数据库名修改)
|
||||
use likei
|
||||
|
||||
print("开始创建火箭系统MongoDB索引...");
|
||||
|
||||
// 1. room_rocket_status 集合索引
|
||||
print("1. 创建 room_rocket_status 索引...");
|
||||
|
||||
// 唯一索引:房间ID+日期
|
||||
db.room_rocket_status.createIndex(
|
||||
{ "room_id": 1, "date": 1 },
|
||||
{ unique: true, name: "uk_room_date", background: true }
|
||||
);
|
||||
print(" ✓ 创建唯一索引 uk_room_date");
|
||||
|
||||
// 普通索引:状态
|
||||
db.room_rocket_status.createIndex(
|
||||
{ "status": 1 },
|
||||
{ name: "idx_status", background: true }
|
||||
);
|
||||
print(" ✓ 创建索引 idx_status");
|
||||
|
||||
// 普通索引:状态+过期时间 (用于定时任务清理)
|
||||
db.room_rocket_status.createIndex(
|
||||
{ "status": 1, "claim_expire_time": 1 },
|
||||
{ name: "idx_status_expire", background: true }
|
||||
);
|
||||
print(" ✓ 创建索引 idx_status_expire");
|
||||
|
||||
// TTL索引:30天自动过期
|
||||
db.room_rocket_status.createIndex(
|
||||
{ "updated_at": 1 },
|
||||
{ expireAfterSeconds: 2592000, name: "ttl_30days", background: true }
|
||||
);
|
||||
print(" ✓ 创建TTL索引 ttl_30days (30天过期)");
|
||||
|
||||
// 2. rocket_launch_history 集合索引
|
||||
print("2. 创建 rocket_launch_history 索引...");
|
||||
|
||||
// 普通索引:房间ID+发射时间 (倒序)
|
||||
db.rocket_launch_history.createIndex(
|
||||
{ "room_id": 1, "launch_time": -1 },
|
||||
{ name: "idx_room_launch_time", background: true }
|
||||
);
|
||||
print(" ✓ 创建索引 idx_room_launch_time");
|
||||
|
||||
// 普通索引:日期
|
||||
db.rocket_launch_history.createIndex(
|
||||
{ "date": 1 },
|
||||
{ name: "idx_date", background: true }
|
||||
);
|
||||
print(" ✓ 创建索引 idx_date");
|
||||
|
||||
// 普通索引:等级
|
||||
db.rocket_launch_history.createIndex(
|
||||
{ "level": 1 },
|
||||
{ name: "idx_level", background: true }
|
||||
);
|
||||
print(" ✓ 创建索引 idx_level");
|
||||
|
||||
// 普通索引:发射时间 (用于时间范围查询)
|
||||
db.rocket_launch_history.createIndex(
|
||||
{ "launch_time": -1 },
|
||||
{ name: "idx_launch_time", background: true }
|
||||
);
|
||||
print(" ✓ 创建索引 idx_launch_time");
|
||||
|
||||
print("\n索引创建完成!\n");
|
||||
|
||||
// 验证索引
|
||||
print("验证 room_rocket_status 索引:");
|
||||
printjson(db.room_rocket_status.getIndexes());
|
||||
|
||||
print("\n验证 rocket_launch_history 索引:");
|
||||
printjson(db.rocket_launch_history.getIndexes());
|
||||
|
||||
print("\n火箭系统MongoDB初始化完成!");
|
||||
@ -1,7 +1,12 @@
|
||||
package com.red.circle.other.app.command.rocket;
|
||||
|
||||
import com.red.circle.other.app.convertor.RocketConvertor;
|
||||
import com.red.circle.other.app.dto.clientobject.RocketStatusCO;
|
||||
import com.red.circle.other.app.manager.RocketImPushManager;
|
||||
import com.red.circle.other.app.util.DistributedLockUtil;
|
||||
import com.red.circle.other.domain.gateway.RocketHistoryGateway;
|
||||
import com.red.circle.other.domain.gateway.RocketStatusGateway;
|
||||
import com.red.circle.other.domain.rocket.RocketHistory;
|
||||
import com.red.circle.other.domain.rocket.RocketStatus;
|
||||
import com.red.circle.other.domain.rocket.RocketStatusEnum;
|
||||
import com.red.circle.other.infra.database.cache.key.RocketKeys;
|
||||
@ -23,7 +28,10 @@ import java.time.LocalDate;
|
||||
public class RocketLaunchCmdExe {
|
||||
|
||||
private final RocketStatusGateway rocketStatusGateway;
|
||||
private final RocketHistoryGateway rocketHistoryGateway;
|
||||
private final DistributedLockUtil distributedLockUtil;
|
||||
private final RocketImPushManager rocketImPushManager;
|
||||
private final RocketConvertor rocketConvertor;
|
||||
|
||||
/**
|
||||
* 执行火箭发射
|
||||
@ -74,14 +82,28 @@ public class RocketLaunchCmdExe {
|
||||
// 6. 保存状态
|
||||
rocketStatusGateway.save(rocketStatus);
|
||||
|
||||
// 7. 保存历史记录
|
||||
try {
|
||||
RocketHistory history = RocketHistory.fromRocketStatus(rocketStatus);
|
||||
String historyId = rocketHistoryGateway.save(history);
|
||||
log.info("保存火箭历史记录成功: historyId={}, roomId={}", historyId, roomId);
|
||||
} catch (Exception e) {
|
||||
log.error("保存火箭历史记录失败: roomId={}", roomId, e);
|
||||
}
|
||||
|
||||
// 8. 推送发射动画消息
|
||||
try {
|
||||
RocketStatusCO statusCO = rocketConvertor.toStatusCO(rocketStatus);
|
||||
rocketImPushManager.pushRocketLaunch(roomId, statusCO);
|
||||
} catch (Exception e) {
|
||||
log.error("推送火箭发射消息失败: roomId={}", roomId, e);
|
||||
}
|
||||
|
||||
log.info("火箭发射成功, roomId={}, level={}, finalEnergy={}, contributors={}, launchTime={}",
|
||||
roomId,
|
||||
rocketStatus.getLevel().getLevel(),
|
||||
rocketStatus.getCurrentEnergy(),
|
||||
rocketStatus.getContributors() != null ? rocketStatus.getContributors().size() : 0,
|
||||
rocketStatus.getLaunchTime());
|
||||
|
||||
// TODO: 7. 推送发射动画 (WebSocket)
|
||||
// TODO: 8. 保存历史记录
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,13 @@ package com.red.circle.other.app.command.rocket;
|
||||
|
||||
import com.red.circle.other.app.dto.clientobject.RocketRewardCO;
|
||||
import com.red.circle.other.app.dto.cmd.RocketRewardClaimCmd;
|
||||
import com.red.circle.other.app.manager.RocketImPushManager;
|
||||
import com.red.circle.other.app.util.DistributedLockUtil;
|
||||
import com.red.circle.other.domain.gateway.RocketHistoryGateway;
|
||||
import com.red.circle.other.domain.gateway.RocketRewardLogGateway;
|
||||
import com.red.circle.other.domain.gateway.RocketStatusGateway;
|
||||
import com.red.circle.other.domain.rocket.RocketContributor;
|
||||
import com.red.circle.other.domain.rocket.RocketRewardLog;
|
||||
import com.red.circle.other.domain.rocket.RocketStatus;
|
||||
import com.red.circle.other.infra.database.cache.key.RocketKeys;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -12,6 +16,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 火箭奖励领取命令执行器
|
||||
@ -25,8 +30,13 @@ import java.time.LocalDate;
|
||||
public class RocketRewardClaimCmdExe {
|
||||
|
||||
private final RocketStatusGateway rocketStatusGateway;
|
||||
private final RocketRewardLogGateway rocketRewardLogGateway;
|
||||
private final RocketHistoryGateway rocketHistoryGateway;
|
||||
private final DistributedLockUtil distributedLockUtil;
|
||||
// TODO: 后续需要注入 WalletGoldClient 调用钱包服务
|
||||
private final RocketImPushManager rocketImPushManager;
|
||||
|
||||
// TODO: 注入钱包服务Feign Client
|
||||
// private final WalletGoldClient walletGoldClient;
|
||||
|
||||
/**
|
||||
* 执行奖励领取
|
||||
@ -60,46 +70,67 @@ public class RocketRewardClaimCmdExe {
|
||||
throw new RuntimeException("当前状态不可领取奖励");
|
||||
}
|
||||
|
||||
// 3. 检查是否已领取 (TODO: 需要查询MySQL防重)
|
||||
// boolean hasClaimed = checkHasClaimed(cmd.getRoomId(), cmd.getUserId(), rocketStatus.getId());
|
||||
// if (hasClaimed) {
|
||||
// throw new RuntimeException("您已经领取过奖励了");
|
||||
// }
|
||||
// 3. 检查是否已领取 (MySQL防重)
|
||||
boolean hasClaimed = rocketRewardLogGateway.existsByRocketAndUser(
|
||||
cmd.getRocketHistoryId(), cmd.getUserId());
|
||||
if (hasClaimed) {
|
||||
throw new RuntimeException("您已经领取过奖励了");
|
||||
}
|
||||
|
||||
// 4. 判断是否为贡献者
|
||||
RocketContributor contributor = findContributor(rocketStatus, cmd.getUserId());
|
||||
boolean isContributor = contributor != null;
|
||||
|
||||
// 5. 计算奖励 (TODO: 奖励配置后续补充)
|
||||
// 5. 计算奖励 (TODO: 后续根据配置计算)
|
||||
Long rewardAmount = calculateReward(isContributor, contributor, rocketStatus);
|
||||
|
||||
RocketRewardCO rewardCO = new RocketRewardCO();
|
||||
rewardCO.setIsContributor(isContributor);
|
||||
rewardCO.setRewardType("GOLD");
|
||||
rewardCO.setRewardAmount(rewardAmount);
|
||||
|
||||
if (isContributor) {
|
||||
// 贡献者奖励
|
||||
rewardCO.setContributionEnergy(contributor.getEnergy());
|
||||
rewardCO.setContributionRate(contributor.getContributionRate());
|
||||
rewardCO.setRewardType("GOLD");
|
||||
rewardCO.setRewardAmount(1000L); // TODO: 根据配置计算
|
||||
rewardCO.setMessage("恭喜您获得贡献者奖励!");
|
||||
} else {
|
||||
// 普通用户奖励
|
||||
rewardCO.setRewardType("GOLD");
|
||||
rewardCO.setRewardAmount(100L); // TODO: 根据配置计算
|
||||
rewardCO.setMessage("恭喜您获得参与奖励!");
|
||||
}
|
||||
|
||||
// 6. 发放奖励 (TODO: 调用钱包服务)
|
||||
// String bizNo = "ROCKET_" + rocketStatus.getId() + "_" + cmd.getUserId();
|
||||
// walletGoldClient.income(...);
|
||||
// 6. 发放奖励 (调用钱包服务)
|
||||
String walletBizNo = RocketRewardLog.buildBizNo(cmd.getRocketHistoryId(), cmd.getUserId());
|
||||
try {
|
||||
sendRewardToWallet(cmd.getUserId(), rewardAmount, walletBizNo);
|
||||
} catch (Exception e) {
|
||||
log.error("调用钱包服务发放奖励失败: userId={}, amount={}", cmd.getUserId(), rewardAmount, e);
|
||||
throw new RuntimeException("奖励发放失败,请稍后重试");
|
||||
}
|
||||
|
||||
// 7. 记录领取日志 (TODO: 保存到MySQL)
|
||||
// 7. 记录领取日志 (MySQL)
|
||||
saveRewardLog(cmd, rocketStatus, isContributor, contributor, rewardAmount, walletBizNo);
|
||||
|
||||
// 8. 更新领取人数
|
||||
rocketStatus.incrementClaimCount();
|
||||
rocketStatusGateway.save(rocketStatus);
|
||||
|
||||
// 9. 更新历史记录的领取统计
|
||||
try {
|
||||
rocketHistoryGateway.updateClaimStats(cmd.getRocketHistoryId(), 1, rewardAmount);
|
||||
} catch (Exception e) {
|
||||
log.error("更新历史记录领取统计失败: historyId={}", cmd.getRocketHistoryId(), e);
|
||||
}
|
||||
|
||||
// 10. 推送领取成功消息
|
||||
try {
|
||||
// TODO: 获取用户名称
|
||||
String userName = "用户" + cmd.getUserId();
|
||||
rocketImPushManager.pushRewardClaimed(cmd.getRoomId(), cmd.getUserId(), userName, rewardAmount);
|
||||
} catch (Exception e) {
|
||||
log.error("推送奖励领取消息失败: roomId={}, userId={}", cmd.getRoomId(), cmd.getUserId(), e);
|
||||
}
|
||||
|
||||
log.info("火箭奖励领取成功, roomId={}, userId={}, isContributor={}, rewardAmount={}",
|
||||
cmd.getRoomId(), cmd.getUserId(), isContributor, rewardCO.getRewardAmount());
|
||||
cmd.getRoomId(), cmd.getUserId(), isContributor, rewardAmount);
|
||||
|
||||
return rewardCO;
|
||||
}
|
||||
@ -116,4 +147,73 @@ public class RocketRewardClaimCmdExe {
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算奖励金额
|
||||
* TODO: 后续根据配置表计算
|
||||
*/
|
||||
private Long calculateReward(boolean isContributor, RocketContributor contributor, RocketStatus rocketStatus) {
|
||||
if (isContributor) {
|
||||
// 贡献者奖励 = 基础奖励 + 按贡献率分配的额外奖励
|
||||
// 目前固定返回1000,后续根据配置计算
|
||||
return 1000L;
|
||||
} else {
|
||||
// 普通用户固定奖励
|
||||
return 100L;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用钱包服务发放奖励
|
||||
* TODO: 集成wallet-inner-api
|
||||
*/
|
||||
private void sendRewardToWallet(Long userId, Long amount, String bizNo) {
|
||||
// 示例代码,需要引入实际的Feign Client
|
||||
/*
|
||||
WalletReceiptReqDTO req = new WalletReceiptReqDTO();
|
||||
req.setUserId(userId);
|
||||
req.setAmount(PennyAmount.of(amount)); // 金币
|
||||
req.setBizType(WalletBizType.ROCKET_REWARD);
|
||||
req.setBizNo(bizNo);
|
||||
req.setRemark("火箭奖励");
|
||||
|
||||
ResultResponse<Void> response = walletGoldClient.income(req);
|
||||
if (!response.isSuccess()) {
|
||||
throw new RuntimeException("钱包服务调用失败: " + response.getMessage());
|
||||
}
|
||||
*/
|
||||
|
||||
log.info("TODO: 调用钱包服务发放奖励, userId={}, amount={}, bizNo={}", userId, amount, bizNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存领取记录
|
||||
*/
|
||||
private void saveRewardLog(RocketRewardClaimCmd cmd, RocketStatus rocketStatus,
|
||||
boolean isContributor, RocketContributor contributor,
|
||||
Long rewardAmount, String walletBizNo) {
|
||||
RocketRewardLog log = new RocketRewardLog();
|
||||
log.setRocketHistoryId(cmd.getRocketHistoryId());
|
||||
log.setRoomId(cmd.getRoomId());
|
||||
log.setUserId(cmd.getUserId());
|
||||
log.setRocketLevel(rocketStatus.getLevel().getLevel());
|
||||
log.setIsContributor(isContributor ? 1 : 0);
|
||||
|
||||
if (isContributor && contributor != null) {
|
||||
log.setContributionEnergy(contributor.getEnergy());
|
||||
log.setContributionRate(contributor.getContributionRate());
|
||||
} else {
|
||||
log.setContributionEnergy(0L);
|
||||
log.setContributionRate(null);
|
||||
}
|
||||
|
||||
log.setRewardType("GOLD");
|
||||
log.setRewardItemId(null);
|
||||
log.setRewardAmount(rewardAmount);
|
||||
log.setWalletBizNo(walletBizNo);
|
||||
log.setClaimedAt(LocalDateTime.now());
|
||||
log.setCreatedAt(LocalDateTime.now());
|
||||
|
||||
rocketRewardLogGateway.save(log);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
package com.red.circle.other.app.listener;
|
||||
|
||||
import com.red.circle.other.app.dto.cmd.RocketEnergyAddCmd;
|
||||
import com.red.circle.other.app.service.RocketService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 礼物送出事件监听器 - 触发火箭能量增加
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GiftSendRocketListener {
|
||||
|
||||
private final RocketService rocketService;
|
||||
|
||||
/**
|
||||
* 监听礼物送出事件
|
||||
* 注意:需要项目中实际的GiftSendEvent类,这里使用占位符
|
||||
*/
|
||||
@Async("rocketExecutor")
|
||||
@EventListener
|
||||
public void onGiftSend(Object event) {
|
||||
// TODO: 替换为实际的GiftSendEvent类型
|
||||
// 示例代码,需要根据实际事件结构调整
|
||||
|
||||
/*
|
||||
try {
|
||||
// 1. 从事件中提取数据
|
||||
Long roomId = event.getRoomId();
|
||||
Long userId = event.getUserId();
|
||||
Long giftGoldValue = event.getGiftGoldValue();
|
||||
Boolean isLucky = event.getIsLuckyGift();
|
||||
String giftOrderId = event.getGiftOrderId();
|
||||
|
||||
// 2. 构建命令
|
||||
RocketEnergyAddCmd cmd = new RocketEnergyAddCmd();
|
||||
cmd.setRoomId(roomId);
|
||||
cmd.setUserId(userId);
|
||||
cmd.setGiftGoldValue(giftGoldValue);
|
||||
cmd.setIsLucky(isLucky != null && isLucky);
|
||||
cmd.setBizNo("GIFT_" + giftOrderId);
|
||||
|
||||
// 3. 执行能量增加
|
||||
rocketService.addEnergy(cmd);
|
||||
|
||||
log.info("礼物事件触发火箭能量增加成功: roomId={}, userId={}, energy={}",
|
||||
roomId, userId, giftGoldValue);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("礼物事件触发火箭能量增加失败", e);
|
||||
}
|
||||
*/
|
||||
|
||||
log.warn("GiftSendRocketListener: 需要接入实际的礼物送出事件");
|
||||
}
|
||||
|
||||
/**
|
||||
* 说明:
|
||||
* 1. 需要在项目中找到实际的礼物送出事件类(可能在live-service或other-service中)
|
||||
* 2. 替换方法参数中的 Object 为实际的事件类型
|
||||
* 3. 根据实际事件结构提取 roomId、userId、giftGoldValue 等字段
|
||||
* 4. 确保事件中包含 isLuckyGift 字段或通过其他方式判断是否幸运礼物
|
||||
*/
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
package com.red.circle.other.app.manager;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.red.circle.other.app.dto.clientobject.RocketStatusCO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 火箭IM消息推送管理器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RocketImPushManager {
|
||||
|
||||
// TODO: 注入实际的IM推送服务
|
||||
// private final ImPushService imPushService;
|
||||
|
||||
/**
|
||||
* 推送能量更新消息
|
||||
*/
|
||||
public void pushEnergyUpdate(Long roomId, RocketStatusCO status) {
|
||||
try {
|
||||
// 构建消息
|
||||
ImMessage message = buildEnergyUpdateMessage(status);
|
||||
|
||||
// TODO: 调用实际的IM推送服务
|
||||
// imPushService.pushToRoom(roomId, message);
|
||||
|
||||
log.info("推送火箭能量更新消息成功: roomId={}, level={}, energy={}/{}",
|
||||
roomId, status.getLevel(), status.getCurrentEnergy(), status.getMaxEnergy());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("推送火箭能量更新消息失败: roomId={}", roomId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送火箭发射消息
|
||||
*/
|
||||
public void pushRocketLaunch(Long roomId, RocketStatusCO status) {
|
||||
try {
|
||||
// 构建消息
|
||||
ImMessage message = buildLaunchMessage(status);
|
||||
|
||||
// TODO: 调用实际的IM推送服务
|
||||
// imPushService.pushToRoom(roomId, message);
|
||||
|
||||
log.info("推送火箭发射消息成功: roomId={}, level={}", roomId, status.getLevel());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("推送火箭发射消息失败: roomId={}", roomId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送奖励领取成功消息
|
||||
*/
|
||||
public void pushRewardClaimed(Long roomId, Long userId, String userName, Long rewardAmount) {
|
||||
try {
|
||||
// 构建消息
|
||||
ImMessage message = buildRewardClaimedMessage(userId, userName, rewardAmount);
|
||||
|
||||
// TODO: 调用实际的IM推送服务
|
||||
// imPushService.pushToRoom(roomId, message);
|
||||
|
||||
log.info("推送奖励领取消息成功: roomId={}, userId={}, amount={}", roomId, userId, rewardAmount);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("推送奖励领取消息失败: roomId={}, userId={}", roomId, userId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送火箭重置消息
|
||||
*/
|
||||
public void pushRocketReset(Long roomId) {
|
||||
try {
|
||||
// 构建消息
|
||||
ImMessage message = buildResetMessage();
|
||||
|
||||
// TODO: 调用实际的IM推送服务
|
||||
// imPushService.pushToRoom(roomId, message);
|
||||
|
||||
log.info("推送火箭重置消息成功: roomId={}", roomId);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("推送火箭重置消息失败: roomId={}", roomId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建能量更新消息
|
||||
*/
|
||||
private ImMessage buildEnergyUpdateMessage(RocketStatusCO status) {
|
||||
ImMessage message = new ImMessage();
|
||||
message.setType("ROCKET_ENERGY_UPDATE");
|
||||
message.setData(JSON.toJSONString(status));
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建发射消息
|
||||
*/
|
||||
private ImMessage buildLaunchMessage(RocketStatusCO status) {
|
||||
ImMessage message = new ImMessage();
|
||||
message.setType("ROCKET_LAUNCH");
|
||||
message.setData(JSON.toJSONString(status));
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建奖励领取消息
|
||||
*/
|
||||
private ImMessage buildRewardClaimedMessage(Long userId, String userName, Long rewardAmount) {
|
||||
RewardClaimedData data = new RewardClaimedData();
|
||||
data.setUserId(userId);
|
||||
data.setUserName(userName);
|
||||
data.setRewardAmount(rewardAmount);
|
||||
|
||||
ImMessage message = new ImMessage();
|
||||
message.setType("ROCKET_REWARD_CLAIMED");
|
||||
message.setData(JSON.toJSONString(data));
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建重置消息
|
||||
*/
|
||||
private ImMessage buildResetMessage() {
|
||||
ImMessage message = new ImMessage();
|
||||
message.setType("ROCKET_RESET");
|
||||
message.setData("{}");
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* IM消息对象(示例)
|
||||
* TODO: 替换为实际的IM消息类
|
||||
*/
|
||||
private static class ImMessage {
|
||||
private String type;
|
||||
private String data;
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 奖励领取数据
|
||||
*/
|
||||
private static class RewardClaimedData {
|
||||
private Long userId;
|
||||
private String userName;
|
||||
private Long rewardAmount;
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public void setRewardAmount(Long rewardAmount) {
|
||||
this.rewardAmount = rewardAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.red.circle.other.domain.gateway;
|
||||
|
||||
import com.red.circle.other.domain.rocket.RocketConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭配置网关
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
public interface RocketConfigGateway {
|
||||
|
||||
/**
|
||||
* 根据等级查询配置
|
||||
*/
|
||||
RocketConfig findByLevel(Integer level);
|
||||
|
||||
/**
|
||||
* 查询所有配置
|
||||
*/
|
||||
List<RocketConfig> findAll();
|
||||
|
||||
/**
|
||||
* 查询启用的配置
|
||||
*/
|
||||
List<RocketConfig> findAllEnabled();
|
||||
|
||||
/**
|
||||
* 保存配置
|
||||
*/
|
||||
void save(RocketConfig config);
|
||||
|
||||
/**
|
||||
* 更新配置
|
||||
*/
|
||||
void update(RocketConfig config);
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.red.circle.other.domain.gateway;
|
||||
|
||||
import com.red.circle.other.domain.rocket.RocketHistory;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭历史网关
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
public interface RocketHistoryGateway {
|
||||
|
||||
/**
|
||||
* 保存历史记录
|
||||
*/
|
||||
String save(RocketHistory history);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
RocketHistory findById(String id);
|
||||
|
||||
/**
|
||||
* 根据房间ID查询历史
|
||||
*/
|
||||
List<RocketHistory> findByRoomId(Long roomId);
|
||||
|
||||
/**
|
||||
* 根据房间ID和日期查询
|
||||
*/
|
||||
List<RocketHistory> findByRoomIdAndDate(Long roomId, String date);
|
||||
|
||||
/**
|
||||
* 根据房间ID和时间范围查询
|
||||
*/
|
||||
List<RocketHistory> findByRoomIdAndTimeRange(Long roomId, LocalDateTime startTime, LocalDateTime endTime);
|
||||
|
||||
/**
|
||||
* 更新领取统计
|
||||
*/
|
||||
void updateClaimStats(String id, int claimedCount, long rewardSent);
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.red.circle.other.domain.gateway;
|
||||
|
||||
import com.red.circle.other.domain.rocket.RocketRewardLog;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭奖励领取记录网关
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
public interface RocketRewardLogGateway {
|
||||
|
||||
/**
|
||||
* 保存领取记录
|
||||
*/
|
||||
void save(RocketRewardLog log);
|
||||
|
||||
/**
|
||||
* 检查是否已领取
|
||||
*/
|
||||
boolean existsByRocketAndUser(String rocketHistoryId, Long userId);
|
||||
|
||||
/**
|
||||
* 根据火箭历史ID查询所有领取记录
|
||||
*/
|
||||
List<RocketRewardLog> findByRocketHistoryId(String rocketHistoryId);
|
||||
|
||||
/**
|
||||
* 根据房间ID和用户ID查询
|
||||
*/
|
||||
List<RocketRewardLog> findByRoomIdAndUserId(Long roomId, Long userId);
|
||||
|
||||
/**
|
||||
* 统计某次发射的领取人数
|
||||
*/
|
||||
int countByRocketHistoryId(String rocketHistoryId);
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
package com.red.circle.other.domain.rocket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 火箭配置领域对象
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Data
|
||||
public class RocketConfig {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 火箭等级
|
||||
*/
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 最大能量值
|
||||
*/
|
||||
private Long maxEnergy;
|
||||
|
||||
/**
|
||||
* 奖励配置(JSON预留)
|
||||
*/
|
||||
private String rewardConfig;
|
||||
|
||||
/**
|
||||
* 贡献者奖励比例%
|
||||
*/
|
||||
private BigDecimal contributorRewardRate;
|
||||
|
||||
/**
|
||||
* 普通用户奖励配置(JSON预留)
|
||||
*/
|
||||
private String normalRewardConfig;
|
||||
|
||||
/**
|
||||
* 状态 1:启用 0:禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return Integer.valueOf(1).equals(this.status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取等级名称
|
||||
*/
|
||||
public String getLevelName() {
|
||||
if (level == null) {
|
||||
return "";
|
||||
}
|
||||
return switch (level) {
|
||||
case 1 -> "一级火箭";
|
||||
case 2 -> "二级火箭";
|
||||
case 3 -> "三级火箭";
|
||||
default -> "未知等级";
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package com.red.circle.other.domain.rocket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭历史领域对象
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Data
|
||||
public class RocketHistory {
|
||||
|
||||
private String id;
|
||||
private Long roomId;
|
||||
private String date;
|
||||
private Integer level;
|
||||
private Long finalEnergy;
|
||||
private Long overEnergy;
|
||||
private List<HistoryContributor> contributors;
|
||||
private Integer totalContributors;
|
||||
private RewardPool rewardPool;
|
||||
private ClaimStats claimStats;
|
||||
private LocalDateTime launchTime;
|
||||
private LocalDateTime claimStartTime;
|
||||
private LocalDateTime claimEndTime;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Data
|
||||
public static class HistoryContributor {
|
||||
private Long userId;
|
||||
private String userName;
|
||||
private String userAvatar;
|
||||
private Long energy;
|
||||
private BigDecimal contributionRate;
|
||||
private Integer rank;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class RewardPool {
|
||||
private Long totalGold;
|
||||
private Long contributorGold;
|
||||
private Long normalGold;
|
||||
|
||||
public static RewardPool empty() {
|
||||
RewardPool pool = new RewardPool();
|
||||
pool.setTotalGold(0L);
|
||||
pool.setContributorGold(0L);
|
||||
pool.setNormalGold(0L);
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ClaimStats {
|
||||
private Integer totalClaimed;
|
||||
private Integer contributorClaimed;
|
||||
private Integer normalClaimed;
|
||||
private Long totalRewardSent;
|
||||
|
||||
public static ClaimStats init() {
|
||||
ClaimStats stats = new ClaimStats();
|
||||
stats.setTotalClaimed(0);
|
||||
stats.setContributorClaimed(0);
|
||||
stats.setNormalClaimed(0);
|
||||
stats.setTotalRewardSent(0L);
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从RocketStatus创建历史记录
|
||||
*/
|
||||
public static RocketHistory fromRocketStatus(RocketStatus status) {
|
||||
RocketHistory history = new RocketHistory();
|
||||
history.setRoomId(status.getRoomId());
|
||||
history.setDate(status.getDate());
|
||||
history.setLevel(status.getLevel().getLevel());
|
||||
history.setFinalEnergy(status.getCurrentEnergy());
|
||||
|
||||
// 计算超出能量
|
||||
Long overEnergy = status.getCurrentEnergy() - status.getLevel().getMaxEnergy();
|
||||
history.setOverEnergy(Math.max(overEnergy, 0L));
|
||||
|
||||
// 转换贡献者
|
||||
List<HistoryContributor> historyContributors = new ArrayList<>();
|
||||
for (int i = 0; i < Math.min(status.getContributors().size(), 100); i++) {
|
||||
RocketContributor contributor = status.getContributors().get(i);
|
||||
HistoryContributor hc = new HistoryContributor();
|
||||
hc.setUserId(contributor.getUserId());
|
||||
hc.setUserName(contributor.getUserName());
|
||||
hc.setUserAvatar(contributor.getUserAvatar());
|
||||
hc.setEnergy(contributor.getEnergy());
|
||||
hc.setContributionRate(contributor.getContributionRate());
|
||||
hc.setRank(i + 1);
|
||||
historyContributors.add(hc);
|
||||
}
|
||||
history.setContributors(historyContributors);
|
||||
history.setTotalContributors(status.getContributors().size());
|
||||
|
||||
// 设置奖励池 (预留)
|
||||
history.setRewardPool(RewardPool.empty());
|
||||
|
||||
// 初始化领取统计
|
||||
history.setClaimStats(ClaimStats.init());
|
||||
|
||||
// 设置时间
|
||||
history.setLaunchTime(status.getLaunchTime());
|
||||
history.setClaimStartTime(status.getLaunchTime());
|
||||
history.setClaimEndTime(status.getClaimExpireTime());
|
||||
history.setCreatedAt(LocalDateTime.now());
|
||||
history.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
return history;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
package com.red.circle.other.domain.rocket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 火箭奖励领取记录领域对象
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Data
|
||||
public class RocketRewardLog {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 火箭历史记录ID (MongoDB _id)
|
||||
*/
|
||||
private String rocketHistoryId;
|
||||
|
||||
/**
|
||||
* 房间ID
|
||||
*/
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 火箭等级
|
||||
*/
|
||||
private Integer rocketLevel;
|
||||
|
||||
/**
|
||||
* 是否贡献者 1:是 0:否
|
||||
*/
|
||||
private Integer isContributor;
|
||||
|
||||
/**
|
||||
* 贡献能量值
|
||||
*/
|
||||
private Long contributionEnergy;
|
||||
|
||||
/**
|
||||
* 贡献率%
|
||||
*/
|
||||
private BigDecimal contributionRate;
|
||||
|
||||
/**
|
||||
* 奖励类型 GOLD/DIAMOND/PROP
|
||||
*/
|
||||
private String rewardType;
|
||||
|
||||
/**
|
||||
* 奖励物品ID
|
||||
*/
|
||||
private Long rewardItemId;
|
||||
|
||||
/**
|
||||
* 奖励数量
|
||||
*/
|
||||
private Long rewardAmount;
|
||||
|
||||
/**
|
||||
* 钱包业务单号
|
||||
*/
|
||||
private String walletBizNo;
|
||||
|
||||
/**
|
||||
* 领取时间
|
||||
*/
|
||||
private LocalDateTime claimedAt;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 判断是否为贡献者
|
||||
*/
|
||||
public boolean isContributorUser() {
|
||||
return Integer.valueOf(1).equals(this.isContributor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建业务单号
|
||||
*/
|
||||
public static String buildBizNo(String rocketHistoryId, Long userId) {
|
||||
return "ROCKET_" + rocketHistoryId + "_" + userId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.red.circle.other.infra.convertor;
|
||||
|
||||
import com.red.circle.other.domain.rocket.RocketConfig;
|
||||
import com.red.circle.other.infra.database.rds.entity.RocketConfigEntity;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 火箭配置转换器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface RocketConfigConvertor {
|
||||
|
||||
RocketConfigConvertor INSTANCE = Mappers.getMapper(RocketConfigConvertor.class);
|
||||
|
||||
/**
|
||||
* Entity转Domain
|
||||
*/
|
||||
RocketConfig toRocketConfig(RocketConfigEntity entity);
|
||||
|
||||
/**
|
||||
* Domain转Entity
|
||||
*/
|
||||
@Mapping(target = "createdAt", ignore = true)
|
||||
@Mapping(target = "updatedAt", ignore = true)
|
||||
RocketConfigEntity toEntity(RocketConfig config);
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.red.circle.other.infra.convertor;
|
||||
|
||||
import com.red.circle.other.domain.rocket.RocketHistory;
|
||||
import com.red.circle.other.infra.database.mongo.document.RocketHistoryDocument;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 火箭历史转换器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface RocketHistoryConvertor {
|
||||
|
||||
RocketHistoryConvertor INSTANCE = Mappers.getMapper(RocketHistoryConvertor.class);
|
||||
|
||||
/**
|
||||
* Document转Domain
|
||||
*/
|
||||
RocketHistory toDomain(RocketHistoryDocument document);
|
||||
|
||||
/**
|
||||
* Domain转Document
|
||||
*/
|
||||
RocketHistoryDocument toDocument(RocketHistory history);
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.red.circle.other.infra.convertor;
|
||||
|
||||
import com.red.circle.other.domain.rocket.RocketRewardLog;
|
||||
import com.red.circle.other.infra.database.rds.entity.RocketRewardClaimLogEntity;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 火箭奖励领取记录转换器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface RocketRewardLogConvertor {
|
||||
|
||||
RocketRewardLogConvertor INSTANCE = Mappers.getMapper(RocketRewardLogConvertor.class);
|
||||
|
||||
/**
|
||||
* Entity转Domain
|
||||
*/
|
||||
RocketRewardLog toDomain(RocketRewardClaimLogEntity entity);
|
||||
|
||||
/**
|
||||
* Domain转Entity
|
||||
*/
|
||||
@Mapping(target = "createdAt", ignore = true)
|
||||
RocketRewardClaimLogEntity toEntity(RocketRewardLog log);
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.red.circle.other.infra.database.mongo.document;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭发射历史文档
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Data
|
||||
@Document(collection = "rocket_launch_history")
|
||||
public class RocketHistoryDocument {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@Field("room_id")
|
||||
private Long roomId;
|
||||
|
||||
@Field("date")
|
||||
private String date;
|
||||
|
||||
@Field("level")
|
||||
private Integer level;
|
||||
|
||||
@Field("final_energy")
|
||||
private Long finalEnergy;
|
||||
|
||||
@Field("over_energy")
|
||||
private Long overEnergy;
|
||||
|
||||
@Field("contributors")
|
||||
private List<HistoryContributor> contributors;
|
||||
|
||||
@Field("total_contributors")
|
||||
private Integer totalContributors;
|
||||
|
||||
@Field("reward_pool")
|
||||
private RewardPool rewardPool;
|
||||
|
||||
@Field("claim_stats")
|
||||
private ClaimStats claimStats;
|
||||
|
||||
@Field("launch_time")
|
||||
private LocalDateTime launchTime;
|
||||
|
||||
@Field("claim_start_time")
|
||||
private LocalDateTime claimStartTime;
|
||||
|
||||
@Field("claim_end_time")
|
||||
private LocalDateTime claimEndTime;
|
||||
|
||||
@Field("created_at")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Field("updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Data
|
||||
public static class HistoryContributor {
|
||||
@Field("user_id")
|
||||
private Long userId;
|
||||
|
||||
@Field("user_name")
|
||||
private String userName;
|
||||
|
||||
@Field("user_avatar")
|
||||
private String userAvatar;
|
||||
|
||||
@Field("energy")
|
||||
private Long energy;
|
||||
|
||||
@Field("contribution_rate")
|
||||
private Double contributionRate;
|
||||
|
||||
@Field("rank")
|
||||
private Integer rank;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class RewardPool {
|
||||
@Field("total_gold")
|
||||
private Long totalGold;
|
||||
|
||||
@Field("contributor_gold")
|
||||
private Long contributorGold;
|
||||
|
||||
@Field("normal_gold")
|
||||
private Long normalGold;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ClaimStats {
|
||||
@Field("total_claimed")
|
||||
private Integer totalClaimed;
|
||||
|
||||
@Field("contributor_claimed")
|
||||
private Integer contributorClaimed;
|
||||
|
||||
@Field("normal_claimed")
|
||||
private Integer normalClaimed;
|
||||
|
||||
@Field("total_reward_sent")
|
||||
private Long totalRewardSent;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.red.circle.other.infra.database.mongo.repository;
|
||||
|
||||
import com.red.circle.other.infra.database.mongo.document.RocketHistoryDocument;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭历史Repository
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Repository
|
||||
public interface RocketHistoryRepository extends MongoRepository<RocketHistoryDocument, String> {
|
||||
|
||||
/**
|
||||
* 根据房间ID查询历史
|
||||
*/
|
||||
List<RocketHistoryDocument> findByRoomIdOrderByLaunchTimeDesc(Long roomId);
|
||||
|
||||
/**
|
||||
* 根据房间ID和日期查询
|
||||
*/
|
||||
List<RocketHistoryDocument> findByRoomIdAndDateOrderByLaunchTimeDesc(Long roomId, String date);
|
||||
|
||||
/**
|
||||
* 根据房间ID和时间范围查询
|
||||
*/
|
||||
List<RocketHistoryDocument> findByRoomIdAndLaunchTimeBetweenOrderByLaunchTimeDesc(
|
||||
Long roomId,
|
||||
LocalDateTime startTime,
|
||||
LocalDateTime endTime
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据等级查询
|
||||
*/
|
||||
List<RocketHistoryDocument> findByLevelOrderByLaunchTimeDesc(Integer level);
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.red.circle.other.infra.database.rds.dao;
|
||||
|
||||
import com.red.circle.other.infra.database.rds.entity.RocketConfigEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭配置Mapper
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Mapper
|
||||
public interface RocketConfigMapper {
|
||||
|
||||
/**
|
||||
* 根据等级查询
|
||||
*/
|
||||
RocketConfigEntity selectByLevel(@Param("level") Integer level);
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
List<RocketConfigEntity> selectAll();
|
||||
|
||||
/**
|
||||
* 查询启用的
|
||||
*/
|
||||
List<RocketConfigEntity> selectAllEnabled();
|
||||
|
||||
/**
|
||||
* 插入
|
||||
*/
|
||||
int insert(RocketConfigEntity entity);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*/
|
||||
int update(RocketConfigEntity entity);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
RocketConfigEntity selectById(@Param("id") Long id);
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.red.circle.other.infra.database.rds.dao;
|
||||
|
||||
import com.red.circle.other.infra.database.rds.entity.RocketRewardClaimLogEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 火箭奖励领取记录Mapper
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Mapper
|
||||
public interface RocketRewardClaimLogMapper {
|
||||
|
||||
/**
|
||||
* 插入
|
||||
*/
|
||||
int insert(RocketRewardClaimLogEntity entity);
|
||||
|
||||
/**
|
||||
* 检查是否已领取
|
||||
*/
|
||||
int countByRocketAndUser(@Param("rocketHistoryId") String rocketHistoryId,
|
||||
@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 根据火箭历史ID查询
|
||||
*/
|
||||
List<RocketRewardClaimLogEntity> selectByRocketHistoryId(@Param("rocketHistoryId") String rocketHistoryId);
|
||||
|
||||
/**
|
||||
* 根据房间ID和用户ID查询
|
||||
*/
|
||||
List<RocketRewardClaimLogEntity> selectByRoomIdAndUserId(@Param("roomId") Long roomId,
|
||||
@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 统计某次发射的领取人数
|
||||
*/
|
||||
int countByRocketHistoryId(@Param("rocketHistoryId") String rocketHistoryId);
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.red.circle.other.infra.database.rds.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 火箭配置实体
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Data
|
||||
@TableName("rocket_config")
|
||||
public class RocketConfigEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 火箭等级 1/2/3
|
||||
*/
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 最大能量值
|
||||
*/
|
||||
private Long maxEnergy;
|
||||
|
||||
/**
|
||||
* 奖励配置(JSON)
|
||||
*/
|
||||
private String rewardConfig;
|
||||
|
||||
/**
|
||||
* 贡献者奖励比例%
|
||||
*/
|
||||
private BigDecimal contributorRewardRate;
|
||||
|
||||
/**
|
||||
* 普通用户奖励配置(JSON)
|
||||
*/
|
||||
private String normalRewardConfig;
|
||||
|
||||
/**
|
||||
* 状态 1:启用 0:禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.red.circle.other.infra.database.rds.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 火箭奖励领取记录实体
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Data
|
||||
@TableName("rocket_reward_claim_log")
|
||||
public class RocketRewardClaimLogEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 火箭历史记录ID
|
||||
*/
|
||||
private String rocketHistoryId;
|
||||
|
||||
/**
|
||||
* 房间ID
|
||||
*/
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 火箭等级
|
||||
*/
|
||||
private Integer rocketLevel;
|
||||
|
||||
/**
|
||||
* 是否贡献者
|
||||
*/
|
||||
private Integer isContributor;
|
||||
|
||||
/**
|
||||
* 贡献能量值
|
||||
*/
|
||||
private Long contributionEnergy;
|
||||
|
||||
/**
|
||||
* 贡献率%
|
||||
*/
|
||||
private BigDecimal contributionRate;
|
||||
|
||||
/**
|
||||
* 奖励类型
|
||||
*/
|
||||
private String rewardType;
|
||||
|
||||
/**
|
||||
* 奖励物品ID
|
||||
*/
|
||||
private Long rewardItemId;
|
||||
|
||||
/**
|
||||
* 奖励数量
|
||||
*/
|
||||
private Long rewardAmount;
|
||||
|
||||
/**
|
||||
* 钱包业务单号
|
||||
*/
|
||||
private String walletBizNo;
|
||||
|
||||
/**
|
||||
* 领取时间
|
||||
*/
|
||||
private LocalDateTime claimedAt;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.red.circle.other.infra.gateway;
|
||||
|
||||
import com.red.circle.other.domain.gateway.RocketConfigGateway;
|
||||
import com.red.circle.other.domain.rocket.RocketConfig;
|
||||
import com.red.circle.other.infra.convertor.RocketConfigConvertor;
|
||||
import com.red.circle.other.infra.database.rds.dao.RocketConfigMapper;
|
||||
import com.red.circle.other.infra.database.rds.entity.RocketConfigEntity;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 火箭配置网关实现
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RocketConfigGatewayImpl implements RocketConfigGateway {
|
||||
|
||||
private final RocketConfigMapper rocketConfigMapper;
|
||||
private final RocketConfigConvertor rocketConfigConvertor;
|
||||
|
||||
@Override
|
||||
public RocketConfig findByLevel(Integer level) {
|
||||
RocketConfigEntity entity = rocketConfigMapper.selectByLevel(level);
|
||||
return rocketConfigConvertor.toRocketConfig(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RocketConfig> findAll() {
|
||||
List<RocketConfigEntity> entities = rocketConfigMapper.selectAll();
|
||||
return entities.stream()
|
||||
.map(rocketConfigConvertor::toRocketConfig)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RocketConfig> findAllEnabled() {
|
||||
List<RocketConfigEntity> entities = rocketConfigMapper.selectAllEnabled();
|
||||
return entities.stream()
|
||||
.map(rocketConfigConvertor::toRocketConfig)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(RocketConfig config) {
|
||||
RocketConfigEntity entity = rocketConfigConvertor.toEntity(config);
|
||||
rocketConfigMapper.insert(entity);
|
||||
config.setId(entity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(RocketConfig config) {
|
||||
RocketConfigEntity entity = rocketConfigConvertor.toEntity(config);
|
||||
rocketConfigMapper.update(entity);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.red.circle.other.infra.gateway;
|
||||
|
||||
import com.red.circle.other.domain.gateway.RocketHistoryGateway;
|
||||
import com.red.circle.other.domain.rocket.RocketHistory;
|
||||
import com.red.circle.other.infra.convertor.RocketHistoryConvertor;
|
||||
import com.red.circle.other.infra.database.mongo.document.RocketHistoryDocument;
|
||||
import com.red.circle.other.infra.database.mongo.repository.RocketHistoryRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 火箭历史网关实现
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RocketHistoryGatewayImpl implements RocketHistoryGateway {
|
||||
|
||||
private final RocketHistoryRepository rocketHistoryRepository;
|
||||
private final RocketHistoryConvertor rocketHistoryConvertor;
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
@Override
|
||||
public String save(RocketHistory history) {
|
||||
RocketHistoryDocument document = rocketHistoryConvertor.toDocument(history);
|
||||
document.setCreatedAt(LocalDateTime.now());
|
||||
document.setUpdatedAt(LocalDateTime.now());
|
||||
RocketHistoryDocument saved = rocketHistoryRepository.save(document);
|
||||
return saved.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RocketHistory findById(String id) {
|
||||
return rocketHistoryRepository.findById(id)
|
||||
.map(rocketHistoryConvertor::toDomain)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RocketHistory> findByRoomId(Long roomId) {
|
||||
List<RocketHistoryDocument> documents = rocketHistoryRepository.findByRoomIdOrderByLaunchTimeDesc(roomId);
|
||||
return documents.stream()
|
||||
.map(rocketHistoryConvertor::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RocketHistory> findByRoomIdAndDate(Long roomId, String date) {
|
||||
List<RocketHistoryDocument> documents =
|
||||
rocketHistoryRepository.findByRoomIdAndDateOrderByLaunchTimeDesc(roomId, date);
|
||||
return documents.stream()
|
||||
.map(rocketHistoryConvertor::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RocketHistory> findByRoomIdAndTimeRange(Long roomId, LocalDateTime startTime, LocalDateTime endTime) {
|
||||
List<RocketHistoryDocument> documents =
|
||||
rocketHistoryRepository.findByRoomIdAndLaunchTimeBetweenOrderByLaunchTimeDesc(
|
||||
roomId, startTime, endTime);
|
||||
return documents.stream()
|
||||
.map(rocketHistoryConvertor::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateClaimStats(String id, int claimedCount, long rewardSent) {
|
||||
Query query = new Query(Criteria.where("_id").is(id));
|
||||
Update update = new Update()
|
||||
.inc("claim_stats.total_claimed", 1)
|
||||
.inc("claim_stats.total_reward_sent", rewardSent)
|
||||
.set("updated_at", LocalDateTime.now());
|
||||
|
||||
mongoTemplate.updateFirst(query, update, RocketHistoryDocument.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.red.circle.other.infra.gateway;
|
||||
|
||||
import com.red.circle.other.domain.gateway.RocketRewardLogGateway;
|
||||
import com.red.circle.other.domain.rocket.RocketRewardLog;
|
||||
import com.red.circle.other.infra.convertor.RocketRewardLogConvertor;
|
||||
import com.red.circle.other.infra.database.rds.dao.RocketRewardClaimLogMapper;
|
||||
import com.red.circle.other.infra.database.rds.entity.RocketRewardClaimLogEntity;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 火箭奖励领取记录网关实现
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RocketRewardLogGatewayImpl implements RocketRewardLogGateway {
|
||||
|
||||
private final RocketRewardClaimLogMapper rocketRewardClaimLogMapper;
|
||||
private final RocketRewardLogConvertor rocketRewardLogConvertor;
|
||||
|
||||
@Override
|
||||
public void save(RocketRewardLog log) {
|
||||
RocketRewardClaimLogEntity entity = rocketRewardLogConvertor.toEntity(log);
|
||||
rocketRewardClaimLogMapper.insert(entity);
|
||||
log.setId(entity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByRocketAndUser(String rocketHistoryId, Long userId) {
|
||||
int count = rocketRewardClaimLogMapper.countByRocketAndUser(rocketHistoryId, userId);
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RocketRewardLog> findByRocketHistoryId(String rocketHistoryId) {
|
||||
List<RocketRewardClaimLogEntity> entities =
|
||||
rocketRewardClaimLogMapper.selectByRocketHistoryId(rocketHistoryId);
|
||||
return entities.stream()
|
||||
.map(rocketRewardLogConvertor::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RocketRewardLog> findByRoomIdAndUserId(Long roomId, Long userId) {
|
||||
List<RocketRewardClaimLogEntity> entities =
|
||||
rocketRewardClaimLogMapper.selectByRoomIdAndUserId(roomId, userId);
|
||||
return entities.stream()
|
||||
.map(rocketRewardLogConvertor::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countByRocketHistoryId(String rocketHistoryId) {
|
||||
return rocketRewardClaimLogMapper.countByRocketHistoryId(rocketHistoryId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.red.circle.other.infra.database.rds.dao.RocketConfigMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="com.red.circle.other.infra.database.rds.entity.RocketConfigEntity">
|
||||
<id column="id" property="id"/>
|
||||
<result column="level" property="level"/>
|
||||
<result column="max_energy" property="maxEnergy"/>
|
||||
<result column="reward_config" property="rewardConfig"/>
|
||||
<result column="contributor_reward_rate" property="contributorRewardRate"/>
|
||||
<result column="normal_reward_config" property="normalRewardConfig"/>
|
||||
<result column="status" property="status"/>
|
||||
<result column="created_at" property="createdAt"/>
|
||||
<result column="updated_at" property="updatedAt"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id, level, max_energy, reward_config, contributor_reward_rate,
|
||||
normal_reward_config, status, created_at, updated_at
|
||||
</sql>
|
||||
|
||||
<select id="selectByLevel" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM rocket_config
|
||||
WHERE level = #{level}
|
||||
</select>
|
||||
|
||||
<select id="selectAll" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM rocket_config
|
||||
ORDER BY level ASC
|
||||
</select>
|
||||
|
||||
<select id="selectAllEnabled" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM rocket_config
|
||||
WHERE status = 1
|
||||
ORDER BY level ASC
|
||||
</select>
|
||||
|
||||
<select id="selectById" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM rocket_config
|
||||
WHERE id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.red.circle.other.infra.database.rds.entity.RocketConfigEntity"
|
||||
useGeneratedKeys="true" keyProperty="id">
|
||||
INSERT INTO rocket_config (
|
||||
level, max_energy, reward_config, contributor_reward_rate,
|
||||
normal_reward_config, status, created_at, updated_at
|
||||
) VALUES (
|
||||
#{level}, #{maxEnergy}, #{rewardConfig}, #{contributorRewardRate},
|
||||
#{normalRewardConfig}, #{status}, #{createdAt}, #{updatedAt}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="update" parameterType="com.red.circle.other.infra.database.rds.entity.RocketConfigEntity">
|
||||
UPDATE rocket_config
|
||||
<set>
|
||||
<if test="maxEnergy != null">max_energy = #{maxEnergy},</if>
|
||||
<if test="rewardConfig != null">reward_config = #{rewardConfig},</if>
|
||||
<if test="contributorRewardRate != null">contributor_reward_rate = #{contributorRewardRate},</if>
|
||||
<if test="normalRewardConfig != null">normal_reward_config = #{normalRewardConfig},</if>
|
||||
<if test="status != null">status = #{status},</if>
|
||||
updated_at = NOW()
|
||||
</set>
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.red.circle.other.infra.database.rds.dao.RocketRewardClaimLogMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="com.red.circle.other.infra.database.rds.entity.RocketRewardClaimLogEntity">
|
||||
<id column="id" property="id"/>
|
||||
<result column="rocket_history_id" property="rocketHistoryId"/>
|
||||
<result column="room_id" property="roomId"/>
|
||||
<result column="user_id" property="userId"/>
|
||||
<result column="rocket_level" property="rocketLevel"/>
|
||||
<result column="is_contributor" property="isContributor"/>
|
||||
<result column="contribution_energy" property="contributionEnergy"/>
|
||||
<result column="contribution_rate" property="contributionRate"/>
|
||||
<result column="reward_type" property="rewardType"/>
|
||||
<result column="reward_item_id" property="rewardItemId"/>
|
||||
<result column="reward_amount" property="rewardAmount"/>
|
||||
<result column="wallet_biz_no" property="walletBizNo"/>
|
||||
<result column="claimed_at" property="claimedAt"/>
|
||||
<result column="created_at" property="createdAt"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id, rocket_history_id, room_id, user_id, rocket_level, is_contributor,
|
||||
contribution_energy, contribution_rate, reward_type, reward_item_id,
|
||||
reward_amount, wallet_biz_no, claimed_at, created_at
|
||||
</sql>
|
||||
|
||||
<insert id="insert" parameterType="com.red.circle.other.infra.database.rds.entity.RocketRewardClaimLogEntity"
|
||||
useGeneratedKeys="true" keyProperty="id">
|
||||
INSERT INTO rocket_reward_claim_log (
|
||||
rocket_history_id, room_id, user_id, rocket_level, is_contributor,
|
||||
contribution_energy, contribution_rate, reward_type, reward_item_id,
|
||||
reward_amount, wallet_biz_no, claimed_at, created_at
|
||||
) VALUES (
|
||||
#{rocketHistoryId}, #{roomId}, #{userId}, #{rocketLevel}, #{isContributor},
|
||||
#{contributionEnergy}, #{contributionRate}, #{rewardType}, #{rewardItemId},
|
||||
#{rewardAmount}, #{walletBizNo}, #{claimedAt}, #{createdAt}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="countByRocketAndUser" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM rocket_reward_claim_log
|
||||
WHERE rocket_history_id = #{rocketHistoryId}
|
||||
AND user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="selectByRocketHistoryId" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM rocket_reward_claim_log
|
||||
WHERE rocket_history_id = #{rocketHistoryId}
|
||||
ORDER BY claimed_at DESC
|
||||
</select>
|
||||
|
||||
<select id="selectByRoomIdAndUserId" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM rocket_reward_claim_log
|
||||
WHERE room_id = #{roomId}
|
||||
AND user_id = #{userId}
|
||||
ORDER BY claimed_at DESC
|
||||
</select>
|
||||
|
||||
<select id="countByRocketHistoryId" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM rocket_reward_claim_log
|
||||
WHERE rocket_history_id = #{rocketHistoryId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
x
Reference in New Issue
Block a user