Vue3+Element+Echarts 绘制统计图表
近期有需求要按照小时、月份、季度、年份做数据统计柱状图和折线图
echarts开发文档:
https://echarts.apache.org/handbook/zh/get-started/
首先需要引入echarts.js
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.2/dist/echarts.min.js">
</script>
效果图:
柱状图js部分代码:
appConfig.components['views/components/BarHeapChart'] = Vue.defineComponent({
// 在 JavaScript 中是 camelCase 的
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '500px'
},
xAxisData: {
type: Array,
default: () => {
return ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
}
},
seriesData: {
type: Array,
default: () => {
return [{
type: 'bar',
smooth: true,
data: [820, 932, 901, 934, 1290, 1330, 1320],
}]
}
}
},
watch: {
xAxisData: {
deep: true,
handler(val) {
this.xAxisData = val
}
},
seriesData: {
deep: true,
handler(val) {
this.seriesData = val
this.disposeChart()
this.initChart()
}
}
},
data: function() {
return {
chart: null
}
},
mounted: function() {
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
this.disposeChart()
},
computed: {
},
methods: {
disposeChart() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
initChart() {
this.chart = echarts.init(this.$el, 'roma')
this.drawChart()
},
drawChart() {
this.chart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
left: 'center'
},
toolbox: {
feature: {
saveAsImage: {}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
data: this.xAxisData
}],
yAxis: [{
type: 'value'
}],
series: this.seriesData
})
}
},
template: `
<div :class="className" :style="{minHeight:height,width:width}"/>
`
})
折线图js部分代码:
appConfig.components['views/components/LineHeapChart'] = Vue.defineComponent({
// 在 JavaScript 中是 camelCase 的
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '500px'
},
xAxisData: {
type: Array,
default: () => {
return ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
}
},
seriesData: {
type: Array,
default: () => {
return [{
type: 'line',
smooth: true,
data: [820, 932, 901, 934, 1290, 1330, 1320],
}]
}
}
},
watch: {
xAxisData: {
deep: true,
handler(val) {
this.xAxisData = val
}
},
seriesData: {
deep: true,
handler(val) {
this.seriesData = val
this.disposeChart()
this.initChart()
}
}
},
data: function() {
return {
chart: null
}
},
mounted: function() {
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
this.disposeChart()
},
computed: {
},
methods: {
disposeChart() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
initChart() {
this.chart = echarts.init(this.$el, 'roma')
this.drawChart()
},
drawChart() {
this.chart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
left: 'center'
},
toolbox: {
feature: {
saveAsImage: {}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
data: this.xAxisData
}],
yAxis: [{
type: 'value'
}],
series: this.seriesData
})
}
},
template: `
<div :class="className" :style="{minHeight:height,width:width}"/>
`
})
前端渲染代码:
(function(){
const importComponents = {
'views/components/BarHeapChart':'BarHeapChart',
'views/components/LineHeapChart':'LineHeapChart',
};
appConfig.components['views/index'] = autoLoadjs(Object.keys(importComponents)).then(function(){
const components = {}
Object.keys(importComponents).map(function(key){
components[importComponents[key]] = appConfig.components[key]
})
return Vue.defineComponent({
components: components,
data:function() {
return {
tableData: [],
listQuery:{
search_date:'',
date_mode:'day'
},
}
},
mounted:function() {
this.initData()
},
methods:{
initData:function(){
const that = this
//开启table加载效果
this.$network("/admin/index/echarts", this.listQuery,{
completeEvent:function(res){ }
}).then(function(res){
var data = res.data || {}
that.tableData = data
})
},
},
template : `
<el-row :gutter="20">
<el-col :span="21">
<el-form-item name="activeState">
<el-radio-group v-model="listQuery.date_mode" fill="#5a8bff" @change="initData(true)">
<el-radio-button label="day">按天筛选</el-radio-button>
<el-radio-button label="week">按周筛选</el-radio-button>
<el-radio-button label="month">按月筛选</el-radio-button>
<el-radio-button label="month60">按季度筛选</el-radio-button>
<el-radio-button label="year">按年筛选</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="21">
<el-form-item name="activeState">
<el-date-picker
type="daterange"
value-format="YYYY-MM-DD"
v-model="listQuery.search_date"
@change="initData(true)"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-card class="box-card">
<h3>订单金额</h3>
<div>
<i class="el-icon-s-shop" style="color: purple"></i>
<span>{{tableData.total_money}}</span>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card class="box-card">
<h3>订单数量</h3>
<div>
<i class="el-icon-user-solid" style="color: green"></i>
<span>{{tableData.total_order}}</span>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card class="box-card">
<h3>访客</h3>
<div>
<i class="el-icon-s-flag" style="color: red"></i>
<span>{{tableData.user}}</span>
</div>
</el-card>
</el-col>
</el-row>
<BarHeapChart ref="BarHeapChart" :xAxisData="tableData.x_axis_data" :seriesData="tableData.series_data"/>
<LineHeapChart ref="LineHeapChart" :xAxisData="tableData.x_axis_data" :seriesData="tableData.series_data" />
`
})
})
})()
最后调PHP后端接口获取最新数据:
//获取统计信息
public function echarts()
{
$input_data = input();
list($x_axis_data1, $series_data1) = LocationUserModel::echarts($input_data);
$fnc = function($name,$data){
return [
"name"=> $name,
"type"=> 'line',
"symbolSize"=> 12,
"data"=> $data
];
};
return $this->_resData(1,'获取成功',[
'x_axis_data'=>$x_axis_data1,
'series_data'=>[$fnc('订单数量',$series_data1)],
'total_order'=>LocationUserModel::where('state','<>',2)->count(),
'total_money'=>LocationUserModel::where('is_pay',1)->where('state','<>',2)->count(),
'user'=>UserModel::count()
]);
}
LocationUserModel模型方法:
//列表统计
public static function echarts(array $php_input)
{
$date_mode = $php_input['date_mode'] ?? 'day';
$where = [];
$group = 'op_time';
$field = ' count(*) as count_num ';
if ($date_mode == 'day') { //按小时计算
$where[] = ['create_time', '>=', strtotime(date('Y-m-d'))];
$field .= ' ,FROM_UNIXTIME(create_time,\'%H\') as op_time';
} elseif ($date_mode == 'week') {
$where[] = ['create_time', '>=', strtotime(date('Y-m-d')) - 7 * 84600];
$field .= ' ,FROM_UNIXTIME(create_time,\'%Y-%m-%d\') as op_time';
} elseif ($date_mode == 'month') {
$field .= ' ,FROM_UNIXTIME(create_time,\'%Y-%m-%d\') as op_time';
$where[] = ['create_time', '>=', strtotime(date('Y-m-d')) - 30 * 84600];
} elseif ($date_mode == 'month60') {
$field .= ' ,FROM_UNIXTIME(create_time,\'%Y-%m-%d\') as op_time';
$where[] = ['create_time', '>=', strtotime(date('Y-m-d')) - 60 * 84600];
} elseif ($date_mode == 'year') {
$field .= ' ,FROM_UNIXTIME(create_time,\'%Y-%m-%d\') as op_time';
$where[] = ['create_time', '>=', strtotime(date('Y-m-d')) - 365 * 84600];
}
$date_list = get_op_time($date_mode);
$list = [];
foreach ($date_list as $vo) {
$list[$vo] = [
'name' => $vo,
'value' => 0
];
}
Db::table('location_user')->field($field)->where($where)
->group($group)->select()->each(function ($item) use (&$list, $date_list) {
$key = $item['op_time'];
$list[$key]['value'] = $item['count_num'];
});
return [array_column($list, 'name'), array_column($list, 'value')];
// self::field($field)->where($where)->gourp($group)->select();
}
评论