u
This commit is contained in:
1 parent
513a991b57
commit
8f8e8d03c8
22 files changed
+2212
-213
No files matched your search
@@ -0,0 +1,141 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Allapp is a family/space mini-program platform — a main shell with sub-apps inside it. The frontend owns most business logic; the backend is deliberately thin and generic (auth, file storage, ID generation, database access).
|
||||
|
||||
- **Backend**: `app-go/` — Go 1.25, Fiber v3.1, pgx (PostgreSQL), JWT, Viper, Zap
|
||||
- **Frontend**: `app-rn/` — React Native 0.85, Expo 56, Expo Router, Zustand, Alova, HeroUI Native, Uniwind (Tailwind CSS)
|
||||
- **Database**: PostgreSQL 18.1, database `allapp`, schema `public`
|
||||
|
||||
Read `PROJECT_CONTEXT.md` for deeper context; this file focuses on what you need day-to-day.
|
||||
|
||||
## Commands
|
||||
|
||||
### Backend (`app-go/`)
|
||||
|
||||
```bash
|
||||
cd app-go
|
||||
go build ./cmd/app # Build
|
||||
go run ./cmd/app # Run server
|
||||
go test ./... # Run all tests
|
||||
go mod tidy # Tidy dependencies
|
||||
```
|
||||
|
||||
### Frontend (`app-rn/`)
|
||||
|
||||
```bash
|
||||
cd app-rn
|
||||
pnpm start # Expo dev server (port 8083)
|
||||
pnpm android # Android build
|
||||
pnpm ios # iOS build
|
||||
pnpm lint # oxlint
|
||||
pnpm exec tsc --noEmit # TypeScript type check
|
||||
pnpm exec oxfmt # Format code
|
||||
```
|
||||
|
||||
WSL-specific: if `node`/`pnpm` are not found, run:
|
||||
```bash
|
||||
export PATH="$HOME/.local/share/fnm:$PATH"
|
||||
eval "$(fnm env --shell bash)"
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Bootstrap Flow
|
||||
|
||||
```
|
||||
Backend: config → logger → S3 → Postgres → db.Init → unique ID → JWT → WeChat → Fiber server
|
||||
Frontend: /index → token check → auth/login or family/entry or /home
|
||||
```
|
||||
|
||||
### Backend Design
|
||||
|
||||
**All CRUD goes through 5 generic data APIs.** Never create dedicated REST endpoints for feature-specific operations:
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|---|---|
|
||||
| `POST /app/data/loadData` | Query by table/view name, conditions, columns, order, args |
|
||||
| `POST /app/data/loadDataPage` | Paginated query — same as loadData + `page`/`page_size`, returns `{rows, total, page, page_size}` |
|
||||
| `POST /app/data/loadDataBySql` | Raw SQL query |
|
||||
| `POST /app/data/saveData` | Batch insert/update/delete by table name and key field |
|
||||
| `POST /app/data/getUniqueId` | Get snowflake IDs (1–100) |
|
||||
|
||||
Auth endpoints: `/app/auth/login/{qq,wechat,test}`, `/app/bind/{qq,wechat}`.
|
||||
|
||||
**File endpoints:**
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|---|---|
|
||||
| `POST /app/s3/upload` | Upload files (multipart form, field name `files`), stored under `YYYY/MM/DD/{uuid}.ext`, returns `string[]` keys |
|
||||
| `POST /app/s3/delete` | Delete files by keys, body `{keys: string[]}`, failure is logged but still returns success |
|
||||
|
||||
On the frontend: `s3UploadFileApi(files[])` wraps files into a `FormData` with key `"files"` and `multipart/form-data` content type.
|
||||
|
||||
Auth token is passed in a custom `Token` header. JWT middleware stores `user_id` in context. Audit fields (`create_time`, `update_time`, `create_by`, `update_by`) are auto-injected by `pkg/db/meta_field.go` for all tables except `b_user` and `b_user_oauth`.
|
||||
|
||||
### Frontend Design
|
||||
|
||||
Expo Router file-based routing under `src/app/`:
|
||||
- `(main)/(tabs)/` — main shell tabs (home, chat, my)
|
||||
- `(main)/auth/`, `(main)/family/`, `(main)/tools/`, `(main)/activities/`
|
||||
- `finance/(tabs)/` — finance sub-app (independent from main)
|
||||
- Layouts: `AppLayout` for main shell, `ModuleLayout` for sub-app shells, `PageLayout` for simple pages
|
||||
|
||||
State: Zustand with `persist` middleware for `user` and `family` (AsyncStorage). Finance store is in-memory only.
|
||||
|
||||
API layer: single Alova instance (`src/request/index.ts`), API wrappers in `src/request/api.ts`. Key wrappers: `loadDataApi`, `loadDataPageApi` (paginated, returns `PageData<T>` with `rows`/`total`/`page`/`page_size`), `loadDataBySqlApi`, `saveDataApi`, `getUniqueIdApi`. Response codes: 1000 (success), 1001 (unauthorized → redirect to login), 2000 (business error), 3000 (system error).
|
||||
|
||||
Startup flow in `src/app/index.tsx`:
|
||||
```
|
||||
no token → /auth/login
|
||||
token invalid → /auth/login
|
||||
no family → /family/entry
|
||||
has family → /home
|
||||
```
|
||||
|
||||
## Critical Conventions
|
||||
|
||||
### 1. No New Dedicated API Endpoints
|
||||
Always reuse the 5 generic data APIs. If you think a new endpoint is needed, **ask the user first**. Even then, new endpoints must be generic helpers, not feature-specific.
|
||||
|
||||
### 2. Database Tables Must Include Audit Columns
|
||||
All new business tables must include: `id BIGINT PRIMARY KEY` (snowflake), `create_time TIMESTAMPTZ`, `update_time TIMESTAMPTZ`, `create_by BIGINT`, `update_by BIGINT`. Do not add new tables to `auditExcludeTables` — only `b_user` and `b_user_oauth` are exempt.
|
||||
|
||||
### 3. Family/Space-Centric Data Model
|
||||
All business data (finance, favorites, etc.) associates with `family_id`. Users link to families via `b_family_member`. Always filter queries by the current user's `family_id`.
|
||||
|
||||
### 4. Family Feed Recording
|
||||
Certain actions must call `recordFeed()` from `@/helpers/feed`. Use `{nickname}` placeholder in content — do NOT hardcode nicknames. The `loadFeeds()` helper replaces it dynamically. Scenarios: creating/joining family (`join`), renaming (`rename`), recording bills (`bill`), favoriting apps (`fav`).
|
||||
|
||||
### 5. Frontend: Use Existing Libraries Only
|
||||
Before writing any page/component, check `app-rn/package.json` for available dependencies. Use HeroUI Native for UI, `@legendapp/list` for long lists, `lucide-react-native` for icons, `sonner-native` for toasts. Use NativeWind `className` for styling, not inline `style={}`.
|
||||
|
||||
### 6. Finance Convention
|
||||
`type = 0` means expense, `type = 1` means income. Category icon names match iconfont names (e.g., `finance_jiaotong`, `finance_canyin`).
|
||||
|
||||
## Key Files
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `PROJECT_CONTEXT.md` | Full project documentation, risks, feature status |
|
||||
| `app-go/internal/bootstrap/app.go` | Backend initialization flow |
|
||||
| `app-go/internal/router/router.go` | Route definitions |
|
||||
| `app-go/pkg/db/meta_field.go` | Audit field auto-injection |
|
||||
| `app-rn/src/app/index.tsx` | Startup/auth routing logic |
|
||||
| `app-rn/src/request/index.ts` | Alova instance, auth interceptor |
|
||||
| `app-rn/src/request/api.ts` | API wrapper functions |
|
||||
| `app-rn/src/store/` | Zustand stores (user, family, finance, app, favorite) |
|
||||
| `app-rn/src/layouts/` | Shell layouts (AppLayout, ModuleLayout, PageLayout) |
|
||||
| `app-rn/src/configs/pages.ts` | Sub-app definitions |
|
||||
| `app-rn/src/helpers/feed.ts` | Family feed recording |
|
||||
|
||||
## Known Risks
|
||||
|
||||
- Generic data APIs accept table names and raw SQL from the frontend — needs server-side whitelisting before production.
|
||||
- `db.local.yml` contains database credentials and should never be committed.
|
||||
- Finance category queries currently don't filter by `family_id`.
|
||||
- Main tab `/space` route is missing its page file.
|
||||
- `GetUniqueIdReq.Count` uses `binding` tag instead of `validate` tag — min/max rules may not run.
|
||||
Reference in new issue
Block a user