import { useState } from 'react' import type { SearchParams, UserSettings } from '@/types' import { COMMON_FILE_TYPES } from '@/types' import { useTranslation } from '@/i18n' import { CollapsibleSection } from './CollapsibleSection' import { TagInput } from './TagInput' import { SearchAdapterFactory } from '@/services/adapters' import { EnginePreferenceService } from '@/services/engine-preference' import { useStorage } from '@/hooks/useStorage' interface SearchFormProps { searchParams: SearchParams onSearchParamsChange: (params: SearchParams) => void // Round 2: 支持外部控制的高级选项状态 showAdvanced?: boolean onToggleAdvanced?: (show: boolean) => void } export function SearchForm({ searchParams, onSearchParamsChange, showAdvanced: externalShowAdvanced, onToggleAdvanced }: SearchFormProps) { const [internalShowAdvanced, setInternalShowAdvanced] = useState(false) const { t } = useTranslation() // 使用外部状态或内部状态 const showAdvanced = externalShowAdvanced !== undefined ? externalShowAdvanced : internalShowAdvanced const setShowAdvanced = onToggleAdvanced || setInternalShowAdvanced // 🔥 从用户设置中获取引擎偏好 const { data: settings } = useStorage('user_settings') // 🔥 使用用户偏好的可见引擎列表(已排序) const visibleEngines = EnginePreferenceService.getVisibleEngines(settings?.enginePreferences) // 🔥 获取当前引擎的适配器和支持的功能 const adapter = SearchAdapterFactory.getAdapter(searchParams.engine) const supportedFeatures = adapter.getSupportedFeatures() // 🔥 检查功能是否支持 const isFeatureSupported = (feature: string) => { return supportedFeatures.includes(feature as any) } // 更新搜索参数 const updateParam = (key: K, value: SearchParams[K]) => { const newParams = { ...searchParams, [key]: value } onSearchParamsChange(newParams) } // 切换高级选项 const toggleAdvanced = () => { if (onToggleAdvanced) { onToggleAdvanced(!showAdvanced) } else { setShowAdvanced(!showAdvanced) } } return (
{/* 关键词输入 */}
updateParam('keyword', e.target.value)} placeholder={t('searchForm.keywordPlaceholder')} className="input" autoFocus />
{/* 搜索引擎选择 */}
{/* 高级选项切换按钮 */} {/* 🔥 动态高级选项 */} {showAdvanced && (
{/* ====== Twitter 专属功能 ====== */} {/* 用户筛选组 */} {isFeatureSupported('from_user') && ( {isFeatureSupported('from_user') && (
updateParam('fromUser', e.target.value)} placeholder={t('searchForm.fromUser.placeholder')} className="input" />

{t('searchForm.fromUser.description')}

)} {isFeatureSupported('to_user') && (
updateParam('toUser', e.target.value)} placeholder={t('searchForm.toUser.placeholder')} className="input" />

{t('searchForm.toUser.description')}

)}
)} {/* 互动筛选组 */} {isFeatureSupported('min_retweets') && ( {isFeatureSupported('min_retweets') && (
updateParam('minRetweets', Number(e.target.value))} placeholder={t('searchForm.minRetweets.placeholder')} className="input" min="0" />

{t('searchForm.minRetweets.description')}

)} {isFeatureSupported('min_faves') && (
updateParam('minFaves', Number(e.target.value))} placeholder={t('searchForm.minFaves.placeholder')} className="input" min="0" />

{t('searchForm.minFaves.description')}

)} {isFeatureSupported('content_filters') && (
{(['images', 'videos', 'links', 'media', 'replies', 'retweets', 'news'] as const).map((filter) => ( ))}

{t('searchForm.contentFilters.description')}

)}
)} {/* ====== 传统搜索引擎功能 ====== */} {/* 位置限定组 */} {isFeatureSupported('site') && ( {isFeatureSupported('site') && (
updateParam('site', e.target.value)} placeholder={t('searchForm.site.placeholder')} className="input" />

{t('searchForm.site.description')}

)} {isFeatureSupported('filetype') && (

{t('searchForm.fileType.description')}

)} {isFeatureSupported('intitle') && (
updateParam('inTitle', e.target.value)} placeholder={t('searchForm.inTitle.placeholder')} className="input" />

{t('searchForm.inTitle.description')}

)} {isFeatureSupported('inurl') && (
updateParam('inUrl', e.target.value)} placeholder={t('searchForm.inUrl.placeholder')} className="input" />

{t('searchForm.inUrl.description')}

)} {isFeatureSupported('intext') && (
updateParam('inText', e.target.value)} placeholder={t('searchForm.inText.placeholder')} className="input" />

{t('searchForm.inText.description')}

)}
)} {/* 匹配精度组 */} {isFeatureSupported('exact_match') && ( {isFeatureSupported('exact_match') && (
updateParam('exactMatch', e.target.value)} placeholder={t('searchForm.exactMatch.placeholder')} className="input" />

{t('searchForm.exactMatch.description')}

)} {isFeatureSupported('wildcard') && (
updateParam('wildcardQuery', e.target.value)} placeholder={t('searchForm.wildcardQuery.placeholder')} className="input" />

{t('searchForm.wildcardQuery.description')}

)} {isFeatureSupported('allintitle') && (
updateParam('allInTitle', e.target.value)} placeholder={t('searchForm.allInTitle.placeholder')} className="input" />

{t('searchForm.allInTitle.description')}

)}
)} {/* 逻辑运算组 */} {(isFeatureSupported('or_keywords') || isFeatureSupported('exclude')) && ( {isFeatureSupported('or_keywords') && (
updateParam('orKeywords', tags)} placeholder={t('searchForm.orKeywords.placeholder')} maxTags={5} />

{t('searchForm.orKeywords.description')}

)} {isFeatureSupported('exclude') && (
updateParam('excludeWords', tags)} placeholder={t('searchForm.excludeWords.placeholder')} maxTags={10} />

{t('searchForm.excludeWords.description')}

)}
)} {/* 范围过滤组 */} {(isFeatureSupported('date_range') || isFeatureSupported('number_range')) && ( {isFeatureSupported('date_range') && (
updateParam('dateRange', { from: e.target.value, to: searchParams.dateRange?.to || '' }) } className="input" placeholder={t('searchForm.dateRange.from')} />

{t('searchForm.dateRange.from')}

updateParam('dateRange', { from: searchParams.dateRange?.from || '', to: e.target.value }) } className="input" placeholder={t('searchForm.dateRange.to')} />

{t('searchForm.dateRange.to')}

{t('searchForm.dateRange.description')}

)} {isFeatureSupported('number_range') && (
updateParam('numberRange', { min: e.target.value ? Number(e.target.value) : undefined, max: searchParams.numberRange?.max } as any) } className="input" placeholder={t('searchForm.numberRange.min')} />

{t('searchForm.numberRange.min')}

updateParam('numberRange', { min: searchParams.numberRange?.min, max: e.target.value ? Number(e.target.value) : undefined } as any) } className="input" placeholder={t('searchForm.numberRange.max')} />

{t('searchForm.numberRange.max')}

{t('searchForm.numberRange.description')}

)}
)} {/* 特殊功能组 */} {(isFeatureSupported('related') || isFeatureSupported('cache') || adapter.getLanguageOptions?.()) && ( {isFeatureSupported('related') && (
updateParam('relatedSite', e.target.value)} placeholder={t('searchForm.relatedSite.placeholder')} className="input" />

{t('searchForm.relatedSite.description')}

)} {isFeatureSupported('cache') && (
updateParam('cacheSite', e.target.value)} placeholder={t('searchForm.cacheSite.placeholder')} className="input" />

{t('searchForm.cacheSite.description')}

)} {/* 🔥 动态语言选择器 - 根据适配器配置自动适配 */} {(() => { const languageConfig = adapter.getLanguageOptions?.() if (!languageConfig) return null return (

{searchParams.engine === 'twitter' && t('searchForm.language.description.twitter')} {searchParams.engine === 'github' && t('searchForm.language.description.github')}

) })()}
)}
)}
) }