├── .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 |
2 |
8 |
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 |
21 |
22 | - Unicode
23 | - Font class
24 | - Symbol
25 |
26 |
27 |
查看项目
28 |
29 |
30 |
31 |
32 |
33 |
34 | -
35 |
36 |
电脑
37 | 
38 |
39 |
40 | -
41 |
42 |
歌单
43 | 
44 |
45 |
46 | -
47 |
48 |
位置
49 | 
50 |
51 |
52 | -
53 |
54 |
历史
55 | 
56 |
57 |
58 | -
59 |
60 |
下一首
61 | 
62 |
63 |
64 | -
65 |
66 |
播放
67 | 
68 |
69 |
70 | -
71 |
72 |
播放
73 | 
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">3</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 |
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 |
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 |
2 |
3 |
4 |
5 |
6 |
21 |
22 |
24 |
--------------------------------------------------------------------------------
/src/components/Control.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
12 |
13 |
23 |
24 |
25 |
![歌曲图片]()
28 |
29 |
30 |
{{ this.$store.state.songData.songName }}
31 |
{{ this.$store.state.songData.singerName }}
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
54 |
55 |
58 |
59 |
60 |
61 |
62 |
63 |
67 |
74 |
75 |
{{ index+1>9 ? index+1 : '0'+(index+1) }}
76 |
{{ item.songName }}
77 |
78 |
{{ item.singerName }}
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
315 |
316 |
499 |
--------------------------------------------------------------------------------
/src/components/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
88 |
89 |
146 |
--------------------------------------------------------------------------------
/src/components/Hotlist.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
13 |
14 |
![]()
15 |
![]()
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
{{ index+1>9 ? index+1 : '0'+(index+1) }}
27 |
28 |
![]()
29 |
30 |
{{ item.name }}
31 |
32 |
{{ item.singer }}
33 |
34 |
35 |
36 |
37 |
38 |
90 |
91 |
178 |
--------------------------------------------------------------------------------
/src/components/Listdata.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
24 |
27 |
28 |
31 |
32 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
210 |
211 |
218 |
--------------------------------------------------------------------------------
/src/components/Listheader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
7 |
8 |
9 |
10 |
![]()
13 |
14 |
15 |
{{ this.$route.query.header.name }}
16 |
17 |
全部播放
18 |
收藏
19 |
24 |
25 | 创建歌单
26 |
27 |
29 |
30 |
31 | 添加到
32 |
33 |
···更多
34 |
35 |
36 |
37 |
38 |
39 |
40 |
115 |
116 |
192 |
--------------------------------------------------------------------------------
/src/components/Menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |

11 |
12 |
21 |
22 |
23 |
24 |
25 |
113 |
114 |
208 |
--------------------------------------------------------------------------------
/src/components/MyplayList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
11 |
![item.name]()
16 |

17 |
18 |

19 |
20 |
{{ item.header.name }}
21 |
22 |
23 |
24 |
25 |

26 |
创建歌单
27 |
28 |
29 |
30 |
31 |
32 |
33 |
106 |
107 |
205 |
--------------------------------------------------------------------------------
/src/components/PlaylistSection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
11 |
12 |
![item.name]()
18 |
19 |

20 |
{{ item.name }}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
97 |
98 |
186 |
--------------------------------------------------------------------------------
/src/components/Searchdata.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
22 |
23 |
26 |
27 |
30 |
31 |
34 |
35 |
36 |
37 |
38 |
39 |
196 |
197 |
207 |
--------------------------------------------------------------------------------
/src/components/Searchheader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
7 |
8 |
9 |
10 |
![]()
13 |
14 |
15 |
{{ singerdata.title }}
16 |
专辑 {{ singerdata.albumNum }} 歌曲 {{ singerdata.songNum }}
17 |
18 |
19 |
20 |
21 |
22 |
42 |
43 |
121 |
--------------------------------------------------------------------------------
/src/components/Swiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
12 |
19 |
20 |
21 |
22 |
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 |
2 |
3 |
10 |
11 |
12 |
13 |
47 |
48 |
60 |
--------------------------------------------------------------------------------
/src/views/Mylist.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
25 |
40 |
--------------------------------------------------------------------------------
/src/views/Playlist.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
31 |
32 |
52 |
--------------------------------------------------------------------------------
/src/views/Searchlist.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
29 |
30 |
50 |
--------------------------------------------------------------------------------
/src/views/Sharelist.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
![]()
13 |
14 |
共{{shareList[0].data.length}}首音乐
15 |
16 |
17 |
21 |
22 |
23 |
从咪咕手机端导入歌单
24 |
25 | 导入
26 |
27 |
28 |
29 |
30 |
31 | 如何从手机导入歌单
32 |
33 |
34 |
41 |
42 | {{item.title}}
43 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
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 |
--------------------------------------------------------------------------------