ZhangXianQiang
2024-05-24 e68eebdf0a7cd3162eb0fac83b39c446bd665b12
Merge branch 'master' into dev-zhang
17个文件已修改
3个文件已添加
764 ■■■■ 已修改文件
src/api/UserConditionExamine.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/dashboard.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/question.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/user.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UploadC.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router.js 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/answer/dataStatistics.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/paper/list.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/question/edit/gap-filling.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/question/edit/multiple-choice.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/question/edit/short-answer.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/question/edit/single-choice.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/question/edit/true-false.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/question/list.vue 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/questionAnswer/edit.vue 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/questionAnswer/list.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/user/UserConditionExamine/list.vue 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/user/departmentExamine/list.vue 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/user/student/list.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/UserConditionExamine.js
New file
@@ -0,0 +1,9 @@
import { get,post } from '@/utils/request'
export default {
  list: query => post('/api/admin/userCondition/examine/list', query),
  save: query => post('/api/admin/userCondition/examine/save', query),
  audit: query => post('/api/admin/userCondition/examine/audit', query),
  delete: id => post('/api/admin/userCondition/examine/delete/' + id),
  getDeptList: id => post('/api/admin/userCondition/list'),
}
src/api/dashboard.js
@@ -3,6 +3,8 @@
export default {
  index: () => post('/api/admin/dashboard/index'),
  getData: query => post('/api/admin/examPaperAnswer/statistic', query),
  data: query => post('/api/admin/examPaperAnswer/data', query),
  queryCondition: query => get('/api/admin/exam/paper/queryCondition', query),
  examPaperList: query => get('/api/admin/exam/paper/list', query),
  page: query => post('/api/admin/examPaperAnswer/page', query)
}
src/api/question.js
@@ -1,4 +1,4 @@
import { post, download } from '@/utils/request'
import { post, download, downloadPost } from '@/utils/request'
export default {
  pageList: query => post('/api/admin/question/page', query),
@@ -6,5 +6,5 @@
  select: id => post('/api/admin/question/select/' + id),
  deleteQuestion: id => post('/api/admin/question/delete/' + id),
  downloadImportTemplate: () => download('/api/admin/question/download/question/import/temp'),
  exportQuestion: query => download('/api/admin/question/question/export', query)
  exportQuestion: query => downloadPost('/api/admin/question/question/export', query)
}
src/api/user.js
@@ -19,5 +19,5 @@
  selectByUserName: query => post('/api/admin/user/selectByUserName', query),
  addMeetin:query => post('/api/admin/video/add', query),
  delMeetin:query => post('/api/admin/video/clear', query),
  setStatus:query => post('/api/admin/user/setStatus', query)
  setStatus:query => post('/api/admin/userCondition/examine/save', query)
}
src/components/UploadC.vue
@@ -43,8 +43,9 @@
      uploadUrl: "http://localhost:8085/api/upload/upload",
      fileTypeList: {
        'video': ['mp4', 'avi'],
        'img': ['jgp', 'png', 'jpeg'],
        'img': ['jpg', 'png', 'jpeg'],
        'pdf': ['pdf'],
        'file': ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'png', 'jpg', 'jpeg', 'pdf'],
      }
    };
  },
