123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- <template>
- <div v-if="isSyncState" class="question-view">
- <question-body
- :questionBody="question.body"
- :examQuestion="examQuestion"
- ></question-body>
- <div class="ops">
- <div class="score">({{ examQuestion.questionScore }}分)</div>
- </div>
- <div class="option">
- <!-- <textarea v-model="studentAnswer" maxlength="5000" type="text" /> -->
- <div>
- <div class="menu">
- <i-button type="info" class="text-ops" size="small" @click="textCopy">
- 复制
- </i-button>
- <i-button type="info" class="text-ops" size="small" @click="textCut">
- 剪切
- </i-button>
- <i-button
- type="info"
- class="text-ops"
- size="small"
- @click="textPaste"
- >
- 粘贴
- </i-button>
- <i-button type="info" class="text-ops" size="small" @click="textSup">
- 上标
- </i-button>
- <i-button
- type="info"
- class="text-ops"
- size="small"
- @click="undoTextSup"
- >
- 取消上标
- </i-button>
- <i-button type="info" class="text-ops" size="small" @click="textSub">
- 下标
- </i-button>
- <i-button
- type="info"
- class="text-ops"
- size="small"
- @click="undoTextSup"
- >
- 取消下标
- </i-button>
- </div>
- <div
- ref="answerDiv"
- @keydown="disableCtrl"
- :contenteditable="true"
- v-html="studentAnswer"
- v-once
- @input="$event => textInput($event)"
- @blur="$event => textInput($event)"
- class="stu-answer"
- ></div>
- </div>
- <div class="reset" style="padding-top: 20px">
- <i-button type="warning" size="large" @click="studentAnswer = null">
- 重置答案
- </i-button>
- <span v-if="examShouldShowAnswer()">
- <i-button
- type="info"
- size="large"
- @click="showAnswer"
- >
- 显示答案
- </i-button>
- </span>
- <div v-if="examShouldShowAnswer() && isShowAnswer">
- 正确答案:
- <div v-html="rightAnswerTransform"></div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script>
- import QuestionBody from "./QuestionBody";
- import { createNamespacedHelpers } from "vuex";
- const { mapMutations, mapGetters } = createNamespacedHelpers(
- "examingHomeModule"
- );
- export default {
- name: "TextQuestionView",
- data() {
- return {
- studentAnswer: this.examQuestion.studentAnswer,
- isShowAnswer: false
- };
- },
- props: {
- question: Object,
- examQuestion: Object
- },
- methods: {
- ...mapMutations(["updateExamQuestion"]),
- ...mapGetters(["examShouldShowAnswer"]),
- disableCtrl(e) {
- if (e.ctrlKey || e.metaKey || e.altKey) {
- // .ctrlKey tells that ctrl key was pressed.
- e.preventDefault();
- return false;
- }
- return true;
- },
- textCopy() {
- var selElm = getSelection();
- var selRange = selElm.getRangeAt(0);
- this.copyNode = selRange.cloneContents();
- },
- textCut() {
- var selElm = getSelection();
- var selRange = selElm.getRangeAt(0);
- this.copyNode = selRange.extractContents();
- this.studentAnswer = this.$refs.answerDiv.innerHTML;
- },
- textPaste() {
- var selElm = getSelection();
- var selRange = selElm.getRangeAt(0);
- selRange.deleteContents();
- selRange.insertNode(this.copyNode.cloneNode(true));
- this.studentAnswer = this.$refs.answerDiv.innerHTML;
- },
- textSup() {
- getSelection()
- .getRangeAt(0)
- .surroundContents(document.createElement("sup"));
- this.studentAnswer = this.$refs.answerDiv.innerHTML;
- },
- undoTextSup() {
- getSelection().modify("extend", "left", "character");
- let selRange = getSelection().getRangeAt(0);
- var documentFragment = selRange.extractContents();
- var text = new Text(documentFragment.textContent);
- selRange.insertNode(text);
- this.studentAnswer = this.$refs.answerDiv.innerHTML;
- },
- textSub() {
- getSelection()
- .getRangeAt(0)
- .surroundContents(document.createElement("sub"));
- this.studentAnswer = this.$refs.answerDiv.innerHTML;
- },
- textInput($event) {
- console.log($event.target.innerHTML);
- this.studentAnswer = $event.target.innerHTML;
- },
- showAnswer() {
- this.isShowAnswer = !this.isShowAnswer;
- }
- },
- watch: {
- examQuestion() {
- // console.log(this.examQuestion.studentAnswer);
- this.studentAnswer = this.examQuestion.studentAnswer;
- },
- studentAnswer() {
- let realAnswer = null;
- if (this.studentAnswer) {
- // 如果有实际内容
- realAnswer = this.studentAnswer
- .replace(/<sup><\/sup>/gi, "")
- .replace(/<sub><\/sub>/gi, "")
- .replace(/<script/gi, "<script")
- .replace(/script>/gi, "script>");
- // .replace(/</gi, "<")
- // .replace(/>/gi, ">")
- // .replace(/<div><br><\/div>/gi, "<div><br></div>");
- }
- if (realAnswer !== this.examQuestion.studentAnswer) {
- this.updateExamQuestion({
- order: this.examQuestion.order,
- studentAnswer: realAnswer
- });
- }
- }
- },
- computed: {
- isSyncState() {
- return this.examQuestion.order == this.$route.params.order;
- },
- rightAnswerTransform() {
- return this.question.rightAnswer.join("");
- }
- },
- components: {
- QuestionBody
- }
- };
- </script>
- <style scoped>
- .question-view {
- display: grid;
- grid-row-gap: 10px;
- }
- .question-body {
- font-size: 18px;
- margin-bottom: 10px;
- }
- .ops {
- display: flex;
- align-items: flex-end;
- }
- .text-ops {
- margin: 0 5px 5px 0;
- }
- .stu-answer {
- width: 100%;
- max-width: 500px;
- min-height: 300px;
- border: 1px solid grey;
- }
- </style>
|