-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
279 lines (270 loc) · 18 KB
/
Copy pathindex.html
File metadata and controls
279 lines (270 loc) · 18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>朋友的声音收藏馆</title>
<meta name="description" content="收藏那些值得被记住的声音">
<meta name="theme-color" id="themeColor" content="#ffffff">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.10.1/APlayer.min.css">
<link rel="stylesheet" href="style.css?v=10">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🎵</text></svg>">
<link rel="manifest" href="manifest.json" id="manifest-link">
</head>
<body>
<div class="bg-gradient"></div>
<div class="container">
<header class="header">
<div class="header-content glass">
<div class="header-top-row">
<div class="header-titles">
<h1 class="site-title">朋友的声音收藏馆</h1>
<p class="site-subtitle">收藏那些值得被记住的声音</p>
</div>
<div class="header-actions">
<button id="adminBtn" class="control-btn" title="管理员登录">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/>
</svg>
</button>
<button id="themeToggle" class="control-btn" title="切换夜间模式">
<svg class="theme-icon-sun" viewBox="0 0 24 24" width="20" height="20" style="display:none">
<path fill="currentColor" d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58a.996.996 0 0 0-1.41 0 .996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37a.996.996 0 0 0-1.41 0 .996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0a.996.996 0 0 0 0-1.41l-1.06-1.06zm1.06-10.96a.996.996 0 0 0 0-1.41.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36a.996.996 0 0 0 0-1.41.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z"/>
</svg>
<svg class="theme-icon-moon" viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M12 3a9 9 0 1 0 9 9c0-.46-.04-.92-.1-1.36a5.389 5.389 0 0 1-4.4 2.26 5.403 5.403 0 0 1-3.14-9.8c-.44-.06-.9-.1-1.36-.1z"/>
</svg>
</button>
</div>
</div>
<div class="header-controls">
<div class="search-box">
<svg class="search-icon" viewBox="0 0 24 24" width="18" height="18">
<path fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 0 0 1.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.5 6.5 0 0 0-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 0 0 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
</svg>
<input type="text" id="searchInput" class="search-input" placeholder="搜索音乐..." autocomplete="off">
</div>
<div class="control-buttons play-mode-buttons">
<button id="sequentialBtn" class="control-btn play-mode-btn active" title="顺序播放" data-mode="sequential">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M4 7h16v2H4V7zm0 6h16v-2H4v2zm0 4h16v-2H4v2zM2 5.5l4 3-4 3v-6zm0 13l4-3-4-3v6z"/>
</svg>
</button>
<button id="shuffleBtn" class="control-btn play-mode-btn" title="随机播放" data-mode="shuffle">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"/>
</svg>
</button>
<button id="singleLoopBtn" class="control-btn play-mode-btn" title="单曲循环" data-mode="single">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/>
</svg>
</button>
<span class="mode-indicator" id="modeIndicator">顺序播放</span>
<button id="playHistoryBtn" class="control-btn play-mode-btn" title="播放历史">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M13 3a9 9 0 0 0-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.954 8.954 0 0 0 13 21a9 9 0 0 0 0-18zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
</svg>
</button>
</div>
</div>
</div>
</header>
<main class="main">
<div class="player-section glass" id="player-section">
<div id="player"></div>
</div>
<section class="playlist-section glass">
<div class="playlist-header">
<h2 class="playlist-title">全部歌曲</h2>
<div class="playlist-header-right">
<button id="refreshBtn" class="now-playing-btn" title="刷新歌单">
<svg viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor" d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/>
</svg>
</button>
<span id="songCount" class="song-count">0 首</span>
<button id="nowPlayingBtn" class="now-playing-btn" title="正在播放">
<svg viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
</button>
</div>
</div>
<div class="playlist-container">
<ul id="playlist" class="playlist"></ul>
<div id="emptyState" class="empty-state">
<svg viewBox="0 0 24 24" width="48" height="48">
<path fill="currentColor" opacity="0.3" d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>
<p>暂无音乐</p>
<span>请将音乐文件上传至 music 目录</span>
</div>
</div>
</section>
</main>
<footer class="footer">
<p>朋友的声音收藏馆 © 2024 — Powered by APlayer</p>
</footer>
</div>
<div class="toast" id="toast"></div>
<!-- Modal -->
<div class="modal-overlay" id="historyModal">
<div class="modal-content glass">
<div class="modal-header">
<h3>播放历史</h3>
<button class="modal-close" id="historyModalClose">×</button>
</div>
<div class="modal-body">
<ul id="historyList" class="history-list">
<li class="history-empty">暂无播放记录</li>
</ul>
<button id="clearHistoryBtn" class="clear-history-btn">清空历史</button>
</div>
</div>
</div>
<!-- Login Modal -->
<div class="modal-overlay" id="loginModal">
<div class="modal-content glass" style="max-width:380px">
<div class="modal-header">
<h3>管理员登录</h3>
<button class="modal-close" id="loginModalClose">×</button>
</div>
<div class="modal-body" style="padding:24px">
<div class="form-group">
<label class="form-label">登录密码</label>
<input type="password" id="loginPassword" class="form-input" placeholder="请输入管理员密码" autocomplete="off">
</div>
<label class="checkbox-label">
<input type="checkbox" id="rememberMe" class="checkbox-input">
<span class="checkbox-mark"></span>
记住密码,自动登录
</label>
<button id="loginBtn" class="form-btn primary">登 录</button>
<p id="loginError" class="form-error"></p>
</div>
</div>
</div>
<!-- Settings Modal -->
<div class="modal-overlay" id="settingsModal">
<div class="modal-content glass settings-modal">
<div class="modal-header">
<h3>管理员设置</h3>
<button class="modal-close" id="settingsModalClose">×</button>
</div>
<div class="settings-layout">
<div class="settings-sidebar">
<button class="settings-tab active" data-tab="site">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
站点设置
</button>
<button class="settings-tab" data-tab="source">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/></svg>
音乐来源
</button>
<button class="settings-tab" data-tab="style">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"/></svg>
样式设置
</button>
<div class="settings-sidebar-spacer"></div>
<button class="settings-tab" data-tab="account">
<svg viewBox="0 0 24 24" width="16" height="16"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/></svg>
账户
</button>
</div>
<div class="settings-content">
<!-- Site Settings -->
<div class="settings-pane active" id="pane-site">
<div class="form-group">
<label class="form-label">网站图标 (favicon URL)</label>
<input type="url" id="siteFavicon" class="form-input" placeholder="https://example.com/favicon.ico">
</div>
<div class="form-group">
<label class="form-label">网站标题</label>
<input type="text" id="siteTitle" class="form-input" placeholder="朋友的声音收藏馆">
</div>
<div class="form-group">
<label class="form-label">网站副标题</label>
<input type="text" id="siteSubtitle" class="form-input" placeholder="收藏那些值得被记住的声音">
</div>
<div class="form-group">
<label class="form-label">页脚版权信息</label>
<input type="text" id="siteFooter" class="form-input" placeholder="朋友的声音收藏馆 © 2024">
</div>
</div>
<!-- Music Source -->
<div class="settings-pane" id="pane-source">
<div class="form-group">
<label class="form-label">WebDAV 地址</label>
<input type="url" id="webdavUrl" class="form-input" placeholder="https://example.com/dav">
</div>
<div class="form-group">
<label class="form-label">WebDAV 用户名</label>
<input type="text" id="webdavUser" class="form-input" placeholder="admin">
</div>
<div class="form-group">
<label class="form-label">WebDAV 密码</label>
<input type="password" id="webdavPass" class="form-input" placeholder="********">
</div>
<button id="testWebdavBtn" class="form-btn" style="margin-bottom:12px">测试连接</button>
</div>
<!-- Style Settings -->
<div class="settings-pane" id="pane-style">
<div class="form-group">
<label class="form-label">默认封面图 URL</label>
<input type="url" id="defaultCover" class="form-input" placeholder="https://example.com/default-cover.jpg">
</div>
<div class="form-group">
<label class="form-label">播放器主题色</label>
<div class="color-input-wrap">
<input type="color" id="accentColor" class="color-input" value="#3b82f6">
<input type="text" id="accentColorText" class="form-input color-text" value="#3b82f6">
</div>
</div>
</div>
<!-- Account -->
<div class="settings-pane" id="pane-account">
<div class="form-group">
<label class="form-label">修改管理员密码</label>
<input type="password" id="adminNewPassword" class="form-input" placeholder="留空则不修改">
</div>
<div class="form-divider"></div>
<div class="form-group">
<label class="form-label">GitHub Token(用于网页后台直接保存配置到仓库)</label>
<input type="password" id="githubToken" class="form-input" placeholder="ghp_xxxxxxxxxxxx">
<p style="font-size:0.75rem;color:var(--text-muted);margin-top:4px">在 GitHub Settings → Developer settings → Personal access tokens → Tokens (classic) 创建,勾选 repo 权限</p>
</div>
<div class="form-group">
<label class="form-label">仓库名(owner/repo)</label>
<input type="text" id="githubRepo" class="form-input" placeholder="用户名/仓库名">
</div>
</div>
<div class="settings-footer">
<div class="form-actions">
<button id="saveSettingsBtn" class="form-btn primary">保存设置</button>
<button id="exportEncBtn" class="form-btn">导出配置</button>
<button id="importConfigBtn" class="form-btn">导入配置</button>
<button id="lockBtn" class="form-btn danger">锁定</button>
</div>
<input type="file" id="importFileInput" accept=".enc,.json" style="display:none">
<p id="settingsStatus" class="form-status"></p>
</div>
</div>
</div>
</div>
</div>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then(regs => {
regs.forEach(r => r.unregister());
});
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.10.1/APlayer.min.js"></script>
<script src="site-config.js"></script>
<script src="script.js?v=14"></script>
</body>
</html>