textReplaceIcon.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <template>
  2. <view v-html="formattedText" :myflag="myflag" :question="question" @click.native="handleClick"
  3. :change:myflag="YY.updateFlag" :change:question="YY.watchQuestionChange"></view>
  4. </template>
  5. <script>
  6. import { debounce } from '@/utils/common';
  7. export default {
  8. props: {
  9. placeholders: { // 占位符
  10. type: Array,
  11. required: true
  12. },
  13. text: {
  14. type: String,
  15. },
  16. showError: {
  17. type: Boolean,
  18. default: false
  19. },
  20. question: {
  21. type: Object,
  22. },
  23. },
  24. data() {
  25. return {
  26. myflag: 0,
  27. isplaying: null,
  28. isFirst: -1,
  29. }
  30. },
  31. computed: {
  32. // 计算属性,用于生成填空后的文本
  33. formattedText() {
  34. let result = this.text;
  35. this.placeholders.forEach((placeholder, index) => {
  36. // 使用正则表达式全局替换占位符
  37. const regex = new RegExp(`\\${placeholder}`, 'g');
  38. if (!this.isplaying) {
  39. result = result.replace(regex,
  40. `<view class="yingyu-canplay-img" id="t_${this.question.stId}_${index}"></view>`
  41. );
  42. } else if (this.question.stId == this.isplaying.stId && this.isplaying.index == index) {
  43. result = result.replace(regex,
  44. `<view class="yingyu-playing-img" id="t_${this.question.stId}_${index}"></view>`
  45. );
  46. } else {
  47. result = result.replace(regex,
  48. `<view class="yingyu-canplay-img" id="t_${this.question.stId}_${index}"</view>`
  49. );
  50. }
  51. });
  52. this.myflag++;
  53. return result;
  54. },
  55. },
  56. methods: {
  57. handleClick() {
  58. this.$emit('@itemclick')
  59. },
  60. audioClick(data) {
  61. if (this.isFirst >= 0) {
  62. uni.$emit('do-yy-audio-stop', data);
  63. this.isFirst = -1
  64. return;
  65. }
  66. if (this.isplaying) {
  67. uni.$emit('do-yy-audio-stop', data);
  68. this.isFirst++;
  69. return;
  70. }
  71. // 初次播放
  72. if (!this.isplaying) {
  73. uni.$emit('do-yy-audio-play', data);
  74. this.isFirst++;
  75. return;
  76. }
  77. }
  78. },
  79. created() {
  80. // 切换不同播放音频时 重置状态
  81. uni.$on('reset-playing-status',(data) => {
  82. if (this.isplaying) {
  83. if (data.stId == this.isplaying.stId && data.index == this.isplaying.index) {
  84. this.isplaying = null;
  85. }
  86. }
  87. })
  88. // 音频播放
  89. uni.$on('yy-audio-playing',(data) => {
  90. if (this.isplaying) {
  91. // 存在播放实例 并且播放非同一音频
  92. if (this.isplaying.stId != data.value.stId) {
  93. this.isplaying = null;
  94. }
  95. } else {
  96. // 不存在播放实例
  97. this.isplaying = data;
  98. }
  99. })
  100. // 音频异常 重置音频
  101. uni.$on('yy-audio-error',(data) => {
  102. this.isplaying = null;
  103. })
  104. // 音频自然播放结束 重置音频
  105. uni.$on('yy-audio-end',(data) => {
  106. this.isplaying = null;
  107. })
  108. // 音频销毁 重置音频
  109. uni.$on('destory-stop',(data) => {
  110. this.isplaying = null;
  111. })
  112. // 试题切换 重置音频
  113. uni.$on('swiper-change',() => {
  114. this.isplaying = null;
  115. })
  116. // 解析关闭 重置音频
  117. uni.$on('question-jiexi-close',() => {
  118. this.isplaying = null;
  119. })
  120. uni.$on('unitTest-submit',() => {
  121. this.isplaying = null;
  122. })
  123. }
  124. }
  125. </script>
  126. <script module="YY" lang="renderjs">
  127. import {debounce} from "@/utils/common.js"
  128. export default {
  129. props: {
  130. showError: {
  131. type: Boolean,
  132. default: false
  133. },
  134. placeholders: { // 占位符
  135. type: Array,
  136. required: true
  137. },
  138. },
  139. data() {
  140. return {
  141. myQ: null,
  142. callbacks: []
  143. }
  144. },
  145. methods: {
  146. updateFlag() {
  147. this.initListener(this.myQ)
  148. },
  149. updateFn({stId,index}) {
  150. const url = this.myQ.audioList[index]
  151. this.$ownerInstance.callMethod('audioClick', {stId,index,url});
  152. },
  153. watchQuestionChange(newValue, oldValue, ownerInstance, instance) {
  154. if (newValue) {
  155. this.myQ = newValue;
  156. this.initListener(newValue)
  157. }
  158. },
  159. initListener(question) {
  160. if (!question) {
  161. return;
  162. }
  163. if (this.showError) {
  164. return;
  165. }
  166. question.placeholders.forEach((item, index) => {
  167. const dom = document.getElementById(`t_${question.stId}_${index}`)
  168. if (dom) {
  169. const qaindex = this.callbacks.findIndex(item => item.index === index)
  170. if (qaindex>-1) {
  171. dom && dom.removeEventListener('click', this.callbacks[qaindex].callback);
  172. this.callbacks = this.callbacks.filter(item => item.index !=qaindex);
  173. }
  174. const callbackFn = debounce(() => { this.updateFn({ stId: question.stId, index})},100)
  175. this.callbacks.push({index: index, callback: callbackFn
  176. })
  177. dom && dom.addEventListener('click', this.callbacks.find(cIte => cIte.index === index).callback)
  178. }
  179. })
  180. },
  181. },
  182. }
  183. </script>
  184. <style>
  185. </style>