dashboard
This commit is contained in:
parent
f0708b12aa
commit
41f470b5de
|
|
@ -35,6 +35,143 @@ class Dashboard extends Backend
|
|||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
|
||||
$start = now()->modify('-30 days')->format('Y-m-d');
|
||||
$end_at = now()->format('Y-m-d 23:29:59');
|
||||
|
||||
$filter = request()->get('range', '');
|
||||
if (!empty($filter)) {
|
||||
$arr = explode(' - ', $filter);
|
||||
if (trim($arr[0])) {
|
||||
$start = trim($arr[0]) . ' 00:00:00';
|
||||
}
|
||||
if (trim($arr[1])) {
|
||||
$end_at = trim($arr[1]) . ' 23:29:59';
|
||||
}
|
||||
}
|
||||
|
||||
$top = $this->getTopTotal($start, $end_at);
|
||||
$lines = $this->getLines($start, $end_at);
|
||||
$this->success(data: [
|
||||
'top' => $top,
|
||||
'lines' => $lines
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
private function prepareEchartsBarData(array $data, string $startDate, string $endDate): array
|
||||
{
|
||||
// 将原始数据用日期作为键索引
|
||||
$indexed = [];
|
||||
foreach ($data as $item) {
|
||||
$indexed[$item['day']] = $item;
|
||||
}
|
||||
|
||||
$start = strtotime($startDate);
|
||||
$end = strtotime($endDate);
|
||||
|
||||
$xAxis = [];
|
||||
$series_total = [];
|
||||
$series_count = [];
|
||||
|
||||
$new_count_array = [];
|
||||
$old_count_array = [];
|
||||
$rent_count_array = [];
|
||||
$new_total_array = [];
|
||||
$old_total_array = [];
|
||||
$rent_total_array = [];
|
||||
|
||||
for ($date = $start; $date <= $end; $date += 86400) {
|
||||
$day = date('Y-m-d', $date);
|
||||
$xAxis[] = $day;
|
||||
|
||||
$total = $indexed[$day]['total'] ?? 0;
|
||||
$count = $indexed[$day]['count'] ?? 0;
|
||||
$new_count = $indexed[$day]['new_count'] ?? 0;
|
||||
$old_count = $indexed[$day]['old_count'] ?? 0;
|
||||
$rent_count = $indexed[$day]['rent_count'] ?? 0;
|
||||
$new_total = $indexed[$day]['new_total'] ?? 0;
|
||||
$old_total = $indexed[$day]['old_total'] ?? 0;
|
||||
$rent_total = $indexed[$day]['rent_total'] ?? 0;
|
||||
|
||||
$series_total[] = $total;
|
||||
$series_count[] = $count;
|
||||
$new_count_array[] = $new_count;
|
||||
$old_count_array[] = $old_count;
|
||||
$rent_count_array[] = $rent_count;
|
||||
$new_total_array[] = $new_total;
|
||||
$old_total_array[] = $old_total;
|
||||
$rent_total_array[] = $rent_total;
|
||||
|
||||
}
|
||||
|
||||
$data = [
|
||||
'xAxis' => $xAxis,
|
||||
'series' => [
|
||||
'total' => $series_total,
|
||||
'count' => $series_count,
|
||||
'new_count' => $new_count_array,
|
||||
'old_count' => $old_count_array,
|
||||
'rent_count' => $rent_count_array,
|
||||
'new_total' => $new_total_array,
|
||||
'old_total' => $old_total_array,
|
||||
'rent_total' => $rent_total_array,
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
// 判断是否需要按月归档
|
||||
if (count($data['xAxis']) > 31) {
|
||||
$monthly = [];
|
||||
|
||||
foreach ($data['xAxis'] as $i => $date) {
|
||||
$month = date('Y-m', strtotime($date));
|
||||
|
||||
if (!isset($monthly[$month])) {
|
||||
$monthly[$month] = [
|
||||
'total' => 0,
|
||||
'count' => 0,
|
||||
'performance' => 0,
|
||||
'rate_sum' => 0,
|
||||
'rate_count' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
$monthly[$month]['total'] += $data['series']['total'][$i];
|
||||
$monthly[$month]['count'] += $data['series']['count'][$i];
|
||||
$monthly[$month]['performance'] += $data['series']['performance'][$i];
|
||||
|
||||
// 处理 rate(字符串,转换为 float)
|
||||
$rate = (float)$data['series']['rate'][$i];
|
||||
$monthly[$month]['rate_sum'] += $rate;
|
||||
$monthly[$month]['rate_count'] += 1;
|
||||
}
|
||||
|
||||
// 重新生成 xAxis 和 series
|
||||
$data['xAxis'] = array_keys($monthly);
|
||||
$data['series'] = [
|
||||
'total' => [],
|
||||
'count' => [],
|
||||
'performance' => [],
|
||||
'rate' => []
|
||||
];
|
||||
|
||||
foreach ($monthly as $month => $values) {
|
||||
$data['series']['total'][] = $values['total'];
|
||||
$data['series']['count'][] = $values['count'];
|
||||
$data['series']['performance'][] = $values['performance'];
|
||||
|
||||
// 平均 rate,保留 2 位小数
|
||||
$averageRate = $values['rate_count'] > 0 ? $values['rate_sum'] / $values['rate_count'] : 0;
|
||||
$data['series']['rate'][] = number_format($averageRate, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getTopTotal($start, $end_at)
|
||||
{
|
||||
$car_num = Db::query('SELECT
|
||||
COUNT(IF(car_type = 1,1,null)) new_car,
|
||||
|
|
@ -75,9 +212,34 @@ COUNT(IF(car_type = 2,1,null)) old_car
|
|||
"sum(total_price) total_price",
|
||||
])->select()[0]->toArray();
|
||||
|
||||
$this->success(data:[
|
||||
return [
|
||||
...$car_num, ...$sale
|
||||
]);
|
||||
];
|
||||
}
|
||||
|
||||
private function getLines($start, $end_at)
|
||||
{
|
||||
$build = new Sales();
|
||||
$build->whereBetween('finish_at', [$start, $end_at]);
|
||||
$res = $build->field([
|
||||
'DATE(finish_at) day',
|
||||
"count(if(type=1,1,null)) new_count",
|
||||
"count(if(type=2,1,null)) old_count",
|
||||
"count(if(type=3,1,null)) rent_count",
|
||||
"sum(if(type=1,total_price,0)) new_total",
|
||||
"sum(if(type=2,total_price,0)) old_total",
|
||||
"sum(if(type=3,total_price,0)) rent_total",
|
||||
'sum(total_price) total',
|
||||
'count(id) count',
|
||||
])->group('DATE(finish_at)')
|
||||
->select();
|
||||
|
||||
$data = [];
|
||||
foreach ($res as $re) {
|
||||
$re = $re->getData();
|
||||
$data [] = $re;
|
||||
}
|
||||
return $this->prepareEchartsBarData($data, $start, $end_at);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,86 +7,377 @@
|
|||
<input type="text" class="form-control datetimerange" value = "{$default_daterange|htmlentities}" data-locale='{"format":"YYYY-MM-DD"}'
|
||||
placeholder="指定日期" name="filter[daterange]" id="daterange" autocomplete="off" style="width: 200px;">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 查询按钮 -->
|
||||
<button class="btn btn-default" id="filter-btn" style="margin-left: 15px;">查询</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<!-- 统计卡片 -->
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card" >
|
||||
<span class="stat-icon new-car">🚙</span>
|
||||
<div class="stat-number">loading</div>
|
||||
<div class="stat-label">新车库存</div>
|
||||
<!-- 新车业务 -->
|
||||
<div class="stat-card new-car">
|
||||
<div class="stat-header">
|
||||
<div class="stat-title">新车业务</div>
|
||||
<div class="stat-icon">
|
||||
<i class="fa fa-car"></i>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-icon used-car">🚗</span>
|
||||
<div class="stat-number">loading</div>
|
||||
<div class="stat-label">二手车库存</div>
|
||||
</div>
|
||||
<div class="stat-card" >
|
||||
<span class="stat-icon rental-car">🚐</span>
|
||||
<div class="stat-number">loading</div>
|
||||
<div class="stat-label">租车车辆</div>
|
||||
<div class="stat-value" id="newCarCount">5 辆</div>
|
||||
<div class="stat-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">销售数量</span>
|
||||
<span class="detail-value" id="newSalesCount">1 辆</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-icon total-sales">💰</span>
|
||||
<div class="stat-number">loading</div>
|
||||
<div class="stat-label">本月销售额</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">销售金额</span>
|
||||
<span class="detail-value" id="newSalesAmount">¥230,000</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 租车业务 -->
|
||||
<div class="stat-card rent-car">
|
||||
<div class="stat-header">
|
||||
<div class="stat-title">租车业务</div>
|
||||
<div class="stat-icon">
|
||||
<i class="fa fa-credit-card"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-value" id="rentCarCount">29 辆</div>
|
||||
<div class="stat-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">订单数量</span>
|
||||
<span class="detail-value" id="rentOrderCount">1 单</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">租金收入</span>
|
||||
<span class="detail-value" id="rentIncome">¥2,222</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 二手车业务 -->
|
||||
<div class="stat-card old-car">
|
||||
<div class="stat-header">
|
||||
<div class="stat-title">二手车业务</div>
|
||||
<div class="stat-icon">
|
||||
<i class="fa fa-handshake-o"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-value" id="oldCarCount">1 辆</div>
|
||||
<div class="stat-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">销售数量</span>
|
||||
<span class="detail-value" id="oldSalesCount">0 辆</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">销售金额</span>
|
||||
<span class="detail-value" id="oldSalesAmount">¥0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 总营收 -->
|
||||
<div class="stat-card total">
|
||||
<div class="stat-header">
|
||||
<div class="stat-title">总营收概览</div>
|
||||
<div class="stat-icon">
|
||||
<i class="fa fa-money"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-value" id="totalRevenue">¥232,222</div>
|
||||
<div class="stat-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">新车占比</span>
|
||||
<span class="detail-value" id="newCarPercent">99.04%</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">租车占比</span>
|
||||
<span class="detail-value" id="rentCarPercent">0.96%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 业务汇总 -->
|
||||
<div class="summary-section">
|
||||
<h2 class="summary-title"><i class="fas fa-chart-bar"></i> 业务数据汇总</h2>
|
||||
<div class="summary-grid">
|
||||
<div class="summary-item">
|
||||
<div class="summary-number" id="totalCars">35</div>
|
||||
<div class="summary-label">车辆总数</div>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<div class="summary-number" id="totalOrders">2</div>
|
||||
<div class="summary-label">总订单数</div>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<div class="summary-number" id="avgOrderValue">¥116,111</div>
|
||||
<div class="summary-label">平均订单金额</div>
|
||||
</div>
|
||||
<div class="summary-item">
|
||||
<div class="summary-number" id="inventoryUtilization">5.7%</div>
|
||||
<div class="summary-label">库存利用率</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="lines">
|
||||
<div id="money_line"></div>
|
||||
</div>
|
||||
|
||||
<div class="update-time">
|
||||
<i class="fas fa-clock"></i> 数据更新时间:<span id="updateTime"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
html {
|
||||
font-size: 13px;
|
||||
}
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Microsoft YaHei', Arial, sans-serif;
|
||||
background: #f5f6fa;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 40px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 15px;
|
||||
background: white;
|
||||
padding: 25px;
|
||||
text-align: center;
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.1);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
|
||||
border-left: 4px solid;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 15px 40px rgba(0,0,0,0.15);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.stat-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: linear-gradient(45deg, rgba(255,255,255,0.1), rgba(255,255,255,0.3));
|
||||
border-radius: 50%;
|
||||
transform: translate(20px, -20px);
|
||||
}
|
||||
|
||||
.stat-card.new-car {
|
||||
border-left-color: #28a745;
|
||||
}
|
||||
|
||||
.stat-card.rent-car {
|
||||
border-left-color: #007bff;
|
||||
}
|
||||
|
||||
.stat-card.old-car {
|
||||
border-left-color: #ffc107;
|
||||
}
|
||||
|
||||
.stat-card.total {
|
||||
border-left-color: #dc3545;
|
||||
background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.stat-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.new-car { color: #4299e1; }
|
||||
.used-car { color: #48bb78; }
|
||||
.rental-car { color: #ed8936; }
|
||||
.total-sales { color: #9f7aea; }
|
||||
.new-car .stat-icon {
|
||||
background: linear-gradient(135deg, #28a745, #20c997);
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
.rent-car .stat-icon {
|
||||
background: linear-gradient(135deg, #007bff, #0056b3);
|
||||
}
|
||||
|
||||
.old-car .stat-icon {
|
||||
background: linear-gradient(135deg, #ffc107, #fd7e14);
|
||||
}
|
||||
|
||||
.total .stat-icon {
|
||||
background: linear-gradient(135deg, #dc3545, #c82333);
|
||||
}
|
||||
|
||||
.stat-title {
|
||||
font-size: 1rem;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.total .stat-title {
|
||||
color: rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.stat-details {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
background: rgba(0,0,0,0.05);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.lines{
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.total .detail-item {
|
||||
background: rgba(255,255,255,0.2);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.total .detail-label {
|
||||
color: rgba(255,255,255,0.8);
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.summary-section {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
border-bottom: 3px solid #667eea;
|
||||
padding-bottom: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.summary-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
border: 2px solid #eee;
|
||||
border-radius: 8px;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.summary-item:hover {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.summary-number {
|
||||
font-size: 1.8rem;
|
||||
font-weight: bold;
|
||||
color: #667eea;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: #718096;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
.summary-label {
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.update-time {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
color: #999;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.lines{
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
#money_line{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.stat-details {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,24 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
|
|||
$('#filter-btn').on('click', function () {
|
||||
Controller.api.getChartData();
|
||||
});
|
||||
|
||||
// 页面加载完成后更新数据
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 模拟数据实时更新(可选)
|
||||
setInterval(() => {
|
||||
Controller.api.getChartData()
|
||||
}, 60000); // 每分钟更新一次时间
|
||||
});
|
||||
|
||||
// 添加卡片点击效果
|
||||
document.querySelectorAll('.stat-card').forEach(card => {
|
||||
card.addEventListener('click', function() {
|
||||
this.style.transform = 'scale(0.95)';
|
||||
setTimeout(() => {
|
||||
this.style.transform = '';
|
||||
}, 150);
|
||||
});
|
||||
});
|
||||
},
|
||||
api: {
|
||||
getChartData: function () {
|
||||
|
|
@ -25,17 +43,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
|
|||
'item_id': item_id,*/
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "dashboard/getData", //
|
||||
Fast.api.ajax({
|
||||
url: "dashboard/getData",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: params,
|
||||
success: function (response) {
|
||||
Controller.api.chart(response);
|
||||
},
|
||||
error: function () {
|
||||
},function (response) {
|
||||
document.getElementById('updateTime').textContent = new Date().toLocaleString('zh-CN');
|
||||
Controller.api.updateDashboard(response.top);
|
||||
Controller.api.money_line(response.lines);
|
||||
return false;
|
||||
},function () {
|
||||
console.error("图表数据加载失败");
|
||||
}
|
||||
});
|
||||
},
|
||||
bindevent: function () {
|
||||
|
|
@ -81,6 +100,196 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts','echarts-th
|
|||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 格式化金额
|
||||
formatCurrency: function (amount) {
|
||||
return new Intl.NumberFormat('zh-CN', {
|
||||
style: 'currency',
|
||||
currency: 'CNY',
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0
|
||||
}).format(parseFloat(amount));
|
||||
},
|
||||
|
||||
// 计算百分比
|
||||
calculatePercentage: function (part, total) {
|
||||
return ((parseFloat(part) / parseFloat(total)) * 100).toFixed(2) + '%';
|
||||
},
|
||||
money_line: function (data){
|
||||
var myChart = echarts.init(document.getElementById('money_line'));
|
||||
|
||||
var option = {
|
||||
title: {
|
||||
text: '总业绩',
|
||||
subtext: '数据',
|
||||
left: 'left'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
crossStyle: {
|
||||
color: '#999'
|
||||
}
|
||||
}
|
||||
},
|
||||
color: [
|
||||
"#18d1b1",
|
||||
"#3fb1e3",
|
||||
"#626c91",
|
||||
"#a0a7e6",
|
||||
"#c4ebad",
|
||||
"#96dee8"
|
||||
],
|
||||
legend: {
|
||||
data: ['订单量', '营销额', '新车单量','新车营销额','租车单量','租车营销额','二手车单量','二手车营销额',],
|
||||
// left: 'left',
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: data.xAxis,
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '金额',
|
||||
position: 'left'
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '单量',
|
||||
position: 'right'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '订单量',
|
||||
type: 'line',
|
||||
data: data.series.count,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
yAxisIndex: 1,
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
{
|
||||
name: '营销额',
|
||||
type: 'bar',
|
||||
data: data.series.total,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
|
||||
{
|
||||
name: '新车单量',
|
||||
type: 'line',
|
||||
data: data.series.new_count,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
yAxisIndex: 1,
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
{
|
||||
name: '新车营销额',
|
||||
type: 'bar',
|
||||
data: data.series.new_total,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
{
|
||||
name: '租车单量',
|
||||
type: 'line',
|
||||
data: data.series.rent_count,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
yAxisIndex: 1,
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
{
|
||||
name: '租车营销额',
|
||||
type: 'line',
|
||||
data: data.series.rent_total,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
{
|
||||
name: '二手车单量',
|
||||
type: 'line',
|
||||
data: data.series.old_count,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
yAxisIndex: 1,
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
{
|
||||
name: '二手车营销额',
|
||||
type: 'bar',
|
||||
data: data.series.old_total,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
barGap: '10%' // 调整柱状图1与柱状图2之间的间距
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
|
||||
// 监听窗口大小变化,自动重新绘制图表
|
||||
window.addEventListener('resize', function() {
|
||||
myChart.resize();
|
||||
});
|
||||
},
|
||||
// 更新界面数据
|
||||
updateDashboard: function (data) {
|
||||
// 基础数据更新
|
||||
document.getElementById('newCarCount').textContent = data.new_car + ' 辆';
|
||||
document.getElementById('rentCarCount').textContent = data.rent_car + ' 辆';
|
||||
document.getElementById('oldCarCount').textContent = data.old_car + ' 辆';
|
||||
|
||||
document.getElementById('newSalesCount').textContent = data.new_count + ' 辆';
|
||||
document.getElementById('rentOrderCount').textContent = data.rent_count + ' 单';
|
||||
document.getElementById('oldSalesCount').textContent = data.old_count + ' 辆';
|
||||
|
||||
document.getElementById('newSalesAmount').textContent = Controller.api.formatCurrency(data.new_sum);
|
||||
document.getElementById('rentIncome').textContent = Controller.api.formatCurrency(data.rent_sum);
|
||||
document.getElementById('oldSalesAmount').textContent = Controller.api.formatCurrency(data.old_sum);
|
||||
document.getElementById('totalRevenue').textContent = Controller.api.formatCurrency(data.total_price);
|
||||
|
||||
// 占比计算
|
||||
document.getElementById('newCarPercent').textContent = Controller.api.calculatePercentage(data.new_sum, data.total_price);
|
||||
document.getElementById('rentCarPercent').textContent = Controller.api.calculatePercentage(data.rent_sum, data.total_price);
|
||||
|
||||
// 汇总数据
|
||||
const totalCars = data.new_car + data.rent_car + data.old_car;
|
||||
const totalOrders = data.new_count + data.rent_count + data.old_count;
|
||||
const avgOrderValue = totalOrders > 0 ? parseFloat(data.total_price) / totalOrders : 0;
|
||||
const inventoryUtilization = (totalOrders / totalCars * 100).toFixed(1);
|
||||
|
||||
document.getElementById('totalCars').textContent = totalCars;
|
||||
document.getElementById('totalOrders').textContent = totalOrders;
|
||||
document.getElementById('avgOrderValue').textContent = Controller.api.formatCurrency(avgOrderValue);
|
||||
document.getElementById('inventoryUtilization').textContent = inventoryUtilization + '%';
|
||||
|
||||
// 更新时间
|
||||
document.getElementById('updateTime').textContent = new Date().toLocaleString('zh-CN');
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user