// 全局变量 let selectedAPIs = JSON.parse(localStorage.getItem('selectedAPIs') || '["heimuer", "dbzy"]'); // 默认选中黑木耳和豆瓣资源 let customAPIs = JSON.parse(localStorage.getItem('customAPIs') || '[]'); // 存储自定义API列表 // 添加当前播放的集数索引 let currentEpisodeIndex = 0; // 添加当前视频的所有集数 let currentEpisodes = []; // 添加当前视频的标题 let currentVideoTitle = ''; // 全局变量用于倒序状态 let episodesReversed = false; // 页面初始化 document.addEventListener('DOMContentLoaded', function() { // 初始化API复选框 initAPICheckboxes(); // 初始化自定义API列表 renderCustomAPIsList(); // 初始化显示选中的API数量 updateSelectedApiCount(); // 渲染搜索历史 renderSearchHistory(); // 设置默认API选择(如果是第一次加载) // 在js/app.js文件中找到类似这样的默认设置代码块 if (!localStorage.getItem('hasInitializedDefaults')) { // 选择所有API源 selectedAPIs = Object.keys(API_SITES).filter(key => key !== 'aggregated' && key !== 'custom'); localStorage.setItem('selectedAPIs', JSON.stringify(selectedAPIs)); // 默认选中过滤开关 - 修改这部分 localStorage.setItem('yellowFilterEnabled', 'false'); // 改为false,默认关闭黄色内容过滤 localStorage.setItem(PLAYER_CONFIG.adFilteringStorage, 'true'); // 保持true,默认开启分片广告过滤 // 默认开启豆瓣热门 localStorage.setItem('doubanEnabled', 'true'); // 设为true,默认开启豆瓣热门推荐 // 标记已初始化默认值 localStorage.setItem('hasInitializedDefaults', 'true'); } // 设置黄色内容过滤开关初始状态 const yellowFilterToggle = document.getElementById('yellowFilterToggle'); if (yellowFilterToggle) { yellowFilterToggle.checked = localStorage.getItem('yellowFilterEnabled') === 'true'; } // 设置广告过滤开关初始状态 const adFilterToggle = document.getElementById('adFilterToggle'); if (adFilterToggle) { adFilterToggle.checked = localStorage.getItem(PLAYER_CONFIG.adFilteringStorage) !== 'false'; // 默认为true } // 设置事件监听器 setupEventListeners(); // 初始检查成人API选中状态 setTimeout(checkAdultAPIsSelected, 100); }); // 初始化API复选框 function initAPICheckboxes() { const container = document.getElementById('apiCheckboxes'); container.innerHTML = ''; // 添加普通API组标题 const normalTitle = document.createElement('div'); normalTitle.className = 'api-group-title'; normalTitle.textContent = '普通资源'; container.appendChild(normalTitle); // 创建普通API源的复选框 Object.keys(API_SITES).forEach(apiKey => { const api = API_SITES[apiKey]; if (api.adult) return; // 跳过成人内容API,稍后添加 const checked = selectedAPIs.includes(apiKey); const checkbox = document.createElement('div'); checkbox.className = 'flex items-center'; checkbox.innerHTML = ` `; container.appendChild(checkbox); // 添加事件监听器 checkbox.querySelector('input').addEventListener('change', function() { updateSelectedAPIs(); checkAdultAPIsSelected(); }); }); // 仅在隐藏设置为false时添加成人API组 if (!HIDE_BUILTIN_ADULT_APIS) { // 添加成人API组标题 const adultTitle = document.createElement('div'); adultTitle.className = 'api-group-title adult'; adultTitle.innerHTML = `黄色资源采集站 `; container.appendChild(adultTitle); // 创建成人API源的复选框 Object.keys(API_SITES).forEach(apiKey => { const api = API_SITES[apiKey]; if (!api.adult) return; // 仅添加成人内容API const checked = selectedAPIs.includes(apiKey); const checkbox = document.createElement('div'); checkbox.className = 'flex items-center'; checkbox.innerHTML = ` `; container.appendChild(checkbox); // 添加事件监听器 checkbox.querySelector('input').addEventListener('change', function() { updateSelectedAPIs(); checkAdultAPIsSelected(); }); }); } // 初始检查成人内容状态 checkAdultAPIsSelected(); } // 检查是否有成人API被选中 function checkAdultAPIsSelected() { // 查找所有内置成人API复选框 const adultBuiltinCheckboxes = document.querySelectorAll('#apiCheckboxes .api-adult:checked'); // 查找所有自定义成人API复选框 const customApiCheckboxes = document.querySelectorAll('#customApisList .api-adult:checked'); const hasAdultSelected = adultBuiltinCheckboxes.length > 0 || customApiCheckboxes.length > 0; const yellowFilterToggle = document.getElementById('yellowFilterToggle'); const yellowFilterContainer = yellowFilterToggle.closest('div').parentNode; const filterDescription = yellowFilterContainer.querySelector('p.filter-description'); // 如果选择了成人API,禁用黄色内容过滤器 if (hasAdultSelected) { yellowFilterToggle.checked = false; yellowFilterToggle.disabled = true; localStorage.setItem('yellowFilterEnabled', 'false'); // 添加禁用样式 yellowFilterContainer.classList.add('filter-disabled'); // 修改描述文字 if (filterDescription) { filterDescription.innerHTML = '选中黄色资源站时无法启用此过滤'; } // 移除提示信息(如果存在) const existingTooltip = yellowFilterContainer.querySelector('.filter-tooltip'); if (existingTooltip) { existingTooltip.remove(); } } else { // 启用黄色内容过滤器 yellowFilterToggle.disabled = false; yellowFilterContainer.classList.remove('filter-disabled'); // 恢复原来的描述文字 if (filterDescription) { filterDescription.innerHTML = '过滤"伦理片"等黄色内容'; } // 移除提示信息 const existingTooltip = yellowFilterContainer.querySelector('.filter-tooltip'); if (existingTooltip) { existingTooltip.remove(); } } } // 渲染自定义API列表 function renderCustomAPIsList() { const container = document.getElementById('customApisList'); if (!container) return; if (customAPIs.length === 0) { container.innerHTML = '

