个人FM电台源代码

复制源码到文档保存为html格式文档 双击打开就可以了

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>辣条FM电台</title>
    <link rel="stylesheet" href=".https://cdn.bootcdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: "Segoe UI", "Microsoft Yahei", sans-serif;
        }

        body {
            background-color: #f9fafb;
            padding: 20px;
            color: #334155;
            line-height: 1.6;
        }

        .container {
            max-width: 900px;
            margin: 0 auto;
            background-color: #ffffff;
            border-radius: 12px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
            padding: 30px;
            overflow: hidden;
        }

        h1 {
            text-align: center;
            color: #1e293b;
            margin-bottom: 24px;
            font-size: 24px;
            font-weight: 600;
        }

        /* 标签与搜索区域 */
        .tab-search-wrap {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            margin-bottom: 12px;
            position: relative;
        }

        .list-tabs {
            display: flex;
            gap: 4px;
            border-bottom: 1px solid #e2e8f0;
            padding-bottom: 8px;
            flex: 1;
        }

        .tab-btn {
            padding: 6px 16px;
            border: none;
            background: transparent;
            color: #64748b;
            font-size: 14px;
            font-weight: 500;
            cursor: pointer;
            border-radius: 6px;
            transition: all 0.2s ease;
            position: relative;
            overflow: hidden;
        }

        .tab-btn::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 0;
            height: 2px;
            background-color: #0ea5e9;
            transition: width 0.2s ease;
        }

        .tab-btn.active {
            color: #0ea5e9;
            background-color: #e0f2fe;
        }

        .tab-btn.active::after {
            width: 100%;
        }

        .search-trigger {
            width: 36px;
            height: 36px;
            border: none;
            border-radius: 6px;
            background-color: #f8fafc;
            color: #64748b;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.2s ease;
        }

        .search-trigger:hover {
            background-color: #e2e8f0;
            color: #0ea5e9;
            transform: scale(1.05);
        }

        .search-trigger:active {
            transform: scale(0.95);
        }

        .search-box {
            position: absolute;
            top: 42px;
            left: 0;
            right: 0;
            background-color: #fff;
            padding: 8px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
            z-index: 10;
            display: none;
            animation: slideDown 0.2s ease;
        }

        @keyframes slideDown {
            from {
                opacity: 0;
                transform: translateY(-10px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .search-box.show {
            display: block;
        }

        .search-input {
            width: 100%;
            padding: 12px 16px;
            border: 1px solid #e2e8f0;
            border-radius: 8px;
            font-size: 14px;
            outline: none;
            transition: all 0.2s ease;
            background-color: #f8fafc;
        }

        .search-input::placeholder {
            color: #94a3b8;
        }

        /* 播放器区域 - 固定定位容器 */
        .player-fixed-wrap {
            position: sticky;
            top: 20px;
            z-index: 5;
            margin-bottom: 20px;
            background-color: #fff;
            padding: 10px;
            border-radius: 12px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.05);
            transition: all 0.3s ease;
        }

        .player-fixed-wrap:hover {
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
        }

        .player {
            padding: 20px;
            background-color: #f8fafc;
            border-radius: 8px;
            display: flex;
            flex-direction: column;
            gap: 16px;
            transition: all 0.3s ease;
        }

        .status {
            color: #64748b;
            font-size: 14px;
            text-align: center;
            line-height: 1.5;
            transition: all 0.3s ease;
            min-height: 21px;
        }

        .status.loading {
            color: #0ea5e9;
            animation: pulse 1.5s ease-in-out infinite;
        }

        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.5; }
        }

        .control-bar {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            flex-wrap: wrap;
        }

        .playback-controls {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .control-btn {
            width: 44px;
            height: 44px;
            border: none;
            border-radius: 8px;
            background-color: #38bdf8;
            color: #ffffff;
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 16px;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            overflow: hidden;
            transform: scale(1);
        }

        .control-btn:hover {
            background-color: #0ea5e9;
            transform: translateY(-1px) scale(1.05);
            box-shadow: 0 4px 12px rgba(56, 189, 248, 0.3);
        }

        .control-btn:active {
            transform: translateY(0) scale(0.95);
        }

        .control-btn.active-mode {
            background-color: #22c55e;
        }

        .control-btn.collect-btn.active {
            background-color: #ef4444;
            animation: heartBeat 0.6s ease;
        }

        @keyframes heartBeat {
            0%, 100% { transform: scale(1); }
            14% { transform: scale(1.1); }
            28% { transform: scale(1); }
            42% { transform: scale(1.1); }
            70% { transform: scale(1); }
        }

        .volume-control {
            display: flex;
            align-items: center;
            gap: 10px;
            flex: 1;
            max-width: 220px;
        }

        .volume-icon {
            font-size: 18px;
            color: #64748b;
            width: 20px;
            text-align: center;
            transition: color 0.2s ease;
            cursor: pointer;
        }

        .volume-icon:hover {
            color: #0ea5e9;
        }

        .volume-slider {
            width: 100%;
            height: 6px;
            -webkit-appearance: none;
            appearance: none;
            background: #e2e8f0;
            border-radius: 3px;
            outline: none;
            transition: all 0.2s ease;
        }

        .volume-slider:hover {
            background: #cbd5e1;
        }

        .volume-slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 16px;
            height: 16px;
            border-radius: 50%;
            background: #38bdf8;
            cursor: pointer;
            transition: all 0.2s ease;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }

        .volume-slider::-webkit-slider-thumb:hover {
            background: #0ea5e9;
            transform: scale(1.2);
            box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
        }

        .volume-slider::-moz-range-thumb {
            width: 16px;
            height: 16px;
            border-radius: 50%;
            background: #38bdf8;
            cursor: pointer;
            border: none;
            transition: all 0.2s ease;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }

        .volume-slider::-moz-range-thumb:hover {
            background: #0ea5e9;
            transform: scale(1.2);
            box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
        }

        audio {
            width: 100%;
            height: 40px;
            border: none;
            border-radius: 8px;
            background-color: #fff;
            padding: 0 8px;
            transition: all 0.3s ease;
        }

        audio:hover {
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
        }

        /* 列表区域 */
        .radio-lists {
            border-radius: 8px;
            overflow: hidden;
            border: 1px solid #e2e8f0;
            max-height: calc(100vh - 320px);
            overflow-y: auto;
            transition: all 0.3s ease;
        }

        .radio-lists:hover {
            border-color: #cbd5e1;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
        }

        .radio-lists::-webkit-scrollbar {
            width: 6px;
        }

        .radio-lists::-webkit-scrollbar-track {
            background: #f1f5f9;
        }

        .radio-lists::-webkit-scrollbar-thumb {
            background: #cbd5e1;
            border-radius: 3px;
        }

        .radio-lists::-webkit-scrollbar-thumb:hover {
            background: #94a3b8;
        }

        .radio-list {
            list-style: none;
            display: none;
        }

        .radio-list.active {
            display: block;
        }

        .radio-item {
            padding: 14px 16px;
            border-bottom: 1px solid #f1f5f9;
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 14px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            overflow: hidden;
        }

        .radio-item::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            width: 3px;
            background-color: transparent;
            transition: background-color 0.2s ease;
        }

        .radio-item:last-child {
            border-bottom: none;
        }

        .radio-item:hover {
            background-color: #f8fafc;
            transform: translateX(4px);
        }

        .radio-item:hover::before {
            background-color: #0ea5e9;
        }

        .radio-item.active {
            background-color: #e0f2fe;
            color: #0ea5e9;
            font-weight: 500;
        }

        .radio-item.active::before {
            background-color: #0ea5e9;
        }

        .radio-item .collect-icon {
            font-size: 16px;
            color: #cbd5e1;
            cursor: pointer;
            transition: all 0.2s ease;
            width: 20px;
            text-align: center;
            transform: scale(1);
        }

        .radio-item .collect-icon:hover {
            color: #ef4444;
            transform: scale(1.2);
        }

        .radio-item .collect-icon.active {
            color: #ef4444;
            animation: heartBeat 0.6s ease;
        }

        .empty-tip {
            padding: 40px 20px;
            text-align: center;
            color: #94a3b8;
            font-size: 14px;
            line-height: 1.6;
            transition: all 0.3s ease;
        }

        .empty-tip i {
            font-size: 32px;
            margin-bottom: 12px;
            display: block;
            color: #cbd5e1;
            transition: all 0.3s ease;
        }

        .empty-tip:hover i {
            transform: scale(1.1);
            color: #94a3b8;
        }

        /* 快捷键提示 */
        .shortcut-tip {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background-color: rgba(30, 41, 59, 0.9);
            color: white;
            padding: 12px 16px;
            border-radius: 8px;
            font-size: 12px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
            opacity: 0.7;
            transition: all 0.3s ease;
            z-index: 100;
        }

        .shortcut-tip:hover {
            opacity: 1;
            transform: translateY(-4px);
        }

        .shortcut-tip h4 {
            margin-bottom: 8px;
            font-size: 13px;
            font-weight: 600;
        }

        .shortcut-tip ul {
            list-style: none;
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 4px 12px;
        }

        .shortcut-tip li {
            display: flex;
            align-items: center;
            gap: 6px;
        }

        .shortcut-key {
            background-color: rgba(255, 255, 255, 0.2);
            padding: 2px 6px;
            border-radius: 4px;
            font-family: monospace;
            font-size: 11px;
        }

        /* 加载动画 */
        .loading-spinner {
            display: inline-block;
            width: 16px;
            height: 16px;
            border: 2px solid rgba(56, 189, 248, 0.3);
            border-radius: 50%;
            border-top-color: #38bdf8;
            animation: spin 0.8s ease-in-out infinite;
            margin-right: 8px;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        /* 管理界面样式 */
        .admin-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 24px;
            padding-bottom: 16px;
            border-bottom: 1px solid #e2e8f0;
        }

        .admin-header h2 {
            font-size: 20px;
            color: #1e293b;
        }

        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: 8px 16px;
            background-color: #38bdf8;
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s ease;
            gap: 6px;
            text-decoration: none;
        }

        .btn:hover {
            background-color: #0ea5e9;
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(56, 189, 248, 0.3);
        }

        .btn:active {
            transform: translateY(0);
        }

        .btn-secondary {
            background-color: #94a3b8;
        }

        .btn-secondary:hover {
            background-color: #64748b;
        }

        .form-group {
            margin-bottom: 16px;
        }

        label {
            display: block;
            margin-bottom: 6px;
            font-weight: 500;
            color: #334155;
            font-size: 14px;
        }

        .form-control {
            width: 100%;
            padding: 10px 12px;
            border: 1px solid #e2e8f0;
            border-radius: 6px;
            font-size: 14px;
            transition: all 0.2s ease;
            background-color: #f8fafc;
        }

        .form-control:focus {
            outline: none;
            border-color: #38bdf8;
            box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.1);
        }

        .form-row {
            display: grid;
            grid-template-columns: 1fr 1fr 120px;
            gap: 16px;
            align-items: end;
        }

        .add-radio-form {
            margin-bottom: 32px;
            padding: 20px;
            background-color: #f8fafc;
            border-radius: 8px;
        }

        .add-radio-form h3 {
            margin-bottom: 16px;
            color: #1e293b;
            font-size: 16px;
        }

        .radio-table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
        }

        .radio-table th,
        .radio-table td {
            padding: 12px 16px;
            text-align: left;
            border-bottom: 1px solid #e2e8f0;
        }

        .radio-table th {
            background-color: #f1f5f9;
            font-weight: 600;
            color: #334155;
            font-size: 14px;
        }

        .radio-table tr:hover {
            background-color: #f8fafc;
        }

        .action-buttons {
            display: flex;
            gap: 8px;
        }

        .delete-btn {
            background-color: #fecaca;
            color: #dc2626;
        }

        .delete-btn:hover {
            background-color: #fef2f2;
            color: #b91c1c;
            box-shadow: none;
        }

        .message {
            padding: 12px 16px;
            border-radius: 6px;
            margin-bottom: 16px;
            font-size: 14px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .message.success {
            background-color: #dcfce7;
            color: #166534;
            border: 1px solid #bbf7d0;
        }

        .message.error {
            background-color: #fee2e2;
            color: #b91c1c;
            border: 1px solid #fecaca;
        }

        #messageContainer {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 1000;
            max-width: 300px;
        }

        .login-form {
            max-width: 400px;
            margin: 0 auto;
            padding: 24px;
            background-color: #f8fafc;
            border-radius: 8px;
        }

        .login-form h2 {
            text-align: center;
            margin-bottom: 24px;
            color: #1e293b;
        }

        /* 模式切换按钮 */
        .mode-switch {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 100;
        }

        /* 隐藏区域 */
        .hidden {
            display: none !important;
        }

        /* 响应式设计 */
        @media (max-width: 768px) {
            body {
                padding: 10px;
            }
            
            .container {
                padding: 20px;
            }
            
            .control-bar {
                flex-direction: column;
                align-items: stretch;
            }
            
            .playback-controls {
                justify-content: center;
            }
            
            .volume-control {
                max-width: 100%;
            }
            
            .radio-lists {
                max-height: calc(100vh - 380px);
            }
            
            .shortcut-tip {
                display: none;
            }

            .form-row {
                grid-template-columns: 1fr;
            }

            .radio-table {
                font-size: 12px;
            }

            .radio-table th,
            .radio-table td {
                padding: 8px 12px;
            }

            .action-buttons {
                flex-direction: column;
            }
        }
    </style>
