龚焕茏
2024-06-03 83bde4c4b6bfdbac8e5def7e1ab808902a6732c6
feat:题目添加-前端界面
2个文件已修改
6个文件已添加
1417 ■■■■ 已修改文件
src/api/subject.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PopUp/gap-filling.vue 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PopUp/multiple-choice.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PopUp/question/Show.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PopUp/short-answer.vue 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PopUp/single-choice.vue 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PopUp/true-false.vue 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Manage/TestPaper/QuestionBank.vue 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/subject.js
@@ -1,9 +1,9 @@
import { post } from '@/utils/request'
export default {
  list: query => post('/api/admin/education/subject/list'),
  pageList: query => post('/api/admin/education/subject/page', query),
  edit: query => post('/api/admin/education/subject/edit', query),
  select: id => post('/api/admin/education/subject/select/' + id),
  deleteSubject: id => post('/api/admin/education/subject/delete/' + id)
  list: query => post('/api/admin/subject/list'),
  pageList: query => post('/api/admin/subject/page', query),
  edit: query => post('/api/admin/subject/edit', query),
  select: id => post('/api/admin/subject/select/' + id),
  deleteSubject: id => post('/api/admin/subject/delete/' + id)
}
src/components/PopUp/gap-filling.vue
New file
@@ -0,0 +1,229 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading" :rules="rules">
      <el-form-item label="学科:" prop="subjectId" required>
        <el-select v-model="form.subjectId" placeholder="学科">
          <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 label="题干:" prop="title" required>
        <el-input v-model="form.title" @focus="inputClick(form, 'title')" />
      </el-form-item>
      <el-form-item label="填空答案:" required>
        <el-form-item :label="item.prefix" :key="item.prefix" v-for="item in form.items" label-width="50px"
          class="question-item-label">
          <el-input v-model="item.content" @focus="inputClick(item, 'content')" class="question-item-content-input"
            style="width: 50%" />
          <span class="question-item-span">分数:</span><el-input-number v-model="item.score" :precision="1" :step="1"
            :max="100"></el-input-number>
        </el-form-item>
      </el-form-item>
      <el-form-item label="解析:" prop="analyze" required>
        <el-input v-model="form.analyze" @focus="inputClick(form, 'analyze')" />
      </el-form-item>
      <el-form-item label="分数:" prop="score" required>
        <el-input-number v-model="form.score" :precision="1" :step="1" :max="100"></el-input-number>
      </el-form-item>
      <el-form-item label="难度:" required>
        <el-rate v-model="form.difficult" class="question-item-rate"></el-rate>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
        <el-button @click="resetForm">重置</el-button>
        <el-button type="success" @click="showQuestion">预览</el-button>
      </el-form-item>
    </el-form>
    <el-dialog :visible.sync="richEditor.dialogVisible" append-to-body :close-on-click-modal="false"
      style="width: 100%;height: 100%" :show-close="false" center>
      <Ueditor @ready="editorReady" />
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editorConfirm">确 定</el-button>
        <el-button @click="richEditor.dialogVisible = false">取 消</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="questionShow.dialog" style="width: 100%;height: 100%" append-to-body>
      <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading" />
    </el-dialog>
  </div>
