import React, { useState, useEffect } from "react"; import { Tabs, Typography } from "antd"; import { EyeOutlined } from "@ant-design/icons"; import { CameraView, TargetList, TemplateList, RealtimeCharts, RealtimeDataTable, TemplateModal, TargetDetailModal, } from "../components"; import { WebSocketProvider, useWebSocket, useWebSocketSubscription, } from "../actions/websocket.jsx"; import { useTemplateStorage } from "../hooks/useTemplateStorage.js"; import { useTargetStorage } from "../hooks/useTargetStorage.js"; const { Title } = Typography; // 内部组件,使用WebSocket hook const WuyuanbiaobaContent = () => { const { isConnected, sendMessage } = useWebSocket(); // 订阅实时数据 const realtimeDataSubscription = useWebSocketSubscription("dev", "data"); const { templates: tempListData, loading: templatesLoading, addTemplate, updateTemplate, deleteTemplate, getTemplateByKey, } = useTemplateStorage(); const { targets: targetListData, loading: targetsLoading, addTarget, updateTarget, deleteTarget, refreshTargets, } = useTargetStorage(); const [selectedTemplate, setSelectedTemplate] = useState(null); const [tableData, setTableData] = useState([]); const [realtimeData, setRealtimeData] = useState([]); const [lastUpdateTime, setLastUpdateTime] = useState(new Date()); // 数据采样相关状态 const [lastSampleTime, setLastSampleTime] = useState(0); // 模板相关状态 const [templateModalVisible, setTemplateModalVisible] = useState(false); const [templateModalMode, setTemplateModalMode] = useState("add"); // 'add' | 'edit' const [currentEditTemplate, setCurrentEditTemplate] = useState(null); // 标靶详情模态框相关状态 const [targetDetailModalVisible, setTargetDetailModalVisible] = useState(false); const [targetDetailModalMode, setTargetDetailModalMode] = useState("edit"); // 'edit' const [currentEditTarget, setCurrentEditTarget] = useState(null); // 添加选中标靶的状态 const [selectedTargetId, setSelectedTargetId] = useState(null); // 处理实时数据并转换为表格格式 const processRealtimeData = (data) => { if (!data || !data.data || !Array.isArray(data.data)) { return []; } return data.data.map((item) => ({ key: item.pos, deviceId: `target${Number(item.pos) + 1}`, xValue: item.x, yValue: item.y, updateTime: data.time || new Date().toLocaleString(), })); }; // 初始化数据 useEffect(() => { // 初始化空的实时数据表格 setRealtimeData([]); setTableData([]); console.log("数据已初始化,等待实时数据...", import.meta.env.MODE); }, []); // 模板数据加载完成后,默认选中内置模板 useEffect(() => { if (!templatesLoading && tempListData.length > 0 && !selectedTemplate) { // 查找内置模板 const builtinTemplate = tempListData.find( (template) => template.key === "builtin_1" ); if (builtinTemplate) { setSelectedTemplate("builtin_1"); console.log("默认选中内置模板:", builtinTemplate.name); } else { // 如果没有内置模板,选择第一个模板 setSelectedTemplate(tempListData[0].key); console.log("默认选中第一个模板:", tempListData[0].name); } } }, [templatesLoading, tempListData, selectedTemplate]); // WebSocket连接成功后的处理 useEffect(() => { if (isConnected) { console.log("WebSocket已连接,等待实时数据..."); } else { console.log("WebSocket未连接"); } }, [isConnected]); // 调试实时数据订阅状态 useEffect(() => { // console.log('实时数据订阅状态:', { // hasData: !!realtimeDataSubscription.latest, // dataCount: realtimeDataSubscription.data?.length || 0, // latestTimestamp: realtimeDataSubscription.latest?.timestamp, // }); }, [realtimeDataSubscription]); // 处理实时数据更新 useEffect(() => { if ( realtimeDataSubscription.latest && realtimeDataSubscription.latest.values ) { const newRealtimeData = processRealtimeData( realtimeDataSubscription.latest.values ); if (newRealtimeData.length > 0) { const currentTime = Date.now(); const currentSecond = Math.floor(currentTime / 1000); // 每秒采样一次数据用于图表和表格显示 if (currentSecond > lastSampleTime) { setLastSampleTime(currentSecond); // 更新采样后的历史数据(用于图表显示) setTableData((prevData) => { const updatedData = [ ...prevData, ...newRealtimeData.map((point) => ({ ...point, key: `${currentTime}_${point.key}`, timestamp: currentTime, updateTime: new Date(currentTime).toLocaleString(), })), ]; // 只保留最近25个数据点(25秒) return updatedData.slice(-75); // 3个设备 * 25个时间点 }); // 更新实时数据表格(使用最新的采样数据) setRealtimeData(newRealtimeData.map((point) => ({ ...point, key: `realtime_${point.key}`, updateTime: new Date(currentTime).toLocaleString(), }))); } setLastUpdateTime(new Date()); } } }, [realtimeDataSubscription.latest, lastSampleTime]); // 编辑标靶的处理函数 const handleEditTarget = (target) => { setCurrentEditTarget(target); setTargetDetailModalMode("edit"); setTargetDetailModalVisible(true); console.log("编辑标靶:", target); }; // 选中标靶的处理函数 const handleSelectTarget = (target) => { setSelectedTargetId(target.id); console.log("选中标靶:", target); }; // 清除选中标靶的处理函数 const handleClearSelection = () => { setSelectedTargetId(null); console.log("清除标靶选中状态"); }; // 处理矩形框点击事件 const handleRectangleClick = (targetData) => { console.log("矩形框被点击,打开标靶详情:", targetData); setCurrentEditTarget(targetData); setTargetDetailModalMode("edit"); setTargetDetailModalVisible(true); }; // 选择模板的处理函数 const handleTemplateSelect = (templateKey) => { setSelectedTemplate(templateKey); console.log("选中模板:", templateKey); }; // 添加新模板的处理函数 const handleAddTemplate = () => { setTemplateModalMode("add"); setCurrentEditTemplate(null); setTemplateModalVisible(true); }; // 编辑模板的处理函数 const handleEditTemplate = (template) => { setTemplateModalMode("edit"); setCurrentEditTemplate(template); setTemplateModalVisible(true); }; // 模态框确认处理函数 const handleTemplateModalOk = (templateInfo) => { console.log(templateInfo, "templateInfo"); let success = false; if (templateModalMode === "add") { success = addTemplate(templateInfo); } else { success = updateTemplate(templateInfo); } if (success) { setTemplateModalVisible(false); } else { console.error("模板操作失败"); // 可以添加用户提示 } }; // 模态框取消处理函数 const handleTemplateModalCancel = () => { setTemplateModalVisible(false); setCurrentEditTemplate(null); }; // 删除模板处理函数 const handleDeleteTemplate = (template) => { const success = deleteTemplate(template.key); if (success) { setTemplateModalVisible(false); // 如果删除的是当前选中的模板,则清空选中状态 if (selectedTemplate === template.key) { setSelectedTemplate(null); } } else { console.error("删除模板失败"); // 可以添加用户提示 } }; // 标靶详情模态框确认处理函数 const handleTargetDetailModalOk = (targetInfo) => { const success = updateTarget(targetInfo); if (success) { setTargetDetailModalVisible(false); setCurrentEditTarget(null); console.log("更新标靶信息:", targetInfo); } else { console.error("更新标靶失败"); // 可以添加用户提示 } }; // 标靶详情模态框取消处理函数 const handleTargetDetailModalCancel = () => { setTargetDetailModalVisible(false); setCurrentEditTarget(null); }; // 删除标靶处理函数 const handleDeleteTarget = (targetKey) => { console.log("开始删除标靶:", targetKey); const success = deleteTarget(targetKey); if (success) { setTargetDetailModalVisible(false); setCurrentEditTarget(null); // 如果删除的标靶是当前选中的,清除选中状态 if (selectedTargetId === targetKey) { setSelectedTargetId(null); } console.log("删除标靶成功:", targetKey); // 强制刷新标靶数据,确保UI立即更新 setTimeout(() => { refreshTargets(); }, 500); } else { console.error("删除标靶失败"); // 可以添加用户提示 } }; // 标靶-一键清零 const onClickClearAll = () => { console.log("一键清零操作"); sendMessage( JSON.stringify({ _from: "setup", cmd: "clearZero", values: {}, }) ); }; // Tabs items 配置 const tabItems = [ { key: "target-list", label: "标靶列表", children: ( ), }, { key: "temp-list", label: "模板列表", children: ( ), }, ]; return (
{/* Header 区域 */}
视觉位移计配置工具
{/* 中间区域 - 固定视口剩余高度 */}
{/* Camera 区域 */} {/* 右侧 Target List / Temp List 区域 */}
{/* 底部区域 - 在视口下方,需要滚动查看 */}
{/* Charts 区域 */} {/* Table 区域 - 使用采样数据显示 */}
{/* 模板编辑模态框 */} {/* 标靶详情模态框 */}
); }; // 主组件,使用WebSocket Provider包装 const Wuyuanbiaoba = () => { return ( ); }; export default Wuyuanbiaoba;