├── .babelrc ├── .browserslistrc ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public └── index.html └── src ├── App.vue ├── assets ├── css │ └── reset.css ├── font │ └── font_2121904_vickjx8nwzn │ │ ├── demo.css │ │ ├── demo_index.html │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.js │ │ ├── iconfont.json │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 └── images │ ├── 404.png │ ├── arrow-lr.png │ ├── cd.png │ ├── close-dark.svg │ ├── close.svg │ ├── empty.png │ ├── gotop.png │ ├── logbg.jpg │ ├── logo-a.png │ ├── logo.png │ ├── logo_black.png │ ├── newbg.png │ ├── newbg1.png │ ├── personal.jpg │ ├── replace.png │ ├── top-bg.jpg │ └── trash.svg ├── axios ├── api.js ├── config.js ├── index.js ├── instance.js └── user.js ├── components ├── common │ ├── AlbumList.vue │ ├── CategoryContainer.vue │ ├── CommentList.vue │ ├── Dialog.vue │ ├── GoTop.vue │ ├── Loading.vue │ ├── PlayButton.vue │ ├── Scroll.vue │ ├── SingerList.vue │ ├── SongSheetList.vue │ ├── TagBar.vue │ ├── VideoList.vue │ ├── VideoMain.vue │ └── VideoRecommend.vue ├── home │ ├── Banner.vue │ ├── RecommendSinger.vue │ ├── RecommendSongSheet.vue │ └── RecommendSongs.vue └── playlistdetail │ ├── Comment.vue │ ├── PlayBar.vue │ ├── PlayList.vue │ ├── Recommend.vue │ ├── SubScribers.vue │ └── TopTitle.vue ├── element-ui └── index.js ├── filter └── filters.js ├── main.js ├── router └── index.js ├── store ├── actions.js ├── getters.js ├── index.js ├── mutation-type.js ├── mutations.js └── state.js ├── utils └── utils.js └── views ├── FooterMain.vue ├── HeaderMain.vue ├── Home.vue ├── Login.vue ├── MV.vue ├── MainRouterPages.vue ├── MvDetail.vue ├── PlayListDetail.vue ├── Profile.vue ├── Rank.vue ├── Register.vue ├── Search.vue ├── Singer.vue ├── SingerDetail.vue ├── SongSheet.vue ├── Video.vue ├── VideoDetail.vue ├── search ├── SearchAlbum.vue ├── SearchComp.vue ├── SearchMv.vue ├── SearchPlayList.vue ├── SearchRadioStation.vue ├── SearchSings.vue ├── SearchSongs.vue ├── SearchUser.vue └── SearchVideo.vue └── singer-detail ├── SimilarSinger.vue ├── SingerAlbum.vue ├── SingerDesc.vue ├── SingerMusic.vue └── SingerMv.vue /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { "modules": false }] 4 | ], 5 | "plugins": [ 6 | [ 7 | "component", 8 | { 9 | "libraryName": "element-ui", 10 | "styleLibraryName": "theme-chalk" 11 | } 12 | ] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # music 2 | 3 | # 下载须知: 4 | 本项目api的是 Binaryify 后端api 地址: https://github.com/Binaryify/NeteaseCloudMusicApi 5 | 6 | ## 下载使用 7 | ``` 8 | git clone https://github.com/Binaryify/NeteaseCloudMusicApi 9 | ``` 10 | ## 开启后端服务 11 | ```$xslt 12 | node app.js 13 | ``` 14 | 15 | ## 下载本项目 16 | ```$xslt 17 | git clone https://github.com/coderps123/music.git 18 | ``` 19 | ## 运行 20 | ```$xslt 21 | npm install 22 | npm run serve 23 | ``` 24 | 25 | ### 特别感谢 26 | Binaryify lxhcool 27 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "music", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.20.0", 11 | "better-scroll": "^2.0.5", 12 | "core-js": "^3.6.5", 13 | "element-ui": "^2.13.2", 14 | "lyric-parser": "^1.0.1", 15 | "swiper": "^5.4.5", 16 | "vue": "^2.6.11", 17 | "vue-awesome-swiper": "^2.6.7", 18 | "vue-kinesis": "^1.1.5", 19 | "vue-lazyload": "^1.3.3", 20 | "vue-router": "^3.4.6", 21 | "vuex": "^3.5.1", 22 | "vuex-persistedstate": "^4.0.0-beta.1" 23 | }, 24 | "devDependencies": { 25 | "@vue/cli-plugin-babel": "^4.4.0", 26 | "@vue/cli-service": "^4.4.0", 27 | "babel-plugin-component": "^1.1.1", 28 | "less": "^2.7.3", 29 | "less-loader": "^7.0.2", 30 | "vue-template-compiler": "^2.6.11" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 20 | 21 | -------------------------------------------------------------------------------- /src/assets/css/reset.css: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Base styles: opinionated defaults 3 | ========================================================================== */ 4 | 5 | body, 6 | h1, 7 | h2, 8 | h3, 9 | h4, 10 | h5, 11 | h6, 12 | hr, 13 | p, 14 | blockquote, 15 | dl, 16 | dt, 17 | dd, 18 | ul, 19 | ol, 20 | li, 21 | pre, 22 | fieldset, 23 | lengend, 24 | button, 25 | input, 26 | textarea, 27 | th, 28 | td { 29 | margin: 0; 30 | padding: 0; 31 | } 32 | 33 | body, 34 | html { 35 | margin: 0; 36 | padding: 0; 37 | height: 100%; 38 | font-weight: 400; 39 | -webkit-font-smoothing: antialiased; 40 | -webkit-tap-highlight-color: transparent; 41 | font-family: PingFang SC, Arial, Microsoft YaHei, sans-serif; 42 | font-size: 14px; 43 | width: 100%; 44 | height: 100%; 45 | background: #ffffff; 46 | } 47 | 48 | * { 49 | -webkit-box-sizing: border-box; 50 | -moz-box-sizing: border-box; 51 | box-sizing: border-box; 52 | } 53 | 54 | *:before, 55 | *:after { 56 | -webkit-box-sizing: border-box; 57 | -moz-box-sizing: border-box; 58 | box-sizing: border-box; 59 | } 60 | 61 | body, 62 | button, 63 | input, 64 | select, 65 | textarea { 66 | font-family: PingFang SC, Arial, Microsoft YaHei, sans-serif; 67 | color: #4a4a4a; 68 | } 69 | 70 | h1 { 71 | font-size: 18px; 72 | } 73 | 74 | h2 { 75 | font-size: 16px; 76 | } 77 | 78 | h3 { 79 | font-size: 14px; 80 | } 81 | 82 | h4, 83 | h5, 84 | h6 { 85 | font-size: 100%; 86 | } 87 | 88 | address, 89 | cite, 90 | dfn, 91 | em, 92 | var { 93 | font-style: normal; 94 | } 95 | 96 | small { 97 | font-size: 12px; 98 | } 99 | 100 | ul, 101 | ol, 102 | li { 103 | list-style: none; 104 | } 105 | 106 | a { 107 | text-decoration: none; 108 | color: #161e27; 109 | } 110 | 111 | abbr[title], 112 | acronym[title] { 113 | border-bottom: 1px dotted; 114 | cursor: help; 115 | } 116 | 117 | q:before, 118 | q:after { 119 | content: ''; 120 | } 121 | 122 | legend { 123 | color: #000; 124 | } 125 | 126 | fieldset, 127 | img { 128 | border: none; 129 | } 130 | 131 | img { 132 | height: auto; 133 | max-width: 100%; 134 | border-style: none; 135 | } 136 | 137 | button, 138 | input, 139 | select, 140 | textarea { 141 | font-size: 100%; 142 | outline: none; 143 | border: 0; 144 | } 145 | 146 | input:focus { 147 | outline: none; 148 | } 149 | 150 | table { 151 | border-collapse: collapse; 152 | border-spacing: 0; 153 | table-layout: fixed; 154 | } 155 | 156 | .unselectable { 157 | user-select: none; 158 | } 159 | 160 | hr { 161 | border: none; 162 | height: 1px; 163 | } 164 | 165 | .clearfix:before, 166 | .clearfix:after { 167 | content: "."; 168 | display: block; 169 | visibility: hidden; 170 | height: 0; 171 | line-height: 0; 172 | font-size: 0; 173 | } 174 | 175 | .clearfix:after { 176 | clear: both; 177 | } 178 | 179 | .clearfix { 180 | zoom: 1; 181 | } 182 | 183 | .clear { 184 | clear: both; 185 | height: 0; 186 | overflow: hidden; 187 | } 188 | 189 | .fl { 190 | float: left; 191 | } 192 | 193 | .fr { 194 | float: right; 195 | } 196 | 197 | /*—滚动条默认显示样式–*/ 198 | 199 | ::-webkit-scrollbar { 200 | width: 0px; 201 | height: 8px; 202 | } 203 | 204 | ::-webkit-scrollbar-thumb { 205 | background: #ababab; 206 | border-radius: 10px; 207 | } 208 | 209 | ::-webkit-scrollbar-track { 210 | border-radius: 10px; 211 | background-color: #fff; 212 | } 213 | -------------------------------------------------------------------------------- /src/assets/font/font_2121904_vickjx8nwzn/demo.css: -------------------------------------------------------------------------------- 1 | /* Logo 字体 */ 2 | @font-face { 3 | font-family: "iconfont logo"; 4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); 5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), 6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), 7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), 8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); 9 | } 10 | 11 | .logo { 12 | font-family: "iconfont logo"; 13 | font-size: 160px; 14 | font-style: normal; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | 19 | /* tabs */ 20 | .nav-tabs { 21 | position: relative; 22 | } 23 | 24 | .nav-tabs .nav-more { 25 | position: absolute; 26 | right: 0; 27 | bottom: 0; 28 | height: 42px; 29 | line-height: 42px; 30 | color: #666; 31 | } 32 | 33 | #tabs { 34 | border-bottom: 1px solid #eee; 35 | } 36 | 37 | #tabs li { 38 | cursor: pointer; 39 | width: 100px; 40 | height: 40px; 41 | line-height: 40px; 42 | text-align: center; 43 | font-size: 16px; 44 | border-bottom: 2px solid transparent; 45 | position: relative; 46 | z-index: 1; 47 | margin-bottom: -1px; 48 | color: #666; 49 | } 50 | 51 | 52 | #tabs .active { 53 | border-bottom-color: #f00; 54 | color: #222; 55 | } 56 | 57 | .tab-container .content { 58 | display: none; 59 | } 60 | 61 | /* 页面布局 */ 62 | .main { 63 | padding: 30px 100px; 64 | width: 960px; 65 | margin: 0 auto; 66 | } 67 | 68 | .main .logo { 69 | color: #333; 70 | text-align: left; 71 | margin-bottom: 30px; 72 | line-height: 1; 73 | height: 110px; 74 | margin-top: -50px; 75 | overflow: hidden; 76 | *zoom: 1; 77 | } 78 | 79 | .main .logo a { 80 | font-size: 160px; 81 | color: #333; 82 | } 83 | 84 | .helps { 85 | margin-top: 40px; 86 | } 87 | 88 | .helps pre { 89 | padding: 20px; 90 | margin: 10px 0; 91 | border: solid 1px #e7e1cd; 92 | background-color: #fffdef; 93 | overflow: auto; 94 | } 95 | 96 | .icon_lists { 97 | width: 100% !important; 98 | overflow: hidden; 99 | *zoom: 1; 100 | } 101 | 102 | .icon_lists li { 103 | width: 100px; 104 | margin-bottom: 10px; 105 | margin-right: 20px; 106 | text-align: center; 107 | list-style: none !important; 108 | cursor: default; 109 | } 110 | 111 | .icon_lists li .code-name { 112 | line-height: 1.2; 113 | } 114 | 115 | .icon_lists .icon { 116 | display: block; 117 | height: 100px; 118 | line-height: 100px; 119 | font-size: 42px; 120 | margin: 10px auto; 121 | color: #333; 122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear; 123 | -moz-transition: font-size 0.25s linear, width 0.25s linear; 124 | transition: font-size 0.25s linear, width 0.25s linear; 125 | } 126 | 127 | .icon_lists .icon:hover { 128 | font-size: 100px; 129 | } 130 | 131 | .icon_lists .svg-icon { 132 | /* 通过设置 font-size 来改变图标大小 */ 133 | width: 1em; 134 | /* 图标和文字相邻时,垂直对齐 */ 135 | vertical-align: -0.15em; 136 | /* 通过设置 color 来改变 SVG 的颜色/fill */ 137 | fill: currentColor; 138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 139 | normalize.css 中也包含这行 */ 140 | overflow: hidden; 141 | } 142 | 143 | .icon_lists li .name, 144 | .icon_lists li .code-name { 145 | color: #666; 146 | } 147 | 148 | /* markdown 样式 */ 149 | .markdown { 150 | color: #666; 151 | font-size: 14px; 152 | line-height: 1.8; 153 | } 154 | 155 | .highlight { 156 | line-height: 1.5; 157 | } 158 | 159 | .markdown img { 160 | vertical-align: middle; 161 | max-width: 100%; 162 | } 163 | 164 | .markdown h1 { 165 | color: #404040; 166 | font-weight: 500; 167 | line-height: 40px; 168 | margin-bottom: 24px; 169 | } 170 | 171 | .markdown h2, 172 | .markdown h3, 173 | .markdown h4, 174 | .markdown h5, 175 | .markdown h6 { 176 | color: #404040; 177 | margin: 1.6em 0 0.6em 0; 178 | font-weight: 500; 179 | clear: both; 180 | } 181 | 182 | .markdown h1 { 183 | font-size: 28px; 184 | } 185 | 186 | .markdown h2 { 187 | font-size: 22px; 188 | } 189 | 190 | .markdown h3 { 191 | font-size: 16px; 192 | } 193 | 194 | .markdown h4 { 195 | font-size: 14px; 196 | } 197 | 198 | .markdown h5 { 199 | font-size: 12px; 200 | } 201 | 202 | .markdown h6 { 203 | font-size: 12px; 204 | } 205 | 206 | .markdown hr { 207 | height: 1px; 208 | border: 0; 209 | background: #e9e9e9; 210 | margin: 16px 0; 211 | clear: both; 212 | } 213 | 214 | .markdown p { 215 | margin: 1em 0; 216 | } 217 | 218 | .markdown>p, 219 | .markdown>blockquote, 220 | .markdown>.highlight, 221 | .markdown>ol, 222 | .markdown>ul { 223 | width: 80%; 224 | } 225 | 226 | .markdown ul>li { 227 | list-style: circle; 228 | } 229 | 230 | .markdown>ul li, 231 | .markdown blockquote ul>li { 232 | margin-left: 20px; 233 | padding-left: 4px; 234 | } 235 | 236 | .markdown>ul li p, 237 | .markdown>ol li p { 238 | margin: 0.6em 0; 239 | } 240 | 241 | .markdown ol>li { 242 | list-style: decimal; 243 | } 244 | 245 | .markdown>ol li, 246 | .markdown blockquote ol>li { 247 | margin-left: 20px; 248 | padding-left: 4px; 249 | } 250 | 251 | .markdown code { 252 | margin: 0 3px; 253 | padding: 0 5px; 254 | background: #eee; 255 | border-radius: 3px; 256 | } 257 | 258 | .markdown strong, 259 | .markdown b { 260 | font-weight: 600; 261 | } 262 | 263 | .markdown>table { 264 | border-collapse: collapse; 265 | border-spacing: 0px; 266 | empty-cells: show; 267 | border: 1px solid #e9e9e9; 268 | width: 95%; 269 | margin-bottom: 24px; 270 | } 271 | 272 | .markdown>table th { 273 | white-space: nowrap; 274 | color: #333; 275 | font-weight: 600; 276 | } 277 | 278 | .markdown>table th, 279 | .markdown>table td { 280 | border: 1px solid #e9e9e9; 281 | padding: 8px 16px; 282 | text-align: left; 283 | } 284 | 285 | .markdown>table th { 286 | background: #F7F7F7; 287 | } 288 | 289 | .markdown blockquote { 290 | font-size: 90%; 291 | color: #999; 292 | border-left: 4px solid #e9e9e9; 293 | padding-left: 0.8em; 294 | margin: 1em 0; 295 | } 296 | 297 | .markdown blockquote p { 298 | margin: 0; 299 | } 300 | 301 | .markdown .anchor { 302 | opacity: 0; 303 | transition: opacity 0.3s ease; 304 | margin-left: 8px; 305 | } 306 | 307 | .markdown .waiting { 308 | color: #ccc; 309 | } 310 | 311 | .markdown h1:hover .anchor, 312 | .markdown h2:hover .anchor, 313 | .markdown h3:hover .anchor, 314 | .markdown h4:hover .anchor, 315 | .markdown h5:hover .anchor, 316 | .markdown h6:hover .anchor { 317 | opacity: 1; 318 | display: inline-block; 319 | } 320 | 321 | .markdown>br, 322 | .markdown>p>br { 323 | clear: both; 324 | } 325 | 326 | 327 | .hljs { 328 | display: block; 329 | background: white; 330 | padding: 0.5em; 331 | color: #333333; 332 | overflow-x: auto; 333 | } 334 | 335 | .hljs-comment, 336 | .hljs-meta { 337 | color: #969896; 338 | } 339 | 340 | .hljs-string, 341 | .hljs-variable, 342 | .hljs-template-variable, 343 | .hljs-strong, 344 | .hljs-emphasis, 345 | .hljs-quote { 346 | color: #df5000; 347 | } 348 | 349 | .hljs-keyword, 350 | .hljs-selector-tag, 351 | .hljs-type { 352 | color: #a71d5d; 353 | } 354 | 355 | .hljs-literal, 356 | .hljs-symbol, 357 | .hljs-bullet, 358 | .hljs-attribute { 359 | color: #0086b3; 360 | } 361 | 362 | .hljs-section, 363 | .hljs-name { 364 | color: #63a35c; 365 | } 366 | 367 | .hljs-tag { 368 | color: #333333; 369 | } 370 | 371 | .hljs-title, 372 | .hljs-attr, 373 | .hljs-selector-id, 374 | .hljs-selector-class, 375 | .hljs-selector-attr, 376 | .hljs-selector-pseudo { 377 | color: #795da3; 378 | } 379 | 380 | .hljs-addition { 381 | color: #55a532; 382 | background-color: #eaffea; 383 | } 384 | 385 | .hljs-deletion { 386 | color: #bd2c00; 387 | background-color: #ffecec; 388 | } 389 | 390 | .hljs-link { 391 | text-decoration: underline; 392 | } 393 | 394 | /* 代码高亮 */ 395 | /* PrismJS 1.15.0 396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ 397 | /** 398 | * prism.js default theme for JavaScript, CSS and HTML 399 | * Based on dabblet (http://dabblet.com) 400 | * @author Lea Verou 401 | */ 402 | code[class*="language-"], 403 | pre[class*="language-"] { 404 | color: black; 405 | background: none; 406 | text-shadow: 0 1px white; 407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 408 | text-align: left; 409 | white-space: pre; 410 | word-spacing: normal; 411 | word-break: normal; 412 | word-wrap: normal; 413 | line-height: 1.5; 414 | 415 | -moz-tab-size: 4; 416 | -o-tab-size: 4; 417 | tab-size: 4; 418 | 419 | -webkit-hyphens: none; 420 | -moz-hyphens: none; 421 | -ms-hyphens: none; 422 | hyphens: none; 423 | } 424 | 425 | pre[class*="language-"]::-moz-selection, 426 | pre[class*="language-"] ::-moz-selection, 427 | code[class*="language-"]::-moz-selection, 428 | code[class*="language-"] ::-moz-selection { 429 | text-shadow: none; 430 | background: #b3d4fc; 431 | } 432 | 433 | pre[class*="language-"]::selection, 434 | pre[class*="language-"] ::selection, 435 | code[class*="language-"]::selection, 436 | code[class*="language-"] ::selection { 437 | text-shadow: none; 438 | background: #b3d4fc; 439 | } 440 | 441 | @media print { 442 | 443 | code[class*="language-"], 444 | pre[class*="language-"] { 445 | text-shadow: none; 446 | } 447 | } 448 | 449 | /* Code blocks */ 450 | pre[class*="language-"] { 451 | padding: 1em; 452 | margin: .5em 0; 453 | overflow: auto; 454 | } 455 | 456 | :not(pre)>code[class*="language-"], 457 | pre[class*="language-"] { 458 | background: #f5f2f0; 459 | } 460 | 461 | /* Inline code */ 462 | :not(pre)>code[class*="language-"] { 463 | padding: .1em; 464 | border-radius: .3em; 465 | white-space: normal; 466 | } 467 | 468 | .token.comment, 469 | .token.prolog, 470 | .token.doctype, 471 | .token.cdata { 472 | color: slategray; 473 | } 474 | 475 | .token.punctuation { 476 | color: #999; 477 | } 478 | 479 | .namespace { 480 | opacity: .7; 481 | } 482 | 483 | .token.property, 484 | .token.tag, 485 | .token.boolean, 486 | .token.number, 487 | .token.constant, 488 | .token.symbol, 489 | .token.deleted { 490 | color: #905; 491 | } 492 | 493 | .token.selector, 494 | .token.attr-name, 495 | .token.string, 496 | .token.char, 497 | .token.builtin, 498 | .token.inserted { 499 | color: #690; 500 | } 501 | 502 | .token.operator, 503 | .token.entity, 504 | .token.url, 505 | .language-css .token.string, 506 | .style .token.string { 507 | color: #9a6e3a; 508 | background: hsla(0, 0%, 100%, .5); 509 | } 510 | 511 | .token.atrule, 512 | .token.attr-value, 513 | .token.keyword { 514 | color: #07a; 515 | } 516 | 517 | .token.function, 518 | .token.class-name { 519 | color: #DD4A68; 520 | } 521 | 522 | .token.regex, 523 | .token.important, 524 | .token.variable { 525 | color: #e90; 526 | } 527 | 528 | .token.important, 529 | .token.bold { 530 | font-weight: bold; 531 | } 532 | 533 | .token.italic { 534 | font-style: italic; 535 | } 536 | 537 | .token.entity { 538 | cursor: help; 539 | } 540 | -------------------------------------------------------------------------------- /src/assets/font/font_2121904_vickjx8nwzn/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/font/font_2121904_vickjx8nwzn/iconfont.eot -------------------------------------------------------------------------------- /src/assets/font/font_2121904_vickjx8nwzn/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2121904", 3 | "name": "music", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "9255860", 10 | "name": "关 闭", 11 | "font_class": "guanbi", 12 | "unicode": "e645", 13 | "unicode_decimal": 58949 14 | }, 15 | { 16 | "icon_id": "15756528", 17 | "name": "足迹", 18 | "font_class": "zuji", 19 | "unicode": "e60d", 20 | "unicode_decimal": 58893 21 | }, 22 | { 23 | "icon_id": "8736357", 24 | "name": "个人中心 我的 人物 标准头 线性", 25 | "font_class": "mine", 26 | "unicode": "e60a", 27 | "unicode_decimal": 58890 28 | }, 29 | { 30 | "icon_id": "9178403", 31 | "name": "等级", 32 | "font_class": "dengji", 33 | "unicode": "e9bc", 34 | "unicode_decimal": 59836 35 | }, 36 | { 37 | "icon_id": "11244534", 38 | "name": "退出", 39 | "font_class": "tuichu", 40 | "unicode": "e681", 41 | "unicode_decimal": 59009 42 | }, 43 | { 44 | "icon_id": "13936220", 45 | "name": "设 置", 46 | "font_class": "shezhi", 47 | "unicode": "e60c", 48 | "unicode_decimal": 58892 49 | }, 50 | { 51 | "icon_id": "9234676", 52 | "name": "昵称", 53 | "font_class": "nicheng", 54 | "unicode": "e662", 55 | "unicode_decimal": 58978 56 | }, 57 | { 58 | "icon_id": "10496444", 59 | "name": "验证码", 60 | "font_class": "yanzhengma", 61 | "unicode": "e676", 62 | "unicode_decimal": 58998 63 | }, 64 | { 65 | "icon_id": "11938539", 66 | "name": "点赞", 67 | "font_class": "dianzan", 68 | "unicode": "e609", 69 | "unicode_decimal": 58889 70 | }, 71 | { 72 | "icon_id": "14165976", 73 | "name": "信息 ", 74 | "font_class": "xinxi", 75 | "unicode": "e986", 76 | "unicode_decimal": 59782 77 | }, 78 | { 79 | "icon_id": "4986983", 80 | "name": "收 藏 选中", 81 | "font_class": "shoucangxuanzhong", 82 | "unicode": "e68b", 83 | "unicode_decimal": 59019 84 | }, 85 | { 86 | "icon_id": "3259673", 87 | "name": "MV", 88 | "font_class": "mv", 89 | "unicode": "e608", 90 | "unicode_decimal": 58888 91 | }, 92 | { 93 | "icon_id": "9549447", 94 | "name": "like", 95 | "font_class": "like", 96 | "unicode": "e614", 97 | "unicode_decimal": 58900 98 | }, 99 | { 100 | "icon_id": "14760515", 101 | "name": "转发", 102 | "font_class": "forward", 103 | "unicode": "e60b", 104 | "unicode_decimal": 58891 105 | }, 106 | { 107 | "icon_id": "8589223", 108 | "name": "错误", 109 | "font_class": "error", 110 | "unicode": "e62d", 111 | "unicode_decimal": 58925 112 | }, 113 | { 114 | "icon_id": "4956169", 115 | "name": "单曲循环", 116 | "font_class": "danquxunhuan", 117 | "unicode": "e6e7", 118 | "unicode_decimal": 59111 119 | }, 120 | { 121 | "icon_id": "8852571", 122 | "name": "随机播放", 123 | "font_class": "play-random", 124 | "unicode": "e616", 125 | "unicode_decimal": 58902 126 | }, 127 | { 128 | "icon_id": "10910095", 129 | "name": "静音", 130 | "font_class": "jingyin", 131 | "unicode": "e62c", 132 | "unicode_decimal": 58924 133 | }, 134 | { 135 | "icon_id": "1920558", 136 | "name": "垃圾桶", 137 | "font_class": "lajitong", 138 | "unicode": "e651", 139 | "unicode_decimal": 58961 140 | }, 141 | { 142 | "icon_id": "2907650", 143 | "name": "删除筛选项", 144 | "font_class": "delete", 145 | "unicode": "e607", 146 | "unicode_decimal": 58887 147 | }, 148 | { 149 | "icon_id": "156123", 150 | "name": "播放列表", 151 | "font_class": "playlsit", 152 | "unicode": "e610", 153 | "unicode_decimal": 58896 154 | }, 155 | { 156 | "icon_id": "1769930", 157 | "name": "循环", 158 | "font_class": "xunhuan", 159 | "unicode": "e6a9", 160 | "unicode_decimal": 59049 161 | }, 162 | { 163 | "icon_id": "2564801", 164 | "name": "循环", 165 | "font_class": "cloud-circulation", 166 | "unicode": "e732", 167 | "unicode_decimal": 59186 168 | }, 169 | { 170 | "icon_id": "3154014", 171 | "name": "播放", 172 | "font_class": "bofang3", 173 | "unicode": "e89a", 174 | "unicode_decimal": 59546 175 | }, 176 | { 177 | "icon_id": "4144167", 178 | "name": "声音 音量 线性", 179 | "font_class": "shengyin", 180 | "unicode": "e94d", 181 | "unicode_decimal": 59725 182 | }, 183 | { 184 | "icon_id": "8791160", 185 | "name": "前进", 186 | "font_class": "prev", 187 | "unicode": "e604", 188 | "unicode_decimal": 58884 189 | }, 190 | { 191 | "icon_id": "9230674", 192 | "name": "后退", 193 | "font_class": "next", 194 | "unicode": "e606", 195 | "unicode_decimal": 58886 196 | }, 197 | { 198 | "icon_id": "9434896", 199 | "name": "播放", 200 | "font_class": "bofang4", 201 | "unicode": "ec73", 202 | "unicode_decimal": 60531 203 | }, 204 | { 205 | "icon_id": "11321701", 206 | "name": "歌词", 207 | "font_class": "geci", 208 | "unicode": "e759", 209 | "unicode_decimal": 59225 210 | }, 211 | { 212 | "icon_id": "16561754", 213 | "name": "暂停 停止", 214 | "font_class": "zantingtingzhi", 215 | "unicode": "e74e", 216 | "unicode_decimal": 59214 217 | }, 218 | { 219 | "icon_id": "12047996", 220 | "name": "播放", 221 | "font_class": "bofang1", 222 | "unicode": "e661", 223 | "unicode_decimal": 58977 224 | }, 225 | { 226 | "icon_id": "611697", 227 | "name": "热门", 228 | "font_class": "hot", 229 | "unicode": "e64d", 230 | "unicode_decimal": 58957 231 | }, 232 | { 233 | "icon_id": "2911591", 234 | "name": "play", 235 | "font_class": "play", 236 | "unicode": "e613", 237 | "unicode_decimal": 58899 238 | }, 239 | { 240 | "icon_id": "12457550", 241 | "name": "收 藏", 242 | "font_class": "shoucang", 243 | "unicode": "e605", 244 | "unicode_decimal": 58885 245 | }, 246 | { 247 | "icon_id": "14493376", 248 | "name": "关 闭 (7)-01 copy", 249 | "font_class": "clear", 250 | "unicode": "e6a2", 251 | "unicode_decimal": 59042 252 | }, 253 | { 254 | "icon_id": "5619016", 255 | "name": "网易云音乐", 256 | "font_class": "wangyiyunyinle", 257 | "unicode": "e603", 258 | "unicode_decimal": 58883 259 | }, 260 | { 261 | "icon_id": "3443559", 262 | "name": "播放", 263 | "font_class": "bofang2", 264 | "unicode": "e612", 265 | "unicode_decimal": 58898 266 | }, 267 | { 268 | "icon_id": "1840580", 269 | "name": "情感", 270 | "font_class": "qinggan", 271 | "unicode": "e617", 272 | "unicode_decimal": 58903 273 | }, 274 | { 275 | "icon_id": "2206525", 276 | "name": "场景", 277 | "font_class": "changjing", 278 | "unicode": "e68a", 279 | "unicode_decimal": 59018 280 | }, 281 | { 282 | "icon_id": "8748301", 283 | "name": "主题", 284 | "font_class": "zhuti", 285 | "unicode": "e62b", 286 | "unicode_decimal": 58923 287 | }, 288 | { 289 | "icon_id": "10617024", 290 | "name": "风格", 291 | "font_class": "fengge", 292 | "unicode": "e85f", 293 | "unicode_decimal": 59487 294 | }, 295 | { 296 | "icon_id": "16152568", 297 | "name": "语种切换", 298 | "font_class": "yuzhong", 299 | "unicode": "e647", 300 | "unicode_decimal": 58951 301 | }, 302 | { 303 | "icon_id": "12376056", 304 | "name": "jiantou you", 305 | "font_class": "jiantouyou", 306 | "unicode": "e660", 307 | "unicode_decimal": 58976 308 | }, 309 | { 310 | "icon_id": "12977445", 311 | "name": "jiantou you", 312 | "font_class": "jiantouxia", 313 | "unicode": "e602", 314 | "unicode_decimal": 58882 315 | }, 316 | { 317 | "icon_id": "3463050", 318 | "name": "github", 319 | "font_class": "github", 320 | "unicode": "e64c", 321 | "unicode_decimal": 58956 322 | }, 323 | { 324 | "icon_id": "5682979", 325 | "name": "csdn", 326 | "font_class": "csdn", 327 | "unicode": "e601", 328 | "unicode_decimal": 58881 329 | }, 330 | { 331 | "icon_id": "10043161", 332 | "name": "播放", 333 | "font_class": "bofang", 334 | "unicode": "e688", 335 | "unicode_decimal": 59016 336 | }, 337 | { 338 | "icon_id": "10267591", 339 | "name": "search", 340 | "font_class": "search", 341 | "unicode": "e600", 342 | "unicode_decimal": 58880 343 | }, 344 | { 345 | "icon_id": "417851", 346 | "name": "手机", 347 | "font_class": "shouji", 348 | "unicode": "e622", 349 | "unicode_decimal": 58914 350 | }, 351 | { 352 | "icon_id": "17228809", 353 | "name": "密 码", 354 | "font_class": "mima", 355 | "unicode": "e618", 356 | "unicode_decimal": 58904 357 | } 358 | ] 359 | } 360 | -------------------------------------------------------------------------------- /src/assets/font/font_2121904_vickjx8nwzn/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/font/font_2121904_vickjx8nwzn/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/font/font_2121904_vickjx8nwzn/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/font/font_2121904_vickjx8nwzn/iconfont.woff -------------------------------------------------------------------------------- /src/assets/font/font_2121904_vickjx8nwzn/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/font/font_2121904_vickjx8nwzn/iconfont.woff2 -------------------------------------------------------------------------------- /src/assets/images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/404.png -------------------------------------------------------------------------------- /src/assets/images/arrow-lr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/arrow-lr.png -------------------------------------------------------------------------------- /src/assets/images/cd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/cd.png -------------------------------------------------------------------------------- /src/assets/images/close-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/empty.png -------------------------------------------------------------------------------- /src/assets/images/gotop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/gotop.png -------------------------------------------------------------------------------- /src/assets/images/logbg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/logbg.jpg -------------------------------------------------------------------------------- /src/assets/images/logo-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/logo-a.png -------------------------------------------------------------------------------- /src/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/logo.png -------------------------------------------------------------------------------- /src/assets/images/logo_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/logo_black.png -------------------------------------------------------------------------------- /src/assets/images/newbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/newbg.png -------------------------------------------------------------------------------- /src/assets/images/newbg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/newbg1.png -------------------------------------------------------------------------------- /src/assets/images/personal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/personal.jpg -------------------------------------------------------------------------------- /src/assets/images/replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/replace.png -------------------------------------------------------------------------------- /src/assets/images/top-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/assets/images/top-bg.jpg -------------------------------------------------------------------------------- /src/assets/images/trash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/axios/api.js: -------------------------------------------------------------------------------- 1 | import instance from "./instance" 2 | 3 | /** 4 | * @methods 获取轮播图 5 | * @params 6 | */ 7 | export const getBanner = () => instance.get("/banner",{}) 8 | 9 | 10 | /** 11 | * @methods 推荐歌单 12 | * @params limit: 取出数量 默认 30 13 | */ 14 | export const getRecommendSongeSheet = limit => instance.get(`/personalized?limit=${limit}`) 15 | 16 | /** 17 | * @methods 推荐新歌曲 18 | * @params 19 | */ 20 | export const getRecommendSongs = () => instance.get(`/personalized/newsong`, {}) 21 | 22 | /** 23 | * @methods 歌曲详情 24 | * @params ids id数组 25 | */ 26 | export const getSongDetail = ids => instance.get(`/song/detail?ids=${ids}`) 27 | 28 | /** 29 | * @methods 推荐歌手 30 | * @params limit 获取歌手个数 31 | */ 32 | export const getRecommendSinger = limit => instance.get(`/top/artists?offset=0&limit=${limit}`) 33 | /** 34 | * @methods 特色榜单 35 | * @params 36 | */ 37 | export const getRankTopList = () => instance.get(`/toplist`) 38 | 39 | /** 40 | * @methods 热门歌单分类 41 | * @params 42 | */ 43 | export const getHotSongSheet = () => instance.get(`/playlist/hot`,{}) 44 | 45 | /** 46 | * @methods 全部歌单 分类 47 | * @params 48 | */ 49 | export const getSongSheetCategory = () => instance.get(`/playlist/catlist`,{}) 50 | 51 | /** 52 | * @methods 获取歌单 53 | * @params 54 | */ 55 | export const getSongSheet = params => instance.get(`/top/playlist`, {params}) 56 | 57 | /** 58 | * @methods 歌手分类 59 | * @params 60 | */ 61 | export const getSingerCategory = params => instance.get(`/artist/list`, {params}) 62 | 63 | /** 64 | * @methods 歌手单曲 65 | * @params id: 歌手id 66 | */ 67 | export const getSingerSingle = params => instance.get(`/artists`, {params}) 68 | 69 | /** 70 | * @methods 歌手专辑 71 | * @params id: 歌手id 72 | * @params offset: 偏移数量 , 用于分页 , 如 :( 页数 -1)*50, 其中 50 为 limit 的值 , 默认 为 0 73 | * @params limit: 去除数量 74 | */ 75 | export const getSingerAlbum = params => instance.get(`/artist/album`, {params}) 76 | 77 | /** 78 | * @methods 歌手MV 79 | */ 80 | export const getSingerMv = id => instance.get(`/artist/mv?id=${id}`, {}) 81 | 82 | /** 83 | * @methods 歌手描述 84 | * @params 必选参数 : id: 歌手 id 85 | */ 86 | export const getSingerDesc = id => instance.get(`/artist/desc?id=${id}`, {}) 87 | 88 | /** 89 | * @methods 全部 mv 90 | * @params 91 | */ 92 | export const getAllMV = params => instance.get(`/mv/all`, {params}) 93 | 94 | /** 95 | * @methods mv详情 96 | * @params mvid: mv 的 id 其中 mv 视频 网易做了防盗链处理 , 可能不能直接播放 , 需要播放的话需要调用 ' mv 地址' 接口 97 | */ 98 | export const getMvDetail = mvId => instance.get(`/mv/detail?mvid=${mvId}`, {}) 99 | 100 | /** 101 | * @methods mv 播放地址 102 | * @params 必选参数 : id: mv id 103 | * @params 可选参数 : r: 分辨率,默认1080,可从 /mv/detail 接口获取分辨率列表 104 | */ 105 | export const getMvURL = params => instance.get(`/mv/url`, {params}) 106 | 107 | /** 108 | * @methods mv 评论 109 | * @params 必选参数 : id: mv id 110 | * @params 可选参数 : limit: 取出评论数量 , 默认为 20 111 | * @params offset: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 112 | * @params before: 分页参数,取上一页最后一项的 time 获取下一页数据(获取超过5000条评论的时候需要用到) 113 | */ 114 | export const getMvComments = params => instance.get(`/comment/mv`, {params}) 115 | 116 | /** 117 | * @methods mv 点赞转发评论数数据 118 | * @params 必选参数 : mvid: mv 的 id 119 | */ 120 | export const getMvDetailInfo = params => instance.get(`/mv/detail/info`, {params}) 121 | 122 | /** 123 | * @methods mv 相似 mv 调用此接口 , 传入 mvid 可获取相似 mv 124 | * @params 必选参数 : mvid: mv id 125 | */ 126 | export const getRecommendMv = id => instance.get(`/simi/mv?mvid=${id}`, {}) 127 | 128 | /** 129 | * @methods 歌单详情 130 | * @params id: 歌单id s: 歌单收藏人数 100 默认为 8 131 | */ 132 | export const getPlayListDetail = params => instance.get(`/playlist/detail`, {params}) 133 | 134 | /** 135 | * @methods 歌单收藏者 136 | * @params id: 歌单id, limit: 取出数量(收藏者数量, 默认为: 20), offset: 偏移量(页码) 137 | */ 138 | export const getSubScribersPlayList = params => instance.get(`/playlist/subscribers`, {params}) 139 | 140 | /** 141 | * @methods 获取歌单推荐 142 | * @params id: 歌单id 143 | */ 144 | export const getPlayListRecommend = id => instance.get(`/related/playlist?id=${id}`, {}) 145 | 146 | /** 147 | * @methods 歌单评论 148 | * @params id: 歌单id, limit: 取出数量(默认20) 149 | */ 150 | export const getPlayListComment = params => instance.get(`/comment/playlist`, {params}) 151 | 152 | /** 153 | * @methods 歌词 154 | * @params id: 歌曲id 155 | */ 156 | export const getCurrentSongLyric = id => instance.get(`/lyric?id=${id}`) 157 | 158 | /** 159 | * @methods 热搜列表(简略) 160 | * @params 说明 : 调用此接口,可获取热门搜索列表 161 | */ 162 | export const getSearchHot = () => instance.get(`/search/hot`) 163 | 164 | /** 165 | * @methods 搜索 166 | * @params 说明 : 调用此接口 , 传入搜索关键词可以搜索该音乐 / 专辑 / 歌手 / 歌单 / 用户 , 关键词可以多个 , 以空格隔开 , 167 | * @params 如 " 周杰伦 搁浅 "( 不需要登录 ), 搜索获取的 mp3url 不能直接用 , 可通过 /song/url 接口传入歌曲 id 获取具体的播放链接 168 | * @params 必选参数 : keywords : 关键词 169 | * @params 可选参数 : limit : 返回数量 , 默认为 30 170 | * @params 可选参数 : offset : 偏移数量,用于分页 , 如 : 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 171 | * @params 可选参数 : type: 搜索类型;默认为 1 即单曲 , 取值意义 : 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 172 | * @params 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频, 1018:综合 173 | */ 174 | export const getSearchData = params => instance.get(`/cloudsearch`, {params}) 175 | 176 | /** 177 | * @methods 获取全部视频列表 178 | * @params 说明 : 调用此接口,可获取视频分类列表,分页参数只能传入offset 179 | * @params 可选参数 : offset: 默认0 180 | */ 181 | export const getAllVideoList = params => instance.get(`/video/timeline/all`, {params}) 182 | 183 | /** 184 | * @methods 获取视频分类列表 185 | * @params 说明 : 调用此接口 , 可获取视频分类列表 186 | */ 187 | export const getVideoCategoryList = params => instance.get(`/video/category/list`, {params}) 188 | 189 | /** 190 | * @methods 获取视频标签列表 191 | * @params 说明 : 调用此接口 , 可获取视频标签列表 192 | */ 193 | export const getVideoTagList = params => instance.get(`/video/group/list`, {params}) 194 | 195 | /** 196 | * @methods 获取视频标签/分类下的视频 197 | * @params 说明 : 调用此接口 , 传入标签/分类id,可获取到相关的视频,分页参数只能传入offset 198 | * @params 必选参数 : id: videoGroup 的 id 199 | * @params 可选参数 : offset: 默认0 200 | */ 201 | export const getVideoList = params => instance.get(`/video/group`, {params}) 202 | 203 | /** 204 | * @methods 获取登录状态 205 | * @params 说明 : 调用此接口,可获取登录状态 206 | */ 207 | export const getLoginStatus = () => instance.get(`/login/status`, {}) 208 | 209 | /** 210 | * @methods 获取视频播放地址 211 | * @params 说明 : 调用此接口 , 传入视频 id,可获取视频播放地址 212 | * @params 必选参数 : id: 视频 的 id 213 | */ 214 | export const getVideoUrl = params => instance.get(`/video/url`, {params}) 215 | 216 | /** 217 | * @methods 视频详情 218 | * @params 说明 : 调用此接口 , 可获取视频详情 219 | * @params 必选参数 : id: 视频 的 id 220 | */ 221 | export const getVideoDetail = params => instance.get(`/video/detail`, {params}) 222 | 223 | /** 224 | * @methods 获取视频点赞转发评论数数据 225 | * @params 说明 : 调用此接口 , 传入 vid ( 视频id ) , 可获取对应视频点赞转发评论数数据 必选参数 : vid: 视频id 226 | * @params 必选参数 : id: 视频 的 id 227 | */ 228 | export const getVideoDetailInfo = params => instance.get(`/video/detail/info`, {params}) 229 | 230 | /** 231 | * @methods 视频评论 232 | * @params 说明 : 调用此接口 , 传入音乐 id 和 limit 参数 , 可获得该 视频 的所有评论 ( 不需要登录 ) 233 | * @params 必选参数 : id: 视频的 id 234 | * @params 可选参数 : limit: 取出评论数量 , 默认为 20 235 | * @params 可选参数 : offset: 偏移数量 , 用于分页 , 如 :( 评论页数 -1)*20, 其中 20 为 limit 的值 236 | * @params 可选参数 : before: 分页参数,取上一页最后一项的 time 获取下一页数据(获取超过5000条评论的时候需要用到) 237 | */ 238 | export const getVideoComment = params => instance.get(`/comment/video`, {params}) 239 | 240 | /** 241 | * @methods 相关视频 242 | * @params 说明 : 调用此接口 , 可获取相关视频 243 | * @params 必选参数 : id: 视频 的 id 244 | */ 245 | export const getRecommendVideo = params => instance.get(`/related/allvideo`, {params}) 246 | 247 | /** 248 | * @methods 楼层评论 249 | * @params 说明 : 调用此接口 , 传入资源 parentCommentId 和资源类型 type和资源id 参数, 可获得该资源的歌曲楼层评论 250 | * @params 必选参数 : parentCommentId: 楼层评论 id 251 | * @params 必选参数 : id : 资源 id 252 | * @params 必选参数 : tpye: 数字 , 资源类型 , 对应歌曲 , mv, 专辑 , 歌单 , 电台, 视频对应以下类型 253 | * @params 0: 歌曲, 1: mv, 2: 歌单, 3: 专辑, 4: 电台, 5: 视频 254 | * @params 可选参数 : limit: 取出评论数量 , 默认为 20 255 | * @params 可选参数 : time: 分页参数,取上一页最后一项的 time 获取下一页数据 256 | */ 257 | // export const getFloorComment = params => instance.get(`/comment/floor`, {params}) 258 | -------------------------------------------------------------------------------- /src/axios/config.js: -------------------------------------------------------------------------------- 1 | let base_url = "" 2 | 3 | if (process.env.NODE_ENV === "development") { 4 | base_url = "http://localhost:3000" 5 | } else if (process.env.NODE_ENV === "production") { 6 | base_url = "https://nicemusic-api.lxhcool.cn/" 7 | } 8 | 9 | export default { base_url } 10 | -------------------------------------------------------------------------------- /src/axios/index.js: -------------------------------------------------------------------------------- 1 | import * as userApi from "./user" 2 | import * as api from "./api" 3 | 4 | export default { 5 | ...userApi, 6 | ...api 7 | } 8 | -------------------------------------------------------------------------------- /src/axios/instance.js: -------------------------------------------------------------------------------- 1 | import axios from "axios" 2 | import config from "./config" 3 | 4 | const instance = axios.create({ 5 | timeout: 5000, 6 | baseURL: config.base_url, 7 | withCredentials: true // 允许跨域 8 | }) 9 | 10 | // 设置请求拦截器 11 | instance.interceptors.request.use( 12 | config => { 13 | return config 14 | }, 15 | error => { 16 | return Promise.error(error) 17 | } 18 | ) 19 | 20 | // 设置响应拦截器 21 | instance.interceptors.response.use( 22 | response => { 23 | return Promise.resolve(response) 24 | }, 25 | error => { 26 | 27 | } 28 | ) 29 | 30 | export default instance 31 | -------------------------------------------------------------------------------- /src/axios/user.js: -------------------------------------------------------------------------------- 1 | import instance from "./instance" 2 | 3 | /** 4 | * @methods 手机登录 5 | * @params phone password 6 | */ 7 | export const login = params => instance.get(`/login/cellphone`, {params}) 8 | 9 | 10 | /** 11 | * @methods 手机注册 12 | * @params 说明 : 调用此接口 ,传入手机号码和验证码,密码,昵称, 可注册网易云音乐账号(同时可修改密码) 13 | * @params 必选参数 : captcha: 验证码; phone : 手机号码; password: 密码; nickname: 昵称 14 | */ 15 | export const register = params => instance.get(`/register/cellphone`, {params}) 16 | 17 | /** 18 | * @methods 发送验证码 19 | * @params 说明 : 调用此接口 ,传入手机号码, 可发送验证码 20 | * @params 必选参数 : phone: 手机号码 21 | * @params 可选参数 : ctcode: 国家区号,默认86即中国 22 | */ 23 | export const getCaptcha = phone => instance.get(`/captcha/sent?phone=${phone}`, {}) 24 | 25 | /** 26 | * @methods 验证验证码 27 | * @params 说明 : 调用此接口 ,传入手机号码和验证码, 可校验验证码是否正确 28 | * @params 必选参数 : phone: 手机号码; captcha: 验证码 29 | */ 30 | export const verifyCaptcha = params => instance.get(`/captcha/verify`, {params}) 31 | 32 | /** 33 | * @methods 获取用户详情 34 | * @params 说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户详情 35 | * @params 必选参数 : uid : 用户 id 36 | */ 37 | export const getUserDetail = uid => instance.get(`/user/detail?uid=${uid}`, {}) 38 | 39 | /** 40 | * @methods 获取用户信息 , 歌单,收藏,mv, dj 数量 41 | * @params 说明 : 登录后调用此接口 , 可以获取用户信息 42 | */ 43 | export const getUserSub = () => instance.get(`/user/subcount`, {}) 44 | 45 | /** 46 | * @methods 收藏/取消收藏歌单 47 | * @params 说明: 调用此接口 , 传入类型和歌单 id 可收藏歌单或者取消收藏歌单 48 | * @params 必选参数: t :类型, 1:收藏, 2:取消收藏 id: 歌单 id 49 | */ 50 | export const setPlayListCollection = params => instance.get(`/playlist/subscribe`, {params}) 51 | 52 | /** 53 | * @methods 获取用户歌单 54 | * @params 说明 : 登录后调用此接口 , 传入用户 id, 可以获取用户歌单 55 | * @params 必选参数 : uid : 用户 id 56 | * @params 可选参数 : limit : 返回数量 , 默认为 30 57 | * @params 可选参数 : offset : 偏移数量,用于分页 , 如 :( 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0 58 | */ 59 | export const getUserPlayList = uid => instance.get(`/user/playlist?uid=${uid}`, {}) 60 | 61 | /** 62 | * @methods 获取用户播放记录 63 | * @params 说明 : 登录后调用此接口 , 传入用户 id, 可获取用户播放记录 64 | * @params 必选参数 : uid : 用户 id 65 | * @params 可选参数 : type : type=1 时只返回 weekData, type=0 时返回 allData 66 | */ 67 | export const getUserPlayRecord = params => instance.get(`/user/record`, {params}) 68 | 69 | /** 70 | * @methods 退出登录 71 | * @params 说明 : 调用此接口 , 可退出登录 72 | */ 73 | export const logout = () => instance.get(`/logout?timeStamp=${new Date().valueOf()}`) 74 | 75 | /** 76 | * @methods 资源点赞 77 | * @params 说明 : 调用此接口 , 可对 MV,电台,视频点赞 78 | * @params 必选参数: type:资源类型,对应以下类型 1: mv, 4: 电台, 5: 视频, 6: 动态 79 | * @params 必选参数: t: 操作,1 为点赞,其他未取消点赞 80 | * @params 必选参数: id: 资源 id 81 | */ 82 | export const resourceLike = params => instance.get(`/resource/like`, {params}) 83 | 84 | /** 85 | * @methods 给评论点赞 86 | * @params 说明 : 调用此接口 , 传入 type, 资源 id, 和评论 id cid 和 是否点赞参数 t 即可给对 应评论点赞 ( 需要登录 ) 87 | * @params 必选参数 : id : 资源 id, 如歌曲 id,mv id 88 | * @params 必选参数 : cid : 评论 id 89 | * @params 必选参数 : t : 是否点赞 ,1 为点赞 ,0 为取消点赞 90 | * @params 必选参数 : tpye : 数字 , 资源类型 , 对应歌曲 , mv, 专辑 , 歌单 , 电台, 视频对应以下类型 91 | * @params 0: 歌曲, 1: mv, 2: 歌单, 3: 专辑, 4: 电台, 5: 视频, 6: 动态 92 | */ 93 | export const commentLike = params => instance.get(`/comment/like`, {params}) 94 | 95 | /** 96 | * @methods 收藏视频 97 | * @params 说明 : 调用此接口,可收藏视频 98 | * @params 必选参数: id : 视频 id 99 | * @params 必选参数: t : 1 为收藏,其他为取消收藏 100 | */ 101 | export const collectionVideo = params => instance.get(`/video/sub`, {params}) 102 | 103 | /** 104 | * @methods 发送/删除评论 105 | * @params 说明 : 调用此接口,可发送评论或者删除评论 106 | * @params 必选参数: t:1 发送, 2 回复 107 | * @params 必选参数: tpye: 数字,资源类型,对应歌曲,mv,专辑,歌单,电台,视频对应以下类型 108 | * @params 0: 歌曲, 1: mv, 2: 歌单, 3: 专辑, 4: 电台, 5: 视频, 6: 动态 109 | * @params 必选参数: id:对应资源 id 110 | * @params 必选参数: content :要发送的内容 111 | * @params 必选参数: commentId :回复的评论id (回复评论时必填) 112 | * @params 调用例子 : /comment?t=1&type=1&id=5436712&content=test (往广岛之恋 mv 发送评论: test) 113 | */ 114 | export const handleComment = params => instance.get(`/comment`, {params}) 115 | 116 | /** 117 | * @methods 收藏/取消收藏歌手 118 | * @params 说明 : 调用此接口,可收藏歌手 119 | * @params 必选参数: id : 歌手 id 120 | * @params 必选参数: t:操作,1 为收藏,其他为取消收藏 121 | */ 122 | export const collectionSinger = params => instance.get(`/artist/sub`, {params}) 123 | -------------------------------------------------------------------------------- /src/components/common/AlbumList.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 27 | 28 | 63 | -------------------------------------------------------------------------------- /src/components/common/CategoryContainer.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 37 | 38 | 57 | -------------------------------------------------------------------------------- /src/components/common/CommentList.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 221 | 222 | 343 | -------------------------------------------------------------------------------- /src/components/common/Dialog.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 36 | 37 | 78 | -------------------------------------------------------------------------------- /src/components/common/GoTop.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 38 | 39 | 53 | -------------------------------------------------------------------------------- /src/components/common/Loading.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 36 | -------------------------------------------------------------------------------- /src/components/common/PlayButton.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 98 | 99 | 193 | -------------------------------------------------------------------------------- /src/components/common/Scroll.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 50 | 51 | 54 | -------------------------------------------------------------------------------- /src/components/common/SingerList.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 35 | 36 | 61 | -------------------------------------------------------------------------------- /src/components/common/SongSheetList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 36 | 37 | 75 | -------------------------------------------------------------------------------- /src/components/common/TagBar.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 118 | 119 | 255 | -------------------------------------------------------------------------------- /src/components/common/VideoList.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 52 | 53 | 138 | -------------------------------------------------------------------------------- /src/components/common/VideoMain.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 83 | 84 | 148 | -------------------------------------------------------------------------------- /src/components/common/VideoRecommend.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 53 | 54 | 121 | -------------------------------------------------------------------------------- /src/components/home/Banner.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 54 | 55 | 82 | -------------------------------------------------------------------------------- /src/components/home/RecommendSinger.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 38 | 39 | 46 | -------------------------------------------------------------------------------- /src/components/home/RecommendSongSheet.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | 35 | -------------------------------------------------------------------------------- /src/components/home/RecommendSongs.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 82 | 83 | 148 | -------------------------------------------------------------------------------- /src/components/playlistdetail/Comment.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 51 | 52 | 89 | -------------------------------------------------------------------------------- /src/components/playlistdetail/PlayList.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 142 | 143 | 251 | -------------------------------------------------------------------------------- /src/components/playlistdetail/Recommend.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 31 | 32 | 68 | -------------------------------------------------------------------------------- /src/components/playlistdetail/SubScribers.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 25 | 26 | 42 | -------------------------------------------------------------------------------- /src/components/playlistdetail/TopTitle.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 73 | 74 | 175 | -------------------------------------------------------------------------------- /src/element-ui/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue" 2 | 3 | import { 4 | Button, 5 | Form, 6 | FormItem, 7 | Input, 8 | Pagination, 9 | Slider, 10 | Dropdown, 11 | DropdownMenu, 12 | DropdownItem, 13 | Message 14 | } from "element-ui" 15 | 16 | Vue 17 | .use(Button) 18 | .use(Form) 19 | .use(FormItem) 20 | .use(Input) 21 | .use(Pagination) 22 | .use(Slider) 23 | .use(Dropdown) 24 | .use(DropdownMenu) 25 | .use(DropdownItem) 26 | 27 | // 挂载到 vue 的实例原型对象上 28 | Vue.prototype.$message = Message 29 | 30 | -------------------------------------------------------------------------------- /src/filter/filters.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue" 2 | 3 | /* 4 | * 处理播放量 5 | * */ 6 | Vue.filter("handlePlayCount", function (playCount) { 7 | if (parseInt(playCount / 100000000) >= 1) { 8 | return parseInt(playCount / 100000000) + "亿" 9 | } else if (playCount > 10000) { 10 | return parseInt(playCount / 10000) + "万" 11 | } else { 12 | return parseInt(playCount) 13 | } 14 | }) 15 | 16 | /* 17 | * 处理播放时间 18 | * */ 19 | Vue.filter("formatPlayTime", function(time) { 20 | // 1. 将毫秒转化为分 21 | let m = parseInt(time / (1000 * 60)) 22 | let s = parseInt(((time % (1000 * 60)) / 1000) % 60) 23 | if (m <= 9) { 24 | m = "0" + m 25 | } 26 | if (s < 10) { 27 | s = "0" + s 28 | } 29 | return m + ":" + s 30 | }) 31 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from "./router" 4 | import store from "./store" 5 | 6 | import api from "./axios/index.js" 7 | import utils from "./utils/utils" 8 | import "./filter/filters" 9 | import VueLazyload from "vue-lazyload"; 10 | 11 | Vue.use(VueLazyload, { 12 | error: require("./assets/images/replace.png"), 13 | loading: require("./assets/images/replace.png") 14 | }) 15 | 16 | import "./element-ui" 17 | Vue.config.productionTip = false 18 | 19 | import "./assets/css/reset.css" 20 | 21 | import VueAwesomeSwiper from 'vue-awesome-swiper' 22 | import 'swiper/css/swiper.css' 23 | Vue.use(VueAwesomeSwiper) 24 | 25 | Vue.prototype.$api = api 26 | Vue.prototype.$utils = utils 27 | Vue.prototype.$bus = new Vue() 28 | 29 | new Vue({ 30 | router, 31 | store, 32 | render: h => h(App), 33 | }).$mount('#app') 34 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue" 2 | import VueRouter from "vue-router" 3 | 4 | Vue.use(VueRouter) 5 | 6 | const Login = () => import("../views/Login") 7 | const Register = () => import("../views/Register") 8 | const Home = () => import("../views/Home") 9 | const Rank = () => import("../views/Rank") 10 | const SongSheet = () => import("../views/SongSheet") 11 | const Singer = () => import("../views/Singer") 12 | const Video = () => import("../views/Video") 13 | const VideoDetail = () => import("../views/VideoDetail") 14 | const MV = () => import("../views/MV") 15 | const PlayListDetail = () => import("../views/PlayListDetail") 16 | const SingerDetail = () => import("../views/SingerDetail") 17 | const SingerMusic = () => import("../views/singer-detail/SingerMusic") 18 | const SingerAlbum = () => import("../views/singer-detail/SingerAlbum") 19 | const SingerMv = () => import("../views/singer-detail/SingerMv") 20 | const SingerDesc = () => import("../views/singer-detail/SingerDesc") 21 | const SimilarSinger = () => import("../views/singer-detail/SimilarSinger") 22 | const MvDetail = () => import("../views/MvDetail") 23 | const Search = () => import("../views/Search") 24 | const SearchSongs = () => import("../views/search/SearchSongs") 25 | const SearchSings = () => import("../views/search/SearchSings") 26 | const SearchAlbum = () => import("../views/search/SearchAlbum") 27 | const SearchVideo = () => import("../views/search/SearchVideo") 28 | const SearchPlayList = () => import("../views/search/SearchPlayList") 29 | const SearchUser = () => import("../views/search/SearchUser") 30 | const SearchMv = () => import("../views/search/SearchMv") 31 | const SearchRadioStation = () => import("../views/search/SearchRadioStation") 32 | const SearchComp = () => import("../views/search/SearchComp") 33 | 34 | /*用户登录*/ 35 | const Profile = () => import("../views/Profile") 36 | 37 | const routes = [ 38 | { 39 | path: "/login", 40 | component: Login 41 | }, 42 | { 43 | path: "/register", 44 | component: Register 45 | }, 46 | { 47 | path: "/", 48 | redirect: "/home" 49 | }, 50 | { 51 | path: "/home", 52 | component: Home 53 | }, 54 | { 55 | path: "/rank", 56 | component: Rank 57 | }, 58 | { 59 | path: "/song_sheet", 60 | component: SongSheet 61 | }, 62 | { 63 | path: "/singer", 64 | component: Singer 65 | }, 66 | { 67 | path: "/video", 68 | component: Video 69 | }, 70 | { 71 | path: "/video-detail/:id", 72 | component: VideoDetail 73 | }, 74 | { 75 | path: "/mv", 76 | component: MV 77 | }, 78 | { 79 | path: "/play-list-detail/:id", 80 | component: PlayListDetail 81 | }, 82 | { 83 | path: "/singer-detail/:id", 84 | redirect: "/singer-detail/:id/singer-music" 85 | }, 86 | { 87 | path: "/singer-detail/:id", 88 | component: SingerDetail, 89 | children: [ 90 | { path: 'singer-music', component: SingerMusic }, 91 | { path: 'singer-album', component: SingerAlbum }, 92 | { path: 'singer-mv', component: SingerMv }, 93 | { path: 'singer-desc', component: SingerDesc }, 94 | { path: 'similar-singer', component: SimilarSinger }, 95 | ] 96 | }, 97 | { 98 | path: "/mv-detail/:id", 99 | component: MvDetail 100 | }, 101 | { 102 | path: "/profile", 103 | component: Profile 104 | }, 105 | { 106 | path: "/search/:keywords", 107 | redirect: "/search/:keywords/songs" 108 | }, 109 | { 110 | path: "/search/:keywords", 111 | component: Search, 112 | children: [ 113 | { path: 'songs', component: SearchSongs }, 114 | { path: 'sings', component: SearchSings }, 115 | { path: 'album', component: SearchAlbum }, 116 | { path: 'video', component: SearchVideo }, 117 | { path: 'play-list', component: SearchPlayList }, 118 | { path: 'user', component: SearchUser }, 119 | { path: 'mv', component: SearchMv }, 120 | { path: 'radio-station', component: SearchRadioStation }, 121 | { path: 'comp', component: SearchComp }, 122 | ] 123 | }, 124 | ] 125 | 126 | const router = new VueRouter({ 127 | routes: routes, 128 | }) 129 | 130 | export default router 131 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/store/actions.js -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | 2 | // 登录状态 3 | export const loginStatus = state => state.loginStatus 4 | 5 | // 用户的个人信息 6 | export const profile = state => state.profile 7 | 8 | // 控制播放暂停按钮的显隐 9 | export const isPlay = state => state.isPlay 10 | 11 | // 当前播放歌曲对象 12 | export const currentSong = state => state.currentSong 13 | 14 | // audio 元素 15 | export const audio = state => state.audio 16 | 17 | // 播放列表 18 | export const playList = state => state.playList 19 | 20 | // 播放记录 21 | export const playRecord = state => state.playRecord 22 | 23 | // 播放模式 24 | export const playMode = state => state.playMode 25 | 26 | // 历史搜索 27 | export const historySearch = state => state.historySearch 28 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue" 2 | import Vuex from "vuex" 3 | import state from "./state" 4 | import * as getters from "./getters" 5 | import * as mutations from "./mutations" 6 | import * as actions from "./actions" 7 | import createLogger from "vuex/dist/logger" 8 | 9 | const debug = process.env.NODE_ENV !== "production" 10 | 11 | Vue.use(Vuex) 12 | 13 | const store = new Vuex.Store({ 14 | state, 15 | getters, 16 | mutations, 17 | actions, 18 | plugins: [createLogger()] 19 | }) 20 | 21 | export default store 22 | -------------------------------------------------------------------------------- /src/store/mutation-type.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderps123/music/12ffc37fb0e8e086f6e9eeffa6bbb88d702d80b5/src/store/mutation-type.js -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | 2 | // 用户的个人信息 3 | export const setProfile = (state, payload) => { 4 | state.profile = payload 5 | } 6 | 7 | // 控制播放暂停按钮的显隐 8 | export const isPlayMutation = (state, payload) => { 9 | state.isPlay = payload 10 | } 11 | 12 | // 清空播放记录 13 | export const deleteAll = (state, payload) => { 14 | state.playRecord = [] 15 | } 16 | 17 | // 移除播放记录某一项 18 | export const removeItem = (state, index) => { 19 | state.playRecord.splice(index, 1) 20 | } 21 | 22 | // 上一首歌曲 23 | export const setPlayPrevSong = (state) => { 24 | if (state.playList.indexOf(state.currentSong) === 0) { 25 | state.currentSong = state.playList[state.playList.length-1] 26 | } else { 27 | state.currentSong = state.playList[state.playList.indexOf(state.currentSong) - 1] 28 | } 29 | // 将当前歌曲加入到播放记录列表中 30 | addPlayRecord(state) 31 | } 32 | 33 | // 下一首歌曲 34 | export const setPlayNextSong = (state) => { 35 | console.log(state.playList); 36 | if (state.playList.indexOf(state.currentSong) === state.playList.length - 1) { 37 | state.currentSong = state.playList[0] 38 | } else { 39 | state.currentSong = state.playList[state.playList.indexOf(state.currentSong) + 1] 40 | } 41 | // 将当前歌曲加入到播放记录列表中 42 | addPlayRecord(state) 43 | } 44 | 45 | // 将当前歌曲加入到播放记录列表中, 并去重 46 | export const addPlayRecord = state => { 47 | let index = state.playRecord.findIndex(item => state.currentSong.id === item.id) 48 | if (index !== -1) { 49 | state.playRecord.splice(index, 1) 50 | state.playRecord.unshift(state.currentSong) 51 | } else { 52 | state.playRecord.unshift(state.currentSong) 53 | } 54 | } 55 | 56 | // 获取 audio 元素 57 | export const getAudio = (state, audio) => { 58 | state.audio = audio 59 | } 60 | 61 | // 播放 62 | export const play = state => { 63 | state.audio.play() 64 | } 65 | 66 | // 暂停 67 | export const pause = state => { 68 | state.audio.pause() 69 | } 70 | 71 | // 设置当前歌曲(在playMode 为: "random" 时调用) 72 | export const setCurrentSong = (state, payload) => { 73 | state.currentSong = payload 74 | } 75 | 76 | // 设置播放列表 77 | export const setPlayList = (state, payload) => { 78 | state.playList = payload 79 | } 80 | 81 | // 设置播放图标的显示 82 | export const setIsPlay = (state, payload) => { 83 | state.isPlay = payload 84 | } 85 | 86 | // 设置播放模式 87 | export const setPlayMode = (state, payload) => { 88 | state.playMode = payload 89 | } 90 | 91 | // 设置错误信息 92 | export const setCurrentSongError = (state, payload) => { 93 | state.currentSong.error = payload 94 | } 95 | 96 | // 设置历史搜索记录 97 | export const setHistorySearch = (state, payload) => { 98 | let index = state.historySearch.indexOf(payload) 99 | if (index !== -1) { 100 | state.historySearch.splice(index, 1) 101 | state.historySearch.unshift(payload) 102 | } else { 103 | state.historySearch.unshift(payload) 104 | } 105 | } 106 | 107 | // 删除历史搜索记录某一项 108 | export const deleteHistorySearchItem = (state, index) => { 109 | state.historySearch.splice(index, 1) 110 | } 111 | 112 | // 清空搜索历史 113 | export const clearHistorySearch = (state, payload) => { 114 | state.historySearch = [] 115 | } 116 | 117 | // 设置登录状态 118 | export const setLoginStatus = (state, payload) => { 119 | console.log(payload) 120 | state.loginStatus = payload 121 | } 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/store/state.js: -------------------------------------------------------------------------------- 1 | 2 | const state = { 3 | // 用户的个人信息 4 | profile: JSON.parse(window.localStorage.getItem("profile")) || null, 5 | // 控制播放暂停按钮的显隐 6 | isPlay: false, 7 | // 播放 8 | playList: [], 9 | // 当前播放歌曲对象 10 | currentSong: {}, 11 | // 播放记录列表 12 | playRecord: JSON.parse(window.localStorage.getItem("playRecord")) || [], 13 | // audio 元素 14 | audio: null, 15 | // 当前播放歌曲的索引值 16 | currentSongIndex: 0, 17 | // 播放模式 ("orderPlay", "oneLoop", "randomPlay") // 默认就是 orderPlay 18 | playMode: "orderPlay", 19 | // 历史搜索 20 | historySearch: JSON.parse(window.localStorage.getItem("historySearch")) || [] 21 | } 22 | 23 | export default state 24 | -------------------------------------------------------------------------------- /src/utils/utils.js: -------------------------------------------------------------------------------- 1 | export default { 2 | /** 3 | * 时间戳转分秒 4 | */ 5 | 6 | /* 7 | * 格式化时间戳 8 | */ 9 | formatDate(time, number) { 10 | let date = new Date(time) // 如果time是13位, 则不需要乘1000 11 | let Y = date.getFullYear() + "-" 12 | let M = ((date.getMonth() + 1) < 10) ? ("0" + (date.getMonth() + 1) + "-") : ((date.getMonth() + 1) + "-") 13 | let D = ((date.getDay() < 10) ? ("0" + date.getDay()) : date.getDay()) + " " 14 | let h = ((date.getHours() < 10) ? ("0" + date.getHours()) : date.getHours()) + ":" 15 | let m = ((date.getMinutes() < 10) ? ("0" + date.getMinutes()) : date.getMinutes()) + ":" 16 | let s = (date.getSeconds() < 10) ? ("0" + date.getSeconds()) : date.getSeconds() 17 | switch (number) { 18 | case 3: 19 | return h+m+s; 20 | case 6: 21 | return Y+M+D+h+m+s 22 | default: 23 | return Y+M+D 24 | } 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /src/views/FooterMain.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 26 | 27 | 60 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 56 | 57 | 65 | -------------------------------------------------------------------------------- /src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 99 | 100 | 184 | -------------------------------------------------------------------------------- /src/views/MV.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 92 | 93 | 100 | -------------------------------------------------------------------------------- /src/views/MainRouterPages.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 38 | 39 | 52 | -------------------------------------------------------------------------------- /src/views/MvDetail.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 204 | 205 | 233 | -------------------------------------------------------------------------------- /src/views/PlayListDetail.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 170 | 171 | 205 | -------------------------------------------------------------------------------- /src/views/Profile.vue: -------------------------------------------------------------------------------- 1 | 90 | 91 | 189 | 190 | 389 | -------------------------------------------------------------------------------- /src/views/Rank.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 54 | 55 | 65 | -------------------------------------------------------------------------------- /src/views/Register.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 128 | 129 | 231 | -------------------------------------------------------------------------------- /src/views/Search.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 137 | 138 | 199 | -------------------------------------------------------------------------------- /src/views/Singer.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 112 | 113 | 120 | -------------------------------------------------------------------------------- /src/views/SingerDetail.vue: -------------------------------------------------------------------------------- 1 | 63 | 64 | 144 | 145 | 257 | -------------------------------------------------------------------------------- /src/views/SongSheet.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 175 | 176 | 216 | -------------------------------------------------------------------------------- /src/views/Video.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 175 | 176 | 200 | -------------------------------------------------------------------------------- /src/views/VideoDetail.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 218 | 219 | 240 | -------------------------------------------------------------------------------- /src/views/search/SearchAlbum.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /src/views/search/SearchComp.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /src/views/search/SearchMv.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /src/views/search/SearchPlayList.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /src/views/search/SearchRadioStation.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /src/views/search/SearchSings.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /src/views/search/SearchSongs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 28 | 29 | 32 | -------------------------------------------------------------------------------- /src/views/search/SearchUser.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /src/views/search/SearchVideo.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /src/views/singer-detail/SimilarSinger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 29 | 30 | 33 | -------------------------------------------------------------------------------- /src/views/singer-detail/SingerAlbum.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 48 | 49 | 55 | -------------------------------------------------------------------------------- /src/views/singer-detail/SingerDesc.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | 27 | 30 | -------------------------------------------------------------------------------- /src/views/singer-detail/SingerMusic.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 51 | 52 | 57 | -------------------------------------------------------------------------------- /src/views/singer-detail/SingerMv.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 38 | 39 | 42 | --------------------------------------------------------------------------------