vue柱状图+table表格

javascript 复制代码
<!--
  @Author: jingtong
  @Description: 培训统计
  @Date: 2023-03-13 14:59:22
 * @LastEditTime: 2023-04-19 10:25:38
-->
<template>
	<el-container class="train-plan-index">
		<el-header>
			<el-row>
				<el-col :span="24">
					<el-form :inline="true" :model="form" :rules="rules" class="demo-form-inline" ref="form">
						<el-form-item label="统计类型" prop="timeSpan">
							<el-select v-model="form.timeSpan">
								<el-option v-for="item in timeSpanList" :key="item.value" :label="item.label" :value="item.value"></el-option>
							</el-select>
						</el-form-item>
						<span v-if="form.timeSpan == 'year'" class="year-span">
							<el-form-item label="时间" prop="yearStart" style="width:50px">
								<el-date-picker v-model="form.yearStart" type="year" placeholder="选择年" value-format="yyyy" :clearable="false"> </el-date-picker>
							</el-form-item>
							<span style="margin-right: 10px">-</span>
							<el-form-item prop="yearEnd">
								<el-date-picker v-model="form.yearEnd" type="year" placeholder="选择年" value-format="yyyy" :clearable="false"> </el-date-picker>
							</el-form-item>
						</span>
						<el-form-item label="时间" prop="time" v-if="form.timeSpan == 'month'">
							<el-date-picker v-model="form.time" type="monthrange" range-separator="---" start-placeholder="开始时间" end-placeholder="结束时间" value-format="yyyy-MM" :clearable="false">
							</el-date-picker>
						</el-form-item>

						<!--<el-form-item label="时间" prop="time">
							<el-date-picker v-model="form.time" format="yyyy-MM-dd" value-format="yyyy-MM-dd HH:mm:ss"
								type="datetimerange" range-separator="---" start-placeholder="开始时间" end-placeholder="结束时间">
							</el-date-picker>
						</el-form-item>-->

						<el-form-item>
							<el-button type="primary" @click="onQuery">查询</el-button>
							<el-button  @click="resetForm">重置</el-button>
						</el-form-item>
					</el-form>
				</el-col>
			</el-row>
		</el-header>

		<el-main class="stat-main">
			<div class="chart-div">
				<!-- 培训次数、培训时长 -->
				<div class="stat-text-div">
					<el-form label-width="125px" class="demo-form">
						<el-row>
							<el-col :span="8">
								<el-form-item label="总培训次数">
									<el-input v-model="sumTrainCount" :disabled="true"></el-input>
								</el-form-item>
							</el-col>

							<el-col :span="8" :disable="true">
								<el-form-item label="总培训时长">
									<el-input v-model="sumTrainTime" :disabled="true"></el-input>
								</el-form-item>
							</el-col>
						</el-row>
					</el-form>
				</div>
				<div id="trainStatCharts" class="stat-chart-div"></div>
			</div>
			<div class="table-div">
				<el-table :data="tableData" border style="width: 100%" stripe height="calc(100% - 40px)" :default-sort="{ prop: 'saveTime', order: 'descending' }">
					<el-table-column type="index" label="序号" align="center" width="60" :index="(index) => this.$common.pageIndexMethod(index, form.pageIndex, form.pageSize)"> </el-table-column>
					<el-table-column prop="trainId" label="培训编号" align="center" width="150"> </el-table-column>
					<el-table-column prop="project" label="培训项目" align="center" width="150"> </el-table-column>
					<el-table-column prop="applyCompany" label="申请单位" align="center" width="100"> </el-table-column>
					<el-table-column prop="trainNumber" label="培训人数" align="center" width="80"> </el-table-column>
					<el-table-column prop="startTime" label="培训开始时间" align="center" :formatter="onRenderTime"> </el-table-column>
					<el-table-column prop="endTime" label="培训结束时间" align="center" :formatter="onRenderTime"> </el-table-column>
					<el-table-column prop="isCert" label="是否为机构取证类" align="center" width="50"> </el-table-column>

					<!--<el-table-column label="操作" align="center" width="240">
					<template slot-scope="scope">
						<el-button type="primary" @click="updateRowData(scope.row)">编辑</el-button>
						<el-button type="primary" @click="removeRowData(scope.row.uuid)">删除</el-button>
					</template>
				</el-table-column>-->
				</el-table>
				<Pagination :total="total" :page.sync="form.pageIndex" :limit.sync="form.pageSize" @pagination="onQuery" />
			</div>
		</el-main>
	</el-container>
</template>

<script>
import Pagination from '@/components/Pagination';

import { pageTrainProjByTime, listTrainCountAndTimesByTime } from '@/api/eams/trainStat.js';

