功能较为齐全的音乐播放器(vue进阶)

时间:2024-02-21 09:10:57

首先是环境的搭建

①安装node.js,安装步骤如下:

进入http://nodejs.cn/download/,我下载的是win64位的安装包,一路下一步,完成安装。进入cmd,输入node -v以及npm -v 查看安装版本。

由于使用npm原本的源下载可能会慢,这里我用的是淘宝的镜像

npm config set registry https://registry.npm.taobao.org
安装淘宝镜像

②安装vue,通过npm install vue安装vue。安装成功后,用vue-cli(脚手架)创建vue项目,通过cmd在想要创建的文件目录下输入 vue create 项目名即可创建项目,

然后回车,出现如下界面。

 

 

 这里是选择项目预设的插件,第一个是默认,第二个是自己设置。这里我选择第二个,出现如下界面,选择插件,这里我只选择了Babel

 

 

 以下为一部分解释

1 >( ) TypeScript                                 // 支持使用 TypeScript 书写源码
2  ( ) Progressive Web App (PWA) Support          // PWA 支持
3  ( *) Router                                     // 支持 vue-router
4  ( ) Vuex                                       // 支持 vuex
5  (* ) CSS Pre-processors                         // 支持 CSS 预处理器。
6  ( *) Linter / Formatter                         // 支持代码风格检查和格式化。
7  ( ) Unit Testing                               // 支持单元测试。
8  ( ) E2E Testing                                // 支持 E2E 测试。

然后都下一步,接着等待vue-cli配置完成。然后cd进入创建的项目文件夹,然后使用npm run serve就可以获得vue项目对应的页面。(我的理解就是编译)

由于我用的是idea,接下来在介绍一下通过idea打开创建的vue项目。首先要安装vue.js插件,通过settings->plugings安装,我是先下载了安装包,再安装的。

安装完成后,通过open可以打开创建的项目,以下是文件目录。

 

 

 *组件是App.vue。组件放在components里,assets里可以放图片等资源。然后还需要安装axios和vue-router(分别用于获取数据和页面的切换)还有element-ui,通过idea终端输入命令npm install vue-router

安装路由,然后需要在main.js中执行。接着就可以使用路由了。通过终端输入命令npm install axios安装axios,在需要使用的页面导入一下即可使用。通过npm i element-ui -S 安装element-ui,然后导入,使用。

 

具体实现:

我实现了以下功能:

①发现音乐 ②推荐歌单 ③最新音乐 ④最新MV ⑤搜索歌曲、歌单、MV

概览

 

 这是一个单页面应用SPA,主页面分为最上面的板块(包含名字,搜索栏)和下面的板块(选项卡+主要内容),其中各个模块都是由路由显示在主要内容里的,即让路由的出口设在那个页面里。

以下为组件图

 

 

 *组件App.vue下是top.vue和main_wrap.vue组件,其他的都是路由设在main_wrap里的组件。

问题总结:

要熟悉一些ES6语法,可以提高代码效率;

需要注意vue组件中html写在<template>标签中,<script>中写js,<style>中写css。<template>中只能有一个顶层标签;

使用的插件如router,axios,element-ui都需要导入,在main.js中完成相应操作;

v-for组件的使用要有key;

在当前组件导入其他组件时,需要使用import导入,然后在components中注册组件;

在组件中传参数可以使用this.$router.push传参,this.$route接收;

created(){},watch:{},的使用;

通过this.$router.push到当前页面会出错,页面不会自动刷新,可以使用watch监听$route变化;

直接在for循环中使用axios会出错,即在for循环中进行异步操作会出问题,可以用递归或者async await解决;

在数据处理时将时间戳转化为年月日,可以使用date对象的方法,我这里通过重写toLocaleString方法获得想要的时间格式;

还有要注意接口获得的数据格式,自己定义的数据格式要与想获得的数据一样;

element-ui中的icon本质是字体,还有轮播图,分页、选项卡,表格的使用都需要注意;

还有一些动态出现的按钮可以通过overflow实现;

这次使用的css有很多重复,下次可以先注意一下,直接引入,而不用在每个组件里都写一遍;

多行文字溢出效果实现,https://blog.csdn.net/anwj1020/article/details/93481799

关于display:flex布局方式,可以查看http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

 

以下为代码:

App.vue

<template>
 <div id="app">
  <top></top>
  <main_wrap></main_wrap>
 </div>
</template>

<script>
  import top from "./components/top.vue"
  import main_wrap from "./components/main_wrap"
export default {
  name: \'App\',
  components: {
     top:top,
     main_wrap:main_wrap,
  }
}
</script>

<style>
  *{
    margin: 0;
    padding: 0;
   box-sizing: border-box;
   transition: 0.5s;
  }
</style>

top.vue

<template>
    <div id="top">
        <span>DougIger\'s MP3</span>
        <input type="text" v-model="inputValue"
               placeholder="搜索歌曲"
               @keyup.enter="searchMusic">
        <el-button  class="search_but" icon="el-icon-search" circle @click="searchMusic"></el-button>
    </div>
</template>

<script>
    export default {
        name: "top",
        data(){
            return{
                inputValue:\'\',
            }
        },
        methods:{
            searchMusic(){
                if(this.inputValue==\'\'){
                    //为空则弹出提示框
                    this.$message({
                        message:\'请输入内容\',
                        center:true,
                        type:\'warning\',
                    })
                }else{
                    //有内容则跳转
                    this.$router.push(\'/result?keyword=\'+this.inputValue);
                }
            }
        }
    }
</script>

<style scoped>
    #top{
        display: flex;
        position: fixed;
        align-items: center;
        width:100%;
        height: 60px;
        top:0;
        left: 0;
        background-color: #f9f9f9;
        z-index: 999;
        padding:20px;
        justify-content:flex-end;

    }
    #top>span{
        position:absolute;
        left: 20px;
        font-size: 25px;
        font-weight: bold;
        color: #A6B0D9;
    }
    #top>img{
        width: 85%;
    }
    .search_but{
        margin-left: 10px;

    }

</style>

main_wrap.vue

 1 <template>
 2     <div id="main_wrap">
 3         <div class="nav">
 4             <ul>
 5                 <li><router-link to="/discovery">发现音乐</router-link></li>
 6                 <li><router-link to="/recommend">推荐歌单</router-link></li>
 7                 <li><router-link to="/newMusic">最新音乐</router-link></li>
 8                 <li><router-link to="/newMv">最新MV</router-link></li>
 9             </ul>
10         </div>
11         <div class="main">
12             <!-- <discovery></discovery>-->
13             <!-- 路由的出口 地址命中之后,把组件显示的位置-->
14             <router-view :key="this.$route.path"></router-view>
15         </div>
16         <div class="player">
17             <audio :src="musicUrl" controls="controls" autoplay></audio>
18         </div>
19     </div>
20 </template>
21 
22 <script>
23     import discovery from \'./discovery.vue\'
24     export default {
25         name: "main_wrap",
26         data(){
27           return{
28               musicUrl:"",
29             }
30         },
31         components:{
32            discovery,//discovery:discovery
33         }
34     }
35 </script>
36 
37 <style scoped>
38  #main_wrap{
39      position: relative;
40      display: flex;
41      width: 100%;
42      /*设置宽度为当前设备的视窗*/
43      height: calc(100vh);
44      padding-top: 60px;
45      padding-bottom: 60px;
46  }
47  .nav{
48      width: 200px;
49      height: 100%;
50      background-color:#ededed;
51  }
52  ul>li{
53      text-align: center;
54      margin:30px auto;
55      font-size: 20px;
56  }
57   .main{
58       flex:1;
59       overflow-y: scroll;
60   }
61    a.router-link-exact-active{
62        color:white;
63        background-color: orange;
64    }
65    a{
66        color:black;
67        text-decoration: none;
68    }
69     .player{
70         position: fixed;
71         bottom: 0;
72         left: 0;
73         height:60px;
74         width: 100%;
75         background-color:rgb(241,243,244);
76     }
77     .player>audio{
78         display: block;
79         outline: none;
80         width: 100%;
81     }
82 
83 </style>

