324 lines
8.2 KiB
TypeScript
324 lines
8.2 KiB
TypeScript
"use client";
|
||
|
||
import React, { useState } from "react";
|
||
import {
|
||
Box,
|
||
TextField,
|
||
Button,
|
||
Typography,
|
||
MenuItem,
|
||
Stack,
|
||
} from "@mui/material";
|
||
import { PlayArrow as PlayArrowIcon } from "@mui/icons-material";
|
||
import { useNotification } from "@refinedev/core";
|
||
import { useGetIdentity } from "@refinedev/core";
|
||
import { api } from "@/lib/api";
|
||
import { config, NETWORK_NAME } from "@/config/config";
|
||
|
||
type IUser = {
|
||
id: string;
|
||
name?: string;
|
||
};
|
||
|
||
const OptimizationParameters: React.FC = () => {
|
||
const { open } = useNotification();
|
||
const { data: user } = useGetIdentity<IUser>();
|
||
|
||
// 表单状态
|
||
const [sensorType, setSensorType] = useState<string>("pressure");
|
||
const [method, setMethod] = useState<string>("kmeans");
|
||
const [sensorCount, setSensorCount] = useState<number>(5);
|
||
const [minDiameter, setMinDiameter] = useState<number>(5);
|
||
const [schemeName, setSchemeName] = useState<string>(
|
||
"Fangan" + new Date().getTime()
|
||
);
|
||
const [network] = useState<string>(NETWORK_NAME);
|
||
const [analyzing, setAnalyzing] = useState<boolean>(false);
|
||
|
||
// 传感器类型选项
|
||
const sensorTypeOptions = [
|
||
{ value: "pressure", label: "压力" },
|
||
{ value: "flow", label: "流量" },
|
||
];
|
||
|
||
// 方法选项
|
||
const methodOptions = [
|
||
{ value: "kmeans", label: "聚类分析" },
|
||
{ value: "sensitivity", label: "灵敏度分析" },
|
||
];
|
||
|
||
// 获取传感器类型的中文标签
|
||
const getSensorTypeLabel = (value: string) => {
|
||
return (
|
||
sensorTypeOptions.find((option) => option.value === value)?.label || value
|
||
);
|
||
};
|
||
|
||
// 创建方案
|
||
const handleCreateScheme = async () => {
|
||
// 验证输入
|
||
if (!schemeName.trim()) {
|
||
open?.({
|
||
type: "error",
|
||
message: "请输入方案名称",
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (sensorCount <= 0) {
|
||
open?.({
|
||
type: "error",
|
||
message: "监测点数目必须大于0",
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (minDiameter < 0) {
|
||
open?.({
|
||
type: "error",
|
||
message: "最小管径不能为负数",
|
||
});
|
||
return;
|
||
}
|
||
|
||
setAnalyzing(true);
|
||
|
||
if (!user || !user.id) {
|
||
open?.({
|
||
type: "error",
|
||
message: "用户信息无效",
|
||
});
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 发送优化请求
|
||
const response = await api.post(
|
||
`${config.BACKEND_URL}/api/v1/sensorplacementscheme/create`,
|
||
null,
|
||
{
|
||
params: {
|
||
network: network,
|
||
scheme_name: schemeName,
|
||
sensor_type: sensorType,
|
||
method: method,
|
||
sensor_count: sensorCount,
|
||
min_diameter: minDiameter,
|
||
user_id: user.id,
|
||
user_name: user.name,
|
||
},
|
||
}
|
||
);
|
||
|
||
console.log("响应数据:", response.data); // 添加日志以便调试
|
||
|
||
// 兼容后端返回字符串 "success" 或对象 { success: true }
|
||
if (response.data.success === true || response.data === "success") {
|
||
open?.({
|
||
type: "success",
|
||
message: "方案创建成功",
|
||
description: `方案 "${schemeName}" 已完成优化分析`,
|
||
});
|
||
|
||
// 重置方案名称
|
||
setSchemeName("Fangan" + new Date().getTime());
|
||
} else {
|
||
throw new Error(response.data?.message || "创建失败");
|
||
}
|
||
} catch (error: any) {
|
||
console.error("创建方案失败:", error);
|
||
open?.({
|
||
type: "error",
|
||
message: "创建方案失败",
|
||
description:
|
||
error.response?.data?.message || error.message || "未知错误",
|
||
});
|
||
} finally {
|
||
setAnalyzing(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<Box className="flex flex-col gap-4">
|
||
{/* 类型选择 */}
|
||
<Box>
|
||
<Typography
|
||
variant="subtitle2"
|
||
className="mb-2 font-semibold text-gray-700"
|
||
>
|
||
类型
|
||
</Typography>
|
||
<TextField
|
||
select
|
||
fullWidth
|
||
size="small"
|
||
value={sensorType}
|
||
onChange={(e) => setSensorType(e.target.value)}
|
||
sx={{
|
||
"& .MuiOutlinedInput-root": {
|
||
"&:hover fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
"&.Mui-focused fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
},
|
||
}}
|
||
>
|
||
{sensorTypeOptions.map((option) => (
|
||
<MenuItem key={option.value} value={option.value}>
|
||
{option.label}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
</Box>
|
||
|
||
{/* 方法选择 */}
|
||
<Box>
|
||
<Typography
|
||
variant="subtitle2"
|
||
className="mb-2 font-semibold text-gray-700"
|
||
>
|
||
方法
|
||
</Typography>
|
||
<TextField
|
||
select
|
||
fullWidth
|
||
size="small"
|
||
value={method}
|
||
onChange={(e) => setMethod(e.target.value)}
|
||
sx={{
|
||
"& .MuiOutlinedInput-root": {
|
||
"&:hover fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
"&.Mui-focused fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
},
|
||
}}
|
||
>
|
||
{methodOptions.map((option) => (
|
||
<MenuItem key={option.value} value={option.value}>
|
||
{option.label}
|
||
</MenuItem>
|
||
))}
|
||
</TextField>
|
||
</Box>
|
||
|
||
{/* 监测点数目 */}
|
||
<Box>
|
||
<Typography
|
||
variant="subtitle2"
|
||
className="mb-2 font-semibold text-gray-700"
|
||
>
|
||
监测点数目
|
||
</Typography>
|
||
<TextField
|
||
fullWidth
|
||
size="small"
|
||
type="number"
|
||
value={sensorCount}
|
||
onChange={(e) => setSensorCount(parseInt(e.target.value) || 0)}
|
||
slotProps={{
|
||
htmlInput: { min: 1 },
|
||
}}
|
||
sx={{
|
||
"& .MuiOutlinedInput-root": {
|
||
"&:hover fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
"&.Mui-focused fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
},
|
||
}}
|
||
/>
|
||
</Box>
|
||
|
||
{/* 压力监测点安装最小管径(可选) */}
|
||
<Box>
|
||
<Typography
|
||
variant="subtitle2"
|
||
className="mb-2 font-semibold text-gray-700"
|
||
>
|
||
{getSensorTypeLabel(sensorType)}监测点安装最小管径(可选)
|
||
</Typography>
|
||
<TextField
|
||
fullWidth
|
||
size="small"
|
||
type="number"
|
||
value={minDiameter}
|
||
onChange={(e) => setMinDiameter(parseInt(e.target.value) || 0)}
|
||
slotProps={{
|
||
htmlInput: { min: 0 },
|
||
}}
|
||
sx={{
|
||
"& .MuiOutlinedInput-root": {
|
||
"&:hover fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
"&.Mui-focused fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
},
|
||
}}
|
||
/>
|
||
</Box>
|
||
|
||
{/* 方案名称 */}
|
||
<Box>
|
||
<Typography
|
||
variant="subtitle2"
|
||
className="mb-2 font-semibold text-gray-700"
|
||
>
|
||
方案名称
|
||
</Typography>
|
||
<TextField
|
||
fullWidth
|
||
size="small"
|
||
value={schemeName}
|
||
onChange={(e) => setSchemeName(e.target.value)}
|
||
placeholder="请输入方案名称"
|
||
sx={{
|
||
"& .MuiOutlinedInput-root": {
|
||
"&:hover fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
"&.Mui-focused fieldset": {
|
||
borderColor: "#257DD4",
|
||
},
|
||
},
|
||
}}
|
||
/>
|
||
</Box>
|
||
|
||
{/* 创建方案按钮 */}
|
||
<Box className="flex justify-end mt-2">
|
||
<Button
|
||
variant="contained"
|
||
startIcon={<PlayArrowIcon />}
|
||
onClick={handleCreateScheme}
|
||
disabled={analyzing}
|
||
sx={{
|
||
backgroundColor: "#257DD4",
|
||
textTransform: "none",
|
||
px: 4,
|
||
py: 1,
|
||
"&:hover": {
|
||
backgroundColor: "#1e6bb8",
|
||
},
|
||
"&:disabled": {
|
||
backgroundColor: "#ccc",
|
||
},
|
||
}}
|
||
>
|
||
{analyzing ? "分析中..." : "创建方案"}
|
||
</Button>
|
||
</Box>
|
||
</Box>
|
||
);
|
||
};
|
||
|
||
export default OptimizationParameters;
|