feat: 新增分销推荐人手动绑定功能,调整自动绑定规则

本次修改:
1. 新增分销绑定 API 接口与路由
2. 老用户不再自动绑定推荐人,需手动输入邀请码绑定
3. 新增绑定推荐人 UI 弹层与展示组件
4. 新增防环校验与关系补全逻辑
5. 调整邀请码存储逻辑,仅未登录用户自动存储
这个提交包含在:
2026-10-26 13:51:52 +08:00
父节点 7b58952cd4
当前提交 b9fdb7cd77
共有 11 个文件被更改,包括 273 次插入 和 29 次删除

查看文件

@@ -46,6 +46,22 @@ class Distribution extends V1
$code = (string)$ext['invite_code'];
$shareUrl = 'https://fenleixinxi.gzyakj.com.cn/#/pages/index/index?ic=' . urlencode($code);
// 查询当前用户的上级推荐人信息(用于前端展示「已绑定推荐人」或「手动绑定邀请码」入口)
$inviterId = (int)(isset($ext['inviter_id']) ? $ext['inviter_id'] : 0);
if ($inviterId <= 0) {
$l1Rel = Db::name('fc_dist_relation')->where('user_id', $uid)->where('level', 1)->find();
if ($l1Rel && (int)$l1Rel['parent_id'] > 0) {
$inviterId = (int)$l1Rel['parent_id'];
}
}
$inviterNickname = '';
if ($inviterId > 0) {
$inviterUser = Db::name('user')->where('id', $inviterId)->field('nickname,username')->find();
if ($inviterUser) {
$inviterNickname = (string)($inviterUser['nickname'] ?: $inviterUser['username']);
}
}
// 商家转账确认收款页需要的商户号与小程序 AppID(非敏感,可下发)
$epay = (array)get_addon_config('epay');
$wx = isset($epay['wechat']) && is_array($epay['wechat']) ? $epay['wechat'] : [];
@@ -60,6 +76,8 @@ class Distribution extends V1
'l1Count' => $l1,
'l2Count' => $l2,
'inviteCode' => $code,
'inviterId' => $inviterId,
'inviterNickname' => $inviterNickname,
'shareUrl' => $shareUrl,
'posterUrl' => '',
// 最低提现金额(后台「分销设置」下发,默认 50)
@@ -351,6 +369,72 @@ class Distribution extends V1
$this->ok($list);
}
/**
* D7 手动输入邀请码补绑推荐人(老用户不支持自动补绑,仅支持通过手动填写邀请码完成补绑)
* POST /api/v1/distribution/bind 入参 {inviteCode}
*
* @return void 输出绑定结果与推荐人信息JSON
*/
public function bind()
{
$user = $this->auth();
$uid = (int)$user['id'];
$inviteCode = strtoupper(trim((string)$this->input('inviteCode', $this->input('invite_code', ''))));
if ($inviteCode === '') {
$this->fail('请输入有效的邀请码');
}
// 检查当前用户是否已绑定过推荐人
$ext = $this->ext($uid);
$existingInviter = (int)(isset($ext['inviter_id']) ? $ext['inviter_id'] : 0);
if ($existingInviter <= 0) {
$l1Rel = Db::name('fc_dist_relation')->where('user_id', $uid)->where('level', 1)->find();
if ($l1Rel && (int)$l1Rel['parent_id'] > 0) {
$existingInviter = (int)$l1Rel['parent_id'];
}
}
if ($existingInviter > 0) {
$this->fail('您已绑定过推荐人,不可重复绑定');
}
// 校验邀请码并定位目标推荐人
if (isset($ext['invite_code']) && strtoupper((string)$ext['invite_code']) === $inviteCode) {
$this->fail('不能填写自己的邀请码');
}
$parentExt = Db::name('fc_user_ext')->where('invite_code', $inviteCode)->find();
if (!$parentExt || (int)$parentExt['user_id'] <= 0) {
$this->fail('邀请码不存在,请核对后重试');
}
$targetInviterId = (int)$parentExt['user_id'];
if ($targetInviterId === $uid) {
$this->fail('不能绑定自己为推荐人');
}
// 防环校验:不能绑定自己的下级成员
$isDownline = Db::name('fc_dist_relation')
->where('user_id', $targetInviterId)
->where('parent_id', $uid)
->count();
if ($isDownline > 0) {
$this->fail('不能绑定您的下级成员为推荐人');
}
$ok = \app\common\library\DistributionService::bindRelation($uid, $targetInviterId, $inviteCode);
if (!$ok) {
$this->fail('绑定失败,请核对邀请码后重试');
}
$inviterUser = Db::name('user')->where('id', $targetInviterId)->field('nickname,username')->find();
$inviterNickname = $inviterUser ? (string)($inviterUser['nickname'] ?: $inviterUser['username']) : '同城合伙人';
$this->ok([
'bound' => true,
'inviterId' => $targetInviterId,
'inviterNickname' => $inviterNickname,
]);
}
/**
* 计算当前用户可提现余额
* 可提现余额 = Σ已结算佣金(status=1) - Σ(申请中/已打款)提现