discovery.vue(发现音乐)

  1 <template>
  2     <div>
  3         <!--elementui的轮播图-->
  4         <el-carousel :interval="4000" type="card" height="250px" class="banner">
  5             <el-carousel-item v-for="(item,index) in banner" :key="index">
  6                 <img :src="item.imageUrl" alt="">
  7             </el-carousel-item>
  8         </el-carousel>
  9         <!--推荐歌单-->
 10         <div class="recommend">
 11             <h3 class="title">推荐歌单</h3>
 12             <div class="items">
 13                 <div class="item" v-for="(item,index) in list" :key="index" @click="toPlayList(item.id)">
 14                     <div class="img_wrap">
 15                         <span class="copywriter">{{item.copywriter}}</span>
 16                         <img :src="item.picUrl" alt="">
 17                         <span></span>
 18                     </div>
 19                     <p>{{item.name}}</p>
 20                 </div>
 21             </div>
 22         </div>
 23         <!--最新歌曲-->
 24         <div class="newsong">
 25             <h3>最新音乐</h3>
 26             <div class="items">
 27                 <div class="item" v-for="(item,index) in newsongs" :key="index">
 28                     <div class="img_wrap">
 29                         <img :src="item.picUrl" alt="">
 30                         <span class="el-icon-video-play play-but" @click="playMusic(item.id)"></span>
 31                     </div>
 32                     <div class="song_wrap">
 33                         <p class="song_name">{{item.name}}</p>
 34                         <p class="song_artist">{{item.song.artists[0].name}}</p>
 35                     </div>
 36                 </div>
 37             </div>
 38         </div>
 39         <!--推荐mv-->
 40         <div class="newMv">
 41             <h3>推荐MV</h3>
 42             <div class="items">
 43                 <div class="item" v-for="(item,index) in mvs" :key="index">
 44                     <div class="img_wrap">
 45                         <img :src="item.picUrl" alt="" @click="toMv(item.id)">
 46                         <span class="play_count"><i class="el-icon-caret-right"></i>{{item.playCount}}</span>
 47                     </div>
 48                     <div class="info_wrap">
 49                         <p>{{item.name}}</p>
 50                         <p class="song_artist">{{item.artistName}}</p>
 51                     </div>
 52                 </div>
 53             </div>
 54         </div>
 55 
 56     </div>
 57 </template>
 58 
 59 <script>
 60     //导入axios
 61     import axios from \'axios\'
 62     export default {
 63         name: "discovery",
 64         data(){
 65             return{
 66                 //轮播图
 67                 banner:[],
 68                 list:[],
 69                 newsongs:[],
 70                 mvs:[],
 71             }
 72         },
 73         created() {
 74             //调用轮播图接口
 75             axios({
 76                 url:\'https://autumnfish.cn/banner\',
 77                 method:\'get\',
 78             }).then(response=>{
 79                 this.banner=response.data.banners;
 80             })
 81             //调用推荐歌单接口
 82             axios({
 83                 url:\'https://autumnfish.cn/personalized\',
 84                 method:\'get\',
 85                 params:{
 86                     //获取的数据量
 87                     limit:10,
 88                 },
 89             }).then(response=>{
 90                 //console.log(response);
 91                 this.list=response.data.result;
 92             })
 93             axios({
 94                 url:\'https://autumnfish.cn/personalized/newsong\',
 95                 method:\'get\',
 96             }).then(response=>{
 97                 //console.log(response);
 98                 this.newsongs=response.data.result;
 99 
100             })
101             axios({
102                 url:\'https://autumnfish.cn/personalized/mv\',
103                 method:\'get\',
104             }).then(response=>{
105                 //console.log(response);
106                 this.mvs=response.data.result;
107             })
108         },
109         methods:{
110             playMusic(id){
111                 axios({
112                     url:\'https://autumnfish.cn/song/url\',
113                     method:\'get\',
114                     params:{
115                         id:id,
116                     },
117                 }).then(response=>{
118                     this.$parent.musicUrl=response.data.data[0].url;
119                 })
120             },
121             toPlayList(id){
122                 //传参数到PlayList
123                 this.$router.push(`/PlayList?id=${id}`);
124             },
125             toMv(id){
126                 //传参数到MV
127                 this.$router.push(`/MV?id=${id}`);
128             }
129         }
130 
131     }
132 </script>
133 
134 
135 <style scoped>
136     img{
137         width: 100%;
138         height: 100%;
139         border-radius:5px ;
140     }
141     .banner{
142         width: 90%;
143         position: relative;
144         overflow: hidden;
145         top:5px;
146         left:5%;
147     }
148     .recommend{
149         position: relative;
150         width:90%;
151         left: 5%;
152     }
153     .items{
154         display: flex;
155         flex-wrap:wrap;
156     }
157     .item{
158         position: relative;
159         width: 200px;
160         margin: 10px;
161         overflow: hidden;
162     }
163     .img_wrap{
164         position: relative;
165         width: 200px;
166         height: 200px;
167         cursor: pointer;
168     }
169     .copywriter{
170         position: absolute;
171         width: 200px;
172         top:-50px;
173         text-align: center;
174     }
175     .img_wrap:hover .copywriter{
176         position: absolute;
177         width: 200px;
178         top:0;
179         color: white;
180         background-color: black;
181         opacity: 0.8;
182         text-align: center;
183     }
184     .newsong{
185         position: relative;
186         top:20px;
187         width:90%;
188         left: 5%;
189     }
190     .newsong .item{
191         display: flex;
192         position: relative;
193         width: 40%;
194         height: 100px;
195         margin: 10px 20px;
196     }
197     .newsong .item:hover{
198         background-color:darkgray;
199         opacity: 0.8;
200     }
201     .newsong .img_wrap{
202         width: 100px;
203         height: 100px;
204     }
205     .newsong .song_wrap{
206         position: relative;
207         flex-direction: row;
208         flex: 1;
209         margin: 10px;
210     }
211     .song_artist{
212         color: grey;
213         font-size:15px;
214         margin-top: 20px;
215     }
216     .play-but{
217         display: block;
218         position: absolute;
219         width: 50px;
220         height: 50px;
221         bottom: -50px;
222         left: 28px;
223         font-size:50px;
224         color: sandybrown;
225     }
226     .img_wrap:hover .play-but{
227         display: block;
228         position: absolute;
229         width: 50px;
230         height: 50px;
231         bottom: 20px;
232         left: 28px;
233         font-size:50px;
234         color: sandybrown;
235     }
236     .newMv{
237         position: relative;
238         top:40px;
239         width:90%;
240         left: 5%;
241     }
242     .newMv .item{
243         width: 22%;
244     }
245     .newMv .img_wrap{
246         width: 250px;
247         height: 150px;
248     }
249     .newMv .info_wrap{
250         text-align: center;
251     }
252     .newMv .song_artist{
253         margin-top: 10px;
254     }
255     .newMv .play_count{
256         background-image: linear-gradient(to right,rgba(255,0,0,0),rgba(58,58,10,1));
257         position: absolute;
258         right: 0;
259         color: white;
260     }
261     h3{
262         font-weight: normal;
263     }
264 
265 
266 
267 </style>

