优化文档管理与导航体验
1、为文档增加编辑接口和前端编辑抽屉,文档列表与详情页统一按创建、更新、删除权限展示操作。 2、将文档版本上传和分发改为抽屉交互,并在详情页补充版本删除权限检查。 3、增强全局面包屑上下文和详情页标题同步,避免详情页重复或缺失导航信息。 4、按项目权限过滤快捷入口、首页费用指标和 eTMF 新建入口,并补充对应前端测试。
This commit is contained in:
@@ -9,7 +9,7 @@ from app.core.deps import get_current_user, get_db_session
|
||||
from app.schemas.acknowledgement import AcknowledgementCreate, AcknowledgementRead
|
||||
from app.schemas.common import PaginatedResponse
|
||||
from app.schemas.distribution import DistributionCreate, DistributionRead
|
||||
from app.schemas.document import DocumentCreate, DocumentDetail, DocumentSummary
|
||||
from app.schemas.document import DocumentCreate, DocumentDetail, DocumentSummary, DocumentUpdate
|
||||
from app.schemas.document_version import DocumentVersionRead
|
||||
from app.services import document_service
|
||||
from app.utils.pagination import paginate
|
||||
@@ -66,6 +66,17 @@ async def get_document_detail(
|
||||
return await document_service.get_document_detail(db, document_id, current_user)
|
||||
|
||||
|
||||
@router.patch("/documents/{document_id}", response_model=DocumentSummary)
|
||||
async def update_document(
|
||||
document_id: uuid.UUID,
|
||||
payload: DocumentUpdate,
|
||||
db: AsyncSession = Depends(get_db_session),
|
||||
current_user=Depends(get_current_user),
|
||||
) -> DocumentSummary:
|
||||
doc = await document_service.update_document(db, document_id, payload, current_user)
|
||||
return DocumentSummary.model_validate(doc)
|
||||
|
||||
|
||||
@router.delete("/documents/{document_id}", response_model=DocumentSummary)
|
||||
async def delete_document(
|
||||
document_id: uuid.UUID,
|
||||
|
||||
@@ -32,7 +32,7 @@ from app.models.document import Document, DocumentScopeType, DocumentStatus
|
||||
from app.models.document_version import DocumentVersion, DocumentVersionStatus
|
||||
from app.schemas.acknowledgement import AcknowledgementCreate
|
||||
from app.schemas.distribution import DistributionCreate, DistributionRead, DistributionStats
|
||||
from app.schemas.document import DocumentCreate, DocumentDetail, DocumentSummary
|
||||
from app.schemas.document import DocumentCreate, DocumentDetail, DocumentSummary, DocumentUpdate
|
||||
from app.schemas.document_version import DocumentVersionRead, DocumentVersionSummary
|
||||
from app.schemas.notification import NotificationItem
|
||||
from app.schemas.user import UserDisplay
|
||||
@@ -43,6 +43,7 @@ DOCUMENT_ACTION_PERMISSIONS = {
|
||||
"view": "documents:read",
|
||||
"ack": "documents:read",
|
||||
"create_document": "documents:create",
|
||||
"update_document": "documents:update",
|
||||
"create_version": "documents:update",
|
||||
"distribute": "documents:update",
|
||||
"delete_document": "documents:delete",
|
||||
@@ -261,6 +262,56 @@ async def get_document_detail(
|
||||
)
|
||||
|
||||
|
||||
async def update_document(
|
||||
db: AsyncSession,
|
||||
document_id: uuid.UUID,
|
||||
doc_in: DocumentUpdate,
|
||||
current_user,
|
||||
) -> Document:
|
||||
doc = await document_crud.get(db, document_id)
|
||||
if not doc:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="文档不存在")
|
||||
await _ensure_study_access(db, doc.trial_id, current_user, action="update_document")
|
||||
|
||||
values = doc_in.model_dump(exclude_unset=True)
|
||||
if not values:
|
||||
return doc
|
||||
|
||||
next_scope = values.get("scope_type", doc.scope_type)
|
||||
next_scope_value = getattr(next_scope, "value", next_scope)
|
||||
next_site_id = values.get("site_id", doc.site_id)
|
||||
if next_scope_value == DocumentScopeType.SITE.value:
|
||||
if not next_site_id:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="分中心文件需指定分中心")
|
||||
site = await site_crud.get_site(db, next_site_id)
|
||||
if not site or site.study_id != doc.trial_id:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="分中心不属于当前项目")
|
||||
if not site.is_active:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="中心已停用")
|
||||
else:
|
||||
values["site_id"] = None
|
||||
|
||||
before = _doc_snapshot(doc)
|
||||
await document_crud.update(db, document_id, values, commit=False)
|
||||
updated = await document_crud.get(db, document_id)
|
||||
if not updated:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="文档不存在")
|
||||
db.add(
|
||||
AuditLog(
|
||||
study_id=updated.trial_id,
|
||||
entity_type="DOCUMENT",
|
||||
entity_id=updated.id,
|
||||
action="DOCUMENT_UPDATED",
|
||||
detail=_audit_detail(before, _doc_snapshot(updated)),
|
||||
operator_id=current_user.id,
|
||||
operator_role=await get_operator_role_label(db, updated.trial_id, current_user),
|
||||
)
|
||||
)
|
||||
await db.commit()
|
||||
await db.refresh(updated)
|
||||
return updated
|
||||
|
||||
|
||||
async def create_version(
|
||||
db: AsyncSession,
|
||||
document_id: uuid.UUID,
|
||||
|
||||
Reference in New Issue
Block a user