</template>
<script>
import QuestionShow from '@/components/PopUp/question/Show'
import Ueditor from '@/components/Ueditor'
import questionApi from '@/api/question'
import subjectApi from '@/api/subject'
export default {
  components: {
    Ueditor, QuestionShow
  },
  data() {
    return {
      subjects: [],
      form: {
        id: null,
        questionType: 4,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
        ],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      },
      formLoading: false,
      rules: {
        gradeLevel: [
          { required: true, message: '请选择年级', trigger: 'change' }
        ],
        subjectId: [
          { required: true, message: '请选择学科', trigger: 'change' }
        ],
        title: [
          { required: true, message: '请输入题干', trigger: 'blur' }
        ],
        analyze: [
          { required: true, message: '请输入解析', trigger: 'blur' }
        ],
        score: [
          { required: true, message: '请输入分数', trigger: 'blur' }
        ]
      },
      richEditor: {
        dialogVisible: false,
        object: null,
        parameterName: '',
        instance: null
      },
      questionShow: {
        qType: 0,
        dialog: false,
        question: null,
        loading: false
      },
    }
  },
  created() {
    let id = this.$route.query.id
    let _this = this
    if (id && parseInt(id) !== 0) {
      _this.formLoading = true
      questionApi.select(id).then(re => {
        _this.form = re.response
        _this.formLoading = false
      })
    }
    this.getSubjects();
  },
  methods: {
    // 获取科目
    getSubjects() {
      subjectApi.list().then(re => {
        this.subjects = re.data
      })
    },
    editorReady(instance) {
      this.richEditor.instance = instance
      let currentContent = this.richEditor.object[this.richEditor.parameterName]
      this.richEditor.instance.setContent(currentContent)
      // 光标定位到Ueditor
      this.richEditor.instance.focus(true)
    },
    inputClick(object, parameterName) {
      this.richEditor.object = object
      this.richEditor.parameterName = parameterName
      this.richEditor.dialogVisible = true
    },
    editorConfirm() {
      let content = this.richEditor.instance.getContent()
      if (this.richEditor.parameterName === 'title') { // 题干的正确答案重置
        if (this.questionItemReset(content)) {
          this.richEditor.object[this.richEditor.parameterName] = content
          this.richEditor.dialogVisible = false
        } else {
        }
      } else {
        this.richEditor.object[this.richEditor.parameterName] = content
        this.richEditor.dialogVisible = false
      }
    },
    questionItemReset(content) {
      let spanRegex = new RegExp('<span class="gapfilling-span (.*?)">(.*?)<\\/span>', 'g')
      let _this = this
      let newFormItem = []
      let gapfillingItems = content.match(spanRegex)
      if (gapfillingItems === null) {
        this.$message.error('请插入填空')
        return false
      }
      gapfillingItems.forEach(function (span, index) {
        let pairRegex = /<span class="gapfilling-span (.*?)">(.*?)<\/span>/
        pairRegex.test(span)
        newFormItem.push({ id: null, itemUuid: RegExp.$1, prefix: RegExp.$2, content: '', score: '0' })
      })
      newFormItem.forEach(function (item) {
        _this.form.items.some((oldItem, index) => {
          if (oldItem.itemUuid === item.itemUuid) {
            item.content = oldItem.content
            item.id = oldItem.id
            item.score = oldItem.score
            return true
          }
        })
      })
      _this.form.items = newFormItem
      return true
    },
    submitForm() {
      let _this = this
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.formLoading = true
          questionApi.edit(this.form).then(re => {
            if (re.code === 1) {
              _this.$message.success(re.message)
              _this.delCurrentView(_this).then(() => {
                _this.$router.push('/exam/question/list')
              })
            } else {
              _this.$message.error(re.message)
              this.formLoading = false
            }
          }).catch(e => {
            this.formLoading = false
          })
        } else {
          return false
        }
      })
    },
    showQuestion() {
      this.questionShow.dialog = true
      this.questionShow.qType = this.form.questionType
      this.questionShow.question = this.form
    },
    resetForm() {
      let lastId = this.form.id
      this.$refs['form'].resetFields()
      this.form = {
        id: null,
        questionType: 4,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
        ],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      }
      this.form.id = lastId
    }
  }
}
</script>
src/components/PopUp/multiple-choice.vue
New file
@@ -0,0 +1,225 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading"  :rules="rules">
      <el-form-item label="学科:" prop="subjectId" required>
        <el-select v-model="form.subjectId" placeholder="学科" >
          <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 label="题干:" prop="title" required>
        <el-input v-model="form.title"   @focus="inputClick(form,'title')" />
      </el-form-item>
      <el-form-item label="选项:" required>
        <el-form-item :label="item.prefix" :key="item.prefix"  v-for="(item,index) in form.items"  label-width="50px" class="question-item-label">
          <el-input v-model="item.prefix"  style="width:50px;" />
          <el-input v-model="item.content"   @focus="inputClick(item,'content')"  class="question-item-content-input"/>
          <el-button type="danger" size="mini" class="question-item-remove" icon="el-icon-delete" @click="questionItemRemove(index)"></el-button>
        </el-form-item>
      </el-form-item>
      <el-form-item label="解析:" prop="analyze" required>
        <el-input v-model="form.analyze"  @focus="inputClick(form,'analyze')" />
      </el-form-item>
      <el-form-item label="分数:" prop="score" required>
        <el-input-number v-model="form.score" :precision="1" :step="1" :max="100"></el-input-number>
      </el-form-item>
      <el-form-item label="难度:" required>
        <el-rate v-model="form.difficult" class="question-item-rate"></el-rate>
      </el-form-item>
      <el-form-item label="正确答案:" prop="correctArray" required>
        <el-checkbox-group v-model="form.correctArray">
          <el-checkbox v-for="item in form.items" :label="item.prefix" :key="item.prefix">{{item.prefix}}</el-checkbox>
        </el-checkbox-group>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
        <el-button @click="resetForm">重置</el-button>
        <el-button type="success" @click="questionItemAdd">添加选项</el-button>
        <el-button type="success" @click="showQuestion">预览</el-button>
      </el-form-item>
    </el-form>
    <el-dialog  :visible.sync="richEditor.dialogVisible"  append-to-body :close-on-click-modal="false" style="width: 100%;height: 100%"   :show-close="false" center>
      <Ueditor @ready="editorReady"/>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editorConfirm">确 定</el-button>
        <el-button @click="richEditor.dialogVisible = false">取 消</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="questionShow.dialog" style="width: 100%;height: 100%" append-to-body>
      <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading"/>
    </el-dialog>
  </div>