export default {
	name: 'trainStat',
	components: { Pagination },
	data() {
		return {
			timeSpanList: [
				{
					value: 'year',
					label: '年',
				},
				{
					value: 'month',
					label: '月',
				},
			],
			form: {
				timeSpan: 'month',
				time: [],
				yearStart: this.$common.parseTime(new Date(), '{y}'),
				yearEnd: this.$common.parseTime(new Date(), '{y}'),

				sortField: '', //排序字段
				sortOrder: '', //排序方向
				pageIndex: 0, //页数
				pageSize: 20, //每页数量
			},
			total: 0, //总数
			tableData: [],
			sumTrainTime: 0,
			sumTrainCount: 0,

			myChart: null,
			xData: [], //横轴
			trainNumChart: [], //培训次数
			trainTimeChart: [],

			//   校验
			rules: {
				startTime: [{ required: true, message: '请选择时间', trigger: 'change' }],
				endTime: [{ required: true, message: '请选择时间', trigger: 'change' }],
				yearStart: [{ required: true, message: '请选择开始年份', trigger: 'change' }],
				yearEnd: [{ required: true, message: '请选择结束年份', trigger: 'change' }],
			},
		};
	},
	mounted() {
		var startDefault = new Date().getFullYear() + '-' + '01';
		var endDefault = this.$common.parseTime(new Date(), '{y}-{m}');
		this.form.time = [startDefault, endDefault];

		//查询
		this.myChart = this.$echarts.init(document.getElementById('trainStatCharts'));
		let self = this;
		this.myChart.on('click', function (params) {
			let param = self.getQueryCondition();
			param.startTime = params.name;
			param.endTime = params.name;
			self.pageTrainPlan(param);
		});
		this.onQuery();
	},

	methods: {
		// 查询
		onQuery() {
			this.$refs.form.validate((valid) => {
				if (valid) {
					// if (param.time) {
					// 	param.startTime = this.$common.parseTime(param.time[0], '{y}-{m}-{d}') + ' 00:00:00';
					// 	param.endTime = this.$common.parseTime(param.time[1], '{y}-{m}-{d}') + ' 23:59:59';
					// }
					const param = this.getQueryCondition();
					this.pageTrainPlan(param);

					//加载统计培训次数
					listTrainCountAndTimesByTime(param).then((res) => {
						var resData = res.data.data;
						this.sumTrainCount = 0;
						this.sumTrainTime = 0;
						this.xData = resData.map((item) => {
							return item.time;
						});
						this.trainNumChart = resData.map((item) => {
							return item.trainCount;
						});
						this.trainNumChart.map((item) => (this.sumTrainCount = this.sumTrainCount + item));
						this.trainTimeChart = resData.map((item) => {
							return item.trainTime;
						});
						this.trainTimeChart.map((item) => (this.sumTrainTime = this.sumTrainTime + item));
						this.onLoadChart();
					});
				}
			});
		},

		pageTrainPlan(param) {
			pageTrainProjByTime(param).then((res) => {
				this.tableData = res.data.data ? res.data.data.data : [];
				this.total = res.data.data.total;
			});
		},

		//查询条件
		getQueryCondition() {
			var param = { ...this.form };
			if (param.timeSpan == 'year') {
				param.startTime = param.yearStart;
				param.endTime = param.yearEnd;
			} else {
				param.startTime = param.time[0];
				param.endTime = param.time[1];
			}

			return param;
		},

		// 重置
		resetForm() {
			this.$refs.form.resetFields();
			this.onQuery();
		},

		//表格排序
		onSortChanged(column) {
			var order = column.order;
			this.form.sortField = column.prop;
			this.form.sortOrder = order
				? order === 'descending' // 第一个问号:order不为空
					? 'desc'
					: 'asc'
				: '';
			this.onQuery();
		},
		//表格渲染时间
		onRenderTime(row, column, cellValue) {
			return this.$common.parseTime(cellValue, '{y}-{m}-{d}');
		},

		//双击表格行
		onTableDblclick(row) {
			this.htmlFlag = 'look';
			this.selectedRow = row;
			this.dialogFormVisible = true;
		},

		//加载柱状图
		onLoadChart() {
			//柱状图
			//柱状图
			var option = {
				tooltip: {
					trigger: 'axis',
				},
				grid: {
					left: '3%',
					right: '5%',
				},
				legend: {
					top: 10,
					data: ['培训次数', '培训时长'],
					textStyle: {
						//color: '#efefef',
					},
				},
				toolbox: {
					show: false,
					feature: {
						dataView: { show: false, readOnly: false },
						magicType: { show: true, type: ['line', 'bar'] },
						restore: { show: false },
						saveAsImage: { show: false },
					},
				},
				calculable: true,
				color: ['#59CE98', '#40B3C4', '#5E98EF', '#5640C4', '#BAB25E'],
				xAxis: [
					{
						type: 'category',
						// prettier-ignore
						data: this.xData,
						axisLabel: {
							//color: '#efefef',
							fontSize: '15px',
						},
					},
				],
				yAxis: [
					{
						type: 'value',
						axisLabel: {
							//color: '#efefef',
							fontSize: '15px',
						},
					},
				],
				series: [
					{
						name: '培训次数',
						type: 'bar',
						data: this.trainNumChart,
						label: {
							show: true,
							position: 'top',
							//color: '#efefef',
							fontSize: 14,
						},
					},
					{
						name: '培训时长',
						type: 'bar',
						data: this.trainTimeChart,
						label: {
							show: true,
							position: 'top',
							//color: '#efefef',
							fontSize: 14,
						},
					},
				],
			};

			this.myChart.setOption(option);
		},
	},
};
</script>

<style scoped>
.train-plan-index .el-header {
	height: auto !important;
}

.upload-plan {
	display: inline-block;
	margin: 0px 10px;
}

.stat-main {
	display: flex;
	flex-direction: row;
}

.chart-div {
	width: 50%;
	height: 100%;
}

.stat-chart-div {
	width: 100%;
	height: calc(100% - 50px);
}

.stat-text-div {
	width: 100%;
	height: 50px;
}

.table-div {
	width: calc(50% - 10px);
	height: 100%;
	margin-left: 10px;
}

.year-span {
	display: inline-block;
	line-height: 32px;
}

.year-span >>> .el-date-editor.el-input {
	width: 100px;
}
</style>
相关推荐
王哲晓1 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
理想不理想v1 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云1 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry2 小时前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子2 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
ZL不懂前端3 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x3 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
我血条子呢3 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
半开半落3 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt