index.tsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. import {
  2. defineComponent,
  3. ref,
  4. reactive,
  5. onMounted,
  6. computed,
  7. watch
  8. } from 'vue';
  9. import { useRoute } from 'vue-router';
  10. import request from '@/helpers/request';
  11. import MEmpty from '@/components/m-empty';
  12. import styles from './index.module.less';
  13. import musicBg from '../../image/music_bg.png';
  14. import titleIcon1 from '../../image/title_icon1.png';
  15. import titleIcon2 from '../../image/title_icon2.png';
  16. import playIcon from '../../image/music_play_icon.png';
  17. import pauseIcon from '../../image/music_pause_icon.png';
  18. import emptyIcon from '../../image/ins-empty-icon.png';
  19. import { NoticeBar } from 'vant';
  20. import PlayItem from '../play-item';
  21. export default defineComponent({
  22. name: 'InstrumentInfo',
  23. props: {
  24. id: {
  25. type: String,
  26. default: ''
  27. },
  28. type: {
  29. type: String,
  30. default: ''
  31. },
  32. show: {
  33. type: Boolean,
  34. default: false
  35. }
  36. },
  37. emits: ['close', 'select'],
  38. setup(props, { emit }) {
  39. const route = useRoute();
  40. const forms = reactive({
  41. detailId: route.query.detailId,
  42. loading: false,
  43. dataInfo: {} as any,
  44. musicList: [] as any,
  45. title: ' ',
  46. playState: 'pause' as 'play' | 'pause',
  47. showPlayer: false,
  48. listActive: 0
  49. });
  50. /** 选中的item */
  51. const activeItem = computed(() => {
  52. return forms.musicList[forms.listActive] || {};
  53. });
  54. const getDetail = async () => {
  55. forms.loading = true;
  56. try {
  57. const { data } = await request.get(
  58. '/edu-app/knowledgeWiki/detail/' + props.id
  59. );
  60. data.intros = data.intros.replace(
  61. /<video/gi,
  62. '<video class="video-music" style="width: 100% !important;" controlslist="nodownload" poster="https://oss.dayaedu.com/ktqy/1701759849244.png"'
  63. );
  64. forms.dataInfo = data || {};
  65. forms.musicList = data.knowledgeWikiResources.map((item: any) => {
  66. return {
  67. id: item.id,
  68. name: item.name,
  69. url: item.url
  70. };
  71. });
  72. } catch {}
  73. forms.loading = false;
  74. };
  75. /** 播放曲目 */
  76. const handlePlay = (item: any) => {
  77. const index = forms.musicList.findIndex(
  78. (_item: any) => _item.id === item.id
  79. );
  80. if (index > -1) {
  81. if (forms.listActive === index) {
  82. forms.playState = forms.playState === 'play' ? 'pause' : 'play';
  83. } else {
  84. forms.playState = 'play';
  85. }
  86. forms.showPlayer = true;
  87. forms.listActive = index;
  88. }
  89. };
  90. /** 音频控制 */
  91. const handleChangeAudio = (
  92. type: 'play' | 'pause' | 'pre' | 'next' | 'favitor'
  93. ) => {
  94. if (type === 'play') {
  95. forms.playState = 'play';
  96. } else if (type === 'pause') {
  97. forms.playState = 'pause';
  98. } else if (type === 'pre') {
  99. if (forms.musicList[forms.listActive - 1]) {
  100. handlePlay(forms.musicList[forms.listActive - 1]);
  101. }
  102. } else if (type === 'next') {
  103. if (forms.musicList[forms.listActive + 1]) {
  104. handlePlay(forms.musicList[forms.listActive + 1]);
  105. }
  106. }
  107. };
  108. watch(
  109. () => props.show,
  110. val => {
  111. if (val) {
  112. // onToggleAudio();
  113. } else {
  114. // audioRef.value.pause();
  115. // data.playState = 'pause';
  116. handleChangeAudio('pause');
  117. try {
  118. // 暂停视频
  119. const doms = document.querySelectorAll('.video-music');
  120. if (doms && doms.length > 0) {
  121. doms.forEach((dom: any) => {
  122. dom.pause();
  123. });
  124. }
  125. } catch {
  126. //
  127. }
  128. }
  129. }
  130. );
  131. onMounted(async () => {
  132. await getDetail();
  133. });
  134. return () => (
  135. <div
  136. class={[styles.knowledgeBg, forms.showPlayer ? styles.wrapBottom : '']}>
  137. <div class={styles.left}>
  138. {props.type === 'wiki' && (
  139. <div class={styles.insTop}>
  140. <div class={styles.imgSection}>
  141. <img
  142. class={styles.img}
  143. src={forms.dataInfo.avatar || musicBg}
  144. />
  145. <div class={styles.pan}>
  146. <img src={forms.dataInfo.avatar || musicBg} />
  147. </div>
  148. </div>
  149. {/* <div class={styles.songName}>{forms.dataInfo.name || '--'}</div> */}
  150. <NoticeBar
  151. text={forms.dataInfo.name}
  152. color="#000"
  153. class={styles.songName}
  154. background="none"
  155. />
  156. <div class={styles.songWords}>
  157. {forms.dataInfo.lyricists && (
  158. <span>作词:{forms.dataInfo.lyricists}</span>
  159. )}
  160. {forms.dataInfo.composers && (
  161. <span>作曲:{forms.dataInfo.composers}</span>
  162. )}
  163. </div>
  164. </div>
  165. )}
  166. {props.type === 'instrument' && (
  167. <div class={styles.insTop}>
  168. <img src={forms.dataInfo.avatar} />
  169. <div class={styles.insName}>{forms.dataInfo.name || ''}</div>
  170. <div class={styles.insTro}>
  171. {forms.dataInfo.knowledgeWikiCategoryName || ''}
  172. </div>
  173. </div>
  174. )}
  175. {props.type === 'musician' && (
  176. <div class={styles.insTop}>
  177. <img class={styles.musician} src={forms.dataInfo.avatar} />
  178. <div class={styles.insName}>{forms.dataInfo.name || ''}</div>
  179. <div class={styles.insTro}>
  180. {forms.dataInfo.knowledgeWikiCategoryName || ''}
  181. </div>
  182. </div>
  183. )}
  184. <div class={styles.insList}>
  185. {forms.musicList.length ? (
  186. <>
  187. {forms.musicList.map((item: any, index: number) => {
  188. return (
  189. <div
  190. class={styles.li}
  191. onClick={(e: Event) => {
  192. e.stopPropagation();
  193. handlePlay(item);
  194. }}>
  195. <img class={styles.liBg} src={musicBg} />
  196. <div class={styles.liName}>{item.name || '--'}</div>
  197. <img
  198. class={styles.liPlay}
  199. src={
  200. forms.listActive === index &&
  201. forms.playState === 'play'
  202. ? pauseIcon
  203. : playIcon
  204. }
  205. />
  206. </div>
  207. );
  208. })}
  209. </>
  210. ) : (
  211. <div class={styles.emptyBox}>
  212. <img src={emptyIcon} />
  213. <span>暂无曲目~</span>
  214. </div>
  215. )}
  216. </div>
  217. </div>
  218. <div class={styles.right}>
  219. <div class={styles.title}>
  220. <img
  221. class={styles.liBg}
  222. src={props.type === 'musician' ? titleIcon2 : titleIcon1}
  223. />
  224. {props.type === 'wiki'
  225. ? '乐器简介'
  226. : props.type === 'instrument'
  227. ? '名曲故事'
  228. : props.type === 'musician'
  229. ? '个人简介'
  230. : ''}
  231. </div>
  232. <div class={styles.desc} v-html={forms.dataInfo.intros}></div>
  233. {!forms.loading && !forms.dataInfo.intros && (
  234. <MEmpty description="暂无内容" />
  235. )}
  236. </div>
  237. {forms.musicList.length !== 0 && (
  238. <PlayItem
  239. show={forms.showPlayer}
  240. playState={forms.playState}
  241. item={activeItem.value}
  242. onChange={value => handleChangeAudio(value)}
  243. />
  244. )}
  245. </div>
  246. );
  247. }
  248. });