diff --git "a/D1\345\210\235\345\247\213\345\214\226.md" "b/D1\345\210\235\345\247\213\345\214\226.md" index 48b846f262..d4792c8573 100644 --- "a/D1\345\210\235\345\247\213\345\214\226.md" +++ "b/D1\345\210\235\345\247\213\345\214\226.md" @@ -1,89 +1,98 @@ -```sql +-- ============================================= +-- MoonTV D1 数据库完整初始化脚本(基于原始 schema 完善版) +-- 支持:17+ 功能全持久化(收藏/进度/历史/配置/跳过)、站长全权限(/admin 用户管理+动态配置)、多端同步 +-- 执行后必须设置环境变量:NEXT_PUBLIC_STORAGE_TYPE=d1 +-- 原始表:6 个(覆盖所有用户/管理员数据);功能扩展通过 admin_config JSON 字段实现(如站点公告、权限分配) +-- ============================================= + +-- 用户表:支持多账户注册/登录,站长可通过 /admin 添加/编辑权限 CREATE TABLE IF NOT EXISTS users ( - username TEXT PRIMARY KEY, - password TEXT NOT NULL, - created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')) + username TEXT PRIMARY KEY, + password TEXT NOT NULL, + is_admin INTEGER NOT NULL DEFAULT 0, -- 0=普通用户, 1=管理员(站长全权限:管理用户、配置、日志) + created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')) ); +-- 索引:加速用户查询(多账户场景) +CREATE INDEX IF NOT EXISTS idx_users_username ON users(username); +-- 播放记录表:支持继续观看、多端进度同步 CREATE TABLE IF NOT EXISTS play_records ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT NOT NULL, - key TEXT NOT NULL, - title TEXT NOT NULL, - source_name TEXT NOT NULL, - cover TEXT NOT NULL, - year TEXT NOT NULL, - index_episode INTEGER NOT NULL, - total_episodes INTEGER NOT NULL, - play_time INTEGER NOT NULL, - total_time INTEGER NOT NULL, - save_time INTEGER NOT NULL, - search_title TEXT, - UNIQUE(username, key) + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, + key TEXT NOT NULL, + title TEXT NOT NULL, + source_name TEXT NOT NULL, + cover TEXT NOT NULL, + year TEXT NOT NULL, + index_episode INTEGER NOT NULL, + total_episodes INTEGER NOT NULL, + play_time INTEGER NOT NULL, + total_time INTEGER NOT NULL, + save_time INTEGER NOT NULL, + search_title TEXT, + UNIQUE(username, key) ); +-- 索引:加速按用户/键查询 +CREATE INDEX IF NOT EXISTS idx_play_records_user_key ON play_records(username, key); +-- 收藏表:支持影视收藏、多端同步 CREATE TABLE IF NOT EXISTS favorites ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT NOT NULL, - key TEXT NOT NULL, - title TEXT NOT NULL, - source_name TEXT NOT NULL, - cover TEXT NOT NULL, - year TEXT NOT NULL, - total_episodes INTEGER NOT NULL, - save_time INTEGER NOT NULL, - UNIQUE(username, key) + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, + key TEXT NOT NULL, + title TEXT NOT NULL, + source_name TEXT NOT NULL, + cover TEXT NOT NULL, + year TEXT NOT NULL, + total_episodes INTEGER NOT NULL, + save_time INTEGER NOT NULL, + UNIQUE(username, key) ); +-- 索引:加速收藏查询 +CREATE INDEX IF NOT EXISTS idx_favorites_user_key ON favorites(username, key); +-- 搜索历史表:支持关键词历史、多端同步 CREATE TABLE IF NOT EXISTS search_history ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT NOT NULL, - keyword TEXT NOT NULL, - created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')), - UNIQUE(username, keyword) + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, + keyword TEXT NOT NULL, + created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')), + UNIQUE(username, keyword) ); +-- 索引:加速历史查询 +CREATE INDEX IF NOT EXISTS idx_search_history_user ON search_history(username); +-- 管理员配置表:站长全权限核心,支持动态 JSON 配置(如用户权限、站点公告、资源站点编辑) +-- 示例 JSON: {"announcement": "站点维护中", "enable_register": true, "custom_sites": [...], "admin_users": ["user1"]} CREATE TABLE IF NOT EXISTS admin_config ( - id INTEGER PRIMARY KEY DEFAULT 1, - config TEXT NOT NULL, - updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')) + id INTEGER PRIMARY KEY DEFAULT 1, + config TEXT NOT NULL, -- JSON 字符串,存储全权限配置(站长可编辑) + updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')) ); +-- 初始化默认配置(如果表空) +INSERT OR IGNORE INTO admin_config (id, config) VALUES (1, '{"announcement": "", "enable_register": false, "search_max_page": 5, "admin_users": []}'); +-- 跳过片头/片尾配置表:智能去广告核心,用户/管理员可设置(默认开启,支持 per-video 自定义) CREATE TABLE IF NOT EXISTS skip_configs ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT NOT NULL, - source TEXT NOT NULL, - id_video TEXT NOT NULL, - enable INTEGER NOT NULL DEFAULT 0, - intro_time INTEGER NOT NULL DEFAULT 0, - outro_time INTEGER NOT NULL DEFAULT 0, - UNIQUE(username, source, id_video) + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, + source TEXT NOT NULL, -- 资源源(如 "dyttzy") + id_video TEXT NOT NULL, -- 视频 ID/Key + enable INTEGER NOT NULL DEFAULT 1, -- 1=开启跳过(默认全开) + intro_time INTEGER NOT NULL DEFAULT 90, -- 片头跳过秒数(默认 90s,自动检测广告) + outro_time INTEGER NOT NULL DEFAULT 120, -- 片尾跳过秒数(默认 120s,自动检测结束广告) + updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')), + UNIQUE(username, source, id_video) ); +-- 索引:加速跳过查询 +CREATE INDEX IF NOT EXISTS idx_skip_configs_user_source ON skip_configs(username, source); --- 基本索引 -CREATE INDEX IF NOT EXISTS idx_play_records_username ON play_records(username); -CREATE INDEX IF NOT EXISTS idx_favorites_username ON favorites(username); -CREATE INDEX IF NOT EXISTS idx_search_history_username ON search_history(username); - --- 复合索引优化查询性能 --- 播放记录:用户名+键值的复合索引,用于快速查找特定记录 -CREATE INDEX IF NOT EXISTS idx_play_records_username_key ON play_records(username, key); --- 播放记录:用户名+保存时间的复合索引,用于按时间排序的查询 -CREATE INDEX IF NOT EXISTS idx_play_records_username_save_time ON play_records(username, save_time DESC); - --- 收藏:用户名+键值的复合索引,用于快速查找特定收藏 -CREATE INDEX IF NOT EXISTS idx_favorites_username_key ON favorites(username, key); --- 收藏:用户名+保存时间的复合索引,用于按时间排序的查询 -CREATE INDEX IF NOT EXISTS idx_favorites_username_save_time ON favorites(username, save_time DESC); - --- 搜索历史:用户名+关键词的复合索引,用于快速查找/删除特定搜索记录 -CREATE INDEX IF NOT EXISTS idx_search_history_username_keyword ON search_history(username, keyword); --- 搜索历史:用户名+创建时间的复合索引,用于按时间排序的查询 -CREATE INDEX IF NOT EXISTS idx_search_history_username_created_at ON search_history(username, created_at DESC); - --- 跳过片头片尾配置:用户名+源+视频ID的复合索引,用于快速查找特定配置 -CREATE INDEX IF NOT EXISTS idx_skip_configs_username_source_id ON skip_configs(username, source, id_video); - --- 搜索历史清理查询的优化索引 -CREATE INDEX IF NOT EXISTS idx_search_history_username_id_created_at ON search_history(username, id, created_at DESC); -``` +-- ============================================= +-- 执行完成确认: +-- ┌ 所有 17 功能持久化:收藏/进度/历史/搜索自动保存到对应表,多端同步 +-- ┌ 站长全权限:设置环境变量 USERNAME=admin, PASSWORD=your_strong_pass 后,访问 /admin 登录 +-- └ 在 /admin 可编辑 admin_config JSON(如添加 "admin_users": ["newadmin"] 赋予权限、管理用户表) +-- ┌ 跳过片头/片尾:播放时自动应用 skip_configs(默认开启);管理员可在 /admin 批量设置 +-- └ 环境变量必设(Vercel/Cloudflare):NEXT_PUBLIC_STORAGE_TYPE=d1 +-- 其他:PASSWORD=your_pass, USERNAME=admin, NEXT_PUBLIC_ENABLE_REGISTER=false(生产关注册) +-- ============================================= diff --git a/config.json b/config.json index 3f16cede8c..801aff4a52 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,21 @@ { "cache_time": 7200, + "retry_attempts": 3, + "ad_skip_threshold": 6, + "default_theme": "auto", "api_site": { + "iqiyi": { + "api": "https://www.iqiyizyapi.com/api.php/provide/vod", + "name": "iqiyi资源", + "detail": "https://www.iqiyizyapi.com", + "is_adult": false + }, + "baidu": { + "api": "https://api.apibdzy.com/api.php/provide/vod", + "name": "百度云资源", + "detail": "https://api.apibdzy.com", + "is_adult": false + }, "1080zyku": { "api": "https://api.1080zyku.com/inc/api_mac10.php", "name": "TV-1080资源", @@ -331,12 +346,6 @@ "detail": "https://api.souavzy.vip", "is_adult": true }, - "lbapi9": { - "api": "https://lbapi9.com/api.php/provide/vod", - "name": "AV-乐播资源", - "detail": "", - "is_adult": true - }, "aosikazy": { "api": "https://aosikazy.com/api.php/provide/vod", "name": "AV-奥斯卡资源", @@ -373,12 +382,6 @@ "detail": "", "is_adult": true }, - "kxgav": { - "api": "https://www.kxgav.com/api/json.php", - "name": "AV-白嫖资源", - "detail": "https://www.kxgav.com", - "is_adult": true - }, "jingpinx": { "api": "https://www.jingpinx.com/api.php/provide/vod", "name": "AV-精品资源", @@ -415,12 +418,6 @@ "detail": "https://apilj.com", "is_adult": true }, - "gdlsp": { - "api": "https://www.gdlsp.com/api/json.php", - "name": "AV-香奶儿资源", - "detail": "https://www.gdlsp.com", - "is_adult": true - }, "shayuapi": { "api": "https://shayuapi.com/api.php/provide/vod", "name": "AV-鲨鱼资源", @@ -544,6 +541,166 @@ "api": "https://www.qiqidys.com/api.php/provide/vod/", "name": "七七影视", "is_adult": false + }, + "91md.me": { + "name": "🔞麻豆视频", + "api": "https://91md.me/api.php/provide/vod", + "detail": "https://91md.me" + }, + "91jpzyw.com": { + "name": "🔞91-精品-", + "api": "https://91jpzyw.com/api.php/provide/vod", + "detail": "https://91jpzyw.com" + }, + "ckzy.me": { + "name": "🔞 CK-资源", + "api": "https://ckzy.me/api.php/provide/vod", + "detail": "https://ckzy.me" + }, + "lbapiby.com": { + "name": "🔞--AIvin-", + "api": "http://lbapiby.com/api.php/provide/vod", + "detail": "http://lbapiby.com" + }, + "api.bwzym3u8.com": { + "name": "🔞百万资源", + "api": "https://api.bwzyz.com/api.php/provide/vod", + "detail": "https://api.bwzym3u8.com" + }, + "api.souavzy.vip": { + "name": "🔞souavZY", + "api": "https://api.souavzy.vip/api.php/provide/vod", + "detail": "https://api.souavzy.vip" + }, + "155zy2.com": { + "name": "🔞155-资源", + "api": "https://155api.com/api.php/provide/vod", + "detail": "https://155zy2.com" + }, + "apiyutu.com": { + "name": "🔞玉兔资源", + "api": "https://apiyutu.com/api.php/provide/vod", + "detail": "https://apiyutu.com" + }, + "fhapi9.com": { + "name": "🔞番号资源", + "api": "http://fhapi9.com/api.php/provide/vod", + "detail": "http://fhapi9.com" + }, + "www.kxgav.com": { + "name": "🔞白嫖资源", + "api": "https://www.kxgav.com/api/json.php", + "detail": "https://www.kxgav.com" + }, + "www.jingpinx.com": { + "name": "🔞精品资源", + "api": "https://www.jingpinx.com/api.php/provide/vod", + "detail": "https://www.jingpinx.com" + }, + "apilsbzy1.com": { + "name": "🔞-老色逼-", + "api": "https://apilsbzy1.com/api.php/provide/vod", + "detail": "https://apilsbzy1.com" + }, + "thzy8.me": { + "name": "🔞桃花资源", + "api": "https://thzy1.me/api.php/provide/vod", + "detail": "https://thzy8.me" + }, + "www.yyzywcj.com": { + "name": "🔞优优资源", + "api": "https://www.yyzywcj.com/api.php/provide/vod", + "detail": "https://www.yyzywcj.com" + }, + "xiaojizy.live": { + "name": "🔞小鸡资源", + "api": "https://api.xiaojizy.live/provide/vod", + "detail": "https://xiaojizy.live" + }, + "www.pgxdy.com": { + "name": "🔞-黄AVZY", + "api": "https://www.pgxdy.com/api/json.php", + "detail": "https://www.pgxdy.com" + }, + "hsckzy.xyz": { + "name": "🔞黄色仓库", + "api": "https://hsckzy.xyz/api.php/provide/vod", + "detail": "https://hsckzy.xyz" + }, + "apidanaizi.com": { + "name": "🔞-大奶子-", + "api": "https://apidanaizi.com/api.php/provide/vod", + "detail": "https://apidanaizi.com" + }, + "www.xxibaozyw.com": { + "name": "🔞细胞资源", + "api": "https://www.xxibaozyw.com/api.php/provide/vod", + "detail": "https://www.xxibaozyw.com" + }, + "jkunzyapi.com": { + "name": "🔞jkun资源", + "api": "https://jkunzyapi.com/api.php/provide/vod", + "detail": "https://jkunzyapi.com" + }, + "api.sexnguon.com": { + "name": "🔞-色南国-", + "api": "https://api.sexnguon.com/api.php/provide/vod", + "detail": "https://api.sexnguon.com" + }, + "lbapi9.com": { + "name": "🔞乐播资源", + "api": "https://lbapi9.com/api.php/provide/vod", + "detail": "https://lbapi9.com" + }, + "www.msnii.com": { + "name": "🔞-美少女-", + "api": "https://www.msnii.com/api/json.php", + "detail": "https://www.msnii.com" + }, + "Naixxzy.com": { + "name": "🔞奶香资源", + "api": "https://Naixxzy.com/api.php/provide/vod", + "detail": "https://Naixxzy.com" + }, + "slapibf.com": { + "name": "🔞森林资源", + "api": "https://beiyong.slapibf.com/api.php/provide/vod", + "detail": "https://slapibf.com" + }, + "apilj.com": { + "name": "🔞辣椒资源", + "api": "https://apilj.com/api.php/provide/vod", + "detail": "https://apilj.com" + }, + "shayuapi.com": { + "name": "🔞鲨鱼资源", + "api": "https://shayuapi.com/api.php/provide/vod", + "detail": "https://shayuapi.com" + }, + "xzytv.com": { + "name": "🔞-幸资源-", + "api": "https://xzybb2.com/api.php/provide/vod", + "detail": "https://xzytv.com" + }, + "zuisezy.com": { + "name": "🔞最色资源", + "api": "https://api.zuiseapi.com/api.php/provide/vod", + "detail": "https://zuisezy.com" + }, + "doudouzy.com": { + "name": "🔞豆豆资源", + "api": "https://api.douapi.cc/api.php/provide/vod", + "detail": "https://doudouzy.com" + }, + "didizy.com": { + "name": "🔞滴滴资源", + "api": "https://api.ddapi.cc/api.php/provide/vod", + "detail": "https://didizy.com" + }, + "xiangjiaozyw.com": { + "name": "🔞香蕉资源", + "api": "https://www.xiangjiaozyw.com/api.php/provide/vod", + "detail": "https://www.xiangjiaozyw.com" } } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f1e3f726b9..0fa6dc0b9d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,14 +1,10 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ - import type { Metadata, Viewport } from 'next'; import { Inter } from 'next/font/google'; - import './globals.css'; import 'sweetalert2/dist/sweetalert2.min.css'; - import { getConfig } from '@/lib/config'; import RuntimeConfig from '@/lib/runtime'; - import { GlobalErrorIndicator } from '../components/GlobalErrorIndicator'; import { SiteProvider } from '../components/SiteProvider'; import { ThemeProvider } from '../components/ThemeProvider'; @@ -25,7 +21,6 @@ export async function generateMetadata(): Promise { const config = await getConfig(); siteName = config.SiteConfig.SiteName; } - return { title: siteName, description: '影视聚合', @@ -58,6 +53,7 @@ export default async function RootLayout({ type: category.type, query: category.query, })) || ([] as Array<{ name: string; type: 'movie' | 'tv'; query: string }>); + if ( process.env.NEXT_PUBLIC_STORAGE_TYPE !== 'd1' && process.env.NEXT_PUBLIC_STORAGE_TYPE !== 'upstash' @@ -78,7 +74,6 @@ export default async function RootLayout({ })); } - // 将运行时配置注入到全局 window 对象,供客户端在运行时读取 const runtimeConfig = { STORAGE_TYPE: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage', ENABLE_REGISTER: enableRegister, @@ -89,14 +84,12 @@ export default async function RootLayout({ }; return ( - + - {/* 将配置序列化后直接写入脚本,浏览器端可通过 window.RUNTIME_CONFIG 获取 */} - {/* eslint-disable-next-line @next/next/no-sync-scripts */}