ImageTextPreview.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div class="imageText-preview" :style="getAreaStyle()">
  4. <template v-if="data.mp3_list && data.mp3_list.length > 0 && mp3_url">
  5. <AudioLine
  6. audioId="Audio"
  7. :mp3="mp3_url"
  8. :getCurTime="getCurTime"
  9. :duration="data.mp3_list[0].media_duration"
  10. :mp3Source="data.mp3_list[0].source"
  11. :width="audio_width"
  12. :ed="ed"
  13. type="audioLine"
  14. ref="audioLine"
  15. @emptyEd="emptyEd"
  16. />
  17. </template>
  18. <div
  19. class="img-box"
  20. :style="{
  21. background: 'url(' + image_url + ') center / contain no-repeat',
  22. width: data.image_width + 'px',
  23. height: data.image_height + 'px',
  24. }"
  25. v-if="image_url"
  26. >
  27. <div
  28. v-for="(itemP, indexP) in data.text_list"
  29. :key="indexP"
  30. :class="['position-item', mageazineDetailIndex === indexP ? 'active' : '']"
  31. :style="{
  32. width: itemP.width,
  33. height: itemP.height,
  34. left: itemP.x,
  35. top: itemP.y,
  36. }"
  37. @click="handleChangePosition(indexP)"
  38. ></div>
  39. <div
  40. v-for="(itemP, indexP) in data.input_list"
  41. :key="indexP"
  42. :class="['position-item position-item-input', 'active']"
  43. :style="{
  44. width: itemP.width,
  45. height: itemP.height,
  46. left: itemP.x,
  47. top: itemP.y,
  48. }"
  49. >
  50. <el-input
  51. type="textarea"
  52. v-model="answer.answer_list[indexP].text"
  53. style="height: 100%"
  54. placeholder="请输入"
  55. ></el-input>
  56. </div>
  57. </div>
  58. </div>
  59. </template>
  60. <script>
  61. import PreviewMixin from '../common/PreviewMixin';
  62. import AudioLine from '../voice_matrix/components/AudioLine.vue';
  63. import { getImageTextData } from '@/views/book/courseware/data/imageText';
  64. import { GetFileURLMap } from '@/api/app';
  65. export default {
  66. name: 'ImageTextPreview',
  67. components: { AudioLine },
  68. mixins: [PreviewMixin],
  69. data() {
  70. return {
  71. data: getImageTextData(),
  72. curTime: 0,
  73. paraIndex: -1, //段落索引
  74. sentIndex: -1, // 句子索引
  75. ed: undefined,
  76. mp3_url: '',
  77. image_url: '',
  78. audio_width: 0,
  79. mageazineDetailIndex: null, // 当前高亮第几个
  80. mageazineDetailShow: false,
  81. inputIndex: null,
  82. };
  83. },
  84. methods: {
  85. initData() {
  86. if (!this.isJudgingRightWrong) {
  87. this.answer.answer_list = [];
  88. this.data.input_list.forEach((item, index) => {
  89. let obj = {
  90. text: '',
  91. answer: item.text,
  92. id: item.id,
  93. };
  94. this.answer.answer_list.push(obj);
  95. });
  96. }
  97. this.data.image_list.forEach((item) => {
  98. GetFileURLMap({ file_id_list: [item.file_id] }).then(({ url_map }) => {
  99. this.image_url = url_map[item.file_id];
  100. });
  101. });
  102. this.data.mp3_list.forEach((item) => {
  103. GetFileURLMap({ file_id_list: [item.file_id] }).then(({ url_map }) => {
  104. this.mp3_url = url_map[item.file_id];
  105. });
  106. });
  107. },
  108. getCurTime(curTime) {
  109. this.curTime = curTime * 1000;
  110. this.getSentIndex(this.curTime);
  111. },
  112. getSentIndex(curTime) {
  113. // for (let i = 0; i < this.curQue.wordTime.length; i++) {
  114. // let bg = this.curQue.wordTime[i].bg;
  115. // let ed = this.curQue.wordTime[i].ed;
  116. // if (curTime >= bg && curTime <= ed) {
  117. // this.sentIndex = i;
  118. // break;
  119. // }
  120. // }
  121. },
  122. emptyEd() {
  123. this.ed = undefined;
  124. },
  125. // 切换画刊里面的卡片
  126. handleChangePosition(index) {
  127. if (this.$refs.audioLine.audio.playing) {
  128. this.$refs.audioLine.PlayAudio();
  129. }
  130. this.mageazineDetailIndex = index;
  131. this.mageazineDetailShow = true;
  132. },
  133. },
  134. created() {
  135. this.initData();
  136. },
  137. mounted() {
  138. this.audio_width = document.getElementsByClassName('imageText-preview')[0].clientWidth - 150;
  139. },
  140. };
  141. </script>
  142. <style lang="scss" scoped>
  143. @use '@/styles/mixin.scss' as *;
  144. .position-item {
  145. position: absolute;
  146. z-index: 1;
  147. cursor: pointer;
  148. border: 3px solid transparent;
  149. &.active {
  150. border-color: #ff1616;
  151. }
  152. &:hover {
  153. border-color: #ff1616;
  154. }
  155. &.position-item-input {
  156. border-color: #f90;
  157. }
  158. :deep .el-textarea__inner {
  159. height: 100%;
  160. font-family: 'League', '楷体';
  161. text-align: center;
  162. resize: none;
  163. background: transparent;
  164. border: none;
  165. }
  166. }
  167. .img-box {
  168. position: relative;
  169. margin: 20px auto;
  170. }
  171. </style>