</template>
<script>
import QuestionShow from '@/components/PopUp/question/Show'
import Ueditor from '@/components/Ueditor'
import { mapGetters, mapState, mapActions } from 'vuex'
import questionApi from '@/api/question'
import subjectApi from '@/api/subject'
export default {
  components: {
    Ueditor, QuestionShow
  },
  data () {
    return {
      subjects: [],
      form: {
        id: null,
        questionType: 2,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
          { id: null, prefix: 'A', content: '' },
          { id: null, prefix: 'B', content: '' },
          { id: null, prefix: 'C', content: '' },
          { id: null, prefix: 'D', content: '' }
        ],
        analyze: '',
        correct: '',
        correctArray: [],
        score: '',
        difficult: 0
      },
      formLoading: false,
      rules: {
        gradeLevel: [
          { required: true, message: '请选择年级', trigger: 'change' }
        ],
        subjectId: [
          { required: true, message: '请选择学科', trigger: 'change' }
        ],
        title: [
          { required: true, message: '请输入题干', trigger: 'blur' }
        ],
        analyze: [
          { required: true, message: '请输入解析', trigger: 'blur' }
        ],
        score: [
          { required: true, message: '请输入分数', trigger: 'blur' }
        ],
        correctArray: [
          { required: true, message: '请选择正确答案', trigger: 'change' }
        ]
      },
      richEditor: {
        dialogVisible: false,
        object: null,
        parameterName: '',
        instance: null
      },
      questionShow: {
        qType: 0,
        dialog: false,
        question: null,
        loading: false
      }
    }
  },
  created () {
    let id = this.$route.query.id
    let _this = this
    if (id && parseInt(id) !== 0) {
      _this.formLoading = true
      questionApi.select(id).then(re => {
        _this.form = re.response
        _this.formLoading = false
      })
    }
    this.getSubjects();
  },
  methods: {
    // 获取科目
    getSubjects() {
      subjectApi.list().then(re => {
        this.subjects = re.data
      })
    },
    editorReady (instance) {
      this.richEditor.instance = instance
      let currentContent = this.richEditor.object[this.richEditor.parameterName]
      this.richEditor.instance.setContent(currentContent)
      // 光标定位到Ueditor
      this.richEditor.instance.focus(true)
    },
    inputClick (object, parameterName) {
      this.richEditor.object = object
      this.richEditor.parameterName = parameterName
      this.richEditor.dialogVisible = true
    },
    editorConfirm () {
      let content = this.richEditor.instance.getContent()
      this.richEditor.object[this.richEditor.parameterName] = content
      this.richEditor.dialogVisible = false
    },
    questionItemRemove (index) {
      this.form.items.splice(index, 1)
    },
    questionItemAdd () {
      let items = this.form.items
      let newLastPrefix
      if (items.length > 0) {
        let last = items[items.length - 1]
        newLastPrefix = String.fromCharCode(last.prefix.charCodeAt() + 1)
      } else {
        newLastPrefix = 'A'
      }
      items.push({ id: null, prefix: newLastPrefix, content: '' })
    },
    submitForm () {
      let _this = this
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.formLoading = true
          questionApi.edit(this.form).then(re => {
            if (re.code === 1) {
              _this.$message.success(re.message)
              _this.delCurrentView(_this).then(() => {
                _this.$router.push('/exam/question/list')
              })
            } else {
              _this.$message.error(re.message)
              this.formLoading = false
            }
          }).catch(e => {
            this.formLoading = false
          })
        } else {
          return false
        }
      })
    },
    showQuestion () {
      this.questionShow.dialog = true
      this.questionShow.qType = this.form.questionType
      this.questionShow.question = this.form
    },
    resetForm () {
      let lastId = this.form.id
      this.$refs['form'].resetFields()
      this.form = {
        id: null,
        questionType: 2,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
          { id: null, prefix: 'A', content: '' },
          { id: null, prefix: 'B', content: '' },
          { id: null, prefix: 'C', content: '' },
          { id: null, prefix: 'D', content: '' }
        ],
        analyze: '',
        correct: '',
        correctArray: [],
        score: '',
        difficult: 0
      }
      this.form.id = lastId
    },
    ...mapActions('exam', { initSubject: 'initSubject' }),
    ...mapActions('tagsView', { delCurrentView: 'delCurrentView' })
  }
}
</script>
src/components/PopUp/question/Show.vue
New file
@@ -0,0 +1,62 @@
<template>
  <div style="line-height:1.8">
    <div v-if="qType==1" v-loading="qLoading">
      <div class="q-title" v-html="question.title"/>
      <div class="q-content">
          <span :key="item.id" v-for="item in question.items" class="q-item-contain">
            <span class="q-item-prefix">{{item.prefix}}</span>
            <span v-html="item.content" class="q-item-content"></span>
          </span>
      </div>
    </div>
    <div v-else-if="qType==2" v-loading="qLoading">
      <div class="q-title" v-html="question.title"/>
      <div class="q-content">
          <span :key="item.id" v-for="item in question.items" class="q-item-contain">
            <span class="q-item-prefix">{{item.prefix}}</span>
            <span v-html="item.content" class="q-item-content"></span>
          </span>
      </div>
    </div>
    <div v-else-if="qType==3" v-loading="qLoading">
      <div class="q-title" v-html="question.title" style="display: inline;margin-right: 10px"/>
      <span>(</span>
      <span :key="item.id" v-for="item in question.items">
        <span v-html="item.content" class="q-item-content"></span>
       </span>
      <span>)</span>
    </div>
    <div v-else-if="qType==4" v-loading="qLoading">
      <div class="q-title" v-html="question.title"/>
    </div>
    <div v-else-if="qType==5" v-loading="qLoading">
      <div class="q-title" v-html="question.title"/>
    </div>
    <div v-else>
    </div>
  </div>
