| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731 |
- <template>
- <el-container>
- <el-header height="220">
- <el-steps :active="curStep" simple>
- <el-step title="组卷配置" icon="el-icon-edit" />
- <el-step title="考试权限" icon="el-icon-lock" />
- <el-step title="补充配置" icon="el-icon-setting" />
- </el-steps>
- <el-button v-show="curStep !== 1" style="margin-top: 10px" @click="curStep--">
- 上一步
- </el-button>
- <el-button v-show="curStep !== 3" style="float:right;margin-top: 10px" type="primary" @click="curStep++">
- 下一步
- </el-button>
- <el-button v-show="curStep === 3" style="float:right;margin-top: 10px" type="primary" @click="createExamPaper">
- 创建试卷
- </el-button>
- </el-header>
- <el-main>
- <!--设置试题信息-->
- <el-card v-show="curStep === 1">
- <el-radio-group
- v-model="makeModel"
- size="medium"
- @change="makeModelChange"
- >
- <el-radio :label="1" border>自由组卷</el-radio>
- <el-radio :label="2" border>题库组卷</el-radio>
- </el-radio-group>
- <span v-show="makeModel === 1" style="float: right;color: red;font-weight: bold">
- {{ '试卷总分:' + sumTotalScore }}
- </span>
- <!-- 自由组卷内容-->
- <div v-show="makeModel === 1" style="margin-top: 25px">
- <el-button icon="el-icon-plus" size="mini" @click="showAddDialog">添加试题</el-button>
- <el-table :data="addExamQuestion1" border style="margin-top: 10px">
- <el-table-column type="index" label="顺序" />
- <el-table-column label="题目内容" align="center">
- <template slot-scope="scope">
- {{ scope.row.content.substr(0, 20) }}
- </template>
- </el-table-column>
- <el-table-column
- align="center"
- label="题目类型"
- prop="type"
- />
- <el-table-column label="单题分数" align="center">
- <template slot-scope="scope">
- <div v-if="scope.row.typeCode !== 8">
- <el-input-number v-model="scope.row.score" :min="1" :max="20" style="margin-left: 5px" />
- </div>
- <div v-else>
- <el-button icon="el-icon-plus" size="mini" @click="showGroupDialog(scope.row.questionId)">
- 设置组合题分数
- </el-button>
- <span>{{scope.row.score}}</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="80" align="center">
- <template slot-scope="scope">
- <el-button
- type="danger"
- icon="el-icon-delete"
- circle
- @click="delQuestion(scope.row.questionId)"
- />
- </template>
- </el-table-column>
- </el-table>
- </div>
- <!-- 题库组卷内容-->
- <div v-show="makeModel === 2" style="margin-top: 25px">
- <el-button icon="el-icon-plus" size="mini" @click="addBank">添加题库</el-button>
- <!--存放题目的信息-->
- <el-table :data="addExamQuestion2" border style="margin-top: 10px">
- <el-table-column label="题库" width="155" align="center">
- <template slot-scope="scope">
- <el-select
- v-model="scope.row.bankName"
- clearable
- placeholder="请选择题库"
- style="margin-left: 5px"
- >
- <el-option
- v-for="item in allSubject"
- :key="item.questionBank.bankId"
- :label="item.questionBank.bankName"
- :value="item.questionBank.bankName"
- />
- </el-select>
- </template>
- </el-table-column>
- <el-table-column label="单选题分数" align="center">
- <template slot-scope="scope">
- <el-input v-model="scope.row.singleScore" style="margin-left: 5px" />
- </template>
- </el-table-column>
- <el-table-column label="多选题分数" align="center">
- <template slot-scope="scope">
- <el-input v-model="scope.row.multipleScore" style="margin-left: 5px" />
- </template>
- </el-table-column>
- <el-table-column label="判断题分数" align="center">
- <template slot-scope="scope">
- <el-input v-model="scope.row.judgeScore" style="margin-left: 5px" />
- </template>
- </el-table-column>
- <el-table-column label="简答题分数" align="center">
- <template slot-scope="scope">
- <el-input v-model="scope.row.shortScore" style="margin-left: 5px" />
- </template>
- </el-table-column>
- <el-table-column label="操作" width="80" align="center">
- <template slot-scope="scope">
- <el-button type="danger" icon="el-icon-delete" circle @click="delBank(scope.row.bankId)" />
- </template>
- </el-table-column>
- </el-table>
- </div>
- </el-card>
- <!--设置考试权限-->
- <el-card v-show="curStep === 2">
- <el-radio-group v-model="examAuthority" size="medium">
- <el-radio :label="1" border>完全公开</el-radio>
- <el-radio :label="2" border>需要密码</el-radio>
- </el-radio-group>
- <el-alert
- style="margin-top: 15px"
- :title="examAuthority === 1? '开放的,任何人都可以进行考试!' : '半开放的,知道密码的人员才可以考试!'"
- type="warning"
- />
- <el-input
- v-show="examAuthority === 2"
- v-model="examPassword"
- style="margin-top: 15px;width: 20%"
- type="password"
- show-password
- placeholder="输入考试密码"
- />
- </el-card>
- <!--设置考试信息-->
- <el-card v-show="curStep === 3">
- <el-form ref="examInfoForm" :model="examInfo" :rules="examInfoRules" label-width="100px">
- <el-form-item label="考试名称" prop="examName">
- <el-input v-model="examInfo.examName" />
- </el-form-item>
- <el-form-item label="考试描述" prop="examDesc">
- <el-input v-model="examInfo.examDesc" />
- </el-form-item>
- <el-form-item v-show="makeModel === 1" label="总分数" prop="totalScore">
- <el-input-number :value="sumTotalScore" :disabled="true" />
- </el-form-item>
- <el-form-item label="及格分数" prop="passScore">
- <el-input-number v-model="examInfo.passScore" :min="1" :max="parseInt(sumTotalScore)" />
- </el-form-item>
- <el-form-item label="考试时长(分钟)" prop="examDuration">
- <el-input-number v-model="examInfo.examDuration" :min="1" :max="120" />
- </el-form-item>
- <el-form-item label="考试开始时间" prop="startTime">
- <el-date-picker
- v-model="examInfo.startTime"
- style="margin-left: 5px"
- type="datetime"
- placeholder="考试开始时间"
- />
- </el-form-item>
- <el-form-item label="考试结束时间" prop="endTime">
- <el-date-picker
- v-model="examInfo.endTime"
- style="margin-left: 5px"
- type="datetime"
- placeholder="考试结束时间"
- />
- </el-form-item>
- </el-form>
- </el-card>
- </el-main>
- <el-dialog title="添加试题" :visible.sync="showQuestionDialog" width="80%" center>
- <el-row>
- <el-select
- v-model="queryInfo.subjectId"
- clearable
- placeholder="请选择科目"
- style="margin-left: 5px"
- @change="subjectChange"
- >
- <el-option
- v-for="item in allSubject"
- :key="item.key"
- :label="item.value"
- :value="item.key"
- />
- </el-select>
- <el-select v-model="queryInfo.questionType" clearable placeholder="请选择试题类型" @change="typeChange">
- <el-option
- v-for="item in allType"
- :key="item.key"
- :label="item.value"
- :value="item.key"
- />
- </el-select>
- <el-input
- v-model="queryInfo.questionContent"
- placeholder="题目内容"
- style="margin-left: 5px;width: 220px"
- prefix-icon="el-icon-search"
- @blur="getQuestionInfo"
- />
- <el-button type="primary" style="float: right" @click="addQuToFree">确认{{ selectedTable.length }}项</el-button>
- </el-row>
- <el-table
- ref="questionTable"
- v-loading="loading"
- highlight-current-row
- :border="true"
- :data="dataList"
- tooltip-effect="dark"
- style="width: 100%;margin-top: 25px;"
- @selection-change="handleTableSectionChange"
- >
- <el-table-column
- align="center"
- type="selection"
- width="55"
- />
- <el-table-column
- align="center"
- label="题目类型"
- prop="type"
- />
- <el-table-column align="center" label="题目内容">
- <template slot-scope="scope">
- <span class="quContent">{{ scope.row.content.substr(0, 20) }}</span>
- </template>
- </el-table-column>
- <el-table-column
- align="center"
- label="难度"
- prop="level"
- />
- <el-table-column
- align="center"
- prop="subject"
- label="所属科目"
- />
- <el-table-column
- align="center"
- prop="createBy"
- label="创建人"
- />
- <el-table-column
- align="center"
- label="创建时间"
- >
- <template slot-scope="scope">
- {{ scope.row.createAt }}
- </template>
- </el-table-column>
- </el-table>
- <!--分页-->
- <el-pagination
- style="margin-top: 25px"
- layout="total, sizes, prev, pager, next, jumper"
- :page-sizes="[10, 20, 50]"
- :page-size="pageSize"
- :current-page="currentPage"
- :total="totalSize"
- @current-change="handleCurrentChange"
- @prev-click="handleCurrentChange"
- @next-click="handleCurrentChange"
- />
- </el-dialog>
- <el-dialog title="组合题分数设置" :visible.sync="showGroupQuestionDialog" width="80%" center>
- <el-button icon="el-icon-plus" size="mini" @click="confirmChildScore">确定</el-button>
- <el-table
- highlight-current-row
- :border="true"
- :data="groupQuestionList"
- tooltip-effect="dark"
- style="width: 100%;margin-top: 25px;"
- >
- <el-table-column
- align="center"
- type="selection"
- width="55"
- />
- <el-table-column
- align="center"
- label="题目类型"
- prop="type"
- />
- <el-table-column align="center" label="题目内容">
- <template slot-scope="scope">
- <span class="quContent">{{ scope.row.content.substr(0, 20) }}</span>
- </template>
- </el-table-column>
- <el-table-column
- align="center"
- label="单题分数"
- prop="score"
- >
- <template slot-scope="scope">
- <el-input-number v-model="scope.row.score" :min="1" :max="20" style="margin-left: 5px" />
- </template>
- </el-table-column>
- <el-table-column
- align="center"
- prop="subject"
- label="所属科目"
- />
- </el-table>
- </el-dialog>
- </el-container>
- </template>
- <script>
- import { getQuestions, getQuestionType, getSubjectKV, addPaper, getQuestion } from '@/api/exam'
- import { validFormAndInvoke } from '@/utils/util'
- export default {
- name: 'ExamPaperAdd',
- props: ['tagInfo'],
- data() {
- return {
- currentPage: 1,
- pageSize: 20,
- totalSize: 0,
- dataList: [],
- // 查询题目的参数
- queryInfo: {
- subjectId: null,
- type: null,
- level: null,
- pageNumber: 1,
- pageSize: 10
- },
- // 所有题库信息
- allSubject: [],
- allType: [],
- // 当前的步骤
- curStep: 1,
- // 组卷模式
- makeModel: 1,
- // 添加考试题目信息(makeModel = 1的时候)
- addExamQuestion1: [],
- // 添加考试题目信息(makeModel = 2 的时候)
- addExamQuestion2: [],
- // 所有题目的对话框
- groupQuestionId: null,
- showQuestionDialog: false,
- showGroupQuestionDialog: false,
- groupQuestionList: [],
- // 对话框中题目表格的加载
- loading: true,
- // 所有题目的信息
- questionInfo: [],
- // 所有题目的对话框中表格被选中
- selectedTable: [],
- // 所有题目总数
- total: 0,
- // 考试权限(1公开, 2密码)
- examAuthority: 1,
- // 考试密码(权限为2时的密码)
- examPassword: '',
- // 补充的考试信息
- examInfo: {
- examId: null,
- examDesc: null,
- passScore: 0,
- examDuration: 0,
- startTime: null,
- endTime: null
- },
- // 补充的考试信息的表单验证
- examInfoRules: {
- examName: [
- {
- required: true,
- message: '请输入考试名称',
- trigger: 'blur'
- }
- ],
- passScore: [
- {
- required: true,
- message: '请输入通过分数',
- trigger: 'blur'
- }
- ],
- examDuration: [
- {
- required: true,
- message: '请输入考试时长',
- trigger: 'blur'
- }
- ]
- }
- }
- },
- computed: {
- // 计算总分
- sumTotalScore() {
- if (this.makeModel === 1) {
- let score = 0
- this.addExamQuestion1.forEach(item => {
- score += parseInt(item.score)
- })
- return score
- }
- }
- },
- created() {
- document.title = '组卷管理'
- // 一创建就改变头部的面包屑
- this.$emit('giveChildChangeBreakInfo', '添加考试', '添加考试')
- // this.createTagsInParent()
- this.getSubjects()
- this.getQuestionTypes()
- },
- methods: {
- // 向父组件中添加头部的tags标签
- createTagsInParent() {
- let flag = false
- this.tagInfo.map(item => {
- // 如果tags全部符合
- if (item.name === '添加考试' && item.url === this.$route.path) {
- flag = true
- } else if (item.name === '添加考试' && item.url !== this.$route.path) {
- this.$emit('updateTagInfo', '添加考试', this.$route.path)
- flag = true
- }
- })
- if (!flag) this.$emit('giveChildAddTag', '添加考试', this.$route.path)
- },
- // 获取所有的题库信息
- getSubjects() {
- getSubjectKV().then((resp) => {
- if (resp.code === 0) {
- this.allSubject = resp.data
- } else {
- this.$notify({
- title: 'Tips',
- message: resp.message,
- type: 'error',
- duration: 2000
- })
- }
- })
- },
- getQuestionTypes() {
- getQuestionType().then((resp) => {
- if (resp.code === 0) {
- this.allType = resp.data
- } else {
- this.$notify({
- title: 'Tips',
- message: resp.message,
- type: 'error',
- duration: 2000
- })
- }
- })
- },
- // 删除当前需要去除的题库
- delBank(bankId) {
- this.addExamQuestion2.forEach((item, index) => {
- if (item.bankId === bankId) this.addExamQuestion2.splice(index, 1)
- })
- },
- // 添加题库组卷中的题库
- addBank() {
- this.addExamQuestion2.push({
- 'bankName': '',
- 'singleScore': 1,
- 'multipleScore': 1,
- 'judgeScore': 1,
- 'shortScore': 1
- })
- },
- // 自由组卷时添加试题
- showAddDialog() {
- this.showQuestionDialog = true
- this.queryInfo.subjectId = null
- this.queryInfo.type = null
- this.queryInfo.level = null
- this.queryInfo.pageNumber = this.currentPage
- this.queryInfo.pageSize = this.pageSize
- this.getQuestionInfo()
- },
- // 自由组卷时删除试题
- delQuestion(questionId) {
- this.addExamQuestion1.forEach((item, index) => {
- if (item.questionId === questionId) this.addExamQuestion1.splice(index, 1)
- })
- },
- // 题目类型变化
- typeChange(val) {
- this.queryInfo.type = val
- this.queryInfo.pageNumber = this.currentPage
- this.queryInfo.pageSize = this.pageSize
- this.getQuestionInfo()
- },
- // 题库变化
- subjectChange(val) {
- this.queryInfo.subjectId = val
- this.queryInfo.pageNumber = this.currentPage
- this.queryInfo.pageSize = this.pageSize
- this.getQuestionInfo()
- },
- // 获取题目信息
- getQuestionInfo() {
- this.dataList = []
- getQuestions(this.queryInfo).then(resp => {
- if (resp.code === 0) {
- this.dataList = resp.data.list
- this.totalSize = resp.data.totalSize
- this.loading = false
- } else {
- this.$notify({
- title: '提示',
- message: resp.msg,
- type: 'warning',
- duration: 3000
- })
- }
- }).catch(error => {
- this.$notify({
- title: '提示',
- message: error.message,
- type: 'error',
- duration: 3000
- })
- })
- },
- // 处理表格被选中
- handleTableSectionChange(val) {
- this.selectedTable = val
- },
- // 分页页面大小改变
- handleSizeChange(val) {
- this.queryInfo.pageSize = val
- this.getQuestionInfo()
- },
- // 分页插件的页数
- handleCurrentChange(val) {
- this.queryInfo.pageNo = val
- this.getQuestionInfo()
- },
- // 自由组卷中选中的题目添加进去
- addQuToFree() {
- this.selectedTable.forEach(item => {
- // 不存在有当前题目
- if (!this.addExamQuestion1.some(i2 => { return i2.questionId === item.id })) {
- this.addExamQuestion1.push({
- 'pos': this.addExamQuestion1.length + 1,
- 'questionId': item.questionId,
- 'content': item.content,
- 'type': item.type,
- 'typeCode': item.typeCode,
- 'score': 1,
- 'children': []
- })
- }
- })
- this.showQuestionDialog = false
- },
- // 组卷模式变化
- makeModelChange() {
- this.$confirm('此操作将丢失当前组卷数据, 是否继续?', 'Tips', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- this.makeModel === 1 ? this.addExamQuestion1 = [] : this.addExamQuestion2 = []
- }).catch(() => {
- })
- },
- // 创建试卷
- createExamPaper() {
- validFormAndInvoke(this.$refs['examInfoForm'], () => {
- if ((this.makeModel === 1 && this.addExamQuestion1.length === 0) ||
- (this.makeModel === 2 && this.addExamQuestion2.length === 0)) {
- this.$message.error('试卷还没有添加试题')
- return false
- }
- // 构造数据对象(考试信息)
- const exam = this.examInfo
- exam.totalScore = this.sumTotalScore
- exam.status = 1
- // 权限id设置
- exam.examAuthority = this.examAuthority
- if (this.examAuthority === 2) { // 考试密码
- if (this.examPassword === '') { // 当前用户选择了需要密码权限,但是密码为空
- this.$message.error('当前权限为需要密码,但是密码为空')
- return false
- }
- exam.examPassword = this.examPassword
- }
- if (this.makeModel === 1 && !this.addExamQuestion1.some(item => item.bankId === '')) {
- var questions = []
- const questionIds = []
- const scores = []
- this.addExamQuestion1.forEach(item => {
- questions.push({
- pos: item.pos,
- questionId: item.questionId,
- score: item.score,
- children: item.children
- })
- questionIds.push(item.questionId)
- scores.push(item.score)
- })
- // exam.questionIds = questionIds.join(',')
- // exam.scores = scores.join(',')
- exam.questions = questions
- this.addExamPaper(exam)
- } else if (this.makeModel === 2) {
- const bankNames = []
- this.addExamQuestion2.forEach(item => bankNames.push(item.bankName))
- exam.bankNames = bankNames.join(',')
- exam.singleScore = this.addExamQuestion2[0].singleScore
- exam.multipleScore = this.addExamQuestion2[0].multipleScore
- exam.judgeScore = this.addExamQuestion2[0].judgeScore
- exam.shortScore = this.addExamQuestion2[0].shortScore
- this.addExamPaper(exam)
- } else {
- this.$message.error('请检查考试规则设置是否完整')
- }
- }, '请检查考试规则设置是否完整')
- },
- addExamPaper(examInfo) {
- addPaper(examInfo).then(resp => {
- if (resp.code === 0) {
- this.$notify({
- title: '提示',
- message: '试卷已创建',
- type: 'warning',
- duration: 3000
- })
- this.$router.push('/exam/paper')
- } else {
- this.$notify({
- title: '提示',
- message: resp.msg,
- type: 'warning',
- duration: 3000
- })
- }
- }).catch(error => {
- this.$notify({
- title: '提示',
- message: error.message,
- type: 'error',
- duration: 3000
- })
- })
- },
- showGroupDialog(questionId) {
- this.groupQuestionId = questionId
- this.showGroupQuestionDialog = true
- getQuestion(questionId).then(resp => {
- if (resp.code === 0) {
- this.groupQuestionList = resp.data.children
- for (const item of this.groupQuestionList) {
- item.score = 0
- }
- }
- })
- },
- confirmChildScore() {
- this.showGroupQuestionDialog = false
- var childIds = []
- var score = 0
- for (const item of this.groupQuestionList) {
- score += item.score
- childIds.push({
- pid: this.groupQuestionId,
- questionId: item.questionId,
- score: item.score
- })
- }
- for (const item of this.addExamQuestion1) {
- if (item.questionId === this.groupQuestionId) {
- item.score = score
- item.children = childIds
- }
- }
- }
- }
- }
- </script>
- <style scoped lang="scss">
- .el-container {
- width: 100%;
- height: 100%;
- }
- .el-container {
- animation: leftMoveIn .7s ease-in;
- }
- @keyframes leftMoveIn {
- 0% {
- transform: translateX(-100%);
- opacity: 0;
- }
- 100% {
- transform: translateX(0%);
- opacity: 1;
- }
- }
- </style>
|