管理后台前后端逻辑、UI美化

This commit is contained in:
Cheng Zhou
2026-01-16 13:50:08 +08:00
parent 05c1f9579a
commit 7fdcfdaadd
82 changed files with 3210 additions and 549 deletions
+18 -9
View File
@@ -3,7 +3,7 @@ import uuid
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.deps import get_db_session, require_study_member, require_study_roles
from app.core.deps import get_db_session, require_study_member, require_study_roles, require_study_not_locked
from app.crud import member as member_crud
from app.crud import study as study_crud
from app.crud import user as user_crud
@@ -24,7 +24,7 @@ async def _ensure_study_exists(db: AsyncSession, study_id: uuid.UUID):
"/",
response_model=StudyMemberRead,
status_code=status.HTTP_201_CREATED,
dependencies=[Depends(require_study_roles(["PM"]))],
dependencies=[Depends(require_study_roles(["PM"])), Depends(require_study_not_locked())],
)
async def add_member(
study_id: uuid.UUID,
@@ -34,6 +34,13 @@ async def add_member(
await _ensure_study_exists(db, study_id)
existing = await member_crud.get_member(db, study_id, member_in.user_id)
if existing:
if not existing.is_active:
updated = await member_crud.update_member(
db,
existing,
StudyMemberUpdate(is_active=True, role_in_study=member_in.role_in_study),
)
return updated
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="成员已存在")
member = await member_crud.add_member(db, study_id, member_in)
return member
@@ -48,6 +55,7 @@ async def list_members(
study_id: uuid.UUID,
skip: int = 0,
limit: int = 100,
include_inactive: bool = False,
db: AsyncSession = Depends(get_db_session),
) -> list[StudyMemberReadWithUser]:
await _ensure_study_exists(db, study_id)
@@ -56,12 +64,13 @@ async def list_members(
users_map = await user_crud.get_users_by_ids(db, user_ids)
result: list[StudyMemberReadWithUser] = []
for m in members:
# 仅返回项目内启用的成员 + 账号启用的用户
if not m.is_active:
continue
user = users_map.get(m.user_id)
if not user or not user.is_active:
continue
if not include_inactive:
# 仅返回项目内启用的成员 + 账号启用的用户
if not m.is_active:
continue
if not user or not user.is_active:
continue
result.append(
StudyMemberReadWithUser(
id=m.id,
@@ -79,7 +88,7 @@ async def list_members(
@router.patch(
"/{member_id}",
response_model=StudyMemberRead,
dependencies=[Depends(require_study_roles(["PM"]))],
dependencies=[Depends(require_study_roles(["PM"])), Depends(require_study_not_locked())],
)
async def update_member(
study_id: uuid.UUID,
@@ -98,7 +107,7 @@ async def update_member(
@router.delete(
"/{member_id}",
response_model=StudyMemberRead,
dependencies=[Depends(require_study_roles(["PM"]))],
dependencies=[Depends(require_study_roles(["PM"])), Depends(require_study_not_locked())],
)
async def remove_member(
study_id: uuid.UUID,