新增水质分析功能模块

This commit is contained in:
JIANG
2026-01-30 15:22:53 +08:00
parent c28325e997
commit d584268acd
12 changed files with 346 additions and 238 deletions
@@ -22,7 +22,7 @@ import { config, NETWORK_NAME } from "@/config/config";
import { useMap } from "@app/OlMap/MapComponent";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Style, Stroke, Fill, Circle as CircleStyle } from "ol/style";
import { Style, Stroke, Fill, Circle as CircleStyle, Icon } from "ol/style";
import Feature from "ol/Feature";
import { handleMapClickSelectFeatures as mapClickSelectFeatures } from "@/utils/mapQueryService";
@@ -31,10 +31,13 @@ const AnalysisParameters: React.FC = () => {
const { open } = useNotification();
const network = NETWORK_NAME;
const [schemeName, setSchemeName] = useState<string>(
"WQ_" + new Date().getTime(),
);
const [startTime, setStartTime] = useState<Dayjs | null>(dayjs(new Date()));
const [sourceNode, setSourceNode] = useState<string>("");
const [concentration, setConcentration] = useState<number>(1);
const [duration, setDuration] = useState<number>(900);
const [concentration, setConcentration] = useState<number>(100);
const [duration, setDuration] = useState<number>(3600);
const [pattern, setPattern] = useState<string>("");
const [isSelecting, setIsSelecting] = useState<boolean>(false);
const [submitting, setSubmitting] = useState<boolean>(false);
@@ -42,7 +45,7 @@ const AnalysisParameters: React.FC = () => {
const [highlightLayer, setHighlightLayer] =
useState<VectorLayer<VectorSource> | null>(null);
const [highlightFeature, setHighlightFeature] = useState<Feature | null>(
null
null,
);
const isFormValid = useMemo(() => {
@@ -51,20 +54,41 @@ const AnalysisParameters: React.FC = () => {
Boolean(startTime) &&
Boolean(sourceNode) &&
concentration > 0 &&
duration > 0
duration > 0 &&
schemeName.trim() !== ""
);
}, [network, startTime, sourceNode, concentration, duration]);
}, [network, startTime, sourceNode, concentration, duration, schemeName]);
useEffect(() => {
if (!map) return;
const sourceStyle = new Style({
image: new CircleStyle({
radius: 10,
fill: new Fill({ color: "rgba(37, 125, 212, 0.35)" }),
stroke: new Stroke({ color: "rgba(37, 125, 212, 1)", width: 3 }),
const themeColor = "rgba(3, 168, 107"; // #03a86b
const sourceStyle = [
// 外层扩散光圈
new Style({
image: new CircleStyle({
radius: 12,
fill: new Fill({ color: `${themeColor}, 0.2)` }),
}),
}),
});
// 中层扩散背景
new Style({
image: new CircleStyle({
radius: 8,
stroke: new Stroke({ color: `${themeColor}, 0.5)`, width: 2 }),
fill: new Fill({ color: `${themeColor}, 0.3)` }),
}),
}),
// 上层图标
new Style({
image: new Icon({
src: "/icons/contaminant_source.svg",
scale: 0.2,
anchor: [0.5, 1],
}),
}),
];
const layer = new VectorLayer({
source: new VectorSource(),
@@ -117,7 +141,7 @@ const AnalysisParameters: React.FC = () => {
setIsSelecting(false);
map.un("click", handleMapClickSelectFeatures);
},
[map, open]
[map, open],
);
const handleStartSelection = () => {
@@ -146,15 +170,19 @@ const AnalysisParameters: React.FC = () => {
message: "方案提交分析中",
undoableTimeout: 3,
});
// 格式化开始时间,去除秒部分
const start_time = startTime
? startTime.format("YYYY-MM-DDTHH:mm:00Z")
: "";
try {
const params = {
network,
start_time: startTime.toISOString(),
start_time: start_time,
source: sourceNode,
concentration,
duration,
pattern: pattern || undefined,
scheme_name: schemeName,
};
await axios.get(`${config.BACKEND_URL}/api/v1/contaminant_simulation/`, {
@@ -297,13 +325,14 @@ const AnalysisParameters: React.FC = () => {
<Box className="mb-4">
<Typography variant="subtitle2" className="mb-2 font-medium">
</Typography>
<TextField
fullWidth
size="small"
value={network}
disabled
value={schemeName}
onChange={(e) => setSchemeName(e.target.value)}
placeholder="输入方案名称"
/>
</Box>