1111.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <template>
  2. <view class="container">
  3. <!-- 加载状态 -->
  4. <view v-if="loading" class="loading">加载中...</view>
  5. <!-- 单词主信息 -->
  6. <view v-if="wordData" class="word-card">
  7. <view class="word-header">
  8. <text class="word-name">{{ wordData.name }}</text>
  9. <text class="word-phonetic">{{ wordData.yinbiao }}</text>
  10. <!-- 主音频播放按钮 -->
  11. <button
  12. v-if="wordData.yinpin"
  13. class="play-btn"
  14. @click="playMainAudio">
  15. 播放单词
  16. </button>
  17. </view>
  18. <!-- 单词释义 -->
  19. <view class="word-meaning">
  20. <text v-for="(meaning, index) in wordData.xiangyi" :key="index">
  21. {{ meaning }}
  22. </text>
  23. </view>
  24. <!-- 音节部分 -->
  25. <view v-if="wordData.yinjie" class="section">
  26. <text class="section-title">音节分解</text>
  27. <view class="syllable-list">
  28. <view
  29. v-for="(syllable, index) in wordData.yinjie"
  30. :key="index"
  31. class="syllable-item"
  32. @click="playSyllableAudio(index)">
  33. <text>{{ syllable.cigen }}</text>
  34. <text>{{ syllable.yinbiao }}</text>
  35. </view>
  36. </view>
  37. </view>
  38. <!-- 频度部分 -->
  39. <view v-if="wordData.pindu" class="section">
  40. <text class="section-title">频度发音</text>
  41. <view class="frequency-list">
  42. <view
  43. v-for="(frequency, index) in wordData.pindu"
  44. :key="index"
  45. class="frequency-item"
  46. @click="playFrequencyAudio(index)">
  47. <text>{{ frequency.cigen }}</text>
  48. <text>{{ frequency.yinbiao }}</text>
  49. </view>
  50. </view>
  51. </view>
  52. </view>
  53. <!-- 清理缓存按钮 -->
  54. <button class="clean-btn" @click="audioManager.clearCache">
  55. 清理音频缓存
  56. </button>
  57. </view>
  58. </template>
  59. <script setup>
  60. import { ref, onMounted } from 'vue'
  61. import audioManager from '@/utils/audioManager'
  62. const wordData = ref(null)
  63. const loading = ref(false)
  64. // 加载单词数据
  65. const loadWordData = async (wordId) => {
  66. try {
  67. loading.value = true
  68. wordData.value = await audioManager.fetchAndCacheData(wordId)
  69. } catch (error) {
  70. uni.showToast({ title: '加载失败', icon: 'none' })
  71. } finally {
  72. loading.value = false
  73. }
  74. }
  75. // 播放主音频
  76. const playMainAudio = () => {
  77. if (!wordData.value?.yinpin) return
  78. audioManager.playAudio(`main_${wordData.value.id}`, wordData.value.yinpin)
  79. }
  80. // 播放音节音频
  81. const playSyllableAudio = (index) => {
  82. const syllable = wordData.value?.yinjie?.[index]
  83. if (!syllable?.yinpin) return
  84. audioManager.playAudio(`syllable_${wordData.value.id}_${index}`, syllable.yinpin)
  85. }
  86. // 播放频度音频
  87. const playFrequencyAudio = (index) => {
  88. const frequency = wordData.value?.pindu?.[index]
  89. if (!frequency?.yinpin) return
  90. audioManager.playAudio(`frequency_${wordData.value.id}_${index}`, frequency.yinpin)
  91. }
  92. onMounted(() => {
  93. // 示例:加载ID为42的单词数据
  94. loadWordData(42)
  95. })
  96. </script>
  97. <style>
  98. .container {
  99. padding: 20rpx;
  100. }
  101. .loading {
  102. text-align: center;
  103. padding: 20rpx;
  104. color: #888;
  105. }
  106. .word-card {
  107. background: #fff;
  108. border-radius: 16rpx;
  109. padding: 30rpx;
  110. margin-bottom: 30rpx;
  111. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  112. }
  113. .word-header {
  114. display: flex;
  115. align-items: center;
  116. margin-bottom: 20rpx;
  117. }
  118. .word-name {
  119. font-size: 40rpx;
  120. font-weight: bold;
  121. margin-right: 20rpx;
  122. }
  123. .word-phonetic {
  124. color: #666;
  125. margin-right: 20rpx;
  126. }
  127. .play-btn {
  128. background: #4a90e2;
  129. color: white;
  130. border-radius: 8rpx;
  131. padding: 8rpx 16rpx;
  132. font-size: 24rpx;
  133. }
  134. .word-meaning {
  135. margin-bottom: 30rpx;
  136. }
  137. .section {
  138. margin-bottom: 30rpx;
  139. }
  140. .section-title {
  141. display: block;
  142. font-weight: bold;
  143. margin-bottom: 15rpx;
  144. color: #333;
  145. }
  146. .syllable-list, .frequency-list {
  147. display: flex;
  148. flex-wrap: wrap;
  149. gap: 20rpx;
  150. }
  151. .syllable-item, .frequency-item {
  152. background: #f5f5f5;
  153. padding: 15rpx 25rpx;
  154. border-radius: 8rpx;
  155. display: flex;
  156. flex-direction: column;
  157. align-items: center;
  158. }
  159. .clean-btn {
  160. background: #f8f8f8;
  161. color: #333;
  162. margin-top: 40rpx;
  163. }
  164. </style>