diff --git a/client/global.d.ts b/client/global.d.ts new file mode 100644 index 0000000..2b52956 --- /dev/null +++ b/client/global.d.ts @@ -0,0 +1,8 @@ +/** + * React Native 全局常量声明。 + * + * 说明:`__DEV__` 在运行时由 RN 注入,用于区分开发/生产环境。 + * 这里补充 TypeScript 声明,避免在代码里使用时出现类型报错。 + */ +declare const __DEV__: boolean; + diff --git a/client/ios/client/Info.plist b/client/ios/client/Info.plist index f49cd82..156926d 100644 --- a/client/ios/client/Info.plist +++ b/client/ios/client/Info.plist @@ -52,7 +52,7 @@ RCTNewArchEnabled UILaunchStoryboardName - + SplashScreen UIRequiredDeviceCapabilities arm64 diff --git a/client/src/constants/env.ts b/client/src/constants/env.ts index 9c327d5..dda7a42 100644 --- a/client/src/constants/env.ts +++ b/client/src/constants/env.ts @@ -31,16 +31,34 @@ function getApiBaseUrl(env: AppRuntimeEnv): string { // 约定:local/dev/prod 三套域名分别配置, 便于后续直接切环境而不改代码 if (env === 'local') { - return getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_LOCAL', 'https://api.damer.fun'); + return getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_LOCAL', 'http://localhost:8000'); } if (env === 'dev') { return getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_DEV', getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_LOCAL', 'https://api.damer.fun')); } - return getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_PROD', getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_LOCAL', 'http://localhost:8000')); + return getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_PROD', getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_LOCAL', 'https://api.damer.fun')); } export const API_BASE_URL = getApiBaseUrl(APP_ENV); +/** + * 调试:打印环境变量注入结果(仅开发环境) + * + * 用途:排查「为什么 API_BASE_URL 不是预期值」的问题(例如 .env.local/命令行注入/缓存导致)。 + */ +if (__DEV__) { + const injected = { + EXPO_PUBLIC_ENV: process.env.EXPO_PUBLIC_ENV, + EXPO_PUBLIC_API_BASE_URL: process.env.EXPO_PUBLIC_API_BASE_URL, + EXPO_PUBLIC_API_BASE_URL_LOCAL: process.env.EXPO_PUBLIC_API_BASE_URL_LOCAL, + EXPO_PUBLIC_API_BASE_URL_DEV: process.env.EXPO_PUBLIC_API_BASE_URL_DEV, + EXPO_PUBLIC_API_BASE_URL_PROD: process.env.EXPO_PUBLIC_API_BASE_URL_PROD, + }; + console.log('[Env] 注入的 EXPO_PUBLIC_*(用于 API_BASE_URL 计算):', injected); + console.log('[Env] 解析得到 APP_ENV:', APP_ENV); + console.log('[Env] 解析得到 API_BASE_URL:', API_BASE_URL); +} + /** * 默认语言策略: * - auto:优先设备语言(支持列表内时),否则回退 en diff --git a/client/src/services/recoApi.ts b/client/src/services/recoApi.ts index 41000fc..a2c067c 100644 --- a/client/src/services/recoApi.ts +++ b/client/src/services/recoApi.ts @@ -37,20 +37,30 @@ export async function fetchRecoFeed(req: RecoRequest): Promise 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: { - 'Content-Type': 'application/json', - // 让后端做 locale 选择(目前后端只区分 en/tc) - 'Accept-Language': acceptLanguage, - }, - body: JSON.stringify({ - 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, - }), + headers, + body: JSON.stringify(bodyObj), signal: controller.signal, }); diff --git a/spec_kit/overview.md b/spec_kit/overview.md index d8bdb69..6121c73 100644 --- a/spec_kit/overview.md +++ b/spec_kit/overview.md @@ -18,6 +18,8 @@ - **已完成编码(阶段性)**: - Expo 工程已在 `client/` 初始化,并完成 `pnpm install` - i18n 基座已接入:5 份语言资源 + 设备语言优先/设置可切换/持久化 + 入口初始化 + - 推荐 Feed 请求链路增加调试日志(仅开发环境):打印 Feed API 请求头与请求体,便于联调排查 + - 环境变量注入增加调试日志(仅开发环境):打印参与 `API_BASE_URL` 计算的 `EXPO_PUBLIC_*` 与最终解析结果,便于定位“打到哪个后端” ## Client User Identity