ZhangXianQiang
2024-05-15 8d83f09e4514b3a47b14af5f199adc92b2d4f297
feat:答卷统计图表
3个文件已修改
309 ■■■■ 已修改文件
.eslintignore 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/answer/sheetStatistics.vue 298 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintignore
@@ -1,2 +1,9 @@
/public/admin/components/ueditor
/public/admin/components/echarts
*.vue
/logs
/node_modules
/dist
/src/js
/package-lock.json
src/views/answer/sheetStatistics.vue
@@ -1,37 +1,88 @@
<template>
<div style="padding: 10px">
  <el-form :model="queryParam" ref="queryForm" :inline="true " style="display: flex">
    <el-form-item label="试卷:" >
      <el-select v-model="queryParam.examPaperId" filterable placeholder="试卷">
        <el-option v-for="item in examPaperList" :key="item.id" :value="item.id" :label="item.name"/>
      </el-select>
    </el-form-item>
    <el-form-item label="部门:" v-if="true">
      <el-select v-model="queryParam.departmentId" placeholder="部门" clearable>
        <el-option v-for="item in levelEnum" :key="item.key" :value="item.key" :label="item.value"/>
      </el-select>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm">查询</el-button>
    </el-form-item>
  <div style="padding: 10px" ref="pageContent">
    <el-form :model="queryParam" ref="queryForm" :inline="true" style="display: flex">
      <el-form-item label="试卷:">
        <el-select v-model="queryParam.examPaperId" filterable placeholder="试卷">
          <el-option v-for="item in examPaperList" :key="item.id" :value="item.id" :label="item.name" />
        </el-select>
      </el-form-item>
      <el-form-item label="部门:" v-if="true">
        <el-select v-model="queryParam.departmentId" placeholder="部门" clearable>
          <el-option v-for="item in levelEnum" :key="item.key" :value="item.key" :label="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">查询</el-button>
      </el-form-item>
  </el-form>
  <el-row class="echarts-line">
    <div id="echarts-moth-user" style="width: 100%;height:400px;" v-loading="loading"/>
  </el-row>
