@@ -42,8 +42,13 @@ import { FixedSizeList } from "react-window";
import { useMap } from "@app/OlMap/MapComponent" ;
import { GeoJSON } from "ol/format" ;
import VectorLayer from "ol/layer/Vector" ;
import VectorSource from "ol/source/Vector" ;
import { Stroke , Style , Circle } from "ol/style" ;
import Feature from "ol/Feature" ;
import { Point } from "ol/geom" ;
import config from "@/config/config" ;
import { get } from "http" ;
const STATUS_OPTIONS : {
value : "online" | "offline" | "warning" | "error" ;
@@ -57,12 +62,14 @@ const STATUS_OPTIONS: {
interface SCADADevice {
id : string ;
name : string ;
transmission_frequency : string ;
reliability : number ;
type : string ;
coordinates : [ number , number ] ;
status : {
value : "online" | "offline" | "warning" | "error" ;
name : "在线" | "离线" | "警告" | "错误" ;
} ;
coordinates : [ number , number ] ;
properties? : Record < string , any > ;
}
@@ -85,6 +92,7 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
const [ searchQuery , setSearchQuery ] = useState < string > ( "" ) ;
const [ selectedType , setSelectedType ] = useState < string > ( "all" ) ;
const [ selectedStatus , setSelectedStatus ] = useState < string > ( "all" ) ;
const [ selectedReliability , setSelectedReliability ] = useState < string > ( "all" ) ;
const [ isExpanded , setIsExpanded ] = useState < boolean > ( true ) ;
const [ internalSelection , setInternalSelection ] = useState < string [ ] > ( [ ] ) ;
const [ pendingSelection , setPendingSelection ] = useState < string [ ] | null > (
@@ -94,6 +102,10 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
const [ loading , setLoading ] = useState < boolean > ( true ) ;
const [ inputValue , setInputValue ] = useState < string > ( "" ) ;
const [ highlightLayer , setHighlightLayer ] =
useState < VectorLayer < VectorSource > | null > ( null ) ;
const [ highlightFeatures , setHighlightFeatures ] = useState < Feature [ ] > ( [ ] ) ;
const debounceTimerRef = useRef < NodeJS.Timeout | null > ( null ) ;
// 防抖更新搜索查询
@@ -139,6 +151,8 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
const data = features . map ( ( feature ) = > ( {
id : feature.get ( "id" ) || feature . getId ( ) ,
name : feature.get ( "id" ) || feature . getId ( ) ,
transmission_frequency : feature.get ( "transmission_frequency" ) ,
reliability : feature.get ( "reliability" ) ,
type : feature . get ( "type" ) === "pipe_flow" ? "流量" : "压力" ,
status : STATUS_OPTIONS [ Math . floor ( Math . random ( ) * 4 ) ] ,
coordinates : ( feature . getGeometry ( ) as Point ) ? . getCoordinates ( ) as [
@@ -170,6 +184,20 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
// 获取设备状态列表
const deviceStatuses = STATUS_OPTIONS ;
// 可靠度文字映射
const getReliability = ( reliability : number ) = > {
switch ( reliability ) {
case 1 :
return "高" ;
case 2 :
return "中" ;
case 3 :
return "低" ;
default :
return "未知" ;
}
} ;
// 过滤设备列表
const filteredDevices = useMemo ( ( ) = > {
return effectiveDevices . filter ( ( device ) = > {
@@ -186,10 +214,21 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
selectedType === "all" || device . type === selectedType ;
const matchesStatus =
selectedStatus === "all" || device . status . value === selectedStatus ;
const matchesReliability =
selectedReliability === "all" ||
getReliability ( device . reliability ) === selectedReliability ;
return matchesSearch && matchesType && matchesStatus ;
return (
matchesSearch && matchesType && matchesStatus && matchesReliability
) ;
} ) ;
} , [ effectiveDevices , searchQuery , selectedType , selectedStatus ] ) ;
} , [
effectiveDevices ,
searchQuery ,
selectedType ,
selectedStatus ,
selectedReliability ,
] ) ;
// 状态颜色映射
const getStatusColor = ( status : string ) = > {
@@ -222,6 +261,17 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
return "●" ;
}
} ;
// 传输频率文字对应
const getTransmissionFrequency = ( transmission_frequency : string ) = > {
// 传输频率文本: 00:01:00, 00:05:00, 00:10:00, 00:30:00, 01:00:00, 转换为分钟数
const parts = transmission_frequency . split ( ":" ) ;
if ( parts . length !== 3 ) return transmission_frequency ;
const hours = parseInt ( parts [ 0 ] , 10 ) ;
const minutes = parseInt ( parts [ 1 ] , 10 ) ;
const seconds = parseInt ( parts [ 2 ] , 10 ) ;
const totalMinutes = hours * 60 + minutes + ( seconds >= 30 ? 1 : 0 ) ;
return totalMinutes ;
} ;
// 处理设备点击
const handleDeviceClick = ( device : SCADADevice , event? : React.MouseEvent ) = > {
@@ -264,6 +314,7 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
setSearchQuery ( "" ) ;
setSelectedType ( "all" ) ;
setSelectedStatus ( "all" ) ;
setSelectedReliability ( "all" ) ;
} ) ;
} , [ ] ) ;
@@ -273,6 +324,56 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
setPendingSelection ( [ ] ) ;
} , [ ] ) ;
// 初始化管道图层和高亮图层
useEffect ( ( ) = > {
if ( ! map ) return ;
// 获取地图的目标容器
const SCADASelectedStyle = ( ) = > {
return new Style ( {
image : new Circle ( {
stroke : new Stroke ( { color : "yellow" , width : 2 } ) ,
radius : 15 ,
} ) ,
} ) ;
} ;
// 创建高亮图层
const highlightLayer = new VectorLayer ( {
source : new VectorSource ( ) ,
style : SCADASelectedStyle ,
maxZoom : 24 ,
minZoom : 12 ,
properties : {
name : "SCADA 选中高亮" ,
value : "scada_selected_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 ) ;
}
} ) ;
} , [ selectedDeviceIds , highlightFeatures ] ) ;
// 清理定时器
useEffect ( ( ) = > {
return ( ) = > {
@@ -364,14 +465,14 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
{ /* 筛选器 */ }
< Stack direction = "row" spacing = { 2 } >
< FormControl size = "small" sx = { { minWidth : 12 0 } } >
< FormControl size = "small" sx = { { minWidth : 8 0 } } >
< InputLabel > 设 备 类 型 < / InputLabel >
< Select
value = { selectedType }
label = "设备类型"
onChange = { ( e ) = > setSelectedType ( e . target . value ) }
>
< MenuItem value = "all" > 全 部 类 型 < / MenuItem >
< MenuItem value = "all" > 全 部 < / MenuItem >
{ deviceTypes . map ( ( type ) = > (
< MenuItem key = { type } value = { type } >
{ type }
@@ -380,14 +481,14 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
< / Select >
< / FormControl >
< FormControl size = "small" sx = { { minWidth : 10 0 } } >
< FormControl size = "small" sx = { { minWidth : 8 0 } } >
< InputLabel > 状 态 < / InputLabel >
< Select
value = { selectedStatus }
label = "状态"
onChange = { ( e ) = > setSelectedStatus ( e . target . value ) }
>
< MenuItem value = "all" > 全 部 状 态 < / MenuItem >
< MenuItem value = "all" > 全 部 < / MenuItem >
{ deviceStatuses . map ( ( status ) = > (
< MenuItem key = { status . value } value = { status . value } >
{ status . name }
@@ -396,6 +497,20 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
< / Select >
< / FormControl >
< FormControl size = "small" sx = { { minWidth : 80 } } >
< InputLabel > 可 靠 度 < / InputLabel >
< Select
value = { selectedReliability }
label = "可靠度"
onChange = { ( e ) = > setSelectedReliability ( e . target . value ) }
>
< MenuItem value = "all" > 全 部 < / MenuItem >
< MenuItem value = "高" > 高 < / MenuItem >
< MenuItem value = "中" > 中 < / MenuItem >
< MenuItem value = "低" > 低 < / MenuItem >
< / Select >
< / FormControl >
< Tooltip title = "重置筛选条件" >
< IconButton onClick = { handleResetFilters } >
< FilterList / >
@@ -523,6 +638,14 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
variant = "outlined"
sx = { { fontSize : "0.7rem" , height : 20 } }
/ >
< Chip
label = {
"可靠度" + getReliability ( device . reliability )
}
size = "small"
variant = "outlined"
sx = { { fontSize : "0.7rem" , height : 20 } }
/ >
< / Stack >
}
secondary = {
@@ -537,8 +660,11 @@ const SCADADeviceList: React.FC<SCADADeviceListProps> = ({
variant = "caption"
color = "text.secondary"
>
坐 标 : { device . coordinates [ 0 ] . toFixed ( 6 ) } , { " " }
{ device . coordinates [ 1 ] . toFixed ( 6 ) }
传 输 频 率 : { " " }
{ getTransmissionFrequency (
device . transmission_frequency
) } { " " }
分 钟
< / Typography >
< / Stack >
}