12 Commits

5 changed files with 2251 additions and 2184 deletions

66
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,66 @@
name: Bug报告
about: 创建一个Bug报告以帮助我们改进
title: '[BUG] '
labels: BUG
assignees: ''
ref: 1.0
body:
- type: textarea
id: description
attributes:
label: 问题描述
description: 请清晰简洁地描述这个Bug是什么
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: 复现步骤
description: 复现这个Bug的步骤
placeholder: |
1. 打开页面 '...'
2. 点击 '....'
3. 滚动到 '....'
4. 看到错误
validations:
required: true
- type: textarea
id: expected
attributes:
label: 预期行为
description: 清晰简洁地描述你期望发生的事情
validations:
required: true
- type: textarea
id: actual
attributes:
label: 实际行为
description: 清晰简洁地描述实际发生的事情
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: 截图
description: 如果适用,添加截图以帮助解释你的问题
validations:
required: false
- type: textarea
id: environment
attributes:
label: 环境信息
description: 请提供你的环境信息
placeholder: |
操作系统: Windows 10
浏览器: Chrome 90.0.4430.212
设备: 桌面
validations:
required: false
- type: textarea
id: additional
attributes:
label: 其他信息
description: 在此处添加有关问题的任何其他上下文
validations:
required: false

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
blank_issues_enabled: false
templates:
- name: Bug报告
about: 创建一个Bug报告以帮助我们改进
file: bug_report.yml
- name: 功能请求
about: 为这个项目提出一个想法
file: feature_request.yml

View File

@@ -0,0 +1,43 @@
name: 功能请求
about: 为这个项目提出一个想法
title: '[FEATURE] '
labels: 增强
assignees: ''
ref: 1.0
body:
- type: textarea
id: feature_description
attributes:
label: 功能描述
description: 清晰简洁地描述你想要的功能是什么
validations:
required: true
- type: textarea
id: use_case
attributes:
label: 使用场景
description: 描述这个功能将如何被使用,以及它解决了什么问题
validations:
required: true
- type: textarea
id: implementation
attributes:
label: 可能的实现方式
description: 如果你有想法,描述你希望这个功能如何实现
validations:
required: false
- type: textarea
id: alternatives
attributes:
label: 替代方案
description: 描述你考虑过的任何替代解决方案或功能
validations:
required: false
- type: textarea
id: additional
attributes:
label: 其他信息
description: 在此处添加有关功能请求的任何其他上下文或截图
validations:
required: false

View File

@@ -1,7 +1,10 @@
# SunShineMusic # SunShineMusic
# 请不要部署,只是查看源码确保安全,很多地方都是硬编码
##### 落日音乐官方 ##### 落日音乐官方
##### 欢迎使用网站:https://shanwogou.cn.audio ##### 欢迎使用网站:https://lrgdmc.cn
##### .gitihub不要管,命名失误
> 代码因文件夹原因需要把zip都解压 > 代码因文件夹原因需要把zip都解压

323
index.php
View File

