1+ <!DOCTYPE html>
2+ < html lang ="zh-CN ">
3+ < head >
4+ < meta charset ="UTF-8 ">
5+ < title > 歌单导入工具</ title >
6+ <!-- 引入Bootstrap CSS -->
7+ < link href ="https://fastly.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css " rel ="stylesheet ">
8+ <!-- 引入Bootstrap JS -->
9+ < script src ="https://fastly.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js "> </ script >
10+ <!-- 引入axios用于发送异步请求 -->
11+ < script src ="https://fastly.jsdelivr.net/npm/axios/dist/axios.min.js "> </ script >
12+ </ head >
13+ < body >
14+ < div class ="container mt-5 ">
15+ < h1 class ="mb-4 "> 歌单导入工具</ h1 >
16+ < p > 请选择一种导入方式并填写相关信息:</ p >
17+
18+ <!-- 表单开始 -->
19+ < form id ="importForm " novalidate >
20+ <!-- 选项卡导航 -->
21+ < ul class ="nav nav-tabs mb-3 " id ="importTabs " role ="tablist ">
22+ < li class ="nav-item " role ="presentation ">
23+ < button class ="nav-link active " id ="metadata-tab " data-bs-toggle ="tab " data-bs-target ="#metadata " type ="button " role ="tab " aria-controls ="metadata " aria-selected ="true "> 元数据导入</ button >
24+ </ li >
25+ < li class ="nav-item " role ="presentation ">
26+ < button class ="nav-link " id ="text-tab " data-bs-toggle ="tab " data-bs-target ="#text " type ="button " role ="tab " aria-controls ="text " aria-selected ="false "> 文字导入</ button >
27+ </ li >
28+ < li class ="nav-item " role ="presentation ">
29+ < button class ="nav-link " id ="link-tab " data-bs-toggle ="tab " data-bs-target ="#link " type ="button " role ="tab " aria-controls ="link " aria-selected ="false "> 链接导入</ button >
30+ </ li >
31+ </ ul >
32+
33+ <!-- 选项卡面板 -->
34+ < div class ="tab-content " id ="importTabContent ">
35+ <!-- 元数据导入 -->
36+ < div class ="tab-pane fade show active " id ="metadata " role ="tabpanel " aria-labelledby ="metadata-tab ">
37+ < table class ="table table-bordered mb-3 ">
38+ < thead >
39+ < tr >
40+ < th scope ="col "> 歌曲名称</ th >
41+ < th scope ="col "> 艺术家</ th >
42+ < th scope ="col "> 专辑</ th >
43+ </ tr >
44+ </ thead >
45+ < tbody id ="metadataTableBody ">
46+ <!-- 默认添加一行 -->
47+ < tr >
48+ < td > < input type ="text " class ="form-control " name ="name[] " placeholder ="歌曲名称 "> </ td >
49+ < td > < input type ="text " class ="form-control " name ="artist[] " placeholder ="艺术家 "> </ td >
50+ < td > < input type ="text " class ="form-control " name ="album[] " placeholder ="专辑 "> </ td >
51+ </ tr >
52+ </ tbody >
53+ </ table >
54+ < button type ="button " class ="btn btn-secondary mb-3 " id ="addMetadataRow "> 增加歌曲</ button >
55+ </ div >
56+ <!-- 文字导入 -->
57+ < div class ="tab-pane fade " id ="text " role ="tabpanel " aria-labelledby ="text-tab ">
58+ < div class ="mb-3 ">
59+ < label for ="textInput " class ="form-label "> 文字:</ label >
60+ < textarea class ="form-control " id ="textInput " name ="text " rows ="5 "> </ textarea >
61+ </ div >
62+ < div class ="mb-3 ">
63+ < label for ="playlistNameInput " class ="form-label "> 歌单名:</ label >
64+ < input type ="text " class ="form-control " id ="playlistNameInput " name ="playlistName " placeholder ="请输入歌单名 ">
65+ </ div >
66+ </ div >
67+ <!-- 链接导入 -->
68+ < div class ="tab-pane fade " id ="link " role ="tabpanel " aria-labelledby ="link-tab ">
69+ < div class ="mb-3 ">
70+ < label for ="linkInputs " class ="form-label "> 链接:</ label >
71+ < div id ="linkInputsContainer ">
72+ < div class ="input-group mb-3 ">
73+ < input type ="text " class ="form-control " id ="linkInput0 " name ="linkInput0 " placeholder ="请输入链接 ">
74+ < button type ="button " class ="btn btn-secondary removeLinkButton " data-index ="0 "> ×</ button >
75+ </ div >
76+ </ div >
77+ < button type ="button " class ="btn btn-secondary mb-3 " id ="addLinkButton "> 增加链接</ button >
78+ < div class ="mb-3 ">
79+ < label for ="playlistNameLinkInput " class ="form-label "> 歌单名:</ label >
80+ < input type ="text " class ="form-control " id ="playlistNameLinkInput " name ="playlistName " placeholder ="请输入歌单名 ">
81+ </ div >
82+ </ div >
83+ </ div >
84+ </ div >
85+
86+ <!-- 是否导入我喜欢的音乐 -->
87+ < div class ="form-check ">
88+ < input class ="form-check-input " type ="checkbox " value ="" id ="importStarCheckbox ">
89+ < label class ="form-check-label " for ="importStarCheckbox ">
90+ 导入“我喜欢的音乐”
91+ </ label >
92+ </ div >
93+
94+ <!-- 提交按钮 -->
95+ < button type ="submit " class ="btn btn-primary mt-3 "> 导入歌曲</ button >
96+ </ form >
97+ <!-- 表单结束 -->
98+
99+ < script >
100+ // 动态增加链接输入框
101+ document . getElementById ( 'addLinkButton' ) . addEventListener ( 'click' , function ( ) {
102+ var container = document . getElementById ( 'linkInputsContainer' ) ;
103+ var newIndex = container . childElementCount - 1 ; // 减去非输入框元素的数量
104+ var newInput = document . createElement ( 'input' ) ;
105+ newInput . type = 'text' ;
106+ newInput . className = 'form-control' ;
107+ newInput . id = `linkInput${ newIndex } ` ;
108+ newInput . name = `linkInput${ newIndex } ` ;
109+ newInput . placeholder = '请输入链接' ;
110+
111+ var removeButton = document . createElement ( 'button' ) ;
112+ removeButton . type = 'button' ;
113+ removeButton . className = 'btn btn-secondary removeLinkButton' ;
114+ removeButton . textContent = '×' ;
115+ removeButton . dataset . index = newIndex . toString ( ) ;
116+ removeButton . addEventListener ( 'click' , function ( ) {
117+ var group = this . closest ( '.input-group' ) ;
118+ container . removeChild ( group ) ;
119+ } ) ;
120+
121+ var inputGroup = document . createElement ( 'div' ) ;
122+ inputGroup . className = 'input-group mb-3' ;
123+ inputGroup . appendChild ( newInput ) ;
124+ inputGroup . appendChild ( removeButton ) ;
125+
126+ container . appendChild ( inputGroup ) ;
127+ } ) ;
128+
129+ // 动态增加元数据行
130+ document . getElementById ( 'addMetadataRow' ) . addEventListener ( 'click' , function ( ) {
131+ var container = document . getElementById ( 'metadataTableBody' ) ;
132+ var newRow = document . createElement ( 'tr' ) ;
133+
134+ var nameInput = document . createElement ( 'input' ) ;
135+ nameInput . type = 'text' ;
136+ nameInput . className = 'form-control' ;
137+ nameInput . name = 'name[]' ;
138+ nameInput . placeholder = '歌曲名称' ;
139+
140+ var artistInput = document . createElement ( 'input' ) ;
141+ artistInput . type = 'text' ;
142+ artistInput . className = 'form-control' ;
143+ artistInput . name = 'artist[]' ;
144+ artistInput . placeholder = '艺术家' ;
145+
146+ var albumInput = document . createElement ( 'input' ) ;
147+ albumInput . type = 'text' ;
148+ albumInput . className = 'form-control' ;
149+ albumInput . name = 'album[]' ;
150+ albumInput . placeholder = '专辑' ;
151+
152+ newRow . innerHTML = `
153+ <td>${ nameInput . outerHTML } </td>
154+ <td>${ artistInput . outerHTML } </td>
155+ <td>${ albumInput . outerHTML } </td>
156+ ` ;
157+
158+ container . appendChild ( newRow ) ;
159+ } ) ;
160+
161+ document . getElementById ( 'importForm' ) . addEventListener ( 'submit' , async function ( event ) {
162+ // 阻止默认行为
163+ event . preventDefault ( ) ;
164+
165+ // 获取表单值
166+ let text = document . getElementById ( 'textInput' ) . value ;
167+ let links = [ ] ;
168+ let local = [ ] ;
169+ let playlistName = '' ;
170+
171+ // 获取所有链接输入框的值
172+ let linkInputs = document . querySelectorAll ( '#linkInputsContainer .input-group .form-control' ) ;
173+ linkInputs . forEach ( function ( input ) {
174+ if ( input . value . trim ( ) !== '' ) {
175+ links . push ( input . value ) ;
176+ }
177+ } ) ;
178+
179+ // 获取元数据
180+ let metadataRows = document . querySelectorAll ( '#metadataTableBody tr' ) ;
181+ metadataRows . forEach ( function ( row ) {
182+ let name = row . querySelector ( 'input[name="name[]"]' ) . value ;
183+ let artist = row . querySelector ( 'input[name="artist[]"]' ) . value ;
184+ let album = row . querySelector ( 'input[name="album[]"]' ) . value ;
185+ if ( name && artist && album ) {
186+ local . push ( { name, artist, album } ) ;
187+ }
188+ } ) ;
189+
190+ // 检查是否有且只有一个输入字段被填写
191+ let filledCount = ( text ? 1 : 0 ) + ( links . length > 0 ? 1 : 0 ) + ( local . length > 0 ? 1 : 0 ) ;
192+ if ( filledCount !== 1 ) {
193+ alert ( "请确保仅填写了一个输入字段!" ) ;
194+ return ;
195+ }
196+
197+ // 获取歌单名
198+ if ( document . getElementById ( 'importStarCheckbox' ) . checked ) {
199+ playlistName = '我喜欢的音乐' ;
200+ } else {
201+ playlistName = document . getElementById ( 'playlistNameInput' ) . value ||
202+ document . getElementById ( 'playlistNameLinkInput' ) . value ||
203+ '导入音乐 ' + new Date ( ) . toLocaleString ( ) ;
204+ }
205+
206+ // 创建请求参数
207+ let data = { } ;
208+ if ( text ) {
209+ data . text = text ;
210+ data . playlistName = playlistName ;
211+ } else if ( links . length > 0 ) {
212+ data . link = JSON . stringify ( links ) ;
213+ data . playlistName = playlistName ;
214+ } else if ( local . length > 0 ) {
215+ data . local = JSON . stringify ( local ) ;
216+ }
217+
218+ // 添加额外参数
219+ if ( document . getElementById ( 'importStarCheckbox' ) . checked ) {
220+ data . importStarPlaylist = true ;
221+ }
222+
223+ try {
224+ const res = await axios ( {
225+ url : `/playlist/import/name/task/create?timestamp=${ Date . now ( ) } ` ,
226+ method : 'post' ,
227+ data : data ,
228+ } ) ;
229+
230+ let taskId = res . data ?. data ?. taskId
231+ if ( taskId ) {
232+ alert ( `任务创建成功! 正在导入, 请稍等; 任务id:${ taskId } ` )
233+ // const res2 = await axios({
234+ // url: `/playlist/import/task/status?timestamp=${Date.now()}`,
235+ // method: 'post',
236+ // data: {
237+ // id: taskId
238+ // },
239+ // });
240+ // alert(JSON.stringify(res2.data, null, 2));
241+ }
242+ } catch ( error ) {
243+ console . error ( 'Error:' , error ) ;
244+ alert ( '导入失败,请检查您的输入或稍后再试。' ) ;
245+ }
246+ } ) ;
247+
248+ // 监听复选框状态变化
249+ document . getElementById ( 'importStarCheckbox' ) . addEventListener ( 'change' , function ( ) {
250+ let isChecked = this . checked ;
251+ let playlistNameInputs = document . querySelectorAll ( '[name="playlistName"]' ) ;
252+ playlistNameInputs . forEach ( function ( input ) {
253+ input . disabled = isChecked ;
254+ } ) ;
255+ } ) ;
256+
257+ // 初始化时设置歌单名输入框的状态
258+ document . getElementById ( 'importStarCheckbox' ) . dispatchEvent ( new Event ( 'change' ) ) ;
259+ </ script >
260+ </ div >
261+ </ body >
262+ </ html >
0 commit comments