listen_together_host.html 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <!-- eslint-disable prettier/prettier -->
  2. <!DOCTYPE html>
  3. <html lang="zh">
  4. <head>
  5. <meta charset="UTF-8" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>一起听</title>
  8. <script src="https://unpkg.com/petite-vue"></script>
  9. <script src="https://cdn.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
  10. <link rel="stylesheet" href="https://unpkg.com/mdui@1.0.2/dist/css/mdui.min.css" />
  11. <script src="https://unpkg.com/mdui@1.0.2/dist/js/mdui.min.js"></script>
  12. </head>
  13. <body class="mdui-container">
  14. <div>
  15. <a href="/qrlogin.html">
  16. 如果没登录,请先登录
  17. </a>
  18. </div>
  19. <h1>一起听 - 主机模式</h1>
  20. <div>消息: {{message}}</div>
  21. <audio id="player" autoplay controls>
  22. </audio>
  23. <br />
  24. <br />
  25. <button v-if="!account.login" @click="login">获取登录状态</button>
  26. <div>您的当前登录账号为: {{account.nickname}}</div>
  27. <br />
  28. <div v-if="account.login">
  29. <button v-if="!roomInfo.roomId" @click="createRoom">创建房间</button>
  30. <details>
  31. <summary>加入房间</summary>
  32. <div><span>房间ID: </span><input v-model="roomInfo.roomId" /></div>
  33. <div><span>邀请者 ID: </span><input v-model="roomInfo.inviterId" /></div>
  34. <button @click="joinRoom">点击加入</button>
  35. </details>
  36. <div v-if="roomInfo.roomId">
  37. <div>分享链接为:
  38. https://st.music.163.com/listen-together/share/?songId=1372188635&roomId={{roomInfo.roomId}}&inviterId={{roomInfo.inviterId}}
  39. </div>
  40. <br />
  41. <button @click="refreshRoom">刷新房间状态</button>
  42. <div>在线用户: </div>
  43. <ul class="mdui-list">
  44. <li v-for="user in roomInfo.roomUsers" class="mdui-list-item mdui-ripple">
  45. <div class="mdui-list-item-avatar">
  46. <img :src="user.avatarUrl" />
  47. </div>
  48. <div class="mdui-list-item-content">{{user.nickname}}</div>
  49. </li>
  50. </ul>
  51. <button v-if="roomInfo.roomId" @click="closeRoom">关闭房间</button>
  52. </div>
  53. </div>
  54. <button @click="playTrack">播放</button>
  55. <button @click="pauseTrack">暂停</button>
  56. <button @click="seekTrack">同步进度</button>
  57. <details>
  58. <summary>播放列表</summary>
  59. <br />
  60. <div><span>歌单ID: </span><input v-model="playlistInfo.playlistId" /></div>
  61. <button @click="loadPlaylist">加载歌单到播放列表</button>
  62. <span>{{playlistInfo.playlistName}}</span>
  63. <br />
  64. <br />
  65. <div>歌单内容: </div>
  66. <ul class="mdui-list">
  67. <li @click="gotoTrack(track.id)" v-for="track in playlistInfo.playlistTracks" class="mdui-list-item mdui-ripple">
  68. <div class="mdui-list-item-avatar">
  69. <img :src="track.al.picUrl" />
  70. </div>
  71. <div class="mdui-list-item-content">{{track.name}}</div>
  72. </li>
  73. </ul>
  74. </details>
  75. </body>
  76. <script>
  77. PetiteVue.createApp({
  78. message: '请点击获取登录状态',
  79. account: {
  80. login: false,
  81. userId: 0,
  82. nickname: '未登录',
  83. },
  84. roomInfo: {
  85. roomId: null,
  86. inviterId: 0,
  87. roomUsers: [],
  88. },
  89. playlistInfo: {
  90. playlistId: 0,
  91. playlistName: '未获取',
  92. playlistTrackIds: [],
  93. playlistTracks: [],
  94. },
  95. playingInfo: {
  96. trackId: 0,
  97. status: 'PLAY',
  98. progress: 1,
  99. },
  100. clientSeq: 1,
  101. login: async function () {
  102. const res = await axios({
  103. url: `/login/status?timestamp=${new Date().getTime()}`,
  104. method: 'get',
  105. data: {
  106. cookie: localStorage.getItem('cookie'),
  107. },
  108. })
  109. if (res.data.data.code != 200) {
  110. alert('请先使用登录 API 登录到网易云音乐')
  111. } else {
  112. this.account.userId = res.data.data.profile.userId
  113. this.account.nickname = res.data.data.profile.nickname
  114. this.account.login = true
  115. this.message = '成功登录, 请创建房间'
  116. }
  117. },
  118. joinRoom: async function () {
  119. const res = await axios({
  120. url: 'listentogether/accept',
  121. method: 'post',
  122. data: {
  123. roomId: this.roomInfo.roomId,
  124. inviterId: this.roomInfo.inviterId,
  125. cookie: localStorage.getItem('cookie'),
  126. },
  127. })
  128. console.log(res)
  129. if (res.data.code != 200) {
  130. this.message = '加入房间出现问题: ' + res.data.message
  131. } else {
  132. this.message = '加入房间成功: ' + this.roomInfo.roomId
  133. const res2 = await axios({
  134. url: 'listentogether/room/check',
  135. method: 'post',
  136. data: {
  137. roomId: this.roomInfo.roomId,
  138. cookie: localStorage.getItem('cookie'),
  139. },
  140. })
  141. console.log(res2)
  142. const res3 = await axios({
  143. url: 'listentogether/sync/playlist/get',
  144. method: 'post',
  145. data: {
  146. roomId: this.roomInfo.roomId,
  147. cookie: localStorage.getItem('cookie'),
  148. },
  149. })
  150. this.playlistInfo.playlistName = "其他人的歌单"
  151. this.playlistInfo.playlistTrackIds = res3.data.data.playlist.displayList.result
  152. .join(',')
  153. const resa = await axios({
  154. url: '/song/detail',
  155. method: 'post',
  156. data: {
  157. ids: this.playlistInfo.playlistTrackIds,
  158. cookie: localStorage.getItem('cookie'),
  159. },
  160. })
  161. console.log(resa)
  162. this.playlistInfo.playlistTracks = resa.data.songs
  163. }
  164. },
  165. createRoom: async function () {
  166. const res = await axios({
  167. url: 'listentogether/room/create',
  168. method: 'get',
  169. data: {
  170. cookie: localStorage.getItem('cookie'),
  171. },
  172. })
  173. console.log(res)
  174. if (res.data.code != 200) {
  175. this.message = '创建房间出现问题: ' + res.data.message
  176. } else {
  177. this.message = '创建房间成功: ' + res.data.data.roomInfo.roomId
  178. this.roomInfo.inviterId = this.account.userId
  179. this.roomInfo.roomId = res.data.data.roomInfo.roomId
  180. const res2 = await axios({
  181. url: 'listentogether/room/check',
  182. method: 'post',
  183. data: {
  184. roomId: this.roomInfo.roomId,
  185. cookie: localStorage.getItem('cookie'),
  186. },
  187. })
  188. console.log(res2)
  189. }
  190. },
  191. refreshRoom: async function () {
  192. const res = await axios({
  193. url: '/listentogether/status',
  194. data: {
  195. cookie: localStorage.getItem('cookie'),
  196. },
  197. })
  198. console.log(res)
  199. if (res.data.code != 200 || !res.data.data.inRoom) {
  200. this.message = '房间状态获取失败, 可能退出了房间'
  201. } else {
  202. this.roomInfo.roomUsers = res.data.data.roomInfo.roomUsers
  203. }
  204. },
  205. closeRoom: async function () {
  206. const res = await axios({
  207. url: '/listentogether/end',
  208. method: 'post',
  209. data: {
  210. roomId: this.roomInfo.roomId,
  211. cookie: localStorage.getItem('cookie'),
  212. },
  213. })
  214. console.log(res)
  215. if (res.data.code != 200 || !res.data.data.success) {
  216. this.message = '房间关闭失败'
  217. } else {
  218. this.message = '房间关闭成功'
  219. this.roomInfo.roomId = null
  220. }
  221. },
  222. loadPlaylist: async function () {
  223. const res = await axios({
  224. url: '/playlist/detail',
  225. method: 'post',
  226. data: {
  227. id: this.playlistInfo.playlistId,
  228. cookie: localStorage.getItem('cookie'),
  229. },
  230. })
  231. console.log(res)
  232. this.playlistInfo.playlistName = res.data.playlist.name
  233. this.playlistInfo.playlistTrackIds = res.data.playlist.trackIds
  234. .map((track) => track.id)
  235. .join(',')
  236. const resa = await axios({
  237. url: '/song/detail',
  238. method: 'post',
  239. data: {
  240. ids: this.playlistInfo.playlistTrackIds,
  241. cookie: localStorage.getItem('cookie'),
  242. },
  243. })
  244. console.log(resa)
  245. this.playlistInfo.playlistTracks = resa.data.songs
  246. if (this.roomInfo.roomId) {
  247. const resb = await axios({
  248. url: 'listentogether/sync/list/command',
  249. method: 'post',
  250. data: {
  251. roomId: this.roomInfo.roomId,
  252. commandType: 'REPLACE',
  253. userId: this.account.userId,
  254. version: this.clientSeq++,
  255. playMode: 'ORDER_LOOP',
  256. displayList: this.playlistInfo.playlistTrackIds,
  257. randomList: this.playlistInfo.playlistTrackIds,
  258. cookie: localStorage.getItem('cookie'),
  259. },
  260. })
  261. console.log(resb)
  262. }
  263. },
  264. gotoTrack: async function (trackId) {
  265. this.playingInfo.trackId = trackId
  266. if (this.roomInfo.roomId) {
  267. await this.playCommand('GOTO')
  268. }
  269. document.getElementById('player').src =
  270. 'https://music.163.com/song/media/outer/url?id=' + trackId + '.mp3'
  271. },
  272. playTrack: async function () {
  273. this.playingInfo.status = 'PLAY'
  274. await this.playCommand('PLAY')
  275. document.getElementById('player').play()
  276. },
  277. pauseTrack: async function () {
  278. this.playingInfo.status = 'PAUSE'
  279. await this.playCommand('PAUSE')
  280. document.getElementById('player').pause()
  281. },
  282. seekTrack: async function () {
  283. this.playingInfo.status = 'PLAY'
  284. await this.playCommand('seek')
  285. document.getElementById('player').play()
  286. },
  287. playCommand: async function (action) {
  288. const res = await axios({
  289. url: 'listentogether/play/command',
  290. method: 'post',
  291. data: {
  292. roomId: this.roomInfo.roomId,
  293. progress: Math.floor(
  294. document.getElementById('player').currentTime * 1000,
  295. ),
  296. commandType: action,
  297. formerSongId: '-1',
  298. targetSongId: this.playingInfo.trackId,
  299. clientSeq: this.clientSeq++,
  300. playStatus: this.playingInfo.status,
  301. cookie: localStorage.getItem('cookie'),
  302. },
  303. })
  304. console.log(res)
  305. },
  306. }).mount()
  307. </script>
  308. </html>