playListInfo.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <script setup lang="ts">
  2. import {defineComponent, onBeforeMount, PropType, ref, watch} from "vue";
  3. import {MusicInfo, param_music_like, PlayList} from "@/types/musicType.ts";
  4. import LickIcon from "@/components/music/common/lickIcon.vue";
  5. import IconSvg from "@/components/public/icon/iconSvg.vue";
  6. import message from "@/components/public/kui/message";
  7. import {api_fetchMusic, api_likeMusic} from "@/apis/musicControl.ts";
  8. import {ErrorCode} from "@/types/apiTypes.ts";
  9. import {secondToTimeStr} from "../../../util/time.ts";
  10. import HideText from "@/components/public/hideText.vue";
  11. defineComponent({name: "play-list-info"});
  12. const props = defineProps({
  13. playList: {
  14. type: Object as PropType<PlayList>,
  15. default: () => ({})
  16. }
  17. })
  18. const musicList = ref<MusicInfo[]>([])
  19. let playlist_id = ref(0)
  20. const lock_loading = ref(false);
  21. const scanCount = ref(0)
  22. const search_key = ref("");
  23. const search_page = ref(1);
  24. const page_limit = 10;
  25. async function loadPlayListMusic(playList: PlayList, page: number, key: string){
  26. if (lock_loading.value)
  27. {
  28. message.info("正在加载中,请稍后");
  29. return;
  30. }
  31. lock_loading.value = true;
  32. let res = await api_fetchMusic(playList.id, page, page_limit, key)
  33. lock_loading.value = false;
  34. if (res.code === ErrorCode.success)
  35. {
  36. if (page === 1)
  37. {
  38. scanCount.value = res.data.total?? 0;
  39. }
  40. let pageData = res.data.data;
  41. for ( let i = 0; i < pageData.length; i++)
  42. {
  43. pageData[i].isLike = !!pageData[i].isLike;
  44. pageData[i].isLocal = !!pageData[i].isLocal;
  45. musicList.value.push(pageData[i]);
  46. }
  47. } else {
  48. message.error(res.msg);
  49. }
  50. }
  51. onBeforeMount(()=>{
  52. if (props.playList && props.playList.id)
  53. {
  54. loadPlayListMusic(props.playList, search_page.value, search_key.value);
  55. }
  56. })
  57. watch(()=>props.playList, ()=>{
  58. if (playlist_id.value !== props.playList.id)
  59. {
  60. musicList.value = [];
  61. loadPlayListMusic(props.playList, 1, search_key.value);
  62. }
  63. })
  64. function playMusic(item: MusicInfo) {
  65. console.log(item);
  66. message.info(`play ${item.name}`);
  67. }
  68. async function likeMusic(item: MusicInfo) {
  69. // console.log(item);
  70. // message.info(`like ${item.name}`);
  71. let nextLike = !item.isLike;
  72. let param: param_music_like = {
  73. musicId: item.id,
  74. isLike: nextLike
  75. }
  76. let res = await api_likeMusic(param);
  77. if (res.code === ErrorCode.success)
  78. {
  79. item.isLike = nextLike;
  80. if ( props.playList.isLike )
  81. {
  82. // 移除该项
  83. musicList.value = musicList.value.filter(item => item.id !== param.musicId);
  84. }
  85. }
  86. else {
  87. message.error(res.msg);
  88. }
  89. }
  90. function showMore(item: MusicInfo) {
  91. console.log(item);
  92. message.info(`show ${item.name}`);
  93. }
  94. let load_more_repeat = 0;
  95. async function loadMore()
  96. {
  97. if (musicList.value.length >= scanCount.value)
  98. {
  99. if (load_more_repeat > 3)
  100. {
  101. message.info("没有更多数据了");
  102. load_more_repeat = 0;
  103. return;
  104. }
  105. return;
  106. }
  107. search_page.value++;
  108. message.info("加载剩余数据");
  109. await loadPlayListMusic(props.playList, search_page.value, search_key.value);
  110. }
  111. </script>
  112. <template>
  113. <div class="play-list-info">
  114. <div class="info">
  115. <div class="cover">
  116. <img :src="playList.cover" alt="">
  117. </div>
  118. <div class="info-content">
  119. <div class="name">{{playList.name}}</div>
  120. <div class="desc">{{playList.description}}</div>
  121. <div class="time">创建时间: {{playList.createTime}}</div>
  122. </div>
  123. </div>
  124. <div class="music-lists">
  125. <div class="music-list-head">
  126. <div class="music-list-item">
  127. <div class="cover">
  128. </div>
  129. <div class="item-info">名称</div>
  130. <div class="origin">来源</div>
  131. <div class="duration">时长</div>
  132. <div class="isLike">喜欢</div>
  133. </div>
  134. </div>
  135. <div class="music-list-con scroll" @scrollend="loadMore()">
  136. <div v-for="item in musicList"
  137. class="music-list-item"
  138. @click="playMusic(item)"
  139. >
  140. <div class="cover">
  141. <img :src="item.cover" alt=""/>
  142. </div>
  143. <hide-text class="item-info" :text="item.name"
  144. :enable-copy="true"
  145. :copy-success="()=>{message.success('复制歌曲名称成功')}">
  146. <div class="name">{{item.name}}</div>
  147. <div class="artists">{{item.artists}}</div>
  148. </hide-text>
  149. <div class="origin">{{item.origin}}</div>
  150. <div class="duration">{{ secondToTimeStr(item.duration, "m分s秒" )}}</div>
  151. <lick-icon class="isLike" :like="item.isLike"
  152. @click.stop.capture="likeMusic(item)"/>
  153. <div class="more">
  154. <icon-svg icon-name="more" @click.stop.capture="showMore(item)"></icon-svg>
  155. </div>
  156. </div>
  157. </div>
  158. </div>
  159. </div>
  160. </template>
  161. <style scoped>
  162. @import "../../../assets/public.css";
  163. .play-list-info {
  164. display: flex;
  165. flex-direction: column;
  166. width: 100%;
  167. height: 100%;
  168. }
  169. .info {
  170. display: flex;
  171. width: 100%;
  172. height: 160px;
  173. padding: 10px;
  174. box-sizing: border-box;
  175. }
  176. .info .cover {
  177. width: 130px;
  178. height: 130px;
  179. background-color: #ccc;
  180. overflow: hidden;
  181. margin-left: 15px;
  182. margin-top: 5px;
  183. }
  184. .info-content {
  185. width: calc(100% - 130px);
  186. height: 100%;
  187. padding-left: 30px;
  188. font-size: 1em;
  189. }
  190. .info-content .name {
  191. font-size: 1.6rem;
  192. font-weight: bold;
  193. }
  194. .info-content .desc {
  195. font-size: 1rem;
  196. color: var(--color-text-subtitle);
  197. }
  198. .info-content .time {
  199. font-size: 0.8rem;
  200. margin-top: 10px;
  201. color: #999;
  202. }
  203. </style>