948 行
45 KiB
PHP
948 行
45 KiB
PHP
<?php
|
||
|
||
namespace app\admin\controller\shopro;
|
||
|
||
use app\admin\model\shopro\order\Order;
|
||
use app\admin\model\shopro\order\OrderItem;
|
||
use app\admin\model\shopro\goods\Goods;
|
||
use app\admin\model\shopro\user\User;
|
||
use app\admin\model\shopro\Share;
|
||
use app\admin\model\shopro\commission\Agent;
|
||
use app\admin\model\shopro\partner\Reward;
|
||
use app\admin\model\shopro\partner\DailyReport;
|
||
use app\admin\model\shopro\partner\RateLog;
|
||
use app\admin\model\shopro\partner\VoucherPlan;
|
||
use addons\shopro\service\SearchHistory;
|
||
use addons\shopro\service\partner\RateService;
|
||
use addons\shopro\service\partner\IdentityService;
|
||
use addons\shopro\service\partner\PartnerConfig;
|
||
use addons\shopro\service\partner\ActiveService;
|
||
use app\admin\model\shopro\Withdraw;
|
||
use app\admin\model\shopro\Refund;
|
||
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
|
||
use app\admin\model\shopro\order\Aftersale;
|
||
|
||
class Dashboard extends Common
|
||
{
|
||
|
||
public function index()
|
||
{
|
||
$cardList = [
|
||
[
|
||
'name' => 'total',
|
||
'card' => 'shopro/dashboard/total',
|
||
'status' => $this->auth->check('shopro/dashboard/total')
|
||
],
|
||
[
|
||
'name' => 'chart',
|
||
'card' => 'shopro/dashboard/chart',
|
||
'status' => $this->auth->check('shopro/dashboard/chart')
|
||
],
|
||
[
|
||
'name' => 'ranking',
|
||
'card' => 'shopro/dashboard/ranking',
|
||
'status' => $this->auth->check('shopro/dashboard/ranking')
|
||
],
|
||
];
|
||
$this->assignconfig('cardList', $cardList);
|
||
return $this->view->fetch();
|
||
}
|
||
|
||
|
||
public function total()
|
||
{
|
||
// 1. 基础用户数据 (保持向下兼容)
|
||
$userData = [
|
||
'total' => User::count(),
|
||
'today' => User::whereTime('createtime', 'today')->count(),
|
||
'week' => User::whereTime('createtime', 'week')->count(),
|
||
'array' => collection(User::field('id,createtime')->whereTime('createtime', 'today')->select())->each(function ($user) {
|
||
$user->counter = 1;
|
||
$user->createtime_unix = $user->getData('createtime') * 1000;
|
||
})
|
||
];
|
||
|
||
// 2. 合伙股东基础数据 (保持向下兼容)
|
||
$agentData = [
|
||
'total' => Agent::count(),
|
||
'today' => Agent::whereTime('createtime', 'today')->count(),
|
||
'week' => Agent::whereTime('createtime', 'week')->count(),
|
||
'array' => collection(Agent::field('user_id,createtime')->whereTime('createtime', 'today')->select())->each(function ($agent) {
|
||
$agent->counter = 1;
|
||
$agent->createtime_unix = $agent->getData('createtime') * 1000;
|
||
})
|
||
];
|
||
|
||
// 3. 分享数据 (保持向下兼容)
|
||
$shareData = [
|
||
'total' => Share::count(),
|
||
'today' => Share::whereTime('createtime', 'today')->count(),
|
||
'week' => Share::whereTime('createtime', 'week')->count(),
|
||
'array' => collection(Share::field('id,createtime')->whereTime('createtime', 'today')->select())->each(function ($share) {
|
||
$share->counter = 1;
|
||
$share->createtime_unix = $share->getData('createtime') * 1000;
|
||
})
|
||
];
|
||
|
||
// 4. 全局实收流水与资金大盘 (以 paid_time 为准,与商户号入账对齐)
|
||
$paidStatuses = [Order::STATUS_PAID, Order::STATUS_COMPLETED];
|
||
$totalGmv = (float) Order::whereIn('status', $paidStatuses)->sum('pay_fee');
|
||
|
||
$todayStart = strtotime('today');
|
||
$todayEnd = strtotime('tomorrow') - 1;
|
||
$getTodayPaidQuery = function() use ($paidStatuses, $todayStart, $todayEnd) {
|
||
return Order::whereIn('status', $paidStatuses)
|
||
->whereRaw("((paid_time >= {$todayStart} AND paid_time <= {$todayEnd}) OR ((paid_time IS NULL OR paid_time = 0) AND createtime >= {$todayStart} AND createtime <= {$todayEnd}))");
|
||
};
|
||
$todayGmv = (float) $getTodayPaidQuery()->sum('pay_fee');
|
||
$paidOrderCount = (int) Order::whereIn('status', $paidStatuses)->count();
|
||
$todayPaidOrderCount = (int) $getTodayPaidQuery()->count();
|
||
$avgOrderAmount = $paidOrderCount > 0 ? round($totalGmv / $paidOrderCount, 2) : 0.00;
|
||
|
||
// 退款数据统计
|
||
$totalRefundAmount = (float) Refund::where('status', 'completed')->sum('refund_fee');
|
||
$totalRefundCount = (int) Refund::where('status', 'completed')->count();
|
||
$todayRefundAmount = (float) Refund::where('status', 'completed')->whereTime('createtime', 'today')->sum('refund_fee');
|
||
|
||
// 净营收 (GMV 扣除退款)
|
||
$netGmv = max(0, round($totalGmv - $totalRefundAmount, 2));
|
||
$todayNetGmv = max(0, round($todayGmv - $todayRefundAmount, 2));
|
||
$refundRate = $totalGmv > 0 ? round(($totalRefundAmount / $totalGmv) * 100, 2) : 0.00;
|
||
|
||
// 现金分成总支出 (status = 1 真实入账)
|
||
$totalPayout = (float) Reward::where('status', 1)->sum('amount');
|
||
$todayPayout = (float) Reward::where('status', 1)->whereTime('createtime', 'today')->sum('amount');
|
||
|
||
// 平台有效留存 = 有效净 GMV (扣除退款后) - 真实分成总支出
|
||
$netRetention = round($netGmv - $totalPayout, 2);
|
||
// 真实综合分成拨比 = 真实分成支出 / 有效净 GMV
|
||
$payoutRate = $netGmv > 0 ? round(($totalPayout / $netGmv) * 100, 2) : 0.00;
|
||
|
||
$wealthData = [
|
||
'total_gmv' => number_format($totalGmv, 2, '.', ''),
|
||
'today_gmv' => number_format($todayGmv, 2, '.', ''),
|
||
'total_refund_amount' => number_format($totalRefundAmount, 2, '.', ''),
|
||
'total_refund_count' => $totalRefundCount,
|
||
'net_gmv' => number_format($netGmv, 2, '.', ''),
|
||
'today_net_gmv' => number_format($todayNetGmv, 2, '.', ''),
|
||
'total_payout' => number_format($totalPayout, 2, '.', ''),
|
||
'today_payout' => number_format($todayPayout, 2, '.', ''),
|
||
'net_retention' => number_format($netRetention, 2, '.', ''),
|
||
'payout_rate' => number_format($payoutRate, 2, '.', ''),
|
||
'refund_rate' => number_format($refundRate, 2, '.', ''),
|
||
'paid_order_count' => $paidOrderCount,
|
||
'today_paid_order_count' => $todayPaidOrderCount,
|
||
'avg_order_amount' => number_format($avgOrderAmount, 2, '.', ''),
|
||
];
|
||
|
||
// 5. 生态营销资产蓄水池 (基于日结订单利润均分释放,单向升值赋能,无现金刚性回购)
|
||
$totalMadow = (float) Agent::sum('madow');
|
||
$rateService = new RateService();
|
||
$currentRate = $rateService->currentRate();
|
||
$totalMadowCny = round($totalMadow * $currentRate, 2);
|
||
$historyOrderN = $rateService->countN();
|
||
|
||
$latestReport = DailyReport::order('settle_date', 'desc')->find();
|
||
$yesterdayMadowPool = $latestReport ? (float) $latestReport->madow_pool : 0.00;
|
||
|
||
$madowData = [
|
||
'total_madow' => IdentityService::formatMadow($totalMadow),
|
||
'current_rate' => number_format($currentRate, 10, '.', ''),
|
||
'rate_per_wan' => number_format($currentRate * 10000, 4, '.', ''),
|
||
'total_madow_cny' => number_format($totalMadowCny, 2, '.', ''),
|
||
'history_order_n' => $historyOrderN,
|
||
'yesterday_madow_pool' => IdentityService::formatMadow($yesterdayMadowPool),
|
||
];
|
||
|
||
// 6. 消费兑换券杠杆池 (商城购物抵扣补贴,非现金兑付,无现金偿债压力)
|
||
$totalVoucher = (float) VoucherPlan::sum('total_amount');
|
||
$releasedVoucher = (float) VoucherPlan::sum('released_amount');
|
||
$usedVoucher = (float) Agent::sum('voucher_used');
|
||
$pendingVoucher = max(0, round($totalVoucher - $releasedVoucher, 2));
|
||
$availableVoucher = max(0, round($releasedVoucher - $usedVoucher, 2));
|
||
|
||
$voucherData = [
|
||
'total_voucher' => number_format($totalVoucher, 2, '.', ''),
|
||
'released_voucher' => number_format($releasedVoucher, 2, '.', ''),
|
||
'used_voucher' => number_format($usedVoucher, 2, '.', ''),
|
||
'pending_voucher' => number_format($pendingVoucher, 2, '.', ''),
|
||
'available_voucher' => number_format($availableVoucher, 2, '.', ''),
|
||
];
|
||
|
||
// 7. 合伙股东网络与全角色身份矩阵 (收益按角色专属类型归集,杜绝重复统计)
|
||
$totalRegisteredUsers = (int) User::count();
|
||
$totalAgents = (int) Agent::count();
|
||
$normalUserCount = max(0, $totalRegisteredUsers - $totalAgents);
|
||
|
||
$tasterCount = (int) Agent::where('level', 1)->count();
|
||
$makerCount = (int) Agent::where('level', '>=', 2)->count();
|
||
$makerLevels = [];
|
||
for ($lv = 2; $lv <= 7; $lv++) {
|
||
$makerLevels['V' . ($lv - 1)] = (int) Agent::where('level', $lv)->count();
|
||
}
|
||
$venueCount = (int) Agent::where('is_venue', 1)->count();
|
||
$countyCount = (int) Agent::where('is_county', 1)->count();
|
||
|
||
// 30天自购活跃度核算 (对接 ActiveService 标准服务类)
|
||
$activeService = new ActiveService();
|
||
$now = time();
|
||
$activeDays = PartnerConfig::activeDays();
|
||
$activeWindowStart = $activeService->windowStart($now);
|
||
$warningWindowStart = $now - (($activeDays - 7) * 86400);
|
||
|
||
// 获取全量合格自购活跃用户 ID 集合 (含历史有效订单容错)
|
||
$activeUserIds = $activeService->activeUserIds($activeWindowStart, $now);
|
||
$activeUserMap = array_flip($activeUserIds);
|
||
|
||
// 全量合伙股东基础信息
|
||
$allAgents = Agent::field('user_id, level, is_venue, is_county, madow, last_self_order_time')->select();
|
||
|
||
// 收益明细按 (user_id + reward_type) 聚合,精确归集各角色产出收益
|
||
$userRewardAgg = Reward::where('status', 1)
|
||
->where('user_id', '>', 0)
|
||
->field('user_id, reward_type, sum(amount) as total_amount, count(*) as count')
|
||
->group('user_id, reward_type')
|
||
->select();
|
||
|
||
$userTypeRewards = [];
|
||
foreach ($userRewardAgg as $rw) {
|
||
$uid = (int) $rw->user_id;
|
||
$rType = (string) $rw->reward_type;
|
||
if (!isset($userTypeRewards[$uid])) {
|
||
$userTypeRewards[$uid] = [];
|
||
}
|
||
$userTypeRewards[$uid][$rType] = [
|
||
'amount' => (float) $rw->total_amount,
|
||
'count' => (int) $rw->count,
|
||
];
|
||
}
|
||
|
||
// 角色专属收益类型映射表
|
||
$roleRewardTypeFilter = [
|
||
'taster' => ['push3'],
|
||
'maker' => ['maker_diff', 'maker_peer', 'maker_overtaken'],
|
||
'venue' => ['team_venue', 'venue_peer', 'venue_share'],
|
||
'county' => ['team_county', 'county_peer', 'county_share'],
|
||
];
|
||
|
||
$calcRoleStats = function ($filterCallback, $roleKey, $roleName, $category, $unit, $badge, $color, $filterLevel = '', $filterType = '', $rewardTypeCategory = null) use ($allAgents, $userTypeRewards, $currentRate, $activeUserMap) {
|
||
$uCount = 0;
|
||
$madowTotal = 0.0;
|
||
$rewardAmt = 0.0;
|
||
$rewardCnt = 0;
|
||
$activeCnt = 0;
|
||
|
||
foreach ($allAgents as $ag) {
|
||
if ($filterCallback($ag)) {
|
||
$uCount++;
|
||
$madowTotal = (float) bcadd((string)$madowTotal, (string)($ag->madow ?? 0), 8);
|
||
$uid = (int) $ag->user_id;
|
||
|
||
// 收益按角色类型精准归集
|
||
if (isset($userTypeRewards[$uid])) {
|
||
foreach ($userTypeRewards[$uid] as $rtype => $rdata) {
|
||
$match = false;
|
||
if ($rewardTypeCategory === null) {
|
||
$match = true;
|
||
} elseif (is_array($rewardTypeCategory) && in_array($rtype, $rewardTypeCategory)) {
|
||
$match = true;
|
||
}
|
||
if ($match) {
|
||
$rewardAmt = round($rewardAmt + $rdata['amount'], 2);
|
||
$rewardCnt += $rdata['count'];
|
||
}
|
||
}
|
||
}
|
||
|
||
if (isset($activeUserMap[$uid])) {
|
||
$activeCnt++;
|
||
}
|
||
}
|
||
}
|
||
|
||
$madowCny = round($madowTotal * $currentRate, 2);
|
||
$activeRate = $uCount > 0 ? round(($activeCnt / $uCount) * 100, 1) : 0.0;
|
||
|
||
return [
|
||
'role_key' => $roleKey,
|
||
'role_name' => $roleName,
|
||
'category' => $category,
|
||
'unit' => $unit,
|
||
'badge' => $badge,
|
||
'color' => $color,
|
||
'user_count' => $uCount,
|
||
'madow_total' => IdentityService::formatMadow($madowTotal),
|
||
'madow_cny' => number_format($madowCny, 2, '.', ''),
|
||
'madow_cny_raw' => round($madowTotal * $currentRate, 4),
|
||
'reward_amount' => number_format($rewardAmt, 2, '.', ''),
|
||
'reward_count' => $rewardCnt,
|
||
'active_count' => $activeCnt,
|
||
'active_rate' => $activeRate,
|
||
'is_exempt_active' => false,
|
||
'filter_level' => $filterLevel,
|
||
'filter_type' => $filterType,
|
||
];
|
||
};
|
||
|
||
// 统计各角色身份详细指标
|
||
$roleList = [
|
||
$calcRoleStats(function($a) { return (int)$a->level == 1; }, 'taster', '品酒师', '基础身份', '人', '品', '#806af6', 1, '', $roleRewardTypeFilter['taster']),
|
||
$calcRoleStats(function($a) { return (int)$a->level == 2; }, 'maker_v1', '创客V1', '创客梯队', '人', 'V1', '#13c2c2', 2, '', $roleRewardTypeFilter['maker']),
|
||
$calcRoleStats(function($a) { return (int)$a->level == 3; }, 'maker_v2', '创客V2', '创客梯队', '人', 'V2', '#13c2c2', 3, '', $roleRewardTypeFilter['maker']),
|
||
$calcRoleStats(function($a) { return (int)$a->level == 4; }, 'maker_v3', '创客V3', '创客梯队', '人', 'V3', '#13c2c2', 4, '', $roleRewardTypeFilter['maker']),
|
||
$calcRoleStats(function($a) { return (int)$a->level == 5; }, 'maker_v4', '创客V4', '创客梯队', '人', 'V4', '#13c2c2', 5, '', $roleRewardTypeFilter['maker']),
|
||
$calcRoleStats(function($a) { return (int)$a->level == 6; }, 'maker_v5', '创客V5', '创客梯队', '人', 'V5', '#13c2c2', 6, '', $roleRewardTypeFilter['maker']),
|
||
$calcRoleStats(function($a) { return (int)$a->level == 7; }, 'maker_v6', '创客V6', '创客梯队', '人', 'V6', '#13c2c2', 7, '', $roleRewardTypeFilter['maker']),
|
||
$calcRoleStats(function($a) { return (int)$a->level >= 2; }, 'maker_total', '创客队伍小计', '创客梯队', '人', '创', '#13c2c2', 'maker', '', $roleRewardTypeFilter['maker']),
|
||
$calcRoleStats(function($a) { return (int)$a->is_venue == 1; }, 'venue', '实体酒道馆', '渠道授权', '家', '馆', '#fa8c16', '', 'venue', $roleRewardTypeFilter['venue']),
|
||
$calcRoleStats(function($a) { return (int)$a->is_county == 1; }, 'county', '区县代理', '渠道授权', '个', '县', '#722ed1', '', 'county', $roleRewardTypeFilter['county']),
|
||
];
|
||
|
||
// 增加普通注册会员行 (明确标明无需自购考核)
|
||
$roleList[] = [
|
||
'role_key' => 'normal_user',
|
||
'role_name' => '普通注册会员',
|
||
'category' => '电商用户',
|
||
'unit' => '人',
|
||
'badge' => '普',
|
||
'color' => '#8c8c8c',
|
||
'user_count' => $normalUserCount,
|
||
'madow_total' => '0.00000000',
|
||
'madow_cny' => '0.00',
|
||
'madow_cny_raw' => 0.0,
|
||
'reward_amount' => '0.00',
|
||
'reward_count' => 0,
|
||
'active_count' => '-',
|
||
'active_rate' => 100,
|
||
'is_exempt_active' => true,
|
||
'active_text' => '无需自购考核',
|
||
'filter_level' => '',
|
||
'filter_type' => 'normal',
|
||
];
|
||
|
||
// 全平台全员合计行 (总马豆与总分佣与顶部大盘完全一致)
|
||
$allTotalRow = [
|
||
'role_key' => 'all_total',
|
||
'role_name' => '全平台全员合计',
|
||
'category' => '全网总计',
|
||
'unit' => '人',
|
||
'badge' => '全',
|
||
'color' => '#1890ff',
|
||
'user_count' => $totalRegisteredUsers,
|
||
'madow_total' => IdentityService::formatMadow($totalMadow),
|
||
'madow_cny' => number_format($totalMadowCny, 2, '.', ''),
|
||
'madow_cny_raw' => $totalMadowCny,
|
||
'reward_amount' => number_format($totalPayout, 2, '.', ''),
|
||
'reward_count' => (int) Reward::where('status', 1)->count(),
|
||
'active_count' => count($activeUserIds),
|
||
'active_rate' => $totalAgents > 0 ? round((count($activeUserIds) / $totalAgents) * 100, 1) : 0.0,
|
||
'is_exempt_active' => false,
|
||
'filter_level' => '',
|
||
'filter_type' => 'all',
|
||
];
|
||
$roleList[] = $allTotalRow;
|
||
|
||
$roleStats = [];
|
||
foreach ($roleList as $rItem) {
|
||
$roleStats[$rItem['role_key']] = $rItem;
|
||
}
|
||
|
||
$activePartnersCount = count($activeUserIds);
|
||
$inactiveCount = max(0, $totalAgents - $activePartnersCount);
|
||
$activeRate = $totalAgents > 0 ? round(($activePartnersCount / $totalAgents) * 100, 1) : 0.0;
|
||
|
||
$partnerNetwork = [
|
||
'total_registered_users' => $totalRegisteredUsers,
|
||
'total_agents' => $totalAgents,
|
||
'normal_user_count' => $normalUserCount,
|
||
'taster_count' => $tasterCount,
|
||
'maker_count' => $makerCount,
|
||
'maker_levels' => $makerLevels,
|
||
'venue_count' => $venueCount,
|
||
'county_count' => $countyCount,
|
||
'active_count' => $activePartnersCount,
|
||
'inactive_count' => $inactiveCount,
|
||
'active_rate' => $activeRate,
|
||
'role_list' => $roleList,
|
||
'role_stats' => $roleStats,
|
||
];
|
||
|
||
// 8. CFO 视角:平台资金池结余、刚性法币流动负债与提现风控
|
||
$userCommissionFloat = (float) User::sum('commission');
|
||
$userMoneyFloat = (float) User::sum('money');
|
||
$totalFloatFunds = round($userCommissionFloat + $userMoneyFloat, 2);
|
||
|
||
$totalWithdrawApplied = (float) Withdraw::sum('amount');
|
||
$totalWithdrawPaid = (float) Withdraw::where('status', 2)->sum('paid_fee');
|
||
$pendingWithdrawAmount = (float) Withdraw::where('status', 0)->sum('amount');
|
||
$pendingWithdrawCount = (int) Withdraw::where('status', 0)->count();
|
||
|
||
// 提现审核完成率 = 已打款出款 / 累计申请总额
|
||
$withdrawAuditRate = $totalWithdrawApplied > 0 ? round(($totalWithdrawPaid / $totalWithdrawApplied) * 100, 2) : 0.0;
|
||
// 佣金提现转化率 = 已打款出款 / 累计产生分成
|
||
$commissionCashRate = $totalPayout > 0 ? round(($totalWithdrawPaid / $totalPayout) * 100, 2) : 0.0;
|
||
|
||
// 平台商户号可用流动资金结余 = 实付总额 - 累计退款 - 已打款出款
|
||
$realNetCashFlow = round($totalGmv - $totalRefundAmount - $totalWithdrawPaid, 2);
|
||
|
||
// 平台刚性法币现金流动负债 = 用户未提现佣金 + 用户账户可用余额 + 待审核打款提现
|
||
$rigidCashLiability = round($userCommissionFloat + $userMoneyFloat + $pendingWithdrawAmount, 2);
|
||
|
||
$financeOverview = [
|
||
'commission_float' => number_format($userCommissionFloat, 2, '.', ''),
|
||
'user_balance_float' => number_format($userMoneyFloat, 2, '.', ''),
|
||
'total_float_funds' => number_format($totalFloatFunds, 2, '.', ''),
|
||
'pending_withdraw_amount' => number_format($pendingWithdrawAmount, 2, '.', ''),
|
||
'pending_withdraw_count' => $pendingWithdrawCount,
|
||
'rigid_cash_liability' => number_format($rigidCashLiability, 2, '.', ''), // 刚性法币流动负债
|
||
'total_withdraw_applied' => number_format($totalWithdrawApplied, 2, '.', ''),
|
||
'total_withdraw_paid' => number_format($totalWithdrawPaid, 2, '.', ''),
|
||
'withdraw_audit_rate' => $withdrawAuditRate, // 提现审核完成率
|
||
'commission_cash_rate' => $commissionCashRate, // 佣金提现转化率
|
||
'total_refund_amount' => number_format($totalRefundAmount, 2, '.', ''),
|
||
'total_refund_count' => $totalRefundCount,
|
||
'refund_rate' => $refundRate,
|
||
'real_net_cash_flow' => number_format($realNetCashFlow, 2, '.', ''), // 真实资金留存
|
||
// 生态非现金权益存量(清晰标注)
|
||
'madow_market_val' => number_format($totalMadowCny, 2, '.', ''),
|
||
'pending_voucher_quota' => number_format($pendingVoucher, 2, '.', ''),
|
||
];
|
||
|
||
// 9. COO 视角:转化复购漏斗、合伙股东自购续期雷达、供应链库存与实时待办看板
|
||
$paidOrderUsers = Order::whereIn('status', [Order::STATUS_PAID, Order::STATUS_COMPLETED])
|
||
->group('user_id')
|
||
->field('user_id, count(*) as buy_count')
|
||
->select();
|
||
|
||
$paidUsersCount = count($paidOrderUsers);
|
||
$singleBuyCount = 0;
|
||
$repeatBuyCount = 0;
|
||
foreach ($paidOrderUsers as $buyer) {
|
||
if ((int)$buyer->buy_count > 1) {
|
||
$repeatBuyCount++;
|
||
} else {
|
||
$singleBuyCount++;
|
||
}
|
||
}
|
||
$payConversionRate = $totalRegisteredUsers > 0 ? round(($paidUsersCount / $totalRegisteredUsers) * 100, 1) : 0.0;
|
||
$repeatPurchaseRate = $paidUsersCount > 0 ? round(($repeatBuyCount / $paidUsersCount) * 100, 1) : 0.0;
|
||
$arpu = $paidUsersCount > 0 ? round($netGmv / $paidUsersCount, 2) : 0.0;
|
||
|
||
// 9.2 合伙股东 30 天自购续期雷达 (仅统计具备合伙股东身份的会员,避免恐慌误判)
|
||
$activePartnersCount = 0;
|
||
$warningPartnersCount = 0;
|
||
$pendingRenewCount = 0;
|
||
$newNoOrderCount = 0;
|
||
$warningList = [];
|
||
$pendingRenewList = [];
|
||
$partnerShareholderCount = 0;
|
||
|
||
$agentUserIds = array_column(collection($allAgents)->toArray(), 'user_id');
|
||
$agentUserMap = [];
|
||
if (!empty($agentUserIds)) {
|
||
$agentUserRows = User::whereIn('id', $agentUserIds)->field('id, nickname, mobile, avatar')->select();
|
||
foreach ($agentUserRows as $uRow) {
|
||
$agentUserMap[$uRow->id] = $uRow;
|
||
}
|
||
}
|
||
|
||
foreach ($allAgents as $ag) {
|
||
$identityData = IdentityService::build($ag);
|
||
// 核心业务规范:合伙股东仅是会员体系下的专属进阶身份(创客V1~V6、酒道馆、区县代理)
|
||
// 普通会员与品酒师属于基础会员,无需自购考核,排除在股东自购掉队雷达之外
|
||
if (empty($identityData['is_partner'])) {
|
||
continue;
|
||
}
|
||
$partnerShareholderCount++;
|
||
|
||
$uid = (int) $ag->user_id;
|
||
$u = $agentUserMap[$uid] ?? null;
|
||
$nickname = $u ? ($u->nickname ?: '用户#' . $uid) : ('用户#' . $uid);
|
||
$mobile = ($u && $u->mobile) ? substr_replace($u->mobile, '****', 3, 4) : '-';
|
||
$avatar = $u ? ($u->avatar ?: '') : '';
|
||
$identityText = $identityData['identity_text'] ?: ('Lv.' . $ag->level);
|
||
|
||
$lastTime = (int) $ag->getData('last_self_order_time');
|
||
$isActive = isset($activeUserMap[$uid]);
|
||
|
||
if ($isActive) {
|
||
if ($lastTime > 0 && $lastTime < $warningWindowStart) {
|
||
// 临近续期预警 (1~7天内需续期自购)
|
||
$warningPartnersCount++;
|
||
$daysLeft = max(1, (int) ceil(($lastTime + $activeDays * 86400 - $now) / 86400));
|
||
$warningList[] = [
|
||
'user_id' => $uid,
|
||
'nickname' => $nickname,
|
||
'avatar' => $avatar,
|
||
'mobile' => $mobile,
|
||
'level_text' => $identityText,
|
||
'last_order_date' => date('Y-m-d H:i', $lastTime),
|
||
'days_left' => $daysLeft,
|
||
];
|
||
} else {
|
||
// 安全活跃达标 (>7天余量)
|
||
$activePartnersCount++;
|
||
}
|
||
} else {
|
||
if ($lastTime > 0) {
|
||
// 待续期激活 (已超30天未自购,自购1单即可恢复极差资格)
|
||
$pendingRenewCount++;
|
||
if (count($pendingRenewList) < 10) {
|
||
$overdueDays = max(1, (int) floor(($now - $lastTime) / 86400) - $activeDays);
|
||
$pendingRenewList[] = [
|
||
'user_id' => $uid,
|
||
'nickname' => $nickname,
|
||
'avatar' => $avatar,
|
||
'mobile' => $mobile,
|
||
'level_text' => $identityText,
|
||
'last_order_date' => date('Y-m-d H:i', $lastTime),
|
||
'overdue_text' => "超期 {$overdueDays} 天待续",
|
||
];
|
||
}
|
||
} else {
|
||
// 新晋股东待自购首购 (尚未下单)
|
||
$newNoOrderCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 股东专属自购达标率(分子为在保合格股东,分母为合伙股东总人数)
|
||
$partnerActiveRate = $partnerShareholderCount > 0
|
||
? round((($activePartnersCount + $warningPartnersCount) / $partnerShareholderCount) * 100, 1)
|
||
: 0.0;
|
||
$partnerNetwork['active_rate'] = $partnerActiveRate;
|
||
|
||
// 9.3 供应链库存安全与动销商品
|
||
$onSaleGoodsCount = (int) Goods::where('status', 'up')->count();
|
||
$totalStock = (int) SkuPriceModel::where('status', 'up')->sum('stock');
|
||
$lowStockCount = (int) SkuPriceModel::alias('sp')
|
||
->join('shopro_goods g', 'sp.goods_id = g.id')
|
||
->where('g.status', 'up')
|
||
->where('sp.status', 'up')
|
||
->where('sp.stock', '<=', 10)
|
||
->count();
|
||
|
||
$lowStockSkuList = SkuPriceModel::alias('sp')
|
||
->join('shopro_goods g', 'sp.goods_id = g.id')
|
||
->where('g.status', 'up')
|
||
->where('sp.status', 'up')
|
||
->where('sp.stock', '<=', 10)
|
||
->field('sp.id as sku_id, sp.goods_id, g.title as goods_title, g.image as goods_image, sp.goods_sku_text, sp.stock, sp.price')
|
||
->order('sp.stock', 'asc')
|
||
->limit(10)
|
||
->select();
|
||
|
||
$lowStockFormatted = [];
|
||
foreach ($lowStockSkuList as $lsku) {
|
||
$skuText = is_array($lsku->goods_sku_text) ? implode(' ', $lsku->goods_sku_text) : ($lsku->goods_sku_text ?: '默认单规格');
|
||
$lowStockFormatted[] = [
|
||
'sku_id' => $lsku->sku_id,
|
||
'goods_id' => $lsku->goods_id,
|
||
'goods_title' => $lsku->goods_title,
|
||
'goods_image' => $lsku->goods_image,
|
||
'sku_text' => $skuText,
|
||
'stock' => (int) $lsku->stock,
|
||
'price' => $lsku->price,
|
||
];
|
||
}
|
||
|
||
// 9.4 平台客观风控指标看板 (客观真实区间,替换主观伪评分)
|
||
$riskIndicators = [
|
||
'payout_rate' => [
|
||
'val' => $payoutRate,
|
||
'text' => $payoutRate <= 35 ? '支出比例正常 (≤35%)' : ($payoutRate <= 50 ? '支出偏高 (35%~50%)' : '支出过高需关注 (>50%)'),
|
||
'status' => $payoutRate <= 35 ? 'success' : ($payoutRate <= 50 ? 'warning' : 'danger'),
|
||
],
|
||
'partner_active_rate' => [
|
||
'val' => $activeRate,
|
||
'text' => "达标率 {$activeRate}%",
|
||
'status' => $activeRate >= 50 ? 'success' : 'warning',
|
||
],
|
||
'withdraw_audit_rate' => [
|
||
'val' => $withdrawAuditRate,
|
||
'text' => "打款率 {$withdrawAuditRate}%",
|
||
'status' => $withdrawAuditRate >= 90 ? 'success' : 'warning',
|
||
],
|
||
'refund_rate' => [
|
||
'val' => $refundRate,
|
||
'text' => $refundRate <= 2.0 ? '退款极低 (≤2%)' : ($refundRate <= 5.0 ? '正常可控 (2%~5%)' : '退款偏高 (>5%)'),
|
||
'status' => $refundRate <= 2.0 ? 'success' : ($refundRate <= 5.0 ? 'warning' : 'danger'),
|
||
],
|
||
];
|
||
|
||
$riskSuggestions = [];
|
||
if ($payoutRate <= 35) {
|
||
$riskSuggestions[] = "分成支出占比 {$payoutRate}%,处于正常合理区间,平台收益结余稳固。";
|
||
} elseif ($payoutRate <= 50) {
|
||
$riskSuggestions[] = "分成支出占比 {$payoutRate}%,略高于正常参考线,建议提升高毛利商品的销售占比。";
|
||
} else {
|
||
$riskSuggestions[] = "分成支出占比 {$payoutRate}% 超出常规合理范围,请检查各层级分成与日结奖励设置。";
|
||
}
|
||
if ($warningPartnersCount > 0) {
|
||
$riskSuggestions[] = "有 {$warningPartnersCount} 位合伙股东 7 天内自购即将到期,建议及时提醒自购维持资格。";
|
||
}
|
||
if ($pendingWithdrawCount > 0) {
|
||
$riskSuggestions[] = "当前有 {$pendingWithdrawCount} 笔提现申请等待审核(¥{$financeOverview['pending_withdraw_amount']}),请及时处理。";
|
||
}
|
||
if ($lowStockCount > 0) {
|
||
$riskSuggestions[] = "仓库有 {$lowStockCount} 款商品库存不足(≤10件),请及时补充库存。";
|
||
}
|
||
|
||
// 9.5 全局实时待办看板 (100% 实时统计,不受日期选择框影响,杜绝漏单漏审)
|
||
$realtimeNosend = (int) Order::pretendPaid()->nosend()->count();
|
||
$realtimeAftersale = (int) Aftersale::whereIn('aftersale_status', [Aftersale::AFTERSALE_STATUS_NOOPER, Aftersale::AFTERSALE_STATUS_ING])->count();
|
||
$realtimeRefundApply = (int) Order::paid()->where('apply_refund_status', Order::APPLY_REFUND_STATUS_APPLY)->count();
|
||
|
||
$todoOverview = [
|
||
'nosend_count' => $realtimeNosend,
|
||
'aftersale_count' => $realtimeAftersale,
|
||
'refund_apply_count' => $realtimeRefundApply,
|
||
'pending_withdraw_count' => $pendingWithdrawCount,
|
||
'low_stock_count' => $lowStockCount,
|
||
];
|
||
|
||
$operationOverview = [
|
||
'total_registered' => $totalRegisteredUsers,
|
||
'paid_users_count' => $paidUsersCount,
|
||
'pay_conversion_rate' => $payConversionRate,
|
||
'single_buy_users_count' => $singleBuyCount,
|
||
'repeat_buy_users_count' => $repeatBuyCount,
|
||
'repeat_purchase_rate' => $repeatPurchaseRate,
|
||
'arpu' => number_format($arpu, 2, '.', ''),
|
||
'active_partners' => $activePartnersCount,
|
||
'warning_partners' => $warningPartnersCount,
|
||
'pending_renew_partners' => $pendingRenewCount,
|
||
'new_no_order_partners' => $newNoOrderCount,
|
||
'warning_list' => $warningList,
|
||
'pending_renew_list' => $pendingRenewList,
|
||
'on_sale_goods_count' => $onSaleGoodsCount,
|
||
'total_stock' => $totalStock,
|
||
'low_stock_count' => $lowStockCount,
|
||
'low_stock_list' => $lowStockFormatted,
|
||
'risk_indicators' => $riskIndicators,
|
||
'risk_suggestions' => $riskSuggestions,
|
||
'todo_overview' => $todoOverview,
|
||
];
|
||
|
||
$this->success('获取成功', null, [
|
||
'user_data' => $userData,
|
||
'agent_data' => $agentData ?? null,
|
||
'share_data' => $shareData,
|
||
'wealth_data' => $wealthData,
|
||
'madow_data' => $madowData,
|
||
'voucher_data' => $voucherData,
|
||
'partner_network' => $partnerNetwork,
|
||
'finance_overview' => $financeOverview,
|
||
'operation_overview' => $operationOverview,
|
||
]);
|
||
}
|
||
|
||
|
||
|
||
public function chart()
|
||
{
|
||
$date = $this->request->param('date', '');
|
||
$date = array_values(array_filter(explode(' - ', $date)));
|
||
if (empty($date) || count($date) < 2) {
|
||
$date = [date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')];
|
||
}
|
||
$startTimestamp = strtotime($date[0]);
|
||
$endTimestamp = strtotime($date[1]);
|
||
|
||
// 1. 时段内支付订单 (以支付时间为准,与分成支出时间严格对齐)
|
||
$paidOrders = Order::with(['items'])
|
||
->paid()
|
||
->whereRaw("((paid_time >= {$startTimestamp} AND paid_time <= {$endTimestamp}) OR ((paid_time IS NULL OR paid_time = 0) AND createtime >= {$startTimestamp} AND createtime <= {$endTimestamp}))")
|
||
->order('id', 'asc')
|
||
->select();
|
||
|
||
// 2. 时段内下单订单数 (反映下单活跃度)
|
||
$createdOrders = Order::whereTime('createtime', 'between', $date)
|
||
->order('id', 'asc')
|
||
->select();
|
||
|
||
$data['orderNum'] = count($createdOrders);
|
||
$data['orderArr'] = [];
|
||
foreach ($createdOrders as $co) {
|
||
$rawCt = $co->getData('createtime');
|
||
$cTime = (is_numeric($rawCt) ? intval($rawCt) : strtotime($rawCt)) * 1000;
|
||
$data['orderArr'][] = [
|
||
'counter' => 1,
|
||
'createtime' => $cTime,
|
||
'user_id' => $co->user_id,
|
||
];
|
||
}
|
||
|
||
// 3. 支付统计
|
||
$data['payOrderNum'] = count($paidOrders);
|
||
$data['payOrderArr'] = [];
|
||
$data['payAmountNum'] = '0.00';
|
||
$data['payAmountArr'] = [];
|
||
$userIds = [];
|
||
$data['payUserNum'] = 0;
|
||
$data['payUserArr'] = [];
|
||
|
||
foreach ($paidOrders as $order) {
|
||
$rawPaid = $order->getData('paid_time');
|
||
$rawCt = $order->getData('createtime');
|
||
$oTimestamp = 0;
|
||
if ($rawPaid) {
|
||
$oTimestamp = is_numeric($rawPaid) ? intval($rawPaid) : strtotime($rawPaid);
|
||
} elseif ($rawCt) {
|
||
$oTimestamp = is_numeric($rawCt) ? intval($rawCt) : strtotime($rawCt);
|
||
}
|
||
$pTime = $oTimestamp * 1000;
|
||
$data['payOrderArr'][] = [
|
||
'counter' => 1,
|
||
'createtime' => $pTime,
|
||
'user_id' => $order->user_id,
|
||
];
|
||
$data['payAmountNum'] = bcadd((string)$data['payAmountNum'], (string)$order->pay_fee, 2);
|
||
$data['payAmountArr'][] = [
|
||
'counter' => (float) $order->pay_fee,
|
||
'createtime' => $pTime,
|
||
];
|
||
if (!in_array($order->user_id, $userIds)) {
|
||
$userIds[] = $order->user_id;
|
||
$data['payUserNum']++;
|
||
$data['payUserArr'][] = [
|
||
'counter' => 1,
|
||
'createtime' => $pTime,
|
||
'user_id' => $order->user_id,
|
||
];
|
||
}
|
||
}
|
||
|
||
// 全局实时待办数据 (不受时段过滤影响,彻底杜绝漏单漏审)
|
||
$data['noSendNum'] = (int) Order::pretendPaid()->nosend()->count();
|
||
$data['aftersaleNum'] = (int) Aftersale::whereIn('aftersale_status', [Aftersale::AFTERSALE_STATUS_NOOPER, Aftersale::AFTERSALE_STATUS_ING])->count();
|
||
$data['refundNum'] = (int) Order::paid()->where('apply_refund_status', Order::APPLY_REFUND_STATUS_APPLY)->count();
|
||
|
||
// 4. 收益分成时段穿透 (以分成入账时间为准)
|
||
$rewards = Reward::where('status', 1)
|
||
->whereTime('createtime', 'between', $date)
|
||
->order('id', 'asc')
|
||
->select();
|
||
|
||
$payoutTotal = 0.00;
|
||
$payoutArr = [];
|
||
$periodMadow = 0.00000000;
|
||
|
||
// 四大业务板块结构
|
||
$structureMap = [
|
||
'push3' => [
|
||
'key' => 'push3',
|
||
'name' => '推荐开拓奖励',
|
||
'types' => ['push3'],
|
||
'amount' => 0.00,
|
||
'count' => 0,
|
||
'color' => '#806AF6',
|
||
],
|
||
'maker' => [
|
||
'key' => 'maker',
|
||
'name' => '创客进阶协同奖励',
|
||
'types' => ['maker_diff', 'maker_peer', 'maker_overtaken'],
|
||
'amount' => 0.00,
|
||
'count' => 0,
|
||
'color' => '#13c2c2',
|
||
],
|
||
'channel' => [
|
||
'key' => 'channel',
|
||
'name' => '实体统筹协同奖励',
|
||
'types' => ['team_venue', 'team_county', 'venue_peer', 'county_peer'],
|
||
'amount' => 0.00,
|
||
'count' => 0,
|
||
'color' => '#fa8c16',
|
||
],
|
||
'share' => [
|
||
'key' => 'share',
|
||
'name' => '全网加权贡献奖励',
|
||
'types' => ['venue_share', 'county_share'],
|
||
'amount' => 0.00,
|
||
'count' => 0,
|
||
'color' => '#eb2f96',
|
||
],
|
||
];
|
||
|
||
// 详细奖项映射
|
||
$detailList = [];
|
||
foreach (PartnerConfig::rewardTypeMap() as $typeKey => $typeName) {
|
||
if (in_array($typeKey, ['madow_share', 'voucher_grant', 'voucher_release'])) {
|
||
continue;
|
||
}
|
||
$detailList[$typeKey] = [
|
||
'type' => $typeKey,
|
||
'name' => $typeName,
|
||
'amount' => 0.00,
|
||
'count' => 0,
|
||
];
|
||
}
|
||
|
||
foreach ($rewards as $reward) {
|
||
$amt = (float) $reward->amount;
|
||
$rwType = $reward->reward_type;
|
||
|
||
if ($rwType === 'madow_share') {
|
||
$periodMadow = function_exists('bcadd')
|
||
? (float) bcadd((string)$periodMadow, (string)($reward->madow ?? 0), 8)
|
||
: ($periodMadow + (float)($reward->madow ?? 0));
|
||
continue;
|
||
}
|
||
|
||
if ($amt > 0) {
|
||
$payoutTotal = round($payoutTotal + $amt, 2);
|
||
$rCt = $reward->getData('createtime');
|
||
$rTime = (is_numeric($rCt) ? intval($rCt) : strtotime($rCt)) * 1000;
|
||
$payoutArr[] = [
|
||
'counter' => $amt,
|
||
'createtime' => $rTime,
|
||
'type' => $rwType,
|
||
];
|
||
|
||
// 归类到板块
|
||
foreach ($structureMap as $catKey => &$cat) {
|
||
if (in_array($rwType, $cat['types'])) {
|
||
$cat['amount'] = round($cat['amount'] + $amt, 2);
|
||
$cat['count']++;
|
||
break;
|
||
}
|
||
}
|
||
unset($cat);
|
||
|
||
if (isset($detailList[$rwType])) {
|
||
$detailList[$rwType]['amount'] = round($detailList[$rwType]['amount'] + $amt, 2);
|
||
$detailList[$rwType]['count']++;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 格式化分成板块占比
|
||
$splitStructure = [];
|
||
foreach ($structureMap as $catKey => $cat) {
|
||
$catAmount = (float) $cat['amount'];
|
||
$ratio = $payoutTotal > 0 ? round(($catAmount / $payoutTotal) * 100, 1) : 0.0;
|
||
$splitStructure[] = [
|
||
'key' => $catKey,
|
||
'name' => $cat['name'],
|
||
'amount' => number_format($catAmount, 2, '.', ''),
|
||
'count' => $cat['count'],
|
||
'ratio' => $ratio,
|
||
'color' => $cat['color'],
|
||
];
|
||
}
|
||
|
||
$payAmountNum = (float) $data['payAmountNum'];
|
||
$data['payoutNum'] = number_format($payoutTotal, 2, '.', '');
|
||
$data['payoutArr'] = $payoutArr;
|
||
$data['retentionNum'] = number_format(max(0, round($payAmountNum - $payoutTotal, 2)), 2, '.', '');
|
||
$data['payoutRate'] = $payAmountNum > 0 ? round(($payoutTotal / $payAmountNum) * 100, 2) : 0.00;
|
||
$data['splitStructure'] = $splitStructure;
|
||
$data['rewardDetails'] = array_values($detailList);
|
||
$data['periodMadow'] = IdentityService::formatMadow($periodMadow);
|
||
|
||
$this->success('获取成功', null, $data);
|
||
}
|
||
|
||
|
||
|
||
public function ranking()
|
||
{
|
||
// 1. 商品真实销量排行 (基于真实已支付订单聚合,杜绝后台虚拟销量刷榜误导)
|
||
$goodsRanking = \think\Db::name('shopro_order_item')->alias('oi')
|
||
->join('shopro_order o', 'oi.order_id = o.id')
|
||
->whereIn('o.status', [Order::STATUS_PAID, Order::STATUS_COMPLETED])
|
||
->field('oi.goods_id, sum(oi.goods_num) as real_sales, sum(oi.goods_num * oi.goods_price) as sale_total_money')
|
||
->group('oi.goods_id')
|
||
->order('real_sales', 'desc')
|
||
->limit(5)
|
||
->select();
|
||
|
||
$goods = [];
|
||
if (!empty($goodsRanking)) {
|
||
$goodsIds = array_column($goodsRanking, 'goods_id');
|
||
$goodsModels = Goods::whereIn('id', $goodsIds)->select();
|
||
$goodsMap = [];
|
||
foreach ($goodsModels as $gm) {
|
||
$goodsMap[$gm->id] = $gm;
|
||
}
|
||
foreach ($goodsRanking as $gr) {
|
||
$gid = $gr['goods_id'];
|
||
$gItem = $goodsMap[$gid] ?? null;
|
||
if ($gItem) {
|
||
$gItem->real_sales = (int) $gr['real_sales'];
|
||
$gItem->sale_total_money = (float) $gr['sale_total_money'];
|
||
$goods[] = $gItem;
|
||
}
|
||
}
|
||
}
|
||
if (empty($goods)) {
|
||
$goods = Goods::where('status', 'up')->limit(5)->order('id', 'desc')->select();
|
||
foreach ($goods as $gd) {
|
||
$gd->real_sales = 0;
|
||
$gd->sale_total_money = 0;
|
||
}
|
||
}
|
||
|
||
// 2. 热搜排行
|
||
$searchHistory = new SearchHistory();
|
||
$hotSearch = $searchHistory->hotSearch();
|
||
|
||
// 3. 合伙股东收益排行 TOP 5
|
||
$partnerRanking = [];
|
||
$rankingRows = Reward::field('user_id, sum(amount) as total_income, count(*) as reward_count')
|
||
->where('status', 1)
|
||
->where('user_id', '>', 0)
|
||
->group('user_id')
|
||
->order('total_income', 'desc')
|
||
->limit(5)
|
||
->select();
|
||
|
||
foreach ($rankingRows as $row) {
|
||
$user = User::field('id, nickname, avatar, mobile')->where('id', $row->user_id)->find();
|
||
$agent = Agent::where('user_id', $row->user_id)->find();
|
||
$identity = IdentityService::build($agent);
|
||
|
||
$partnerRanking[] = [
|
||
'user_id' => $row->user_id,
|
||
'nickname' => $user ? ($user->nickname ?: '用户#' . $row->user_id) : '用户#' . $row->user_id,
|
||
'avatar' => $user ? $user->avatar : '',
|
||
'mobile' => $user ? $user->mobile : '',
|
||
'total_income' => number_format((float)$row->total_income, 2, '.', ''),
|
||
'reward_count' => (int) $row->reward_count,
|
||
'identity_text' => $identity['identity_text'] ?: '普通会员',
|
||
'is_partner' => $identity['is_partner'],
|
||
'direct_order_seq' => $agent ? (int) $agent->direct_order_seq : 0,
|
||
];
|
||
}
|
||
|
||
// 4. 最新日结概览
|
||
$dailyReport = DailyReport::order('settle_date', 'desc')->find();
|
||
$recentReport = null;
|
||
if ($dailyReport) {
|
||
$recentReport = [
|
||
'settle_date' => $dailyReport->settle_date,
|
||
'gmv' => number_format((float)$dailyReport->gmv, 2, '.', ''),
|
||
'order_count' => (int)$dailyReport->order_count,
|
||
'order_count_n' => (int)$dailyReport->order_count_n,
|
||
'rate' => number_format((float)$dailyReport->rate, 10, '.', ''),
|
||
'madow_pool' => IdentityService::formatMadow($dailyReport->madow_pool),
|
||
'share_user_count' => (int)$dailyReport->share_user_count,
|
||
'venue_pool' => number_format((float)$dailyReport->venue_pool, 2, '.', ''),
|
||
'venue_user_count' => (int)$dailyReport->venue_user_count,
|
||
'county_pool' => number_format((float)$dailyReport->county_pool, 2, '.', ''),
|
||
'county_user_count' => (int)$dailyReport->county_user_count,
|
||
'voucher_release_total' => number_format((float)$dailyReport->voucher_release_total, 2, '.', ''),
|
||
'status' => (int)$dailyReport->status,
|
||
'status_text' => $dailyReport->status_text,
|
||
];
|
||
}
|
||
|
||
$this->success('获取成功', null, [
|
||
'goods' => $goods,
|
||
'hot_search' => $hotSearch,
|
||
'partner_ranking' => $partnerRanking,
|
||
'daily_report_recent' => $recentReport,
|
||
]);
|
||
}
|
||
}
|