From c5d3075ae24cb1b76ecd1f7668b4b6dc18b8f6b6 Mon Sep 17 00:00:00 2001 From: Jiang Date: Tue, 17 Mar 2026 18:27:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=8E=B7=E5=8F=96=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E4=BF=A1=E6=81=AF=E6=8E=A5=E5=8F=A3=E5=8F=8A=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=95=B0=E6=8D=AE=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/v1/endpoints/project.py | 41 ++++++++++++++++++- app/domain/schemas/metadata.py | 1 + app/infra/db/metadb/models.py | 1 + .../repositories/metadata_repository.py | 39 ++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/app/api/v1/endpoints/project.py b/app/api/v1/endpoints/project.py index 3c7e898..95584b6 100644 --- a/app/api/v1/endpoints/project.py +++ b/app/api/v1/endpoints/project.py @@ -1,7 +1,10 @@ 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 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 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 @@ -39,6 +42,42 @@ inpDir = "data/" # Assuming data directory exists or is defined somewhere. router = APIRouter() 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="获取服务器上所有可用的供水管网项目名称列表。") async def list_projects_endpoint() -> list[str]: """ diff --git a/app/domain/schemas/metadata.py b/app/domain/schemas/metadata.py index b3f4952..91dc4c3 100644 --- a/app/domain/schemas/metadata.py +++ b/app/domain/schemas/metadata.py @@ -18,6 +18,7 @@ class ProjectMetaResponse(BaseModel): code: str description: Optional[str] gs_workspace: str + map_extent: Optional[dict] status: str project_role: str geoserver: Optional[GeoServerConfigResponse] diff --git a/app/infra/db/metadb/models.py b/app/infra/db/metadb/models.py index 7c48643..6236080 100644 --- a/app/infra/db/metadb/models.py +++ b/app/infra/db/metadb/models.py @@ -42,6 +42,7 @@ class Project(Base): code: Mapped[str] = mapped_column(String(50), unique=True) description: Mapped[str | None] = mapped_column(Text, nullable=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") created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=datetime.utcnow diff --git a/app/infra/db/metadb/repositories/metadata_repository.py b/app/infra/db/metadb/repositories/metadata_repository.py index 943097f..9631d7b 100644 --- a/app/infra/db/metadb/repositories/metadata_repository.py +++ b/app/infra/db/metadb/repositories/metadata_repository.py @@ -61,10 +61,23 @@ class ProjectSummary: code: str description: Optional[str] gs_workspace: str + map_extent: Optional[dict] status: 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: """元数据访问层(system_hub)""" @@ -89,6 +102,30 @@ class MetadataRepository: ) 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( self, project_id: UUID, user_id: UUID ) -> Optional[str]: @@ -179,6 +216,7 @@ class MetadataRepository: code=project.code, description=project.description, gs_workspace=project.gs_workspace, + map_extent=project.map_extent, status=project.status, project_role=role, ) @@ -196,6 +234,7 @@ class MetadataRepository: code=project.code, description=project.description, gs_workspace=project.gs_workspace, + map_extent=project.map_extent, status=project.status, project_role="owner", )