@@ -3,27 +3,61 @@ h5CommInit();
3
3
const el = {
4
4
mp3 : $ ( '#mp3' ) ,
5
5
pl : $ ( '#pl' ) ,
6
+ nextComment : $ ( '#nextComment' ) ,
6
7
yh : $ ( '#yh' ) ,
7
- bf : $ ( '#bf ' ) ,
8
+ bf : $ ( '#bfBtn ' ) ,
8
9
img : $ ( '#img' ) ,
9
10
toplistContain : document . getElementById ( 'toplistContain' ) ,
11
+ /** 看歌词按钮 */
12
+ lrcBtn : $ ( '#lrcBtn' ) ,
13
+ hotBtn : $ ( '#hotBtn' ) ,
14
+ lrc : document . getElementById ( 'lrc' ) ,
15
+ lrcUpdate : $ ( '#lrcUpdate' ) ,
10
16
} ;
11
- var hotList ;
12
- var dataJson ;
13
17
14
- $ ( function ( ) {
15
- var aud = el . mp3 [ 0 ] ;
16
- aud . onended = function ( ) {
18
+ const urlParams = h5Utils . getUrlParams ( ) ;
19
+ const cache = {
20
+ playList : new Map ( ) ,
21
+ data : new Map ( ) ,
22
+ /** 歌单 ID */
23
+ pid : + ( urlParams . pid || urlParams . ca ) || 3778678 ,
24
+ } ;
25
+ let hotList ;
26
+ let dataJson ;
27
+
28
+ $ ( async function ( ) {
29
+ initEvets ( ) ;
30
+ if ( cache . pid ) await getHotList ( true , cache . pid ) . catch ( e => console . log ( e ) ) ;
31
+ const mid = + urlParams . id ;
32
+ if ( mid ) playMp3 ( mid ) ;
33
+ else Nextone ( ) ;
34
+ } ) ;
35
+
36
+ function initEvets ( ) {
37
+ const audio = el . mp3 [ 0 ] ;
38
+ audio . onended = ( ) => Nextone ( ) ;
39
+ audio . addEventListener ( 'timeupdate' , updateLyric ) ;
40
+ audio . addEventListener ( 'error' , ev => {
41
+ console . log ( ev . message || ev ) ;
42
+ if ( dataJson ) h5Utils . toast ( `[${ dataJson . name } ] 播放异常` , { icon : 'error' } ) ;
17
43
Nextone ( ) ;
18
- } ;
44
+ } ) ;
45
+ audio . addEventListener ( 'pause' , ( ) => {
46
+ el . bf . html ( '播放' ) ;
47
+ el . img . removeClass ( 'play-rotate' ) . addClass ( 'pause' ) ;
48
+ } ) ;
49
+ audio . addEventListener ( 'play' , ( ) => {
50
+ el . bf . html ( '暂停' ) ;
51
+ el . img . addClass ( 'play-rotate' ) . removeClass ( 'pause' ) ;
52
+ } ) ;
19
53
20
- el . pl . on ( 'click' , function ( ) {
54
+ el . nextComment . on ( 'click' , function ( ) {
21
55
if ( dataJson ) {
22
56
if ( dataJson . hotComments ) {
23
57
updateComment ( ) ;
24
58
} else {
25
59
$ . getJSON ( '../iapi/163music/hot.php?type=comment&id=' + dataJson . id ) . then ( function ( d ) {
26
- if ( d . hotComments ) {
60
+ if ( dataJson && d . hotComments ) {
27
61
dataJson . hotComments = d . hotComments ;
28
62
updateComment ( ) ;
29
63
}
@@ -32,6 +66,15 @@ $(function () {
32
66
}
33
67
} ) ;
34
68
69
+ el . lrcBtn . on ( 'click' , async function ( ) {
70
+ if ( el . lrc . style . display === 'block' ) {
71
+ el . lrc . style . display = 'none' ;
72
+ } else {
73
+ const lrc = await getLrc ( ) ;
74
+ if ( lrc ) el . lrc . style . display = 'block' ;
75
+ }
76
+ } ) ;
77
+
35
78
el . toplistContain . addEventListener (
36
79
'click' ,
37
80
ev => {
@@ -54,23 +97,16 @@ $(function () {
54
97
} ,
55
98
false
56
99
) ;
100
+ }
57
101
58
- const mid = + h5Utils . getUrlParams ( ) . id ;
59
- if ( mid ) playMp3 ( mid ) ;
60
- else Nextone ( ) ;
61
- } ) ;
62
-
102
+ /** 播放音乐 */
63
103
function bf ( ) {
64
- var audio = el . mp3 [ 0 ] ;
104
+ const audio = el . mp3 [ 0 ] ;
65
105
if ( audio !== null ) {
66
106
if ( audio . paused ) {
67
107
audio . play ( ) ;
68
- el . bf . html ( '暂停' ) ;
69
- el . img . addClass ( 'play-rotate' ) . removeClass ( 'pause' ) ;
70
108
} else {
71
109
audio . pause ( ) ;
72
- el . bf . html ( '播放' ) ;
73
- el . img . removeClass ( 'play-rotate' ) . addClass ( 'pause' ) ;
74
110
}
75
111
}
76
112
}
@@ -95,7 +131,7 @@ async function Nextone(json) {
95
131
$ ( '#title' ) . html ( json . data . name + '(' + json . data . artistsname + ')' ) ;
96
132
el . mp3 . attr ( 'src' , json . data . url ) ;
97
133
el . mp3 . attr ( 'controls' , 'controls' ) ;
98
- el . img . attr ( 'src' , json . data . picurl ) ;
134
+ el . img . attr ( 'src' , String ( json . data . picurl ) . replace ( 'http:' , 'https:' ) ) ;
99
135
// $("#img2").attr("src", json.data.avatarurl);
100
136
el . yh . html ( '来自网易云用户「@' + json . data . nickname + '」的评论:' ) ;
101
137
el . pl . html ( json . data . content ) ;
@@ -105,34 +141,38 @@ async function Nextone(json) {
105
141
history . pushState ( null , '' , u . toString ( ) ) ;
106
142
107
143
dataJson = json . data ;
144
+ cache . data . set ( json . data . id , json . data ) ;
145
+ $ ( '#header' ) . css ( { display : 'flex' } ) ;
146
+
147
+ await getLrc ( ) ;
108
148
}
109
149
110
- function copyUrl2 ( ) {
111
- var Url2 = document . getElementById ( 'pl' ) . innerText ;
112
- var oInput = document . createElement ( 'input' ) ;
113
- oInput . value = Url2 ;
114
- document . body . appendChild ( oInput ) ;
115
- oInput . select ( ) ; // 选择对象
116
- document . execCommand ( 'Copy' ) ; // 执行浏览器复制命令
117
- oInput . style . display = 'none' ;
118
- h5Utils . alert ( '复制成功' ) ;
150
+ function copyComment ( ) {
151
+ var comment = document . getElementById ( 'pl' ) . innerText ;
152
+ if ( ! comment ) return h5Utils . toast ( '没有内容' , { icon : 'warning' } ) ;
153
+ if ( h5Utils . copy ( comment ) ) h5Utils . toast ( '复制成功!' ) ;
154
+ else h5Utils . toast ( '复制失败' , { icon : 'error' } ) ;
119
155
}
120
156
function updateComment ( ) {
121
- var hotComments = dataJson . hotComments ;
157
+ const hotComments = dataJson . hotComments ;
122
158
if ( dataJson . commentIdx == null ) dataJson . commentIdx = 0 ;
123
159
else dataJson . commentIdx += 1 ;
124
160
if ( dataJson . commentIdx >= hotComments . length ) dataJson . commentIdx = 0 ;
125
161
126
- var rndItem = hotComments [ dataJson . commentIdx ] ;
162
+ const rndItem = hotComments [ dataJson . commentIdx ] ;
127
163
el . yh . html ( '来自网易云用户「@' + rndItem . user . nickname + '」的评论:' ) ;
128
164
el . pl . text ( rndItem . content ) ;
129
165
}
130
166
131
- async function getHotList ( isPreLoad ) {
167
+ async function getHotList ( isPreLoad , id = 3778678 ) {
132
168
if ( ! hotList ) {
133
- const d = await fetch ( `../iapi/163music/hot .php?type=playlist ` ) . then ( d => d . json ( ) ) ;
169
+ const d = await fetch ( `../iapi/163music/api .php?type=toplist&id= ${ id } ` ) . then ( d => d . json ( ) ) ;
134
170
if ( d . code !== 200 ) return h5Utils . alert ( d . errmsg || '获取失败!' ) ;
135
171
hotList = d ;
172
+ if ( hotList . result . name ) {
173
+ el . hotBtn . text ( hotList . result . name ) ;
174
+ el . hotBtn . attr ( 'title' , hotList . result . name ) ;
175
+ }
136
176
if ( isPreLoad ) return hotList ;
137
177
}
138
178
@@ -141,7 +181,7 @@ async function getHotList(isPreLoad) {
141
181
htmllist . push (
142
182
`<li>` ,
143
183
`<span class="left">` ,
144
- `<span class="idx">${ idx } </span>` ,
184
+ `<span class="idx">${ idx + 1 } </span>` ,
145
185
n . ablum ? `<img src="${ n . ablum . picUrl } ">` : '' ,
146
186
`<span class="tilte">${ n . name } - <span class="author">${ n . artists ? n . artists . map ( m => m . name ) . join ( ',' ) : '' } </span></span>` ,
147
187
`</span>` ,
@@ -157,24 +197,83 @@ async function getHotList(isPreLoad) {
157
197
158
198
async function playMp3 ( id ) {
159
199
if ( ! hotList ) await getHotList ( true ) ;
160
- const item = hotList . result . tracks . find ( d => d . id == id ) ;
161
- if ( ! item ) return false ;
162
-
163
- const comments = await $ . getJSON ( `../iapi/163music/hot.php?type=comment&id=${ id } ` ) ;
164
- dataJson = {
165
- id,
166
- commentIdx : 0 ,
167
- hotComments : comments . hotComments ,
168
- name : item . name ,
169
- url : `https://music.163.com/song/media/outer/url?id=${ id } .mp3` ,
170
- picurl : item . album . picUrl ,
171
- artistsname : item . artists [ 0 ] . name ,
172
- nickname : comments . hotComments [ 0 ] . user . nickname ,
173
- avatarurl : comments . hotComments [ 0 ] . user . avatarUrl ,
174
- content : comments . hotComments [ 0 ] . content ,
175
- } ;
200
+ const item = hotList . result . tracks . find ( d => d . id == id ) || hotList . result . tracks [ 0 ] ;
201
+
202
+ dataJson = cache . data . get ( id ) ;
203
+ if ( ! dataJson ) {
204
+ const comments = await $ . getJSON ( `../iapi/163music/hot.php?type=comment&id=${ id } ` ) ;
205
+ const comment = comments . hotComments [ 0 ] ;
206
+ dataJson = {
207
+ id,
208
+ commentIdx : 0 ,
209
+ hotComments : comments . hotComments ,
210
+ name : item . name ,
211
+ url : `https://music.163.com/song/media/outer/url?id=${ id } .mp3` ,
212
+ picurl : item . album . picUrl ,
213
+ artistsname : item . artists [ 0 ] . name ,
214
+ nickname : comment ? comment . user . nickname : '' ,
215
+ avatarurl : comment ? comment . user . avatarUrl : '' ,
216
+ content : comment ? comment . content : '' ,
217
+ } ;
218
+
219
+ cache . data . set ( id , dataJson ) ;
220
+ }
176
221
177
222
Nextone ( { data : dataJson } ) ;
178
223
updateComment ( ) ;
179
224
return true ;
180
225
}
226
+
227
+ async function getLrc ( ) {
228
+ const data = dataJson ;
229
+ if ( ! data ) return ;
230
+
231
+ if ( ! data . lrc ) {
232
+ const d = await $ . getJSON ( '../iapi/163music/api.php?type=lrc&id=' + data . id ) ;
233
+ if ( d . lrc ) {
234
+ data . lrc = d . lrc ;
235
+ data . lrc . list = [ ] ;
236
+ String ( data . lrc . lyric )
237
+ . split ( '\n' )
238
+ . forEach ( line => {
239
+ const r = line . match ( / \[ ( [ \d : . ] + ) \] ( .+ ) / ) ;
240
+ if ( r ) {
241
+ const [ _a , timeStr , text ] = r . map ( d => d . trim ( ) ) ;
242
+ const [ min , sec ] = timeStr . split ( ':' ) . map ( d => + d ) ;
243
+ const time = Number ( ( min * 60 + sec ) . toFixed ( 3 ) ) ;
244
+ data . lrc . list . push ( { text, time } ) ;
245
+ }
246
+ } ) ;
247
+
248
+ el . lrc . innerHTML = data . lrc . lyric || '暂无歌词' ;
249
+ }
250
+ }
251
+
252
+ return data . lrc ;
253
+ }
254
+
255
+ // 播放歌曲的函数
256
+ function updateLyric ( ) {
257
+ if ( ! dataJson || ! dataJson . lrc ) return ;
258
+
259
+ var currentTime = this . currentTime ; // 获取当前歌曲播放时间
260
+ var currentLyricIndex = - 1 ;
261
+ const lyrics = dataJson . lrc . list ;
262
+
263
+ // 查找当前歌词索引
264
+ for ( var i = 0 ; i < lyrics . length ; i ++ ) {
265
+ if ( currentTime >= lyrics [ i ] . time ) {
266
+ currentLyricIndex = i ;
267
+ } else {
268
+ break ; // 找到当前时间对应的歌词后退出循环
269
+ }
270
+ }
271
+
272
+ // 显示当前歌词
273
+ const lyricText = [ currentLyricIndex - 1 , currentLyricIndex , currentLyricIndex + 1 ]
274
+ . filter ( i => lyrics [ i ] )
275
+ . map ( i => `<div class="lyric-line ${ i == currentLyricIndex ? 'current' : '' } ">${ lyrics [ i ] . text } </div>` )
276
+ . join ( '' ) ;
277
+
278
+ if ( el . lrcUpdate . html ( ) !== lyricText ) el . lrcUpdate . html ( lyricText ) ;
279
+ }
0 commit comments