feat: 添加成人内容过滤功能

- 新增用户设置系统支持内容过滤开关
- 扩展类型定义支持成人内容标记
- 实现用户设置API端点(GET/PATCH/PUT)
- 增强搜索API支持内容分组和过滤
- 创建AdultContentFilter UI组件
- 添加用户设置页面和认证检查
- 更新配置示例和README文档
- 实现LocalStorage和Redis存储后端
- 默认启用过滤确保安全性
This commit is contained in:
katelya
2025-09-04 21:11:02 +08:00
parent c9429efba6
commit 86ebbb2cf6
12 changed files with 658 additions and 17 deletions
+52 -2
View File
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import { AdminConfig } from './admin.types';
import { EpisodeSkipConfig, Favorite, IStorage, PlayRecord } from './types';
import { EpisodeSkipConfig, Favorite, IStorage, PlayRecord, UserSettings } from './types';
/**
* LocalStorage 存储实现
@@ -290,6 +290,56 @@ export class LocalStorage implements IStorage {
}
}
// ---------- 用户设置 ----------
async getUserSettings(userName: string): Promise<UserSettings | null> {
if (typeof window === 'undefined') return null;
try {
const storageKey = this.getStorageKey('settings', userName);
const data = localStorage.getItem(storageKey);
if (data) {
return JSON.parse(data);
}
// 如果用户设置不存在,返回默认设置
const defaultSettings: UserSettings = {
filter_adult_content: true, // 默认开启成人内容过滤
theme: 'auto',
language: 'zh-CN',
auto_play: true,
video_quality: 'auto'
};
return defaultSettings;
} catch (error) {
console.error('Error getting user settings:', error);
return null;
}
}
async setUserSettings(userName: string, settings: UserSettings): Promise<void> {
if (typeof window === 'undefined') return;
try {
const storageKey = this.getStorageKey('settings', userName);
localStorage.setItem(storageKey, JSON.stringify(settings));
} catch (error) {
console.error('Error setting user settings:', error);
}
}
async updateUserSettings(userName: string, settings: Partial<UserSettings>): Promise<void> {
if (typeof window === 'undefined') return;
try {
const currentSettings = await this.getUserSettings(userName);
const updatedSettings = { ...currentSettings, ...settings };
await this.setUserSettings(userName, updatedSettings as UserSettings);
} catch (error) {
console.error('Error updating user settings:', error);
}
}
// ---------- 管理员功能 ----------
async getAllUsers(): Promise<string[]> {
if (typeof window === 'undefined') return [];
@@ -365,7 +415,7 @@ export class LocalStorage implements IStorage {
localStorage.removeItem(userKey);
// 删除用户相关的所有数据
const prefixes = ['playrecord', 'favorite', 'searchhistory', 'skipconfig'];
const prefixes = ['playrecord', 'favorite', 'searchhistory', 'skipconfig', 'settings'];
for (const prefix of prefixes) {
const dataPrefix = this.getStorageKey(prefix, userName);