171 lines
5.9 KiB
MySQL
171 lines
5.9 KiB
MySQL
|
|
-- ============================================
|
||
|
|
-- MoonTV Plus - Cloudflare D1 数据库结构
|
||
|
|
-- 版本: 1.0.0
|
||
|
|
-- 创建时间: 2026-01-30
|
||
|
|
-- ============================================
|
||
|
|
|
||
|
|
-- 1. 用户表
|
||
|
|
CREATE TABLE IF NOT EXISTS users (
|
||
|
|
username TEXT PRIMARY KEY,
|
||
|
|
password_hash TEXT NOT NULL,
|
||
|
|
role TEXT NOT NULL CHECK(role IN ('owner', 'admin', 'user')),
|
||
|
|
banned INTEGER DEFAULT 0,
|
||
|
|
tags TEXT, -- JSON array: ["vip", "premium"]
|
||
|
|
oidc_sub TEXT UNIQUE,
|
||
|
|
enabled_apis TEXT, -- JSON array: ["api1", "api2"]
|
||
|
|
created_at INTEGER NOT NULL,
|
||
|
|
playrecord_migrated INTEGER DEFAULT 0,
|
||
|
|
favorite_migrated INTEGER DEFAULT 0,
|
||
|
|
skip_migrated INTEGER DEFAULT 0,
|
||
|
|
last_movie_request_time INTEGER,
|
||
|
|
email TEXT,
|
||
|
|
email_notifications INTEGER DEFAULT 1
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_users_oidc_sub ON users(oidc_sub) WHERE oidc_sub IS NOT NULL;
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_users_created_at ON users(created_at);
|
||
|
|
|
||
|
|
-- 2. 播放记录表
|
||
|
|
CREATE TABLE IF NOT EXISTS play_records (
|
||
|
|
username TEXT NOT NULL,
|
||
|
|
key TEXT NOT NULL, -- format: "source+id" (e.g., "tmdb+12345")
|
||
|
|
title TEXT NOT NULL,
|
||
|
|
source_name TEXT NOT NULL,
|
||
|
|
cover TEXT,
|
||
|
|
year TEXT,
|
||
|
|
episode_index 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,
|
||
|
|
PRIMARY KEY (username, key),
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_play_records_save_time ON play_records(username, save_time DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_play_records_source ON play_records(username, source_name);
|
||
|
|
|
||
|
|
-- 3. 收藏表
|
||
|
|
CREATE TABLE IF NOT EXISTS favorites (
|
||
|
|
username TEXT NOT NULL,
|
||
|
|
key TEXT NOT NULL, -- format: "source+id"
|
||
|
|
source_name TEXT NOT NULL,
|
||
|
|
total_episodes INTEGER NOT NULL,
|
||
|
|
title TEXT NOT NULL,
|
||
|
|
year TEXT,
|
||
|
|
cover TEXT,
|
||
|
|
save_time INTEGER NOT NULL,
|
||
|
|
search_title TEXT,
|
||
|
|
origin TEXT CHECK(origin IN ('vod', 'live')),
|
||
|
|
is_completed INTEGER DEFAULT 0,
|
||
|
|
vod_remarks TEXT,
|
||
|
|
PRIMARY KEY (username, key),
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_favorites_save_time ON favorites(username, save_time DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_favorites_source ON favorites(username, source_name);
|
||
|
|
|
||
|
|
-- 4. 搜索历史表
|
||
|
|
CREATE TABLE IF NOT EXISTS search_history (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
username TEXT NOT NULL,
|
||
|
|
keyword TEXT NOT NULL,
|
||
|
|
timestamp INTEGER NOT NULL,
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE,
|
||
|
|
UNIQUE(username, keyword)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_search_history_user_time ON search_history(username, timestamp DESC);
|
||
|
|
|
||
|
|
-- 5. 跳过配置表(片头片尾)
|
||
|
|
CREATE TABLE IF NOT EXISTS skip_configs (
|
||
|
|
username TEXT NOT NULL,
|
||
|
|
key TEXT NOT NULL, -- format: "source+id"
|
||
|
|
enable INTEGER NOT NULL DEFAULT 1,
|
||
|
|
intro_time INTEGER NOT NULL DEFAULT 0, -- 片头时长(秒)
|
||
|
|
outro_time INTEGER NOT NULL DEFAULT 0, -- 片尾时长(秒)
|
||
|
|
PRIMARY KEY (username, key),
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
-- 6. 弹幕过滤配置表
|
||
|
|
CREATE TABLE IF NOT EXISTS danmaku_filter_configs (
|
||
|
|
username TEXT PRIMARY KEY,
|
||
|
|
rules TEXT NOT NULL, -- JSON array: [{"keyword": "xxx", "type": "normal", "enabled": true}]
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
-- 7. 通知表
|
||
|
|
CREATE TABLE IF NOT EXISTS notifications (
|
||
|
|
id TEXT PRIMARY KEY,
|
||
|
|
username TEXT NOT NULL,
|
||
|
|
type TEXT NOT NULL CHECK(type IN ('favorite_update', 'system', 'announcement', 'movie_request', 'request_fulfilled')),
|
||
|
|
title TEXT NOT NULL,
|
||
|
|
message TEXT NOT NULL,
|
||
|
|
timestamp INTEGER NOT NULL,
|
||
|
|
read INTEGER DEFAULT 0,
|
||
|
|
metadata TEXT, -- JSON object
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_user_time ON notifications(username, timestamp DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_user_read ON notifications(username, read, timestamp DESC);
|
||
|
|
|
||
|
|
-- 8. 求片请求表
|
||
|
|
CREATE TABLE IF NOT EXISTS movie_requests (
|
||
|
|
id TEXT PRIMARY KEY,
|
||
|
|
tmdb_id INTEGER,
|
||
|
|
title TEXT NOT NULL,
|
||
|
|
year TEXT,
|
||
|
|
media_type TEXT NOT NULL CHECK(media_type IN ('movie', 'tv')),
|
||
|
|
season INTEGER,
|
||
|
|
poster TEXT,
|
||
|
|
overview TEXT,
|
||
|
|
requested_by TEXT NOT NULL, -- JSON array: ["user1", "user2"]
|
||
|
|
request_count INTEGER NOT NULL DEFAULT 1,
|
||
|
|
status TEXT NOT NULL CHECK(status IN ('pending', 'fulfilled')) DEFAULT 'pending',
|
||
|
|
created_at INTEGER NOT NULL,
|
||
|
|
updated_at INTEGER NOT NULL,
|
||
|
|
fulfilled_at INTEGER,
|
||
|
|
fulfilled_source TEXT,
|
||
|
|
fulfilled_id TEXT
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_movie_requests_status ON movie_requests(status, created_at DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_movie_requests_tmdb ON movie_requests(tmdb_id) WHERE tmdb_id IS NOT NULL;
|
||
|
|
|
||
|
|
-- 9. 用户求片关联表(用于快速查询用户的求片记录)
|
||
|
|
CREATE TABLE IF NOT EXISTS user_movie_requests (
|
||
|
|
username TEXT NOT NULL,
|
||
|
|
request_id TEXT NOT NULL,
|
||
|
|
PRIMARY KEY (username, request_id),
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE,
|
||
|
|
FOREIGN KEY (request_id) REFERENCES movie_requests(id) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_user_movie_requests_user ON user_movie_requests(username);
|
||
|
|
|
||
|
|
-- 10. 全局配置表(键值对存储)
|
||
|
|
CREATE TABLE IF NOT EXISTS global_config (
|
||
|
|
key TEXT PRIMARY KEY,
|
||
|
|
value TEXT NOT NULL,
|
||
|
|
updated_at INTEGER NOT NULL
|
||
|
|
);
|
||
|
|
|
||
|
|
-- 11. 管理员配置表(单例)
|
||
|
|
CREATE TABLE IF NOT EXISTS admin_config (
|
||
|
|
id INTEGER PRIMARY KEY CHECK(id = 1), -- 确保只有一条记录
|
||
|
|
config TEXT NOT NULL, -- JSON object
|
||
|
|
updated_at INTEGER NOT NULL
|
||
|
|
);
|
||
|
|
|
||
|
|
-- 12. 收藏更新检查时间表
|
||
|
|
CREATE TABLE IF NOT EXISTS favorite_check_times (
|
||
|
|
username TEXT PRIMARY KEY,
|
||
|
|
last_check_time INTEGER NOT NULL,
|
||
|
|
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE
|
||
|
|
);
|