@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,67 +5,320 @@
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>更新头像</title>
|
|
8
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
9
|
+
<style>
|
|
10
|
+
* {
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
background: #f5f5f5;
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
padding: 20px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.container {
|
|
27
|
+
background: white;
|
|
28
|
+
border-radius: 12px;
|
|
29
|
+
padding: 40px;
|
|
30
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
31
|
+
max-width: 400px;
|
|
32
|
+
width: 100%;
|
|
33
|
+
text-align: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
h1 {
|
|
37
|
+
font-size: 24px;
|
|
38
|
+
font-weight: 600;
|
|
39
|
+
color: #333;
|
|
40
|
+
margin-bottom: 8px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.subtitle {
|
|
44
|
+
font-size: 14px;
|
|
45
|
+
color: #666;
|
|
46
|
+
margin-bottom: 32px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.avatar-wrapper {
|
|
50
|
+
position: relative;
|
|
51
|
+
width: 160px;
|
|
52
|
+
height: 160px;
|
|
53
|
+
margin: 0 auto 32px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.avatar {
|
|
57
|
+
width: 100%;
|
|
58
|
+
height: 100%;
|
|
59
|
+
border-radius: 50%;
|
|
60
|
+
object-fit: cover;
|
|
61
|
+
border: 3px solid #fff;
|
|
62
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.avatar-wrapper.loading .avatar {
|
|
66
|
+
opacity: 0.5;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.loading-overlay {
|
|
70
|
+
position: absolute;
|
|
71
|
+
top: 0;
|
|
72
|
+
left: 0;
|
|
73
|
+
width: 100%;
|
|
74
|
+
height: 100%;
|
|
75
|
+
border-radius: 50%;
|
|
76
|
+
background: rgba(255, 255, 255, 0.9);
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
opacity: 0;
|
|
81
|
+
transition: opacity 0.2s ease;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.avatar-wrapper.loading .loading-overlay {
|
|
85
|
+
opacity: 1;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.spinner {
|
|
89
|
+
width: 40px;
|
|
90
|
+
height: 40px;
|
|
91
|
+
border: 3px solid #e0e0e0;
|
|
92
|
+
border-top-color: #333;
|
|
93
|
+
border-radius: 50%;
|
|
94
|
+
animation: spin 0.8s linear infinite;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@keyframes spin {
|
|
98
|
+
to {
|
|
99
|
+
transform: rotate(360deg);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.upload-btn {
|
|
104
|
+
display: inline-block;
|
|
105
|
+
position: relative;
|
|
106
|
+
padding: 12px 28px;
|
|
107
|
+
background: #333;
|
|
108
|
+
color: white;
|
|
109
|
+
font-size: 15px;
|
|
110
|
+
font-weight: 500;
|
|
111
|
+
border-radius: 6px;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
transition: background 0.2s ease;
|
|
114
|
+
border: none;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.upload-btn:hover {
|
|
118
|
+
background: #555;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.upload-btn input[type="file"] {
|
|
122
|
+
position: absolute;
|
|
123
|
+
top: 0;
|
|
124
|
+
left: 0;
|
|
125
|
+
width: 100%;
|
|
126
|
+
height: 100%;
|
|
127
|
+
opacity: 0;
|
|
128
|
+
cursor: pointer;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.login-link {
|
|
132
|
+
display: block;
|
|
133
|
+
margin-top: 24px;
|
|
134
|
+
color: #666;
|
|
135
|
+
font-size: 14px;
|
|
136
|
+
text-decoration: none;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.login-link:hover {
|
|
140
|
+
color: #333;
|
|
141
|
+
text-decoration: underline;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.toast {
|
|
145
|
+
position: fixed;
|
|
146
|
+
bottom: 24px;
|
|
147
|
+
left: 50%;
|
|
148
|
+
transform: translateX(-50%) translateY(100px);
|
|
149
|
+
padding: 12px 20px;
|
|
150
|
+
border-radius: 6px;
|
|
151
|
+
font-size: 14px;
|
|
152
|
+
font-weight: 500;
|
|
153
|
+
color: white;
|
|
154
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
155
|
+
opacity: 0;
|
|
156
|
+
transition: all 0.3s ease;
|
|
157
|
+
z-index: 1000;
|
|
158
|
+
max-width: 90%;
|
|
159
|
+
text-align: center;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.toast.show {
|
|
163
|
+
transform: translateX(-50%) translateY(0);
|
|
164
|
+
opacity: 1;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.toast.success {
|
|
168
|
+
background: #10b981;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.toast.error {
|
|
172
|
+
background: #ef4444;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.toast.info {
|
|
176
|
+
background: #3b82f6;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.hint {
|
|
180
|
+
margin-top: 20px;
|
|
181
|
+
font-size: 12px;
|
|
182
|
+
color: #999;
|
|
183
|
+
}
|
|
184
|
+
</style>
|
|
8
185
|
</head>
|
|
9
186
|
|
|
10
187
|
<body>
|
|
11
|
-
<div>
|
|
12
|
-
<
|
|
13
|
-
|
|
188
|
+
<div class="container">
|
|
189
|
+
<h1>更新头像</h1>
|
|
190
|
+
<p class="subtitle">选择一张图片作为您的新头像</p>
|
|
191
|
+
|
|
192
|
+
<div class="avatar-wrapper" id="avatarWrapper">
|
|
193
|
+
<img id="avatar" class="avatar" src="" alt="头像" />
|
|
194
|
+
<div class="loading-overlay">
|
|
195
|
+
<div class="spinner"></div>
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
<label class="upload-btn">
|
|
200
|
+
选择图片
|
|
201
|
+
<input id="file" type="file" accept="image/*" />
|
|
202
|
+
</label>
|
|
203
|
+
|
|
204
|
+
<a href="/qrlogin-nocookie.html" class="login-link">
|
|
205
|
+
还没有登录?点击登录
|
|
14
206
|
</a>
|
|
207
|
+
|
|
208
|
+
<p class="hint">支持 JPG、PNG 格式,建议尺寸 200x200</p>
|
|
15
209
|
</div>
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
210
|
+
|
|
211
|
+
<div id="toast" class="toast"></div>
|
|
212
|
+
|
|
213
|
+
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
|
|
20
214
|
<script>
|
|
21
215
|
main()
|
|
22
216
|
|
|
23
217
|
async function main() {
|
|
24
|
-
document.querySelector('input[type="file"]')
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
218
|
+
const fileInput = document.querySelector('input[type="file"]');
|
|
219
|
+
const avatarWrapper = document.getElementById('avatarWrapper');
|
|
220
|
+
|
|
221
|
+
fileInput.addEventListener('change', function(e) {
|
|
222
|
+
const file = this.files[0];
|
|
223
|
+
if (file) {
|
|
224
|
+
upload(file);
|
|
225
|
+
}
|
|
226
|
+
}, false);
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
showToast('正在加载头像...', 'info');
|
|
230
|
+
avatarWrapper.classList.add('loading');
|
|
231
|
+
const res = await axios({
|
|
232
|
+
url: `/user/detail?uid=32953014×tamp=${Date.now()}`,
|
|
233
|
+
withCredentials: true
|
|
234
|
+
});
|
|
235
|
+
document.querySelector('#avatar').src = res.data.profile.avatarUrl;
|
|
236
|
+
hideToast();
|
|
237
|
+
} catch (error) {
|
|
238
|
+
hideToast();
|
|
239
|
+
showToast('加载头像失败,请刷新页面重试', 'error');
|
|
240
|
+
console.error('加载头像失败:', error);
|
|
241
|
+
} finally {
|
|
242
|
+
avatarWrapper.classList.remove('loading');
|
|
243
|
+
}
|
|
37
244
|
}
|
|
38
245
|
|
|
39
246
|
async function upload(file) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
247
|
+
const avatarWrapper = document.getElementById('avatarWrapper');
|
|
248
|
+
|
|
249
|
+
if (!file.type.startsWith('image/')) {
|
|
250
|
+
showToast('请选择图片文件', 'error');
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
showToast('正在上传头像...', 'info');
|
|
256
|
+
avatarWrapper.classList.add('loading');
|
|
257
|
+
|
|
258
|
+
var formData = new FormData();
|
|
259
|
+
formData.append('imgFile', file);
|
|
260
|
+
const imgSize = await getImgSize(file);
|
|
261
|
+
|
|
262
|
+
const res = await axios({
|
|
263
|
+
method: 'post',
|
|
264
|
+
url: `/avatar/upload?cookie=${localStorage.getItem('cookie')}&imgSize=${imgSize.width}&imgX=0&imgY=0×tamp=${Date.now()}`,
|
|
265
|
+
headers: {
|
|
266
|
+
'Content-Type': 'multipart/form-data',
|
|
267
|
+
},
|
|
268
|
+
data: formData,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
document.querySelector('#avatar').src = res.data.data.url;
|
|
272
|
+
showToast('头像更新成功!', 'success');
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error('上传失败:', error);
|
|
275
|
+
const errorMsg = error.response?.data?.message || error.message || '上传失败,请重试';
|
|
276
|
+
showToast(errorMsg, 'error');
|
|
277
|
+
} finally {
|
|
278
|
+
avatarWrapper.classList.remove('loading');
|
|
279
|
+
}
|
|
53
280
|
}
|
|
281
|
+
|
|
54
282
|
function getImgSize(file) {
|
|
55
283
|
return new Promise((resolve, reject) => {
|
|
56
|
-
let reader = new FileReader()
|
|
57
|
-
reader.readAsDataURL(file)
|
|
58
|
-
reader.onload = function
|
|
59
|
-
let image = new Image()
|
|
60
|
-
image.src = theFile.target.result
|
|
61
|
-
image.onload = function
|
|
284
|
+
let reader = new FileReader();
|
|
285
|
+
reader.readAsDataURL(file);
|
|
286
|
+
reader.onload = function(theFile) {
|
|
287
|
+
let image = new Image();
|
|
288
|
+
image.src = theFile.target.result;
|
|
289
|
+
image.onload = function() {
|
|
62
290
|
resolve({
|
|
63
291
|
width: this.width,
|
|
64
292
|
height: this.height,
|
|
65
|
-
})
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
293
|
+
});
|
|
294
|
+
};
|
|
295
|
+
image.onerror = function() {
|
|
296
|
+
reject(new Error('图片加载失败'));
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
reader.onerror = function() {
|
|
300
|
+
reject(new Error('文件读取失败'));
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function showToast(message, type = 'info') {
|
|
306
|
+
const toast = document.getElementById('toast');
|
|
307
|
+
toast.textContent = message;
|
|
308
|
+
toast.className = `toast ${type}`;
|
|
309
|
+
|
|
310
|
+
requestAnimationFrame(() => {
|
|
311
|
+
toast.classList.add('show');
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
setTimeout(() => {
|
|
315
|
+
toast.classList.remove('show');
|
|
316
|
+
}, 3000);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function hideToast() {
|
|
320
|
+
const toast = document.getElementById('toast');
|
|
321
|
+
toast.classList.remove('show');
|
|
69
322
|
}
|
|
70
323
|
</script>
|
|
71
324
|
</body>
|
package/public/cloud.html
CHANGED
|
@@ -4,26 +4,135 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>云盘上传</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
16
|
+
min-height: 100vh;
|
|
17
|
+
background: #f5f5f5;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.container {
|
|
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;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.login-link {
|
|
38
|
+
display: block;
|
|
39
|
+
margin-bottom: 24px;
|
|
40
|
+
color: #666;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
text-decoration: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.login-link:hover {
|
|
46
|
+
color: #333;
|
|
47
|
+
text-decoration: underline;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.upload-section {
|
|
51
|
+
margin-bottom: 32px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.upload-btn {
|
|
55
|
+
display: inline-block;
|
|
56
|
+
padding: 12px 28px;
|
|
57
|
+
background: #333;
|
|
58
|
+
color: white;
|
|
59
|
+
font-size: 15px;
|
|
60
|
+
font-weight: 500;
|
|
61
|
+
border-radius: 6px;
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
transition: background 0.2s ease;
|
|
64
|
+
border: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.upload-btn:hover {
|
|
68
|
+
background: #555;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.upload-btn input[type="file"] {
|
|
72
|
+
display: none;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.songs-list {
|
|
76
|
+
list-style: none;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.song-item {
|
|
80
|
+
padding: 12px 16px;
|
|
81
|
+
border-bottom: 1px solid #eee;
|
|
82
|
+
font-size: 14px;
|
|
83
|
+
color: #333;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.song-item:last-child {
|
|
87
|
+
border-bottom: none;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.empty-state {
|
|
91
|
+
text-align: center;
|
|
92
|
+
padding: 40px 20px;
|
|
93
|
+
color: #999;
|
|
94
|
+
font-size: 14px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.loading {
|
|
98
|
+
text-align: center;
|
|
99
|
+
padding: 20px;
|
|
100
|
+
color: #666;
|
|
101
|
+
}
|
|
102
|
+
</style>
|
|
7
103
|
</head>
|
|
8
104
|
|
|
9
105
|
<body>
|
|
10
|
-
<div>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
106
|
+
<div class="container">
|
|
107
|
+
<h1>云盘上传</h1>
|
|
108
|
+
<a href="/qrlogin-nocookie.html" class="login-link">还没登录?点击登录</a>
|
|
109
|
+
|
|
110
|
+
<div class="upload-section">
|
|
111
|
+
<label class="upload-btn">
|
|
112
|
+
选择文件(支持多选)
|
|
113
|
+
<input id="file" type="file" multiple accept="audio/*" />
|
|
114
|
+
</label>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div id="app">
|
|
118
|
+
<div v-if="loading" class="loading">加载中...</div>
|
|
119
|
+
<ul v-else-if="songs.length > 0" class="songs-list">
|
|
120
|
+
<li v-for="(item, index) in songs" :key="index" class="song-item">
|
|
121
|
+
{{ item.songName }}
|
|
122
|
+
</li>
|
|
123
|
+
</ul>
|
|
124
|
+
<div v-else class="empty-state">暂无云盘歌曲</div>
|
|
125
|
+
</div>
|
|
18
126
|
</div>
|
|
19
127
|
|
|
20
128
|
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
|
|
21
|
-
<script src="https://fastly.jsdelivr.net/npm/vue"></script>
|
|
129
|
+
<script src="https://fastly.jsdelivr.net/npm/vue@3"></script>
|
|
22
130
|
<script>
|
|
23
131
|
const app = Vue.createApp({
|
|
24
132
|
data() {
|
|
25
133
|
return {
|
|
26
134
|
songs: [],
|
|
135
|
+
loading: false,
|
|
27
136
|
}
|
|
28
137
|
},
|
|
29
138
|
created() {
|
|
@@ -31,19 +140,23 @@
|
|
|
31
140
|
},
|
|
32
141
|
methods: {
|
|
33
142
|
getData() {
|
|
34
|
-
|
|
35
|
-
const _this = this
|
|
143
|
+
this.loading = true
|
|
36
144
|
axios({
|
|
37
|
-
url: `/user/cloud?time=${Date.now()}&cookie=${localStorage.getItem(
|
|
38
|
-
'cookie',
|
|
39
|
-
)}`,
|
|
40
|
-
}).then((res) => {
|
|
41
|
-
console.info(res.data)
|
|
42
|
-
_this.songs = res.data.data
|
|
145
|
+
url: `/user/cloud?time=${Date.now()}&cookie=${localStorage.getItem('cookie')}`,
|
|
43
146
|
})
|
|
147
|
+
.then((res) => {
|
|
148
|
+
this.songs = res.data.data || []
|
|
149
|
+
})
|
|
150
|
+
.catch((err) => {
|
|
151
|
+
console.error('获取云盘数据失败:', err)
|
|
152
|
+
})
|
|
153
|
+
.finally(() => {
|
|
154
|
+
this.loading = false
|
|
155
|
+
})
|
|
44
156
|
},
|
|
45
157
|
},
|
|
46
158
|
}).mount('#app')
|
|
159
|
+
|
|
47
160
|
const fileUpdateTime = {}
|
|
48
161
|
let fileLength = 0
|
|
49
162
|
|
|
@@ -51,51 +164,46 @@
|
|
|
51
164
|
document
|
|
52
165
|
.querySelector('input[type="file"]')
|
|
53
166
|
.addEventListener('change', function (e) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
upload(
|
|
167
|
+
const files = this.files
|
|
168
|
+
if (files.length === 0) return
|
|
169
|
+
|
|
170
|
+
fileLength = files.length
|
|
171
|
+
for (let i = 0; i < files.length; i++) {
|
|
172
|
+
upload(files[i], i + 1)
|
|
60
173
|
}
|
|
61
174
|
})
|
|
62
175
|
}
|
|
63
176
|
main()
|
|
64
177
|
|
|
65
|
-
function upload(file,
|
|
178
|
+
function upload(file, currentIndex) {
|
|
66
179
|
var formData = new FormData()
|
|
67
180
|
formData.append('songFile', file)
|
|
181
|
+
|
|
68
182
|
axios({
|
|
69
183
|
method: 'post',
|
|
70
|
-
url: `/cloud?time=${Date.now()}&cookie=${localStorage.getItem(
|
|
71
|
-
'cookie',
|
|
72
|
-
)}`,
|
|
184
|
+
url: `/cloud?time=${Date.now()}&cookie=${localStorage.getItem('cookie')}`,
|
|
73
185
|
headers: {
|
|
74
186
|
'Content-Type': 'multipart/form-data',
|
|
75
187
|
},
|
|
76
188
|
data: formData,
|
|
77
189
|
})
|
|
78
190
|
.then((res) => {
|
|
79
|
-
console.
|
|
80
|
-
if (
|
|
81
|
-
console.
|
|
191
|
+
console.log(`${file.name} 上传成功`)
|
|
192
|
+
if (currentIndex >= fileLength) {
|
|
193
|
+
console.log('所有文件上传完毕')
|
|
82
194
|
}
|
|
83
195
|
app.getData()
|
|
84
196
|
})
|
|
85
|
-
.catch(
|
|
86
|
-
console.
|
|
87
|
-
|
|
88
|
-
fileUpdateTime[file.name]
|
|
89
|
-
? (fileUpdateTime[file.name] += 1)
|
|
90
|
-
: (fileUpdateTime[file.name] = 1)
|
|
197
|
+
.catch((err) => {
|
|
198
|
+
console.error(`${file.name} 上传失败:`, err)
|
|
199
|
+
fileUpdateTime[file.name] = (fileUpdateTime[file.name] || 0) + 1
|
|
91
200
|
if (fileUpdateTime[file.name] >= 4) {
|
|
92
|
-
console.error(
|
|
201
|
+
console.error(`文件 ${file.name} 上传失败次数过多,已停止重试`)
|
|
93
202
|
return
|
|
94
203
|
} else {
|
|
95
|
-
console.error(`${file.name}
|
|
204
|
+
console.error(`${file.name} 上传失败 ${fileUpdateTime[file.name]} 次,正在重试...`)
|
|
205
|
+
upload(file, currentIndex)
|
|
96
206
|
}
|
|
97
|
-
// await login()
|
|
98
|
-
upload(file, currentIndx)
|
|
99
207
|
})
|
|
100
208
|
}
|
|
101
209
|
</script>
|
package/public/docs/home.md
CHANGED
|
@@ -3633,6 +3633,14 @@ type='1009' 获取其 id, 如`/search?keywords= 代码时间 &type=1009`
|
|
|
3633
3633
|
|
|
3634
3634
|
**调用例子 :** `/musician/tasks/new`
|
|
3635
3635
|
|
|
3636
|
+
### 音乐人黑胶会员任务
|
|
3637
|
+
|
|
3638
|
+
说明 : 音乐人登录后调用此接口 , 可获取音乐人黑胶会员任务。返回的数据中`missionStatus`字段为任务状态,100 表示任务完成。
|
|
3639
|
+
|
|
3640
|
+
**接口地址 :** `/musician/vip/tasks`
|
|
3641
|
+
|
|
3642
|
+
**调用例子 :** `/musician/vip/tasks`
|
|
3643
|
+
|
|
3636
3644
|
### 账号云豆数
|
|
3637
3645
|
|
|
3638
3646
|
说明 : 音乐人登录后调用此接口 , 可获取账号云豆数
|
|
@@ -4875,6 +4883,43 @@ let data = encodeURIComponent(
|
|
|
4875
4883
|
|
|
4876
4884
|
**调用例子:** `/vip/sign/info`
|
|
4877
4885
|
|
|
4886
|
+
|
|
4887
|
+
### 用户的创建歌单列表
|
|
4888
|
+
|
|
4889
|
+
说明 : 调用此接口, 传入用户id, 获取用户的创建歌单列表
|
|
4890
|
+
|
|
4891
|
+
**必选参数 :**
|
|
4892
|
+
|
|
4893
|
+
`uid`: 用户 id
|
|
4894
|
+
|
|
4895
|
+
**可选参数 :**
|
|
4896
|
+
|
|
4897
|
+
`limit` : 返回数量 , 默认为 100
|
|
4898
|
+
|
|
4899
|
+
`offset` : 偏移数量,用于分页 ,如 :( 页数 -1)\*30, 其中 30 为 limit 的值 , 默认为 0
|
|
4900
|
+
|
|
4901
|
+
**接口地址 :** `/user/playlist/create`
|
|
4902
|
+
|
|
4903
|
+
**调用例子 :** `/user/playlist/create?uid=32953014`
|
|
4904
|
+
|
|
4905
|
+
### 用户的收藏歌单列表
|
|
4906
|
+
|
|
4907
|
+
说明 : 调用此接口, 传入用户id, 获取用户的收藏歌单列表
|
|
4908
|
+
|
|
4909
|
+
**必选参数 :**
|
|
4910
|
+
|
|
4911
|
+
`uid`: 用户 id
|
|
4912
|
+
|
|
4913
|
+
**可选参数 :**
|
|
4914
|
+
|
|
4915
|
+
`limit` : 返回数量 , 默认为 100
|
|
4916
|
+
|
|
4917
|
+
`offset` : 偏移数量,用于分页 ,如 :( 页数 -1)\*30, 其中 30 为 limit 的值 , 默认为 0
|
|
4918
|
+
|
|
4919
|
+
**接口地址 :** `/user/playlist/collect`
|
|
4920
|
+
|
|
4921
|
+
**调用例子 :** `/user/playlist/collect?uid=32953014`
|
|
4922
|
+
|
|
4878
4923
|
## 离线访问此文档
|
|
4879
4924
|
|
|
4880
4925
|
此文档同时也是 Progressive Web Apps(PWA), 加入了 serviceWorker, 可离线访问
|
package/public/docs/index.html
CHANGED
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
}
|
|
37
37
|
</script>
|
|
38
38
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
39
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id=
|
|
39
|
+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BPRGR23JEG"></script>
|
|
40
40
|
<script>
|
|
41
41
|
window.dataLayer = window.dataLayer || [];
|
|
42
|
-
function gtag(){dataLayer.push(arguments);}
|
|
42
|
+
function gtag() { dataLayer.push(arguments); }
|
|
43
43
|
gtag('js', new Date());
|
|
44
44
|
|
|
45
|
-
gtag('config', '
|
|
45
|
+
gtag('config', 'G-BPRGR23JEG');
|
|
46
46
|
</script>
|
|
47
47
|
</html>
|