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

34 KiB
Raw Permalink Blame History

后端API接口设计文档

技术栈

  • 框架: FastAPI 0.104+
  • 数据库: MongoDB
  • ODM: Beanie 1.23+
  • 认证: JWT (可选)
  • 部署: Uvicorn

统一响应格式

单例数据响应

{
  "code": 200,
  "msg": "ok",
  "result": {}
}

分页列表响应

{
  "code": 200,
  "msg": "ok",
  "result": {
    "items": [],
    "skip": 0,
    "total": 0
  }
}

错误响应

{
  "code": 400,
  "msg": "错误描述",
  "result": null
}

数据模型定义 (Beanie Models)

1. Transaction 交易记录模型

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 聊天消息模型

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 预算模型

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 账单提醒模型

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设置模型

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 用户偏好模型

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

请求体:

{
  "item": "午餐",
  "amount": 35.5,
  "type": "expense",
  "category": "餐饮",
  "date": "2026-01-19",
  "timestamp": 1737331200000
}

响应:

{
  "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实现示例:

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)

响应:

{
  "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实现示例:

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}

响应:

{
  "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实现示例:

@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}

请求体:

{
  "item": "晚餐",
  "amount": 50.0,
  "type": "expense",
  "category": "餐饮",
  "date": "2026-01-19"
}

响应:

{
  "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实现示例:

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}

响应:

{
  "code": 200,
  "msg": "删除成功",
  "result": null
}

FastAPI实现示例:

@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

请求体:

{
  "transaction_ids": [
    "65a1b2c3d4e5f6g7h8i9j0k1",
    "65a1b2c3d4e5f6g7h8i9j0k2"
  ]
}

响应:

{
  "code": 200,
  "msg": "ok",
  "result": {
    "deleted_count": 2
  }
}

1.7 统计接口

接口: GET /transactions/stats/summary

查询参数:

  • month: str (必填,月份 YYYY-MM)

响应:

{
  "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实现示例:

@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

请求体:

{
  "role": "user",
  "content": "花了30块钱吃午饭",
  "timestamp": 1737331200000,
  "related_transaction_id": null
}

响应:

{
  "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 (可选,获取该时间戳之前的消息)

响应:

{
  "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

请求体:

{
  "messages": [
    {
      "role": "user",
      "content": "花了30块钱吃午饭",
      "timestamp": 1737331200000
    },
    {
      "role": "assistant",
      "content": "已记录",
      "timestamp": 1737331201000,
      "related_transaction_id": "65a1b2c3d4e5f6g7h8i9j0k1"
    }
  ]
}

响应:

{
  "code": 200,
  "msg": "ok",
  "result": {
    "created_count": 2
  }
}

2.4 删除聊天消息

接口: DELETE /messages/{message_id}

响应:

{
  "code": 200,
  "msg": "删除成功",
  "result": null
}

2.5 清空聊天历史

接口: DELETE /messages/clear

响应:

{
  "code": 200,
  "msg": "ok",
  "result": {
    "deleted_count": 150
  }
}

三、预算管理接口

3.1 获取月度预算

接口: GET /budgets/{month}

路径参数:

  • month: str (月份 YYYY-MM)

响应:

{
  "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}

请求体:

{
  "budgets": {
    "总预算": 5000,
    "餐饮预算": 1500,
    "购物预算": 800,
    "交通预算": 500
  }
}

响应:

{
  "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

响应:

{
  "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

请求体:

{
  "title": "信用卡还款",
  "amount": 5000,
  "frequency": "monthly",
  "target_date": "15"
}

响应:

{
  "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 (可选,筛选单次提醒所属月份)

响应:

{
  "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}

请求体:

{
  "title": "信用卡还款(更新)",
  "amount": 6000,
  "target_date": "20"
}

响应:

{
  "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

响应:

{
  "code": 200,
  "msg": "ok",
  "result": {
    "id": "65a1b2c3d4e5f6g7h8i9j0k1",
    "is_completed": true
  }
}

4.5 删除账单提醒

接口: DELETE /reminders/{reminder_id}

响应:

{
  "code": 200,
  "msg": "删除成功",
  "result": null
}

4.6 获取即将到期的提醒

接口: GET /reminders/upcoming

查询参数:

  • days: int = 7 (未来N天内)

响应:

{
  "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

响应:

{
  "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

请求体:

{
  "name": "小崔",
  "persona": "温柔体贴的管家...",
  "avatar": "data:image/png;base64,iVBORw0KGgoAAAANS..."
}

响应:

{
  "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

响应:

{
  "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

响应:

{
  "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

请求体:

{
  "custom_preset_name": "我的助手",
  "custom_preset_description": "专属定制",
  "theme_index": 3
}

响应:

{
  "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

请求体:

{
  "transactions": [...],
  "messages": [...],
  "budgets": {...},
  "reminders": [...],
  "ai_settings": {...},
  "preferences": {...}
}

响应:

{
  "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 (时间戳,获取该时间之后的数据)

响应:

{
  "code": 200,
  "msg": "ok",
  "result": {
    "transactions": [...],
    "messages": [...],
    "reminders": [...],
    "synced_at": "2026-01-19T11:00:00Z"
  }
}

7.3 获取最后同步时间

接口: GET /sync/status

响应:

{
  "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)

响应:

{
  "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文件>

响应:

{
  "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

请求体:

{
  "message": "今天花了50块钱吃饭",
  "image_base64": null,
  "mime_type": null
}

响应:

{
  "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: <图片文件>

响应:

{
  "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 示例

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)

# 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

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. 启动命令

# 开发环境
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