1.将部门修改为渠道,并且所有dice_表关联渠道表
2.将所有配置表,记录表设置关联渠道 3.优化后台页面设置
This commit is contained in:
@@ -6,13 +6,15 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\ante_config;
|
||||
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\helper\ConfigScopeEditHelper;
|
||||
use app\dice\model\ante_config\DiceAnteConfig;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
|
||||
/**
|
||||
* 底注配置逻辑层
|
||||
*/
|
||||
class DiceAnteConfigLogic extends BaseLogic
|
||||
class DiceAnteConfigLogic extends DiceBaseLogic
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@@ -23,21 +25,32 @@ class DiceAnteConfigLogic extends BaseLogic
|
||||
{
|
||||
return $this->transaction(function () use ($data) {
|
||||
$this->normalizeDefaultField($data);
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId(null, $data['dept_id'] ?? AdminScopeHelper::DEFAULT_TEMPLATE_DEPT);
|
||||
if ((int) ($data['is_default'] ?? 0) === 1) {
|
||||
$this->clearOtherDefaults();
|
||||
$this->clearOtherDefaults(null, $deptId);
|
||||
}
|
||||
return parent::add($data);
|
||||
});
|
||||
}
|
||||
|
||||
public function edit($id, array $data): mixed
|
||||
public function edit($id, array $data, ?array $adminInfo = null, $requestDeptId = null): mixed
|
||||
{
|
||||
return $this->transaction(function () use ($id, $data) {
|
||||
$pickedDeptId = AdminScopeHelper::pickRequestDeptId($requestDeptId, $data);
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId($adminInfo, $pickedDeptId);
|
||||
return $this->transaction(function () use ($id, $data, $deptId, $adminInfo, $pickedDeptId) {
|
||||
$this->normalizeDefaultField($data);
|
||||
if ((int) ($data['is_default'] ?? 0) === 1) {
|
||||
$this->clearOtherDefaults((int) $id);
|
||||
$this->clearOtherDefaults((int) $id, $deptId);
|
||||
}
|
||||
return parent::edit($id, $data);
|
||||
return ConfigScopeEditHelper::updateByPkAndDept(
|
||||
$this->model,
|
||||
$id,
|
||||
$deptId,
|
||||
$data,
|
||||
['id', 'dept_id', 'create_time', 'update_time', 'delete_time', 'row_id'],
|
||||
$adminInfo,
|
||||
$pickedDeptId
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,9 +92,10 @@ class DiceAnteConfigLogic extends BaseLogic
|
||||
$data['is_default'] = ((int) $data['is_default']) === 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
private function clearOtherDefaults(?int $excludeId = null): void
|
||||
private function clearOtherDefaults(?int $excludeId = null, int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): void
|
||||
{
|
||||
$query = $this->model->where('is_default', 1);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($query, $deptId);
|
||||
if ($excludeId !== null && $excludeId > 0) {
|
||||
$query->where('id', '<>', $excludeId);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\config;
|
||||
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\helper\ConfigScopeEditHelper;
|
||||
use plugin\saiadmin\basic\eloquent\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
@@ -14,7 +16,7 @@ use app\dice\model\config\DiceConfig;
|
||||
/**
|
||||
* 摇色子配置逻辑层
|
||||
*/
|
||||
class DiceConfigLogic extends BaseLogic
|
||||
class DiceConfigLogic extends DiceBaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
@@ -24,4 +26,13 @@ class DiceConfigLogic extends BaseLogic
|
||||
$this->model = new DiceConfig();
|
||||
}
|
||||
|
||||
public function edit($id, array $data, ?array $adminInfo = null, $requestDeptId = null): mixed
|
||||
{
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId(
|
||||
$adminInfo,
|
||||
AdminScopeHelper::pickRequestDeptId($requestDeptId, $data)
|
||||
);
|
||||
return ConfigScopeEditHelper::updateByBusinessIdAndDept($this->model, (int) $id, $deptId, $data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,16 +4,33 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\game;
|
||||
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\helper\ConfigScopeEditHelper;
|
||||
use plugin\saiadmin\basic\eloquent\BaseLogic;
|
||||
use app\dice\model\game\DiceGame;
|
||||
|
||||
/**
|
||||
* 游戏管理逻辑层
|
||||
*/
|
||||
class DiceGameLogic extends BaseLogic
|
||||
class DiceGameLogic extends DiceBaseLogic
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new DiceGame();
|
||||
}
|
||||
|
||||
public function edit($id, array $data, ?array $adminInfo = null, $requestDeptId = null): mixed
|
||||
{
|
||||
$pickedDeptId = AdminScopeHelper::pickRequestDeptId($requestDeptId, $data);
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId($adminInfo, $pickedDeptId);
|
||||
return ConfigScopeEditHelper::updateByPkAndDept(
|
||||
$this->model,
|
||||
$id,
|
||||
$deptId,
|
||||
$data,
|
||||
['id', 'dept_id', 'create_time', 'update_time', 'delete_time', 'row_id'],
|
||||
$adminInfo,
|
||||
$pickedDeptId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\lottery_pool_config;
|
||||
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\helper\ConfigScopeEditHelper;
|
||||
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use support\think\Cache;
|
||||
@@ -15,7 +17,7 @@ use support\think\Cache;
|
||||
/**
|
||||
* 色子奖池配置逻辑层
|
||||
*/
|
||||
class DiceLotteryPoolConfigLogic extends BaseLogic
|
||||
class DiceLotteryPoolConfigLogic extends DiceBaseLogic
|
||||
{
|
||||
/** Redis 当前彩金池(type=0 实例)key,无则按 type=0 创建 */
|
||||
private const REDIS_KEY_CURRENT_POOL = 'api:game:lottery_pool:default';
|
||||
@@ -30,19 +32,55 @@ class DiceLotteryPoolConfigLogic extends BaseLogic
|
||||
$this->model = new DiceLotteryPoolConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 按渠道隔离更新(主键 id 全局唯一,仍校验 dept_id 防止越权)
|
||||
*/
|
||||
public function edit($id, array $data, ?array $adminInfo = null, $requestDeptId = null): mixed
|
||||
{
|
||||
$pickedDeptId = AdminScopeHelper::pickRequestDeptId($requestDeptId, $data);
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId($adminInfo, $pickedDeptId);
|
||||
return ConfigScopeEditHelper::updateByPkAndDept(
|
||||
$this->model,
|
||||
$id,
|
||||
$deptId,
|
||||
$data,
|
||||
['id', 'dept_id', 'create_time', 'update_time', 'delete_time', 'row_id'],
|
||||
$adminInfo,
|
||||
$pickedDeptId
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前彩金池(type=0)+ 杀分权重为 type=1 的只读展示
|
||||
* profit_amount 每次从 DB 实时读取;t1_weight~t5_weight 来自 type=1(杀分权重,不可在弹窗内修改)
|
||||
*
|
||||
* @return array{id:int,name:string,safety_line:int,kill_enabled:int,t1_weight:int,...,t5_weight:int,profit_amount:float}
|
||||
*/
|
||||
public function getCurrentPool(): array
|
||||
public function getCurrentPool(int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): array
|
||||
{
|
||||
$configType0 = DiceLotteryPoolConfig::where('name', 'default')->find();
|
||||
$query0 = DiceLotteryPoolConfig::where('name', 'default');
|
||||
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
$query0->where(function ($q) {
|
||||
$q->where('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT)
|
||||
->whereOr('dept_id', null);
|
||||
});
|
||||
} else {
|
||||
$query0->where('dept_id', $deptId);
|
||||
}
|
||||
$configType0 = $query0->find();
|
||||
if (!$configType0) {
|
||||
throw new ApiException('No name=default pool config found, please create one first');
|
||||
}
|
||||
$configType1 = DiceLotteryPoolConfig::where('name', 'killScore')->find();
|
||||
$query1 = DiceLotteryPoolConfig::where('name', 'killScore');
|
||||
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
$query1->where(function ($q) {
|
||||
$q->where('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT)
|
||||
->whereOr('dept_id', null);
|
||||
});
|
||||
} else {
|
||||
$query1->where('dept_id', $deptId);
|
||||
}
|
||||
$configType1 = $query1->find();
|
||||
$row0 = $configType0->toArray();
|
||||
$profitAmount = isset($row0['profit_amount']) ? (float) $row0['profit_amount'] : (isset($row0['ev']) ? (float) $row0['ev'] : 0.0);
|
||||
$pool = [
|
||||
@@ -66,9 +104,9 @@ class DiceLotteryPoolConfigLogic extends BaseLogic
|
||||
*
|
||||
* @param array{safety_line?:int,kill_enabled?:int} $data
|
||||
*/
|
||||
public function updateCurrentPool(array $data): void
|
||||
public function updateCurrentPool(array $data, int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): void
|
||||
{
|
||||
$pool = $this->getCurrentPool();
|
||||
$pool = $this->getCurrentPool($deptId);
|
||||
$id = (int) $pool['id'];
|
||||
if (!array_key_exists('safety_line', $data) && !array_key_exists('kill_enabled', $data)) {
|
||||
return;
|
||||
@@ -83,17 +121,21 @@ class DiceLotteryPoolConfigLogic extends BaseLogic
|
||||
if ($update === []) {
|
||||
return;
|
||||
}
|
||||
DiceLotteryPoolConfig::where('id', $id)->update($update);
|
||||
$query = DiceLotteryPoolConfig::where('id', $id);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($query, $deptId);
|
||||
$query->update($update);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置当前彩金池的玩家累计盈利:将 profit_amount 置为 0,并刷新 Redis 缓存
|
||||
*/
|
||||
public function resetProfitAmount(): void
|
||||
public function resetProfitAmount(int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): void
|
||||
{
|
||||
$pool = $this->getCurrentPool();
|
||||
$pool = $this->getCurrentPool($deptId);
|
||||
$id = (int) $pool['id'];
|
||||
DiceLotteryPoolConfig::where('id', $id)->update(['profit_amount' => 0]);
|
||||
$query = DiceLotteryPoolConfig::where('id', $id);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($query, $deptId);
|
||||
$query->update(['profit_amount' => 0]);
|
||||
$pool['profit_amount'] = 0.0;
|
||||
Cache::set(self::REDIS_KEY_CURRENT_POOL, json_encode($pool), self::EXPIRE);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\play_record;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use app\dice\model\play_record\DicePlayRecord;
|
||||
@@ -14,7 +14,7 @@ use app\dice\model\play_record\DicePlayRecord;
|
||||
/**
|
||||
* 玩家抽奖记录逻辑层
|
||||
*/
|
||||
class DicePlayRecordLogic extends BaseLogic
|
||||
class DicePlayRecordLogic extends DiceBaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\play_record_test;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use app\dice\model\play_record_test\DicePlayRecordTest;
|
||||
@@ -14,7 +14,7 @@ use app\dice\model\play_record_test\DicePlayRecordTest;
|
||||
/**
|
||||
* 玩家抽奖记录(测试数据)逻辑层
|
||||
*/
|
||||
class DicePlayRecordTestLogic extends BaseLogic
|
||||
class DicePlayRecordTestLogic extends DiceBaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\player;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use app\dice\model\player\DicePlayer;
|
||||
@@ -14,7 +14,7 @@ use app\dice\model\player\DicePlayer;
|
||||
/**
|
||||
* 大富翁-玩家逻辑层
|
||||
*/
|
||||
class DicePlayerLogic extends BaseLogic
|
||||
class DicePlayerLogic extends DiceBaseLogic
|
||||
{
|
||||
/** 密码加密盐(可与 config 统一) */
|
||||
private const PASSWORD_SALT = 'dice_player_salt_2024';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\player_ticket_record;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use app\dice\model\player_ticket_record\DicePlayerTicketRecord;
|
||||
@@ -14,7 +14,7 @@ use app\dice\model\player_ticket_record\DicePlayerTicketRecord;
|
||||
/**
|
||||
* 抽奖券获取记录逻辑层
|
||||
*/
|
||||
class DicePlayerTicketRecordLogic extends BaseLogic
|
||||
class DicePlayerTicketRecordLogic extends DiceBaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\player_wallet_record;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use app\dice\model\player_wallet_record\DicePlayerWalletRecord;
|
||||
use app\dice\model\player\DicePlayer;
|
||||
@@ -15,7 +16,7 @@ use app\api\cache\UserCache;
|
||||
/**
|
||||
* 玩家钱包流水逻辑层
|
||||
*/
|
||||
class DicePlayerWalletRecordLogic extends BaseLogic
|
||||
class DicePlayerWalletRecordLogic extends DiceBaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
@@ -27,6 +28,18 @@ class DicePlayerWalletRecordLogic extends BaseLogic
|
||||
$this->setOrderType('DESC');
|
||||
}
|
||||
|
||||
/**
|
||||
* 按与列表相同的筛选条件汇总平台币变化(不含 with / 分页 / 排序)
|
||||
*/
|
||||
public function sumCoinBySearch(array $where, ?array $adminInfo, $requestDeptId = null): float
|
||||
{
|
||||
$query = $this->search($where);
|
||||
AdminScopeHelper::applyAdminScope($query, $adminInfo, $requestDeptId);
|
||||
$table = $this->model->getTable();
|
||||
$sum = $query->sum($table . '.coin');
|
||||
return round((float) $sum, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据(补全抽奖次数字段默认值)
|
||||
*/
|
||||
@@ -83,9 +96,11 @@ class DicePlayerWalletRecordLogic extends BaseLogic
|
||||
}
|
||||
|
||||
$playerAdminId = ($player->admin_id ?? null) ? (int) $player->admin_id : null;
|
||||
$playerDeptId = ($player->dept_id ?? null) ? (int) $player->dept_id : null;
|
||||
$record = [
|
||||
'player_id' => $playerId,
|
||||
'admin_id' => $playerAdminId,
|
||||
'dept_id' => $playerDeptId,
|
||||
'coin' => $type === 3 ? $coin : -$coin,
|
||||
'type' => $type,
|
||||
'wallet_before' => $walletBefore,
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\reward;
|
||||
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\helper\ConfigScopeEditHelper;
|
||||
use app\dice\model\reward\DiceReward;
|
||||
use app\dice\model\reward_config\DiceRewardConfig;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
@@ -29,8 +31,14 @@ class DiceRewardLogic
|
||||
* @param int $limit
|
||||
* @return array{total: int, per_page: int, current_page: int, data: array}
|
||||
*/
|
||||
public function getListWithConfig(int $direction, array $where, int $page = 1, int $limit = 10): array
|
||||
{
|
||||
public function getListWithConfig(
|
||||
int $direction,
|
||||
array $where,
|
||||
int $page = 1,
|
||||
int $limit = 10,
|
||||
?array $adminInfo = null,
|
||||
$requestDeptId = null
|
||||
): array {
|
||||
$tier = isset($where['tier']) ? trim((string) $where['tier']) : '';
|
||||
$orderField = isset($where['orderField']) && $where['orderField'] !== '' ? (string) $where['orderField'] : 'r.tier';
|
||||
$orderType = isset($where['orderType']) && strtoupper((string) $where['orderType']) === 'DESC' ? 'desc' : 'asc';
|
||||
@@ -41,6 +49,10 @@ class DiceRewardLogic
|
||||
->order($orderField, $orderType)
|
||||
->order('r.end_index', 'asc');
|
||||
|
||||
if ($adminInfo !== null) {
|
||||
AdminScopeHelper::applyConfigScope($query, $adminInfo, $requestDeptId, 'r.dept_id');
|
||||
}
|
||||
|
||||
if ($tier !== '') {
|
||||
$query->where('r.tier', $tier);
|
||||
}
|
||||
@@ -74,7 +86,7 @@ class DiceRewardLogic
|
||||
* @param int $direction 0=顺时针 1=逆时针
|
||||
* @param array<int, array{id: int, weight: int}> $items id 为 end_index(DiceRewardConfig.id)
|
||||
*/
|
||||
public function batchUpdateWeightsByDirection(int $direction, array $items): void
|
||||
public function batchUpdateWeightsByDirection(int $direction, array $items, ?int $deptId = null): void
|
||||
{
|
||||
if (empty($items)) {
|
||||
return;
|
||||
@@ -90,23 +102,36 @@ class DiceRewardLogic
|
||||
}
|
||||
$weight = max(self::WEIGHT_MIN, min(self::WEIGHT_MAX, $weight));
|
||||
|
||||
$tier = DiceRewardConfig::where('id', $id)->value('tier');
|
||||
$configQuery = DiceRewardConfig::where('id', $id);
|
||||
if ($deptId !== null) {
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($configQuery, $deptId);
|
||||
}
|
||||
$tier = $configQuery->value('tier');
|
||||
if ($tier === null || $tier === '') {
|
||||
throw new ApiException(\app\api\util\ApiLang::translateParams('配置ID %s 不存在或档位为空', [$id]));
|
||||
}
|
||||
$tier = (string) $tier;
|
||||
|
||||
$affected = DiceReward::where('tier', $tier)->where('direction', $direction)->where('end_index', $id)->update(['weight' => $weight]);
|
||||
$rewardQuery = DiceReward::where('tier', $tier)
|
||||
->where('direction', $direction)
|
||||
->where('end_index', $id);
|
||||
if ($deptId !== null) {
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($rewardQuery, $deptId);
|
||||
}
|
||||
$affected = $rewardQuery->update(['weight' => $weight]);
|
||||
if ($affected === 0) {
|
||||
$m = new DiceReward();
|
||||
$m->tier = $tier;
|
||||
$m->direction = $direction;
|
||||
$m->end_index = $id;
|
||||
$m->weight = $weight;
|
||||
if ($deptId !== null && $deptId > 0) {
|
||||
$m->dept_id = $deptId;
|
||||
}
|
||||
$m->save();
|
||||
}
|
||||
}
|
||||
DiceReward::refreshCache();
|
||||
DiceReward::refreshCache($deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,11 +139,11 @@ class DiceRewardLogic
|
||||
* @param int $direction 0=顺时针 1=逆时针
|
||||
* @return array<string, array> 键 T1|T2|...|BIGWIN,值为该档位下带 weight 的行数组
|
||||
*/
|
||||
public function getListGroupedByTierForDirection(int $direction): array
|
||||
public function getListGroupedByTierForDirection(int $direction, ?int $deptId = null): array
|
||||
{
|
||||
$configInstance = DiceRewardConfig::getCachedInstance();
|
||||
$configInstance = DiceRewardConfig::getCachedInstance($deptId);
|
||||
$byTier = $configInstance['by_tier'] ?? [];
|
||||
$rewardInstance = DiceReward::getCachedInstance();
|
||||
$rewardInstance = DiceReward::getCachedInstance($deptId);
|
||||
$byTierDirection = $rewardInstance['by_tier_direction'] ?? [];
|
||||
|
||||
$result = [];
|
||||
@@ -153,9 +178,9 @@ class DiceRewardLogic
|
||||
*
|
||||
* @return array<string, array{0: array, 1: array}>
|
||||
*/
|
||||
public function getListGroupedByTierWithDirection(): array
|
||||
public function getListGroupedByTierWithDirection(?int $deptId = null): array
|
||||
{
|
||||
$rewardInstance = DiceReward::getCachedInstance();
|
||||
$rewardInstance = DiceReward::getCachedInstance($deptId);
|
||||
$byTierDirection = $rewardInstance['by_tier_direction'] ?? [];
|
||||
|
||||
$result = [];
|
||||
@@ -185,7 +210,7 @@ class DiceRewardLogic
|
||||
* @param array<int, array{id: int, weight: int}> $items 每项 id 为 dice_reward 表主键,weight 为 1-10000
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function batchUpdateWeights(array $items): void
|
||||
public function batchUpdateWeights(array $items, ?int $deptId = null): void
|
||||
{
|
||||
if (empty($items)) {
|
||||
return;
|
||||
@@ -203,13 +228,24 @@ class DiceRewardLogic
|
||||
}
|
||||
$weight = isset($item['weight']) ? (int) $item['weight'] : self::WEIGHT_MIN;
|
||||
$weight = max(self::WEIGHT_MIN, min(self::WEIGHT_MAX, $weight));
|
||||
$model = DiceReward::find($id);
|
||||
$query = DiceReward::where('id', $id);
|
||||
if ($deptId !== null) {
|
||||
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
$query->where(function ($q) {
|
||||
$q->where('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT)
|
||||
->whereOr('dept_id', null);
|
||||
});
|
||||
} else {
|
||||
$query->where('dept_id', $deptId);
|
||||
}
|
||||
}
|
||||
$model = $query->find();
|
||||
if ($model !== null) {
|
||||
$model->weight = $weight;
|
||||
$model->save();
|
||||
}
|
||||
}
|
||||
DiceReward::refreshCache();
|
||||
DiceReward::refreshCache($deptId);
|
||||
}
|
||||
|
||||
/** BIGWIN 权重范围:0=0% 中奖,10000=100% 中奖;grid_number=5/30 固定 100% 不可改 */
|
||||
@@ -219,9 +255,9 @@ class DiceRewardLogic
|
||||
* 按 grid_number 获取 BIGWIN 档位权重(取顺时针方向,用于编辑展示)
|
||||
* 若 DiceReward 无该点数则 5/30 返回 10000,其余返回 0
|
||||
*/
|
||||
public function getBigwinWeightByGridNumber(int $gridNumber): int
|
||||
public function getBigwinWeightByGridNumber(int $gridNumber, ?int $deptId = null): int
|
||||
{
|
||||
$inst = DiceReward::getCachedInstance();
|
||||
$inst = DiceReward::getCachedInstance($deptId);
|
||||
$rows = $inst['by_tier_direction']['BIGWIN'][DiceReward::DIRECTION_CLOCKWISE] ?? [];
|
||||
foreach ($rows as $row) {
|
||||
if ((int) ($row['grid_number'] ?? 0) === $gridNumber) {
|
||||
@@ -235,21 +271,24 @@ class DiceRewardLogic
|
||||
* 更新 BIGWIN 档位某点数的权重(顺/逆时针同时更新);0=0% 中奖,10000=100% 中奖
|
||||
* 表 dice_reward 唯一键为 (direction, grid_number),同一点数同一方向仅一条记录,故先按该键查找再更新,避免重复插入
|
||||
*/
|
||||
public function updateBigwinWeight(int $gridNumber, int $weight): void
|
||||
public function updateBigwinWeight(int $gridNumber, int $weight, ?int $deptId = null): void
|
||||
{
|
||||
$weight = min(self::BIGWIN_WEIGHT_MAX, max(0, $weight));
|
||||
$config = DiceRewardConfig::where('tier', 'BIGWIN')
|
||||
->where('grid_number', $gridNumber)
|
||||
->find();
|
||||
if ($deptId === null) {
|
||||
$deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
|
||||
}
|
||||
$configQuery = DiceRewardConfig::where('tier', 'BIGWIN')->where('grid_number', $gridNumber);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($configQuery, $deptId);
|
||||
$config = $configQuery->find();
|
||||
if (! $config) {
|
||||
return;
|
||||
}
|
||||
$configArr = $config->toArray();
|
||||
foreach ([DiceReward::DIRECTION_CLOCKWISE, DiceReward::DIRECTION_COUNTERCLOCKWISE] as $direction) {
|
||||
// 按唯一键 (direction, grid_number) 查找,存在则更新,不存在则插入
|
||||
$row = DiceReward::where('direction', $direction)
|
||||
->where('grid_number', $gridNumber)
|
||||
->find();
|
||||
$rowQuery = DiceReward::where('direction', $direction)->where('grid_number', $gridNumber);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($rowQuery, $deptId);
|
||||
$row = $rowQuery->find();
|
||||
if ($row) {
|
||||
$row->tier = 'BIGWIN';
|
||||
$row->weight = $weight > 0 ? $weight : self::WEIGHT_MIN;
|
||||
@@ -272,10 +311,13 @@ class DiceRewardLogic
|
||||
$m->remark = (string) ($configArr['remark'] ?? '');
|
||||
$m->type = $configArr['type'] ?? null;
|
||||
$m->weight = $weight > 0 ? $weight : self::WEIGHT_MIN;
|
||||
if (!AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
$m->dept_id = $deptId;
|
||||
}
|
||||
$m->save();
|
||||
}
|
||||
}
|
||||
DiceReward::refreshCache();
|
||||
DiceReward::refreshCache($deptId);
|
||||
}
|
||||
|
||||
/** 盘面格数(用于顺时针/逆时针计算 end_index) */
|
||||
@@ -309,9 +351,19 @@ class DiceRewardLogic
|
||||
* @return array{created_clockwise: int, created_counterclockwise: int, updated_clockwise: int, updated_counterclockwise: int, skipped: int}
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function createRewardReferenceFromConfig(): array
|
||||
public function createRewardReferenceFromConfig(?int $deptId = null): array
|
||||
{
|
||||
$list = DiceRewardConfig::order('id', 'asc')->select()->toArray();
|
||||
$configQuery = DiceRewardConfig::order('id', 'asc');
|
||||
if ($deptId === null || $deptId === \app\dice\helper\AdminScopeHelper::DEFAULT_TEMPLATE_DEPT) {
|
||||
$templateId = \app\dice\helper\AdminScopeHelper::DEFAULT_TEMPLATE_DEPT;
|
||||
$configQuery->where(function ($q) use ($templateId) {
|
||||
$q->where('dept_id', $templateId)->whereOr('dept_id', 'null');
|
||||
});
|
||||
$deptId = null;
|
||||
} else {
|
||||
$configQuery->where('dept_id', $deptId);
|
||||
}
|
||||
$list = $configQuery->select()->toArray();
|
||||
if (empty($list)) {
|
||||
throw new ApiException('Reward config is empty, please maintain dice_reward_config first');
|
||||
}
|
||||
@@ -326,8 +378,12 @@ class DiceRewardLogic
|
||||
}
|
||||
|
||||
$table = (new DiceReward())->getTable();
|
||||
Db::execute('DELETE FROM `' . $table . '`');
|
||||
DiceReward::refreshCache();
|
||||
if ($deptId === null) {
|
||||
Db::table($table)->whereNull('dept_id')->delete();
|
||||
} else {
|
||||
Db::table($table)->where('dept_id', $deptId)->delete();
|
||||
}
|
||||
DiceReward::refreshCache($deptId ?? AdminScopeHelper::DEFAULT_TEMPLATE_DEPT);
|
||||
|
||||
// 按 id 排序后,盘面位置 0..25 对应 $list[$pos],避免 config.id 非 0-25/1-26 时取模结果找不到
|
||||
$gridToPosition = [];
|
||||
@@ -379,7 +435,13 @@ class DiceRewardLogic
|
||||
'remark' => $configCw['remark'] ?? '',
|
||||
'type' => isset($configCw['type']) ? (int) $configCw['type'] : 0,
|
||||
];
|
||||
$existing = DiceReward::where('direction', DiceReward::DIRECTION_CLOCKWISE)->where('grid_number', $gridNumber)->find();
|
||||
$existingQuery = DiceReward::where('direction', DiceReward::DIRECTION_CLOCKWISE)->where('grid_number', $gridNumber);
|
||||
if ($deptId === null) {
|
||||
$existingQuery->whereNull('dept_id');
|
||||
} else {
|
||||
$existingQuery->where('dept_id', $deptId);
|
||||
}
|
||||
$existing = $existingQuery->find();
|
||||
if ($existing) {
|
||||
DiceReward::where('id', $existing->id)->update($payloadCw);
|
||||
$updatedCw++;
|
||||
@@ -395,6 +457,9 @@ class DiceRewardLogic
|
||||
$m->real_ev = $configCw['real_ev'] ?? null;
|
||||
$m->remark = $configCw['remark'] ?? '';
|
||||
$m->type = isset($configCw['type']) ? (int) $configCw['type'] : 0;
|
||||
if ($deptId !== null) {
|
||||
$m->dept_id = $deptId;
|
||||
}
|
||||
$m->save();
|
||||
$createdCw++;
|
||||
}
|
||||
@@ -419,7 +484,13 @@ class DiceRewardLogic
|
||||
'remark' => $configCcw['remark'] ?? '',
|
||||
'type' => isset($configCcw['type']) ? (int) $configCcw['type'] : 0,
|
||||
];
|
||||
$existing = DiceReward::where('direction', DiceReward::DIRECTION_COUNTERCLOCKWISE)->where('grid_number', $gridNumber)->find();
|
||||
$existingQuery = DiceReward::where('direction', DiceReward::DIRECTION_COUNTERCLOCKWISE)->where('grid_number', $gridNumber);
|
||||
if ($deptId === null) {
|
||||
$existingQuery->whereNull('dept_id');
|
||||
} else {
|
||||
$existingQuery->where('dept_id', $deptId);
|
||||
}
|
||||
$existing = $existingQuery->find();
|
||||
if ($existing) {
|
||||
DiceReward::where('id', $existing->id)->update($payloadCcw);
|
||||
$updatedCcw++;
|
||||
@@ -435,6 +506,9 @@ class DiceRewardLogic
|
||||
$m->real_ev = $configCcw['real_ev'] ?? null;
|
||||
$m->remark = $configCcw['remark'] ?? '';
|
||||
$m->type = isset($configCcw['type']) ? (int) $configCcw['type'] : 0;
|
||||
if ($deptId !== null) {
|
||||
$m->dept_id = $deptId;
|
||||
}
|
||||
$m->save();
|
||||
$createdCcw++;
|
||||
}
|
||||
@@ -442,7 +516,7 @@ class DiceRewardLogic
|
||||
}
|
||||
}
|
||||
|
||||
DiceReward::refreshCache();
|
||||
DiceReward::refreshCache($deptId ?? AdminScopeHelper::DEFAULT_TEMPLATE_DEPT);
|
||||
return [
|
||||
'created_clockwise' => $createdCw,
|
||||
'created_counterclockwise' => $createdCcw,
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\reward_config;
|
||||
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\helper\ConfigScopeEditHelper;
|
||||
use app\dice\logic\reward\DiceRewardLogic;
|
||||
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
||||
use app\dice\model\reward\DiceRewardConfig;
|
||||
use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use support\Log;
|
||||
@@ -19,7 +21,7 @@ use support\Log;
|
||||
* 奖励配置逻辑层(DiceRewardConfig)
|
||||
* weight 1-10000,各档位权重和不限制
|
||||
*/
|
||||
class DiceRewardConfigLogic extends BaseLogic
|
||||
class DiceRewardConfigLogic extends DiceBaseLogic
|
||||
{
|
||||
/** weight 取值范围 */
|
||||
private const WEIGHT_MIN = 1;
|
||||
@@ -36,18 +38,23 @@ class DiceRewardConfigLogic extends BaseLogic
|
||||
public function add(array $data): mixed
|
||||
{
|
||||
$result = parent::add($data);
|
||||
DiceRewardConfig::refreshCache();
|
||||
$deptId = AdminScopeHelper::normalizeRecordDeptId($data['dept_id'] ?? null);
|
||||
DiceRewardConfig::refreshCache($deptId);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改:保存后刷新缓存;BIGWIN 的 weight 直接写入 dice_reward_config 表,抽奖时从 Config 读取
|
||||
* 修改:按业务 id + 渠道更新;保存后刷新该渠道缓存
|
||||
*/
|
||||
public function edit($id, array $data): mixed
|
||||
public function edit($id, array $data, ?array $adminInfo = null, $requestDeptId = null): mixed
|
||||
{
|
||||
$result = parent::edit($id, $data);
|
||||
DiceRewardConfig::refreshCache();
|
||||
return $result;
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId(
|
||||
$adminInfo,
|
||||
AdminScopeHelper::pickRequestDeptId($requestDeptId, $data)
|
||||
);
|
||||
ConfigScopeEditHelper::updateByBusinessIdAndDept($this->model, (int) $id, $deptId, $data);
|
||||
DiceRewardConfig::refreshCache($deptId);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,8 +159,9 @@ class DiceRewardConfigLogic extends BaseLogic
|
||||
/**
|
||||
* 批量更新奖励索引配置:grid_number、ui_text、real_ev、tier、remark(不含 weight,BIGWIN 权重单独接口)
|
||||
* @param array $items 每项 [id, grid_number?, ui_text?, real_ev?, tier?, remark?]
|
||||
* @param int $deptId 渠道 ID(0=默认模板)
|
||||
*/
|
||||
public function batchUpdate(array $items): void
|
||||
public function batchUpdate(array $items, int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): void
|
||||
{
|
||||
foreach ($items as $row) {
|
||||
if (! array_key_exists('id', $row) || $row['id'] === null || $row['id'] === '') {
|
||||
@@ -167,10 +175,18 @@ class DiceRewardConfigLogic extends BaseLogic
|
||||
}
|
||||
}
|
||||
if (! empty($data)) {
|
||||
parent::edit($id, $data);
|
||||
$this->updateByBusinessIdAndDept($id, $deptId, $data);
|
||||
}
|
||||
}
|
||||
DiceRewardConfig::refreshCache();
|
||||
DiceRewardConfig::refreshCache($deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按业务 id(0~25)与渠道更新单条配置
|
||||
*/
|
||||
private function updateByBusinessIdAndDept(int $businessId, int $deptId, array $data): void
|
||||
{
|
||||
ConfigScopeEditHelper::updateByBusinessIdAndDept($this->model, $businessId, $deptId, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,8 +217,9 @@ class DiceRewardConfigLogic extends BaseLogic
|
||||
/**
|
||||
* 批量更新 BIGWIN 档位权重(仅写 dice_reward_config 表,不操作 dice_reward)
|
||||
* @param array $items 每项 [grid_number => 5-30, weight => 0-10000]
|
||||
* @param int $deptId 渠道 ID(0=默认模板)
|
||||
*/
|
||||
public function batchUpdateBigwinWeight(array $items): void
|
||||
public function batchUpdateBigwinWeight(array $items, int $deptId = AdminScopeHelper::DEFAULT_TEMPLATE_DEPT): void
|
||||
{
|
||||
$weightMin = 0;
|
||||
$weightMax = 10000;
|
||||
@@ -213,21 +230,33 @@ class DiceRewardConfigLogic extends BaseLogic
|
||||
continue;
|
||||
}
|
||||
$weight = max($weightMin, min($weightMax, $weight));
|
||||
$this->model->where('tier', 'BIGWIN')
|
||||
->where('grid_number', $gridNumber)
|
||||
->update(['weight' => $weight]);
|
||||
$query = $this->model->where('tier', 'BIGWIN')->where('grid_number', $gridNumber);
|
||||
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
$query->where(function ($q) {
|
||||
$q->where('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT)
|
||||
->whereOr('dept_id', null);
|
||||
});
|
||||
} else {
|
||||
$query->where('dept_id', $deptId);
|
||||
}
|
||||
$exists = (clone $query)->find();
|
||||
if ($exists === null) {
|
||||
throw new ApiException('BIGWIN grid_number=' . $gridNumber . ' not found for current channel');
|
||||
}
|
||||
$query->update(['weight' => $weight]);
|
||||
}
|
||||
DiceRewardConfig::refreshCache();
|
||||
DiceRewardConfig::refreshCache($deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除后刷新缓存
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
public function destroy($ids, ?array $adminInfo = null, $requestDeptId = null): bool
|
||||
{
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId($adminInfo, $requestDeptId);
|
||||
$result = parent::destroy($ids);
|
||||
if ($result) {
|
||||
DiceRewardConfig::refreshCache();
|
||||
DiceRewardConfig::refreshCache($deptId);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
@@ -403,6 +432,12 @@ class DiceRewardConfigLogic extends BaseLogic
|
||||
$record->lottery_config_id = $config ? (int) $config->id : null;
|
||||
$record->result_counts = $counts;
|
||||
$record->admin_id = $adminId;
|
||||
if ($adminId > 0) {
|
||||
$admin = \plugin\saiadmin\app\model\system\SystemUser::find($adminId);
|
||||
if ($admin && !empty($admin->dept_id)) {
|
||||
$record->dept_id = $admin->dept_id;
|
||||
}
|
||||
}
|
||||
$record->create_time = date('Y-m-d H:i:s');
|
||||
$record->save();
|
||||
$recordId = (int) $record->id;
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\dice\logic\reward_config_record;
|
||||
|
||||
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
||||
use app\api\util\ApiLang;
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\helper\ConfigScopeEditHelper;
|
||||
use app\dice\model\ante_config\DiceAnteConfig;
|
||||
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
||||
use app\dice\model\reward\DiceReward;
|
||||
use app\dice\model\reward\DiceRewardConfig;
|
||||
use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use app\dice\basic\DiceBaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\app\model\system\SystemUser;
|
||||
|
||||
@@ -17,7 +20,7 @@ use plugin\saiadmin\app\model\system\SystemUser;
|
||||
* 奖励配置权重测试记录逻辑层
|
||||
*
|
||||
*/
|
||||
class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
class DiceRewardConfigRecordLogic extends DiceBaseLogic
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@@ -88,6 +91,7 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
throw new ApiException('Test record not found');
|
||||
}
|
||||
$record = is_array($record) ? $record : $record->toArray();
|
||||
$configDeptId = AdminScopeHelper::normalizeRecordDeptId($record['dept_id'] ?? null);
|
||||
|
||||
$snapshot = $record['weight_config_snapshot'] ?? null;
|
||||
if (is_string($snapshot)) {
|
||||
@@ -112,9 +116,9 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
$tier = $tierFromDb !== null ? (string) $tierFromDb : '';
|
||||
}
|
||||
// 仅按方向 + 点数更新 DiceReward(若存在则更新,不存在才插入,避免唯一键冲突)
|
||||
$reward = DiceReward::where('direction', $direction)
|
||||
->where('grid_number', $gridNumber)
|
||||
->find();
|
||||
$rewardQuery = DiceReward::where('direction', $direction)->where('grid_number', $gridNumber);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($rewardQuery, $configDeptId);
|
||||
$reward = $rewardQuery->find();
|
||||
if ($reward) {
|
||||
$reward->weight = $weight;
|
||||
// 若快照中有 tier,补齐 tier 信息
|
||||
@@ -130,10 +134,13 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
$m->direction = $direction;
|
||||
$m->grid_number = $gridNumber;
|
||||
$m->weight = $weight;
|
||||
if (!AdminScopeHelper::isTemplateDeptId($configDeptId)) {
|
||||
$m->dept_id = $configDeptId;
|
||||
}
|
||||
$m->save();
|
||||
}
|
||||
}
|
||||
DiceReward::refreshCache();
|
||||
DiceReward::refreshCache($configDeptId);
|
||||
}
|
||||
|
||||
// 使用记录中的 bigwin_weight JSON 将 BIGWIN 概率导入到 DiceRewardConfig
|
||||
@@ -152,11 +159,11 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
if ($weight < 0) {
|
||||
$weight = 0;
|
||||
}
|
||||
DiceRewardConfig::where('tier', 'BIGWIN')
|
||||
->where('grid_number', $gridNumber)
|
||||
->update(['weight' => $weight]);
|
||||
$bigwinQuery = DiceRewardConfig::where('tier', 'BIGWIN')->where('grid_number', $gridNumber);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($bigwinQuery, $configDeptId);
|
||||
$bigwinQuery->update(['weight' => $weight]);
|
||||
}
|
||||
DiceRewardConfig::refreshCache();
|
||||
DiceRewardConfig::refreshCache($configDeptId);
|
||||
}
|
||||
|
||||
$tiers = ['T1', 'T2', 'T3', 'T4', 'T5'];
|
||||
@@ -225,7 +232,8 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
DiceLotteryPoolConfig::where('id', $freeTargetId)->update($update);
|
||||
}
|
||||
|
||||
DiceRewardConfig::refreshCache();
|
||||
DiceRewardConfig::refreshCache($configDeptId);
|
||||
DiceReward::refreshCache($configDeptId);
|
||||
DiceRewardConfig::clearRequestInstance();
|
||||
}
|
||||
|
||||
@@ -237,8 +245,12 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
* @return int 记录 ID
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function createWeightTestRecord(array|int $params, mixed $adminIdOrFreeS = null, mixed $freeSOrFreeN = null, mixed $freeN = null): int
|
||||
{
|
||||
public function createWeightTestRecord(
|
||||
array|int $params,
|
||||
mixed $adminIdOrFreeS = null,
|
||||
?array $adminInfo = null,
|
||||
$requestDeptId = null
|
||||
): int {
|
||||
$adminId = null;
|
||||
if (!is_array($params)) {
|
||||
// 兼容旧版调用:createWeightTestRecord(paid_s_count, paid_n_count)
|
||||
@@ -249,15 +261,14 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
} else {
|
||||
$adminId = $adminIdOrFreeS !== null && $adminIdOrFreeS !== '' ? (int) $adminIdOrFreeS : null;
|
||||
}
|
||||
|
||||
$deptId = $this->resolveWeightTestDeptId(
|
||||
$adminInfo,
|
||||
AdminScopeHelper::pickRequestDeptId($requestDeptId, is_array($params) ? $params : []),
|
||||
is_array($params) ? $params : []
|
||||
);
|
||||
$allowed = [100, 500, 1000, 5000];
|
||||
$ante = isset($params['ante']) ? intval($params['ante']) : 1;
|
||||
if ($ante <= 0) {
|
||||
throw new ApiException('ante must be greater than 0');
|
||||
}
|
||||
$anteExists = DiceAnteConfig::where('mult', $ante)->count();
|
||||
if ($anteExists <= 0) {
|
||||
throw new ApiException('ante not allowed: ' . $ante);
|
||||
}
|
||||
$ante = $this->resolveWeightTestAnte($params, $deptId);
|
||||
|
||||
$lotteryConfigId = isset($params['lottery_config_id']) ? (int) $params['lottery_config_id'] : 0;
|
||||
$paidConfigId = isset($params['paid_lottery_config_id']) ? (int) $params['paid_lottery_config_id'] : 0;
|
||||
@@ -296,8 +307,8 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
$paidTierWeights = null;
|
||||
$freeTierWeights = null;
|
||||
|
||||
// 来自 DiceReward 的当前权重快照(按方向+点数),用于权重测试模拟
|
||||
$instance = DiceReward::getCachedInstance();
|
||||
// 来自当前渠道的 DiceReward 权重快照(按方向+点数),用于权重测试模拟
|
||||
$instance = DiceReward::getCachedInstance($deptId);
|
||||
$byTierDirection = $instance['by_tier_direction'] ?? [];
|
||||
foreach ($byTierDirection as $tier => $byDir) {
|
||||
foreach ($byDir as $dir => $rows) {
|
||||
@@ -316,7 +327,7 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
// BIGWIN 概率快照从 DiceRewardConfig 读取(例如豹子号配置)
|
||||
// JSON 结构 {"grid_number": weight, ...}
|
||||
$bigwinWeights = [];
|
||||
$bigwinConfigs = DiceRewardConfig::getCachedByTier('BIGWIN');
|
||||
$bigwinConfigs = DiceRewardConfig::getCachedByTier('BIGWIN', $deptId);
|
||||
foreach ($bigwinConfigs as $cfg) {
|
||||
$grid = isset($cfg['grid_number']) ? (int) $cfg['grid_number'] : 0;
|
||||
if ($grid <= 0) {
|
||||
@@ -327,10 +338,7 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
}
|
||||
|
||||
if ($paidConfigId > 0) {
|
||||
$config = DiceLotteryPoolConfig::find($paidConfigId);
|
||||
if (!$config) {
|
||||
throw new ApiException('Paid pool config not found');
|
||||
}
|
||||
$config = $this->findPoolConfigInDept($paidConfigId, $deptId, 'Paid pool config not found');
|
||||
$tierWeightsSnapshot['paid'] = [
|
||||
'T1' => (int) ($config->t1_weight ?? 0),
|
||||
'T2' => (int) ($config->t2_weight ?? 0),
|
||||
@@ -359,10 +367,7 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
}
|
||||
|
||||
if ($freeConfigId > 0) {
|
||||
$config = DiceLotteryPoolConfig::find($freeConfigId);
|
||||
if (!$config) {
|
||||
throw new ApiException('Free pool config not found');
|
||||
}
|
||||
$config = $this->findPoolConfigInDept($freeConfigId, $deptId, 'Free pool config not found');
|
||||
$tierWeightsSnapshot['free'] = [
|
||||
'T1' => (int) ($config->t1_weight ?? 0),
|
||||
'T2' => (int) ($config->t2_weight ?? 0),
|
||||
@@ -428,9 +433,94 @@ class DiceRewardConfigRecordLogic extends BaseLogic
|
||||
$record->bigwin_weight = $bigwinWeights ?: null;
|
||||
$record->ante = $ante;
|
||||
$record->admin_id = $adminId;
|
||||
$record->dept_id = $deptId;
|
||||
$record->create_time = date('Y-m-d H:i:s');
|
||||
$record->save();
|
||||
|
||||
return (int) $record->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析一键测试所属渠道:请求 dept_id > 奖池配置 dept_id > 渠道管理员本渠道
|
||||
*/
|
||||
private function resolveWeightTestDeptId(?array $adminInfo, $requestDeptId, array $params): int
|
||||
{
|
||||
$deptId = AdminScopeHelper::resolveConfigDeptId($adminInfo, $requestDeptId);
|
||||
if (! AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
return $deptId;
|
||||
}
|
||||
|
||||
foreach (['paid_lottery_config_id', 'free_lottery_config_id', 'lottery_config_id'] as $key) {
|
||||
$poolId = isset($params[$key]) ? (int) $params[$key] : 0;
|
||||
if ($poolId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$pool = DiceLotteryPoolConfig::find($poolId);
|
||||
if (! $pool) {
|
||||
continue;
|
||||
}
|
||||
$poolDeptId = AdminScopeHelper::normalizeRecordDeptId($pool->dept_id ?? null);
|
||||
if (! AdminScopeHelper::isTemplateDeptId($poolDeptId)) {
|
||||
return $poolDeptId;
|
||||
}
|
||||
}
|
||||
|
||||
$scopeDeptId = AdminScopeHelper::getDeptId($adminInfo);
|
||||
if ($scopeDeptId !== null && $scopeDeptId > 0) {
|
||||
return $scopeDeptId;
|
||||
}
|
||||
|
||||
return $deptId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验奖池配置属于当前渠道
|
||||
*/
|
||||
private function findPoolConfigInDept(int $poolId, int $deptId, string $notFoundMsg): DiceLotteryPoolConfig
|
||||
{
|
||||
$config = DiceLotteryPoolConfig::find($poolId);
|
||||
if (!$config) {
|
||||
throw new ApiException($notFoundMsg);
|
||||
}
|
||||
$poolDeptId = AdminScopeHelper::normalizeRecordDeptId($config->dept_id ?? null);
|
||||
if ($poolDeptId !== $deptId) {
|
||||
throw new ApiException('POOL_CONFIG_NOT_IN_CHANNEL');
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析一键测试底注:优先 ante_config_id,否则按 mult + 渠道校验
|
||||
*/
|
||||
private function resolveWeightTestAnte(array $params, int $deptId): int
|
||||
{
|
||||
$anteConfigId = isset($params['ante_config_id']) ? (int) $params['ante_config_id'] : 0;
|
||||
if ($anteConfigId > 0) {
|
||||
$config = DiceAnteConfig::find($anteConfigId);
|
||||
if (! $config) {
|
||||
throw new ApiException('ANTE_CONFIG_NOT_FOUND');
|
||||
}
|
||||
$configDeptId = AdminScopeHelper::normalizeRecordDeptId($config->dept_id ?? null);
|
||||
if ($configDeptId !== $deptId) {
|
||||
throw new ApiException('ANTE_CONFIG_NOT_IN_CHANNEL');
|
||||
}
|
||||
$mult = (int) ($config->mult ?? 0);
|
||||
if ($mult <= 0) {
|
||||
throw new ApiException('ANTE_MUST_POSITIVE');
|
||||
}
|
||||
return $mult;
|
||||
}
|
||||
|
||||
$ante = isset($params['ante']) ? (int) $params['ante'] : 0;
|
||||
if ($ante <= 0) {
|
||||
throw new ApiException('ANTE_MUST_POSITIVE');
|
||||
}
|
||||
$anteQuery = DiceAnteConfig::where('mult', $ante);
|
||||
ConfigScopeEditHelper::applyDeptIdWhere($anteQuery, $deptId);
|
||||
if ($anteQuery->count() <= 0) {
|
||||
throw new ApiException(ApiLang::translateParams('ANTE_NOT_ALLOWED', [$ante]));
|
||||
}
|
||||
|
||||
return $ante;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
namespace app\dice\logic\reward_config_record;
|
||||
|
||||
use app\api\logic\PlayStartLogic;
|
||||
use app\dice\helper\AdminScopeHelper;
|
||||
use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig;
|
||||
use app\dice\model\play_record_test\DicePlayRecordTest;
|
||||
use app\dice\model\reward_config_record\DiceRewardConfigRecord;
|
||||
@@ -19,9 +20,13 @@ use support\think\Db;
|
||||
class WeightTestRunner
|
||||
{
|
||||
private const BATCH_SIZE = 10;
|
||||
|
||||
/** 本次测试所属渠道(与 dice_reward_config_record.dept_id 一致) */
|
||||
private int $runDeptId = 0;
|
||||
/** 测试记录写库白名单字段 */
|
||||
private const PLAY_RECORD_TEST_COLUMNS = [
|
||||
'reward_config_record_id',
|
||||
'dept_id',
|
||||
'admin_id',
|
||||
'lottery_config_id',
|
||||
'lottery_type',
|
||||
@@ -61,10 +66,15 @@ class WeightTestRunner
|
||||
return;
|
||||
}
|
||||
|
||||
$configType0 = DiceLotteryPoolConfig::where('name', 'default')->find();
|
||||
$configType1 = DiceLotteryPoolConfig::where('name', 'killScore')->find();
|
||||
$this->runDeptId = $this->resolveRunDeptId($recordId, $record);
|
||||
$deptId = $this->runDeptId;
|
||||
DiceReward::setRequestDeptId($deptId);
|
||||
DiceRewardConfig::clearRequestInstance();
|
||||
|
||||
$configType0 = DiceLotteryPoolConfig::findByNameForDept('default', $deptId);
|
||||
$configType1 = DiceLotteryPoolConfig::findByNameForDept('killScore', $deptId);
|
||||
if (!$configType0) {
|
||||
$this->markFailed($recordId, '彩金池配置 name=default 不存在');
|
||||
$this->markFailed($recordId, '彩金池配置 name=default 不存在(当前渠道)');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,12 +89,12 @@ class WeightTestRunner
|
||||
$freePoolConfigId = (int) ($record->free_lottery_config_id ?? 0);
|
||||
|
||||
$paidPoolConfig = $paidPoolConfigId > 0 ? DiceLotteryPoolConfig::find($paidPoolConfigId) : $configType0;
|
||||
if (!$paidPoolConfig) {
|
||||
if (!$paidPoolConfig || AdminScopeHelper::normalizeRecordDeptId($paidPoolConfig->dept_id ?? null) !== $deptId) {
|
||||
$paidPoolConfig = $configType0;
|
||||
}
|
||||
$freePoolConfig = $freePoolConfigId > 0 ? DiceLotteryPoolConfig::find($freePoolConfigId) : $configType1;
|
||||
if (!$freePoolConfig) {
|
||||
$freePoolConfig = $configType0;
|
||||
if (!$freePoolConfig || AdminScopeHelper::normalizeRecordDeptId($freePoolConfig->dept_id ?? null) !== $deptId) {
|
||||
$freePoolConfig = $configType1 ?: $configType0;
|
||||
}
|
||||
|
||||
if ($paidTierWeightsCustom !== null && array_sum($paidTierWeightsCustom) <= 0) {
|
||||
@@ -118,6 +128,7 @@ class WeightTestRunner
|
||||
try {
|
||||
$this->runChainFreeMode(
|
||||
$recordId,
|
||||
$deptId,
|
||||
$playLogic,
|
||||
$paidS,
|
||||
$paidN,
|
||||
@@ -145,6 +156,9 @@ class WeightTestRunner
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('WeightTestRunner exception: ' . $e->getMessage(), ['record_id' => $recordId, 'trace' => $e->getTraceAsString()]);
|
||||
$this->markFailed($recordId, $e->getMessage());
|
||||
} finally {
|
||||
DiceReward::clearRequestInstance();
|
||||
DiceRewardConfig::clearRequestInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +167,7 @@ class WeightTestRunner
|
||||
*/
|
||||
private function runChainFreeMode(
|
||||
int $recordId,
|
||||
int $deptId,
|
||||
PlayStartLogic $playLogic,
|
||||
int $paidS,
|
||||
int $paidN,
|
||||
@@ -199,12 +214,12 @@ class WeightTestRunner
|
||||
$customWeights = $freeTierWeightsCustom;
|
||||
}
|
||||
|
||||
$row = $playLogic->simulateOnePlay($cfg, $dir, $lotteryType, $playAnte, $customWeights);
|
||||
$row = $playLogic->simulateOnePlay($cfg, $dir, $lotteryType, $playAnte, $customWeights, $deptId);
|
||||
$winCoin = (float) ($row['win_coin'] ?? 0);
|
||||
$paidAmount = (float) ($row['paid_amount'] ?? 0);
|
||||
$playerProfitTotal += $winCoin - $paidAmount;
|
||||
$this->aggregate($row, $resultCounts, $tierCounts);
|
||||
$buffer[] = $this->rowForInsert($row, $recordId);
|
||||
$buffer[] = $this->rowForInsert($row, $recordId, $deptId);
|
||||
$done++;
|
||||
|
||||
if (!empty($row['grants_free_ticket'])) {
|
||||
@@ -217,6 +232,58 @@ class WeightTestRunner
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析本次测试渠道:优先读库字段,避免 ORM 字段缓存未含 dept_id 时读不到
|
||||
*/
|
||||
private function resolveRunDeptId(int $recordId, DiceRewardConfigRecord $record): int
|
||||
{
|
||||
$recordTable = (new DiceRewardConfigRecord())->getTable();
|
||||
$fromDb = Db::table($recordTable)->where('id', $recordId)->value('dept_id');
|
||||
$deptId = AdminScopeHelper::normalizeRecordDeptId($fromDb);
|
||||
if (! AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
return $deptId;
|
||||
}
|
||||
|
||||
$deptId = AdminScopeHelper::normalizeRecordDeptId($record->dept_id ?? null);
|
||||
if (! AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
return $deptId;
|
||||
}
|
||||
|
||||
return $this->resolveDeptIdFromRecordPools($record, $deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 历史记录 dept_id=0 时,从关联奖池配置反推并回写
|
||||
*/
|
||||
private function resolveDeptIdFromRecordPools(DiceRewardConfigRecord $record, int $fallbackDeptId): int
|
||||
{
|
||||
foreach (
|
||||
[
|
||||
(int) ($record->paid_lottery_config_id ?? 0),
|
||||
(int) ($record->free_lottery_config_id ?? 0),
|
||||
(int) ($record->lottery_config_id ?? 0),
|
||||
] as $poolId
|
||||
) {
|
||||
if ($poolId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$pool = DiceLotteryPoolConfig::find($poolId);
|
||||
if (! $pool) {
|
||||
continue;
|
||||
}
|
||||
$poolDeptId = AdminScopeHelper::normalizeRecordDeptId($pool->dept_id ?? null);
|
||||
if (! AdminScopeHelper::isTemplateDeptId($poolDeptId)) {
|
||||
if (AdminScopeHelper::normalizeRecordDeptId($record->dept_id ?? null) !== $poolDeptId) {
|
||||
$record->dept_id = $poolDeptId;
|
||||
$record->save();
|
||||
}
|
||||
return $poolDeptId;
|
||||
}
|
||||
}
|
||||
|
||||
return $fallbackDeptId;
|
||||
}
|
||||
|
||||
private function aggregate(array $row, array &$resultCounts, array &$tierCounts): void
|
||||
{
|
||||
$grid = (int) ($row['roll_number_for_count'] ?? $row['roll_number'] ?? 0);
|
||||
@@ -229,10 +296,14 @@ class WeightTestRunner
|
||||
}
|
||||
}
|
||||
|
||||
private function rowForInsert(array $row, int $rewardConfigRecordId): array
|
||||
private function rowForInsert(array $row, int $rewardConfigRecordId, int $deptId): array
|
||||
{
|
||||
$bindDeptId = ! AdminScopeHelper::isTemplateDeptId($this->runDeptId)
|
||||
? $this->runDeptId
|
||||
: $deptId;
|
||||
$out = [
|
||||
'reward_config_record_id' => $rewardConfigRecordId,
|
||||
'dept_id' => $bindDeptId,
|
||||
];
|
||||
$keys = [
|
||||
'admin_id', 'lottery_config_id', 'lottery_type', 'is_win', 'win_coin',
|
||||
@@ -254,7 +325,7 @@ class WeightTestRunner
|
||||
return;
|
||||
}
|
||||
$this->insertBuffer($buffer);
|
||||
$buffer = [];
|
||||
array_splice($buffer, 0, count($buffer));
|
||||
$this->updateProgress($recordId, $done, $resultCounts, $tierCounts, $recordTotalPlayCount);
|
||||
}
|
||||
|
||||
@@ -263,6 +334,7 @@ class WeightTestRunner
|
||||
if (empty($rows)) {
|
||||
return;
|
||||
}
|
||||
$table = (new DicePlayRecordTest())->getTable();
|
||||
foreach ($rows as $row) {
|
||||
if (!is_array($row)) {
|
||||
continue;
|
||||
@@ -273,6 +345,9 @@ class WeightTestRunner
|
||||
$payload[$column] = $row[$column];
|
||||
}
|
||||
}
|
||||
if (! AdminScopeHelper::isTemplateDeptId($this->runDeptId)) {
|
||||
$payload['dept_id'] = $this->runDeptId;
|
||||
}
|
||||
if (!array_key_exists('create_time', $payload) || $payload['create_time'] === null || $payload['create_time'] === '') {
|
||||
$payload['create_time'] = date('Y-m-d H:i:s');
|
||||
}
|
||||
@@ -282,10 +357,26 @@ class WeightTestRunner
|
||||
if ($payload === []) {
|
||||
continue;
|
||||
}
|
||||
Db::name((new DicePlayRecordTest())->getTable())->insert($payload);
|
||||
// strict(false):表结构新增 dept_id 后,避免连接层字段缓存未刷新导致插入被丢弃
|
||||
Db::table($table)->strict(false)->insert($payload);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本批测试明细 dept_id 与主记录对齐(修复历史 worker 未写入 dept_id 的情况)
|
||||
*/
|
||||
private function syncPlayRecordTestDeptId(int $recordId, int $deptId): void
|
||||
{
|
||||
if (AdminScopeHelper::isTemplateDeptId($deptId)) {
|
||||
return;
|
||||
}
|
||||
DicePlayRecordTest::where('reward_config_record_id', $recordId)
|
||||
->where(function ($query) {
|
||||
$query->whereNull('dept_id')->whereOr('dept_id', AdminScopeHelper::DEFAULT_TEMPLATE_DEPT);
|
||||
})
|
||||
->update(['dept_id' => $deptId]);
|
||||
}
|
||||
|
||||
private function updateProgress(int $recordId, int $overPlayCount, array $resultCounts, array $tierCounts, ?int $totalPlayCount = null): void
|
||||
{
|
||||
$record = DiceRewardConfigRecord::find($recordId);
|
||||
@@ -308,6 +399,13 @@ class WeightTestRunner
|
||||
{
|
||||
$record = DiceRewardConfigRecord::find($recordId);
|
||||
if ($record) {
|
||||
$deptId = AdminScopeHelper::normalizeRecordDeptId($record->dept_id ?? null);
|
||||
if (AdminScopeHelper::isTemplateDeptId($deptId) && ! AdminScopeHelper::isTemplateDeptId($this->runDeptId)) {
|
||||
$deptId = $this->runDeptId;
|
||||
$record->dept_id = $deptId;
|
||||
}
|
||||
$this->syncPlayRecordTestDeptId($recordId, $deptId);
|
||||
|
||||
// 平台盈利通过关联测试记录统计
|
||||
$platformProfit = DiceRewardConfigRecord::computePlatformProfitFromRelated($recordId);
|
||||
// 落点统计也通过关联测试记录重新统计,避免模拟过程异常导致为空
|
||||
|
||||
Reference in New Issue
Block a user