vue+vant音乐播放器(andriod)项目
新建项目
在适合的目录下打开终端输入vue create music_player,回车
选择Default([Vue 2] babel,eslint)
等待项目构建完成


项目构建成功

安装路由
用vscode打开项目所在文件夹

新建终端输入命令npm install vue-router@3.5.2 --save

在src目录下新建文件夹router,并在其下新建文件index.js

在新建的文件index.js中写入路由模板代码,成为路由配置文件
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = []
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
在main.js中引入路由配置文件
import Vue from 'vue'
import App from './App.vue'
//引入路由
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
在App.vue文件中清除多余代码,并写入全局路由组件
<template>
<div>
<!-- 全局组件 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
/* 全局设置样式 */
html,body,#app{
height: 100%;
}
</style>
安装vant组件库
在终端中输入npm install vant@latest-v2 -S

在终端中输入npm install qs --save

在src目录下新建文件夹plugins,并在其下新建文件vant.js
并写入代码
import Vue from 'vue'
import Vant, { Locale } from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)

在main.js中引入vant.js
import Vue from 'vue'
import App from './App.vue'
//引入路由
import router from './router'
//引入vant.js文件
import './plugins/vant.js'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
安装axios
在终端中输入npm install axios --save

在src目录下新建文件夹http,并新建文件axios.js
并写入代码
import axios from 'axios'
let baseUrl='https://my-run-music-api.vercel.app'
/**
get方式请求
*/
export function get(addurl, data) {
return axios({
method: 'get',
url:baseUrl+addurl,
params:data, // get 请求时带的参数
})
}
export default axios

配置路由
在src下新建文件夹views,并新建文件Login.vue和Manage.vue
在新建的views目录下新建文件夹Home和Me
在新建的Home目录下新建文件home.vue和about.vue
在Me目录下新建文件me.vue

