- 修复前端路由守卫:未登录时不显示提示,直接跳转登录页 - 修复API拦截器:401错误不显示提示,直接跳转 - 增强验证码显示:图片尺寸从120x40增加到200x80 - 增大验证码字体:从28号增加到48号 - 优化验证码字符:排除易混淆的0和1 - 减少干扰线:从5条减少到3条,添加背景色优化 - 增强登录API日志:添加详细的调试日志 - 增强验证码生成和验证日志 - 优化异常处理和错误追踪 影响文件: - src/router/index.ts - src/api/request.ts - app/services/auth_service.py - app/api/v1/auth.py - app/schemas/user.py 测试状态: - 前端构建通过 - 后端语法检查通过 - 验证码显示效果优化完成 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
241 lines
6.4 KiB
Python
241 lines
6.4 KiB
Python
"""
|
||
机构网点API路由
|
||
"""
|
||
from typing import List, Optional
|
||
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||
from sqlalchemy.orm import Session
|
||
from app.core.deps import get_db, get_current_user
|
||
from app.schemas.organization import (
|
||
OrganizationCreate,
|
||
OrganizationUpdate,
|
||
OrganizationResponse,
|
||
OrganizationTreeNode,
|
||
OrganizationWithParent
|
||
)
|
||
from app.services.organization_service import organization_service
|
||
from app.utils.redis_client import redis_client
|
||
|
||
router = APIRouter()
|
||
|
||
|
||
# 异步缓存包装器
|
||
@redis_client.cached_async("organizations:list", expire=1800) # 缓存30分钟
|
||
async def _cached_get_organizations(
|
||
skip: int,
|
||
limit: int,
|
||
org_type: Optional[str],
|
||
status: Optional[str],
|
||
keyword: Optional[str],
|
||
db: Session
|
||
):
|
||
"""获取机构列表的缓存包装器"""
|
||
items, total = organization_service.get_organizations(
|
||
db=db,
|
||
skip=skip,
|
||
limit=limit,
|
||
org_type=org_type,
|
||
status=status,
|
||
keyword=keyword
|
||
)
|
||
return items
|
||
|
||
|
||
@redis_client.cached_async("organizations:tree", expire=1800) # 缓存30分钟
|
||
async def _cached_get_organization_tree(
|
||
status: Optional[str],
|
||
db: Session
|
||
):
|
||
"""获取机构树的缓存包装器"""
|
||
return organization_service.get_organization_tree(db, status)
|
||
|
||
|
||
@router.get("/", response_model=List[OrganizationResponse])
|
||
async def get_organizations(
|
||
skip: int = Query(0, ge=0, description="跳过条数"),
|
||
limit: int = Query(20, ge=1, le=100, description="返回条数"),
|
||
org_type: Optional[str] = Query(None, description="机构类型"),
|
||
status: Optional[str] = Query(None, description="状态"),
|
||
keyword: Optional[str] = Query(None, description="搜索关键词"),
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
获取机构列表(已启用缓存,30分钟)
|
||
|
||
- **skip**: 跳过条数
|
||
- **limit**: 返回条数(最大100)
|
||
- **org_type**: 机构类型筛选(province/city/outlet)
|
||
- **status**: 状态筛选(active/inactive)
|
||
- **keyword**: 搜索关键词(代码或名称)
|
||
"""
|
||
return await _cached_get_organizations(
|
||
skip=skip,
|
||
limit=limit,
|
||
org_type=org_type,
|
||
status=status,
|
||
keyword=keyword,
|
||
db=db
|
||
)
|
||
|
||
|
||
@router.get("/tree", response_model=List[OrganizationTreeNode])
|
||
async def get_organization_tree(
|
||
status: Optional[str] = Query(None, description="状态筛选"),
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
获取机构树(已启用缓存,30分钟)
|
||
|
||
- **status**: 状态筛选(active/inactive)
|
||
|
||
返回树形结构的机构列表
|
||
"""
|
||
return await _cached_get_organization_tree(status, db)
|
||
|
||
|
||
@router.get("/{org_id}", response_model=OrganizationWithParent)
|
||
def get_organization(
|
||
org_id: int,
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
获取机构详情
|
||
|
||
- **org_id**: 机构ID
|
||
|
||
返回机构详情及其父机构信息
|
||
"""
|
||
org = organization_service.get_organization(db, org_id)
|
||
|
||
# 加载父机构信息
|
||
if org.parent_id:
|
||
from app.crud.organization import organization as organization_crud
|
||
parent = organization_crud.get(db, org.parent_id)
|
||
org.parent = parent
|
||
|
||
return org
|
||
|
||
|
||
@router.get("/{org_id}/children", response_model=List[OrganizationResponse])
|
||
def get_organization_children(
|
||
org_id: int,
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
获取直接子机构
|
||
|
||
- **org_id**: 父机构ID(0表示根节点)
|
||
|
||
返回指定机构的直接子机构列表
|
||
"""
|
||
return organization_service.get_organization_children(db, org_id)
|
||
|
||
|
||
@router.get("/{org_id}/all-children", response_model=List[OrganizationResponse])
|
||
def get_all_organization_children(
|
||
org_id: int,
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
递归获取所有子机构
|
||
|
||
- **org_id**: 父机构ID
|
||
|
||
返回指定机构的所有子机构(包括子节点的子节点)
|
||
"""
|
||
return organization_service.get_all_children(db, org_id)
|
||
|
||
|
||
@router.get("/{org_id}/parents", response_model=List[OrganizationResponse])
|
||
def get_organization_parents(
|
||
org_id: int,
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
递归获取所有父机构
|
||
|
||
- **org_id**: 子机构ID
|
||
|
||
返回从根到直接父节点的所有父机构列表
|
||
"""
|
||
return organization_service.get_parents(db, org_id)
|
||
|
||
|
||
@router.post("/", response_model=OrganizationResponse, status_code=status.HTTP_201_CREATED)
|
||
def create_organization(
|
||
obj_in: OrganizationCreate,
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
创建机构
|
||
|
||
- **org_code**: 机构代码(唯一)
|
||
- **org_name**: 机构名称
|
||
- **org_type**: 机构类型(province/city/outlet)
|
||
- **parent_id**: 父机构ID(可选)
|
||
- **address**: 地址
|
||
- **contact_person**: 联系人
|
||
- **contact_phone**: 联系电话
|
||
- **sort_order**: 排序
|
||
"""
|
||
return organization_service.create_organization(
|
||
db=db,
|
||
obj_in=obj_in,
|
||
creator_id=current_user.id
|
||
)
|
||
|
||
|
||
@router.put("/{org_id}", response_model=OrganizationResponse)
|
||
def update_organization(
|
||
org_id: int,
|
||
obj_in: OrganizationUpdate,
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
更新机构
|
||
|
||
- **org_id**: 机构ID
|
||
- **org_name**: 机构名称
|
||
- **org_type**: 机构类型
|
||
- **parent_id**: 父机构ID
|
||
- **address**: 地址
|
||
- **contact_person**: 联系人
|
||
- **contact_phone**: 联系电话
|
||
- **status**: 状态
|
||
- **sort_order**: 排序
|
||
"""
|
||
return organization_service.update_organization(
|
||
db=db,
|
||
org_id=org_id,
|
||
obj_in=obj_in,
|
||
updater_id=current_user.id
|
||
)
|
||
|
||
|
||
@router.delete("/{org_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||
def delete_organization(
|
||
org_id: int,
|
||
db: Session = Depends(get_db),
|
||
current_user = Depends(get_current_user)
|
||
):
|
||
"""
|
||
删除机构
|
||
|
||
- **org_id**: 机构ID
|
||
|
||
软删除机构(如果机构下存在子机构则无法删除)
|
||
"""
|
||
organization_service.delete_organization(
|
||
db=db,
|
||
org_id=org_id,
|
||
deleter_id=current_user.id
|
||
)
|
||
return None
|