Files
cursor/plans/free_credits_老用户隐藏评审_1c0ab623.plan.md
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

6.2 KiB
Raw Blame History

name, overview, todos, isProject
name overview todos isProject
Free Credits 老用户隐藏评审 EventBus 写库确定参加、status 只读展示;在此基础上用环境变量 FREE_CREDITS_ENROLL_REG_AFTER 做注册时间门槛——regTime 晚于该时间的用户才有资格参加,否则一律 status=-1 且 EventBus 跳过写池。
id content status
env-reg-cutoff 新增 FREE_CREDITS_ENROLL_REG_AFTER 环境变量与 FreeCreditsLogic::isEligibleByRegTime(uid) 统一门禁 completed
id content status
apply-gate-all-paths 在 status、syncHomeWithdrawUnlocked、handleFreeCreditInit、advanceAfterRecharge、claim、firstCashout 入口应用注册时间门禁 completed
id content status
fix-docs-lobby 修正 FreeCreditsController PHPDoc含 status=-1 含老用户/未达注册门槛LobbyController 清理无用 import completed
id content status
guard-claim-cashout 无资格或无 player 时 claim/firstCashout 返回明确业务错误 completed
id content status
verify-reg-cutoff 联调regTime 早于门槛 status=-1 且 EventBus 不建池;晚于门槛走 win/首充完整流程 completed
false

Free Credits 老用户隔离:注册时间门槛(计划)

目标

C 端全量更新后,注册时间早于活动上线节点的用户视为老用户,不参加、不展示注册时间晚于该节点的新用户在现有「EventBus 写库 = 参加」模型下正常走活动。

「默认参加」含义:有资格参加EventBus 允许建池、status 可读),不是无需 EventBus 自动插入 free_credits_player


分层架构(保持不变)

flowchart TB
  gate{regTime > FREE_CREDITS_ENROLL_REG_AFTER?}
  gate -->|否| block[不参加: status=-1 EventBus return]
  gate -->|是| eligible[有资格]
  eligible --> win[EventBus syncHomeWithdrawUnlocked]
  eligible --> init[EventBus free_credit_init]
  eligible --> api[status 只读 player 行]
  win --> pool[(free_credits_player)]
  init --> pool
  api --> pool
路径 行为
status() 未达注册门槛 → status=-1;达门槛且无 player 行 → -1;有行 → buildStatus
EventBus 未达注册门槛 → 各 Logic 方法开头直接 return不建池、不定格、不推进

实现要点

1. 环境变量

.env / 部署说明中增加(示例):

# 用户注册时间Unix 或 Y-m-d H:i:s建议与 TIMEZONE 一致)晚于此值才可参加 Free Credits
FREE_CREDITS_ENROLL_REG_AFTER=2026-05-20 00:00:00
  • config/app.php 或新建 config/free_credits.php 读取:getenv('FREE_CREDITS_ENROLL_REG_AFTER')strtotime 解析为 enroll_reg_after_ts(启动时或首次调用缓存)。
  • 未配置时的默认策略(已确认)FREE_CREDITS_ENROLL_REG_AFTER 为空或未配置 → 全员不参加isEligibleByRegTime 恒 falsestatus=-1EventBus 不写池)。

2. 统一门禁方法(建议放在 FreeCreditsLogic

/**
 * 是否具备 Free Credits 参与资格(注册时间晚于环境变量门槛)。
 */
protected function isEligibleByRegTime(int $uid): bool
{
    $cutoff = self::enrollRegAfterTimestamp(); // 0 表示未配置
    if ($cutoff <= 0) {
        return false;
    }

    $userInfo = \app\service\user\UserService::getUserInfoEntity($uid);
    if ($userInfo === null || $userInfo->create_at === '') {
        return false;
    }

    $regTime = strtotime($userInfo->create_at);
    return $regTime !== false && $regTime > $cutoff; // 严格「晚于」
}
  • 数据来源app\service\user\UserService::getUserInfoEntity(调 user 服 /innerapi/user/info),与 EventBus::registerEvent 等同用法。
  • 注册时间字段app\entity\UserInfoEntity::$create_atY-m-d H:i:s),比较前 strtotime 为 Unix 秒。
  • 不用 UserTagService::tagInfo->regTime(标签缓存,与账号创建时间可能不一致)。
  • 备选:若 Logic 内已大量使用 slotLib可用 \slotLib\services\UserService::getInstance()->setUid($uid)->getUserInfo()?->regTime(构造函数内由 create_at 解析),但 console 侧优先统一 app\service\user\UserService

3. 调用点(读写对称)

方法 未达门槛时
status() 直接 return ['status' => -1]
syncHomeWithdrawUnlocked() return null
handleFreeCreditInit() return
advanceAfterRecharge() return
claim() / firstCashout() throw BusinessException('...') 或统一文案

说明:已达门槛、但库中无 player 行 → 仍为 status=-1(尚未被 EventBus 纳入);达门槛且 win 后 → EventBus 建池 → status 非 -1

4. 与「已首充」的关系

  • 注册门槛解决:老账号 / 老注册 不进入活动。
  • 钱包侧 maybeSendFreeCreditInit 仍仅 首充 发定格,二者叠加,互不替代。

5. 撤销项

  • 不再单独做 total_deposit == 0 的 EventBus 门禁(由注册时间门槛覆盖「老用户」定义)。
  • 不再要求 frozen_amount > 0 才展示(保留 HOME_UNLOCKED 阶段)。

6. 文档与测试

  • 更新 FreeCreditsControllerstatus=-1 = 未参加 / 活动关 / 注册时间早于门槛
  • 单测mock regTime 与 env cutoff覆盖 eligible / ineligible 的 status 与 freeze 是否被调用。
  • 联调矩阵见下。

联调矩阵

regTime vs 门槛 win 达门槛 首充定格 status EventBus 建池
早于 - - -1
晚于 -1
晚于 1 sync 建池
晚于 - 3/4 + packages freeze

新 C 端约定(不变)

  • status === -1:隐藏(含老用户、未达注册门槛、未参加)。
  • status !== -1:已参加,按 FreeCreditsPlayerModel 状态渲染。