Commit 7a130150 authored by 刘小敏's avatar 刘小敏

数据中心统计

parent c64d3b9c
...@@ -3,11 +3,8 @@ ...@@ -3,11 +3,8 @@
namespace app\admin\controller\shopro; namespace app\admin\controller\shopro;
use app\admin\model\shopro\order\Order; 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\user\User;
use app\admin\model\shopro\Share; use app\admin\model\shopro\order\Address as OrderAddress;
use addons\shopro\service\SearchHistory;
use think\Db; use think\Db;
/** /**
...@@ -26,6 +23,7 @@ use think\Db; ...@@ -26,6 +23,7 @@ use think\Db;
*/ */
class Dashboard extends Common class Dashboard extends Common
{ {
protected $noNeedLogin = ['recentOrders'];
/** /**
* 数据统计中心首页 * 数据统计中心首页
...@@ -109,30 +107,30 @@ class Dashboard extends Common ...@@ -109,30 +107,30 @@ class Dashboard extends Common
$this->success('获取成功', null, $result); $this->success('获取成功', null, $result);
} }
$days = $this->getDaysByTimeRange($timeRange); // $days = $this->getDaysByTimeRange($timeRange);
$trendData = $this->getTrendData($days, $period); // $trendData = $this->getTrendData($days, $period);
$result = [ // $result = [
'total_amount' => $trendData['total_amount'], // 'total_amount' => $trendData['total_amount'],
'total_amount_compare_rate' => $trendData['total_amount_compare_rate'] ?? 0, // 'total_amount_compare_rate' => $trendData['total_amount_compare_rate'] ?? 0,
'profit_rate' => $trendData['profit_rate'], // 'profit_rate' => $trendData['profit_rate'],
'profit_rate_compare_rate' => $trendData['profit_rate_compare_rate'] ?? 0, // 'profit_rate_compare_rate' => $trendData['profit_rate_compare_rate'] ?? 0,
'avg_amount' => $trendData['avg_amount'], // 'avg_amount' => $trendData['avg_amount'],
'avg_amount_compare_rate' => $trendData['avg_amount_compare_rate'] ?? 0, // 'avg_amount_compare_rate' => $trendData['avg_amount_compare_rate'] ?? 0,
'order_count' => $trendData['order_count'], // 'order_count' => $trendData['order_count'],
'order_count_compare_rate' => $trendData['order_count_compare_rate'] ?? 0, // 'order_count_compare_rate' => $trendData['order_count_compare_rate'] ?? 0,
'visitor_count' => $trendData['visitor_count'], // 'visitor_count' => $trendData['visitor_count'],
'visitor_count_compare_rate' => $trendData['visitor_count_compare_rate'] ?? 0, // 'visitor_count_compare_rate' => $trendData['visitor_count_compare_rate'] ?? 0,
'conversion_rate' => $trendData['conversion_rate'], // 'conversion_rate' => $trendData['conversion_rate'],
'conversion_rate_compare_rate' => $trendData['conversion_rate_compare_rate'] ?? 0, // 'conversion_rate_compare_rate' => $trendData['conversion_rate_compare_rate'] ?? 0,
'register_users' => $trendData['register_users'], // 'register_users' => $trendData['register_users'],
'register_users_compare_rate' => $trendData['register_users_compare_rate'] ?? 0, // 'register_users_compare_rate' => $trendData['register_users_compare_rate'] ?? 0,
'trend_data' => $trendData['trend_data'], // 'trend_data' => $trendData['trend_data'],
'from_cache' => false, // 'from_cache' => false,
'update_time' => $updateTime ? date('Y-m-d H:i:s', $updateTime) : date('Y-m-d H:i:s') // 'update_time' => $updateTime ? date('Y-m-d H:i:s', $updateTime) : date('Y-m-d H:i:s')
]; // ];
$this->success('获取成功', null, $result); // $this->success('获取成功', null, $result);
} }
/** /**
...@@ -165,11 +163,12 @@ class Dashboard extends Common ...@@ -165,11 +163,12 @@ class Dashboard extends Common
'register_num' => $registerValues[$index] ?? 0 'register_num' => $registerValues[$index] ?? 0
]; ];
} }
return $result; // return $result;
// 周/月聚合逻辑(暂时禁用,需要时取消注释) // 周/月聚合逻辑(暂时禁用,需要时取消注释)
/* if ($period === 'day') {
if ($period === 'week') { return $result;
} elseif ($period === 'week') {
return $this->aggregateByWeek($labels, $amountValues, $orderValues, $registerValues); return $this->aggregateByWeek($labels, $amountValues, $orderValues, $registerValues);
} elseif ($period === 'month') { } elseif ($period === 'month') {
return $this->aggregateByMonth($labels, $amountValues, $orderValues, $registerValues); return $this->aggregateByMonth($labels, $amountValues, $orderValues, $registerValues);
...@@ -185,7 +184,7 @@ class Dashboard extends Common ...@@ -185,7 +184,7 @@ class Dashboard extends Common
]; ];
} }
return $result; return $result;
*/
} }
/** /**
...@@ -610,62 +609,83 @@ class Dashboard extends Common ...@@ -610,62 +609,83 @@ class Dashboard extends Common
} }
/** /**
* 获取实时订单动态 * 获取实时订单动态(支持分页)
* *
* 获取最近10条已支付或已完成的订单信息 * 获取已支付或已完成的订单信息,支持分页加载
* 优先从缓存读取,缓存未命中时降级到数据库查询 * 默认每页10条数据
*
* @param int page 页码,默认1
* @param int pageSize 每页条数,默认10
* *
* 返回数据数组,每个元素包含: * 返回数据数组,每个元素包含:
* - amount: 订单金额 * - amount: 订单金额
* - time: 订单时间(格式化为相对时间,如'刚刚'、'5分钟前'等) * - time: 订单时间(格式化为相对时间,如'刚刚'、'5分钟前'等)
* - location: 用户位置(城市名称) * - location: 用户位置(城市名称)
* - hasMore: 是否有更多数据
* - total: 总记录数
*/ */
public function recentOrders() public function recentOrders()
{ {
$cacheKey = 'shopro:data_stats_center:30days'; $page = $this->request->param('page/d', 1);
$cachedData = cache($cacheKey); $pageSize = $this->request->param('pageSize/d', 10);
$pageSize = min($pageSize, 50);
if ($cachedData !== false && isset($cachedData['recent_orders'])) { $query = Order::whereIn('status', [Order::STATUS_PAID, Order::STATUS_COMPLETED])
$orders = $cachedData['recent_orders']; ->order('createtime', 'desc');
$result = [];
foreach ($orders as $order) {
$result[] = [
'amount' => $order['amount'],
'time' => $this->formatTime(strtotime($order['time'])),
'location' => $order['user'] ?: '未知'
];
}
$this->success('获取成功', null, $result);
}
$orders = Order::whereIn('status', [Order::STATUS_PAID, Order::STATUS_COMPLETED]) $total = $query->count();
->order('createtime', 'desc') $orders = $query->page($page, $pageSize)->select();
->limit(10)
->select();
$result = []; $result = [];
foreach ($orders as $order) { foreach ($orders as $order) {
$user = User::where('id', $order['user_id'])->find(); $address = OrderAddress::where('order_id', $order['id'])->find();
$result[] = [ $result[] = [
'amount' => $order['pay_fee'], 'amount' => $order['pay_fee'],
'time' => $this->formatTime($order['createtime']), 'time' => $this->formatTime($order['createtime']),
'location' => $user ? ($user['city'] ?: '未知') : '未知' 'location' => $address ? ($address['province_name'] ?: '未知') : '未知'
]; ];
} }
$this->success('获取成功', null, $result); $hasMore = ($page * $pageSize) < $total;
$this->success('获取成功', null, [
'list' => $result,
'total' => $total,
'page' => $page,
'pageSize' => $pageSize,
'hasMore' => $hasMore
]);
} }
/** /**
* 格式化时间为相对时间 * 格式化时间为相对时间
* *
* @param int $timestamp 时间戳 * @param mixed $timestamp 时间戳或日期字符串
* @return string 格式化后的时间字符串 * @return string 格式化后的时间字符串
*/ */
private function formatTime($timestamp) private function formatTime($timestamp)
{ {
if (empty($timestamp)) {
return '未知时间';
}
// 如果不是数字,尝试转换为时间戳
if (!is_numeric($timestamp)) {
$timestamp = strtotime($timestamp);
if ($timestamp === false) {
return '未知时间';
}
}
$timestamp = (int)$timestamp;
// 验证时间戳是否在合理范围内(1970年到2100年)
if ($timestamp < 0 || $timestamp > 4102444800) {
return '未知时间';
}
$now = time(); $now = time();
$diff = $now - (int)($timestamp); $diff = $now - $timestamp;
if ($diff < 60) { if ($diff < 60) {
return '刚刚'; return '刚刚';
......
...@@ -296,9 +296,28 @@ ...@@ -296,9 +296,28 @@
margin-left: 10px; margin-left: 10px;
} }
.order-list { .order-list {
/* 移除内层滚动,让容器处理滚动 */
}
.order-list-container {
max-height: 200px; max-height: 200px;
overflow-y: auto; overflow-y: auto;
} }
.order-loading,
.order-no-more,
.order-load-more {
text-align: center;
padding: 10px;
color: #9ca3af;
font-size: 12px;
}
.order-load-more a {
color: #4a90d9;
text-decoration: none;
}
.order-load-more a:hover {
color: #357abd;
text-decoration: underline;
}
.order-item { .order-item {
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -465,11 +484,11 @@ ...@@ -465,11 +484,11 @@
<div class="chart-panel-title">成交总额趋势</div> <div class="chart-panel-title">成交总额趋势</div>
<div class="chart-panel-subtitle" id="gmv-subtitle">近30天每日GMV走势</div> <div class="chart-panel-subtitle" id="gmv-subtitle">近30天每日GMV走势</div>
</div> </div>
<!-- <div class="chart-tabs"> <div class="chart-tabs">
<button class="chart-tab active" id="gmv-day" data-chart="gmv" data-period="day"></button> <button class="chart-tab active" id="gmv-day" data-chart="gmv" data-period="day"></button>
<button class="chart-tab" id="gmv-week" data-chart="gmv" data-period="week"></button> <button class="chart-tab" id="gmv-week" data-chart="gmv" data-period="week"></button>
<button class="chart-tab" id="gmv-month" data-chart="gmv" data-period="month"></button> <button class="chart-tab" id="gmv-month" data-chart="gmv" data-period="month"></button>
</div> --> </div>
</div> </div>
<div id="gmv-chart" class="chart-container"></div> <div id="gmv-chart" class="chart-container"></div>
</div> </div>
...@@ -481,11 +500,11 @@ ...@@ -481,11 +500,11 @@
<div class="chart-panel-title">订单数趋势</div> <div class="chart-panel-title">订单数趋势</div>
<div class="chart-panel-subtitle" id="order-subtitle">近30天订单量走势</div> <div class="chart-panel-subtitle" id="order-subtitle">近30天订单量走势</div>
</div> </div>
<!-- <div class="chart-tabs"> <div class="chart-tabs">
<button class="chart-tab active" id="order-day" data-chart="order" data-period="day"></button> <button class="chart-tab active" id="order-day" data-chart="order" data-period="day"></button>
<button class="chart-tab" id="order-week" data-chart="order" data-period="week"></button> <button class="chart-tab" id="order-week" data-chart="order" data-period="week"></button>
<button class="chart-tab" id="order-month" data-chart="order" data-period="month"></button> <button class="chart-tab" id="order-month" data-chart="order" data-period="month"></button>
</div> --> </div>
</div> </div>
<div id="order-chart" class="chart-container"></div> <div id="order-chart" class="chart-container"></div>
</div> </div>
...@@ -606,14 +625,17 @@ ...@@ -606,14 +625,17 @@
<div class="chart-panel-subtitle">最新成交订单</div> <div class="chart-panel-subtitle">最新成交订单</div>
</div> </div>
</div> </div>
<div class="order-list-container" id="order-list-container">
<div class="order-list" id="order-list"> <div class="order-list" id="order-list">
<div class="order-item">
<span class="order-status"></span>
<div class="order-info">
<div class="order-amount">¥ 0.00</div>
<div class="order-time">加载中...</div>
</div> </div>
<span class="order-tag">成功</span> <div class="order-loading" id="order-loading" style="display: none;">
<i class="fa fa-spinner fa-spin"></i> 加载中...
</div>
<div class="order-load-more" id="order-load-more" style="display: none;">
<a href="javascript:void(0);" id="load-more-link">点击加载更多</a>
</div>
<div class="order-no-more" id="order-no-more" style="display: none;">
已加载全部订单
</div> </div>
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment