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