</div>
    </el-form>
    <el-row :gutter="20">
      <el-col :xl="12" class="echarts-row">
        <el-card>
          <div class="card-chart-container">
            <div id="ageChart" ref="ageChart" class="chart-style" v-loading="chartLoading1" />
          </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-col>
    </el-row>
    <el-row :gutter="20">
      <el-col :xl="24">
        <el-card>
          <div class="card-chart-container">
            <div id="peopleChart" ref="peopleChart" class="chart-style" v-loading="chartLoading3" />
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<script>
import { mapGetters, mapState, mapActions } from 'vuex'
import dashboardApi from '@/api/dashboard'
import { mapGetters, mapState, mapActions } from 'vuex';
import dashboardApi from '@/api/dashboard';
const colorList = ['#3498DB', '#E74C3C', '#F1C40F', '#95A5A6', '#8E44AD', '#F39C12', '#D35400'];
const ageLabel = {
  'age0To19': '0-19岁',
  'age20To29': '20-29岁',
  'age30To39': '30-39岁',
  'age40To49': '40-49岁',
  'ageOver50': '大于50岁',
};
const scoreLabel = {
  'score0To59': '小于60分',
  'score60To79': '60-79分',
  'score80To100': '80-100分'
};
const pieLabel = {
  'totalAbsent': '参与考试',
  'totalAttended': '未参与考试'
};
let ageChart = null;
let scroeChart = null;
let peopleChart = null;
let observer = null;
export default {
  data(){
    return{
  data() {
    return {
      examPaperList: [],
      max:'',
      min:'',
      avg:'',
      loading:false,
      max: '',
      min: '',
      avg: '',
      chartLoading1: false,
      chartLoading2: false,
      chartLoading3: false,
      loading: false,
      examPaperCount: 0,
      questionCount: 0,
      doExamPaperCount: 0,
@@ -44,79 +95,149 @@
        pageIndex: 1,
        pageSize: 10
      },
      listLoading:false
    }
      listLoading: false
    };
  },
  mounted(){
  created() {
    dashboardApi.examPaperList().then(res => {
      this.examPaperList = res.response
    })
    let _this = this
    dashboardApi.getData(this.queryParam).then(re => {
      let response = re.response
      console.log(response)
      _this.avg = response.avg
      _this.max = response.max
      _this.min = response.min
      _this.examPaperCount = response.examPaperCount
      _this.questionCount = response.questionCount
      _this.doExamPaperCount = response.doExamPaperCount
      _this.doQuestionCount = response.doQuestionCount
      _this.echartsUserAction.setOption(this.option('用户活跃度', '{b}分{c}人', response.mothDayText, response))
      // _this.echartsQuestion.setOption(this.option('题目月数量', '{b}日{c}题', response.mothDayText, response.mothDayDoExamQuestionValue))
      this.loading = false
    })
    this.echartsUserAction = echarts.init(document.getElementById('echarts-moth-user'), 'macarons')
      this.examPaperList = res.response;
    });
  },
  methods:{
    option (title, formatter, label, vaule) {
  mounted() {
    ageChart = echarts.init(this.$refs.ageChart);
    scroeChart = echarts.init(this.$refs.scoreChart);
    peopleChart = echarts.init(this.$refs.peopleChart);
    this.getChartData();
    this.observe();
  },
  methods: {
    getChartData() {
      this.chartLoading1 = true;
      this.chartLoading2 = true;
      this.chartLoading3 = true;
      dashboardApi.getData(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;
      });
    },
    barOption(title, data, labelList) {
      const dataKeys = data.map(item => labelList[Object.keys(item)[0]]);
      const dataValues = data.map(item => Object.values(item)[0]);
      return {
        title: {
          text: '答卷统计',
          x: 'center'
          text: title,
          x: 'left'
        },
        color: colorList,
        tooltip: {
          trigger: 'item',
          formatter: formatter
        },
        xAxis: {
          type: 'category',
          data: ['0-60','60-80','80-100']
          trigger: 'item'
        },
        grid: {
          left: 10,
          right: 10,
          bottom: 20,
          top: 30,
          top: 40,
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: dataKeys
        },
        yAxis: {
          type: 'value'
        },
        series: [{
          data: [vaule.lowGrade,vaule.intermediate,vaule.advanced],
          type: 'bar',
          barMaxWidth:'10%'
        }]
        series: [
          {
            type: 'bar',
            label: {
              show: true,
              fontSize: 16
            },
            barMaxWidth: '40%',
            data: dataValues,
          }
        ]
      };
    },
    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: colorList,
        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.queryParam.pageIndex = 1;
      this.getChartData();
    },
    // 监听变化
    observe() {
      if (!observer) {
        observer = new ResizeObserver(entries => {
          this.handleResize();
        });
      }
      observer.observe(this.$refs.pageContent);
    },
    search () {
      // this.listLoading = true
      let _this = this
      dashboardApi.getData(this.queryParam).then(re => {
        console.log(re)
        let response = re.response
        _this.avg = response.avg
        _this.max = response.max
        _this.min = response.min
        _this.echartsUserAction.setOption(this.option('用户活跃度', '{b}分{c}人', response.mothDayText, response))
      })
      this.echartsUserAction = echarts.init(document.getElementById('echarts-moth-user'), 'macarons')
    },
    submitForm () {
      this.queryParam.pageIndex = 1
      this.search()
    // 窗口变换
    handleResize() {
      if (ageChart) {
        ageChart.resize();
      }
      if (scroeChart) {
        scroeChart.resize();
      }
      if (peopleChart) {
        peopleChart.resize();
      }
    }
  },
  beforeDestroy() {
    observer.unobserve(this.$refs.pageContent);
  },
  computed: {
    ...mapGetters('enumItem', ['enumFormat']),
@@ -124,9 +245,22 @@
      levelEnum: state => state.user.levelEnum
    })
  }
}
};
</script>
<style scoped lang="scss">
.echarts-row {
  margin-bottom: 20px;
}
.card-chart-container {
  width: 100%;
  height: 400px;
}
.chart-style {
  width: 100%;
  height: 100%;
}
</style>
vue.config.js
@@ -9,7 +9,7 @@
  publicPath: './',
  outputDir: 'admin',
  assetsDir: 'static',
  lintOnSave: true,
  lintOnSave: false,
  productionSourceMap: false,
  devServer: {
    open: true,
@@ -19,7 +19,7 @@
    hotOnly: false,
    proxy: {
      '/api': {
        // target: 'http://80.36.32.171:8085',
        // target: 'http://192.168.3.87:8085',
        target: 'http://localhost:8085',
        changeOrigin: true
      }