From 83bde4c4b6bfdbac8e5def7e1ab808902a6732c6 Mon Sep 17 00:00:00 2001 From: 龚焕茏 <2842157468@qq.com> Date: 星期一, 03 六月 2024 17:47:12 +0800 Subject: [PATCH] feat:题目添加-前端界面 --- src/components/PopUp/multiple-choice.vue | 225 +++++++++ src/views/Manage/TestPaper/QuestionBank.vue | 279 ++++------ src/components/PopUp/gap-filling.vue | 229 +++++++++ src/components/PopUp/single-choice.vue | 222 +++++++++ src/components/PopUp/true-false.vue | 202 ++++++++ src/components/PopUp/question/Show.vue | 62 ++ src/api/subject.js | 10 src/components/PopUp/short-answer.vue | 188 +++++++ 8 files changed, 1,247 insertions(+), 170 deletions(-) diff --git a/src/api/subject.js b/src/api/subject.js index 124c6a3..99d3491 100644 --- a/src/api/subject.js +++ b/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) } diff --git a/src/components/PopUp/gap-filling.vue b/src/components/PopUp/gap-filling.vue new file mode 100644 index 0000000..4deb149 --- /dev/null +++ b/src/components/PopUp/gap-filling.vue @@ -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="瑙f瀽锛�" 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) + // 鍏夋爣瀹氫綅鍒癠editor + 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> diff --git a/src/components/PopUp/multiple-choice.vue b/src/components/PopUp/multiple-choice.vue new file mode 100644 index 0000000..cd1effc --- /dev/null +++ b/src/components/PopUp/multiple-choice.vue @@ -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="瑙f瀽锛�" 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="姝g‘绛旀锛�" 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: '璇烽�夋嫨姝g‘绛旀', 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) + // 鍏夋爣瀹氫綅鍒癠editor + 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> diff --git a/src/components/PopUp/question/Show.vue b/src/components/PopUp/question/Show.vue new file mode 100644 index 0000000..2b7e9c9 --- /dev/null +++ b/src/components/PopUp/question/Show.vue @@ -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> diff --git a/src/components/PopUp/short-answer.vue b/src/components/PopUp/short-answer.vue new file mode 100644 index 0000000..4f2994f --- /dev/null +++ b/src/components/PopUp/short-answer.vue @@ -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="瑙f瀽锛�" 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) + // 鍏夋爣瀹氫綅鍒癠editor + 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> diff --git a/src/components/PopUp/single-choice.vue b/src/components/PopUp/single-choice.vue new file mode 100644 index 0000000..ad7e191 --- /dev/null +++ b/src/components/PopUp/single-choice.vue @@ -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="瑙f瀽锛�" 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="姝g‘绛旀锛�" 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: '璇烽�夋嫨姝g‘绛旀', 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) + // 鍏夋爣瀹氫綅鍒癠editor + 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> diff --git a/src/components/PopUp/true-false.vue b/src/components/PopUp/true-false.vue new file mode 100644 index 0000000..1b49929 --- /dev/null +++ b/src/components/PopUp/true-false.vue @@ -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="瑙f瀽锛�" 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="姝g‘绛旀锛�" 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: '璇烽�夋嫨姝g‘绛旀', 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) + // 鍏夋爣瀹氫綅鍒癠editor + 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> diff --git a/src/views/Manage/TestPaper/QuestionBank.vue b/src/views/Manage/TestPaper/QuestionBank.vue index b4f6d6b..e7b4c3e 100644 --- a/src/views/Manage/TestPaper/QuestionBank.vue +++ b/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: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A", "B"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - type: "閫夋嫨棰�", - subject: "璇枃", - score: ["A"], - }, - { - title: "褰揂涓嶣涓�璧蜂慨璺�", - 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> - - -- Gitblit v1.8.0