talk-picture-question.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <template>
  2. <!-- 看图说话题 -->
  3. <view class="talk-picture-area" v-model="questionData">
  4. <view class="question_title">
  5. <text class="question_number">
  6. {{ questionNumberEndIsBracket(questionData.property.question_number) }}
  7. </text>
  8. <text class="question_stem" v-html="sanitizeHTML(questionData.stem)"
  9. :ref="'richText-1-1'+questionData.question_id"
  10. @longpress="previewByRichTextImg(-1,-1,questionData.question_id)"></text>
  11. </view>
  12. <view class="description" :ref="'richText-2-2'+questionData.question_id"
  13. @longpress="previewByRichTextImg(-2,-2,questionData.question_id)"
  14. v-if="isEnable(questionData.property.is_enable_description)&&questionData.description"
  15. v-html="sanitizeHTML(questionData.description)">
  16. </view>
  17. <view class="option-area">
  18. <uni-swiper-dot :info="questionData.option_list" :current="active_index" :mode="mode" @clickItem="clickItem">
  19. <swiper class="swiper" circular previous-margin="50px" next-margin="50px" @change="changeImg"
  20. :current="swiperDotIndex">
  21. <swiper-item v-for="(item, index) in questionData.option_list" :key="index">
  22. <view :class="['swiper-item',active_index==index?'active':'']">
  23. <image :src="pic_list[item.picture_file_id]" mode="aspectFit"
  24. @click="preview(pic_list[item.picture_file_id])" />
  25. </view>
  26. </swiper-item>
  27. </swiper>
  28. </uni-swiper-dot>
  29. <!-- <text class="pic-title" v-html="sanitizeHTML(questionData.option_list[active_index].picture_title)"></text> -->
  30. <view class="pic-info-area" v-if="questionData.option_list[active_index].picture_info">
  31. <text class="pic-num">{{ computedQuestionNumber(active_index,questionData.option_number_show_mode) }}</text>
  32. <text class="pic-info" v-html="sanitizeHTML(questionData.option_list[active_index].picture_info)"
  33. :ref="'richText-3-3'+questionData.question_id"
  34. @longpress="previewByRichTextImg(-3,-3,questionData.question_id)"></text>
  35. </view>
  36. <!-- <view class="write-content">
  37. <textarea v-model="answer_list[active_index].value" placeholder="请输入" />
  38. </view> -->
  39. <view class="reference" v-if="isViewReference&&answer_control[questionData.question_id].isViewRightAnswer">
  40. <text class="reference-title">参考答案</text>
  41. <text class="reference-answer" v-html="sanitizeHTML(questionData.option_list[active_index].reference_answer)"
  42. :ref="'richText-4-4'+questionData.question_id"
  43. @longpress="previewByRichTextImg(-4,-4,questionData.question_id)">
  44. </text>
  45. </view>
  46. <view class="reference" v-if="isViewAnalysis&&answer_control[questionData.question_id].isViewRightAnswer">
  47. <text class="reference-title">解析</text>
  48. <text class="reference-answer" v-html="sanitizeHTML(questionData.option_list[active_index].analysis)"
  49. :ref="'richText-5-5'+questionData.question_id"
  50. @longpress="previewByRichTextImg(-5,-5,questionData.question_id)">
  51. </text>
  52. </view>
  53. <view class="sound-record-area">
  54. <text class="pic-num">{{ computedQuestionNumber(active_index,questionData.option_number_show_mode) }}</text>
  55. <SoundRecord :disabled="answer_control[questionData.question_id].isReadOnly"
  56. :wav-blob.sync="answer_list[active_index].audio_file_id" />
  57. </view>
  58. </view>
  59. </view>
  60. </template>
  61. <script>
  62. import {
  63. questionData,
  64. sanitizeHTML,
  65. isEnable,
  66. answer_mode_list,
  67. answer_control,
  68. computedQuestionNumber,
  69. } from '@/pages/answer_question/common/data/common.js';
  70. import {
  71. GetFileStoreInfo
  72. } from '@/api/api.js';
  73. import SoundRecord from '@/components/sound-record/sound-record.vue';
  74. import AnswerControlMixin from '@/pages/answer_question/common/data/AnswerControlMixin.js';
  75. export default {
  76. name: "talk-picture-question",
  77. mixins: [AnswerControlMixin],
  78. props: {
  79. questionData: questionData
  80. },
  81. components: {
  82. SoundRecord
  83. },
  84. data() {
  85. return {
  86. sanitizeHTML,
  87. isEnable,
  88. computedQuestionNumber,
  89. answer_control,
  90. pic_list: {},
  91. mode: 'indexes',
  92. swiperDotIndex: 0,
  93. active_index: 0,
  94. answer_list: [],
  95. };
  96. },
  97. watch: {
  98. answer_list: {
  99. handler(val) {
  100. if (this.isAnswerReady)
  101. this.saveUserAnswer();
  102. },
  103. deep: true,
  104. immediate: true,
  105. },
  106. 'questionData.question_id': {
  107. handler(val) {
  108. this.isAnswerReady = true;
  109. this.setUserAnswer();
  110. this.handleData();
  111. this.commonComputedAnswerControl(val);
  112. },
  113. immediate: true,
  114. deep: true
  115. }
  116. },
  117. computed: {
  118. isViewReference: function() {
  119. return isEnable(this.questionData.property.is_enable_reference_answer);
  120. },
  121. isViewAnalysis: function() {
  122. return isEnable(this.questionData.property.is_enable_analysis);
  123. }
  124. },
  125. methods: {
  126. // 初始化数据
  127. handleData() {
  128. this.answer_list = [];
  129. this.pic_list = {};
  130. this.active_index = 0;
  131. this.swiperDotIndex = 0;
  132. this.questionData.file_id_list.forEach((item) => {
  133. GetFileStoreInfo({
  134. file_id: item
  135. }).then(({
  136. file_id,
  137. file_url
  138. }) => {
  139. this.$set(this.pic_list, file_id, file_url);
  140. });
  141. });
  142. this.questionData.option_list.forEach((item) => {
  143. let obj = {
  144. mark: item.mark,
  145. value: '',
  146. audio_file_id: '',
  147. };
  148. this.answer_list.push(obj);
  149. });
  150. },
  151. changeImg(e) {
  152. this.active_index = e.detail.current;
  153. },
  154. clickItem(e) {
  155. this.swiperDotIndex = e;
  156. },
  157. //填写答案后保存答案
  158. saveUserAnswer: function() {
  159. var that = this;
  160. var questionId = this.questionData.question_id;
  161. this.questionData.user_answer[questionId].isEdit = true;
  162. var ansed = that.answer_list;
  163. this.questionData.user_answer[questionId].is_fill_answer =
  164. ansed.filter(p => p.value && p.audio_file_id).length > 0;
  165. this.questionData.user_answer[questionId].content = JSON.stringify(ansed);
  166. this.questionData.user_answer[questionId].answer_list = ansed;
  167. },
  168. //获取用户答案
  169. setUserAnswer: function() {
  170. var that = this;
  171. var callback = function() {
  172. var questionId = that.questionData.question_id;
  173. if (that.questionData.user_answer[questionId].answer_list.length > 0)
  174. that.answer_list = that.questionData.user_answer[questionId].answer_list;
  175. }
  176. this.$emit("getUserAnswer", this.questionData.question_id, callback);
  177. },
  178. }
  179. }
  180. </script>
  181. <style lang="scss" scoped>
  182. .talk-picture-area {
  183. .option-area {
  184. margin-top: 32rpx;
  185. /deep/.uni-swiper__warp {
  186. height: 380rpx;
  187. .uni-swiper__dots-box {
  188. bottom: 0 !important;
  189. }
  190. .swiper {
  191. height: 328rpx;
  192. .swiper-item {
  193. height: 100%;
  194. margin: 0 8rpx;
  195. border-radius: 8rpx;
  196. background-color: $uni-bg-color-grey;
  197. display: flex;
  198. justify-content: center;
  199. align-items: center;
  200. opacity: 0.4;
  201. image {
  202. // width: 440rpx;
  203. // height: 328rpx;
  204. border-radius: 8rpx;
  205. }
  206. &.active {
  207. opacity: 1;
  208. }
  209. }
  210. }
  211. }
  212. // .pic-title {
  213. // display: block;
  214. // font-size: 24rpx;
  215. // font-weight: 600;
  216. // }
  217. .pic-info-area {
  218. display: flex;
  219. column-gap: 8rpx;
  220. margin: 32rpx 0;
  221. font-size: 12pt;
  222. }
  223. .write-content {
  224. margin-top: 32rpx;
  225. height: 252rpx;
  226. width: 100%;
  227. background-color: $uni-bg-color-grey;
  228. border-radius: 16rpx;
  229. textarea {
  230. width: 100%;
  231. height: 100%;
  232. font-size: 28rpx;
  233. line-height: 56rpx;
  234. margin: 0 16rpx;
  235. }
  236. }
  237. .sound-record-area {
  238. height: 240rpx;
  239. .pic-num {
  240. position: absolute;
  241. bottom: 224rpx;
  242. font-size: 16pt;
  243. z-index: 1;
  244. }
  245. /deep/ .sound-record-wrapper {
  246. width: 88%;
  247. position: absolute;
  248. bottom: 134rpx;
  249. padding: 32rpx 0;
  250. background-color: #ffffff;
  251. .sound-item-box {
  252. width: 74%;
  253. margin: 0 auto;
  254. }
  255. }
  256. }
  257. .reference {
  258. margin-top: 32rpx;
  259. background-color: $uni-bg-color-grey;
  260. padding: 24rpx;
  261. font-size: 28rpx;
  262. .reference-title {
  263. display: block;
  264. line-height: 64rpx;
  265. color: #4E5969;
  266. }
  267. .reference-answer {
  268. color: #1D2129;
  269. line-height: 48rpx;
  270. }
  271. }
  272. }
  273. }
  274. </style>
  275. <style>
  276. /deep/ .uni-swiper__dots-box {
  277. .uni-swiper__dots-indexes {
  278. width: 38rpx !important;
  279. height: 38rpx !important;
  280. }
  281. }
  282. </style>