未添加自定义API

'; return; } container.innerHTML = ''; customAPIs.forEach((api, index) => { const apiItem = document.createElement('div'); apiItem.className = 'flex items-center justify-between p-1 mb-1 bg-[#222] rounded'; // 根据是否是成人内容设置不同的样式 const textColorClass = api.isAdult ? 'text-pink-400' : 'text-white'; // 将(18+)标记移到最前面 const adultTag = api.isAdult ? '(18+)' : ''; apiItem.innerHTML = `
${adultTag}${api.name}
${api.url}
`; container.appendChild(apiItem); // 添加事件监听器 apiItem.querySelector('input').addEventListener('change', function() { updateSelectedAPIs(); checkAdultAPIsSelected(); }); }); } // 编辑自定义API function editCustomApi(index) { if (index < 0 || index >= customAPIs.length) return; const api = customAPIs[index]; // 填充表单数据 const nameInput = document.getElementById('customApiName'); const urlInput = document.getElementById('customApiUrl'); const isAdultInput = document.getElementById('customApiIsAdult'); nameInput.value = api.name; urlInput.value = api.url; if (isAdultInput) isAdultInput.checked = api.isAdult || false; // 显示表单 const form = document.getElementById('addCustomApiForm'); if (form) { form.classList.remove('hidden'); // 替换表单按钮操作 const buttonContainer = form.querySelector('div:last-child'); buttonContainer.innerHTML = ` `; } } // 更新自定义API function updateCustomApi(index) { if (index < 0 || index >= customAPIs.length) return; const nameInput = document.getElementById('customApiName'); const urlInput = document.getElementById('customApiUrl'); const isAdultInput = document.getElementById('customApiIsAdult'); const name = nameInput.value.trim(); let url = urlInput.value.trim(); const isAdult = isAdultInput ? isAdultInput.checked : false; if (!name || !url) { showToast('请输入API名称和链接', 'warning'); return; } // 确保URL格式正确 if (!/^https?:\/\/.+/.test(url)) { showToast('API链接格式不正确,需以http://或https://开头', 'warning'); return; } // 移除URL末尾的斜杠 if (url.endsWith('/')) { url = url.slice(0, -1); } // 更新API信息 customAPIs[index] = { name, url, isAdult }; localStorage.setItem('customAPIs', JSON.stringify(customAPIs)); // 重新渲染自定义API列表 renderCustomAPIsList(); // 重新检查成人API选中状态 checkAdultAPIsSelected(); // 恢复添加按钮 restoreAddCustomApiButtons(); // 清空表单并隐藏 nameInput.value = ''; urlInput.value = ''; if (isAdultInput) isAdultInput.checked = false; document.getElementById('addCustomApiForm').classList.add('hidden'); showToast('已更新自定义API: ' + name, 'success'); } // 取消编辑自定义API function cancelEditCustomApi() { // 清空表单 document.getElementById('customApiName').value = ''; document.getElementById('customApiUrl').value = ''; const isAdultInput = document.getElementById('customApiIsAdult'); if (isAdultInput) isAdultInput.checked = false; // 隐藏表单 document.getElementById('addCustomApiForm').classList.add('hidden'); // 恢复添加按钮 restoreAddCustomApiButtons(); } // 恢复自定义API添加按钮 function restoreAddCustomApiButtons() { const form = document.getElementById('addCustomApiForm'); const buttonContainer = form.querySelector('div:last-child'); buttonContainer.innerHTML = ` `; } // 更新选中的API列表 function updateSelectedAPIs() { // 获取所有内置API复选框 const builtInApiCheckboxes = document.querySelectorAll('#apiCheckboxes input:checked'); // 获取选中的内置API const builtInApis = Array.from(builtInApiCheckboxes).map(input => input.dataset.api); // 获取选中的自定义API const customApiCheckboxes = document.querySelectorAll('#customApisList input:checked'); const customApiIndices = Array.from(customApiCheckboxes).map(input => 'custom_' + input.dataset.customIndex); // 合并内置和自定义API selectedAPIs = [...builtInApis, ...customApiIndices]; // 保存到localStorage localStorage.setItem('selectedAPIs', JSON.stringify(selectedAPIs)); // 更新显示选中的API数量 updateSelectedApiCount(); } // 更新选中的API数量显示 function updateSelectedApiCount() { const countEl = document.getElementById('selectedApiCount'); if (countEl) { countEl.textContent = selectedAPIs.length; } } // 全选或取消全选API function selectAllAPIs(selectAll = true, excludeAdult = false) { const checkboxes = document.querySelectorAll('#apiCheckboxes input[type="checkbox"]'); checkboxes.forEach(checkbox => { if (excludeAdult && checkbox.classList.contains('api-adult')) { checkbox.checked = false; } else { checkbox.checked = selectAll; } }); updateSelectedAPIs(); checkAdultAPIsSelected(); } // 显示添加自定义API表单 function showAddCustomApiForm() { const form = document.getElementById('addCustomApiForm'); if (form) { form.classList.remove('hidden'); } } // 取消添加自定义API - 修改函数来重用恢复按钮逻辑 function cancelAddCustomApi() { const form = document.getElementById('addCustomApiForm'); if (form) { form.classList.add('hidden'); document.getElementById('customApiName').value = ''; document.getElementById('customApiUrl').value = ''; const isAdultInput = document.getElementById('customApiIsAdult'); if (isAdultInput) isAdultInput.checked = false; // 确保按钮是添加按钮 restoreAddCustomApiButtons(); } } // 添加自定义API function addCustomApi() { const nameInput = document.getElementById('customApiName'); const urlInput = document.getElementById('customApiUrl'); const isAdultInput = document.getElementById('customApiIsAdult'); const name = nameInput.value.trim(); let url = urlInput.value.trim(); const isAdult = isAdultInput ? isAdultInput.checked : false; if (!name || !url) { showToast('请输入API名称和链接', 'warning'); return; } // 确保URL格式正确 if (!/^https?:\/\/.+/.test(url)) { showToast('API链接格式不正确,需以http://或https://开头', 'warning'); return; } // 移除URL末尾的斜杠 if (url.endsWith('/')) { url = url.slice(0, -1); } // 添加到自定义API列表 - 增加isAdult属性 customAPIs.push({ name, url, isAdult }); localStorage.setItem('customAPIs', JSON.stringify(customAPIs)); // 默认选中新添加的API const newApiIndex = customAPIs.length - 1; selectedAPIs.push('custom_' + newApiIndex); localStorage.setItem('selectedAPIs', JSON.stringify(selectedAPIs)); // 重新渲染自定义API列表 renderCustomAPIsList(); // 更新选中的API数量 updateSelectedApiCount(); // 重新检查成人API选中状态 checkAdultAPIsSelected(); // 清空表单并隐藏 nameInput.value = ''; urlInput.value = ''; if (isAdultInput) isAdultInput.checked = false; document.getElementById('addCustomApiForm').classList.add('hidden'); showToast('已添加自定义API: ' + name, 'success'); } // 移除自定义API function removeCustomApi(index) { if (index < 0 || index >= customAPIs.length) return; const apiName = customAPIs[index].name; // 从列表中移除API customAPIs.splice(index, 1); localStorage.setItem('customAPIs', JSON.stringify(customAPIs)); // 从选中列表中移除此API const customApiId = 'custom_' + index; selectedAPIs = selectedAPIs.filter(id => id !== customApiId); // 更新大于此索引的自定义API索引 selectedAPIs = selectedAPIs.map(id => { if (id.startsWith('custom_')) { const currentIndex = parseInt(id.replace('custom_', '')); if (currentIndex > index) { return 'custom_' + (currentIndex - 1); } } return id; }); localStorage.setItem('selectedAPIs', JSON.stringify(selectedAPIs)); // 重新渲染自定义API列表 renderCustomAPIsList(); // 更新选中的API数量 updateSelectedApiCount(); // 重新检查成人API选中状态 checkAdultAPIsSelected(); showToast('已移除自定义API: ' + apiName, 'info'); } // 设置事件监听器 function setupEventListeners() { // 回车搜索 document.getElementById('searchInput').addEventListener('keypress', function(e) { if (e.key === 'Enter') { search(); } }); // 点击外部关闭设置面板 document.addEventListener('click', function(e) { const panel = document.getElementById('settingsPanel'); const settingsButton = document.querySelector('button[onclick="toggleSettings(event)"]'); if (!panel.contains(e.target) && !settingsButton.contains(e.target) && panel.classList.contains('show')) { panel.classList.remove('show'); } }); // 黄色内容过滤开关事件绑定 const yellowFilterToggle = document.getElementById('yellowFilterToggle'); if (yellowFilterToggle) { yellowFilterToggle.addEventListener('change', function(e) { localStorage.setItem('yellowFilterEnabled', e.target.checked); }); } // 广告过滤开关事件绑定 const adFilterToggle = document.getElementById('adFilterToggle'); if (adFilterToggle) { adFilterToggle.addEventListener('change', function(e) { localStorage.setItem(PLAYER_CONFIG.adFilteringStorage, e.target.checked); }); } } // 重置搜索区域 function resetSearchArea() { // 清理搜索结果 document.getElementById('results').innerHTML = ''; document.getElementById('searchInput').value = ''; // 恢复搜索区域的样式 document.getElementById('searchArea').classList.add('flex-1'); document.getElementById('searchArea').classList.remove('mb-8'); document.getElementById('resultsArea').classList.add('hidden'); // 确保页脚正确显示,移除相对定位 const footer = document.querySelector('.footer'); if (footer) { footer.style.position = ''; } // 如果有豆瓣功能,检查是否需要显示豆瓣推荐区域 if (typeof updateDoubanVisibility === 'function') { updateDoubanVisibility(); } } // 获取自定义API信息 function getCustomApiInfo(customApiIndex) { const index = parseInt(customApiIndex); if (isNaN(index) || index < 0 || index >= customAPIs.length) { return null; } return customAPIs[index]; } // 搜索功能 - 修改为支持多选API async function search() { // 密码保护校验 if (window.isPasswordProtected && window.isPasswordVerified) { if (window.isPasswordProtected() && !window.isPasswordVerified()) { showPasswordModal && showPasswordModal(); return; } } const query = document.getElementById('searchInput').value.trim(); if (!query) { showToast('请输入搜索内容', 'info'); return; } if (selectedAPIs.length === 0) { showToast('请至少选择一个API源', 'warning'); return; } showLoading(); try { // 保存搜索历史 saveSearchHistory(query); // 从所有选中的API源搜索 let allResults = []; const searchPromises = selectedAPIs.map(async (apiId) => { try { let apiUrl, apiName; // 处理自定义API if (apiId.startsWith('custom_')) { const customIndex = apiId.replace('custom_', ''); const customApi = getCustomApiInfo(customIndex); if (!customApi) return []; apiUrl = customApi.url + API_CONFIG.search.path + encodeURIComponent(query); apiName = customApi.name; } else { // 内置API if (!API_SITES[apiId]) return []; apiUrl = API_SITES[apiId].api + API_CONFIG.search.path + encodeURIComponent(query); apiName = API_SITES[apiId].name; } // 添加超时处理 const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 8000); const response = await fetch(PROXY_URL + encodeURIComponent(apiUrl), { headers: API_CONFIG.search.headers, signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { return []; } const data = await response.json(); if (!data || !data.list || !Array.isArray(data.list) || data.list.length === 0) { return []; } // 添加源信息到每个结果 const results = data.list.map(item => ({ ...item, source_name: apiName, source_code: apiId, api_url: apiId.startsWith('custom_') ? getCustomApiInfo(apiId.replace('custom_', ''))?.url : undefined })); return results; } catch (error) { console.warn(`API ${apiId} 搜索失败:`, error); return []; } }); // 等待所有搜索请求完成 const resultsArray = await Promise.all(searchPromises); // 合并所有结果 resultsArray.forEach(results => { if (Array.isArray(results) && results.length > 0) { allResults = allResults.concat(results); } }); // 更新搜索结果计数 const searchResultsCount = document.getElementById('searchResultsCount'); if (searchResultsCount) { searchResultsCount.textContent = allResults.length; } // 显示结果区域,调整搜索区域 document.getElementById('searchArea').classList.remove('flex-1'); document.getElementById('searchArea').classList.add('mb-8'); document.getElementById('resultsArea').classList.remove('hidden'); // 隐藏豆瓣推荐区域(如果存在) const doubanArea = document.getElementById('doubanArea'); if (doubanArea) { doubanArea.classList.add('hidden'); } const resultsDiv = document.getElementById('results'); // 如果没有结果 if (!allResults || allResults.length === 0) { resultsDiv.innerHTML = `

没有找到匹配的结果

请尝试其他关键词或更换数据源

`; hideLoading(); return; } // 处理搜索结果过滤:如果启用了黄色内容过滤,则过滤掉分类含有敏感内容的项目 const yellowFilterEnabled = localStorage.getItem('yellowFilterEnabled') === 'true'; if (yellowFilterEnabled) { const banned = ['伦理片','门事件','萝莉少女','制服诱惑','国产传媒','cosplay','黑丝诱惑','无码','日本无码','有码','日本有码','SWAG','网红主播', '色情片','同性片','福利视频','福利片']; allResults = allResults.filter(item => { const typeName = item.type_name || ''; return !banned.some(keyword => typeName.includes(keyword)); }); } // 添加XSS保护,使用textContent和属性转义 resultsDiv.innerHTML = allResults.map(item => { const safeId = item.vod_id ? item.vod_id.toString().replace(/[^\w-]/g, '') : ''; const safeName = (item.vod_name || '').toString() .replace(//g, '>') .replace(/"/g, '"'); const sourceInfo = item.source_name ? `${item.source_name}` : ''; const sourceCode = item.source_code || ''; // 添加API URL属性,用于详情获取 const apiUrlAttr = item.api_url ? `data-api-url="${item.api_url.replace(/"/g, '"')}"` : ''; // 更紧凑的卡片布局 const hasCover = item.vod_pic && item.vod_pic.startsWith('http'); return `
${hasCover ? `
${safeName}
` : ''}

