【Vue2.0】历时两周,我的音乐播放器终于“成型”了

主要技术栈

主要技术栈

需求功能实现

固定样式——

  1. 头部栏:路由导航、搜索框(历史记录、热搜榜)
  2. 底部栏:音乐播放样式、播放列表(列表循环)

首页(发现音乐)——

  1. 顶部引入Element轮播图组件
  2. 通过接口获取推荐歌单、最新音乐和推荐MV数据

推荐歌单——

  1. 通过接口获取歌单数据(歌单分类)
  2. 点击歌单进入歌单详情页

歌单详情页——

  1. 歌单信息(全部播放)
  2. 歌曲列表
  3. 最热评论、最新评论

最新音乐——

  1. 音乐分类
  2. 点击播放

最新MV——

  1. MV分类检索
  2. 点击跳转MV详情页

MV详情页——

  1. 自动播放MV
  2. MV相关信息、相关推荐
  3. 最热评论、最新评论

样式图展示

首页(发现音乐)

扫描二维码关注公众号,回复: 15031117 查看本文章

推荐歌单

歌单详情
列表播放

最新音乐

最新MV

MV详情
在这里插入图片描述

部分代码展示

首页(发现音乐):

<template>
 <!--首页(发现音乐)-->
  <div class="discover">
    <!-- 轮播图 -->
    <div class="Carousel">
      <el-carousel :interval="4000" type="card" height="250px">
        <el-carousel-item v-for="(item, index) in banners" :key="index">
          <img
            :src="item.imageUrl"
            alt="banner"
            width="100%"
            height="100%"
            class="item-img"
          />
        </el-carousel-item>
      </el-carousel>
    </div>
    <!-- 推荐歌单 -->
    <div class="songs-warp">
      <h3>推荐歌单</h3>
      <div class="list">
        <ul>
          <li
            class="iconfont icon-play"
            v-for="(item, index) in musiclists"
            :key="index"
            @click="playListDetail(item.id)"
          >
            <p class="first-p">{
    
    {
    
     item.copywriter }}</p>
            <img :src="item.picUrl" alt="recommd" />
            <p class="last-p" :title="item.name">{
    
    {
    
     item.name }}</p>
          </li>
        </ul>
      </div>
    </div>
    <!-- 最新音乐 -->
    <div class="songs-warp">
      <h3>最新音乐</h3>
      <ul class="new-songs">
        <li
          v-for="(item, index) in newsmusic"
          :key="index"
          @click="playMusic(item)"
        >
          <div class="music-img-warp">
            <img :src="item.picUrl" alt="newSongs" />
            <p class="iconfont icon-play"></p>
          </div>
          <div class="music-info">
            <p class="music-name">{
    
    {
    
     item.name }}</p>
            <p class="music-singer">{
    
    {
    
     item.song.artists[0].name }}</p>
          </div>
        </li>
      </ul>
    </div>
    <!-- 最新M V -->
    <div class="songs-warp mv-warp">
      <h3>推荐MV</h3>
      <ul class="mv-list">
        <li
          v-for="(item, index) in newsmv"
          :key="index"
          @click="toMvdetail(item.id)"
        >
          <div class="mv-img-warp">
            <img alt="newMvs" :src="item.picUrl" />
            <p class="iconfont icon-play play"></p>
            <p class="play-count iconfont icon-play">{
    
    {
    
     item.playCount }}</p>
          </div>
          <div class="mv-info">
            <p class="title">{
    
    {
    
     item.name }}</p>
            <p class="author">{
    
    {
    
     item.artists[0].name }}</p>
          </div>
        </li>
      </ul>
    </div>
  </div>
</template>
<script>
// 导入axios
import axios from "axios";
export default {
    
    
  name: "FindMusic",
  data() {
    
    
    return {
    
    
      // 轮播图
      banners: [],
      // 推荐歌单
      musiclists: [],
      // 最新音乐
      newsmusic: [],
      // 最新mv
      newsmv: [],
    };
  },
  computed: {
    
    
    musicQueue() {
    
    
      return this.$store.state.musicQueue;
    },
  },
  created() {
    
    
    // 轮播图:https://autumnfish.cn/banner
    axios({
    
    
      url: "https://autumnfish.cn/banner",
      method: "get",
      params: {
    
    },
    }).then((res) => {
    
    
      this.banners = res.data.banners;
    });
    // 推荐歌单:https://autumnfish.cn/personalized
    axios({
    
    
      url: "https://autumnfish.cn/personalized",
      method: "get",
      params: {
    
    
        // 获取的数据量
        limit: 10,
      },
    }).then((res) => {
    
    
      this.musiclists = res.data.result;
    });
    // 最新音乐:https://autumnfish.cn/personalized/newsong
    axios({
    
    
      url: "https://autumnfish.cn/personalized/newsong",
      method: "get",
      params: {
    
    
        limit: 10,
      },
    }).then((res) => {
    
    
      this.newsmusic = res.data.result;
    });
    // 最新MV:https://autumnfish.cn/personalized/mv
    axios({
    
    
      url: "https://autumnfish.cn/personalized/mv",
      method: "get",
      params: {
    
    
        limit: 8,
      },
    }).then((res) => {
    
    
      this.newsmv = res.data.result;
    });
  },
  methods: {
    
    
    // 播放音乐:https://autumnfish.cn/song/url
    playMusic(item) {
    
    
      axios({
    
    
        url: "https://autumnfish.cn/song/url",
        method: "get",
        params: {
    
    
          id: item.id,
        },
      }).then((res) => {
    
    
        this.$parent.$data.musicinfo = item;
        this.$parent.$data.musicurl = res.data.data[0].url;
      });
      let time = item.song.duration;
      let min = parseInt(time / 60000)
        .toString()
        .padStart(2, "0");
      let second = parseInt((time - min * 60000) / 1000)
        .toString()
        .padStart(2, "0");
      time = min + ":" + second;
      let musicitem = {
    
    
        id: item.id,
        name: item.name,
        musicArtist: item.song.artists[0].name,
        duration: time,
        picUrl: item.picUrl,
      };
      this.$store.commit("changeMusicInfo", musicitem);
      this.$store.commit("changeMusicQueue", musicitem);
      let ids = [];
      for (const row of this.musicQueue) {
    
    
        ids.push(row.id);
      }
      this.$store.commit("changeNowIndex", ids.indexOf(item.id));
    },
    playListDetail(id) {
    
    
      this.$router.push(`/playlistdetail?q=${
      
      id}`);
    },
    toMvdetail(id) {
    
    
      this.$router.push(`/mvdetail?q=${
      
      id}`);
    },
  },
};
</script>
<style scoped>
@import "../assets/icomoon/style.css";
.discover {
    
    
  z-index: 12;
  max-width: 1300px;
  margin: 0 auto;
  padding: 20px;
}
.el-carousel--horizontal {
    
    
  overflow-x: hidden;
}
.el-carousel {
    
    
  position: relative;
}
.el-carousel__item--card {
    
    
  border-radius: 20px;
}

.Carousel >>> .el-carousel__indicator.is-active button {
    
    
  background-color: pink;
  height: 3px;
  border-radius: 20px;
}

.songs-warp {
    
    
  margin-bottom: 20px;
}
.songs-warp h3 {
    
    
  color: rgb(145, 137, 139);
  margin-bottom: 20px;
}
/* 推荐歌单 */
.songs-warp .list ul {
    
    
  list-style: none;
  width: 100%;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}
.list ul li {
    
    
  width: 18%;
  margin: 10px 0;
  position: relative;
  overflow-y: hidden;
}