</template>
<script>
export default {
  name: 'QuestionShow',
  props: {
    question: {
      type: Object,
      default: function () {
        return {}
      }
    },
    qLoading: {
      type: Boolean,
      default: false
    },
    qType: {
      type: Number,
      default: 0
    }
  },
  methods: {}
}
</script>
src/components/PopUp/short-answer.vue
New file
@@ -0,0 +1,188 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading" :rules="rules">
      <el-form-item label="学科:" prop="subjectId" required>
        <el-select v-model="form.subjectId" placeholder="学科" >
          <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 label="题干:" prop="title" required>
        <el-input v-model="form.title"   @focus="inputClick(form,'title')" />
      </el-form-item>
      <el-form-item label="答案:" prop="correct" required>
        <el-input v-model="form.correct"   @focus="inputClick(form,'correct')" />
      </el-form-item>
      <el-form-item label="解析:" prop="analyze" required>
        <el-input v-model="form.analyze"  @focus="inputClick(form,'analyze')" />
      </el-form-item>
      <el-form-item label="分数:" prop="score" required>
        <el-input-number v-model="form.score" :precision="1" :step="1" :max="100"></el-input-number>
      </el-form-item>
      <el-form-item label="难度:" required>
        <el-rate v-model="form.difficult" class="question-item-rate"></el-rate>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
        <el-button @click="resetForm">重置</el-button>
        <el-button type="success" @click="showQuestion">预览</el-button>
      </el-form-item>
    </el-form>
    <el-dialog  :visible.sync="richEditor.dialogVisible"  append-to-body :close-on-click-modal="false" style="width: 100%;height: 100%"   :show-close="false" center>
      <Ueditor @ready="editorReady"/>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editorConfirm">确 定</el-button>
        <el-button @click="richEditor.dialogVisible = false">取 消</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="questionShow.dialog" style="width: 100%;height: 100%" append-to-body>
      <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading"/>
    </el-dialog>
  </div>
</template>
<script>
import QuestionShow from '@/components/PopUp/question/Show'
import Ueditor from '@/components/Ueditor'
import { mapGetters, mapState, mapActions } from 'vuex'
import questionApi from '@/api/question'
import subjectApi from '@/api/subject'
export default {
  components: {
    Ueditor, QuestionShow
  },
  data () {
    return {
      subjects: [],
      form: {
        id: null,
        questionType: 5,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      },
      subjectFilter: null,
      formLoading: false,
      rules: {
        gradeLevel: [
          { required: true, message: '请选择年级', trigger: 'change' }
        ],
        subjectId: [
          { required: true, message: '请选择学科', trigger: 'change' }
        ],
        title: [
          { required: true, message: '请输入题干', trigger: 'blur' }
        ],
        correct: [
          { required: true, message: '请输入答案', trigger: 'blur' }
        ],
        analyze: [
          { required: true, message: '请输入解析', trigger: 'blur' }
        ],
        score: [
          { required: true, message: '请输入分数', trigger: 'blur' }
        ]
      },
      richEditor: {
        dialogVisible: false,
        object: null,
        parameterName: '',
        instance: null
      },
      questionShow: {
        qType: 0,
        dialog: false,
        question: null,
        loading: false
      }
    }
  },
  created () {
    let id = this.$route.query.id
    let _this = this
    if (id && parseInt(id) !== 0) {
      _this.formLoading = true
      questionApi.select(id).then(re => {
        _this.form = re.response
        _this.formLoading = false
      })
    }
    this.getSubjects();
  },
  methods: {
    // 获取科目
    getSubjects() {
      subjectApi.list().then(re => {
        this.subjects = re.data
      })
    },
    editorReady (instance) {
      this.richEditor.instance = instance
      let currentContent = this.richEditor.object[this.richEditor.parameterName]
      this.richEditor.instance.setContent(currentContent)
      // 光标定位到Ueditor
      this.richEditor.instance.focus(true)
    },
    inputClick (object, parameterName) {
      this.richEditor.object = object
      this.richEditor.parameterName = parameterName
      this.richEditor.dialogVisible = true
    },
    editorConfirm () {
      let content = this.richEditor.instance.getContent()
      this.richEditor.object[this.richEditor.parameterName] = content
      this.richEditor.dialogVisible = false
    },
    submitForm () {
      let _this = this
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.formLoading = true
          questionApi.edit(this.form).then(re => {
            if (re.code === 1) {
              _this.$message.success(re.message)
              _this.delCurrentView(_this).then(() => {
                _this.$router.push('/exam/question/list')
              })
            } else {
              _this.$message.error(re.message)
              this.formLoading = false
            }
          }).catch(e => {
            this.formLoading = false
          })
        } else {
          return false
        }
      })
    },
    resetForm () {
      let lastId = this.form.id
      this.$refs['form'].resetFields()
      this.form = {
        id: null,
        questionType: 5,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      }
      this.form.id = lastId
    },
    showQuestion () {
      this.questionShow.dialog = true
      this.questionShow.qType = this.form.questionType
      this.questionShow.question = this.form
    }
  }
}
</script>
src/components/PopUp/single-choice.vue
New file
@@ -0,0 +1,222 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading" :rules="rules">
      <el-form-item label="学科:" prop="subjectId" required>
        <el-select v-model="form.subjectId" placeholder="学科" >
          <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 label="题干:" prop="title" required>
        <el-input v-model="form.title"   @focus="inputClick(form,'title')" />
      </el-form-item>
      <el-form-item label="选项:" required>
        <el-form-item :label="item.prefix" :key="item.prefix"  v-for="(item,index) in form.items"  label-width="50px" class="question-item-label">
          <el-input v-model="item.prefix"  style="width:50px;" />
          <el-input v-model="item.content"   @focus="inputClick(item,'content')"  class="question-item-content-input"/>
           <el-button type="danger" size="mini" class="question-item-remove" icon="el-icon-delete" @click="questionItemRemove(index)"></el-button>
        </el-form-item>
      </el-form-item>
      <el-form-item label="解析:" prop="analyze" required>
        <el-input v-model="form.analyze"  @focus="inputClick(form,'analyze')" />
      </el-form-item>
      <el-form-item label="分数:" prop="score" required>
        <el-input-number v-model="form.score" :precision="1" :step="1" :max="100"></el-input-number>
      </el-form-item>
      <el-form-item label="难度:" required>
        <el-rate v-model="form.difficult" class="question-item-rate"></el-rate>
      </el-form-item>
      <el-form-item label="正确答案:" prop="correct" required>
        <el-radio-group v-model="form.correct">
          <el-radio  v-for="item in form.items"  :key="item.prefix"  :label="item.prefix">{{item.prefix}}</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
        <el-button @click="resetForm">重置</el-button>
        <el-button type="success" @click="questionItemAdd">添加选项</el-button>
        <el-button type="success" @click="showQuestion">预览</el-button>
      </el-form-item>
    </el-form>
    <el-dialog  :visible.sync="richEditor.dialogVisible"  append-to-body :close-on-click-modal="false" style="width: 100%;height: 100%"   :show-close="false" center>
      <Ueditor @ready="editorReady"/>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editorConfirm">确 定</el-button>
        <el-button @click="richEditor.dialogVisible = false">取 消</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="questionShow.dialog" style="width: 100%;height: 100%" append-to-body>
      <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading"/>
    </el-dialog>
  </div>
