WritePictruePreview.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div v-if="show_preview" class="writepicture-preview">
  4. <div class="stem">
  5. <span class="question-number" :style="{ fontSize: data.property.stem_question_number_font_size }">
  6. {{ questionNumberEndIsBracket(data.property.question_number) }}
  7. </span>
  8. <span v-html="sanitizeHTML(data.stem)"></span>
  9. </div>
  10. <div
  11. v-if="isEnable(data.property.is_enable_description)"
  12. class="description rich-text"
  13. v-html="sanitizeHTML(data.description)"
  14. ></div>
  15. <div class="content">
  16. <div v-for="(item, index) in data.option_list" :key="index" class="content-item">
  17. <!-- <el-image
  18. v-if="pic_list[item.picture_file_id]"
  19. style="width: 370px; height: 238px"
  20. :src="pic_list[item.picture_file_id]"
  21. fit="contain"
  22. /> -->
  23. <div class="img-box">
  24. <img
  25. v-if="pic_list[item.picture_file_id]"
  26. :src="pic_list[item.picture_file_id]"
  27. style="max-width: 370px; max-height: 238px"
  28. />
  29. </div>
  30. <p class="pic-info rich-text" v-html="sanitizeHTML(item.picture_info)"></p>
  31. </div>
  32. </div>
  33. <div v-if="answer.answer_list[active_index]" class="content-right">
  34. <el-input
  35. v-model="answer.answer_list[active_index].text"
  36. class="write-input"
  37. rows="12"
  38. resize="none"
  39. type="textarea"
  40. placeholder="请输入"
  41. :maxlength="data.property.word_num"
  42. show-word-limit
  43. :readonly="disabled"
  44. :autosize="{ minRows: 5 }"
  45. @input="handleInput"
  46. />
  47. </div>
  48. <template v-if="isEnable(data.property.is_enable_upload_accessory)">
  49. <!-- 上传附件 -->
  50. <UploadFiles
  51. v-if="answer.answer_list[active_index]"
  52. :disabled="disabled"
  53. :fille-number="999"
  54. file-type-name="文件"
  55. :upload-type="'*'"
  56. :file-id-list="answer.answer_list[active_index].accessory_file_id"
  57. @upload="handleUpload"
  58. @deleteFile="handleDelete"
  59. />
  60. </template>
  61. <template v-if="isEnable(data.property.is_enable_sample_text) && isShowRightAnswer">
  62. <el-divider content-position="center"
  63. ><span
  64. :class="['sample-text', show_sample_text ? 'sample-show' : 'sample-hide']"
  65. @click="show_sample_text = !show_sample_text"
  66. >{{ show_sample_text ? '隐藏范文' : '查看范文' }}</span
  67. ></el-divider
  68. >
  69. <div
  70. v-if="show_sample_text"
  71. class="article-content rich-text"
  72. v-html="sanitizeHTML(this.show_sample_break)"
  73. ></div>
  74. </template>
  75. <div v-if="isEnable(data.property.is_enable_analysis) && isShowRightAnswer" class="analysis">
  76. <span class="analysis-title">解析</span>
  77. <div class="analysis-content" v-html="sanitizeHTML(data.analysis)"></div>
  78. </div>
  79. </div>
  80. </template>
  81. <script>
  82. import PreviewMixin from './components/PreviewMixin';
  83. import { GetFileStoreInfo } from '@/api/app';
  84. import UploadFiles from './components/common/UploadFiles.vue';
  85. export default {
  86. name: 'WritePicturePreview',
  87. components: {
  88. UploadFiles,
  89. },
  90. mixins: [PreviewMixin],
  91. data() {
  92. return {
  93. show_sample_text: true,
  94. pic_list: {},
  95. active_index: 0,
  96. show_preview: false,
  97. show_sample_break: '',
  98. };
  99. },
  100. watch: {
  101. data: {
  102. handler(val) {
  103. if (!val || this.data.type !== 'write_picture') return;
  104. this.handleData();
  105. },
  106. deep: true,
  107. immediate: true,
  108. },
  109. },
  110. methods: {
  111. // 初始化数据
  112. handleData() {
  113. this.show_preview = true;
  114. this.pic_list = {};
  115. this.active_index = 0;
  116. this.data.file_id_list.forEach((item) => {
  117. GetFileStoreInfo({ file_id: item }).then(({ file_id, file_url }) => {
  118. this.$set(this.pic_list, file_id, file_url);
  119. });
  120. });
  121. if (!this.isJudgingRightWrong) {
  122. let obj = {
  123. text: '',
  124. accessory_file_id: [], // 上传文件列表
  125. };
  126. this.answer.answer_list.push(obj);
  127. }
  128. this.show_sample_break = this.data.sample_text ? this.data.sample_text.replace(/#/g, '</p><p>') : '';
  129. },
  130. changeImg(index) {
  131. this.active_index = index;
  132. },
  133. // 文件上传成功
  134. handleUpload(fileId) {
  135. this.answer.answer_list[this.active_index].accessory_file_id.push(fileId);
  136. },
  137. // 删除文件
  138. handleDelete(fileId) {
  139. this.answer.answer_list[this.active_index].accessory_file_id.splice(
  140. this.answer.answer_list[this.active_index].accessory_file_id.indexOf(fileId),
  141. 1,
  142. );
  143. },
  144. handleInput(value) {
  145. if (value.length >= this.data.property.word_num) {
  146. this.$message.warning(`字数达到${value.length}字!`);
  147. }
  148. },
  149. },
  150. };
  151. </script>
  152. <style lang="scss" scoped>
  153. @use '@/styles/mixin.scss' as *;
  154. .writepicture-preview {
  155. @include preview;
  156. :deep p {
  157. margin: 0;
  158. }
  159. .content {
  160. display: flex;
  161. column-gap: 8px;
  162. width: 100%;
  163. padding-bottom: 24px;
  164. overflow: auto;
  165. .img-box {
  166. display: flex;
  167. align-items: center;
  168. justify-content: center;
  169. height: 238px;
  170. }
  171. .pic-title {
  172. margin: 8px 0 4px;
  173. font-size: 12px;
  174. font-weight: 600;
  175. line-height: 20px;
  176. color: #000;
  177. word-break: break-word;
  178. }
  179. .pic-info {
  180. margin: 0;
  181. font-size: 12px;
  182. font-weight: 400;
  183. line-height: 20px;
  184. color: #000;
  185. word-break: break-word;
  186. }
  187. }
  188. .reference-box {
  189. padding: 12px;
  190. background: $content-color;
  191. .reference-title {
  192. margin: 0 0 10px;
  193. font-size: 14px;
  194. font-weight: 400;
  195. line-height: 32px;
  196. color: $font-light-color;
  197. }
  198. }
  199. .el-divider--horizontal {
  200. margin: 12px 0;
  201. }
  202. .sample-text {
  203. font-size: 14px;
  204. font-weight: 400;
  205. line-height: 30px;
  206. color: #000;
  207. cursor: pointer;
  208. &.sample-show {
  209. color: $light-main-color;
  210. }
  211. }
  212. .article-content,
  213. .description {
  214. :deep p {
  215. margin: 0;
  216. }
  217. }
  218. .article-content {
  219. text-indent: 2em;
  220. }
  221. .write-input {
  222. font-size: 16px;
  223. }
  224. :deep .el-textarea .el-textarea__inner {
  225. padding-bottom: 25px;
  226. }
  227. :deep .el-textarea .el-input__count {
  228. bottom: 5px;
  229. font-size: 14px;
  230. background-color: $fill-color;
  231. }
  232. }
  233. /* 横向滚动条 */
  234. ::-webkit-scrollbar {
  235. height: 5px;
  236. background-color: #f5f5f5;
  237. }
  238. /* 横向滚动条滑块 */
  239. ::-webkit-scrollbar-thumb {
  240. background-color: #ccc;
  241. border-radius: 2px;
  242. }
  243. /* 鼠标悬停在滚动条上的滑块 */
  244. ::-webkit-scrollbar-thumb:hover {
  245. background-color: #555;
  246. }
  247. </style>