</head>
<body>
    <div class="mode-switch">
        <button class="btn btn-secondary" id="switchModeBtn">
            <i class="fas fa-cog"></i> 切换到管理模式
        </button>
    </div>
    
    <div class="container">
        <h1>辣条FM电台</h1>

        <!-- 前台播放区域 -->
        <div id="playerArea">
            <!-- 固定播放区域 -->
            <div class="player-fixed-wrap">
                <div class="player">
                    <div class="status" id="status">请选择下方电台开始播放</div>
                    
                    <div class="control-bar">
                        <div class="playback-controls">
                            <button class="control-btn" id="playPauseBtn" title="播放/暂停 (空格键)">
                                <i class="fas fa-play"></i>
                            </button>
                            <button class="control-btn" id="nextBtn" title="下一曲 (→)">
                                <i class="fas fa-step-forward"></i>
                            </button>
                            <button class="control-btn" id="sequenceBtn" title="顺序播放">
                                <i class="fas fa-list-ol"></i>
                            </button>
                            <button class="control-btn" id="randomBtn" title="随机播放">
                                <i class="fas fa-shuffle"></i>
                            </button>
                            <button class="control-btn collect-btn" id="collectBtn" title="收藏当前电台 (F)">
                                <i class="fas fa-heart"></i>
                            </button>
                        </div>
                        <div class="volume-control">
                            <i class="fas fa-volume-up volume-icon" id="volumeIcon" title="静音/取消静音 (M)"></i>
                            <input type="range" class="volume-slider" id="volumeSlider" min="0" max="1" step="0.05" value="1">
                        </div>
                    </div>

                    <audio id="audioPlayer" controls></audio>
                </div>
            </div>

            <!-- 标签与搜索区域 -->
            <div class="tab-search-wrap">
                <div class="list-tabs">
                    <button class="tab-btn active" data-tab="all">全部电台</button>
                    <button class="tab-btn" data-tab="collect">我的收藏</button>
                </div>
                <button class="search-trigger" id="searchTrigger" title="搜索电台 (S)">
                    <i class="fas fa-search"></i>
                </button>
                <div class="search-box" id="searchBox">
                    <input type="text" class="search-input" id="searchInput" placeholder="输入电台名称搜索...">
                </div>
            </div>

            <!-- 可滚动列表区域 -->
            <div class="radio-lists">
                <ul class="radio-list active" id="allRadioList"></ul>
                <ul class="radio-list" id="collectRadioList"></ul>
            </div>
        </div>

        <!-- 管理区域 -->
        <div id="adminArea" class="hidden">
            <div class="admin-header">
                <h2>电台管理</h2>
                <button class="btn btn-secondary" id="backToPlayer">
                    <i class="fas fa-home"></i>
                    返回前台
                </button>
            </div>

            <!-- 消息提示 -->
            <div id="messageContainer"></div>

            <!-- 添加电台表单 -->
            <div class="add-radio-form">
                <h3>添加新电台</h3>
                <form id="addRadioForm" class="form-row">
                    <div class="form-group">
                        <label for="radioTitle">电台名称</label>
                        <input type="text" class="form-control" id="radioTitle" placeholder="请输入电台名称" required>
                    </div>
                    <div class="form-group">
                        <label for="radioUrl">电台URL</label>
                        <input type="url" class="form-control" id="radioUrl" placeholder="请输入电台流地址" required>
                    </div>
                    <button type="submit" class="btn btn-primary">
                        <i class="fas fa-plus"></i>
                        添加
                    </button>
                </form>
            </div>

            <!-- 电台列表 -->
            <table class="radio-table">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>电台名称</th>
                        <th>URL地址</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody id="radioTableBody"></tbody>
            </table>
        </div>

        <!-- 管理员登录 -->
        <div id="loginForm" class="login-form hidden">
            <h2>管理员登录</h2>
            <div class="form-group">
                <label for="password">密码</label>
                <input type="password" class="form-control" id="password" placeholder="请输入管理员密码">
            </div>
            <button class="btn btn-primary" style="width: 100%;" id="loginBtn">登录</button>
            <div class="message error" id="loginError" style="display: none; margin-top: 16px;">
                <i class="fas fa-exclamation-circle"></i>
                <span>密码错误,请重试</span>
            </div>
        </div>
    </div>

    <!-- 快捷键提示 -->
    <div class="shortcut-tip">
        <h4>快捷键</h4>
        <ul>
            <li><span class="shortcut-key">空格</span> 播放/暂停</li>
            <li><span class="shortcut-key">→</span> 下一曲</li>
            <li><span class="shortcut-key">F</span> 收藏/取消</li>
            <li><span class="shortcut-key">M</span> 静音/取消</li>
            <li><span class="shortcut-key">S</span> 搜索</li>
            <li><span class="shortcut-key">ESC</span> 关闭搜索</li>
        </ul>
    </div>

    <script>
        // 采用模块化设计,封装所有功能
        (function() {
            // 管理员密码(实际应用中应使用更安全的方式存储和验证)
            const ADMIN_PASSWORD = 'admin123'; // 可以修改为你需要的密码
            let isAdminLoggedIn = false;
            
            // 电台数据 - 优先从localStorage读取,没有则使用默认数据
            let radioData = JSON.parse(localStorage.getItem('radioData')) || [
                {"title": "怀集音乐之声", "url": "http://lhttp.qingting.fm/live/4804/64k.mp3", "isCollected": false},
                {"title": "两广之声音乐台", "url": "http://lhttp.qingting.fm/live/20500149/64k.mp3", "isCollected": false},
                {"title": "清晨音乐台", "url": "http://lhttp.qingting.fm/live/4915/64k.mp3", "isCollected": false},
                {"title": "河北音乐广播", "url": "http://lhttp.qingting.fm/live/1649/64k.mp3", "isCollected": false},
                {"title": "上海流行音乐LoveRadio", "url": "http://lhttp.qingting.fm/live/273/64k.mp3", "isCollected": false},
                {"title": "江苏经典流行音乐", "url": "http://lhttp.qingting.fm/live/4938/64k.mp3", "isCollected": false},
                {"title": "广东音乐之声", "url": "http://lhttp.qingting.fm/live/1260/64k.mp3", "isCollected": false},
                {"title": "上海动感101", "url": "http://lhttp.qingting.fm/live/274/64k.mp3", "isCollected": false},
                {"title": "怀旧好声音", "url": "http://lhttp.qingting.fm/live/1223/64k.mp3", "isCollected": false},
                {"title": "哈尔滨音乐广播", "url": "http://lhttp.qingting.fm/live/839/64k.mp3", "isCollected": false},
                {"title": "苏州音乐广播", "url": "http://lhttp.qingting.fm/live/2803/64k.mp3", "isCollected": false},
                {"title": "959年代音乐怀旧好声音", "url": "http://lhttp.qingting.fm/live/5021381/64k.mp3", "isCollected": false},
                {"title": "动听音乐台", "url": "http://lhttp.qingting.fm/live/5022107/64k.mp3", "isCollected": false},
                {"title": "500首华语经典", "url": "http://lhttp.qingting.fm/live/5022308/64k.mp3", "isCollected": false},
                {"title": "北京音乐广播", "url": "http://lhttp.qingting.fm/live/332/64k.mp3", "isCollected": false},
                {"title": "954汽车音乐广播", "url": "http://lhttp.qingting.fm/live/1936/64k.mp3", "isCollected": false},
                {"title": "深圳飞扬971", "url": "http://lhttp.qingting.fm/live/1271/64k.mp3", "isCollected": false},
                {"title": "950广西音乐台", "url": "http://lhttp.qingting.fm/live/4875/64k.mp3", "isCollected": false},
                {"title": "厦门音乐广播", "url": "http://lhttp.qingting.fm/live/1739/64k.mp3", "isCollected": false},
                {"title": "欧美音乐88.7", "url": "http://lhttp.qingting.fm/live/15318703/64k.mp3", "isCollected": false},
                {"title": "无锡音乐广播", "url": "http://lhttp.qingting.fm/live/2779/64k.mp3", "isCollected": false},
                {"title": "四川城市之音", "url": "http://lhttp.qingting.fm/live/1111/64k.mp3", "isCollected": false},
                {"title": "陕西音乐广播", "url": "http://lhttp.qingting.fm/live/4873/64k.mp3", "isCollected": false},
                {"title": "崂山921", "url": "http://lhttp.qingting.fm/live/20212426/64k.mp3", "isCollected": false},
                {"title": "长沙101.7城市之声", "url": "http://lhttp.qingting.fm/live/4237/64k.mp3", "isCollected": false},
                {"title": "上海经典947", "url": "http://lhttp.qingting.fm/live/267/64k.mp3", "isCollected": false},
                {"title": "湖北经典音乐广播", "url": "http://lhttp.qingting.fm/live/1296/64k.mp3", "isCollected": false},
                {"title": "成都年代音乐怀旧好声音", "url": "http://lhttp.qingting.fm/live/20211686/64k.mp3", "isCollected": false},
                {"title": "山东经典音乐广播", "url": "http://lhttp.qingting.fm/live/20240/64k.mp3", "isCollected": false},
                {"title": "江苏音乐广播Play897", "url": "http://lhttp.qingting.fm/live/4936/64k.mp3", "isCollected": false},
                {"title": "天津TIKI 100.5", "url": "http://lhttp.qingting.fm/live/20003/64k.mp3", "isCollected": false},
                {"title": "杭州90.7", "url": "http://lhttp.qingting.fm/live/15318146/64k.mp3", "isCollected": false},
                {"title": "长春广播电视台 88.0", "url": "http://lhttp.qingting.fm/live/4850/64k.mp3", "isCollected": false},
                {"title": "星河音乐", "url": "http://lhttp.qingting.fm/live/20210755/64k.mp3", "isCollected": false},
                {"title": "江西音乐广播", "url": "http://lhttp.qingting.fm/live/1802/64k.mp3", "isCollected": false},
                {"title": "广东广播电视台珠江之声", "url": "http://lhttp.qingting.fm/live/470/64k.mp3", "isCollected": false},
                {"title": "内蒙古音乐之声", "url": "http://lhttp.qingting.fm/live/1886/64k.mp3", "isCollected": false},
                {"title": "88.6长沙音乐广播", "url": "http://lhttp.qingting.fm/live/20847/64k.mp3", "isCollected": false},
                {"title": "楚天音乐广播", "url": "http://lhttp.qingting.fm/live/1289/64k.mp3", "isCollected": false},
                {"title": "重庆音乐广播", "url": "http://lhttp.qingting.fm/live/647/64k.mp3", "isCollected": false},
                {"title": "年代音乐1022", "url": "http://lhttp.qingting.fm/live/20500066/64k.mp3", "isCollected": false},
                {"title": "武安融媒综合广播", "url": "http://lhttp.qingting.fm/live/5022474/64k.mp3", "isCollected": false},
                {"title": "南宁经典1049", "url": "http://lhttp.qingting.fm/live/20769/64k.mp3", "isCollected": false},
                {"title": "惠州音乐广播", "url": "http://lhttp.qingting.fm/live/5021523/64k.mp3", "isCollected": false},
                {"title": "黑龙江音乐广播", "url": "http://lhttp.qingting.fm/live/4969/64k.mp3", "isCollected": false},
                {"title": "嘉兴音乐广播", "url": "http://lhttp.qingting.fm/live/1136/64k.mp3", "isCollected": false},
                {"title": "80后音悦台", "url": "http://lhttp.qingting.fm/live/20207761/64k.mp3", "isCollected": false},
                {"title": "经典983电台", "url": "http://lhttp.qingting.fm/live/20211575/64k.mp3", "isCollected": false},
                {"title": "西安音乐广播", "url": "http://lhttp.qingting.fm/live/1612/64k.mp3", "isCollected": false},
                {"title": "武汉经典音乐广播", "url": "http://lhttp.qingting.fm/live/1297/64k.mp3", "isCollected": false},
                {"title": "怀旧音乐广播895", "url": "http://lhttp.qingting.fm/live/20211619/64k.mp3", "isCollected": false},
                {"title": "定州交通音乐广播", "url": "http://lhttp.qingting.fm/live/20211638/64k.mp3", "isCollected": false},
                {"title": "好听 1055", "url": "http://lhttp.qingting.fm/live/4885/64k.mp3", "isCollected": false},
                {"title": "南通音乐广播", "url": "http://lhttp.qingting.fm/live/21275/64k.mp3", "isCollected": false},
                {"title": "1003温州音乐之声", "url": "http://lhttp.qingting.fm/live/1149/64k.mp3", "isCollected": false},
                {"title": "济南音乐广播88.7", "url": "http://lhttp.qingting.fm/live/1671/64k.mp3", "isCollected": false},
                {"title": "就爱927 Love Radio", "url": "http://lhttp.qingting.fm/live/1831/64k.mp3", "isCollected": false},
                {"title": "AsiaFM 亚洲音乐台", "url": "http://lhttp.qingting.fm/live/5022405/64k.mp3", "isCollected": false},
                {"title": "89.3芒果音乐台", "url": "http://lhttp.qingting.fm/live/4979/64k.mp3", "isCollected": false},
                {"title": "亚洲音乐成都FM96.5", "url": "http://lhttp.qingting.fm/live/4581/64k.mp3", "isCollected": false},
                {"title": "1047 Nice FM", "url": "http://lhttp.qingting.fm/live/20033/64k.mp3", "isCollected": false},
                {"title": "常州音乐广播", "url": "http://lhttp.qingting.fm/live/2799/64k.mp3", "isCollected": false},
                {"title": "AsiaFM HD音乐台", "url": "http://lhttp.qingting.fm/live/15318341/64k.mp3", "isCollected": false},
                {"title": "FM102.2亲子智慧电台", "url": "http://lhttp.qingting.fm/live/4930/64k.mp3", "isCollected": false},
                {"title": "察布查尔FM99.5", "url": "http://lhttp.qingting.fm/live/5022610/64k.mp3", "isCollected": false},
                {"title": "包头汽车音乐广播", "url": "http://lhttp.qingting.fm/live/1892/64k.mp3", "isCollected": false},
                {"title": "吴江交通音乐广播", "url": "http://lhttp.qingting.fm/live/5022050/64k.mp3", "isCollected": false},
                {"title": "大连easy radio106.7", "url": "http://lhttp.qingting.fm/live/1084/64k.mp3", "isCollected": false},
                {"title": "青岛音乐体育广播", "url": "http://lhttp.qingting.fm/live/1677/64k.mp3", "isCollected": false},
                {"title": "唐山音乐广播", "url": "http://lhttp.qingting.fm/live/4871/64k.mp3", "isCollected": false},
                {"title": "贵州FM91.6音乐广播", "url": "http://lhttp.qingting.fm/live/20067/64k.mp3", "isCollected": false},
                {"title": "廊坊飞扬105", "url": "http://lhttp.qingting.fm/live/20211678/64k.mp3", "isCollected": false},
                {"title": "徐州音乐广播FM91.9", "url": "http://lhttp.qingting.fm/live/4923/64k.mp3", "isCollected": false},
                {"title": "江西潮台969", "url": "http://lhttp.qingting.fm/live/20500092/64k.mp3", "isCollected": false},
                {"title": "吉林市音乐广播", "url": "http://lhttp.qingting.fm/live/20211679/64k.mp3", "isCollected": false},
                {"title": "冰城1026哈尔滨古典音乐广播", "url": "http://lhttp.qingting.fm/live/5022338/64k.mp3", "isCollected": false},
                {"title": "台州音乐广播", "url": "http://lhttp.qingting.fm/live/1144/64k.mp3", "isCollected": false},
                {"title": "流行音乐广播999正青春", "url": "http://lhttp.qingting.fm/live/20211620/64k.mp3", "isCollected": false},
                {"title": "云南音乐广播", "url": "http://lhttp.qingting.fm/live/1929/64k.mp3", "isCollected": false},
                {"title": "宁波音乐广播私家车986", "url": "http://lhttp.qingting.fm/live/1142/64k.mp3", "isCollected": false},
                {"title": "宁夏音乐广播", "url": "http://lhttp.qingting.fm/live/15318294/64k.mp3", "isCollected": false},
                {"title": "安阳1008音乐广播", "url": "http://lhttp.qingting.fm/live/2123/64k.mp3", "isCollected": false},
                {"title": "海口WHIZRADIO音乐电台", "url": "http://lhttp.qingting.fm/live/20010/64k.mp3", "isCollected": false},
                {"title": "邯郸音乐广播", "url": "http://lhttp.qingting.fm/live/4601/64k.mp3", "isCollected": false},
                {"title": "沧州音乐广播FM103.6", "url": "http://lhttp.qingting.fm/live/5021902/64k.mp3", "isCollected": false},
                {"title": "FM93.0霸州汽车音乐广播", "url": "http://lhttp.qingting.fm/live/20211658/64k.mp3", "isCollected": false},
                {"title": "保定城市服务广播乐动1016", "url": "http://lhttp.qingting.fm/live/20406/64k.mp3", "isCollected": false},
                {"title": "潍坊982广播电台", "url": "http://lhttp.qingting.fm/live/4865/64k.mp3", "isCollected": false},
                {"title": "90后潮流音悦台", "url": "http://lhttp.qingting.fm/live/20207760/64k.mp3", "isCollected": false},
                {"title": "盛京FM105.6", "url": "http://lhttp.qingting.fm/live/5022520/64k.mp3", "isCollected": false},
                {"title": "100.7重庆永川之声", "url": "http://lhttp.qingting.fm/live/20210236/64k.mp3", "isCollected": false},
                {"title": "乌鲁木齐旅游音乐", "url": "http://lhttp.qingting.fm/live/1920/64k.mp3", "isCollected": false},
                {"title": "襄阳文化教育广播", "url": "http://lhttp.qingting.fm/live/5057/64k.mp3", "isCollected": false},
                {"title": "蚌埠广播电视台经典104.2", "url": "http://lhttp.qingting.fm/live/20152/64k.mp3", "isCollected": false},
                {"title": "新闻听天下", "url": "http://lhttp.qingting.fm/live/20500169/64k.mp3", "isCollected": false}
            ];

            // 保存电台数据到localStorage
            function saveRadioData(data) {
                localStorage.setItem('radioData', JSON.stringify(data));
                radioData = data;
            }

            // 获取电台数据
            function getRadioData() {
                return [...radioData];
            }

            // DOM元素
            const elements = {
                // 公共元素
                switchModeBtn: document.getElementById('switchModeBtn'),
                playerArea: document.getElementById('playerArea'),
                adminArea: document.getElementById('adminArea'),
                loginForm: document.getElementById('loginForm'),
                backToPlayer: document.getElementById('backToPlayer'),
                
                // 前台播放元素
                searchTrigger: document.getElementById('searchTrigger'),
                searchBox: document.getElementById('searchBox'),
                searchInput: document.getElementById('searchInput'),
                allRadioList: document.getElementById('allRadioList'),
                collectRadioList: document.getElementById('collectRadioList'),
                audioPlayer: document.getElementById('audioPlayer'),
                status: document.getElementById('status'),
                playPauseBtn: document.getElementById('playPauseBtn'),
                nextBtn: document.getElementById('nextBtn'),
                sequenceBtn: document.getElementById('sequenceBtn'),
                randomBtn: document.getElementById('randomBtn'),
                collectBtn: document.getElementById('collectBtn'),
                volumeSlider: document.getElementById('volumeSlider'),
                volumeIcon: document.getElementById('volumeIcon'),
                tabBtns: document.querySelectorAll('.tab-btn'),
                
                // 管理后台元素
                addRadioForm: document.getElementById('addRadioForm'),
                radioTitle: document.getElementById('radioTitle'),
                radioUrl: document.getElementById('radioUrl'),
                radioTableBody: document.getElementById('radioTableBody'),
                messageContainer: document.getElementById('messageContainer'),
                
                // 登录元素
                password: document.getElementById('password'),
                loginBtn: document.getElementById('loginBtn'),
                loginError: document.getElementById('loginError')
            };

            // 播放状态
            const state = {
                currentRadioIndex: -1,
                isPlaying: false,
                isMuted: false,
                playMode: 'sequence', // sequence 顺序播放, random 随机播放
                searchTerm: ''
            };

            // 前台播放功能
            // 渲染电台列表
            function renderRadioList(listElement, radios) {
                listElement.innerHTML = '';
                
                if (radios.length === 0) {
                    listElement.innerHTML = `
                        <li class="empty-tip">
                            <i class="fas fa-headphones"></i>
                            <p>没有找到电台</p>
                        </li>
                    `;
                    return;
                }
                
                radios.forEach((radio, index) => {
                    const li = document.createElement('li');
                    li.className = `radio-item ${state.currentRadioIndex === getRadioData().indexOf(radio) ? 'active' : ''}`;
                    li.innerHTML = `
                        <span>${radio.title}</span>
                        <i class="fas fa-heart collect-icon ${radio.isCollected ? 'active' : ''}" data-index="${getRadioData().indexOf(radio)}"></i>
                    `;
                    li.dataset.index = getRadioData().indexOf(radio);
                    listElement.appendChild(li);
                });

                // 添加收藏按钮事件
                document.querySelectorAll('.collect-icon').forEach(icon => {
                    icon.addEventListener('click', function(e) {
                        e.stopPropagation();
                        const index = parseInt(this.dataset.index);
                        toggleCollect(index);
                    });
                });
            }

            // 获取收藏的电台
            function getCollectData() {
                return getRadioData().filter(radio => radio.isCollected);
            }

            // 获取搜索过滤后的全部电台
            function getFilteredAllData() {
                if (!state.searchTerm) return getRadioData();
                return getRadioData().filter(radio => 
                    radio.title.toLowerCase().includes(state.searchTerm.toLowerCase())
                );
            }

            // 播放电台
            function playRadio(index) {
                const radio = getRadioData()[index];
                if (!radio) return;
                
                state.currentRadioIndex = index;
                elements.audioPlayer.src = radio.url;
                elements.audioPlayer.load();
                elements.audioPlayer.play();
                
                state.isPlaying = true;
                elements.playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>';
                elements.status.innerHTML = `正在播放: ${radio.title}`;
                
                // 更新收藏按钮状态
                updateCollectBtnState();
                
                // 更新列表激活状态
                renderRadioList(elements.allRadioList, getFilteredAllData());
                renderRadioList(elements.collectRadioList, getCollectData());
            }

            // 切换播放/暂停
            function togglePlayPause() {
                if (state.currentRadioIndex === -1) {
                    // 如果没有选中电台,默认播放第一个
                    if (getRadioData().length > 0) {
                        playRadio(0);
                    }
                    return;
                }
                
                if (state.isPlaying) {
                    elements.audioPlayer.pause();
                } else {
                    elements.audioPlayer.play();
                }
            }

            // 播放下一个电台
            function playNextRadio() {
                if (getRadioData().length === 0) return;
                
                let nextIndex;
                if (state.playMode === 'random') {
                    // 随机播放
                    nextIndex = Math.floor(Math.random() * getRadioData().length);
                } else {
                    // 顺序播放
                    nextIndex = (state.currentRadioIndex + 1) % getRadioData().length;
                }
                
                playRadio(nextIndex);
            }

            // 切换收藏状态
            function toggleCollect(index) {
                const radioData = getRadioData();
                radioData[index].isCollected = !radioData[index].isCollected;
                saveRadioData(radioData);
                
                // 更新列表
                renderRadioList(elements.allRadioList, getFilteredAllData());
                renderRadioList(elements.collectRadioList, getCollectData());
                
                // 如果当前播放的是这个电台,更新收藏按钮
                if (index === state.currentRadioIndex) {
                    updateCollectBtnState();
                }
                
                showMessage(radioData[index].isCollected ? 'success' : 'success', 
                    `${radioData[index].isCollected ? '收藏' : '取消收藏'}成功: ${radioData[index].title}`);
            }

            // 更新收藏按钮状态
            function updateCollectBtnState() {
                if (state.currentRadioIndex === -1) {
                    elements.collectBtn.classList.remove('active');
                    return;
                }
                
                const isCollected = getRadioData()[state.currentRadioIndex].isCollected;
                if (isCollected) {
                    elements.collectBtn.classList.add('active');
                } else {
                    elements.collectBtn.classList.remove('active');
                }
            }

            // 切换当前播放电台的收藏状态
            function toggleCurrentCollect() {
                if (state.currentRadioIndex === -1) return;
                toggleCollect(state.currentRadioIndex);
            }

            // 切换静音
            function toggleMute() {
                state.isMuted = !state.isMuted;
                elements.audioPlayer.muted = state.isMuted;
                updateVolumeIcon();
            }

            // 更新音量图标
            function updateVolumeIcon() {
                if (state.isMuted) {
                    elements.volumeIcon.className = 'fas fa-volume-mute volume-icon';
                    return;
                }
                
                const volume = elements.audioPlayer.volume;
                if (volume === 0) {
                    elements.volumeIcon.className = 'fas fa-volume-off volume-icon';
                } else if (volume < 0.5) {
                    elements.volumeIcon.className = 'fas fa-volume-down volume-icon';
                } else {
                    elements.volumeIcon.className = 'fas fa-volume-up volume-icon';
                }
            }

            // 切换播放模式
            function setPlayMode(mode) {
                state.playMode = mode;
                
                // 更新按钮状态
                elements.sequenceBtn.classList.remove('active-mode');
                elements.randomBtn.classList.remove('active-mode');
                
                if (mode === 'sequence') {
                    elements.sequenceBtn.classList.add('active-mode');
                } else if (mode === 'random') {
                    elements.randomBtn.classList.add('active-mode');
                }
            }

            // 切换搜索框显示/隐藏
            function toggleSearchBox() {
                elements.searchBox.classList.toggle('show');
                if (elements.searchBox.classList.contains('show')) {
                    elements.searchInput.focus();
                } else {
                    elements.searchInput.value = '';
                    state.searchTerm = '';
                    renderRadioList(elements.allRadioList, getFilteredAllData());
                }
            }

            // 关闭搜索框
            function closeSearchBox() {
                elements.searchBox.classList.remove('show');
                elements.searchInput.value = '';
                state.searchTerm = '';
                renderRadioList(elements.allRadioList, getFilteredAllData());
            }

            // 处理电台列表点击
            function handleRadioListClick(e) {
                const radioItem = e.target.closest('.radio-item');
                if (radioItem) {
                    const index = parseInt(radioItem.dataset.index);
                    playRadio(index);
                }
            }

            // 管理后台功能
            // 渲染管理后台的电台列表
            function renderAdminRadioList() {
                const radioData = getRadioData();
                elements.radioTableBody.innerHTML = '';
                
                radioData.forEach((radio, index) => {
                    const row = document.createElement('tr');
                    row.innerHTML = `
                        <td>${index + 1}</td>
                        <td>${radio.title}</td>
                        <td>${radio.url}</td>
                        <td>
                            <div class="action-buttons">
                                <button class="btn delete-btn" data-index="${index}">
                                    <i class="fas fa-trash"></i>
                                    删除
                                </button>
                            </div>
                        </td>
                    `;
                    elements.radioTableBody.appendChild(row);
                });

                // 添加删除按钮事件监听
                document.querySelectorAll('.delete-btn').forEach(btn => {
                    btn.addEventListener('click', function() {
                        const index = parseInt(this.dataset.index);
                        deleteRadio(index);
                    });
                });
            }

            // 删除电台
            function deleteRadio(index) {
                if (confirm('确定要删除这个电台吗?')) {
                    const radioData = getRadioData();
                    const deletedRadio = radioData.splice(index, 1)[0];
                    saveRadioData(radioData);
                    renderAdminRadioList();
                    
                    // 如果删除的是当前播放的电台
                    if (index === state.currentRadioIndex) {
                        state.currentRadioIndex = -1;
                        elements.audioPlayer.src = '';
                        elements.status.innerHTML = '请选择下方电台开始播放';
                        elements.playPauseBtn.innerHTML = '<i class="fas fa-play"></i>';
                        state.isPlaying = false;
                    } else if (index < state.currentRadioIndex) {
                        // 如果删除的是当前播放电台之前的电台,调整索引
                        state.currentRadioIndex--;
                    }
                    
                    // 更新前台列表
                    renderRadioList(elements.allRadioList, getFilteredAllData());
                    renderRadioList(elements.collectRadioList, getCollectData());
                    
                    showMessage('success', `成功删除电台:${deletedRadio.title}`);
                }
            }

            // 添加电台
            function addRadio(e) {
                e.preventDefault();
                
                const title = elements.radioTitle.value.trim();
                const url = elements.radioUrl.value.trim();
                
                if (!title || !url) {
                    showMessage('error', '请填写完整的电台信息');
                    return;
                }

                // 验证URL格式
                try {
                    new URL(url);
                } catch (error) {
                    showMessage('error', '请输入有效的URL地址');
                    return;
                }

                const radioData = getRadioData();
                
                // 检查是否已存在相同URL的电台
                if (radioData.some(radio => radio.url === url)) {
                    showMessage('error', '该电台URL已存在');
                    return;
                }

                // 添加新电台
                radioData.push({
                    title: title,
                    url: url,
                    isCollected: false
                });

                saveRadioData(radioData);
                renderAdminRadioList();
                renderRadioList(elements.allRadioList, getFilteredAllData());
                
                // 清空表单
                elements.radioTitle.value = '';
                elements.radioUrl.value = '';
                
                showMessage('success', `成功添加电台:${title}`);
            }

            // 登录验证
            function login() {
                const password = elements.password.value.trim();
                
                if (password === ADMIN_PASSWORD) {
                    // 登录成功
                    isAdminLoggedIn = true;
                    elements.loginForm.classList.add('hidden');
                    elements.adminArea.classList.remove('hidden');
                    renderAdminRadioList();
                } else {
                    // 登录失败
                    elements.loginError.style.display = 'block';
                    setTimeout(() => {
                        elements.loginError.style.display = 'none';
                    }, 3000);
                }
            }

            // 显示消息提示
            function showMessage(type, text) {
                const message = document.createElement('div');
                message.className = `message ${type}`;
                message.innerHTML = `
                    <i class="fas ${type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'}"></i>
                    <span>${text}</span>
                `;
                
                elements.messageContainer.appendChild(message);
                
                // 3秒后自动移除消息
                setTimeout(() => {
                    message.style.opacity = '0';
                    message.style.transform = 'translateY(-10px)';
                    message.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
                    setTimeout(() => {
                        message.remove();
                    }, 300);
                }, 3000);
            }

            // 切换模式(前台/管理)
            function switchMode() {
                if (elements.playerArea.classList.contains('hidden')) {
                    // 切换到前台播放模式
                    elements.playerArea.classList.remove('hidden');
                    elements.adminArea.classList.add('hidden');
                    elements.loginForm.classList.add('hidden');
                    elements.switchModeBtn.innerHTML = '<i class="fas fa-cog"></i> 切换到管理模式';
                } else {
                    // 切换到管理模式
                    elements.playerArea.classList.add('hidden');
                    if (isAdminLoggedIn) {
                        elements.adminArea.classList.remove('hidden');
                        elements.loginForm.classList.add('hidden');
                    } else {
                        elements.adminArea.classList.add('hidden');
                        elements.loginForm.classList.remove('hidden');
                        elements.password.value = '';
                        elements.loginError.style.display = 'none';
                    }
                    elements.switchModeBtn.innerHTML = '<i class="fas fa-music"></i> 切换到播放模式';
                }
            }

            // 初始化事件监听
            function initEventListeners() {
                // 前台播放事件
                elements.playPauseBtn.addEventListener('click', togglePlayPause);
                elements.nextBtn.addEventListener('click', playNextRadio);
                elements.sequenceBtn.addEventListener('click', () => setPlayMode('sequence'));
                elements.randomBtn.addEventListener('click', () => setPlayMode('random'));
                elements.collectBtn.addEventListener('click', toggleCurrentCollect);
                
                elements.volumeSlider.addEventListener('input', function() {
                    elements.audioPlayer.volume = this.value;
                    state.isMuted = false;
                    updateVolumeIcon();
                });
                
                elements.volumeIcon.addEventListener('click', toggleMute);
                
                elements.audioPlayer.addEventListener('play', () => {
                    state.isPlaying = true;
                    elements.playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>';
                });
                
                elements.audioPlayer.addEventListener('pause', () => {
                    state.isPlaying = false;
                    elements.playPauseBtn.innerHTML = '<i class="fas fa-play"></i>';
                });
                
                elements.audioPlayer.addEventListener('volumechange', updateVolumeIcon);
                
                // 列表点击事件委托
                elements.allRadioList.addEventListener('click', handleRadioListClick);
                elements.collectRadioList.addEventListener('click', handleRadioListClick);
                
                // 搜索相关事件
                elements.searchTrigger.addEventListener('click', toggleSearchBox);
                elements.searchInput.addEventListener('input', function() {
                    state.searchTerm = this.value;
                    renderRadioList(elements.allRadioList, getFilteredAllData());
                });
                
                // 点击页面其他区域关闭搜索框
                document.addEventListener('click', function(e) {
                    if (!elements.searchBox.contains(e.target) && !elements.searchTrigger.contains(e.target)) {
                        closeSearchBox();
                    }
                });
                
                // 标签切换事件
                elements.tabBtns.forEach(btn => {
                    btn.addEventListener('click', function() {
                        elements.tabBtns.forEach(b => b.classList.remove('active'));
                        this.classList.add('active');
                        
                        const tab = this.dataset.tab;
                        document.querySelectorAll('.radio-list').forEach(list => {
                            list.classList.remove('active');
                        });
                        document.getElementById(`${tab}RadioList`).classList.add('active');
                    });
                });
                
                // 键盘快捷键
                document.addEventListener('keydown', function(e) {
                    // 避免在输入框中触发快捷键
                    if (e.target.tagName === 'INPUT') return;

                    switch(e.code) {
                        case 'Space':
                            e.preventDefault();
                            togglePlayPause();
                            break;
                        case 'ArrowRight':
                            e.preventDefault();
                            playNextRadio();
                            break;
                        case 'KeyF':
                            e.preventDefault();
                            toggleCurrentCollect();
                            break;
                        case 'KeyM':
                            e.preventDefault();
                            toggleMute();
                            break;
                        case 'KeyS':
                            e.preventDefault();
                            toggleSearchBox();
                            break;
                        case 'Escape':
                            e.preventDefault();
                            closeSearchBox();
                            break;
                    }
                });
                
                // 管理后台事件
                elements.addRadioForm.addEventListener('submit', addRadio);
                elements.loginBtn.addEventListener('click', login);
                elements.password.addEventListener('keypress', function(e) {
                    if (e.key === 'Enter') {
                        login();
                    }
                });
                elements.backToPlayer.addEventListener('click', switchMode);
                elements.switchModeBtn.addEventListener('click', switchMode);
            }

            // 页面初始化
            function init() {
                renderRadioList(elements.allRadioList, getFilteredAllData());
                renderRadioList(elements.collectRadioList, getCollectData());
                elements.audioPlayer.volume = elements.volumeSlider.value;
                elements.sequenceBtn.classList.add('active-mode');
                updateVolumeIcon();
                initEventListeners();
            }

            // 页面加载完成后初始化
            window.addEventListener('load', init);
        })();
    </script>
</body>
</html>
个人FM电台源代码
https://www.ifmo.cn/index.php/archives/132.html
本文作者 辣条
发布时间 2025-12-08
许可协议 CC BY-NC-SA 4.0
发表新评论
    < 总访问:-- < 今日:--