import i18n from 'i18next'; import { API_BASE_URL } from '@/src/constants/env'; import type { UserProfileV1_2 } from '@/src/features/userProfileScoring'; export type RecommendedItem = { content_id: number; text: string; final_score: number; fallback_level_final: number; explanations?: Record | null; }; export type RecoMeta = Record; export type RecoEngineResult = { items: RecommendedItem[]; meta: RecoMeta; }; export type RecoRequest = { k?: number; user_profile: UserProfileV1_2; already_recommended_ids?: Array; touched_or_viewed_ids?: Array; now?: string; // ISO8601(可选) }; function withTimeout(ms: number): AbortController { const controller = new AbortController(); setTimeout(() => controller.abort(), ms); return controller; } export async function fetchRecoFeed(req: RecoRequest): Promise { const controller = withTimeout(12_000); const url = `${API_BASE_URL}/v1/reco/feed`; const acceptLanguage = i18n.language?.toLowerCase().startsWith('zh') ? 'tc' : 'en'; const headers: Record = { 'Content-Type': 'application/json', // 让后端做 locale 选择(目前后端只区分 en/tc) 'Accept-Language': acceptLanguage, }; const bodyObj = { k: req.k, user_profile: req.user_profile, already_recommended_ids: req.already_recommended_ids ?? [], touched_or_viewed_ids: req.touched_or_viewed_ids ?? [], now: req.now, }; // 仅在开发环境打印,避免生产环境日志泄露敏感信息 if (__DEV__) { console.log('[Feed API] 请求地址:', url); console.log('[Feed API] Feed的API请求头:', headers); console.log('[Feed API] Feed的API请求体:', bodyObj); } const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(bodyObj), signal: controller.signal, }); if (!res.ok) { const text = await res.text().catch(() => ''); throw new Error(`推荐接口请求失败:${res.status} ${res.statusText} ${text}`.trim()); } return (await res.json()) as RecoEngineResult; }