优化列表分页和数据加载

This commit is contained in:
yml2213
2026-07-24 13:25:27 +08:00
parent 6840728da6
commit f91c05c108
17 changed files with 647 additions and 161 deletions
+64 -5
View File
@@ -1,8 +1,8 @@
"""账号管理路由"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import func
from sqlalchemy.orm import Session, joinedload
from sqlalchemy import func, or_
from sqlalchemy.orm import Session, defer, joinedload
from ..database import get_db
from ..models import User, Account, AuditLog, LoginTask
@@ -16,11 +16,15 @@ from ..services.account_service import (
router = APIRouter(prefix="/api/accounts", tags=["账号管理"])
@router.get("", response_model=list[AccountOut])
@router.get("")
def list_accounts(
assigned_only: bool = Query(False),
tag: str = Query(None),
has_cookie: bool = Query(False),
search: str = Query(""),
page: int | None = Query(None, ge=1),
page_size: int = Query(20, ge=1, le=200),
include_sensitive: bool = Query(True),
db: Session = Depends(get_db),
current: User = Depends(get_current_user),
):
@@ -44,7 +48,31 @@ def list_accounts(
if tag:
query = query.filter(Account.tag == tag)
accounts = query.order_by(Account.id).options(joinedload(Account.assigned_user)).all()
search_text = (search or "").strip()
if search_text:
pattern = f"%{search_text}%"
query = query.filter(or_(
Account.username.ilike(pattern),
Account.tag.ilike(pattern),
Account.remark.ilike(pattern),
))
total = None
if page is not None:
total = query.order_by(None).count()
query = query.order_by(Account.id)
if page is not None:
query = query.offset((page - 1) * page_size).limit(page_size)
can_include_sensitive = include_sensitive and user_has_permission(current, "account:view_full")
options = [joinedload(Account.assigned_user)]
if not can_include_sensitive:
options.extend([
defer(Account.password),
defer(Account.email),
defer(Account.email_password),
])
accounts = query.options(*options).all()
result = []
for acc in accounts:
item = AccountOut(
@@ -55,14 +83,45 @@ def list_accounts(
created_at=acc.created_at,
)
# 只有管理员可看完整字段(密码、邮箱等)
if user_has_permission(current, "account:view_full"):
if can_include_sensitive:
item.password = acc.password
item.email = acc.email
item.email_password = acc.email_password
result.append(item)
if page is not None:
return {"items": result, "total": total or 0, "page": page, "page_size": page_size}
return result
@router.get("/summary")
def accounts_summary(
db: Session = Depends(get_db),
current: User = Depends(get_current_user),
):
"""账号管理统计,避免前端为了卡片统计拉全量账号。"""
query = db.query(Account)
if not user_has_permission(current, "account:view_all"):
if user_has_permission(current, "account:view_assigned"):
query = query.filter(Account.assigned_to == current.id)
else:
raise HTTPException(status_code=403, detail="无权查看账号")
total = query.count()
assigned_count = query.filter(Account.assigned_to.isnot(None)).count()
tag_count = (
query.filter(Account.tag != "", Account.tag.isnot(None))
.with_entities(Account.tag)
.distinct()
.count()
)
return {
"total": total,
"assigned_count": assigned_count,
"unassigned_count": max(0, total - assigned_count),
"tag_count": tag_count,
}
@router.post("/import")
def import_accounts(
req: AccountImport,