${safeName}

${(item.type_name || '').toString().replace(/ ${(item.type_name || '').toString().replace(/` : ''} ${(item.vod_year || '') ? ` ${item.vod_year} ` : ''}

${(item.vod_remarks || '暂无介绍').toString().replace(/

${sourceInfo ? `
${sourceInfo}
` : '
'}
播放
`; }).join(''); } catch (error) { console.error('搜索错误:', error); if (error.name === 'AbortError') { showToast('搜索请求超时,请检查网络连接', 'error'); } else { showToast('搜索请求失败,请稍后重试', 'error'); } } finally { hideLoading(); } } // 显示详情 - 修改为支持自定义API async function showDetails(id, vod_name, sourceCode) { // 密码保护校验 if (window.isPasswordProtected && window.isPasswordVerified) { if (window.isPasswordProtected() && !window.isPasswordVerified()) { showPasswordModal && showPasswordModal(); return; } } if (!id) { showToast('视频ID无效', 'error'); return; } showLoading(); try { // 构建API参数 let apiParams = ''; // 处理自定义API源 if (sourceCode.startsWith('custom_')) { const customIndex = sourceCode.replace('custom_', ''); const customApi = getCustomApiInfo(customIndex); if (!customApi) { showToast('自定义API配置无效', 'error'); hideLoading(); return; } apiParams = '&customApi=' + encodeURIComponent(customApi.url) + '&source=custom'; } else { // 内置API apiParams = '&source=' + sourceCode; } const response = await fetch('/api/detail?id=' + encodeURIComponent(id) + apiParams); const data = await response.json(); const modal = document.getElementById('modal'); const modalTitle = document.getElementById('modalTitle'); const modalContent = document.getElementById('modalContent'); // 显示来源信息 const sourceName = data.videoInfo && data.videoInfo.source_name ? ` (${data.videoInfo.source_name})` : ''; // 不对标题进行截断处理,允许完整显示 modalTitle.innerHTML = `${vod_name || '未知视频'}${sourceName}`; currentVideoTitle = vod_name || '未知视频'; if (data.episodes && data.episodes.length > 0) { // 安全处理集数URL const safeEpisodes = data.episodes.map(url => { try { // 确保URL是有效的并且是http或https开头 return url && (url.startsWith('http://') || url.startsWith('https://')) ? url.replace(/"/g, '"') : ''; } catch (e) { return ''; } }).filter(url => url); // 过滤掉空URL // 保存当前视频的所有集数 currentEpisodes = safeEpisodes; episodesReversed = false; // 默认正序 modalContent.innerHTML = `
${renderEpisodes(vod_name)}
`; } else { modalContent.innerHTML = '

没有找到可播放的视频

'; } modal.classList.remove('hidden'); } catch (error) { console.error('获取详情错误:', error); showToast('获取详情失败,请稍后重试', 'error'); } finally { hideLoading(); } } // 更新播放视频函数,修改为在新标签页中打开播放页面,并保存到历史记录 function playVideo(url, vod_name, episodeIndex = 0) { // 密码保护校验 if (window.isPasswordProtected && window.isPasswordVerified) { if (window.isPasswordProtected() && !window.isPasswordVerified()) { showPasswordModal && showPasswordModal(); return; } } if (!url) { showToast('无效的视频链接', 'error'); return; } // 获取当前视频来源名称(从模态框标题中提取) let sourceName = ''; const modalTitle = document.getElementById('modalTitle'); if (modalTitle) { const sourceSpan = modalTitle.querySelector('span.text-gray-400'); if (sourceSpan) { // 提取括号内的来源名称, 例如从 "(黑木耳)" 提取 "黑木耳" const sourceText = sourceSpan.textContent; const match = sourceText.match(/\(([^)]+)\)/); if (match && match[1]) { sourceName = match[1].trim(); } } } // 保存当前状态到localStorage,让播放页面可以获取 const currentVideoTitle = vod_name; localStorage.setItem('currentVideoTitle', currentVideoTitle); localStorage.setItem('currentEpisodeIndex', episodeIndex); localStorage.setItem('currentEpisodes', JSON.stringify(currentEpisodes)); localStorage.setItem('episodesReversed', episodesReversed); // 构建视频信息对象,使用标题作为唯一标识 const videoTitle = vod_name || currentVideoTitle; const videoInfo = { title: videoTitle, url: url, episodeIndex: episodeIndex, sourceName: sourceName, timestamp: Date.now(), // 重要:将完整的剧集信息也添加到历史记录中 episodes: currentEpisodes && currentEpisodes.length > 0 ? [...currentEpisodes] : [] }; // 保存到观看历史,添加sourceName if (typeof addToViewingHistory === 'function') { addToViewingHistory(videoInfo); } // 构建播放页面URL,传递必要参数 const playerUrl = `player.html?url=${encodeURIComponent(url)}&title=${encodeURIComponent(videoTitle)}&index=${episodeIndex}&source=${encodeURIComponent(sourceName)}`; // 在新标签页中打开播放页面 window.open(playerUrl, '_blank'); } // 播放上一集 function playPreviousEpisode() { if (currentEpisodeIndex > 0) { const prevIndex = currentEpisodeIndex - 1; const prevUrl = currentEpisodes[prevIndex]; playVideo(prevUrl, currentVideoTitle, prevIndex); } } // 播放下一集 function playNextEpisode() { if (currentEpisodeIndex < currentEpisodes.length - 1) { const nextIndex = currentEpisodeIndex + 1; const nextUrl = currentEpisodes[nextIndex]; playVideo(nextUrl, currentVideoTitle, nextIndex); } } // 处理播放器加载错误 function handlePlayerError() { hideLoading(); showToast('视频播放加载失败,请尝试其他视频源', 'error'); } // 辅助函数用于渲染剧集按钮(使用当前的排序状态) function renderEpisodes(vodName) { const episodes = episodesReversed ? [...currentEpisodes].reverse() : currentEpisodes; return episodes.map((episode, index) => { // 根据倒序状态计算真实的剧集索引 const realIndex = episodesReversed ? currentEpisodes.length - 1 - index : index; return ` `; }).join(''); } // 切换排序状态的函数 function toggleEpisodeOrder() { episodesReversed = !episodesReversed; // 重新渲染剧集区域,使用 currentVideoTitle 作为视频标题 const episodesGrid = document.getElementById('episodesGrid'); if (episodesGrid) { episodesGrid.innerHTML = renderEpisodes(currentVideoTitle); } // 更新按钮文本和箭头方向 const toggleBtn = document.querySelector('button[onclick="toggleEpisodeOrder()"]'); if (toggleBtn) { toggleBtn.querySelector('span').textContent = episodesReversed ? '正序排列' : '倒序排列'; const arrowIcon = toggleBtn.querySelector('svg'); if (arrowIcon) { arrowIcon.style.transform = episodesReversed ? 'rotate(180deg)' : 'rotate(0deg)'; } } } // app.js 或路由文件中 const authMiddleware = require('./middleware/auth'); const config = require('./config'); // 对所有请求启用鉴权(按需调整作用范围) if (config.auth.enabled) { app.use(authMiddleware); } // 或者针对特定路由 app.use('/api', authMiddleware);