</template>
<script>
import QuestionShow from '@/components/PopUp/question/Show'
import Ueditor from '@/components/Ueditor'
import { mapGetters, mapState, mapActions } from 'vuex'
import questionApi from '@/api/question'
import subjectApi from '@/api/subject'
export default {
  components: {
    Ueditor, QuestionShow
  },
  data () {
    return {
      subjects: [],
      form: {
        id: null,
        questionType: 1,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
          { prefix: 'A', content: '' },
          { prefix: 'B', content: '' },
          { prefix: 'C', content: '' },
          { prefix: 'D', content: '' }
        ],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      },
      subjectFilter: null,
      formLoading: false,
      rules: {
        gradeLevel: [
          { required: true, message: '请选择年级', trigger: 'change' }
        ],
        subjectId: [
          { required: true, message: '请选择学科', trigger: 'change' }
        ],
        title: [
          { required: true, message: '请输入题干', trigger: 'blur' }
        ],
        analyze: [
          { required: true, message: '请输入解析', trigger: 'blur' }
        ],
        score: [
          { required: true, message: '请输入分数', trigger: 'blur' }
        ],
        correct: [
          { required: true, message: '请选择正确答案', trigger: 'change' }
        ]
      },
      richEditor: {
        dialogVisible: false,
        object: null,
        parameterName: '',
        instance: null
      },
      questionShow: {
        qType: 0,
        dialog: false,
        question: null,
        loading: false
      }
    }
  },
  created () {
    let id = this.$route.query.id
    let _this = this
    if (id && parseInt(id) !== 0) {
      _this.formLoading = true
      questionApi.select(id).then(re => {
        _this.form = re.response
        _this.formLoading = false
      })
    }
    this.getSubjects();
  },
  methods: {
    // 获取科目
    getSubjects() {
      subjectApi.list().then(re => {
        this.subjects = re.data
      })
    },
    editorReady (instance) {
      this.richEditor.instance = instance
      let currentContent = this.richEditor.object[this.richEditor.parameterName]
      this.richEditor.instance.setContent(currentContent)
      // 光标定位到Ueditor
      this.richEditor.instance.focus(true)
    },
    inputClick (object, parameterName) {
      this.richEditor.object = object
      this.richEditor.parameterName = parameterName
      this.richEditor.dialogVisible = true
    },
    editorConfirm () {
      let content = this.richEditor.instance.getContent()
      this.richEditor.object[this.richEditor.parameterName] = content
      this.richEditor.dialogVisible = false
    },
    questionItemRemove (index) {
      this.form.items.splice(index, 1)
    },
    questionItemAdd () {
      let items = this.form.items
      let newLastPrefix
      if (items.length > 0) {
        let last = items[items.length - 1]
        newLastPrefix = String.fromCharCode(last.prefix.charCodeAt() + 1)
      } else {
        newLastPrefix = 'A'
      }
      items.push({ id: null, prefix: newLastPrefix, content: '' })
    },
    submitForm () {
      let _this = this
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.formLoading = true
          questionApi.edit(this.form).then(re => {
            if (re.code === 1) {
              _this.$message.success(re.message)
              _this.delCurrentView(_this).then(() => {
                _this.$router.push('/exam/question/list')
              })
            } else {
              _this.$message.error(re.message)
              this.formLoading = false
            }
          }).catch(e => {
            this.formLoading = false
          })
        } else {
          return false
        }
      })
    },
    resetForm () {
      let lastId = this.form.id
      this.$refs['form'].resetFields()
      this.form = {
        id: null,
        questionType: 1,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
          { prefix: 'A', content: '' },
          { prefix: 'B', content: '' },
          { prefix: 'C', content: '' },
          { prefix: 'D', content: '' }
        ],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      }
      this.form.id = lastId
    },
    showQuestion () {
      this.questionShow.dialog = true
      this.questionShow.qType = this.form.questionType
      this.questionShow.question = this.form
    }
  }
}
</script>
src/components/PopUp/true-false.vue
New file
@@ -0,0 +1,202 @@
<template>
  <div class="app-container">
    <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading"  :rules="rules">
      <el-form-item label="学科:" prop="subjectId" required>
        <el-select v-model="form.subjectId" placeholder="学科" >
          <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 label="题干:" prop="title" required>
        <el-input v-model="form.title"   @focus="inputClick(form,'title')" />
      </el-form-item>
      <el-form-item label="选项:" required>
        <el-form-item :label="item.prefix" :key="item.prefix"  v-for="(item) in form.items"  label-width="50px" class="question-item-label">
          <el-input v-model="item.prefix"  style="width:50px;" />
          <el-input v-model="item.content"   @focus="inputClick(item,'content')"  class="question-item-content-input"/>
        </el-form-item>
      </el-form-item>
      <el-form-item label="解析:" prop="analyze" required>
        <el-input v-model="form.analyze"  @focus="inputClick(form,'analyze')" />
      </el-form-item>
      <el-form-item label="分数:" prop="score" required>
        <el-input-number v-model="form.score" :precision="1" :step="1" :max="100"></el-input-number>
      </el-form-item>
      <el-form-item label="难度:" required>
        <el-rate v-model="form.difficult" class="question-item-rate"></el-rate>
      </el-form-item>
      <el-form-item label="正确答案:" prop="correct" required>
        <el-radio-group v-model="form.correct">
          <el-radio  v-for="item in form.items"  :key="item.prefix"  :label="item.prefix">{{item.prefix}}</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
        <el-button @click="resetForm">重置</el-button>
        <el-button type="success" @click="showQuestion">预览</el-button>
      </el-form-item>
    </el-form>
    <el-dialog  :visible.sync="richEditor.dialogVisible"  append-to-body :close-on-click-modal="false" style="width: 100%;height: 100%"   :show-close="false" center>
      <Ueditor @ready="editorReady"/>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editorConfirm">确 定</el-button>
        <el-button @click="richEditor.dialogVisible = false">取 消</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="questionShow.dialog" style="width: 100%;height: 100%" append-to-body>
      <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading"/>
    </el-dialog>
  </div>
