Commit 032fc097 authored by 刘小敏's avatar 刘小敏

数据统计中心可运行版本初始化

parent 4e29464a
...@@ -36,24 +36,24 @@ class Dashboard extends Common ...@@ -36,24 +36,24 @@ class Dashboard extends Common
*/ */
public function index() public function index()
{ {
$cardList = [ // $cardList = [
[ // [
'name' => 'total', // 'name' => 'total',
'card' => 'shopro/dashboard/total', // 'card' => 'shopro/dashboard/total',
'status' => $this->auth->check('shopro/dashboard/total') // 'status' => $this->auth->check('shopro/dashboard/total')
], // ],
[ // [
'name' => 'chart', // 'name' => 'chart',
'card' => 'shopro/dashboard/chart', // 'card' => 'shopro/dashboard/chart',
'status' => $this->auth->check('shopro/dashboard/chart') // 'status' => $this->auth->check('shopro/dashboard/chart')
], // ],
[ // [
'name' => 'ranking', // 'name' => 'ranking',
'card' => 'shopro/dashboard/ranking', // 'card' => 'shopro/dashboard/ranking',
'status' => $this->auth->check('shopro/dashboard/ranking') // 'status' => $this->auth->check('shopro/dashboard/ranking')
], // ],
]; // ];
$this->assignconfig('cardList', $cardList); // $this->assignconfig('cardList', $cardList);
return $this->view->fetch(); return $this->view->fetch();
} }
...@@ -96,12 +96,19 @@ class Dashboard extends Common ...@@ -96,12 +96,19 @@ class Dashboard extends Common
$result = [ $result = [
'total_amount' => $summary['total_amount']['value'], 'total_amount' => $summary['total_amount']['value'],
'total_amount_compare_rate' => $summary['total_amount']['compare_rate'],
'profit_rate' => $summary['profit_rate']['formatted'], 'profit_rate' => $summary['profit_rate']['formatted'],
'profit_rate_compare_rate' => $summary['profit_rate']['compare_rate'],
'avg_amount' => $summary['avg_amount']['value'], 'avg_amount' => $summary['avg_amount']['value'],
'avg_amount_compare_rate' => $summary['avg_amount']['compare_rate'],
'order_count' => $summary['order_count']['value'], 'order_count' => $summary['order_count']['value'],
'order_count_compare_rate' => $summary['order_count']['compare_rate'],
'visitor_count' => $summary['visitor_count']['value'], 'visitor_count' => $summary['visitor_count']['value'],
'visitor_count_compare_rate' => $summary['visitor_count']['compare_rate'],
'conversion_rate' => $summary['conversion_rate']['formatted'], 'conversion_rate' => $summary['conversion_rate']['formatted'],
'conversion_rate_compare_rate' => $summary['conversion_rate']['compare_rate'],
'register_users' => $summary['register_users']['value'], 'register_users' => $summary['register_users']['value'],
'register_users_compare_rate' => $summary['register_users']['compare_rate'],
'trend_data' => $trendData, 'trend_data' => $trendData,
'from_cache' => true 'from_cache' => true
]; ];
...@@ -623,226 +630,4 @@ class Dashboard extends Common ...@@ -623,226 +630,4 @@ class Dashboard extends Common
} }
} }
/**
* 获取用户、分销商、分享统计数据
*
* 返回数据:
* - user_data: 用户数据
* - total: 总用户数
* - today: 今日新增用户数
* - week: 本周新增用户数
* - array: 今日用户创建时间数组(用于图表)
* - agent_data: 分销商数据
* - total: 总分销商数
* - today: 今日新增分销商数
* - week: 本周新增分销商数
* - array: 今日分销商创建时间数组(用于图表)
* - share_data: 分享数据
* - total: 总分享次数
* - today: 今日分享次数
* - week: 本周分享次数
* - array: 今日分享创建时间数组(用于图表)
*/
public function old_total()
{
// $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;
// })
// ];
// $agentData = [
// 'total' => \app\admin\model\shopro\commission\Agent::count(),
// 'today' => \app\admin\model\shopro\commission\Agent::whereTime('createtime', 'today')->count(),
// 'week' => \app\admin\model\shopro\commission\Agent::whereTime('createtime', 'week')->count(),
// 'array' => collection(\app\admin\model\shopro\commission\Agent::field('user_id,createtime')->whereTime('createtime', 'today')->select())->each(function ($agent) {
// $agent->counter = 1;
// $agent->createtime_unix = $agent->getData('createtime') * 1000;
// })
// ];
// $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;
// })
// ];
// $this->success('获取成功', null, [
// 'user_data' => $userData,
// 'agent_data' => $agentData ?? null,
// 'share_data' => $shareData
// ]);
}
/**
* 获取订单图表数据
*
* 根据指定时间范围统计订单数据,用于渲染订单趋势图表
*
* 请求参数:
* - date: 时间范围,格式为 '开始时间 - 结束时间'
*
* 返回数据:
* - orderNum: 订单总数
* - orderArr: 订单创建时间数组(用于图表)
* - payOrderNum: 支付订单数
* - payOrderArr: 支付订单创建时间数组(用于图表)
* - payAmountNum: 支付金额总数
* - payAmountArr: 支付金额创建时间数组(用于图表)
* - payUserNum: 支付用户数(去重)
* - payUserArr: 支付用户创建时间数组(用于图表)
* - noSendNum: 待发货订单数
* - noSendArr: 待发货订单创建时间数组(用于图表)
* - aftersaleNum: 售后维权订单数
* - aftersaleArr: 售后维权订单创建时间数组(用于图表)
* - refundNum: 退款订单数
* - refundArr: 退款订单创建时间数组(用于图表)
*/
public function old_chart()
{
// $date = $this->request->param('date', '');
// $date = array_values(array_filter(explode(' - ', $date)));
// $orders = Order::with(['items'])->whereTime('createtime', 'between', $date)
// ->order('id', 'asc')->select();
// $data['orderNum'] = count($orders);
// $data['orderArr'] = [];
// $data['payOrderNum'] = 0;
// $data['payOrderArr'] = [];
// $data['payAmountNum'] = 0;
// $data['payAmountArr'] = [];
// $userIds = [];
// $data['payUserNum'] = 0;
// $data['payUserArr'] = [];
// $data['noSendNum'] = 0;
// $data['noSendArr'] = [];
// $data['aftersaleNum'] = 0;
// $data['aftersaleArr'] = [];
// $data['refundNum'] = 0;
// $data['refundArr'] = [];
// foreach ($orders as $key => $order) {
// $data['orderArr'][] = [
// 'counter' => 1,
// 'createtime' => $order->getData('createtime') * 1000,
// 'user_id' => $order->user_id
// ];
// if (in_array($order->status, [Order::STATUS_PAID, Order::STATUS_COMPLETED])) {
// $data['payOrderNum']++;
// $data['payOrderArr'][] = [
// 'counter' => 1,
// 'createtime' => $order->getData('createtime') * 1000,
// 'user_id' => $order->user_id
// ];
// $data['payAmountNum'] = bcadd((string)$data['payAmountNum'], $order->pay_fee, 2);
// $data['payAmountArr'][] = [
// 'counter' => $order->pay_fee,
// 'createtime' => $order->getData('createtime') * 1000,
// ];
// if (!in_array($order->user_id, $userIds)) {
// $data['payUserNum']++;
// $data['payUserArr'][] = [
// 'counter' => 1,
// 'createtime' => $order->getData('createtime') * 1000,
// 'user_id' => $order->user_id
// ];
// }
// }
// if (in_array($order->status, [Order::STATUS_PAID, Order::STATUS_COMPLETED]) || $order->isOffline($order)) {
// $flagnoSend = false;
// $flagaftersale = false;
// $flagrefund = false;
// $aftersaleIng = false;
// foreach ($order->items as $k => $item) {
// if (
// !$flagnoSend
// && $item->dispatch_status == OrderItem::DISPATCH_STATUS_NOSEND
// && $item->refund_status == OrderItem::REFUND_STATUS_NOREFUND
// && in_array($order->apply_refund_status, [
// Order::APPLY_REFUND_STATUS_NOAPPLY,
// Order::APPLY_REFUND_STATUS_REFUSE
// ])
// ) {
// $flagnoSend = true;
// }
// if (
// $item->aftersale_status == OrderItem::AFTERSALE_STATUS_ING
// && $item->dispatch_status == OrderItem::DISPATCH_STATUS_NOSEND
// && $item->refund_status == OrderItem::REFUND_STATUS_NOREFUND
// ) {
// $aftersaleIng = true;
// }
// if (!$flagaftersale && $item->aftersale_status != OrderItem::AFTERSALE_STATUS_NOAFTER) {
// $data['aftersaleNum']++;
// $flagaftersale = true;
// }
// if (!$flagrefund && $item->refund_status > OrderItem::REFUND_STATUS_NOREFUND) {
// $data['refundNum']++;
// $flagrefund = true;
// }
// }
// if (!$aftersaleIng && $flagnoSend) {
// $data['noSendNum']++;
// }
// }
// }
// $this->success('获取成功', null, $data);
}
/**
* 获取商品排名和热门搜索
*
* 返回数据:
* - goods: 销量前5的商品列表,每个商品包含:
* - id: 商品ID
* - title: 商品标题
* - sales: 销量
* - real_sales: 真实销量(包含虚拟销量)
* - sale_total_money: 销售总额
* - hot_search: 热门搜索关键词列表,每个关键词包含:
* - keyword: 搜索词
* - num: 搜索次数
*/
public function old_ranking()
{
// $goods = Goods::limit(5)->order('sales', 'desc')->select();
// foreach ($goods as $key => $gd) {
// $gd->append(['real_sales']);
// $result = OrderItem::field('sum(goods_num * goods_price) as sale_total_money')->where('goods_id', $gd['id'])
// ->whereExists(function ($query) use ($gd) {
// $order_table_name = (new Order())->getQuery()->getTable();
// $table_name = (new OrderItem())->getQuery()->getTable();
// $query->table($order_table_name)->where($table_name . '.order_id=' . $order_table_name . '.id')
// ->whereIn('status', [Order::STATUS_PAID, Order::STATUS_COMPLETED]);
// })->find();
// $gd['sale_total_money'] = $result['sale_total_money'] ?: 0;
// }
// $searchHistory = new SearchHistory();
// $this->success('获取成功', null, [
// 'goods' => $goods,
// 'hot_search' => $searchHistory->hotSearch()
// ]);
}
} }
\ No newline at end of file
...@@ -629,356 +629,4 @@ ...@@ -629,356 +629,4 @@
</el-container> </el-container>
</div> </div>
<script type="text/javascript"> </div>
var gmvChart, orderChart, userGrowthChart; \ No newline at end of file
var currentTimeRange = '30days';
var currentGmvPeriod = 'day';
var currentOrderPeriod = 'day';
function generateDateLabels(days) {
var labels = [];
for (var i = days - 1; i >= 0; i--) {
var date = new Date();
date.setDate(date.getDate() - i);
labels.push((date.getMonth() + 1) + '月' + date.getDate() + '日');
}
return labels;
}
function generateRandomData(length, min, max) {
var data = [];
for (var i = 0; i < length; i++) {
data.push(Math.floor(Math.random() * (max - min + 1)) + min);
}
return data;
}
function initCharts() {
gmvChart = echarts.init(document.getElementById('gmv-chart'));
var gmvOption = {
grid: { top: 20, right: 20, bottom: 30, left: 50 },
xAxis: {
type: 'category',
data: generateDateLabels(30),
axisLine: { lineStyle: { color: '#e5e7eb' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
splitLine: { lineStyle: { color: '#f3f4f6' } },
axisLabel: {
color: '#9ca3af',
fontSize: 10,
formatter: function(value) { return '¥' + (value / 10000).toFixed(0) + '万'; }
}
},
series: [{
type: 'line',
smooth: true,
data: generateRandomData(30, 50000, 150000),
lineStyle: { color: '#667eea', width: 3 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(102, 126, 234, 0.3)' },
{ offset: 1, color: 'rgba(102, 126, 234, 0.05)' }
])
},
symbol: 'none'
}]
};
gmvChart.setOption(gmvOption);
orderChart = echarts.init(document.getElementById('order-chart'));
var orderOption = {
grid: { top: 20, right: 20, bottom: 30, left: 50 },
xAxis: {
type: 'category',
data: generateDateLabels(30),
axisLine: { lineStyle: { color: '#e5e7eb' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
splitLine: { lineStyle: { color: '#f3f4f6' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
series: [{
type: 'bar',
data: generateRandomData(30, 1500, 4000),
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#10b981' },
{ offset: 1, color: '#34d399' }
]),
borderRadius: [4, 4, 0, 0]
}
}]
};
orderChart.setOption(orderOption);
userGrowthChart = echarts.init(document.getElementById('user-growth-chart'));
var userGrowthOption = {
grid: { top: 20, right: 20, bottom: 30, left: 50 },
legend: {
data: ['活跃用户', '新增用户'],
top: 0,
textStyle: { color: '#6b7280', fontSize: 12 }
},
xAxis: {
type: 'category',
data: generateDateLabels(30),
axisLine: { lineStyle: { color: '#e5e7eb' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
splitLine: { lineStyle: { color: '#f3f4f6' } },
axisLabel: {
color: '#9ca3af',
fontSize: 10
}
},
series: [
{
name: '活跃用户',
type: 'line',
smooth: true,
data: [120, 156, 132, 189, 210, 198, 234, 256, 212, 188, 245, 267, 234, 289, 312, 278, 245, 267, 298, 321, 287, 265, 290, 310, 334, 301, 276, 289, 312, 345],
lineStyle: { color: '#f59e0b', width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(245, 158, 11, 0.2)' },
{ offset: 1, color: 'rgba(245, 158, 11, 0.02)' }
])
},
symbol: 'none'
},
{
name: '新增用户',
type: 'line',
smooth: true,
data: [45, 67, 52, 78, 89, 76, 98, 102, 87, 72, 95, 110, 98, 120, 135, 112, 95, 105, 125, 140, 128, 115, 130, 145, 156, 142, 128, 135, 152, 168],
lineStyle: { color: '#06b6d4', width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(6, 182, 212, 0.2)' },
{ offset: 1, color: 'rgba(6, 182, 212, 0.02)' }
])
},
symbol: 'none'
}
]
};
userGrowthChart.setOption(userGrowthOption);
window.addEventListener('resize', function() {
gmvChart.resize();
orderChart.resize();
userGrowthChart.resize();
});
}
function switchPeriod(chartType, period) {
if (chartType === 'gmv') {
currentGmvPeriod = period;
document.querySelectorAll('#gmv-day, #gmv-week, #gmv-month').forEach(el => el.classList.remove('active'));
document.getElementById('gmv-' + period).classList.add('active');
var subtitle = '';
if (period === 'day') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每日GMV走势';
} else if (period === 'week') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每周GMV走势';
} else {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每月GMV走势';
}
document.getElementById('gmv-subtitle').textContent = subtitle;
} else {
currentOrderPeriod = period;
document.querySelectorAll('#order-day, #order-week, #order-month').forEach(el => el.classList.remove('active'));
document.getElementById('order-' + period).classList.add('active');
var subtitle = '';
if (period === 'day') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每日订单量走势';
} else if (period === 'week') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每周订单量走势';
} else {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每月订单量走势';
}
document.getElementById('order-subtitle').textContent = subtitle;
}
loadStatistics(currentTimeRange);
}
function loadStatistics(timeRange) {
currentTimeRange = timeRange;
$.getJSON('{:url("shopro/dashboard/statistics")}', {
time_range: timeRange,
period: currentGmvPeriod
}, function(res) {
console.log('=== statistics 接口返回数据 ===', res);
if (res.code === 1) {
var data = res.data;
console.log('data.trend_data:', data.trend_data);
console.log('from_cache:', data.from_cache);
document.getElementById('stat-total-amount').textContent = '¥' + formatNumber(data.total_amount, 2);
document.getElementById('stat-profit-rate').textContent = data.profit_rate;
document.getElementById('stat-avg-amount').textContent = '¥' + formatNumber(data.avg_amount, 2);
document.getElementById('stat-order-count').textContent = formatNumber(data.order_count);
document.getElementById('stat-visitor-count').textContent = formatNumber(data.visitor_count);
document.getElementById('stat-conversion-rate').textContent = data.conversion_rate;
document.getElementById('stat-register-users').textContent = formatNumber(data.register_users);
updateGmvChart(data.trend_data);
if (currentGmvPeriod === currentOrderPeriod) {
updateOrderChart(data.trend_data);
} else {
$.getJSON('{:url("shopro/dashboard/statistics")}', {
time_range: timeRange,
period: currentOrderPeriod
}, function(res) {
if (res.code === 1) {
updateOrderChart(res.data.trend_data);
}
});
}
}
});
loadFunnel(timeRange);
loadPriceDistribution(timeRange);
loadRecentOrders();
}
function updateGmvChart(trendData) {
var labels = trendData.map(function(item) { return item.date; });
var amounts = trendData.map(function(item) { return item.amount; });
var orders = trendData.map(function(item) { return item.order_num; });
var registers = trendData.map(function(item) { return item.register_num; });
gmvChart.setOption({
xAxis: { data: labels },
series: [{ data: amounts }]
});
userGrowthChart.setOption({
xAxis: { data: labels },
series: [
{ data: orders },
{ data: registers }
]
});
var totalRegister = registers.reduce(function(a, b) { return a + b; }, 0);
document.getElementById('growth-badge').textContent = '+' + formatNumber(totalRegister);
}
function updateOrderChart(trendData) {
var labels = trendData.map(function(item) { return item.date; });
var orders = trendData.map(function(item) { return item.order_num; });
orderChart.setOption({
xAxis: { data: labels },
series: [{ data: orders }]
});
}
function loadFunnel(timeRange) {
$.getJSON('{:url("shopro/dashboard/funnel")}', { time_range: timeRange }, function(res) {
if (res.code === 1) {
var data = res.data;
var max = data.visit || 1;
document.getElementById('funnel-visit').textContent = formatNumber(data.visit);
var browsePercent = max > 0 ? Math.round(data.browse / max * 100) : 0;
document.getElementById('funnel-browse').textContent = formatNumber(data.browse);
document.getElementById('funnel-browse').style.width = browsePercent + '%';
var cartPercent = max > 0 ? Math.round(data.cart / max * 100) : 0;
document.getElementById('funnel-cart').textContent = formatNumber(data.cart);
document.getElementById('funnel-cart').style.width = cartPercent + '%';
var submitPercent = max > 0 ? Math.round(data.submit_order / max * 100) : 0;
document.getElementById('funnel-submit').textContent = formatNumber(data.submit_order);
document.getElementById('funnel-submit').style.width = submitPercent + '%';
var payPercent = max > 0 ? Math.round(data.pay / max * 100) : 0;
document.getElementById('funnel-pay').textContent = formatNumber(data.pay);
document.getElementById('funnel-pay').style.width = payPercent + '%';
}
});
}
function loadPriceDistribution(timeRange) {
$.getJSON('{:url("shopro/dashboard/priceDistribution")}', { time_range: timeRange }, function(res) {
if (res.code === 1) {
var data = res.data;
document.getElementById('price-0-100').style.width = data['0-100'] + '%';
document.getElementById('price-0-100-percent').textContent = data['0-100'] + '%';
document.getElementById('price-100-300').style.width = data['100-300'] + '%';
document.getElementById('price-100-300-percent').textContent = data['100-300'] + '%';
document.getElementById('price-300-500').style.width = data['300-500'] + '%';
document.getElementById('price-300-500-percent').textContent = data['300-500'] + '%';
document.getElementById('price-500-1000').style.width = data['500-1000'] + '%';
document.getElementById('price-500-1000-percent').textContent = data['500-1000'] + '%';
document.getElementById('price-1000').style.width = data['1000+'] + '%';
document.getElementById('price-1000-percent').textContent = data['1000+'] + '%';
}
});
}
function loadRecentOrders() {
$.getJSON('{:url("shopro/dashboard/recentOrders")}', function(res) {
if (res.code === 1) {
var orders = res.data;
var html = '';
orders.forEach(function(order) {
html += '<div class="order-item">' +
'<span class="order-status"></span>' +
'<div class="order-info">' +
'<div class="order-amount">¥ ' + formatNumber(order.amount, 2) + '</div>' +
'<div class="order-time">' + order.location + ' · ' + order.time + '</div>' +
'</div>' +
'<span class="order-tag">成功</span>' +
'</div>';
});
document.getElementById('order-list').innerHTML = html;
}
});
}
function formatNumber(num, decimals) {
if (num === null || num === undefined) num = 0;
if (decimals !== undefined) {
return parseFloat(num).toFixed(decimals);
}
return parseInt(num).toLocaleString();
}
function refreshAllData() {
document.getElementById('refreshBtn').innerHTML = '<i class="fa fa-spinner fa-spin"></i><span>刷新中...</span>';
document.getElementById('refreshBtn').disabled = true;
setTimeout(function() {
loadStatistics(currentTimeRange);
document.getElementById('update-time').textContent = new Date().toLocaleString('zh-CN');
document.getElementById('refreshBtn').innerHTML = '<i class="fa fa-refresh"></i><span>刷新数据</span>';
document.getElementById('refreshBtn').disabled = false;
}, 500);
}
document.addEventListener('DOMContentLoaded', function() {
initCharts();
loadStatistics('30days');
});
</script>
\ No newline at end of file
...@@ -2,7 +2,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -2,7 +2,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
var Controller = { var Controller = {
index: () => { index: () => {
const { reactive, onMounted } = Vue const { reactive, onMounted } = Vue;
var gmvChart, orderChart, userGrowthChart;
var currentTimeRange = '30days';
var currentGmvPeriod = 'day';
var currentOrderPeriod = 'day';
const index = { const index = {
setup() { setup() {
const state = reactive({ const state = reactive({
...@@ -20,7 +26,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -20,7 +26,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
data: {}, data: {},
color: '#409EFF', color: '#409EFF',
color1: 'rgba(64, 158, 255, 0.4)', color1: 'rgba(64, 158, 255, 0.4)',
color2: ' rgba(64, 158, 255, 0)', color2: 'rgba(64, 158, 255, 0)',
title: '分销商数量', title: '分销商数量',
tip: '今日新增人数', tip: '今日新增人数',
footer: '本周新增分销商人数', footer: '本周新增分销商人数',
...@@ -35,7 +41,597 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -35,7 +41,597 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
footer: '本周新增分享次数', footer: '本周新增分享次数',
}, },
}, },
}) });
const chart = reactive({
tabsData: {
order: '订单数',
payOrder: '支付订单',
payAmount: '支付金额',
},
tabActive: 'order',
dateTime: getTimeSlot(),
shortcuts: [
{
text: '今天',
value: getTimeSlot(),
},
{
text: '昨天',
value: () => {
return getTimeSlot('yesterday');
},
},
{
text: '近一周',
value: () => {
return getTimeSlot('week');
},
},
],
data: {
payAmountArr: [],
payOrderArr: [],
orderArr: [],
},
});
const statistics = reactive({
total_amount: 0,
total_amount_compare_rate: 0,
profit_rate: '0%',
profit_rate_compare_rate: 0,
avg_amount: 0,
avg_amount_compare_rate: 0,
order_count: 0,
order_count_compare_rate: 0,
visitor_count: 0,
visitor_count_compare_rate: 0,
conversion_rate: '0%',
conversion_rate_compare_rate: 0,
register_users: 0,
register_users_compare_rate: 0,
trend_data: [],
from_cache: false
});
const chartOption = reactive({
grid: {
left: '10px',
top: '20px',
bottom: '20px',
right: '20px',
containLabel: true,
},
xAxis: {
type: 'category',
data: [],
offset: 5,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'value',
offset: 5,
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
show: true,
status: 'shadow',
z: -1,
shadowStyle: {
color: 'rgba(191, 191, 191, 0.24)',
},
type: 'shadow',
},
},
series: [
{
name: chart.tabsData[chart.tabActive],
type: 'bar',
data: [],
zlevel: 1,
z: 1,
label: {
show: false,
position: 'top',
},
itemStyle: {
color: '#806af6',
},
showBackground: true,
backgroundStyle: {
color: 'rgba(191, 191, 191, 0.24)',
},
},
],
});
function generateDateLabels(days) {
var labels = [];
for (var i = days - 1; i >= 0; i--) {
var date = new Date();
date.setDate(date.getDate() - i);
labels.push((date.getMonth() + 1) + '月' + date.getDate() + '日');
}
return labels;
}
function formatNumber(num, decimals) {
if (num === null || num === undefined) num = 0;
if (decimals !== undefined) {
return parseFloat(num).toFixed(decimals);
}
return parseInt(num).toLocaleString();
}
function updateTrendElement(element, compareRate) {
if (!element) return;
compareRate = parseFloat(compareRate) || 0;
var trendText = '';
var trendClass = '';
if (compareRate > 0) {
trendText = '+' + compareRate.toFixed(2) + '%';
trendClass = 'up';
} else if (compareRate < 0) {
trendText = compareRate.toFixed(2) + '%';
trendClass = 'down';
} else {
trendText = '+0%';
trendClass = 'up';
}
element.textContent = trendText;
var parentDiv = element.parentElement;
if (parentDiv) {
parentDiv.classList.remove('up', 'down');
parentDiv.classList.add(trendClass);
var icon = parentDiv.querySelector('i');
if (icon) {
icon.classList.remove('fa-arrow-up', 'fa-arrow-down');
icon.classList.add(trendClass === 'up' ? 'fa-arrow-up' : 'fa-arrow-down');
}
}
}
function initCharts() {
gmvChart = echarts.init(document.getElementById('gmv-chart'));
var gmvOption = {
grid: { top: 20, right: 20, bottom: 30, left: 50 },
xAxis: {
type: 'category',
data: generateDateLabels(30),
axisLine: { lineStyle: { color: '#e5e7eb' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
splitLine: { lineStyle: { color: '#f3f4f6' } },
axisLabel: {
color: '#9ca3af',
fontSize: 10,
formatter: function(value) { return '¥' + (value / 10000).toFixed(0) + '万'; }
}
},
series: [{
type: 'line',
smooth: true,
data: [],
lineStyle: { color: '#667eea', width: 3 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(102, 126, 234, 0.3)' },
{ offset: 1, color: 'rgba(102, 126, 234, 0.05)' }
])
},
symbol: 'none'
}]
};
gmvChart.setOption(gmvOption);
orderChart = echarts.init(document.getElementById('order-chart'));
var orderOption = {
grid: { top: 20, right: 20, bottom: 30, left: 50 },
xAxis: {
type: 'category',
data: generateDateLabels(30),
axisLine: { lineStyle: { color: '#e5e7eb' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
splitLine: { lineStyle: { color: '#f3f4f6' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
series: [{
type: 'bar',
data: [],
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#10b981' },
{ offset: 1, color: '#34d399' }
]),
borderRadius: [4, 4, 0, 0]
}
}]
};
orderChart.setOption(orderOption);
userGrowthChart = echarts.init(document.getElementById('user-growth-chart'));
var userGrowthOption = {
grid: { top: 20, right: 20, bottom: 30, left: 50 },
legend: {
data: ['活跃用户', '新增用户'],
top: 0,
textStyle: { color: '#6b7280', fontSize: 12 }
},
xAxis: {
type: 'category',
data: generateDateLabels(30),
axisLine: { lineStyle: { color: '#e5e7eb' } },
axisLabel: { color: '#9ca3af', fontSize: 10 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
splitLine: { lineStyle: { color: '#f3f4f6' } },
axisLabel: {
color: '#9ca3af',
fontSize: 10
}
},
series: [
{
name: '活跃用户',
type: 'line',
smooth: true,
data: [],
lineStyle: { color: '#f59e0b', width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(245, 158, 11, 0.2)' },
{ offset: 1, color: 'rgba(245, 158, 11, 0.02)' }
])
},
symbol: 'none'
},
{
name: '新增用户',
type: 'line',
smooth: true,
data: [],
lineStyle: { color: '#06b6d4', width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(6, 182, 212, 0.2)' },
{ offset: 1, color: 'rgba(6, 182, 212, 0.02)' }
])
},
symbol: 'none'
}
]
};
userGrowthChart.setOption(userGrowthOption);
window.addEventListener('resize', function() {
gmvChart.resize();
orderChart.resize();
userGrowthChart.resize();
});
}
function switchPeriod(chartType, period) {
if (chartType === 'gmv') {
currentGmvPeriod = period;
document.querySelectorAll('#gmv-day, #gmv-week, #gmv-month').forEach(el => el.classList.remove('active'));
var periodEl = document.getElementById('gmv-' + period);
if (periodEl) periodEl.classList.add('active');
var subtitle = '';
if (period === 'day') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每日GMV走势';
} else if (period === 'week') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每周GMV走势';
} else {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每月GMV走势';
}
var subtitleEl = document.getElementById('gmv-subtitle');
if (subtitleEl) subtitleEl.textContent = subtitle;
} else {
currentOrderPeriod = period;
document.querySelectorAll('#order-day, #order-week, #order-month').forEach(el => el.classList.remove('active'));
var periodEl = document.getElementById('order-' + period);
if (periodEl) periodEl.classList.add('active');
var subtitle = '';
if (period === 'day') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每日订单量走势';
} else if (period === 'week') {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每周订单量走势';
} else {
subtitle = '近' + currentTimeRange.replace('days', '') + '天每月订单量走势';
}
var subtitleEl = document.getElementById('order-subtitle');
if (subtitleEl) subtitleEl.textContent = subtitle;
}
loadStatistics(currentTimeRange);
}
function loadStatistics(timeRange) {
currentTimeRange = timeRange;
Fast.api.ajax({
url: 'shopro/dashboard/statistics',
type: 'GET',
data: {
time_range: timeRange,
period: currentGmvPeriod
}
}, function (ret, res) {
if (res.code === 1) {
var data = res.data;
statistics.total_amount = data.total_amount;
statistics.total_amount_compare_rate = data.total_amount_compare_rate || 0;
statistics.profit_rate = data.profit_rate;
statistics.profit_rate_compare_rate = data.profit_rate_compare_rate || 0;
statistics.avg_amount = data.avg_amount;
statistics.avg_amount_compare_rate = data.avg_amount_compare_rate || 0;
statistics.order_count = data.order_count;
statistics.order_count_compare_rate = data.order_count_compare_rate || 0;
statistics.visitor_count = data.visitor_count;
statistics.visitor_count_compare_rate = data.visitor_count_compare_rate || 0;
statistics.conversion_rate = data.conversion_rate;
statistics.conversion_rate_compare_rate = data.conversion_rate_compare_rate || 0;
statistics.register_users = data.register_users;
statistics.register_users_compare_rate = data.register_users_compare_rate || 0;
statistics.trend_data = data.trend_data;
statistics.from_cache = data.from_cache;
var statTotalAmount = document.getElementById('stat-total-amount');
var statProfitRate = document.getElementById('stat-profit-rate');
var statAvgAmount = document.getElementById('stat-avg-amount');
var statOrderCount = document.getElementById('stat-order-count');
var statVisitorCount = document.getElementById('stat-visitor-count');
var statConversionRate = document.getElementById('stat-conversion-rate');
var statRegisterUsers = document.getElementById('stat-register-users');
var statTotalTrend = document.getElementById('stat-total-trend');
var statProfitTrend = document.getElementById('stat-profit-trend');
var statAvgTrend = document.getElementById('stat-avg-trend');
var statOrderTrend = document.getElementById('stat-order-trend');
var statVisitorTrend = document.getElementById('stat-visitor-trend');
var statConversionTrend = document.getElementById('stat-conversion-trend');
if (statTotalAmount) statTotalAmount.textContent = '¥' + formatNumber(data.total_amount, 2);
if (statProfitRate) statProfitRate.textContent = data.profit_rate;
if (statAvgAmount) statAvgAmount.textContent = '¥' + formatNumber(data.avg_amount, 2);
if (statOrderCount) statOrderCount.textContent = formatNumber(data.order_count);
if (statVisitorCount) statVisitorCount.textContent = formatNumber(data.visitor_count);
if (statConversionRate) statConversionRate.textContent = data.conversion_rate;
if (statRegisterUsers) statRegisterUsers.textContent = formatNumber(data.register_users);
updateTrendElement(statTotalTrend, data.total_amount_compare_rate);
updateTrendElement(statProfitTrend, data.profit_rate_compare_rate);
updateTrendElement(statAvgTrend, data.avg_amount_compare_rate);
updateTrendElement(statOrderTrend, data.order_count_compare_rate);
updateTrendElement(statVisitorTrend, data.visitor_count_compare_rate);
updateTrendElement(statConversionTrend, data.conversion_rate_compare_rate);
updateGmvChart(data.trend_data);
if (currentGmvPeriod === currentOrderPeriod) {
updateOrderChart(data.trend_data);
} else {
Fast.api.ajax({
url: 'shopro/dashboard/statistics',
type: 'GET',
data: {
time_range: timeRange,
period: currentOrderPeriod
}
}, function (ret2, res2) {
if (res2.code === 1) {
updateOrderChart(res2.data.trend_data);
}
return false;
});
}
}
return false;
});
loadFunnel(timeRange);
loadPriceDistribution(timeRange);
loadRecentOrders();
}
function updateGmvChart(trendData) {
var labels = trendData.map(function(item) { return item.date; });
var amounts = trendData.map(function(item) { return item.amount; });
var orders = trendData.map(function(item) { return item.order_num; });
var registers = trendData.map(function(item) { return item.register_num; });
if (gmvChart) {
gmvChart.setOption({
xAxis: { data: labels },
series: [{ data: amounts }]
});
}
if (userGrowthChart) {
userGrowthChart.setOption({
xAxis: { data: labels },
series: [
{ data: orders },
{ data: registers }
]
});
}
var totalRegister = registers.reduce(function(a, b) { return a + b; }, 0);
var growthBadge = document.getElementById('growth-badge');
if (growthBadge) growthBadge.textContent = '+' + formatNumber(totalRegister);
}
function updateOrderChart(trendData) {
var labels = trendData.map(function(item) { return item.date; });
var orders = trendData.map(function(item) { return item.order_num; });
if (orderChart) {
orderChart.setOption({
xAxis: { data: labels },
series: [{ data: orders }]
});
}
}
function loadFunnel(timeRange) {
Fast.api.ajax({
url: 'shopro/dashboard/funnel',
type: 'GET',
data: { time_range: timeRange }
}, function (ret, res) {
if (res.code === 1) {
var data = res.data;
var max = data.visit || 1;
var funnelVisit = document.getElementById('funnel-visit');
if (funnelVisit) funnelVisit.textContent = formatNumber(data.visit);
var funnelBrowse = document.getElementById('funnel-browse');
var browsePercent = max > 0 ? Math.round(data.browse / max * 100) : 0;
if (funnelBrowse) {
funnelBrowse.textContent = formatNumber(data.browse);
funnelBrowse.style.width = browsePercent + '%';
}
var funnelCart = document.getElementById('funnel-cart');
var cartPercent = max > 0 ? Math.round(data.cart / max * 100) : 0;
if (funnelCart) {
funnelCart.textContent = formatNumber(data.cart);
funnelCart.style.width = cartPercent + '%';
}
var funnelSubmit = document.getElementById('funnel-submit');
var submitPercent = max > 0 ? Math.round(data.submit_order / max * 100) : 0;
if (funnelSubmit) {
funnelSubmit.textContent = formatNumber(data.submit_order);
funnelSubmit.style.width = submitPercent + '%';
}
var funnelPay = document.getElementById('funnel-pay');
var payPercent = max > 0 ? Math.round(data.pay / max * 100) : 0;
if (funnelPay) {
funnelPay.textContent = formatNumber(data.pay);
funnelPay.style.width = payPercent + '%';
}
}
return false;
});
}
function loadPriceDistribution(timeRange) {
Fast.api.ajax({
url: 'shopro/dashboard/priceDistribution',
type: 'GET',
data: { time_range: timeRange }
}, function (ret, res) {
if (res.code === 1) {
var data = res.data;
var price0100 = document.getElementById('price-0-100');
var price0100Percent = document.getElementById('price-0-100-percent');
if (price0100) price0100.style.width = data['0-100'] + '%';
if (price0100Percent) price0100Percent.textContent = data['0-100'] + '%';
var price100300 = document.getElementById('price-100-300');
var price100300Percent = document.getElementById('price-100-300-percent');
if (price100300) price100300.style.width = data['100-300'] + '%';
if (price100300Percent) price100300Percent.textContent = data['100-300'] + '%';
var price300500 = document.getElementById('price-300-500');
var price300500Percent = document.getElementById('price-300-500-percent');
if (price300500) price300500.style.width = data['300-500'] + '%';
if (price300500Percent) price300500Percent.textContent = data['300-500'] + '%';
var price5001000 = document.getElementById('price-500-1000');
var price5001000Percent = document.getElementById('price-500-1000-percent');
if (price5001000) price5001000.style.width = data['500-1000'] + '%';
if (price5001000Percent) price5001000Percent.textContent = data['500-1000'] + '%';
var price1000 = document.getElementById('price-1000');
var price1000Percent = document.getElementById('price-1000-percent');
if (price1000) price1000.style.width = data['1000+'] + '%';
if (price1000Percent) price1000Percent.textContent = data['1000+'] + '%';
}
return false;
});
}
function loadRecentOrders() {
Fast.api.ajax({
url: 'shopro/dashboard/recentOrders',
type: 'GET'
}, function (ret, res) {
if (res.code === 1) {
var orders = res.data;
var html = '';
orders.forEach(function(order) {
html += '<div class="order-item">' +
'<span class="order-status"></span>' +
'<div class="order-info">' +
'<div class="order-amount">¥ ' + formatNumber(order.amount, 2) + '</div>' +
'<div class="order-time">' + order.location + ' · ' + order.time + '</div>' +
'</div>' +
'<span class="order-tag">成功</span>' +
'</div>';
});
var orderList = document.getElementById('order-list');
if (orderList) orderList.innerHTML = html;
}
return false;
});
}
function refreshAllData() {
var refreshBtn = document.getElementById('refreshBtn');
var updateTime = document.getElementById('update-time');
if (refreshBtn) {
refreshBtn.innerHTML = '<i class="fa fa-spinner fa-spin"></i><span>刷新中...</span>';
refreshBtn.disabled = true;
}
setTimeout(function() {
loadStatistics(currentTimeRange);
if (updateTime) updateTime.textContent = new Date().toLocaleString('zh-CN');
if (refreshBtn) {
refreshBtn.innerHTML = '<i class="fa fa-refresh"></i><span>刷新数据</span>';
refreshBtn.disabled = false;
}
}, 500);
}
function getTotal() { function getTotal() {
Fast.api.ajax({ Fast.api.ajax({
...@@ -47,19 +643,20 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -47,19 +643,20 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
state.total.user.data = res.data.user_data; state.total.user.data = res.data.user_data;
for (var key in state.total) { for (var key in state.total) {
if (state.total[key].data) { if (state.total[key].data) {
initChartTotal(key) initChartTotal(key);
} }
} }
return false return false;
}, function (ret, res) { }) }, function (ret, res) { });
} }
function initChartTotal(key) { function initChartTotal(key) {
var chartEl = document.getElementById(`${key}Total`); var chartEl = document.getElementById(key + 'Total');
if (!chartEl) return; if (!chartEl) return;
var myChart = echarts.init(chartEl); var myChart = echarts.init(chartEl);
window.onresize = () => { window.onresize = () => {
myChart.resize() myChart.resize();
} };
var option = { var option = {
grid: { grid: {
left: 6, left: 6,
...@@ -97,8 +694,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -97,8 +694,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
}, },
}, },
series: [{ series: [{
// name: state.total.user.title, data: [5, 20, 36, 10, 10, 20],
data: [5, 20, 36, 10, 10, 20], // [5, 20, 36, 10, 10, 20]
type: 'line', type: 'line',
smooth: true, smooth: true,
showSymbol: false, showSymbol: false,
...@@ -131,13 +727,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -131,13 +727,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
}, },
}] }]
}; };
initIntervalTotal(24, 'hours', option, key);
initIntervalTotal(24, 'hours', option, key)
myChart.setOption(option); myChart.setOption(option);
} }
function initIntervalTotal(interval, kld, option, key) { function initIntervalTotal(interval, kld, option, key) {
let dateTime = `${Moment().format('YYYY-MM-DD')} 00:00:00`; let dateTime = Moment().format('YYYY-MM-DD') + ' 00:00:00';
let x = []; let x = [];
let y = []; let y = [];
let timeStamp = []; let timeStamp = [];
...@@ -162,39 +757,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -162,39 +757,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
option.series[0].data = y; option.series[0].data = y;
} }
const chart = reactive({
tabsData: {
order: '订单数',
payOrder: '支付订单',
payAmount: '支付金额',
},
tabActive: 'order',
dateTime: getTimeSlot(),
shortcuts: [
{
text: '今天',
value: getTimeSlot(),
},
{
text: '昨天',
value: () => {
return getTimeSlot('yesterday');
},
},
{
text: '近一周',
value: () => {
return getTimeSlot('week');
},
},
],
data: {
payAmountArr: [], // 销售额
payOrderArr: [], // 订单
orderArr: [], //订单数
},
});
function onChangeTabActive(type) { function onChangeTabActive(type) {
chart.tabActive = type; chart.tabActive = type;
chartOption.series[0].name = chart.tabsData[chart.tabActive]; chartOption.series[0].name = chart.tabsData[chart.tabActive];
...@@ -202,144 +764,30 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -202,144 +764,30 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
} }
function onChangeDateTime(e) { function onChangeDateTime(e) {
// 时间date必选
e && getChart(); e && getChart();
} }
const statistics = reactive({ // function getChart() {
order: { // Fast.api.ajax({
num: 0, // url: 'shopro/dashboard/chart',
text: '订单数', // type: 'GET',
path: '', // data: {
tip: '时间区间内总的下单数量(包含未支付订单)', // date: chart.dateTime.join(' - '),
status: 'all', // }
}, // }, function (ret, res) {
payAmount: { // for (let key in statistics) {
num: 0, // statistics[key].num = res.data[key + 'Num'];
text: '支付金额', // }
path: '',
tip: '时间区间内支付订单的支付总金额(包含退款订单)',
status: 'paid',
},
payOrder: {
num: 0,
text: '支付订单',
path: '',
tip: '时间区间内支付的订单数量(包含退款订单)',
status: 'paid',
},
noSend: {
num: 0,
text: '待发货订单',
path: '',
tip: '时间区间内待发货订单数量',
status: 'nosend',
},
aftersale: {
num: 0,
text: '售后维权',
path: '',
tip: '时间区间内申请售后维权的订单数量',
status: 'aftersale',
},
refund: {
num: 0,
text: '退款订单',
path: '',
tip: '时间区间内退款的订单数量',
status: 'refund',
},
});
async function getChart() {
Fast.api.ajax({
url: 'shopro/dashboard/chart',
type: 'GET',
data: {
date: chart.dateTime.join(' - '),
}
}, function (ret, res) {
for (let key in statistics) {
statistics[key].num = res.data[`${key}Num`];
}
chart.data.payAmountArr = res.data.payAmountArr; // 销售额
chart.data.payOrderArr = res.data.payOrderArr; // 订单
chart.data.orderArr = res.data.orderArr; //订单数
initChart(); // chart.data.payAmountArr = res.data.payAmountArr;
return false // chart.data.payOrderArr = res.data.payOrderArr;
}, function (ret, res) { }) // chart.data.orderArr = res.data.orderArr;
}
// 柱状图参数 // initChart();
const chartOption = reactive({ // return false;
grid: { // }, function (ret, res) { });
left: '10px', // }
top: '20px',
bottom: '20px',
right: '20px',
containLabel: true,
},
xAxis: {
type: 'category',
data: [],
offset: 5,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'value',
offset: 5,
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
show: true,
status: 'shadow',
z: -1,
shadowStyle: {
color: 'rgba(191, 191, 191, 0.24)',
},
type: 'shadow',
},
},
series: [
{
name: chart.tabsData[chart.tabActive],
type: 'bar',
data: [],
zlevel: 1,
z: 1,
label: {
show: false,
position: 'top',
},
itemStyle: {
color: '#806af6',
},
showBackground: true,
backgroundStyle: {
color: 'rgba(191, 191, 191, 0.24)',
},
},
],
});
// 获取时间刻度
function initChart() { function initChart() {
if (chart.dateTime) { if (chart.dateTime) {
let time = let time =
...@@ -351,42 +799,36 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -351,42 +799,36 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
let interval = 0; let interval = 0;
if (time <= 60 * 60) { if (time <= 60 * 60) {
interval = parseInt(time / 60); interval = parseInt(time / 60);
kld = 'minutes'; kld = 'minutes';
} else if (time <= 60 * 60 * 24) { } else if (time <= 60 * 60 * 24) {
interval = parseInt(time / (60 * 60)); interval = parseInt(time / (60 * 60));
kld = 'hours'; kld = 'hours';
} else if (time <= 60 * 60 * 24 * 30 * 1.5) { } else if (time <= 60 * 60 * 24 * 30 * 1.5) {
interval = parseInt(time / (60 * 60 * 24)); interval = parseInt(time / (60 * 60 * 24));
kld = 'days'; kld = 'days';
} else if (time < 60 * 60 * 24 * 30 * 24) { } else if (time < 60 * 60 * 24 * 30 * 24) {
interval = parseInt(time / (60 * 60 * 24 * 30)); interval = parseInt(time / (60 * 60 * 24 * 30));
kld = 'months'; kld = 'months';
} else if (time >= 60 * 60 * 24 * 30 * 24) { } else if (time >= 60 * 60 * 24 * 30 * 24) {
interval = parseInt(time / (60 * 60 * 24 * 30 * 12)); interval = parseInt(time / (60 * 60 * 24 * 30 * 12));
kld = 'years'; kld = 'years';
} }
drawX(interval, kld); drawX(interval, kld);
console.log(chartOption, 'chartOption')
var chartContentEl = document.getElementById(`chartContent`); var chartContentEl = document.getElementById('chartContent');
if (chartContentEl) { if (chartContentEl) {
var myChart2 = echarts.init(chartContentEl); var myChart2 = echarts.init(chartContentEl);
window.onresize = () => { window.onresize = () => {
myChart2.resize() myChart2.resize();
} };
myChart2.setOption(chartOption); myChart2.setOption(chartOption);
} }
} else { } else {
chartOption.xAxis.data = []; chartOption.xAxis.data = [];
chartOption.series[0].data = []; chartOption.series[0].data = [];
} }
} }
// 给柱状图数据赋值
function drawX(interval, kld) { function drawX(interval, kld) {
let x = []; let x = [];
let y = []; let y = [];
...@@ -410,7 +852,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -410,7 +852,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
timeStamp.push(Moment(chart.dateTime[0]).add(i, kld).valueOf()); timeStamp.push(Moment(chart.dateTime[0]).add(i, kld).valueOf());
} }
x.forEach((item, index) => { x.forEach((item, index) => {
chart.data[`${chart.tabActive}Arr`].forEach((item) => { chart.data[chart.tabActive + 'Arr'].forEach((item) => {
if ( if (
item.createtime > (index - 1 >= 0 ? timeStamp[index - 1] : 0) && item.createtime > (index - 1 >= 0 ? timeStamp[index - 1] : 0) &&
item.createtime <= timeStamp[index] item.createtime <= timeStamp[index]
...@@ -426,7 +868,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -426,7 +868,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
chartOption.xAxis.data = x; chartOption.xAxis.data = x;
chartOption.series[0].data = y; chartOption.series[0].data = y;
} }
// 默认获取当天的时间赋值
function getTimeSlot(e) { function getTimeSlot(e) {
let beginTime = Moment(new Date()).format('YYYY-MM-DD'); let beginTime = Moment(new Date()).format('YYYY-MM-DD');
let endTime = Moment(new Date()).format('YYYY-MM-DD'); let endTime = Moment(new Date()).format('YYYY-MM-DD');
...@@ -448,7 +890,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -448,7 +890,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
const ranking = reactive({ const ranking = reactive({
goods: [], goods: [],
hot_search: [] hot_search: []
}) });
const pieOption = reactive({ const pieOption = reactive({
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
...@@ -483,55 +926,46 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -483,55 +926,46 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
}, },
], ],
}); });
function getRanking() {
Fast.api.ajax({
url: 'shopro/dashboard/ranking',
type: 'GET',
}, function (ret, res) {
ranking.goods = res.data.goods
ranking.hot_search = res.data.hot_search
pieOption.series[0].data = []
ranking.hot_search.forEach(item => {
pieOption.series[0].data.push({
name: item.keyword,
value: item.num,
});
})
var rankingContentEl = document.getElementById(`rankingContent`); // function getRanking() {
if (rankingContentEl) { // Fast.api.ajax({
var myChart3 = echarts.init(rankingContentEl); // url: 'shopro/dashboard/ranking',
window.onresize = () => { // type: 'GET',
myChart3.resize() // }, function (ret, res) {
} // ranking.goods = res.data.goods;
myChart3.setOption(pieOption); // ranking.hot_search = res.data.hot_search;
} // pieOption.series[0].data = [];
// ranking.hot_search.forEach(item => {
// pieOption.series[0].data.push({
// name: item.keyword,
// value: item.num,
// });
// });
return false // var rankingContentEl = document.getElementById('rankingContent');
}, function (ret, res) { }) // if (rankingContentEl) {
} // var myChart3 = echarts.init(rankingContentEl);
// window.onresize = () => {
// myChart3.resize();
// };
// myChart3.setOption(pieOption);
// }
// return false;
// }, function (ret, res) { });
// }
function onOpen(status) { function onOpen(status) {
Fast.api.open(`shopro/order/order/index?status=${status}&createtime=${encodeURI(JSON.stringify(chart.dateTime))}`, "订单", { Fast.api.open('shopro/order/order/index?status=' + status + '&createtime=' + encodeURI(JSON.stringify(chart.dateTime)), "订单", {
callback() { callback() {
getChart() getChart();
} }
}) });
} }
onMounted(() => { onMounted(() => {
Config.cardList.forEach(item => { initCharts();
if (item.name == 'total' && item.status) { loadStatistics('30days');
getTotal() });
}
if (item.name == 'chart' && item.status) {
getChart()
}
if (item.name == 'ranking' && item.status) {
getRanking()
}
})
})
return { return {
state, state,
...@@ -547,9 +981,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ( ...@@ -547,9 +981,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function (
getTimeSlot, getTimeSlot,
ranking, ranking,
onOpen, onOpen,
} initCharts,
loadStatistics,
updateGmvChart,
updateOrderChart,
loadFunnel,
loadPriceDistribution,
loadRecentOrders,
refreshAllData,
switchPeriod,
formatNumber,
};
} }
} };
createApp('index', index); createApp('index', index);
}, },
}; };
......
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