116 lines
3.9 KiB
TypeScript
116 lines
3.9 KiB
TypeScript
import { getWorkbenchAccessToken } from "./request-context";
|
|
import { z } from "zod";
|
|
import type { WorkbenchAccess } from "./request-context";
|
|
import { env } from "@/shared/config/env";
|
|
import type { WaterNetworkSourceId } from "../map/sources";
|
|
import {
|
|
createWorkbenchHeaders,
|
|
findOwnedWorkbenchProject,
|
|
getServerError
|
|
} from "./project-client";
|
|
|
|
const gisAttributeGroupSchema = z.object({
|
|
dataset_key: z.string().min(1),
|
|
dataset_title: z.string().min(1),
|
|
source_date: z.string().date(),
|
|
layer_key: z.string().min(1),
|
|
layer_name: z.string().min(1),
|
|
source_fid: z.number().int(),
|
|
match_method: z.enum(["node_pair", "geometry", "source"]),
|
|
match_distance_m: z.number().finite().nonnegative().nullable(),
|
|
attributes: z.record(z.unknown())
|
|
});
|
|
|
|
const elementGisPropertiesSchema = z.object({
|
|
element_type: z.enum([
|
|
"pipes",
|
|
"junctions",
|
|
"valves",
|
|
"reservoirs",
|
|
"pumps",
|
|
"tanks",
|
|
"scada"
|
|
]),
|
|
element_id: z.string().min(1),
|
|
groups: z.array(gisAttributeGroupSchema)
|
|
});
|
|
|
|
const sourceGisFeaturePropertiesSchema = z.object({
|
|
layer_key: z.string().min(1),
|
|
source_fid: z.number().int().nonnegative(),
|
|
group: gisAttributeGroupSchema
|
|
});
|
|
|
|
export type GisAttributeGroup = z.infer<typeof gisAttributeGroupSchema>;
|
|
|
|
const SERVER_API_BASE_URL = env.TJWATER_SERVER_API_BASE_URL.replace(/\/$/, "");
|
|
|
|
export async function fetchElementGisProperties(
|
|
elementType: WaterNetworkSourceId,
|
|
elementId: string,
|
|
projectId: string | null,
|
|
getAccessToken?: WorkbenchAccess,
|
|
signal?: AbortSignal
|
|
): Promise<GisAttributeGroup[]> {
|
|
const ownedProject = projectId
|
|
? null
|
|
: await findOwnedWorkbenchProject(getAccessToken, signal);
|
|
const accessToken = ownedProject?.accessToken ?? await getWorkbenchAccessToken(getAccessToken);
|
|
const resolvedProjectId = projectId ?? ownedProject?.project.project_id;
|
|
if (!resolvedProjectId) throw new Error("未找到 GIS 台账所属项目");
|
|
const path = [
|
|
"/api/v1/elements",
|
|
encodeURIComponent(elementType),
|
|
encodeURIComponent(elementId),
|
|
"gis-properties"
|
|
].join("/");
|
|
const response = await fetch(`${SERVER_API_BASE_URL}${path}`, {
|
|
headers: createWorkbenchHeaders(accessToken, resolvedProjectId),
|
|
signal
|
|
});
|
|
const payload: unknown = await response.json().catch(() => null);
|
|
if (!response.ok) {
|
|
throw new Error(getServerError(payload, response.status, "GIS 台账属性查询"));
|
|
}
|
|
const result = elementGisPropertiesSchema.parse(payload);
|
|
if (result.element_type !== elementType || result.element_id !== elementId) {
|
|
throw new Error("GIS 台账属性与所选元素不一致");
|
|
}
|
|
return result.groups;
|
|
}
|
|
|
|
export async function fetchSourceGisFeatureProperties(
|
|
layerKey: string,
|
|
sourceFid: number,
|
|
projectId: string | null,
|
|
getAccessToken?: WorkbenchAccess,
|
|
signal?: AbortSignal
|
|
): Promise<GisAttributeGroup[]> {
|
|
const ownedProject = projectId
|
|
? null
|
|
: await findOwnedWorkbenchProject(getAccessToken, signal);
|
|
const accessToken = ownedProject?.accessToken ?? await getWorkbenchAccessToken(getAccessToken);
|
|
const resolvedProjectId = projectId ?? ownedProject?.project.project_id;
|
|
if (!resolvedProjectId) throw new Error("未找到 GIS 台账所属项目");
|
|
const path = [
|
|
"/api/v1/source-gis/layers",
|
|
encodeURIComponent(layerKey),
|
|
"features",
|
|
encodeURIComponent(String(sourceFid)),
|
|
"properties"
|
|
].join("/");
|
|
const response = await fetch(`${SERVER_API_BASE_URL}${path}`, {
|
|
headers: createWorkbenchHeaders(accessToken, resolvedProjectId),
|
|
signal
|
|
});
|
|
const payload: unknown = await response.json().catch(() => null);
|
|
if (!response.ok) {
|
|
throw new Error(getServerError(payload, response.status, "源 GIS 属性查询"));
|
|
}
|
|
const result = sourceGisFeaturePropertiesSchema.parse(payload);
|
|
if (result.layer_key !== layerKey || result.source_fid !== sourceFid) {
|
|
throw new Error("源 GIS 属性与所选要素不一致");
|
|
}
|
|
return [result.group];
|
|
}
|