风萧 发表于 4 天前

[十八岁太奶奶驾到,重整家族荣耀][第二季全集]

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Discuz M3U8 分集播放器</title>
    <!-- 引入 TailwindCSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <script>
      tailwind.config = {
      corePlugins: {
      preflight: false, // 关闭Tailwind的全局重置样式,避免覆盖Discuz原有页面样式
                     }
      }
    </script>
    <!-- 引入 Font Awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <!-- 引入 Hls.js -->
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest/dist/hls.min.js"></script>
    <style>
      /* 自定义滚动条样式 */
      .episode-scroll::-webkit-scrollbar {
            width: 6px;
            height: 6px;
      }
      .episode-scroll::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 3px;
      }
      .episode-scroll::-webkit-scrollbar-thumb {
            background: #cbd5e1;
            border-radius: 3px;
      }
      .episode-scroll::-webkit-scrollbar-thumb:hover {
            background: #94a3b8;
      }
      /* 选中状态动画 */
      .episode-btn.active {
            background-color: #3b82f6;
            color: white;
            border-color: #3b82f6;
      }
      /* 加载动画 */
      .loader {
            border: 3px solid #f3f3f3;
            border-radius: 50%;
            border-top: 3px solid #3b82f6;
            width: 24px;
            height: 24px;
            -webkit-animation: spin 1s linear infinite; /* Safari */
            animation: spin 1s linear infinite;
      }
      @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
      }
    </style>
