提交roll日创建

This commit is contained in:
2026-07-19 12:05:45 +08:00
parent 6a9ff1a1e5
commit 55fdf24f3a
9 changed files with 118 additions and 12 deletions
+7 -1
View File
@@ -17,7 +17,9 @@ CREATE TABLE IF NOT EXISTS `tt_official_roll_config` (
`roll_password` varchar(32) DEFAULT '' COMMENT '房间密码,为空则无密码',
`min_recharge` decimal(10,2) DEFAULT '0.00' COMMENT '充值门槛,0为无门槛',
`people_num` int DEFAULT '50' COMMENT '人数上限',
`robot_num` int DEFAULT '0' COMMENT '每次自动加入的机器人数量,0则不加',
`robot_num` int DEFAULT '0' COMMENT '每次自动加入的机器人数量,0则不加(兼容旧数据)',
`robot_min` int DEFAULT '0' COMMENT '每次自动加入的机器人数量下限,0则不加',
`robot_max` int DEFAULT '0' COMMENT '每次自动加入的机器人数量上限,0则不加',
`cdk_count` int DEFAULT '0' COMMENT '每次自动创建房间生成的CDK数量,0则不启用CDK',
`sort_by` int DEFAULT '0' COMMENT '排序',
`status` char(1) DEFAULT '0' COMMENT '状态 0启用 1停用',
@@ -33,6 +35,10 @@ CREATE TABLE IF NOT EXISTS `tt_official_roll_config` (
-- 若 tt_official_roll_config 表此前已创建(无 cdk_count 列),执行下句补列;全新执行本脚本已含该列,可跳过:
-- ALTER TABLE `tt_official_roll_config` ADD COLUMN `cdk_count` int DEFAULT '0' COMMENT '每次自动创建房间生成的CDK数量,0则不启用CDK';
-- 若 tt_official_roll_config 表此前已创建(无 robot_min/robot_max 列),执行下句补列;全新执行本脚本已含该列,可跳过:
-- ALTER TABLE `tt_official_roll_config` ADD COLUMN `robot_min` int DEFAULT '0' COMMENT '每次自动加入的机器人数量下限,0则不加';
-- ALTER TABLE `tt_official_roll_config` ADD COLUMN `robot_max` int DEFAULT '0' COMMENT '每次自动加入的机器人数量上限,0则不加';
-- ------------------------------------------------------------
-- 2) tt_roll 增加 official_config_id 列(标记房间由哪条配置生成,用于每日幂等)
-- 注意:MySQL 不支持 ADD COLUMN IF NOT EXISTS,若该列已存在请跳过本句。
@@ -41,7 +41,11 @@
</template>
</el-table-column>
<el-table-column align="center" prop="roomName" label="房间名"></el-table-column>
<el-table-column align="center" prop="robotNum" label="机器人数量" width="100"></el-table-column>
<el-table-column align="center" label="机器人范围" width="120">
<template slot-scope="scope">
{{ scope.row.robotMin }} ~ {{ scope.row.robotMax }}
</template>
</el-table-column>
<el-table-column align="center" prop="cdkCount" label="CDK数量" width="90"></el-table-column>
<el-table-column align="center" prop="peopleNum" label="人数上限" width="90"></el-table-column>
<el-table-column align="center" prop="rollPassword" label="密码" width="80"></el-table-column>
@@ -92,10 +96,14 @@
<el-form-item label="房间描述" prop="description">
<el-input type="textarea" v-model="form.description" placeholder="请输入房间描述"></el-input>
</el-form-item>
<el-form-item label="机器人数量" prop="robotNum">
<el-input-number v-model="form.robotNum" :min="0" :max="100000" label="机器人数量"></el-input-number>
<el-form-item label="机器人范围" prop="robotRange">
<div style="display:flex; align-items:center; gap:8px;">
<el-input-number v-model="form.robotMin" :min="0" :max="100000" label="机器人数量下限"></el-input-number>
<span>~</span>
<el-input-number v-model="form.robotMax" :min="0" :max="100000" label="机器人数量上限"></el-input-number>
</div>
<span style="font-size: 12px;">
<i class="el-icon-info"></i> 每天自动创建房间后加入的机器人数量为0则不加机器人
<i class="el-icon-info"></i> 每天自动创建房间后随机加入[下限,上限]机器人为0则不加机器人
</span>
</el-form-item>
<el-form-item label="人数上限" prop="peopleNum">
@@ -161,7 +169,19 @@ export default {
configName: [{ required: true, message: "请输入配置名称", trigger: "blur" }],
jackpotId: [{ required: true, message: "请选择奖池", trigger: "change" }],
roomName: [{ required: true, message: "请输入房间名", trigger: "blur" }],
peopleNum: [{ required: true, message: "请输入人数上限", trigger: "blur" }]
peopleNum: [{ required: true, message: "请输入人数上限", trigger: "blur" }],
robotRange: [
{
validator: (rule, value, callback) => {
if (this.form.robotMin > this.form.robotMax) {
callback(new Error("机器人数量下限不能大于上限"));
} else {
callback();
}
},
trigger: "change"
}
]
}
};
},
@@ -180,6 +200,8 @@ export default {
description: null,
minRecharge: 0,
robotNum: 0,
robotMin: 0,
robotMax: 0,
cdkCount: 0,
peopleNum: 100,
rollPassword: null,
@@ -59,10 +59,18 @@ public class TtOfficialRollConfig implements Serializable {
@Excel(name = "人数上限")
private Integer peopleNum;
/** 每天(每周期)自动加入的机器人数量 */
/** 每天(每周期)自动加入的机器人数量(兼容旧数据) */
@Excel(name = "机器人数量")
private Integer robotNum;
/** 每天自动加入的机器人数量下限 */
@Excel(name = "机器人数量下限")
private Integer robotMin;
/** 每天自动加入的机器人数量上限 */
@Excel(name = "机器人数量上限")
private Integer robotMax;
/** 每次自动创建房间生成的CDK数量,0则不启用CDK(使用普通密码) */
@Excel(name = "CDK数量")
private Integer cdkCount;
@@ -3,6 +3,7 @@ package com.ruoyi.admin.domain.body;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import java.util.List;
@Data
public class AddRobotBody {
@@ -11,4 +12,7 @@ public class AddRobotBody {
private Integer rollId;
private Integer robotNum;
/** 需要排除的机器人ID列表(例如已在其他官方房中使用的机器人) */
private List<Integer> excludeRobotIds;
}
@@ -18,4 +18,9 @@ public interface TtRollMapper extends BaseMapper<TtRoll> {
List<TtUser> getRollUser(Integer rollId);
List<Integer> getRollRobotIds(Integer rollId);
/**
* 查询所有未开奖官方日Roll房中的机器人ID
*/
List<Integer> getActiveOfficialRollRobotIds();
}
@@ -63,6 +63,16 @@ public class TtOfficialRollConfigServiceImpl
if (config.getRobotNum() != null && config.getRobotNum() < 0) {
return AjaxResult.error("机器人数量不能为负数");
}
if (config.getRobotMin() != null && config.getRobotMin() < 0) {
return AjaxResult.error("机器人数量下限不能为负数");
}
if (config.getRobotMax() != null && config.getRobotMax() < 0) {
return AjaxResult.error("机器人数量上限不能为负数");
}
if (config.getRobotMin() != null && config.getRobotMax() != null
&& config.getRobotMin() > config.getRobotMax()) {
return AjaxResult.error("机器人数量下限不能大于上限");
}
return null;
}
@@ -72,6 +82,8 @@ public class TtOfficialRollConfigServiceImpl
private void normalize(TtOfficialRollConfig config) {
if (config.getMinRecharge() == null) config.setMinRecharge(BigDecimal.ZERO);
if (config.getRobotNum() == null) config.setRobotNum(0);
if (config.getRobotMin() == null) config.setRobotMin(0);
if (config.getRobotMax() == null) config.setRobotMax(0);
if (config.getSortBy() == null) config.setSortBy(0);
if (StringUtils.isEmpty(config.getStatus())) config.setStatus("0");
}
@@ -556,9 +556,13 @@ public class TtRollServiceImpl extends ServiceImpl<TtRollMapper, TtRoll> impleme
// 查询已经在房间中的机器人ID
List<Integer> rollRobotIds = ttRollMapper.getRollRobotIds(addRobotBody.getRollId());
// 过滤掉已经在房间中的机器人ID
// 查询需要排除的机器人ID(例如已在其他官方房中使用的机器人
List<Integer> excludeRobotIds = addRobotBody.getExcludeRobotIds();
// 过滤掉已经在房间中或被排除的机器人ID
List<Integer> filteredRobotIdList = robotIdList.stream()
.filter(robotId -> !rollRobotIds.contains(robotId))
.filter(robotId -> excludeRobotIds == null || !excludeRobotIds.contains(robotId))
.collect(Collectors.toList());
if (filteredRobotIdList.size() < addRobotBody.getRobotNum()) {
return AjaxResult.error("可用机器人数量不足");
@@ -4,11 +4,13 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.admin.domain.body.AddRobotBody;
import com.ruoyi.admin.mapper.TtRollMapper;
import com.ruoyi.admin.service.TtOfficialRollConfigService;
import com.ruoyi.admin.service.TtRollCdkService;
import com.ruoyi.admin.service.TtRollService;
import com.ruoyi.admin.service.TtUserService;
import com.ruoyi.admin.service.impl.TtOfficialRollConfigServiceImpl;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.domain.entity.roll.TtOfficialRollConfig;
import com.ruoyi.domain.entity.roll.TtRoll;
import com.ruoyi.domain.entity.sys.TtUser;
@@ -20,6 +22,7 @@ import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* 官方周期Roll房定时创建任务。
@@ -54,6 +57,9 @@ public class OfficialRollTask {
@Autowired
private TtRollCdkService rollCdkService;
@Autowired
private TtRollMapper rollMapper;
/**
* 每天为所有启用的 DAILY 配置创建当日官方roll房并自动加入机器人。
* 充值统计起点=当天0点(今日充值),开奖=当日23:59:59。
@@ -135,10 +141,12 @@ public class OfficialRollTask {
}
/**
* 为指定房间按配置数量加入机器人。数量取 min(配置机器人数, 可用机器人总数),避免"可用机器人数量不足"导致一个都不加。
* 为指定房间按配置数量加入机器人。
* 若配置指定了 robotMin/robotMax 范围,则在范围内随机生成数量;否则使用固定 robotNum。
* 会排除当前已在其他未开奖官方日Roll房中的机器人,保证不同日期的官方房间机器人不重复。
*/
private void addRobots(Integer rollId, TtOfficialRollConfig config) {
Integer robotNum = config.getRobotNum();
Integer robotNum = resolveRobotNum(config);
if (rollId == null || robotNum == null || robotNum <= 0) {
return;
}
@@ -149,16 +157,37 @@ public class OfficialRollTask {
log.warn("[官方周期Roll] 配置{}需要{}个机器人,但用户表无可用机器人,跳过加入", config.getId(), robotNum);
return;
}
// 查询其他未开奖官方日Roll房中已使用的机器人,避免重复
List<Integer> activeOfficialRobots = rollMapper.getActiveOfficialRollRobotIds();
AddRobotBody body = new AddRobotBody();
body.setRollId(rollId);
body.setRobotNum(toAdd);
rollService.addRobot(body);
body.setExcludeRobotIds(activeOfficialRobots);
AjaxResult result = rollService.addRobot(body);
if (!result.isSuccess()) {
log.warn("[官方周期Roll] 配置{} 房间{} 加入机器人结果:{}", config.getId(), rollId, result.get(AjaxResult.MSG_TAG));
} else {
log.info("[官方周期Roll] 配置{} 房间{} 已尝试加入{}个机器人", config.getId(), rollId, toAdd);
}
} catch (Exception e) {
log.error("[官方周期Roll] 配置{} 房间{} 加入机器人失败:{}", config.getId(), rollId, e.getMessage(), e);
}
}
/**
* 解析配置中的机器人数量:优先使用 robotMin/robotMax 范围随机,否则回退到固定 robotNum
*/
private Integer resolveRobotNum(TtOfficialRollConfig config) {
Integer min = config.getRobotMin();
Integer max = config.getRobotMax();
if (min != null && min > 0 && max != null && max > 0) {
int lower = Math.min(min, max);
int upper = Math.max(min, max);
return ThreadLocalRandom.current().nextInt(lower, upper + 1);
}
return config.getRobotNum();
}
/**
* 按配置数量为房间生成CDK;0或空则不生成(使用普通密码)。
*/
@@ -61,4 +61,20 @@
WHERE
tru.roll_id = #{rollId} AND tu.user_type = 03
</select>
<select id="getActiveOfficialRollRobotIds" resultType="Integer">
SELECT DISTINCT
tu.user_id
FROM
tt_roll_user AS tru
LEFT JOIN
tt_user AS tu ON tru.user_id = tu.user_id
LEFT JOIN
tt_roll AS tr ON tru.roll_id = tr.id
WHERE
tu.user_type = '03'
AND tr.roll_type = '0'
AND tr.official_config_id IS NOT NULL
AND tr.roll_status = '0'
</select>
</mapper>