diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index d1302da..8d91667 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -336,6 +336,7 @@ interface SiteConfig { PansouApiUrl?: string; PansouUsername?: string; PansouPassword?: string; + PansouKeywordBlocklist?: string; EnableComments: boolean; EnableRegistration?: boolean; RegistrationRequireTurnstile?: boolean; @@ -6679,6 +6680,7 @@ const SiteConfigComponent = ({ PansouApiUrl: '', PansouUsername: '', PansouPassword: '', + PansouKeywordBlocklist: '', EnableComments: false, EnableRegistration: false, RegistrationRequireTurnstile: false, @@ -6769,6 +6771,7 @@ const SiteConfigComponent = ({ PansouApiUrl: config.SiteConfig.PansouApiUrl || '', PansouUsername: config.SiteConfig.PansouUsername || '', PansouPassword: config.SiteConfig.PansouPassword || '', + PansouKeywordBlocklist: config.SiteConfig.PansouKeywordBlocklist || '', EnableComments: config.SiteConfig.EnableComments || false, }); } @@ -7508,6 +7511,28 @@ const SiteConfigComponent = ({ 配置账号密码后,系统会自动登录并缓存 Token

+ + {/* 关键词屏蔽 */} +
+ + + setSiteSettings((prev) => ({ + ...prev, + PansouKeywordBlocklist: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 设置后会过滤包含这些关键词的搜索结果 +

+
{/* 评论功能配置 */} diff --git a/src/app/api/admin/site/route.ts b/src/app/api/admin/site/route.ts index 4be703b..2a35297 100644 --- a/src/app/api/admin/site/route.ts +++ b/src/app/api/admin/site/route.ts @@ -49,6 +49,7 @@ export async function POST(request: NextRequest) { PansouApiUrl, PansouUsername, PansouPassword, + PansouKeywordBlocklist, EnableComments, CustomAdFilterCode, CustomAdFilterVersion, @@ -89,6 +90,7 @@ export async function POST(request: NextRequest) { PansouApiUrl?: string; PansouUsername?: string; PansouPassword?: string; + PansouKeywordBlocklist?: string; EnableComments: boolean; CustomAdFilterCode?: string; CustomAdFilterVersion?: number; @@ -129,6 +131,7 @@ export async function POST(request: NextRequest) { (TMDBReverseProxy !== undefined && typeof TMDBReverseProxy !== 'string') || (BannerDataSource !== undefined && typeof BannerDataSource !== 'string') || (RecommendationDataSource !== undefined && typeof RecommendationDataSource !== 'string') || + (PansouKeywordBlocklist !== undefined && typeof PansouKeywordBlocklist !== 'string') || typeof EnableComments !== 'boolean' || (CustomAdFilterCode !== undefined && typeof CustomAdFilterCode !== 'string') || (CustomAdFilterVersion !== undefined && typeof CustomAdFilterVersion !== 'number') || @@ -184,6 +187,7 @@ export async function POST(request: NextRequest) { PansouApiUrl, PansouUsername, PansouPassword, + PansouKeywordBlocklist, EnableComments, CustomAdFilterCode, CustomAdFilterVersion, diff --git a/src/app/api/pansou/search/route.ts b/src/app/api/pansou/search/route.ts index 7f10dff..89e87e4 100644 --- a/src/app/api/pansou/search/route.ts +++ b/src/app/api/pansou/search/route.ts @@ -3,7 +3,7 @@ import { NextRequest, NextResponse } from 'next/server'; import { getConfig } from '@/lib/config'; -import { searchPansou } from '@/lib/pansou.client'; +import { PansouLink, searchPansou } from '@/lib/pansou.client'; export const runtime = 'nodejs'; @@ -44,13 +44,50 @@ export async function POST(request: NextRequest) { password, }); + const rawBlocklist = config.SiteConfig.PansouKeywordBlocklist || ''; + const normalizedBlocklist = rawBlocklist.replace(/,/g, ','); + const blockedKeywords = normalizedBlocklist + .split(',') + .map((item) => item.trim()) + .filter(Boolean); + + let filteredResults = results; + + if (blockedKeywords.length > 0 && results.merged_by_type) { + const mergedByType: Record = {}; + let total = 0; + + const shouldBlock = (link: PansouLink) => { + const content = `${link.note || ''} ${link.url || ''} ${link.source || ''}`.toLowerCase(); + return blockedKeywords.some((item) => + content.includes(item.toLowerCase()) + ); + }; + + Object.entries(results.merged_by_type).forEach(([type, links]) => { + const filteredLinks = links.filter((link) => !shouldBlock(link)); + if (filteredLinks.length > 0) { + mergedByType[type] = filteredLinks; + total += filteredLinks.length; + } + }); + + filteredResults = { + ...results, + merged_by_type: mergedByType, + total, + }; + } + console.log('Pansou 搜索结果:', { - total: results.total, - hasData: !!results.merged_by_type, - types: results.merged_by_type ? Object.keys(results.merged_by_type) : [], + total: filteredResults.total, + hasData: !!filteredResults.merged_by_type, + types: filteredResults.merged_by_type + ? Object.keys(filteredResults.merged_by_type) + : [], }); - return NextResponse.json(results); + return NextResponse.json(filteredResults); } catch (error: any) { console.error('Pansou 搜索失败:', error); return NextResponse.json( diff --git a/src/lib/admin.types.ts b/src/lib/admin.types.ts index 2adde6f..3eff29f 100644 --- a/src/lib/admin.types.ts +++ b/src/lib/admin.types.ts @@ -29,6 +29,7 @@ export interface AdminConfig { PansouApiUrl?: string; PansouUsername?: string; PansouPassword?: string; + PansouKeywordBlocklist?: string; // 评论功能开关 EnableComments: boolean; // 自定义去广告代码 diff --git a/src/lib/config.ts b/src/lib/config.ts index 74ad294..6c09dd7 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -251,6 +251,11 @@ async function getInitConfig(configFile: string, subConfig: { TMDBApiKey: process.env.TMDB_API_KEY || '', TMDBProxy: process.env.TMDB_PROXY || '', TMDBReverseProxy: process.env.TMDB_REVERSE_PROXY || '', + // Pansou配置 + PansouApiUrl: '', + PansouUsername: '', + PansouPassword: '', + PansouKeywordBlocklist: '', // 评论功能开关 EnableComments: false, }, @@ -446,6 +451,10 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig { FluidSearch: true, DanmakuApiBase: 'http://localhost:9321', DanmakuApiToken: '87654321', + PansouApiUrl: '', + PansouUsername: '', + PansouPassword: '', + PansouKeywordBlocklist: '', EnableComments: false, }; } @@ -460,6 +469,9 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig { if (adminConfig.SiteConfig.EnableComments === undefined) { adminConfig.SiteConfig.EnableComments = false; } + if (adminConfig.SiteConfig.PansouKeywordBlocklist === undefined) { + adminConfig.SiteConfig.PansouKeywordBlocklist = ''; + } if (!adminConfig.UserConfig) { adminConfig.UserConfig = { Users: [] }; } @@ -665,4 +677,4 @@ export async function setCachedConfig(config: AdminConfig) { export async function clearConfigCache() { cachedConfig = null as any; configInitPromise = null; -} \ No newline at end of file +}