</head>
<body class="bg-gray-100 p-4 font-sans">

    <!-- 播放器容器 -->
    <div id="dz-video-player-container" class="max-w-4xl mx-auto bg-white rounded-xl shadow-lg overflow-hidden border border-gray-200" style="isolation: isolate;">
      
      <!-- 视频区域 -->
      <div class="relative w-full aspect-video bg-black group">
            <video id="dz-video-element" class="w-full h-full object-contain" controls playsinline poster="/data/attachment/album/202608/31/200711vfnhzq7opn8dqp00.jpg"></video>
            
            <!-- 加载指示器 -->
            <div id="dz-loading-indicator" class="absolute inset-0 flex items-center justify-center bg-black/50 hidden z-10">
                <div class="loader"></div>
            </div>

            <!-- 错误提示层 -->
            <div id="dz-error-overlay" class="absolute inset-0 flex flex-col items-center justify-center bg-black/80 text-white hidden z-20">
                <i class="fas fa-exclamation-triangle text-4xl mb-2 text-red-500"></i>
                <p class="text-sm">视频加载失败,请检查网络或链接有效性</p>
                <button onclick="retryLoad()" class="mt-4 px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded text-sm transition">重试</button>
            </div>
      </div>

      <!-- 控制面板:标题与分集 -->
      <div class="p-4 bg-white">
            <div class="flex justify-between items-center mb-4 border-b pb-2">
                <h2 id="dz-video-title" class="text-lg font-bold text-gray-800 truncate pr-4">正在播放:第 1 集</h2>
                <!-- div class="text-xs text-gray-500 flex items-center gap-2">
                  <span id="dz-quality-badge" class="px-2 py-1 bg-gray-100 rounded text-gray-600">HD</span>
                  <span id="dz-duration">00:00</span>
                </div -->
            </div>

            <!-- 分集列表 -->
            <div class="mb-2 flex justify-between items-center">
                <span class="text-sm font-semibold text-gray-700"><i class="fas fa-list-ul mr-1"></i> 选集</span>
                <div class="flex gap-2">
                     <button onclick="toggleOrder()" class="text-xs text-blue-600 hover:text-blue-800 flex items-center gap-1">
                        <i class="fas fa-sort-amount-down" id="sort-icon"></i> <span id="sort-text">倒序</span>
                  </button>
                </div>
            </div>
            
            <div id="dz-episode-list" class="grid grid-cols-4 sm:grid-cols-6 md:grid-cols-8 gap-2 max-h-40 overflow-y-auto episode-scroll p-1">
                <!-- 分集按钮将通过 JS 动态生成 -->
            </div>
      </div>
    </div>

    <script>
      /**
         * Discuz M3U8 Player Configuration
         * 在 Discuz 发帖时,只需修改此处的 videoData 数组即可
         */
      const videoData = [
            { title: "第01集", url: "https://v.lzcdn24.com/20250826/41375_fb54f688/2000k/hls/mixed.m3u8"},
            { title: "第02集", url: "https://v.lzcdn24.com/20250826/41379_b1548d61/2000k/hls/mixed.m3u8"},
            { title: "第03集", url: "https://v.lzcdn24.com/20250826/41378_9aae9ba2/2000k/hls/mixed.m3u8"},
            { title: "第04集", url: "https://v.lzcdn24.com/20250826/41376_223b9ae4/2000k/hls/mixed.m3u8"},
            { title: "第05集", url: "https://v.lzcdn24.com/20250826/41377_20f8a2f5/2000k/hls/mixed.m3u8"},
            { title: "第06集", url: "https://v.lzcdn24.com/20250826/41374_41af246d/2000k/hls/mixed.m3u8"},
            { title: "第07集", url: "https://v.lzcdn24.com/20250826/41382_d163bc52/2000k/hls/mixed.m3u8"},
            { title: "第08集", url: "https://v.lzcdn24.com/20250826/41381_16a769f5/2000k/hls/mixed.m3u8"},
            { title: "第09集", url: "https://v.lzcdn24.com/20250826/41380_c9647129/2000k/hls/mixed.m3u8"},
            { title: "第10集", url: "https://v.lzcdn24.com/20250826/41385_fe7c1859/2000k/hls/mixed.m3u8"},
            { title: "第11集", url: "https://v.lzcdn24.com/20250826/41383_125bda2a/2000k/hls/mixed.m3u8"},
            { title: "第12集", url: "https://v.lzcdn24.com/20250826/41384_e05fc6e5/2000k/hls/mixed.m3u8"},
            { title: "第13集", url: "https://v.lzcdn24.com/20250826/41387_c7eb6541/2000k/hls/mixed.m3u8"},
            { title: "第14集", url: "https://v.lzcdn24.com/20250826/41391_cc566c64/2000k/hls/mixed.m3u8"},
            { title: "第15集", url: "https://v.lzcdn24.com/20250826/41389_1b9507ea/2000k/hls/mixed.m3u8"},
            { title: "第16集", url: "https://v.lzcdn24.com/20250826/41390_ae5ea1ac/2000k/hls/mixed.m3u8"},
            { title: "第17集", url: "https://v.lzcdn24.com/20250826/41386_d22707bc/2000k/hls/mixed.m3u8"},
            { title: "第18集", url: "https://v.lzcdn24.com/20250826/41388_68ee1936/2000k/hls/mixed.m3u8"},
            { title: "第19集", url: "https://v.lzcdn24.com/20250826/41393_84818466/2000k/hls/mixed.m3u8"},
            { title: "第20集", url: "https://v.lzcdn24.com/20250826/41394_62a4ad59/2000k/hls/mixed.m3u8"},
            { title: "第21集", url: "https://v.lzcdn24.com/20250826/41397_c26d5dfb/2000k/hls/mixed.m3u8"},
            { title: "第22集", url: "https://v.lzcdn24.com/20250826/41395_beb4409f/2000k/hls/mixed.m3u8"},
            { title: "第23集", url: "https://v.lzcdn24.com/20250826/41392_f6e714e9/2000k/hls/mixed.m3u8"},
            { title: "第24集", url: "https://v.lzcdn24.com/20250826/41396_1bdddbe7/2000k/hls/mixed.m3u8"},
            { title: "第25集", url: "https://v.lzcdn24.com/20250826/41399_392b47e6/2000k/hls/mixed.m3u8"},
            { title: "第26集", url: "https://v.lzcdn24.com/20250826/41398_4f493611/2000k/hls/mixed.m3u8"},
            { title: "第27集", url: "https://v.lzcdn24.com/20250826/41401_1370e073/2000k/hls/mixed.m3u8"},
            { title: "第28集", url: "https://v.lzcdn24.com/20250826/41400_a51c2ddc/2000k/hls/mixed.m3u8"},
            { title: "第29集", url: "https://v.lzcdn24.com/20250826/41402_f502bb97/2000k/hls/mixed.m3u8"},
            { title: "第30集", url: "https://v.lzcdn24.com/20250826/41403_74e88aa3/2000k/hls/mixed.m3u8"},
            { title: "第31集", url: "https://v.lzcdn24.com/20250826/41405_2e86f955/2000k/hls/mixed.m3u8"},
            { title: "第32集", url: "https://v.lzcdn24.com/20250826/41406_4c4a594e/2000k/hls/mixed.m3u8"},
            { title: "第33集", url: "https://v.lzcdn24.com/20250826/41407_eb647699/2000k/hls/mixed.m3u8"},
            { title: "第34集", url: "https://v.lzcdn24.com/20250826/41404_352a1393/2000k/hls/mixed.m3u8"},
            { title: "第35集", url: "https://v.lzcdn24.com/20250826/41409_86eec164/2000k/hls/mixed.m3u8"},
            { title: "第36集", url: "https://v.lzcdn24.com/20250826/41408_f4db06a0/2000k/hls/mixed.m3u8"},
            { title: "第37集", url: "https://v.lzcdn24.com/20250826/41410_90e8c1d4/2000k/hls/mixed.m3u8"},
            { title: "第38集", url: "https://v.lzcdn24.com/20250826/41411_fdacd051/2000k/hls/mixed.m3u8"},
            { title: "第39集", url: "https://v.lzcdn24.com/20250826/41412_c237618e/2000k/hls/mixed.m3u8"},
            { title: "第40集", url: "https://v.lzcdn24.com/20250826/41413_94d8df16/2000k/hls/mixed.m3u8"},
            { title: "第41集", url: "https://v.lzcdn24.com/20250826/41416_c52bb8a9/2000k/hls/mixed.m3u8"},
            { title: "第42集", url: "https://v.lzcdn24.com/20250826/41415_46fe0239/2000k/hls/mixed.m3u8"},
            { title: "第43集", url: "https://v.lzcdn24.com/20250826/41417_447f63c5/2000k/hls/mixed.m3u8"},
            { title: "第44集", url: "https://v.lzcdn24.com/20250826/41414_307683a0/2000k/hls/mixed.m3u8"},
            { title: "第45集", url: "https://v.lzcdn24.com/20250826/41419_302b755e/2000k/hls/mixed.m3u8"},
            { title: "第46集", url: "https://v.lzcdn24.com/20250826/41418_55fa04a1/2000k/hls/mixed.m3u8"},
            { title: "第47集", url: "https://v.lzcdn24.com/20250826/41424_1fa4e0ed/2000k/hls/mixed.m3u8"},
            { title: "第48集", url: "https://v.lzcdn24.com/20250826/41423_0b2ead2e/2000k/hls/mixed.m3u8"},
          { title: "第49集", url: "https://v.lzcdn24.com/20250826/41421_965f9823/2000k/hls/mixed.m3u8"},
          { title: "第50集", url: "https://v.lzcdn24.com/20250826/41422_750ab9e0/2000k/hls/mixed.m3u8"},
          { title: "第51集", url: "https://v.lzcdn24.com/20250826/41420_997e84c2/2000k/hls/mixed.m3u8"},
          { title: "第52集", url: "https://v.lzcdn24.com/20250826/41425_83309efa/2000k/hls/mixed.m3u8"},
          { title: "第53集", url: "https://v.lzcdn24.com/20250826/41426_5fa362aa/2000k/hls/mixed.m3u8"},
          { title: "第54集", url: "https://v.lzcdn24.com/20250826/41427_08e38092/2000k/hls/mixed.m3u8"},
          { title: "第55集", url: "https://v.lzcdn24.com/20250826/41428_040cc5a1/2000k/hls/mixed.m3u8"},
          { title: "第56集", url: "https://v.lzcdn24.com/20250826/41429_837df459/2000k/hls/mixed.m3u8"},
          { title: "第57集", url: "https://v.lzcdn24.com/20250826/41430_473b8b96/2000k/hls/mixed.m3u8"},
          { title: "第58集", url: "https://v.lzcdn24.com/20250826/41431_c084b562/2000k/hls/mixed.m3u8"},
          { title: "第59集", url: "https://v.lzcdn24.com/20250826/41435_cecf2547/2000k/hls/mixed.m3u8"},
          { title: "第60集", url: "https://v.lzcdn24.com/20250826/41432_816f0f47/2000k/hls/mixed.m3u8"},
          { title: "第61集", url: "https://v.lzcdn24.com/20250826/41434_5938c4b1/2000k/hls/mixed.m3u8"},
          { title: "第62集", url: "https://v.lzcdn24.com/20250826/41433_c51f49b7/2000k/hls/mixed.m3u8"},
          { title: "第63集", url: "https://v.lzcdn24.com/20250826/41436_04a85442/2000k/hls/mixed.m3u8"},
          { title: "第64集", url: "https://v.lzcdn24.com/20250826/41441_ed4cf29a/2000k/hls/mixed.m3u8"},
          { title: "第65集", url: "https://v.lzcdn24.com/20250826/41442_81c5d2ca/2000k/hls/mixed.m3u8"},
          { title: "第66集", url: "https://v.lzcdn24.com/20250826/41438_7ba23096/2000k/hls/mixed.m3u8"},
          { title: "第67集", url: "https://v.lzcdn24.com/20250826/41437_0890f24c/2000k/hls/mixed.m3u8"},
          { title: "第68集", url: "https://v.lzcdn24.com/20250826/41439_d43f447c/2000k/hls/mixed.m3u8"},
          { title: "第69集", url: "https://v.lzcdn24.com/20250826/41440_0a4b803d/2000k/hls/mixed.m3u8"},
          { title: "第70集", url: "https://v.lzcdn24.com/20250826/41445_06ab1680/2000k/hls/mixed.m3u8"},
          { title: "第71集", url: "https://v.lzcdn24.com/20250826/41444_fbc685c5/2000k/hls/mixed.m3u8"},
          { title: "第72集", url: "https://v.lzcdn24.com/20250826/41443_4b7e2053/2000k/hls/mixed.m3u8"},
          { title: "第73集", url: "https://v.lzcdn24.com/20250826/41446_19255e17/2000k/hls/mixed.m3u8"},
          { title: "第74集", url: "https://v.lzcdn24.com/20250826/41447_21a8c1f5/2000k/hls/mixed.m3u8"},
          { title: "第75集", url: "https://v.lzcdn24.com/20250826/41448_0561073f/2000k/hls/mixed.m3u8"},
          { title: "第76集", url: "https://v.lzcdn24.com/20250826/41450_eb8f2515/2000k/hls/mixed.m3u8"},
          { title: "第77集", url: "https://v.lzcdn24.com/20250826/41449_96cddc0c/2000k/hls/mixed.m3u8"},
          { title: "第78集", url: "https://v.lzcdn24.com/20250826/41451_e44d5cb4/2000k/hls/mixed.m3u8"},
          { title: "第79集", url: "https://v.lzcdn24.com/20250826/41452_dd54950f/2000k/hls/mixed.m3u8"},
          { title: "第80集", url: "https://v.lzcdn24.com/20250826/41454_56ded0a7/2000k/hls/mixed.m3u8"},
          { title: "第81集", url: "https://v.lzcdn24.com/20250826/41453_eab85d15/2000k/hls/mixed.m3u8"},
          { title: "第82集", url: "https://v.lzcdn24.com/20250826/41456_e838b35e/2000k/hls/mixed.m3u8"},
          { title: "第83集", url: "https://v.lzcdn24.com/20250826/41458_edc061bd/2000k/hls/mixed.m3u8"},
          { title: "第84集", url: "https://v.lzcdn24.com/20250826/41457_47c5463d/2000k/hls/mixed.m3u8"},
          { title: "第85集", url: "https://v.lzcdn24.com/20250826/41455_f057f799/2000k/hls/mixed.m3u8"},
          { title: "第86集", url: "https://v.lzcdn24.com/20250826/41459_9d38f752/2000k/hls/mixed.m3u8"},
          { title: "第87集", url: "https://v.lzcdn24.com/20250826/41460_4c55b3d3/2000k/hls/mixed.m3u8"},
          { title: "第88集", url: "https://v.lzcdn24.com/20250826/41461_d70b1aa7/2000k/hls/mixed.m3u8"},
          { title: "第89集", url: "https://v.lzcdn24.com/20250826/41463_44a9222c/2000k/hls/mixed.m3u8"},
          { title: "第90集", url: "https://v.lzcdn24.com/20250826/41462_515a2290/2000k/hls/mixed.m3u8"},
          { title: "第91集", url: "https://v.lzcdn24.com/20250826/41465_148c1554/2000k/hls/mixed.m3u8"},
          { title: "第92集", url: "https://v.lzcdn24.com/20250826/41464_e9b97bcf/2000k/hls/mixed.m3u8"},
          { title: "第93集", url: "https://v.lzcdn24.com/20250826/41467_e551534f/2000k/hls/mixed.m3u8"},
          { title: "第94集", url: "https://v.lzcdn24.com/20250826/41468_7bb0e554/2000k/hls/mixed.m3u8"},
          { title: "第95集", url: "https://v.lzcdn24.com/20250826/41466_67a2d34c/2000k/hls/mixed.m3u8"},
          { title: "第96集", url: "https://v.lzcdn24.com/20250826/41471_8103a416/2000k/hls/mixed.m3u8"},
          { title: "第97集", url: "https://v.lzcdn24.com/20250826/41469_0a86cf3c/2000k/hls/mixed.m3u8"},
          { title: "第98集", url: "https://v.lzcdn24.com/20250826/41470_973ec85a/2000k/hls/mixed.m3u8"},
          { title: "第99集", url: "https://v.lzcdn24.com/20250826/41473_f5a8f20e/2000k/hls/mixed.m3u8"},
          { title: "第100集", url: "https://v.lzcdn24.com/20250826/41472_ca20d614/2000k/hls/mixed.m3u8"}
      ];

      // 全局变量
      let hls = null;
      let currentEpisodeIndex = 0;
      let isReversed = false;
      let displayedData = [...videoData];
      const videoElement = document.getElementById('dz-video-element');
      const episodeListContainer = document.getElementById('dz-episode-list');
      const loadingIndicator = document.getElementById('dz-loading-indicator');
      const errorOverlay = document.getElementById('dz-error-overlay');
      const titleElement = document.getElementById('dz-video-title');
      const durationElement = document.getElementById('dz-duration');

      /**
         * 初始化播放器
         */
      function initPlayer() {
            renderEpisodes();
            loadEpisode(0); // 默认加载第一集
            
            // 监听视频元数据加载完成,更新时长显示
            videoElement.addEventListener('loadedmetadata', () => {
                durationElement.innerText = formatTime(videoElement.duration);
            });

            // 监听播放结束,自动下一集
            videoElement.addEventListener('ended', () => {
                playNext();
            });
      }

      /**
         * 渲染分集列表
         */
      function renderEpisodes() {
            episodeListContainer.innerHTML = '';
            displayedData.forEach((item, index) => {
                // 找到原始数据中的真实索引,用于点击事件
                const originalIndex = videoData.indexOf(item);
               
                const btn = document.createElement('button');
                btn.className = `episode-btn px-3 py-2 text-xs font-medium rounded border border-gray-200 text-gray-700 hover:bg-blue-50 hover:border-blue-200 transition-all truncate ${originalIndex === currentEpisodeIndex ? 'active' : ''}`;
                btn.innerText = item.title;
                btn.onclick = () => loadEpisode(originalIndex);
                episodeListContainer.appendChild(btn);
            });
      }

      /**
         * 加载指定集数
         * @param {number} index - 原始数据数组中的索引
         */
      function loadEpisode(index) {
            if (index < 0 || index >= videoData.length) return;

            currentEpisodeIndex = index;
            const data = videoData;
            
            // 更新UI状态
            updateActiveButton();
            titleElement.innerText = `正在播放:${data.title}`;
            showLoading(true);
            hideError();

            // 销毁旧的 HLS 实例
            if (hls) {
                hls.destroy();
            }

            // 创建新的 HLS 实例
            if (Hls.isSupported()) {
                hls = new Hls({
                  debug: false,
                  enableWorker: true,
                  lowLatencyMode: true,
                  backBufferLength: 90
                });

                hls.loadSource(data.url);
                hls.attachMedia(videoElement);

                hls.on(Hls.Events.MANIFEST_PARSED, function() {
                  videoElement.play().catch(e => console.log("Auto-play prevented:", e));
                  showLoading(false);
                });

                hls.on(Hls.Events.ERROR, function(event, data) {
                  if (data.fatal) {
                        switch(data.type) {
                            case Hls.ErrorTypes.NETWORK_ERROR:
                              console.log("fatal network error encountered, try to recover");
                              hls.startLoad();
                              break;
                            case Hls.ErrorTypes.MEDIA_ERROR:
                              console.log("fatal media error encountered, try to recover");
                              hls.recoverMediaError();
                              break;
                            default:
                              showError();
                              hls.destroy();
                              break;
                        }
                  }
                });

            } else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
                // Safari 原生支持
                videoElement.src = data.url;
                videoElement.addEventListener('loadedmetadata', function() {
                  videoElement.play();
                  showLoading(false);
                });
            } else {
                showError();
            }
      }

      /**
         * 更新按钮激活状态
         */
      function updateActiveButton() {
            const buttons = episodeListContainer.querySelectorAll('.episode-btn');
            buttons.forEach((btn, idx) => {
                // 注意:displayedData 可能是反转的,所以需要比对内容或重新映射
                // 这里简单起见,我们重新渲染或者通过文本匹配,但更优解是重新渲染
                // 为了性能,我们直接重新渲染整个列表是最安全的,因为列表通常不长
                renderEpisodes();
            });
      }

      /**
         * 播放下一集
         */
      function playNext() {
            if (currentEpisodeIndex < videoData.length - 1) {
                loadEpisode(currentEpisodeIndex + 1);
                // 滚动到当前选中的按钮
                setTimeout(() => {
                  const activeBtn = document.querySelector('.episode-btn.active');
                  if(activeBtn) activeBtn.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                }, 100);
            }
      }

      /**
         * 切换排序(正序/倒序)
         */
      function toggleOrder() {
            isReversed = !isReversed;
            const sortIcon = document.getElementById('sort-icon');
            const sortText = document.getElementById('sort-text');
            
            if (isReversed) {
                displayedData = [...videoData].reverse();
                sortIcon.className = "fas fa-sort-amount-up";
                sortText.innerText = "正序";
            } else {
                displayedData = [...videoData];
                sortIcon.className = "fas fa-sort-amount-down";
                sortText.innerText = "倒序";
            }
            renderEpisodes();
      }

      /**
         * 重试加载
         */
      function retryLoad() {
            loadEpisode(currentEpisodeIndex);
      }

      /**
         * UI 辅助函数
         */
      function showLoading(show) {
            loadingIndicator.classList.toggle('hidden', !show);
      }

      function showError() {
            errorOverlay.classList.remove('hidden');
            showLoading(false);
      }

      function hideError() {
            errorOverlay.classList.add('hidden');
      }

      function formatTime(seconds) {
            if (isNaN(seconds)) return "00:00";
            const m = Math.floor(seconds / 60);
            const s = Math.floor(seconds % 60);
            return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
      }

      // 启动
      document.addEventListener('DOMContentLoaded', initPlayer);

    </script>
</body>
</html>
页: [1]
查看完整版本: [十八岁太奶奶驾到,重整家族荣耀][第二季全集]