// ==UserScript== // @name 阿豆影视界面适配 // @namespace https://scriptcat.org/zh-CN/ // @run-at document-start // @match *://movie.douban.com/tv* // @match *://movie.douban.com/explore* // @match *://movie.douban.com/subject/* // @match *://movie.douban.com/ // @match *://m.douban.com/tv* // @match *://m.douban.com/movie* // @match *://search.douban.com/movie/subject_search* // @match *://www.douban.com/doubanapp/dispatch* // @grant none // @author 失辛向南 // @version 5.9.0 // @description 优化豆瓣影视页面(TV/探索/搜索)的显示与交互,支持移动端/PC端自适应重定向、自动加载更多内容及页面布局适配。采用全新卡片样式(4:5海报、评分徽章同行、响应式列数)。 // @license MIT // ==/UserScript== (function() { 'use strict'; const DEBUG = false; function log(...args) { if (DEBUG) console.log('[豆瓣适配]', ...args); } window._noButtonRetryCount = 0; // ========== 最高优先级:doubanapp 跳转 ========== (function() { const url = window.location.href; const hostname = window.location.hostname; const pathname = window.location.pathname; if (hostname === 'www.douban.com' && pathname === '/doubanapp/dispatch') { try { const params = new URLSearchParams(window.location.search); const uri = params.get('uri'); if (uri && (uri.startsWith('/tv/') || uri.startsWith('/movie/'))) { const idMatch = uri.match(/\/(\d+)/); if (idMatch) { if (window.stop) window.stop(); document.documentElement.innerHTML = ''; const targetUrl = `https://m.douban.com/movie/subject/${idMatch[1]}/`; window.location.replace(targetUrl); return; } } } catch(e) { console.error(e); } } })(); // ========== 配置 ========== const CONFIG = { DESKTOP_UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", SUBJECT_REDIRECT: { enable: true, minWidthForDesktop: 769, originHost: "movie.douban.com", targetHost: "m.douban.com", pathPrefix: "/movie" }, M_SUBJECT_REDIRECT: { enable: true, minWidthForMobile: 769, originHost: "m.douban.com", targetHost: "movie.douban.com", pathPrefixRemove: "/movie" }, SEARCH_REDIRECT: { enable: true, originHost: "search.douban.com", originPath: "/movie/subject_search", targetHost: "m.douban.com", targetPath: "/search/", searchParam: "search_text", targetParam: "query" }, AUTO_LOAD: { enable: true, triggerDistance: 250, lockResetTime: 2000, loadCooldown: 1000, noDataCheckDelay: 1200 }, ADAPT_ENABLE: true, M_TO_MOVIE_REDIRECT: { enable: true, originHost: "m.douban.com", targetHost: "movie.douban.com", targetPath: "/tv", excludePaths: ["/subject/", "/celebrity/"], matchListPaths: ["/tv", "/movie"] }, // 卡片样式配置(新增) RESPONSIVE_MODE: true, // 是否启用响应式列数 POSTER_ASPECT_RATIO: '4 / 5' // 海报宽高比 }; // 根据屏幕宽度获取响应式列数 function getResponsiveColumns() { const width = window.innerWidth; if (width < 600) return 3; else if (width < 900) return 5; else if (width < 1200) return 6; else return 10; } function getNormalColumns() { if (CONFIG.RESPONSIVE_MODE) { return getResponsiveColumns(); } else { return 3; // 默认3列 } } const currentLocation = window.location; const currentHostname = currentLocation.hostname; const currentPathname = currentLocation.pathname; const currentHref = currentLocation.href; const isMovieDoubanDomain = currentHostname === CONFIG.SUBJECT_REDIRECT.originHost; const isMDoubanDomain = currentHostname === CONFIG.M_SUBJECT_REDIRECT.originHost; const isTvPage = isMovieDoubanDomain && (currentPathname.startsWith('/tv') || currentPathname === '/tv'); const isExplorePage = isMovieDoubanDomain && (currentPathname.startsWith('/explore') || currentPathname === '/explore'); const isHomePage = isMovieDoubanDomain && (currentPathname === '/' || currentPathname === ''); const needAdaptPage = isTvPage || isExplorePage; if (isHomePage) return; const getViewportWidth = () => window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; // 手机版详情页 -> 电脑版 const isMSubjectPage = isMDoubanDomain && currentPathname.startsWith('/movie/subject/'); if (CONFIG.M_SUBJECT_REDIRECT.enable && isMSubjectPage) { const screenWidth = getViewportWidth(); if (screenWidth >= CONFIG.M_SUBJECT_REDIRECT.minWidthForMobile) { try { const newPathname = currentPathname.replace(CONFIG.M_SUBJECT_REDIRECT.pathPrefixRemove, ''); const targetUrl = new URL(currentHref); targetUrl.hostname = CONFIG.M_SUBJECT_REDIRECT.targetHost; targetUrl.pathname = newPathname; if (targetUrl.href !== currentHref) { log(`跳转电脑版详情页`); window.location.replace(targetUrl.href); return; } } catch(e) { console.error(e); } } } if (isTvPage && currentLocation.hash !== '#douban-desktop-adapt') { window.location.hash = 'douban-desktop-adapt'; } // UA 伪装 if (needAdaptPage) { const rewriteNavigatorProp = (prop, value) => { Object.defineProperty(navigator, prop, { get: () => value, configurable: true, enumerable: true }); }; rewriteNavigatorProp('userAgent', CONFIG.DESKTOP_UA); rewriteNavigatorProp('appVersion', CONFIG.DESKTOP_UA.replace('Mozilla/', '')); rewriteNavigatorProp('platform', 'Win64'); rewriteNavigatorProp('oscpu', 'Windows NT 10.0; Win64; Win64; x64'); Object.defineProperty(window.screen, 'width', { get: () => 1920, configurable: true }); Object.defineProperty(window.screen, 'height', { get: () => 1080, configurable: true }); Object.defineProperty(window.screen, 'availWidth', { get: () => 1920, configurable: true }); Object.defineProperty(window.screen, 'availHeight', { get: () => 1040, configurable: true }); } // viewport (function() { if (isTvPage || isExplorePage) { const meta = document.createElement('meta'); meta.name = 'viewport'; meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes'; if (document.head) document.head.appendChild(meta); else document.write(''); } })(); // 搜索页跳转 const isSearchPage = currentHostname === CONFIG.SEARCH_REDIRECT.originHost && currentPathname.startsWith(CONFIG.SEARCH_REDIRECT.originPath); if (CONFIG.SEARCH_REDIRECT.enable && isSearchPage) { try { const urlParams = new URLSearchParams(currentLocation.search); const searchKeyword = urlParams.get(CONFIG.SEARCH_REDIRECT.searchParam); if (searchKeyword) { const targetUrl = new URL(currentLocation.origin + CONFIG.SEARCH_REDIRECT.targetPath); targetUrl.hostname = CONFIG.SEARCH_REDIRECT.targetHost; targetUrl.searchParams.set(CONFIG.SEARCH_REDIRECT.targetParam, searchKeyword); if (targetUrl.href !== currentHref) window.location.replace(targetUrl.href); return; } } catch(e) { console.error(e); } } // 详情页跳转手机版 const isSubjectPage = isMovieDoubanDomain && currentPathname.startsWith('/subject/'); if (CONFIG.SUBJECT_REDIRECT.enable && isSubjectPage) { const screenWidth = getViewportWidth(); if (screenWidth < CONFIG.SUBJECT_REDIRECT.minWidthForDesktop) { try { const targetUrl = new URL(currentHref); targetUrl.hostname = CONFIG.SUBJECT_REDIRECT.targetHost; targetUrl.pathname = CONFIG.SUBJECT_REDIRECT.pathPrefix + targetUrl.pathname; if (targetUrl.href !== currentHref) window.location.replace(targetUrl.href); return; } catch(e) { console.error(e); } } } // m站列表页跳回电脑版 const isMDoubanListPage = isMDoubanDomain && !currentPathname.includes('/subject/') && !currentPathname.includes('/celebrity/') && (currentPathname.startsWith('/tv') || currentPathname.startsWith('/movie')); if (CONFIG.M_TO_MOVIE_REDIRECT.enable && isMDoubanListPage) { try { const targetUrl = new URL(currentHref); targetUrl.hostname = CONFIG.M_TO_MOVIE_REDIRECT.targetHost; targetUrl.pathname = CONFIG.M_TO_MOVIE_REDIRECT.targetPath; targetUrl.hash = 'douban-desktop-adapt'; if (targetUrl.href !== currentHref) { const link = document.createElement('a'); link.href = targetUrl.href; link.referrerPolicy = 'no-referrer'; link.style.display = 'none'; document.body.appendChild(link); link.click(); setTimeout(() => link.remove(), 100); return; } } catch(e) { console.error(e); } } // ========== 样式注入(保留筛选区重构样式,卡片样式升级为4:5海报+评分徽章) ========== function injectAdaptStyle() { const style = document.createElement('style'); style.textContent = ` html, body, #wrapper, .grid-16-8, .article { overflow-x: hidden !important; max-width: 100% !important; width: 100% !important; box-sizing: border-box !important; } * { box-sizing: border-box; } #db-global-nav, #db-nav-movie .nav-primary, #db-nav-movie .nav-secondary, .global-nav, .top-nav-info, .site-nav, .nav-search, .movieannual, .nav-logo, .nav-items, #footer, .aside, .extra, #recommend-groups, .dale_movie_tv_bottom_banner, .grid-16-8 .aside, .grid-16-8 .extra { display: none !important; } .rating-range, .score-range, .filter-checkbox, .drc-checkbox, .explore-all-filter, .rating-range-container, [class*="rating-range"], [class*="score-range"] { display: none !important; } /* 原有筛选组基础样式 */ .selector-item, .tag-group, .base-selector { margin: 0 !important; padding: 6px 14px !important; background: #f5f5f7 !important; border-radius: 30px !important; font-size: 14px !important; font-weight: 500 !important; color: #2c3e50 !important; white-space: nowrap !important; transition: all 0.2s ease !important; } .selector-item.active, .tag-group.active, .base-selector.active { background: #1e2a3e !important; color: white !important; } .grid-16-8 .article, #content .article { float: none !important; width: 100% !important; margin: 0 !important; padding: 0 12px !important; box-sizing: border-box; overflow-x: hidden !important; } #content > h1 { margin: 16px 0 8px 0 !important; font-size: 22px !important; font-weight: 600 !important; padding-left: 8px !important; } /* ========== 筛选区重构专用样式(水平滚动 + 垂直滚动) ========== */ .dh-filter-horizontal { display: flex !important; flex-direction: row !important; overflow-x: auto !important; overflow-y: visible !important; gap: 12px !important; padding: 12px 8px !important; margin: 0 0 8px 0 !important; scrollbar-width: thin; -webkit-overflow-scrolling: touch; background: transparent !important; box-shadow: none !important; border-radius: 0 !important; } .dh-filter-horizontal .tag-group { flex: 0 0 auto !important; display: inline-flex !important; flex-direction: column !important; background: #ffffff !important; border-radius: 12px !important; padding: 8px 12px !important; margin: 0 !important; box-shadow: 0 1px 2px rgba(0,0,0,0.05) !important; min-width: 110px !important; } .dh-filter-horizontal .tag-group .tag-group-title { font-size: 14px !important; font-weight: 600 !important; margin-bottom: 8px !important; color: #1e2a3e !important; } .dh-filter-horizontal .tag-group .selector-item, .dh-filter-horizontal .tag-group .tag-group { display: inline-block !important; margin: 4px 6px 4px 0 !important; white-space: nowrap !important; } .dh-filter-vertical { max-height: 280px !important; overflow-y: auto !important; overflow-x: hidden !important; padding: 8px 12px !important; margin: 0 0 12px 0 !important; background: transparent !important; border-radius: 16px !important; box-shadow: none !important; scrollbar-width: thin; -webkit-overflow-scrolling: touch; } .dh-filter-vertical .tag-group { background: transparent !important; padding: 0 !important; margin: 0 !important; box-shadow: none !important; display: flex !important; flex-wrap: wrap !important; gap: 8px !important; } .dh-filter-vertical .selector-item, .dh-filter-vertical .tag-group .selector-item { display: inline-block !important; margin: 0 !important; background: #f5f5f7 !important; border-radius: 30px !important; padding: 6px 14px !important; font-size: 13px !important; } .explore-all-selectors, .explore-menu, .tag-group-list, .base-selector { background: transparent !important; box-shadow: none !important; border: none !important; padding: 0 !important; margin: 0 !important; } .dh-filter-vertical .tag-group .tag-group-title { display: none !important; } .dh-filter-horizontal::-webkit-scrollbar { height: 4px; } .dh-filter-horizontal::-webkit-scrollbar-track { background: #e9ecef; border-radius: 4px; } .dh-filter-horizontal::-webkit-scrollbar-thumb { background: #adb5bd; border-radius: 4px; } .dh-filter-vertical::-webkit-scrollbar { width: 4px; } .dh-filter-vertical::-webkit-scrollbar-track { background: #e9ecef; border-radius: 4px; } .dh-filter-vertical::-webkit-scrollbar-thumb { background: #adb5bd; border-radius: 4px; } /* ========== 全新卡片网格样式(4:5海报 + 评分徽章同行) ========== */ /* 隐藏冗余信息 */ .drc-subject-info-subtitle, .subject-cast, .meta.abstract, .meta.abstract_2, .info .gray-text, .rating .gray-text, .cast, .abstract, .pl, .rating span.pl, .subject-desc, .drc-subject-info-subtitle, .drc-subject-info-subtitle * { display: none !important; } /* 网格容器 */ ul.subject-list-list, #explore-rec .list, .grid-view, .search-result-list, .subject-list { display: grid !important; gap: 8px !important; padding: 8px !important; margin: 0 !important; width: 100% !important; max-width: 100% !important; box-sizing: border-box !important; } /* 卡片条目 */ ul.subject-list-list > li, #explore-rec .list > li, .grid-view .item, .search-result-list .sc-bZQynM, .subject-list .subject-item, .drc-subject-card { display: flex !important; flex-direction: column !important; background: #fff !important; border-radius: 8px !important; overflow: hidden !important; box-shadow: 0 1px 4px rgba(0,0,0,0.1) !important; margin: 0 !important; padding: 0 !important; width: 100% !important; list-style: none !important; } /* 海报容器 */ .drc-cover, .pic, .cover, .subject-cover, .drc-cover-container, ul.subject-list-list > li .drc-cover, #explore-rec .list > li .pic, .grid-view .item .pic, .search-result-list .sc-bZQynM .cover { width: 100% !important; padding-top: 0 !important; aspect-ratio: ${CONFIG.POSTER_ASPECT_RATIO} !important; height: auto !important; max-height: none !important; overflow: hidden !important; background: #f0f0f0 !important; border-radius: 0 !important; box-shadow: none !important; position: relative !important; display: block !important; } /* 海报图片 */ .drc-cover img, .pic img, .cover img, .subject-cover img, .drc-cover-pic { width: 100% !important; height: 100% !important; object-fit: cover !important; position: absolute !important; top: 0 !important; left: 0 !important; display: block !important; } /* 信息区域(评分与标题同行) */ .drc-subject-card-main, .info, .subject-info, .detail, ul.subject-list-list > li .info, #explore-rec .list > li .info, .grid-view .item .info, .search-result-list .sc-bZQynM .detail { padding: 6px 4px 8px !important; background: #fff !important; display: flex !important; flex-direction: row !important; align-items: center !important; flex-wrap: nowrap !important; gap: 4px !important; width: 100% !important; box-sizing: border-box !important; } /* 评分徽章 */ .drc-rating-num, .rating_num, .rate, .rating_nums, .drc-subject-info-rating .drc-rating-num { background: rgba(0, 0, 0, 0.7) !important; color: #ff9900 !important; font-size: 11px !important; font-weight: bold !important; padding: 2px 6px !important; border-radius: 12px !important; display: inline-block !important; line-height: 1 !important; flex-shrink: 0 !important; margin-right: 4px !important; order: 0 !important; } /* 标题 */ .drc-subject-info-title-text, .title a, .subject-title a, .title-text, .drc-subject-info-title .drc-subject-info-title-text { font-size: 12px !important; font-weight: 600 !important; color: #333 !important; text-decoration: none !important; display: inline-block !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; flex: 1 !important; min-width: 0 !important; order: 1 !important; } .drc-subject-info-title { display: contents !important; } .drc-rating-stars, .allstar00, .allstar10, .allstar20, .allstar30, .allstar40, .allstar50, .rating-stars { display: none !important; } .search-result-list .sc-bZQynM { display: flex !important; flex-direction: column !important; } .search-result-list .sc-bZQynM .cover { width: 100% !important; aspect-ratio: ${CONFIG.POSTER_ASPECT_RATIO} !important; height: auto !important; } .search-result-list .sc-bZQynM .detail { display: flex !important; flex-direction: row !important; align-items: center !important; } .subject-list-more { margin: 30px 0 40px !important; text-align: center !important; } .subject-list-more button, .subject-list-more .drc-button, .subject-list-more a { border-radius: 60px !important; padding: 10px 28px !important; background-color: #f0f2f5 !important; border: none !important; color: #1e2a3e !important; font-weight: 600 !important; font-size: 14px !important; cursor: pointer !important; transition: background 0.2s, transform 0.1s !important; box-shadow: 0 1px 2px rgba(0,0,0,0.05); } .subject-list-more button:active, .subject-list-more .drc-button:active { transform: scale(0.97); background-color: #e4e6e9; } #content { padding-bottom: 20px !important; } .article .item, .grid-view .item { break-inside: avoid; } a, button, .selector-item, .tag-group { cursor: pointer; touch-action: manipulation; } `; document.head.appendChild(style); } function cleanPage() { const hideSelectors = ['.rating-range', '.score-range', '.filter-checkbox', '.drc-checkbox', '.explore-all-filter', '.rating-range-container', '[class*="rating-range"]', '[class*="score-range"]']; hideSelectors.forEach(sel => document.querySelectorAll(sel).forEach(el => el && (el.style.display = 'none'))); const candidates = document.querySelectorAll('.explore-all-selectors, .explore-menu, .tag-group-list, .base-selector, .subject-list-list, .grid-view, .list-view'); candidates.forEach(container => { if (!container) return; const elements = container.querySelectorAll('div, span, li'); elements.forEach(el => { const txt = el.innerText || ''; if ((txt.includes('评分区间') || txt.includes('未看过') || txt.includes('可播放')) && !el.querySelector('a, .selector-item, .tag-group, button')) { el.style.display = 'none'; } }); }); } // ========== 筛选区重构:水平滚动(类型/地区/年代/平台/排序) + 垂直滚动(国家列表) ========== let isFilterRestructured = false; function restructureFilterPanel() { if (!needAdaptPage) return; if (isFilterRestructured) return; const filterContainer = document.querySelector('.explore-all-selectors, .explore-menu, .tag-group-list'); if (!filterContainer) return; let groups = Array.from(filterContainer.querySelectorAll(':scope > .tag-group, :scope > .base-selector')); if (groups.length === 0) return; let countryGroup = null; let otherGroups = []; const countryKeywords = ['华语', '欧美', '韩国', '日本', '美国', '英国', '泰国', '法国', '德国', '西班牙', '俄罗斯', '瑞典', '巴西', '丹麦', '印度', '加拿大', '爱尔兰', '澳大利亚', '中国台湾', '中国香港', '意大利']; for (let group of groups) { const items = group.querySelectorAll('.selector-item, .tag-group'); const itemCount = items.length; const innerText = group.innerText || ''; let isCountry = itemCount > 8; if (!isCountry) { let matchCount = 0; for (let kw of countryKeywords) { if (innerText.includes(kw)) matchCount++; if (matchCount >= 2) break; } isCountry = matchCount >= 2; } if (isCountry && !countryGroup) { countryGroup = group; } else { otherGroups.push(group); } } if (!countryGroup && groups.length > 0) { let maxSize = 0; for (let g of groups) { let cnt = g.querySelectorAll('.selector-item, .tag-group').length; if (cnt > maxSize && cnt > 6) { maxSize = cnt; countryGroup = g; } } if (countryGroup) { otherGroups = groups.filter(g => g !== countryGroup); } else { return; } } if (!countryGroup || otherGroups.length === 0) return; const horizontalWrap = document.createElement('div'); horizontalWrap.className = 'dh-filter-horizontal'; const verticalWrap = document.createElement('div'); verticalWrap.className = 'dh-filter-vertical'; otherGroups.forEach(group => { horizontalWrap.appendChild(group.cloneNode(true)); group.remove(); }); const clonedCountry = countryGroup.cloneNode(true); verticalWrap.appendChild(clonedCountry); countryGroup.remove(); filterContainer.appendChild(horizontalWrap); filterContainer.appendChild(verticalWrap); horizontalWrap.querySelectorAll('.tag-group').forEach(group => { if (!group.querySelector('.tag-group-title')) { let title = ''; const firstText = group.childNodes[0]?.nodeType === Node.TEXT_NODE ? group.childNodes[0].textContent.trim() : ''; if (firstText && firstText.length < 10) title = firstText; else if (group.innerText) title = group.innerText.split(/\s/)[0]; if (title) { const titleSpan = document.createElement('div'); titleSpan.className = 'tag-group-title'; titleSpan.innerText = title; group.insertBefore(titleSpan, group.firstChild); } } }); isFilterRestructured = true; log('筛选面板重构完成'); } // ========== 动态更新卡片列数 ========== let currentNormalColumns = getNormalColumns(); function updateNormalColumns() { const cols = getNormalColumns(); if (cols === currentNormalColumns) return; currentNormalColumns = cols; applyGridColumns(); } function applyGridColumns() { const cols = getNormalColumns(); document.querySelectorAll('ul.subject-list-list, #explore-rec .list, .grid-view, .search-result-list, .subject-list').forEach(el => { el.style.display = 'grid'; el.style.gridTemplateColumns = `repeat(${cols}, 1fr)`; }); } // ========== 自动加载逻辑(严格防闪烁) ========== let isLoading = false; let noMoreData = false; let lastLoadTime = 0; let lastItemCount = 0; let pendingCheck = false; let contentObserver = null; function getCurrentItemCount() { return document.querySelectorAll('.subject-list-list li, .grid-view .item, .list-view .item, .drc-subject-card').length; } function getLoadMoreBtn() { if (noMoreData) return null; const isValidBtn = (el) => { if (!el) return false; if (el.disabled) return false; const rect = el.getBoundingClientRect(); if (rect.width === 0 && rect.height === 0) return false; const style = window.getComputedStyle(el); if (style.display === 'none' || style.visibility === 'hidden') return false; const text = (el.textContent || '').trim(); return text.includes('加载更多') || text.includes('Load more') || text.includes('更多'); }; const selectors = [ '.subject-list-more button', '.subject-list-more .drc-button', '.subject-list-more a', '.more a', '.load-more a', '.list-more a', '.next a', '.load-more-btn', '.btn-more', '.more-btn', 'a.more', 'button.more', '[class*="load-more"]', '[class*="loadmore"]', '#load-more', '.load-more-button', '.more-link', '.next-page', '.paginator .next a' ]; for (const selector of selectors) { try { const elements = document.querySelectorAll(selector); for (const el of elements) { if (isValidBtn(el)) return el; } } catch(e) {} } try { const xpath = "//*[contains(text(),'加载更多') or contains(text(),'Load more')]"; const result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); let node = result.singleNodeValue; while (node) { if (isValidBtn(node)) return node; let parent = node.parentElement; while (parent && parent !== document.body) { if (isValidBtn(parent) || parent.tagName === 'A' || parent.tagName === 'BUTTON') { if (isValidBtn(parent)) return parent; } parent = parent.parentElement; } node = node.parentElement; } } catch(e) {} const all = document.querySelectorAll('a, button, .more, .load-more, [role="button"]'); for (const el of all) { if (isValidBtn(el)) return el; } return null; } function checkNoMoreDataByText() { const bodyText = document.body.innerText; if (bodyText.includes('没有更多') || bodyText.includes('已经到底') || bodyText.includes('No more') || bodyText.includes('End of list')) { if (!noMoreData) log('文本检测到无更多数据'); return true; } const btn = getLoadMoreBtn(); if (btn && btn.disabled) { if (!noMoreData) log('按钮已禁用,无更多数据'); return true; } return false; } function performLoad() { if (isLoading) { log('跳过:正在加载'); return false; } if (noMoreData) { log('跳过:已无更多数据'); return false; } const now = Date.now(); if (now - lastLoadTime < CONFIG.AUTO_LOAD.loadCooldown) { log('跳过:冷却中'); return false; } if (checkNoMoreDataByText()) { noMoreData = true; return false; } const loadBtn = getLoadMoreBtn(); if (!loadBtn) { window._noButtonRetryCount = (window._noButtonRetryCount || 0) + 1; if (window._noButtonRetryCount > 3) { log('多次未找到按钮,标记无更多数据'); noMoreData = true; } return false; } window._noButtonRetryCount = 0; const beforeCount = getCurrentItemCount(); isLoading = true; lastLoadTime = now; loadBtn.click(); log(`触发加载,当前条目: ${beforeCount}`); const lockTimer = setTimeout(() => { if (isLoading) { log('加载超时,强制重置锁'); isLoading = false; } }, CONFIG.AUTO_LOAD.lockResetTime); setTimeout(() => { clearTimeout(lockTimer); if (!isLoading) return; const afterCount = getCurrentItemCount(); if (afterCount > beforeCount) { log(`加载成功: ${beforeCount} -> ${afterCount}`); noMoreData = false; lastItemCount = afterCount; applyGridColumns(); // 加载后重新应用网格列数 } else { log(`加载无新条目,停止自动加载`); noMoreData = true; } isLoading = false; }, CONFIG.AUTO_LOAD.noDataCheckDelay); return true; } function checkAndLoad() { if (isLoading || noMoreData) return; if (pendingCheck) return; pendingCheck = true; setTimeout(() => { pendingCheck = false; }, 150); if (checkNoMoreDataByText()) { noMoreData = true; return; } const docEl = document.documentElement; const scrollTop = window.pageYOffset || docEl.scrollTop || 0; const windowHeight = window.innerHeight || docEl.clientHeight || 0; const documentHeight = Math.max(docEl.scrollHeight, docEl.offsetHeight, document.body.scrollHeight); const distanceToBottom = documentHeight - (scrollTop + windowHeight); if (distanceToBottom <= CONFIG.AUTO_LOAD.triggerDistance) { performLoad(); } } let changeTimer = null; function onContentChanged() { if (changeTimer) clearTimeout(changeTimer); changeTimer = setTimeout(() => { const newCount = getCurrentItemCount(); if (newCount !== lastItemCount) { log(`条目变化: ${lastItemCount} -> ${newCount}`); lastItemCount = newCount; if (noMoreData && newCount > lastItemCount) { log('检测到新条目,重置无数据标志'); noMoreData = false; } applyGridColumns(); // 内容变化时重新应用列数 } if (!noMoreData) checkAndLoad(); }, 300); } function setupContentMonitor() { if (contentObserver) contentObserver.disconnect(); contentObserver = new MutationObserver(() => onContentChanged()); contentObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'] }); lastItemCount = getCurrentItemCount(); } function initAfterDOMLoad() { if (needAdaptPage) { injectAdaptStyle(); cleanPage(); const observer = new MutationObserver(() => cleanPage()); observer.observe(document.body, { childList: true, subtree: true }); // 重构筛选面板 restructureFilterPanel(); const filterObserver = new MutationObserver(() => { if (!isFilterRestructured) restructureFilterPanel(); }); filterObserver.observe(document.body, { childList: true, subtree: true }); // 应用卡片网格列数并监听响应式 applyGridColumns(); if (CONFIG.RESPONSIVE_MODE) { let resizeTimer; window.addEventListener('resize', () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { updateNormalColumns(); applyGridColumns(); }, 100); }); } // 确保动态加载后网格列数正确 const gridObserver = new MutationObserver(() => applyGridColumns()); gridObserver.observe(document.body, { childList: true, subtree: true }); } if (CONFIG.AUTO_LOAD.enable && needAdaptPage) { setupContentMonitor(); window.addEventListener('scroll', checkAndLoad, { passive: true }); window.addEventListener('resize', checkAndLoad, { passive: true }); window.addEventListener('load', () => setTimeout(checkAndLoad, 300)); setTimeout(checkAndLoad, 500); setInterval(() => { if (!isLoading && !noMoreData && needAdaptPage) { checkAndLoad(); } }, 3000); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAfterDOMLoad); } else { initAfterDOMLoad(); } })();