index.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
  2. import { useRoute, useRouter } from 'vue-router'
  3. import request from '@/helpers/request'
  4. import ColHeader from '@/components/col-header'
  5. import { Button, Icon, Image, List, NavBar, Sticky } from 'vant'
  6. import classNames from 'classnames'
  7. import Footer from '../album/footer'
  8. import FavoriteIcon from '../album/favorite.svg'
  9. import FavoritedIcon from '../album/favorited.svg'
  10. import styles from './index.module.less'
  11. import Item from '../list/item'
  12. import { useRect } from '@vant/use'
  13. import { useEventListener, useWindowScroll } from '@vueuse/core'
  14. import { getRandomKey, musicBuy } from '../music'
  15. import { state } from '@/state'
  16. import IconPan from './pan.png'
  17. import oStart from './oStart.png'
  18. import Title from '../component/title'
  19. import Song from '../component/song'
  20. import ColResult from '@/components/col-result'
  21. import MusicGrid from '../component/music-grid'
  22. const noop = () => {}
  23. export default defineComponent({
  24. name: 'AlbumDetail',
  25. props: {
  26. onItemClick: {
  27. type: Function,
  28. default: noop
  29. }
  30. },
  31. setup({ onItemClick }) {
  32. localStorage.setItem('behaviorId', getRandomKey())
  33. const router = useRouter()
  34. const params = reactive({
  35. search: '',
  36. page: 1,
  37. rows: 200
  38. })
  39. const albumDetail = ref<any>(null)
  40. const data = ref<any>(null)
  41. const rows = ref<any[]>([])
  42. const loading = ref(false)
  43. const finished = ref(false)
  44. const isError = ref(false)
  45. const favorited = ref(0)
  46. const albumFavoriteCount = ref(0)
  47. const headers = ref(null)
  48. const background = ref<string>('rgba(55, 205, 177, 0)')
  49. const heightInfo = ref<any>('auto')
  50. const route = useRoute()
  51. const FetchList = async () => {
  52. if (loading.value) {
  53. return
  54. }
  55. loading.value = true
  56. isError.value = false
  57. try {
  58. const res = await request.post('/music/album/detail', {
  59. prefix:
  60. state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student',
  61. data: { id: route.params.id, ...params }
  62. })
  63. const { musicSheetList, ...rest } = res.data
  64. rows.value = [...rows.value, ...musicSheetList.rows]
  65. const musicTagNames = rest?.musicTagNames?.split(',') || []
  66. albumDetail.value = {
  67. ...rest,
  68. musicTagNames
  69. }
  70. data.value = musicSheetList
  71. params.page = musicSheetList.pageNo + 1
  72. finished.value = musicSheetList.pageNo >= musicSheetList.totalPage
  73. favorited.value = rest.favorite
  74. albumFavoriteCount.value = rest.albumFavoriteCount
  75. } catch (error) {
  76. isError.value = true
  77. }
  78. loading.value = false
  79. }
  80. const favoriteLoading = ref(false)
  81. onMounted(() => {
  82. FetchList()
  83. useEventListener(document, 'scroll', evt => {
  84. const { y } = useWindowScroll()
  85. background.value = `rgba(55, 205, 177, ${y.value / 100})`
  86. })
  87. })
  88. const toggleFavorite = async (id: number) => {
  89. favoriteLoading.value = true
  90. try {
  91. await request.post('/music/album/favorite/' + id, {
  92. prefix:
  93. state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student'
  94. })
  95. favorited.value = favorited.value === 1 ? 0 : 1
  96. albumFavoriteCount.value += favorited.value ? 1 : -1
  97. } catch (error) {}
  98. favoriteLoading.value = false
  99. }
  100. return () => {
  101. return (
  102. <div class={styles.detail}>
  103. <div ref={headers}>
  104. <ColHeader
  105. background={background.value}
  106. border={false}
  107. color="#fff"
  108. backIconColor="white"
  109. onHeaderBack={() => {
  110. nextTick(() => {
  111. const { height } = useRect(headers as any)
  112. heightInfo.value = height
  113. })
  114. }}
  115. />
  116. </div>
  117. <img class={styles.bgImg} src={albumDetail.value?.albumCoverUrl} />
  118. <div class={styles.musicContent}></div>
  119. <div class={styles.bg}>
  120. <div class={styles.alumWrap}>
  121. <div class={styles.img}>
  122. <Image
  123. class={styles.image}
  124. width="100%"
  125. height="100%"
  126. fit="cover"
  127. src={albumDetail.value?.albumCoverUrl}
  128. />
  129. </div>
  130. <div class={styles.alumDes}>
  131. <div class={[styles.alumTitle, 'van-ellipsis']}>
  132. {albumDetail.value?.albumName}
  133. </div>
  134. <div class={styles.tags}>
  135. {albumDetail.value?.musicTagNames?.map((tag: any) => (
  136. <span class={styles.tag}>{tag}</span>
  137. ))}
  138. </div>
  139. <div
  140. class={[styles.des, 'van-multi-ellipsis--l3']}
  141. style={{
  142. height: '48px',
  143. lineHeight: '16px'
  144. }}
  145. >
  146. {albumDetail.value?.albumDesc}
  147. </div>
  148. </div>
  149. </div>
  150. <div class={styles.alumCollect}>
  151. <img src={IconPan} />
  152. <span>共{albumDetail.value?.musicSheetCount}首曲目</span>
  153. <img class={styles.right} src={oStart} />
  154. <span>{albumDetail.value?.albumFavoriteCount}人收藏</span>
  155. </div>
  156. </div>
  157. <div class={styles.alumnContainer}>
  158. <div class={styles.alumnList}>
  159. <Title title="曲目列表" isMore={false} />
  160. <Song
  161. list={rows.value}
  162. onDetail={(item: any) => {
  163. if (onItemClick === noop || !onItemClick) {
  164. musicBuy(item, () => {}, {
  165. albumId: route.params.id
  166. })
  167. } else {
  168. onItemClick(item)
  169. }
  170. }}
  171. />
  172. {rows.value && rows.value.length <= 0 && (
  173. <ColResult btnStatus={false} tips="暂无曲目" />
  174. )}
  175. </div>
  176. {albumDetail.value?.relatedMusicAlbum &&
  177. albumDetail.value?.relatedMusicAlbum.length > 0 && (
  178. <>
  179. <Title
  180. title="相关专辑"
  181. onMore={() => {
  182. router.push({
  183. path: '/music-album'
  184. })
  185. }}
  186. />
  187. <MusicGrid
  188. list={albumDetail.value?.relatedMusicAlbum}
  189. onGoto={(n: any) =>
  190. router.push({
  191. path: '/music-album-detail/' + n.id
  192. })
  193. }
  194. />
  195. </>
  196. )}
  197. </div>
  198. </div>
  199. )
  200. }
  201. }
  202. })