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>
相关推荐
秋雨凉人心5 小时前
简单发布一个npm包
前端·javascript·webpack·npm·node.js
LCG元7 小时前
Vue.js组件开发-使用vue-pdf显示PDF
vue.js
哥谭居民00017 小时前
将一个组件的propName属性与父组件中的variable变量进行双向绑定的vue3(组件传值)
javascript·vue.js·typescript·npm·node.js·css3
烟波人长安吖~8 小时前
【目标跟踪+人流计数+人流热图(Web界面)】基于YOLOV11+Vue+SpringBoot+Flask+MySQL
vue.js·pytorch·spring boot·深度学习·yolo·目标跟踪
踢足球的,程序猿8 小时前
Android native+html5的混合开发
javascript
前端没钱8 小时前
探索 ES6 基础:开启 JavaScript 新篇章
前端·javascript·es6
PleaSure乐事9 小时前
使用Vue的props进行组件传递校验时出现 Extraneous non-props attributes的解决方案
vue.js
一条不想当淡水鱼的咸鱼9 小时前
taro中实现带有途径点的路径规划
javascript·react.js·taro
土豆炒马铃薯。9 小时前
【Vue】前端使用node.js对数据库直接进行CRUD操作
前端·javascript·vue.js·node.js·html5
温轻舟10 小时前
前端开发 -- 自动回复机器人【附完整源码】
前端·javascript·css·机器人·html·交互·温轻舟