8 changed files with 384 additions and 24 deletions
@ -0,0 +1,68 @@ |
|||||
|
# V1.2.0 更新日志 |
||||
|
|
||||
|
- **更新日期**: 2025年12月3日 |
||||
|
- **版本号**: 1.2.0 |
||||
|
|
||||
|
## 新增功能 |
||||
|
|
||||
|
### 1. 中值滤波算法配置 |
||||
|
- **新增中值滤波算法配置界面**:在系统设置中新增"中值滤波算法配置"功能模块 |
||||
|
- **按需加载机制**:优化数据加载逻辑,仅在打开配置弹窗时才加载算法配置数据,提升性能 |
||||
|
- **可视化配置**:支持对每个测点进行独立的中值滤波参数配置 |
||||
|
- X方向窗口大小配置 |
||||
|
- Y方向窗口大小配置 |
||||
|
- 算法启用/禁用开关 |
||||
|
- **实时同步**:配置数据可实时同步到设备端 |
||||
|
- **数据持久化**:配置保存到设备后自动加载,支持配置的读取和设置 |
||||
|
|
||||
|
## Bug 修复 |
||||
|
|
||||
|
### 1. 算法配置加载优化 |
||||
|
- **修复数据加载时机问题**:避免组件加载时不必要的数据请求 |
||||
|
- **优化 Modal 打开逻辑**:确保只在用户主动打开配置界面时才触发数据加载 |
||||
|
|
||||
|
## 🔧 优化改进 |
||||
|
|
||||
|
### 1. 组件架构优化 |
||||
|
- **解耦组件职责**:将算法设置按钮移至父组件,优化组件结构 |
||||
|
- **受控组件模式**:AlgorithmSettings 改为完全受控的 Modal 组件 |
||||
|
- **状态管理优化**:通过 props 传递控制状态,提升代码可维护性 |
||||
|
|
||||
|
### 2. 用户体验提升 |
||||
|
- **设备连接状态检测**:按钮在设备未连接时自动禁用,避免无效操作 |
||||
|
- **加载状态反馈**:添加加载动画,提供更好的用户反馈 |
||||
|
- **错误提示优化**:完善错误提示信息,帮助用户快速定位问题 |
||||
|
|
||||
|
## 技术细节 |
||||
|
|
||||
|
### IPC 通信 |
||||
|
- 新增 IPC 事件: |
||||
|
- `MEDIAN_FILTER_CONFIG_GET (win:get)`:获取中值滤波算法配置 |
||||
|
- `MEDIAN_FILTER_CONFIG_SET (win:set)`:设置中值滤波算法配置 |
||||
|
|
||||
|
### 数据格式 |
||||
|
```json |
||||
|
{ |
||||
|
"type": "median", |
||||
|
"sensors": [ |
||||
|
{ |
||||
|
"enable": false, |
||||
|
"pos": "1", |
||||
|
"xLen": 0, |
||||
|
"yLen": 0 |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 依赖更新 |
||||
|
- 无依赖包更新 |
||||
|
|
||||
|
## 注意事项 |
||||
|
1. 确保设备固件版本支持中值滤波算法配置功能 |
||||
|
2. 配置参数的有效范围请参考设备手册 |
||||
|
3. 建议在修改配置前备份当前配置 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**完整更新内容请查看项目 Git 提交记录** |
||||
@ -0,0 +1,173 @@ |
|||||
|
import styles from './AlgorithmSettings.module.css' |
||||
|
import { Button, Flex, Input, Switch, Modal, List, message } from 'antd' |
||||
|
import { useState, useEffect } from 'react' |
||||
|
import useDeviceStore from '../../stores/deviceStore' |
||||
|
import { IPC_EVENT } from '../../common/ipcEvents' |
||||
|
|
||||
|
function AlgorithmSettings({ visible, onClose }) { |
||||
|
const [loading, setLoading] = useState(false) |
||||
|
|
||||
|
const connectedDevice = useDeviceStore((state) => state.connectedDevice) |
||||
|
console.log('当前连接的设备:', connectedDevice) |
||||
|
// 点位配置列表数据 |
||||
|
const [pointSettings, setPointSettings] = useState([]) |
||||
|
|
||||
|
// 只在 Modal 打开时获取中值滤波算法配置 |
||||
|
useEffect(() => { |
||||
|
const loadMedianFilterConfig = async () => { |
||||
|
if (!visible) { |
||||
|
// Modal 未打开,不加载数据 |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
if (!connectedDevice) { |
||||
|
console.log('未连接设备,跳过加载中值滤波配置') |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
setLoading(true) |
||||
|
try { |
||||
|
const result = await window.electron.ipcRenderer.invoke(IPC_EVENT.MEDIAN_FILTER_CONFIG_GET, { |
||||
|
ip: connectedDevice |
||||
|
}) |
||||
|
|
||||
|
if (result.success && result.data) { |
||||
|
console.log('中值滤波算法配置加载成功:', result.data) |
||||
|
const data = result.data.values |
||||
|
|
||||
|
// 根据返回的数据更新 pointSettings |
||||
|
if (data && data.sensors && Array.isArray(data.sensors)) { |
||||
|
const updatedSettings = data.sensors.map((sensor, index) => ({ |
||||
|
id: index + 1, |
||||
|
pos: `点位${sensor.pos}`, |
||||
|
xLen: sensor.xLen || null, |
||||
|
yLen: sensor.yLen || null, |
||||
|
enable: sensor.enable || false |
||||
|
})) |
||||
|
setPointSettings(updatedSettings) |
||||
|
message.success('算法配置加载成功') |
||||
|
} else { |
||||
|
message.warning('配置数据格式异常') |
||||
|
} |
||||
|
} else { |
||||
|
console.error('加载中值滤波配置失败:', result.error) |
||||
|
message.error(result.error || '加载配置失败') |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('加载中值滤波配置异常:', error) |
||||
|
message.error('加载配置异常') |
||||
|
} finally { |
||||
|
setLoading(false) |
||||
|
} |
||||
|
} |
||||
|
loadMedianFilterConfig() |
||||
|
}, [visible, connectedDevice]) // 依赖 visible,当 Modal 打开时触发加载 |
||||
|
|
||||
|
// 更新点位配置 |
||||
|
const updatePointSetting = (id, field, value) => { |
||||
|
setPointSettings((prev) => |
||||
|
prev.map((item) => (item.id === id ? { ...item, [field]: value } : item)) |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
// 保存配置 |
||||
|
const handleSave = async () => { |
||||
|
if (!connectedDevice) { |
||||
|
message.error('设备未连接') |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
// 转换为设备需要的数据格式 |
||||
|
const values = { |
||||
|
type: 'median', |
||||
|
sensors: pointSettings.map((setting) => ({ |
||||
|
enable: setting.enable, |
||||
|
pos: setting.pos.replace('点位', ''), // 从"点位1"中提取"1" |
||||
|
xLen: setting.xLen, |
||||
|
yLen: setting.yLen |
||||
|
})) |
||||
|
} |
||||
|
|
||||
|
console.log('保存配置:', values) |
||||
|
|
||||
|
const result = await window.electron.ipcRenderer.invoke(IPC_EVENT.MEDIAN_FILTER_CONFIG_SET, { |
||||
|
ip: connectedDevice, |
||||
|
values: values |
||||
|
}) |
||||
|
|
||||
|
if (result.success) { |
||||
|
message.success('配置保存成功!') |
||||
|
onClose && onClose() |
||||
|
} else { |
||||
|
message.error(result.error || '配置保存失败') |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('保存配置异常:', error) |
||||
|
message.error('配置保存异常') |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<Modal |
||||
|
title="算法设置详情" |
||||
|
open={visible} |
||||
|
onCancel={onClose} |
||||
|
onOk={onClose} |
||||
|
width={700} |
||||
|
footer={[ |
||||
|
<Button key="save" type="primary" onClick={handleSave}> |
||||
|
保存 |
||||
|
</Button>, |
||||
|
<Button key="close" onClick={onClose}> |
||||
|
关闭 |
||||
|
</Button> |
||||
|
]} |
||||
|
> |
||||
|
<List |
||||
|
itemLayout="vertical" |
||||
|
dataSource={pointSettings} |
||||
|
renderItem={(item) => ( |
||||
|
<List.Item> |
||||
|
<div style={{ width: '100%' }}> |
||||
|
<div style={{ fontWeight: 'bold', marginBottom: 12 }}>{item.pos}</div> |
||||
|
<Flex vertical gap={12}> |
||||
|
<Flex align="center" gap={8}> |
||||
|
<span style={{ minWidth: 100 }}>X方向:</span> |
||||
|
<Input |
||||
|
type="number" |
||||
|
value={item.xLen} |
||||
|
onChange={(e) => |
||||
|
updatePointSetting(item.id, 'xLen', Number(e.target.value)) |
||||
|
} |
||||
|
style={{ width: 150 }} |
||||
|
/> |
||||
|
</Flex> |
||||
|
<Flex align="center" gap={8}> |
||||
|
<span style={{ minWidth: 100 }}>Y方向:</span> |
||||
|
<Input |
||||
|
type="number" |
||||
|
value={item.yLen} |
||||
|
onChange={(e) => |
||||
|
updatePointSetting(item.id, 'yLen', Number(e.target.value)) |
||||
|
} |
||||
|
style={{ width: 150 }} |
||||
|
/> |
||||
|
</Flex> |
||||
|
<Flex align="center" gap={8} justify="space-between"> |
||||
|
<span>是否启用中值滤波算法:</span> |
||||
|
<Switch |
||||
|
checked={item.enable} |
||||
|
onChange={(checked) => updatePointSetting(item.id, 'enable', checked)} |
||||
|
/> |
||||
|
</Flex> |
||||
|
</Flex> |
||||
|
</div> |
||||
|
</List.Item> |
||||
|
)} |
||||
|
/> |
||||
|
</Modal> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default AlgorithmSettings |
||||
@ -0,0 +1,10 @@ |
|||||
|
.subSection { |
||||
|
margin-bottom: 6px; |
||||
|
border: 1px solid #eee; |
||||
|
padding: 4px; |
||||
|
} |
||||
|
|
||||
|
.subSectionTitle { |
||||
|
font-weight: bold; |
||||
|
margin-bottom: 6px; |
||||
|
} |
||||
Loading…
Reference in new issue