196 行
8.0 KiB
PHP
196 行
8.0 KiB
PHP
<?php
|
||
|
||
namespace app\admin\controller;
|
||
|
||
use app\admin\model\Appeal;
|
||
use app\admin\model\Master;
|
||
use app\admin\model\Merchant;
|
||
use app\admin\model\Order;
|
||
use app\admin\model\Service;
|
||
use app\admin\model\User;
|
||
use app\admin\model\Withdraw;
|
||
use app\common\controller\Backend;
|
||
use think\Db;
|
||
|
||
/**
|
||
* 优匠优服数字化运营指挥中心(数据大盘首页)
|
||
*
|
||
* @icon fa fa-tachometer
|
||
* @remark 平台核心业务数据大屏,实时监控订单履约、资金流水、运力健康度与待办预警
|
||
*/
|
||
class Home extends Backend
|
||
{
|
||
|
||
public function index()
|
||
{
|
||
try {
|
||
Db::execute("SET @@sql_mode='';");
|
||
} catch (\Exception $e) {
|
||
|
||
}
|
||
|
||
// 1. 时间范围定义
|
||
$todayStart = strtotime(date('Y-m-d 00:00:00'));
|
||
$todayEnd = strtotime(date('Y-m-d 23:59:59'));
|
||
$monthStart = strtotime(date('Y-m-01 00:00:00'));
|
||
|
||
// 2. 核心经营 KPI (真实数据聚合:仅统计已支付且未取消的有效订单流水)
|
||
$totalOrder = Order::count();
|
||
$paidOrderCount = Order::where('pay_status', 1)->where('status', '<>', 9)->count();
|
||
$totalGmv = (float)(Order::where('pay_status', 1)->where('status', '<>', 9)->sum('pay_amount') ?: 0);
|
||
$avgTicket = $paidOrderCount > 0 ? round($totalGmv / $paidOrderCount, 2) : 0;
|
||
|
||
$todayOrderCount = Order::whereBetween('createtime', [$todayStart, $todayEnd])->count();
|
||
$todayGmv = (float)(Db::name('order')
|
||
->where('pay_status', 1)
|
||
->where('status', '<>', 9)
|
||
->whereRaw('IF(pay_time > 0, pay_time, createtime) BETWEEN ' . (int)$todayStart . ' AND ' . (int)$todayEnd)
|
||
->sum('pay_amount') ?: 0);
|
||
$monthGmv = (float)(Db::name('order')
|
||
->where('pay_status', 1)
|
||
->where('status', '<>', 9)
|
||
->whereRaw('IF(pay_time > 0, pay_time, createtime) BETWEEN ' . (int)$monthStart . ' AND ' . (int)$todayEnd)
|
||
->sum('pay_amount') ?: 0);
|
||
|
||
// 运力与商户统计
|
||
$totalMaster = Master::where('verify_status', 'pass')->count();
|
||
$onlineMaster = Master::where('verify_status', 'pass')->where('work_status', 'on')->count();
|
||
$totalMerchant = Merchant::where('verify_status', 'pass')->count();
|
||
$totalUser = Db::name('user')->alias('u')
|
||
->join('master ma', 'ma.user_id = u.id', 'LEFT')
|
||
->join('merchant me', 'me.user_id = u.id', 'LEFT')
|
||
->whereNull('ma.id')
|
||
->whereNull('me.id')
|
||
->count();
|
||
|
||
// 3. 订单状态分布与履约漏斗
|
||
$statusCounts = Order::field('status, count(*) as cnt')
|
||
->group('status')
|
||
->select();
|
||
$statusCountMap = [];
|
||
foreach ($statusCounts as $s) {
|
||
$statusCountMap[$s['status']] = (int)$s['cnt'];
|
||
}
|
||
|
||
$unpaidCount = $statusCountMap[0] ?? 0;
|
||
$waitDispatchCount = $statusCountMap[1] ?? 0;
|
||
$inServiceCount = ($statusCountMap[3] ?? 0) + ($statusCountMap[4] ?? 0) + ($statusCountMap[5] ?? 0) + ($statusCountMap[6] ?? 0) + ($statusCountMap[7] ?? 0);
|
||
$doneCount = $statusCountMap[8] ?? 0;
|
||
$afterSaleCount = $statusCountMap[10] ?? 0;
|
||
|
||
// 4. 实时待办预警与风控中心(6大核心运营待办)
|
||
$pendingMaster = Master::where('verify_status', 'pending')->count();
|
||
$pendingMerchant = Merchant::where('verify_status', 'pending')->count();
|
||
$waitingAppeal = Appeal::where('status', 'wait')->count();
|
||
$waitingWithdraw = Withdraw::where('status', 'wait')->count();
|
||
$waitingInvoice = Db::name('invoice')->where('status', 'wait')->count();
|
||
$pendingDispatch = $waitDispatchCount;
|
||
|
||
// 5. 近 7 天订单趋势与已付 GMV 流水 (双轴图表数据)
|
||
$dateColumns = [];
|
||
$orderCounts = [];
|
||
$orderAmounts = [];
|
||
for ($i = 6; $i >= 0; $i--) {
|
||
$date = date('Y-m-d', strtotime("-$i days"));
|
||
$dateColumns[] = date('m-d', strtotime("-$i days"));
|
||
$dayStart = strtotime($date . ' 00:00:00');
|
||
$dayEnd = strtotime($date . ' 23:59:59');
|
||
|
||
$cnt = Order::whereBetween('createtime', [$dayStart, $dayEnd])->count();
|
||
$amt = Db::name('order')
|
||
->where('pay_status', 1)
|
||
->where('status', '<>', 9)
|
||
->whereRaw('IF(pay_time > 0, pay_time, createtime) BETWEEN ' . (int)$dayStart . ' AND ' . (int)$dayEnd)
|
||
->sum('pay_amount') ?: 0;
|
||
|
||
$orderCounts[] = (int)$cnt;
|
||
$orderAmounts[] = round((float)$amt, 2);
|
||
}
|
||
|
||
// 6. 服务品类与运力健康指标
|
||
$masterAvg = Db::name('master')
|
||
->where('verify_status', 'pass')
|
||
->field('ROUND(AVG(score), 1) as avg_score, ROUND(AVG(accept_rate), 1) as avg_accept, ROUND(AVG(ontime_rate), 1) as avg_ontime')
|
||
->find();
|
||
|
||
$totalService = Service::count();
|
||
$totalCategory = Db::name('service_cat')->count();
|
||
|
||
// 7. 环形状态分布数据
|
||
$statusDisplayNames = [
|
||
0 => '待支付',
|
||
1 => '待接单',
|
||
2 => '报价中',
|
||
3 => '已接单',
|
||
4 => '待上门',
|
||
5 => '已到达',
|
||
6 => '服务中',
|
||
7 => '待验收',
|
||
8 => '已完成',
|
||
9 => '已取消',
|
||
10 => '售后中',
|
||
];
|
||
$statusChartData = [];
|
||
foreach ($statusCountMap as $stKey => $val) {
|
||
$statusChartData[] = [
|
||
'name' => $statusDisplayNames[$stKey] ?? ('状态' . $stKey),
|
||
'value' => $val,
|
||
];
|
||
}
|
||
|
||
// 8. 最新动态订单
|
||
$recentOrders = Db::name('order')
|
||
->alias('o')
|
||
->join('user u', 'o.user_id = u.id', 'LEFT')
|
||
->field('o.id, o.order_no, o.service_name, o.pay_amount, o.status, o.createtime, u.nickname as user_name')
|
||
->order('o.id', 'desc')
|
||
->limit(6)
|
||
->select();
|
||
|
||
$this->view->assign([
|
||
'totalOrder' => $totalOrder,
|
||
'totalGmv' => number_format($totalGmv, 2, '.', ','),
|
||
'avgTicket' => number_format($avgTicket, 2, '.', ''),
|
||
'todayOrderCount' => $todayOrderCount,
|
||
'todayGmv' => number_format($todayGmv, 2, '.', ','),
|
||
'monthGmv' => number_format($monthGmv, 2, '.', ','),
|
||
|
||
'totalMaster' => $totalMaster,
|
||
'onlineMaster' => $onlineMaster,
|
||
'totalMerchant' => $totalMerchant,
|
||
'totalUser' => $totalUser,
|
||
|
||
'unpaidCount' => $unpaidCount,
|
||
'waitDispatchCount' => $waitDispatchCount,
|
||
'inServiceCount' => $inServiceCount,
|
||
'doneCount' => $doneCount,
|
||
'afterSaleCount' => $afterSaleCount,
|
||
|
||
'pendingMaster' => $pendingMaster,
|
||
'pendingMerchant' => $pendingMerchant,
|
||
'waitingAppeal' => $waitingAppeal,
|
||
'waitingWithdraw' => $waitingWithdraw,
|
||
'waitingInvoice' => $waitingInvoice,
|
||
'pendingDispatch' => $pendingDispatch,
|
||
|
||
'masterAvgScore' => ($masterAvg && $masterAvg['avg_score'] !== null) ? (string)$masterAvg['avg_score'] : '0.0',
|
||
'masterAvgAccept' => ($masterAvg && $masterAvg['avg_accept'] !== null) ? (string)$masterAvg['avg_accept'] : '0',
|
||
'masterAvgOntime' => ($masterAvg && $masterAvg['avg_ontime'] !== null) ? (string)$masterAvg['avg_ontime'] : '0',
|
||
|
||
'totalService' => $totalService,
|
||
'totalCategory' => $totalCategory,
|
||
'recentOrders' => $recentOrders,
|
||
'systemClock' => date('Y-m-d H:i:s'),
|
||
]);
|
||
|
||
// ECharts 配置注入
|
||
$this->assignconfig('dateColumns', $dateColumns);
|
||
$this->assignconfig('orderCounts', $orderCounts);
|
||
$this->assignconfig('orderAmounts', $orderAmounts);
|
||
$this->assignconfig('statusChartData', $statusChartData);
|
||
$this->assignconfig('totalOrder', $totalOrder);
|
||
|
||
return $this->view->fetch();
|
||
}
|
||
}
|