文件
Henglianshutong/addons/shopro/controller/commission/Agent.php

360 行
14 KiB
PHP

<?php
namespace addons\shopro\controller\commission;
use think\Db;
use app\admin\model\shopro\user\User as UserModel;
use app\admin\model\shopro\commission\Agent as AgentModel;
use app\admin\model\shopro\goods\Goods as GoodsModel;
use addons\shopro\service\Wallet;
class Agent extends Commission
{
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];
// 分销商详情
public function index()
{
$status = $this->service->getAgentStatus(true);
$condition = [
'type' => '',
'value' => ''
];
switch ($status) {
case AgentModel::AGENT_STATUS_NULL:
$condition = $this->service->config->getBecomeAgentEvent();
if ($condition['type'] === 'goods') {
$condition['value'] = GoodsModel::show()->whereIn('id', $condition['value'])->select();
}
$this->error('', $condition, 100);
break;
case AgentModel::AGENT_STATUS_NEEDINFO:
$this->error('待完善信息,请补充您的资料后提交审核', $condition, 103);
break;
case AgentModel::AGENT_STATUS_PENDING:
$this->error('正在审核中,请耐心等候结果', $condition, 104);
break;
case AgentModel::AGENT_STATUS_REJECT:
$agentFormStatus = $this->service->config->isAgentApplyForm();
if ($agentFormStatus) {
$this->error('抱歉!您的申请信息未通过,请尝试修改后重新提交', $condition, 105);
} else {
$this->error('抱歉!您的申请未通过,请尝试重新申请', $condition, 106);
}
break;
case AgentModel::AGENT_STATUS_FREEZE:
$this->error('抱歉!您的账户已被冻结,如有疑问请联系客服', $condition, 107);
break;
}
$data = \addons\shopro\service\partner\IdentityService::attachAgent($this->service->agent);
$this->success('分销商信息', $data);
}
// 分销商完善个人信息
public function form()
{
if (!$this->service->config->isAgentApplyForm()) {
$this->error('未开启分销商申请');
}
$agentForm = $this->service->config->getAgentForm();
$protocol = $this->service->config->getApplyProtocol();
$applyInfo = $this->service->agent->apply_info ?? [];
$config = [
'form' => $agentForm['content'],
'status' => $this->service->getAgentStatus(true),
'background' => $agentForm['background_image'],
'protocol' => $protocol,
'applyInfo' => $applyInfo
];
$this->success("", $config);
}
// 申请分销商/完善资料
public function apply()
{
if (!$this->request->isPost()) {
$this->error('');
}
if (!$this->service->config->isAgentApplyForm()) {
$this->error('未开启分销商申请');
}
$status = $this->service->getAgentStatus(true);
if (!in_array($status, [AgentModel::AGENT_STATUS_NEEDINFO, AgentModel::AGENT_STATUS_REJECT, AgentModel::AGENT_STATUS_NORMAL])) {
$this->error('您暂时不能申请');
}
Db::transaction(function () use ($status) {
$data = $this->request->param('data/a');
// 过滤无效表单字段数据
$config = $this->service->config->getAgentForm();
$form = (array)$config['content'];
$data = array_column($data, 'value', 'name');
foreach ($form as &$item) {
if (!empty($data[$item['name']])) {
$item['value'] = $data[$item['name']];
} else {
$this->error($item['name'] . '不能为空');
}
}
if ($status === AgentModel::AGENT_STATUS_NEEDINFO) {
$this->service->createNewAgent('', $form);
} else {
// 重置为审核中
if ($status === AgentModel::AGENT_STATUS_REJECT) {
$this->service->agent->status = AgentModel::AGENT_STATUS_PENDING;
}
// 更新分销商信息
$this->service->agent->apply_info = $form;
$this->service->agent->save();
}
});
$this->success('提交成功');
}
// 我的团队
public function team()
{
$agentId = $this->service->user->id;
$levelType = $this->request->param('level_type', '1'); // 1=直推, 2=间推, all=全部
$filterType = $this->request->param('filter_type', 'all'); // all, partner, active, expiring, inactive
$keyword = trim((string) $this->request->param('keyword', ''));
$sort = $this->request->param('sort', 'createtime'); // createtime, child_count, consume
$listRows = (int) $this->request->param('list_rows', 10);
// 1. 获取直推一级成员 ID 列表
$level1Ids = UserModel::where('parent_user_id', $agentId)
->where('status', 'normal')
->column('id');
// 2. 根据 level_type 确定父级范围
$query = UserModel::alias('u')->where('u.status', 'normal');
if ($levelType == '2') {
if (empty($level1Ids)) {
$query->whereRaw('1=0');
} else {
$query->whereIn('u.parent_user_id', $level1Ids);
}
} elseif ($levelType == 'all') {
$allParentIds = array_merge([$agentId], $level1Ids);
$query->whereIn('u.parent_user_id', $allParentIds);
} else {
$query->where('u.parent_user_id', $agentId);
}
// 3. 关键字搜索 (昵称/手机号/ID)
if ($keyword !== '') {
$query->where(function ($q) use ($keyword) {
if (is_numeric($keyword)) {
$q->where('u.id', intval($keyword))
->whereOr('u.mobile', 'like', "%{$keyword}%")
->whereOr('u.nickname', 'like', "%{$keyword}%");
} else {
$q->where('u.nickname', 'like', "%{$keyword}%");
}
});
}
// 4. 计算活跃度时间窗口 (默认30天保活,剩余<=5天为临期)
$windowDays = \addons\shopro\service\partner\PartnerConfig::activeDays();
$windowStart = (new \addons\shopro\service\partner\ActiveService())->windowStart();
$expiringStart = time() - ($windowDays - 5) * 86400;
// 5. 身份与活跃状态过滤
if ($filterType === 'partner') {
$partnerUserIds = AgentModel::where('status', 'in', ['normal', 'freeze'])
->where(function ($q) {
$q->where('level', '>=', 2)
->whereOr('is_venue', 1)
->whereOr('is_county', 1);
})->column('user_id');
if (empty($partnerUserIds)) {
$query->whereRaw('1=0');
} else {
$query->whereIn('u.id', $partnerUserIds);
}
} elseif ($filterType === 'active') {
$activeUserIds = AgentModel::where('last_self_order_time', '>=', $expiringStart)->column('user_id');
if (empty($activeUserIds)) {
$query->whereRaw('1=0');
} else {
$query->whereIn('u.id', $activeUserIds);
}
} elseif ($filterType === 'expiring') {
$expiringUserIds = AgentModel::where('last_self_order_time', '>=', $windowStart)
->where('last_self_order_time', '<', $expiringStart)
->column('user_id');
if (empty($expiringUserIds)) {
$query->whereRaw('1=0');
} else {
$query->whereIn('u.id', $expiringUserIds);
}
} elseif ($filterType === 'inactive') {
$validUserIds = AgentModel::where('last_self_order_time', '>=', $windowStart)->column('user_id');
if (!empty($validUserIds)) {
$query->whereNotIn('u.id', $validUserIds);
}
}
// 6. 排序处理
if ($sort === 'child_count') {
$agentTable = (new AgentModel())->getTable();
$query->join($agentTable . ' a', 'u.id = a.user_id', 'LEFT')
->order('a.child_user_count_1', 'desc')
->order('u.id', 'desc');
} elseif ($sort === 'consume') {
$query->order('u.total_consume', 'desc')->order('u.id', 'desc');
} else {
$query->order('u.createtime', 'desc')->order('u.id', 'desc');
}
$query->field('u.*');
// 7. 分页并加载推荐人与分销商信息
$data = $query->with([
'parentUser' => function ($q) {
$q->field('id, nickname, avatar, mobile');
},
'agent' => function ($q) {
$q->with('level_info');
}
])->paginate($listRows);
// 8. 增强成员卡片数据
$now = time();
$data->each(function ($user) use ($agentId, $windowDays, $now) {
$userAgent = $user->agent;
if ($userAgent) {
$attached = \addons\shopro\service\partner\IdentityService::attachAgent($userAgent);
$user->setRelation('agent', $attached);
$last = intval($attached['last_self_order_time'] ?? 0);
$isActive = !empty($attached['active_30d']);
if ($isActive) {
if ($last > 0) {
$daysPassed = floor(($now - $last) / 86400);
$remaining = max(0, intval($windowDays - $daysPassed));
$user->active_status = ($remaining <= 5) ? 'expiring' : 'active';
$user->days_remaining = $remaining;
} else {
$user->active_status = 'active';
$user->days_remaining = $windowDays;
}
} else {
$user->active_status = 'inactive';
$user->days_remaining = 0;
}
$user->order_count = intval($userAgent['child_order_count_0'] ?? 0);
$user->consume_amount = \addons\shopro\service\partner\IdentityService::formatMoney($userAgent['child_order_money_0'] ?? ($user->total_consume ?? 0));
$user->child_user_count_1 = intval($userAgent['child_user_count_1'] ?? 0);
} else {
$user->active_status = 'inactive';
$user->days_remaining = 0;
$user->order_count = 0;
$user->consume_amount = \addons\shopro\service\partner\IdentityService::formatMoney($user->total_consume ?? 0);
$user->child_user_count_1 = 0;
}
$user->team_level = ($user->parent_user_id == $agentId) ? 1 : 2;
$rawMobile = $user->mobile ? (string) $user->mobile : '';
$user->mobile_raw = $rawMobile;
$user->mobile_hide = $rawMobile ? (strlen($rawMobile) == 11 ? substr_replace($rawMobile, '****', 3, 4) : $rawMobile) : '';
});
// 9. 计算整体团队健康度统计
$summary = $this->getTeamHealthSummary($agentId, $level1Ids, $windowStart, $expiringStart);
$result = $data->toArray();
$result['summary'] = $summary;
$this->success("", $result);
}
/**
* 计算团队保活健康度统计
*/
protected function getTeamHealthSummary($agentId, $level1Ids, $windowStart, $expiringStart)
{
$allMembers = array_merge([$agentId], $level1Ids);
$teamUserIds = UserModel::whereIn('parent_user_id', $allMembers)
->where('status', 'normal')
->column('id');
if (empty($teamUserIds)) {
return [
'total_count' => 0,
'active_count' => 0,
'expiring_count' => 0,
'inactive_count' => 0,
'partner_count' => 0,
];
}
$agents = AgentModel::whereIn('user_id', $teamUserIds)->select();
$activeCount = 0;
$expiringCount = 0;
$inactiveCount = 0;
$partnerCount = 0;
foreach ($agents as $ag) {
$level = intval($ag->level ?? 0);
$isVenue = intval($ag->is_venue ?? 0);
$isCounty = intval($ag->is_county ?? 0);
if ($level >= 2 || $isVenue == 1 || $isCounty == 1) {
$partnerCount++;
}
$last = intval($ag->last_self_order_time ?? 0);
if ($last >= $expiringStart) {
$activeCount++;
} elseif ($last >= $windowStart) {
$expiringCount++;
} else {
$inactiveCount++;
}
}
$missingAgentCount = count($teamUserIds) - count($agents);
if ($missingAgentCount > 0) {
$inactiveCount += $missingAgentCount;
}
return [
'total_count' => count($teamUserIds),
'active_count' => $activeCount,
'expiring_count' => $expiringCount,
'inactive_count' => $inactiveCount,
'partner_count' => $partnerCount,
];
}
// 佣金转余额
public function transfer()
{
if (!$this->request->isPost()) {
$this->error('');
}
$amount = $this->request->param('amount');
if ($amount <= 0) {
$this->error('请输入正确的金额');
}
Db::transaction(function () use ($amount) {
$user = auth_user();
Wallet::change($user, 'commission', -$amount, 'transfer_to_money');
Wallet::change($user, 'money', $amount, 'transfer_by_commission');
});
$this->success('');
}
}