更新api url

This commit is contained in:
JIANG
2026-01-29 11:18:54 +08:00
parent 7122b0b2ac
commit 5cb2d17be1
17 changed files with 85 additions and 84 deletions

View File

@@ -91,13 +91,13 @@ const fetchFromBackend = async (
.join(","); .join(",");
// 监测值数据接口use_cleaned=false // 监测值数据接口use_cleaned=false
const rawDataUrl = `${config.BACKEND_URL}/timescaledb/composite/element-scada?element_id=${feature_ids}&start_time=${start_time}&end_time=${end_time}&use_cleaned=false`; const rawDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-scada?element_id=${feature_ids}&start_time=${start_time}&end_time=${end_time}&use_cleaned=false`;
// 清洗数据接口use_cleaned=true // 清洗数据接口use_cleaned=true
const cleanedDataUrl = `${config.BACKEND_URL}/timescaledb/composite/element-scada?element_id=${feature_ids}&start_time=${start_time}&end_time=${end_time}&use_cleaned=true`; const cleanedDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-scada?element_id=${feature_ids}&start_time=${start_time}&end_time=${end_time}&use_cleaned=true`;
// 模拟数据接口 // 模拟数据接口
const simulationDataUrl = `${config.BACKEND_URL}/timescaledb/composite/element-simulation?feature_infos=${feature_infos}&start_time=${start_time}&end_time=${end_time}`; const simulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-simulation?feature_infos=${feature_infos}&start_time=${start_time}&end_time=${end_time}`;
// 策略模拟数据接口 // 策略模拟数据接口
const schemeSimulationDataUrl = `${config.BACKEND_URL}/timescaledb/composite/element-simulation?feature_infos=${feature_infos}&start_time=${start_time}&end_time=${end_time}&scheme_type=${scheme_type}&scheme_name=${scheme_name}`; const schemeSimulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-simulation?feature_infos=${feature_infos}&start_time=${start_time}&end_time=${end_time}&scheme_type=${scheme_type}&scheme_name=${scheme_name}`;
try { try {
if (type === "none") { if (type === "none") {

View File

@@ -29,7 +29,6 @@ import { FiSkipBack, FiSkipForward } from "react-icons/fi";
import { useData } from "../MapComponent"; import { useData } from "../MapComponent";
import { config, NETWORK_NAME } from "@/config/config"; import { config, NETWORK_NAME } from "@/config/config";
import { useMap } from "../MapComponent"; import { useMap } from "../MapComponent";
const backendUrl = config.BACKEND_URL;
interface TimelineProps { interface TimelineProps {
schemeDate?: Date; schemeDate?: Date;
@@ -103,7 +102,7 @@ const Timeline: React.FC<TimelineProps> = ({
junctionProperties: string, junctionProperties: string,
pipeProperties: string, pipeProperties: string,
schemeName: string, schemeName: string,
schemeType: string schemeType: string,
) => { ) => {
const query_time = queryTime.toISOString(); const query_time = queryTime.toISOString();
let nodeRecords: any = { results: [] }; let nodeRecords: any = { results: [] };
@@ -119,12 +118,12 @@ const Timeline: React.FC<TimelineProps> = ({
} else { } else {
disableDateSelection && schemeName disableDateSelection && schemeName
? (nodePromise = fetch( ? (nodePromise = fetch(
// `${backendUrl}/queryallschemerecordsbytimeproperty/?querytime=${query_time}&type=node&property=${junctionProperties}&schemename=${schemeName}` // `${config.BACKEND_URL}/queryallschemerecordsbytimeproperty/?querytime=${query_time}&type=node&property=${junctionProperties}&schemename=${schemeName}`
`${backendUrl}/timescaledb/scheme/query/by-scheme-time-property?scheme_type=${schemeType}&scheme_name=${schemeName}&query_time=${query_time}&type=node&property=${junctionProperties}` `${config.BACKEND_URL}/api/v1/scheme/query/by-scheme-time-property?scheme_type=${schemeType}&scheme_name=${schemeName}&query_time=${query_time}&type=node&property=${junctionProperties}`,
)) ))
: (nodePromise = fetch( : (nodePromise = fetch(
// `${backendUrl}/queryallrecordsbytimeproperty/?querytime=${query_time}&type=node&property=${junctionProperties}` // `${config.BACKEND_URL}/queryallrecordsbytimeproperty/?querytime=${query_time}&type=node&property=${junctionProperties}`
`${backendUrl}/timescaledb/realtime/query/by-time-property?query_time=${query_time}&type=node&property=${junctionProperties}` `${config.BACKEND_URL}/api/v1/realtime/query/by-time-property?query_time=${query_time}&type=node&property=${junctionProperties}`,
)); ));
requests.push(nodePromise); requests.push(nodePromise);
} }
@@ -140,12 +139,12 @@ const Timeline: React.FC<TimelineProps> = ({
} else { } else {
disableDateSelection && schemeName disableDateSelection && schemeName
? (linkPromise = fetch( ? (linkPromise = fetch(
// `${backendUrl}/queryallschemerecordsbytimeproperty/?querytime=${query_time}&type=link&property=${pipeProperties}&schemename=${schemeName}` // `${config.BACKEND_URL}/queryallschemerecordsbytimeproperty/?querytime=${query_time}&type=link&property=${pipeProperties}&schemename=${schemeName}`
`${backendUrl}/timescaledb/scheme/query/by-scheme-time-property?scheme_type=${schemeType}&scheme_name=${schemeName}&query_time=${query_time}&type=link&property=${pipeProperties}` `${config.BACKEND_URL}/api/v1/scheme/query/by-scheme-time-property?scheme_type=${schemeType}&scheme_name=${schemeName}&query_time=${query_time}&type=link&property=${pipeProperties}`,
)) ))
: (linkPromise = fetch( : (linkPromise = fetch(
// `${backendUrl}/queryallrecordsbytimeproperty/?querytime=${query_time}&type=link&property=${pipeProperties}` // `${config.BACKEND_URL}/queryallrecordsbytimeproperty/?querytime=${query_time}&type=link&property=${pipeProperties}`
`${backendUrl}/timescaledb/realtime/query/by-time-property?query_time=${query_time}&type=link&property=${pipeProperties}` `${config.BACKEND_URL}/api/v1/realtime/query/by-time-property?query_time=${query_time}&type=link&property=${pipeProperties}`,
)); ));
requests.push(linkPromise); requests.push(linkPromise);
} }
@@ -162,7 +161,7 @@ const Timeline: React.FC<TimelineProps> = ({
// 缓存数据(修复键以包含 schemeName // 缓存数据(修复键以包含 schemeName
nodeCacheRef.current.set( nodeCacheRef.current.set(
`${query_time}_${junctionProperties}_${schemeName}_${schemeType}`, `${query_time}_${junctionProperties}_${schemeName}_${schemeType}`,
nodeRecords || [] nodeRecords || [],
); );
} }
if (linkPromise) { if (linkPromise) {
@@ -173,7 +172,7 @@ const Timeline: React.FC<TimelineProps> = ({
// 缓存数据(修复键以包含 schemeName // 缓存数据(修复键以包含 schemeName
linkCacheRef.current.set( linkCacheRef.current.set(
`${query_time}_${pipeProperties}_${schemeName}_${schemeType}`, `${query_time}_${pipeProperties}_${schemeName}_${schemeType}`,
linkRecords || [] linkRecords || [],
); );
} }
// 更新状态 // 更新状态
@@ -249,7 +248,7 @@ const Timeline: React.FC<TimelineProps> = ({
setCurrentTime(value); setCurrentTime(value);
}, 500); // 500ms 防抖延迟 }, 500); // 500ms 防抖延迟
}, },
[timeRange, minTime, maxTime] [timeRange, minTime, maxTime],
); );
// 播放控制 // 播放控制
@@ -366,7 +365,7 @@ const Timeline: React.FC<TimelineProps> = ({
}, newInterval); }, newInterval);
} }
}, },
[isPlaying] [isPlaying],
); );
// 计算时间段改变处理 // 计算时间段改变处理
const handleCalculatedIntervalChange = useCallback((event: any) => { const handleCalculatedIntervalChange = useCallback((event: any) => {
@@ -393,10 +392,17 @@ const Timeline: React.FC<TimelineProps> = ({
junctionText, junctionText,
pipeText, pipeText,
schemeName, schemeName,
schemeType schemeType,
); );
} }
}, [junctionText, pipeText, currentTime, selectedDate, schemeName, schemeType]); }, [
junctionText,
pipeText,
currentTime,
selectedDate,
schemeName,
schemeType,
]);
// 组件卸载时清理定时器和防抖 // 组件卸载时清理定时器和防抖
useEffect(() => { useEffect(() => {
@@ -445,7 +451,7 @@ const Timeline: React.FC<TimelineProps> = ({
const dateStr = date.toISOString().split("T")[0]; const dateStr = date.toISOString().split("T")[0];
const clearCache = ( const clearCache = (
cacheRef: ReturnType<typeof useRef<Map<string, any[]>>> cacheRef: ReturnType<typeof useRef<Map<string, any[]>>>,
) => { ) => {
if (!cacheRef.current) return; if (!cacheRef.current) return;
const cacheKeys = Array.from(cacheRef.current.keys()); const cacheKeys = Array.from(cacheRef.current.keys());
@@ -474,7 +480,7 @@ const Timeline: React.FC<TimelineProps> = ({
junctionText, junctionText,
pipeText, pipeText,
schemeName, schemeName,
schemeType schemeType,
); );
}; };
@@ -508,14 +514,14 @@ const Timeline: React.FC<TimelineProps> = ({
}; };
const response = await fetch( const response = await fetch(
`${backendUrl}/runsimulationmanuallybydate/`, `${config.BACKEND_URL}/api/v1/runsimulationmanuallybydate/`,
{ {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify(body), body: JSON.stringify(body),
} },
); );
if (response.ok) { if (response.ok) {

View File

@@ -20,7 +20,6 @@ import { handleMapClickSelectFeatures as mapClickSelectFeatures } from "@/utils/
import { useNotification } from "@refinedev/core"; import { useNotification } from "@refinedev/core";
import { config } from "@/config/config"; import { config } from "@/config/config";
const backendUrl = config.BACKEND_URL;
// 添加接口定义隐藏按钮的props // 添加接口定义隐藏按钮的props
interface ToolbarProps { interface ToolbarProps {
@@ -229,7 +228,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
if (getBaseType(layerId) !== getBaseType(firstLayerId)) { if (getBaseType(layerId) !== getBaseType(firstLayerId)) {
// 如果点击的是已选中的要素(为了取消选中),则不报错 // 如果点击的是已选中的要素(为了取消选中),则不报错
const isAlreadySelected = highlightFeatures.some( const isAlreadySelected = highlightFeatures.some(
(f) => f.getProperties().id === featureId (f) => f.getProperties().id === featureId,
); );
if (!isAlreadySelected) { if (!isAlreadySelected) {
open?.({ open?.({
@@ -243,7 +242,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
setHighlightFeatures((prev) => { setHighlightFeatures((prev) => {
const existingIndex = prev.findIndex( const existingIndex = prev.findIndex(
(f) => f.getProperties().id === featureId (f) => f.getProperties().id === featureId,
); );
if (existingIndex !== -1) { if (existingIndex !== -1) {
@@ -259,7 +258,7 @@ const Toolbar: React.FC<ToolbarProps> = ({
setHighlightFeatures([feature]); setHighlightFeatures([feature]);
} }
}, },
[map, activeTools, highlightFeatures, open] [map, activeTools, highlightFeatures, open],
); );
// 添加矢量属性查询事件监听器 // 添加矢量属性查询事件监听器
useEffect(() => { useEffect(() => {
@@ -388,13 +387,13 @@ const Toolbar: React.FC<ToolbarProps> = ({
let response; let response;
if (queryType === "scheme") { if (queryType === "scheme") {
response = await fetch( response = await fetch(
// `${backendUrl}/queryschemesimulationrecordsbyidtime/?scheme_name=${schemeName}&id=${id}&querytime=${querytime}&type=${type}` // `${config.BACKEND_URL}/queryschemesimulationrecordsbyidtime/?scheme_name=${schemeName}&id=${id}&querytime=${querytime}&type=${type}`
`${backendUrl}/timescaledb/scheme/query/by-id-time?scheme_name=${schemeName}&id=${id}&type=${type}&query_time=${querytime}` `${config.BACKEND_URL}/api/v1/scheme/query/by-id-time?scheme_name=${schemeName}&id=${id}&type=${type}&query_time=${querytime}`,
); );
} else { } else {
response = await fetch( response = await fetch(
// `${backendUrl}/querysimulationrecordsbyidtime/?id=${id}&querytime=${querytime}&type=${type}` // `${config.BACKEND_URL}/querysimulationrecordsbyidtime/?id=${id}&querytime=${querytime}&type=${type}`
`${backendUrl}/timescaledb/realtime/query/by-id-time?id=${id}&type=${type}&query_time=${querytime}` `${config.BACKEND_URL}/api/v1/realtime/query/by-id-time?id=${id}&type=${type}&query_time=${querytime}`,
); );
} }
if (!response.ok) { if (!response.ok) {

View File

@@ -154,11 +154,11 @@ const App = (props: React.PropsWithChildren<AppProps>) => {
}, },
}, },
{ {
name: "爆管分析定位", name: "风险分析定位",
list: "/burst-pipe-analysis", list: "/risk-analysis-location",
meta: { meta: {
icon: <TbLocationPin className="w-6 h-6" />, icon: <TbLocationPin className="w-6 h-6" />,
label: "爆管分析定位", label: "风险分析定位",
}, },
}, },
{ {

View File

@@ -283,7 +283,7 @@ const AnalysisParameters: React.FC = () => {
}; };
try { try {
await axios.post(`${config.BACKEND_URL}/burst_analysis/`, body, { await axios.post(`${config.BACKEND_URL}/api/v1/burst_analysis/`, body, {
headers: { headers: {
"Accept-Encoding": "gzip", "Accept-Encoding": "gzip",
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@@ -129,7 +129,7 @@ const BurstPipeAnalysisPanel: React.FC<BurstPipeAnalysisPanelProps> = ({
const handleLocateScheme = async (scheme: SchemeRecord) => { const handleLocateScheme = async (scheme: SchemeRecord) => {
try { try {
const response = await axios.get( const response = await axios.get(
`${config.BACKEND_URL}/postgresql/burst-locate-result/${scheme.schemeName}` `${config.BACKEND_URL}/api/v1/burst-locate-result/${scheme.schemeName}`
); );
setLocationResults(response.data); setLocationResults(response.data);
setCurrentTab(2); // 切换到定位结果标签页 setCurrentTab(2); // 切换到定位结果标签页

View File

@@ -133,7 +133,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
setLoading(true); setLoading(true);
try { try {
const response = await axios.get( const response = await axios.get(
`${config.BACKEND_URL}/getallschemes/?network=${network}` `${config.BACKEND_URL}/api/v1/getallschemes/?network=${network}`
); );
let filteredResults = response.data; let filteredResults = response.data;

View File

@@ -157,7 +157,7 @@ const AnalysisParameters: React.FC = () => {
pattern: pattern || undefined, pattern: pattern || undefined,
}; };
await axios.get(`${config.BACKEND_URL}/contaminant_simulation/`, { await axios.get(`${config.BACKEND_URL}/api/v1/contaminant_simulation/`, {
params, params,
}); });

View File

@@ -93,7 +93,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
setLoading(true); setLoading(true);
try { try {
const response = await axios.get( const response = await axios.get(
`${config.BACKEND_URL}/getallschemes/?network=${network}` `${config.BACKEND_URL}/api/v1/getallschemes/?network=${network}`
); );
let filteredResults = response.data; let filteredResults = response.data;

View File

@@ -38,8 +38,6 @@ import {
RISK_BREAKS, RISK_BREAKS,
} from "./types"; } from "./types";
const backendUrl = config.BACKEND_URL;
// 辅助函数将日期向下取整到最近的15分钟 // 辅助函数将日期向下取整到最近的15分钟
const getRoundedDate = (date: Date): Date => { const getRoundedDate = (date: Date): Date => {
const minutes = date.getHours() * 60 + date.getMinutes(); const minutes = date.getHours() * 60 + date.getMinutes();
@@ -49,7 +47,7 @@ const getRoundedDate = (date: Date): Date => {
Math.floor(roundedMinutes / 60), Math.floor(roundedMinutes / 60),
roundedMinutes % 60, roundedMinutes % 60,
0, 0,
0 0,
); );
return roundedDate; return roundedDate;
}; };
@@ -124,7 +122,7 @@ const Timeline: React.FC<TimelineProps> = ({
setCurrentYear(value); setCurrentYear(value);
}, 500); // 500ms 防抖延迟 }, 500); // 500ms 防抖延迟
}, },
[minTime, maxTime] [minTime, maxTime],
); );
// 播放控制 // 播放控制
@@ -215,7 +213,7 @@ const Timeline: React.FC<TimelineProps> = ({
}, newInterval); }, newInterval);
} }
}, },
[isPlaying] [isPlaying],
); );
// 组件加载时设置初始时间为当前时间的最近15分钟 // 组件加载时设置初始时间为当前时间的最近15分钟
@@ -245,7 +243,7 @@ const Timeline: React.FC<TimelineProps> = ({
const safeIndex = Math.max(0, Math.min(index, y.length - 1)); const safeIndex = Math.max(0, Math.min(index, y.length - 1));
return y[safeIndex]; return y[safeIndex];
}, },
[] [],
); );
// 更新管道图层中的 healthRisk 属性 // 更新管道图层中的 healthRisk 属性
@@ -270,7 +268,7 @@ const Timeline: React.FC<TimelineProps> = ({
}); });
}); });
}, },
[pipeLayer] [pipeLayer],
); );
// 监听瓦片加载,为新瓦片设置 healthRisk 属性 // 监听瓦片加载,为新瓦片设置 healthRisk 属性
@@ -313,7 +311,7 @@ const Timeline: React.FC<TimelineProps> = ({
predictionResults.forEach((result) => { predictionResults.forEach((result) => {
const probability = getSurvivalProbabilityAtYear( const probability = getSurvivalProbabilityAtYear(
result.survival_function, result.survival_function,
currentYear - 4 // 使用索引 (0-based) currentYear - 4, // 使用索引 (0-based)
); );
pipeHealthData.set(result.link_id, probability); pipeHealthData.set(result.link_id, probability);
}); });
@@ -347,7 +345,7 @@ const Timeline: React.FC<TimelineProps> = ({
widthCases.push(["<=", ["get", "healthRisk"], breakValue], width); widthCases.push(["<=", ["get", "healthRisk"], breakValue], width);
}); });
console.log( console.log(
`应用健康风险样式,年份: ${currentYear}, 分段: ${breaks.length}` `应用健康风险样式,年份: ${currentYear}, 分段: ${breaks.length}`,
); );
console.log("颜色表达式:", colorCases); console.log("颜色表达式:", colorCases);
console.log("宽度表达式:", widthCases); console.log("宽度表达式:", widthCases);
@@ -371,7 +369,7 @@ const Timeline: React.FC<TimelineProps> = ({
const layers = map.getLayers().getArray(); const layers = map.getLayers().getArray();
const pipesLayer = layers.find( const pipesLayer = layers.find(
(layer) => (layer) =>
layer instanceof WebGLVectorTileLayer && layer.get("value") === "pipes" layer instanceof WebGLVectorTileLayer && layer.get("value") === "pipes",
) as WebGLVectorTileLayer | undefined; ) as WebGLVectorTileLayer | undefined;
if (pipesLayer) { if (pipesLayer) {
@@ -426,7 +424,7 @@ const Timeline: React.FC<TimelineProps> = ({
}); });
try { try {
const response = await fetch( const response = await fetch(
`${backendUrl}/timescaledb/composite/pipeline-health-prediction?query_time=${query_time}&network_name=${NETWORK_NAME}` `${config.BACKEND_URL}/api/v1/composite/pipeline-health-prediction?query_time=${query_time}&network_name=${NETWORK_NAME}`,
); );
if (response.ok) { if (response.ok) {

View File

@@ -94,7 +94,7 @@ const OptimizationParameters: React.FC = () => {
try { try {
// 发送优化请求 // 发送优化请求
const response = await axios.post( const response = await axios.post(
`${config.BACKEND_URL}/sensorplacementscheme/create`, `${config.BACKEND_URL}/api/v1/sensorplacementscheme/create`,
null, null,
{ {
params: { params: {

View File

@@ -148,7 +148,7 @@ const SchemeQuery: React.FC<SchemeQueryProps> = ({
setLoading(true); setLoading(true);
try { try {
const response = await axios.get( const response = await axios.get(
`${config.BACKEND_URL}/getallsensorplacements/?network=${network}` `${config.BACKEND_URL}/api/v1/getallsensorplacements/?network=${network}`
); );
let filteredResults = response.data; let filteredResults = response.data;

View File

@@ -78,7 +78,7 @@ type LoadingState = "idle" | "loading" | "success" | "error";
*/ */
const fetchFromBackend = async ( const fetchFromBackend = async (
deviceIds: string[], deviceIds: string[],
range: { from: Date; to: Date } range: { from: Date; to: Date },
): Promise<TimeSeriesPoint[]> => { ): Promise<TimeSeriesPoint[]> => {
if (deviceIds.length === 0) { if (deviceIds.length === 0) {
return []; return [];
@@ -88,12 +88,11 @@ const fetchFromBackend = async (
const start_time = dayjs(range.from).toISOString(); const start_time = dayjs(range.from).toISOString();
const end_time = dayjs(range.to).toISOString(); const end_time = dayjs(range.to).toISOString();
// 清洗数据接口 // 清洗数据接口
const cleaningDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`; const cleaningDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`;
// 原始数据 // 原始数据
const rawDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`; const rawDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`;
// 模拟数据接口 // 模拟数据接口
const simulationDataUrl = `${config.BACKEND_URL}/timescaledb/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`; const simulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`;
try { try {
// 优先查询清洗数据和模拟数据 // 优先查询清洗数据和模拟数据
const [cleaningRes, simulationRes] = await Promise.all([ const [cleaningRes, simulationRes] = await Promise.all([
@@ -115,7 +114,7 @@ const fetchFromBackend = async (
simulationData, simulationData,
deviceIds, deviceIds,
"clean", "clean",
"sim" "sim",
); );
} else { } else {
// 如果清洗数据没有数据,查询原始数据,返回模拟和原始数据 // 如果清洗数据没有数据,查询原始数据,返回模拟和原始数据
@@ -128,7 +127,7 @@ const fetchFromBackend = async (
rawData, rawData,
deviceIds, deviceIds,
"sim", "sim",
"raw" "raw",
); );
} }
} catch (error) { } catch (error) {
@@ -143,7 +142,7 @@ const fetchFromBackend = async (
*/ */
const transformBackendData = ( const transformBackendData = (
backendData: any, backendData: any,
deviceIds: string[] deviceIds: string[],
): TimeSeriesPoint[] => { ): TimeSeriesPoint[] => {
// 处理后端返回的对象格式: { deviceId: [{time: "...", value: ...}] } // 处理后端返回的对象格式: { deviceId: [{time: "...", value: ...}] }
if (backendData && !Array.isArray(backendData)) { if (backendData && !Array.isArray(backendData)) {
@@ -176,12 +175,12 @@ const transformBackendData = (
([timestamp, values]) => ({ ([timestamp, values]) => ({
timestamp, timestamp,
values, values,
}) }),
); );
result.sort( result.sort(
(a, b) => (a, b) =>
new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),
); );
return result; return result;
@@ -200,7 +199,7 @@ const mergeTimeSeriesData = (
data2: TimeSeriesPoint[], data2: TimeSeriesPoint[],
deviceIds: string[], deviceIds: string[],
suffix1: string, suffix1: string,
suffix2: string suffix2: string,
): TimeSeriesPoint[] => { ): TimeSeriesPoint[] => {
const timeMap = new Map<string, Record<string, number | null>>(); const timeMap = new Map<string, Record<string, number | null>>();
@@ -228,7 +227,7 @@ const mergeTimeSeriesData = (
})); }));
result.sort( result.sort(
(a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),
); );
return result; return result;
@@ -239,7 +238,7 @@ const formatTimestamp = (timestamp: string) =>
const ensureValidRange = ( const ensureValidRange = (
from: Dayjs, from: Dayjs,
to: Dayjs to: Dayjs,
): { from: Dayjs; to: Dayjs } => { ): { from: Dayjs; to: Dayjs } => {
if (from.isAfter(to)) { if (from.isAfter(to)) {
return { from: to, to: from }; return { from: to, to: from };
@@ -251,7 +250,7 @@ const buildDataset = (
points: TimeSeriesPoint[], points: TimeSeriesPoint[],
deviceIds: string[], deviceIds: string[],
fractionDigits: number, fractionDigits: number,
showCleaning: boolean showCleaning: boolean,
) => { ) => {
return points.map((point) => { return points.map((point) => {
const entry: Record<string, any> = { const entry: Record<string, any> = {
@@ -325,19 +324,18 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
return async ( return async (
deviceIds: string[], deviceIds: string[],
range: { from: Date; to: Date } range: { from: Date; to: Date },
): Promise<TimeSeriesPoint[]> => { ): Promise<TimeSeriesPoint[]> => {
const device_ids = deviceIds.join(","); const device_ids = deviceIds.join(",");
const start_time = dayjs(range.from).toISOString(); const start_time = dayjs(range.from).toISOString();
const end_time = dayjs(range.to).toISOString(); const end_time = dayjs(range.to).toISOString();
// 清洗数据接口 // 清洗数据接口
const cleaningDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`; const cleaningDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`;
// 原始数据 // 原始数据
const rawDataUrl = `${config.BACKEND_URL}/timescaledb/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`; const rawDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`;
// 模拟数据接口 // 模拟数据接口
const simulationDataUrl = `${config.BACKEND_URL}/timescaledb/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`; const simulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`;
try { try {
const [cleanRes, rawRes, simRes] = await Promise.all([ const [cleanRes, rawRes, simRes] = await Promise.all([
fetch(cleaningDataUrl) fetch(cleaningDataUrl)
@@ -381,12 +379,12 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
([timestamp, values]) => ({ ([timestamp, values]) => ({
timestamp, timestamp,
values, values,
}) }),
); );
result.sort( result.sort(
(a, b) => (a, b) =>
new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),
); );
return result; return result;
@@ -420,7 +418,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
const dataset = useMemo( const dataset = useMemo(
() => buildDataset(timeSeries, deviceIds, fractionDigits, showCleaning), () => buildDataset(timeSeries, deviceIds, fractionDigits, showCleaning),
[timeSeries, deviceIds, fractionDigits, showCleaning] [timeSeries, deviceIds, fractionDigits, showCleaning],
); );
const handleFetch = useCallback( const handleFetch = useCallback(
@@ -447,7 +445,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
setLoadingState("error"); setLoadingState("error");
} }
}, },
[deviceIds, customFetcher, hasDevices, normalizedRange] [deviceIds, customFetcher, hasDevices, normalizedRange],
); );
// 处理数据清洗 // 处理数据清洗
@@ -479,9 +477,9 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
const response = await axios.post( const response = await axios.post(
`${ `${
config.BACKEND_URL config.BACKEND_URL
}/timescaledb/composite/clean-scada?device_ids=${deviceIds.join( }/api/v1/composite/clean-scada?device_ids=${deviceIds.join(
"," ",",
)}&start_time=${startTime}&end_time=${endTime}` )}&start_time=${startTime}&end_time=${endTime}`,
); );
console.log("[SCADADataPanel] 清洗响应:", response.data); console.log("[SCADADataPanel] 清洗响应:", response.data);
@@ -627,7 +625,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
const fieldKey = `${id}_${key}`; const fieldKey = `${id}_${key}`;
// 检查是否有该字段的数据 // 检查是否有该字段的数据
const hasData = dataset.some( const hasData = dataset.some(
(item) => item[fieldKey] !== null && item[fieldKey] !== undefined (item) => item[fieldKey] !== null && item[fieldKey] !== undefined,
); );
if (hasData) { if (hasData) {
@@ -663,7 +661,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
}-${index}`, }-${index}`,
...item, ...item,
})), })),
[dataset] [dataset],
); );
const renderEmpty = () => { const renderEmpty = () => {
@@ -760,7 +758,7 @@ const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
["raw", "clean", "sim"].forEach((suffix, sIndex) => { ["raw", "clean", "sim"].forEach((suffix, sIndex) => {
const key = `${id}_${suffix}`; const key = `${id}_${suffix}`;
const hasData = dataset.some( const hasData = dataset.some(
(item) => item[key] !== null && item[key] !== undefined (item) => item[key] !== null && item[key] !== undefined,
); );
if (hasData) { if (hasData) {
series.push({ series.push({

View File

@@ -617,7 +617,7 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
// 调用后端清洗接口 // 调用后端清洗接口
const response = await axios.post( const response = await axios.post(
`${config.BACKEND_URL}/timescaledb/composite/clean-scada?device_ids=all&start_time=${startTime}&end_time=${endTime}` `${config.BACKEND_URL}/api/v1/composite/clean-scada?device_ids=all&start_time=${startTime}&end_time=${endTime}`
); );
// 处理成功响应 // 处理成功响应

View File

@@ -23,7 +23,7 @@ export const config = {
}, },
MAP_AVAILABLE_LAYERS: process.env.NEXT_PUBLIC_MAP_AVAILABLE_LAYERS MAP_AVAILABLE_LAYERS: process.env.NEXT_PUBLIC_MAP_AVAILABLE_LAYERS
? process.env.NEXT_PUBLIC_MAP_AVAILABLE_LAYERS.split(",").map((item) => ? process.env.NEXT_PUBLIC_MAP_AVAILABLE_LAYERS.split(",").map((item) =>
item.trim().toLowerCase() item.trim().toLowerCase(),
) )
: ["junctions", "pipes", "valves", "reservoirs", "pumps", "tanks", "scada"], : ["junctions", "pipes", "valves", "reservoirs", "pumps", "tanks", "scada"],
}; };