在src/router/index.js中写入代码
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
// 路由重定向 用户一次进入程序的时候 进入登录页面
{
path:'/',
redirect:'/login'
// redirect:'/manage/home'
},
// 登录页面的路由
{
path:'/login',
name:'Login',
component:()=>import('../views/Login.vue')
},
// 管理页面的路由
{
path:'/manage',
name:'Manage',
component:()=>import('../views/Manage.vue'),
// 配置子路由
children:[
// 首页
{
path:'home',
component:()=>import('../views/Home/home.vue')
},
// 我的页面
{
path:'me',
component:()=>import('../views/Me/me.vue')
},
// 关于页面
{
path:'about',
component:()=>import('../views/Home/about.vue')
}
]
}
]
const router = new VueRouter({
// mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
一些问题的解决方案
在 vue eslint 报错 error “Component name “*****“ should always be multi-word”
在vue.config.js文件中加入代码lintOnSave:false
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false
})
Vue中出现“**** is defined but never used”
在packagejson文件的rules里加入规则"no-unused-vars":"off"
{
"name": "music_player",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.27.2",
"core-js": "^3.8.3",
"qs": "^6.11.0",
"vant": "^2.12.48",
"vue": "^2.6.14",
"vue-router": "^3.5.2"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {
"no-unused-vars": "off"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
编写登录页面
调整页面整体样式
<template>
<div class="login">
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
/* 调整页面样式 */
/* 设置页面的整体样式 */
.login {
width: 100%;
height: 100vh;
/* 调整渐变色 */
background-image: linear-gradient(#70e1f5, #e5e5be, #e4e5e6);
overflow: hidden;
}
</style>
好看的渐变色获取网站https://uigradients.com/#Sylvia

App的名称或主题图片
往class="login"的div里添加代码
<div class="login">
<!-- 登录页面的头部 -->
<div class="header">
<!-- App的名称或主题图片 -->
<div class="title">
<img src="" alt="" />
<h1>XX音乐</h1>
</div>
</div>
</div>
设置头部区域的样式
/* 设置头部区域的样式 */
.header {
width: 100%;
/* 声明为绝对定位布局 */
position: absolute;
top: 60px;
text-align: center;
}
.header .title h1 {
color: #8a8a8a;
display: inline;
vertical-align: top;
}
.header .title img {
width: 45px;
}
获取矢量图标的网站https://www.iconfont.cn/

在src下新建文件夹img,下载所需要的图标


在空出的图片img的src中填入图片路径../img/ttleMusic.png
<template>
<div class="login">
<!-- 登录页面的头部 -->
<div class="header">
<!-- App的名称或主题图片 -->
<div class="title">
<img src="../img/titleMusic.png" alt="图片加载失败" />
<h1>XX音乐</h1>
</div>
</div>
</div>
</template>
<script>
export default {};
</script>
<style scoped>
/* 调整页面样式 */
/* 设置页面的整体样式 */
.login {
width: 100%;
height: 100vh;
/* 调整渐变色 */
background-image: linear-gradient(#70e1f5, #e5e5be, #e4e5e6);
overflow: hidden;
}
/* 设置头部区域的样式 */
.header {
width: 100%;
/* 声明为绝对定位布局 */
position: absolute;
top: 60px;
text-align: center;
}
.header .title h1 {
color: #8a8a8a;
display: inline;
vertical-align: top;
}
.header .title img {
width: 45px;
}
</style>
大logo
继续在class="login"的div里写入代码
<!-- 大logo -->
<div class="logo">
<img src="../img/themeMusic.png" alt="图片加载失败" />
<p>听我想听</p>
</div>
设置样式
/* 设置主题中心区域的样式 */
.logo {
width: 100%;
/* 声明为绝对定位布局 */
position: absolute;
top: 60px;
text-align: center;
top: 150px;
color: #1afa29;
}
.logo p {
font-size: 30px;
font-family: "Times New Roman", Times, serif;
}
登录表单的区域
<!-- 登录表单的区域 -->
<div class="loginArea">
<van-form @submit="onSubmit">
<van-field
v-model="username"
name="用户名"
label="用户名"
placeholder="用户名"
:rules="[{ required: true, message: '请填写用户名' }]"
/>
<van-field
v-model="password"
type="password"
name="密码"
label="密码"
placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]"
/>
<div style="margin: 16px">
<van-button round block type="info" native-type="submit"
>提交</van-button
>
</div>
</van-form>
</div>
设置样式
/* 设置登录表单区域的样式 */
.loginArea {
width: 90%;
/* 通过外边距的形式 */
margin: 460px auto;
/* 设置圆角 */
border-radius: 15px;
}
.loginArea .van-form .van-cell {
/* 设置圆角 */
border-radius: 15px;
/* 设置背景色通明 */
background-color: rgba(255, 255, 255, 0.2);
height: 50px;
}
.loginArea .van-form .van-button {
background-image: linear-gradient(to right, #74ebd5, #acb6e5);
}
编写js代码
export default {
data() {
return {
// 用户名
username: "",
// 密码
password: "",
};
},
methods: {
// 登录事件
onSubmit() {
// 设置对应的参数
let userInfo = {
// 用户名
username: this.username,
// 密码
password: this.password,
};
console.log(userInfo);
sessionStorage.setItem('userInfo',userInfo.username)
this.$router.push("/manage/home");
},
},
};
路由管理页面
在src/views/Manage.vue文件中写入代码
<template>
<div class="manage">
<!-- 声明渲染组件routerView -->
<router-view></router-view>
<!-- 创建tabbar结构 -->
<van-tabbar v-model="active">
<!-- 首页 -->
<van-tabbar-item icon="home-o" to="/manage/home">首页</van-tabbar-item>
<!-- 我的 -->
<van-tabbar-item icon="friends-o" to="/manage/me">我的</van-tabbar-item>
</van-tabbar>
</div>
</template>
<script>
export default {
data() {
return {
active: 0,
};
},
};
</script>
<style scoped>
</style>
自定义播放器组件
在src/components目录下新建文件MusicPlayer.vue
<template>
<div>
<div class="music-container" id="music-container">
<!-- 音乐信息 -->
<div class="music-info">
<!-- 音乐标题 -->
<h4 id="title">{{ songName }}</h4>
<!-- 音乐播放进度条 -->
<div class="progress-container" id="progress-container">
<div class="progress" id="progress"></div>
</div>
</div>
<!-- 默认第一首音乐 -->
<audio :src="songUrl" id="audio"></audio>
<!-- 音乐封面 -->
<div class="img-container">
<img :src="songImg" alt="加载中" id="music-cover" />
</div>
<!-- 播放控制 -->
<div class="navigation">
<button id="prev" class="action-btn" @click="prevSong">
<i class="fas fa-backward"></i>
</button>
<button id="play" class="action-btn action-btn-big" @click="playBtn">
<i class="fas fa-play"></i>
</button>
<button id="next" class="action-btn" @click="nextSong">
<i class="fas fa-forward"></i>
</button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
songList: [],
},
data() {
return {
//songList: [
// {
// songId: "5257138", //512085302
// songName: "屋顶",
// songImg:
// "https://p1.music.126.net/81BsxxhomJ4aJZYvEbyPkw==/109951165671182684.jpg",
// songUrl: "https://music.163.com/song/media/outer/url?id=5257138.mp3",
// },
//],
songId: "",
songName: "",
songImg: "",
songUrl: "",
songIndex: 0,
};
},
// 自动调用
created() {
this.reload();
},
methods: {
// 更新播放歌曲
reload() {
// console.log(this.songIndex + 1 + " in " + this.songList.length+':'+this.songList[this.songIndex].songUrl);
this.songId = this.songList[this.songIndex].songId;
this.songImg = this.songList[this.songIndex].songImg;
this.songName = this.songList[this.songIndex].songName;
this.songUrl = this.songList[this.songIndex].songUrl;
},
// 播放歌曲
playSong() {
let audio = this.$el.querySelector("#audio");
let musicContainer = this.$el.querySelector("#music-container");
let playBtn = this.$el.querySelector("#play");
musicContainer.classList.add("play");
playBtn.querySelector("i.fas").classList.remove("fa-play");
playBtn.querySelector("i.fas").classList.add("fa-pause");
audio.play();
},
// 播放器按钮
playBtn() {
let musicContainer = this.$el.querySelector("#music-container");
musicContainer.classList.contains("play")
? this.pauseSong()
: this.playSong();
},
// 停止播放
pauseSong() {
let audio = this.$el.querySelector("#audio");
let musicContainer = this.$el.querySelector("#music-container");
let playBtn = this.$el.querySelector("#play");
musicContainer.classList.remove("play");
playBtn.querySelector("i.fas").classList.add("fa-play");
playBtn.querySelector("i.fas").classList.remove("fa-pause");
audio.pause();
},
// 上一首
prevSong() {
this.songIndex--;
if (this.songIndex < 0) {
this.songIndex = this.songList.length - 1;
}
// 加载歌曲信息并播放
this.reload();
this.pauseSong();
},
// 下一首
nextSong() {
this.songIndex++;
if (this.songIndex > this.songList.length - 1) {
this.songIndex = 0;
}
this.reload();
this.pauseSong();
return this.songIndex;
},
// 结束
},
mounted() {
const audio = document.getElementById("audio");
const progress = document.getElementById("progress");
const progressContainer = document.getElementById("progress-container");
// 进度条更新
function updateProgress(e) {
// 对象解构操作
const { duration, currentTime } = e.target;
const progressPercent = (currentTime / duration) * 100;
// 进度条
progress.style.width = `${progressPercent}%`;
}
// 设置进度条
function setProgress(e) {
// progressContainer代理视图宽度
const width = this.clientWidth;
// 鼠标点击时处于progressContainer里的水平偏移量
const clickX = e.offsetX;
// audio.duration: 音频长度
const duration = audio.duration;
// audio.currentTime: 音频播放位置
audio.currentTime = (clickX / width) * duration;
}
// 事件监听
// 3.播放器进度条相关
// 3.1 设置播放进度
progressContainer.onclick = setProgress;
// 3.2 进度条更新
audio.ontimeupdate = updateProgress;
},
};
</script>
<style scoped>
@import "../../public/style.css";
@import "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/all.min.css";
</style>
在public目录下新建文件style.css
@import url('https://fonts.googleapis.com/css?family=Lato&display=swap');
.music-container {
background-image: linear-gradient(#ff6e7f, #bfe9ff);
border-radius: 15px;
display: flex;
position: fixed;
margin: 0;
left: 50%;
transform: translate(-50%,0);
z-index: 5;
}
.img-container {
position: relative;
width: 110px;
}
.img-container::after {
content: "";
background-color: #fff;
border-radius: 50%;
position: absolute;
bottom: 100%;
left: 50%;
width: 15px;
height: 15px;
/* 旋转 */
transform: translate(-50%, 50%);
}
.img-container img {
border-radius: 50%;
height: 110px;
width: inherit;
object-fit: cover;
position: absolute;
bottom: 0;
left: 0;
/* 封面360°旋转,默认不动 */
animation: rotate 3s linear infinite;
animation-play-state: paused;
}
/* 定义旋转动画 */
@keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
.navigation {
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
}
.action-btn {
/* 取消默认样式 */
border: 0;
background-color: rgba(247, 247, 247, 0.1);
/* ----- */
color:#ff6e7f;
font-size: 20px;
cursor: pointer;
padding: 10px;
margin: 0 20px;
}
.action-btn:focus {
/* 取消默认样式 */
outline: 0;
}
.action-btn.action-btn-big {
font-size: 30px;
}
.music-info {
position: absolute;
top: 0;
left: 20px;
/* 父元素宽度-40px */
width: calc(100% - 200px);
background-color: rgba(255, 255, 255, 0.5);
border-radius: 15px 15px 0 0;
padding: 10px 10px 10px 150px;
/* 没播放时默认隐藏 */
opacity: 0;
transform: translateY(0%);
transition: transform 0.3s ease-in, opacity 0.3s ease-in;
z-index: 0;
}
.music-info h4 {
/* 取消默认边距 */
margin: 0;
}
.music-container.play .music-info {
opacity: 1;
transform: translateY(-100%);
}
.progress-container {
background-color: #fff;
border-radius: 5px;
cursor: pointer;
margin: 10px 0;
height: 4px;
width: 100%;
}
.progress {
background-color: #0decfc;
border-radius: 5px;
height: 100%;
/* 一开始进度条长度为0 */
width: 0%;
transition: width 0.1s linear;
}
编写主页
<template>
<div class="home">
<!-- 搜索框 -->
<van-sticky>
<div class="search">
<van-search
shape="round"
background="linear-gradient(to right,#ff6e7f, #bfe9ff)"
placeholder="请输入搜索关键词"
@click="gotoAboutPage"
/>
</div>
</van-sticky>
<!-- 轮播图 -->
<div class="swiper">
<van-swipe
class="my-swipe"
:autoplay="1500"
indicator-color="white"
:height="200"
>
<van-swipe-item v-for="(item, index) in swiperPic" :key="index">
<img :src="item.pic" alt="无法加载图片" width="100%" :v-lazy="item.pic" />
</van-swipe-item>
</van-swipe>
</div>
<!-- 歌单宫格 -->
<div class="songGrid">
<van-grid :border="true" :column-num="5" square>
<van-grid-item v-for="(item, index) in songGrid" :key="index">
<van-image
:src="item.iconUrl"
style="
width: 30px;
background-image: linear-gradient(#ed4264, #ffedbc);
border-radius: 50px;
"
/>
<div style="font-size: 10px; height: 0px">{{ item.name }}</div>
</van-grid-item>
</van-grid>
</div>
<!-- 歌单 -->
<div class="songList">
<van-swipe-cell class="goodList" v-if="show">
<div class="text">推荐歌曲</div>
<van-card
v-for="(item, index) in songList"
:key="index"
:title="item.songName"
:v-lazy="item.songImg"
:thumb="item.songImg"
class="goods-card"
@click="playSong(index)"
/>
</van-swipe-cell>
<!-- 未加载 -->
<div class="noLoad" v-else>
<van-empty image="network" description="网络错误" />
</div>
<div class="space">
<van-card style="background-color: rgba(247, 247, 247, 0)" />
</div>
<div class="space">
<van-card style="background-color: rgba(247, 247, 247, 0)" />
</div>
</div>
<!-- 音频播放器 -->
<div class="musicArea">
<MusicPlayer
:songList="songList"
v-if="show"
ref="playSong"
class="music-player"
></MusicPlayer>
</div>
</div>
</template>
<script>
import MusicPlayer from "../../components/MusicPlayer.vue";
import { get } from "../../http/axios";
export default {
data() {
return {
// 轮播图
swiperPic: [],
// 宫格
songGrid: [],
// 歌曲列表
songList: [],
show: false,
};
},
components: { MusicPlayer },
created() {
this.getSongListData();
this.getSwiperData();
this.getSongGridData();
this.addSong();
},
methods: {
addSong() {
// 获取到路由传参传递过来的activeKey 给data中的对应的变量进行赋值
// console.log(this.$route.query.songId);
if (this.$route.query.songId)
this.songList.push({
songId: this.$route.query.songId,
songName: this.$route.query.songName,
songImg: this.$route.query.songImg,
songUrl: this.$route.query.songUrl,
});
},
// 点击事件播放歌曲
playSong(index) {
// console.log(index);
for (; this.$refs.playSong.nextSong() != index; ) {}
},
// 获取歌曲列表数据
async getSongListData() {
// 发送网络请求
let res = await get("/personalized/newsong");
// console.log(res.data.result);
// 向data中的变量进行赋值
for (let index in res.data.result) {
if (index < 10)
this.songList.push({
songId: res.data.result[index].id,
songName: res.data.result[index].name,
songImg: res.data.result[index].picUrl,
songUrl:
"https://music.163.com/song/media/outer/url?id=" +
res.data.result[index].id +
".mp3",
});
}
this.show = true;
},
// 获取轮播图数据
async getSwiperData() {
// 1.发送网络请求 获取对应的数据
let res = await get("/homepage/block/page");
this.swiperPic = res.data.data.blocks[0].extInfo.banners;
},
// 获取宫格数据
async getSongGridData() {
// 发送网络请求获取对应的数据
let res = await get("/homepage/dragon/ball");
// console.log(res.data.data);
// 向data中的变量进行赋值
this.songGrid = res.data.data;
},
// 点击搜索框跳转到关于页面
gotoAboutPage() {
this.$router.push("/manage/about");
},
/**
*
*/
},
};
</script>
<style scoped>
/* 整体样式 */
.home {
background-image: linear-gradient(to right, #ff6e7f, #bfe9ff);
}
/* 分区样式 */
.swiper,
.songList,
.songGrid {
margin: 15px;
}
.my-swipe,
.songList .goodList {
border-radius: 15px;
}
/* 轮播图样式 */
.my-swipe {
height: 120px;
}
.my-swipe .van-swipe-item {
color: #fff;
font-size: 20px;
line-height: 150px;
text-align: center;
background-color: #39a9ed;
}
/* 歌单宫格样式 */
.songGrid {
/* height: 110px; */
padding: 5px;
background-color: rgba(247, 247, 247, 0.4);
border-radius: 15px;
}
.songGrid /deep/ .van-grid-item__content {
background-color: rgba(255, 255, 255, 0);
}
/* 歌单样式 */
.songList .goodList .goods-card,
.songList .text {
margin: 0;
padding: 10px;
background-color: rgba(247, 247, 247, 0.4);
}
.songList .goodList .text {
font-size: 30px;
font-family: Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
}
.songList .goodList .goods-card .van-card__header {
height: 60px;
}
.songList .goodList .goods-card .van-card__title {
font-size: 20px;
height: 30px;
}
.songList .goodList .goods-card .van-card__thumb {
width: 60px;
height: 60px;
}
.songList .goodList .goods-card .delete-button {
height: 100%;
}
/* 音乐播放器 */
.musicArea {
width: 100%;
height: 100px;
position: fixed;
bottom: 0px;
}
</style>
编写我的页面
<template>
<div class="mine">
<!-- 顶部的背景 -->
<div class="bg"></div>
<!-- 顶部用户信息 -->
<div class="userInfo">
<!-- 用户头像 -->
<div class="userFace">
<img src="../../img/head.jpg" alt="" />
</div>
<!-- 用户名 -->
<div class="userName">
{{ userInfo.username }}
</div>
</div>
<!-- 操作列表 指示列表 -->
<div class="cellArea">
<!-- title 标题 icon-是左侧图标 name-右侧图标 -->
<van-cell title="设置" icon="setting-o">
<!-- 使用 right-icon 插槽来自定义右侧图标 -->
<template #right-icon>
<van-icon name="arrow" class="search-icon" />
</template>
</van-cell>
<van-cell title="联系我们" icon="service-o">
<!-- 使用 right-icon 插槽来自定义右侧图标 -->
<template #right-icon>
<van-icon name="arrow" class="search-icon" />
</template>
</van-cell>
<van-cell title="关于我们" icon="service-o">
<!-- 使用 right-icon 插槽来自定义右侧图标 -->
<template #right-icon>
<van-icon name="arrow" class="search-icon" />
</template>
</van-cell>
</div>
<!-- 退出按钮 -->
<div class="logoutBtn" @click="logoutHandler">退出登录</div>
</div>
</template>
<script>
import { Dialog } from "vant";
export default {
data() {
return {
// 用户信息
userInfo:{
username:"马保国"
}
};
},
created() {
this.getUserInfo()
},
methods: {
getUserInfo(){
this.userInfo.username=sessionStorage.getItem('userInfo')
},
// 退出登录
logoutHandler() {
// 做一个提示
Dialog.confirm({
message: "是否确认退出登录?",
theme: "round-button",
})
.then(() => {
// 点击确认按钮 执行退出登录
// 清除掉本地保存的token 执行退出的网络操作
// delToken();
// 跳转回到登录页面
this.$router.push("/login");
})
.catch(() => {
// on cancel
});
},
},
};
</script>
<style scoped>
/* 设置顶部的背景样式 */
.mine .bg {
/* 设置渐变色 */
background-image: linear-gradient(to right, #ff6e7f, #bfe9ff);
height: 200px;
/* 设置底部左右两侧的弧度为一个圆形 */
border-bottom-left-radius: 50%;
border-bottom-right-radius: 50%;
}
/* 用户区域样式 */
.mine .userInfo {
background-color: #fff;
width: 80%;
height: 160px;
/* 开启绝对定位 */
position: absolute;
top: 100px;
left: 50%;
margin-left: -40%;
/* 透明度 */
opacity: 0.8;
/* 阴影 */
box-shadow: 0 0 10px #ccc;
border-radius: 10px;
}
/* 用户区域头像样式 */
.userInfo .userFace {
width: 100px;
height: 100px;
/* 要设置一个元素为圆形 */
border-radius: 50%;
/* margin: 0 auto; */
position: absolute;
left: 50%;
/* 形变 平移 */
transform: translate(-50%, -50%);
}
/* 用户区域头像的图片样式 */
.userInfo .userFace img {
width: 100%;
height: 100%;
border-radius: 50%;
}
/* 用户名的样式 */
.userInfo .userName {
/* background-color: green; */
text-align: center;
margin-top: 70px;
font-size: 28px;
}
/* 设置操作列表区域的样式 */
.mine .cellArea {
margin: 120px auto;
width: 95%;
box-shadow: 4px 4px 4px 0 rgba(248, 123, 140, 0.3);
border-radius: 10px;
}
/* van-cell的样式 */
.search-icon {
font-size: 16px;
line-height: inherit;
}
/* 退出按钮的样式 */
.logoutBtn {
width: 50%;
/* 设置渐变色 */
background-image: linear-gradient(to right, #ff6e7f, #bfe9ff);
text-align: center;
color: #fff;
/* 设置行高 */
line-height: 35px;
border-radius: 20px;
margin: 0 auto;
cursor: pointer;
}
</style>
编写搜索页面
<template>
<div class="about">
<!-- 搜索框 -->
<van-sticky>
<div class="search">
<van-search
shape="round"
background="linear-gradient(to right,#ff6e7f, #bfe9ff)"
v-model="value"
clearable
placeholder="请输入搜索关键词"
@input="getSearchData"
>
<template #left-icon>
<van-icon name="arrow-left" @click="onCancel"/>
</template>
</van-search>
</div>
</van-sticky>
<!-- 歌单 -->
<div class="songList">
<!-- 已输入 -->
<div class="input" v-if="showList">
<van-swipe-cell class="goodList">
<div class="text">单曲</div>
<van-card
v-for="(item, index) in songList"
:key="index"
:title="item.songName"
:desc="item.songDesc"
class="goods-card"
@click="playSong(index)"
/>
</van-swipe-cell>
</div>
<!-- 未输入 -->
<div class="noInput" v-else>
<van-empty image="search" />
</div>
<div class="space">
<van-card style="background-color: rgba(247, 247, 247, 0)" />
</div>
</div>
</div>
</template>
<script>
import { get } from "../../http/axios";
export default {
data() {
return {
value: "",
songList: [],
showList: false,
};
},
methods: {
// 取消并返回
onCancel() {
this.$router.go(-1);
},
// 通过搜索获取歌曲
async getSearchData() {
this.songList = [];
this.showList = false;
let data = {
keywords: this.value,
};
let res = await get("/search", data);
this.songList = [];
for (let index in res.data.result.songs) {
this.getSongDetailById(res.data.result.songs[index].id);
}
// });
},
// 通过歌曲id获取歌曲详情
async getSongDetailById(Id) {
let data = {
ids: Id,
};
let res = await get("/song/detail", data);
this.songList.push({
songId: res.data.songs[0].id,
songName: res.data.songs[0].name,
songDesc: res.data.songs[0].ar[0].name,
songImg: res.data.songs[0].al.picUrl,
songUrl:
"https://music.163.com/song/media/outer/url?id=" +
res.data.songs[0].id +
".mp3",
});
this.showList = true;
// });
},
// 播放歌曲并跳转
playSong(index) {
// 跳转页面 并 传参
this.$router.push({
// 页面的路径
path: "/manage/home",
// 传递的参数
query: {
songId: this.songList[index].songId,
songName: this.songList[index].songName,
songImg: this.songList[index].songImg,
songUrl: this.songList[index].songUrl,
},
});
},
},
};
</script>
<style scoped>
/* 整体样式 */
.about {
background-image: linear-gradient(to right, #ff6e7f, #bfe9ff);
}
/* 歌单样式 */
.songList {
margin: 15px;
}
.songList .goodList {
border-radius: 15px;
}
.songList .goodList .goods-card,
.songList .text {
margin: 0;
padding: 10px;
background-color: rgba(247, 247, 247, 0.4);
}
.songList .goodList .text {
font-size: 30px;
font-family: Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
}
.songList .goodList .goods-card .van-card__header {
height: 60px;
}
.songList .goodList .goods-card .van-card__title {
padding: 2px 0;
font-size: 20px;
height: 30px;
}
.songList .goodList .goods-card .delete-button {
height: 100%;
}
/* 未输入 */
.songList .noInput .van-empty {
height: 650px;
}
</style>

浙公网安备 33010602011771号