// ==UserScript== // @name 豆瓣电影排行榜 // @namespace https://scriptcat.org/zh-CN/ // @version 1.2.8 // @description 豆瓣电影分类排行榜移动端适配:28类无缝切换,无限滚动加载,自动续接下一页。左上搜索设置(6选项含默认跳转)、点海报按所选引擎搜索、右上搜索历史(≤30条自动清理)。https://movie.douban.com/chart可使用 // @author 失心向南 // @match *://movie.douban.com/chart* // @match *://movie.douban.com/typerank* // @match *://m.douban.com/movie/chart* // @grant GM_xmlhttpRequest // @connect movie.douban.com // @connect *.doubanio.com // @run-at document-start // @license MIT // ==/UserScript== (function () { 'use strict'; const vp = document.querySelector('meta[name="viewport"]'); if (vp) vp.setAttribute('content', 'width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no'); const CATEGORIES = [ ['11', '剧情'], ['24', '喜剧'], ['5', '动作'], ['13', '爱情'], ['17', '科幻'], ['25', '动画'], ['10', '悬疑'], ['19', '惊悚'], ['20', '恐怖'], ['1', '纪录片'], ['23', '短片'], ['6', '情色'], ['14', '音乐'], ['7', '歌舞'], ['28', '家庭'], ['8', '儿童'], ['2', '传记'], ['4', '历史'], ['22', '战争'], ['3', '犯罪'], ['27', '西部'], ['16', '奇幻'], ['15', '冒险'], ['12', '灾难'], ['29', '武侠'], ['30', '古装'], ['18', '运动'], ['31', '黑色电影'], ]; // ---------- 搜索引擎配置 ---------- const ENGINES = [ { key: 'ikan1', name: '爱看1', prefix: 'https://ikanbot.eu.org/search?q=' }, { key: 'ikan2', name: '爱看2', prefix: 'https://www1.ikanbot.com/search?q=' }, { key: 'quark', name: '夸克', prefix: 'https://m.quark.cn/s?q=' }, { key: 'bing', name: '必应', prefix: 'https://www.bing.com/search?q=' }, { key: 'sogou', name: '搜狗', prefix: 'https://www.sogou.com/web?query=' }, { key: 'default', name: '默认', prefix: '' }, ]; let engine = localStorage.getItem('db-rank-engine') || 'ikan1'; let state = { type: '11', start: 0, isLast: false, loading: false, }; const style = document.createElement('style'); style.textContent = ` html, body { margin: 0 !important; padding: 0 !important; background: #f5f5f7 !important; } body > *:not(#db-root):not(#db-engine-menu):not(#db-history-menu) { display: none !important; } #db-root { position: fixed; inset: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; background: #f5f5f7; } #db-root * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; } #db-root .db-header { position: sticky; top: 0; z-index: 10; background: #fff; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; padding: max(12px, env(safe-area-inset-top)) 12px 12px; box-shadow: 0 1px 4px rgba(0,0,0,.06); } #db-root .db-icon-btn { width: 34px; height: 34px; border: 0; background: #f0f0f3; color: #333; border-radius: 17px; font-size: 18px; cursor: pointer; padding: 0; display: flex; align-items: center; justify-content: center; } #db-root .db-menu-btn { justify-self: start; } #db-root .db-history-btn { justify-self: end; } #db-root .db-title { font-size: 17px; font-weight: 700; color: #333; justify-self: center; line-height: 1; } #db-root .db-tabs { display: flex; gap: 8px; overflow-x: auto; padding: 10px 16px; background: #fff; scrollbar-width: none; border-bottom: 1px solid #f0f0f0; position: sticky; top: 58px; z-index: 9; } #db-root .db-tabs::-webkit-scrollbar { display: none; } #db-root .db-tabs button { flex: 0 0 auto; border: 0; background: #f0f0f3; padding: 7px 14px; border-radius: 18px; font-size: 13px; color: #666; cursor: pointer; white-space: nowrap; } #db-root .db-tabs button.active { background: #00b894; color: #fff; font-weight: 600; } #db-root .db-list { padding: 12px 12px 40px; } #db-root .db-movie { display: flex; gap: 12px; background: #fff; border-radius: 12px; padding: 12px; margin-bottom: 10px; cursor: pointer; } #db-root .db-movie img { width: 64px; height: 90px; border-radius: 6px; object-fit: cover; flex: 0 0 auto; background: #eee; } #db-root .db-info { flex: 1; min-width: 0; } #db-root .db-row { display: flex; align-items: center; gap: 8px; } #db-root .db-rank { font-size: 16px; font-weight: 800; color: #ccc; min-width: 24px; } #db-root .db-rank.r1 { color: #e74c3c; } #db-root .db-rank.r2 { color: #e67e22; } #db-root .db-rank.r3 { color: #f1c40f; } #db-root .db-name { font-size: 15px; font-weight: 700; color: #222; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } #db-root .db-score { font-size: 15px; font-weight: 700; color: #00b894; flex: 0 0 auto; } #db-root .db-meta { font-size: 12px; color: #999; margin-top: 4px; } #db-root .db-actors { font-size: 12px; color: #aaa; margin-top: 4px; line-height: 1.5; } #db-root .db-sentinel { padding: 20px; text-align: center; color: #999; font-size: 13px; } #db-engine-menu, #db-history-menu { position: fixed; z-index: 9999; background: #fff; border-radius: 12px; box-shadow: 0 6px 24px rgba(0,0,0,.18); padding: 6px 0; display: none; } #db-engine-menu { top: 58px; left: 12px; min-width: 172px; } #db-history-menu { top: 58px; right: 12px; min-width: 210px; max-width: 260px; max-height: 62vh; overflow-y: auto; } #db-engine-menu.show, #db-history-menu.show { display: block; } #db-engine-menu h3, #db-history-menu h3 { font-size: 13px; color: #999; font-weight: 500; margin: 0; padding: 8px 16px; display: flex; align-items: center; justify-content: space-between; } #db-engine-menu button, #db-history-menu button { display: flex; align-items: center; width: 100%; border: 0; background: transparent; padding: 11px 16px; font-size: 15px; color: #333; cursor: pointer; text-align: left; } #db-engine-menu button .check { margin-left: auto; color: #00b894; font-weight: 700; } #db-engine-menu button.active { background: #e8f8f4; color: #00b894; } #db-history-menu button[data-htitle] { border-bottom: 1px solid #f5f5f7; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } #db-history-menu .db-history-empty { padding: 18px 16px; font-size: 13px; color: #999; text-align: center; } #db-history-menu #db-clear-history { width: auto; padding: 3px 10px; font-size: 12px; color: #666; background: #f0f0f3; border-radius: 10px; flex: 0 0 auto; } `; let root = document.createElement('div'); root.id = 'db-root'; let observer = null; let engineMenu = null; let historyMenu = null; // ---------- 搜索历史 ---------- function getHistory() { try { return JSON.parse(localStorage.getItem('db-rank-history') || '[]'); } catch (e) { return []; } } function saveHistory(arr) { localStorage.setItem('db-rank-history', JSON.stringify(arr)); } function pushHistory(title) { const h = getHistory().filter(x => x !== title); h.unshift(title); if (h.length > 30) h.length = 30; saveHistory(h); } function clearHistory() { saveHistory([]); } function escapeHtml(s) { return String(s).replace(/&/g, '&').replace(/"/g, '"').replace(//g, '>'); } // 按当前引擎搜索片名:写入历史 + 打开搜索页(引擎为「默认」时回退第一个可搜索引擎) function searchTitle(title) { if (!title) return; pushHistory(title); renderHistoryMenu(); const en = ENGINES.find(e => e.key === engine && e.prefix) || ENGINES.find(e => e.prefix); window.open(en.prefix + encodeURIComponent(title), '_blank'); } // ---------- 下拉面板 ---------- function renderEngineMenu() { engineMenu.innerHTML = '