recommendList.vue(推荐歌单)

  1 <template>
  2     <div>
  3         <div class="top_card">
  4             <div class="img_wrap">
  5                 <img :src="topList.coverImgUrl" alt="">
  6             </div>
  7             <div class="info_wrap">
  8                 <div class="tag">精品歌单</div>
  9                 <div class="title">{{topList.name}}</div>
 10                 <div class="content">{{topList.description}}</div>
 11             </div>
 12             <img :src="topList.coverImgUrl" class="bgimg">
 13             <div class="bg_mask"></div>
 14         </div>
 15         <div class="main_card">
 16             <div class="tab_bar">
 17                 <span class="types" :class="{active:tag==\'全部\'}" @click="tag=\'全部\'">全部</span>
 18                 <span class="types" :class="{active:tag==\'欧美\'}" @click="tag=\'欧美\'">欧美</span>
 19                 <span class="types" :class="{active:tag==\'华语\'}" @click="tag=\'华语\'">华语</span>
 20                 <span class="types" :class="{active:tag==\'流行\'}" @click="tag=\'流行\'">流行</span>
 21                 <span class="types" :class="{active:tag==\'说唱\'}" @click="tag=\'说唱\'">说唱</span>
 22                 <span class="types" :class="{active:tag==\'摇滚\'}" @click="tag=\'摇滚\'">摇滚</span>
 23                 <span class="types" :class="{active:tag==\'民谣\'}" @click="tag=\'民谣\'">民谣</span>
 24                 <span class="types" :class="{active:tag==\'电子\'}" @click="tag=\'电子\'">电子</span>
 25                 <span class="types" :class="{active:tag==\'轻音乐\'}" @click="tag=\'轻音乐\'">轻音乐</span>
 26                 <span class="types" :class="{active:tag==\'影视原声\'}" @click="tag=\'影视原声\'">影视原声</span>
 27                 <span class="types" :class="{active:tag==\'ACG\'}" @click="tag=\'ACG\'">ACG</span>
 28                 <span class="types" :class="{active:tag==\'怀旧\'}" @click="tag=\'怀旧\'">怀旧</span>
 29                 <span class="types" :class="{active:tag==\'治愈\'}" @click="tag=\'治愈\'">治愈</span>
 30                 <span class="types" :class="{active:tag==\'旅行\'}" @click="tag=\'旅行\'">旅行</span>
 31             </div>
 32             <div class="items">
 33                 <div class="item" v-for="(item,index) in list" :key="index" @click="toPlayList(item.id)">
 34                     <div class="img_wrap">
 35                         <span class="copywriter">播放量:{{item.playCount}}</span>
 36                         <img :src="item.coverImgUrl" alt="">
 37                         <span class="el-icon-video-play play-but" ></span>
 38                     </div>
 39                     <div class="info_wrap">
 40                         <p>{{item.name}}</p>
 41                     </div>
 42                 </div>
 43             </div>
 44         </div>
 45         <div class="page_card">
 46             <el-pagination
 47                     @current-change="currentPage"
 48                     layout="prev, pager, next"
 49                     :current-page="page"
 50                     :page-size="15"
 51                     :total="total">
 52             </el-pagination>
 53         </div>
 54 
 55     </div>
 56 </template>
 57 
 58 <script>
 59     //导入axios
 60     import axios from \'axios\';
 61     export default {
 62         name: "recommendList",
 63         data(){
 64             return{
 65                 topList:{},
 66                 list:[],
 67                 tag:\'全部\',
 68                 //分页的总记录数
 69                 total:0,
 70                 //当前页数
 71                 page:1,
 72             }
 73 
 74         },
 75         //侦听器
 76         watch:{
 77             tag(){
 78                 if(this.tag!=\'旅行\')//接口中没有旅行
 79                  this.topData();
 80                 this.page=1;
 81                 this.listData();
 82             }
 83         },
 84         created(){
 85            this.topData();
 86            this.listData();
 87 
 88         },
 89         methods:{
 90             topData(){
 91                 axios({
 92                     url:\'https://autumnfish.cn/top/playlist/highquality\',
 93                     method:\'get\',
 94                     params:{
 95                         limit:1,
 96                         cat:this.tag,
 97                     }
 98                 }).then(response=>{
 99                     //console.log(response);
100                     this.topList=response.data.playlists[0];
101                 })
102             },
103             listData(){
104                 axios({
105                     url:\'https://autumnfish.cn/top/playlist\',
106                     method:\'get\',
107                     params:{
108                         limit: 15,
109                         offset:(this.page-1)*15,
110                         cat: this.tag,
111                     }
112                 }).then(response=>{
113                     //console.log(response);
114                     this.total=response.data.total;
115                     this.list=response.data.playlists;
116                 })
117             },
118             currentPage(tpage){
119                 //console.log("当前页"+tpage);
120                 this.page=tpage;
121                 this.listData();
122             },
123             toPlayList(id){
124                 this.$router.push(`/PlayList?id=${id}`);
125             },
126 
127         },
128 
129     }
130 </script>
131 
132 <style scoped>
133     img{
134         width: 100%;
135         height: 100%;
136         border-radius: 5px;
137     }
138     .top_card{
139         display: flex;
140         position:relative;
141         width: 90%;
142         height: 200px;
143         left: 5%;
144         top:5px;
145         overflow: hidden;
146         padding: 10px;
147         border-radius: 5px;
148     }
149     .top_card .img_wrap{
150         position: relative;
151         width: 180px;
152         height: 180px;
153         z-index: 1;
154         flex:0 0 auto;
155         margin-right: 20px;
156     }
157     .top_card .info_wrap{
158        z-index: 1;
159        width: 80%;
160        height: 200px;
161        flex:0 0 auto;
162    }
163     .top_card .info_wrap .tag{
164         position: relative;
165         width: 100px;
166         height: 30px;
167         border: 1px solid orange;
168         text-align: center;
169         color: orange;
170         line-height: 30px;
171     }
172     .top_card .info_wrap .title{
173         position: relative;
174         width: 100%;
175         top:5px;
176         color: white;
177     }
178     .top_card .info_wrap .content{
179         position: relative;
180         color: grey;
181         width: 100%;
182         top:10px;
183         text-overflow: ellipsis;
184         /*多行文字溢出效果*/
185         display: -webkit-box;
186         -webkit-box-orient: vertical;
187         -webkit-line-clamp:6;
188     }
189     .top_card .bgimg{
190         position: absolute;
191         top: 0;
192         left: 0;
193         right: 0;
194         bottom: 0;
195         z-index: 0;
196         width: 100%;
197         filter: blur(20px);
198     }
199     .top_card .bg_mask{
200         position: absolute;
201         width: 100%;
202         left: 0;
203         top: 0;
204         right: 0;
205         bottom: 0;
206         background-color: rgba(0,0,0,0.5);
207     }
208     .main_card{
209         position: relative;
210         width: 90%;
211         padding-top: 30px;
212         left: 5%;
213     }
214     .main_card .tab_bar{
215         display: flex;
216         justify-content: flex-end;
217     }
218     .tab_bar .types{
219         color: grey;
220         font-size: 16px;
221         margin-right: 20px;
222         cursor:pointer;
223     }
224     .tab_bar .types.active{
225         color: crimson;
226     }
227     .items .img_wrap{
228         position: relative;
229         width: 200px;
230         height: 200px;
231     }
232     .items{
233         display: flex;
234         flex-wrap:wrap;
235     }
236     .item{
237         position: relative;
238         width: 210px;
239         margin: 10px;
240         overflow: hidden;
241         cursor: pointer;
242     }
243     .copywriter{
244         position: absolute;
245         width: 200px;
246         top:-50px;
247     }
248     .img_wrap:hover .copywriter{
249         position: absolute;
250         width: 200px;
251         top:0;
252         color: white;
253         background-color: black;
254         opacity: 0.8;
255     }
256     .play-but{
257         display: block;
258         position: absolute;
259         width: 50px;
260         height: 50px;
261         bottom: -200px;
262         right: 0;
263         font-size:50px;
264         color: sandybrown;
265     }
266     .img_wrap:hover .play-but{
267         display: block;
268         position: absolute;
269         width: 50px;
270         height: 50px;
271         bottom: 0;
272         right: 0;
273         font-size:50px;
274         color: sandybrown;
275         cursor:pointer;
276     }
277     .page_card{
278         position: relative;
279         width: 90%;
280         left: 5%;
281         text-align: center;
282     }
283 
284 
285 </style>

newMusic.vue(最新音乐)

  1 <template>
  2     <div>
  3         <div class="tab_bar">
  4             <span class="types" :class="{active:tag==\'0\'}" @click="tag=\'0\'">全部</span>
  5             <span class="types" :class="{active:tag==\'7\'}" @click="tag=\'7\'">华语</span>
  6             <span class="types" :class="{active:tag==\'96\'}" @click="tag=\'96\'">欧美</span>
  7             <span class="types" :class="{active:tag==\'8\'}" @click="tag=\'8\'">日本</span>
  8             <span class="types" :class="{active:tag==\'16\'}" @click="tag=\'16\'">韩国</span>
  9         </div>
 10         <div class="table_card">
 11             <table class="el-table">
 12                 <thead>
 13                 <th width="5%"></th>
 14                 <th width="15%"></th>
 15                 <th width="20%">音乐标题</th>
 16                 <th width="20%">歌手</th>
 17                 <th width="30%">专辑</th>
 18                 <th width="10%">时长</th>
 19                 </thead>
 20                 <tbody>
 21                 <tr v-for="(item,index) in tableData" :key="index">
 22                     <td>{{index+1}}</td>
 23                     <td class="img_column">
 24                         <img :src="item.album.picUrl" alt="">
 25                         <span class="el-icon-video-play play-but" @click="playMusic(item.id)"></span>
 26                     </td>
 27                     <td>{{item.name}}</td>
 28                     <td>{{item.artists[0].name}}</td>
 29                     <td>{{item.album.name}}</td>
 30                     <td>{{item.duration}}</td>
 31                 </tr>
 32                 </tbody>
 33             </table>
 34         </div>
 35 
 36     </div>
 37 </template>
 38 
 39 <script>
 40     //导入axios
 41     import axios from \'axios\';
 42     export default {
 43         name: "newMusic",
 44         data(){
 45             return{
 46                 tag:\'0\',
 47                 tableData:[],
 48             }
 49         },
 50         watch:{
 51             tag(){
 52               this.getTable();
 53             }
 54 
 55         },
 56         created() {
 57             this.getTable();
 58 
 59     },
 60         methods:{
 61             getTable(){
 62                 axios({
 63                     url:\'https://autumnfish.cn/top/song\',
 64                     method:\'get\',
 65                     params:{
 66                         type:this.tag,
 67                     }
 68                 }).then(response=>{
 69                    // console.log(response);
 70                     this.tableData=response.data.data;
 71                     for(let i=0;i<this.tableData.length;i++)
 72                     {   //将获取到的毫秒转化为分+秒
 73                         let duration=this.tableData[i].duration;
 74                         let min=parseInt(duration/1000/60);
 75                         let second=parseInt(duration/1000%60);
 76                         if(min<10)
 77                             min=\'0\'+min;
 78                         if(second<10)
 79                             second=\'0\'+second;
 80                         this.tableData[i].duration=`${min}:${second}`;
 81                     }
 82                 })
 83             },
 84             playMusic(id){
 85                 axios({
 86                     url:\'https://autumnfish.cn/song/url\',
 87                     method:\'get\',
 88                     params:{
 89                         id:id,
 90                     }
 91                 }).then(response=>{
 92                     //console.log(response);
 93                     this.$parent.musicUrl=response.data.data[0].url;
 94                 })
 95 
 96             }
 97         },
 98     }
 99 </script>
100 
101 <style scoped>
102     img{
103         width: 100%;
104         height: 100%;
105     }
106     .tab_bar{
107         position: relative;
108         width: 90%;
109         height: 30px;
110         left: 5%;
111         top:10px;
112         display: flex;
113         justify-content: flex-end;
114     }
115     .tab_bar .types{
116         color: grey;
117         font-size: 16px;
118         margin-right: 20px;
119         cursor:pointer;
120     }
121     .tab_bar .types.active{
122         color: crimson;
123     }
124     .table_card{
125         position: relative;
126         width: 90%;
127         left: 5%;
128     }
129     .img_column>img{
130         width: 100px;
131         height: 100px;
132     }
133     .play-but{
134         display: block;
135         position: absolute;
136         width: 50px;
137         height: 50px;
138         left: 30px;
139         top:40px;
140         font-size:40px;
141         color: sandybrown;
142         cursor: pointer;
143     }
144     .el-table td, .el-table th{
145         padding: 12px 10px;
146     }
147 
148 </style>

newMv.vue(最新MV)

  1 <template>
  2   <div>
  3     <div class="type_card">
  4       <div class="atype">
  5         <span class="atitle">地区:</span>
  6         <span class="types" :class="{active:area==\'全部\'}" @click="area=\'全部\'">全部</span>
  7         <span class="types" :class="{active:area==\'内地\'}" @click="area=\'内地\'">内地</span>
  8         <span class="types" :class="{active:area==\'港台\'}" @click="area=\'港台\'">港台</span>
  9         <span class="types" :class="{active:area==\'欧美\'}" @click="area=\'欧美\'">欧美</span>
 10         <span class="types" :class="{active:area==\'日本\'}" @click="area=\'日本\'">日本</span>
 11         <span class="types" :class="{active:area==\'韩国\'}" @click="area=\'韩国\'">韩国</span>
 12       </div>
 13       <div class="atype">
 14         <span class="atitle">类型:</span>
 15         <span class="types" :class="{active:type==\'全部\'}" @click="type=\'全部\'">全部</span>
 16         <span class="types" :class="{active:type==\'官方版\'}" @click="type=\'官方版\'">官方版</span>
 17         <span class="types" :class="{active:type==\'原声\'}" @click="type=\'原声\'">原声</span>
 18         <span class="types" :class="{active:type==\'现场版\'}" @click="type=\'现场版\'">现场版</span>
 19         <span class="types" :class="{active:type==\'网易出品\'}" @click="type=\'网易出品\'">网易出品</span>
 20       </div>
 21       <div class="atype">
 22         <span class="atitle">排序:</span>
 23         <span class="types" :class="{active:order==\'排序上升\'}" @click="order=\'排序上升\'">排序上升</span>
 24         <span class="types" :class="{active:order==\'最热\'}" @click="order=\'最热\'">最热</span>
 25         <span class="types" :class="{active:order==\'最新\'}" @click="order=\'最新\'">最新</span>
 26       </div>
 27     </div>
 28     <div class="newMv">
 29       <div class="items">
 30         <div class="item" v-for="(item,index) in mvList" :key="index">
 31           <div class="img_wrap" @click="toMv(item.id)">
 32             <img :src="item.cover" alt="">
 33             <span class="play_count"><i class="el-icon-caret-right"></i>{{item.playCount}}</span>
 34           </div>
 35           <div class="info_wrap">
 36             <p>{{item.name}}</p>
 37             <p class="song_artist">{{item.artistName}}</p>
 38           </div>
 39         </div>
 40       </div>
 41     </div>
 42     <div class="page_card">
 43       <el-pagination
 44           @current-change="currentPage"
 45           layout="prev, pager, next"
 46           :current-page="page"
 47           :page-size="16"
 48           :total="total">
 49       </el-pagination>
 50     </div>
 51 
 52   </div>
 53 </template>
 54 
 55 <script>
 56   import axios from \'axios\'
 57     export default {
 58         name: "newMv",
 59         data(){
 60           return{
 61             mvList:[],
 62             area:\'\',
 63             type:\'\',
 64             order:\'\',
 65             page:1,
 66             total:0,
 67           }
 68         },
 69         methods:{
 70           getMv(){
 71             axios({
 72               url:\'https://autumnfish.cn/mv/all\',
 73               method:\'get\',
 74               params:{
 75                 area:this.area,
 76                 type:this.type,
 77                 order:this.order,
 78                 limit:16,
 79                 offset:(this.page-1)*16,
 80               },
 81             }).then(response=>{
 82               //console.log(response);
 83               //接口问题,只有第一页有数据总数
 84               if(this.page==1)
 85               this.total=response.data.count;
 86               this.mvList=response.data.data;
 87             })
 88           },
 89           currentPage(tPage){
 90             this.page=tPage;
 91             this.getMv();
 92           },
 93           toMv(id){
 94             //传参数到MV
 95             this.$router.push(`/MV?id=${id}`);
 96           },
 97 
 98         },
 99       created() {
100           this.getMv();
101       },
102       watch:{
103           area(){
104             this.page=1;
105             this.getMv();
106           },
107           type(){
108             this.page=1;
109             this.getMv();
110           },
111           order(){
112             this.page=1;
113             this.getMv();
114           }
115       }
116     }
117 </script>
118 
119 <style scoped>
120     img{
121         width: 100%;
122         height: 100%;
123         border-radius: 5px;
124     }
125     .type_card{
126       position: relative;
127       width: 90%;
128       left: 5%;
129       top:10px;
130     }
131     .atitle{
132       width: 8%;
133     }
134     .atype{
135       position: relative;
136       display: flex;
137       height: 30px;
138       margin: 15px;
139     }
140     .types{
141       color: grey;
142       font-size: 16px;
143       margin-right: 80px;
144       cursor:pointer;
145     }
146     .types.active{
147       color: crimson;
148     }
149     .newMv{
150       position: relative;
151       width:90%;
152       left: 5%;
153     }
154     .newMv .items{
155       display: flex;
156       flex-wrap: wrap;
157     }
158     .newMv .item{
159       width: 22%;
160       margin: 10px;
161     }
162     .newMv .img_wrap{
163       position: relative;
164       width: 250px;
165       height: 150px;
166       cursor: pointer;
167     }
168     .newMv .info_wrap{
169       text-align: center;
170     }
171     .newMv .play_count{
172       background-image: linear-gradient(to right,rgba(255,0,0,0),rgba(58,58,10,1));
173       position: absolute;
174       right: 0;
175       color: white;
176     }
177     .song_artist{
178       color: grey;
179       font-size:15px;
180       margin-top: 5px;
181     }
182     .page_card{
183       width: 90%;
184       position: relative;
185       left: 5%;
186       text-align: center;
187     }
188 
189 </style>

result.vue(搜索结果)

  1 <template>
  2     <div>
  3         <div class="title_wrap">
  4             <h2>{{this.$route.query.keyword}}</h2>
  5             <span>找到{{this.count}}个结果</span>
  6         </div>
  7         <div class="tab_wrap">
  8             <el-tabs v-model="activeName">
  9                 <el-tab-pane label="歌曲" name="songs">
 10                     <table class="el-table">
 11                         <thead>
 12                         <th width="5%"></th>
 13                         <th width="30%">音乐标题</th>
 14                         <th width="20%">歌手</th>
 15                         <th width="35%">专辑</th>
 16                         <th width="10%">时长</th>
 17                         </thead>
 18                         <tbody>
 19                         <tr v-for="(item,index) in songList" :key="index" class="el-table--enable-row-hover"
 20                             @dblclick="playMusic(item.id)">
 21                             <td>{{index+1}}</td>
 22                             <td>
 23                                 <div>
 24                                     <span>{{item.name}}</span>
 25                                     <span class="el-icon-video-play" v-if="item.mvid!=0"></span>
 26                                 </div>
 27                                 <div>
 28                                     <p v-if="item.alias.length!=0">{{item.alias[0]}}</p>
 29                                 </div>
 30                             </td>
 31                             <td><span>{{item.artists[0].name}}</span></td>
 32                             <td><span>{{item.album.name}}</span></td>
 33                             <td><span>{{item.duration}}</span></td>
 34                         </tr>
 35                         </tbody>
 36                     </table>
 37                 </el-tab-pane>
 38                 <el-tab-pane label="歌单" name="playLists" class="playLists">
 39                     <div class="items">
 40                         <div class="item" v-for="(item,index) in playList" :key="index" @click="toPlayList(item.id)">
 41                             <div class="img_wrap">
 42                                 <span class="copywriter">播放量:{{item.playCount}}</span>
 43                                 <img :src="item.coverImgUrl" alt="">
 44                                 <span class="el-icon-video-play play-but" ></span>
 45                             </div>
 46                             <div class="info_wrap">
 47                                 <p>{{item.name}}</p>
 48                             </div>
 49                         </div>
 50                     </div>
 51                 </el-tab-pane>
 52                 <el-tab-pane label="MV"  name="mvs" class="mvs">
 53                     <div class="items">
 54                         <div class="item" v-for="(item,index) in mvs" :key="index">
 55                             <div class="img_wrap" @click="toMv(item.id)">
 56                                 <img :src="item.cover" alt="">
 57                                 <span class="play_count"><i class="el-icon-caret-right"></i>{{item.playCount}}</span>
 58                             </div>
 59                             <div class="info_wrap">
 60                                 <p>{{item.name}}</p>
 61                                 <p class="song_artist">{{item.artistName}}</p>
 62                             </div>
 63                         </div>
 64                     </div>
 65                 </el-tab-pane>
 66             </el-tabs>
 67         </div>
 68         <div class="page_card">
 69             <el-pagination
 70                     @current-change="currentPage"
 71                     layout="prev, pager, next"
 72                     :current-page="page"
 73                     :page-size="20"
 74                     :total="total">
 75             </el-pagination>
 76         </div>
 77     </div>
 78 </template>
 79 
 80 <script>
 81     import axios from \'axios\'
 82     export default {
 83         name: "result",
 84         data(){
 85             return{
 86                 //标签名
 87                 activeName:\'songs\',
 88                 songList:[],
 89                 count:0,
 90                 playList:[],
 91                 mvs:[],
 92                 page:1,
 93                 total:0,
 94             }
 95         },
 96         watch:{
 97             activeName(){
 98                 if(this.activeName==\'songs\')
 99                 {
100                     this.getSongs();
101                     this.page=1;
102                 }
103                 if(this.activeName==\'playLists\')
104                 {
105                     this.getLists();
106                     this.page=1;
107                 }
108                 if(this.activeName==\'mvs\')
109                 {
110                     this.getMvs();
111                     this.page=1;
112                 }
113             },
114             /*因为vue的路由传参传到当前的页面是不会刷新的,所以需要监听路由的变化,
115             变化后再执行一次获取各数据的函数即可。
116              */
117             $route(){
118                 if(this.activeName==\'songs\')
119                 {
120                     this.getSongs();
121                     this.page=1;
122                 }
123                 if(this.activeName==\'playLists\')
124                 {
125                     this.getLists();
126                     this.page=1;
127                 }
128                 if(this.activeName==\'mvs\')
129                 {
130                     this.getMvs();
131                     this.page=1;
132                 }
133 
134             },
135         },
136         //生命周期钩子 created
137         //回调函数,添加之后自动执行
138         //内部可以通过this访问vue实例
139         created() {
140             console.log(this.$route);
141             if(this.activeName==\'songs\')
142             {
143                 this.getSongs();
144                 this.page=1;
145             }
146             if(this.activeName==\'playLists\')
147             {
148                 this.getLists();
149                 this.page=1;
150             }
151             if(this.activeName==\'mvs\')
152             {
153                 this.getMvs();
154                 this.page=1;
155             }
156 
157         },
158         methods:{
159             getSongs(){
160                 axios({
161                     url:\'https://autumnfish.cn/search\',
162                     method:\'get\',
163                     params:{
164                         keywords:this.$route.query.keyword,
165                         limit:20,
166                         offset:(this.page-1)*20,
167                         type:1,
168                     }
169                 }).then(response=>{
170                     //console.log(response);
171                     this.songList=response.data.result.songs;
172                     this.count=response.data.result.songCount;
173                     this.total=this.count;
174                     for(let i=0;i<this.songList.length;i++)
175                     {   //将获取到的毫秒转化为分+秒
176                         let duration=this.songList[i].duration;
177                         let min=parseInt(duration/1000/60);
178                         let second=parseInt(duration/1000%60);
179                         if(min<10)
180                             min=\'0\'+min;
181                         if(second<10)
182                             second=\'0\'+second;
183                         this.songList[i].duration=`${min}:${second}`;
184                     }
185                 })
186             },
187             getLists(){
188                 axios({
189                     url:\'https://autumnfish.cn/search\',
190                     method:\'get\',
191                     params:{
192                         keywords:this.$route.query.keyword,
193                         limit:20,
194                         offset:(this.page-1)*20,
195                         type:1000,
196                     }
197                 }).then(response=>{
198                     //console.log(response);
199                     this.playList=response.data.result.playlists;
200                     this.count=response.data.result.playlistCount;
201                     this.total=this.count;
202 
203                 })
204             },
205             getMvs(){
206                 axios({
207                     url:\'https://autumnfish.cn/search\',
208                     method:\'get\',
209                     params:{
210                         keywords:this.$route.query.keyword,
211                         limit:20,
212                         offset:(this.page-1)*20,
213                         type:1004,
214                     }
215                 }).then(response=>{
216                     //console.log(response);
217                     this.mvs=response.data.result.mvs;
218                     this.count=response.data.result.mvCount;
219                     this.total=this.count;
220                 })
221             },
222 
223             playMusic(id){
224                 axios({
225                     url:\'https://autumnfish.cn/song/url\',
226                     method:\'get\',
227                     params:{
228                         id:id,
229                     }
230                 }).then(response=>{
231                     //console.log(response);
232                     this.$parent.musicUrl=response.data.data[0].url;
233                 })
234             },
235             currentPage(tPage){
236                 this.page=tPage;
237                 if(this.activeName==\'songs\')
238                 {
239                     this.getSongs();
240                 }
241                 if(this.activeName==\'playLists\')
242                 {
243                     this.getLists();
244                 }
245                 if(this.activeName==\'mvs\')
246                 {
247                     this.getMvs();
248                 }
249             },
250             toPlayList(id){
251                 //传参数到PlayList
252                 this.$router.push(`/PlayList?id=${id}`);
253             },
254             toMv(id){
255                 //传参数到MV
256                 this.$router.push(`/MV?id=${id}`);
257             },
258         },
259     }
260 </script>
261 
262 <style scoped>
263     img{
264         width: 100%;
265         height: 100%;
266         border-radius: 5px;
267     }
268     .title_wrap{
269         position: relative;
270         width: 90%;
271         left: 5%;
272         top:5px;
273     }
274     .tab_wrap{
275         position: relative;
276         width: 90%;
277         left: 5%;
278     }
279     .items .img_wrap{
280         position: relative;
281         width: 200px;
282         height: 200px;
283     }
284     .playLists .items{
285         display: flex;
286         flex-wrap:wrap;
287     }
288     .playLists .item{
289         position: relative;
290         width: 210px;
291         margin: 10px;
292         overflow: hidden;
293         cursor: pointer;
294     }
295     .playLists .copywriter{
296         position: absolute;
297         width: 200px;
298         top:-50px;
299     }
300     .playLists .img_wrap:hover .copywriter{
301         position: absolute;
302         width: 200px;
303         top:0;
304         color: white;
305         background-color: black;
306         opacity: 0.8;
307     }
308     .playLists .play-but{
309         display: block;
310         position: absolute;
311         width: 50px;
312         height: 50px;
313         bottom: -200px;
314         right: 0;
315         font-size:50px;
316         color: sandybrown;
317     }
318     .playLists .img_wrap:hover .play-but{
319         display: block;
320         position: absolute;
321         width: 50px;
322         height: 50px;
323         bottom: 0;
324         right: 0;
325         font-size:50px;
326         color: sandybrown;
327         cursor:pointer;
328     }
329     .mvs .items{
330         display: flex;
331         flex-wrap: wrap;
332     }
333     .mvs .item{
334         width: 22%;
335         margin: 10px;
336 
337     }
338     .mvs .img_wrap{
339         position: relative;
340         width: 250px;
341         height: 150px;
342         cursor: pointer;
343     }
344     .mvs .info_wrap{
345         text-align: center;
346     }
347     .mvs .play_count{
348         background-image: linear-gradient(to right,rgba(255,0,0,0),rgba(58,58,10,1));
349         position: absolute;
350         right: 0;
351         color: white;
352     }
353     .song_artist{
354         color: grey;
355         font-size:15px;
356         margin-top: 5px;
357     }
358     .page_card{
359         width: 90%;
360         position: relative;
361         left: 5%;
362         text-align: center;
363     }
364 
365 
366 
367 </style>

MV.vue(MV详情页面)

  1 <template>
  2     <div>
  3         <div class="main_wrap">
  4             <div class="mv_info">
  5                 <h3>MV详情</h3>
  6                 <div class="video">
  7                     <video :src="mvUrl" controls="controls"></video>
  8                 </div>
  9                 <div class="artist">
 10                     <img :src="imgUrl" alt="">
 11                     <span>{{mvInfo.artistName}}</span>
 12                 </div>
 13                 <div class="mv_name">
 14                     <span>{{mvInfo.name}}</span>
 15                 </div>
 16                 <div class="mv_time">
 17                     <span>发布:{{mvInfo.publishTime}}</span>
 18                     <span>播放:{{mvInfo.playCount}}次</span>
 19                 </div>
 20                 <div class="description">
 21                     <span>{{mvInfo.desc}}</span>
 22                 </div>
 23 
 24             </div>
 25             <div class="mv_about">
 26                 <h3>相关推荐</h3>
 27                 <div class="item" v-for="(item,index) in mvs" :key="index">
 28                     <div class="img_wrap">
 29                         <img :src="item.cover" alt="" @click="toMv(item.id)">
 30                         <span class="play_count"><i class="el-icon-caret-right"></i>{{item.playCount}}</span>
 31                     </div>
 32                     <div class="info_wrap">
 33                         <p>{{item.name}}</p>
 34                         <p class="song_artist">{{item.artistName}}</p>
 35                     </div>
 36                 </div>
 37             </div>
 38 
 39         </div>
 40         <div class="comments">
 41             <div class="comment_wrap" v-if="hotCommentCount!=0">
 42                 <h3>热门评论({{hotCommentCount}})</h3>
 43                 <div class="item" v-for="(item,index) in hotcomment" :key="index">
 44                     <div class="icon_wrap">
 45                         <img :src="item.user.avatarUrl" alt="">
 46                     </div>
 47                     <div class="info_wrap">
 48                         <div class="user_id">
 49                             <span class="text_blue">{{item.user.nickname}}:</span>
 50                             {{item.content}}
 51                         </div>
 52                         <div class="re_content" v-if="item.beReplied.length!=0">
 53                             <span class="text_blue">{{item.beReplied[0].user.nickname}}:</span>
 54                             {{item.beReplied[0].content}}
 55                         </div>
 56                         <div class="user_time">
 57                             <span>{{item.time}}</span>
 58                         </div>
 59                     </div>
 60                 </div>
 61             </div>
 62             <div class="comment_wrap">
 63                 <h3>最新评论({{commentCount}})</h3>
 64                 <div class="item" v-for="(item,index) in comment" :key="index">
 65                     <div class="icon_wrap">
 66                         <img :src="item.user.avatarUrl" alt="">
 67                     </div>
 68                     <div class="info_wrap">
 69                         <div class="user_id">
 70                             <span class="text_blue">{{item.user.nickname}}:</span>
 71                             {{item.content}}
 72                         </div>
 73                         <div class="re_content" v-if="item.beReplied.length!=0">
 74                             <span class="text_blue">{{item.beReplied[0].user.nickname}}:</span>
 75                             {{item.beReplied[0].content}}
 76                         </div>
 77                         <div class="user_time">
 78                             <span>{{item.time}}</span>
 79                         </div>
 80                     </div>
 81                 </div>
 82             </div>
 83             <div class="page_card">
 84                 <el-pagination
 85                         @current-change="currentPage"
 86                         layout="prev, pager, next"
 87                         :current-page="page"
 88                         :page-size="20"
 89                         :total="commentCount">
 90                 </el-pagination>
 91             </div>
 92 
 93         </div>
 94     </div>
 95 </template>
 96 
 97 <script>
 98     import axios from \'axios\';
 99     export default {
100         name: "MV",
101         data(){
102             return{
103                 mvUrl:\'\',
104                 mvInfo:[],
105                 imgUrl:\'\',
106                 mvs:[],
107                 hotcomment:[],
108                 hotCommentCount:0,
109                 comment:[],
110                 commentCount:0,
111                 page:1,
112             }
113         },
114         methods:{
115             playMv(){
116                 axios({
117                     url:\'https://autumnfish.cn/mv/url\',
118                     method:\'get\',
119                     params:{
120                         id:this.$route.query.id,
121                     }
122                 }).then(response=>{
123                     //console.log(response);
124                     this.mvUrl=response.data.data.url;
125                 })
126             },
127             getMvAbout(){
128                 axios({
129                     url:\'https://autumnfish.cn/simi/mv\',
130                     method:\'get\',
131                     params:{
132                         mvid:this.$route.query.id,
133                     }
134                 }).then(response=>{
135                     //console.log(response);
136                     this.mvs=response.data.mvs;
137                 })
138             },
139             getMvInfo(){
140                 axios({
141                     url:\'https://autumnfish.cn/mv/detail\',
142                     method:\'get\',
143                     params:{
144                         mvid:this.$route.query.id,
145                     }
146                 }).then(response=>{
147                     //console.log(response);
148                     this.mvInfo=response.data.data;
149 
150                     axios({
151                         url:\'https://autumnfish.cn/artists\',
152                         method:\'get\',
153                         params:{
154                             id:this.mvInfo.artistId,
155                         }
156                     }).then(res=>{
157                        // console.log(res);
158                         this.imgUrl=res.data.artist.picUrl;
159 
160                     })
161                 })
162             },
163             getMvComment(){
164                 axios({
165                     url:\'https://autumnfish.cn/comment/mv\',
166                     method:\'get\',
167                     params:{
168                         id:this.$route.query.id,
169                         limit:20,
170                         offset:(this.page-1)*20,
171                     }
172                 }).then(response=>{
173                     //console.log(response);
174                     this.comment=response.data.comments;
175                     this.commentCount=response.data.total;
176                     this.hotcomment=response.data.hotComments;
177                     if(response.data.hotComments)
178                     this.hotCommentCount=response.data.hotComments.length;
179                     else
180                         this.hotCommentCount=0;
181                 })
182             },
183             currentPage(tPage){
184                 this.page=tPage;
185                 this.getMvComment();
186             },
187             toMv(id){
188                 //传参数到MV
189                 this.$router.push(`/MV?id=${id}`);
190             },
191         },
192         created() {
193             this.playMv();
194             this.getMvInfo();
195             this.getMvAbout();
196             this.getMvComment();
197         },
198         watch:{
199             $route(){
200                 this.page=1;
201                 this.playMv();
202                 this.getMvInfo();
203                 this.getMvAbout();
204                 this.getMvComment();
205             }
206         },
207     }
208 </script>
209 
210 <style scoped>
211     img{
212         width: 100%;
213         height: 100%;
214         border-radius: 5px;
215     }
216     .main_wrap{
217         position: relative;
218         display: flex;
219         width: 90%;
220         left: 5%;
221         top:5px;
222     }
223     .main_wrap .mv_info{
224        flex:6.5;
225     }
226     .main_wrap .mv_info .video{
227         width: 93%;
228         height: 400px;
229         margin:10px 0;
230     }
231     .main_wrap .mv_info .video>video{
232         width: 100%;
233         height: 100%;
234         outline: none;
235     }
236     .main_wrap .mv_info .artist{
237         width: 100%;
238         margin:10px 0;
239         display: flex;
240         align-items: center;
241         font-size: 18px;
242     }
243     .main_wrap .mv_info .artist>img{
244         width: 70px;
245         height: 70px;
246         border-radius: 50%;
247         margin-right: 10px;
248     }
249     .main_wrap .mv_info .mv_name{
250         width: 100%;
251         font-size: 25px;
252         font-weight: bold;
253         margin:10px 0;
254     }
255 
256     .main_wrap .mv_info .mv_time{
257         width: 100%;
258         font-size: 14px;
259         color: grey;
260         margin:10px 0;
261     }
262     .main_wrap .mv_info .description{
263         margin:10px 0;
264     }
265     .main_wrap .mv_info .mv_time>span{
266         margin-right: 30px;
267     }
268     .main_wrap .mv_about{
269         position: relative;
270         flex:3.5;
271     }
272     .main_wrap .mv_about .item{
273         width: 100%;
274         display: flex;
275         margin-top: 10px;
276         align-items: center;
277     }
278     .main_wrap .mv_about .img_wrap{
279         width: 200px;
280         height: 110px;
281         position: relative;
282         cursor: pointer;
283     }
284     .main_wrap .mv_about .info_wrap{
285         flex: 1;
286         margin-left: 6px;
287     }
288     .main_wrap .mv_about .song_artist{
289         margin-top: 10px;
290         color: grey;
291         font-size: 15px;
292     }
293     .main_wrap .mv_about .play_count{
294         background-image: linear-gradient(to right,rgba(255,0,0,0),rgba(58,58,10,1));
295         position: absolute;
296         right: 0;
297         color: white;
298     }
299 
300     .comments{
301         position: relative;
302         width: 90%;
303         left: 5%;
304         margin-top: 20px;
305     }
306     .comments .comment_wrap{
307         width: 100%;
308     }
309     .comments .comment_wrap .item{
310         width: 100%;
311         padding: 5px;
312         margin: 15px;
313         display: flex;
314         border-bottom: 1px solid grey;
315     }
316     .comments .comment_wrap .icon_wrap{
317         width: 50px;
318         height: 50px;
319         border-radius: 50%;
320         background: white;
321     }
322     .comments .comment_wrap .icon_wrap>img{
323         border-radius: 50%;
324     }
325     .comments .comment_wrap .info_wrap{
326         flex:1;
327         margin-left: 10px;
328     }
329     .comments .comment_wrap .info_wrap .user_id{
330         position: relative;
331     }
332     .text_blue{
333         color: #517EAF;
334     }
335     .comments .comment_wrap .info_wrap .re_content{
336         position: relative;
337         background:#E6E5E6;
338         border-radius: 5px;
339         line-height: 30px;
340     }
341     .comments .comment_wrap .info_wrap .user_time{
342         position: relative;
343         top:5px;
344         color: grey;
345         font-size: 14px;
346         height: 30px;
347     }
348     .page_card{
349         width: 90%;
350         position: relative;
351         left: 5%;
352         text-align: center;
353     }
354 
355 </style>

PlayList.vue(歌单详情页)

  1 <template>
  2     <div>
  3         <div class="top_wrap">
  4             <div class="img_wrap">
  5                 <img :src="playList.coverImgUrl">
  6             </div>
  7             <div class="info_wrap">
  8                 <div class="description">
  9                     <span>{{playList.name}}</span>
 10                 </div>
 11                 <div class="description user">
 12                     <img :src="playList.creator.avatarUrl" class="user_icon">
 13                     <span>{{playList.creator.nickname}}</span>
 14                     <span class="Date">{{playList.createTime}}创建</span>
 15                 </div>
 16                 <div class="description">
 17                     <span class="title">标签:</span>
 18                     <span>{{playList.tags[0]}}/{{playList.tags[1]}}/{{playList.tags[2]}}</span>
 19                 </div>
 20                 <div class="description text_overflow">
 21                     <span class="title">简介:</span>
 22                     <span>{{playList.description}}</span>
 23                 </div>
 24             </div>
 25         </div>
 26         <div class="main_wrap">
 27             <el-tabs v-model="activeName">
 28                 <el-tab-pane label="歌曲列表" name="songs">
 29                     <table class="el-table">
 30                         <thead>
 31                         <th width="5%"></th>
 32                         <th width="15%"></th>
 33                         <th width="25%">音乐标题</th>
 34                         <th width="15%">歌手</th>
 35                         <th width="30%">专辑</th>
 36                         <th width="10%">时长</th>
 37                         </thead>
 38                         <tbody>
 39                         <tr v-for="(item,index) in songList" :key="index">
 40                             <td>{{index+1}}</td>
 41                             <td class="img_column">
 42                                 <img :src="item.al.picUrl" alt="">
 43                                 <span class="el-icon-video-play play-but" @click="playMusic(item.id)"></span>
 44                             </td>
 45                             <td>{{item.name}}</td>
 46                             <td>{{item.ar[0].name}}</td>
 47                             <td>{{item.al.name}}</td>
 48                             <td>{{item.dt}}</td>
 49                         </tr>
 50                         </tbody>
 51                     </table>
 52                 </el-tab-pane>
 53                 <el-tab-pane label="评论" name="comments">
 54                     <div class="comment_wrap" v-if="hotCommentCount!=0">
 55                         <h3>热门评论({{hotCommentCount}})</h3>
 56                         <div class="item" v-for="(item,index) in hotcomment" :key="index">
 57                             <div class="icon_wrap">
 58                                 <img :src="item.user.avatarUrl" alt="">
 59                             </div>
 60                             <div class="info_wrap">
 61                                 <div class="user_id">
 62                                     <span class="text_blue">{{item.user.nickname}}:</span>
 63                                     {{item.content}}
 64                                 </div>
 65                                 <div class="re_content" v-if="item.beReplied.length!=0">
 66                                     <span class="text_blue">{{item.beReplied[0].user.nickname}}:</span>
 67                                     {{item.beReplied[0].content}}
 68                                 </div>
 69                                 <div class="user_time">
 70                                     <span>{{item.time}}</span>
 71                                 </div>
 72                             </div>
 73                         </div>
 74                     </div>
 75                     <div class="comment_wrap">
 76                         <h3>最新评论({{commentCount}})</h3>
 77                         <div class="item" v-for="(item,index) in comment" :key="index">
 78                             <div class="icon_wrap">
 79                                 <img :src="item.user.avatarUrl" alt="">
 80                             </div>
 81                             <div class="info_wrap">
 82                                 <div class="user_id">
 83                                     <span class="text_blue">{{item.user.nickname}}:</span>
 84                                     {{item.content}}
 85                                 </div>
 86                                 <div class="re_content" v-if="item.beReplied.length!=0">
 87                                     <span class="text_blue">{{item.beReplied[0].user.nickname}}:</span>
 88                                     {{item.beReplied[0].content}}
 89                                 </div>
 90                                 <div class="user_time">
 91                                     <span>{{item.time}}</span>
 92                                 </div>
 93                             </div>
 94                         </div>
 95                     </div>
 96                     <div class="page_card">
 97                         <el-pagination
 98                                 @current-change="currentPage"
 99                                 layout="prev, pager, next"
100                                 :current-page="page"
101                                 :page-size="20"
102                                 :total="commentCount">
103                         </el-pagination>
104                     </div>
105 
106                 </el-tab-pane>
107             </el-tabs>
108 
109         </div>
110     </div>
111 </template>
112 
113 <script>
114     import axios from \'axios\'
115     export default {
116         name: "PlayList",
117         data(){
118             return{
119                 playList:{
120                     creator:{},
121                     tags:[],
122                     trackIds:[],
123                 },
124                 songList:[],
125                 activeName:\'songs\',
126                 hotcomment:[],
127                 hotCommentCount:0,
128                 comment:[],
129                 commentCount:0,
130                 page:1,
131             }
132         },
133         methods:{
134            getSongs(){
135                //获取vue容器
136                var that=this;
137                axios({
138                     url:\'https://autumnfish.cn/playlist/detail\',
139                     method:\'get\',
140                     params:{
141                         id:this.$route.query.id,
142                     },
143                 }).then(response=>{
144                     //console.log(response);
145                     this.playList=response.data.playlist;
146                     let app=this.playList;
147                     var date=new Date(this.playList.createTime);
148                     //将获取到的创建时间由毫秒转化为想要的格式
149                    Date.prototype.toLocaleString=function(){
150                        //自定义时间格式
151                       function addZero(num) {
152                           if(num<10)
153                           {
154                               return \'0\'+num;
155                           }
156                           else
157                               return num;
158                       }
159                        return this.getFullYear()+\'-\'+addZero((this.getMonth()+1))+\'-\'+addZero(this.getDate());
160                    };
161                     this.playList.createTime=date.toLocaleString();
162                     getSongList(0,app.trackIds.length);
163                    //尝试一下递归
164                    /*递归可以解决顺序问题,暂且先用递归*/
165                    function getSongList(j,length) {
166                        axios({
167                            url:\'https://autumnfish.cn/song/detail\',
168                            method:\'get\',
169                            params:{
170                                ids:app.trackIds[j].id,
171                            },
172                        }).then(response=>{
173                            that.songList.push(response.data.songs[0]);
174                            //将获取到的毫秒转化为分+秒
175                            let duration=that.songList[j].dt;
176                            let min=parseInt(duration/1000/60);
177                            let second=parseInt(duration/1000%60);
178                            if(min<10)
179                                min=\'0\'+min;
180                            if(second<10)
181                                second=\'0\'+second;
182                            that.songList[j].dt=`${min}:${second}`;
183 
184                            if(++j<length){
185                                getSongList(j,length);
186                            }
187                        })
188                    }
189                    //另一个思路:像播放音乐那样,给tr绑定一个函数,可以传id,用什么事件绑定是问题,然后可以用songList.值来代替
190                    //item
191                     //通过track的id获取歌曲的详细信息,在for循环中异步会出问题
192                    /******************
193                    for(let i=0;i<this.playList.trackIds.length;i++)
194                     {
195                           axios({
196                             url:\'https://autumnfish.cn/song/detail\',
197                             method:\'get\',
198                             params:{
199                                 ids:this.playList.trackIds[i].id,
200                             },
201                         }).then(response=>{
202                               //this.songList[i]=response.data.songs[0];
203                             //这个会导致每次产生的结果不同,原因即为在当前循环中axios还没获得接口传过来的数据,
204                             //then后面已经执行了.因此根据i赋值会错位。而用push会每次结果不同。
205                              this.songList.push(response.data.songs[0]);
206 
207                             if(i==this.playList.trackIds.length-1)
208                             {
209                                 for(let j=0;j<this.songList.length;j++)
210                                 {   //将获取到的毫秒转化为分+秒
211                                     let duration=this.songList[j].dt;
212                                     let min=parseInt(duration/1000/60);
213                                     let second=parseInt(duration/1000%60);
214                                     if(min<10)
215                                         min=\'0\'+min;
216                                     if(second<10)
217                                         second=\'0\'+second;
218                                     this.songList[j].dt=`${min}:${second}`;
219                                 }
220                             }
221                        })
222                     }
223                     *************************/
224                    // console.log(this.songList);
225                 })
226             },
227             playMusic(id){
228                 axios({
229                     url:\'https://autumnfish.cn/song/url\',
230                     method:\'get\',
231                     params:{
232                         id:id,
233                     },
234                 }).then(response=>{
235                     this.$parent.musicUrl=response.data.data[0].url;
236                 })
237             },
238             gethotComments(){
239                axios({
240                    url:\'https://autumnfish.cn/comment/hot\',
241                    method:\'get\',
242                    params:{
243                        id:this.$route.query.id,
244                        type:2,
245                        limit:20,
246                    },
247                }).then(response=>{
248                    //console.log(response);
249                    this.hotcomment=response.data.hotComments;
250                    this.hotCommentCount=response.data.total;
251 
252                    Date.prototype.toLocaleString=function(){
253                        //自定义时间格式
254                        function addZero(num) {
255                            //加0
256                            if(num<10)
257                            {
258                                return \'0\'+num;
259                            }
260                            else
261                                return num;
262                        }
263                        return this.getFullYear()+\'-\'+addZero((this.getMonth()+1))+\'-\'+ addZero(this.getDate())+\' \'+
264                            addZero(this.getHours())+\':\'+addZero(this.getMinutes());
265                    };
266                    for(let i=0;i<this.hotcomment.length;i++)
267                    {
268                        var date=new Date(this.hotcomment[i].time);
269                        this.hotcomment[i].time=date.toLocaleString();
270                    }
271                })
272             },
273             getComments(){
274                 axios({
275                     url:\'https://autumnfish.cn/comment/playlist\',
276                     method:\'get\',
277                     params:{
278                         id:this.$route.query.id,
279                         limit:20,
280                         offset:(this.page-1)*20,
281                     },
282                 }).then(response=>{
283                     //console.log(response);
284                     this.comment=response.data.comments;
285                     this.commentCount=response.data.total;
286 
287                     Date.prototype.toLocaleString=function(){
288                         //自定义时间格式
289                         function addZero(num) {
290                             //加0
291                             if(num<10)
292                             {
293                                 return \'0\'+num;
294                             }
295                             else
296                                 return num;
297                         }
298                         return this.getFullYear()+\'-\'+addZero((this.getMonth()+1))+\'-\'+ addZero(this.getDate())+\' \'+
299                             addZero(this.getHours())+\':\'+addZero(this.getMinutes());
300                     };
301                     for(let i=0;i<this.comment.length;i++)
302                     {
303                         var date=new Date(this.comment[i].time);
304                         this.comment[i].time=date.toLocaleString();
305                     }
306                 })
307             },
308             currentPage(tPage){
309                 this.page=tPage;
310                 this.getComments();
311             },
312         },
313         created() {
314             this.getSongs();
315             this.gethotComments();
316             this.getComments();
317         }
318     }
319 </script>
320 
321 <style scoped>
322     img{
323         width:100%;
324         height: 100%;
325         border-radius: 5px;
326     }
327     .top_wrap{
328         position: relative;
329         display: flex;
330         width: 90%;
331         left: 5%;
332         top:5px;
333         padding: 10px;
334     }
335     .main_wrap{
336         position: relative;
337         width: 90%;
338         left: 5%;
339         top:5px;
340         padding: 10px;
341     }
342     .top_wrap .img_wrap{
343         width: 200px;
344         height: 200px;
345     }
346     .top_wrap .info_wrap{
347         flex: 1;
348         padding-left: 20px;
349     }
350     .top_wrap .info_wrap .description{
351         height: 30px;
352         margin: 10px;
353         line-height: 30px;
354     }
355     .top_wrap .info_wrap .text_overflow{
356         display: -webkit-box;
357         -webkit-box-orient: vertical;
358         -webkit-line-clamp: 3;
359         height: 90px;
360         overflow: hidden;
361     }
362     .top_wrap .info_wrap .user>span{
363         position: relative;
364         display: inline-block;
365         margin-left: 10px;
366         bottom: 5px;
367     }
368     .top_wrap .info_wrap .user .Date{
369         font-size: 15px;
370         color: grey;
371     }
372     .top_wrap .info_wrap .description .user_icon{
373         display: inline-block;
374         width: 30px;
375         height: 30px;
376         border-radius: 50%;
377     }
378     .top_wrap .info_wrap .title{
379         font-size: 18px;
380     }
381     .main_wrap .img_column>img{
382         width: 100px;
383         height: 100px;
384     }
385     .main_wrap .play-but{
386         display: block;
387         position: absolute;
388         width: 50px;
389         height: 50px;
390         left: 40px;
391         top:40px;
392         font-size:40px;
393         color: sandybrown;
394         cursor: pointer;
395     }
396     .el-table td, .el-table th{
397        padding: 12px 10px;
398     }
399     .main_wrap .comment_wrap{
400         width: 100%;
401     }
402     .main_wrap .comment_wrap .item{
403         width: 100%;
404         padding: 5px;
405         margin: 15px;
406         display: flex;
407         border-bottom: 1px solid grey;
408     }
409     .main_wrap .comment_wrap .icon_wrap{
410         width: 50px;
411         height: 50px;
412         border-radius: 50%;
413         background: white;
414     }
415     .main_wrap .comment_wrap .icon_wrap>img{
416         border-radius: 50%;
417     }
418     .main_wrap .comment_wrap .info_wrap{
419         flex:1;
420         margin-left: 10px;
421     }
422     .main_wrap .comment_wrap .info_wrap .user_id{
423         position: relative;
424     }
425     .text_blue{
426         color: #517EAF;
427     }
428     .main_wrap .comment_wrap .info_wrap .re_content{
429         position: relative;
430         background:#E6E5E6;
431         border-radius: 5px;
432         line-height: 30px;
433     }
434     .main_wrap .comment_wrap .info_wrap .user_time{
435         position: relative;
436         top:5px;
437         color: grey;
438         font-size: 14px;
439         height: 30px;
440     }
441     .page_card{
442         width: 90%;
443         position: relative;
444         left: 5%;
445         text-align: center;
446     }
447 
448 
449 
450 </style>

main.js

import Vue from \'vue\'
import App from \'./App.vue\'

Vue.config.productionTip = false

//导入
import VueRouter from \'vue-router\'
//use一下
Vue.use(VueRouter)
//导入 需要通过路由管理的组件
import discovery from "./components/discovery";
import recommendList from "./components/recommendList";
import newMusic from "./components/newMusic";
import newMv from "./components/newMv";
import result from "./components/result";
import PlayList from "./components/PlayList";
import MV from "./components/MV";
//创建路由
let router=new VueRouter({
   routes:[
    //配置地址 和 组件的对应关系
     {
       //地址
       path:\'/discovery\',
       //组件
       component:discovery,
     },
     {
         path:\'\',
         component: discovery,
      },
     {
        //地址
        path:\'/recommend\',
        component:recommendList,
     },
     {
         //地址
         path: \'/newMusic\',
         component: newMusic,

     },
     {
         //地址
         path: \'/newMv\',
         component: newMv,

     },
     {
         //地址
         path: \'/result\',
         component: result,
     },
     {
         path: \'/playlist\',
         component:PlayList,
     }  ,
       {
           path: \'/mv\',
           component: MV,
       }

   ]
})
//导入element-ui
import ElementUI from \'element-ui\'
//导入element-ui的样式
import \'element-ui/lib/theme-chalk/index.css\';
//使用一下
Vue.use(ElementUI);

new Vue({
  render: h => h(App),
  //挂载到vue实例上
  router,//router:router
}).$mount(\'#app\')

 

-webkit-line-clamp 多行文字溢出...