"use client"; import React, { useEffect, useState } from "react"; import { Box, Button, Typography, Checkbox, FormControlLabel, IconButton, Card, CardContent, Chip, Tooltip, Collapse, Link, } from "@mui/material"; import { Info as InfoIcon, LocationOn as LocationIcon, } from "@mui/icons-material"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs, { Dayjs } from "dayjs"; import "dayjs/locale/zh-cn"; import axios from "axios"; import moment from "moment"; import { config, NETWORK_NAME } from "@config/config"; import { useNotification } from "@refinedev/core"; import { useMap } from "@app/OlMap/MapComponent"; import { queryFeaturesByIds } from "@/utils/mapQueryService"; import { GeoJSON } from "ol/format"; import VectorLayer from "ol/layer/Vector"; import VectorSource from "ol/source/Vector"; import { Style, Icon, Circle, Fill, Stroke } from "ol/style"; import Feature, { FeatureLike } from "ol/Feature"; import { bbox, featureCollection } from "@turf/turf"; interface SchemeRecord { id: number; schemeName: string; sensorNumber: number; minDiameter: number; user: string; create_time: string; sensorLocation?: string[]; } interface SchemaItem { id: number; scheme_name: string; sensor_number: number; min_diameter: number; username: string; create_time: string; sensor_location?: string[]; } interface SchemeQueryProps { schemes?: SchemeRecord[]; onSchemesChange?: (schemes: SchemeRecord[]) => void; onLocate?: (id: number) => void; network?: string; } const SchemeQuery: React.FC = ({ schemes: externalSchemes, onSchemesChange, onLocate, network = NETWORK_NAME, }) => { const [queryAll, setQueryAll] = useState(true); const [queryDate, setQueryDate] = useState(dayjs(new Date())); const [internalSchemes, setInternalSchemes] = useState([]); const [loading, setLoading] = useState(false); const [expandedId, setExpandedId] = useState(null); const { open } = useNotification(); const map = useMap(); const [highlightLayer, setHighlightLayer] = useState | null>(null); const [highlightFeatures, setHighlightFeatures] = useState([]); // 使用外部提供的 schemes 或内部状态 const schemes = externalSchemes !== undefined ? externalSchemes : internalSchemes; const setSchemes = onSchemesChange || setInternalSchemes; // 格式化简短日期 const formatShortDate = (timeStr: string) => { const time = moment(timeStr); return time.format("MM-DD"); }; // 初始化管道图层和高亮图层 useEffect(() => { if (!map) return; // 定义传感器样式 const sensorStyle = new Style({ image: new Icon({ src: "/icons/sensor.svg", scale: 0.2, anchor: [0.5, 1], }), }); // 创建高亮图层 - 爆管管段标识样式 const highlightLayer = new VectorLayer({ source: new VectorSource(), style: sensorStyle, maxZoom: 24, minZoom: 12, properties: { name: "传感器高亮", value: "sensor_highlight", }, }); map.addLayer(highlightLayer); setHighlightLayer(highlightLayer); return () => { map.removeLayer(highlightLayer); }; }, [map]); // 高亮要素的函数 useEffect(() => { if (!highlightLayer) { return; } const source = highlightLayer.getSource(); if (!source) { return; } // 清除之前的高亮 source.clear(); // 添加新的高亮要素 highlightFeatures.forEach((feature) => { if (feature instanceof Feature) { source.addFeature(feature); } }); }, [highlightFeatures]); // 查询方案 const handleQuery = async () => { if (!queryAll && !queryDate) return; setLoading(true); try { const response = await axios.get( `${config.backendUrl}/getallsensorplacements/?network=${network}` ); let filteredResults = response.data; // 按日期过滤 if (!queryAll && queryDate) { const formattedDate = queryDate.format("YYYY-MM-DD"); filteredResults = filteredResults.filter((item: SchemaItem) => { const itemDate = moment(item.create_time).format("YYYY-MM-DD"); return itemDate === formattedDate; }); } setSchemes( filteredResults.map((item: SchemaItem) => ({ id: item.id, schemeName: item.scheme_name, sensorNumber: item.sensor_number, minDiameter: item.min_diameter, user: item.username, create_time: item.create_time, sensorLocation: item.sensor_location, })) ); if (filteredResults.length === 0) { open?.({ type: "error", message: "查询结果", description: queryAll ? "没有找到任何方案" : `${queryDate?.format("YYYY-MM-DD")} 没有找到相关方案`, }); } } catch (error) { console.error("查询请求失败:", error); open?.({ type: "error", message: "查询失败", description: "获取方案列表失败,请稍后重试", }); } finally { setLoading(false); } }; // 定位传感器 const handleLocateSensors = (sensorIds: string[]) => { if (!map) { open?.({ type: "error", message: "地图未加载", }); return; } if (sensorIds.length > 0) { queryFeaturesByIds(sensorIds).then((features) => { if (features.length > 0) { // 设置高亮要素 setHighlightFeatures(features); // 将 OpenLayers Feature 转换为 GeoJSON Feature const geojsonFormat = new GeoJSON(); const geojsonFeatures = features.map((feature) => geojsonFormat.writeFeatureObject(feature) ); const extent = bbox(featureCollection(geojsonFeatures as any)); if (extent) { map?.getView().fit(extent, { maxZoom: 18, duration: 1000 }); } } }); } }; // 查看详情(展开/收起) const handleViewDetails = (id: number) => { setExpandedId(expandedId === id ? null : id); }; // 保存方案(示例功能) const handleSaveScheme = (scheme: SchemeRecord) => { open?.({ type: "success", message: "保存成功", description: `方案 "${scheme.schemeName}" 已保存`, }); }; return ( {/* 查询条件 - 单行布局 */} setQueryAll(e.target.checked)} size="small" /> } label={查询全部日期} className="m-0" /> value && dayjs.isDayjs(value) && setQueryDate(value) } format="YYYY-MM-DD" disabled={queryAll} slotProps={{ textField: { size: "small", sx: { width: 200 }, }, }} /> {/* 结果列表 */} {schemes.length === 0 ? ( 总共 0 条 No data ) : ( 共 {schemes.length} 条记录 {schemes.map((scheme) => ( {/* 主要信息行 */} {scheme.schemeName} 最小半径: {scheme.minDiameter} · 用户: {scheme.user} · 日期: {formatShortDate(scheme.create_time)} {/* 操作按钮 */} setExpandedId( expandedId === scheme.id ? null : scheme.id ) } color="primary" className="p-1" > onLocate?.(scheme.id)} color="primary" className="p-1" > {/* 可折叠的详细信息 */} {/* 信息网格布局 */} {/* 传感器信息列 */} 传感器数量: {scheme.sensorNumber} 最小半径: {scheme.minDiameter} {/* 方案信息列 */} 用户: {scheme.user} 创建时间: {moment(scheme.create_time).format( "YYYY-MM-DD HH:mm" )} {/* 传感器位置列表 */} {scheme.sensorLocation && scheme.sensorLocation.length > 0 && ( 传感器位置 ({scheme.sensorLocation.length}个): {scheme.sensorLocation.map( (sensorId, index) => ( { e.preventDefault(); handleLocateSensors([sensorId]); }} > {sensorId} ) )} )} {/* 操作按钮区域 */} {scheme.sensorLocation && scheme.sensorLocation.length > 0 && ( )} ))} )} ); }; export default SchemeQuery;