Files
SunShineMusic/sou.php
2025-09-24 14:15:37 +00:00

667 lines
35 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once 'config.php';
// 页面标题
$pageTitle = "音乐搜索 - 落日音乐";
// 设备识别函数
function isMobileDevice() {
$userAgent = $_SERVER['HTTP_USER_AGENT'];
$mobileKeywords = [
'Android', 'webOS', 'iPhone', 'iPad', 'iPod', 'BlackBerry',
'Windows Phone', 'Opera Mini', 'IEMobile', 'Mobile'
];
foreach ($mobileKeywords as $keyword) {
if (stripos($userAgent, $keyword) !== false) {
return true;
}
}
return false;
}
$isMobile = isMobileDevice();
$htmlClass = $isMobile ? 'mobile' : 'desktop';
// 检查用户登录状态
session_start();
$isLoggedIn = isset($_SESSION['user_logged_in']) && $_SESSION['user_logged_in'] === true;
$userInfo = isset($_SESSION['user_info']) ? $_SESSION['user_info'] : null;
// 处理登出
if (isset($_GET['action']) && $_GET['action'] == 'logout') {
session_unset();
session_destroy();
header("Location: index.php");
exit;
}
// 定义音乐分类及其配色
$categories = [
'all' => ['name' => '全部音乐', 'color' => '#b89e81', 'text_color' => '#5d4037'],
'cantonese' => ['name' => '粤语歌曲', 'color' => '#c8e6c9', 'text_color' => '#2e7d32'],
'mandarin' => ['name' => '国语歌曲', 'color' => '#fff3e0', 'text_color' => '#e65100'],
'waiyu' => ['name' => '外语歌曲', 'color' => '#e3f2fd', 'text_color' => '#0d47a1'],
'classic' => ['name' => '经典老歌', 'color' => '#efebe9', 'text_color' => '#3e2723'],
'other' => ['name' => '其他音乐', 'color' => '#f3e5f5', 'text_color' => '#6a1b9a']
];
// 获取音乐列表数据
$musicList = require_once __DIR__ . '/data/music.php';
// 获取并清理搜索词
$searchTerm = isset($_GET['s']) ? trim($_GET['s']) : '';
// 搜索功能:匹配歌名或歌手(不区分大小写)
$searchResults = [];
if (!empty($searchTerm)) {
$lowerTerm = strtolower($searchTerm);
foreach ($musicList as $music) {
if (strpos(strtolower($music['title']), $lowerTerm) !== false ||
strpos(strtolower($music['artist']), $lowerTerm) !== false) {
$searchResults[] = $music;
}
}
}
// 获取当前页面URL
function getCurrentPageURL() {
$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$host = $_SERVER['HTTP_HOST'];
$script = $_SERVER['SCRIPT_NAME'];
return $protocol . $host . $script;
}
$currentPageUrl = getCurrentPageURL();
?>
<!DOCTYPE html>
<html lang="zh_cn" class="<?php echo $htmlClass; ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title><?php echo htmlspecialchars($pageTitle); ?></title>
<meta name="copyright" content="本网站内容受版权保护,未经许可不得复制或使用">
<link rel="icon" href="./static/icon/icon.png" type="image/png">
<link rel="alternate icon" href="./static/icon/icon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@font-face {
font-family: "MyCustomFont";
src: url("./static/font/bbc.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
/* === 基础样式与暗黑模式变量 === */
:root {
--bg-color: #f5f5f7;
--text-color: #333;
--card-bg: #ffffff;
--card-shadow: 0 4px 12px rgba(0,0,0,0.1);
--primary-color: #2c3e50;
--primary-hover: #34495e;
--muted-color: #666;
--border-color: #ddd;
--accent-color: #e74c3c;
--notification-bg: #2c3e50;
--notification-text: #ffffff;
--main-font: "MyCustomFont", sans-serif; /* 自定义字体变量 */
}
.dark-mode {
--bg-color: #121212;
--text-color: #e0e0e0;
--card-bg: #1e1e1e;
--card-shadow: 0 4px 12px rgba(0,0,0,0.5);
--primary-color: #bb86fc;
--primary-hover: #9c6cd6;
--muted-color: #b0b0b0;
--border-color: #333;
--accent-color: #ff6b6b;
--notification-bg: #111;
--notification-text: #e0e0e0;
}
body {
font-family: var(--main-font), /* 应用自定义字体 */ sans-serif; margin: 0; padding: 0; background-color: var(--bg-color); color: var(--text-color); transition: background-color 0.3s ease, color 0.3s ease; }
.app-container { display: flex; flex-direction: column; min-height: 100vh; }
.top-bar { display: flex; justify-content: space-between; align-items: center; padding: 1rem 1.5rem; background-color: var(--card-bg); box-shadow: 0 2px 8px rgba(0,0,0,0.1); position: sticky; top: 0; z-index: 100; transition: background-color 0.3s ease; }
.site-title { margin: 0; font-size: 1.4rem; color: var(--primary-color); }
.theme-toggle, .user-menu-btn, .back-link { background: none; border: 1px solid var(--border-color); color: var(--text-color); padding: 0.5rem 0.8rem; border-radius: 20px; cursor: pointer; display: flex; align-items: center; gap: 0.5rem; transition: all 0.3s ease; text-decoration: none; }
.theme-toggle:hover, .user-menu-btn:hover, .back-link:hover { background-color: var(--primary-color); color: white; border-color: var(--primary-color); }
.main-content { flex: 1; max-width: 1200px; width: 100%; margin: 0 auto; padding: 1rem; box-sizing: border-box; }
h1, h2, h3 { color: var(--primary-color); }
h1 { font-size: 1.8rem; text-align: center; margin: 1rem 0; }
/* 搜索框 */
.search-container { margin: 1rem 0; text-align: center; }
#search-form { max-width: 600px; margin: 0 auto; }
#search-input { width: 100%; max-width: 600px; padding: 0.8rem 1rem; border: 1px solid var(--border-color); border-radius: 25px; font-size: 1rem; background-color: var(--card-bg); color: var(--text-color); transition: all 0.3s ease; }
#search-input:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 2px rgba(44, 62, 80, 0.1); }
/* 音乐项样式 */
.music-item { background-color: var(--card-bg); border-radius: 12px; padding: 1.2rem; box-shadow: var(--card-shadow); margin-bottom: 1.2rem; transition: background-color 0.3s ease; }
.category-tag { display: inline-block; padding: 0.3rem 0.8rem; border-radius: 15px; font-size: 0.8rem; font-weight: 500; margin-right: 0.5rem; margin-bottom: 0.8rem; }
.artist-info { color: var(--muted-color); font-size: 0.9rem; margin-bottom: 1rem; font-style: italic; }
/* 播放器、视频、下载、分享 样式 */
.custom-audio-player, .video-container, .download-section, .share-section { margin-top: 1rem; }
.custom-audio-player { width: 100%; background-color: var(--bg-color); border-radius: 8px; padding: 0.8rem; display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; }
.audio-controls, .volume-control { display: flex; align-items: center; gap: 0.8rem; }
.audio-button, .volume-button { background: none; border: none; cursor: pointer; color: var(--primary-color); font-size: 1.2rem; width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; }
.audio-button:hover, .volume-button:hover { background-color: rgba(44, 62, 80, 0.1); }
.audio-button.active { background-color: var(--primary-color); color: white; }
.progress-container { flex-grow: 1; display: flex; align-items: center; gap: 0.5rem; min-width: 200px; }
.audio-progress { flex-grow: 1; height: 4px; background-color: var(--border-color); border-radius: 2px; cursor: pointer; position: relative; }
.progress-fill { height: 100%; background-color: var(--primary-color); border-radius: 2px; width: 0%; }
.progress-handle { position: absolute; width: 12px; height: 12px; border-radius: 50%; background-color: var(--primary-color); top: 50%; transform: translateY(-50%); left: 0%; display: none; box-shadow: 0 0 5px rgba(0,0,0,0.2); }
.audio-progress:hover .progress-handle { display: block; }
.time-display, .time-separator { font-size: 0.8rem; color: var(--muted-color); width: 40px; text-align: center; }
.volume-slider { width: 80px; height: 4px; -webkit-appearance: none; appearance: none; background: var(--border-color); border-radius: 2px; outline: none; }
.volume-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--primary-color); cursor: pointer; }
.video-container { position: relative; width: 100%; padding-top: 56.25%; border-radius: 8px; overflow: hidden; }
.video-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; }
.download-link { display: inline-block; color: var(--primary-color); text-decoration: none; padding: 0.5rem 1rem; border: 1px solid var(--primary-color); border-radius: 20px; transition: all 0.3s ease; font-size: 0.95rem; }
.download-link:hover { background-color: var(--primary-color); color: white; }
.share-section { display: flex; align-items: center; gap: 0.5rem; }
.share-link-container { display: flex; align-items: center; gap: 0.5rem; flex-grow: 1; }
.share-link { flex-grow: 1; padding: 0.5rem; border: 1px solid var(--border-color); border-radius: 4px; font-size: 0.9rem; color: var(--text-color); background-color: var(--bg-color); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.copy-button, .jump-button { background-color: var(--bg-color); border: 1px solid var(--border-color); padding: 0.5rem; border-radius: 4px; cursor: pointer; transition: all 0.3s ease; color: var(--text-color); text-decoration: none; }
.copy-button:hover, .jump-button:hover { background-color: var(--primary-color); color: white; }
/* 结果提示 */
.results-info, .no-results { text-align: center; padding: 1rem; color: var(--muted-color); }
.no-results { padding: 3rem 1rem; }
.no-results h3 { color: var(--muted-color); }
.no-results p { margin: 1rem 0; }
.no-results a { color: var(--primary-color); text-decoration: none; }
.no-results a:hover { text-decoration: underline; }
/* 复制提示和回到顶部 */
.copy-notification, .back-to-top { position: fixed; bottom: 20px; right: 20px; background-color: var(--notification-bg); color: var(--notification-text); padding: 0.8rem 1.2rem; border-radius: 4px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); opacity: 0; transform: translateY(20px); transition: all 0.3s ease; pointer-events: none; z-index: 999; }
.copy-notification.show, .back-to-top.show { opacity: 1; transform: translateY(0); pointer-events: auto; }
.back-to-top { width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 1.5rem; cursor: pointer; }
/* 移动端适配 */
@media (max-width: 768px) {
.progress-container { order: 2; width: 100%; }
.volume-control { margin-top: 0.5rem; width: 100%; justify-content: center; order: 3; }
.share-section { flex-direction: column; align-items: stretch; }
.share-link-container { width: 100%; }
}
</style>
</head>
<body>
<div class="app-container">
<div class="top-bar">
<a href="index.php" class="back-link"><i class="fas fa-arrow-left"></i> 返回主页</a>
<h1 class="site-title">音乐搜索</h1>
<div style="display: flex; gap: 10px;">
<button class="theme-toggle" id="theme-toggle"><i class="fas fa-moon"></i><span>暗黑模式</span></button>
</div>
</div>
<div class="main-content">
<div class="search-container">
<form id="search-form" action="sou.php" method="get">
<input type="text" id="search-input" name="s" placeholder="搜索音乐名称或歌手..." value="<?php echo htmlspecialchars($searchTerm); ?>">
</form>
</div>
<?php if (!empty($searchTerm)): ?>
<div class="results-info">
<p>为您找到 "<?php echo htmlspecialchars($searchTerm); ?>" 的相关结果,共 <?php echo count($searchResults); ?> 条。</p>
</div>
<?php endif; ?>
<div id="music-list-container">
<?php if (!empty($searchResults)): ?>
<?php foreach ($searchResults as $music): ?>
<?php
$shareUrl = $currentPageUrl . "?s=" . urlencode($searchTerm) . "&play=" . $music['id'];
$categoryConfig = $categories[$music['category']];
?>
<div class="music-item" data-category="<?php echo $music['category']; ?>" data-id="<?php echo $music['id']; ?>">
<span class="category-tag" style="background-color: <?php echo $categoryConfig['color']; ?>; color: <?php echo $categoryConfig['text_color']; ?>"><?php echo $categoryConfig['name']; ?></span>
<h2><?php echo htmlspecialchars($music['title']); ?></h2>
<p class="artist-info">作者:<?php echo htmlspecialchars($music['artist']); ?></p>
<div class="custom-audio-player">
<div class="audio-controls">
<button class="audio-button play-pause" data-audio="<?php echo $music['id']; ?>">▶</button>
<button class="audio-button loop" data-audio="<?php echo $music['id']; ?>">🔄</button>
</div>
<div class="progress-container">
<div class="audio-progress" data-audio="<?php echo $music['id']; ?>">
<div class="progress-fill" data-audio="<?php echo $music['id']; ?>"></div>
<div class="progress-handle" data-audio="<?php echo $music['id']; ?>"></div>
</div>
<span class="time-display current-time" data-audio="<?php echo $music['id']; ?>">0:00</span>
<span class="time-separator">/</span>
<span class="time-display total-time" data-audio="<?php echo $music['id']; ?>"><?php echo $music['duration']; ?></span>
</div>
<div class="volume-control" data-audio="<?php echo $music['id']; ?>">
<button class="volume-button" data-audio="<?php echo $music['id']; ?>">🔊</button>
<input type="range" class="volume-slider" data-audio="<?php echo $music['id']; ?>" min="0" max="1" step="0.05" value="1">
</div>
</div>
<audio id="<?php echo $music['id']; ?>" class="audio-element" src="<?php echo htmlspecialchars($music['mp3']); ?>" type="audio/mpeg">
您的浏览器不支持音频播放
</audio>
<div class="video-container">
<iframe
src="https://player.bilibili.com/player.html?bvid=<?php echo $music['bvid']; ?>&page=1"
allowfullscreen="true"
loading="lazy">
</iframe>
</div>
<div class="download-section">
<p>下载:
<a href="<?php echo htmlspecialchars($music['mp3']); ?>" class="download-link" download>点我下载</a>
</p>
</div>
<!-- 分享功能 -->
<div class="share-section">
<div class="share-link-container">
<input type="text" class="share-link" value="<?php echo htmlspecialchars($shareUrl); ?>" readonly>
<button class="copy-button" data-audio="<?php echo $music['id']; ?>" title="复制链接">
<i class="fas fa-copy"></i>
</button>
<a href="<?php echo htmlspecialchars($shareUrl); ?>"
class="jump-button"
target="_blank"
title="在新窗口打开">
<i class="fas fa-external-link-alt"></i>
</a>
</div>
</div>
</div>
<?php endforeach; ?>
<?php elseif (!empty($searchTerm)): ?>
<!-- 没有搜索结果时显示 -->
<div class="no-results">
<h3>未找到相关结果</h3>
<p>没有找到与 "<?php echo htmlspecialchars($searchTerm); ?>" 相关的音乐</p>
<p>请尝试其他关键词或<a href="index.php">浏览全部音乐</a></p>
</div>
<?php else: ?>
<!-- 没有输入搜索词时显示 -->
<div class="no-results">
<h3>请输入搜索关键词</h3>
<p>在上方搜索框中输入音乐名称或歌手名进行搜索</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
<!-- 复制成功提示 -->
<div class="copy-notification" id="copy-notification">
链接已复制到剪贴板!
</div>
<!-- 回到顶部按钮 -->
<div class="back-to-top" id="back-to-top">
<i class="fas fa-arrow-up"></i>
</div>
<script>
// 核心功能代码
(function(d, w) {
// 工具函数简写
var q = d.querySelector.bind(d);
var qa = d.querySelectorAll.bind(d);
var addEvt = function(el, evt, fn) {
if (el.addEventListener) el.addEventListener(evt, fn);
else if (el.attachEvent) el.attachEvent('on' + evt, fn);
};
// 格式化时间(秒 -> 分:秒)
function formatTime(seconds) {
if (isNaN(seconds)) return "0:00";
var minutes = Math.floor(seconds / 60);
var secs = Math.floor(seconds % 60);
return minutes + ":" + (secs < 10 ? "0" + secs : secs);
}
// 切换播放/暂停状态
function togglePlayback(audio, playBtn) {
if (audio.paused) {
// 暂停其他正在播放的音频
qa('.audio-element').forEach(function(otherAudio) {
if (otherAudio !== audio && !otherAudio.paused) {
otherAudio.pause();
q('.play-pause[data-audio="' + otherAudio.id + '"]').textContent = '▶';
}
});
audio.play();
playBtn.textContent = '⏸';
} else {
audio.pause();
playBtn.textContent = '▶';
}
}
// 初始化暗黑模式
function initDarkMode() {
const themeToggle = q('#theme-toggle');
const themeIcon = themeToggle.querySelector('i');
const themeText = themeToggle.querySelector('span');
// 检查用户偏好或本地存储
if (localStorage.getItem('theme') === 'dark' ||
(!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
d.body.classList.add('dark-mode');
themeIcon.classList.remove('fa-moon');
themeIcon.classList.add('fa-sun');
themeText.textContent = '明亮模式';
}
// 绑定切换事件
addEvt(themeToggle, 'click', function() {
d.body.classList.toggle('dark-mode');
if (d.body.classList.contains('dark-mode')) {
themeIcon.classList.remove('fa-moon');
themeIcon.classList.add('fa-sun');
themeText.textContent = '明亮模式';
localStorage.setItem('theme', 'dark');
} else {
themeIcon.classList.remove('fa-sun');
themeIcon.classList.add('fa-moon');
themeText.textContent = '暗黑模式';
localStorage.setItem('theme', 'light');
}
});
}
// 播放进度记忆功能
function initPlaybackPositionMemory() {
// 保存播放进度
window.savePlaybackPosition = function(songId, position) {
const positions = JSON.parse(localStorage.getItem('playbackPositions') || '{}');
positions[songId] = {
position: position,
timestamp: new Date().getTime()
};
localStorage.setItem('playbackPositions', JSON.stringify(positions));
};
// 恢复播放进度
window.restorePlaybackPosition = function(songId) {
const positions = JSON.parse(localStorage.getItem('playbackPositions') || '{}');
return positions[songId] ? positions[songId].position : 0;
};
}
// 初始化播放器
function initAudioPlayers() {
const audios = qa('.audio-element');
audios.forEach(function(audio) {
const id = audio.id;
const playBtn = q('.play-pause[data-audio="' + id + '"]');
const loopBtn = q('.loop[data-audio="' + id + '"]');
const progressBar = q('.audio-progress[data-audio="' + id + '"]');
const progressFill = q('.progress-fill[data-audio="' + id + '"]');
const progressHandle = q('.progress-handle[data-audio="' + id + '"]');
const currentTime = q('.current-time[data-audio="' + id + '"]');
const totalTime = q('.total-time[data-audio="' + id + '"]');
const volumeBtn = q('.volume-button[data-audio="' + id + '"]');
const volumeSlider = q('.volume-slider[data-audio="' + id + '"]');
// 获取歌曲信息
const musicItem = audio.closest('.music-item');
const songTitle = musicItem.querySelector('h2').textContent;
const artist = musicItem.querySelector('.artist-info').textContent.replace('作者:', '');
let originalVolume = 1;
let isDragging = false;
// 音频加载完成 - 恢复上次播放进度
addEvt(audio, 'loadedmetadata', function() {
totalTime.textContent = formatTime(audio.duration);
audio.volume = volumeSlider.value;
// 恢复播放进度
const savedPosition = restorePlaybackPosition(id);
if (savedPosition > 0 && savedPosition < audio.duration) {
audio.currentTime = savedPosition;
// 更新UI
const progress = (savedPosition / audio.duration) * 100;
progressFill.style.width = progress + '%';
progressHandle.style.left = progress + '%';
currentTime.textContent = formatTime(savedPosition);
}
});
// 播放/暂停
addEvt(playBtn, 'click', function() {
togglePlayback(audio, playBtn);
// 添加到播放历史(复用首页的存储逻辑)
addToHistory(id, songTitle, artist);
});
// 循环播放
addEvt(loopBtn, 'click', function() {
audio.loop = !audio.loop;
loopBtn.classList.toggle('active', audio.loop);
if (audio.loop) {
loopBtn.style.transform = 'scale(1.1)';
setTimeout(function() {
loopBtn.style.transform = 'scale(1)';
}, 200);
}
});
// 更新进度 - 并保存播放进度
addEvt(audio, 'timeupdate', function() {
if (!isDragging) {
const progress = (audio.currentTime / audio.duration) * 100;
progressFill.style.width = progress + '%';
progressHandle.style.left = progress + '%';
currentTime.textContent = formatTime(audio.currentTime);
// 定期保存播放进度
if (audio.currentTime > 0 &&
(audio.currentTime % 30 < 0.1 ||
Math.abs(audio.currentTime - (audio.duration * 0.9)) < 0.5)) {
savePlaybackPosition(id, audio.currentTime);
}
}
});
// 播放结束时保存最终进度
addEvt(audio, 'ended', function() {
savePlaybackPosition(id, 0); // 播放结束后重置进度
playBtn.textContent = '▶';
});
// 进度条拖动
const startDrag = function(e) {
isDragging = true;
progressHandle.classList.add('dragging');
updateProgress(e);
};
const updateProgress = function(e) {
if (!audio.duration) return;
// 获取进度条的位置和宽度
const rect = progressBar.getBoundingClientRect();
let pos = (e.clientX - rect.left) / rect.width;
pos = Math.max(0, Math.min(1, pos)); // 限制在0-1之间
// 更新UI
const percentage = pos * 100;
progressFill.style.width = percentage + '%';
progressHandle.style.left = percentage + '%';
currentTime.textContent = formatTime(pos * audio.duration);
};
const endDrag = function() {
if (!isDragging) return;
isDragging = false;
progressHandle.classList.remove('dragging');
// 设置音频位置
const pos = parseFloat(progressFill.style.width) / 100;
audio.currentTime = pos * audio.duration;
savePlaybackPosition(id, audio.currentTime);
};
// 进度条事件
addEvt(progressBar, 'click', updateProgress);
addEvt(progressHandle, 'mousedown', startDrag);
addEvt(d, 'mousemove', function(e) { if (isDragging) updateProgress(e); });
addEvt(d, 'mouseup', endDrag);
addEvt(d, 'mouseleave', endDrag);
// 移动端触摸事件
addEvt(progressBar, 'touchstart', function(e) {
e.preventDefault();
startDrag(e.touches[0]);
});
addEvt(d, 'touchmove', function(e) {
if (isDragging) {
e.preventDefault();
updateProgress(e.touches[0]);
}
});
addEvt(d, 'touchend', endDrag);
// 音量控制
addEvt(volumeBtn, 'click', function() {
if (audio.volume > 0) {
originalVolume = audio.volume;
audio.volume = 0;
volumeBtn.textContent = '🔇';
volumeSlider.value = 0;
} else {
audio.volume = originalVolume;
volumeBtn.textContent = '🔊';
volumeSlider.value = originalVolume;
}
});
addEvt(volumeSlider, 'input', function() {
audio.volume = this.value;
originalVolume = this.value;
volumeBtn.textContent = this.value > 0 ? '🔊' : '🔇';
});
});
}
// 初始化复制功能
function initCopyFunctionality() {
const copyButtons = qa('.copy-button');
const notification = q('#copy-notification');
copyButtons.forEach(function(btn) {
addEvt(btn, 'click', function() {
const audioId = this.getAttribute('data-audio');
const shareLink = this.parentElement.querySelector('.share-link');
if (shareLink) {
shareLink.select();
d.execCommand('copy');
// 显示通知
notification.classList.add('show');
setTimeout(function() {
notification.classList.remove('show');
}, 2000);
}
});
});
}
// 初始化回到顶部按钮
function initBackToTop() {
const backToTopBtn = q('#back-to-top');
addEvt(w, 'scroll', function() {
if (w.pageYOffset > 300) {
backToTopBtn.classList.add('show');
} else {
backToTopBtn.classList.remove('show');
}
});
addEvt(backToTopBtn, 'click', function() {
w.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
// 添加到播放历史(与首页保持一致的存储格式)
window.addToHistory = function(songId, songTitle, artist) {
let history = JSON.parse(localStorage.getItem('playHistory') || '[]');
// 移除已存在的相同歌曲(避免重复)
history = history.filter(item => item.id !== songId);
// 添加新记录到最前面
history.unshift({
id: songId,
title: songTitle,
artist: artist,
timestamp: new Date().getTime()
});
// 限制历史记录数量
if (history.length > 20) {
history = history.slice(0, 20);
}
localStorage.setItem('playHistory', JSON.stringify(history));
};
// 检查URL参数自动播放指定音乐
function autoPlayFromUrl() {
const params = new URLSearchParams(w.location.search);
const playId = params.get('play');
if (playId) {
const audio = q('#' + playId);
const playBtn = q('.play-pause[data-audio="' + playId + '"]');
if (audio && playBtn) {
// 滚动到音乐项
const musicItem = audio.closest('.music-item');
if (musicItem) {
musicItem.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// 播放音乐
setTimeout(function() {
if (audio.paused) {
togglePlayback(audio, playBtn);
}
}, 500);
}
}
}
// 初始化所有功能
function initAll() {
initDarkMode();
initPlaybackPositionMemory();
initAudioPlayers();
initCopyFunctionality();
initBackToTop();
autoPlayFromUrl();
}
// 页面加载完成后初始化
addEvt(w, 'load', initAll);
})(document, window);
</script>
</body>
</html>