textReplaceIcon.vue 5.2 KB

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