ShortAnswerQuestion.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <template>
  2. <div class="mta-short-answer-question" v-if="pageData.name">
  3. <el-row class="mta-first-row" type="flex">
  4. <el-col>
  5. <span class="wrap-shitiIndex" v-if="!!shitiIndex">
  6. <span v-if="isYueDu">({{shitiIndex}})</span>
  7. <span v-else>{{shitiIndex}}.</span>
  8. </span>
  9. <!-- 试题题目 -->
  10. <div class="mta-SC-title" v-html="pageData.name">
  11. </div>
  12. <span class="mta-SC-score" v-if="getShowScore && !isYueDu">({{pageData.score}}分)</span>
  13. </el-col>
  14. </el-row>
  15. <el-row class="mta-two-row" type="flex" v-if='audioOptions'>
  16. <mta-bus-audio-player :options="audioOptions"
  17. :checktimes="false"></mta-bus-audio-player>
  18. </el-row>
  19. <el-row class="mta-two-row" type="flex">
  20. <el-col>
  21. <!-- 试题内容区域 -->
  22. <!--<el-input
  23. @change="inputChange"
  24. type="textarea"
  25. :rows="2"
  26. :readonly="typeCase=== 'yulan' || typeCase=== 'geren'"
  27. placeholder="请输入简答题答案"
  28. v-model="textarea">
  29. </el-input>-->
  30. <mta-st-quill-editor
  31. ref="editorQuill"
  32. :value="textarea"
  33. :quillEditorRef="quillEditorRef"
  34. flg="1"
  35. @syncValue="syncValue">
  36. </mta-st-quill-editor>
  37. </el-col>
  38. </el-row>
  39. <!--答案-->
  40. <mta-answer-area
  41. v-if="typeCase === 'geren' || typeCase === 'cuoti2' || typeCase === 'cuoti3' || typeCase === 'yulan'"
  42. :data="{
  43. showAnswer:showAnswer,
  44. analysis: pageData.answer
  45. }"
  46. ></mta-answer-area>
  47. <el-row class="mta-three-row ShortAnswer-btn-box" type="flex">
  48. <el-col>
  49. <el-button type="primary" v-if="filesArray&&filesArray.length>0" @click="downloadDialog=true"
  50. class="response-btn">
  51. 下载附件
  52. </el-button>
  53. <el-button @click="yulanDialog=true" class="ShortAnswer-yl-btn" type="primary" v-if="imgArray&&imgArray.length>0">
  54. 预览图片
  55. <!-- <el-image :src="imgArray[0]" :preview-src-list="imgArray" class="ShortAnswer-image-btn"></el-image>-->
  56. </el-button>
  57. </el-col>
  58. </el-row>
  59. <el-dialog title="下载附件" :append-to-body="true" :visible.sync="downloadDialog" class="ShortAnswer-fj-dialog"
  60. width="30%">
  61. <div v-for="(item,index) in filesArray" class="fj-box">
  62. <div @click="downloadFile(item)">附件{{index+1}}</div>
  63. </div>
  64. </el-dialog>
  65. <el-dialog title="图片"
  66. :visible.sync="yulanDialog"
  67. width="50%"
  68. center
  69. class="yulanDl"
  70. :close-on-click-modal="false"
  71. :append-to-body="true"
  72. @close="yulanDialogClose"
  73. @open="yulanDialogOpen"
  74. >
  75. <Perfect-scrollbar>
  76. <div v-if="imgArray&&imgArray.length>0"
  77. style="display: flex;justify-content: flex-start; flex-wrap: wrap; height: 300px" >
  78. <el-image
  79. v-for="(item,index) in imgArray"
  80. :key="index"
  81. style="width: 100px; height: 100px; margin-left: 10px; margin-bottom: 6px"
  82. :src="item"
  83. :preview-src-list="[...item]">
  84. <div slot="error" class="image-slot">
  85. <!-- 图片请求异常时的异常处理 -->
  86. <i class="el-icon-picture-outline"></i>
  87. </div>
  88. </el-image>
  89. </div>
  90. </Perfect-scrollbar>
  91. <div slot="footer" class="dialog-footer">
  92. <el-button @click="yulanDialog = false">关 闭</el-button>
  93. </div>
  94. </el-dialog>
  95. </div>
  96. </template>
  97. <script>
  98. import { mapGetters } from 'vuex';
  99. import { getStringByHtml2 } from '@/utils/common.js';
  100. import MtaAnswerArea from '@/components/client/QuestionsForCuoti/AnswerArea.vue';
  101. import MtaBusAudioPlayer from '@/components/custom/MtaBusAudioPlayer.vue';
  102. import MtaStQuillEditor from '@/components/management/QuillEditor.vue';
  103. import { PerfectScrollbar } from 'vue2-perfect-scrollbar';
  104. export default {
  105. name: 'ShortAnswerQuestion',
  106. props: {
  107. questionData: { // 简答题数据
  108. require: true,
  109. type: Object,
  110. },
  111. shitiIndex: {
  112. type: Number,
  113. default: 0,
  114. },
  115. isYueDu: {
  116. type: Boolean,
  117. default: false,
  118. },
  119. yuduIndex: {
  120. type: Number,
  121. },
  122. // 组件接环状态, kaoshi,geren,yulan,cuoti2
  123. typeCase: {
  124. type: String,
  125. default: 'kaoshi',
  126. },
  127. getShowModel: {
  128. type: Boolean,
  129. default: true,
  130. },
  131. },
  132. components: {
  133. MtaAnswerArea,
  134. MtaBusAudioPlayer,
  135. MtaStQuillEditor,
  136. PerfectScrollbar
  137. },
  138. watch: {
  139. questionData: {
  140. handler(newVal, oldVal) {
  141. switch (this.typeCase) {
  142. case `kaoshi`:
  143. this.pageData = newVal;
  144. this.textarea = newVal.reply === `null` ? '' : newVal.reply;
  145. break;
  146. case `geren`:
  147. this.pageData = newVal;
  148. // 答案
  149. this.textarea = newVal.reply === `null` ? '' : newVal.reply;
  150. // 解析答案
  151. this.showAnswer = getStringByHtml2(newVal.result);
  152. // 解析
  153. this.analysis = getStringByHtml2(newVal.answer);
  154. break;
  155. case `cuoti`:
  156. this.pageData = newVal;
  157. // 答案
  158. this.textarea = newVal.reply === `null` ? '' : newVal.reply;
  159. break;
  160. case `yulan`:
  161. this.pageData = newVal;
  162. // 答案
  163. // this.textarea = getStringByHtml(newVal.result === `null` ? '' : newVal.result);
  164. this.textarea = '';
  165. // 解析答案
  166. this.showAnswer = getStringByHtml2(newVal.result);
  167. // 解析
  168. this.analysis = getStringByHtml2(newVal.answer);
  169. break;
  170. case `cuoti2`:
  171. this.pageData = newVal;
  172. // 答案
  173. this.textarea = newVal.reply === `null` ? '' : newVal.reply;
  174. // 解析答案
  175. this.showAnswer = getStringByHtml2(newVal.result);
  176. // 解析
  177. this.analysis = getStringByHtml2(newVal.answer);
  178. break;
  179. case `cuoti3`:
  180. this.pageData = newVal;
  181. // 答案
  182. this.textarea = newVal.reply === `null` ? '' : newVal.reply;
  183. // 解析答案
  184. this.showAnswer = getStringByHtml2(newVal.result);
  185. // 解析
  186. this.analysis = getStringByHtml2(newVal.answer);
  187. break;
  188. }
  189. let data = this.questionData;
  190. if (data.adjunct) {
  191. let arrItem = JSON.parse(data.adjunct);
  192. for (const item of arrItem) {
  193. if (item.type === 'audio') {
  194. this.audioOptions = {};
  195. this.audioOptions.src = item.src;
  196. this.audioOptions.title = item.oriname.split('.')[0];
  197. this.audioOptions.autoplay = false;
  198. this.audioOptions.dragable = item.dragable;
  199. this.audioOptions.playtimes = item.playtimes;
  200. }
  201. }
  202. }
  203. if (data.files) {
  204. let allFiles = JSON.parse(data.files);
  205. let imgArray = [];
  206. let filesArray = [];
  207. let imageType = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff'];
  208. for (let name of allFiles) {
  209. var index1 = name.lastIndexOf('.');
  210. var index2 = name.length;
  211. var suffix = name.substring(index1 + 1, index2);
  212. if (imageType.indexOf(suffix) != -1) {
  213. imgArray.push(name); // 如果为图片
  214. } else {
  215. filesArray.push(name);
  216. }
  217. }
  218. this.imgArray = imgArray;
  219. this.filesArray = filesArray;
  220. }
  221. },
  222. immediate: true,
  223. deep: true,
  224. },
  225. },
  226. computed: {
  227. ...mapGetters(['getShowScore']),
  228. },
  229. data() {
  230. return {
  231. // 页面渲染必须数据
  232. pageData: null,
  233. // 答案
  234. textarea: null,
  235. // 显示答案
  236. showAnswer: null,
  237. // 解析
  238. analysis: null,
  239. audioOptions: '',
  240. imgArray: [],
  241. filesArray: [],
  242. downloadDialog: false,
  243. quillEditorRef: '',
  244. yulanDialog: false,
  245. };
  246. },
  247. methods: {
  248. yulanDialogClose(){
  249. },
  250. yulanDialogOpen(){
  251. },
  252. downloadFile(data) {
  253. window.location.href = data;
  254. },
  255. inputChange(val) {
  256. // this.$emit('reply', [1, this.questionData.stId, val]);
  257. if (this.isYueDu) {
  258. this.$emit('reply', {
  259. paragraph: this.questionData.paragraph,
  260. type: 'jianda',
  261. stId: this.questionData.stId,
  262. data: val,
  263. number: this.yuduIndex,
  264. });
  265. } else {
  266. this.$emit('reply', {
  267. paragraph: this.questionData.paragraph,
  268. stId: this.questionData.stId,
  269. data: val,
  270. number: this.shitiIndex - 1,
  271. });
  272. }
  273. },
  274. syncValue(flg, content) {
  275. this.content = content;
  276. this.textarea = content;
  277. if (this.isYueDu) {
  278. this.$emit('reply', {
  279. paragraph: this.questionData.paragraph,
  280. type: 'jianda',
  281. stId: this.questionData.stId,
  282. files: this.questionData.files,
  283. data: content,
  284. number: this.yuduIndex,
  285. });
  286. } else {
  287. this.$emit('reply', {
  288. paragraph: this.questionData.paragraph,
  289. stId: this.questionData.stId,
  290. files: this.questionData.files,
  291. data: content,
  292. number: this.shitiIndex - 1,
  293. });
  294. }
  295. },
  296. },
  297. created() {
  298. this.quillEditorRef = 'quillEditorRef' + Math.floor(Math.random() * 100000);
  299. },
  300. };
  301. </script>