int, 'total_released' => int] */ public function executeRelease(): array { $rate = (int)SystemConfigService::get('hjf_release_rate', 4); $releaseDate = date('Y-m-d'); $processed = 0; $totalReleased = 0; // 分批处理,每批 200 条,避免内存溢合 $page = 1; $limit = 200; do { $users = $this->userDao->selectList( ['frozen_points' => ['>', 0]], 'uid,frozen_points,available_points', $page, $limit, 'uid', 'asc' ); if (empty($users)) { break; } foreach ($users as $user) { $frozenBefore = (int)$user['frozen_points']; // 使用 bcmath 确保精度 $releaseAmount = (int)bcdiv(bcmul((string)$frozenBefore, (string)$rate), '1000'); if ($releaseAmount <= 0) { continue; } $frozenAfter = $frozenBefore - $releaseAmount; try { Db::transaction(function () use ($user, $releaseAmount, $frozenBefore, $frozenAfter, $releaseDate) { // 更新用户积分字段 $this->userDao->update($user['uid'], [ 'frozen_points' => $frozenAfter, 'available_points' => Db::raw('available_points + ' . $releaseAmount), ], 'uid'); // 写 points_release_log(本次每日释放记录) $this->logDao->save([ 'uid' => $user['uid'], 'points' => $releaseAmount, 'pm' => 1, 'type' => 'release', 'title' => '每日释放', 'mark' => "积分每日自动解冻,释放日期 {$releaseDate}", 'status' => 'released', 'release_date' => $releaseDate, ]); // 同步写入 eb_user_bill,使管理后台积分日志页面可见 $integralBalance = (int)($this->userDao->value(['uid' => $user['uid']], 'integral') ?: 0); $this->userBillServices->income( 'frozen_points_release', (int)$user['uid'], (int)$releaseAmount, $integralBalance, 0, 0, "积分每日自动解冻,释放日期 {$releaseDate}" ); }); $totalReleased += $releaseAmount; $processed++; } catch (\Throwable $e) { Log::error("[PointsRelease] uid={$user['uid']} 释放失败: " . $e->getMessage()); } } $page++; } while (count($users) === $limit); Log::info("[PointsRelease] 完成,processed={$processed} total_released={$totalReleased}"); return [ 'processed' => $processed, 'total_released' => $totalReleased, 'release_date' => $releaseDate, ]; } }