diff --git a/saiadmin-artd/src/views/plugin/dice/player/index/modules/edit-dialog.vue b/saiadmin-artd/src/views/plugin/dice/player/index/modules/edit-dialog.vue index a0553f1..8448d06 100644 --- a/saiadmin-artd/src/views/plugin/dice/player/index/modules/edit-dialog.vue +++ b/saiadmin-artd/src/views/plugin/dice/player/index/modules/edit-dialog.vue @@ -336,6 +336,13 @@ return v == null || v === 0 } + /** 将彩金池配置的 T1–T5 写入表单(绑定彩金池时展示与提交均以池为准) */ + function applyPoolWeightsToForm(cfg: LotteryPoolConfigOption) { + WEIGHT_FIELDS.forEach((key) => { + ;(formData as Record)[key] = Number(cfg[key] ?? 0) + }) + } + /** 根据当前 lottery_config_id 加载 DiceLotteryConfig,并将五个权重写入当前 player.*_weight */ async function loadCurrentLotteryConfig() { const id = formData.lottery_config_id @@ -349,9 +356,7 @@ if (payload) { const row = parseLotteryPoolConfigOption(payload) currentLotteryConfig.value = row - WEIGHT_FIELDS.forEach((key) => { - ;(formData as any)[key] = Number(row[key] ?? 0) - }) + applyPoolWeightsToForm(row) } else { currentLotteryConfig.value = null } @@ -360,6 +365,15 @@ } } + watch( + () => currentLotteryConfig.value, + (cfg) => { + if (cfg && !isLotteryConfigEmpty()) { + applyPoolWeightsToForm(cfg) + } + } + ) + watch( () => props.modelValue, (newVal) => { @@ -378,9 +392,7 @@ const payload = extractReadPayload(res) if (payload) { const row = parseLotteryPoolConfigOption(payload) - WEIGHT_FIELDS.forEach((key) => { - ;(formData as any)[key] = Number(row[key] ?? 0) - }) + applyPoolWeightsToForm(row) currentLotteryConfig.value = row } else { currentLotteryConfig.value = null @@ -513,6 +525,13 @@ const payload = { ...formData } if (isLotteryConfigEmpty()) { ;(payload as any).lottery_config_id = null + } else if (currentLotteryConfig.value) { + applyPoolWeightsToForm(currentLotteryConfig.value) + WEIGHT_FIELDS.forEach((key) => { + ;(payload as Record)[key] = Number( + (formData as Record)[key] ?? 0 + ) + }) } if (props.dialogType === 'edit' && !payload.password) { delete (payload as any).password diff --git a/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php b/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php index 2ad4413..b9c720c 100644 --- a/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php +++ b/server/app/dice/logic/lottery_pool_config/DiceLotteryPoolConfigLogic.php @@ -6,6 +6,7 @@ // +---------------------------------------------------------------------- namespace app\dice\logic\lottery_pool_config; +use app\api\cache\UserCache; use app\api\service\LotteryService; use app\dice\helper\AdminScopeHelper; use app\dice\helper\ConfigScopeEditHelper; @@ -15,6 +16,7 @@ use app\dice\basic\DiceBaseLogic; use plugin\saiadmin\exception\ApiException; use plugin\saiadmin\utils\Helper; use support\think\Cache; +use support\think\Db; /** * 色子奖池配置逻辑层 @@ -51,7 +53,7 @@ class DiceLotteryPoolConfigLogic extends DiceBaseLogic $pickedDeptId ); if ($result) { - $pool = DiceLotteryPoolConfig::find($id); + $pool = DiceLotteryPoolConfig::where('id', $id)->find(); if ($pool && $pool->isPlayerDefaultTemplate()) { $this->syncPlayersBoundToPlayerDefaultPool($pool); } @@ -60,7 +62,7 @@ class DiceLotteryPoolConfigLogic extends DiceBaseLogic } /** - * 修改 playerDefault 后:同步同渠道所有 lottery_config_id 指向该池的玩家 T1–T5 权重,并刷新 Redis 彩金池快照 + * 修改 playerDefault 后:同步同渠道所有绑定该池(及应跟随 playerDefault 的玩家)T1–T5 权重,并刷新 Redis * * @return int 已同步玩家数量 */ @@ -70,38 +72,86 @@ class DiceLotteryPoolConfigLogic extends DiceBaseLogic if ($poolId <= 0) { return 0; } - $weights = [ - 't1_weight' => (int) ($pool->t1_weight ?? 0), - 't2_weight' => (int) ($pool->t2_weight ?? 0), - 't3_weight' => (int) ($pool->t3_weight ?? 0), - 't4_weight' => (int) ($pool->t4_weight ?? 0), - 't5_weight' => (int) ($pool->t5_weight ?? 0), - ]; - $poolDeptId = AdminScopeHelper::normalizeRecordDeptId($pool->dept_id ?? null); + $fresh = DiceLotteryPoolConfig::where('id', $poolId)->find(); + if (!$fresh || !$fresh->isPlayerDefaultTemplate()) { + return 0; + } + $pool = $fresh; - $query = DicePlayer::where('lottery_config_id', $poolId); - if (AdminScopeHelper::isTemplateDeptId($poolDeptId)) { + $weights = $this->extractPoolTierWeights($pool); + $poolDeptId = AdminScopeHelper::normalizeRecordDeptId($pool->dept_id ?? null); + $legacyDefaultPoolId = $this->findDefaultPoolIdForDept($poolDeptId); + + $idsMap = []; + + $boundPlayers = DicePlayer::where('lottery_config_id', $poolId)->select(); + foreach ($boundPlayers as $player) { + $idsMap[(int) $player->id] = true; + } + + if ($legacyDefaultPoolId > 0 && $legacyDefaultPoolId !== $poolId) { + $legacyPlayers = DicePlayer::where('lottery_config_id', $legacyDefaultPoolId)->select(); + foreach ($legacyPlayers as $player) { + if (AdminScopeHelper::resolvePlayerConfigDeptId($player) === $poolDeptId) { + $idsMap[(int) $player->id] = true; + } + } + } + + $unboundPlayers = DicePlayer::where(function ($q) { + $q->where('lottery_config_id', 0)->whereOr('lottery_config_id', null); + })->select(); + foreach ($unboundPlayers as $player) { + if (AdminScopeHelper::resolvePlayerConfigDeptId($player) === $poolDeptId) { + $idsMap[(int) $player->id] = true; + } + } + + if ($idsMap === []) { + return 0; + } + + $ids = array_keys($idsMap); + $update = array_merge($weights, ['lottery_config_id' => $poolId]); + Db::table('dice_player')->whereIn('id', $ids)->update($update); + + foreach ($ids as $playerId) { + LotteryService::patchPlayerWeightsCache($playerId, $weights); + LotteryService::invalidatePlayerLotteryCache($playerId); + UserCache::deleteUser($playerId); + } + + return count($ids); + } + + /** + * @return array{t1_weight:float,t2_weight:float,t3_weight:float,t4_weight:float,t5_weight:float} + */ + private function extractPoolTierWeights(DiceLotteryPoolConfig $pool): array + { + $data = $pool->getData(); + return [ + 't1_weight' => (float) ($data['t1_weight'] ?? 0), + 't2_weight' => (float) ($data['t2_weight'] ?? 0), + 't3_weight' => (float) ($data['t3_weight'] ?? 0), + 't4_weight' => (float) ($data['t4_weight'] ?? 0), + 't5_weight' => (float) ($data['t5_weight'] ?? 0), + ]; + } + + private function findDefaultPoolIdForDept(int $deptId): int + { + $query = DiceLotteryPoolConfig::where('name', 'default'); + 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', $poolDeptId); + $query->where('dept_id', $deptId); } - - $playerIds = $query->column('id'); - if ($playerIds === [] || $playerIds === null) { - return 0; - } - $ids = array_map('intval', is_array($playerIds) ? $playerIds : [$playerIds]); - - DicePlayer::whereIn('id', $ids)->update($weights); - - foreach ($ids as $playerId) { - LotteryService::patchPlayerWeightsCache($playerId, $weights); - } - - return count($ids); + $row = $query->find(); + return $row ? (int) $row->id : 0; } /** diff --git a/server/app/dice/logic/player/DicePlayerLogic.php b/server/app/dice/logic/player/DicePlayerLogic.php index 20a1a49..184fa67 100644 --- a/server/app/dice/logic/player/DicePlayerLogic.php +++ b/server/app/dice/logic/player/DicePlayerLogic.php @@ -7,6 +7,7 @@ namespace app\dice\logic\player; use app\dice\basic\DiceBaseLogic; +use app\dice\model\lottery_pool_config\DiceLotteryPoolConfig; use plugin\saiadmin\exception\ApiException; use plugin\saiadmin\utils\Helper; use app\dice\model\player\DicePlayer; @@ -48,9 +49,30 @@ class DicePlayerLogic extends DiceBaseLogic } else { unset($data['password']); } + $data = $this->applyLotteryPoolWeightsToPlayerData($data); return parent::edit($id, $data); } + /** + * 已绑定彩金池时:玩家 T1–T5 以池配置为准,避免前端提交陈旧权重覆盖同步结果 + */ + private function applyLotteryPoolWeightsToPlayerData(array $data): array + { + $configId = isset($data['lottery_config_id']) ? (int) $data['lottery_config_id'] : 0; + if ($configId <= 0) { + return $data; + } + $config = DiceLotteryPoolConfig::find($configId); + if (!$config) { + return $data; + } + $row = $config->getData(); + foreach (['t1_weight', 't2_weight', 't3_weight', 't4_weight', 't5_weight'] as $field) { + $data[$field] = $row[$field] ?? 0; + } + return $data; + } + /** * 密码加密:md5(salt . password) */