管理后台前后端逻辑、UI美化
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user