├── .editorconfig ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── index.html └── logo.ico ├── resources └── ico │ ├── ic_launcher.ico │ └── ic_launcher.png ├── src ├── App.vue ├── assets │ ├── add.png │ ├── btn-play.png │ ├── delete.png │ ├── gd_b_data.png │ ├── help1.png │ ├── help2.png │ ├── help3.png │ ├── hotsong.png │ ├── ic_launcher.png │ ├── iconfont │ │ ├── demo.css │ │ ├── demo_index.html │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.js │ │ ├── iconfont.json │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ ├── logo.png │ ├── n-login.png │ ├── newsong.png │ ├── original.png │ ├── unlode.jpg │ └── unlogin.jpg ├── background.js ├── components │ ├── A11A.vue │ ├── Control.vue │ ├── Header.vue │ ├── Hotlist.vue │ ├── Listdata.vue │ ├── Listheader.vue │ ├── Menu.vue │ ├── MyplayList.vue │ ├── PlaylistSection.vue │ ├── Searchdata.vue │ ├── Searchheader.vue │ └── Swiper.vue ├── main.js ├── migu_api │ ├── lyric.js │ ├── playlist.js │ ├── search.js │ ├── singer.js │ ├── song.js │ └── top.js ├── router │ └── index.js ├── store │ └── index.js ├── utils │ └── migu_request.js └── views │ ├── Home.vue │ ├── Login.vue │ ├── Mylist.vue │ ├── Playlist.vue │ ├── Searchlist.vue │ └── Sharelist.vue └── vue.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.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 | 25 | #Electron-builder output 26 | /dist_electron -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # miguu 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run electron:serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run electron:build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "miguu", 3 | "version": "1.1.0", 4 | "private": true, 5 | "appId": "com.ipp.electronvue", 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint", 10 | "electron:build": "vue-cli-service electron:build", 11 | "electron:serve": "vue-cli-service electron:serve", 12 | "postinstall": "electron-builder install-app-deps", 13 | "postuninstall": "electron-builder install-app-deps" 14 | }, 15 | "main": "background.js", 16 | "dependencies": { 17 | "axios": "^0.21.1", 18 | "cheerio": "^1.0.0-rc.5", 19 | "core-js": "^3.6.5", 20 | "crypto-js": "^4.0.0", 21 | "element-ui": "^2.15.0", 22 | "node-jsencrypt": "^1.0.0", 23 | "request": "^2.88.2", 24 | "vue": "^2.6.11", 25 | "vue-right-click-menu": "^1.1.0", 26 | "vue-router": "^3.2.0", 27 | "vuex": "^3.4.0" 28 | }, 29 | "devDependencies": { 30 | "@vue/cli-plugin-babel": "~4.5.0", 31 | "@vue/cli-plugin-eslint": "~4.5.0", 32 | "@vue/cli-plugin-router": "~4.5.0", 33 | "@vue/cli-plugin-vuex": "~4.5.0", 34 | "@vue/cli-service": "~4.5.0", 35 | "@vue/eslint-config-standard": "^5.1.2", 36 | "axios": "^0.21.1", 37 | "babel-eslint": "^10.1.0", 38 | "electron": "^9.0.0", 39 | "electron-devtools-installer": "^3.1.0", 40 | "eslint": "^6.7.2", 41 | "eslint-plugin-import": "^2.20.2", 42 | "eslint-plugin-node": "^11.1.0", 43 | "eslint-plugin-promise": "^4.2.1", 44 | "eslint-plugin-standard": "^4.0.0", 45 | "eslint-plugin-vue": "^6.2.2", 46 | "rightmenu": "^1.1.0", 47 | "stylus": "^0.54.7", 48 | "stylus-loader": "^3.0.2", 49 | "vue-cli-plugin-electron-builder": "~2.0.0-rc.5", 50 | "vue-template-compiler": "^2.6.11" 51 | }, 52 | "eslintConfig": { 53 | "root": true, 54 | "env": { 55 | "node": true 56 | }, 57 | "extends": [ 58 | "plugin:vue/essential", 59 | "@vue/standard" 60 | ], 61 | "parserOptions": { 62 | "parser": "babel-eslint" 63 | }, 64 | "rules": {} 65 | }, 66 | "browserslist": [ 67 | "> 1%", 68 | "last 2 versions", 69 | "not dead" 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /public/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/public/logo.ico -------------------------------------------------------------------------------- /resources/ico/ic_launcher.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/resources/ico/ic_launcher.ico -------------------------------------------------------------------------------- /resources/ico/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/resources/ico/ic_launcher.png -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 64 | 162 | -------------------------------------------------------------------------------- /src/assets/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/add.png -------------------------------------------------------------------------------- /src/assets/btn-play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/btn-play.png -------------------------------------------------------------------------------- /src/assets/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/delete.png -------------------------------------------------------------------------------- /src/assets/gd_b_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/gd_b_data.png -------------------------------------------------------------------------------- /src/assets/help1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/help1.png -------------------------------------------------------------------------------- /src/assets/help2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/help2.png -------------------------------------------------------------------------------- /src/assets/help3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/help3.png -------------------------------------------------------------------------------- /src/assets/hotsong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/hotsong.png -------------------------------------------------------------------------------- /src/assets/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/ic_launcher.png -------------------------------------------------------------------------------- /src/assets/iconfont/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/iconfont/demo_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IconFont Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |

