功能: - 通知提醒系统: 还款日提醒、逾期提醒、系统消息横幅、登录时通知 - 通知中心UI: 铃铛图标 + 下拉列表 + 未读徽章 - 定时任务: APScheduler 每小时检查即将到期的还款 - 邮件通知: SMTP 发送还款提醒和安全警告 - 异常登录通知: 3/5/10次失败触发网页和邮件通知 安全: - 登录安全告警: 异常登录次数达到阈值时发送通知 - 密码重置链接: 一次性使用, 5分钟有效期 - 登录频率限制: IP级和账户级限制 技术: - 后端: FastAPI + SQLAlchemy + PostgreSQL - 前端: 纯 HTML/CSS/JS - 部署: Docker Compose (新增 build 配置)
257 lines
4.6 KiB
Python
257 lines
4.6 KiB
Python
from pydantic import BaseModel
|
|
from datetime import datetime
|
|
|
|
|
|
class RegisterRequest(BaseModel):
|
|
account: str
|
|
password: str
|
|
nickname: str = ""
|
|
group_id: int | None = None
|
|
|
|
|
|
class LoginRequest(BaseModel):
|
|
account: str
|
|
password: str
|
|
|
|
|
|
class TokenResponse(BaseModel):
|
|
access_token: str
|
|
refresh_token: str
|
|
token_type: str = "bearer"
|
|
|
|
|
|
class RefreshRequest(BaseModel):
|
|
refresh_token: str
|
|
|
|
|
|
class UserProfile(BaseModel):
|
|
id: int
|
|
account: str
|
|
nickname: str
|
|
real_email: str = ""
|
|
role: str
|
|
status: str
|
|
group_id: int | None = None
|
|
group_name: str = ""
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class ChangePasswordRequest(BaseModel):
|
|
old_password: str
|
|
new_password: str
|
|
|
|
|
|
class GroupCreate(BaseModel):
|
|
name: str
|
|
description: str = ""
|
|
|
|
|
|
class GroupResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
description: str
|
|
member_count: int = 0
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class GroupMemberAdd(BaseModel):
|
|
user_id: int
|
|
|
|
|
|
class LoanCreate(BaseModel):
|
|
name: str
|
|
date: str
|
|
amount: float
|
|
rate: float
|
|
periods: int
|
|
method: str
|
|
purpose: str = ""
|
|
schedule: list[dict] = []
|
|
paid: list[int] = []
|
|
|
|
|
|
class LoanResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
date: str
|
|
amount: float
|
|
rate: float
|
|
periods: int
|
|
method: str
|
|
purpose: str
|
|
schedule: list[dict]
|
|
paid: list[int]
|
|
user_id: int
|
|
owner_name: str = ""
|
|
|
|
|
|
class DebtCreate(BaseModel):
|
|
creditor_name: str
|
|
amount: int
|
|
borrow_date: datetime
|
|
interest_rate: float
|
|
rate_type: str = "annual"
|
|
repayment_method: str
|
|
period_count: int
|
|
period_unit: str = "month"
|
|
notes: str = ""
|
|
|
|
|
|
class DebtUpdate(BaseModel):
|
|
creditor_name: str | None = None
|
|
amount: int | None = None
|
|
borrow_date: datetime | None = None
|
|
interest_rate: float | None = None
|
|
rate_type: str | None = None
|
|
repayment_method: str | None = None
|
|
period_count: int | None = None
|
|
period_unit: str | None = None
|
|
notes: str | None = None
|
|
|
|
|
|
class DebtResponse(BaseModel):
|
|
id: int
|
|
user_id: int
|
|
creditor_name: str
|
|
amount: int
|
|
borrow_date: datetime
|
|
interest_rate: float
|
|
rate_type: str
|
|
repayment_method: str
|
|
period_count: int
|
|
period_unit: str
|
|
status: str
|
|
notes: str
|
|
created_at: datetime
|
|
total_paid: int = 0
|
|
total_interest: int = 0
|
|
owner_name: str = ""
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class RepaymentPlanResponse(BaseModel):
|
|
id: int
|
|
debt_id: int
|
|
due_date: datetime
|
|
principal_due: int
|
|
interest_due: int
|
|
total_due: int
|
|
status: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class RepaymentRecordCreate(BaseModel):
|
|
debt_id: int
|
|
plan_id: int | None = None
|
|
amount: int
|
|
paid_date: datetime
|
|
notes: str = ""
|
|
|
|
|
|
class RepaymentRecordResponse(BaseModel):
|
|
id: int
|
|
debt_id: int
|
|
plan_id: int | None
|
|
amount: int
|
|
paid_date: datetime
|
|
notes: str
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class DashboardSummary(BaseModel):
|
|
total_debt: int
|
|
total_paid: int
|
|
total_remaining: int
|
|
active_count: int
|
|
overdue_count: int
|
|
paid_count: int
|
|
upcoming_payments: list[dict]
|
|
|
|
|
|
class AdminUserResponse(BaseModel):
|
|
id: int
|
|
account: str
|
|
nickname: str
|
|
real_email: str = ""
|
|
role: str
|
|
status: str
|
|
group_id: int | None = None
|
|
group_name: str = ""
|
|
created_at: datetime
|
|
debt_count: int = 0
|
|
total_amount: int = 0
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class AdminDashboard(BaseModel):
|
|
total_users: int
|
|
active_debts: int
|
|
total_amount: int
|
|
overdue_count: int
|
|
rate_distribution: dict
|
|
status_distribution: dict
|
|
|
|
|
|
class SystemSettingUpdate(BaseModel):
|
|
value: str
|
|
|
|
|
|
class NotificationResponse(BaseModel):
|
|
id: int
|
|
user_id: int
|
|
title: str
|
|
message: str
|
|
type: str
|
|
is_read: int
|
|
related_debt_id: int | None = None
|
|
related_plan_id: int | None = None
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class NotificationListResponse(BaseModel):
|
|
items: list[NotificationResponse]
|
|
total: int
|
|
unread: int
|
|
|
|
|
|
class EmailServiceConfig(BaseModel):
|
|
smtp_host: str = ""
|
|
smtp_port: int = 465
|
|
smtp_user: str = ""
|
|
smtp_password: str = ""
|
|
smtp_from: str = ""
|
|
smtp_use_tls: bool = True
|
|
|
|
|
|
class ForgotPasswordRequest(BaseModel):
|
|
account: str
|
|
|
|
|
|
class VerifyResetCodeRequest(BaseModel):
|
|
account: str
|
|
code: str
|
|
|
|
|
|
class ResetPasswordRequest(BaseModel):
|
|
account: str
|
|
code: str
|
|
new_password: str
|