Compare commits
2 Commits
6a09cbeb70
...
440fc23e2f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
440fc23e2f | ||
![]() |
499d80ab0e |
@ -12,7 +12,7 @@
|
||||
<div class="card-header">
|
||||
<span class="card-label">总订单量</span>
|
||||
<div class="card-icon">
|
||||
<svg-icon icon-class="shopping" class="text-blue-600" />
|
||||
<svg-icon icon-class="shopping" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-value">{{ summaryData.totalOrderCount }}</div>
|
||||
@ -23,7 +23,7 @@
|
||||
<div class="card-header">
|
||||
<span class="card-label">订单总金额</span>
|
||||
<div class="card-icon">
|
||||
<svg-icon icon-class="money" class="text-green-600" />
|
||||
<svg-icon icon-class="money" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-value">¥{{ summaryData.totalOrderAmount }}</div>
|
||||
@ -125,7 +125,7 @@
|
||||
<div class="double-chart-section">
|
||||
<!-- 无人机型号分布图 -->
|
||||
<div class="chart-box">
|
||||
<h3 class="chart-title">无人机型号分布</h3>
|
||||
<h3 class="chart-title">无人机型号订单占比</h3>
|
||||
<div class="chart-wrapper" ref="modelChartContainer"></div>
|
||||
</div>
|
||||
|
||||
@ -493,9 +493,9 @@ export default {
|
||||
}
|
||||
|
||||
console.log('接口响应数据:', response);
|
||||
this.summaryData.totalOrderAmount = response.totalOrderAmount;
|
||||
this.summaryData.totalOrderCount = response.totalOrderCount;
|
||||
this.processResponseData(response.data);
|
||||
|
||||
this.processResponseData(response);
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取订单分析数据失败:', error);
|
||||
this.$message.error('获取数据失败,请重试');
|
||||
@ -599,15 +599,17 @@ export default {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 简单添加标题和最大值标注
|
||||
const maxValue = Math.max(...seriesData);
|
||||
const maxIndex = seriesData.indexOf(maxValue);
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
formatter: params => {
|
||||
const value = params[0].value;
|
||||
const axisValue = params[0].axisValue;
|
||||
return `${axisValue}<br/>订单数量: ${value}`;
|
||||
return `${axisValue}<br/>当前订单量: ${value}`;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
@ -618,20 +620,25 @@ export default {
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
name:'时间',
|
||||
data: xAxisData,
|
||||
axisTick: {
|
||||
show: true,
|
||||
inside: true, // 刻度在轴内
|
||||
},
|
||||
axisLabel: {
|
||||
rotate: xAxisData.length > 10 ? 45 : 0,
|
||||
formatter: value => {
|
||||
switch (this.filter.timeRange) {
|
||||
case 'day': return value.split('-').slice(1).join('-');
|
||||
case 'month': return value.split('-')[1];
|
||||
case 'year': return value;
|
||||
case 'month': return value.split('-')[1]+ '月';
|
||||
case 'year': return value+ '年';
|
||||
default: return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: { type: 'value', minInterval: 1 },
|
||||
yAxis: { type: 'value', minInterval: 1,name: '订单数量'},
|
||||
series: [{
|
||||
name: '订单数量',
|
||||
data: seriesData,
|
||||
@ -639,11 +646,23 @@ export default {
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(58, 77, 233, 0.8)' },
|
||||
{ offset: 1, color: 'rgba(58, 77, 233, 0.1)' }
|
||||
{ offset: 0, color: 'rgb(121, 165, 247,0.5)' },
|
||||
{ offset: 1, color: 'rgb(234, 241, 253, 0.1)' }
|
||||
])
|
||||
},
|
||||
itemStyle: { color: '#3a4de9' }
|
||||
axisTick: {
|
||||
show: true,
|
||||
inside: true, // 刻度在轴内
|
||||
},
|
||||
itemStyle: { color: '#4E80EE' },
|
||||
markPoint: {
|
||||
data: [{
|
||||
type: 'max',
|
||||
label: {
|
||||
formatter: '{c}'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
@ -673,13 +692,14 @@ export default {
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: 10,
|
||||
top: 'center'
|
||||
top: 'center',
|
||||
itemGap: 10
|
||||
},
|
||||
series: [{
|
||||
name: '无人机型号分布',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
center: ['40%', '50%'],
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
@ -705,72 +725,102 @@ export default {
|
||||
},
|
||||
|
||||
updateRouteChart(routeDistribution) {
|
||||
if (!this.routeChart) return;
|
||||
if (!this.routeChart) return;
|
||||
|
||||
// 过滤掉数量为0的路线
|
||||
const topRoutes = (routeDistribution || [])
|
||||
.filter(item => item.count > 0)
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, 10);
|
||||
// 1. 处理数据:过滤无效值并按值从大到小排序
|
||||
const topRoutes = (routeDistribution || [])
|
||||
.filter(item => item.count > 0)
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, 10);
|
||||
|
||||
if (topRoutes.length === 0) {
|
||||
this.routeChart.setOption({
|
||||
title: {
|
||||
text: '暂无数据',
|
||||
left: 'center',
|
||||
top: 'center'
|
||||
if (topRoutes.length === 0) {
|
||||
this.routeChart.setOption({
|
||||
title: {
|
||||
text: '暂无数据',
|
||||
left: 'center',
|
||||
top: 'center'
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.routeChart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
formatter: params => {
|
||||
const route = topRoutes[params[0].dataIndex];
|
||||
return `路线: ${route.routeName || '未知路线'}<br>景区: ${route.scenicName || '未知景区'}<br>订单量: ${params[0].data}`;
|
||||
}
|
||||
// 2. 颜色梯度计算(值越大颜色越深)
|
||||
const maxValue = Math.max(...topRoutes.map(item => item.count));
|
||||
const colorGradient = (value) => {
|
||||
const ratio = value / maxValue;
|
||||
return new echarts.graphic.LinearGradient(0, 0, 0,1, [
|
||||
{ offset: 0, color: `rgba(9, 71, 179, ${0.3 + ratio * 0.7})` }, // 顶部颜色更深
|
||||
{ offset: 1, color: `rgba(58, 119, 233, ${0.3 + ratio * 0.7})` } // 底部颜色更浅
|
||||
]);
|
||||
};
|
||||
|
||||
// 3. 设置图表配置
|
||||
this.routeChart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
formatter: (params) => {
|
||||
const data = params[0];
|
||||
return `
|
||||
<div style="font-weight:bold">${data.name}</div>
|
||||
<div>订单量: ${data.value}件</div>
|
||||
${data.data.percentage ? `<div>完成率: ${data.data.percentage}</div>` : ''}
|
||||
`;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '12%', // 为右侧数值留更多空间
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
name: '订单数量(件)',
|
||||
splitLine: {
|
||||
show: false // 移除背景竖线
|
||||
},
|
||||
axisTick: {
|
||||
show: false // 隐藏刻度
|
||||
},
|
||||
max: Math.max(50, maxValue) // 动态调整最大值
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
name: '景区路线',
|
||||
nameLocation: 'start',
|
||||
data: topRoutes.map(item => item.routeName),
|
||||
axisLabel: {
|
||||
formatter: (name) => name.length > 8 ? `${name.substring(0, 8)}...` : name
|
||||
},
|
||||
axisTick: {
|
||||
show: false // 隐藏刻度
|
||||
},
|
||||
splitLine: {
|
||||
show: false // 移除背景横线
|
||||
},
|
||||
inverse: true // 反转Y轴使最大值在上方
|
||||
},
|
||||
series: [{
|
||||
name: '订单量',
|
||||
type: 'bar',
|
||||
data: topRoutes.map(item => ({
|
||||
value: item.count,
|
||||
name: item.routeName,
|
||||
percentage: item.count.toString().includes('%') ? item.count : null,
|
||||
itemStyle: {
|
||||
color: colorGradient(item.count)
|
||||
}
|
||||
})),
|
||||
barWidth: '40%',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'right', // 数值显示在右侧
|
||||
formatter: ({ data }) => data.displayValue || `${data.value}`,
|
||||
}
|
||||
}]
|
||||
}, true);
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01],
|
||||
minInterval: 1 // 确保显示整数
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: topRoutes.map(item => item.routeName || `路线 ${item.routeId}`),
|
||||
axisLabel: {
|
||||
formatter: value => value.length > 6 ? value.substring(0, 6) + '...' : value
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: '订单量',
|
||||
type: 'bar',
|
||||
data: topRoutes.map(item => item.count),
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: '#83bff6' },
|
||||
{ offset: 0.5, color: '#188df0' },
|
||||
{ offset: 1, color: '#0052d9' }
|
||||
]),
|
||||
borderRadius: [0, 5, 5, 0]
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'right',
|
||||
formatter: '{c}'
|
||||
}
|
||||
}]
|
||||
}, true);
|
||||
},
|
||||
|
||||
handleJump() {
|
||||
const page = parseInt(this.jumpPage);
|
||||
@ -837,11 +887,9 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 保持原有的样式不变 */
|
||||
.order-analysis-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
font-family: 'Arial', sans-serif;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
@ -858,61 +906,48 @@ export default {
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 卡片布局 */
|
||||
.card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
padding: 16px;
|
||||
min-height: 70px;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
min-height: 60px;
|
||||
border-radius: 6px;
|
||||
transition: transform 0.2s;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.blue-card {
|
||||
background: linear-gradient(to bottom right, #ebf4ff, white);
|
||||
}
|
||||
|
||||
.green-card {
|
||||
background: linear-gradient(to bottom right, #ecfdf5, white);
|
||||
}
|
||||
|
||||
.purple-card {
|
||||
background: linear-gradient(to bottom right, #e5e2f4, white);
|
||||
}
|
||||
|
||||
.orange-card {
|
||||
background: linear-gradient(to bottom right, #f7f5e7, white);
|
||||
}
|
||||
/* 卡片颜色变体 */
|
||||
.blue-card { background: linear-gradient(to bottom right, #ebf4ff, white) }
|
||||
.green-card { background: linear-gradient(to bottom right, #ecfdf5, white) }
|
||||
.purple-card { background: linear-gradient(to bottom right, #e5e2f4, white) }
|
||||
.orange-card { background: linear-gradient(to bottom right, #f7f5e7, white) }
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.card-label {
|
||||
font-size: 18px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
@ -920,63 +955,53 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: inherit;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 28px;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 筛选区域 */
|
||||
.filter-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
padding: 12px;
|
||||
background-color: #f9fafb;
|
||||
border-radius: 8px;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-right: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.time-range-buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.time-button {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dcdfe6;
|
||||
background: #f5f7fa;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.time-button.active {
|
||||
background: #409eff;
|
||||
color: white;
|
||||
@ -989,45 +1014,34 @@ export default {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
color: #606266;
|
||||
padding: 0 5px;
|
||||
/* 图表区域 */
|
||||
.chart-section, .data-table-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.chart-section {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.double-chart-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20px;
|
||||
margin-bottom: 32px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.chart-box {
|
||||
.chart-box, .data-table-section {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
||||
padding: 20px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
font-size: 18px;
|
||||
.chart-title, .table-title {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.chart-title { font-size: 16px }
|
||||
.table-title { font-size: 18px }
|
||||
|
||||
.chart-title::before {
|
||||
.chart-title::before, .table-title::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
@ -1039,39 +1053,13 @@ export default {
|
||||
|
||||
.chart-wrapper {
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.data-table-section {
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.table-title {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.table-title::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
background-color: #3a4de9;
|
||||
margin-right: 8px;
|
||||
border-radius: 2px;
|
||||
height: 320px;
|
||||
}
|
||||
|
||||
/* 表格区域 */
|
||||
.table-wrapper {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -1080,113 +1068,39 @@ export default {
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.pagination-info {
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.pagination-jump {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.jump-text {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.jump-input {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.jump-input .el-input__inner {
|
||||
text-align: center;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.jump-button {
|
||||
padding: 8px 15px;
|
||||
}
|
||||
|
||||
/* 响应式布局 */
|
||||
@media (max-width: 1200px) {
|
||||
.card-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.double-chart-section {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.date-range-picker {
|
||||
width: 280px;
|
||||
}
|
||||
.card-grid { grid-template-columns: repeat(2, 1fr) }
|
||||
.double-chart-section { grid-template-columns: 1fr }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.card-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.date-range-picker {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.time-range-buttons {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.card-grid { grid-template-columns: 1fr }
|
||||
.filter-section { flex-direction: column }
|
||||
.filter-group, .time-range-buttons, .date-range-picker { width: 100% }
|
||||
.filter-item { flex-direction: column; align-items: flex-start }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.main-content {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.content-box {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.chart-wrapper {
|
||||
height: 300px;
|
||||
}
|
||||
.main-content { padding: 10px }
|
||||
.content-box { padding: 16px }
|
||||
.chart-wrapper { height: 280px }
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user