├── .browserslistrc ├── .env.dev ├── .env.prod ├── public ├── favicon.ico ├── format.ico └── index.html ├── src ├── assets │ ├── mv.png │ ├── aside.png │ ├── center.png │ ├── format.png │ ├── needle.png │ ├── sub-0.png │ ├── sub-1.png │ ├── sub-2.png │ ├── sub-3.png │ ├── sub-4.png │ ├── top50.png │ ├── topbar.png │ ├── biaozhun.png │ ├── big_aside.png │ ├── default.jpg │ ├── default.png │ ├── history.png │ ├── iconall.png │ ├── loading.gif │ ├── playbar.png │ ├── statbar.png │ ├── vipmusic.png │ ├── footer_bar.png │ ├── loginPhone.png │ ├── other_login.png │ ├── default_album.jpg │ └── default_head.jpg ├── views │ ├── home │ │ ├── main │ │ │ ├── childComponents │ │ │ │ ├── findMusicWrap │ │ │ │ │ ├── dj │ │ │ │ │ │ └── DjMain.vue │ │ │ │ │ ├── artist │ │ │ │ │ │ └── childComponents │ │ │ │ │ │ │ ├── SimilarityArtist.vue │ │ │ │ │ │ │ └── ArtistDesc.vue │ │ │ │ │ ├── newSonglist │ │ │ │ │ │ └── childComponents │ │ │ │ │ │ │ ├── AlbumInfo.vue │ │ │ │ │ │ │ └── TopAlbumDetail.vue │ │ │ │ │ ├── songlist │ │ │ │ │ │ └── childComponents │ │ │ │ │ │ │ ├── AllSongListSub.vue │ │ │ │ │ │ │ └── SongListHead.vue │ │ │ │ │ ├── personalization │ │ │ │ │ │ └── childComponents │ │ │ │ │ │ │ └── PrivateNewSongDetail.vue │ │ │ │ │ ├── FindMusicMain.vue │ │ │ │ │ └── rankSonglist │ │ │ │ │ │ ├── childComponents │ │ │ │ │ │ └── RankSonglistDetail.vue │ │ │ │ │ │ └── RankSonglistMain.vue │ │ │ │ ├── songListWrap │ │ │ │ │ ├── PlayAllBtn.vue │ │ │ │ │ └── ShareBtn.vue │ │ │ │ ├── subscribersWrap │ │ │ │ │ ├── SubscribersItem.vue │ │ │ │ │ └── SubscribersDetail.vue │ │ │ │ ├── CountryCodeWrap.vue │ │ │ │ └── Mine.vue │ │ │ └── MusicMain.vue │ │ └── aside │ │ │ ├── AsideItem.vue │ │ │ └── MusicAside.vue │ └── head │ │ └── childComponents │ │ └── DirectionNav.vue ├── util │ ├── NumberTransfrom.js │ └── DateUtil.js ├── icons │ ├── index.js │ └── svg │ │ ├── add.svg │ │ ├── add-fff.svg │ │ ├── play1.svg │ │ ├── arrow-down-filling.svg │ │ ├── arrow-down-filling-999.svg │ │ ├── bofang.svg │ │ ├── arrow-left.svg │ │ ├── arrow-right.svg │ │ ├── complate.svg │ │ ├── close.svg │ │ ├── sex_man.svg │ │ ├── xiazai2.svg │ │ ├── huifu.svg │ │ ├── qu.svg │ │ ├── search.svg │ │ ├── log-out.svg │ │ ├── play_cir.svg │ │ ├── ver-code.svg │ │ ├── huiyuan.svg │ │ ├── prompt.svg │ │ ├── person.svg │ │ ├── user1.svg │ │ ├── emoji.svg │ │ ├── msg-err.svg │ │ ├── playall.svg │ │ ├── fenxiang.svg │ │ ├── headlike.svg │ │ ├── zan-red.svg │ │ ├── user.svg │ │ ├── yunpan.svg │ │ ├── shoucangjia.svg │ │ ├── share.svg │ │ ├── mic.svg │ │ ├── headnolike.svg │ │ ├── song_vip.svg │ │ ├── bendimusic.svg │ │ ├── sign.svg │ │ ├── gereninfo.svg │ │ ├── xiazai.svg │ │ ├── clothes.svg │ │ ├── like.svg │ │ ├── shejiao.svg │ │ ├── download.svg │ │ ├── sex_male.svg │ │ ├── letter.svg │ │ ├── wangguan.svg │ │ ├── huati.svg │ │ ├── song_shiting.svg │ │ ├── shoucang.svg │ │ ├── zan.svg │ │ ├── telephone.svg │ │ ├── shopping.svg │ │ ├── dengji.svg │ │ ├── loading.svg │ │ ├── rili.svg │ │ ├── at.svg │ │ ├── diantai.svg │ │ ├── hot.svg │ │ ├── song_mv.svg │ │ ├── xindong.svg │ │ ├── song_sq.svg │ │ └── setting.svg ├── store │ ├── modules │ │ ├── country.js │ │ └── song.js │ ├── index.js │ ├── getters.js │ └── localStorage │ │ └── logcalStorage.js ├── App.vue ├── mixin │ └── loadingMixin.js ├── components │ ├── message │ │ ├── index.js │ │ └── Message.vue │ ├── svgIcon │ │ └── index.vue │ ├── loading │ │ ├── loading.vue │ │ └── index.js │ ├── swiper │ │ └── icon.css │ ├── layout │ │ └── LayOut.vue │ ├── playList │ │ └── PlayListWrap.vue │ └── song │ │ └── childComponents │ │ └── LyricWrap.vue ├── style │ ├── index.css │ └── base.css ├── network │ └── request.js ├── main.js ├── background.js └── router │ └── index.js ├── .gitignore ├── babel.config.js ├── package.json ├── README.md └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.env.dev: -------------------------------------------------------------------------------- 1 | NODE_ENV = 'development' 2 | VUE_APP_API_URL = '/api' -------------------------------------------------------------------------------- /.env.prod: -------------------------------------------------------------------------------- 1 | NODE_ENV = 'production' 2 | VUE_APP_API_URL = 'http://123.207.32.32:9001/' -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/format.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/public/format.ico -------------------------------------------------------------------------------- /src/assets/mv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/mv.png -------------------------------------------------------------------------------- /src/assets/aside.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/aside.png -------------------------------------------------------------------------------- /src/assets/center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/center.png -------------------------------------------------------------------------------- /src/assets/format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/format.png -------------------------------------------------------------------------------- /src/assets/needle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/needle.png -------------------------------------------------------------------------------- /src/assets/sub-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/sub-0.png -------------------------------------------------------------------------------- /src/assets/sub-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/sub-1.png -------------------------------------------------------------------------------- /src/assets/sub-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/sub-2.png -------------------------------------------------------------------------------- /src/assets/sub-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/sub-3.png -------------------------------------------------------------------------------- /src/assets/sub-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/sub-4.png -------------------------------------------------------------------------------- /src/assets/top50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/top50.png -------------------------------------------------------------------------------- /src/assets/topbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/topbar.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | #Electron-builder output 4 | /dist_electron 5 | .VSCodeCounter 6 | dist -------------------------------------------------------------------------------- /src/assets/biaozhun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/biaozhun.png -------------------------------------------------------------------------------- /src/assets/big_aside.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/big_aside.png -------------------------------------------------------------------------------- /src/assets/default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/default.jpg -------------------------------------------------------------------------------- /src/assets/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/default.png -------------------------------------------------------------------------------- /src/assets/history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/history.png -------------------------------------------------------------------------------- /src/assets/iconall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/iconall.png -------------------------------------------------------------------------------- /src/assets/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/loading.gif -------------------------------------------------------------------------------- /src/assets/playbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/playbar.png -------------------------------------------------------------------------------- /src/assets/statbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/statbar.png -------------------------------------------------------------------------------- /src/assets/vipmusic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/vipmusic.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/footer_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/footer_bar.png -------------------------------------------------------------------------------- /src/assets/loginPhone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/loginPhone.png -------------------------------------------------------------------------------- /src/assets/other_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/other_login.png -------------------------------------------------------------------------------- /src/assets/default_album.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/default_album.jpg -------------------------------------------------------------------------------- /src/assets/default_head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liulei0114/MUSIC-PC/HEAD/src/assets/default_head.jpg -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/dj/DjMain.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /src/util/NumberTransfrom.js: -------------------------------------------------------------------------------- 1 | export function number2wan(num) { 2 | if (num === null) return num 3 | if (typeof num !== 'number') { 4 | num = Number(num) 5 | } 6 | if (num >= 100000) { 7 | return ~~(num / 10000) + "万" 8 | } 9 | return num 10 | } -------------------------------------------------------------------------------- /src/icons/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import SvgIcon from '@/components/svgIcon'// svg组件 3 | 4 | // register globally 5 | Vue.component('svg-icon', SvgIcon) 6 | 7 | const requireAll = requireContext => requireContext.keys().map(requireContext) 8 | const req = require.context('./svg', false, /\.svg$/) 9 | requireAll(req) 10 | -------------------------------------------------------------------------------- /src/store/modules/country.js: -------------------------------------------------------------------------------- 1 | 2 | const countryModule = { 3 | namespaced: true, 4 | state: { 5 | countryList: [] 6 | }, 7 | mutations: { 8 | SET_COUNTRY_LIST(state, data) { 9 | state.countryList = data 10 | }, 11 | }, 12 | actions: { 13 | 14 | } 15 | 16 | 17 | } 18 | 19 | export default countryModule -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vuex from 'vuex' 2 | import Vue from 'vue' 3 | 4 | import loginModule from './modules/login' 5 | import countryModule from './modules/country' 6 | import songModule from './modules/song' 7 | import getters from './getters' 8 | 9 | Vue.use(Vuex) 10 | 11 | 12 | const store = new Vuex.Store({ 13 | modules: { 14 | loginModule, 15 | countryModule, 16 | songModule 17 | }, 18 | getters 19 | }) 20 | 21 | 22 | export default store -------------------------------------------------------------------------------- /src/icons/svg/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/add-fff.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/play1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/home/main/MusicMain.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | -------------------------------------------------------------------------------- /src/mixin/loadingMixin.js: -------------------------------------------------------------------------------- 1 | import { Loading } from "element-ui"; 2 | 3 | export const loadingMixin = { 4 | data() { 5 | return { 6 | loadingOptions: { 7 | target: "#MusicMain", 8 | text: "拼命加载中", 9 | background: "rgba(0, 0, 0, 0.7)", 10 | spinner: "el-icon-loading", 11 | }, 12 | loadingInstance: null, 13 | } 14 | }, 15 | methods: { 16 | initLoading() { 17 | this.loadingInstance = Loading.service(this.loadingOptions); 18 | }, 19 | endLoading() { 20 | this.$nextTick(() => { 21 | this.loadingInstance.close(); 22 | }); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/components/message/index.js: -------------------------------------------------------------------------------- 1 | import Message from './Message.vue' 2 | 3 | const globalMessage = { 4 | install: function (Vue) { 5 | // 获取组件构造器 6 | let messageContru = Vue.extend(Message) 7 | 8 | // 根据构造器创建组件实例 9 | let messageInstance = new messageContru(); 10 | 11 | // 挂载在页面上 12 | messageInstance.$mount(document.createElement('div')) 13 | 14 | // 因为app.vue 下是routerview 不加Vue.nextTick 会被覆盖掉,当然往body中插入不需要加的 15 | Vue.nextTick(() => { 16 | document.getElementById('app').appendChild(messageInstance.$el) 17 | }) 18 | //追加在页面上 19 | 20 | //设置为全局变量 21 | Vue.prototype.$gMessage = messageInstance 22 | 23 | } 24 | } 25 | 26 | export default globalMessage -------------------------------------------------------------------------------- /src/icons/svg/arrow-down-filling.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/style/index.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | h1 { 4 | margin: 0; 5 | } 6 | 7 | .flexL { 8 | display: flex; 9 | justify-content: left; 10 | align-items: center; 11 | } 12 | 13 | .textOverflow { 14 | white-space: nowrap; 15 | overflow: hidden; 16 | /* text-overflow: hidden; */ 17 | } 18 | 19 | .textOverflowElli { 20 | overflow: hidden; 21 | text-overflow: ellipsis; 22 | white-space: nowrap; 23 | } 24 | 25 | /* 全局变量 */ 26 | :root { 27 | --headBgColor: #ec4141; 28 | --footerBgColor: #f6f6f8; 29 | --mainBgColor: #ffffff; 30 | --asideBgColor: #ffffff; 31 | } 32 | 33 | 34 | @keyframes rotate{ 35 | from{ 36 | transform: rotate(0deg); 37 | } 38 | to{ 39 | transform: rotate(360deg); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/icons/svg/arrow-down-filling-999.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/bofang.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/arrow-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/arrow-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/complate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/sex_man.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/svgIcon/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 33 | 34 | 43 | -------------------------------------------------------------------------------- /src/icons/svg/xiazai2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 网易云音乐,年轻人的音乐 11 | 12 | 13 | 14 | 15 | 19 | 22 |
23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/network/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | 4 | // 创建axios实例 5 | const service = axios.create({ 6 | baseURL: process.env.VUE_APP_API_URL, // api的base_url 7 | // baseURL: "http://localhost:3000", 8 | timeout: 15000 // 请求超时时间 9 | }) 10 | 11 | // request拦截器 12 | service.interceptors.request.use(config => { 13 | return config 14 | }, error => { 15 | console.log(error) // for debug 16 | Promise.reject('error') 17 | }) 18 | 19 | // respone拦截器 20 | service.interceptors.response.use( 21 | response => { 22 | const res = response.data 23 | if (res.code !== 200) { // 返回错误 24 | return Promise.reject(res) 25 | } else { // 成功 26 | return Promise.resolve(res) 27 | } 28 | }, 29 | error => { //非2XX 30 | if (error && error.response && error.response.status) { 31 | return Promise.reject(error.response.data) 32 | } 33 | } 34 | ) 35 | 36 | export default service -------------------------------------------------------------------------------- /src/icons/svg/huifu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/qu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/log-out.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/play_cir.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | loginDialogStatus(state) { return state.loginModule.loginDialogStatus }, 3 | countryList(state) { return state.countryModule.countryList }, 4 | userProfile(state) { return state.loginModule.userProfile }, 5 | asideMenu(state) { return state.loginModule.asideMenu }, 6 | songListDetail(state) { return state.songModule.songListDetail }, 7 | menu(state) { return state.loginModule.menu }, 8 | likeMusicList(state) { return state.songModule.likeMusicMap }, 9 | historyMusicList(state) { return state.songModule.historyMusicList }, 10 | playMusicList(state) { return state.songModule.playMusicList }, 11 | playListDrawerStatus(state) { return state.songModule.playListDrawerStatus }, 12 | curPlaySongIndex(state) { return state.songModule.curPlaySongIndex }, 13 | curPlaySongId(state) { return state.songModule.curPlaySongId }, 14 | songMainStatus(state) { return state.songModule.songMainStatus }, 15 | songPlayStatus(state) { return state.songModule.songPlayStatus } 16 | } 17 | export default getters 18 | -------------------------------------------------------------------------------- /src/views/head/childComponents/DirectionNav.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 29 | 30 | -------------------------------------------------------------------------------- /src/icons/svg/ver-code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/huiyuan.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/prompt.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/person.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/user1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/emoji.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/msg-err.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/playall.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/fenxiang.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/headlike.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/zan-red.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/yunpan.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/shoucangjia.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/share.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/style/base.css: -------------------------------------------------------------------------------- 1 | /*清除元素默认的内外边距 */ 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | box-sizing: border-box; 6 | 7 | } 8 | 9 | /*让所有斜体 不倾斜*/ 10 | em, 11 | i { 12 | font-style: normal; 13 | } 14 | 15 | /*去掉列表前面的小点*/ 16 | li { 17 | list-style: none; 18 | } 19 | 20 | /*图片没有边框 去掉图片底侧的空白缝隙*/ 21 | img { 22 | border: 0; 23 | /*ie6*/ 24 | vertical-align: middle; 25 | } 26 | 27 | /*让button 按钮 变成小手*/ 28 | button { 29 | cursor: pointer; 30 | } 31 | 32 | /*取消链接的下划线*/ 33 | a { 34 | color: #666; 35 | text-decoration: none; 36 | } 37 | 38 | a:hover { 39 | color: #e33333; 40 | } 41 | 42 | button, 43 | input { 44 | font-family: 'Microsoft YaHei', 'Heiti SC', tahoma, arial, 'Hiragino Sans GB', \\5B8B\4F53, sans-serif; 45 | /*取消轮廓线 蓝色的*/ 46 | outline: none; 47 | } 48 | 49 | body { 50 | background-color: #fff; 51 | font: 16px 'Microsoft YaHei', 'Heiti SC', tahoma, arial, 'Hiragino Sans GB', \\5B8B\4F53, sans-serif; 52 | color: #666; 53 | overflow: scroll; 54 | overflow-x: hidden; 55 | overflow-y: hidden; 56 | } 57 | 58 | .hide, 59 | .none { 60 | display: none; 61 | } 62 | 63 | /*清除浮动*/ 64 | .clearfix:after { 65 | visibility: hidden; 66 | clear: both; 67 | display: block; 68 | content: "."; 69 | height: 0 70 | } 71 | 72 | .clearfix { 73 | *zoom: 1 74 | } 75 | 76 | 77 | .font-extra-small { 78 | font-size: 13px; 79 | color: #606266; 80 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "music-pc", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve --mode dev", 7 | "build:prod": "vue-cli-service build --mode prod", 8 | "electron:build": "vue-cli-service electron:build", 9 | "electron:serve": "vue-cli-service --mode dev electron:serve", 10 | "postinstall": "electron-builder install-app-deps", 11 | "postuninstall": "electron-builder install-app-deps" 12 | }, 13 | "main": "background.js", 14 | "dependencies": { 15 | "@liripeng/vue-audio-player": "^1.2.4", 16 | "axios": "^0.21.0", 17 | "core-js": "^3.6.5", 18 | "element-ui": "^2.14.1", 19 | "js-md5": "^0.7.3", 20 | "lodash": "^4.17.20", 21 | "moment": "^2.29.1", 22 | "normalize.css": "^8.0.1", 23 | "swiper": "^4.5.0", 24 | "vue": "^2.6.11", 25 | "vue-flag-icon": "^1.0.0", 26 | "vue-happy-scroll": "^2.1.1", 27 | "vue-lazyload": "^1.3.3", 28 | "vue-router": "^3.4.9", 29 | "vuex": "^3.6.0" 30 | }, 31 | "devDependencies": { 32 | "@vue/cli-plugin-babel": "~4.5.0", 33 | "@vue/cli-service": "~4.5.0", 34 | "electron": "^9.0.0", 35 | "less": "3.12.2", 36 | "less-loader": "^4.1.0", 37 | "svg-sprite-loader": "^5.1.1", 38 | "vue-cli-plugin-electron-builder": "~2.0.0-rc.5", 39 | "vue-template-compiler": "^2.6.11" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/icons/svg/headnolike.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-cli 2 | 3 | ## 安装依赖 4 | ``` 5 | npm install 6 | 项目使用electron,npm下载慢,有可能部分人安装失败可以把package.json中的electron相关依赖注释掉,8-11行和34行。 7 | 启动前先把后台node服务器启动!!!! 8 | 前端端口默认9999,后台服务3000 9 | ``` 10 | 11 | ### 运行项目 12 | ``` 13 | npm run serve 14 | ``` 15 | 16 | ### 后台使用Binaryify大佬提供的node服务,没有线上地址,自行下载下来启动 17 | ``` 18 | github [Configuration Reference](https://github.com/Binaryify/NeteaseCloudMusicApi.git). 19 | ``` 20 | 21 | ### 效果图 22 | 23 | ![1](https://user-images.githubusercontent.com/29829316/109665676-650d6c00-7ba9-11eb-9e2e-c453a7f99a26.png) 24 | ![2](https://user-images.githubusercontent.com/29829316/109665712-6b034d00-7ba9-11eb-8a50-0f8f40ed6f95.png) 25 | ![3](https://user-images.githubusercontent.com/29829316/109665720-6d65a700-7ba9-11eb-8c0d-c4f651ecf061.png) 26 | ![4](https://user-images.githubusercontent.com/29829316/109665724-6f2f6a80-7ba9-11eb-9314-0bf9bade40ad.png) 27 | ![5](https://user-images.githubusercontent.com/29829316/109665731-70609780-7ba9-11eb-934c-c81ba9ba1991.png) 28 | ![6](https://user-images.githubusercontent.com/29829316/109665737-72c2f180-7ba9-11eb-9c17-0f0df826cf9c.png) 29 | ![7](https://user-images.githubusercontent.com/29829316/109665745-73f41e80-7ba9-11eb-8d52-6a73c24b85de.png) 30 | ![8](https://user-images.githubusercontent.com/29829316/109665751-75254b80-7ba9-11eb-93f2-46303df6ca23.png) 31 | ![10](https://user-images.githubusercontent.com/29829316/109665767-7b1b2c80-7ba9-11eb-9a88-2260fec0ceb1.png) 32 | 33 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/songListWrap/PlayAllBtn.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 20 | 21 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import ElementUI from 'element-ui'; 4 | import 'element-ui/lib/theme-chalk/index.css'; 5 | import router from '@/router' 6 | import store from '@/store' 7 | import _ from 'lodash' 8 | import md5 from 'js-md5'; 9 | import HappyScroll from 'vue-happy-scroll' 10 | //1.导入 monment 文件 11 | import moment from 'moment' 12 | import VueLazyLoad from 'vue-lazyload' 13 | 14 | import AudioPlayer from '@liripeng/vue-audio-player' 15 | 16 | 17 | // * 注册自定义全局组件 18 | import gMessage from '@/components/message' 19 | 20 | // 通用css normal.css 21 | import 'normalize.css/normalize.css' 22 | import '@/style/index.css' 23 | // 引入 24 | import '@/icons/index' 25 | // 引入css 26 | import 'vue-happy-scroll/docs/happy-scroll.css' 27 | 28 | //播放插件css 29 | import '@liripeng/vue-audio-player/lib/vue-audio-player.css' 30 | 31 | 32 | import gLoading from '@/components/loading' 33 | 34 | Vue.prototype._ = _ 35 | Vue.config.productionTip = false 36 | Vue.prototype.$bus = new Vue() 37 | Vue.prototype.$md5 = md5; 38 | Vue.prototype.$moment = moment; 39 | 40 | Vue.use(gMessage) 41 | Vue.use(ElementUI) 42 | Vue.use(HappyScroll) 43 | Vue.use(gLoading) 44 | Vue.use(AudioPlayer) 45 | 46 | 47 | //3.调用API进行汉化 48 | moment.locale('zh-cn'); 49 | 50 | 51 | Vue.use(VueLazyLoad, { 52 | loading: require('@/assets/default.jpg') 53 | }) 54 | 55 | new Vue({ 56 | router, 57 | store, 58 | render: h => h(App), 59 | }).$mount('#app') 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/icons/svg/song_vip.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/bendimusic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/store/localStorage/logcalStorage.js: -------------------------------------------------------------------------------- 1 | 2 | export function getItem(name) { 3 | let a = localStorage.getItem(name) 4 | return a ? JSON.parse(a) : null; 5 | } 6 | 7 | export function getLocalProfile() { 8 | let profile = localStorage.getItem('profile') 9 | return profile ? JSON.parse(profile) : null; 10 | } 11 | 12 | //存入localstore 13 | export function setLocalProfile(loginPhoneResult) { 14 | let { 15 | city, 16 | province, 17 | userId, 18 | nickname, 19 | avatarUrl, 20 | avatarImgIdStr, 21 | backgroundUrl, 22 | backgroundImgIdStr, 23 | vipType, 24 | signature, 25 | birthday, 26 | gender, 27 | playlistBeSubscribedCount, // 播放列表被订阅数量 28 | playlistCount, //播放列表数量 29 | followeds, // 粉丝数 30 | follows, //关注数 31 | eventCount, // 动态数 32 | } = loginPhoneResult.profile; 33 | let profile = { 34 | city, 35 | province, 36 | userId, 37 | nickname, 38 | avatarUrl, 39 | avatarImgIdStr, 40 | backgroundUrl, 41 | backgroundImgIdStr, 42 | vipType, 43 | signature, 44 | birthday, 45 | gender, 46 | playlistBeSubscribedCount, 47 | playlistCount, 48 | followeds, 49 | follows, 50 | eventCount, 51 | }; 52 | localStorage.setItem("profile", JSON.stringify(profile)); 53 | return profile 54 | } 55 | 56 | export function removeLocalProfile() { 57 | localStorage.removeItem('profile') 58 | } 59 | 60 | export function setLocalAsideMenu(playListResult) { 61 | localStorage.setItem('asideMenu', JSON.stringify(playListResult)) 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/icons/svg/sign.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/gereninfo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/xiazai.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/clothes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/like.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/shejiao.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/artist/childComponents/SimilarityArtist.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 52 | 53 | -------------------------------------------------------------------------------- /src/icons/svg/download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/artist/childComponents/ArtistDesc.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 48 | 49 | -------------------------------------------------------------------------------- /src/icons/svg/sex_male.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/letter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/wangguan.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/message/Message.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 55 | 56 | -------------------------------------------------------------------------------- /src/icons/svg/huati.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/song_shiting.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/shoucang.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/zan.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/telephone.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/shopping.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/loading/loading.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 47 | 48 | -------------------------------------------------------------------------------- /src/components/swiper/icon.css: -------------------------------------------------------------------------------- 1 | @font-face {font-family: "iconfont"; 2 | src:url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAVAAAsAAAAAB9QAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kgRY21hcAAAAYAAAABmAAABnM7+amhnbHlmAAAB6AAAAU4AAAGETZmiVGhlYWQAAAM4AAAALwAAADYRVnI7aGhlYQAAA2gAAAAcAAAAJAfeA4VobXR4AAADhAAAABAAAAAQD+kAAGxvY2EAAAOUAAAACgAAAAoBOACcbWF4cAAAA6AAAAAfAAAAIAETAF1uYW1lAAADwAAAAUUAAAJtPlT+fXBvc3QAAAUIAAAANQAAAFLIdFLIeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/sU4gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDxTZW7438AQw9zA0AAUZgTJAQAmwQyTeJzFkMENwCAIRT9iG9N0C+Otx6YD9dQRnJg1LKAXJ/CbJ/BDxABgA8DKpUSAPhBMr7rkPuNwP+LROukJGqtkKa1NmYm8I3kW7GXasUy0bvSs0+97VLbvOtAvSu7YXqV0wD+5HxCTAAB4nHXPvU7CUADF8Xtu7S1FKHJbetsCtlDhYsAmYoUQIh+Ji8bBxMnR0UEHFxYHFhMHYtzcjYkvweDGcxB9jiohrJ6c+Zf8iUrI71KZKw4xSYMcklNySQhYE1WDllGRcUSbKFTUgrAMRYayooXVSDmBqDLLbnfiumAay8HALo4q7Y6MqMRxPKB9tO0y4Ba9K14rceUVaUfuPiXn9B0FPyzlBgfJWWtotQMzNclw7nI+SzFVTVG6lTNwJ2xd1dMs+VBzXmHu71MfGVd6F9fZoMhvnuP7ck3owHQKsxgYn8O8l1/90bNN7mo72ZTjZcM9C5OfbcfMlOvfZDWsWr/oUhkRTohqiwFiqWPVIJkGZgl6a5X8hkgW6ImGX7KSFyFaJmhzLNBHX4ybFGYyc0bOxlKCjcW0CHFXRz3udG0B29LwtrbQSxZrCw//Wn95oDyyAAB4nGNgZGBgAOIN11q+xfPbfGXgZmEAgevS0+UR9P8DLAzMDkAuBwMTSBQAOiQKEQB4nGNgZGBgbvjfwBDDwgACQJKRARWwAABHCgJtBAAAAAPpAAAEAAAABAAAAAAAAAAAdgCcAMIAAHicY2BkYGBgYQhkYGUAASYg5gJCBob/YD4DABESAXEAeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicY2BigAAuBuyAhZGJkZmRhZGVgbFCIDM5Py8eiEoyUuNzUtNKBJEFijLTM0oYGAAk/A5OAAAA') format('woff'); 3 | } 4 | 5 | .iconfont { 6 | font-family:"iconfont" !important; 7 | font-size:16px; 8 | font-style:normal; 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | 13 | .icon-left:before { content: "\e623"; } 14 | 15 | .icon-right:before { content: "\e625"; } -------------------------------------------------------------------------------- /src/views/home/main/childComponents/songListWrap/ShareBtn.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 62 | 63 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/subscribersWrap/SubscribersItem.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 40 | 41 | -------------------------------------------------------------------------------- /src/icons/svg/dengji.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/rili.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/at.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/diantai.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/hot.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/home/aside/AsideItem.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 44 | 45 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | const path = require('path') 3 | 4 | module.exports = { 5 | // 部署应用包时的基本 URL,用法和 webpack 本身的 output.publicPath 一致 6 | publicPath: './', 7 | // 输出文件目录 8 | outputDir: 'dist', 9 | //静态资源目录(js、css、img、fonts),相对outputDir的目录(默认'') 10 | assetsDir: '', 11 | // 以多页模式构建应用程序。 12 | pages: undefined, 13 | //指定生成index.html的输出路径(相对outputDir)也可以是绝对路径 14 | indexPath: 'index.html', 15 | // eslint-loader 是否在保存的时候检查 16 | lintOnSave: false, 17 | // 是否使用包含运行时编译器的 Vue 构建版本 18 | runtimeCompiler: false, 19 | // 生产环境是否生成 sourceMap 文件 20 | productionSourceMap: false, 21 | // 生成的 HTML 中的 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/util/DateUtil.js: -------------------------------------------------------------------------------- 1 | 2 | export function _YMDhms() { 3 | let setZero = (num) => { 4 | return num < 10 ? '0' + num : num; 5 | } 6 | let str = '' 7 | let date = new Date() 8 | let Y = date.getFullYear() 9 | let M = setZero(date.getMonth() + 1) 10 | let D = setZero(date.getDate()) 11 | let h = setZero(date.getHours()) 12 | let m = setZero(date.getMinutes()) 13 | let s = setZero(date.getSeconds()) 14 | str = Y + '-' + M + '-' + D + ' ' + h + ':' + m + ':' + s; 15 | return str 16 | } 17 | 18 | export function _YMD(strDate = '') { 19 | let setZero = (num) => { 20 | return num < 10 ? '0' + num : num; 21 | } 22 | let str = '' 23 | let date = strDate ? new Date(strDate) : new Date(); 24 | let Y = date.getFullYear() 25 | let M = setZero(date.getMonth() + 1) 26 | let D = setZero(date.getDate()) 27 | str = Y + '-' + M + '-' + D 28 | return str 29 | } 30 | 31 | 32 | // date.js 33 | export function formatDate(date, fmt) { 34 | if (/(y+)/.test(fmt)) { 35 | fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); 36 | } 37 | let o = { 38 | 'M+': date.getMonth() + 1, 39 | 'd+': date.getDate(), 40 | 'h+': date.getHours(), 41 | 'm+': date.getMinutes(), 42 | 's+': date.getSeconds() 43 | }; 44 | for (let k in o) { 45 | if (new RegExp(`(${k})`).test(fmt)) { 46 | let str = o[k] + ''; 47 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str)); 48 | } 49 | } 50 | return fmt; 51 | } 52 | 53 | function padLeftZero(str) { 54 | return ('00' + str).substr(str.length); 55 | } 56 | 57 | export function str2Date(dateStr, separator) { 58 | if (!separator) { 59 | separator = "-"; 60 | } 61 | let dateArr = dateStr.split(separator); 62 | let year = parseInt(dateArr[0]); 63 | let month; 64 | //处理月份为04这样的情况 65 | if (dateArr[1].indexOf("0") == 0) { 66 | month = parseInt(dateArr[1].substring(1)); 67 | } else { 68 | month = parseInt(dateArr[1]); 69 | } 70 | let day = parseInt(dateArr[2]); 71 | let date = new Date(year, month - 1, day); 72 | return date; 73 | } 74 | 75 | export function millisecondToDate(msd) { 76 | var time = parseFloat(msd) / 1000; 77 | if (null != time && "" != time) { 78 | if (time > 60 && time < 60 * 60) { 79 | time = leftzZero(parseInt(time / 60.0)) + ":" + leftzZero(parseInt((parseFloat(time / 60.0) - 80 | parseInt(time / 60.0)) * 60)); 81 | } 82 | else if (time >= 60 * 60 && time < 60 * 60 * 24) { 83 | time = leftzZero(parseInt(time / 3600.0)) + ":" + leftzZero(parseInt((parseFloat(time / 3600.0) - 84 | parseInt(time / 3600.0)) * 60)) + ":" + 85 | leftzZero(parseInt((parseFloat((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60) - 86 | parseInt((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60)) * 60)); 87 | } 88 | else { 89 | time = leftzZero(parseInt(time)) + "秒"; 90 | } 91 | } 92 | return time; 93 | 94 | function leftzZero(time) { 95 | time = time.toString(); 96 | return time.length === 1 ? `0${time}` : time 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/icons/svg/song_sq.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/CountryCodeWrap.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 69 | 70 | 115 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/subscribersWrap/SubscribersDetail.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 | 85 | 86 | -------------------------------------------------------------------------------- /src/store/modules/song.js: -------------------------------------------------------------------------------- 1 | import { fetchSongListDetailApi, fetchLikeListAPI, fetchHistoryMusicListAPI, fetchSongDetailApi } from "@/network/api/musicApi.js"; 2 | import { SongListDeatil, Track } from '@/common/pojo.js' 3 | import _ from 'lodash' 4 | 5 | 6 | 7 | const songModule = { 8 | namespaced: true, 9 | state: { 10 | songListDetail: [], 11 | likeMusicMap: null, 12 | historyMusicList: null, 13 | playMusicList: [], 14 | playListDrawerStatus: false, 15 | curPlaySongIndex: 0, 16 | curPlaySongId: '', 17 | songMainStatus: false, 18 | songPlayStatus: false 19 | }, 20 | mutations: { 21 | SET_SONG_LIST_DETAIL(state, data) { 22 | state.songListDetail = data 23 | }, 24 | SET_LIKE_MUSIC_MAP(state, data) { 25 | state.likeMusicMap = data 26 | }, 27 | SET_HISTORY_MUSIC_LIST(state, data) { 28 | state.historyMusicList = data 29 | }, 30 | SET_PLAY_MUSIC_LIST(state, data) { 31 | state.playMusicList = data 32 | }, 33 | SET_PLAY_LIST_DRAWER_STATUS(state, data) { 34 | state.playListDrawerStatus = data 35 | }, 36 | SET_CUR_PLAY_SONG_INDEX(state, data) { 37 | state.curPlaySongIndex = data 38 | }, 39 | SET_CUR_PLAY_SONG_ID(state, data) { 40 | state.curPlaySongId = data 41 | }, 42 | SET_SONG_MAIN_STATUS(state, data) { 43 | state.songMainStatus = data 44 | }, 45 | SET_SONG_PLAY_STATUS(state, data) { 46 | state.songPlayStatus = data 47 | } 48 | }, 49 | actions: { 50 | // ? 本地保存歌曲列表信息 51 | async SaveSongListDetail({ state, commit, dispatch, rootGetters }, data) { 52 | let params = new URLSearchParams(); 53 | params.append("id", data.id) 54 | params.append('timestamp', (new Date()).valueOf()) 55 | let songListDetailData = await fetchSongListDetailApi(params); 56 | let songListDetail = new SongListDeatil(songListDetailData.playlist); 57 | return songListDetail; 58 | }, 59 | // ? 保存所有我喜欢的音乐 60 | async SaveLikeMusicList({ state, commit, dispatch, rootGetters }) { 61 | let uid = rootGetters.userProfile.userId; 62 | let result = await fetchLikeListAPI({ 63 | uid, 64 | timestamp: new Date().valueOf(), 65 | }); 66 | let likeMap = {} 67 | result.ids.forEach((e, i) => { 68 | likeMap[e] = true; 69 | }); 70 | commit('SET_LIKE_MUSIC_MAP', likeMap) 71 | }, 72 | // ? 保存用户历史播放记录 73 | async SaveHistoryMusicList({ rootGetters, commit }) { 74 | let uid = rootGetters.userProfile.userId; 75 | let result = await fetchHistoryMusicListAPI({ 76 | uid, 77 | timestamp: new Date().valueOf(), 78 | type: 1 79 | }); 80 | let hisMusicIds = [] 81 | 82 | result.weekData.forEach((e, i) => { 83 | hisMusicIds.push(e.song.id) 84 | }); 85 | let hisMusicList = [] 86 | if (hisMusicIds.length !== 0) { 87 | let songDetail = await fetchSongDetailApi({ ids: hisMusicIds.join(',') }) 88 | songDetail.songs.forEach((e, i) => { 89 | hisMusicList.push(new Track(e, songDetail.privileges[i])); 90 | }) 91 | } 92 | commit('SET_HISTORY_MUSIC_LIST', hisMusicList) 93 | 94 | } 95 | } 96 | 97 | 98 | } 99 | 100 | export default songModule -------------------------------------------------------------------------------- /src/icons/svg/setting.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/songlist/childComponents/AllSongListSub.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 52 | 53 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/songlist/childComponents/SongListHead.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 73 | 74 | -------------------------------------------------------------------------------- /src/components/layout/LayOut.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 73 | -------------------------------------------------------------------------------- /src/views/home/aside/MusicAside.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 102 | 103 | -------------------------------------------------------------------------------- /src/components/playList/PlayListWrap.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 84 | 85 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/personalization/childComponents/PrivateNewSongDetail.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 63 | 64 | -------------------------------------------------------------------------------- /src/background.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import { app, protocol, BrowserWindow, Menu, ipcMain } from 'electron' 4 | import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' 5 | const isDevelopment = process.env.NODE_ENV !== 'production' 6 | const electron = require('electron'); 7 | let ipc = ipcMain 8 | 9 | 10 | // Scheme must be registered before the app is ready 11 | protocol.registerSchemesAsPrivileged([ 12 | { scheme: 'app', privileges: { secure: true, standard: true } } 13 | ]) 14 | 15 | async function createWindow() { 16 | // Create the browser window. 17 | let win = new BrowserWindow({ 18 | width: 1022, 19 | height: 670, 20 | frame: false, 21 | maximizable: false, 22 | resizable: false,//可否缩放 23 | useContentSize: true, 24 | webPreferences: { 25 | // nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, 26 | nodeIntegration: true, 27 | // webSecurity: false 28 | }, 29 | icon: `${__static}/format.ico` 30 | }) 31 | 32 | if (process.env.WEBPACK_DEV_SERVER_URL) { 33 | // Load the url of the dev server if in development mode 34 | await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) 35 | if (!process.env.IS_TEST) win.webContents.openDevTools() 36 | } else { 37 | createProtocol('app') 38 | // Load the index.html when not in development 39 | win.loadURL('app://./index.html') 40 | } 41 | 42 | win.on('close', e => { 43 | e.preventDefault(); //先阻止一下默认行为,不然直接关了,提示框只会闪一下 44 | electron.dialog.showMessageBox({ 45 | 46 | type: 'info', 47 | title: '提示', 48 | message: '确认退出?', 49 | buttons: ['确认', '取消'], //选择按钮,点击确认则下面的idx为0,取消为1 50 | cancelId: 1, //这个的值是如果直接把提示框×掉返回的值,这里设置成和“取消”按钮一样的值,下面的idx也会是1 51 | }).then(idx => { 52 | //注意上面↑是用的then,网上好多是直接把方法做为showMessageBox的第二个参数,我的测试下不成功 53 | if (idx.response == 1) { 54 | console.log('index==1,取消关闭') 55 | e.preventDefault(); 56 | } else { 57 | console.log('index==0,关闭') 58 | win = null 59 | app.exit() 60 | } 61 | }) 62 | }); 63 | ipc.on('window-close', function () { 64 | win.close(); 65 | }) 66 | win.on('closed', () => { 67 | win = null; 68 | }) 69 | 70 | createMenu() 71 | 72 | } 73 | function createMenu() { 74 | // darwin表示macOS,针对macOS的设置 75 | if (process.platform === 'darwin') { 76 | const template = [{ 77 | label: 'App Demo', 78 | // submenu: [ 79 | // {role: 'about'}, 80 | // { 81 | // role: 'quit' 82 | // }] 83 | }] 84 | const menu = Menu.buildFromTemplate(template) 85 | Menu.setApplicationMenu(menu) 86 | } else { 87 | // windows及linux系统 88 | Menu.setApplicationMenu(null) 89 | } 90 | } 91 | 92 | 93 | 94 | // Quit when all windows are closed. 95 | app.on('window-all-closed', () => { 96 | // On macOS it is common for applications and their menu bar 97 | // to stay active until the user quits explicitly with Cmd + Q 98 | if (process.platform !== 'darwin') { 99 | app.quit() 100 | } 101 | }) 102 | 103 | app.on('activate', () => { 104 | // On macOS it's common to re-create a window in the app when the 105 | // dock icon is clicked and there are no other windows open. 106 | if (BrowserWindow.getAllWindows().length === 0) createWindow() 107 | }) 108 | 109 | // This method will be called when Electron has finished 110 | // initialization and is ready to create browser windows. 111 | // Some APIs can only be used after this event occurs. 112 | app.on('ready', async () => { 113 | // if (isDevelopment && !process.env.IS_TEST) { 114 | // // Install Vue Devtools 115 | // try { 116 | // await installExtension(VUEJS_DEVTOOLS) 117 | // } catch (e) { 118 | // console.error('Vue Devtools failed to install:', e.toString()) 119 | // } 120 | // } 121 | createWindow() 122 | }) 123 | 124 | 125 | 126 | // Exit cleanly on request from parent process in development mode. 127 | if (isDevelopment) { 128 | if (process.platform === 'win32') { 129 | process.on('message', (data) => { 130 | if (data === 'graceful-exit') { 131 | app.quit() 132 | } 133 | }) 134 | } else { 135 | process.on('SIGTERM', () => { 136 | app.quit() 137 | }) 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/FindMusicMain.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from "vue-router" 3 | import store from '@/store' 4 | 5 | Vue.use(VueRouter) 6 | 7 | const routes = [ 8 | 9 | { 10 | path: '', 11 | redirect: '/find/music/alization', 12 | }, 13 | { 14 | path: '/find/music', 15 | redirect: '/find/music/alization', 16 | }, 17 | { 18 | path: '/find', 19 | component: () => import('@/components/layout/LayOut'), 20 | children: [ 21 | { 22 | path: 'music', 23 | component: () => import('@/views/home/main/childComponents/findMusicWrap/FindMusicMain'), 24 | children: [ 25 | { 26 | path: 'alization', 27 | component: () => import('@/views/home/main/childComponents/findMusicWrap/personalization/PersonAlizationMain.vue'), 28 | meta: { 29 | index: 1 30 | } 31 | }, 32 | { 33 | path: 'songlist', 34 | component: () => import('@/views/home/main/childComponents/findMusicWrap/songlist/SongListMain.vue'), 35 | meta: { 36 | index: 2 37 | } 38 | }, 39 | { 40 | path: 'dj', 41 | component: () => import('@/views/home/main/childComponents/findMusicWrap/dj/DjMain.vue'), 42 | meta: { 43 | index: 3 44 | } 45 | }, 46 | { 47 | path: 'rank', 48 | component: () => import('@/views/home/main/childComponents/findMusicWrap/rankSonglist/RankSonglistMain.vue'), 49 | meta: { 50 | index: 4 51 | } 52 | }, 53 | { 54 | path: 'artist', 55 | component: () => import('@/views/home/main/childComponents/findMusicWrap/artist/ArtistMain.vue'), 56 | meta: { 57 | index: 5 58 | } 59 | }, 60 | { 61 | path: 'new', 62 | component: () => import('@/views/home/main/childComponents/findMusicWrap/newSonglist/NewSonglistMain.vue'), 63 | meta: { 64 | index: 6 65 | } 66 | }, 67 | ] 68 | } 69 | ] 70 | }, 71 | 72 | { 73 | path: '/personalized', 74 | component: () => import('@/components/layout/LayOut'), 75 | children: [ 76 | // 歌单详情页 77 | { 78 | path: 'songlist/:id', 79 | name: 'PersonalizedSongList', 80 | component: () => import('@/views/home/main/childComponents/songListWrap/SongListWrap.vue'), 81 | }, 82 | // 专辑详情页 83 | { 84 | path: 'album/:id', 85 | name: 'PersonalizedAlbum', 86 | component: () => import('@/views/home/main/childComponents/findMusicWrap/newSonglist/childComponents/AlbumDetail.vue'), 87 | }, 88 | // 歌手详情页 89 | { 90 | path: 'artist/:id', 91 | name: 'PersonalizedArtist', 92 | component: () => import('@/views/home/main/childComponents/findMusicWrap/artist/childComponents/ArtistDetail.vue'), 93 | }, 94 | // 歌曲详情页 95 | { 96 | path: 'song/:id', 97 | name: 'SongMain', 98 | components: { 99 | SongMain: () => import('@/components/song/SongMain.vue'), 100 | } 101 | }, 102 | ] 103 | }, 104 | 105 | ] 106 | const originalPush = VueRouter.prototype.push 107 | VueRouter.prototype.push = function push(location, onResolve, onReject) { 108 | if (onResolve || onReject) 109 | return originalPush.call(this, location, onResolve, onReject) 110 | return originalPush.call(this, location).catch((err) => err) 111 | } 112 | 113 | const router = new VueRouter({ 114 | scrollBehavior: () => ({ y: 0 }), 115 | routes 116 | }) 117 | 118 | router.beforeEach((to, from, next) => { 119 | 120 | if (store.getters.userProfile) { 121 | // ! 有个bug,不影响使用,页面刷新vuex数据清空,加载所有喜欢音乐是异步操作会导致加载两次 122 | // 是否有我喜欢的音乐,没有加载 123 | 124 | if (store.getters.menu) { 125 | next() 126 | } else { 127 | if (!store.getters.likeMusicList) { 128 | // 清空我喜欢的音乐 129 | store.dispatch('songModule/SaveLikeMusicList') 130 | } 131 | if (!store.getters.historyMusicList) { 132 | // 清空我喜欢的音乐 133 | store.dispatch('songModule/SaveHistoryMusicList') 134 | } 135 | store.dispatch('loginModule/AddMenuRouter').then((result) => { 136 | router.addRoutes(result) 137 | next({ ...to, replace: true }) 138 | }) 139 | } 140 | } else { 141 | next() 142 | } 143 | 144 | 145 | }) 146 | 147 | export default router -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/rankSonglist/childComponents/RankSonglistDetail.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 73 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/rankSonglist/RankSonglistMain.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 136 | 137 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/findMusicWrap/newSonglist/childComponents/TopAlbumDetail.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 136 | 137 | -------------------------------------------------------------------------------- /src/components/song/childComponents/LyricWrap.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 160 | 161 | -------------------------------------------------------------------------------- /src/views/home/main/childComponents/Mine.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 148 | 149 | --------------------------------------------------------------------------------