添加获取项目信息接口及相关数据模型

This commit is contained in:
2026-03-17 18:27:58 +08:00
parent 2ea5ce14ba
commit c5d3075ae2
4 changed files with 81 additions and 1 deletions
+40 -1
View File
@@ -1,7 +1,10 @@
import json import json
from fastapi import APIRouter, Request, HTTPException, Query, Path, Body from fastapi import APIRouter, Request, HTTPException, Query, Path, Body, Depends
from fastapi.responses import PlainTextResponse from fastapi.responses import PlainTextResponse
from typing import Any, Dict, List from typing import Any, Dict, List
from app.infra.db.metadb.repositories.metadata_repository import MetadataRepository
from app.auth.project_dependencies import get_metadata_repository
from app.domain.schemas.metadata import ProjectMetaResponse, GeoServerConfigResponse
import app.services.project_info as project_info import app.services.project_info as project_info
from app.infra.db.postgresql.database import get_database_instance as get_pg_db from app.infra.db.postgresql.database import get_database_instance as get_pg_db
from app.infra.db.timescaledb.database import get_database_instance as get_ts_db from app.infra.db.timescaledb.database import get_database_instance as get_ts_db
@@ -39,6 +42,42 @@ inpDir = "data/" # Assuming data directory exists or is defined somewhere.
router = APIRouter() router = APIRouter()
lockedPrjs: Dict[str, str] = {} lockedPrjs: Dict[str, str] = {}
@router.get("/project_info/", summary="获取项目信息", description="从数据库获取项目的详细信息,包括地图范围等。", response_model=ProjectMetaResponse)
async def get_project_info_endpoint(
network: str = Query(..., description="管网名称(或项目代码)"),
metadata_repo: MetadataRepository = Depends(get_metadata_repository),
):
"""
获取项目信息
- **network**: 管网名称(或项目代码)
"""
project_detail = await metadata_repo.get_project_detail_by_code(network)
if not project_detail:
raise HTTPException(status_code=404, detail=f"Project {network} not found")
geoserver_payload = None
if project_detail.geoserver:
geoserver_payload = GeoServerConfigResponse(
gs_base_url=project_detail.geoserver.gs_base_url,
gs_admin_user=project_detail.geoserver.gs_admin_user,
gs_datastore_name=project_detail.geoserver.gs_datastore_name,
default_extent=project_detail.geoserver.default_extent,
srid=project_detail.geoserver.srid,
)
return ProjectMetaResponse(
project_id=project_detail.project_id,
name=project_detail.name,
code=project_detail.code,
description=project_detail.description,
gs_workspace=project_detail.gs_workspace,
map_extent=project_detail.map_extent,
status=project_detail.status,
project_role="viewer", # Default role for public access
geoserver=geoserver_payload
)
@router.get("/listprojects/", summary="获取项目列表", description="获取服务器上所有可用的供水管网项目名称列表。") @router.get("/listprojects/", summary="获取项目列表", description="获取服务器上所有可用的供水管网项目名称列表。")
async def list_projects_endpoint() -> list[str]: async def list_projects_endpoint() -> list[str]:
""" """
+1
View File
@@ -18,6 +18,7 @@ class ProjectMetaResponse(BaseModel):
code: str code: str
description: Optional[str] description: Optional[str]
gs_workspace: str gs_workspace: str
map_extent: Optional[dict]
status: str status: str
project_role: str project_role: str
geoserver: Optional[GeoServerConfigResponse] geoserver: Optional[GeoServerConfigResponse]
+1
View File
@@ -42,6 +42,7 @@ class Project(Base):
code: Mapped[str] = mapped_column(String(50), unique=True) code: Mapped[str] = mapped_column(String(50), unique=True)
description: Mapped[str | None] = mapped_column(Text, nullable=True) description: Mapped[str | None] = mapped_column(Text, nullable=True)
gs_workspace: Mapped[str] = mapped_column(String(100), unique=True) gs_workspace: Mapped[str] = mapped_column(String(100), unique=True)
map_extent: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
status: Mapped[str] = mapped_column(String(20), default="active") status: Mapped[str] = mapped_column(String(20), default="active")
created_at: Mapped[datetime] = mapped_column( created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=datetime.utcnow DateTime(timezone=True), default=datetime.utcnow
@@ -61,10 +61,23 @@ class ProjectSummary:
code: str code: str
description: Optional[str] description: Optional[str]
gs_workspace: str gs_workspace: str
map_extent: Optional[dict]
status: str status: str
project_role: str project_role: str
@dataclass(frozen=True)
class ProjectDetail:
project_id: UUID
name: str
code: str
description: Optional[str]
gs_workspace: str
map_extent: Optional[dict]
status: str
geoserver: Optional[ProjectGeoServerInfo]
class MetadataRepository: class MetadataRepository:
"""元数据访问层(system_hub""" """元数据访问层(system_hub"""
@@ -89,6 +102,30 @@ class MetadataRepository:
) )
return result.scalar_one_or_none() return result.scalar_one_or_none()
async def get_project_by_code(self, code: str) -> Optional[models.Project]:
result = await self.session.execute(
select(models.Project).where(models.Project.code == code)
)
return result.scalar_one_or_none()
async def get_project_detail_by_code(self, code: str) -> Optional[ProjectDetail]:
project = await self.get_project_by_code(code)
if not project:
return None
geoserver = await self.get_geoserver_config(project.id)
return ProjectDetail(
project_id=project.id,
name=project.name,
code=project.code,
description=project.description,
gs_workspace=project.gs_workspace,
map_extent=project.map_extent,
status=project.status,
geoserver=geoserver
)
async def get_membership_role( async def get_membership_role(
self, project_id: UUID, user_id: UUID self, project_id: UUID, user_id: UUID
) -> Optional[str]: ) -> Optional[str]:
@@ -179,6 +216,7 @@ class MetadataRepository:
code=project.code, code=project.code,
description=project.description, description=project.description,
gs_workspace=project.gs_workspace, gs_workspace=project.gs_workspace,
map_extent=project.map_extent,
status=project.status, status=project.status,
project_role=role, project_role=role,
) )
@@ -196,6 +234,7 @@ class MetadataRepository:
code=project.code, code=project.code,
description=project.description, description=project.description,
gs_workspace=project.gs_workspace, gs_workspace=project.gs_workspace,
map_extent=project.map_extent,
status=project.status, status=project.status,
project_role="owner", project_role="owner",
) )