textReplaceIcon.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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 {
  7. debounce
  8. } from '@/utils/common';
  9. import {UseAudio} from "./useAudio.js"
  10. export default {
  11. props: {
  12. placeholders: { // 占位符
  13. type: Array,
  14. required: true
  15. },
  16. text: {
  17. type: String,
  18. },
  19. question: {
  20. type: Object,
  21. },
  22. code: {
  23. type: String
  24. },
  25. },
  26. data() {
  27. return {
  28. myflag: 0,
  29. isplaying: null,
  30. }
  31. },
  32. computed: {
  33. // 计算属性,用于生成填空后的文本
  34. formattedText() {
  35. let result = this.text;
  36. this.placeholders.forEach((placeholder, index) => {
  37. // 使用正则表达式全局替换占位符
  38. const regex = new RegExp(`\\${placeholder}`, 'g');
  39. if (!this.isplaying) {
  40. const cId = this.code ? `t_${this.question.stId}_${index}_${this.code}` :
  41. `t_${this.question.stId}_${index}`
  42. result = result.replace(regex,
  43. `<view class="yingyu-canplay-img" id="${cId}"></view>`
  44. );
  45. } else if (this.isplaying && this.question.stId == this.isplaying.stId && this.isplaying
  46. .index == index) {
  47. const cId = this.code ? `t_${this.question.stId}_${index}_${this.code}` :
  48. `t_${this.question.stId}_${index}`
  49. result = result.replace(regex,
  50. `<view class="yingyu-playing-img" id="${cId}"></view>`
  51. );
  52. } else {
  53. const cId = this.code ? `t_${this.question.stId}_${index}_${this.code}` :
  54. `t_${this.question.stId}_${index}`
  55. result = result.replace(regex,
  56. `<view class="yingyu-canplay-img" id="${cId}"></view>`
  57. );
  58. }
  59. });
  60. this.myflag++;
  61. return result;
  62. },
  63. },
  64. methods: {
  65. onResetPlayStatus(data) {
  66. if (this.isplaying) {
  67. if (data.stId == this.isplaying.stId && data.index == this.isplaying.index) {
  68. this.isplaying = null;
  69. }
  70. }
  71. },
  72. onYYAudioPlaying(data) {
  73. if (this.isplaying) {
  74. // 存在播放实例 并且播放非同一音频
  75. if (this.isplaying.stId != data.stId) {
  76. this.isplaying = null;
  77. }
  78. } else {
  79. // 不存在播放实例
  80. this.isplaying = data;
  81. }
  82. },
  83. onYYAudioError() {
  84. this.isplaying = null;
  85. },
  86. onYYAudioEnd() {
  87. this.isplaying = null;
  88. },
  89. onDestoryStop() {
  90. this.isplaying = null;
  91. },
  92. onSwiperChange() {
  93. this.isplaying = null;
  94. UseAudio.create().instance.stop();
  95. },
  96. onQuestionJiexiClose() {
  97. this.isplaying = null;
  98. UseAudio.create().instance.stop();
  99. },
  100. onUnitTestSubmit() {
  101. this.isplaying = null;
  102. UseAudio.create().instance.stop();
  103. },
  104. onBackOutPage() {
  105. this.isplaying = null;
  106. UseAudio.create().instance.stop();
  107. },
  108. handleClick() {
  109. this.$emit('itemclick')
  110. },
  111. audioClick(data) {
  112. UseAudio.create().instance.play(data);
  113. },
  114. },
  115. created() {
  116. // 切换不同播放音频时 重置状态
  117. uni.$on('reset-playing-status', this.onResetPlayStatus)
  118. // 音频播放
  119. uni.$on('yy-audio-playing', this.onYYAudioPlaying)
  120. // 音频异常 重置音频
  121. uni.$on('yy-audio-error', this.onYYAudioError)
  122. // 音频自然播放结束 重置音频
  123. uni.$on('yy-audio-end', this.onYYAudioEnd)
  124. // 音频销毁 重置音频
  125. uni.$on('destory-stop', this.onDestoryStop)
  126. // 试题切换 重置音频
  127. uni.$on('swiper-change',this.onSwiperChange)
  128. // 解析关闭 重置音频
  129. uni.$on('question-jiexi-close', this.onQuestionJiexiClose)
  130. uni.$on('unitTest-submit', this.onUnitTestSubmit)
  131. uni.$on('back-outpage', this.onBackOutPage)
  132. },
  133. destroyed() {
  134. // 切换不同播放音频时 重置状态
  135. uni.$off('reset-playing-status', this.onResetPlayStatus)
  136. // 音频播放
  137. uni.$off('yy-audio-playing', this.onYYAudioPlaying)
  138. // 音频异常 重置音频
  139. uni.$off('yy-audio-error', this.onYYAudioError)
  140. // 音频自然播放结束 重置音频
  141. uni.$off('yy-audio-end', this.onYYAudioEnd)
  142. // 音频销毁 重置音频
  143. uni.$off('destory-stop', this.onDestoryStop)
  144. // 试题切换 重置音频
  145. uni.$off('swiper-change',this.onSwiperChange)
  146. // 解析关闭 重置音频
  147. uni.$off('question-jiexi-close', this.onQuestionJiexiClose)
  148. uni.$off('unitTest-submit', this.onUnitTestSubmit)
  149. uni.$off('back-outpage', this.onBackOutPage)
  150. }
  151. }
  152. </script>
  153. <script module="YY" lang="renderjs">
  154. export default {
  155. data() {
  156. return {
  157. myQ: null,
  158. callbacks: [],
  159. status: '',
  160. }
  161. },
  162. methods: {
  163. debounce(func, wait) {
  164. let timeout;
  165. return function(...args) {
  166. // 清除之前的定时器
  167. clearTimeout(timeout);
  168. // 设置新的定时器
  169. timeout = setTimeout(() => {
  170. func.apply(this, args);
  171. }, wait);
  172. };
  173. },
  174. updateFlag() {
  175. this.initListener(this.myQ)
  176. },
  177. updateFn({
  178. stId,
  179. index
  180. }) {
  181. const url = this.myQ.audioList[index]
  182. this.$ownerInstance.callMethod('audioClick', {
  183. stId,
  184. index,
  185. url
  186. });
  187. },
  188. watchQuestionChange(newValue, oldValue, ownerInstance, instance) {
  189. if (newValue) {
  190. this.myQ = newValue;
  191. this.initListener(newValue)
  192. }
  193. },
  194. initListener(question) {
  195. if (!question) {
  196. return;
  197. }
  198. this.callbacks = [];
  199. question.placeholders.forEach((item, index) => {
  200. const cId = question.code ? `t_${question.stId}_${index}_${question.code}` :
  201. `t_${question.stId}_${index}`
  202. const dom = document.getElementById(cId)
  203. if (dom) {
  204. const qaindex = this.callbacks.findIndex(item => item.index === index)
  205. if (qaindex > -1) {
  206. dom && dom.removeEventListener('click', this.callbacks[qaindex].callback);
  207. this.callbacks = this.callbacks.filter(item => item.index != qaindex);
  208. }
  209. const callbackFn = this.debounce(() => {
  210. this.updateFn({
  211. stId: question.stId,
  212. index
  213. })
  214. }, 10)
  215. this.callbacks.push({
  216. index: index,
  217. stId: question.stId,
  218. callback: callbackFn
  219. })
  220. dom && dom.addEventListener('click', this.callbacks.find(cIte => cIte.index === index)
  221. .callback)
  222. }
  223. })
  224. },
  225. },
  226. }
  227. </script>
  228. <style>
  229. </style>