.list li .first-p {
    
    
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 40px;
  background-image: linear-gradient(
    rgba(255, 192, 203, 0.5),
    rgba(255, 192, 203, 0)
  );
  color: #fff;
  font-size: 12px;
  padding: 5px;
  box-sizing: border-box;
  /* border-top-left-radius: 10px;
      border-top-right-radius: 10px; */
  transform: translateY(-100%);
  transition: 0.5s;
}

.list li::before {
    
    
  content: "";
  position: absolute;
  bottom: 25px;
  right: 5px;
  width: 35px;
  height: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 35px;
  color: #d87093;
  opacity: 0;
  transition: 0.3s;
  cursor: pointer;
}

.list li:hover .first-p {
    
    
  transform: translateY(0);
}
.list li:hover .last-p {
    
    
  color: palevioletred;
}
.list li:hover::before {
    
    
  opacity: 1;
}

ul img {
    
    
  width: 100%;
  border-radius: 5px;
  /* opacity: 1; */
}

ul .last-p {
    
    
  cursor: pointer;
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 5px;
}
ul .last-p:hover {
    
    
  color: palevioletred;
}
/* 最新音乐  */
.new-songs {
    
    
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.new-songs li {
    
    
  width: 50%;
  display: flex;
  padding: 10px;
  box-sizing: border-box;
  position: relative;
}

.new-songs li:hover {
    
    
  background-image: linear-gradient(
    to right,
    rgba(255, 192, 203, 0.5),
    rgba(255, 192, 203, 0)
  );
  border-radius: 5px;
}

.new-songs li:hover::before {
    
    
  opacity: 1;
}

.new-songs .music-img-warp {
    
    
  position: relative;
  width: 100px;
  cursor: pointer;
}

.new-songs .music-img-warp:hover p::before {
    
    
  opacity: 1;
}

.new-songs .music-img-warp p::before {
    
    
  content: "\ea42";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 35px;
  height: 35px;
  font-size: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: palevioletred;
  opacity: 0;
  transition: 0.3s;
  cursor: pointer;
}

.music-info {
    
    
  flex: 1;
  padding: 0 10px;
}

.new-songs li p:first-child {
    
    
  margin-bottom: 20px;
}

.music-singer {
    
    
  color: rgb(145, 137, 139);
  font-size: 12px;
}
/* 最新MV */
.mv-list {
    
    
  display: flex;
  justify-content: flex-start;
  list-style: none;
  flex-wrap: wrap;
}

.mv-list li {
    
    
  width: 23%;
  padding: 0 10px;
}

.mv-img-warp {
    
    
  position: relative;
  cursor: pointer;
}

.mv-img-warp:hover .play::before {
    
    
  opacity: 1;
}

.mv-img-warp .play::before {
    
    
  content: "\ea42";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 35px;
  height: 35px;
  font-size: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: palevioletred;
  opacity: 0;
  transition: 0.3s;
  cursor: pointer;
}

.play-count {
    
    
  position: absolute;
  top: 5px;
  right: 5px;
  color: #fff;
  text-shadow: 0 0 2px rgb(255, 192, 203);
}

.play-count::before {
    
    
  margin-right: 5px;
}

.mv-info p {
    
    
  margin: 5px 0;
}

.mv-info .author {
    
    
  color: #a5a1a1;
  font-size: 12px;
}
.mv-warp {
    
    
  margin-bottom: 200px;
}
</style>

推荐歌单:

<template>
  <!-- 推荐歌单 -->
  <div class="playlists">
    <div class="top-card-wrap">
      <!-- 封面 -->
      <img :src="topList.coverImgUrl" alt="" class="bg-blur" />
      <div class="top-card">
        <div class="img-wrap">
          <img :src="topList.coverImgUrl" alt="" />
        </div>
        <div class="card-content">
          <div class="card-tag">精品歌单</div>
          <div class="card-title">{
    
    {
    
     topList.name }}</div>
          <div class="card-info">{
    
    {
    
     topList.description }}</div>
        </div>
      </div>
    </div>
    <div class="tab-container">
      <div class="tab-bar">
        <ul>
          <li
            :class="item == tabActive ? 'tab-item active' : 'tab-item'"
            v-for="(item, index) in tabItems"
            :key="index"
            @click="changeActive(item)"
          >
            {
    
    {
    
     item }}
          </li>
        </ul>
      </div>
      <div class="tab-content">
        <div class="songs-wrap">
          <div class="list">
            <ul>
              <li
                class="iconfont icon-play"
                v-for="(item, index) in list"
                :key="index"
                @click="playListDetail(item.id)"
              >
                <p class="first-p">播放量:{
    
    {
    
     item.playCount }}</p>
                <img :src="item.coverImgUrl" alt="" />
                <p class="last-p">{
    
    {
    
     item.name }}</p>
              </li>
            </ul>
          </div>
        </div>
      </div>
      <div class="page-list">
        <el-pagination
          @current-change="handleCurrentChange"
          :page-size="10"
          :current-page="page"
          layout="prev, pager, next"
          :total="total"
        >
        </el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
// 导入axios
import axios from "axios";
import "../assets/common/tab.css";
export default {
    
    
  name: "PlayLists",
  data() {
    
    
    return {
    
    
      // 总条数
      total: 0,
      // 页码
      page: 1,
      // 顶部的推荐歌单
      topList: {
    
    },
      // 歌单列表
      list: [],
      tabActive: "全部",
      tabItems: [
        "全部",
        "欧美",
        "华语",
        "流行",
        "说唱",
        "摇滚",
        "民谣",
        "电子",
        "轻音乐",
        "影视原声",
        "ACG",
        "怀旧",
      ],
    };
  },
  created() {
    
    
    // 顶部精品歌单
    this.topData();
    // 歌单列表
    this.listData();
  },
  methods: {
    
    
    // 顶部的精品歌单接口:https://autumnfish.cn/top/playlist/highquality
    topData() {
    
    
      axios({
    
    
        url: "https://autumnfish.cn/top/playlist/highquality",
        method: "get",
        params: {
    
    
          limit: 1,
          // 分类数据
          cat: this.tabActive,
        },
      }).then((res) => {
    
    
        // console.log(res.data.playlists[0]);
        this.topList = res.data.playlists[0];
      });
    },
    // 歌单列表接口:https://autumnfish.cn/top/playlist
    listData() {
    
    
      axios({
    
    
        url: "https://autumnfish.cn/top/playlist",
        method: "get",
        params: {
    
    
          limit: 10,
          // 起始的值:(页码-1)*每页多少条数据
          offset: (this.page - 1) * 10,
          // 分类数据
          cat: this.tabActive,
        },
      }).then((res) => {
    
    
        console.log(res.data.playlists);
        this.list = res.data.playlists;
        this.total = res.data.total;
      });
    },
    changeActive(item) {
    
    
      this.tabActive = item;
    },
    // 页码发生了改变
    handleCurrentChange(val) {
    
    
      console.log(`当前页:${
      
      val}`);
      this.page = val;
      // 重新获取数据
      this.listData();
    },
    playListDetail(id) {
    
    
      this.$router.push(`/playlistdetail?q=${
      
      id}`);
    },
  },
  // 侦听器
  watch: {
    
    
    tabActive() {
    
    
      // 顶部的精品歌单接口:https://autumnfish.cn/top/playlist/highquality
      this.topData();
      // 歌单列表接口:https://autumnfish.cn/top/playlist
      this.listData();
      // 修改页码为1
      this.page = 1;
      console.log(this.page);
    },
  },
};
</script>
<style scoped>
@import "../assets/common/tab.css";
ul {
    
    
  list-style: none;
}
.playlists {
    
    
  z-index: 12;
  max-width: 1300px;
  margin: 0 auto;
  padding: 20px;
}
.top-card-wrap {
    
    
  height: 250px;
  padding: 20px;
  position: relative;
  z-index: 1;
  box-sizing: border-box;
  border-radius: 10px;
  overflow: hidden;
  display: flex;
  align-items: center;
}

.bg-blur {
    
    
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  filter: blur(20px);
  z-index: 2;
}

.top-card {
    
    
  display: flex;
  position: absolute;
  z-index: 3;
}

.img-wrap {
    
    
  width: 200px;
  height: 200px;
}

.img-wrap img {
    
    
  width: 100%;
  height: 100%;
}

.card-content {
    
    
  flex: 1;
  padding: 0 20px;
}

.card-tag {
    
    
  padding: 5px;
  width: 100px;
  box-sizing: border-box;
  border: 1px solid #d87093;
  color: palevioletred;
  text-align: center;
  border-radius: 10px;
  cursor: pointer;
}

.card-title {
    
    
  color: #fff;
  margin: 10px 0;
}

.card-info {
    
    
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 8;
  /* color: #888482; */
  color: #e3e3e3;
}

/* tab导航 */
.tab-container {
    
    
  margin-top: 20px;
  margin-bottom: 200px;
}

.tab-bar ul {
    
    
  height: 25px;
  display: flex;
  justify-content: flex-end;
}

.tab-item {
    
    
  margin-left: 20px;
  cursor: pointer;
  font-size: 15px;
  color: grey;
}

.active {
    
    
  color: palevioletred;
}

.tab-content {
    
    
  margin-top: 20px;
}

.songs-wrap .list ul {
    
    
  width: 100%;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}

.songs-wrap .list li {
    
    
  width: 18%;
  margin: 10px 0;
  position: relative;
  overflow-y: hidden;
}

.list li .first-p {
    
    
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 12px;
  padding: 5px;
  box-sizing: border-box;
  /* border-top-left-radius: 10px;
      border-top-right-radius: 10px; */
  transform: translateY(-100%);
  transition: 0.5s;
}

.list li::before {
    
    
  content: "\ea42";
  position: absolute;
  bottom: 25px;
  right: 5px;
  width: 35px;
  height: 35px;
  font-size: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: palevioletred;
  opacity: 0;
  transition: 0.3s;
  cursor: pointer;
}

.list li:hover .first-p {
    
    
  transform: translateY(0);
}

.list li:hover::before {
    
    
  opacity: 1;
}

.songs-wrap ul img {
    
    
  width: 100%;
  border-radius: 5px;
  /* opacity: 1; */
}

.songs-wrap ul .last-p {
    
    
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin: 5px 0;
}
.page-list {
    
    
  margin: 10px;
  margin-bottom: 100px;
  text-align: center;
}
</style>

最新音乐:

<template>
  <!-- 最新音乐 -->
  <div class="new-songs" :style="backgroundDiv">
    <div class="tab-bar">
      <span class="item" @click="tag = 0" :class="{ active: tag == 0 }"
        >全部</span
      >
      <span class="item" @click="tag = 7" :class="{ active: tag == 7 }"
        >华语</span
      >
      <span class="item" @click="tag = 96" :class="{ active: tag == 96 }"
        >欧美</span
      >
      <span class="item" @click="tag = 8" :class="{ active: tag == 8 }"
        >日本</span
      >
      <span class="item" @click="tag = 16" :class="{ active: tag == 16 }"
        >韩文</span
      >
    </div>
    <div class="songs-table">
      <el-table :data="tableData" style="width: 100%">
        <el-table-column type="index" width="50"></el-table-column>

        <el-table-column width="180">
          <template slot-scope="scope">
            <div class="img-wrap" @click="playMusic(scope.row)">
              <img :src="scope.row.album.picUrl" alt="" />
              <p class="iconfont icon-play"></p>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="name" label="音乐标题" width="250">
        </el-table-column>
        <el-table-column prop="artists[0].name" label="歌手" width="250">
        </el-table-column>
        <el-table-column prop="album.name" label="专辑" width="250">
        </el-table-column>
        <el-table-column prop="duration" label="时长" width="250">
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>
<script>
// 导入axios
import axios from "axios";
export default {
    
    
  name: "NewSongs",
  data() {
    
    
    return {
    
    
      tableData: [],
      tag: "0",
      backgroundDiv: {
    
    },
    };
  },
  created() {
    
    
    this.getNewSongs();
  },
  computed: {
    
    
    musicQueue() {
    
    
      return this.$store.state.musicQueue;
    },
  },
  methods: {
    
    
    getNewSongs() {
    
    
      // 获取最新音乐数据接口:https://autumnfish.cn/top/song
      axios({
    
    
        url: "https://autumnfish.cn/top/song",
        method: "get",
        params: {
    
    
          type: this.tag,
          limit: 10,
          // 起始的值:(页码-1)*每页多少条数据
          offset: (this.page - 1) * 10,
        },
      }).then((res) => {
    
    
        // console.log(res.data);
        let songsList = [];
        this.total = 50;
        let resultList = res.data.data.slice(0, 50);
        for (const item of resultList) {
    
    
          /**毫秒————350750
           * 秒 ————350750/1000
           * 分 ————350750/1000/60
           * 秒 ————350750/1000%60
           */
          let duration = item.duration;
          // console.log(duration);
          let min = parseInt(duration / 60000)
            .toString()
            .padStart(2, "0");
          let second = parseInt((duration - min * 60000) / 1000)
            .toString()
            .padStart(2, "0");
          duration = `${
      
      min}:${
      
      second}`;
          item.duration = duration;
          songsList.push(item);
        }
        this.tableData = songsList;
      });
    },
    playMusic(row) {
    
    
      // 播放音乐:https://autumnfish.cn/song/url
      let id = row.id;
      axios({
    
    
        url: "https://autumnfish.cn/song/url",
        method: "get",
        params: {
    
    
          id,
        },
      }).then((res) => {
    
    
        this.$parent.$data.musicinfo = row;
        this.$parent.$data.musicurl = res.data.data[0].url;
      });
      let musicitem = {
    
    
        id: row.id,
        name: row.name,
        musicArtist: row.artists[0].name,
        duration: row.duration,
        picUrl: row.album.picUrl,
      };
      this.$store.commit("changeMusicInfo", musicitem);
      this.$store.commit("changeMusicQueue", musicitem);
      let ids = [];
      for (const item of this.musicQueue) {
    
    
        ids.push(item.id);
      }
      this.$store.commit("changeNowIndex", ids.indexOf(row.id));
    },
  },
  watch: {
    
    
    tag() {
    
    
      this.getNewSongs();
    },
  },
};
</script>
<style scoped>
@import "../assets/common/tab.css";
ul {
    
    
  list-style: none;
}
.new-songs {
    
    
  max-width: 1300px;
  margin: 0 auto;
  padding: 20px;
}

.new-songs >>> .el-loading-spinner {
    
    
  top: 50%;
}

.el-table td,
.el-table th.is-leaf {
    
    
  border-bottom: none;
}

.el-table::before {
    
    
  opacity: 0;
}

.songs-table {
    
    
  width: 100%;
}

.img-wrap {
    
    
  width: 60px;
  height: 60px;
  position: relative;
}

.img-wrap img {
    
    
  width: 100%;
  height: 100%;
  border-radius: 10px;
}

.img-wrap .iconfont::before {
    
    
  content: "\ea42";
  position: absolute;
  bottom: 12px;
  right: 12px;
  width: 35px;
  height: 35px;
  font-size: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: palevioletred;
  opacity: 0;
  transition: 0.3s;
  cursor: pointer;
}
.img-wrap:hover .iconfont::before {
    
    
  opacity: 1;
}
.page-list {
    
    
  margin: 10px;
  margin-bottom: 150px;
}
.songs-table {
    
    
  margin-bottom: 200px;
}
.tab-bar span {
    
    
  height: 25px;
  margin-left: 20px;
  cursor: pointer;
  font-size: 15px;
  color: grey;
}

.tab-bar .item.active {
    
    
  color: palevioletred;
  font-weight: bold;
}
</style>

最新MV:

<template>
  <!-- 最新MV -->
  <div class="new-mvs">
    <div class="filter-wrap">
      <div class="section-wrap">
        <span class="section-name">地区:</span>
        <ul class="section-tabs">
          <li>
            <span :class="{ active: area == '全部' }" @click="area = '全部'"
              >全部</span
            >
          </li>
          <li>
            <span :class="{ active: area == '内地' }" @click="area = '内地'"
              >内地</span
            >
          </li>
          <li>
            <span :class="{ active: area == '港台' }" @click="area = '港台'"
              >港台</span
            >
          </li>
          <li>
            <span :class="{ active: area == '欧美' }" @click="area = '欧美'"
              >欧美</span
            >
          </li>
          <li>
            <span :class="{ active: area == '日本' }" @click="area = '日本'"
              >日本</span
            >
          </li>
          <li>
            <span :class="{ active: area == '韩国' }" @click="area = '韩国'"
              >韩国</span
            >
          </li>
        </ul>
      </div>

      <div class="section-wrap">
        <span class="section-name">类型:</span>
        <ul class="section-tabs">
          <li>
            <span :class="{ active: type == '全部' }" @click="type = '全部'"
              >全部</span
            >
          </li>
          <li>
            <span :class="{ active: type == '官方版' }" @click="type = '官方版'"
              >官方版</span
            >
          </li>
          <li>
            <span :class="{ active: type == '原声' }" @click="type = '原声'"
              >原声</span
            >
          </li>
          <li>
            <span :class="{ active: type == '现场版' }" @click="type = '现场版'"
              >现场版</span
            >
          </li>
          <li>
            <span
              :class="{ active: type == '网易出品' }"
              @click="type = '网易出品'"
              >网易出品</span
            >
          </li>
        </ul>
      </div>
      <div class="section-wrap">
        <span class="section-name">排序:</span>
        <ul class="section-tabs">
          <li>
            <span
              :class="{ active: order == '上升最快' }"
              @click="order = '上升最快'"
              >上升最快</span
            >
          </li>
          <li>
            <span :class="{ active: order == '最热' }" @click="order = '最热'"
              >最热</span
            >
          </li>
          <li>
            <span :class="{ active: order == '最新' }" @click="order = '最新'"
              >最新</span
            >
          </li>
        </ul>
      </div>
    </div>
    <div class="mv-wrap">
      <ul class="mv-list">
        <li
          v-for="(item, index) in mvLists"
          :key="index"
          @click="toMvdetail(item.id)"
        >
          <div class="mv-img-wrap">
            <img :src="item.cover" alt="newMvs" />
            <p class="iconfont icon-play play"></p>
            <p class="play-count iconfont icon-play">{
    
    {
    
     item.playCount }}</p>
          </div>
          <div class="mv-info">
            <p class="title">{
    
    {
    
     item.name }}</p>
            <p class="author">{
    
    {
    
     item.artistName }}</p>
          </div>
        </li>
      </ul>

      <el-pagination
        class="page-list"
        @current-change="handleCurrentChange"
        :page-size="12"
        :current-page="page"
        layout="prev, pager, next"
        :total="total"
      >
      </el-pagination>
    </div>
  </div>
</template>
<script>
import axios from "axios";
export default {
    
    
  name: "NewMvs",
  data() {
    
    
    return {
    
    
      area: "全部",
      type: "全部",
      order: "上升最快",
      mvLists: [],
      page: 1,
      // 总条数
      total: 0,
    };
  },
  created() {
    
    
    this.mvlistData();
  },
  methods: {
    
    
    mvlistData() {
    
    
      axios({
    
    
        url: "https://autumnfish.cn/mv/all",
        method: "get",
        params: {
    
    
          limit: 12,
          type: this.type,
          order: this.order,
          area: this.area,
          offset: (this.page - 1) * 12,
        },
      }).then((res) => {
    
    
        this.mvLists = res.data.data;
        // 接口问题
        if (res.data.count) {
    
    
          this.total = res.data.count;
        }
        // 处理次数
        for (let i = 0; i < this.mvLists.length; i++) {
    
    
          if (this.mvLists[i].playCount > 100000) {
    
    
            this.mvLists[i].playCount =
              parseInt(this.mvLists[i].playCount / 10000) + "w";
          }
        }
      });
    },
    // 页码发生了改变
    handleCurrentChange(val) {
    
    
      console.log(`当前页:${
      
      val}`);
      this.page = val;
      // 重新获取数据
      this.mvlistData();
    },
    toMvdetail(id) {
    
    
      this.$router.push(`/mvdetail?q=${
      
      id}`);
    },
  },
  // 侦听器
  watch: {
    
    
    area() {
    
    
      // 获取数据
      this.mvlistData();
      this.page = 1;
    },
    type() {
    
    
      this.mvlistData();
      this.page = 1;
    },
    order() {
    
    
      this.mvlistData();
      this.page = 1;
    },
  },
};
</script>
<style scoped>
ul {
    
    
  list-style: none;
}
.new-mvs {
    
    
  z-index: 12;
  max-width: 1300px;
  margin: 0 auto;
  padding: 20px;
}
.section-wrap {
    
    
  display: flex;
  align-items: center;
  margin-bottom: 30px;
  font-size: 14px;
}

.section-tabs {
    
    
  display: flex;
  color: grey;
}

.section-tabs li:not(:last-of-type) {
    
    
  border-right: 1px solid #f2f2f1;
}

.section-tabs li span {
    
    
  margin: 20px;
  padding: 5px 20px;
  cursor: pointer;
  box-sizing: border-box;
}

.section-tabs .active {
    
    
  color: #f199a4;
  background-color: #fcf5fa;
  border-radius: 20px;
}
.mv-list {
    
    
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
}

.mv-list li {
    
    
  /* width: 250px;
      margin-right: 25px;
      margin-bottom: 30px; */
  width: 23%;
  margin-bottom: 20px;
  margin-right: 20px;
}
.mv-wrap {
    
    
  margin-bottom: 200px;
  overflow: auto;
}

.mv-img-wrap {
    
    
  position: relative;
  cursor: pointer;
}

.mv-img-wrap img {
    
    
  width: 100%;
  height: 100%;
  border-radius: 5px;
}

.mv-img-wrap:hover .play::before {
    
    
  opacity: 1;
}

.mv-img-wrap .play::before {
    
    
  content: "\ea42";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 35px;
  height: 35px;
  font-size: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: palevioletred;
  opacity: 0;
  transition: 0.3s;
  cursor: pointer;
}

.play-count {
    
    
  position: absolute;
  top: 5px;
  right: 5px;
  color: #fff;
  text-shadow: 0 0 2px rgb(0, 0, 0);
}

.play-count::before {
    
    
  margin-right: 5px;
}

.mv-info p {
    
    
  margin: 5px 0;
}

.mv-info p.title {
    
    
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mv-info .author {
    
    
  color: #a5a1a1;
  font-size: 12px;
}
.page-list {
    
    
  text-align: center;
}
</style>

代码链接和网站推荐

完整代码:aDiaoYa’s PlayMusic
视频推荐:带你进阶Vue技术栈:手把手教你打造自己的音乐播放器
Element-Ui:Element-Ui组件库
阿里巴巴图标库:阿里巴巴矢量图标库

作品或许有bug未修复,若友友们有发现,请指正!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/aDiaoYa_/article/details/129384784