feat: initialize drainage network frontend

This commit is contained in:
2026-07-10 16:16:17 +08:00
commit 66de96d9e4
133 changed files with 33057 additions and 0 deletions
@@ -0,0 +1,55 @@
"use client";
import { X } from "lucide-react";
import {
MAP_MAJOR_PANEL_RADIUS_CLASS_NAME,
MAP_READABLE_RADIUS_CLASS_NAME
} from "@/features/map/core/components/map-control-styles";
import { cn } from "@/lib/utils";
import type { DetailFeature } from "../types";
import { getLocalizedFeatureProperties } from "../utils/feature-properties";
type FeaturePopoverProps = {
feature: DetailFeature | null;
onClose: () => void;
};
export function FeaturePopover({ feature, onClose }: FeaturePopoverProps) {
if (!feature) {
return null;
}
const entries = getLocalizedFeatureProperties(feature.properties).slice(0, 4);
return (
<aside className={cn("pointer-events-auto absolute left-1/2 top-[92px] z-20 w-[min(360px,calc(100vw-32px))] -translate-x-1/2 border border-white/60 bg-white/70 p-4 shadow-2xl shadow-blue-950/20 backdrop-blur-2xl", MAP_MAJOR_PANEL_RADIUS_CLASS_NAME)}>
<div className="flex items-start justify-between gap-3">
<div className="min-w-0">
<p className="text-xs font-semibold text-blue-600">{feature.layer === "pipes" ? "管线要素" : "节点要素"}</p>
<h3 className="mt-1 truncate text-base font-semibold text-slate-950">{feature.title}</h3>
<p className="mt-1 truncate text-sm text-slate-500">{feature.subtitle}</p>
</div>
<button
type="button"
aria-label="关闭要素信息"
title="关闭要素信息"
onClick={onClose}
className="grid h-8 w-8 shrink-0 place-items-center rounded-full text-slate-500 hover:bg-slate-100 hover:text-slate-900"
>
<X size={16} aria-hidden="true" />
</button>
</div>
{entries.length > 0 ? (
<dl className="mt-3 grid grid-cols-2 gap-2">
{entries.map((entry) => (
<div key={entry.key} className={cn("bg-white/95 px-3 py-2 shadow-lg shadow-blue-950/10", MAP_READABLE_RADIUS_CLASS_NAME)}>
<dt className="truncate text-xs font-medium text-slate-500">{entry.label}</dt>
<dd className="mt-1 truncate text-sm font-semibold text-slate-800">{entry.value}</dd>
</div>
))}
</dl>
) : null}
</aside>
);
}