396 lines
18 KiB
HTML
396 lines
18 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width, initial-scale=1.0, viewport-fit=cover, maximum-scale=1"
|
|
/>
|
|
<meta name="theme-color" content="#f4f5f9" />
|
|
<title>Xiao の 电台</title>
|
|
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
|
<link rel="stylesheet" href="vendor/bootstrap.min.css" />
|
|
<link rel="stylesheet" href="vendor/bootstrap-icons.css" />
|
|
<script src="vendor/Sortable.min.js"></script>
|
|
<link rel="stylesheet" href="css/style.css" />
|
|
</head>
|
|
<body>
|
|
<div class="page-bg"></div>
|
|
<div class="bg-shapes">
|
|
<div class="s"></div>
|
|
<div class="s"></div>
|
|
<div class="s"></div>
|
|
</div>
|
|
<div class="toast-container" id="toastContainer"></div>
|
|
|
|
<!-- Header -->
|
|
<header class="top-header">
|
|
<div class="header-inner">
|
|
<div class="brand">
|
|
<div class="brand-icon">
|
|
<img src="favicon.png" alt="logo" />
|
|
</div>
|
|
<span>Xiao の 电台</span>
|
|
<span class="live-pill"
|
|
><span class="live-dot"></span>LIVE</span
|
|
>
|
|
</div>
|
|
<div class="header-actions">
|
|
<span class="cache-pill" id="cacheInfo"><i class="bi bi-database"></i> --</span>
|
|
<select class="stream-select" id="streamSelect" title="切换频道"></select>
|
|
<a href="#" id="liveLink" class="btn-link-sm" target="_blank" title="打开直播流"
|
|
><i class="bi bi-link-45deg"></i></a
|
|
>
|
|
<button class="btn-link-sm" id="btnLogout" title="退出登录"
|
|
><i class="bi bi-box-arrow-right"></i></button>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Pages -->
|
|
<div class="page-container">
|
|
<!-- 1. Search -->
|
|
<div class="page active" id="pageSearch">
|
|
<div class="search-card">
|
|
<div class="search-header">
|
|
<h2>导入音源</h2>
|
|
<p>输入网易云歌曲 ID、链接或歌名查询并下载</p>
|
|
</div>
|
|
<div class="search-input-wrap">
|
|
<div class="search-field">
|
|
<input
|
|
type="text"
|
|
id="musicId"
|
|
placeholder="歌曲 ID、链接或歌名,如 33894312 / 知我"
|
|
inputmode="text"
|
|
autocomplete="off"
|
|
spellcheck="false"
|
|
/>
|
|
<button class="btn-search" id="btnSearch">
|
|
查询
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="parse-hint" id="parseHint">
|
|
<i class="bi bi-magic"></i>
|
|
已自动解析为 ID:<code id="parsedId"></code>
|
|
</div>
|
|
<!-- Preview: info only -->
|
|
<div id="musicPreview" style="display: none">
|
|
<div class="preview-card">
|
|
<div class="preview-cover-section">
|
|
<div class="preview-cover-wrap">
|
|
<img
|
|
id="musicCover"
|
|
class="preview-cover"
|
|
src=""
|
|
alt=""
|
|
/>
|
|
</div>
|
|
<div class="preview-info">
|
|
<div
|
|
class="preview-title"
|
|
id="musicName"
|
|
></div>
|
|
<div
|
|
class="preview-artist"
|
|
id="musicArtist"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="preview-details"
|
|
id="musicDetails"
|
|
></div>
|
|
<div class="preview-actions">
|
|
<button class="btn-download" id="btnDownload">
|
|
<i class="bi bi-download"></i> 下载到资源库
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
id="searchResults"
|
|
class="searchResults"
|
|
style="display: none"
|
|
></div>
|
|
<div class="search-tips" id="searchTips">
|
|
<div class="tips-icon">
|
|
<i class="bi bi-music-note-beamed"></i>
|
|
</div>
|
|
<div class="tips-title">搜索并下载音乐</div>
|
|
<div class="tips-desc">
|
|
在网易云音乐中复制歌曲 ID 或完整链接<br />粘贴到上方输入框即可自动识别
|
|
</div>
|
|
</div>
|
|
<!-- Import local audio -->
|
|
<div class="import-card" id="importCard">
|
|
<div class="import-header">
|
|
<h3><i class="bi bi-upload"></i> 本地导入</h3>
|
|
<p>上传音频文件,自动识别作者与封面(封面存本地)</p>
|
|
</div>
|
|
<input type="file" id="importFile" accept="audio/*,.mp3,.m4a,.flac,.wav,.aac,.ogg" hidden />
|
|
<input type="text" id="importTitle" class="import-input" placeholder="歌曲名(选填,留空则用文件名)" />
|
|
<input type="text" id="importArtist" class="import-input" placeholder="作者(选填,留空自动匹配)" />
|
|
<button class="btn-download" id="btnImport"><i class="bi bi-upload"></i> 选择文件并导入</button>
|
|
<div class="import-progress" id="importProgress"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 2. Resources -->
|
|
<div class="page" id="pageResources">
|
|
<div class="section-card">
|
|
<div class="section-header">
|
|
<div class="section-title">
|
|
<i
|
|
class="bi bi-folder2-open"
|
|
style="color: var(--accent)"
|
|
></i>
|
|
已有音乐
|
|
<span class="section-count" id="resourceCount"
|
|
>0</span
|
|
>
|
|
</div>
|
|
<input
|
|
type="text"
|
|
class="resource-search"
|
|
id="resourceSearch"
|
|
placeholder="搜索已有音乐..."
|
|
autocomplete="off"
|
|
spellcheck="false"
|
|
/>
|
|
</div>
|
|
<div class="section-body" id="resourceList">
|
|
<div class="empty-state">
|
|
<div class="empty-icon">
|
|
<i class="bi bi-arrow-repeat"></i>
|
|
</div>
|
|
<div class="empty-title">加载中...</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 3. Playlist -->
|
|
<div class="page" id="pagePlaylist">
|
|
<div class="section-card">
|
|
<div class="section-header">
|
|
<div class="section-title">
|
|
<i
|
|
class="bi bi-music-note-list"
|
|
style="color: var(--accent)"
|
|
></i>
|
|
播放列表
|
|
<span class="section-count" id="playlistCount"
|
|
>0</span
|
|
>
|
|
</div>
|
|
<button class="btn-clear" id="btnClear">
|
|
<i class="bi bi-trash3"></i> 清空
|
|
</button>
|
|
</div>
|
|
<div class="section-body" id="playlistList">
|
|
<div class="empty-state">
|
|
<div class="empty-icon">
|
|
<i class="bi bi-arrow-repeat"></i>
|
|
</div>
|
|
<div class="empty-title">加载中...</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 4. About — 保持原有风格体系 -->
|
|
<div class="page" id="pageAbout">
|
|
<div class="about-card">
|
|
<!-- Hero -->
|
|
<div class="about-hero">
|
|
<div class="about-logo">
|
|
<img src="favicon.png" alt="logo" />
|
|
</div>
|
|
<h2>Xiao の 电台</h2>
|
|
<p>基于 HLS 的个人在线音乐电台</p>
|
|
</div>
|
|
|
|
<!-- Body -->
|
|
<div class="about-body">
|
|
<!-- 项目简介 -->
|
|
<div class="about-section">
|
|
<div class="about-section-icon">
|
|
<i class="bi bi-book"></i>
|
|
</div>
|
|
<div class="about-section-content">
|
|
<h3>项目简介</h3>
|
|
<p>
|
|
一个基于 Web 的个人在线音乐电台,支持通过网易云音乐歌曲 ID、链接或歌名进行搜索、试听与下载,提供 HLS 直播流播放、资源管理与播放列表拖拽排序等功能。界面采用简约玻璃拟态风格,适配移动端与桌面端多种屏幕尺寸。
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 核心功能 -->
|
|
<div class="about-section">
|
|
<div class="about-section-icon">
|
|
<i class="bi bi-lightning-charge"></i>
|
|
</div>
|
|
<div class="about-section-content">
|
|
<h3>核心功能</h3>
|
|
<div class="about-feature-list">
|
|
<div class="about-feat">
|
|
<i class="bi bi-search" style="color: var(--accent)"></i>
|
|
<span>智能搜索 — 歌曲 ID、链接或歌名关键词,自动解析并一键导入</span>
|
|
</div>
|
|
<div class="about-feat">
|
|
<i class="bi bi-broadcast" style="color: var(--success)"></i>
|
|
<span>直播流 — FFmpeg HLS 切片 + 滑动窗口,5 秒精度连续输出</span>
|
|
</div>
|
|
<div class="about-feat">
|
|
<i class="bi bi-database-check" style="color: var(--warning)"></i>
|
|
<span>智能缓存 — 预生成切片、增量追踪、LRU 淘汰与自动清理</span>
|
|
</div>
|
|
<div class="about-feat">
|
|
<i class="bi bi-hand-index-thumb" style="color: #8b5cf6"></i>
|
|
<span>播放列表 — 拖拽排序、添加/移除/跳转,SSE 实时状态推送</span>
|
|
</div>
|
|
<div class="about-feat">
|
|
<i class="bi bi-phone" style="color: #06b6d4"></i>
|
|
<span>全端适配 — 玻璃拟态 UI,手势滑动、键盘快捷键、拖拽进度条</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 技术栈 -->
|
|
<div class="about-section">
|
|
<div class="about-section-icon">
|
|
<i class="bi bi-tools"></i>
|
|
</div>
|
|
<div class="about-section-content">
|
|
<h3>技术栈</h3>
|
|
<div class="tech-tags">
|
|
<span>HTML5</span>
|
|
<span>CSS3</span>
|
|
<span>JavaScript ES6+</span>
|
|
<span>Bootstrap 5</span>
|
|
<span>SortableJS</span>
|
|
<span>HLS.js</span>
|
|
<span>Node.js</span>
|
|
<span>Express</span>
|
|
<span>FFmpeg</span>
|
|
<span>Chokidar</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 开发语言 -->
|
|
<div class="about-section">
|
|
<div class="about-section-icon">
|
|
<i class="bi bi-translate"></i>
|
|
</div>
|
|
<div class="about-section-content">
|
|
<h3>开发语言</h3>
|
|
<p>前端:HTML / CSS / JavaScript | 后端:Node.js</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 作者 -->
|
|
<div class="about-section">
|
|
<div class="about-section-icon">
|
|
<i class="bi bi-person"></i>
|
|
</div>
|
|
<div class="about-section-content">
|
|
<h3>作者</h3>
|
|
<p style="margin-bottom: 0.45rem">Xiao — 独立开发者</p>
|
|
<a
|
|
href="https://github.com/Xiao-no-love/"
|
|
target="_blank"
|
|
rel="noopener"
|
|
class="about-gh-link"
|
|
>
|
|
<i class="bi bi-github"></i>
|
|
<span>Xiao-no-love</span>
|
|
<i class="bi bi-box-arrow-up-right" style="font-size: 0.6rem; opacity: 0.5"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 免责声明 -->
|
|
<div class="about-section disclaimer-section">
|
|
<div class="about-section-icon">
|
|
<i class="bi bi-exclamation-triangle"></i>
|
|
</div>
|
|
<div class="about-section-content">
|
|
<h3>免责声明</h3>
|
|
<p>
|
|
本项目所有音源均来自网易云音乐,仅供个人学习与技术研究使用,严禁用于任何商业用途。音乐版权归原创作者及网易云音乐平台所有。如有侵权,请联系删除。请于下载后 24 小时内清除,支持正版音乐。
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<div class="about-version">
|
|
v2.0.0 · Built with ♥ ·
|
|
<a
|
|
href="https://github.com/Xiao-no-love/"
|
|
target="_blank"
|
|
rel="noopener"
|
|
style="color: var(--accent); text-decoration: none"
|
|
>GitHub</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mini Player — full background progress + drag seek -->
|
|
<div class="mini-player" id="miniPlayer">
|
|
<div class="mp-progress" id="mpProgress"></div>
|
|
<div class="mp-body" id="mpBody">
|
|
<img
|
|
class="mp-cover"
|
|
id="mpCover"
|
|
src=""
|
|
alt=""
|
|
onerror="this.style.display = 'none'"
|
|
/>
|
|
<div class="mp-info">
|
|
<div class="mp-name" id="mpName">未在播放</div>
|
|
<div class="mp-artist" id="mpArtist">--</div>
|
|
</div>
|
|
<div class="mp-controls">
|
|
<span class="mp-time" id="mpTime">0:00</span>
|
|
<button class="mp-play" id="mpPlay">
|
|
<i class="bi bi-play-fill"></i>
|
|
</button>
|
|
<button class="mp-expand" id="mpExpand" title="查看详情">
|
|
<i class="bi bi-chevron-up"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottom Nav — 4 tabs, full-width aligned with content -->
|
|
<nav class="bottom-nav">
|
|
<div class="bottom-nav-inner">
|
|
<button class="nav-tab active" data-page="pageSearch">
|
|
<i class="bi bi-search"></i><span>搜索</span>
|
|
</button>
|
|
<button class="nav-tab" data-page="pageResources">
|
|
<i class="bi bi-folder"></i><span>资源</span>
|
|
</button>
|
|
<button class="nav-tab" data-page="pagePlaylist">
|
|
<i class="bi bi-list-ul"></i><span>列表</span>
|
|
</button>
|
|
<button class="nav-tab" data-page="pageAbout">
|
|
<i class="bi bi-info-circle"></i><span>关于</span>
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Global audio element -->
|
|
<audio id="musicPlayer" preload="none" style="display: none"></audio>
|
|
|
|
<script src="js/app.js"></script>
|
|
</body>
|
|
</html>
|