| | |
| | | <el-form :model="queryParam" ref="queryForm" :inline="true" style="display: flex"> |
| | | <el-form-item label="试卷:"> |
| | | <el-select v-model="queryParam.id" filterable placeholder="试卷"> |
| | | <el-option v-for="item in examPaperList" :key="item.id" :value="item.id" :label="item.name" @change="getType(item.type)" /> |
| | | <el-option v-for="item in examPaperList" :key="item.id" :value="item.id" :label="item.name" |
| | | @change="getType(item.paperType)" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | |
| | | </el-form> |
| | | <el-row :gutter="20"> |
| | | <el-col :xl="12" class="echarts-row"> |
| | | <el-col :xl="24" class="echarts-row"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="6"> |
| | | <el-card> |
| | | <div class="card-chart-container"> |
| | | <div id="ageChart" ref="ageChart" class="chart-style" v-loading="chartLoading1" /> |
| | | <div class="data-item"> |
| | | <div class="data-icon" :style="{ 'background-color': iconList[0].color }"> |
| | | <i class="el-icon-tickets"></i> |
| | | </div> |
| | | <div class="data-info"> |
| | | <div class="data-label"> |
| | | 总考试次数 |
| | | </div> |
| | | <div class="data-num"> |
| | | {{ totalInfo.examTotal }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | </el-col> |
| | | |
| | | <el-col :span="6"> |
| | | <el-card> |
| | | <div class="data-item"> |
| | | <div class="data-icon" :style="{ 'background-color': iconList[1].color }"> |
| | | <i class="el-icon-s-claim"></i> |
| | | </div> |
| | | <div class="data-info"> |
| | | <div class="data-label"> |
| | | 参考人数 |
| | | </div> |
| | | <div class="data-num"> |
| | | {{ totalInfo.factPeopleTotal }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | </el-col> |
| | | |
| | | <el-col :span="6"> |
| | | <el-card> |
| | | <div class="data-item"> |
| | | <div class="data-icon" :style="{ 'background-color': iconList[2].color }"> |
| | | <i class="el-icon-edit"></i> |
| | | </div> |
| | | <div class="data-info"> |
| | | <div class="data-label"> |
| | | 平均分 |
| | | </div> |
| | | <div class="data-num"> |
| | | {{ totalInfo.averageScore }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | </el-col> |
| | | |
| | | <el-col :span="6"> |
| | | <el-card> |
| | | <div class="data-item"> |
| | | <div class="data-icon" :style="{ 'background-color': iconList[3].color }"> |
| | | <i class="el-icon-s-data"></i> |
| | | </div> |
| | | <div class="data-info"> |
| | | <div class="data-label"> |
| | | 参考人数百分比 |
| | | </div> |
| | | <div class="data-num"> |
| | | {{ totalInfo.referencePercentage }}% |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | |
| | | <el-col :xl="12" class="echarts-row"> |
| | | <el-card> |
| | | <div class="card-chart-container"> |
| | | <div id="scoreChart" ref="scoreChart" class="chart-style" v-loading="chartLoading2" /> |
| | | </div> |
| | | </el-card> |
| | | </el-row> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | |
| | | <el-col :xl="24"> |
| | | <el-card> |
| | | <div class="card-chart-container"> |
| | | <div id="peopleChart" ref="peopleChart" class="chart-style" v-loading="chartLoading3" /> |
| | | <div id="peopleChart" ref="peopleChart" class="chart-style" v-loading="chartLoading" /> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | |
| | | import { mapGetters, mapState } from 'vuex'; |
| | | import dashboardApi from '@/api/dashboard'; |
| | | |
| | | const colorList = ['#3498DB', '#E74C3C', '#F1C40F', '#95A5A6', '#8E44AD', '#F39C12', '#D35400']; |
| | | const colorList = ['#3eba45', '#3da7f8', '#ffbe40', '#95A5A6', '#8E44AD', '#F39C12', '#D35400']; |
| | | |
| | | |
| | | const ageLabel = { |
| | | 'age0To19': '0-19岁', |
| | | 'age20To29': '20-29岁', |
| | | 'age30To39': '30-39岁', |
| | | 'age40To49': '40-49岁', |
| | | 'ageOver50': '大于50岁', |
| | | const dataKeyMap = { |
| | | 'factPeopleTotal': '参考人数', |
| | | 'averageScore': '平均分', |
| | | 'referencePercentage': '参考人数百分比', |
| | | }; |
| | | const scoreLabel = { |
| | | 'score0To59': '小于60分', |
| | | 'score60To69': '60-69分', |
| | | 'score70To79': '70-79分', |
| | | 'score80To89': '80-89分', |
| | | 'score90To100': '90-100分' |
| | | }; |
| | | const pieLabel = { |
| | | 'totalAttended': '参与考试', |
| | | 'totalAbsent': '未参与考试' |
| | | }; |
| | | let ageChart = null; |
| | | let scroeChart = null; |
| | | |
| | | let peopleChart = null; |
| | | let observer = null; |
| | | export default { |
| | | data() { |
| | | return { |
| | | examPaperList: [], |
| | | chartLoading1: false, |
| | | chartLoading2: false, |
| | | chartLoading3: false, |
| | | totalInfo: {}, |
| | | dataList: [], |
| | | iconList: [ |
| | | { icon: 'el-icon-tickets', color: '#7868d9' }, |
| | | { icon: 'el-icon-s-claim', color: '#3eba45' }, |
| | | { icon: 'el-icon-edit', color: '#3da7f8' }, |
| | | { icon: 'el-icon-warning', color: '#ffbe40' }, |
| | | { icon: 'el-icon-error', color: '#fe640d' }, |
| | | ], |
| | | chartLoading: false, |
| | | queryParam: { |
| | | id: '', |
| | | type: 1 |
| | |
| | | if (sessionStorage.getItem('deptAdmin') == 1) { |
| | | this.admin = false; |
| | | } |
| | | ageChart = echarts.init(this.$refs.ageChart); |
| | | scroeChart = echarts.init(this.$refs.scoreChart); |
| | | peopleChart = echarts.init(this.$refs.peopleChart); |
| | | dashboardApi.queryCondition().then(res => { |
| | | this.examPaperList = res.response; |
| | | this.queryParam.id = this.examPaperList[0].id |
| | | this.queryParam.type = this.examPaperList[0].paperType |
| | | this.queryParam.id = this.examPaperList[0].id; |
| | | this.queryParam.type = this.examPaperList[0].paperType; |
| | | this.getChartData(); |
| | | this.observe(); |
| | | }); |
| | |
| | | this.getChartData(); |
| | | }, |
| | | getChartData() { |
| | | this.chartLoading1 = true; |
| | | this.chartLoading2 = true; |
| | | this.chartLoading3 = true; |
| | | this.chartLoading = true; |
| | | dashboardApi.data(this.queryParam).then(re => { |
| | | const { age, score, examPeopleNum } = re.response; |
| | | |
| | | const ageOption = this.barOption('年龄段统计', age, ageLabel); |
| | | const scoreOption = this.barOption('分数段统计', score, scoreLabel); |
| | | const peopleOption = this.pieOption('考试人数', examPeopleNum, pieLabel); |
| | | |
| | | ageChart.setOption(ageOption, true); |
| | | scroeChart.setOption(scoreOption, true); |
| | | peopleChart.setOption(peopleOption, true); |
| | | |
| | | this.chartLoading1 = false; |
| | | this.chartLoading2 = false; |
| | | this.chartLoading3 = false; |
| | | const { data, total } = re.response; |
| | | this.totalInfo = total; |
| | | this.dataList = data; |
| | | this.barOption(this.dataList); |
| | | this.chartLoading = false; |
| | | }); |
| | | }, |
| | | barOption(title, data, labelList) { |
| | | const dataKeys = data.map(item => labelList[Object.keys(item)[0]]); |
| | | const dataValues = data.map(item => Object.values(item)[0]); |
| | | return { |
| | | |
| | | barOption(dataList) { |
| | | const nameList = dataList.map((item) => item.name); |
| | | const options = { |
| | | title: { |
| | | text: title, |
| | | text: '部门统计', |
| | | x: 'left' |
| | | }, |
| | | legend: { |
| | | orient: 'horizontal', |
| | | }, |
| | | color: colorList, |
| | | tooltip: { |
| | |
| | | grid: { |
| | | left: 10, |
| | | right: 10, |
| | | bottom: 20, |
| | | bottom: 10, |
| | | top: 40, |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: dataKeys |
| | | data: nameList, |
| | | axisLabel: { |
| | | show: true, |
| | | rotate: 35, |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: 'value' |
| | | }, |
| | | series: [ |
| | | { |
| | | series: Object.keys(dataKeyMap).map(key => { |
| | | console.log(key); |
| | | return this.filterData(dataList, key); |
| | | }) |
| | | }; |
| | | peopleChart.setOption(options, true); |
| | | }, |
| | | |
| | | filterData(data, key) { |
| | | const mapData = data.map(item => item[key]); |
| | | return { |
| | | name: dataKeyMap[key], |
| | | type: 'bar', |
| | | label: { |
| | | show: true, |
| | | fontSize: 16 |
| | | }, |
| | | barMaxWidth: '40%', |
| | | data: dataValues, |
| | | } |
| | | ] |
| | | |
| | | data: mapData |
| | | }; |
| | | }, |
| | | |
| | | }, |
| | | pieOption(title, data, labelList) { |
| | | const pieData = data.map(item => { |
| | | return { |
| | | name: labelList[Object.keys(item)[0]], |
| | | value: Object.values(item)[0] |
| | | }; |
| | | }); |
| | | return { |
| | | title: { |
| | | text: title, |
| | | x: 'left' |
| | | }, |
| | | color: ['#E74C3C', '#3498DB', '#F1C40F', '#95A5A6', '#8E44AD', '#F39C12', '#D35400'], |
| | | tooltip: { |
| | | trigger: 'item' |
| | | }, |
| | | legend: { |
| | | orient: 'horizontal', |
| | | }, |
| | | series: [ |
| | | { |
| | | type: 'pie', |
| | | radius: '50%', |
| | | data: pieData, |
| | | emphasis: { |
| | | itemStyle: { |
| | | shadowBlur: 10, |
| | | shadowOffsetX: 0, |
| | | shadowColor: 'rgba(0, 0, 0, 0.5)' |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | |
| | | }; |
| | | |
| | | }, |
| | | submitForm() { |
| | | this.getChartData(); |
| | | }, |
| | |
| | | handleResize() { |
| | | if (ageChart) { |
| | | ageChart.resize(); |
| | | } |
| | | if (scroeChart) { |
| | | scroeChart.resize(); |
| | | } |
| | | if (peopleChart) { |
| | | peopleChart.resize(); |
| | | } |
| | | } |
| | | }, |
| | |
| | | |
| | | .card-chart-container { |
| | | width: 100%; |
| | | height: 400px; |
| | | height: 500px; |
| | | } |
| | | |
| | | |
| | |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .data-item { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | border-radius: 10px; |
| | | overflow: hidden; |
| | | |
| | | .data-icon { |
| | | font-size: 70px; |
| | | padding: 20px 30px; |
| | | color: #fff; |
| | | border-radius: 10px; |
| | | overflow: hidden; |
| | | margin-right: 20px; |
| | | } |
| | | |
| | | .data-info { |
| | | .data-label { |
| | | font-size: 18px; |
| | | margin-bottom: 10px; |
| | | color: #707070; |
| | | } |
| | | |
| | | .data-num { |
| | | font-size: 28px; |
| | | } |
| | | } |
| | | } |
| | | </style> |