20 | 30 |
31 |
32 |
    33 | 34 |
  • 35 | 36 |
    电脑
    37 |
    &#xe60d;
    38 |
  • 39 | 40 |
  • 41 | 42 |
    歌单
    43 |
    &#xe601;
    44 |
  • 45 | 46 |
  • 47 | 48 |
    位置
    49 |
    &#xe602;
    50 |
  • 51 | 52 |
  • 53 | 54 |
    历史
    55 |
    &#xe60b;
    56 |
  • 57 | 58 |
  • 59 | 60 |
    下一首
    61 |
    &#xe600;
    62 |
  • 63 | 64 |
  • 65 | 66 |
    播放
    67 |
    &#xe66c;
    68 |
  • 69 | 70 |
  • 71 | 72 |
    播放
    73 |
    &#xe773;
    74 |
  • 75 | 76 |
77 |
78 |

Unicode 引用

79 |
80 | 81 |

Unicode 是字体在网页端最原始的应用方式,特点是:

82 |
    83 |
  • 兼容性最好,支持 IE6+,及所有现代浏览器。
  • 84 |
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • 85 |
  • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
  • 86 |
87 |
88 |

注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式

89 |
90 |

Unicode 使用步骤如下:

91 |

第一步:拷贝项目下面生成的 @font-face

92 |
@font-face {
 94 |   font-family: 'iconfont';
 95 |   src: url('iconfont.eot');
 96 |   src: url('iconfont.eot?#iefix') format('embedded-opentype'),
 97 |       url('iconfont.woff2') format('woff2'),
 98 |       url('iconfont.woff') format('woff'),
 99 |       url('iconfont.ttf') format('truetype'),
100 |       url('iconfont.svg#iconfont') format('svg');
101 | }
102 | 
103 |

第二步:定义使用 iconfont 的样式

104 |
.iconfont {
106 |   font-family: "iconfont" !important;
107 |   font-size: 16px;
108 |   font-style: normal;
109 |   -webkit-font-smoothing: antialiased;
110 |   -moz-osx-font-smoothing: grayscale;
111 | }
112 | 
113 |

第三步:挑选相应图标并获取字体编码,应用于页面

114 |
115 | <span class="iconfont">&#x33;</span>
117 | 
118 |
119 |

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

120 |
121 |
122 |
123 |
124 |
    125 | 126 |
  • 127 | 128 |
    129 | 电脑 130 |
    131 |
    .el-icon-fontdiannao 132 |
    133 |
  • 134 | 135 |
  • 136 | 137 |
    138 | 歌单 139 |
    140 |
    .el-icon-fontgedan 141 |
    142 |
  • 143 | 144 |
  • 145 | 146 |
    147 | 位置 148 |
    149 |
    .el-icon-fontweizhi 150 |
    151 |
  • 152 | 153 |
  • 154 | 155 |
    156 | 历史 157 |
    158 |
    .el-icon-fontlishi 159 |
    160 |
  • 161 | 162 |
  • 163 | 164 |
    165 | 下一首 166 |
    167 |
    .el-icon-fontxiayishou-copy-copy 168 |
    169 |
  • 170 | 171 |
  • 172 | 173 |
    174 | 播放 175 |
    176 |
    .el-icon-fontbofang 177 |
    178 |
  • 179 | 180 |
  • 181 | 182 |
    183 | 播放 184 |
    185 |
    .el-icon-fontbofang1 186 |
    187 |
  • 188 | 189 |
190 |
191 |

font-class 引用

192 |
193 | 194 |

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

195 |

与 Unicode 使用方式相比,具有如下特点:

196 |
    197 |
  • 兼容性良好,支持 IE8+,及所有现代浏览器。
  • 198 |
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • 199 |
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • 200 |
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  • 201 |
202 |

使用步骤如下:

203 |

第一步:引入项目下面生成的 fontclass 代码:

204 |
<link rel="stylesheet" href="./iconfont.css">
205 | 
206 |

第二步:挑选相应图标并获取类名,应用于页面:

207 |
<span class="iconfont el-icon-fontxxx"></span>
208 | 
209 |
210 |

" 211 | iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

212 |
213 |
214 |
215 |
216 |
    217 | 218 |
  • 219 | 222 |
    电脑
    223 |
    #el-icon-fontdiannao
    224 |
  • 225 | 226 |
  • 227 | 230 |
    歌单
    231 |
    #el-icon-fontgedan
    232 |
  • 233 | 234 |
  • 235 | 238 |
    位置
    239 |
    #el-icon-fontweizhi
    240 |
  • 241 | 242 |
  • 243 | 246 |
    历史
    247 |
    #el-icon-fontlishi
    248 |
  • 249 | 250 |
  • 251 | 254 |
    下一首
    255 |
    #el-icon-fontxiayishou-copy-copy
    256 |
  • 257 | 258 |
  • 259 | 262 |
    播放
    263 |
    #el-icon-fontbofang
    264 |
  • 265 | 266 |
  • 267 | 270 |
    播放
    271 |
    #el-icon-fontbofang1
    272 |
  • 273 | 274 |
