feat: 统一后端分页查询与前端服务层适配

后端新增通用分页模块,为报销单、员工、预算、agent 资产等
端点统一接入分页参数和游标查询,优化 repository 层分页实
现,前端服务层适配分页响应结构,完善预算图表和全局样式,
优化侧边栏和企业选择器组件,引入 Element Plus 插件注册。
This commit is contained in:
caoxiaozhu
2026-05-29 14:11:06 +08:00
parent e080105f9f
commit 678f64d772
43 changed files with 1863 additions and 378 deletions

View File

@@ -7,8 +7,9 @@ from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from app.api.deps import CurrentUserContext, get_current_user, get_db
from app.api.pagination import PageNumber, PageSize, page_payload, wants_page
from app.schemas.budget import BudgetClaimAnalysisRead
from app.schemas.common import ErrorResponse
from app.schemas.common import ErrorResponse, PaginatedResponse
from app.schemas.reimbursement import (
ExpenseClaimAttachmentActionResponse,
ExpenseClaimActionResponse,
@@ -25,8 +26,8 @@ from app.schemas.reimbursement import (
TravelReimbursementCalculatorRequest,
TravelReimbursementCalculatorResponse,
)
from app.services.expense_claims import ExpenseClaimService
from app.services.budget import BudgetService
from app.services.expense_claims import ExpenseClaimService
from app.services.reimbursement import ReimbursementService
from app.services.travel_reimbursement_calculator import TravelReimbursementCalculatorService
@@ -37,12 +38,19 @@ CurrentUser = Annotated[CurrentUserContext, Depends(get_current_user)]
@router.get(
"",
response_model=list[ReimbursementRead],
response_model=list[ReimbursementRead] | PaginatedResponse[ReimbursementRead],
summary="查询报销申请列表",
description="返回当前系统中的报销申请列表。",
)
def list_reimbursements(db: DbSession) -> list[ReimbursementRead]:
return ReimbursementService(db).list_reimbursements()
def list_reimbursements(
db: DbSession,
page: PageNumber = None,
page_size: PageSize = None,
) -> list[ReimbursementRead] | PaginatedResponse[ReimbursementRead]:
service = ReimbursementService(db)
if wants_page(page, page_size):
return page_payload(service.list_reimbursements_page(page=page, page_size=page_size))
return service.list_reimbursements()
@router.post(
@@ -81,32 +89,60 @@ def calculate_travel_reimbursement(
@router.get(
"/claims",
response_model=list[ExpenseClaimRead],
response_model=list[ExpenseClaimRead] | PaginatedResponse[ExpenseClaimRead],
summary="查询个人报销单列表",
description="返回当前登录用户可见的真实个人报销单据列表。",
)
def list_expense_claims(db: DbSession, current_user: CurrentUser) -> list[ExpenseClaimRead]:
return ExpenseClaimService(db).list_claims(current_user)
def list_expense_claims(
db: DbSession,
current_user: CurrentUser,
page: PageNumber = None,
page_size: PageSize = None,
) -> list[ExpenseClaimRead] | PaginatedResponse[ExpenseClaimRead]:
service = ExpenseClaimService(db)
if wants_page(page, page_size):
return page_payload(service.list_claims_page(current_user, page=page, page_size=page_size))
return service.list_claims(current_user)
@router.get(
"/claims/approvals",
response_model=list[ExpenseClaimRead],
response_model=list[ExpenseClaimRead] | PaginatedResponse[ExpenseClaimRead],
summary="查询当前用户审批待办报销单列表",
description="返回当前登录用户有权处理的待审批报销单据,不混入个人报销列表。",
)
def list_expense_claim_approvals(db: DbSession, current_user: CurrentUser) -> list[ExpenseClaimRead]:
return ExpenseClaimService(db).list_approval_claims(current_user)
def list_expense_claim_approvals(
db: DbSession,
current_user: CurrentUser,
page: PageNumber = None,
page_size: PageSize = None,
) -> list[ExpenseClaimRead] | PaginatedResponse[ExpenseClaimRead]:
service = ExpenseClaimService(db)
if wants_page(page, page_size):
return page_payload(
service.list_approval_claims_page(current_user, page=page, page_size=page_size)
)
return service.list_approval_claims(current_user)
@router.get(
"/claims/archives",
response_model=list[ExpenseClaimRead],
response_model=list[ExpenseClaimRead] | PaginatedResponse[ExpenseClaimRead],
summary="查询归档中心报销单列表",
description="返回公司已归档入账的报销单据,供财务与审计角色集中查阅。",
)
def list_archived_expense_claims(db: DbSession, current_user: CurrentUser) -> list[ExpenseClaimRead]:
return ExpenseClaimService(db).list_archived_claims(current_user)
def list_archived_expense_claims(
db: DbSession,
current_user: CurrentUser,
page: PageNumber = None,
page_size: PageSize = None,
) -> list[ExpenseClaimRead] | PaginatedResponse[ExpenseClaimRead]:
service = ExpenseClaimService(db)
if wants_page(page, page_size):
return page_payload(
service.list_archived_claims_page(current_user, page=page, page_size=page_size)
)
return service.list_archived_claims(current_user)
@router.get(