</template>
<script>
import QuestionShow from '@/components/PopUp/question/Show'
import Ueditor from '@/components/Ueditor'
import { mapGetters, mapState, mapActions } from 'vuex'
import questionApi from '@/api/question'
import subjectApi from '@/api/subject'
export default {
  components: {
    Ueditor, QuestionShow
  },
  data () {
    return {
      subjects: [],
      form: {
        id: null,
        questionType: 3,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
          { id: null, prefix: 'A', content: '是' },
          { id: null, prefix: 'B', content: '否' }
        ],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      },
      subjectFilter: null,
      formLoading: false,
      rules: {
        gradeLevel: [
          { required: true, message: '请选择年级', trigger: 'change' }
        ],
        subjectId: [
          { required: true, message: '请选择学科', trigger: 'change' }
        ],
        title: [
          { required: true, message: '请输入题干', trigger: 'blur' }
        ],
        analyze: [
          { required: true, message: '请输入解析', trigger: 'blur' }
        ],
        score: [
          { required: true, message: '请输入分数', trigger: 'blur' }
        ],
        correct: [
          { required: true, message: '请选择正确答案', trigger: 'change' }
        ]
      },
      richEditor: {
        dialogVisible: false,
        object: null,
        parameterName: '',
        instance: null
      },
      questionShow: {
        qType: 0,
        dialog: false,
        question: null,
        loading: false
      }
    }
  },
  created () {
    let id = this.$route.query.id
    let _this = this
    if (id && parseInt(id) !== 0) {
      _this.formLoading = true
      questionApi.select(id).then(re => {
        _this.form = re.response
        _this.formLoading = false
      })
    }
    this.getSubjects();
  },
  methods: {
    // 获取科目
    getSubjects() {
      subjectApi.list().then(re => {
        this.subjects = re.data
      })
    },
    editorReady (instance) {
      this.richEditor.instance = instance
      let currentContent = this.richEditor.object[this.richEditor.parameterName]
      this.richEditor.instance.setContent(currentContent)
      // 光标定位到Ueditor
      this.richEditor.instance.focus(true)
    },
    inputClick (object, parameterName) {
      this.richEditor.object = object
      this.richEditor.parameterName = parameterName
      this.richEditor.dialogVisible = true
    },
    editorConfirm () {
      let content = this.richEditor.instance.getContent()
      this.richEditor.object[this.richEditor.parameterName] = content
      this.richEditor.dialogVisible = false
    },
    submitForm () {
      let _this = this
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.formLoading = true
          questionApi.edit(this.form).then(re => {
            if (re.code === 1) {
              _this.$message.success(re.message)
              _this.delCurrentView(_this).then(() => {
                _this.$router.push('/exam/question/list')
              })
            } else {
              _this.$message.error(re.message)
              this.formLoading = false
            }
          }).catch(e => {
            this.formLoading = false
          })
        } else {
          return false
        }
      })
    },
    resetForm () {
      let lastId = this.form.id
      this.$refs['form'].resetFields()
      this.form = {
        id: null,
        questionType: 3,
        gradeLevel: null,
        subjectId: null,
        title: '',
        items: [
          { id: null, prefix: 'A', content: '是' },
          { id: null, prefix: 'B', content: '否' }
        ],
        analyze: '',
        correct: '',
        score: '',
        difficult: 0
      }
      this.form.id = lastId
    },
    showQuestion () {
      this.questionShow.dialog = true
      this.questionShow.qType = this.form.questionType
      this.questionShow.question = this.form
    }
  }
}
</script>
src/views/Manage/TestPaper/QuestionBank.vue
@@ -8,213 +8,141 @@
        <div class="content">
          <!-- 试卷生成按钮 -->
          <div style="padding-bottom:20px; border-bottom: 3px solid #409EFF;margin-bottom: 20px;">
            <el-button
              type="primary"
              @click="getDialogFormVisible"
            >录入题目</el-button>
            <el-popover placement="bottom" trigger="click">
              <el-button type="warning" size="mini" v-for="item in editUrlEnum" :key="item.key"
                @click="getDialogFormVisible(item.name)">{{ item.name }}
              </el-button>
              <el-button slot="reference" type="primary" class="link-left">录入题目</el-button>
            </el-popover>
          </div>
          <!-- 搜索 -->
          <div>
            <el-form
              :inline="true"
              :model="formLabelAlign"
              class="demo-form-inline"
              label-width="80px"
            >
            <el-form :inline="true" :model="formLabelAlign" class="demo-form-inline" label-width="80px">
              <el-form-item>
                <el-input
                  v-model="formLabelAlign.type"
                  placeholder="题目名"
                ></el-input>
                <el-input v-model="formLabelAlign.type" placeholder="题目名"></el-input>
              </el-form-item>
              <el-form-item>
                <el-select
                  v-model="formLabelAlign.region"
                  placeholder="全部科目"
                >
                  <el-option
                    label="全部科目"
                    value="shanghai"
                  ></el-option>
                  <el-option
                    label="语文"
                    value="beijing"
                  ></el-option>
                  <el-option
                    label="数学"
                    value="beijing"
                  ></el-option>
                  <el-option
                    label="英语"
                    value="beijing"
                  ></el-option>
                <el-select v-model="formLabelAlign.region" placeholder="全部科目">
                  <el-option label="全部科目" value="shanghai"></el-option>
                  <el-option label="语文" value="beijing"></el-option>
                  <el-option label="数学" value="beijing"></el-option>
                  <el-option label="英语" value="beijing"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-select
                  v-model="formLabelAlign.region"
                  placeholder="选择题"
                >
                  <el-option
                    label="选择题"
                    value="shanghai"
                  ></el-option>
                  <el-option
                    label="问答题"
                    value="beijing"
                  ></el-option>
                  <el-option
                    label="判断题"
                    value="beijing"
                  ></el-option>
                <el-select v-model="formLabelAlign.region" placeholder="选择题">
                  <el-option label="选择题" value="shanghai"></el-option>
                  <el-option label="问答题" value="beijing"></el-option>
                  <el-option label="判断题" value="beijing"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="">
                <el-button
                  style="width:100px;"
                  type="primary"
                  size="small"
                >查询</el-button>
                <el-button style="width:100px;" type="primary" size="small" @click="search()">查询</el-button>
              </el-form-item>
            </el-form>
          </div>
          <!-- 表格 -->
          <el-table
            :header-cell-style="getRowClass"
            :data="tableData"
            border
            style="width: 100%;"
          >
            <el-table-column
              align="center"
              prop="title"
              label="题目名"
            >
          <el-table v-loading="listLoading" :header-cell-style="getRowClass" :data="tableData" border style="width: 100%;">
            <el-table-column align="center" prop="title" label="题目名">
            </el-table-column>
            <el-table-column
              align="center"
              prop="subject"
              label="科目"
            >
            <el-table-column align="center" prop="subject" label="科目">
            </el-table-column>
            <el-table-column
              align="center"
              prop="type"
              label="题目类型"
            >
            <el-table-column align="center" prop="type" label="题目类型">
            </el-table-column>
            <el-table-column
              align="center"
              prop="score"
              label="参考答案"
            >
            <el-table-column align="center" prop="score" label="参考答案">
            </el-table-column>
            <el-table-column
              label="操作"
              align="center"
            >
            <el-table-column label="操作" align="center">
              <el-button type="text">编辑</el-button>
              <el-button type="text">删除</el-button>
            </el-table-column>
          </el-table>
          <div
            class="block"
            style="display: flex; margin-top: 40px;"
          >
            <el-pagination
              style="margin:auto"
              background
              :page-size="10"
              layout="prev, pager, next, jumper"
              :total="100"
            >
            </el-pagination>
          <div class="block" style="display: flex; margin-top: 40px;">
            <pagination v-show="total > 0" :total="total" :page.sync="queryParam.pageIndex"
              :limit.sync="queryParam.pageSize" @pagination="search" />
          </div>
        </div>
      </div>
    </div>
    <PopUp
      ref="popUp"
      @children="parentGoods"
    />
    <!-- 填空 -->
    <el-dialog :visible.sync="gapVisible" :close-on-click-modal="false">
      <gap ref="gap" @children="parentGoods" />
    </el-dialog>
    <!-- 多选 -->
    <el-dialog :visible.sync="multipleVisible" :close-on-click-modal="false">
      <multiple ref="multiple" @children="parentGoods" />
    </el-dialog>
    <!-- 简答 -->
    <el-dialog :visible.sync="shortVisible" :close-on-click-modal="false">
      <short ref="short" @children="parentGoods" />
    </el-dialog>
    <!-- 单选 -->
    <el-dialog :visible.sync="singleVisible" :close-on-click-modal="false">
      <single ref="single" @children="parentGoods" />
    </el-dialog>
    <!-- 判断 -->
    <el-dialog :visible.sync="truesVisible" :close-on-click-modal="false">
      <trues ref="trues" @children="parentGoods" />
    </el-dialog>
  </div>
