文章详情

返回首页

CF搭建视频播放带密码登录

分享文章 作者: Ws01 创建时间: 2025-11-24 📝 字数: 18,925 字 👁️ 阅读: 14 次
export default { async fetch(request, env, ctx) { // 设置CORS头 const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }; // 处理预检请求 if (request.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } const url = new URL(request.url); // 登录逻辑 if (url.pathname === '/login' && request.method === 'POST') { const formData = await request.formData(); const password = formData.get('password'); const adminPassword = env.ADMIN_PASSWORD || 'admin123'; // 从环境变量读取密码,默认为admin123 if (password === adminPassword) { // 登录成功,设置 Cookie return new Response('', { status: 302, headers: { 'Set-Cookie': `auth=1; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`, 'Location': '/' } }); } else { return new Response(this.renderLoginPage('密码错误,请重试!'), { headers: { 'Content-Type': 'text/html;charset=utf-8', ...corsHeaders } }); } } // 退出逻辑 if (url.pathname === '/logout') { return new Response('', { status: 302, headers: { 'Set-Cookie': `auth=; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=0`, 'Location': '/' } }); } // 检查是否已登录 const cookie = request.headers.get('Cookie') || ''; if (!cookie.includes('auth=1')) { return new Response(this.renderLoginPage(), { headers: { 'Content-Type': 'text/html;charset=utf-8', ...corsHeaders } }); } // 读取视频列表文件 let links = []; let randomLink = ''; try { const videoList1 = await fetch('https://img.boke.us.to/config/9527qita/video-list.txt'); const videoList2 = await fetch('https://img.boke.us.to/config/9527qita/video-list.txt'); const links1 = (await videoList1.text()).split('\n').filter(line => line.trim() !== ''); const links2 = (await videoList2.text()).split('\n').filter(line => line.trim() !== ''); // 合并两个文件的内容 links = [...links1, ...links2]; // 检查文件是否为空 if (links.length === 0) { return new Response('链接文件为空或未找到!', { status: 500, headers: { 'Content-Type': 'text/html;charset=utf-8' } }); } // 默认选择第一个链接 randomLink = links[0]; } catch (error) { // 如果获取视频列表失败,使用默认视频 console.error('获取视频列表失败:', error); links = ['https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_1mb.mp4|测试视频']; randomLink = links[0]; } // 生成 HTML 内容 const htmlContent = ` <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>自动随机播放 MP4 视频</title> <link rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2280%22>💠</text></svg>"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> <style> body { margin: 0; padding: 0; height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #f0f0f0; font-family: Arial, sans-serif; flex-direction: column; } /* 按钮样式 */ #playPauseBtn, #prevBtn, #nextBtn, #togglePlaylistBtn { background-color: black; color: white; border: none; padding: 10px 20px; margin: 5px; cursor: pointer; border-radius: 5px; transition: background-color 0.3s ease; } /* 按钮悬停效果 */ #playPauseBtn:hover, #prevBtn:hover, #nextBtn:hover, #togglePlaylistBtn:hover { background-color: #333; } .sites { width: 640px; background: #F2F2F2; border: 1px solid rgba(0,0,0,.01); margin: 15px auto; padding: 0; } /* 居中对齐容器 */ .video-container { display: flex; justify-content: center; align-items: center; margin: -0cm 0 0 0; } /* 标题下移 */ h2 { text-align: center; margin-bottom: 1cm; } /* 播放列表样式 */ .playlist { list-style-type: none; padding: 0; margin: 10px 0 0 0; width:638px; max-height: 162px; overflow-y: auto; text-align: left; border: 1px solid #ccc; background-color: #F2F2F2; } .playlist li { margin: 5px 0; cursor: pointer; color: #000000; font-size: 15px; text-decoration: underline; transition: color 0.3s ease; } .playlist li:hover { color: green; } /* 定义正在播放的样式 */ .playlist li.playing { color: red !important; font-weight: bold; } </style> </head> <body> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1cm;"> <h2 style="margin: 0;">自动随机播放 MP4 视频</h2> <a href="/logout" style="color: #666; text-decoration: none; padding: 8px 12px; border-radius: 6px; transition: all 0.2s; background-color: rgba(0,0,0,0.1);" onmouseover="this.style.backgroundColor='rgba(0,0,0,0.2)'; this.style.color='#333'" onmouseout="this.style.backgroundColor='rgba(0,0,0,0.1)'; this.style.color='#666'" title="退出登录"> <i class="fas fa-sign-out-alt"></i> 退出 </a> </div> <div class="video-container"> <video id="videoPlayer" width="640" height="360" controls> <source src="${randomLink}" type="video/mp4"> 您的浏览器不支持视频播放。 </video> </div> <!-- 新增按钮区域 --> <div style="text-align: center; margin: 10px 0;"> <!-- 新增:播放列表按钮 --> <button id="togglePlaylistBtn">播放列表</button> <button id="playPauseBtn">▶</button> <button id="prevBtn">&#10074;&#9664;</button> <button id="nextBtn">&#9654;&#10074;</button> </div> <div class="sites"> <ul class="playlist" id="playlist" style="display: none;"> ${links.map((link, index) => { const [url, title] = link.split('|'); return `<li data-src="${url}">${index + 1}. ${title}</li>`; }).join('')} </ul> </div> <script> // 将视频链接列表转换为 JavaScript 数组 const videoLinks = ${JSON.stringify(links)}; // 选择视频元素 const videoPlayer = document.getElementById('videoPlayer'); // 新增按钮功能 const playPauseBtn = document.getElementById('playPauseBtn'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); // 默认从第一个视频开始播放,并在页面加载时播放 let currentVideoIndex = 0; // 页面加载时自动播放第一个视频 document.addEventListener('DOMContentLoaded', () => { playVideo(currentVideoIndex); // 新增:为当前播放的列表项添加 playing 类 updatePlaylistStyle(currentVideoIndex); }); // 新增:更新播放列表样式的函数 function updatePlaylistStyle(index) { const playlistItems = document.querySelectorAll('#playlist li'); playlistItems.forEach((item, i) => { if (i === index) { item.classList.add('playing'); } else { item.classList.remove('playing'); } }); } // 播放视频时更新样式 function playVideo(index) { const [url] = videoLinks[index].split('|'); videoPlayer.src = url; videoPlayer.play(); // 更新播放列表样式 updatePlaylistStyle(index); } // 播放/暂停按钮功能 playPauseBtn.addEventListener('click', () => { if (videoPlayer.paused) { videoPlayer.play(); playPauseBtn.textContent = '⏸'; } else { videoPlayer.pause(); playPauseBtn.textContent = '▶'; } }); // 上一首按钮功能 prevBtn.addEventListener('click', () => { currentVideoIndex = (currentVideoIndex - 1 + videoLinks.length) % videoLinks.length; playVideo(currentVideoIndex); }); // 下一首按钮功能 nextBtn.addEventListener('click', () => { currentVideoIndex = (currentVideoIndex + 1) % videoLinks.length; playVideo(currentVideoIndex); }); // 视频播放结束时,随机播放下一个视频 videoPlayer.addEventListener('ended', () => { // 新增:随机选择未播放的视频 const unplayedVideos = videoLinks.filter((_, index) => !playedIndexes.includes(index)); if (unplayedVideos.length === 0) { // 如果所有视频都已播放过,重置记录 playedIndexes = []; currentVideoIndex = Math.floor(Math.random() * videoLinks.length); } else { // 随机选择一个未播放的视频 const randomIndex = Math.floor(Math.random() * unplayedVideos.length); currentVideoIndex = videoLinks.indexOf(unplayedVideos[randomIndex]); } playVideo(currentVideoIndex); playedIndexes.push(currentVideoIndex); }); // 新增:用于记录已播放视频的索引 let playedIndexes = []; // 新增:播放列表按钮功能 const togglePlaylistBtn = document.getElementById('togglePlaylistBtn'); const playlist = document.getElementById('playlist'); togglePlaylistBtn.addEventListener('click', () => { if (playlist.style.display === 'none') { playlist.style.display = 'block'; togglePlaylistBtn.textContent = '隐藏列表'; } else { playlist.style.display = 'none'; togglePlaylistBtn.textContent = '播放列表'; } }); // 点击播放列表中的链接后播放选择的视频 document.getElementById('playlist').addEventListener('click', function(event) { if (event.target.tagName === 'LI') { const selectedUrl = event.target.getAttribute('data-src'); videoPlayer.src = selectedUrl; videoPlayer.play(); // 更新当前视频索引 currentVideoIndex = videoLinks.findIndex(link => link.split('|')[0] === selectedUrl); // 更新播放列表样式 updatePlaylistStyle(currentVideoIndex); } }); </script> </body> </html> `; return new Response(htmlContent, { headers: { 'Content-Type': 'text/html', ...corsHeaders, }, }) }, // 登录页面渲染函数 renderLoginPage(msg = '') { return `<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>视频播放器 - 登录</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> <link rel="shortcut icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2280%22>💠</text></svg>"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Noto Sans SC', 'Segoe UI', Arial, sans-serif; background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab); background-size: 400% 400%; animation: gradient-animation 15s ease infinite; height: 100vh; display: flex; justify-content: center; align-items: center; overflow: hidden; } @keyframes gradient-animation { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .login-container { background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(20px); border-radius: 20px; padding: 40px 30px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); width: 100%; max-width: 400px; text-align: center; animation: fadeInUp 0.6s ease-out; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } .logo { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 20px; color: #333; } .logo i { font-size: 32px; color: #0F52BA; } .logo span { font-size: 24px; font-weight: bold; } .login-title { font-size: 22px; color: #333; margin-bottom: 10px; font-weight: 600; } .login-subtitle { color: #666; margin-bottom: 30px; font-size: 14px; } .error-message { background: rgba(211, 47, 47, 0.1); color: #d32f2f; padding: 12px; border-radius: 8px; margin-bottom: 20px; font-size: 14px; border: 1px solid rgba(211, 47, 47, 0.2); } .form-group { margin-bottom: 20px; text-align: left; } .form-group label { display: block; color: #333; margin-bottom: 8px; font-weight: 500; font-size: 14px; } .password-wrapper { position: relative; width: 100%; } .password-wrapper input { width: 100%; padding: 15px 50px 15px 15px; border: 2px solid #e0e0e0; border-radius: 12px; font-size: 16px; outline: none; transition: all 0.3s ease; background: rgba(255, 255, 255, 0.9); } .password-wrapper input:focus { border-color: #0F52BA; box-shadow: 0 0 0 3px rgba(15, 82, 186, 0.1); background: #fff; } .password-wrapper input::placeholder { color: #999; } .toggle-password { position: absolute; right: 15px; top: 50%; transform: translateY(-50%); background: none; border: none; color: #666; cursor: pointer; font-size: 18px; transition: color 0.3s ease; padding: 5px; } .toggle-password:hover { color: #0F52BA; } .login-btn { width: 100%; padding: 15px; background: linear-gradient(135deg, #0F52BA, #00318C); border: none; border-radius: 12px; color: #fff; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; margin-top: 10px; } .login-btn:hover { background: linear-gradient(135deg, #00318C, #001F5C); transform: translateY(-2px); box-shadow: 0 10px 25px rgba(15, 82, 186, 0.3); } .login-btn:active { transform: translateY(0); } .login-footer { margin-top: 20px; color: #666; font-size: 12px; } .login-footer a { color: #0F52BA; text-decoration: none; } .login-footer a:hover { text-decoration: underline; } /* 响应式设计 */ @media (max-width: 480px) { .login-container { margin: 20px; padding: 30px 20px; } } </style> </head> <body> <div class="login-container"> <div class="logo"> <i class="fas fa-video"></i> <span>视频播放器</span> </div> <h1 class="login-title">🔒 请输入密码</h1> <p class="login-subtitle">访问视频播放器需要身份验证</p> ${msg ? `<div class="error-message">${msg}</div>` : ''} <form method="POST" action="/login"> <div class="form-group"> <label for="password">管理员密码</label> <div class="password-wrapper"> <input type="password" id="password" name="password" placeholder="输入登录密码" required> <button type="button" class="toggle-password" onclick="togglePassword()"> <i class="fas fa-eye"></i> </button> </div> </div> <button type="submit" class="login-btn"> <i class="fas fa-sign-in-alt"></i> 登录 </button> </form> <div class="login-footer"> <p>© 2025 视频播放器</p> </div> </div> <script> function togglePassword() { const input = document.getElementById('password'); const icon = document.querySelector('.toggle-password i'); if (input.type === 'password') { input.type = 'text'; icon.className = 'fas fa-eye-slash'; } else { input.type = 'password'; icon.className = 'fas fa-eye'; } } // 回车键登录 document.getElementById('password').addEventListener('keypress', function(e) { if (e.key === 'Enter') { document.querySelector('form').submit(); } }); // 自动聚焦到密码输入框 window.addEventListener('load', function() { document.getElementById('password').focus(); }); </script> </body> </html>`; }, };