fix: 修复账单删除功能并支持分析页面删除操作
Some checks are pending
Deploy BillAI / Deploy to Production (push) Waiting to run
Some checks are pending
Deploy BillAI / Deploy to Production (push) Waiting to run
- 将删除接口从 DELETE /api/bills/:id 改为 POST /api/bills/:id/delete 以兼容 SvelteKit 代理 - 分析页面组件 (TopExpenses/BillRecordsTable/DailyTrendChart) 支持删除并同步更新统计数据 - Review 接口改为直接查询 MongoDB 而非读取文件 - 软删除时记录 updated_at 时间戳 - 添加 .dockerignore 文件优化构建 - 完善 AGENTS.md 文档
This commit is contained in:
184
AGENTS.md
184
AGENTS.md
@@ -3,139 +3,125 @@
|
||||
Guidelines for AI coding agents working on BillAI - a microservices bill analysis system.
|
||||
|
||||
## Architecture
|
||||
- `web/` - SvelteKit 5 + TailwindCSS 4 + TypeScript
|
||||
- `server/` - Go 1.21 + Gin + MongoDB
|
||||
- `analyzer/` - Python 3.12 + FastAPI
|
||||
- `web/` - SvelteKit 5 + TailwindCSS 4 + TypeScript (Frontend Proxy & UI)
|
||||
- `server/` - Go 1.21 + Gin + MongoDB (Main API & Data Storage)
|
||||
- `analyzer/` - Python 3.12 + FastAPI (Data Cleaning & Analysis Service)
|
||||
|
||||
## Build/Lint/Test Commands
|
||||
|
||||
### Frontend (web/)
|
||||
**Working Directory:** `/Users/clz/Projects/BillAI/web`
|
||||
|
||||
```bash
|
||||
npm run dev # Start dev server
|
||||
npm run build # Production build
|
||||
npm run check # TypeScript check
|
||||
npm run check # TypeScript check (svelte-check)
|
||||
npm run lint # Prettier + ESLint
|
||||
npm run format # Format code
|
||||
npm run test # Run all tests
|
||||
npx vitest run src/routes/+page.spec.ts # Single test file
|
||||
npx vitest run -t "test name" # Test by name
|
||||
npm run format # Format code (Prettier)
|
||||
npm run test:unit # Run all unit tests (Vitest)
|
||||
npx vitest run src/routes/+page.spec.ts # Run single test file
|
||||
npx vitest run -t "test name" # Run test by name pattern
|
||||
```
|
||||
|
||||
### Backend (server/)
|
||||
**Working Directory:** `/Users/clz/Projects/BillAI/server`
|
||||
|
||||
```bash
|
||||
go run . # Start server
|
||||
go build . # Build binary
|
||||
go build -o server . # Build binary
|
||||
go mod tidy # Clean dependencies
|
||||
go test ./... # All tests
|
||||
go test ./handler/... # Package tests
|
||||
go test -run TestName # Single test
|
||||
go test ./... # Run all tests
|
||||
go test ./handler/... # Run package tests
|
||||
go test -run TestName # Run single test function
|
||||
go test -v ./handler/... # Run tests with verbose output
|
||||
```
|
||||
|
||||
### Analyzer (analyzer/)
|
||||
**Working Directory:** `/Users/clz/Projects/BillAI/analyzer`
|
||||
|
||||
```bash
|
||||
python server.py # Start FastAPI server
|
||||
pytest # All tests
|
||||
pytest test_file.py # Single file
|
||||
pytest -k "test_name" # Test by pattern
|
||||
python server.py # Start FastAPI server directly
|
||||
uvicorn server:app --reload # Start with hot reload
|
||||
pytest # Run all tests
|
||||
pytest test_file.py # Run single test file
|
||||
pytest -k "test_name" # Run test by name pattern
|
||||
pip install -r requirements.txt # Install dependencies
|
||||
```
|
||||
|
||||
### Docker
|
||||
**Working Directory:** `/Users/clz/Projects/BillAI`
|
||||
|
||||
```bash
|
||||
docker-compose up -d --build # Start/rebuild all
|
||||
docker-compose up -d --build # Start/rebuild all services
|
||||
docker-compose logs -f server # Follow service logs
|
||||
docker-compose down # Stop all services
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
### TypeScript/Svelte
|
||||
**Prettier config:** Tabs, single quotes, no trailing commas, width 100
|
||||
### General
|
||||
- **Comments:** Existing comments often use Chinese for business logic explanations. Maintain this style where appropriate, but English is also acceptable for technical explanations.
|
||||
- **Conventions:** Follow existing patterns strictly. Do not introduce new frameworks or libraries without checking `package.json`/`go.mod`/`requirements.txt`.
|
||||
|
||||
**Imports:**
|
||||
```typescript
|
||||
import { browser } from '$app/environment'; // SvelteKit
|
||||
import { auth } from '$lib/stores/auth'; // Internal
|
||||
import type { UIBill } from '$lib/models/bill';
|
||||
```
|
||||
### TypeScript/Svelte (web/)
|
||||
- **Formatting:** Prettier (Tabs, single quotes, no trailing commas, printWidth 100).
|
||||
- **Naming:** `PascalCase` for types/components/interfaces, `camelCase` for variables/functions.
|
||||
- **Imports:** Use `$lib` alias for internal imports.
|
||||
```typescript
|
||||
import { browser } from '$app/environment';
|
||||
import { auth } from '$lib/stores/auth';
|
||||
import type { UIBill } from '$lib/models/bill';
|
||||
```
|
||||
- **Types:** Define interfaces for data models. Use `export interface`.
|
||||
- **Error Handling:** Check `response.ok`. Throw `Error` with status for UI to catch.
|
||||
|
||||
**Types:**
|
||||
```typescript
|
||||
export interface UploadResponse {
|
||||
result: boolean;
|
||||
message: string;
|
||||
data?: UploadData;
|
||||
}
|
||||
```
|
||||
### Go Backend (server/)
|
||||
- **Structure:** `handler` (HTTP) → `service` (Logic) → `repository` (DB) → `model` (Structs).
|
||||
- **Tags:** Use `json` (snake_case) and `form` tags. Use `omitempty` for optional fields.
|
||||
```go
|
||||
type UpdateBillRequest struct {
|
||||
Category *string `json:"category,omitempty" form:"category"`
|
||||
}
|
||||
```
|
||||
- **Error Handling:** Return `500` for DB errors, `400` for bad requests. Wrap errors with context.
|
||||
```go
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, Response{Result: false, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
**Naming:** PascalCase (types, components), camelCase (functions, variables)
|
||||
|
||||
**Error handling:**
|
||||
```typescript
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`);
|
||||
}
|
||||
// Handle 401 -> logout redirect
|
||||
```
|
||||
|
||||
### Go Backend
|
||||
**Structure:** `handler/` → `service/` → `repository/` → MongoDB
|
||||
|
||||
**JSON tags:** snake_case, omitempty for optional fields
|
||||
```go
|
||||
type UpdateBillRequest struct {
|
||||
Category *string `json:"category,omitempty"`
|
||||
Amount *float64 `json:"amount,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
**Response format:**
|
||||
```go
|
||||
type Response struct {
|
||||
Result bool `json:"result"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
**Error handling:**
|
||||
```go
|
||||
if err == repository.ErrNotFound {
|
||||
c.JSON(http.StatusNotFound, Response{Result: false, Message: "not found"})
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
### Python Analyzer
|
||||
**Style:** PEP 8, type hints, Pydantic models
|
||||
|
||||
```python
|
||||
def do_clean(
|
||||
input_path: str,
|
||||
output_path: str,
|
||||
bill_type: str = "auto"
|
||||
) -> tuple[bool, str, str]:
|
||||
```
|
||||
|
||||
**Error handling:**
|
||||
```python
|
||||
if not success:
|
||||
raise HTTPException(status_code=400, detail=message)
|
||||
```
|
||||
### Python Analyzer (analyzer/)
|
||||
- **Style:** PEP 8. Use `snake_case` for variables/functions.
|
||||
- **Type Hints:** Mandatory for function arguments and return types.
|
||||
- **Models:** Use `pydantic.BaseModel` for API schemas.
|
||||
```python
|
||||
class CleanRequest(BaseModel):
|
||||
input_path: str
|
||||
bill_type: Optional[str] = "auto"
|
||||
```
|
||||
- **Docstrings:** Use triple quotes. Chinese descriptions are common for API docs.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
**API Flow:** Frontend (SvelteKit proxy) → Go API → MongoDB + Python analyzer
|
||||
- **API Flow:**
|
||||
- Frontend talks to `server` (Go) via `/api` proxy.
|
||||
- `server` handles auth, DB operations, and delegates complex file processing to `analyzer` (Python).
|
||||
- `analyzer` cleanses CSV/Excel files and returns structured JSON/CSV to `server`.
|
||||
|
||||
**Auth:** JWT tokens, Bearer header, 401 → logout redirect
|
||||
- **Authentication:**
|
||||
- JWT based. Token stored in frontend.
|
||||
- Header: `Authorization: Bearer <token>`.
|
||||
- Backend middleware checks token. 401 triggers logout/redirect.
|
||||
|
||||
**File Processing:** ZIP → extract → convert (GBK→UTF-8, xlsx→csv) → clean → import
|
||||
|
||||
**Testing:** Vitest + Playwright for frontend, Go test for backend
|
||||
- **File Processing:**
|
||||
- Flow: Upload (ZIP/XLSX) -> Extract/Convert (to UTF-8 CSV) -> Clean (normalize columns) -> Import to DB.
|
||||
- `analyzer` uses `openpyxl` for Excel and regex for cleaning text.
|
||||
|
||||
## Important Files
|
||||
- `web/src/lib/api.ts` - API client
|
||||
- `web/src/lib/models/` - UI data models
|
||||
- `server/handler/` - HTTP handlers
|
||||
- `server/service/` - Business logic
|
||||
- `server/model/` - Go data structures
|
||||
- `analyzer/cleaners/` - Bill processing
|
||||
- `mock_data/*.zip` - Test data (password: 123456)
|
||||
- `web/src/lib/api.ts` - Centralized API client methods.
|
||||
- `web/src/lib/models/*.ts` - Frontend data models (should match backend JSON).
|
||||
- `server/handler/*.go` - HTTP endpoint definitions.
|
||||
- `server/repository/mongo.go` - MongoDB connection and queries.
|
||||
- `analyzer/server.py` - FastAPI entry point and routing.
|
||||
- `analyzer/cleaners/*.py` - Specific logic for Alipay/Wechat/JD bills.
|
||||
|
||||
Reference in New Issue
Block a user