<template> <el-dialog class="paper-params" :visible.sync="modalIsShow" top="10px" width="785px" :close-on-click-modal="false" :close-on-press-escape="false" append-to-body @open="dialogOpen" > <h1 class="params-dialog-title" slot="title"> 请上传阅卷参数 <span >卷面总分合计:<em class="param-sum-score">{{ pageSumScore }}分</em> </span> </h1> <div class="params-main"> <div class="params-head"> <el-button :type="!topicType ? 'primary' : 'default'" @click="selectType(0)" >客观题区</el-button > <el-button :type="topicType ? 'primary' : 'default'" @click="selectType(1)" >主观题区</el-button > </div> <div class="params-body"> <div style="text-align:right;"> <upload-button btn-icon="el-icon-upload" btn-content="选择上传主观题标答文件(doc/docx)" btn-type="warning" :upload-url="uploadUrl" :format="['doc', 'docx']" @valid-error="validError" @upload-success="uploadSuccess" style="margin: 0;" v-if="topicType" > </upload-button> </div> <div class="params-part" v-for="topic in curTopicList" :key="topic.id"> <h2 class="params-title">{{ topic.topicName }}</h2> <p class="params-subtitle"> <span>题型:{{ topic.name }}</span> <span v-if="topic.type !== 'COMPOSITION'"> 通配小题分值: <el-input-number v-model="topic.commonQuestionScore" size="small" :min="0.1" :max="200" :step="0.1" step-strictly :controls="false" @change="commonQuestionScoreChange(topic)" ></el-input-number >分,</span > <span >本大题总分合计:<em class="param-sum-score" >{{ topic.sumScore }}分</em ></span > </p> <div class="params-table" v-if="topic.type !== 'COMPOSITION'"> <table class="table table-striped"> <tr> <th>题号</th> <th>分值</th> <th>题号</th> <th>分值</th> </tr> <tr v-for="(group, gindex) in topic.questions" :key="gindex"> <template v-for="question in group"> <td :key="`${question.questionNo}-1`"> <span>{{ question.questionNo }}</span> </td> <td :key="`${question.questionNo}-2`"> <el-input-number v-model="question.score" size="small" :min="0.1" :max="200" :step="0.1" step-strictly :controls="false" @change="questionScoreChange(topic)" v-if="question.questionNo" ></el-input-number> </td> </template> </tr> </table> </div> <div class="params-table" v-else> <el-input-number v-model="topic.sumScore" :min="0.1" :max="200" :step="0.1" step-strictly :controls="false" @change="getPageSumScore" ></el-input-number> </div> </div> </div> </div> <div slot="footer" style="text-align: right;"> <el-button type="primary" @click="submit">确认</el-button> <el-button type="danger" @click="cancel" plain>取消</el-button> </div> </el-dialog> </template> <script> import { calcSum, isEmptyObject, objAssign } from "../plugins/utils"; import UploadButton from "./UploadButton"; export default { name: "paper-params", components: { UploadButton }, props: { pages: { type: Array, default() { return []; } }, paperParams: { type: Object, default() { return {}; } } }, data() { return { modalIsShow: false, topicType: 0, pageSumScore: 0, subjectiveAttachmentId: "", curTopicList: [], objectives: [], subjectives: [], cacheScores: {}, initTopic: { id: "", topicNo: "", topicName: "", type: "" }, // import uploadUrl: "/api/print/basic/sys/saveAttachment" }; }, methods: { selectType(topicType) { this.topicType = topicType; this.curTopicList = topicType ? this.subjectives : this.objectives; }, listIncludeItem(list, item) { const index = list.findIndex(elem => elem.id === item.id); return index !== -1; }, dialogOpen() { if (!isEmptyObject(this.paperParams)) { this.getCacheScore([ ...this.paperParams.objectives, ...this.paperParams.subjectives ]); this.subjectiveAttachmentId = this.paperParams.subjectiveAttachmentId; } // 每次打开时,重新生成试题结构,以便避免题卡结构变化之后,当前页面的试题结构没有变的问题 let objectiveList = []; let subjectiveList = []; let objectives = []; let subjectives = []; this.pages.forEach(page => { page.columns.forEach(column => { column.elements.forEach(element => { if ( element.sign && element.type !== "TOPIC_HEAD" && element.type !== "CARD_HEAD" ) { if (element.sign === "objective") objectiveList.push(element); if (element.sign === "subjective") subjectiveList.push(element); } }); }); }); // 客观题 objectiveList.forEach(item => { const topic = item.parent || item; if (this.listIncludeItem(objectives, topic)) return; let data = { sumScore: 0, commonQuestionScore: 1, name: this.getObjectiveTopicName(topic), choiceList: this.getChoiceList(topic), questions: this.getQuestions(topic), ...objAssign(this.initTopic, topic) }; data.sumScore = this.getTopicSumScore(data); objectives.push(data); }); // 主观题 subjectiveList.forEach(item => { const topic = item.parent || item; if (this.listIncludeItem(subjectives, topic)) return; let data = { sumScore: 0, commonQuestionScore: 1, name: this.getSubjectiveTopicName(topic), ...objAssign(this.initTopic, topic) }; if (topic.type === "COMPOSITION") { data.sumScore = this.cacheScores[topic.topicNo] || 1; } else { data.questions = this.getQuestions(topic); data.sumScore = this.getTopicSumScore(data); } subjectives.push(data); }); this.subjectives = subjectives; this.objectives = objectives; this.getPageSumScore(); this.selectType(0); }, getQuestions(topic) { let questions = []; let numPerColumn = Math.ceil(topic.questionsCount / 2); for (let j = topic.startNumber; j <= numPerColumn; j++) { let group = []; let question = { questionNo: j, score: this.cacheScores[`${topic.topicNo}-${j}`] || 1 }; if (topic.type === "FILL_QUESTION") question.answers = topic.isMultiply ? [] : ""; group[0] = question; if (numPerColumn + j <= topic.questionsCount) { group[1] = { questionNo: numPerColumn + j, score: this.cacheScores[`${topic.topicNo}-${numPerColumn + j}`] || 1, answers: topic.type === "FILL_QUESTION" && topic.isMultiply ? [] : "" }; } else { group[1] = { questionNo: "" }; } questions.push(group); } return questions; }, getObjectiveTopicName(data) { if (data.isMultiply) { return "选择题(多选)"; } else if (data.isBoolean) { return "填空题"; } else { return "选择题(单选)"; } }, getSubjectiveTopicName(data) { const names = { EXPLAIN: "解答题", COMPOSITION: "作文题", FILL_LINE: "填空题" }; return names[data.type]; }, getChoiceList(data) { const options = data.isBoolean ? data.booleanType : "abcdefghijklmnopqrstuv"; return options .toUpperCase() .slice(0, data.optionCount) .split(""); }, commonQuestionScoreChange(topic) { topic.questions.map(group => { group.map(question => { question.score = topic.commonQuestionScore; }); }); this.questionScoreChange(topic); }, questionScoreChange(topic) { topic.sumScore = this.getTopicSumScore(topic); this.getPageSumScore(); }, getTopicSumScore(topic) { const scoreList = topic.questions.map(group => { return calcSum(group.map(question => question.score || 0)); }); return calcSum(scoreList); }, getPageSumScore() { this.pageSumScore = calcSum(this.objectives.map(item => item.sumScore)) + calcSum(this.subjectives.map(item => item.sumScore)); }, getCacheScore(topics) { topics = topics || [...this.objectives, ...this.subjectives]; let cacheScores = {}; topics.map(topic => { if (topic.type === "COMPOSITION") { cacheScores[`${topic.topicNo}`] = topic.sumScore; } else { topic.questions.map(group => { group.map(question => { cacheScores[`${topic.topicNo}-${question.questionNo}`] = question.score; }); }); } }); this.cacheScores = cacheScores; }, // import validError(errorData) { this.$message.error(errorData.message); }, uploadSuccess(data) { this.$message.success("上传成功!"); this.subjectiveAttachmentId = data.id; }, // dialog cancel() { this.modalIsShow = false; }, open() { this.modalIsShow = true; }, submit() { this.$emit("confirm", { pageSumScore: this.pageSumScore, objectives: this.objectives, subjectives: this.subjectives, subjectiveAttachmentId: this.subjectiveAttachmentId }); this.modalIsShow = false; } } }; </script>