275 |
276 |

Symbol 引用

277 |
278 | 279 |

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 280 | 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

281 |
    282 |
  • 支持多色图标了,不再受单色限制。
  • 283 |
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • 284 |
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • 285 |
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • 286 |
287 |

使用步骤如下:

288 |

第一步:引入项目下面生成的 symbol 代码:

289 |
<script src="./iconfont.js"></script>
290 | 
291 |

第二步:加入通用 CSS 代码(引入一次就行):

292 |
<style>
293 | .icon {
294 |   width: 1em;
295 |   height: 1em;
296 |   vertical-align: -0.15em;
297 |   fill: currentColor;
298 |   overflow: hidden;
299 | }
300 | </style>
301 | 
302 |

第三步:挑选相应图标并获取类名,应用于页面:

303 |
<svg class="icon" aria-hidden="true">
304 |   <use xlink:href="#icon-xxx"></use>
305 | </svg>
306 | 
307 |
308 |
309 | 310 |
311 |
312 | 331 | 332 | 333 | -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face {font-family: "iconfont"; 2 | src: url('iconfont.eot?t=1617593578266'); /* IE9 */ 3 | src: url('iconfont.eot?t=1617593578266#iefix') format('embedded-opentype'), /* IE6-IE8 */ 4 | url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAXoAAsAAAAAC6wAAAWaAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDZAqJXIgNATYCJAMgCxIABCAFhG0HcxsCClGUUE4S2Y/D2G0yRBVFYzo3/PpdfVT28fC13+u5u/fB55ekwApQdSoBdaeqqhLQxVXFVgE5W+c2JeH/4VzeA6qBMDeQZflqRAp9ml7y+UIKrIZOT5lNyE24Hf9eOS/ZvcRHZAt/HaDd1ge7SkoGhYD//17VTNsWnNe+xWXuRXlAOaEAB2iszmkLqKCtUAuiPcwz6OC44qXiq3uYwNw5hsGji7tHmEvsUCDeK8lgHrPIEmYY9X3OhdnFZ52xfCzf+OT+fPxzI0aKrmKPevLyPICj5nC/vmxfPKsvDtpz4XoZFdeBJA5yPR+M/Mx1I/P376THwNKoyFbaoq3a+8P97ZYmpmC5sDTxTtApqpzPP95A9IhmicnPswONxOhoAQoNo9IWGElbqcG077FLb6eluMMARnzBBJwD8Y34j1FuudXcTNEJoUzT4mrmrnFOeUz8uZPLzGm2XMYU53a2tm47UJRpepyKkKQxzHgFIP6ihHGrpNXjV4or0mkkrerML1kBmLiS4YCWV7jrbTlttbTKjkYMKDOhp65GuLQqhcaZAsRAnqpGz9QYc8UW6HEyYHy1pNK+C0Sl4oyGIM6wZbRQgrhyfFuxcSuaeQDeHIf2J7CIS2HHqZJmzyFXowx0KoGKQaJxvHOzqtokyDZYwC4aXbmScPVq4vXryXiyppUcu9Z+8fXYo1fbLbhSxQCt54BtLr2lePVgYmLy9cPXhWvXUrZdki6PvyheqLQQRrVJ1qdce5Z0/Xny1aeJV54kDFRHtx4w0TZRWb56ll0S3tz/xTag2uWt2uGCzd3ZI1+zB2U26/WSOrBI3bICHERb3czC9sWaVFVkKx0uDkex8dN8+20kmolys9GEnhhtVh6iSvHrImUeOYOzhbNlXlWXJutmw1OL0dZLrcdYuXrHXMh9owt+F8AZXYj1rkliP3APOeCmcxbs+vtT73+rci9yn5ERVqSX9fKUswvoOpX7z+50/rdjaGkePwY/RhgasuNvPrpveU4zUVJtESlEGqKEKMg6zZMryUZyFcmTs8hGYpZb9YPYB3J2DrXbapdoYhI3mSPuohp9186+GysZGwkpoirC4iVu1cNjhl+J8Plat7dxKTvQ/pwPGFFeHopHRq0yXkTh64zPNlbXZ1e9E41GkjCaxBqTiSBNxo6bhscOb9/PSwD/WY4mTULlne0iQ1NnFa8v2pA2y80+Uo+V59ykLDHHo49H7/Z92gMeslf3+7duL2f9/rO3uv78wc2KP7/3PrqhNwi6G9hkMKikTjDob2CjIOCvh+GhrKWzJZfCr9y3bIVk7TBz89x4+DpUYN7R1z0HlD/4pOUtnfKo8nWE50P63QJhwTuGZN6BR/iyea53a1ZbU+ZgY3268515bm+7wc3x+RNXfZIyF5Ua98JQYFvx/dg5gP8v6xHcETMR9psnJY6LHktsPN3nhV0CAMDeYhNPl10QtO9ac7Z50FeS+Qct3Jmy9BVR1M9qMSqApSfHQB4Cst7kzDrma0gizsclYN7op3mmYB4OnRaBXX9t6o7SWsLoKIVicBaq0Xl8kq9DZ+Em9EZ3Ye6ay8sX9uRGIme46hNBmHxBsfYLqskPPsm/0DnmH3pTVJh7Grs3XLgYb5anObGSAvQ7VFwnQtjLpVd/T7KKWB6Vu+xnygsVR9dykvlLSihv45Sill5ZChS5jvECPY6iSGOa6w3x0lqXZbqybZH3SRbXMSw9lCNMiQSQr4MUTksIPb+0TH3/PSJVIkxeMvYt+IzkCmp55LI4APylJgGNHUtroSZ5SpISkLjWajF0QVwk4hkNpfnbNghXsqxrpFIrNkEJqMbqXxcfaZ2DOIG95RglamR00ccQY8wMzxVLEqYnkgKWTBtS/VpNIlXo1G6rWOdV6srkOu1U19TXgiVyZtwuAAAA') format('woff2'), 5 | url('iconfont.woff?t=1617593578266') format('woff'), 6 | url('iconfont.ttf?t=1617593578266') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 7 | url('iconfont.svg?t=1617593578266#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont { 11 | font-family: "iconfont" !important; 12 | font-size: 16px; 13 | font-style: normal; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | } 17 | 18 | [class^="el-icon-font"], 19 | [class*="el-icon-font"] { 20 | font-family: "iconfont" !important; 21 | font-size: 16px; 22 | font-style: normal; 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | .el-icon-fontdiannao:before { 28 | content: "\e60d"; 29 | } 30 | 31 | .el-icon-fontgedan:before { 32 | content: "\e601"; 33 | } 34 | 35 | .el-icon-fontweizhi:before { 36 | content: "\e602"; 37 | } 38 | 39 | .el-icon-fontlishi:before { 40 | content: "\e60b"; 41 | } 42 | 43 | .el-icon-fontxiayishou-copy-copy:before { 44 | content: "\e600"; 45 | } 46 | 47 | .el-icon-fontbofang:before { 48 | content: "\e66c"; 49 | } 50 | 51 | .el-icon-fontbofang1:before { 52 | content: "\e773"; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/iconfont/iconfont.eot -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.js: -------------------------------------------------------------------------------- 1 | !function(c){var t,e,o,n,i,l,h='',a=(a=document.getElementsByTagName("script"))[a.length-1].getAttribute("data-injectcss");if(a&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}function d(){i||(i=!0,o())}t=function(){var c,t,e,o;(o=document.createElement("div")).innerHTML=h,h=null,(e=o.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",c=e,(t=document.body).firstChild?(o=c,(e=t.firstChild).parentNode.insertBefore(o,e)):t.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(e=function(){document.removeEventListener("DOMContentLoaded",e,!1),t()},document.addEventListener("DOMContentLoaded",e,!1)):document.attachEvent&&(o=t,n=c.document,i=!1,(l=function(){try{n.documentElement.doScroll("left")}catch(c){return void setTimeout(l,50)}d()})(),n.onreadystatechange=function(){"complete"==n.readyState&&(n.onreadystatechange=null,d())})}(window); -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2015248", 3 | "name": "elicon", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "el-icon-font", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "7719364", 10 | "name": "电脑", 11 | "font_class": "diannao", 12 | "unicode": "e60d", 13 | "unicode_decimal": 58893 14 | }, 15 | { 16 | "icon_id": "8228494", 17 | "name": "歌单", 18 | "font_class": "gedan", 19 | "unicode": "e601", 20 | "unicode_decimal": 58881 21 | }, 22 | { 23 | "icon_id": "12343427", 24 | "name": "位置", 25 | "font_class": "weizhi", 26 | "unicode": "e602", 27 | "unicode_decimal": 58882 28 | }, 29 | { 30 | "icon_id": "20231071", 31 | "name": "历史", 32 | "font_class": "lishi", 33 | "unicode": "e60b", 34 | "unicode_decimal": 58891 35 | }, 36 | { 37 | "icon_id": "8065312", 38 | "name": "下一首", 39 | "font_class": "xiayishou-copy-copy", 40 | "unicode": "e600", 41 | "unicode_decimal": 58880 42 | }, 43 | { 44 | "icon_id": "11466072", 45 | "name": "播放", 46 | "font_class": "bofang", 47 | "unicode": "e66c", 48 | "unicode_decimal": 58988 49 | }, 50 | { 51 | "icon_id": "11807384", 52 | "name": "播放", 53 | "font_class": "bofang1", 54 | "unicode": "e773", 55 | "unicode_decimal": 59251 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/iconfont/iconfont.woff -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/n-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/n-login.png -------------------------------------------------------------------------------- /src/assets/newsong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/newsong.png -------------------------------------------------------------------------------- /src/assets/original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/original.png -------------------------------------------------------------------------------- /src/assets/unlode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/unlode.jpg -------------------------------------------------------------------------------- /src/assets/unlogin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FliPPeDround/MiguMusic/ae3a89bc26aff789d156a069a9b5b8de4da2e7b7/src/assets/unlogin.jpg -------------------------------------------------------------------------------- /src/background.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import { app, protocol, BrowserWindow, ipcMain, screen, Tray, Menu } from 'electron' 4 | 5 | import { 6 | createProtocol 7 | /* installVueDevtools */ 8 | } from 'vue-cli-plugin-electron-builder/lib' 9 | 10 | const searchMusic = require('./migu_api/search') 11 | const song = require('./migu_api/song') 12 | const top = require('./migu_api/top') 13 | 14 | const isDevelopment = process.env.NODE_ENV !== 'production' 15 | 16 | // Keep a global reference of the window object, if you don't, the window will 17 | // be closed automatically when the JavaScript object is garbage collected. 18 | let win 19 | let tray 20 | 21 | // Scheme must be registered before the app is ready 22 | protocol.registerSchemesAsPrivileged([{ scheme: 'app', privileges: { secure: true, standard: true } }]) 23 | 24 | function createWindow () { 25 | // Create the browser window. 26 | const size = screen.getPrimaryDisplay().workAreaSize 27 | const width = parseInt(size.height * 1.3) 28 | const height = parseInt(size.height * 0.8) 29 | win = new BrowserWindow({ 30 | width: width, 31 | height: height, 32 | frame: false, 33 | transparent: true, 34 | resizable: false, 35 | webPreferences: { 36 | nodeIntegration: true, 37 | webSecurity: false, 38 | experimentalFeatures: true 39 | } 40 | }) 41 | 42 | if (process.env.WEBPACK_DEV_SERVER_URL) { 43 | // Load the url of the dev server if in development mode 44 | win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) 45 | if (!process.env.IS_TEST) win.webContents.openDevTools() 46 | } else { 47 | createProtocol('app') 48 | // Load the index.html when not in development 49 | win.loadURL('app://./index.html') 50 | } 51 | 52 | win.on('closed', () => { 53 | win = null 54 | }) 55 | } 56 | 57 | // const winURL = process.env.NODE_ENV === 'development' 58 | // ? 'http://localhost:8080' 59 | // : `file://${__dirname}/index.html` 60 | 61 | // win.loadURL(winURL) 62 | 63 | // let loginWin 64 | // // 创建calendar窗口方法 65 | // function openloginWindow () { 66 | // loginWin = new BrowserWindow({ 67 | // width: 400, 68 | // height: 550, 69 | // parent: win, // win是主窗口 70 | // webPreferences: { 71 | // nodeIntegration: true 72 | // } 73 | // }) 74 | // loginWin.loadURL(winURL + '#/Login') 75 | // loginWin.on('closed', () => { loginWin = null }) 76 | // } 77 | // ipcMain.on('openloginWindow', e => 78 | // openloginWindow() 79 | // ) 80 | 81 | // Quit when all windows are closed. 82 | app.on('window-all-closed', () => { 83 | // On macOS it is common for applications and their menu bar 84 | // to stay active until the user quits explicitly with Cmd + Q 85 | if (process.platform !== 'darwin') { 86 | app.quit() 87 | } 88 | }) 89 | 90 | app.on('activate', () => { 91 | // On macOS it's common to re-create a window in the app when the 92 | // dock icon is clicked and there are no other windows open. 93 | if (win === null) { 94 | createWindow() 95 | } 96 | }) 97 | 98 | // This method will be called when Electron has finished 99 | // initialization and is ready to create browser windows. 100 | // Some APIs can only be used after this event occurs. 101 | app.on('ready', async () => { 102 | if (isDevelopment && !process.env.IS_TEST) { 103 | } 104 | tray = new Tray('resources/ico/ic_launcher.png') 105 | const trayContextMenu = Menu.buildFromTemplate([ 106 | { 107 | label: '打开', 108 | click: () => { 109 | win.show() 110 | } 111 | }, { 112 | label: '退出', 113 | click: () => { 114 | app.quit() 115 | } 116 | } 117 | ]) 118 | tray.setToolTip('Miguu') 119 | tray.on('click', () => { 120 | win.show() 121 | }) 122 | tray.on('right-click', () => { 123 | tray.popUpContextMenu(trayContextMenu) 124 | }) 125 | 126 | createWindow() 127 | }) 128 | 129 | app.commandLine.appendSwitch('wm-window-animations-disabled') 130 | 131 | ipcMain.on('close', e => 132 | win.hide() 133 | ) 134 | 135 | ipcMain.on('minimize', e => 136 | win.minimize() 137 | ) 138 | 139 | // 热搜接口 140 | // ipcMain.on('getHotlist', async e => { 141 | // const hotList = await searchMusic.hotSearch() 142 | // e.sender.send('sendHotlist', hotList) 143 | // }) 144 | 145 | ipcMain.on('suggestSearch', async (e, data) => { 146 | const suggestkey = await searchMusic.suggestSearch(data) 147 | e.returnValue = suggestkey 148 | }) 149 | 150 | ipcMain.on('searchmusic', async (e, data) => { 151 | const songsdata = await searchMusic.searchsongs(data) 152 | const singerdata = await searchMusic.searchsingers(songsdata.musics[0].artist) 153 | e.sender.send('singerdata', singerdata) 154 | e.sender.send('songsdata', songsdata) 155 | }) 156 | 157 | ipcMain.on('songcid', async (e, data) => { 158 | const songurl = await song.song(data) 159 | e.returnValue = songurl 160 | }) 161 | 162 | ipcMain.on('hotlist', async (e, data) => { 163 | const toplist = await top.top(data) 164 | e.returnValue = toplist 165 | }) 166 | 167 | // Exit cleanly on request from parent process in development mode. 168 | if (isDevelopment) { 169 | if (process.platform === 'win32') { 170 | process.on('message', data => { 171 | if (data === 'graceful-exit') { 172 | app.quit() 173 | } 174 | }) 175 | } else { 176 | process.on('SIGTERM', () => { 177 | app.quit() 178 | }) 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/components/A11A.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | 22 | 24 | -------------------------------------------------------------------------------- /src/components/Control.vue: -------------------------------------------------------------------------------- 1 | 86 | 87 | 315 | 316 | 499 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 88 | 89 | 146 | -------------------------------------------------------------------------------- /src/components/Hotlist.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 90 | 91 | 178 | -------------------------------------------------------------------------------- /src/components/Listdata.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 210 | 211 | 218 | -------------------------------------------------------------------------------- /src/components/Listheader.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 115 | 116 | 192 | -------------------------------------------------------------------------------- /src/components/Menu.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 113 | 114 | 208 | -------------------------------------------------------------------------------- /src/components/MyplayList.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 106 | 107 | 205 | -------------------------------------------------------------------------------- /src/components/PlaylistSection.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 97 | 98 | 186 | -------------------------------------------------------------------------------- /src/components/Searchdata.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 196 | 197 | 207 | -------------------------------------------------------------------------------- /src/components/Searchheader.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 42 | 43 | 121 | -------------------------------------------------------------------------------- /src/components/Swiper.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 80 | 81 | 89 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import axios from 'axios' 3 | import ElementUI from 'element-ui' 4 | import 'element-ui/lib/theme-chalk/index.css' 5 | import App from './App.vue' 6 | import router from './router' 7 | import store from './store' 8 | import './assets/iconfont/iconfont.css' 9 | import Contextmenu from 'vue-contextmenujs' 10 | 11 | Vue.use(ElementUI) 12 | Vue.use(Contextmenu) 13 | Vue.config.productionTip = false 14 | axios.defaults.withCredentials = true 15 | Vue.prototype.$axios = axios 16 | 17 | new Vue({ 18 | router, 19 | store, 20 | render: h => h(App) 21 | }).$mount('#app') 22 | -------------------------------------------------------------------------------- /src/migu_api/lyric.js: -------------------------------------------------------------------------------- 1 | const { migu_request } = require("../../../util/migu_request"); 2 | const APIError = require("../../../middlewares/rest").APIError; 3 | 4 | 5 | let lyric = async (ctx) => { 6 | if (ctx.request.method === 'GET') { 7 | var cid = ctx.request.query.cid || ''; 8 | // console.log(typeof ctx.request.query.limit, limit); 9 | } else if (ctx.request.method === 'POST') { 10 | var cid = ctx.request.body.cid || ''; 11 | } 12 | 13 | let result = await migu_request(`https://music.migu.cn/v3/api/music/audioPlayer/getLyric`, { 14 | copyrightId: cid.trim() 15 | }); 16 | 17 | ctx.rest(result.data); 18 | // try { 19 | // ctx.body = JSON.stringify(result.data); 20 | // } catch (error) { 21 | // ctx.body = JSON.stringify({ 22 | // error: '服务端数据解析错误', 23 | // status: 400 24 | // }) 25 | // } 26 | // ctx.type = 'application/json'; 27 | } 28 | 29 | module.exports = { 30 | lyric 31 | } -------------------------------------------------------------------------------- /src/migu_api/playlist.js: -------------------------------------------------------------------------------- 1 | const requestMigu = require('../utils/migu_request') 2 | 3 | // eslint-disable-next-line camelcase 4 | const playList_info = async (platlistId) => { 5 | const result = await requestMigu.requestMigu('https://m.music.migu.cn/migu/remoting/playlistcontents_query_tag', { 6 | playListType: 2, 7 | playListId: platlistId, 8 | contentCount: '30' 9 | }) 10 | return result.data 11 | } 12 | 13 | module.exports = { 14 | playList_info 15 | } 16 | -------------------------------------------------------------------------------- /src/migu_api/search.js: -------------------------------------------------------------------------------- 1 | const requestMigu = require('../utils/migu_request') 2 | 3 | const searchsongs = async (searchKey) => { 4 | const result = await requestMigu.requestMigu('https://m.music.migu.cn/migu/remoting/scr_search_tag', { 5 | rows: '30', 6 | type: '2', 7 | keyword: searchKey, 8 | pgc: '1' 9 | }) 10 | return result.data 11 | } 12 | 13 | const searchsingers = async (searchKey) => { 14 | const result = await requestMigu.requestMigu('https://m.music.migu.cn/migu/remoting/scr_search_tag', { 15 | rows: '15', 16 | type: '1', 17 | keyword: searchKey, 18 | pgc: '1' 19 | }) 20 | return result.data 21 | } 22 | 23 | const hotSearch = async () => { 24 | const result = await requestMigu.requestMigu('https://music.migu.cn/v3/api/search/hotwords') 25 | return result.data.data.hotwords[0].hotwordList.slice(0, 10) 26 | } 27 | 28 | const suggestSearch = async (searchKey) => { 29 | const result = await requestMigu.requestMigu('https://m.music.migu.cn/migu/remoting/autocomplete_tag', { 30 | keyword: searchKey 31 | }) 32 | return result.data.key 33 | } 34 | 35 | module.exports = { 36 | searchsongs, 37 | searchsingers, 38 | hotSearch, 39 | suggestSearch 40 | } 41 | -------------------------------------------------------------------------------- /src/migu_api/singer.js: -------------------------------------------------------------------------------- 1 | const { migu_request } = require("../../../util/migu_request"); 2 | const APIError = require("../../../middlewares/rest").APIError; 3 | 4 | 5 | // 歌手基本信息显示 6 | let singer_Info = async (ctx) => { 7 | if (ctx.request.method === 'GET') { 8 | var artistId = ctx.request.query.artistId || '18196'; 9 | // console.log(typeof ctx.request.query.limit, limit); 10 | } else if (ctx.request.method === 'POST') { 11 | var artistId = ctx.request.body.artistId || '18196'; 12 | } 13 | 14 | let result = await migu_request(`https://m.music.migu.cn/migu/remoting/cms_artist_detail_tag`, { 15 | artistId: artistId.trim() 16 | }); 17 | 18 | ctx.rest(result.data); 19 | // try { 20 | // ctx.body = JSON.stringify(result.data); 21 | // } catch (error) { 22 | // ctx.body = JSON.stringify({ 23 | // error: '服务端数据解析错误', 24 | // status: 400 25 | // }) 26 | // } 27 | // ctx.type = 'application/json'; 28 | } 29 | 30 | // 歌手的相关歌曲显示 31 | // 每一页数据都是 默认 20 首 32 | let singer_songList = async (ctx) => { 33 | if (ctx.request.method === 'GET') { 34 | var artistId = ctx.request.query.artistId || '112'; 35 | var offset = ctx.request.query.offset || '1'; 36 | // console.log(typeof ctx.request.query.limit, limit); 37 | } else if (ctx.request.method === 'POST') { 38 | var artistId = ctx.request.query.artistId || '112'; 39 | var offset = ctx.request.body.offset || '1'; 40 | } 41 | 42 | let result = await migu_request(`https://music.migu.cn/v3/music/artist/${artistId.trim()}/song`, { 43 | page: offset.trim() 44 | }); 45 | 46 | let re_str = /
.*?data-aid="(.*?)".*?data-mids="(.*?)".*?data-cids="(.*?)".*?data-share='(.*?)'.*?<\/a>/gs; 47 | let re_total = /全部歌曲((.*?))<\/span>/s; 48 | 49 | try { 50 | // ctx.body = JSON.stringify(result.data); 51 | let arr; 52 | let songList = []; 53 | while ((arr = re_str.exec(result.data)) !== null) { 54 | // console.log(arr[1], arr[2], arr[3], arr[4]); 55 | songList.push({ 56 | albumId: arr[1], 57 | id: arr[2], 58 | copyrightId: arr[3], 59 | al: JSON.parse(arr[4]) 60 | }); 61 | } 62 | let _result = { 63 | status: 200, 64 | total: re_total.exec(result.data)[1], 65 | num: 20, 66 | songList: songList 67 | }; 68 | ctx.body = JSON.stringify(_result); 69 | 70 | arr = null; 71 | _result = null; 72 | songList = null; 73 | } catch (error) { 74 | ctx.body = JSON.stringify({ 75 | error: '服务端数据解析错误', 76 | status: 400 77 | }) 78 | } 79 | ctx.type = 'application/json'; 80 | } 81 | 82 | module.exports = { 83 | singer_Info, 84 | singer_songList 85 | } -------------------------------------------------------------------------------- /src/migu_api/song.js: -------------------------------------------------------------------------------- 1 | const CrypotJs = require('crypto-js') 2 | const JsEncrypt = require('node-jsencrypt') 3 | const requestMigu = require('../utils/migu_request') 4 | 5 | const song = async (cid) => { 6 | const publicKey = `-----BEGIN PUBLIC KEY----- 7 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8asrfSaoOb4je+DSmKdriQJKW 8 | VJ2oDZrs3wi5W67m3LwTB9QVR+cE3XWU21Nx+YBxS0yun8wDcjgQvYt625ZCcgin 9 | 2ro/eOkNyUOTBIbuj9CvMnhUYiR61lC1f1IGbrSYYimqBVSjpifVufxtx/I3exRe 10 | ZosTByYp4Xwpb1+WAQIDAQAB 11 | -----END PUBLIC KEY-----` 12 | 13 | const o = `{"copyrightId":"${cid}","type":${'1'},"auditionsFlag":0}` 14 | const s = new JsEncrypt() 15 | s.setPublicKey(publicKey) 16 | const a = 1e3 * Math.random() 17 | const u = CrypotJs.SHA256(String(a)).toString() 18 | const c = CrypotJs.AES.encrypt(o, u).toString() 19 | const f = s.encrypt(u) 20 | 21 | const result = await requestMigu.requestMigu('http://music.migu.cn/v3/api/music/audioPlayer/getPlayInfo', { 22 | dataType: 2, 23 | data: c, 24 | secKey: f 25 | }) 26 | 27 | return result.data 28 | } 29 | 30 | module.exports = { 31 | song 32 | } 33 | -------------------------------------------------------------------------------- /src/migu_api/top.js: -------------------------------------------------------------------------------- 1 | const requestMigu = require('../utils/migu_request') 2 | 3 | const top = async (topId) => { 4 | const topList = { 5 | 0: 'jianjiao_newsong', 6 | 1: 'jianjiao_hotsong', 7 | 2: 'jianjiao_original' 8 | } 9 | 10 | const result = await requestMigu.requestMigu(`https://music.migu.cn/v3/music/top/${topList[topId]}`) 11 | const rule = / 38 | 74 | -------------------------------------------------------------------------------- /src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 13 | 47 | 48 | 60 | -------------------------------------------------------------------------------- /src/views/Mylist.vue: -------------------------------------------------------------------------------- 1 | 6 | 25 | 40 | -------------------------------------------------------------------------------- /src/views/Playlist.vue: -------------------------------------------------------------------------------- 1 | 7 | 31 | 32 | 52 | -------------------------------------------------------------------------------- /src/views/Searchlist.vue: -------------------------------------------------------------------------------- 1 | 7 | 29 | 30 | 50 | -------------------------------------------------------------------------------- /src/views/Sharelist.vue: -------------------------------------------------------------------------------- 1 | 54 | 147 | 188 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 第三方插件配置 3 | pluginOptions: { 4 | // vue-cli-plugin-electron-builder 配置 5 | electronBuilder: { 6 | nodeIntegration: true, 7 | builderOptions: { 8 | // 设置打包之后的应用名称 9 | productName: 'MiguuMusic', 10 | win: { 11 | icon: 'resources/ico/ic_launcher.ico', 12 | // 图标路径 windows系统中icon需要256*256的ico格式图片,更换应用图标亦在此处 13 | target: [{ 14 | // 打包成一个独立的 exe 安装程序 15 | target: 'nsis', 16 | // 这个意思是打出来32 bit + 64 bit的包,但是要注意:这样打包出来的安装包体积比较大 17 | arch: [ 18 | 'x64' 19 | // 'ia32' 20 | ] 21 | }] 22 | }, 23 | dmg: { 24 | contents: [ 25 | { 26 | x: 410, 27 | y: 150, 28 | type: 'link', 29 | path: '/Applications' 30 | }, 31 | { 32 | x: 130, 33 | y: 150, 34 | type: 'file' 35 | } 36 | ] 37 | }, 38 | linux: { 39 | // 设置linux的图标 40 | icon: 'resources/ico/ic_launcher.ico', 41 | target: 'AppImage' 42 | }, 43 | mac: { 44 | icon: 'resources/ico/ic_launcher.ico' 45 | }, 46 | files: ['**/*'], 47 | extraResources: { 48 | // 拷贝dll等静态文件到指定位置,否则打包之后回出现找不大dll的问题 49 | from: 'resources/', 50 | to: './' 51 | }, 52 | asar: false, 53 | nsis: { 54 | // 是否一键安装,建议为 false,可以让用户点击下一步、下一步、下一步的形式安装程序,如果为true,当用户双击构建好的程序,自动安装程序并打开,即:一键安装(one-click installer) 55 | oneClick: false, 56 | // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。 57 | allowElevation: true, 58 | // 允许修改安装目录,建议为 true,是否允许用户改变安装目录,默认是不允许 59 | allowToChangeInstallationDirectory: true, 60 | // 安装图标 61 | installerIcon: 'resources/ico/ic_launcher.ico', 62 | // 卸载图标 63 | uninstallerIcon: 'resources/ico/ic_launcher.ico', 64 | // 安装时头部图标 65 | installerHeaderIcon: 'resources/ico/ic_launcher.ico', 66 | // 创建桌面图标 67 | createDesktopShortcut: true, 68 | // 创建开始菜单图标 69 | createStartMenuShortcut: true 70 | } 71 | }, 72 | chainWebpackMainProcess: config => { 73 | config.plugin('define').tap(args => { 74 | args[0].IS_ELECTRON = true 75 | return args 76 | }) 77 | }, 78 | chainWebpackRendererProcess: config => { 79 | config.plugin('define').tap(args => { 80 | args[0].IS_ELECTRON = true 81 | return args 82 | }) 83 | } 84 | } 85 | } 86 | } 87 | --------------------------------------------------------------------------------