@@ -3,7 +3,7 @@ require_once 'config.php';
// 页面标题和版本信息 // 页面标题和版本信息
$pageTitle = "落日音乐 - 发现好音乐"; $pageTitle = "落日音乐 - 发现好音乐";
$siteVersion = "1.8.3.6016"; $siteVersion = "1.8.3.6016.001";
$bqsy = "2024-2025 落日音乐. JGZ_YES. 版权所有"; $bqsy = "2024-2025 落日音乐. JGZ_YES. 版权所有";
// 定义网站版权信息 // 定义网站版权信息
@@ -622,21 +622,6 @@ $currentPageUrl = getCurrentPageURL();
background-color: var(--primary-hover); background-color: var(--primary-hover);
} }
.recommendations-link {
display: block;
text-align: center;
margin-top: 1rem;
color: var(--primary-color);
text-decoration: none;
font-weight: 500;
padding: 0.5rem 0;
font-family: var(--main-font); /* 应用自定义字体 */
}
.recommendations-link:hover {
text-decoration: underline;
}
.message { .message {
padding: 1rem; padding: 1rem;
border-radius: 8px; border-radius: 8px;
@@ -1094,6 +1079,42 @@ $currentPageUrl = getCurrentPageURL();
.dark-mode .avatar-loading::after { .dark-mode .avatar-loading::after {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="%23fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M16 12a4 4 0 1 1-8 0"></path></svg>'); background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="%23fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M16 12a4 4 0 1 1-8 0"></path></svg>');
} }
.recommendations-link {
/* 让链接成为一个块级元素,方便控制 */
display: inline-block;
/* 为 transform 和 box-shadow 的变化添加过渡效果, duration 0.3s, timing-function ease */
/* 这会让悬浮效果更丝滑,而不是瞬间变化 */
transition: transform 0.3s ease, box-shadow 0.3s ease;
/* 可选:移除图片下方可能出现的小间隙 */
line-height: 0;
}
/* 当鼠标悬浮在链接上时 */
.recommendations-link:hover {
transform: translateY(-5px) scale(1.05); /* 向上移动5px并放大1.05倍 */
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.25);
}
/* 确保图片本身是响应式的,这里沿用你 inline 的 style */
.recommendations-link img {
/* 你原有的宽度设置,这里保持一致 */
width: 120px;
height: auto;
/* 可选:为图片添加圆角,视觉效果更好 */
/* border-radius: 8px; */
}
.music-item.centered-links {
display: flex;
flex-direction: column; /* 让子元素垂直排列 */
align-items: center; /* 水平居中对齐 */
justify-content: center; /* 垂直居中(如果容器有高度) */
text-align: center; /* 确保内部文本也居中 */
gap: 15px; /* 增加元素之间的间距,替代<br> */
padding: 20px 0; /* 上下增加一些内边距 */
}
</style> </style>
</head> </head>
<body> <body>
@@ -1304,17 +1325,24 @@ $currentPageUrl = getCurrentPageURL();
</div> </div>
<!-- 快捷链接 --> <!-- 快捷链接 -->
<div class="music-item"> <div class="music-item centered-links">
<h2>其他链接</h2> <h2>其他链接</h2>
<a href="http://leonmmcoset.jjxmm.win:8010/developer_apps.php?id=9" class="recommendations-link" target="_blank" rel="noopener noreferrer"> <a href="http://leonmmcoset.jjxmm.win:8010/developer_apps.php?id=9" class="recommendations-link" target="_blank" rel="noopener noreferrer">
<img src="https://shanwogou.cn/icon/leonapp.png" alt="LeonAPP" style="width: 120px; height: auto;"> <img src="https://shanwogou.cn/icon/leonapp.png" alt="LeonAPP" style="width: 120px; height: auto;">
</a> </a>
<a href="https://space.bilibili.com/2143228115?spm_id_from=333.1387.0.0" class="recommendations-link" target="_blank" rel="noopener noreferrer"> <a href="https://space.bilibili.com/2143228115?spm_id_from=333.1387.0.0" class="recommendations-link" target="_blank" rel="noopener noreferrer">
<img src="https://shanwogou.cn/icon/bilibili.png" alt="bilibili" style="width: 120px; height: auto;"> <img src="https://shanwogou.cn/icon/bilibili.png" alt="bilibili" style="width: 120px; height: auto;">
</a> </a>
<a href="https://afdian.com/a/sunmusic" class="recommendations-link" target="_blank" rel="noopener noreferrer"> <a href="https://afdian.com/a/sunmusic" class="recommendations-link" target="_blank" rel="noopener noreferrer">
<img src="https://shanwogou.cn/icon/aifadian.png" alt="爱发电支持" style="width: 120px; height: auto;"> <img src="https://shanwogou.cn/icon/aifadian.png" alt="爱发电支持" style="width: 120px; height: auto;">
</a> </a>
<a href="http://leonmmcoset.jjxmm.win:2000/JGZ_YES/SunShineMusic" class="recommendations-link" target="_blank" rel="noopener noreferrer">
<img src="https://shanwogou.cn/icon/leongit-jgz&leon.png" alt="LeonGit" style="width: 120px; height: auto;">
</a>
</div> </div>
<div class="music-item"> <div class="music-item">
@@ -1427,7 +1455,7 @@ $currentPageUrl = getCurrentPageURL();
<!-- 分享功能 --> <!-- 分享功能 -->
<div class="share-section"> <div class="share-section">
<div class="share-link-container"> <div class="share-link-container">
<input type="text" class="share-link" value="<?php echo htmlspecialchars($shareUrl); ?>" readonly> <input type="text" class="share-link" value="<?php echo htmlspecialchars($shareUrl); ?>" readonly data-audio="<?php echo $music['id']; ?>">
<button class="copy-button" data-audio="<?php echo $music['id']; ?>" title="复制链接"> <button class="copy-button" data-audio="<?php echo $music['id']; ?>" title="复制链接">
<i class="fas fa-copy"></i> <i class="fas fa-copy"></i>
</button> </button>
@@ -1482,6 +1510,43 @@ $currentPageUrl = getCurrentPageURL();
return minutes + ":" + (secs < 10 ? "0" + secs : secs); return minutes + ":" + (secs < 10 ? "0" + secs : secs);
} }
// 获取下一首要播放的音频ID
function getNextAudioId(currentId) {
// 获取当前激活的分类
const activeCategory = q('.category-btn.active').getAttribute('data-category');
// 获取当前分类下所有可见的音乐项
let visibleItems = Array.from(qa(`.music-item[data-category="${activeCategory}"]`)).filter(item => {
return item.style.display !== 'none';
});
// 如果当前分类没有歌曲(不太可能),则获取所有歌曲
if (visibleItems.length === 0) {
visibleItems = Array.from(qa('.music-item'));
}
const totalItems = visibleItems.length;
if (totalItems === 0) return null;
// 查找当前歌曲在列表中的索引
let currentIndex = -1;
for (let i = 0; i < totalItems; i++) {
if (visibleItems[i].getAttribute('data-id') === currentId) {
currentIndex = i;
break;
}
}
// 如果没找到当前歌曲或只有一首歌,则返回第一首
if (currentIndex === -1 || totalItems === 1) {
return visibleItems[0].getAttribute('data-id');
}
// 返回下一首的ID如果是最后一首则返回第一首
const nextIndex = (currentIndex + 1) % totalItems;
return visibleItems[nextIndex].getAttribute('data-id');
}
// 切换播放/暂停状态 // 切换播放/暂停状态
function togglePlayback(audio, playBtn) { function togglePlayback(audio, playBtn) {
if (audio.paused) { if (audio.paused) {
@@ -1495,6 +1560,33 @@ $currentPageUrl = getCurrentPageURL();
audio.play(); audio.play();
playBtn.textContent = '⏸'; playBtn.textContent = '⏸';
// 为当前播放的音频注册结束事件,用于自动播放下一首
audio.onended = function() {
// 保存当前歌曲的进度为0
savePlaybackPosition(audio.id, 0);
playBtn.textContent = '▶';
// 获取下一首歌曲的ID
const nextId = getNextAudioId(audio.id);
if (nextId) {
const nextAudio = q('#' + nextId);
const nextPlayBtn = q('.play-pause[data-audio="' + nextId + '"]');
if (nextAudio && nextPlayBtn) {
// 滚动到下一首歌曲
const nextMusicItem = nextAudio.closest('.music-item');
if (nextMusicItem) {
nextMusicItem.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// 播放下一首歌曲
setTimeout(function() {
togglePlayback(nextAudio, nextPlayBtn);
}, 500);
}
}
};
} else { } else {
audio.pause(); audio.pause();
playBtn.textContent = '▶'; playBtn.textContent = '▶';
@@ -1506,12 +1598,10 @@ $currentPageUrl = getCurrentPageURL();
const sidebar = q('#sidebar'); const sidebar = q('#sidebar');
const toggleBtn = q('#sidebar-toggle'); const toggleBtn = q('#sidebar-toggle');
// 点击切换按钮显示/隐藏侧边栏
addEvt(toggleBtn, 'click', function() { addEvt(toggleBtn, 'click', function() {
sidebar.classList.toggle('show'); sidebar.classList.toggle('show');
}); });
// 点击侧边栏外的区域关闭侧边栏
addEvt(d, 'click', function(e) { addEvt(d, 'click', function(e) {
if (!sidebar.contains(e.target) && if (!sidebar.contains(e.target) &&
e.target !== toggleBtn && e.target !== toggleBtn &&
@@ -1521,11 +1611,9 @@ $currentPageUrl = getCurrentPageURL();
} }
}); });
// 在小屏幕上,点击历史项后关闭侧边栏
const historyItems = qa('.history-item'); const historyItems = qa('.history-item');
historyItems.forEach(function(item) { historyItems.forEach(function(item) {
addEvt(item, 'click', function() { addEvt(item, 'click', function() {
// 检测是否为移动设备
if (document.documentElement.classList.contains('mobile')) { if (document.documentElement.classList.contains('mobile')) {
sidebar.classList.remove('show'); sidebar.classList.remove('show');
} }
@@ -1539,7 +1627,6 @@ $currentPageUrl = getCurrentPageURL();
const themeIcon = themeToggle.querySelector('i'); const themeIcon = themeToggle.querySelector('i');
const themeText = themeToggle.querySelector('span'); const themeText = themeToggle.querySelector('span');
// 检查用户偏好或本地存储
if (localStorage.getItem('theme') === 'dark' || if (localStorage.getItem('theme') === 'dark' ||
(!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) { (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
d.body.classList.add('dark-mode'); d.body.classList.add('dark-mode');
@@ -1548,10 +1635,8 @@ $currentPageUrl = getCurrentPageURL();
themeText.textContent = '明亮模式'; themeText.textContent = '明亮模式';
} }
// 绑定切换事件
addEvt(themeToggle, 'click', function() { addEvt(themeToggle, 'click', function() {
d.body.classList.toggle('dark-mode'); d.body.classList.toggle('dark-mode');
if (d.body.classList.contains('dark-mode')) { if (d.body.classList.contains('dark-mode')) {
themeIcon.classList.remove('fa-moon'); themeIcon.classList.remove('fa-moon');
themeIcon.classList.add('fa-sun'); themeIcon.classList.add('fa-sun');
@@ -1573,18 +1658,15 @@ $currentPageUrl = getCurrentPageURL();
const logoutBtn = q('#logout-btn'); const logoutBtn = q('#logout-btn');
if (userMenuBtn && userDropdown) { if (userMenuBtn && userDropdown) {
// 点击用户按钮显示/隐藏下拉菜单
addEvt(userMenuBtn, 'click', function(e) { addEvt(userMenuBtn, 'click', function(e) {
e.stopPropagation(); e.stopPropagation();
userDropdown.classList.toggle('show'); userDropdown.classList.toggle('show');
}); });
// 点击其他区域关闭下拉菜单
addEvt(d, 'click', function() { addEvt(d, 'click', function() {
userDropdown.classList.remove('show'); userDropdown.classList.remove('show');
}); });
// 登出功能
if (logoutBtn) { if (logoutBtn) {
addEvt(logoutBtn, 'click', function() { addEvt(logoutBtn, 'click', function() {
if (confirm('确定要退出登录吗?')) { if (confirm('确定要退出登录吗?')) {
@@ -1601,122 +1683,70 @@ $currentPageUrl = getCurrentPageURL();
const clearHistoryBtn = q('#clear-history'); const clearHistoryBtn = q('#clear-history');
const placeholder = historyList.querySelector('.history-placeholder'); const placeholder = historyList.querySelector('.history-placeholder');
// 从localStorage获取历史记录 function getHistory() { return JSON.parse(localStorage.getItem('playHistory') || '[]'); }
function getHistory() { function saveHistory(history) { localStorage.setItem('playHistory', JSON.stringify(history)); }
return JSON.parse(localStorage.getItem('playHistory') || '[]');
}
// 保存历史记录到localStorage
function saveHistory(history) {
localStorage.setItem('playHistory', JSON.stringify(history));
}
// 更新历史记录UI
function updateHistoryUI() { function updateHistoryUI() {
const history = getHistory(); const history = getHistory();
// 清空现有内容(除了占位符)
const items = historyList.querySelectorAll('.history-item'); const items = historyList.querySelectorAll('.history-item');
items.forEach(item => item.remove()); items.forEach(item => item.remove());
// 显示或隐藏占位符
if (history.length === 0) { if (history.length === 0) {
if (placeholder) placeholder.style.display = 'block'; if (placeholder) placeholder.style.display = 'block';
} else { } else {
if (placeholder) placeholder.style.display = 'none'; if (placeholder) placeholder.style.display = 'none';
// 添加历史记录项
history.forEach(item => { history.forEach(item => {
const historyItem = d.createElement('div'); const historyItem = d.createElement('div');
historyItem.className = 'history-item'; historyItem.className = 'history-item';
historyItem.setAttribute('data-audio', item.id); historyItem.setAttribute('data-audio', item.id);
// 格式化时间
const date = new Date(item.timestamp); const date = new Date(item.timestamp);
const formattedTime = `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; const formattedTime = `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
historyItem.innerHTML = ` historyItem.innerHTML = `
<div class="history-info"> <div class="history-info">
<h4 class="history-title">${item.title}</h4> <h4 class="history-title">${item.title}</h4>
<p class="history-artist">${item.artist}</p> <p class="history-artist">${item.artist}</p>
</div> </div>
<span class="history-time">${formattedTime}</span> <span class="history-time">${formattedTime}</span>`;
`;
// 点击历史项播放音乐
addEvt(historyItem, 'click', function() { addEvt(historyItem, 'click', function() {
const audioId = this.getAttribute('data-audio'); const audioId = this.getAttribute('data-audio');
const audio = q('#' + audioId); const audio = q('#' + audioId);
const playBtn = q('.play-pause[data-audio="' + audioId + '"]'); const playBtn = q('.play-pause[data-audio="' + audioId + '"]');
if (audio && playBtn) { if (audio && playBtn) {
// 滚动到音乐项
const musicItem = audio.closest('.music-item'); const musicItem = audio.closest('.music-item');
if (musicItem) { if (musicItem) { musicItem.scrollIntoView({ behavior: 'smooth', block: 'start' }); }
musicItem.scrollIntoView({ behavior: 'smooth', block: 'start' }); if (audio.paused) { togglePlayback(audio, playBtn); }
}
// 播放音乐
if (audio.paused) {
togglePlayback(audio, playBtn);
}
} }
}); });
historyList.appendChild(historyItem); historyList.appendChild(historyItem);
}); });
} }
} }
// 添加到历史记录
window.addToHistory = function(songId, songTitle, artist) { window.addToHistory = function(songId, songTitle, artist) {
let history = getHistory(); let history = getHistory();
// 移除已存在的相同歌曲(避免重复)
history = history.filter(item => item.id !== songId); 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); }
history.unshift({
id: songId,
title: songTitle,
artist: artist,
timestamp: new Date().getTime()
});
// 限制历史记录数量
if (history.length > 20) {
history = history.slice(0, 20);
}
saveHistory(history); saveHistory(history);
updateHistoryUI(); updateHistoryUI();
}; };
// 清空历史记录
addEvt(clearHistoryBtn, 'click', function() { addEvt(clearHistoryBtn, 'click', function() {
if (confirm('确定要清空所有播放历史吗?')) { if (confirm('确定要清空所有播放历史吗?')) {
localStorage.removeItem('playHistory'); localStorage.removeItem('playHistory');
updateHistoryUI(); updateHistoryUI();
} }
}); });
// 初始加载历史记录
updateHistoryUI(); updateHistoryUI();
} }
// 播放进度记忆功能 // 播放进度记忆功能
function initPlaybackPositionMemory() { function initPlaybackPositionMemory() {
// 保存播放进度
window.savePlaybackPosition = function(songId, position) { window.savePlaybackPosition = function(songId, position) {
const positions = JSON.parse(localStorage.getItem('playbackPositions') || '{}'); const positions = JSON.parse(localStorage.getItem('playbackPositions') || '{}');
positions[songId] = { positions[songId] = { position: position, timestamp: new Date().getTime() };
position: position,
timestamp: new Date().getTime()
};
localStorage.setItem('playbackPositions', JSON.stringify(positions)); localStorage.setItem('playbackPositions', JSON.stringify(positions));
}; };
// 恢复播放进度
window.restorePlaybackPosition = function(songId) { window.restorePlaybackPosition = function(songId) {
const positions = JSON.parse(localStorage.getItem('playbackPositions') || '{}'); const positions = JSON.parse(localStorage.getItem('playbackPositions') || '{}');
return positions[songId] ? positions[songId].position : 0; return positions[songId] ? positions[songId].position : 0;
@@ -1727,23 +1757,12 @@ $currentPageUrl = getCurrentPageURL();
function initTitleEffects() { function initTitleEffects() {
const originalTitle = document.title; const originalTitle = document.title;
let titleChangeTimer = null; let titleChangeTimer = null;
// 监听页面可见性变化
addEvt(document, 'visibilitychange', function() { addEvt(document, 'visibilitychange', function() {
// 清除之前的定时器 if (titleChangeTimer) { clearTimeout(titleChangeTimer); titleChangeTimer = null; }
if (titleChangeTimer) {
clearTimeout(titleChangeTimer);
titleChangeTimer = null;
}
if (document.hidden) { if (document.hidden) {
// 页面不可见时显示挽留信息
document.title = '你不要走啊 ! ..(。•ˇ‸ˇ•。)…'; document.title = '你不要走啊 ! ..(。•ˇ‸ˇ•。)…';
} else { } else {
// 页面可见时先显示欢迎回来信息
document.title = '耶,又回来了!(^_^)'; document.title = '耶,又回来了!(^_^)';
// 3秒后恢复原始标题
titleChangeTimer = setTimeout(function() { titleChangeTimer = setTimeout(function() {
document.title = originalTitle; document.title = originalTitle;
titleChangeTimer = null; titleChangeTimer = null;
@@ -1767,7 +1786,6 @@ $currentPageUrl = getCurrentPageURL();
const volumeBtn = q('.volume-button[data-audio="' + id + '"]'); const volumeBtn = q('.volume-button[data-audio="' + id + '"]');
const volumeSlider = q('.volume-slider[data-audio="' + id + '"]'); const volumeSlider = q('.volume-slider[data-audio="' + id + '"]');
// 获取歌曲信息
const musicItem = audio.closest('.music-item'); const musicItem = audio.closest('.music-item');
const songTitle = musicItem.querySelector('h2').textContent; const songTitle = musicItem.querySelector('h2').textContent;
const artist = musicItem.querySelector('.artist-info').textContent.replace('作者:', ''); const artist = musicItem.querySelector('.artist-info').textContent.replace('作者:', '');
@@ -1775,17 +1793,12 @@ $currentPageUrl = getCurrentPageURL();
let originalVolume = 1; let originalVolume = 1;
let isDragging = false; let isDragging = false;
// 音频加载完成 - 恢复上次播放进度
addEvt(audio, 'loadedmetadata', function() { addEvt(audio, 'loadedmetadata', function() {
totalTime.textContent = formatTime(audio.duration); totalTime.textContent = formatTime(audio.duration);
audio.volume = volumeSlider.value; audio.volume = volumeSlider.value;
// 恢复播放进度
const savedPosition = restorePlaybackPosition(id); const savedPosition = restorePlaybackPosition(id);
if (savedPosition > 0 && savedPosition < audio.duration) { if (savedPosition > 0 && savedPosition < audio.duration) {
audio.currentTime = savedPosition; audio.currentTime = savedPosition;
// 更新UI
const progress = (savedPosition / audio.duration) * 100; const progress = (savedPosition / audio.duration) * 100;
progressFill.style.width = progress + '%'; progressFill.style.width = progress + '%';
progressHandle.style.left = progress + '%'; progressHandle.style.left = progress + '%';
@@ -1793,123 +1806,67 @@ $currentPageUrl = getCurrentPageURL();
} }
}); });
// 播放/暂停
addEvt(playBtn, 'click', function() { addEvt(playBtn, 'click', function() {
togglePlayback(audio, playBtn); togglePlayback(audio, playBtn);
// 添加到播放历史
addToHistory(id, songTitle, artist); addToHistory(id, songTitle, artist);
}); });
// 循环播放
addEvt(loopBtn, 'click', function() { addEvt(loopBtn, 'click', function() {
audio.loop = !audio.loop; audio.loop = !audio.loop;
loopBtn.classList.toggle('active', audio.loop); loopBtn.classList.toggle('active', audio.loop);
if (audio.loop) { if (audio.loop) {
loopBtn.style.transform = 'scale(1.1)'; loopBtn.style.transform = 'scale(1.1)';
setTimeout(function() { setTimeout(() => loopBtn.style.transform = 'scale(1)', 200);
loopBtn.style.transform = 'scale(1)';
}, 200);
} }
}); });
// 更新进度 - 并保存播放进度
addEvt(audio, 'timeupdate', function() { addEvt(audio, 'timeupdate', function() {
if (!isDragging) { if (!isDragging) {
const progress = (audio.currentTime / audio.duration) * 100; const progress = (audio.currentTime / audio.duration) * 100;
progressFill.style.width = progress + '%'; progressFill.style.width = progress + '%';
progressHandle.style.left = progress + '%'; progressHandle.style.left = progress + '%';
currentTime.textContent = formatTime(audio.currentTime); currentTime.textContent = formatTime(audio.currentTime);
if (audio.currentTime > 0 && (audio.currentTime % 30 < 0.1 || Math.abs(audio.currentTime - (audio.duration * 0.9)) < 0.5)) {
// 定期保存播放进度每30秒或进度有显著变化时
if (audio.currentTime > 0 &&
(audio.currentTime % 30 < 0.1 ||
Math.abs(audio.currentTime - (audio.duration * 0.9)) < 0.5)) {
savePlaybackPosition(id, audio.currentTime); savePlaybackPosition(id, audio.currentTime);
} }
} }
}); });
// 播放结束时保存最终进度 // 进度条拖动逻辑
addEvt(audio, 'ended', function() { const startDrag = (e) => { isDragging = true; progressHandle.classList.add('dragging'); updateProgress(e); };
savePlaybackPosition(id, 0); // 播放结束后重置进度 const updateProgress = (e) => {
playBtn.textContent = '▶';
});
// 进度条拖动
const startDrag = function(e) {
isDragging = true;
progressHandle.classList.add('dragging');
updateProgress(e);
};
const updateProgress = function(e) {
if (!audio.duration) return; if (!audio.duration) return;
// 获取进度条的位置和宽度
const rect = progressBar.getBoundingClientRect(); const rect = progressBar.getBoundingClientRect();
let pos = (e.clientX - rect.left) / rect.width; let pos = (e.clientX - rect.left) / rect.width;
pos = Math.max(0, Math.min(1, pos)); // 限制在0-1之间 pos = Math.max(0, Math.min(1, pos));
// 更新UI
const percentage = pos * 100; const percentage = pos * 100;
progressFill.style.width = percentage + '%'; progressFill.style.width = percentage + '%';
progressHandle.style.left = percentage + '%'; progressHandle.style.left = percentage + '%';
currentTime.textContent = formatTime(pos * audio.duration); currentTime.textContent = formatTime(pos * audio.duration);
}; };
const endDrag = () => {
const endDrag = function() {
if (!isDragging) return; if (!isDragging) return;
isDragging = false; isDragging = false;
progressHandle.classList.remove('dragging'); progressHandle.classList.remove('dragging');
// 设置音频位置
const pos = parseFloat(progressFill.style.width) / 100; const pos = parseFloat(progressFill.style.width) / 100;
audio.currentTime = pos * audio.duration; audio.currentTime = pos * audio.duration;
savePlaybackPosition(id, audio.currentTime); savePlaybackPosition(id, audio.currentTime);
}; };
// 进度条事件
addEvt(progressBar, 'click', updateProgress); addEvt(progressBar, 'click', updateProgress);
addEvt(progressHandle, 'mousedown', startDrag); addEvt(progressHandle, 'mousedown', startDrag);
addEvt(d, 'mousemove', function(e) { if (isDragging) updateProgress(e); }); addEvt(d, 'mousemove', (e) => { if (isDragging) updateProgress(e); });
addEvt(d, 'mouseup', endDrag); addEvt(d, 'mouseup', endDrag);
addEvt(d, 'mouseleave', endDrag); addEvt(d, 'mouseleave', endDrag);
addEvt(progressBar, 'touchstart', (e) => { e.preventDefault(); startDrag(e.touches[0]); });
// 移动端触摸事件 addEvt(d, 'touchmove', (e) => { if (isDragging) { e.preventDefault(); updateProgress(e.touches[0]); } });
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(d, 'touchend', endDrag);
// 音量控制 // 音量控制
addEvt(volumeBtn, 'click', function() { addEvt(volumeBtn, 'click', function() {
if (audio.volume > 0) { if (audio.volume > 0) { originalVolume = audio.volume; audio.volume = 0; volumeBtn.textContent = '🔇'; volumeSlider.value = 0; }
originalVolume = audio.volume; else { audio.volume = originalVolume; volumeBtn.textContent = '🔊'; volumeSlider.value = originalVolume; }
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 ? '🔊' : '🔇';
}); });
addEvt(volumeSlider, 'input', function() { audio.volume = this.value; originalVolume = this.value; volumeBtn.textContent = this.value > 0 ? '🔊' : '🔇'; });
}); });
} }
@@ -2015,8 +1972,7 @@ $currentPageUrl = getCurrentPageURL();
copyButtons.forEach(function(btn) { copyButtons.forEach(function(btn) {
addEvt(btn, 'click', function() { addEvt(btn, 'click', function() {
const audioId = this.getAttribute('data-audio'); const audioId = this.getAttribute('data-audio');
const shareLink = q('.share-link[data-audio="' + audioId + '"]') || const shareLink = q('.share-link[data-audio="' + audioId + '"]');
this.parentElement.querySelector('.share-link');
if (shareLink) { if (shareLink) {
shareLink.select(); shareLink.select();
@@ -2078,7 +2034,7 @@ $currentPageUrl = getCurrentPageURL();
} }
} }
// 初始化头像加载(核心修复部分) // 初始化头像加载
function initAvatarLoading() { function initAvatarLoading() {
// 获取头像URL列表从PHP传递过来 // 获取头像URL列表从PHP传递过来
<?php <?php
@@ -2091,12 +2047,10 @@ $currentPageUrl = getCurrentPageURL();
// 获取头像元素 // 获取头像元素
const userAvatarImg = q('#user-avatar-img'); const userAvatarImg = q('#user-avatar-img');
const dropdownAvatarImg = q('#dropdown-avatar-img');
const userAvatarContainer = q('#user-avatar-container'); const userAvatarContainer = q('#user-avatar-container');
const dropdownAvatarContainer = q('#dropdown-avatar-container');
// 如果没有头像元素,直接返回 // 如果没有头像元素,直接返回
if (!userAvatarImg || !dropdownAvatarImg) { if (!userAvatarImg || !userAvatarContainer) {
console.log("未找到头像元素,跳过头像加载"); console.log("未找到头像元素,跳过头像加载");
return; return;
} }
@@ -2107,11 +2061,8 @@ $currentPageUrl = getCurrentPageURL();
if (index >= urls.length) { if (index >= urls.length) {
console.error("所有头像URL都加载失败使用默认头像"); console.error("所有头像URL都加载失败使用默认头像");
userAvatarImg.src = urls[urls.length - 1]; userAvatarImg.src = urls[urls.length - 1];
dropdownAvatarImg.src = urls[urls.length - 1];
userAvatarImg.style.display = 'block'; userAvatarImg.style.display = 'block';
dropdownAvatarImg.style.display = 'block';
userAvatarContainer.classList.remove('avatar-loading'); userAvatarContainer.classList.remove('avatar-loading');
dropdownAvatarContainer.classList.remove('avatar-loading');
return; return;
} }
@@ -2126,11 +2077,8 @@ $currentPageUrl = getCurrentPageURL();
testImg.onload = function() { testImg.onload = function() {
console.log(`头像加载成功:`, currentUrl); console.log(`头像加载成功:`, currentUrl);
userAvatarImg.src = currentUrl; userAvatarImg.src = currentUrl;
dropdownAvatarImg.src = currentUrl;
userAvatarImg.style.display = 'block'; userAvatarImg.style.display = 'block';
dropdownAvatarImg.style.display = 'block';
userAvatarContainer.classList.remove('avatar-loading'); userAvatarContainer.classList.remove('avatar-loading');
dropdownAvatarContainer.classList.remove('avatar-loading');
}; };
// 加载失败尝试下一个URL // 加载失败尝试下一个URL
@@ -2180,4 +2128,3 @@ $currentPageUrl = getCurrentPageURL();
</script> </script>
</body> </body>
</html> </html>