textReplaceIcon.vue 5.2 KB

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