</template>
<script>
// 引入彈出窗口組件
import PopUp from "../../../components/PopUp/Question.vue";
import gap from "@/components/PopUp/gap-filling.vue";
import multiple from "@/components/PopUp/multiple-choice.vue";
import short from "@/components/PopUp/short-answer.vue";
import single from "@/components/PopUp/single-choice.vue";
import trues from "@/components/PopUp/true-false.vue";
import { mapGetters, mapState } from 'vuex'
import questionApi from '@/api/question'
export default {
  // 注册
  components: {
    PopUp,
    gap,
    multiple,
    short,
    single,
    trues,
  },
  data() {
    return {
      listLoading: true,
      queryParam: {
        questionType: null,
        subjectId: null,
        pageIndex: 1,
        pageSize: 10
      },
      total: 0,
      gapVisible: false,
      multipleVisible: false,
      shortVisible: false,
      singleVisible: false,
      truesVisible: false,
      formLabelAlign: {
        type: "",
        user: "",
        region: "",
      },
      tableData: [
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A", "B"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
        {
          title: "当A与B一起修路",
          type: "选择题",
          subject: "语文",
          score: ["A"],
        },
      ],
      tableData: [],
    };
  },
  created() {
    this.search()
  },
  methods: {
    // 获取列表
    search() {
      this.listLoading = true
      questionApi.pageList(this.queryParam).then(re => {
        this.tableData = re.data
        this.total = re.total
        this.queryParam.pageIndex = re.pageNum
        this.listLoading = false
      })
    },
    // 返回上一个页面
    goBack() {
      this.$router.back();
@@ -223,7 +151,6 @@
    getRowClass() {
      return "background:#d2d3d6";
    },
    // 生成试卷
    getCreate() {
      // 跳转到生成页面
@@ -232,10 +159,25 @@
        path: "/manage/test-paper-generation",
      });
    },
    // 点击后调用弹窗组件的方法,开启弹窗
    getDialogFormVisible() {
      this.$refs.popUp.showDialog();
    getDialogFormVisible(value) {
      switch (value) {
        case "填空题":
          this.gapVisible = true;
          break;
        case "多选题":
          this.multipleVisible = true;
          break;
        case "简答题":
          this.shortVisible = true;
          break;
        case "单选题":
          this.singleVisible = true;
          break;
        case "判断题":
          this.truesVisible = true;
          break;
      }
    },
    // 弹窗
    // 接收弹窗组件返回的表单值
@@ -243,12 +185,21 @@
      console.log(obj, "弹窗组件的表单值");
    },
  },
  computed: {
    ...mapGetters('enumItem', ['enumFormat']),
    ...mapState('enumItem', {
      questionTypeEnum: state => state.exam.question.typeEnum,
      editUrlEnum: state => state.exam.question.editUrlEnum
    }),
    ...mapState('exam', { subjects: state => state.subjects })
  }
};
</script>
<style scoped lang="scss">
.flex {
  display: flex;
}
// 内容
.content {
  width: 1262px;
@@ -258,5 +209,3 @@
  border-radius: 10px;
}
</style>