@neteasecloudmusicapienhanced/api 4.29.21 → 4.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.MD +9 -0
- package/interface.d.ts +2 -0
- package/module/musician_vip_tasks.js +11 -0
- package/module/user_playlist_collect.js +14 -0
- package/module/user_playlist_create.js +14 -0
- package/package.json +12 -8
- package/public/api.html +115 -49
- package/public/audio_match_demo/afp.js +2 -3
- package/public/audio_match_demo/index.html +213 -44
- package/public/avatar_update.html +296 -43
- package/public/cloud.html +148 -40
- package/public/docs/home.md +45 -0
- package/public/docs/index.html +3 -3
- package/public/eapi_decrypt.html +174 -36
- package/public/index.html +18 -18
- package/public/listen_together_host.html +294 -65
- package/public/login.html +190 -18
- package/public/playlist_cover_update.html +278 -31
- package/public/playlist_import.html +381 -226
- package/public/qrlogin-nocookie.html +170 -43
- package/public/qrlogin.html +170 -42
- package/public/unblock_test.html +95 -35
- package/public/voice_upload.html +256 -57
- package/server.js +1 -1
- package/util/client-sign.js +1 -1
- package/util/request.js +6 -6
|
@@ -5,45 +5,164 @@
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>二维码登录</title>
|
|
8
|
+
<style>
|
|
9
|
+
* {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
body {
|
|
16
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
background: #f5f5f5;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
padding: 20px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.container {
|
|
26
|
+
background: white;
|
|
27
|
+
border-radius: 12px;
|
|
28
|
+
padding: 48px;
|
|
29
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
30
|
+
max-width: 450px;
|
|
31
|
+
width: 100%;
|
|
32
|
+
text-align: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
h1 {
|
|
36
|
+
font-size: 24px;
|
|
37
|
+
font-weight: 600;
|
|
38
|
+
color: #333;
|
|
39
|
+
margin-bottom: 8px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.subtitle {
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
color: #666;
|
|
45
|
+
margin-bottom: 32px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.qr-wrapper {
|
|
49
|
+
display: inline-block;
|
|
50
|
+
padding: 16px;
|
|
51
|
+
background: #f9f9f9;
|
|
52
|
+
border-radius: 8px;
|
|
53
|
+
margin-bottom: 24px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#qrImg {
|
|
57
|
+
width: 200px;
|
|
58
|
+
height: 200px;
|
|
59
|
+
display: block;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.info {
|
|
63
|
+
text-align: left;
|
|
64
|
+
padding: 16px;
|
|
65
|
+
background: #f9f9f9;
|
|
66
|
+
border-radius: 6px;
|
|
67
|
+
font-family: 'Courier New', monospace;
|
|
68
|
+
font-size: 12px;
|
|
69
|
+
color: #666;
|
|
70
|
+
white-space: pre-wrap;
|
|
71
|
+
word-break: break-all;
|
|
72
|
+
max-height: 200px;
|
|
73
|
+
overflow-y: auto;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.status {
|
|
77
|
+
margin-top: 16px;
|
|
78
|
+
padding: 12px;
|
|
79
|
+
border-radius: 6px;
|
|
80
|
+
font-size: 14px;
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.status.waiting {
|
|
85
|
+
background: #fef3c7;
|
|
86
|
+
color: #92400e;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.status.success {
|
|
90
|
+
background: #d1fae5;
|
|
91
|
+
color: #065f46;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.status.error {
|
|
95
|
+
background: #fee2e2;
|
|
96
|
+
color: #991b1b;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.hint {
|
|
100
|
+
margin-top: 16px;
|
|
101
|
+
font-size: 13px;
|
|
102
|
+
color: #999;
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
8
105
|
</head>
|
|
9
106
|
|
|
10
107
|
<body>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
108
|
+
<div class="container">
|
|
109
|
+
<h1>二维码登录</h1>
|
|
110
|
+
<p class="subtitle">使用网易云音乐App扫描二维码登录</p>
|
|
111
|
+
|
|
112
|
+
<div class="qr-wrapper">
|
|
113
|
+
<img id="qrImg" src="" alt="二维码加载中..." />
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<div id="status" class="status waiting">等待扫描...</div>
|
|
16
117
|
|
|
118
|
+
<div id="info" class="info"></div>
|
|
119
|
+
|
|
120
|
+
<p class="hint">请打开网易云音乐App,扫描上方二维码完成登录</p>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
|
|
124
|
+
<script>
|
|
17
125
|
async function login() {
|
|
18
126
|
let timer
|
|
19
|
-
|
|
127
|
+
const statusDiv = document.getElementById('status')
|
|
20
128
|
const cookie = localStorage.getItem('cookie')
|
|
129
|
+
|
|
130
|
+
updateStatus('加载二维码...', 'waiting')
|
|
21
131
|
getLoginStatus(cookie)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const res = await axios({
|
|
135
|
+
url: `/login/qr/key?timestamp=${Date.now()}`,
|
|
136
|
+
})
|
|
137
|
+
const key = res.data.data.unikey
|
|
138
|
+
|
|
139
|
+
const res2 = await axios({
|
|
140
|
+
url: `/login/qr/create?key=${key}&platform=web&qrimg=true×tamp=${Date.now()}`,
|
|
141
|
+
})
|
|
142
|
+
document.querySelector('#qrImg').src = res2.data.data.qrimg
|
|
143
|
+
updateStatus('请扫描二维码', 'waiting')
|
|
144
|
+
|
|
145
|
+
timer = setInterval(async () => {
|
|
146
|
+
const statusRes = await checkStatus(key)
|
|
147
|
+
if (statusRes.code === 800) {
|
|
148
|
+
updateStatus('二维码已过期,请刷新页面', 'error')
|
|
149
|
+
clearInterval(timer)
|
|
150
|
+
} else if (statusRes.code === 801) {
|
|
151
|
+
updateStatus('二维码已扫描,请在手机上确认', 'waiting')
|
|
152
|
+
} else if (statusRes.code === 802) {
|
|
153
|
+
updateStatus('登录成功,正在保存信息...', 'waiting')
|
|
154
|
+
} else if (statusRes.code === 803) {
|
|
155
|
+
clearInterval(timer)
|
|
156
|
+
updateStatus('授权登录成功!', 'success')
|
|
157
|
+
await getLoginStatus(statusRes.cookie)
|
|
158
|
+
localStorage.setItem('cookie', statusRes.cookie)
|
|
159
|
+
}
|
|
160
|
+
}, 3000)
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error('登录失败:', error)
|
|
163
|
+
updateStatus('二维码加载失败,请刷新页面重试', 'error')
|
|
164
|
+
}
|
|
45
165
|
}
|
|
46
|
-
login()
|
|
47
166
|
|
|
48
167
|
async function checkStatus(key) {
|
|
49
168
|
const res = await axios({
|
|
@@ -51,22 +170,30 @@
|
|
|
51
170
|
})
|
|
52
171
|
return res.data
|
|
53
172
|
}
|
|
173
|
+
|
|
54
174
|
async function getLoginStatus(cookie = '') {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
175
|
+
try {
|
|
176
|
+
const res = await axios({
|
|
177
|
+
url: `/login/status?timestamp=${Date.now()}`,
|
|
178
|
+
method: 'post',
|
|
179
|
+
data: {
|
|
180
|
+
cookie,
|
|
181
|
+
},
|
|
182
|
+
})
|
|
183
|
+
document.querySelector('#info').textContent = JSON.stringify(res.data, null, 2)
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error('获取登录状态失败:', error)
|
|
186
|
+
}
|
|
63
187
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
188
|
+
|
|
189
|
+
function updateStatus(message, type) {
|
|
190
|
+
const statusDiv = document.getElementById('status')
|
|
191
|
+
statusDiv.textContent = message
|
|
192
|
+
statusDiv.className = 'status ' + type
|
|
68
193
|
}
|
|
69
|
-
|
|
194
|
+
|
|
195
|
+
login()
|
|
196
|
+
</script>
|
|
70
197
|
</body>
|
|
71
198
|
|
|
72
199
|
</html>
|
package/public/qrlogin.html
CHANGED
|
@@ -5,44 +5,164 @@
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>二维码登录</title>
|
|
8
|
+
<style>
|
|
9
|
+
* {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
body {
|
|
16
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
background: #f5f5f5;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
padding: 20px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.container {
|
|
26
|
+
background: white;
|
|
27
|
+
border-radius: 12px;
|
|
28
|
+
padding: 48px;
|
|
29
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
30
|
+
max-width: 450px;
|
|
31
|
+
width: 100%;
|
|
32
|
+
text-align: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
h1 {
|
|
36
|
+
font-size: 24px;
|
|
37
|
+
font-weight: 600;
|
|
38
|
+
color: #333;
|
|
39
|
+
margin-bottom: 8px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.subtitle {
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
color: #666;
|
|
45
|
+
margin-bottom: 32px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.qr-wrapper {
|
|
49
|
+
display: inline-block;
|
|
50
|
+
padding: 16px;
|
|
51
|
+
background: #f9f9f9;
|
|
52
|
+
border-radius: 8px;
|
|
53
|
+
margin-bottom: 24px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#qrImg {
|
|
57
|
+
width: 200px;
|
|
58
|
+
height: 200px;
|
|
59
|
+
display: block;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.info {
|
|
63
|
+
text-align: left;
|
|
64
|
+
padding: 16px;
|
|
65
|
+
background: #f9f9f9;
|
|
66
|
+
border-radius: 6px;
|
|
67
|
+
font-family: 'Courier New', monospace;
|
|
68
|
+
font-size: 12px;
|
|
69
|
+
color: #666;
|
|
70
|
+
white-space: pre-wrap;
|
|
71
|
+
word-break: break-all;
|
|
72
|
+
max-height: 200px;
|
|
73
|
+
overflow-y: auto;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.status {
|
|
77
|
+
margin-top: 16px;
|
|
78
|
+
padding: 12px;
|
|
79
|
+
border-radius: 6px;
|
|
80
|
+
font-size: 14px;
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.status.waiting {
|
|
85
|
+
background: #fef3c7;
|
|
86
|
+
color: #92400e;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.status.success {
|
|
90
|
+
background: #d1fae5;
|
|
91
|
+
color: #065f46;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.status.error {
|
|
95
|
+
background: #fee2e2;
|
|
96
|
+
color: #991b1b;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.hint {
|
|
100
|
+
margin-top: 16px;
|
|
101
|
+
font-size: 13px;
|
|
102
|
+
color: #999;
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
8
105
|
</head>
|
|
9
106
|
|
|
10
107
|
<body>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
108
|
+
<div class="container">
|
|
109
|
+
<h1>二维码登录</h1>
|
|
110
|
+
<p class="subtitle">使用网易云音乐App扫描二维码登录</p>
|
|
111
|
+
|
|
112
|
+
<div class="qr-wrapper">
|
|
113
|
+
<img id="qrImg" src="" alt="二维码加载中..." />
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<div id="status" class="status waiting">等待扫描...</div>
|
|
117
|
+
|
|
118
|
+
<div id="info" class="info"></div>
|
|
119
|
+
|
|
120
|
+
<p class="hint">请打开网易云音乐App,扫描上方二维码完成登录</p>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
|
|
15
124
|
<script>
|
|
16
125
|
async function login() {
|
|
17
126
|
let timer
|
|
18
|
-
|
|
127
|
+
const statusDiv = document.getElementById('status')
|
|
19
128
|
const cookie = localStorage.getItem('cookie')
|
|
129
|
+
|
|
130
|
+
updateStatus('加载二维码...', 'waiting')
|
|
20
131
|
getLoginStatus(cookie)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const res = await axios({
|
|
135
|
+
url: `/login/qr/key?timestamp=${Date.now()}`,
|
|
136
|
+
})
|
|
137
|
+
const key = res.data.data.unikey
|
|
138
|
+
|
|
139
|
+
const res2 = await axios({
|
|
140
|
+
url: `/login/qr/create?key=${key}&platform=web&qrimg=true×tamp=${Date.now()}&ua=pc`,
|
|
141
|
+
})
|
|
142
|
+
document.querySelector('#qrImg').src = res2.data.data.qrimg
|
|
143
|
+
updateStatus('请扫描二维码', 'waiting')
|
|
144
|
+
|
|
145
|
+
timer = setInterval(async () => {
|
|
146
|
+
const statusRes = await checkStatus(key)
|
|
147
|
+
if (statusRes.code === 800) {
|
|
148
|
+
updateStatus('二维码已过期,请刷新页面', 'error')
|
|
149
|
+
clearInterval(timer)
|
|
150
|
+
} else if (statusRes.code === 801) {
|
|
151
|
+
updateStatus('二维码已扫描,请在手机上确认', 'waiting')
|
|
152
|
+
} else if (statusRes.code === 802) {
|
|
153
|
+
updateStatus('登录成功,正在保存信息...', 'waiting')
|
|
154
|
+
} else if (statusRes.code === 803) {
|
|
155
|
+
clearInterval(timer)
|
|
156
|
+
updateStatus('授权登录成功!', 'success')
|
|
157
|
+
await getLoginStatus(statusRes.cookie)
|
|
158
|
+
localStorage.setItem('cookie', statusRes.cookie)
|
|
159
|
+
}
|
|
160
|
+
}, 3000)
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error('登录失败:', error)
|
|
163
|
+
updateStatus('二维码加载失败,请刷新页面重试', 'error')
|
|
164
|
+
}
|
|
44
165
|
}
|
|
45
|
-
login()
|
|
46
166
|
|
|
47
167
|
async function checkStatus(key) {
|
|
48
168
|
const res = await axios({
|
|
@@ -50,22 +170,30 @@
|
|
|
50
170
|
})
|
|
51
171
|
return res.data
|
|
52
172
|
}
|
|
173
|
+
|
|
53
174
|
async function getLoginStatus(cookie = '') {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
175
|
+
try {
|
|
176
|
+
const res = await axios({
|
|
177
|
+
url: `/login/status?timestamp=${Date.now()}&ua=pc`,
|
|
178
|
+
method: 'post',
|
|
179
|
+
data: {
|
|
180
|
+
cookie,
|
|
181
|
+
},
|
|
182
|
+
})
|
|
183
|
+
document.querySelector('#info').textContent = JSON.stringify(res.data, null, 2)
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error('获取登录状态失败:', error)
|
|
186
|
+
}
|
|
62
187
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
188
|
+
|
|
189
|
+
function updateStatus(message, type) {
|
|
190
|
+
const statusDiv = document.getElementById('status')
|
|
191
|
+
statusDiv.textContent = message
|
|
192
|
+
statusDiv.className = 'status ' + type
|
|
67
193
|
}
|
|
68
|
-
|
|
194
|
+
|
|
195
|
+
login()
|
|
196
|
+
</script>
|
|
69
197
|
</body>
|
|
70
198
|
|
|
71
199
|
</html>
|
package/public/unblock_test.html
CHANGED
|
@@ -5,79 +5,136 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>音乐解灰测试</title>
|
|
7
7
|
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
body {
|
|
9
|
-
font-family:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
padding:
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
16
|
+
min-height: 100vh;
|
|
17
|
+
background: #f5f5f5;
|
|
18
|
+
padding: 20px;
|
|
13
19
|
}
|
|
20
|
+
|
|
14
21
|
.container {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
max-width: 800px;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
background: white;
|
|
25
|
+
border-radius: 12px;
|
|
26
|
+
padding: 32px;
|
|
27
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
h1 {
|
|
31
|
+
font-size: 24px;
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
color: #333;
|
|
34
|
+
margin-bottom: 24px;
|
|
18
35
|
}
|
|
36
|
+
|
|
19
37
|
.form-group {
|
|
20
|
-
margin-bottom:
|
|
38
|
+
margin-bottom: 20px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
label {
|
|
42
|
+
display: block;
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
font-weight: 500;
|
|
45
|
+
color: #555;
|
|
46
|
+
margin-bottom: 8px;
|
|
21
47
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
48
|
+
|
|
49
|
+
input {
|
|
50
|
+
width: 100%;
|
|
51
|
+
padding: 12px 14px;
|
|
52
|
+
border: 1px solid #ddd;
|
|
53
|
+
border-radius: 6px;
|
|
54
|
+
font-size: 15px;
|
|
55
|
+
outline: none;
|
|
27
56
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
gap: 5px;
|
|
57
|
+
|
|
58
|
+
input:focus {
|
|
59
|
+
border-color: #333;
|
|
32
60
|
}
|
|
61
|
+
|
|
33
62
|
button {
|
|
34
|
-
background
|
|
63
|
+
background: #333;
|
|
35
64
|
color: white;
|
|
36
|
-
padding:
|
|
65
|
+
padding: 14px 28px;
|
|
37
66
|
border: none;
|
|
38
|
-
border-radius:
|
|
67
|
+
border-radius: 6px;
|
|
68
|
+
font-size: 15px;
|
|
69
|
+
font-weight: 500;
|
|
39
70
|
cursor: pointer;
|
|
71
|
+
transition: background 0.2s ease;
|
|
40
72
|
}
|
|
73
|
+
|
|
41
74
|
button:hover {
|
|
42
|
-
background
|
|
75
|
+
background: #555;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
button:disabled {
|
|
79
|
+
background: #999;
|
|
80
|
+
cursor: not-allowed;
|
|
43
81
|
}
|
|
82
|
+
|
|
44
83
|
#result {
|
|
45
|
-
margin-top:
|
|
46
|
-
padding:
|
|
47
|
-
|
|
48
|
-
border-radius:
|
|
84
|
+
margin-top: 24px;
|
|
85
|
+
padding: 16px;
|
|
86
|
+
background: #f9f9f9;
|
|
87
|
+
border-radius: 6px;
|
|
88
|
+
border: 1px solid #eee;
|
|
89
|
+
font-family: 'Courier New', monospace;
|
|
90
|
+
font-size: 13px;
|
|
49
91
|
white-space: pre-wrap;
|
|
92
|
+
word-break: break-all;
|
|
93
|
+
min-height: 100px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.hint {
|
|
97
|
+
font-size: 12px;
|
|
98
|
+
color: #999;
|
|
99
|
+
margin-top: 4px;
|
|
50
100
|
}
|
|
51
101
|
</style>
|
|
52
102
|
</head>
|
|
53
103
|
<body>
|
|
54
104
|
<div class="container">
|
|
55
105
|
<h1>音乐解灰测试</h1>
|
|
106
|
+
|
|
56
107
|
<div class="form-group">
|
|
57
|
-
<label for="songId">音乐 ID
|
|
58
|
-
<input type="number" id="songId" placeholder="请输入音乐ID"
|
|
108
|
+
<label for="songId">音乐 ID</label>
|
|
109
|
+
<input type="number" id="songId" placeholder="请输入音乐ID" />
|
|
110
|
+
<div class="hint">例如: 1372188635</div>
|
|
59
111
|
</div>
|
|
112
|
+
|
|
60
113
|
<div class="form-group">
|
|
61
|
-
<label for="sources"
|
|
62
|
-
<input type="text" id="sources" placeholder="请输入音源
|
|
114
|
+
<label for="sources">音源列表(可选)</label>
|
|
115
|
+
<input type="text" id="sources" placeholder="请输入音源" />
|
|
116
|
+
<div class="hint">例如: kuwo, kugou, migu</div>
|
|
63
117
|
</div>
|
|
64
|
-
|
|
118
|
+
|
|
119
|
+
<button id="testBtn" onclick="testSong()">开始测试</button>
|
|
120
|
+
|
|
65
121
|
<div id="result"></div>
|
|
66
122
|
</div>
|
|
67
123
|
|
|
68
124
|
<script>
|
|
69
125
|
async function testSong() {
|
|
70
126
|
const songId = document.getElementById('songId').value;
|
|
127
|
+
const sources = document.getElementById('sources').value;
|
|
128
|
+
const testBtn = document.getElementById('testBtn');
|
|
129
|
+
const resultDiv = document.getElementById('result');
|
|
130
|
+
|
|
71
131
|
if (!songId) {
|
|
72
132
|
alert('请输入音乐ID');
|
|
73
133
|
return;
|
|
74
134
|
}
|
|
75
135
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const resultDiv = document.getElementById('result');
|
|
136
|
+
testBtn.disabled = true;
|
|
137
|
+
testBtn.textContent = '测试中...';
|
|
81
138
|
resultDiv.textContent = '正在请求...';
|
|
82
139
|
|
|
83
140
|
try {
|
|
@@ -86,6 +143,9 @@
|
|
|
86
143
|
resultDiv.textContent = JSON.stringify(data, null, 2);
|
|
87
144
|
} catch (error) {
|
|
88
145
|
resultDiv.textContent = `请求失败: ${error.message}`;
|
|
146
|
+
} finally {
|
|
147
|
+
testBtn.disabled = false;
|
|
148
|
+
testBtn.textContent = '开始测试';
|
|
89
149
|
}
|
|
90
150
|
}
|
|
91
151
|
</script>
|