|
|
|
|
@ -0,0 +1,361 @@
|
|
|
|
|
<template>
|
|
|
|
|
<el-row class="rank-page" :gutter="0">
|
|
|
|
|
<!-- 左侧柱状图 -->
|
|
|
|
|
<el-col :span="16" class="chart-col">
|
|
|
|
|
<div style="text-align: right;width: 100%;margin-bottom: 10px;">
|
|
|
|
|
<el-date-picker v-model="dateRange" @change="changeDate" format="yyyy-MM-dd" value-format="yyyy-MM-dd"
|
|
|
|
|
type="daterange" range-separator="至" start-placeholder="开始日期" unlink-panels end-placeholder="结束日期"
|
|
|
|
|
:picker-options="pickerOptions">
|
|
|
|
|
</el-date-picker>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="chart-title">{{year}}年商业购买服务区域分析图</div>
|
|
|
|
|
<div ref="barChart" class="bar-chart"></div>
|
|
|
|
|
</el-col>
|
|
|
|
|
<!-- 右侧信息区 -->
|
|
|
|
|
<el-col :span="8" class="info-col">
|
|
|
|
|
<div class="logo-box">
|
|
|
|
|
<img :src="logo" class="logo-img" alt="logo" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="summary">
|
|
|
|
|
<div class="summary-title">
|
|
|
|
|
<span class="highlight">{{startDate}}</span>
|
|
|
|
|
至<span class="highlight">{{endDate}}</span>,商业化总收入
|
|
|
|
|
<span class="income highlight">{{total}}元</span>;
|
|
|
|
|
</div>
|
|
|
|
|
<div class="rank-title">区域排名</div>
|
|
|
|
|
<div class="rank-list">
|
|
|
|
|
<div v-for="(item, idx) in barData" :key="item.name">
|
|
|
|
|
第{{ idx + 1 }}名:<span class="highlight">{{ item.name }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import echarts from 'echarts'
|
|
|
|
|
import {
|
|
|
|
|
accompanyChart
|
|
|
|
|
} from "@/api/chart/accompany.js"
|
|
|
|
|
export default {
|
|
|
|
|
name: 'Rank',
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
logo: require("@/assets/logo.png"),
|
|
|
|
|
pickerOptions: {
|
|
|
|
|
shortcuts: [{
|
|
|
|
|
text: '最近一周',
|
|
|
|
|
onClick(picker) {
|
|
|
|
|
const end = new Date();
|
|
|
|
|
const start = new Date();
|
|
|
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
|
|
|
|
|
picker.$emit('pick', [start, end]);
|
|
|
|
|
}
|
|
|
|
|
}, {
|
|
|
|
|
text: '最近一个月',
|
|
|
|
|
onClick(picker) {
|
|
|
|
|
const end = new Date();
|
|
|
|
|
const start = new Date();
|
|
|
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
|
|
|
|
picker.$emit('pick', [start, end]);
|
|
|
|
|
}
|
|
|
|
|
}, {
|
|
|
|
|
text: '最近三个月',
|
|
|
|
|
onClick(picker) {
|
|
|
|
|
const end = new Date();
|
|
|
|
|
const start = new Date();
|
|
|
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
|
|
|
|
|
picker.$emit('pick', [start, end]);
|
|
|
|
|
}
|
|
|
|
|
}, {
|
|
|
|
|
text: '最近一年',
|
|
|
|
|
onClick(picker) {
|
|
|
|
|
const end = new Date();
|
|
|
|
|
const start = new Date();
|
|
|
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 365);
|
|
|
|
|
picker.$emit('pick', [start, end]);
|
|
|
|
|
}
|
|
|
|
|
}, {
|
|
|
|
|
text: '最近三年',
|
|
|
|
|
onClick(picker) {
|
|
|
|
|
const end = new Date();
|
|
|
|
|
const start = new Date();
|
|
|
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 365 * 3);
|
|
|
|
|
picker.$emit('pick', [start, end]);
|
|
|
|
|
}
|
|
|
|
|
}]
|
|
|
|
|
},
|
|
|
|
|
dateRange: [],
|
|
|
|
|
select: {
|
|
|
|
|
start_date: '',
|
|
|
|
|
end_date: '',
|
|
|
|
|
},
|
|
|
|
|
startDate: '',
|
|
|
|
|
endDate: '',
|
|
|
|
|
year: new Date().getFullYear() + '',
|
|
|
|
|
colorList: [
|
|
|
|
|
['#3a7bd5', '#00d2ff'], // 西昌
|
|
|
|
|
['#ff8008', '#ffc837'], // 湖塘
|
|
|
|
|
['#ffd200', '#f7971e'], // 金坛
|
|
|
|
|
['#43e97b', '#38f9d7'], // 永红
|
|
|
|
|
['#11998e', '#38ef7d'], // 潞阳
|
|
|
|
|
['#f85032', '#e73827'], // 直溪
|
|
|
|
|
['#b6c0c5', '#b6c0c5'], // 南夏墅
|
|
|
|
|
['#b6c0c5', '#b6c0c5'] // 高新北
|
|
|
|
|
],
|
|
|
|
|
total: 0,
|
|
|
|
|
barData: []
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
this.getToday()
|
|
|
|
|
this.getChart()
|
|
|
|
|
|
|
|
|
|
// this.initChart()
|
|
|
|
|
window.addEventListener('resize', this.resizeChart)
|
|
|
|
|
},
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
window.removeEventListener('resize', this.resizeChart)
|
|
|
|
|
if (this.chart) this.chart.dispose()
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
changeDate(e) {
|
|
|
|
|
if (e) {
|
|
|
|
|
this.select.start_date = e[0]
|
|
|
|
|
this.select.end_date = e[1]
|
|
|
|
|
this.startDate = this.formatDateToChinese(e[0])
|
|
|
|
|
this.endDate = this.formatDateToChinese(e[1])
|
|
|
|
|
this.getChart()
|
|
|
|
|
} else {
|
|
|
|
|
this.select.start_date = ''
|
|
|
|
|
this.select.end_date = ''
|
|
|
|
|
this.getToday()
|
|
|
|
|
this.getChart()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
formatDateToChinese(dateStr) {
|
|
|
|
|
if (!dateStr) return '';
|
|
|
|
|
|
|
|
|
|
const date = new Date(dateStr);
|
|
|
|
|
const year = date.getFullYear();
|
|
|
|
|
// 注意:getMonth() 返回 0-11,所以要加 1
|
|
|
|
|
const month = date.getMonth() + 1;
|
|
|
|
|
const day = date.getDate();
|
|
|
|
|
|
|
|
|
|
return `${year}年${month}月${day}日`;
|
|
|
|
|
},
|
|
|
|
|
getToday() {
|
|
|
|
|
const currentDate = new Date()
|
|
|
|
|
const year = currentDate.getFullYear()
|
|
|
|
|
const month = currentDate.getMonth() + 1
|
|
|
|
|
const day = currentDate.getDate()
|
|
|
|
|
this.endDate = year + '年' + month + '月' + day + '日'
|
|
|
|
|
this.startDate = year + '年' + '1月' + '1日'
|
|
|
|
|
},
|
|
|
|
|
getColor(index) {
|
|
|
|
|
const colorList = this.colorList
|
|
|
|
|
return colorList[index % colorList.length]
|
|
|
|
|
},
|
|
|
|
|
async getChart() {
|
|
|
|
|
const res = await accompanyChart({
|
|
|
|
|
start_date: this.select.start_date,
|
|
|
|
|
end_date: this.select.end_date
|
|
|
|
|
})
|
|
|
|
|
let arr = []
|
|
|
|
|
res.sites.map(item => {
|
|
|
|
|
arr.push({
|
|
|
|
|
name: item.name,
|
|
|
|
|
value: item.accompany_order_sum
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
this.barData = arr
|
|
|
|
|
this.initChart()
|
|
|
|
|
},
|
|
|
|
|
initChart() {
|
|
|
|
|
this.chart = echarts.init(this.$refs.barChart)
|
|
|
|
|
const option = {
|
|
|
|
|
grid: {
|
|
|
|
|
left: 60,
|
|
|
|
|
right: 20,
|
|
|
|
|
bottom: 40,
|
|
|
|
|
top: 60
|
|
|
|
|
},
|
|
|
|
|
xAxis: {
|
|
|
|
|
type: 'category',
|
|
|
|
|
data: this.barData.map(d => d.name),
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#ccc'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#333',
|
|
|
|
|
fontSize: 16
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
yAxis: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
splitLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#eee'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisLine: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#333',
|
|
|
|
|
fontSize: 16
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
series: [{
|
|
|
|
|
type: 'bar',
|
|
|
|
|
barWidth: 48,
|
|
|
|
|
data: this.barData.map((d, i) => {
|
|
|
|
|
const color = this.getColor(i)
|
|
|
|
|
return {
|
|
|
|
|
value: d.value,
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: {
|
|
|
|
|
type: 'linear',
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
x2: 0,
|
|
|
|
|
y2: 1,
|
|
|
|
|
colorStops: [{
|
|
|
|
|
offset: 0,
|
|
|
|
|
color: color[0]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
offset: 1,
|
|
|
|
|
color: color[1]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
borderRadius: [24, 24, 0, 0],
|
|
|
|
|
shadowColor: d.value > 0 ? color[0] : '#ccc',
|
|
|
|
|
shadowBlur: 10
|
|
|
|
|
},
|
|
|
|
|
label: {
|
|
|
|
|
show: true,
|
|
|
|
|
position: 'top',
|
|
|
|
|
color: color[0],
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
fontSize: 16,
|
|
|
|
|
formatter: d.value > 0 ? d.value : ''
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
z: 3
|
|
|
|
|
}]
|
|
|
|
|
}
|
|
|
|
|
this.chart.setOption(option)
|
|
|
|
|
},
|
|
|
|
|
resizeChart() {
|
|
|
|
|
if (this.chart) this.chart.resize()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.rank-page {
|
|
|
|
|
height: 100vh;
|
|
|
|
|
background: #fff;
|
|
|
|
|
min-width: 1200px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chart-col {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
align-items: center;
|
|
|
|
|
background: #fff;
|
|
|
|
|
padding: 40px 0 0 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chart-title {
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
text-align: left;
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
color: #222;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bar-chart {
|
|
|
|
|
width: 90%;
|
|
|
|
|
height: 500px;
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-col {
|
|
|
|
|
background: #fff;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: flex-end;
|
|
|
|
|
padding: 40px 40px 0 0;
|
|
|
|
|
min-width: 350px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.logo-box {
|
|
|
|
|
width: 220px;
|
|
|
|
|
margin-bottom: 30px;
|
|
|
|
|
align-self: flex-end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.logo-img {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.summary {
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
color: #222;
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-width: 350px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.summary-title {
|
|
|
|
|
margin-bottom: 30px;
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.income {
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.highlight {
|
|
|
|
|
color: #1976d2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.rank-title {
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
color: #1976d2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.rank-list {
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
line-height: 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1200px) {
|
|
|
|
|
.rank-page {
|
|
|
|
|
min-width: 900px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bar-chart {
|
|
|
|
|
height: 350px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-col {
|
|
|
|
|
padding: 20px 10px 0 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|