From 6a9796ef16ea6f6ecffdfebc3386a1c0c7ec7dc1 Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期一, 17 六月 2024 11:20:37 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- src/views/exam/question/edit/analysis.vue | 193 ++++++++++++ src/views/exam/question/edit/calculate.vue | 193 ++++++++++++ src/views/exam/paper/list.vue | 86 +++-- src/views/answer/components/QuestionAnswerShow.vue | 6 src/store/modules/enumItem.js | 8 src/layout/index.vue | 3 src/views/answer/list.vue | 4 src/router.js | 14 src/views/exam/paper/edit.vue | 356 +++++++++++++++++------ src/api/examPaper.js | 2 src/views/exam/question/components/Show.vue | 2 src/views/exam/question/edit/audio.vue | 19 + 12 files changed, 746 insertions(+), 140 deletions(-) diff --git a/src/api/examPaper.js b/src/api/examPaper.js index 71d3cfa..1a11e5c 100644 --- a/src/api/examPaper.js +++ b/src/api/examPaper.js @@ -2,7 +2,7 @@ export default { pageList: query => post('/api/admin/exam/paper/page', query), - taskExamPage: query => post('/api/admin/exam/paper/taskExamPage', query), + addPaper: query => post('/api/admin/exam/paper/addPaper', query), edit: query => post('/api/admin/exam/paper/edit', query), select: id => post('/api/admin/exam/paper/select/' + id), deletePaper: id => post('/api/admin/exam/paper/delete/' + id), diff --git a/src/layout/index.vue b/src/layout/index.vue index 86d3b47..ad5300f 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -8,9 +8,6 @@ <tags-view/> </div> <app-main /> - <div class="foot-copyright"> - <span>Copyright 漏2019-2024 姝︽眽鎬濈淮璺宠穬绉戞妧鏈夐檺鍏徃 鐗堟潈鎵�鏈�</span> - </div> <back-to-top :visibility-height="100" :back-position="0" transition-name="fade" ref="backTop"/> </div> </div> diff --git a/src/router.js b/src/router.js index 3b719fc..922ffb7 100644 --- a/src/router.js +++ b/src/router.js @@ -180,6 +180,20 @@ name: 'audioPage', meta: { title: '璇煶棰樼紪杈�', noCache: true, activeMenu: '/exam/question/list' }, hidden: true + }, + { + path: 'question/edit/calculate', + component: () => import('@/views/exam/question/edit/calculate'), + name: 'audioPage', + meta: { title: '璁$畻棰樼紪杈�', noCache: true, activeMenu: '/exam/question/list' }, + hidden: true + }, + { + path: 'question/edit/analysis', + component: () => import('@/views/exam/question/edit/analysis'), + name: 'audioPage', + meta: { title: '鍒嗘瀽棰樼紪杈�', noCache: true, activeMenu: '/exam/question/list' }, + hidden: true } ] }, diff --git a/src/store/modules/enumItem.js b/src/store/modules/enumItem.js index a49585f..9572098 100644 --- a/src/store/modules/enumItem.js +++ b/src/store/modules/enumItem.js @@ -12,16 +12,18 @@ }, exam: { examPaper: { - paperTypeEnum: [{ key: 1, value: '鍥哄畾璇曞嵎' }, { key: 4, value: '鏃舵璇曞嵎' }, { key: 6, value: '浠诲姟璇曞嵎' }] + paperTypeEnum: [{ key: 1, value: '鍥哄畾璇曞嵎' }, { key: 2, value: '闅忔満璇曞嵎' }, { key: 3, value: '闅忓簭璇曞嵎' }] }, question: { - typeEnum: [{ key: 1, value: '鍗曢�夐' }, { key: 2, value: '澶氶�夐' }, { key: 3, value: '鍒ゆ柇棰�' }, { key: 4, value: '濉┖棰�' }, { key: 5, value: '绠�绛旈' }, { key: 6, value: '璇煶棰�' }], + typeEnum: [{ key: 1, value: '鍗曢�夐' }, { key: 2, value: '澶氶�夐' }, { key: 3, value: '鍒ゆ柇棰�' }, { key: 4, value: '濉┖棰�' }, { key: 5, value: '绠�绛旈' }, { key: 6, value: '璇煶棰�' }, { key: 7, value: '璁$畻棰�' }, { key: 8, value: '鍒嗘瀽棰�' }], editUrlEnum: [{ key: 1, value: '/exam/question/edit/singleChoice', name: '鍗曢�夐' }, { key: 2, value: '/exam/question/edit/multipleChoice', name: '澶氶�夐' }, { key: 3, value: '/exam/question/edit/trueFalse', name: '鍒ゆ柇棰�' }, { key: 4, value: '/exam/question/edit/gapFilling', name: '濉┖棰�' }, { key: 5, value: '/exam/question/edit/shortAnswer', name: '绠�绛旈' }, - { key: 6, value: '/exam/question/edit/audio', name: '璇煶棰�' }] + { key: 6, value: '/exam/question/edit/audio', name: '璇煶棰�' }, + { key: 7, value: '/exam/question/edit/calculate', name: '璁$畻棰�' }, + { key: 8, value: '/exam/question/edit/analysis', name: '鍒嗘瀽棰�' }] } } } diff --git a/src/views/answer/components/QuestionAnswerShow.vue b/src/views/answer/components/QuestionAnswerShow.vue index 087f037..f84e195 100644 --- a/src/views/answer/components/QuestionAnswerShow.vue +++ b/src/views/answer/components/QuestionAnswerShow.vue @@ -1,6 +1,6 @@ <template> <div v-loading="qLoading" style="line-height:1.8"> - <div v-if="qType == 1 || qType == 2 || qType == 3 || qType == 4 || qType == 5 || qType == 6"> + <div v-if="qType == 1 || qType == 2 || qType == 3 || qType == 4 || qType == 5 || qType == 6 || qType == 7 || qType == 8"> <div v-if="qType == 1 || qType == 6"> <div class="q-title" v-html="question.title" /> <div class="q-content"> @@ -42,7 +42,7 @@ </el-form-item> </div> </div> - <div v-else-if="qType == 5"> + <div v-else-if="qType == 5 || qType == 7 || qType == 8"> <div class="q-title" v-html="question.title" /> <div> <el-input v-model="answer.content" type="textarea" rows="5"></el-input> @@ -69,7 +69,7 @@ </div> <div class="question-answer-show-item"> <span class="question-show-item">姝g‘绛旀锛�</span> - <span v-if="qType == 1 || qType == 2 || qType == 5 || qType == 6" v-html="question.correct" class="q-item-span-content" /> + <span v-if="qType == 1 || qType == 2 || qType == 5 || qType == 6 || qType == 7 || qType == 8" v-html="question.correct" class="q-item-span-content" /> <span v-if="qType == 3" v-html="trueFalseFormatter(question)" class="q-item-span-content" /> <span v-if="qType == 4">{{ question.correctArray }}</span> </div> diff --git a/src/views/answer/list.vue b/src/views/answer/list.vue index 8b8e238..63d1414 100644 --- a/src/views/answer/list.vue +++ b/src/views/answer/list.vue @@ -2,6 +2,9 @@ <div class="app-container"> <el-form :inline="true" :model="queryParam" class="demo-form-inline" label-width="80px"> <el-form-item> + <el-input v-model="queryParam.examName" placeholder="璇疯緭鍏ヨ�冭瘯鍚嶇О" clearable></el-input> + </el-form-item> + <el-form-item> <el-input v-model="queryParam.name" placeholder="璇疯緭鍏ヨ瘯鍗峰悕绉�" clearable></el-input> </el-form-item> <el-form-item> @@ -15,6 +18,7 @@ </el-form> <el-table v-loading="listLoading" :data="tableData" border style="width: 100%;"> + <el-table-column align="center" prop="examName" label="鑰冭瘯鍚嶇О" /> <el-table-column align="center" prop="paperName" label="璇曞嵎鍚嶇О" /> <el-table-column align="center" prop="subjectName" label="绉戠洰" /> <el-table-column align="center" prop="paperType" label="璇曞嵎绫诲瀷" width="150px"> diff --git a/src/views/exam/paper/edit.vue b/src/views/exam/paper/edit.vue index 9185182..7ac665c 100644 --- a/src/views/exam/paper/edit.vue +++ b/src/views/exam/paper/edit.vue @@ -1,15 +1,9 @@ <template> <div class="app-container"> - <el-form :model="form" ref="form" label-width="100px" v-loading="formLoading" :rules="rules"> - <el-form-item label="骞寸骇锛�" prop="level" required> - <el-select v-model="form.level" placeholder="骞寸骇" @change="levelChange"> - <el-option v-for="item in levelEnum" :key="item.key" :value="item.key" :label="item.value"></el-option> - </el-select> - </el-form-item> + <el-form :model="form" ref="form" label-width="150px" 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 subjectFilter" :key="item.id" :value="item.id" - :label="item.name+' ( '+item.levelName+' )'"></el-option> + <el-option v-for="item in subjects" :key="item.id" :label="item.name" :value="item.id"/> </el-select> </el-form-item> <el-form-item label="璇曞嵎绫诲瀷锛�" prop="paperType" required> @@ -17,53 +11,99 @@ <el-option v-for="item in paperTypeEnum" :key="item.key" :value="item.key" :label="item.value"></el-option> </el-select> </el-form-item> - <el-form-item label="鏃堕棿闄愬埗锛�" required v-show="form.paperType===4"> - <el-date-picker v-model="form.limitDateTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" - range-separator="鑷�" start-placeholder="寮�濮嬫棩鏈�" end-placeholder="缁撴潫鏃ユ湡"> - </el-date-picker> + <el-form-item label="璇曞嵎鍚嶇О锛�" prop="name" required> + <el-input style="width: 300px" v-model="form.name"/> </el-form-item> - <el-form-item label="璇曞嵎鍚嶇О锛�" prop="name" required> - <el-input v-model="form.name"/> - </el-form-item> - <el-form-item :key="index" :label="'鏍囬'+(index+1)+'锛�'" required v-for="(titleItem,index) in form.titleItems"> - <el-input v-model="titleItem.name" style="width: 80%"/> + <el-form-item :key="index" :label="'鏍囬'+(index+1)+'锛�'" required + v-for="(titleItem,index) in form.questionTitleList" v-show="form.paperType===1"> + <el-input v-model="titleItem.title" style="width: 50%"/> + <el-select @change="addQuestionType" v-model="titleItem.questionType" style="margin-left: 20px" + placeholder="璇烽�夋嫨棰樼洰绫诲瀷"> + <el-option + v-for="item in questionTypeList" + :key="item.value" + :label="item.name" + :value="item.value" + :disabled="addedQuestionTypes.includes(item.value)"/><!-- 绂佺敤宸叉坊鍔犵殑閫夐」 --> + </el-select> + <el-input-number v-show ="titleItem.questionList.length > 0" v-model="titleItem.eachScore" @change="updateScores(titleItem)" :min="0" :precision="1" + style="margin-left: 20px" placeholder="姣忛鍒嗘暟"></el-input-number> <el-button type="text" class="link-left" style="margin-left: 20px" size="mini" @click="addQuestion(titleItem)"> 娣诲姞棰樼洰 </el-button> - <el-button type="text" class="link-left" size="mini" @click="form.titleItems.splice(index,1)">鍒犻櫎</el-button> - <el-card class="exampaper-item-box" v-if="titleItem.questionItems.length!==0"> + <el-button type="text" class="link-left" size="mini" @click="removeTitleItem(titleItem,index)">鍒犻櫎</el-button> + <el-card class="exampaper-item-box" v-if="titleItem.questionList.length!==0"> <el-form-item :key="questionIndex" :label="'棰樼洰'+(questionIndex+1)+'锛�'" - v-for="(questionItem,questionIndex) in titleItem.questionItems" style="margin-bottom: 15px"> + v-for="(questionItem,questionIndex) in titleItem.questionList" style="margin-bottom: 15px"> <el-row> - <el-col :span="23"> - <QuestionShow :qType="questionItem.questionType" :question="questionItem"/> + <el-col :span="18"> + <QuestionShow :qType="titleItem.questionType" :question="questionItem"/> </el-col> - <el-col :span="1"> - <el-button type="text" size="mini" @click="titleItem.questionItems.splice(questionIndex,1)">鍒犻櫎 + <el-col :span="3"> + <el-input-number v-model="questionItem.score" size="mini" :min="0" :precision="1" placeholder="鍒嗘暟" + :controls="false" @change="updateTotalScore"/> + </el-col> + <el-col :span="3"> + <el-button type="text" size="mini" @click="removeQuestion(titleItem,questionItem)">鍒犻櫎 </el-button> </el-col> </el-row> </el-form-item> </el-card> </el-form-item> - <el-form-item label="寤鸿鏃堕暱锛�" prop="suggestTime" required> - <el-input v-model="form.suggestTime" placeholder="鍒嗛挓"/> + <el-form-item label="澶氶�夐寰楀垎绫诲瀷锛�" prop="deductType"> + <div> + <el-select v-model="form.deductType" placeholder="璇烽�夋嫨澶氶�夐寰楀垎绫诲瀷" style="width: 200px;margin-right: 30px"> + <el-option + v-for="item in deductTypeList" + :key="item.value" + :label="item.name" + :value="item.value" + /> + </el-select> + <el-input-number v-model="form.deductTypeScore" placeholder="璇疯緭鍏ュ閫夎瘎鍒�" + v-show="form.deductType === 2 || form.deductType === 3" :min="0"/> + </div> + </el-form-item> + <el-form-item label="寤鸿鏃堕暱(鍒嗛挓)锛�" prop="suggestTime" required> + <el-input-number v-model="form.suggestTime" placeholder="鍒嗛挓" :min="0"/> + </el-form-item> + <el-form-item label="鏉冮檺锛�" prop="visibility"> + <el-radio v-model="form.visibility" :label="'1'">绉佹湁</el-radio> + <el-radio v-model="form.visibility" :label="'2'">鍏紑</el-radio> + </el-form-item> + <el-form-item v-show="form.paperType ===2 ||form.paperType ===3" :key="index" + :label="translateQuestionType(item.questionType)+'锛�'" v-for="(item,index) in form.questionSetting"> + <div style="display: flex;"> + <span style="margin-right: 10px">{{ '鏍囬' }}</span> + <el-input v-model="item.title" style="margin-right: 50px;width: 500px"/> + <span style="margin-right: 10px">{{ '鏁伴噺' }}</span> + <el-input-number v-model="item.num" :precision="0" :min="0" style="margin-right: 50px"/> + <span style="margin-right: 10px">{{ '姣忛鍒嗘暟' }}</span> + <el-input-number v-model="item.score" :min="0" :precision="1"/> + </div> + </el-form-item> + <el-form-item label="鍚堣锛�"> + <div style="display: flex;"> + <span style="margin-right: 10px">{{ '鏁伴噺锛�' }}</span> + <span v-if ="form.paperType ===2 || (form.paperType ===3 && !form.id)" style="margin-right: 50px;width: 100px">{{ totalNum }}</span> + <span v-if ="form.paperType ===1" style="margin-right: 50px;width: 100px">{{ form.num }}</span> + <span style="margin-right: 10px">{{ '鎬诲垎锛�' }}</span> + <span v-if ="form.paperType ===2 || (form.paperType ===3 && !form.id)" style="width: 100px">{{ totalScore }}</span> + <span v-if ="form.paperType ===1" style="width: 100px">{{ form.score }}</span> + </div> </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="addTitle">娣诲姞鏍囬</el-button> + <el-button type="success" @click="addTitle" v-show="form.paperType ===1">娣诲姞鏍囬</el-button> </el-form-item> </el-form> - <el-dialog :visible.sync="questionPage.showDialog" width="70%"> + + <el-dialog :visible.sync="questionPage.showDialog" width="70%"> <el-form :model="questionPage.queryParam" ref="queryForm" :inline="true"> <el-form-item label="ID锛�"> - <el-input v-model="questionPage.queryParam.id" clearable></el-input> - </el-form-item> - <el-form-item label="棰樺瀷锛�"> - <el-select v-model="questionPage.queryParam.questionType" clearable> - <el-option v-for="item in questionTypeEnum" :key="item.key" :value="item.key" :label="item.value"></el-option> - </el-select> + <el-input v-model="questionPage.queryParam.id" clearable></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="queryForm">鏌ヨ</el-button> @@ -73,24 +113,29 @@ @selection-change="handleSelectionChange" border fit highlight-current-row style="width: 100%"> <el-table-column type="selection" width="35"></el-table-column> <el-table-column prop="id" label="Id" width="60px"/> - <el-table-column prop="questionType" label="棰樺瀷" :formatter="questionTypeFormatter" width="70px"/> + <el-table-column prop="questionType" label="棰樺瀷" width="70px"> + <template slot-scope="scope"> + <div> {{ translateQuestionType(scope.row.questionType) }}</div> + </template> + </el-table-column> <el-table-column prop="shortTitle" label="棰樺共" show-overflow-tooltip/> </el-table> <pagination v-show="questionPage.total>0" :total="questionPage.total" :page.sync="questionPage.queryParam.pageIndex" :limit.sync="questionPage.queryParam.pageSize" @pagination="search"/> <span slot="footer" class="dialog-footer"> - <el-button @click="questionPage.showDialog = false">鍙� 娑�</el-button> <el-button type="primary" @click="confirmQuestionSelect">纭畾</el-button> - </span> + <el-button @click="questionPage.showDialog = false">鍙� 娑�</el-button> + </span> </el-dialog> </div> </template> <script> -import { mapGetters, mapState, mapActions } from 'vuex' +import { mapState, mapActions } from 'vuex' import Pagination from '@/components/Pagination' +import subjectApi from '@/api/subject' import QuestionShow from '../question/components/Show' import examPaperApi from '@/api/examPaper' import questionApi from '@/api/question' @@ -101,15 +146,44 @@ return { form: { id: null, - level: null, subjectId: null, paperType: 1, - limitDateTime: [], name: '', - suggestTime: null, - titleItems: [] + num: 0, + score: 0, + suggestTime: 0, + deductType: 1, + deductTypeScore: 0, + visibility: '1', + questionSetting: [ + { questionType: 1, title: '鍗曢�夐', score: null, num: null }, + { questionType: 2, title: '澶氶�夐', score: null, num: null }, + { questionType: 3, title: '鍒ゆ柇棰�', score: null, num: null }, + { questionType: 4, title: '濉┖棰�', score: null, num: null }, + { questionType: 5, title: '绠�绛旈', score: null, num: null }, + { questionType: 6, title: '璇煶棰�', score: null, num: null }, + { questionType: 7, title: '璁$畻棰�', score: null, num: null }, + { questionType: 8, title: '鍒嗘瀽棰�', score: null, num: null }, + ], + questionTitleList: [] }, - subjectFilter: null, + deductTypeList: [ + { name: '绛旈敊涓嶅緱鍒�', value: 1 }, + { name: '婕忛�夊緱鍥哄畾鍒嗗��,鍖呭惈閿欒閫夐」涓嶅緱鍒�', value: 2 }, + { name: '姣忓涓�棰樺緱鐩稿簲鍒嗗��,鍖呭惈閿欒閫夐」涓嶅緱鍒�', value: 3 }, + ], + questionTypeList: [ + { name: '鍗曢�夐', value: 1 }, + { name: '澶氶�夐', value: 2 }, + { name: '鍒ゆ柇棰�', value: 3 }, + { name: '濉┖棰�', value: 4 }, + { name: '绠�绛旈', value: 5 }, + { name: '璇煶棰�', value: 6 }, + { name: '璁$畻棰�', value: 7 }, + { name: '鍒嗘瀽棰�', value: 8 }, + ], + addedQuestionTypes: [], // 宸叉坊鍔犵殑棰樼洰绫诲瀷 + subjects: [], formLoading: false, rules: { level: [ @@ -133,8 +207,8 @@ showDialog: false, queryParam: { id: null, - questionType: null, - subjectId: 1, + questionType: [], + subjectId: [], pageIndex: 1, pageSize: 5 }, @@ -148,57 +222,123 @@ created () { let id = this.$route.query.id let _this = this - this.initSubject(function () { - _this.subjectFilter = _this.subjects - }) + this.getSubjects() if (id && parseInt(id) !== 0) { _this.formLoading = true examPaperApi.select(id).then(re => { - _this.form = re.response + _this.form = re.data _this.formLoading = false }) } }, methods: { + updateTotalScore () { + this.form.score = 0 + this.form.questionTitleList.forEach(titleItem => { + titleItem.questionList.forEach(questionItem => { + if (questionItem.score) { + this.form.score += questionItem.score + } + }) + }) + }, + updateScores (titleItem) { + if (titleItem && titleItem.questionList) { + titleItem.questionList.forEach(questionItem => { + questionItem.score = titleItem.eachScore // 鏇存柊姣忎釜棰樼洰鐨勫垎鏁� + }) + } + this.updateTotalScore() + }, + // 娣诲姞棰樼洰绫诲瀷 + addQuestionType () { + if (this.form.questionTitleList.length > 0) { + this.addedQuestionTypes = [] + // 閬嶅巻棰樼洰鍒楄〃 + this.form.questionTitleList.forEach((titleItem) => { + // 妫�鏌ュ綋鍓嶉鐩殑绫诲瀷鏄惁杩樻病鏈夎娣诲姞鍒板凡娣诲姞鐨勯鐩被鍨嬫暟缁勪腑 + if (!this.addedQuestionTypes.includes(titleItem.questionType)) { + // 濡傛灉杩樻病鏈夎娣诲姞锛屽垯娣诲姞鍒版暟缁勪腑 + this.addedQuestionTypes.push(titleItem.questionType) + } + }) + } + }, + // 鑾峰彇绉戠洰 + getSubjects () { + subjectApi.list().then(re => { + this.subjects = re.data + }) + }, + translateQuestionType (questionTypeId) { + const questionType = this.questionTypeList.find(questionType => questionType.value === questionTypeId) + return questionType ? questionType.name : '鏈煡' + }, submitForm () { let _this = this this.$refs.form.validate((valid) => { if (valid) { this.formLoading = true - examPaperApi.edit(this.form).then(re => { - if (re.code === 1) { - _this.$message.success(re.message) - _this.delCurrentView(_this).then(() => { - _this.$router.push('/exam/paper/list') - }) - } else { - _this.$message.error(re.message) + if (this.form.id) { + examPaperApi.edit(this.form).then(re => { + if (re.code === 1) { + _this.$message.success(re.message) + _this.delCurrentView(_this).then(() => { + _this.$router.push('/exam/paper/list') + }) + } else { + _this.$message.error(re.message) + this.formLoading = false + } + }).catch(e => { this.formLoading = false - } - }).catch(e => { - this.formLoading = false - }) + }) + } else { + examPaperApi.addPaper(this.form).then(re => { + if (re.code === 1) { + _this.$message.success(re.message) + _this.delCurrentView(_this).then(() => { + _this.$router.push('/exam/paper/list') + }) + } else { + _this.$message.error(re.message) + this.formLoading = false + } + }).catch(e => { + this.formLoading = false + }) + } } else { return false } }) }, addTitle () { - this.form.titleItems.push({ - name: '', - questionItems: [] + this.form.questionTitleList.push({ + questionList: [] }) }, addQuestion (titleItem) { this.currentTitleItem = titleItem + this.questionPage.queryParam.questionType = [] + this.questionPage.queryParam.questionType.push(titleItem.questionType) this.questionPage.showDialog = true this.search() }, - removeTitleItem (titleItem) { - this.form.titleItems.remove(titleItem) + removeTitleItem (titleItem ,index) { + this.form.questionTitleList.splice(index, 1) + this.form.num = this.form.num - titleItem.questionList.length + this.updateTotalScore(); + if (!this.form.questionTitleList || this.form.questionTitleList.length === 0) { + this.addedQuestionTypes = [] + } else { + this.addQuestionType() + } }, - removeQuestion (titleItem, questionItem) { - titleItem.questionItems.remove(questionItem) + removeQuestion (titleItem ,questionIndex) { + titleItem.questionList.splice(questionIndex ,1) + this.updateTotalScore(); + this.form.num = this.form.num - 1 }, queryForm () { this.questionPage.queryParam.pageIndex = 1 @@ -208,20 +348,18 @@ let _this = this this.questionPage.multipleSelection.forEach(q => { questionApi.select(q.id).then(re => { - _this.currentTitleItem.questionItems.push(re.response) + _this.currentTitleItem.questionList.push(re.data) + this.form.num += 1 }) }) this.questionPage.showDialog = false }, - levelChange () { - this.form.subjectId = null - this.subjectFilter = this.subjects.filter(data => data.level === this.form.level) - }, search () { - this.questionPage.queryParam.subjectId = this.form.subjectId + this.questionPage.queryParam.subjectId = [] + this.questionPage.queryParam.subjectId.push(this.form.subjectId) this.questionPage.listLoading = true questionApi.pageList(this.questionPage.queryParam).then(data => { - const re = data.response + const re = data.data this.questionPage.tableData = re.list this.questionPage.total = re.total this.questionPage.queryParam.pageIndex = re.pageNum @@ -231,48 +369,72 @@ handleSelectionChange (val) { this.questionPage.multipleSelection = val }, - questionTypeFormatter (row, column, cellValue, index) { - return this.enumFormat(this.questionTypeEnum, cellValue) - }, - subjectFormatter (row, column, cellValue, index) { - return this.subjectEnumFormat(cellValue) - }, resetForm () { let lastId = this.form.id this.$refs['form'].resetFields() this.form = { - id: null, - level: null, subjectId: null, paperType: 1, - limitDateTime: [], name: '', - suggestTime: null, - titleItems: [] + num: 0, + score: 0, + suggestTime: 0, + deductType: 1, + deductTypeScore: 0, + visibility: '1', + questionSetting: [ + { questionType: 1, title: '鍗曢�夐', score: null, num: null }, + { questionType: 2, title: '澶氶�夐', score: null, num: null }, + { questionType: 3, title: '鍒ゆ柇棰�', score: null, num: null }, + { questionType: 4, title: '濉┖棰�', score: null, num: null }, + { questionType: 5, title: '绠�绛旈', score: null, num: null }, + { questionType: 6, title: '璁$畻棰�', score: null, num: null }, + ], + questionTitleList: [] } this.form.id = lastId }, - ...mapActions('exam', { initSubject: 'initSubject' }), ...mapActions('tagsView', { delCurrentView: 'delCurrentView' }) }, computed: { - ...mapGetters('enumItem', ['enumFormat']), ...mapState('enumItem', { - questionTypeEnum: state => state.exam.question.typeEnum, paperTypeEnum: state => state.exam.examPaper.paperTypeEnum, - levelEnum: state => state.user.levelEnum }), - ...mapState('exam', { subjects: state => state.subjects }) + totalNum () { + if (this.form.paperType === 2 || this.form.paperType === 3) { + let total = 0 + for (let item of this.form.questionSetting) { + total += parseInt(item.num || 0, 10) + } + this.form.num = total + return total + } else { + + } + }, + totalScore () { + if (this.form.paperType === 2 || this.form.paperType === 3) { + let total = 0 + for (let item of this.form.questionSetting) { + const num = parseInt(item.num || 0, 10) + const score = parseFloat(item.score || 0) + total += num * score + } + this.form.score = total.toFixed(1) + return total.toFixed(1) // 淇濈暀涓�浣嶅皬鏁� + } + } } } </script> <style lang="scss"> - .exampaper-item-box { - .q-title { - margin: 0px 5px 0px 5px; - } - .q-item-content { - } +.exampaper-item-box { + .q-title { + margin: 0px 5px 0px 5px; } + + .q-item-content { + } +} </style> diff --git a/src/views/exam/paper/list.vue b/src/views/exam/paper/list.vue index bd9c2e5..bc8a314 100644 --- a/src/views/exam/paper/list.vue +++ b/src/views/exam/paper/list.vue @@ -1,17 +1,16 @@ <template> <div class="app-container"> <el-form :model="queryParam" ref="queryForm" :inline="true"> - <el-form-item label="棰樼洰ID锛�"> + <el-form-item label="璇曞嵎ID锛�"> <el-input v-model="queryParam.id" clearable></el-input> </el-form-item> - <el-form-item label="骞寸骇锛�"> - <el-select v-model="queryParam.level" placeholder="骞寸骇" @change="levelChange" clearable> - <el-option v-for="item in levelEnum" :key="item.key" :value="item.key" :label="item.value"></el-option> - </el-select> - </el-form-item> <el-form-item label="瀛︾锛�" > - <el-select v-model="queryParam.subjectId" clearable> - <el-option v-for="item in subjectFilter" :key="item.id" :value="item.id" :label="item.name+' ( '+item.levelName+' )'"></el-option> + <el-select + v-model="queryParam.subjectId" + placeholder="鍏ㄩ儴绉戠洰" + clearable + > + <el-option v-for="item in subjects" :key="item.id" :label="item.name" :value="item.id"/> </el-select> </el-form-item> <el-form-item> @@ -22,10 +21,43 @@ </el-form-item> </el-form> <el-table v-loading="listLoading" :data="tableData" border fit highlight-current-row style="width: 100%"> - <el-table-column prop="id" label="Id" width="90px"/> - <el-table-column prop="subjectId" label="瀛︾" :formatter="subjectFormatter" width="120px" /> - <el-table-column prop="name" label="鍚嶇О" /> - <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="160px"/> + <el-table-column align="center" prop="id" label="Id" width="90px"/> + <el-table-column align="center" prop="subjectId" label="瀛︾" width="120px" > + <template slot-scope="scope"> + {{ translate(scope.row.subjectId) }} + </template> + </el-table-column> + <el-table-column align="center" prop="name" label="鍚嶇О" /> + <el-table-column + align="center" + prop="paperType" + label="璇曞嵎绫诲瀷" + > + <template slot-scope="scope"> + <div v-if="scope.row.paperType === 1">鍥哄畾璇曞嵎</div> + <div v-else-if="scope.row.paperType === 2">闅忔満璇曞嵎</div> + <div v-else-if="scope.row.paperType === 3">闅忓簭璇曞嵎</div> + </template> + </el-table-column> + <el-table-column + align="center" + prop="suggestTime" + label="寤鸿鏃堕暱(鍒嗛挓)" + > + </el-table-column> + <el-table-column + align="center" + prop="num" + label="棰樼洰鏁伴噺" + > + </el-table-column> + <el-table-column + align="center" + prop="score" + label="鎬诲垎" + > + </el-table-column> + <el-table-column align="center" prop="createTime" label="鍒涘缓鏃堕棿" width="160px"/> <el-table-column label="鎿嶄綔" align="center" width="160px"> <template slot-scope="{row}"> <el-button size="mini" @click="$router.push({path:'/exam/paper/edit',query:{id:row.id}})" >缂栬緫</el-button> @@ -39,8 +71,8 @@ </template> <script> -import { mapGetters, mapState, mapActions } from 'vuex' import Pagination from '@/components/Pagination' +import subjectApi from '@/api/subject' import examPaperApi from '@/api/examPaper' export default { @@ -54,14 +86,14 @@ pageIndex: 1, pageSize: 10 }, - subjectFilter: null, listLoading: true, tableData: [], + subjects: [], total: 0 } }, created () { - this.initSubject() + this.getSubjects() this.search() }, methods: { @@ -90,22 +122,16 @@ } }) }, - levelChange () { - this.queryParam.subjectId = null - this.subjectFilter = this.subjects.filter(data => data.level === this.queryParam.level) + // 鑾峰彇绉戠洰 + getSubjects() { + subjectApi.list().then(re => { + this.subjects = re.data + }) }, - subjectFormatter (row, column, cellValue, index) { - return this.subjectEnumFormat(cellValue) - }, - ...mapActions('exam', { initSubject: 'initSubject' }) - }, - computed: { - ...mapGetters('enumItem', ['enumFormat']), - ...mapState('enumItem', { - levelEnum: state => state.user.levelEnum - }), - ...mapGetters('exam', ['subjectEnumFormat']), - ...mapState('exam', { subjects: state => state.subjects }) + translate(subjectId) { + const subject = this.subjects.find(subject => subject.id == subjectId); + return subject ? subject.name : '鏈煡'; + } } } </script> diff --git a/src/views/exam/question/components/Show.vue b/src/views/exam/question/components/Show.vue index 468780b..2179805 100644 --- a/src/views/exam/question/components/Show.vue +++ b/src/views/exam/question/components/Show.vue @@ -29,7 +29,7 @@ <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 v-else-if="qType==5 || qType == 7 || qType == 8" v-loading="qLoading"> <div class="q-title" v-html="question.title"/> </div> <div v-else> diff --git a/src/views/exam/question/edit/analysis.vue b/src/views/exam/question/edit/analysis.vue new file mode 100644 index 0000000..eb200f0 --- /dev/null +++ b/src/views/exam/question/edit/analysis.vue @@ -0,0 +1,193 @@ +<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="闅惧害锛�" 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%"> + <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading"/> + </el-dialog> + </div> +</template> + +<script> +import QuestionShow from '../components/Show' +import Ueditor from '@/components/Ueditor' +import { mapGetters, mapState, mapActions } from 'vuex' +import questionApi from '@/api/question' + +export default { + components: { + Ueditor, QuestionShow + }, + data () { + return { + form: { + id: null, + questionType: 8, + 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 + this.initSubject(function () { + _this.subjectFilter = _this.subjects + }) + if (id && parseInt(id) !== 0) { + _this.formLoading = true + questionApi.select(id).then(re => { + _this.form = re.data + _this.formLoading = false + }) + } + }, + methods: { + 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 + }, + levelChange () { + this.form.subjectId = null + this.subjectFilter = this.subjects.filter(data => data.level === this.form.gradeLevel) + }, + showQuestion () { + this.questionShow.dialog = true + this.questionShow.qType = this.form.questionType + this.questionShow.question = this.form + }, + ...mapActions('exam', { initSubject: 'initSubject' }), + ...mapActions('tagsView', { delCurrentView: 'delCurrentView' }) + }, + computed: { + ...mapGetters('enumItem', ['enumFormat']), + ...mapState('enumItem', { + questionTypeEnum: state => state.exam.question.typeEnum, + levelEnum: state => state.user.levelEnum + }), + ...mapState('exam', { subjects: state => state.subjects }) + } +} +</script> diff --git a/src/views/exam/question/edit/audio.vue b/src/views/exam/question/edit/audio.vue index 7f88df7..4743443 100644 --- a/src/views/exam/question/edit/audio.vue +++ b/src/views/exam/question/edit/audio.vue @@ -11,8 +11,10 @@ </el-form-item> <el-form-item label="璇煶锛�" prop="audioFile" required> <el-upload v-model="form.audioFile" :action="uploadUrl" :limit="1" accept="audio/*" :on-success="uploadSuccess" - :file-list="audioList"> + :on-remove="handleRemove" :file-list="audioList"> <el-button size="small" type="primary">鐐瑰嚮涓婁紶</el-button> + <el-button v-if="form.audioFile" size="small" type="primary" @click.stop="audioPlay(form.audioFile)">{{ + audioInstance ? '鏆傚仠' : '璇曞惉' }}</el-button> </el-upload> </el-form-item> <el-form-item label="閫夐」锛�" required> @@ -125,7 +127,8 @@ dialog: false, question: null, loading: false - } + }, + audioInstance: null } }, created() { @@ -144,6 +147,18 @@ } }, methods: { + handleRemove() { + this.form.audioFile = '' + }, + audioPlay(url) { + if (this.audioInstance) { + this.audioInstance.pause(); + this.audioInstance = null; + } else { + this.audioInstance = new Audio('/api/files/' + url); + this.audioInstance.play(); + } + }, uploadSuccess(response) { this.form.audioFile = response.data.url; this.form.originalFile = response.data.name; diff --git a/src/views/exam/question/edit/calculate.vue b/src/views/exam/question/edit/calculate.vue new file mode 100644 index 0000000..7533456 --- /dev/null +++ b/src/views/exam/question/edit/calculate.vue @@ -0,0 +1,193 @@ +<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="闅惧害锛�" 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%"> + <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading"/> + </el-dialog> + </div> +</template> + +<script> +import QuestionShow from '../components/Show' +import Ueditor from '@/components/Ueditor' +import { mapGetters, mapState, mapActions } from 'vuex' +import questionApi from '@/api/question' + +export default { + components: { + Ueditor, QuestionShow + }, + data () { + return { + form: { + id: null, + questionType: 7, + 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 + this.initSubject(function () { + _this.subjectFilter = _this.subjects + }) + if (id && parseInt(id) !== 0) { + _this.formLoading = true + questionApi.select(id).then(re => { + _this.form = re.data + _this.formLoading = false + }) + } + }, + methods: { + 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 + }, + levelChange () { + this.form.subjectId = null + this.subjectFilter = this.subjects.filter(data => data.level === this.form.gradeLevel) + }, + showQuestion () { + this.questionShow.dialog = true + this.questionShow.qType = this.form.questionType + this.questionShow.question = this.form + }, + ...mapActions('exam', { initSubject: 'initSubject' }), + ...mapActions('tagsView', { delCurrentView: 'delCurrentView' }) + }, + computed: { + ...mapGetters('enumItem', ['enumFormat']), + ...mapState('enumItem', { + questionTypeEnum: state => state.exam.question.typeEnum, + levelEnum: state => state.user.levelEnum + }), + ...mapState('exam', { subjects: state => state.subjects }) + } +} +</script> -- Gitblit v1.8.0