CLAUDE.md 7.0 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

个人开发项目。优先帮我把活干完、踩过的坑别再踩,不要纠结协作规范、提交模板、验证清单、影响面汇报这些东西。

项目概览

  • Loan Assistant / 借贷助手 客户端
  • 技术栈:Expo 55、React Native 0.83、React 19、TypeScript(strict)、expo-router(typedRoutes + reactCompiler)、NativeWind 4、@ant-design/react-native 5
  • 目标平台:iOS、Android、Web(部署在 /h5 子路径下)
  • 包管理器:pnpm(仓库以 pnpm-lock.yaml 为准)

命令

  • 使用 pnpm
  • package.json 已经列出常规命令。
  • 验证以 pnpm lint + 真机/模拟器为准。

大图架构

启动流程(src/app/_layout.tsx

RootLayout 渲染 <Stack> 之前按顺序:

  1. 加载 antd 图标字体(useFonts({ antoutline })
  2. POST common/check_version 检查原生版本,必要时弹 Modal 引导跳商店/下载链接(type: 'apk' | 'url'force 控制是否可取消)。最近一次检查时间存在 MMKV 的 last_update_app,15 分钟内不再重复
  3. expo-updates 拉热更新(__DEV__ 下完全跳过)
  4. Provider 嵌套顺序固定:ThemeProvider(react-navigation) → antd Provider(theme=antdTheme) → AuthProviderStack

新增全局 Provider 一律加在这里,不要散落到子页面。Stack.screenOptions 已设置了 iOS 风格透明模糊 header,新页面默认继承,特殊页(如 sign-in)通过 Stack.Screen 单独覆盖。

路由(src/app/

  • expo-router + experiments.typedRoutes,新增页面文件即新增路由,不需要中央路由表
  • 底部 Tab 在 src/app/(tabs)/index/customer/credit/reports/profile),改 Tab 结构同时改 (tabs)/_layout.tsx
  • 业务子流程目录:credit/customer/;登录注册:sign-in.tsxsign-up.tsx;Web 专属入口 web.tsx+html.tsx
  • app.json -> experiments.baseUrl: "/h5",Web 部署到 /h5,本地 dev server 也带这个前缀

网络层(src/utils/api.ts

唯一的 axios client:

  • baseURL 来自 src/config.jsonapi.url),不要绕开它硬编码
  • 自动注入 header x-app-namex-app-version(拼了 app.json version + 平台 versionCode/buildNumber + config.jsonjsVersion)、x-app-platform
  • access token 是模块级单例(setAccessToken / getAccessToken),由 AuthProvider 在登录/启动时注入;过期判断带 30 秒余量,过期会自动清空
  • 响应约定:HTTP 200 + data.code === "1" 才算成功,其它一律抛 ApiErrorHttpError 是父类,提供 is4xx/is5xx 等静态判断)
  • validateStatus 放行 200–499,5xx 才走 axios reject 路径
  • 文件上传走 uploadFile(用 expo/fetch,避开 RN 的 multipart 兼容问题)
  • __DEV__ 下挂了请求/响应拦截器打 console;生产构建由 metro.config.jsdrop_console: true 整体剔除

鉴权(src/utils/auth.tsx

  • AuthProvider 启动时从 MMKV access_token 读 token,调 setAccessToken 注入 api client
  • signIn / smsSignIn / signUp / signOut 调完接口后由调用方 setToken(...) 写回,Provider 同步落 MMKV 并切 authStatus
  • token 落盘用 getGlobalStorage().setObject(key, value, ttl),TTL 用接口返回的 expires_in(秒)

持久化(src/utils/storage.ts

三个独立 MMKV 实例,路径都落在 expo-file-systemcacheDirectory

  • getGlobalStorage() — 长期 KV(token、上次版本检查时间)
  • getCaches() — 业务通用缓存
  • getApiCache() — 接口结果缓存

扩展方法 setObject(key, value, ttlSeconds) / getObject(key) 把 TTL 编进 JSON;后台每 15 分钟扫一遍清理过期项。Web 端有 storage.web.ts 同名导出,靠 Metro 平台后缀分流。

主题与样式

平台分流

文件级用平台后缀:*.web.tsx*.tsx 共存即可(如 animated-icon.tsx / animated-icon.web.tsxstorage.ts / storage.web.ts)。避免在单文件里堆过多 Platform.OS 分支。

目录约定

  • src/app/expo-router 路由 / layout / 页面级 screen
  • src/components/ — 跨页面复用组件;src/components/ui/ 放更基础的 UI 积木
  • src/hooks/ — 自定义 hooks
  • src/utils/apiauthstoragecache 等基础能力
  • src/constants/ — 主题与常量
  • assets/ — 运行时资源
  • docs/antd/ — 本地 antd-rn 参考文档(llms-semantic.md / llms-full.txt / llms.txt),新增/调整 antd 组件优先查阅
  • design/ — 设计稿,作为运行时代码来源
  • android/ios/ — 原生工程,JS 改动默认不动
  • dist/ — 构建产物,不要手工编辑

路径别名(tsconfig.json):@/*src/*@/assets/*assets/*

踩坑提醒

  • React 19 + experiments.reactCompiler: true 已开启,为了"优化"到处补 useMemo / useCallback,编译器自己会处理
  • TypeScript strict,新代码别用 any 糊过去
  • 复用现有基础组件 / Tailwind token,别在页面里重复造按钮/输入框/弹窗/状态标签或散落魔法颜色值
  • airpush.sh <runtimeVersion> 发热更新时,runtimeVersion 必须等于已安装客户端的 app.json -> expo.version(policy 是 appVersion),否则设备拉不到
  • pnpm reset-project 会把 app/ 移走,正常开发绝对别跑
  • 不要引入重量级新依赖,除非现有方案明显不够用
  • app.json / babel.config.js / metro.config.js / tailwind.config.js 改前先想清楚影响面

仓库与外部上下文

  • 上一级目录 Loan/ 下还有 server/(后端)、expo-updates-server/(热更新服务)、ant-design-mobile-rn/(被 fork 的 antd-rn)等同胞仓库;改接口/热更新协议可能需要联动它们,但默认不跨仓改
  • 接口 base URL https://loan.ewaga.com/api/v1/,热更新服务 https://updates-loan.ewaga.com/
  • iOS bundleId / Android package:com.cdloan.assistant,应用显示名"借贷助手" / "Loan Assistant"
  • 代码签名证书在 code-signing/expo-updates 用它校验热更新包,提交私钥