将数据统计成按单周,双周,还有按月统计数据代码逻辑,主要看日期。具体功能如下图展示。
单周
双周
按月
后端获取到的数据是一个start Time:2024-05-21 10:30:00的列表,具体数据需要自己修改操作。修改getlist接口中的数据。
具体实现如下
<template>
<div class='line-chart'>
<div class="title-search">
<div class="title">次数</div>
</div>
<div class="tooltip">
<div class="item">
<div class="finished-total-line"></div>
<div class="text">累计数</div>
</div>
<div class="item">
<div class="finished-line"></div>
<div class="text">当期数</div>
</div>
<div class="box" style="width:55%"></div>
<!-- <div class="timeSelect" style="width:10%">
<el-select v-model="value" placeholder="请选择时间" @change="changeSelect">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</div > -->
<div>
<el-radio-group v-model="value" style="margin-bottom: 30px; " @change="changeSelect" >
<el-radio-button label="1">单周</el-radio-button>
<el-radio-button label="2">双周</el-radio-button>
<el-radio-button label="3">月</el-radio-button>
</el-radio-group>
</div>
</div>
<div class="chart">
<div id="myLineChart"></div>
</div>
</div>
</template>
<script>
import *as echarts from 'echarts'
import moment from 'moment'
import {getProjectAppointmentList, getCompanyAppointmentList} from '@/api/'
export default {
name: "LineChart",
props: {
userId: String,
projectId: String,
companyId: String,
},
data() {
return {
value: '2',
sortList: [],
listEcharts: [],
object: [],
option: {
color: ['#5383FF', '#E8B957'],
tooltip: {
trigger: 'axis',
},
grid: {
left: '5%',
right: '5%',
bottom: '10%',
top: '10%',
},
xAxis: {
type: 'category',
boundaryGap: false,
axisTick: {
interval: 'auto',
},
axisLabel: {
interval: 'auto',
rotate: 0,
},
data: []
},
yAxis: [
{
type: 'value',
name: '当期约谈次数',
min: 0,
max: 10,
position: 'left',
show: false,
},
{
type: 'value',
name: '累计约谈次数',
min: 0,
max: 100,
position: 'right',
show: false,
}
],
series: [
{
label: {
show: true,
position: 'top',
color: '#5383FF',
fontSize: 12,
fontWeight: 700,
formatter: '{c}',
},
name: '当期会谈数',
type: 'line',
data: [],
smooth: true,
symbol: 'circle',
showSymbol: true,
yAxisIndex: 0,
},
{
label: {
show: true,
position: 'top',
color: '#E8B957',
fontSize: 12,
fontWeight: 700,
distance: 10,
formatter: '{c}',
},
name: '累计会谈数',
type: 'line',
data: [],
smooth: false,
symbol: 'circle',
showSymbol: true,
yAxisIndex: 1,
},
]
}
}
},
mounted() {
this.getList()
this.myChat = echarts.init(document.getElementById('myLineChart'))
console.log(document.getElementById('myLineChart').clientWidth)
window.addEventListener('resize', this.resizeChart)
},
beforeDestroy() {
if (!this.myChat) {
return
}
window.removeEventListener('resize', this.resizeChart)
this.myChat.dispose()
this.myChat = null
},
watch: {
sortList() {
this.changeSelect()
}
},
methods: {
resizeChart: _.debounce(function () {
console.log('chart resize!')
if (this.myChat != null) {
this.myChat.resize()
}
}, 100),
getList() {
//调用接口
getProjectAppointmentList().then(res => {
this.object = res
const list = this.object
//获取时间排序列表
this.sortList = list.sort(function (a, b) {
return moment(a.appointmentInfo.startTime).isBefore(moment(b.appointmentInfo.startTime)) ? -1 : 1
})
})
},
renderChart() {
console.log('renderChart')
this.$nextTick(() => { //使用nextTick为了保证dom元素都已经渲染完毕
this.myChat.setOption(this.option)
});
this.myChat.resize()
},
/**
* @description: 计算两个日期相差多少个月
* @param {String} startTime 开始时间
* @param {String} endTime 结束时间
* @return: 相差的月数
*/
getDistanceMonth(startTime, endTime) {
startTime = new Date(startTime)
endTime = new Date(endTime)
var dateToMonth = 0
var startDate = startTime.getDate() + startTime.getHours() / 24 + startTime.getMinutes() / 24 / 60;
var endDate = endTime.getDate() + endTime.getHours() / 24 + endTime.getMinutes() / 24 / 60;
if (endDate >= startDate) {
dateToMonth = 0
} else {
dateToMonth = -1
}
let yearToMonth = (endTime.getYear() - startTime.getYear()) * 12
let monthToMonth = endTime.getMonth() - startTime.getMonth()
return yearToMonth + monthToMonth + dateToMonth
},
getMonthList() {
// 获取最早时间日期
var minDate = this.sortList[0].appointmentInfo.startTime
// 月份间隔列表
var TimeList = []
//最小月份
minDate = minDate.slice(0, 10)
let Nowdate = new Date()
let nowMonth = Nowdate.getMonth() // 当前月
let nowYear = Nowdate.getFullYear() // 当前年
let monthEndDate = new Date(nowYear, nowMonth + 1, 0)// 当前月的结束时间
// 当前月前一个月的结束时间
this.monthEnd = this.$dayjs(monthEndDate).format('YYYY-MM-DD')
//月份数
let monthes = this.getDistanceMonth(minDate, this.monthEnd)
TimeList.push({ time: this.monthEnd, count: 0, Cumulative: 0 })
for (let i = 0; i < monthes; i++) {
monthEndDate = new Date(nowYear, nowMonth - i, 0)
this.monthEndDate = this.$dayjs(monthEndDate).format('YYYY-MM-DD')
TimeList.push({ time: this.monthEndDate, count: 0, Cumulative: 0 })
}
TimeList = TimeList.reverse()
for (let i = 0, j = 0; i < TimeList.length, j < this.sortList.length; j++) {
//如果日期超过当前结点 控制时间节点到下一坐标
while (moment(this.sortList[j].appointmentInfo.startTime).isAfter(moment(TimeList[i].time + " 24:00:00"))) {
i++
if (i >= TimeList.length) {
break
}
}
if( i >= TimeList.length){
break
}
if (moment(this.sortList[j].appointmentInfo.startTime).isBefore(moment(TimeList[i].time + " 24:00:00"))) {
TimeList[i].count = parseInt(TimeList[i].count) + 1
}
}
TimeList = this.CountList(TimeList)
return TimeList
},
//日期转字符串格式
DateToStr(date) {
var year = date.getFullYear();//年
var month = date.getMonth();//月
var day = date.getDate();//日
var hours = date.getHours();//时
var min = date.getMinutes();//分
var second = date.getSeconds();//秒
return year + "-" +
((month + 1) > 9 ? (month + 1) : "0" + (month + 1)) + "-" +
(day > 9 ? day : ("0" + day)) + " " +
(hours > 9 ? hours : ("0" + hours)) + ":" +
(min > 9 ? min : ("0" + min)) + ":" +
(second > 9 ? second : ("0" + second));
},
//计算两个日期所差周数
diffInWeeks(date1, date2) {
// 计算日期之间的毫秒数差值
const diffMilliseconds = Math.abs(date2 - date1);
// 毫秒数转换为周数
const millisecondsInWeek = 1000 * 60 * 60 * 24 * 7;
const weeks = diffMilliseconds / millisecondsInWeek;
// 返回结果
return Math.floor(weeks);
},
//根据日期找到该日期所在周周日
getNextSunday(dateString) {
const date = new Date(dateString);
const dayOfWeek = date.getDay();
// 如果当前日期是星期日(0),则返回当前日期
if (dayOfWeek === 0) {
return date;
} else {
// 找到下一个周日
const nextSunday = new Date(date);
nextSunday.setDate(date.getDate() + (7 - dayOfWeek));
return nextSunday;
}
},
getWeekList(week) {
var TimeList = []
var minDate = this.sortList[0].appointmentInfo.startTime
var minDateWeek = this.getNextSunday(minDate)
minDateWeek = this.DateToStr(minDateWeek).slice(0, 10)
var now = new Date();
var nowTime = now.getTime();
var day = now.getDay();
var oneDayTime = 24 * 60 * 60 * 1000;
//显示周日
var lastSundayTime = nowTime + (7 - day) * oneDayTime;
var lastTime = new Date(lastSundayTime)
var strLastTime = this.DateToStr(lastTime).slice(0, 10)
TimeList.push({ time: strLastTime, count: 0, Cumulative: 0 })
//计算相差周数
var diffWeeks = this.diffInWeeks(new Date(minDateWeek), new Date(strLastTime))
if (week == 1) {
for (let i = 1; i <= diffWeeks; i++) {
var tmp = moment(strLastTime).add(-7 * i, 'd').format("YYYY-MM-DD")
TimeList.push({ time: tmp, count: 0, Cumulative: 0 })
}
} else if (week == 2) {
for (let i = 1; i <= diffWeeks / 2; i++) {
var tmp = moment(strLastTime).add(-14 * i, 'd').format("YYYY-MM-DD")
TimeList.push({ time: tmp, count: 0, Cumulative: 0 })
}
}
TimeList = TimeList.reverse()
//TimeList时间节点列表 sortList排序后列表
for (let i = 0, j = 0; j < this.sortList.length; j++) {
//如果日期超过当前结点 控制时间节点到下一坐标
while (moment(this.sortList[j].appointmentInfo.startTime).isAfter(moment(TimeList[i].time + " 24:00:00"))) {
i++
if (i >= TimeList.length) {
break
}
}
if( i >= TimeList.length){
break
}
if (moment(this.sortList[j].appointmentInfo.startTime).isBefore(moment(TimeList[i].time + " 24:00:00"))) {
TimeList[i].count = parseInt(TimeList[i].count) + 1
}
}
TimeList = this.CountList(TimeList)
return TimeList
},
//计算每日数量及累计
CountList(echlist) {
var cumulativeCount = 0
for (let i = 0; i < echlist.length; i++) {
cumulativeCount += parseInt(echlist[i].count)
echlist[i].Cumulative += cumulativeCount
}
return echlist;
},
changeSelect() {
this.option.xAxis.data = []
this.option.series[0].data = []
this.option.series[1].data = []
var echartsList = []
//一周
if (this.value == 1) {
echartsList = this.getWeekList(1)
for (let i = 0; i < echartsList.length; i++) {
this.option.xAxis.data.push(echartsList[i].time)
this.option.series[0].data.push(parseInt(echartsList[i].count))
this.option.series[1].data.push(parseInt(echartsList[i].Cumulative))
}
//两周
} else if (this.value == 2) {
echartsList = this.getWeekList(2)
for (let i = 0; i < echartsList.length; i++) {
this.option.xAxis.data.push(echartsList[i].time)
this.option.series[0].data.push(parseInt(echartsList[i].count))
this.option.series[1].data.push(parseInt(echartsList[i].Cumulative))
}
} else if (this.value == 3) {
echartsList = this.getMonthList()
for (let i = 0; i < echartsList.length; i++) {
this.option.xAxis.data.push(echartsList[i].time)
this.option.series[0].data.push(parseInt(echartsList[i].count))
this.option.series[1].data.push(parseInt(echartsList[i].Cumulative))
}
}
this.option.yAxis[1].max = Math.floor(Math.max(...this.option.series[1].data) * 2.2)
this.option.yAxis[0].max = Math.floor(Math.max(...this.option.series[0].data) * 1)
this.renderChart()
}
},
}
</script>
<style lang='scss' scoped>
::v-deep.el-radio-button{
.el-radio-button__inner {
width: 80px;
line-height: 1.5;
padding: 12px 15px;
font-size: 13px;
// border-radius: 7px;
}
.el-radio-button__inner:hover {
color: #E8B957;
}
.el-radio-button__orig-radio:checked+.el-radio-button__inner {
color: #E8B957;
background-color: white;
border-color: #E8B957;
box-shadow: 0px 0px 2px 2px #E8B957 !important;
z-index:1;
}
}
.line-chart {
box-sizing: border-box;
width: 100%;
padding: 32px;
border-radius: 16px;
background: #FFF;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
.frequency {
display: flex;
align-items: center;
justify-content: start;
margin-top: 32px;
.item {
margin-right: 48px;
text-align: center;
}
.num {
color: rgb(0 0 0 / 90%);
font-family: DIN Alternate;
font-size: 32px;
font-weight: 700;
}
.label {
margin-top: 8px;
color: rgb(0 0 0 / 50%);
font-size: 12px;
}
}
.tooltip {
display: flex;
align-items: center;
justify-content: start;
padding: 16px 0;
gap: 16px;
.timeSelect {
position: relative;
display: flex;
margin-right: 8%;
}
.item {
display: flex;
align-items: center;
.finished-total-line {
width: 15px;
height: 2px;
border-radius: 2px;
background-color: #E8B957;
}
.finished-line {
width: 15px;
height: 2px;
border-radius: 2px;
background-color: #5383FF;
}
.healthy-line {
width: 15px;
height: 2px;
border-radius: 2px;
background-color: #0E7319;
}
.text {
margin-left: 4px;
color: rgb(0 0 0 / 50%);
font-size: 12px;
}
}
}
.chart {
height: 400px;
width: 100%;
#myLineChart {
width: 100%;
height: 400px;
}
}
}
</style>
<style lang="scss">
.line-chart {
.title-search .search {
.el-date-editor {
width: 256px;
}
}
}
</style>
```
```