src/router.js
@@ -78,6 +78,12 @@
        meta: { title: '调动审核', noCache: true }
      },
      {
        path: 'UserConditionExamine/list',
        component: () => import('@/views/user/UserConditionExamine/list'),
        name: 'UserConditionExamineList',
        meta: { title: '状态审核', noCache: true }
      },
      {
        path: 'tag/list',
        component: () => import('@/views/user/tag/list'),
        name: 'TagAdminPageList',
@@ -308,7 +314,13 @@
        path: 'sheetStatistics',
        component: () => import('@/views/answer/sheetStatistics.vue'),
        name: 'AnswerPageList',
        meta: { title: '答卷统计', noCache: true }
        meta: { title: '人数分布', noCache: true }
      },
      {
        path: 'dataStatistics',
        component: () => import('@/views/answer/dataStatistics.vue'),
        name: 'AnswerPageList',
        meta: { title: '分数统计', noCache: true }
      },
      {
        path: 'achievementStatistics',
@@ -484,6 +496,12 @@
        name: 'departmentExamineList',
        meta: { title: '调动审核', noCache: true }
      },
      {
        path: 'UserConditionExamine/list',
        component: () => import('@/views/user/UserConditionExamine/list'),
        name: 'UserConditionExamineList',
        meta: { title: '状态审核', noCache: true }
      },
    ]
  },
  {
@@ -496,19 +514,19 @@
    },
    alwaysShow: true,
    children: [
      {
        path: 'paper/list',
        component: () => import('@/views/exam/paper/list'),
        name: 'ExamPaperPageList',
        meta: { title: '试卷列表', noCache: true }
      },
      {
        path: 'paper/edit',
        component: () => import('@/views/exam/paper/edit'),
        name: 'ExamPaperEdit',
        meta: { title: '试卷编辑', noCache: true, activeMenu: '/exam/paper/list' },
        hidden: true
      },
      // {
      //   path: 'paper/list',
      //   component: () => import('@/views/exam/paper/list'),
      //   name: 'ExamPaperPageList',
      //   meta: { title: '试卷列表', noCache: true }
      // },
      // {
      //   path: 'paper/edit',
      //   component: () => import('@/views/exam/paper/edit'),
      //   name: 'ExamPaperEdit',
      //   meta: { title: '试卷编辑', noCache: true, activeMenu: '/exam/paper/list' },
      //   hidden: true
      // },
      {
        path: 'personalRandomTemplate/list',
        component: () => import('@/views/exam/personalRandomTemplate/list'),
@@ -558,7 +576,7 @@
        path: 'sheetStatistics',
        component: () => import('@/views/answer/sheetStatistics.vue'),
        name: 'AnswerPageList',
        meta: { title: '答卷统计', noCache: true }
        meta: { title: '人数分布', noCache: true }
      },
    ]
  },
