Files
app_02_bill/docs/后端API接口设计文档.md
karlcarlo c06e74bd01 feat(app): 实现完整的财务管家记账聊天与统计功能
- 新增App主组件,实现聊天、账本、统计三大功能模块切换
- 支持语音及文本输入,自动解析记账信息并生成交易记录
- 交易记录支持编辑、删除、提醒等操作,数据本地持久化
- 管家性格预设和自定义设定,包含头像上传和语气调整
- 会话展示支持关联交易显示,样式区分收入与支出
- 账本页添加日期分组交易列表及饼图统计展示
- 消息列表实现渐变背景和交互动画,提升用户体验
- 支持图片上传并同步发送给AI进行解析记账
- 底部导航实现三标签切换并同步显示对应内容
- 全局事务编辑弹窗支持直接调用和删除操作
- 增加环境变量示例和.gitignore规则,完善工程配置
2026-01-19 20:20:54 +08:00

1687 lines
34 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后端API接口设计文档
## 技术栈
- **框架**: FastAPI 0.104+
- **数据库**: MongoDB
- **ODM**: Beanie 1.23+
- **认证**: JWT (可选)
- **部署**: Uvicorn
---
## 统一响应格式
### 单例数据响应
```json
{
"code": 200,
"msg": "ok",
"result": {}
}
```
### 分页列表响应
```json
{
"code": 200,
"msg": "ok",
"result": {
"items": [],
"skip": 0,
"total": 0
}
}
```
### 错误响应
```json
{
"code": 400,
"msg": "错误描述",
"result": null
}
```
---
## 数据模型定义 (Beanie Models)
### 1. Transaction 交易记录模型
```python
from beanie import Document
from pydantic import Field
from typing import Optional
from datetime import datetime
from enum import Enum
class TransactionType(str, Enum):
"""交易类型枚举"""
EXPENSE = "expense"
INCOME = "income"
class ExpenseCategory(str, Enum):
"""支出分类枚举"""
FOOD = "餐饮"
SHOPPING = "购物"
TRANSPORT = "交通"
HOUSING = "住房"
ENTERTAINMENT = "娱乐"
MEDICAL = "医疗"
SOCIAL = "人情"
EDUCATION = "学习"
FINANCE = "金融"
CHILD = "孩子"
PET = "宠物"
CAR = "汽车"
BEAUTY = "美容"
BUSINESS = "经营"
MISC = "杂项"
class IncomeCategory(str, Enum):
"""收入分类枚举"""
SALARY = "工资"
BONUS = "奖金"
INVESTMENT = "理财"
PARTTIME = "兼职"
GIFT = "红包"
OTHER = "其他收入"
class Transaction(Document):
"""交易记录文档模型"""
user_id: str = Field(..., description="用户ID")
item: str = Field(..., min_length=1, max_length=200, description="交易项目名称")
amount: float = Field(..., gt=0, description="交易金额")
type: TransactionType = Field(..., description="交易类型")
category: str = Field(..., description="交易分类")
date: str = Field(..., description="交易日期 YYYY-MM-DD")
timestamp: int = Field(..., description="时间戳(毫秒)")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class Settings:
name = "transactions"
indexes = [
"user_id",
"date",
"type",
[("user_id", 1), ("date", -1)],
[("user_id", 1), ("type", 1)],
]
class Config:
json_schema_extra = {
"example": {
"user_id": "user_123",
"item": "午餐",
"amount": 35.5,
"type": "expense",
"category": "餐饮",
"date": "2026-01-19",
"timestamp": 1737331200000
}
}
```
### 2. Message 聊天消息模型
```python
from typing import Optional
class MessageRole(str, Enum):
"""消息角色枚举"""
USER = "user"
ASSISTANT = "assistant"
class Message(Document):
"""聊天消息文档模型"""
user_id: str = Field(..., description="用户ID")
role: MessageRole = Field(..., description="消息角色")
content: str = Field(..., description="消息内容")
timestamp: int = Field(..., description="时间戳(毫秒)")
related_transaction_id: Optional[str] = Field(None, description="关联的交易ID")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
class Settings:
name = "messages"
indexes = [
"user_id",
"timestamp",
[("user_id", 1), ("timestamp", -1)],
]
class Config:
json_schema_extra = {
"example": {
"user_id": "user_123",
"role": "user",
"content": "花了30块钱吃午饭",
"timestamp": 1737331200000,
"related_transaction_id": None
}
}
```
### 3. Budget 预算模型
```python
from typing import Dict
class Budget(Document):
"""预算文档模型"""
user_id: str = Field(..., description="用户ID")
budgets: Dict[str, float] = Field(..., description="预算字典 {名称: 金额}")
month: str = Field(..., description="预算月份 YYYY-MM")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class Settings:
name = "budgets"
indexes = [
"user_id",
[("user_id", 1), ("month", 1)],
]
class Config:
json_schema_extra = {
"example": {
"user_id": "user_123",
"budgets": {
"总预算": 3000,
"餐饮预算": 1000,
"购物预算": 500
},
"month": "2026-01"
}
}
```
### 4. BillReminder 账单提醒模型
```python
class ReminderFrequency(str, Enum):
"""提醒频率枚举"""
MONTHLY = "monthly"
ONCE = "once"
class BillReminder(Document):
"""账单提醒文档模型"""
user_id: str = Field(..., description="用户ID")
title: str = Field(..., min_length=1, max_length=100, description="提醒标题")
amount: Optional[float] = Field(None, gt=0, description="金额(可选)")
frequency: ReminderFrequency = Field(..., description="频率")
target_date: str = Field(..., description="目标日期: DD(每月) 或 YYYY-MM-DD(单次)")
is_completed: bool = Field(default=False, description="完成状态")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class Settings:
name = "bill_reminders"
indexes = [
"user_id",
"frequency",
[("user_id", 1), ("is_completed", 1)],
]
class Config:
json_schema_extra = {
"example": {
"user_id": "user_123",
"title": "信用卡还款",
"amount": 5000,
"frequency": "monthly",
"target_date": "15",
"is_completed": False
}
}
```
### 5. AISettings AI设置模型
```python
class AISettings(Document):
"""AI助手设置文档模型"""
user_id: str = Field(..., description="用户ID", unique=True)
name: str = Field(..., min_length=1, max_length=50, description="AI助手名称")
persona: str = Field(..., min_length=1, max_length=500, description="AI性格描述")
avatar: Optional[str] = Field(None, description="头像Base64编码")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class Settings:
name = "ai_settings"
indexes = ["user_id"]
class Config:
json_schema_extra = {
"example": {
"user_id": "user_123",
"name": "崔经理",
"persona": "一个精明、毒舌但实际上很负责任的财务经理...",
"avatar": None
}
}
```
### 6. UserPreference 用户偏好模型
```python
class UserPreference(Document):
"""用户偏好设置文档模型"""
user_id: str = Field(..., description="用户ID", unique=True)
custom_preset_name: str = Field(default="自定义", description="自定义预设名称")
custom_preset_description: str = Field(
default="可以根据你喜欢的方式设定助手的语气和风格",
description="自定义预设描述"
)
theme_index: int = Field(default=0, ge=0, le=4, description="主题索引")
created_at: datetime = Field(default_factory=datetime.utcnow, description="创建时间")
updated_at: datetime = Field(default_factory=datetime.utcnow, description="更新时间")
class Settings:
name = "user_preferences"
indexes = ["user_id"]
class Config:
json_schema_extra = {
"example": {
"user_id": "user_123",
"custom_preset_name": "自定义",
"custom_preset_description": "温柔又严格的助手",
"theme_index": 0
}
}
```
---
## API接口设计
### 基础URL
```
https://api.example.com/api/v1
```
---
## 一、交易记录接口
### 1.1 创建交易记录
**接口**: `POST /transactions`
**请求体**:
```json
{
"item": "午餐",
"amount": 35.5,
"type": "expense",
"category": "餐饮",
"date": "2026-01-19",
"timestamp": 1737331200000
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"item": "午餐",
"amount": 35.5,
"type": "expense",
"category": "餐饮",
"date": "2026-01-19",
"timestamp": 1737331200000,
"created_at": "2026-01-19T10:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
}
```
**FastAPI实现示例**:
```python
from fastapi import APIRouter, Depends, HTTPException
from typing import List
from pydantic import BaseModel
router = APIRouter(prefix="/transactions", tags=["交易记录"])
class TransactionCreate(BaseModel):
item: str
amount: float
type: TransactionType
category: str
date: str
timestamp: int
class ResponseModel(BaseModel):
code: int = 200
msg: str = "ok"
result: dict | None = None
@router.post("", response_model=ResponseModel)
async def create_transaction(
data: TransactionCreate,
user_id: str = Depends(get_current_user_id)
):
"""创建交易记录"""
transaction = Transaction(
user_id=user_id,
**data.dict()
)
await transaction.insert()
return ResponseModel(
code=200,
msg="ok",
result=transaction.dict(by_alias=True)
)
```
---
### 1.2 查询交易记录列表(分页)
**接口**: `GET /transactions`
**查询参数**:
- `skip`: int = 0 (分页偏移)
- `limit`: int = 20 (每页数量,最大100)
- `type`: str (可选,筛选类型: expense/income)
- `category`: str (可选,筛选分类)
- `date_from`: str (可选,起始日期 YYYY-MM-DD)
- `date_to`: str (可选,结束日期 YYYY-MM-DD)
- `month`: str (可选,月份筛选 YYYY-MM)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"items": [
{
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"item": "午餐",
"amount": 35.5,
"type": "expense",
"category": "餐饮",
"date": "2026-01-19",
"timestamp": 1737331200000,
"created_at": "2026-01-19T10:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
],
"skip": 0,
"total": 100
}
}
```
**FastAPI实现示例**:
```python
class PaginatedResponse(BaseModel):
code: int = 200
msg: str = "ok"
result: dict
@router.get("", response_model=PaginatedResponse)
async def list_transactions(
skip: int = 0,
limit: int = 20,
type: Optional[TransactionType] = None,
category: Optional[str] = None,
date_from: Optional[str] = None,
date_to: Optional[str] = None,
month: Optional[str] = None,
user_id: str = Depends(get_current_user_id)
):
"""查询交易记录列表"""
query = {"user_id": user_id}
if type:
query["type"] = type
if category:
query["category"] = category
if date_from and date_to:
query["date"] = {"$gte": date_from, "$lte": date_to}
elif month:
query["date"] = {"$regex": f"^{month}"}
total = await Transaction.find(query).count()
items = await Transaction.find(query)\
.sort([("date", -1), ("timestamp", -1)])\
.skip(skip)\
.limit(min(limit, 100))\
.to_list()
return PaginatedResponse(
result={
"items": [item.dict(by_alias=True) for item in items],
"skip": skip,
"total": total
}
)
```
---
### 1.3 获取单个交易记录
**接口**: `GET /transactions/{transaction_id}`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"item": "午餐",
"amount": 35.5,
"type": "expense",
"category": "餐饮",
"date": "2026-01-19",
"timestamp": 1737331200000,
"created_at": "2026-01-19T10:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
}
```
**FastAPI实现示例**:
```python
@router.get("/{transaction_id}", response_model=ResponseModel)
async def get_transaction(
transaction_id: str,
user_id: str = Depends(get_current_user_id)
):
"""获取单个交易记录"""
transaction = await Transaction.get(transaction_id)
if not transaction or transaction.user_id != user_id:
raise HTTPException(status_code=404, detail="交易记录不存在")
return ResponseModel(
result=transaction.dict(by_alias=True)
)
```
---
### 1.4 更新交易记录
**接口**: `PUT /transactions/{transaction_id}`
**请求体**:
```json
{
"item": "晚餐",
"amount": 50.0,
"type": "expense",
"category": "餐饮",
"date": "2026-01-19"
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"item": "晚餐",
"amount": 50.0,
"type": "expense",
"category": "餐饮",
"date": "2026-01-19",
"timestamp": 1737331200000,
"created_at": "2026-01-19T10:00:00Z",
"updated_at": "2026-01-19T11:00:00Z"
}
}
```
**FastAPI实现示例**:
```python
class TransactionUpdate(BaseModel):
item: Optional[str] = None
amount: Optional[float] = None
type: Optional[TransactionType] = None
category: Optional[str] = None
date: Optional[str] = None
@router.put("/{transaction_id}", response_model=ResponseModel)
async def update_transaction(
transaction_id: str,
data: TransactionUpdate,
user_id: str = Depends(get_current_user_id)
):
"""更新交易记录"""
transaction = await Transaction.get(transaction_id)
if not transaction or transaction.user_id != user_id:
raise HTTPException(status_code=404, detail="交易记录不存在")
update_data = data.dict(exclude_unset=True)
update_data["updated_at"] = datetime.utcnow()
await transaction.set(update_data)
return ResponseModel(
result=transaction.dict(by_alias=True)
)
```
---
### 1.5 删除交易记录
**接口**: `DELETE /transactions/{transaction_id}`
**响应**:
```json
{
"code": 200,
"msg": "删除成功",
"result": null
}
```
**FastAPI实现示例**:
```python
@router.delete("/{transaction_id}", response_model=ResponseModel)
async def delete_transaction(
transaction_id: str,
user_id: str = Depends(get_current_user_id)
):
"""删除交易记录"""
transaction = await Transaction.get(transaction_id)
if not transaction or transaction.user_id != user_id:
raise HTTPException(status_code=404, detail="交易记录不存在")
await transaction.delete()
return ResponseModel(
msg="删除成功",
result=None
)
```
---
### 1.6 批量删除交易记录
**接口**: `POST /transactions/batch-delete`
**请求体**:
```json
{
"transaction_ids": [
"65a1b2c3d4e5f6g7h8i9j0k1",
"65a1b2c3d4e5f6g7h8i9j0k2"
]
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"deleted_count": 2
}
}
```
---
### 1.7 统计接口
**接口**: `GET /transactions/stats/summary`
**查询参数**:
- `month`: str (必填,月份 YYYY-MM)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"month": "2026-01",
"total_income": 10000.0,
"total_expense": 5500.5,
"balance": 4499.5,
"expense_by_category": {
"餐饮": 1200.0,
"交通": 500.0,
"购物": 3800.5
},
"income_by_category": {
"工资": 8000.0,
"兼职": 2000.0
},
"daily_expense": [
{"date": "2026-01-01", "amount": 150.0},
{"date": "2026-01-02", "amount": 200.5}
]
}
}
```
**FastAPI实现示例**:
```python
@router.get("/stats/summary", response_model=ResponseModel)
async def get_transaction_stats(
month: str,
user_id: str = Depends(get_current_user_id)
):
"""获取交易统计数据"""
pipeline = [
{"$match": {
"user_id": user_id,
"date": {"$regex": f"^{month}"}
}},
{"$group": {
"_id": "$type",
"total": {"$sum": "$amount"}
}}
]
stats = await Transaction.aggregate(pipeline).to_list()
# 处理统计数据...
return ResponseModel(result={
"month": month,
"total_income": total_income,
"total_expense": total_expense,
"balance": total_income - total_expense,
# ...
})
```
---
## 二、聊天消息接口
### 2.1 创建聊天消息
**接口**: `POST /messages`
**请求体**:
```json
{
"role": "user",
"content": "花了30块钱吃午饭",
"timestamp": 1737331200000,
"related_transaction_id": null
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"role": "user",
"content": "花了30块钱吃午饭",
"timestamp": 1737331200000,
"related_transaction_id": null,
"created_at": "2026-01-19T10:00:00Z"
}
}
```
---
### 2.2 查询聊天消息列表(分页)
**接口**: `GET /messages`
**查询参数**:
- `skip`: int = 0
- `limit`: int = 50 (建议最大500)
- `before_timestamp`: int (可选,获取该时间戳之前的消息)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"items": [
{
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"role": "user",
"content": "花了30块钱吃午饭",
"timestamp": 1737331200000,
"related_transaction_id": null,
"created_at": "2026-01-19T10:00:00Z"
}
],
"skip": 0,
"total": 250
}
}
```
---
### 2.3 批量创建消息(用于同步)
**接口**: `POST /messages/batch`
**请求体**:
```json
{
"messages": [
{
"role": "user",
"content": "花了30块钱吃午饭",
"timestamp": 1737331200000
},
{
"role": "assistant",
"content": "已记录",
"timestamp": 1737331201000,
"related_transaction_id": "65a1b2c3d4e5f6g7h8i9j0k1"
}
]
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"created_count": 2
}
}
```
---
### 2.4 删除聊天消息
**接口**: `DELETE /messages/{message_id}`
**响应**:
```json
{
"code": 200,
"msg": "删除成功",
"result": null
}
```
---
### 2.5 清空聊天历史
**接口**: `DELETE /messages/clear`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"deleted_count": 150
}
}
```
---
## 三、预算管理接口
### 3.1 获取月度预算
**接口**: `GET /budgets/{month}`
**路径参数**:
- `month`: str (月份 YYYY-MM)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"budgets": {
"总预算": 3000,
"餐饮预算": 1000,
"购物预算": 500
},
"month": "2026-01",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
}
}
```
---
### 3.2 设置/更新月度预算
**接口**: `PUT /budgets/{month}`
**请求体**:
```json
{
"budgets": {
"总预算": 5000,
"餐饮预算": 1500,
"购物预算": 800,
"交通预算": 500
}
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"budgets": {
"总预算": 5000,
"餐饮预算": 1500,
"购物预算": 800,
"交通预算": 500
},
"month": "2026-01",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
}
```
---
### 3.3 获取预算执行情况
**接口**: `GET /budgets/{month}/execution`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"month": "2026-01",
"budgets": {
"总预算": {
"budget": 5000,
"spent": 3500.5,
"remaining": 1499.5,
"percentage": 70.01
},
"餐饮预算": {
"budget": 1500,
"spent": 1200.0,
"remaining": 300.0,
"percentage": 80.00
}
},
"total_budget": 5000,
"total_spent": 3500.5,
"total_remaining": 1499.5,
"is_over_budget": false
}
}
```
---
## 四、账单提醒接口
### 4.1 创建账单提醒
**接口**: `POST /reminders`
**请求体**:
```json
{
"title": "信用卡还款",
"amount": 5000,
"frequency": "monthly",
"target_date": "15"
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"title": "信用卡还款",
"amount": 5000,
"frequency": "monthly",
"target_date": "15",
"is_completed": false,
"created_at": "2026-01-19T10:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
}
```
---
### 4.2 查询账单提醒列表
**接口**: `GET /reminders`
**查询参数**:
- `skip`: int = 0
- `limit`: int = 50
- `frequency`: str (可选,筛选频率)
- `is_completed`: bool (可选,筛选完成状态)
- `month`: str (可选,筛选单次提醒所属月份)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"items": [
{
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"title": "信用卡还款",
"amount": 5000,
"frequency": "monthly",
"target_date": "15",
"is_completed": false,
"days_remaining": 5,
"created_at": "2026-01-19T10:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
],
"skip": 0,
"total": 10
}
}
```
---
### 4.3 更新账单提醒
**接口**: `PUT /reminders/{reminder_id}`
**请求体**:
```json
{
"title": "信用卡还款(更新)",
"amount": 6000,
"target_date": "20"
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"title": "信用卡还款(更新)",
"amount": 6000,
"frequency": "monthly",
"target_date": "20",
"is_completed": false,
"created_at": "2026-01-19T10:00:00Z",
"updated_at": "2026-01-19T11:00:00Z"
}
}
```
---
### 4.4 切换提醒完成状态
**接口**: `PATCH /reminders/{reminder_id}/toggle`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"is_completed": true
}
}
```
---
### 4.5 删除账单提醒
**接口**: `DELETE /reminders/{reminder_id}`
**响应**:
```json
{
"code": 200,
"msg": "删除成功",
"result": null
}
```
---
### 4.6 获取即将到期的提醒
**接口**: `GET /reminders/upcoming`
**查询参数**:
- `days`: int = 7 (未来N天内)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"items": [
{
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"title": "信用卡还款",
"amount": 5000,
"target_date": "2026-01-20",
"days_remaining": 1,
"is_overdue": false
}
],
"skip": 0,
"total": 3
}
}
```
---
## 五、AI设置接口
### 5.1 获取AI设置
**接口**: `GET /ai-settings`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"name": "崔经理",
"persona": "一个精明、毒舌但实际上很负责任的财务经理...",
"avatar": null,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
}
```
---
### 5.2 更新AI设置
**接口**: `PUT /ai-settings`
**请求体**:
```json
{
"name": "小崔",
"persona": "温柔体贴的管家...",
"avatar": "data:image/png;base64,iVBORw0KGgoAAAANS..."
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"name": "小崔",
"persona": "温柔体贴的管家...",
"avatar": "data:image/png;base64,iVBORw0KGgoAAAANS...",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-19T11:00:00Z"
}
}
```
---
### 5.3 重置AI设置为默认
**接口**: `POST /ai-settings/reset`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"name": "崔经理",
"persona": "一个精明、毒舌但实际上很负责任的财务经理...",
"avatar": null,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-19T11:00:00Z"
}
}
```
---
## 六、用户偏好接口
### 6.1 获取用户偏好
**接口**: `GET /preferences`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"custom_preset_name": "自定义",
"custom_preset_description": "温柔又严格的助手",
"theme_index": 2,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-19T10:00:00Z"
}
}
```
---
### 6.2 更新用户偏好
**接口**: `PUT /preferences`
**请求体**:
```json
{
"custom_preset_name": "我的助手",
"custom_preset_description": "专属定制",
"theme_index": 3
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"id": "65a1b2c3d4e5f6g7h8i9j0k1",
"user_id": "user_123",
"custom_preset_name": "我的助手",
"custom_preset_description": "专属定制",
"theme_index": 3,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-19T11:00:00Z"
}
}
```
---
## 七、数据同步接口
### 7.1 全量数据同步(上传)
**接口**: `POST /sync/upload`
**请求体**:
```json
{
"transactions": [...],
"messages": [...],
"budgets": {...},
"reminders": [...],
"ai_settings": {...},
"preferences": {...}
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"synced_at": "2026-01-19T11:00:00Z",
"transactions_count": 150,
"messages_count": 300,
"reminders_count": 10
}
}
```
---
### 7.2 增量数据同步(下载)
**接口**: `GET /sync/download`
**查询参数**:
- `since`: int (时间戳,获取该时间之后的数据)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"transactions": [...],
"messages": [...],
"reminders": [...],
"synced_at": "2026-01-19T11:00:00Z"
}
}
```
---
### 7.3 获取最后同步时间
**接口**: `GET /sync/status`
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"last_sync_at": "2026-01-19T10:00:00Z",
"transactions_count": 150,
"messages_count": 300,
"reminders_count": 10
}
}
```
---
## 八、数据导出/导入接口
### 8.1 导出所有数据
**接口**: `GET /export`
**查询参数**:
- `format`: str = "json" (导出格式: json/csv)
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"export_url": "https://cdn.example.com/exports/user_123_20260119.json",
"expires_at": "2026-01-20T11:00:00Z"
}
}
```
---
### 8.2 导入数据
**接口**: `POST /import`
**请求体** (multipart/form-data):
```
file: <JSON文件>
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"imported_transactions": 150,
"imported_messages": 300,
"imported_reminders": 10,
"import_time": "2026-01-19T11:00:00Z"
}
}
```
---
## 九、AI处理接口(与Gemini交互)
### 9.1 处理用户消息
**接口**: `POST /ai/process`
**请求体**:
```json
{
"message": "今天花了50块钱吃饭",
"image_base64": null,
"mime_type": null
}
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"transaction": {
"item": "吃饭",
"amount": 50,
"type": "expense",
"category": "餐饮"
},
"reply": "记下了!🍽️\n又花钱了... 💸",
"created_transaction_id": "65a1b2c3d4e5f6g7h8i9j0k1",
"created_message_ids": [
"65a1b2c3d4e5f6g7h8i9j0k2",
"65a1b2c3d4e5f6g7h8i9j0k3"
]
}
}
```
---
### 9.2 图片识别账单
**接口**: `POST /ai/recognize-receipt`
**请求体** (multipart/form-data):
```
image: <图片文件>
```
**响应**:
```json
{
"code": 200,
"msg": "ok",
"result": {
"transaction": {
"item": "超市购物",
"amount": 125.50,
"type": "expense",
"category": "购物"
},
"reply": "识别成功!🛒\n买了不少啊... 💰"
}
}
```
---
## 附录
### A. 错误码说明
| 错误码 | 说明 |
|-------|------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未授权 |
| 403 | 禁止访问 |
| 404 | 资源不存在 |
| 409 | 资源冲突 |
| 422 | 数据验证失败 |
| 500 | 服务器内部错误 |
| 503 | 服务不可用 |
---
### B. 完整项目结构示例
```
backend/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI应用入口
│ ├── config.py # 配置文件
│ ├── database.py # 数据库连接
│ ├── dependencies.py # 依赖注入
│ │
│ ├── models/ # Beanie数据模型
│ │ ├── __init__.py
│ │ ├── transaction.py
│ │ ├── message.py
│ │ ├── budget.py
│ │ ├── reminder.py
│ │ ├── ai_settings.py
│ │ └── user_preference.py
│ │
│ ├── schemas/ # Pydantic验证模型
│ │ ├── __init__.py
│ │ ├── transaction.py
│ │ ├── message.py
│ │ ├── budget.py
│ │ ├── reminder.py
│ │ └── response.py
│ │
│ ├── routers/ # API路由
│ │ ├── __init__.py
│ │ ├── transactions.py
│ │ ├── messages.py
│ │ ├── budgets.py
│ │ ├── reminders.py
│ │ ├── ai_settings.py
│ │ ├── preferences.py
│ │ ├── sync.py
│ │ └── ai_process.py
│ │
│ ├── services/ # 业务逻辑
│ │ ├── __init__.py
│ │ ├── gemini_service.py
│ │ ├── stats_service.py
│ │ └── sync_service.py
│ │
│ └── utils/ # 工具函数
│ ├── __init__.py
│ ├── auth.py
│ └── helpers.py
│
├── tests/ # 测试文件
├── requirements.txt
├── .env.example
└── README.md
```
---
### C. main.py 示例
```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from beanie import init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
from app.config import settings
from app.models import Transaction, Message, Budget, BillReminder, AISettings, UserPreference
from app.routers import (
transactions,
messages,
budgets,
reminders,
ai_settings,
preferences,
sync,
ai_process
)
app = FastAPI(
title="智能账本 API",
version="1.0.0",
description="基于FastAPI+Beanie的账本管理后端API"
)
# CORS配置
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.on_event("startup")
async def startup_event():
"""应用启动时初始化数据库连接"""
client = AsyncIOMotorClient(settings.MONGODB_URL)
await init_beanie(
database=client[settings.DATABASE_NAME],
document_models=[
Transaction,
Message,
Budget,
BillReminder,
AISettings,
UserPreference
]
)
# 注册路由
app.include_router(transactions.router, prefix="/api/v1")
app.include_router(messages.router, prefix="/api/v1")
app.include_router(budgets.router, prefix="/api/v1")
app.include_router(reminders.router, prefix="/api/v1")
app.include_router(ai_settings.router, prefix="/api/v1")
app.include_router(preferences.router, prefix="/api/v1")
app.include_router(sync.router, prefix="/api/v1")
app.include_router(ai_process.router, prefix="/api/v1")
@app.get("/")
async def root():
return {"message": "智能账本 API", "version": "1.0.0"}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
```
---
### D. 环境变量配置 (.env.example)
```env
# MongoDB配置
MONGODB_URL=mongodb://localhost:27017
DATABASE_NAME=bill_app
# JWT配置
SECRET_KEY=your-secret-key-here
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=10080
# Gemini API配置
GEMINI_API_KEY=your-gemini-api-key
# 服务配置
HOST=0.0.0.0
PORT=8000
RELOAD=True
# CORS配置
ALLOWED_ORIGINS=http://localhost:5173,https://your-frontend.com
```
---
### E. requirements.txt
```txt
fastapi==0.104.1
uvicorn[standard]==0.24.0
beanie==1.23.6
motor==3.3.2
pydantic==2.5.0
pydantic-settings==2.1.0
python-jose[cryptography]==3.3.0
passlib[bcrypt]==1.7.4
python-multipart==0.0.6
google-generativeai==0.3.0
```
---
### F. 启动命令
```bash
# 开发环境
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# 生产环境
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
```
---
## 总结
本文档详细设计了智能账本应用的后端API接口,包括:
✅ **6大核心模块**:交易记录、聊天消息、预算管理、账单提醒、AI设置、用户偏好
✅ **完整的Beanie数据模型定义**
✅ **RESTful API设计**:增删改查、统计、同步、AI处理
✅ **统一响应格式**:单例数据 & 分页列表
✅ **详细的FastAPI实现示例**
✅ **完整的项目结构建议**
**文档版本**: v1.0
**生成时间**: 2026-01-19
**技术栈**: FastAPI + Beanie + MongoDB + Gemini API