非常感谢那些无私开源的程序员,希望我也能够有能力像你们那样,开源很多很有意思的东西~~

//index.html
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>cloud-music</title><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=format-detection content="telephone=no"><meta name=format-detection content="email=no"><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-status-bar-style content=black><meta name=full-screen content=yes><meta name=browsermode content=application><meta name=x5-orientation content=portrait><meta name=x5-fullscreen content=true><meta name=x5-page-mode content=app><!--清除缓存--><meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /><meta http-equiv="Pragma" content="no-cache" /><meta http-equiv="Expires" content="0" /><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui"><link rel="icon" href="static/logo.ico" type="image/x-icon" /><link rel="shortcut icon" href="static/logo.ico" type="image/x-icon" /><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic"><link href="http://cdn.bootcss.com/material-design-icons/3.0.1/iconfont/material-icons.min.css" rel="stylesheet"><script>;(function (doc, win, undefined) {let docEl = doc.documentElement,resizeEvt = 'orientationchange' in win? 'orientationchange' : 'resize',recalc = function () {let clientWidth = docEl.clientWidth;if (clientWidth === undefined) return;docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';};if (doc.addEventListener === undefined) return;win.addEventListener(resizeEvt, recalc, false);doc.addEventListener('DOMContentLoaded', recalc, false)})(document, window);</script><style>* {margin: 0;padding: 0;}a {text-decoration: none;}p, span {font-size: 12px;}</style>
</head>
<body>
<div id="app"><keep-alive><router-view v-if="$route.meta.keepAlive"></router-view></keep-alive><router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
<script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script>
<script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script>
<script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
</body>
</html>
//app.vue
<template><div><!-- 主界面部分 --><loading :show="loadingShow"></loading><keep-alive><router-view v-if="$route.meta.keepAlive"></router-view></keep-alive><router-view v-if="!$route.meta.keepAlive"></router-view><player v-show="songList.length > 0 && !showDetail"></player></div>
</template>
<script>import player from './components/playerBar/playerBar';import loading from './components/loading/overall-loading';import { mapGetters } from 'vuex';export default {name: 'app',mounted () {console.log('%c 浅滩戏虾', 'background-image:-webkit-gradient( linear, left top,right top, color-stop(0, #00a419),color-stop(0.15, #f44336), color-stop(0.29, #ff4300),color-stop(0.3, #AA00FF),color-stop(0.4, #8BC34A), color-stop(0.45, #607D8B),color-stop(0.6, #4096EE), color-stop(0.75, #D50000),color-stop(0.9, #4096EE), color-stop(1, #FF1A00));color:transparent;-webkit-background-clip:text;font-size:13px;');},computed: {...mapGetters(['songList','showDetail','loadingShow'])},components: {player,loading}};
</script>
//main.js
import Vue from 'vue';
import store from './vuex';
import VueRouter from 'vue-router';
import VueLazyload from 'vue-lazyload';  // 引入图片懒加载模块
import App from './App';
import routes from './routers';
// import {loadFromlLocal} from './common/js/store'; // 公共方法:本地缓存
// 注册为全局组件
Vue.use(VueRouter);
// error,loading是图片路径, 用require引入
Vue.use(VueLazyload, {error: require('./assets/404.png'),loading: require('./assets/loading.jpg'),attempt: 1}
);const scrollBehavior = (to, from, savedPosition) => {if (savedPosition) {// savedPosition is only available for popstate navigations.return savedPosition;} else {let position = {};// new navigation.// scroll to anchor by returning the selectorif (to.hash) {position.selector = to.hash;}// check if any matched route config has meta that requires scrolling to topif (to.matched.some(m => m.meta.scrollToTop)) {// cords will be used if no selector is provided,// or if the selector didn't match any element.position.x = 0;position.y = 0;}// if the returned position is falsy or an empty object,// will retain current scroll position.return position;}
};const router = new VueRouter({// mode: 'history','linkActiveClass': 'active',routes, // (缩写)相当于 routes: routesscrollBehavior
});/*** 创建和挂载根实例。* 记得要通过 router 配置参数注入路由,* 从而让整个应用都有路由功能*/
const routerApp = new Vue({router,store,render: h => h(App)
}).$mount('#app');/*** loadFromlLocal()是读取本地缓存数据,具体common/js/store.js 查看*/
// if (!loadFromlLocal('music', 'find', false)) {
//   router.push('/find');
// }
export default routerApp;
//router.js
/*** 整个app的路由设置*/
const router = [{path: '/find',  //  引导页name: 'index',component (resolve) {require.ensure(['./views/index'], () => {resolve(require('./views/index'));});},children: [{path: '/find',  //  发现name: 'find',component (resolve) {require.ensure(['./views/find/find'], () => {resolve(require('./views/find/find'));});},meta: { keepAlive: true }}],meta: { keepAlive: true }
}, {path: '/search',  //  搜索页name: 'search',component (resolve) {require.ensure(['./views/search/search'], () => {resolve(require('./views/search/search'));});},meta: { keepAlive: true }
}, {path: '/player/:id', //  单曲播放页name: 'player',component (resolve) {require.ensure(['./views/detail/player/player'], () => {resolve(require('./views/detail/player/player'));});},meta: { keepAlive: false }
}, {path: '/playLists/:id',  //  歌单详情页name: 'playLists',component (resolve) {require.ensure(['./views/detail/playList/playlists'], () => {resolve(require('./views/detail/playList/playlists'));});},meta: { keepAlive: false }
}, {path: '/singer/:id',  //  歌手详情页name: 'singer',component (resolve) {require.ensure(['./views/detail/singer/singer'], () => {resolve(require('./views/detail/singer/singer'));});},meta: { keepAlive: false }
}, {path: '/album/:id',  // 专辑详情页name: 'album',component (resolve) {require.ensure(['./views/detail/album/album'], () => {resolve(require('./views/detail/album/album'));});},meta: { keepAlive: false }
}, {path: '/user/:id',  // 用户详情页name: 'user',component (resolve) {require.ensure(['./views/detail/user/user'], () => {resolve(require('./views/detail/user/user'));});},meta: { keepAlive: false }
}, {path: '/ranking/:idx',  // 榜单详情页name: 'ranking',component (resolve) {require.ensure(['./views/detail/ranking/ranking'], () => {resolve(require('./views/detail/ranking/ranking'));});},meta: { keepAlive: false }
}, {path: '/mv/:id',  // 视频播放name: 'mv',component (resolve) {require.ensure(['./views/detail/mvPlay/mvPlay'], () => {resolve(require('./views/detail/mvPlay/mvPlay'));});},meta: { keepAlive: false }
}, {path: '/playListComment/:id',  // 歌单评论name: 'playListComment',component (resolve) {require.ensure(['./views/detail/playList/playListComment'], () => {resolve(require('./views/detail/playList/playListComment'));});},meta: { keepAlive: false }
}, {path: '/albumComment/:id',  // 专辑评论name: 'albumComment',component (resolve) {require.ensure(['./views/detail/album/albumComment'], () => {resolve(require('./views/detail/album/albumComment'));});},meta: { keepAlive: false }
}, {path: '/rankingComment/:id',  // 排行榜歌单评论name: 'rankingComment',component (resolve) {require.ensure(['./views/detail/ranking/rankingComment'], () => {resolve(require('./views/detail/ranking/rankingComment'));});},meta: { keepAlive: false }
}, {path: '*', redirect: '/find' //  url错误重回定向
}];
export default router;
//find.vue
<template><transition name="fade"><div class="find-page"><tab :line-width=2 active-color='#b72712' defaultColor='#666' bar-active-color='#b72712'v-model="index"><!-- 切换 --><tab-item class="vux-center" :selected="type === item" v-for="(item, index) in tabList"@click="type = item" :key="index" style="background-color: #fdfffe;">{{item}}</tab-item></tab><!-- 轮播切换的 --><!-- 这个是左右的那种切换 --><swiper v-model="index" height="100%" :show-dots="false" class="swiper-container" style="width:100%;height: 100%;padding-bottom: 90px;background-color: #eef2f1;"><swiper-item :key="1"><div class="tab-swiper vux-center"><v-recommend></v-recommend></div></swiper-item><swiper-item :key="2"><div class="tab-swiper vux-center"><v-play-lists></v-play-lists></div></swiper-item><swiper-item :key="3"><div class="tab-swiper vux-center"><v-ranking></v-ranking></div></swiper-item></swiper></div></transition>
</template>
<script>import { Tab, TabItem, Swiper, SwiperItem } from 'vux';import vRecommend from './recommend/recommend';import vPlayLists from './playLists/playLists';import vRanking from './ranking/ranking';//tabList:list()const list = () => ['个性推荐', '歌单', '排行榜'];export default {name: 'find',data () {return {index: 0,tabList: list(),type: '个性推荐'};},components: {vPlayLists,vRecommend,vRanking,Tab,TabItem,Swiper,SwiperItem}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import 'find.styl';
</style>
//activitysList.vue
<template><ul class="activitys-area"><li class="activity-card-find" v-for="(data, index) in activitys" :key="index"><img v-lazy="data.picUrl + '?param=400y200'" lazy="loading"><h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2></li></ul>
</template>
<script>export default {name: 'v-activity-list',props: {activitys: {type: Array,default: []}}};
</script>
<style lang="stylus" rel="stylesheet/stylus">@import 'activitysList.styl';
</style>
//mvList.vue
<template><ul class="MV-area"><li class="mv-card-find" v-for="(data, index) in MVs" style="flex: 0 0 49.5%" @click="jumpMvDetail(data.id)" :key="index"><img v-lazy="data.picUrl + '?param=400y200'" lazy="loading"><h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2></li></ul>
</template>
<script>export default {name: 'v-mv-list',props: {MVs: {type: Array,default: []}},methods: {jumpMvDetail(id) {this.$router.push({path: '/mv/' + id});}}};
</script>
//newSongList.vue
<template><ul class="newSongList-area"><li class="newSongList-card-find" v-for="(data, index) in newSong" @click="jumpAlbumDetail(data.song.album.id)" :key="index"><img v-lazy="data.song.album.picUrl+ '?param=200y200'" lazy="loading"><h2 style="-webkit-box-orient: vertical;-webkit-line-clamp: 1">{{data.name}}</h2><p style="-webkit-box-orient: vertical;">{{data.song.artists[0].name}}</p></li></ul>
</template>
<script>export default {name: 'v-new-song-lists',props: {newSong: {type: Array,default: []}},methods: {jumpAlbumDetail(id) {this.$router.push({path: '/album/' + id});}}};
</script>
//djProgram.vue
<template><ul class="djProgram-area"><li class="djProgram-card-find" v-for="(data, index) in djProgram" :key="index"><img v-lazy="data.picUrl+ '?param=200y200'" lazy="loading"><h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2></li></ul>
</template>
<script>export default {name: 'v-dj-program-lists',props: {djProgram: {type: Array,default: []}},methods: {jumpPlayListsDetail(id) {this.$router.push({path: '/playLists/' + id});}}};
</script>
//recommend.vue
<template><div class="recommend-area"><div id="slider"><swiper :options="swiperOption" style="height: 100%;"><swiper-slide v-for="(item, index) in slide_list" :key="index"><img :src="item" class="banner-item"  alt="" style="width: 100%; height: 100%;"></swiper-slide><div class="swiper-pagination swiper-pagination-white" slot="pagination"></div></swiper></div><div class="recommend-playLists-area"><h1 class="title">推荐歌单</h1><!-- 推荐歌单,有与后端交互 --><v-play-lists :playlists="playlists"></v-play-lists></div><div class="recommend-activitys-area"><h1 class="title">独家放送</h1><v-activitys-list :activitys="activitys"></v-activitys-list></div><div class="recommend-mv-area"><h1 class="title">最新音乐</h1><v-new-song-list :newSong="newSong"></v-new-song-list></div><div class="recommend-mv-area"><h1 class="title">推荐MV</h1><v-mv-list :MVs="MVs"></v-mv-list></div><div class="recommend-mv-area"><h1 class="title">主播电台</h1><v-dj-program-list :djProgram="djProgram"></v-dj-program-list></div></div>
</template>
<script>import api from '../../../api/index';import { swiper, swiperSlide } from 'vue-awesome-swiper';// v-forimport vPlayLists from '../../../components/list/find/recommend/playLists';// v-forimport vActivitysList from '../../../components/list/find/recommend/activitysList';import vMvList from '../../../components/list/find/recommend/mvList';import vNewSongList from '../../../components/list/find/recommend/newSongList';import vDjProgramList from '../../../components/list/find/recommend/djProgram';const imgList = ['/static/banner1.jpg', '/static/banner2.jpg', '/static/banner3.jpg', '/static/banner4.jpg'];export default {name: 'v-recommend',data () {return {swiperOption: {pagination: '.swiper-pagination',paginationClickable: true,autoplay: 2500},slide_list: imgList,playlists: [],activitys: [],MVs: [],newSong: [],djProgram: []};},mounted () {this.getPersonalizedResource();this.getPrivatecontentResource();this.getPersonalizedMvResource();this.getNewSongResource();this.getDjProgramResource();},methods: {getPersonalizedResource() {api.getPersonalized().then((response) => {this.playlists = response.data.result;console.log('getPersonalizedResource',response);}).catch((response) => {console.log(response);});},getPrivatecontentResource() {api.getPrivatecontent().then((response) => {this.activitys = response.data.result;}).catch((response) => {console.log(response);});},getPersonalizedMvResource() {api.getPersonalizedMv().then((response) => {this.MVs = response.data.result;}).catch((response) => {console.log(response);});},getNewSongResource() {api.getNewSong().then((response) => {this.newSong = response.data.result.slice(0, 6);}).catch((response) => {console.log(response);});},getDjProgramResource() {api.getDjProgram().then((response) => {this.djProgram = response.data.result.slice(0, 6);}).catch((response) => {console.log(response);});}},components: {swiper,swiperSlide,vPlayLists,vActivitysList,vMvList,vNewSongList,vDjProgramList}};
</script>
<style lang="stylus" rel="stylesheet/stylus">@import 'recommend.styl';
</style>

//主界面部分代码
<template><!-- 主界面部分 --><transition name="fade"><div class="index"><!-- 侧边栏 --><asideMenu v-show="isShowAsideMenu"></asideMenu><!-- 头部 --><v-header></v-header><router-view></router-view></div></transition>
</template>
<script>import vHeader from '../components/header/header';import asideMenu from '../components/aside/aside';export default {computed: {isShowAsideMenu() {return this.$store.state.isShowAsideMenu;}},components: {vHeader,asideMenu}                                                };
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import 'index.styl';
</style>
//header.vue
<template><div class="header"><div class="name"><span @click="showAsideMenu(true)" class="func"><i class="func-icon"></i></span><router-link to="/find" class="item"><span class="music"><i class="music-icon"></i></span></router-link><router-link to="/search" class="item"><span class="personal"><i class="personal-icon"></i></span></router-link><span class="search"><i @click="toSearch" class="search-icon"></i></span></div></div>
</template><script>
export default {name: 'header',methods: {toSearch () {this.$router.push('/search');},showAsideMenu (flag) {this.$store.commit('showAsideMenu', flag);}}
};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import "header.styl";
</style>
//src/components/aside/aside.vue
<template><transition name="fadeIn"><div  class="aside-menu"><i @click="showAsideMenu" class="back"></i><div class="aside"><div class="info"><img src="https://avatars2.githubusercontent.com/u/16521402?v=3&u=225ef33c491d879294c4cb06621ec15f5b01f02a&s=400"><p class="author">浅滩戏虾</p></div></div><div @click.stop.prevent="showAsideMenu" class="mask"></div></div></transition>
</template>
<script>
export default {name: 'aside',data () {return {isSignIn: false};},methods: {showAsideMenu () {this.$store.commit('showAsideMenu', false);}}
};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import "aside.styl";
</style>


//src/views/find/playLists/playLists.vue
<template><div class="playLists-area"><button-tab v-model="index"><button-tab-item @on-item-click="selectType()">最新</button-tab-item><button-tab-item @on-item-click="selectType()">最热</button-tab-item></button-tab><div class="playLists"><ul><li v-for="(data, index) in playlists" :key="index"><v-play-list :data="data"></v-play-list></li></ul></div></div>
</template>
<script>import api from '../../../api/index';import { ButtonTab, ButtonTabItem } from 'vux';import vPlayList from '../../../components/card/findCard/playList/playList';export default {name: 'v-play-lists',data () {return {index: 0,keys: 'new',playlists: []};},mounted: function() {this.getTopPlaylistResource();},methods: {selectType () {this.keys = this.index ? 'hot' : 'new';//点击切换,从后端获取数据this.getTopPlaylistResource();},getTopPlaylistResource() {this.$store.commit('update_loading', true);api.getTopPlaylistResource(this.keys, 20, 0).then((response) => {this.playlists = response.data.playlists;//数据会先渲染出来,所以要重新渲染完后执行// $nextTick() 在dom 重新渲染完后执行this.$nextTick(() => {this.$store.commit('update_loading', false);});}).catch((response) => {console.log(response);});}},components: {vPlayList,ButtonTab,ButtonTabItem}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import 'playLists.styl';
</style>
//src/components/list/find/ranking/songsList.vue
<template><ul class="ranking-songsList"><li style="-webkit-box-orient: vertical;" v-for="(item, index) in data" :key="index">{{index + 1}}.{{item.name}}-{{item.artists[0].name}}</li></ul>
</template>
<script>export default {name: 'v-songs-list',props: {data: {type: Array,default: []//如果有和后端交互的数据,页面会展示}}};
</script>
<style lang="stylus" rel="stylesheet/stylus">@import 'songsList.styl';
</style>

//search.vue
<template lang="html"><transition name="fade"><div class="search-page"><div class='header-other'><span @click="goBack" class="back"><i class="back-icon"></i></span><div class="input"><input v-model="keywords" @keyup.enter="toSearch(keywords)" type="text" placeholder='搜素音乐、歌手、歌词、用户'><i @click="keywords=''" v-show="keywords!==''&&!isShowHot" class="icon-cancel"></i></div></div><div class="hot" v-if="isShowHot"><p>热门搜索</p><ul class="keywords"><li v-for="item of hotKeywords" v-text="item" @click="toSearch(item)" class="keyword"></li></ul></div><div v-else class="search-list"><tab :line-width=2 active-color='#b72712' defaultColor='#666' bar-active-color='#b72712'v-model="index"><tab-item class="vux-center" :selected="type === item" v-for="(item, index) in tabList"@click="type = item" :key="index">{{item}}</tab-item></tab><swiper v-model="index" height="100%" :show-dots="false" class="swiper-container"><swiper-item :key="1"><div class="tab-swiper vux-center search-area"><v-single-list :songs="songs"></v-single-list></div></swiper-item><swiper-item :key="2"><div class="tab-swiper vux-center search-area"><v-singer-list :singer="singer"></v-singer-list></div></swiper-item><swiper-item :key="3"><div class="tab-swiper vux-center search-area"><v-album-list :albums="albums"></v-album-list></div></swiper-item><swiper-item :key="4"><div class="tab-swiper vux-center search-area"><v-play-lists :playlist="playlist"></v-play-lists></div></swiper-item><swiper-item :key="5"><div class="tab-swiper vux-center search-area"><v-user-list :user="user"></v-user-list></div></swiper-item><swiper-item :key="6"><div class="tab-swiper vux-center search-area"><v-mv-list :MVs="mvs"></v-mv-list></div></swiper-item></swiper></div></div></transition>
</template><script>import api from '../../api/index';import { Tab, TabItem, Swiper, SwiperItem } from 'vux';import vSingleList from '../../components/list/search/singleList';import vSingerList from '../../components/list/search/singerList';import vAlbumList from '../../components/list/search/albumList';import vPlayLists from '../../components/list/search/playLists';import vUserList from '../../components/list/search/userList';import vMvList from '../../components/list/search/mvList';const list = () => ['单曲', '歌手', '专辑', '歌单', '用户', 'MV'];const hotKeywordsList = () => ['清白之年', '我喜欢上你时的内心活动', '我想和你唱','hyukoh', '童话镇', '陈奕迅', '漂洋过海来看你', '许嵩', '成都', '林俊杰'];export default {name: 'search',data () {return {index: 0,tabList: list(),hotKeywords: hotKeywordsList(),type: '单曲',keywords: '',isShowHot: true,songs: [],singer: [],albums: [],playlist: [],user: [],mvs: []};},// watch $route 决定是否清除关键词watch: {'$route' (to, from) {if (from.name === 'find') {this.keywords = '';this.isShowHot = true;}}},methods: {initSearchList () {this.getSingleResource(); //  获取搜索单曲this.getAlbumResource(); //  获取搜索专辑this.getSingerResource(); //  获取搜索歌手this.getPlayListResource(); //  获取搜索歌单this.getUserResource(); //  获取搜索用户this.getMvResource(); // 获取搜索MV},goBack () {//返回this.$router.push({path: '/find'});},// 关键词搜索toSearch (keywords) {//关键词搜索this.keywords = keywords;if (this.keywords.trim()) {this.isShowHot = false;this.$router.push({path: '/search',query: {keywords: keywords}});this.initSearchList();}},//  获取搜索单曲getSingleResource() {this.$store.commit('update_loading', true);//获取搜索单曲api.getSearchResource(this.$route.query.keywords, 1, 30, 0).then((response) => {this.songs = response.data.result.songs;// $nextTick() 在dom 重新渲染完后执行this.$nextTick(() => {this.$store.commit('update_loading', false);});}).catch((response) => {console.log(response);});},//  获取搜索专辑getSingerResource() {//与后端交互api.getSearchResource(this.$route.query.keywords, 100, 30, 0).then((response) => {this.singer = response.data.result.artists;}).catch((response) => {console.log(response);});},//  获取搜索歌手getAlbumResource() {api.getSearchResource(this.$route.query.keywords, 10, 30, 0).then((response) => {this.albums = response.data.result.albums;}).catch((response) => {console.log(response);});},//  获取搜索歌单getPlayListResource() {api.getSearchResource(this.$route.query.keywords, 1000, 30, 0).then((response) => {this.playlist = response.data.result.playlists;}).catch((response) => {console.log(response);});},//  获取搜索用户getUserResource() {api.getSearchResource(this.$route.query.keywords, 1002, 30, 0).then((response) => {this.user = response.data.result.userprofiles;}).catch((response) => {console.log(response);});},//  获取搜索MVgetMvResource() {api.getSearchResource(this.$route.query.keywords, 1004, 30, 0).then((response) => {this.mvs = response.data.result.mvs;}).catch((response) => {console.log(response);});}},components: {Tab,TabItem,Swiper,SwiperItem,vSingleList,vSingerList,vAlbumList,vPlayLists,vUserList,vMvList}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import "search.styl";
</style>

//singerList.vue
<template><ul class="singer-list"><li class="singer-card"  v-for="(data, index) in singer" @click="jumpSingerDetail(data.id)" :key="index"><img v-lazy="data.picUrl + '?param=200y200'" lazy="loading" class="avatar"><p class="singer-name"><span class="name" style="-webkit-box-orient: vertical;">{{data.name}}</span><span class="trans" v-show="data.trans">({{data.trans}})</span></p></li></ul>
</template>
<script>export default {name: 'v-singer-list',props: {singer: {type: Array,default: []}},methods: {jumpSingerDetail(id) {this.$router.push({path: '/singer/' + id});}}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import 'singerList.styl';
</style>
//albumList.vue
<template><ul class="album-list"><v-album-card :data="data" v-for="(data, index) in albums" :key="index"></v-album-card></ul>
</template>
<script>
import vAlbumCard from '../../card/searchCard/albumCard';export default {name: 'v-album-list',components: {vAlbumCard},props: {albums: {type: Array,default: []}}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import 'albumList.styl';
</style>
//userList.vue
<template><ul class="user-list"><li v-for="(data, index) in user" class="user-card" @click="jumpUserDetail(data.userId)" :key="index"><img v-lazy="data.avatarUrl + '?param=200y200'" lazy="loading" class="avatarImage"><div class="avatar-info"><p class="avatar-name">{{data.nickname}}<span class="gender-man" v-if="data.gender === 1"><i class="man-icon"></i></span><span class="gender-female" v-else><i class="female-icon"></i></span></p><p class="avatar-intro" style="-webkit-box-orient: vertical;">{{data.signature}}</p></div></li></ul>
</template>
<!-- v-if v-else的使用 -->
<script>export default {name: 'v-user-card',props: {user: {type: Array,default: []}},methods: {jumpUserDetail(id) {this.$router.push({path: '/user/' + id});}}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import 'userList.styl';
</style>
//mvList.vue
<template><ul class="mv-list"><li class="mv-card" v-for="(data, index) in MVs" style="flex: 0 0 49.5%" @click="jumpMvDetail(data.id)" :key="index"><img v-lazy="data.cover + '?param=400y200'" lazy="loading" class="mv-image"><h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2><p style="-webkit-box-orient: vertical;">{{data.artistName}}</p></li></ul>
</template>
<script>export default {name: 'v-mv-list',props: {MVs: {type: Array,default: []}},methods: {jumpMvDetail(id) {this.$router.push({path: '/mv/' + id});}}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import 'mvList.styl';
</style>

//user.vue
<template><transition name="fade"><div class="user-detail"><div class="user-info" :style="{'background-image': 'url(' + backgroundImage + ')'}"><x-header :left-options="{backText: ''}" style="background-color:inherit; width: 100%;">{{userInfo.nickname}}</x-header><img v-lazy="avatarImage + '?param=200y200'" lazy="loading"><p class="user-name">{{userInfo.nickname}}<span class="gender-man" v-if="userInfo.gender === 1"><i class="man-icon"></i></span><span class="gender-female" v-else><i class="female-icon"></i></span></p></div><div class="tab-list"><tab :line-width=2 active-color='#b72712' defaultColor='#666' bar-active-color='#b72712' v-model="index"><tab-item class="vux-center" :selected="type === item" v-for="(item, index) in tabList" @click="type = item" :key="index">{{item}}</tab-item></tab><swiper v-model="index" height="100%" :show-dots="false"><swiper-item :key="0"><div class="tab-swiper vux-center"><div class="play-lists-detail"><ul style="list-style: none;"><li v-for="(data, index) in playlist" :key="index"><v-play-lists-card :data="data"></v-play-lists-card></li></ul></div></div></swiper-item><swiper-item :key="1"><!--<div class="tab-swiper vux-center">--><!--<div class="hot-single-list">--><!--<ul>--><!--<li v-for="(data, order) in playlist">--><!--<v-single-card :data="data" :order="order"></v-single-card>--><!--</li>--><!--</ul>--><!--</div>--><!--</div>--></swiper-item></swiper></div></div></transition>
</template>
<script type="text/ecmascript-6">import api from '../../../api';import { XHeader, Tab, TabItem, Swiper, SwiperItem } from 'vux';import vPlayListsCard from '../../../components/card/detail/playlists';const list = () => ['歌单', '关于TA'];export default {data () {return {tName: '歌单',type: '歌单',tabList: list(),index: 0,backgroundColor: '',userInfo: {},playlist: {}};},mounted: function() {this.getUserInfo();},methods: {back () {this.$router.go(-1);},getUserInfo () {this.$store.commit('update_loading', true);//与后端交互获取资源api.getUserPlaylistResource(this.$route.params.id).then((response) => {this.playlist = response.data.playlist;this.userInfo = response.data.playlist[0].creator;// $nextTick() 在dom 重新渲染完后执行this.$nextTick(() => {this.$store.commit('update_loading', false);});}).catch((response) => {console.log(response);});}},computed: {backgroundImage() {return '' || (this.userInfo.backgroundUrl + '?param=500y500');},avatarImage() {return '' || this.userInfo.avatarUrl;}},components: {Tab,TabItem,Swiper,SwiperItem,XHeader,vPlayListsCard}};
</script>
<style lang="less" scoped>.vux-swiper {height: 100%;}.vux-slider {height: 100%;}.tab-swiper {background-color: #fff;height: 100%;}
</style>
<style lang="stylus" rel="stylesheet/stylus">@import "user.styl";
</style>
//playlists.vue
<template><transition name="fade"><div class="playlist"><div class="fixed-title" :style="{'background': 'rgba(183, 39, 18, '+ opacity +')'}" style="transition: opacity .1s;" v-show="!isShowDetail"><x-header :left-options="{backText: ''}" style="background-color:transparent">{{tName}}</x-header></div><div class="playlist-info" :style="{'background-image': 'url(' + playListImage + '?param=500y500'+ ')'}" v-show="!isShowDetail"><div class="playlist-info-blur"><div class="playlist-intro"><img v-lazy="playListImage" class="playlist-image" lazy="loading" alt="photo" @click="showDetail()"><div class="playlist-intro-other"><p class="playlist-title" style="-webkit-box-orient: vertical;">{{playlist.name}}</p><div class="playlist-creator" @click="jumpUserDetail(creator.userId)"><img v-lazy="creatorImage + '?param=100y100'" lazy="loading"><span class="playlist-nickname" style="-webkit-box-orient: vertical;">{{creator.nickname}}</span><span class="more"> > </span></div></div></div><div class="playlist-status"><div class="playCount"><span class="file"><i class="icon-file"></i></span><span>{{playlist.playCount}}</span></div><div class="commentCount"><span class="comment" @click="jumpCommentDetail()"><i class="icon-comment"></i></span><span>{{playlist.commentCount}}</span></div><div class="shareCount"><span class="share"><i class="icon-share"></i></span><span>{{playlist.shareCount}}</span></div></div></div></div><div class="play-list" v-show="!isShowDetail"><v-play-all :data="commonSongs"></v-play-all><ul><li v-for="(data, index) in list" :key='index'><v-single-card :data="data" :index="index"></v-single-card></li></ul></div><v-play-list-detail :data="playlist" v-show="isShowDetail"></v-play-list-detail></div></transition>
</template>
<script>import api from '../../../api';import { XHeader } from 'vux';import vPlayAll from '../../../components/playAll/playAll.vue';import vSingleCard from '../../../components/card/detail/singleCard.vue';import vPlayListDetail from './playListDetail';export default {data () {return {playlist: {},tName: '歌单',creator: {},data: [],index: '',list: [],commonSongs: [],backgroundColor: '',opacity: 0,isShowDetail: false};},// 解除keep-alive的缓存beforeRouteEnter: (to, from, next) => {next(vm => {window.onscroll = () => {let opa = window.pageYOffset / 222;if (opa > 1) {vm.tName = vm.playlist.name;vm.opacity = 1;} else {vm.tName = '歌单';vm.opacity = 0;}};});},// 路由离开时清除onscroll事件beforeRouteLeave: (to, from, next) => {window.onscroll = null;next();},mounted: function() {let self = this;this.getPlayListDetail();this.$root.$on('close-detail', (condition) => {self.isShowDetail = condition;});},methods: {showDetail () {this.isShowDetail = true;},jumpUserDetail(id) {this.$router.push({path: '/user/' + id});},jumpCommentDetail() {this.$router.push({path: '/playListComment/' + this.$route.params.id});},getPlayListDetail () {//与后端交互获取数据this.$store.commit('update_loading', true);api.getPlaylistDetailResource(this.$route.params.id).then((response) => {this.playlist = response.data.playlist;this.list = response.data.playlist.tracks;this.creator = response.data.playlist.creator;this.songsToCommon(this.list);// $nextTick() 在dom 重新渲染完后执行this.$nextTick(() => {this.$store.commit('update_loading', false);});}).catch((error) => {console.log('加载歌单信息出错:' + error);});},songsToCommon (items) {let vm = this;this.commonSongs = items.map(function (item) {return {'id': item.id,'name': item.name,'singer': vm.getAuthorList(item.ar),'albumPic': item.al.picUrl,'location': '','album': item.al.id};});},getAuthorList(authorInfo) {return authorInfo.map(function (item) {return item.name;}).toString();}},computed: {playListImage() {return '' || (this.playlist.picUrl);},creatorImage() {return '' || this.creator.avatarUrl;}},components: {XHeader,vPlayAll,vSingleCard,vPlayListDetail}};
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>@import "playlists.styl";
</style>

本文学习自这位非常美丽的小姐姐,表白你哇

转载于:https://www.cnblogs.com/smart-girl/p/10817227.html

cloud-music相关推荐

  1. Alibaba Cloud Linux 2.1903 LTS 64位服务器yum源下载404,Alibaba Cloud Linux 2实例中使用docker-ce、epel等YUM源安装软件失败

    [Alibaba Cloud Linux 2.1903 LTS 64位]服务器yum源下载404 failure: repodata/repomd.xml from docker-ce-stable: ...

  2. Spring cloud 微服务docker容器化最佳实践

    Spring cloud 是当下最炙手可热的微服务套件,我们将介绍如何整合Docker容器达到高效快捷的构建发布 采用了dockerfile-maven-plugin插件发布镜像到远程docker主机 ...

  3. 激光雷达数据到云cloud

    激光雷达数据到云cloud 在美国地质调查局的3D提升计划(3DEP)被激发到一个新的方式可用性宣布从3DEP仓库的访问和处理激光雷达点云数据. 3DEP一直在美国使用光检测和测距(激光)技术获取三维 ...

  4. Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现

    自Spring Cloud Alibaba发布第一个Release以来,就备受国内开发者的高度关注.虽然Spring Cloud Alibaba还没能纳入Spring Cloud的主版本管理中,但是凭 ...

  5. Spring Cloud下微服务权限方案

    背景 从传统的单体应用转型Spring Cloud的朋友都在问我,Spring Cloud下的微服务权限怎么管?怎么设计比较合理?从大层面讲叫服务权限,往小处拆分,分别为三块:用户认证.用户权限.服务 ...

  6. 玩转Spring Cloud之配置中心(config server config client)

    玩转Spring Cloud之配置中心(config server &config client)  本文内容导航: 一.搭建配置服务中心(config server) 1.1.git方式 1 ...

  7. mysql配置文件没有spring_spring cloud config使用mysql存储配置文件

    spring cloud config使用mysql存储配置文件 1.结构图 2.pom.xml: 4.0.0 com.didispace config-server-db 1.0.0 jar con ...

  8. 1命名规则 sentinel_Spring Cloud Alibaba 整合 Sentinel 流控

    前面我们都是直接通过集成sentinel的依赖,通过编码的方式配置规则等.对于集成到Spring Cloud中阿里已经有了一套开源框架spring-cloud-alibaba,就是用于将一系列的框架成 ...

  9. (曲率系列2:)Paper6:Curvature Estimation of 3D Point Cloud Surfaces Through the Fitting of Normal

    文献下载链接:https://download.csdn.net/download/m0_37957160/12919965 简单说明原理就是:用一个点邻域内点的法向量计算该点的法曲率,根据欧拉公式得 ...

  10. Paper2:Fast 3D Line Segment Detection From Unorganized Point Cloud

    文献下载链接:https://download.csdn.net/download/m0_37957160/12543541 摘要: 本文提出了一种非常简单有效的算法,从大规模无序点云中进行3维线段的 ...

最新文章

  1. Tensorflow 可视化 TensorBoard 尝试~
  2. Ghost 系统的过程
  3. JavaFX 8的弹出式编辑器
  4. 给你的执行力马上充值
  5. qpython3绘图_比Excel制图更强大,Python可视化工具Altair入门教程
  6. JQuery安装与下载教程
  7. 老男孩python课后作业_老男孩python基础知识练习题(一)上
  8. 关于使用Git pull出现冲突“error: Your local changes to the following files would be overwritten by merge”解决方案
  9. PS怎么做抽象流彩油画丙烯画效果
  10. Hbase数据管理工具
  11. 自己写Anki插件-单词宝
  12. /” 和 “\” 有什么区别
  13. 2023年开网店还能赚钱吗?去哪里找货源?
  14. Win10配置adb环境
  15. Ps Camera Raw 打开图像错位花屏原因- PC 上的独立显卡背锅
  16. css下拉菜单汇总案例
  17. Typora ——一款Markdown编辑器入门教程
  18. 按键精灵简单的限时找图并点击
  19. 第十八届中日韩三国IT局长OSS会议暨东北亚开源软件推进论坛在韩国首尔成功举办...
  20. html5 css3实现字幕滚动的效果

热门文章

  1. C/C++研发实习生要求
  2. 【板栗糖GIS】arcmap—如何防止数据路径失效出现红色感叹号
  3. 无人机激光雷达系统在森林资源调查中的应用
  4. SPSS在房地产业中的应用
  5. 怎么设置谷歌浏览器默认以无痕浏览方式打开
  6. 2020年牛客网校招编程笔试题相关问题
  7. action mailbox
  8. 【论文写作】图像分割学术论文中常用词汇记录
  9. 关于WIN7总是突然间Aero出错以及显卡满载问题
  10. request到ATA cmd的转换过程