src/utils/request.js
@@ -119,6 +119,19 @@
  return request(false, query)
}
const downloadPost = function (url, params) {
  const query = {
    baseURL: process.env.VUE_APP_URL,
    url: url,
    method: 'post',
    withCredentials: true,
    timeout: 300000,
    data: params,
    responseType: 'blob' // 关键
  }
  return request(false, query)
}
export const down = function (url, params) {
  const query = {
    baseURL: process.env.VUE_APP_URL,
@@ -137,5 +150,6 @@
  postWithOutLoadTip,
  get,
  form,
  download
  download,
  downloadPost
}
src/views/answer/dataStatistics.vue
New file
@@ -0,0 +1,257 @@
<template>
  <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.id" filterable placeholder="试卷">
          <el-option v-for="item in examPaperList" :key="item.id" :value="item.id" :label="item.name" @change="getType(item.type)" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">查询</el-button>
      </el-form-item>
    </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 } 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分',
  '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,
      queryParam: {
        id: '',
        type: 1
      },
      admin: true
    };
  },
  mounted() {
    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.getChartData();
      this.observe();
    });
  },
  methods: {
    getType(type) {
      this.queryParam.type = type;
      this.getChartData();
    },
    getChartData() {
      this.chartLoading1 = true;
      this.chartLoading2 = true;
      this.chartLoading3 = 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;
      });
    },
    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: title,
          x: 'left'
        },
        color: colorList,
        tooltip: {
          trigger: 'item'
        },
        grid: {
          left: 10,
          right: 10,
          bottom: 20,
          top: 40,
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: dataKeys
        },
        yAxis: {
          type: 'value'
        },
        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: ['#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();
    },
    // 监听变化
    observe() {
      if (!observer) {
        observer = new ResizeObserver(entries => {
          this.handleResize();
        });
      }
      observer.observe(this.$refs.pageContent);
    },
    // 窗口变换
    handleResize() {
      if (ageChart) {
        ageChart.resize();
      }
      if (scroeChart) {
        scroeChart.resize();
      }
      if (peopleChart) {
        peopleChart.resize();
      }
    }
  },
  beforeDestroy() {
    observer.unobserve(this.$refs.pageContent);
  },
  computed: {
    ...mapGetters('enumItem', ['enumFormat']),
    ...mapState('enumItem', {
      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>
src/views/exam/paper/list.vue
@@ -9,7 +9,7 @@
      </el-form-item>
      <el-form-item label="课目:" >
        <el-select v-model="queryParam.subjectId"  clearable>
          <el-option v-for="item in subjectFilter" :key="item.id" :value="item.id" :label="item.name+' '"></el-option>
          <el-option v-for="item in subjects" :key="item.id" :value="item.id" :label="item.name+' '"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
src/views/exam/question/edit/gap-filling.vue
@@ -1,8 +1,8 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading"  :rules="rules">
      <el-form-item label="部门:" prop="gradeLevel" style="display: none">
        <el-select v-model="form.gradeLevel" placeholder="部门" @change="levelChange">
      <el-form-item label="所属部门:" prop="deptIds">
        <el-select v-model="form.deptIds" placeholder="所属部门" multiple filterable>
          <el-option v-for="item in depart" :key="item.id" :value="item.id" :label="item.name"></el-option>
        </el-select>
      </el-form-item>
@@ -72,7 +72,7 @@
        id: null,
        questionType: 4,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
        ],
@@ -236,7 +236,7 @@
        id: null,
        questionType: 4,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
        ],
src/views/exam/question/edit/multiple-choice.vue
@@ -1,8 +1,8 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading"  :rules="rules">
      <el-form-item label="部门:" prop="gradeLevel"  style="display: none">
        <el-select v-model="form.gradeLevel" placeholder="部门"  @change="levelChange">
      <el-form-item label="所属部门:" prop="deptIds">
        <el-select v-model="form.deptIds" placeholder="所属部门" multiple filterable>
          <el-option v-for="item in depart" :key="item.id" :value="item.id" :label="item.name"></el-option>
        </el-select>
      </el-form-item>
@@ -79,7 +79,7 @@
        id: null,
        questionType: 2,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
          { id: null, prefix: 'A', content: '' },
@@ -228,7 +228,7 @@
        id: null,
        questionType: 2,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
          { id: null, prefix: 'A', content: '' },
src/views/exam/question/edit/short-answer.vue
@@ -1,8 +1,8 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading" :rules="rules">
      <el-form-item label="部门:" prop="gradeLevel"  style="display: none">
        <el-select v-model="form.gradeLevel"   placeholder="部门"  @change="levelChange">
      <el-form-item label="所属部门:" prop="deptIds">
        <el-select v-model="form.deptIds" placeholder="所属部门" multiple filterable>
          <el-option v-for="item in depart" :key="item.id" :value="item.id" :label="item.name"></el-option>
        </el-select>
      </el-form-item>
@@ -69,7 +69,7 @@
        id: null,
        questionType: 5,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [],
        analyze: '',
@@ -189,7 +189,7 @@
        id: null,
        questionType: 5,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [],
        analyze: '',
src/views/exam/question/edit/single-choice.vue
@@ -1,8 +1,8 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading" :rules="rules">
      <el-form-item label="部门:" prop="gradeLevel" style="display: none">
        <el-select v-model="form.gradeLevel" placeholder="部门"  @change="levelChange" clearable>
      <el-form-item label="所属部门:" prop="deptIds">
        <el-select v-model="form.deptIds" placeholder="所属部门" multiple filterable>
          <el-option v-for="item in depart" :key="item.id" :value="item.id" :label="item.name"></el-option>
        </el-select>
      </el-form-item>
@@ -79,7 +79,7 @@
        id: null,
        questionType: 1,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
          { prefix: 'A', content: '' },
@@ -219,7 +219,7 @@
        id: null,
        questionType: 1,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
          { prefix: 'A', content: '' },
src/views/exam/question/edit/true-false.vue
@@ -1,14 +1,13 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading"  :rules="rules">
      <el-form-item label="部门:" prop="gradeLevel" style="display: none">
        <el-select v-model="form.gradeLevel" placeholder="部门"  @change="levelChange">
      <el-form-item label="所属部门:" prop="deptIds">
        <el-select v-model="form.deptIds" placeholder="所属部门" multiple filterable>
          <el-option v-for="item in depart" :key="item.id" :value="item.id" :label="item.name"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="课目:" prop="subjectIds" required>
        <el-select v-model="form.subjectIds" placeholder="课目"  multiple
                   collapse-tags>
        <el-select v-model="form.subjectIds" placeholder="课目"  multiple collapse-tags>
          <el-option v-for="item in subjectFilter" :key="item.id" :value="item.id" :label="item.name+' '"></el-option>
        </el-select>
      </el-form-item>
@@ -74,11 +73,10 @@
      },
      depart:[],
      form: {
        id: null,
        questionType: 3,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
          { id: null, prefix: 'A', content: '是' },
@@ -202,7 +200,7 @@
        id: null,
        questionType: 3,
        gradeLevel: null,
        deptIds: [],
        title: '',
        items: [
          { id: null, prefix: 'A', content: '是' },
@@ -216,7 +214,6 @@
      this.form.id = lastId
    },
    levelChange () {
      this.subjectFilter = this.subjects.filter(data => data.level === this.form.gradeLevel)
    },
    showQuestion () {
src/views/exam/question/list.vue
@@ -33,22 +33,13 @@
          <el-form
            label-position="top"
          >
            <el-form-item label="题型:">
              <el-select v-model="exportForm.questionType" clearable>
                <el-option v-for="item in questionType" :key="item.key" :value="item.key" :label="item.value"></el-option>
            <el-form-item label="课目:">
              <el-select v-model="exportForm.subjectIds" clearable filterable multiple>
                <el-option v-for="item in subjectIdList" :key="item.id" :value="item.id" :label="item.name"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="创建时间:">
              <el-date-picker
                v-model="timeRange"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期">
              </el-date-picker>
            <el-form-item style="text-align: center;margin-top: 5px">
            <el-form-item>
              <el-button type="primary" @click="exportQuestion">导出</el-button>
            </el-form-item>
            </el-form-item>
          </el-form>
          <el-button slot="reference" class="op-item" type="success">导出</el-button>
@@ -72,6 +63,7 @@
    </el-form>
    <el-table v-loading="listLoading" :data="tableData" border fit highlight-current-row style="width: 100%">
      <el-table-column prop="subjectId" label="课目" :formatter="subjectIdFormatte" width="120px"/>
      <el-table-column prop="deptNames" label="所属部门" width="150px"/>
      <el-table-column prop="questionType" label="题型" :formatter="questionTypeFormatter" width="70px"/>
      <el-table-column prop="shortTitle" label="题干" show-overflow-tooltip/>
      <el-table-column prop="score" label="分数" width="60px"/>
@@ -98,17 +90,16 @@
import Pagination from '@/components/Pagination'
import QuestionShow from './components/Show'
import questionApi from '@/api/question'
import SubjectApi from '@/api/subject'
import { downloadExcel } from '@/utils/download'
export default {
  components: { Pagination, QuestionShow },
  data () {
    return {
      subjectIdList: [],
      timeRange: [],
      exportForm: {
        questionType: null,
        start: null,
        end: null
        subjectIds: [],
      },
      upLoadUrl: '/api/admin/question/import',
      fileList: [],
@@ -136,16 +127,13 @@
  created () {
    this.initSubject()
    this.search()
    this.getSubjectIds()
    this.queryParam.subjectId = null
    this.subjectFilter = this.subjects
  },
  methods: {
    // 导出题目
    exportQuestion () {
      if (this.timeRange && this.timeRange.length > 1) {
        this.exportForm.startStr = this.timeRange[0]
        this.exportForm.endStr = this.timeRange[1]
      }
      questionApi.exportQuestion(this.exportForm).then(res => {
        downloadExcel(res, '题目导出')
      })
@@ -175,17 +163,6 @@
        this.$message.warning('文件格式不对,仅限xls和xlsx')
        return false
      }
      // console.log(file)
      // const isJPG = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
      // // const isLt2M = file.size / 1024 / 1024 < 2;
      //
      // if (!isJPG) {
      //   this.$message.error('上传文件只能是Excel!');
      // }
      // // if (!isLt2M) {
      // //   this.$message.error('上传头像图片大小不能超过 2MB!');
      // // }
      // return isJPG ;
    },
    submitForm () {
      this.queryParam.pageIndex = 1
@@ -217,6 +194,11 @@
        _this.questionShow.question = re.response
        _this.questionShow.loading = false
      })
    },
    getSubjectIds() {
       SubjectApi.list().then(res => {
         this.subjectIdList = res.response
      });
    },
    editQuestion (row) {
      let url = this.enumFormat(this.editUrlEnum, row.questionType)
@@ -250,7 +232,6 @@
    ...mapActions('exam', { initSubject: 'initSubject' })
  },
  computed: {
    headers: function () {
      // console.log(store.getters.Admin-Token)
      // const tenantId = store.getters.userInfo.tenantId
src/views/questionAnswer/edit.vue
@@ -3,10 +3,13 @@
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading" :rules="rules">
      <el-form-item label="问题:"  prop="question">
        <el-input v-model="form.question"></el-input>
        <el-input v-model="form.question" maxlength="48"></el-input>
      </el-form-item>
      <el-form-item label="答案:"  prop="answer">
        <el-input v-model="form.answer"></el-input>
        <el-input v-model="form.answer" maxlength="1000"></el-input>
      </el-form-item>
      <el-form-item label="附件:"  prop="attachment">
        <upload :fileUrl="form.contentUrl" :fileSizeLimitM="1024" :uploadNum="1" @getUploadUrl="getUploadAttachmentUrl" @removeFile="removeAttachmentFile"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
@@ -19,14 +22,27 @@
<script>
import { mapGetters, mapState, mapActions } from 'vuex'
import questionAnswerApi from '@/api/questionAnswer'
import Upload from '@/components/UploadC'
export default {
  components: { Upload },
  computed: {
    fileContentUrl: () => {
      return this.form ? this.form.contentUrl ? [this.form.contentUrl] : [] : [];
    }
  },
  data () {
    return {
      form: {
        id: null,
        question: '',
        answer: ''
        answer: '',
        contentType: 'file',
        subject: '',
        belongType: 2,
        contentUrl: [],
        attachment: '',
        temp: []
      },
      formLoading: false,
      rules: {
@@ -45,17 +61,30 @@
    if (id && parseInt(id) !== 0) {
      _this.formLoading = true
      questionAnswerApi.query(id).then(re => {
        _this.form = re.response
        _this.form.id = re.response.id
        _this.form.question = re.response.question
        _this.form.answer = re.response.answer
        _this.form.attachment = re.response.attachment ? re.response.attachment : ''
        _this.form.contentUrl = re.response.attachment ? JSON.parse(re.response.attachment) : []
        _this.formLoading = false
      })
    }
  },
  methods: {
    removeAttachmentFile(fileList, fileName) {
      this.form.attachment = JSON.stringify(fileList.filter(item => item.name !== fileName));
      this.form.contentUrl = fileList.filter(item => item.name !== fileName);
    },
    getUploadAttachmentUrl(uploadData) {
      this.form.attachment = JSON.stringify(uploadData);
      this.form.contentUrl = uploadData;
    },
    submitForm () {
      let _this = this
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.formLoading = true
          questionAnswerApi.save(this.form).then(data => {
            if (data.code === 1) {
              _this.$message.success(data.message)
src/views/questionAnswer/list.vue
@@ -17,6 +17,13 @@
    <el-table v-loading="listLoading" :data="tableData" border fit highlight-current-row style="width: 100%">
      <el-table-column prop="question" label="问题" />
      <el-table-column prop="answer" label="回答" />
      <el-table-column prop="attachment" label="附件" show-overflow-tooltip>
        <template slot-scope="scope">
          <div v-for="item in getUrl(scope.row.attachment)" :key="item.url">
            <el-link :underline="false" type="primary" :href="'/api/upload/download?url=' + item.url +'&fileName=' + item.name" >{{ item.name }}</el-link>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="状态" prop="status" width="70px">
        <template slot-scope="{row}">
          <el-tag :type="row.status !== '启用' ? 'danger' : 'success'">
@@ -67,6 +74,9 @@
    this.search()
  },
  methods: {
    getUrl(urlJson) {
      return urlJson ? JSON.parse(urlJson) : [];
    },
    search() {
      this.listLoading = true
      questionAnswerApi.pageList(this.queryParam).then(data => {
src/views/user/UserConditionExamine/list.vue
New file
@@ -0,0 +1,180 @@
<template>
  <div class="app-container">
    <el-form :model="queryParam" ref="queryForm" :inline="true">
      <el-form-item label="用户名:">
        <el-input v-model="queryParam.userName"></el-input>
      </el-form-item>
      <el-form-item>
        <div style="display: flex">
          <el-button type="primary" @click="search()">查询</el-button>
        </div>
      </el-form-item>
    </el-form>
    <el-table v-loading="listLoading" :data="tableData" border fit highlight-current-row style="width: 100%">
      <el-table-column prop="userName" label="用户" />
      <el-table-column prop="targetCondition" label="申请状态" />
      <el-table-column prop="sourceCondition" label="当前状态" />
      <el-table-column prop="reason" label="调动原因"  show-overflow-tooltip/>
      <el-table-column prop="attachment" label="附件" show-overflow-tooltip>
        <template slot-scope="scope">
          <div v-for="item in getUrl(scope.row.attachment)" :key="item.url">
            <el-link :underline="false" type="primary" :href="'/api/upload/download?url=' + item.url +'&fileName=' + item.name" >{{ item.name }}</el-link>
          </div>
        </template>
      </el-table-column>
      <el-table-column prop="result" label="审核结果" width="90px" align="center">
        <template slot-scope="{row}">
          <el-tag :type="row.result === '审核通过' ? 'success' : row.result === '审核驳回' ? 'danger' : 'info'">{{row.result}}</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="remark" label="审核意见" show-overflow-tooltip />
      <el-table-column prop="createUserName" label="创建人" />
      <el-table-column prop="createTime" label="创建时间" width="160px" />
      <el-table-column label="操作" align="center" v-if="!deptAdmin()">
        <template slot-scope="{row}">
          <el-button v-if="row.result === '待审核'" type="primary" size="mini" @click="transposition(row)" class="link-left">审核</el-button>
          <el-popconfirm title="确认删除" @confirm="deleteUser(row)">
            <el-button slot="reference" size="mini" type="danger" class="link-left">删除</el-button>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <pagination v-show="total > 0" :total="total" :page.sync="queryParam.pageIndex" :limit.sync="queryParam.pageSize"
      @pagination="search" />
    <!-- 审核弹窗 -->
    <el-dialog :visible.sync="statusVisible" append-to-body :show-close="false" center width="400px">
      <el-radio-group v-model="user.result">
        <el-radio label="审核通过">通过</el-radio>
        <el-radio label="审核驳回">驳回</el-radio>
      </el-radio-group>
      <el-input type="textarea" maxlength="100" show-word-limit :autosize="{ minRows: 4 }" :rows="2"
        v-model="user.remark" placeholder="请输入审核意见" style="margin-top: 30px;"></el-input>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="statusConfirm">确 定</el-button>
        <el-button @click="statusVisible = false">取 消</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import UserConditionExamineApi from '@/api/UserConditionExamine'
import Pagination from '@/components/Pagination'
import { mapGetters, mapState } from 'vuex'
export default {
  components: { Pagination },
  data() {
    return {
      user: {},
      statusVisible: false,
      fileList: [],
      queryParam: {
        userName: '',
        role: 1,
        pageIndex: 1,
        pageSize: 10
      },
      listLoading: true,
      tableData: [],
      total: 0,
    }
  },
  created() {
    this.search()
  },
  methods: {
    getUrl(urlJson) {
      return urlJson ? JSON.parse(urlJson) : [];
    },
    deptAdmin() {
      return sessionStorage.getItem('deptAdmin') === '1'
    },
    transposition(user) {
      this.statusVisible = true;
      this.user = { ...user };
    },
    statusConfirm() {
      if (this.user.result === "待审核") {
        this.$message.error("请选择审核结果")
        return
      }
      UserConditionExamineApi.audit(this.user).then(res => {
        if (res.code === 1) {
          this.$message.success("操作成功")
          this.statusVisible = false;
          this.search()
        } else {
          this.$message.error("操作失败")
        }
      })
    },
    search() {
      this.listLoading = true
      UserConditionExamineApi.list(this.queryParam).then(data => {
        const re = data.response
        this.tableData = re.list
        this.total = re.total
        this.queryParam.pageIndex = re.pageNum
        this.listLoading = false
      })
    },
    changeStatus(row) {
      let _this = this
      userApi.changeStatus(row.id).then(re => {
        if (re.code === 1) {
          row.status = re.response
          _this.$message.success(re.message)
        } else {
          _this.$message.error(re.message)
        }
      })
    },
    deleteUser(row) {
      let _this = this
      UserConditionExamineApi.delete(row.id).then(re => {
        if (re.code === 1) {
          _this.search()
          _this.$message.success(re.message)
        } else {
          _this.$message.error(re.message)
        }
      })
    },
    levelFormatter(row, column, cellValue, index) {
      return this.enumFormat(this.levelEnum, cellValue)
    },
    sexFormatter(row, column, cellValue, index) {
      return this.enumFormat(this.sexEnum, cellValue)
    },
    statusFormatter(status) {
      return this.enumFormat(this.statusEnum, status)
    },
    statusTagFormatter(status) {
      return this.enumFormat(this.statusTag, status)
    },
    statusBtnFormatter(status) {
      return this.enumFormat(this.statusBtn, status)
    }
  },
  computed: {
    ...mapGetters('enumItem', [
      'enumFormat'
    ]),
    ...mapState('enumItem', {
      sexEnum: state => state.user.sexEnum,
      statusEnum: state => state.user.statusEnum,
      statusTag: state => state.user.statusTag,
      statusBtn: state => state.user.statusBtn,
      levelEnum: state => state.user.levelEnum
    })
  }
}
</script>
<style lang="scss" scoped>
.upload-demo {
  margin-left: 5px;
}
</style>
src/views/user/departmentExamine/list.vue
@@ -12,9 +12,17 @@
    </el-form>
    <el-table v-loading="listLoading" :data="tableData" border fit highlight-current-row style="width: 100%">
      <el-table-column prop="userName" label="用户名" />
      <el-table-column prop="departmentName" label="部门名称" />
      <el-table-column prop="nowDepartmentName" label="原部门名称" />
      <el-table-column prop="userName" label="用户" />
      <el-table-column prop="departmentName" label="调动部门" />
      <el-table-column prop="nowDepartmentName" label="原部门" />
      <el-table-column prop="reason" label="调动原因"  show-overflow-tooltip/>
      <el-table-column prop="attachment" label="附件" show-overflow-tooltip>
        <template slot-scope="scope">
          <div v-for="item in getUrl(scope.row.attachment)" :key="item.url">
            <el-link :underline="false" type="primary" :href="'/api/upload/download?url=' + item.url +'&fileName=' + item.name" >{{ item.name }}</el-link>
          </div>
        </template>
      </el-table-column>
      <el-table-column prop="result" label="审核结果" width="90px" align="center">
        <template slot-scope="{row}">
          <el-tag :type="row.result === '审核通过' ? 'success' : row.result === '审核驳回' ? 'danger' : 'info'">{{row.result}}</el-tag>
@@ -23,7 +31,7 @@
      <el-table-column prop="remark" label="审核意见" show-overflow-tooltip />
      <el-table-column prop="createUserName" label="创建人" />
      <el-table-column prop="createTime" label="创建时间" width="160px" />
      <el-table-column label="操作" align="center" v-if="isDeptAdmin()">
      <el-table-column label="操作" align="center" v-if="!deptAdmin()">
        <template slot-scope="{row}">
          <el-button v-if="row.result === '待审核'" type="primary" size="mini" @click="transposition(row)" class="link-left">审核</el-button>
          <el-popconfirm title="确认删除" @confirm="deleteUser(row)">
@@ -78,16 +86,19 @@
    this.search()
  },
  methods: {
    isDeptAdmin() {
      return sessionStorage.getItem('deptAdmin') !== '1'
    getUrl(urlJson) {
      return urlJson ? JSON.parse(urlJson) : [];
    },
    deptAdmin() {
      return sessionStorage.getItem('deptAdmin') === '1'
    },
    transposition(user) {
      this.statusVisible = true;
      this.user = { ...user };
    },
    statusConfirm() {
      if (this.user.result === null) {
        this.$message.error("请选择状态")
      if (this.user.result === "待审核") {
        this.$message.error("请选择审核结果")
        return
      }
      departmentExamineApi.audit(this.user).then(res => {
src/views/user/student/list.vue
@@ -20,7 +20,6 @@
           :file-list="fileList"
           :before-upload="beforeAvatarUpload">
           <el-button type="primary">导入</el-button>
           <!--          <div slot="tip" class="el-upload__tip">只能上传Excel文件</div>-->
         </el-upload>
       </div>
      </el-form-item>
@@ -40,7 +39,6 @@
          <el-tag :type="row.condition == '正常' || row.condition == null  ? 'success' : 'warning'">{{ row.condition ? row.condition : '正常' }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="conditionDetail" label="具体情况" :show-overflow-tooltip="true"/>
      <el-table-column prop="sex" label="性别" width="60px;" :formatter="sexFormatter"/>
      <el-table-column prop="phone" label="手机号" width="120"/>
      <el-table-column prop="createTime" label="创建时间" width="160px"/>
@@ -51,9 +49,9 @@
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column width="400px" label="操作" fixed="right" align="center">
      <el-table-column :width="deptAdmin() ? '310px' : '400px'" label="操作" fixed="right" align="center">
        <template slot-scope="{row}">
          <el-button size="mini"  @click="changeStatus(row)" class="link-left">
          <el-button size="mini" v-if="!deptAdmin()" @click="changeStatus(row)" class="link-left">
            {{ statusBtnFormatter(row.status) }}
          </el-button>
          <router-link :to="{path:'/user/student/edit', query:{id:row.id}}" class="link-left">
@@ -64,7 +62,9 @@
          </router-link>
          <el-button  size="mini" @click="status(row)" class="link-left">状态</el-button>
          <el-button type="primary" size="mini" @click="transposition(row)" class="link-left">调动</el-button>
          <el-button  size="mini" type="danger" @click="deleteUser(row)" class="link-left">删除</el-button>
          <el-popconfirm title="确认删除吗" @confirm="deleteUser(row)">
            <el-button v-if="!deptAdmin()" slot="reference" size="mini" type="danger" class="link-left">删除</el-button>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
@@ -72,14 +72,15 @@
                @pagination="search"/>
    <!-- 状态弹窗 -->
    <el-dialog :visible.sync="statusVisible" append-to-body :close-on-click-modal="false" :show-close="false" center width="400px">
      <el-radio-group v-model="user.condition">
    <el-dialog :visible.sync="statusVisible" append-to-body :show-close="false" center width="400px">
      <el-radio-group v-model="conditionExamine.targetCondition">
        <el-radio label="正常">正常</el-radio>
        <el-radio label="病假">病假</el-radio>
        <el-radio label="出差">出差</el-radio>
        <el-radio label="其他">其他</el-radio>
      </el-radio-group>
      <el-input type="textarea" maxlength="100" show-word-limit :autosize="{ minRows: 4}" :rows="2" v-model="user.conditionDetail" placeholder="请输入详细情况" style="margin-top: 30px;"></el-input>
      <el-input type="textarea" maxlength="100" show-word-limit :autosize="{ minRows: 4}" :rows="2" v-model="conditionExamine.reason" placeholder="请输入详细情况" style="margin-top: 30px;"></el-input>
      <upload :fileUrl="conditionExamine.contentUrl" :fileSizeLimitM="1024" :uploadNum="1" @getUploadUrl="getConditionUploadAttachmentUrl" @removeFile="removeConditionAttachmentFile" style="margin-top: 30px;"/>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="statusConfirm">确 定</el-button>
        <el-button @click="statusVisible = false">取 消</el-button>
@@ -99,6 +100,8 @@
          :value="item.id">
        </el-option>
      </el-select>
      <el-input type="textarea" maxlength="100" show-word-limit :autosize="{ minRows: 4}" :rows="2" v-model="examine.reason" placeholder="请输入情况说明" style="margin-top: 30px;"></el-input>
      <upload :fileUrl="examine.contentUrl" :fileSizeLimitM="1024" :uploadNum="1" @getUploadUrl="getUploadAttachmentUrl" @removeFile="removeAttachmentFile" style="margin-top: 30px;"/>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitExamine">确 定</el-button>
@@ -112,9 +115,15 @@
import Pagination from '@/components/Pagination'
import userApi from '@/api/user'
import departmentExamineApi from '@/api/departmentExamine'
import Upload from '@/components/UploadC'
export default {
  components: { Pagination },
  components: { Pagination, Upload },
  computed: {
    fileContentUrl: () => {
      return this.form ? this.form.contentUrl ? [this.form.contentUrl] : [] : [];
    }
  },
  data () {
    return {
      user:{},
@@ -135,6 +144,17 @@
        departmentId: [],
        departmentIds: '',
        nowDepartmentIds: '',
        contentUrl: [],
        attachment: ''
      },
      conditionExamine: {
        userId: '',
        targetCondition: '',
        sourceCondition: '',
        reason: '',
        result: 0,
        contentUrl: [],
        attachment: ''
      },
      title: '部门调动',
      dialogVisible: false,
@@ -145,6 +165,25 @@
    this.search()
  },
  methods: {
    deptAdmin() {
      return sessionStorage.getItem('deptAdmin') === '1'
    },
    removeAttachmentFile(fileList, fileName) {
      this.examine.attachment = JSON.stringify(fileList.filter(item => item.name !== fileName));
      this.examine.contentUrl = fileList.filter(item => item.name !== fileName);
    },
    getUploadAttachmentUrl(uploadData) {
      this.examine.attachment = JSON.stringify(uploadData);
      this.examine.contentUrl = uploadData;
    },
    removeConditionAttachmentFile(fileList, fileName) {
      this.conditionExamine.attachment = JSON.stringify(fileList.filter(item => item.name !== fileName));
      this.conditionExamine.contentUrl = fileList.filter(item => item.name !== fileName);
    },
    getConditionUploadAttachmentUrl(uploadData) {
      this.conditionExamine.attachment = JSON.stringify(uploadData);
      this.conditionExamine.contentUrl = uploadData;
    },
    submitExamine() {
      this.examine.departmentIds = this.examine.departmentId.join(',')
      departmentExamineApi.save(this.examine).then(res => {
@@ -172,14 +211,15 @@
    },
    status(user) {
      this.statusVisible = true;
      this.user = { ...user };
      this.conditionExamine.sourceCondition = user.condition ? user.condition : '0';
      this.conditionExamine.userId = user.id
    },
    statusConfirm() {
      if (this.user.condition === null) {
      if (this.conditionExamine.targetCondition === null) {
        this.$message.error("请选择状态")
        return
      }
      userApi.setStatus(this.user).then(res => {
      userApi.setStatus(this.conditionExamine).then(res => {
        if (res.code === 1) {
          this.$message.success("操作成功")
          this.statusVisible = false;
@@ -208,17 +248,6 @@
        this.$message.warning('文件格式不对,仅限xls和xlsx')
        return false
      }
      // console.log(file)
      // const isJPG = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
      // // const isLt2M = file.size / 1024 / 1024 < 2;
      //
      // if (!isJPG) {
      //   this.$message.error('上传文件只能是Excel!');
      // }
      // // if (!isLt2M) {
      // //   this.$message.error('上传头像图片大小不能超过 2MB!');
      // // }
      // return isJPG ;
    },
    search () {
      this.listLoading = true