提交roll日创建
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
-- ============================================================
|
||||
-- 官方日Roll定时任务 + 机器人管理页面 一次性数据库脚本
|
||||
-- 目标库:ruoyi 业务库(与 tt_roll / tt_user / sys_menu / sys_job 同库)
|
||||
-- 说明:执行一次即可;执行后请【重启后端】,随后在"系统监控-定时任务"可见"官方日Roll生成"。
|
||||
-- ============================================================
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1) 官方周期Roll房配置表
|
||||
-- ------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `tt_official_roll_config` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '配置ID',
|
||||
`config_name` varchar(64) NOT NULL DEFAULT '' COMMENT '配置标识',
|
||||
`jackpot_id` int DEFAULT NULL COMMENT '奖池ID(tt_roll_jackpot.jackpot_id)',
|
||||
`period_type` varchar(16) NOT NULL DEFAULT 'DAILY' COMMENT '周期类型 DAILY每日/WEEKLY每周',
|
||||
`room_name` varchar(64) NOT NULL DEFAULT '' COMMENT '生成的房间名称',
|
||||
`description` varchar(255) DEFAULT '' COMMENT '房间描述',
|
||||
`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则不加',
|
||||
`cdk_count` int DEFAULT '0' COMMENT '每次自动创建房间生成的CDK数量,0则不启用CDK',
|
||||
`sort_by` int DEFAULT '0' COMMENT '排序',
|
||||
`status` char(1) DEFAULT '0' COMMENT '状态 0启用 1停用',
|
||||
`last_generate_time` datetime DEFAULT NULL COMMENT '上次生成时间',
|
||||
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_by` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志 0存在 2删除',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='官方周期Roll房配置' ROW_FORMAT=DYNAMIC;
|
||||
|
||||
-- 若 tt_official_roll_config 表此前已创建(无 cdk_count 列),执行下句补列;全新执行本脚本已含该列,可跳过:
|
||||
-- ALTER TABLE `tt_official_roll_config` ADD COLUMN `cdk_count` int DEFAULT '0' COMMENT '每次自动创建房间生成的CDK数量,0则不启用CDK';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2) tt_roll 增加 official_config_id 列(标记房间由哪条配置生成,用于每日幂等)
|
||||
-- 注意:MySQL 不支持 ADD COLUMN IF NOT EXISTS,若该列已存在请跳过本句。
|
||||
-- ------------------------------------------------------------
|
||||
ALTER TABLE `tt_roll`
|
||||
ADD COLUMN `official_config_id` int DEFAULT NULL COMMENT '官方周期Roll配置ID(tt_official_roll_config.id),手动创建为NULL';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3) 注册定时任务到"系统监控-定时任务":每天10点创建官方日Roll房并自动加入机器人
|
||||
-- ------------------------------------------------------------
|
||||
SET @jobId = (SELECT IFNULL(MAX(job_id), 100) + 1 FROM sys_job);
|
||||
INSERT INTO `sys_job`(`job_id`,`job_name`,`job_group`,`invoke_target`,`cron_expression`,`misfire_policy`,`concurrent`,`status`,`create_by`,`create_time`,`remark`)
|
||||
VALUES (@jobId, '官方日Roll生成', 'DEFAULT', 'officialRollTask.generateDailyRolls()', '0 0 10 * * ?', '3', '1', '0', 'admin', NOW(), '每天10点为启用的日Roll配置自动创建官方Roll房并加入机器人');
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4) 菜单:机器人管理(挂"用户管理"下)、日Roll配置(挂"Roll房设置"下)
|
||||
-- 父菜单按名称查找;若你的父菜单名称不同,请调整下面 menu_name 的匹配值。
|
||||
-- 若父菜单未找到(@xxxId 为 NULL),菜单将挂到顶级(parent_id=0),可在"菜单管理"里再拖动调整。
|
||||
-- ------------------------------------------------------------
|
||||
SET @userMgrId = (SELECT menu_id FROM (SELECT menu_id FROM sys_menu WHERE menu_name = '用户管理' AND menu_type = 'M' ORDER BY menu_id LIMIT 1) t);
|
||||
SET @rollMgrId = (SELECT menu_id FROM (SELECT menu_id FROM sys_menu WHERE menu_name = 'Roll房设置' AND menu_type = 'M' ORDER BY menu_id LIMIT 1) t);
|
||||
SET @menuBase = (SELECT IFNULL(MAX(menu_id), 2000) FROM sys_menu);
|
||||
|
||||
INSERT INTO `sys_menu`(`menu_id`,`menu_name`,`parent_id`,`order_num`,`path`,`component`,`query`,`is_frame`,`is_cache`,`menu_type`,`visible`,`status`,`perms`,`icon`,`create_by`,`create_time`)
|
||||
VALUES (@menuBase + 1, '机器人管理', IFNULL(@userMgrId, 0), 5, 'robotUser', 'skins/robotUser/index', '', 1, 0, 'C', '0', '0', 'admin:robot:list', 'user', 'admin', NOW());
|
||||
|
||||
INSERT INTO `sys_menu`(`menu_id`,`menu_name`,`parent_id`,`order_num`,`path`,`component`,`query`,`is_frame`,`is_cache`,`menu_type`,`visible`,`status`,`perms`,`icon`,`create_by`,`create_time`)
|
||||
VALUES (@menuBase + 2, '日Roll配置', IFNULL(@rollMgrId, 0), 9, 'officialRollConfig', 'skins/ttRoll/officialRollConfig', '', 1, 0, 'C', '0', '0', 'admin:officialRollConfig:list', 'time', 'admin', NOW());
|
||||
|
||||
-- ============================================================
|
||||
-- 完成。若为非 admin 角色,请在"角色管理"里为角色勾选以上两个菜单权限。
|
||||
-- ============================================================
|
||||
@@ -225,11 +225,12 @@ export function generateRollCdk(data) {
|
||||
});
|
||||
}
|
||||
|
||||
/** 查询Roll房CDK列表 */
|
||||
export function getRollCdkList(rollId) {
|
||||
/** 查询Roll房CDK列表(分页) */
|
||||
export function getRollCdkList(rollId, query) {
|
||||
return request({
|
||||
url: `/admin/roll/cdk/list/${rollId}`,
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
@@ -240,3 +241,49 @@ export function deleteRollCdk(cdkId) {
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// ---- 官方周期Roll配置(日Roll/周Roll 自动创建) ----
|
||||
|
||||
// 官方周期Roll配置-列表
|
||||
export function officialRollConfigList(query) {
|
||||
return request({
|
||||
url: '/admin/officialRollConfig/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
// 官方周期Roll配置-新增
|
||||
export function officialRollConfigAdd(data) {
|
||||
return request({
|
||||
url: '/admin/officialRollConfig',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 官方周期Roll配置-编辑
|
||||
export function officialRollConfigChange(data) {
|
||||
return request({
|
||||
url: '/admin/officialRollConfig',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 官方周期Roll配置-删除
|
||||
export function officialRollConfigDel(id) {
|
||||
return request({
|
||||
url: `/admin/officialRollConfig/${id}`,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// 官方周期Roll配置-启用/停用
|
||||
export function officialRollConfigChangeStatus(data) {
|
||||
return request({
|
||||
url: '/admin/officialRollConfig/changeStatus',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryForm"
|
||||
size="small"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="用户ID" prop="userId">
|
||||
<el-input
|
||||
v-model="queryParams.userId"
|
||||
placeholder="请输入用户ID"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="昵称" prop="nickName">
|
||||
<el-input
|
||||
v-model="queryParams.nickName"
|
||||
placeholder="请输入机器人昵称"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phoneNumber">
|
||||
<el-input
|
||||
v-model="queryParams.phoneNumber"
|
||||
placeholder="请输入手机号码"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
icon="el-icon-circle-plus-outline"
|
||||
type="primary"
|
||||
plain
|
||||
size="mini"
|
||||
@click="addRobot = true"
|
||||
>生成机器人</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column label="ID" align="center" prop="userId" />
|
||||
<el-table-column label="机器人昵称" align="center" prop="nickName" />
|
||||
<el-table-column label="头像" align="center" prop="avatar">
|
||||
<template slot-scope="scope">
|
||||
<image-preview :src="scope.row.avatar" :width="50" :height="50" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号码" align="center" prop="phoneNumber" />
|
||||
<el-table-column label="账户金额" align="center" prop="accountAmount" />
|
||||
<el-table-column label="VIP等级" align="center" prop="vipLevel">
|
||||
<template slot-scope="scope">VIP{{ scope.row.vipLevel }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 生成机器人 -->
|
||||
<el-dialog title="生成机器人" :visible.sync="addRobot" width="600px">
|
||||
<el-form>
|
||||
<el-form-item label="请选择数量:" style="margin-bottom: 2px;">
|
||||
<el-input-number size="mini" v-model="newNumber" :min="1" :max="10" label="描述文字"></el-input-number>
|
||||
</el-form-item>
|
||||
<div style="font-size:14px;color:#797979;">
|
||||
<i class="el-icon-info"></i> 要生成的机器人数量(每次最多10个)
|
||||
</div>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="addRobot = false">取 消</el-button>
|
||||
<el-button type="primary" @click="generateRobot">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listUser, delUser, generateRobot } from "@/api/skins/ttuser/api";
|
||||
|
||||
export default {
|
||||
name: "RobotUser",
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
showSearch: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
total: 0,
|
||||
userList: [],
|
||||
addRobot: false,
|
||||
newNumber: 1,
|
||||
queryParams: {
|
||||
userId: null,
|
||||
nickName: null,
|
||||
phoneNumber: null,
|
||||
// 固定只查机器人(userType=03)
|
||||
userType: "03",
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询机器人列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.queryParams.userType = "03";
|
||||
listUser(this.queryParams).then(response => {
|
||||
this.userList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
userId: null,
|
||||
nickName: null,
|
||||
phoneNumber: null,
|
||||
userType: "03",
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
};
|
||||
this.handleQuery();
|
||||
},
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.userId);
|
||||
this.multiple = !selection.length;
|
||||
},
|
||||
/** 生成机器人 */
|
||||
generateRobot() {
|
||||
generateRobot(this.newNumber).then(res => {
|
||||
this.getList();
|
||||
(this.newNumber = 1), (this.addRobot = false);
|
||||
const blob = new Blob([res], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
});
|
||||
const objectURL = URL.createObjectURL(blob);
|
||||
const aTag = document.createElement("a");
|
||||
aTag.href = objectURL;
|
||||
aTag.download = `机器人账号数据_${new Date().getTime()}.txt`;
|
||||
aTag.click();
|
||||
URL.revokeObjectURL(objectURL);
|
||||
});
|
||||
},
|
||||
/** 删除机器人 */
|
||||
handleDelete(row) {
|
||||
const userIds = row.userId || this.ids;
|
||||
this.$modal
|
||||
.confirm('是否确认删除机器人编号为"' + userIds + '"的数据项?')
|
||||
.then(() => {
|
||||
return delUser(userIds);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -318,6 +318,14 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="cdkTotal > 0"
|
||||
:total="cdkTotal"
|
||||
:page.sync="cdkQueryParams.pageNum"
|
||||
:limit.sync="cdkQueryParams.pageSize"
|
||||
@pagination="loadCdkList"
|
||||
small
|
||||
/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cdkDialogVisible = false">关 闭</el-button>
|
||||
</div>
|
||||
@@ -401,7 +409,12 @@ export default {
|
||||
cdkList: [],
|
||||
cdkLoading: false,
|
||||
cdkGenCount: 10,
|
||||
currentCdkRollId: null
|
||||
currentCdkRollId: null,
|
||||
cdkTotal: 0,
|
||||
cdkQueryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -577,14 +590,16 @@ export default {
|
||||
// 打开CDK管理弹窗
|
||||
handleCdk(row) {
|
||||
this.currentCdkRollId = row.id;
|
||||
this.cdkQueryParams.pageNum = 1;
|
||||
this.cdkDialogVisible = true;
|
||||
this.loadCdkList();
|
||||
},
|
||||
// 加载CDK列表
|
||||
loadCdkList() {
|
||||
this.cdkLoading = true;
|
||||
getRollCdkList(this.currentCdkRollId).then(res => {
|
||||
this.cdkList = res.data || [];
|
||||
getRollCdkList(this.currentCdkRollId, this.cdkQueryParams).then(res => {
|
||||
this.cdkList = res.rows || [];
|
||||
this.cdkTotal = res.total || 0;
|
||||
this.cdkLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
|
||||
<el-form-item label="配置名称" prop="configName">
|
||||
<el-input
|
||||
v-model="queryParams.configName"
|
||||
placeholder="请输入配置名称"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||
<el-option label="启用" value="0"></el-option>
|
||||
<el-option label="停用" value="1"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleCreat"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
<el-table :data="tableData" style="width: 100%" v-loading="loading">
|
||||
<el-table-column align="center" prop="id" label="ID" width="60"></el-table-column>
|
||||
<el-table-column align="center" prop="configName" label="配置名称"></el-table-column>
|
||||
<el-table-column align="center" prop="jackpotId" label="奖池" width="140">
|
||||
<template slot-scope="scope">
|
||||
{{ jackpotName(scope.row.jackpotId) }}
|
||||
</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" 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>
|
||||
<el-table-column align="center" prop="status" label="状态" width="90">
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
:value="scope.row.status === '0'"
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="lastGenerateTime" label="上次生成时间" width="160"></el-table-column>
|
||||
<el-table-column align="center" label="操作" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" icon="el-icon-edit" @click="handleChange(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="mini" icon="el-icon-delete" @click="handleDelete(scope.row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<el-dialog :title="title" :visible.sync="dialogFormVisible" width="35%">
|
||||
<el-form :model="form" :rules="rules" label-width="120px" ref="ruleForm">
|
||||
<el-form-item label="配置名称" prop="configName">
|
||||
<el-input v-model="form.configName" autocomplete="off" placeholder="请输入配置名称(内部标识)"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="奖池" prop="jackpotId">
|
||||
<el-select v-model="form.jackpotId" filterable placeholder="请选择奖池" clearable>
|
||||
<el-option
|
||||
v-for="item in JackpotList"
|
||||
:key="item.jackpotId"
|
||||
:label="item.jackpotName"
|
||||
:value="item.jackpotId"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="房间名" prop="roomName">
|
||||
<el-input v-model="form.roomName" autocomplete="off" placeholder="请输入生成房间的名称"></el-input>
|
||||
</el-form-item>
|
||||
<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>
|
||||
<span style="font-size: 12px;">
|
||||
<i class="el-icon-info"></i> 每天自动创建房间后加入的机器人数量,为0则不加机器人
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="人数上限" prop="peopleNum">
|
||||
<el-input-number v-model="form.peopleNum" :min="1" :max="100000" label="人数上限"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="房间密码" prop="rollPassword">
|
||||
<el-input v-model="form.rollPassword" autocomplete="off" placeholder="请输入房间密码"></el-input>
|
||||
<span style="font-size: 12px;">
|
||||
<i class="el-icon-info"></i> 为空表示无密码
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="CDK数量" prop="cdkCount">
|
||||
<el-input-number v-model="form.cdkCount" :min="0" :max="500" label="CDK数量"></el-input-number>
|
||||
<span style="font-size: 12px;">
|
||||
<i class="el-icon-info"></i> 填0则不启用CDK模式,使用普通密码
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio label="0">启用</el-radio>
|
||||
<el-radio label="1">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm('ruleForm')">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
officialRollConfigList,
|
||||
officialRollConfigAdd,
|
||||
officialRollConfigChange,
|
||||
officialRollConfigDel,
|
||||
officialRollConfigChangeStatus,
|
||||
rollJackpotList
|
||||
} from "@/api/skins/ttRoll/api";
|
||||
|
||||
export default {
|
||||
name: "OfficialRollConfig",
|
||||
data() {
|
||||
return {
|
||||
total: 0,
|
||||
loading: false,
|
||||
showSearch: true,
|
||||
dialogFormVisible: false,
|
||||
title: "",
|
||||
isEdit: false,
|
||||
tableData: [],
|
||||
JackpotList: [],
|
||||
queryParams: {
|
||||
configName: null,
|
||||
periodType: null,
|
||||
status: null,
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
form: this.emptyForm(),
|
||||
rules: {
|
||||
configName: [{ required: true, message: "请输入配置名称", trigger: "blur" }],
|
||||
jackpotId: [{ required: true, message: "请选择奖池", trigger: "change" }],
|
||||
roomName: [{ required: true, message: "请输入房间名", trigger: "blur" }],
|
||||
peopleNum: [{ required: true, message: "请输入人数上限", trigger: "blur" }]
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
this.loadJackpot();
|
||||
},
|
||||
methods: {
|
||||
emptyForm() {
|
||||
return {
|
||||
id: null,
|
||||
configName: null,
|
||||
periodType: "DAILY",
|
||||
jackpotId: null,
|
||||
roomName: null,
|
||||
description: null,
|
||||
minRecharge: 0,
|
||||
robotNum: 0,
|
||||
cdkCount: 0,
|
||||
peopleNum: 100,
|
||||
rollPassword: null,
|
||||
sortBy: 0,
|
||||
status: "0"
|
||||
};
|
||||
},
|
||||
jackpotName(jackpotId) {
|
||||
const j = this.JackpotList.find(item => item.jackpotId == jackpotId);
|
||||
return j ? j.jackpotName : jackpotId;
|
||||
},
|
||||
loadJackpot() {
|
||||
rollJackpotList({ pageNum: 1, pageSize: 9999 }).then(res => {
|
||||
this.JackpotList = res.rows || [];
|
||||
});
|
||||
},
|
||||
getList() {
|
||||
this.loading = true;
|
||||
officialRollConfigList(this.queryParams).then(res => {
|
||||
this.tableData = res.rows || [];
|
||||
this.total = res.total || 0;
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
configName: null,
|
||||
periodType: null,
|
||||
status: null,
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
};
|
||||
this.handleQuery();
|
||||
},
|
||||
handleCreat() {
|
||||
this.form = this.emptyForm();
|
||||
this.isEdit = false;
|
||||
this.title = "新增官方周期Roll配置";
|
||||
this.dialogFormVisible = true;
|
||||
},
|
||||
handleChange(row) {
|
||||
this.form = Object.assign(this.emptyForm(), row);
|
||||
this.isEdit = true;
|
||||
this.title = "编辑官方周期Roll配置";
|
||||
this.dialogFormVisible = true;
|
||||
},
|
||||
submitForm(formName) {
|
||||
this.$refs[formName].validate(valid => {
|
||||
if (!valid) return false;
|
||||
const api = this.isEdit ? officialRollConfigChange : officialRollConfigAdd;
|
||||
api(this.form).then(() => {
|
||||
this.$modal.msgSuccess(this.isEdit ? "编辑成功" : "新增成功");
|
||||
this.dialogFormVisible = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
handleStatusChange(row) {
|
||||
const newStatus = row.status === "0" ? "1" : "0";
|
||||
const text = newStatus === "0" ? "启用" : "停用";
|
||||
this.$modal
|
||||
.confirm(`确认要${text}配置"${row.configName}"吗?`)
|
||||
.then(() => {
|
||||
return officialRollConfigChangeStatus({ id: row.id, status: newStatus });
|
||||
})
|
||||
.then(() => {
|
||||
row.status = newStatus;
|
||||
this.$modal.msgSuccess(text + "成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
handleDelete(id) {
|
||||
this.$modal
|
||||
.confirm('是否确认删除ID为"' + id + '"的配置?')
|
||||
.then(() => {
|
||||
return officialRollConfigDel(id);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.home {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -71,14 +71,6 @@
|
||||
v-hasPermi="['admin:user:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
icon="el-icon-circle-plus-outline"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="addRobot = true"
|
||||
>生成机器人</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
@@ -114,21 +106,6 @@
|
||||
<el-button type="primary" @click="generateAccount">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 生成机器人 -->
|
||||
<el-dialog title="生成机器人" :visible.sync="addRobot" width="600px">
|
||||
<el-form>
|
||||
<el-form-item label="请选择数量:" style="margin-bottom: 2px;">
|
||||
<el-input-number size="mini" v-model="newNumber" :min="1" :max="10" label="描述文字"></el-input-number>
|
||||
</el-form-item>
|
||||
<div style="font-size:14px;color:#797979;">
|
||||
<i class="el-icon-info"></i> 要生成的账号数量
|
||||
</div>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="addRobot = false">取 消</el-button>
|
||||
<el-button type="primary" @click="generateRobot">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
@@ -284,7 +261,6 @@ import {
|
||||
delUser,
|
||||
updateUser,
|
||||
generateAccount,
|
||||
generateRobot,
|
||||
getUserProfitStatistics,
|
||||
resetUserBalance,
|
||||
forceDeleteUser
|
||||
@@ -300,7 +276,6 @@ export default {
|
||||
openView: false,
|
||||
newNumber: 1,
|
||||
addNewUser: false,
|
||||
addRobot: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
@@ -467,22 +442,6 @@ export default {
|
||||
URL.revokeObjectURL(objectURL);
|
||||
});
|
||||
},
|
||||
/* 生成账号 */
|
||||
generateRobot() {
|
||||
generateRobot(this.newNumber).then(res => {
|
||||
this.getList();
|
||||
(this.newNumber = null), (this.addRobot = false);
|
||||
const blob = new Blob([res], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
});
|
||||
const objectURL = URL.createObjectURL(blob);
|
||||
const aTag = document.createElement("a");
|
||||
aTag.href = objectURL;
|
||||
aTag.download = `账号数据_${new Date().getTime()}.txt`;
|
||||
aTag.click();
|
||||
URL.revokeObjectURL(objectURL);
|
||||
});
|
||||
},
|
||||
/** 查询注册用户列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.ruoyi.domain.entity.roll;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 官方周期Roll房配置模板。
|
||||
* 每条配置指定奖池、周期(日/周)、充值门槛、人数、机器人数量等,
|
||||
* 由 OfficialRollTask 定时按周期自动创建 tt_roll 房间并自动加入机器人。
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@Builder
|
||||
@TableName(value = "tt_official_roll_config")
|
||||
public class TtOfficialRollConfig implements Serializable {
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Excel(name = "配置标识")
|
||||
private String configName;
|
||||
|
||||
@Excel(name = "奖池ID")
|
||||
private Integer jackpotId;
|
||||
|
||||
/** 周期类型: DAILY=每日, WEEKLY=每周 */
|
||||
@Excel(name = "周期类型")
|
||||
private String periodType;
|
||||
|
||||
@Excel(name = "房间名称")
|
||||
private String roomName;
|
||||
|
||||
@Excel(name = "房间描述")
|
||||
private String description;
|
||||
|
||||
private String rollPassword;
|
||||
|
||||
@Excel(name = "充值门槛")
|
||||
private BigDecimal minRecharge;
|
||||
|
||||
@Excel(name = "人数上限")
|
||||
private Integer peopleNum;
|
||||
|
||||
/** 每天(每周期)自动加入的机器人数量 */
|
||||
@Excel(name = "机器人数量")
|
||||
private Integer robotNum;
|
||||
|
||||
/** 每次自动创建房间生成的CDK数量,0则不启用CDK(使用普通密码) */
|
||||
@Excel(name = "CDK数量")
|
||||
private Integer cdkCount;
|
||||
|
||||
@Excel(name = "排序依据")
|
||||
private Integer sortBy;
|
||||
|
||||
/** 状态: 0=启用, 1=停用 */
|
||||
@Excel(name = "状态")
|
||||
private String status;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
|
||||
private Date lastGenerateTime;
|
||||
|
||||
private String createBy;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
|
||||
private Date createTime;
|
||||
|
||||
private String updateBy;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
|
||||
private Date updateTime;
|
||||
|
||||
@TableField(select = false)
|
||||
private String delFlag;
|
||||
}
|
||||
@@ -82,4 +82,7 @@ public class TtRoll implements Serializable {
|
||||
@TableField(select = false)
|
||||
private String delFlag;
|
||||
|
||||
// 官方周期Roll配置ID(tt_official_roll_config.id),标记该房由哪条配置生成,手动创建的房间为NULL
|
||||
private Integer officialConfigId;
|
||||
|
||||
}
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.ruoyi.admin.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.admin.service.TtOfficialRollConfigService;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.PageDataInfo;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.entity.roll.TtOfficialRollConfig;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "管理端 官方周期Roll配置")
|
||||
@RestController
|
||||
@RequestMapping("/admin/officialRollConfig")
|
||||
public class TtOfficialRollConfigController extends BaseController {
|
||||
|
||||
private final TtOfficialRollConfigService configService;
|
||||
|
||||
public TtOfficialRollConfigController(TtOfficialRollConfigService configService) {
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
@ApiOperation("配置列表")
|
||||
@GetMapping("/list")
|
||||
public PageDataInfo<TtOfficialRollConfig> list(
|
||||
@RequestParam(value = "configName", required = false) String configName,
|
||||
@RequestParam(value = "periodType", required = false) String periodType,
|
||||
@RequestParam(value = "status", required = false) String status) {
|
||||
startPage();
|
||||
LambdaQueryWrapper<TtOfficialRollConfig> wrapper = Wrappers.lambdaQuery();
|
||||
if (StringUtils.isNotEmpty(configName)) wrapper.like(TtOfficialRollConfig::getConfigName, configName);
|
||||
if (StringUtils.isNotEmpty(periodType)) wrapper.eq(TtOfficialRollConfig::getPeriodType, periodType);
|
||||
if (StringUtils.isNotEmpty(status)) wrapper.eq(TtOfficialRollConfig::getStatus, status);
|
||||
wrapper.orderByAsc(TtOfficialRollConfig::getSortBy).orderByDesc(TtOfficialRollConfig::getCreateTime);
|
||||
List<TtOfficialRollConfig> configList = configService.list(wrapper);
|
||||
return getPageData(configList);
|
||||
}
|
||||
|
||||
@ApiOperation("配置详情")
|
||||
@GetMapping("/{id}")
|
||||
public R<TtOfficialRollConfig> getInfo(@PathVariable("id") Integer id) {
|
||||
return R.ok(configService.getById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("新增配置")
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody TtOfficialRollConfig config) {
|
||||
config.setCreateBy(getUsername());
|
||||
config.setCreateTime(DateUtils.getNowDate());
|
||||
return configService.addConfig(config);
|
||||
}
|
||||
|
||||
@ApiOperation("编辑配置")
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody TtOfficialRollConfig config) {
|
||||
config.setUpdateBy(getUsername());
|
||||
config.setUpdateTime(DateUtils.getNowDate());
|
||||
return configService.editConfig(config);
|
||||
}
|
||||
|
||||
@ApiOperation("删除配置")
|
||||
@DeleteMapping("/{id}")
|
||||
public AjaxResult remove(@PathVariable("id") Integer id) {
|
||||
return configService.removeById(id) ? AjaxResult.success() : AjaxResult.error("删除失败");
|
||||
}
|
||||
|
||||
@ApiOperation("启用/停用配置")
|
||||
@PutMapping("/changeStatus")
|
||||
public AjaxResult changeStatus(@RequestBody TtOfficialRollConfig config) {
|
||||
if (config.getId() == null) return AjaxResult.error("配置ID不能为空");
|
||||
if (!"0".equals(config.getStatus()) && !"1".equals(config.getStatus())) {
|
||||
return AjaxResult.error("状态不合法");
|
||||
}
|
||||
TtOfficialRollConfig update = new TtOfficialRollConfig();
|
||||
update.setId(config.getId());
|
||||
update.setStatus(config.getStatus());
|
||||
update.setUpdateBy(getUsername());
|
||||
update.setUpdateTime(DateUtils.getNowDate());
|
||||
return configService.updateById(update) ? AjaxResult.success() : AjaxResult.error("操作失败");
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -201,12 +201,13 @@ public class TtRollController extends BaseController {
|
||||
return success("生成成功");
|
||||
}
|
||||
|
||||
/** 查看Roll房所有CDK列表 */
|
||||
/** 查看Roll房所有CDK列表(分页) */
|
||||
@ApiOperation("查看Roll房CDK列表")
|
||||
@GetMapping("/cdk/list/{rollId}")
|
||||
public AjaxResult getCdkList(@PathVariable("rollId") Integer rollId) {
|
||||
public PageDataInfo<TtRollCdk> getCdkList(@PathVariable("rollId") Integer rollId) {
|
||||
startPage();
|
||||
List<TtRollCdk> list = rollCdkService.listByRollId(rollId);
|
||||
return success(list);
|
||||
return getPageData(list);
|
||||
}
|
||||
|
||||
/** 删除指定CDK */
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.admin.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.domain.entity.roll.TtOfficialRollConfig;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface TtOfficialRollConfigMapper extends BaseMapper<TtOfficialRollConfig> {
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.ruoyi.admin.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.domain.entity.roll.TtOfficialRollConfig;
|
||||
|
||||
public interface TtOfficialRollConfigService extends IService<TtOfficialRollConfig> {
|
||||
|
||||
/** 新增配置(含校验) */
|
||||
AjaxResult addConfig(TtOfficialRollConfig config);
|
||||
|
||||
/** 编辑配置(含校验) */
|
||||
AjaxResult editConfig(TtOfficialRollConfig config);
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.ruoyi.admin.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.admin.mapper.TtOfficialRollConfigMapper;
|
||||
import com.ruoyi.admin.service.TtOfficialRollConfigService;
|
||||
import com.ruoyi.admin.service.TtRollJackpotService;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.entity.roll.TtOfficialRollConfig;
|
||||
import com.ruoyi.domain.entity.roll.TtRollJackpot;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Service
|
||||
public class TtOfficialRollConfigServiceImpl
|
||||
extends ServiceImpl<TtOfficialRollConfigMapper, TtOfficialRollConfig>
|
||||
implements TtOfficialRollConfigService {
|
||||
|
||||
/** 周期类型:每日 */
|
||||
public static final String PERIOD_DAILY = "DAILY";
|
||||
|
||||
@Autowired
|
||||
private TtRollJackpotService rollJackpotService;
|
||||
|
||||
@Override
|
||||
public AjaxResult addConfig(TtOfficialRollConfig config) {
|
||||
AjaxResult check = validate(config);
|
||||
if (check != null) return check;
|
||||
normalize(config);
|
||||
return save(config) ? AjaxResult.success() : AjaxResult.error("新增失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult editConfig(TtOfficialRollConfig config) {
|
||||
if (config.getId() == null) return AjaxResult.error("配置ID不能为空");
|
||||
AjaxResult check = validate(config);
|
||||
if (check != null) return check;
|
||||
return updateById(config) ? AjaxResult.success() : AjaxResult.error("修改失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本校验:配置名、房间名、奖池存在、周期合法、人数>0、门槛/机器人数非负;返回 null 表示通过
|
||||
*/
|
||||
private AjaxResult validate(TtOfficialRollConfig config) {
|
||||
if (config == null) return AjaxResult.error("参数不能为空");
|
||||
if (StringUtils.isEmpty(config.getConfigName())) return AjaxResult.error("配置标识不能为空");
|
||||
if (StringUtils.isEmpty(config.getRoomName())) return AjaxResult.error("房间名称不能为空");
|
||||
if (config.getJackpotId() == null) return AjaxResult.error("请选择奖池");
|
||||
TtRollJackpot jackpot = rollJackpotService.getById(config.getJackpotId());
|
||||
if (jackpot == null) return AjaxResult.error("指定的奖池不存在");
|
||||
String period = config.getPeriodType();
|
||||
if (!PERIOD_DAILY.equals(period)) {
|
||||
return AjaxResult.error("周期类型不合法,仅支持 DAILY");
|
||||
}
|
||||
if (config.getPeopleNum() == null || config.getPeopleNum() <= 0) {
|
||||
return AjaxResult.error("人数上限必须大于0");
|
||||
}
|
||||
if (config.getMinRecharge() != null && config.getMinRecharge().compareTo(BigDecimal.ZERO) < 0) {
|
||||
return AjaxResult.error("充值门槛不能为负数");
|
||||
}
|
||||
if (config.getRobotNum() != null && config.getRobotNum() < 0) {
|
||||
return AjaxResult.error("机器人数量不能为负数");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化默认值
|
||||
*/
|
||||
private void normalize(TtOfficialRollConfig config) {
|
||||
if (config.getMinRecharge() == null) config.setMinRecharge(BigDecimal.ZERO);
|
||||
if (config.getRobotNum() == null) config.setRobotNum(0);
|
||||
if (config.getSortBy() == null) config.setSortBy(0);
|
||||
if (StringUtils.isEmpty(config.getStatus())) config.setStatus("0");
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -132,7 +132,12 @@ public class TtUserServiceImpl extends ServiceImpl<TtUserMapper, TtUser> impleme
|
||||
wrapper.like(TtUser::getUserName, ttUserBody.getUserName());
|
||||
if (StringUtils.isNotNull(ttUserBody.getNickName()))
|
||||
wrapper.like(TtUser::getNickName, ttUserBody.getNickName());
|
||||
if (StringUtils.isNotNull(ttUserBody.getUserType())) wrapper.eq(TtUser::getUserType, ttUserBody.getUserType());
|
||||
if (StringUtils.isNotEmpty(ttUserBody.getUserType())) {
|
||||
wrapper.eq(TtUser::getUserType, ttUserBody.getUserType());
|
||||
} else {
|
||||
// 用户列表默认排除机器人(userType=03),机器人在独立的机器人管理页显式传 userType=03 查询
|
||||
wrapper.and(w -> w.isNull(TtUser::getUserType).or().ne(TtUser::getUserType, "03"));
|
||||
}
|
||||
if (StringUtils.isNotEmpty(ttUserBody.getPhoneNumber()))
|
||||
wrapper.likeRight(TtUser::getPhoneNumber, ttUserBody.getPhoneNumber());
|
||||
if (StringUtils.isNotEmpty(ttUserBody.getStatus())) wrapper.eq(TtUser::getStatus, ttUserBody.getStatus());
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
package com.ruoyi.admin.task;
|
||||
|
||||
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.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.domain.entity.roll.TtOfficialRollConfig;
|
||||
import com.ruoyi.domain.entity.roll.TtRoll;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 官方周期Roll房定时创建任务。
|
||||
* <p>
|
||||
* 注册到 RuoYi 系统监控-定时任务(由 sys_job 统一调度,不加 @Scheduled):
|
||||
* - 任务名称:官方日Roll生成 调用目标:officialRollTask.generateDailyRolls() 默认cron:0 0 10 * * ?(每天10:00)
|
||||
* <p>
|
||||
* 复用官方房(roll_type=0)语义,直接创建 tt_roll,并按配置的机器人数量自动加入机器人。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component("officialRollTask")
|
||||
public class OfficialRollTask {
|
||||
|
||||
/** 官方房类型 */
|
||||
private static final String ROLL_TYPE_OFFICIAL = "0";
|
||||
/** 未开奖状态 */
|
||||
private static final String ROLL_STATUS_OPEN = "0";
|
||||
/** 官方房创建者ID(0=官方) */
|
||||
private static final Integer OFFICIAL_USER_ID = 0;
|
||||
/** 机器人用户类型 */
|
||||
private static final String ROBOT_USER_TYPE = "03";
|
||||
|
||||
@Autowired
|
||||
private TtOfficialRollConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private TtRollService rollService;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@Autowired
|
||||
private TtRollCdkService rollCdkService;
|
||||
|
||||
/**
|
||||
* 每天为所有启用的 DAILY 配置创建当日官方roll房并自动加入机器人。
|
||||
* 充值统计起点=当天0点(今日充值),开奖=当日23:59:59。
|
||||
*/
|
||||
public void generateDailyRolls() {
|
||||
Date start = todayStart();
|
||||
Date end = todayEnd();
|
||||
generate(TtOfficialRollConfigServiceImpl.PERIOD_DAILY, start, end);
|
||||
}
|
||||
|
||||
private void generate(String periodType, Date rechargeStartTime, Date endTime) {
|
||||
log.info("[官方周期Roll] 开始生成 period={}, start={}, end={}", periodType, rechargeStartTime, endTime);
|
||||
|
||||
LambdaQueryWrapper<TtOfficialRollConfig> query = Wrappers.lambdaQuery();
|
||||
query.eq(TtOfficialRollConfig::getStatus, "0")
|
||||
.eq(TtOfficialRollConfig::getPeriodType, periodType);
|
||||
List<TtOfficialRollConfig> configs = configService.list(query);
|
||||
|
||||
if (configs == null || configs.isEmpty()) {
|
||||
log.info("[官方周期Roll] 无启用的 {} 配置,跳过", periodType);
|
||||
return;
|
||||
}
|
||||
|
||||
int created = 0;
|
||||
int skipped = 0;
|
||||
for (TtOfficialRollConfig config : configs) {
|
||||
try {
|
||||
// 幂等:同一配置 + 同一充值统计起点 至多生成一个房间
|
||||
long exists = rollService.count(Wrappers.<TtRoll>lambdaQuery()
|
||||
.eq(TtRoll::getOfficialConfigId, config.getId())
|
||||
.eq(TtRoll::getRechargeStartTime, rechargeStartTime));
|
||||
if (exists > 0) {
|
||||
skipped++;
|
||||
log.info("[官方周期Roll] 配置{}({})本周期房间已存在,跳过", config.getId(), config.getConfigName());
|
||||
continue;
|
||||
}
|
||||
|
||||
TtRoll roll = TtRoll.builder()
|
||||
.jackpotId(config.getJackpotId())
|
||||
.userId(OFFICIAL_USER_ID)
|
||||
.rollType(ROLL_TYPE_OFFICIAL)
|
||||
.rollName(config.getRoomName())
|
||||
.description(config.getDescription())
|
||||
.endTime(endTime)
|
||||
.peopleNum(config.getPeopleNum())
|
||||
.rollPassword(config.getRollPassword())
|
||||
.minRecharge(config.getMinRecharge() != null ? config.getMinRecharge() : BigDecimal.ZERO)
|
||||
.rechargeStartTime(rechargeStartTime)
|
||||
.sortBy(config.getSortBy())
|
||||
.rollStatus(ROLL_STATUS_OPEN)
|
||||
.officialConfigId(config.getId())
|
||||
.createBy("system")
|
||||
.createTime(new Date())
|
||||
.build();
|
||||
rollService.save(roll);
|
||||
|
||||
// 自动加入机器人:数量取配置值,且不超过可用机器人总数;addRobot 会自动跳过该房已有机器人
|
||||
addRobots(roll.getId(), config);
|
||||
|
||||
// 按配置数量为房间生成CDK(0则不生成,使用普通密码)
|
||||
generateCdks(roll.getId(), config);
|
||||
|
||||
// 回写上次生成时间(幂等辅助/可观测)
|
||||
TtOfficialRollConfig update = new TtOfficialRollConfig();
|
||||
update.setId(config.getId());
|
||||
update.setLastGenerateTime(new Date());
|
||||
configService.updateById(update);
|
||||
|
||||
created++;
|
||||
log.info("[官方周期Roll] 配置{}({}) 已生成房间 rollId={},起点={},开奖={}",
|
||||
config.getId(), config.getConfigName(), roll.getId(), rechargeStartTime, endTime);
|
||||
} catch (Exception e) {
|
||||
log.error("[官方周期Roll] 配置{}生成房间失败:{}", config.getId(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("[官方周期Roll] 生成完成 period={}, 配置数={}, 新建={}, 跳过={}",
|
||||
periodType, configs.size(), created, skipped);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为指定房间按配置数量加入机器人。数量取 min(配置机器人数, 可用机器人总数),避免"可用机器人数量不足"导致一个都不加。
|
||||
*/
|
||||
private void addRobots(Integer rollId, TtOfficialRollConfig config) {
|
||||
Integer robotNum = config.getRobotNum();
|
||||
if (rollId == null || robotNum == null || robotNum <= 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
long robotTotal = userService.count(new QueryWrapper<TtUser>().eq("user_type", ROBOT_USER_TYPE));
|
||||
int toAdd = (int) Math.min(robotNum.longValue(), robotTotal);
|
||||
if (toAdd <= 0) {
|
||||
log.warn("[官方周期Roll] 配置{}需要{}个机器人,但用户表无可用机器人,跳过加入", config.getId(), robotNum);
|
||||
return;
|
||||
}
|
||||
AddRobotBody body = new AddRobotBody();
|
||||
body.setRollId(rollId);
|
||||
body.setRobotNum(toAdd);
|
||||
rollService.addRobot(body);
|
||||
log.info("[官方周期Roll] 配置{} 房间{} 已尝试加入{}个机器人", config.getId(), rollId, toAdd);
|
||||
} catch (Exception e) {
|
||||
log.error("[官方周期Roll] 配置{} 房间{} 加入机器人失败:{}", config.getId(), rollId, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按配置数量为房间生成CDK;0或空则不生成(使用普通密码)。
|
||||
*/
|
||||
private void generateCdks(Integer rollId, TtOfficialRollConfig config) {
|
||||
Integer cdkCount = config.getCdkCount();
|
||||
if (rollId == null || cdkCount == null || cdkCount <= 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
rollCdkService.generateCdks(rollId, cdkCount);
|
||||
log.info("[官方周期Roll] 配置{} 房间{} 已生成{}个CDK", config.getId(), rollId, cdkCount);
|
||||
} catch (Exception e) {
|
||||
log.error("[官方周期Roll] 配置{} 房间{} 生成CDK失败:{}", config.getId(), rollId, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/** 今天0点 */
|
||||
private Date todayStart() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
clearTime(c);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
/** 今天23:59:59 */
|
||||
private Date todayEnd() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.set(Calendar.HOUR_OF_DAY, 23);
|
||||
c.set(Calendar.MINUTE, 59);
|
||||
c.set(Calendar.SECOND, 59);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
private void clearTime(Calendar c) {
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
c.set(Calendar.MINUTE, 0);
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class fightTask {
|
||||
private Executor customThreadPoolExecutor;
|
||||
|
||||
// 定时更新超时未结束的对局
|
||||
@Scheduled(cron = "0/6 * * * * ?")
|
||||
//@Scheduled(cron = "0/6 * * * * ?")
|
||||
private void refreshDayTask() {
|
||||
log.info("定时更新超时未结束的对局");
|
||||
// Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
|
||||
Reference in New Issue
Block a user