2025-09-25 11:33:03 +00:00
|
|
|
|
<?php
|
|
|
|
|
|
require_once 'config.php';
|
|
|
|
|
|
|
|
|
|
|
|
// 页面标题和版本信息
|
|
|
|
|
|
$pageTitle = "落日音乐 - 发现好音乐";
|
|
|
|
|
|
$siteVersion = "1.8.3.6016.001";
|
|
|
|
|
|
$bqsy = "2024-2025 落日音乐. JGZ_YES. 版权所有";
|
|
|
|
|
|
|
|
|
|
|
|
// 定义网站版权信息
|
|
|
|
|
|
$copyrightInfo = "本网站所有代码和内容受版权保护,未经授权禁止复制、修改和使用。Copyright © 2023 音乐分享网站 保留所有权利。";
|
|
|
|
|
|
|
|
|
|
|
|
// 设备识别函数
|
|
|
|
|
|
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';
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前页面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="https://shanwogou.cn/audio/static/icon/new-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;
|
|
|
|
|
|
--sidebar-bg: #ffffff;
|
|
|
|
|
|
--sidebar-shadow: -2px 0 10px rgba(0,0,0,0.05);
|
|
|
|
|
|
--history-item-hover: #f9f9f9;
|
|
|
|
|
|
--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;
|
|
|
|
|
|
--sidebar-bg: #1a1a1a;
|
|
|
|
|
|
--sidebar-shadow: -2px 0 10px rgba(0,0,0,0.7);
|
|
|
|
|
|
--history-item-hover: #2d2d2d;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 基础布局 */
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
background-color: var(--bg-color);
|
|
|
|
|
|
color: var(--text-color);
|
|
|
|
|
|
transition: background-color 0.3s ease, color 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 桌面端布局 */
|
|
|
|
|
|
.desktop .app-container {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.desktop .main-wrapper {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
margin-left: 280px; /* 为固定侧边栏留出空间 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.desktop .main-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
max-width: 1200px;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 侧边栏 - 固定在用户左侧 */
|
|
|
|
|
|
.desktop .sidebar {
|
|
|
|
|
|
width: 280px;
|
|
|
|
|
|
background-color: var(--sidebar-bg);
|
|
|
|
|
|
box-shadow: var(--sidebar-shadow);
|
|
|
|
|
|
padding: 1.5rem;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
/* 关键样式:固定在左侧 */
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
height: 100vh;
|
|
|
|
|
|
z-index: 90;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 移动端布局 */
|
|
|
|
|
|
.mobile .app-container {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .main-wrapper {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .main-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
padding: 0.5rem;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .sidebar {
|
|
|
|
|
|
width: 250px;
|
|
|
|
|
|
background-color: var(--sidebar-bg);
|
|
|
|
|
|
box-shadow: var(--sidebar-shadow);
|
|
|
|
|
|
padding: 1.5rem;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
transition: transform 0.3s ease, background-color 0.3s ease, box-shadow 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
/* 关键样式:固定在左侧但默认隐藏 */
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
height: 100vh;
|
|
|
|
|
|
z-index: 101;
|
|
|
|
|
|
transform: translateX(-100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .sidebar.show {
|
|
|
|
|
|
transform: translateX(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .sidebar-toggle {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
top: 1rem;
|
|
|
|
|
|
left: 1rem;
|
|
|
|
|
|
z-index: 100;
|
|
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 顶部工具栏 */
|
|
|
|
|
|
.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, box-shadow 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.site-title {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 1.4rem;
|
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.theme-toggle, .user-menu-btn {
|
|
|
|
|
|
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;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.theme-toggle:hover, .user-menu-btn:hover {
|
|
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border-color: var(--primary-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
h1, h2, h3 {
|
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
h1 { font-size: 1.8rem; text-align: center; margin: 1rem 0; }
|
|
|
|
|
|
h2 { font-size: 1.4rem; margin-bottom: 0.5rem; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 搜索框 */
|
|
|
|
|
|
.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;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
#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, box-shadow 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 视图切换 */
|
|
|
|
|
|
.view-toggle { display: flex; justify-content: center; gap: 0.8rem; margin: 1rem 0; }
|
|
|
|
|
|
.view-toggle button {
|
|
|
|
|
|
background-color: var(--card-bg);
|
|
|
|
|
|
border: 1px solid var(--border-color);
|
|
|
|
|
|
color: var(--text-color);
|
|
|
|
|
|
padding: 0.5rem 1rem; border-radius: 20px; cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s ease; display: flex; align-items: center; gap: 0.5rem;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
.view-toggle button:hover, .view-toggle button.active {
|
|
|
|
|
|
background-color: var(--primary-color); color: white; border-color: var(--primary-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 列表/卡片视图 */
|
|
|
|
|
|
.list-view .music-item { display: block; }
|
|
|
|
|
|
|
|
|
|
|
|
.desktop .card-view {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
|
|
|
|
|
|
gap: 1.2rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .card-view {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
gap: 1.2rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 分类导航 */
|
|
|
|
|
|
.category-nav { display: flex; gap: 0.8rem; flex-wrap: wrap; justify-content: center; margin-top: 1rem; }
|
|
|
|
|
|
.category-btn {
|
|
|
|
|
|
border: none; padding: 0.5rem 1.2rem; border-radius: 20px; cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s ease; font-size: 0.9rem; font-weight: 500;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
.category-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
|
|
|
|
|
|
.category-btn.active { box-shadow: 0 4px 8px rgba(0,0,0,0.15); font-weight: bold; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 分类标签 */
|
|
|
|
|
|
.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;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.artist-info {
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
font-style: italic;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 自定义音频播放器样式 */
|
|
|
|
|
|
.custom-audio-player {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
margin: 1.5rem 0;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
background-color: var(--bg-color);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 0.8rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.8rem;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
transition: background-color 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.audio-controls {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.8rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.audio-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 {
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .progress-container {
|
|
|
|
|
|
order: 2;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.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%;
|
|
|
|
|
|
transition: width 0.1s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
|
transition: left 0.1s ease;
|
|
|
|
|
|
box-shadow: 0 0 5px rgba(0,0,0,0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.audio-progress:hover .progress-handle {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.progress-handle.dragging {
|
|
|
|
|
|
transform: translateY(-50%) scale(1.2);
|
|
|
|
|
|
box-shadow: 0 0 8px rgba(44, 62, 80, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.time-display {
|
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.time-separator {
|
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
width: 10px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 音量控制样式 */
|
|
|
|
|
|
.volume-control {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.desktop .volume-control {
|
|
|
|
|
|
margin-left: 0.5rem;
|
|
|
|
|
|
min-width: 100px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .volume-control {
|
|
|
|
|
|
margin-top: 0.5rem;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
order: 3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.volume-button {
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
|
width: 28px;
|
|
|
|
|
|
height: 28px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.volume-button:hover {
|
|
|
|
|
|
background-color: rgba(44, 62, 80, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.volume-slider {
|
|
|
|
|
|
width: 80px;
|
|
|
|
|
|
height: 4px;
|
|
|
|
|
|
-webkit-appearance: none;
|
|
|
|
|
|
appearance: none;
|
|
|
|
|
|
background: var(--border-color);
|
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
transition: all 0.1s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.volume-slider::-webkit-slider-thumb {
|
|
|
|
|
|
-webkit-appearance: none;
|
|
|
|
|
|
appearance: none;
|
|
|
|
|
|
width: 12px;
|
|
|
|
|
|
height: 12px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background: var(--primary-color);
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.1s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.volume-slider::-webkit-slider-thumb:hover,
|
|
|
|
|
|
.volume-slider::-webkit-slider-thumb:active {
|
|
|
|
|
|
transform: scale(1.2);
|
|
|
|
|
|
box-shadow: 0 0 8px rgba(44, 62, 80, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.download-link {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
|
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;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.download-link:hover {
|
|
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.recommend-container {
|
|
|
|
|
|
background-color: var(--card-bg);
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 1.2rem;
|
|
|
|
|
|
box-shadow: var(--card-shadow);
|
|
|
|
|
|
margin-top: 1.5rem;
|
|
|
|
|
|
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-group {
|
|
|
|
|
|
margin-bottom: 1.2rem;
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-group label {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
margin-bottom: 0.5rem;
|
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-control {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
padding: 0.8rem;
|
|
|
|
|
|
border: 1px solid var(--border-color);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
background-color: var(--bg-color);
|
|
|
|
|
|
color: var(--text-color);
|
|
|
|
|
|
transition: border-color 0.3s ease;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-group label:after {
|
|
|
|
|
|
content: " *";
|
|
|
|
|
|
color: var(--accent-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.submit-btn {
|
|
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
padding: 0.8rem 2rem;
|
|
|
|
|
|
border-radius: 25px;
|
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: background-color 0.3s ease;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.submit-btn:hover {
|
|
|
|
|
|
background-color: var(--primary-hover);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.message {
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-size: 0.95rem;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.success {
|
|
|
|
|
|
background-color: #d4edda;
|
|
|
|
|
|
color: #155724;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.error {
|
|
|
|
|
|
background-color: #f8d7da;
|
|
|
|
|
|
color: #721c24;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.error-input {
|
|
|
|
|
|
border-color: var(--accent-color) !important;
|
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(231, 76, 60, 0.1) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-prompt {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
background-color: rgba(44, 62, 80, 0.1);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-prompt a {
|
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.login-prompt a:hover {
|
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.file-info {
|
|
|
|
|
|
margin-top: 0.5rem;
|
|
|
|
|
|
font-size: 0.85rem;
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 视频容器样式 */
|
|
|
|
|
|
.video-container {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
padding-top: 56.25%; /* 16:9比例 */
|
|
|
|
|
|
margin: 1rem 0;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .video-container {
|
|
|
|
|
|
padding-top: 62.5%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.video-container iframe {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.download-section {
|
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 分享功能样式 */
|
|
|
|
|
|
.share-section {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .share-section {
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.share-button {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.3rem;
|
|
|
|
|
|
background-color: var(--bg-color);
|
|
|
|
|
|
border: 1px solid var(--border-color);
|
|
|
|
|
|
padding: 0.5rem 1rem;
|
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
|
color: var(--text-color);
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.share-button:hover {
|
|
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.share-link-container {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
|
flex-grow: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.mobile .share-link-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.copy-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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.copy-button:hover {
|
|
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
|
margin-left: 5px;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.jump-button:hover {
|
|
|
|
|
|
background-color: #27ae60;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.copy-notification {
|
|
|
|
|
|
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;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.copy-notification.show {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 回到顶部按钮样式 */
|
|
|
|
|
|
.back-to-top {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
bottom: 30px;
|
|
|
|
|
|
right: 30px;
|
|
|
|
|
|
width: 50px;
|
|
|
|
|
|
height: 50px;
|
|
|
|
|
|
background-color: var(--primary-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-size: 1.5rem;
|
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
visibility: hidden;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
z-index: 999;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.back-to-top.show {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
visibility: visible;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.back-to-top:hover {
|
|
|
|
|
|
background-color: var(--primary-hover);
|
|
|
|
|
|
transform: translateY(-5px);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 网站信息与在线人数样式 */
|
|
|
|
|
|
.site-info {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
bottom: 5px;
|
|
|
|
|
|
right: 5px;
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
z-index: 9999;
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 最近播放历史样式 */
|
|
|
|
|
|
.recent-history {
|
|
|
|
|
|
margin-top: 2rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-list {
|
|
|
|
|
|
max-height: calc(100vh - 180px); /* 计算高度,使其在视口内 */
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
|
padding-right: 0.5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 滚动条美化 */
|
|
|
|
|
|
.history-list::-webkit-scrollbar {
|
|
|
|
|
|
width: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-list::-webkit-scrollbar-track {
|
|
|
|
|
|
background: var(--bg-color);
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-list::-webkit-scrollbar-thumb {
|
|
|
|
|
|
background: var(--border-color);
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-list::-webkit-scrollbar-thumb:hover {
|
|
|
|
|
|
background: var(--muted-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-item {
|
|
|
|
|
|
padding: 0.8rem;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 0.8rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: background-color 0.2s ease;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-item:hover {
|
|
|
|
|
|
background-color: var(--history-item-hover);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-info {
|
|
|
|
|
|
flex-grow: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-title {
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
margin: 0 0 0.2rem 0;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-artist {
|
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-time {
|
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
margin-left: 1rem;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.clear-history {
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
border: 1px solid var(--border-color);
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
padding: 0.4rem 0.8rem;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 0.85rem;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
margin-top: 0.5rem;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.clear-history:hover {
|
|
|
|
|
|
background-color: var(--accent-color);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
border-color: var(--accent-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 用户菜单样式 */
|
|
|
|
|
|
.user-menu {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-dropdown {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
top: 100%;
|
|
|
|
|
|
background-color: var(--card-bg);
|
|
|
|
|
|
box-shadow: var(--card-shadow);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
width: 200px;
|
|
|
|
|
|
padding: 0.5rem 0;
|
|
|
|
|
|
margin-top: 0.5rem;
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
z-index: 101;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-dropdown.show {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-dropdown a, .user-dropdown button {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
padding: 0.8rem 1rem;
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
color: var(--text-color);
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-dropdown a:hover, .user-dropdown button:hover {
|
|
|
|
|
|
background-color: var(--history-item-hover);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-info {
|
|
|
|
|
|
padding: 0.8rem 1rem;
|
|
|
|
|
|
border-bottom: 1px solid var(--border-color);
|
|
|
|
|
|
margin-bottom: 0.5rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-name {
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
margin-bottom: 0.3rem;
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-email {
|
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
|
color: var(--muted-color);
|
|
|
|
|
|
font-family: var(--main-font); /* 应用自定义字体 */
|
|
|
|
|
|
}
|
|
|
|
|
|
.afdian-btn {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
margin-bottom: 1px; /* 与下方元素拉开距离,可根据需要调整 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 用户头像样式 */
|
|
|
|
|
|
.user-avatar {
|
|
|
|
|
|
width: 30px;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-avatar img {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 下拉菜单中的头像 */
|
|
|
|
|
|
.dropdown-avatar {
|
|
|
|
|
|
width: 60px;
|
|
|
|
|
|
height: 60px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
margin: 0 auto 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dropdown-avatar img {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 调整用户菜单按钮样式 */
|
|
|
|
|
|
.user-menu-btn {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
|
/* 其他原有样式 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 头像加载指示器 */
|
|
|
|
|
|
.avatar-loading {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
background-color: #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-loading::after {
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.5) 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="%23333" 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>') no-repeat center;
|
|
|
|
|
|
background-size: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dark-mode .avatar-loading {
|
|
|
|
|
|
background-color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.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>');
|
|
|
|
|
|
}
|
|
|
|
|
|
.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>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<div class="app-container">
|
|
|
|
|
|
<!-- 侧边栏 - 固定在用户左侧 -->
|
|
|
|
|
|
<div class="sidebar" id="sidebar">
|
|
|
|
|
|
<h3>最近播放</h3>
|
|
|
|
|
|
<div class="recent-history">
|
|
|
|
|
|
<div class="history-list" id="history-list">
|
|
|
|
|
|
<!-- 最近播放历史将通过JavaScript动态填充 -->
|
|
|
|
|
|
<p class="history-placeholder" style="color: var(--muted-color); text-align: center; padding: 1rem;">
|
|
|
|
|
|
暂无播放记录
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<button class="clear-history" id="clear-history">
|
|
|
|
|
|
<i class="fas fa-trash-alt"></i> 清空历史
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 移动端侧边栏切换按钮 -->
|
|
|
|
|
|
<button class="sidebar-toggle" id="sidebar-toggle">
|
|
|
|
|
|
<i class="fas fa-history"></i>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="main-wrapper">
|
|
|
|
|
|
<!-- 顶部工具栏 - 包含网站标题、暗黑模式切换和登录/注册 -->
|
|
|
|
|
|
<div class="top-bar">
|
|
|
|
|
|
<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>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="./upload.php" class="theme-toggle">
|
|
|
|
|
|
<i class="fas fa-cloud-upload-alt"></i>
|
|
|
|
|
|
<span>上传音乐</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<?php if ($isLoggedIn && $userInfo): ?>
|
|
|
|
|
|
<!-- 登录状态显示用户菜单 -->
|
|
|
|
|
|
<div class="user-menu">
|
|
|
|
|
|
<button class="user-menu-btn" id="user-menu-btn">
|
|
|
|
|
|
<!-- 显示用户头像 -->
|
|
|
|
|
|
<div class="user-avatar avatar-loading" id="user-avatar-container">
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// 定义从OSS获取头像路径的函数(完全重构版)
|
|
|
|
|
|
function getUserAvatar($userId, $config, &$debugInfo) {
|
|
|
|
|
|
// 记录调试信息
|
|
|
|
|
|
$debugInfo = [];
|
|
|
|
|
|
$debugInfo[] = "用户ID: {$userId}";
|
|
|
|
|
|
|
|
|
|
|
|
// 默认头像路径(使用两种不同的默认头像作为备用)
|
|
|
|
|
|
$defaultAvatars = [
|
|
|
|
|
|
'./static/icon/icon.png',
|
|
|
|
|
|
'https://shanwogou.cn/audio/static/icon/new-icon.png'
|
|
|
|
|
|
];
|
|
|
|
|
|
$debugInfo[] = "默认头像路径列表: " . implode(', ', $defaultAvatars);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查配置文件
|
|
|
|
|
|
if (empty($config)) {
|
|
|
|
|
|
$debugInfo[] = "错误: 配置文件为空";
|
|
|
|
|
|
return $defaultAvatars;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查OSS配置
|
|
|
|
|
|
$ossParams = ['oss_access_key', 'oss_secret_key', 'oss_endpoint', 'oss_bucket'];
|
|
|
|
|
|
$missingOssParams = [];
|
|
|
|
|
|
|
|
|
|
|
|
foreach ($ossParams as $param) {
|
|
|
|
|
|
if (!isset($config[$param]) || empty($config[$param])) {
|
|
|
|
|
|
$missingOssParams[] = $param;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$debugInfo[] = "找到OSS配置: {$param} = " . (strpos($param, 'key') !== false ? '******' : $config[$param]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有缺失的配置项,直接返回默认头像
|
|
|
|
|
|
if (!empty($missingOssParams)) {
|
|
|
|
|
|
$debugInfo[] = "错误: 缺少OSS配置项 - " . implode(', ', $missingOssParams);
|
|
|
|
|
|
return $defaultAvatars;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构建多种可能的OSS头像URL格式
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 1. 直接使用配置中的完整访问域名
|
|
|
|
|
|
$ossBaseUrl1 = rtrim($config['oss_endpoint'], '/');
|
|
|
|
|
|
$object = 'sunmusic/profile/' . $userId . '头像.png';
|
|
|
|
|
|
$avatarUrls[] = $ossBaseUrl1 . '/' . $object . '?t=' . time();
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 使用bucket+endpoint格式
|
|
|
|
|
|
$ossBaseUrl2 = rtrim($config['oss_bucket'] . '.' . $config['oss_endpoint'], '/');
|
|
|
|
|
|
$avatarUrls[] = 'https://' . $ossBaseUrl2 . '/' . $object . '?t=' . time();
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 不使用HTTPS的格式(作为备选)
|
|
|
|
|
|
$avatarUrls[] = 'http://' . $ossBaseUrl2 . '/' . $object . '?t=' . time();
|
|
|
|
|
|
|
|
|
|
|
|
$debugInfo[] = "构建的OSS头像URL列表: " . implode(', ', $avatarUrls);
|
|
|
|
|
|
|
|
|
|
|
|
// 返回所有可能的URL,包括默认头像作为最后的备选
|
|
|
|
|
|
return array_merge($avatarUrls, $defaultAvatars);
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
$debugInfo[] = "错误: 构建URL时发生异常 - " . $e->getMessage();
|
|
|
|
|
|
return $defaultAvatars;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 加载配置文件
|
|
|
|
|
|
$config = [];
|
|
|
|
|
|
$configFile = 'pmconfig.php';
|
|
|
|
|
|
$debugInfo = [];
|
|
|
|
|
|
|
|
|
|
|
|
if (file_exists($configFile)) {
|
|
|
|
|
|
$debugInfo[] = "找到配置文件: {$configFile}";
|
|
|
|
|
|
$config = include $configFile;
|
|
|
|
|
|
if (!is_array($config)) {
|
|
|
|
|
|
$debugInfo[] = "错误: 配置文件未返回数组";
|
|
|
|
|
|
$config = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$debugInfo[] = "错误: 未找到配置文件 {$configFile}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户ID(尝试多种可能的键名)
|
|
|
|
|
|
$userId = $userInfo['id'] ?? ($userInfo['user_id'] ?? ($userInfo['uid'] ?? 0));
|
|
|
|
|
|
$avatarUrls = getUserAvatar($userId, $config, $debugInfo);
|
|
|
|
|
|
|
|
|
|
|
|
// 显示调试信息(可用于排查问题)
|
|
|
|
|
|
echo '<div style="display:none;" id="avatar-debug-info"><pre>';
|
|
|
|
|
|
echo "头像加载调试信息:\n";
|
|
|
|
|
|
echo implode("\n", $debugInfo);
|
|
|
|
|
|
echo '</pre></div>';
|
|
|
|
|
|
|
|
|
|
|
|
// 输出初始img标签,使用JavaScript动态尝试加载
|
|
|
|
|
|
echo '<img id="user-avatar-img" src="" alt="用户头像" style="display:none;">';
|
|
|
|
|
|
?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span><?php echo htmlspecialchars($userInfo['nickname'] ?? '用户'); ?></span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<div class="user-dropdown" id="user-dropdown">
|
|
|
|
|
|
<div class="user-info">
|
|
|
|
|
|
<div class="user-name"><?php echo htmlspecialchars($userInfo['nickname'] ?? '用户'); ?></div>
|
|
|
|
|
|
<div class="user-email"><?php echo htmlspecialchars($userInfo['nickname'] ?? '进入个人设置查看头像'); ?></div>
|
|
|
|
|
|
<div class="user-email">
|
|
|
|
|
|
<?php
|
|
|
|
|
|
if (!empty($userInfo['email'])) {
|
|
|
|
|
|
echo htmlspecialchars($userInfo['email']);
|
|
|
|
|
|
} elseif (!empty($userInfo['phone'])) {
|
|
|
|
|
|
echo htmlspecialchars(substr($userInfo['phone'], 0, 3) . '****' . substr($userInfo['phone'], 7));
|
|
|
|
|
|
}
|
|
|
|
|
|
?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<a href="./profile.php"><i class="fas fa-user-cog"></i> 个人设置</a>
|
|
|
|
|
|
<button id="logout-btn"><i class="fas fa-sign-out-alt"></i> 退出登录</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<!-- 未登录状态显示登录和注册按钮 -->
|
|
|
|
|
|
<a href="login.php" class="theme-toggle">
|
|
|
|
|
|
<i class="fas fa-sign-in-alt"></i>
|
|
|
|
|
|
<span>登录</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a href="register.php" class="theme-toggle">
|
|
|
|
|
|
<i class="fas fa-user-plus"></i>
|
|
|
|
|
|
<span>注册</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="main-content">
|
|
|
|
|
|
<!-- 版权信息 -->
|
|
|
|
|
|
<div style="display:none">
|
|
|
|
|
|
<?php echo htmlspecialchars($copyrightInfo); ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 修改搜索框为表单提交到sou.php -->
|
|
|
|
|
|
<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 isset($_GET['s']) ? htmlspecialchars($_GET['s']) : ''; ?>">
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 音乐分类导航 -->
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h2>音乐分类</h2>
|
|
|
|
|
|
<div class="category-nav">
|
|
|
|
|
|
<?php foreach ($categories as $key => $category): ?>
|
|
|
|
|
|
<button class="category-btn <?php echo $key === 'all' ? 'active' : ''; ?>"
|
|
|
|
|
|
data-category="<?php echo $key; ?>"
|
|
|
|
|
|
style="background-color: <?php echo $category['color']; ?>;
|
|
|
|
|
|
color: <?php echo $category['text_color']; ?>">
|
|
|
|
|
|
<?php echo $category['name']; ?>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 视图切换按钮 -->
|
|
|
|
|
|
<div class="view-toggle">
|
|
|
|
|
|
<button class="list-view-btn active" data-view="list">
|
|
|
|
|
|
<i class="fas fa-list"></i> 列表视图
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button class="card-view-btn" data-view="card">
|
|
|
|
|
|
<i class="fas fa-th-large"></i> 卡片视图
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 快捷链接 -->
|
|
|
|
|
|
<div class="music-item centered-links">
|
|
|
|
|
|
<h2>其他链接</h2>
|
|
|
|
|
|
|
|
|
|
|
|
<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;">
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<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;">
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<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;">
|
|
|
|
|
|
</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 class="music-item">
|
|
|
|
|
|
<h2>最新公告</h2>
|
|
|
|
|
|
<p class="artist-info">作者:<i class="fas fa-crown" style="color: #FFD700;">JGZ_YES</i></p>
|
|
|
|
|
|
<div id="latest-announcement">
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// 数据库连接信息
|
|
|
|
|
|
$servername = "localhost";
|
|
|
|
|
|
$dbUsername = "a1sax1m9i";
|
|
|
|
|
|
$dbPassword = "a1sax1m9i";
|
|
|
|
|
|
$dbName = "a1sax1m9i";
|
|
|
|
|
|
|
|
|
|
|
|
// 创建连接并强制设置编码
|
|
|
|
|
|
$conn_gg = new mysqli($servername, $dbUsername, $dbPassword, $dbName);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查连接
|
|
|
|
|
|
if ($conn_gg->connect_error) {
|
|
|
|
|
|
die("<p>数据库连接失败: " . htmlspecialchars($conn_gg->connect_error, ENT_QUOTES, 'UTF-8') . "</p>");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 关键:设置连接字符集为utf8mb4(必须在查询前执行)
|
|
|
|
|
|
if (!$conn_gg->set_charset("utf8mb4")) {
|
|
|
|
|
|
die("<p>字符集设置失败: " . htmlspecialchars($conn_gg->error, ENT_QUOTES, 'UTF-8') . "</p>");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查询最新公告(带错误处理)
|
|
|
|
|
|
$sql = "SELECT nr, time FROM announcements ORDER BY id DESC LIMIT 1";
|
|
|
|
|
|
$result = $conn_gg->query($sql);
|
|
|
|
|
|
|
|
|
|
|
|
if ($result === FALSE) {
|
|
|
|
|
|
// 错误信息仍需转义,避免恶意代码
|
|
|
|
|
|
echo "<p>查询错误: " . htmlspecialchars($conn_gg->error, ENT_QUOTES, 'UTF-8') . "</p>";
|
|
|
|
|
|
} elseif ($result->num_rows > 0) {
|
|
|
|
|
|
$row = $result->fetch_assoc();
|
|
|
|
|
|
// 1. 保留nl2br():将数据库中的\n换行符转为HTML的<br>标签
|
|
|
|
|
|
// 2. 移除htmlspecialchars():让HTML标签(如<a>、<img>)正常解析
|
|
|
|
|
|
echo "<p>" . nl2br($row["nr"]) . "</p>";
|
|
|
|
|
|
// 发布时间仍需转义(纯文本,避免注入)
|
|
|
|
|
|
echo "<p class='file-info'>发布时间: " . htmlspecialchars($row["time"], ENT_QUOTES, 'UTF-8') . "</p>";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
echo "<p>暂无公告</p>";
|
|
|
|
|
|
}
|
|
|
|
|
|
$conn_gg->close();
|
|
|
|
|
|
?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<a href="gg.php" class="recommendations-link">
|
|
|
|
|
|
<i class="fa fa-history"></i>
|
|
|
|
|
|
<span>查看历史公告</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 音乐列表容器 -->
|
|
|
|
|
|
<div id="music-list-container" class="list-view">
|
|
|
|
|
|
<?php foreach ($musicList as $music): ?>
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// 生成当前歌曲的分享链接
|
|
|
|
|
|
$shareUrl = "https://shanwogou.cn/audio/play.php" . "?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 data-audio="<?php echo $music['id']; ?>">
|
|
|
|
|
|
<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; ?>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</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>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 网站信息 -->
|
|
|
|
|
|
<div class="site-info" id="site-info">
|
|
|
|
|
|
<div>版本: <?php echo $siteVersion; ?></div>
|
|
|
|
|
|
<div>© <?php echo $bqsy; ?></div> <!--2024-2025 落日音乐. JGZ_YES. 版权所有-->
|
|
|
|
|
|
<div>歌曲资源如有侵权联系<a href="mailto:383260290@qq.com">383260290@qq.com</a>删除</div>
|
|
|
|
|
|
</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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取下一首要播放的音频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) {
|
|
|
|
|
|
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 = '⏸';
|
|
|
|
|
|
|
|
|
|
|
|
// 为当前播放的音频注册结束事件,用于自动播放下一首
|
|
|
|
|
|
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 {
|
|
|
|
|
|
audio.pause();
|
|
|
|
|
|
playBtn.textContent = '▶';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化侧边栏切换(移动端)
|
|
|
|
|
|
function initSidebarToggle() {
|
|
|
|
|
|
const sidebar = q('#sidebar');
|
|
|
|
|
|
const toggleBtn = q('#sidebar-toggle');
|
|
|
|
|
|
|
|
|
|
|
|
addEvt(toggleBtn, 'click', function() {
|
|
|
|
|
|
sidebar.classList.toggle('show');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
addEvt(d, 'click', function(e) {
|
|
|
|
|
|
if (!sidebar.contains(e.target) &&
|
|
|
|
|
|
e.target !== toggleBtn &&
|
|
|
|
|
|
!toggleBtn.contains(e.target) &&
|
|
|
|
|
|
sidebar.classList.contains('show')) {
|
|
|
|
|
|
sidebar.classList.remove('show');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const historyItems = qa('.history-item');
|
|
|
|
|
|
historyItems.forEach(function(item) {
|
|
|
|
|
|
addEvt(item, 'click', function() {
|
|
|
|
|
|
if (document.documentElement.classList.contains('mobile')) {
|
|
|
|
|
|
sidebar.classList.remove('show');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化暗黑模式
|
|
|
|
|
|
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 initUserMenu() {
|
|
|
|
|
|
const userMenuBtn = q('#user-menu-btn');
|
|
|
|
|
|
const userDropdown = q('#user-dropdown');
|
|
|
|
|
|
const logoutBtn = q('#logout-btn');
|
|
|
|
|
|
|
|
|
|
|
|
if (userMenuBtn && userDropdown) {
|
|
|
|
|
|
addEvt(userMenuBtn, 'click', function(e) {
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
userDropdown.classList.toggle('show');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
addEvt(d, 'click', function() {
|
|
|
|
|
|
userDropdown.classList.remove('show');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (logoutBtn) {
|
|
|
|
|
|
addEvt(logoutBtn, 'click', function() {
|
|
|
|
|
|
if (confirm('确定要退出登录吗?')) {
|
|
|
|
|
|
window.location.href = 'index.php?action=logout';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 最近播放历史功能
|
|
|
|
|
|
function initPlayHistory() {
|
|
|
|
|
|
const historyList = q('#history-list');
|
|
|
|
|
|
const clearHistoryBtn = q('#clear-history');
|
|
|
|
|
|
const placeholder = historyList.querySelector('.history-placeholder');
|
|
|
|
|
|
|
|
|
|
|
|
function getHistory() { return JSON.parse(localStorage.getItem('playHistory') || '[]'); }
|
|
|
|
|
|
function saveHistory(history) { localStorage.setItem('playHistory', JSON.stringify(history)); }
|
|
|
|
|
|
|
|
|
|
|
|
function updateHistoryUI() {
|
|
|
|
|
|
const history = getHistory();
|
|
|
|
|
|
const items = historyList.querySelectorAll('.history-item');
|
|
|
|
|
|
items.forEach(item => item.remove());
|
|
|
|
|
|
|
|
|
|
|
|
if (history.length === 0) {
|
|
|
|
|
|
if (placeholder) placeholder.style.display = 'block';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (placeholder) placeholder.style.display = 'none';
|
|
|
|
|
|
history.forEach(item => {
|
|
|
|
|
|
const historyItem = d.createElement('div');
|
|
|
|
|
|
historyItem.className = 'history-item';
|
|
|
|
|
|
historyItem.setAttribute('data-audio', item.id);
|
|
|
|
|
|
const date = new Date(item.timestamp);
|
|
|
|
|
|
const formattedTime = `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
|
|
|
|
|
historyItem.innerHTML = `
|
|
|
|
|
|
<div class="history-info">
|
|
|
|
|
|
<h4 class="history-title">${item.title}</h4>
|
|
|
|
|
|
<p class="history-artist">${item.artist}</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="history-time">${formattedTime}</span>`;
|
|
|
|
|
|
addEvt(historyItem, 'click', function() {
|
|
|
|
|
|
const audioId = this.getAttribute('data-audio');
|
|
|
|
|
|
const audio = q('#' + audioId);
|
|
|
|
|
|
const playBtn = q('.play-pause[data-audio="' + audioId + '"]');
|
|
|
|
|
|
if (audio && playBtn) {
|
|
|
|
|
|
const musicItem = audio.closest('.music-item');
|
|
|
|
|
|
if (musicItem) { musicItem.scrollIntoView({ behavior: 'smooth', block: 'start' }); }
|
|
|
|
|
|
if (audio.paused) { togglePlayback(audio, playBtn); }
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
historyList.appendChild(historyItem);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
window.addToHistory = function(songId, songTitle, artist) {
|
|
|
|
|
|
let history = getHistory();
|
|
|
|
|
|
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); }
|
|
|
|
|
|
saveHistory(history);
|
|
|
|
|
|
updateHistoryUI();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
addEvt(clearHistoryBtn, 'click', function() {
|
|
|
|
|
|
if (confirm('确定要清空所有播放历史吗?')) {
|
|
|
|
|
|
localStorage.removeItem('playHistory');
|
|
|
|
|
|
updateHistoryUI();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
updateHistoryUI();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 播放进度记忆功能
|
|
|
|
|
|
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 initTitleEffects() {
|
|
|
|
|
|
const originalTitle = document.title;
|
|
|
|
|
|
let titleChangeTimer = null;
|
|
|
|
|
|
addEvt(document, 'visibilitychange', function() {
|
|
|
|
|
|
if (titleChangeTimer) { clearTimeout(titleChangeTimer); titleChangeTimer = null; }
|
|
|
|
|
|
if (document.hidden) {
|
|
|
|
|
|
document.title = '你不要走啊 ! ..(。•ˇ‸ˇ•。)…';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
document.title = '耶,又回来了!(^_^)';
|
|
|
|
|
|
titleChangeTimer = setTimeout(function() {
|
|
|
|
|
|
document.title = originalTitle;
|
|
|
|
|
|
titleChangeTimer = null;
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化播放器
|
|
|
|
|
|
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;
|
|
|
|
|
|
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(() => 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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 进度条拖动逻辑
|
|
|
|
|
|
const startDrag = (e) => { isDragging = true; progressHandle.classList.add('dragging'); updateProgress(e); };
|
|
|
|
|
|
const updateProgress = (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));
|
|
|
|
|
|
const percentage = pos * 100;
|
|
|
|
|
|
progressFill.style.width = percentage + '%';
|
|
|
|
|
|
progressHandle.style.left = percentage + '%';
|
|
|
|
|
|
currentTime.textContent = formatTime(pos * audio.duration);
|
|
|
|
|
|
};
|
|
|
|
|
|
const endDrag = () => {
|
|
|
|
|
|
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', (e) => { if (isDragging) updateProgress(e); });
|
|
|
|
|
|
addEvt(d, 'mouseup', 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(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 initViewToggle() {
|
|
|
|
|
|
const listViewBtn = q('.list-view-btn');
|
|
|
|
|
|
const cardViewBtn = q('.card-view-btn');
|
|
|
|
|
|
const container = q('#music-list-container');
|
|
|
|
|
|
|
|
|
|
|
|
addEvt(listViewBtn, 'click', function() {
|
|
|
|
|
|
container.classList.remove('card-view');
|
|
|
|
|
|
container.classList.add('list-view');
|
|
|
|
|
|
listViewBtn.classList.add('active');
|
|
|
|
|
|
cardViewBtn.classList.remove('active');
|
|
|
|
|
|
localStorage.setItem('viewMode', 'list');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
addEvt(cardViewBtn, 'click', function() {
|
|
|
|
|
|
container.classList.remove('list-view');
|
|
|
|
|
|
container.classList.add('card-view');
|
|
|
|
|
|
cardViewBtn.classList.add('active');
|
|
|
|
|
|
listViewBtn.classList.remove('active');
|
|
|
|
|
|
localStorage.setItem('viewMode', 'card');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 恢复用户偏好的视图模式
|
|
|
|
|
|
const savedView = localStorage.getItem('viewMode');
|
|
|
|
|
|
if (savedView === 'card') {
|
|
|
|
|
|
cardViewBtn.click();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化分类筛选
|
|
|
|
|
|
function initCategoryFilter() {
|
|
|
|
|
|
const categoryBtns = qa('.category-btn');
|
|
|
|
|
|
const musicItems = qa('.music-item');
|
|
|
|
|
|
|
|
|
|
|
|
categoryBtns.forEach(function(btn) {
|
|
|
|
|
|
addEvt(btn, 'click', function() {
|
|
|
|
|
|
// 更新按钮状态
|
|
|
|
|
|
categoryBtns.forEach(b => b.classList.remove('active'));
|
|
|
|
|
|
this.classList.add('active');
|
|
|
|
|
|
|
|
|
|
|
|
const category = this.getAttribute('data-category');
|
|
|
|
|
|
|
|
|
|
|
|
// 筛选音乐项
|
|
|
|
|
|
musicItems.forEach(function(item) {
|
|
|
|
|
|
if (category === 'all' || item.getAttribute('data-category') === category) {
|
|
|
|
|
|
item.style.display = 'block';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
item.style.display = 'none';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 保存用户选择的分类
|
|
|
|
|
|
localStorage.setItem('selectedCategory', category);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 恢复用户上次选择的分类
|
|
|
|
|
|
const savedCategory = localStorage.getItem('selectedCategory');
|
|
|
|
|
|
if (savedCategory) {
|
|
|
|
|
|
const savedBtn = q('.category-btn[data-category="' + savedCategory + '"]');
|
|
|
|
|
|
if (savedBtn) savedBtn.click();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化搜索功能(首页保留即时筛选,同时支持表单提交到搜索页)
|
|
|
|
|
|
function initSearch() {
|
|
|
|
|
|
const searchForm = q('#search-form');
|
|
|
|
|
|
const searchInput = q('#search-input');
|
|
|
|
|
|
const musicItems = qa('.music-item');
|
|
|
|
|
|
|
|
|
|
|
|
// 回车键提交表单
|
|
|
|
|
|
addEvt(searchInput, 'keypress', function(e) {
|
|
|
|
|
|
if (e.key === 'Enter') {
|
|
|
|
|
|
searchForm.submit();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 首页保留即时筛选功能
|
|
|
|
|
|
addEvt(searchInput, 'input', function() {
|
|
|
|
|
|
const searchTerm = this.value.toLowerCase().trim();
|
|
|
|
|
|
|
|
|
|
|
|
musicItems.forEach(function(item) {
|
|
|
|
|
|
const title = item.querySelector('h2').textContent.toLowerCase();
|
|
|
|
|
|
const artist = item.querySelector('.artist-info').textContent.toLowerCase();
|
|
|
|
|
|
|
|
|
|
|
|
if (title.includes(searchTerm) || artist.includes(searchTerm)) {
|
|
|
|
|
|
item.style.display = 'block';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
item.style.display = 'none';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化复制功能
|
|
|
|
|
|
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 = q('.share-link[data-audio="' + audioId + '"]');
|
|
|
|
|
|
|
|
|
|
|
|
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'
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查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 initAvatarLoading() {
|
|
|
|
|
|
// 获取头像URL列表(从PHP传递过来)
|
|
|
|
|
|
<?php
|
|
|
|
|
|
// 将头像URL列表转换为JavaScript数组
|
|
|
|
|
|
echo "const avatarUrls = " . json_encode($avatarUrls) . ";\n";
|
|
|
|
|
|
?>
|
|
|
|
|
|
|
|
|
|
|
|
// 显示调试信息
|
|
|
|
|
|
console.log("开始尝试加载头像,URL列表:", avatarUrls);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取头像元素
|
|
|
|
|
|
const userAvatarImg = q('#user-avatar-img');
|
|
|
|
|
|
const userAvatarContainer = q('#user-avatar-container');
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有头像元素,直接返回
|
|
|
|
|
|
if (!userAvatarImg || !userAvatarContainer) {
|
|
|
|
|
|
console.log("未找到头像元素,跳过头像加载");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试加载头像的函数
|
|
|
|
|
|
function tryLoadAvatar(urls, index = 0) {
|
|
|
|
|
|
// 如果所有URL都尝试过了,使用最后一个默认头像
|
|
|
|
|
|
if (index >= urls.length) {
|
|
|
|
|
|
console.error("所有头像URL都加载失败,使用默认头像");
|
|
|
|
|
|
userAvatarImg.src = urls[urls.length - 1];
|
|
|
|
|
|
userAvatarImg.style.display = 'block';
|
|
|
|
|
|
userAvatarContainer.classList.remove('avatar-loading');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试当前URL
|
|
|
|
|
|
const currentUrl = urls[index];
|
|
|
|
|
|
console.log(`尝试加载头像 (${index + 1}/${urls.length}):`, currentUrl);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建临时图片对象测试加载
|
|
|
|
|
|
const testImg = new Image();
|
|
|
|
|
|
|
|
|
|
|
|
// 加载成功
|
|
|
|
|
|
testImg.onload = function() {
|
|
|
|
|
|
console.log(`头像加载成功:`, currentUrl);
|
|
|
|
|
|
userAvatarImg.src = currentUrl;
|
|
|
|
|
|
userAvatarImg.style.display = 'block';
|
|
|
|
|
|
userAvatarContainer.classList.remove('avatar-loading');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 加载失败,尝试下一个URL
|
|
|
|
|
|
testImg.onerror = function() {
|
|
|
|
|
|
console.error(`头像加载失败,尝试下一个URL:`, currentUrl);
|
|
|
|
|
|
tryLoadAvatar(urls, index + 1);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 设置超时时间(5秒)
|
|
|
|
|
|
testImg.timeout = 5000;
|
|
|
|
|
|
testImg.ontimeout = function() {
|
|
|
|
|
|
console.error(`头像加载超时,尝试下一个URL:`, currentUrl);
|
|
|
|
|
|
tryLoadAvatar(urls, index + 1);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 开始加载
|
|
|
|
|
|
testImg.src = currentUrl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 开始尝试加载头像
|
|
|
|
|
|
tryLoadAvatar(avatarUrls);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化所有功能
|
|
|
|
|
|
function initAll() {
|
|
|
|
|
|
initSidebarToggle();
|
|
|
|
|
|
initDarkMode();
|
|
|
|
|
|
initUserMenu();
|
|
|
|
|
|
initPlayHistory();
|
|
|
|
|
|
initPlaybackPositionMemory();
|
|
|
|
|
|
initTitleEffects();
|
|
|
|
|
|
initAudioPlayers();
|
|
|
|
|
|
initViewToggle();
|
|
|
|
|
|
initCategoryFilter();
|
|
|
|
|
|
initSearch();
|
|
|
|
|
|
initCopyFunctionality();
|
|
|
|
|
|
initBackToTop();
|
|
|
|
|
|
autoPlayFromUrl();
|
|
|
|
|
|
|
|
|
|
|
|
// 头像加载必须在最后初始化,确保DOM已完全加载
|
|
|
|
|
|
initAvatarLoading();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 页面加载完成后初始化
|
|
|
|
|
|
addEvt(w, 'load', initAll);
|
|
|
|
|
|
})(document, window);
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|