feat(invite-code): one-time invite codes with rewards, usage log, import/export

- 一次性邀请码:批量生成(次数/有效期/备注/四类奖励)、原子消费防超发、
  开启注册验证时奖励延迟发放(账本幂等键)
- Zibll 兼容文本导入(points/balance/vip/vip_time/level_integral,分隔符可自定义,
  第三段标识存为备注)、CSV 全字段导出与可回流文本导出
- 使用记录表 aksrt_invite_code_usage + 后台使用者列;注册表单 400ms 防抖实时校验
- 注册门控三模式(close/open/must)设置链路(PHP schema + admin SPA schema)
- 契约测试覆盖建表/消费竞态/导入导出/备注全链路
This commit is contained in:
kate522 committed 2026-09-21 20:53:36 +08:00
1 parent 20387fdb06
commit 3dd3f71c97
16 files changed
+1285 -1

No files matched your search

+5
View File
@@ -41,6 +41,11 @@ trait CreditsPaymentGroups {
return CreditsRuntime::get_referral_registration_settings();
}
/** @return array{enabled:bool,register_field:string,open_desc:string,required_desc:string} */
public static function get_invite_code_registration_settings(): array {
return CreditsRuntime::get_invite_code_registration_settings();
}
/**
* 积分功能是否启用(仅积分系统开关)。
*/
+32 -1
View File
@@ -91,13 +91,18 @@ class CreditsRuntime {
/**
* Shared ref-code settings.
*
* @return array{code_length:int,window_days:int}
* @return array{code_length:int,window_days:int,attribution_model:string}
*/
public static function get_referral_settings(): array {
$all = Settings::get_all();
$attribution = sanitize_key((string) ($all['referral_attribution_model'] ?? 'first_touch'));
if (!in_array($attribution, ['first_touch', 'last_touch'], true)) {
$attribution = 'first_touch';
}
return [
'code_length' => max(4, min(12, (int) ($all['referral_code_length'] ?? 12))),
'window_days' => max(1, min(365, (int) ($all['referral_window_days'] ?? 30))),
'attribution_model' => $attribution,
];
}
@@ -145,6 +150,32 @@ class CreditsRuntime {
];
}
/**
* @return array{enabled:bool,register_field:string,open_desc:string,required_desc:string}
*/
public static function get_invite_code_registration_settings(): array {
$all = Settings::get_all();
$mode = sanitize_key((string) ($all['invite_code_s'] ?? 'close'));
if (!in_array($mode, ['close', 'open', 'must'], true)) {
$mode = 'close';
}
$open_desc = trim((string) ($all['invite_code_open_desc'] ?? ''));
if ($open_desc === '') {
$open_desc = __('请输入邀请码,注册成功后奖励将自动发放', 'aksrt');
}
$required_desc = trim((string) ($all['invite_code_must_desc'] ?? ''));
if ($required_desc === '') {
$required_desc = __('<div>本站需凭邀请码注册</div><div>获取邀请码请与客服联系</div>', 'aksrt');
}
return [
'enabled' => $mode !== 'close',
'register_field' => $mode === 'must' ? 'required' : ($mode === 'open' ? 'optional' : 'hidden'),
'open_desc' => $open_desc,
'required_desc' => $required_desc,
];
}
/**
* 积分功能是否启用。
* 仅看积分系统开关;不再与 cms_features.download_credit 联合(该开关表示积分购买模式,非按次扣费)。