textReplaceIcon.vue 5.2 KB

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