前端集成修复完成报告
问题总结
症状: 前端显示错误消息 “获取采集通道失败” 根本原因: 前端 API 调用与后端三级架构 API 端点不匹配
修复详情
1. 后端代码修改
1.1 内部/模型/types.go - 添加 JSON 标签和 PointData 结构
原因: Go 结构体默认不序列化为 JSON,需要添加明确的 JSON 标签
修改:
- Point 结构: 添加
json:"fieldname"标签 - ThresholdConfig 结构: 添加 JSON 标签
- Device 结构: 添加 JSON 标签(保留 StopChan 和 NodeRuntime 的
json:"-") - Channel 结构: 添加 JSON 标签(保留 StopChan 和 NodeRuntime 的
json:"-") - Value 结构: 更新字段名映射
ChannelID→channel_idDeviceID→device_idPointID→point_idValue→valueQuality→qualityTS→timestamp
- 新增 PointData 结构 (用于前端显示):
type PointData struct { ID string `json:"id"` Name string `json:"name"` Address string `json:"address"` DataType string `json:"datatype"` Value any `json:"value"` Quality string `json:"quality"` Timestamp time.Time `json:"timestamp"` Unit string `json:"unit,omitempty"` }
1.2 内部/核心/channel_manager.go - 更新 GetDevicePoints 返回类型
原因: GetDevicePoints 需要返回完整的点信息(包括名称),而不仅仅是值
修改:
- GetDevicePoints 返回类型:
[]model.Value→[]model.PointData - 修复未使用的变量
ch
2. 前端代码修改
2.1 ui/index.html - API 端点更新
位置: 290-311 行 修改: refreshChannels() 函数
// 旧
const response = await fetch('/api/devices');
// 新
const response = await fetch('/api/channels');
位置: 314-334 行 修改: selectChannel() 函数
// 旧
const response = await fetch(`/api/devices/${channel.id}`);
deviceList.value = [{
id: data.id,
name: data.name,
protocol: data.protocol, // ← 设备中没有此字段
enable: data.enable,
interval: data.interval
}];
// 新
const response = await fetch(`/api/channels/${channel.id}/devices`);
deviceList.value = data || [];
位置: 340-353 行 修改: refreshPointData() 函数
// 旧
const response = await fetch(`/api/devices/${selectedChannel.value.id}/points`);
// 新
const response = await fetch(`/api/channels/${selectedChannel.value.id}/devices/${selectedDevice.value.id}/points`);
位置: 339 行 修改: connectWebSocket() 函数
// 旧
ws = new WebSocket(`${protocol}//${window.location.host}/ws/values`);
// 新
ws = new WebSocket(`${protocol}//${window.location.host}/api/ws/values`);
2.2 ui/index.html - HTML 表格绑定更新
点位表格 (行 204-223)
prop="PointID"→prop="id"prop="Value"→prop="value"prop="Quality"→prop="quality"prop="TS"→prop="timestamp"- 添加点位名称列:
prop="name"
设备表格 (行 161-171)
- 移除
prop="protocol"列(协议字段现在在 Channel 中)
2.3 ui/index.html - WebSocket 消息处理更新
位置: 348-365 行
// 旧
const index = pointDataList.value.findIndex(item => item.PointID === data.PointID);
if (index !== -1) {
pointDataList.value[index] = data;
}
// 新
if (data.channel_id === selectedChannel.value.id && data.device_id === selectedDevice.value.id) {
const index = pointDataList.value.findIndex(item => item.id === data.point_id);
if (index !== -1) {
pointDataList.value[index].value = data.value;
pointDataList.value[index].quality = data.quality;
pointDataList.value[index].timestamp = data.timestamp;
}
}
2.4 ui/index.html - 写入命令更新
writeForm 初始化 (行 276-281)
const writeForm = reactive({
channelID: '', // ← 新增
deviceID: '',
pointID: '',
value: ''
});
openWriteDialog() (行 377-383)
const openWriteDialog = (row) => {
writeForm.channelID = selectedChannel.value.id; // ← 新增
writeForm.deviceID = selectedDevice.value.id;
writeForm.pointID = row.id; // 使用 id 而不是 PointID
writeForm.value = '';
writeDialogVisible.value = true;
};
submitWrite() (行 385-400)
body: JSON.stringify({
channel_id: writeForm.channelID, // ← 新增
device_id: writeForm.deviceID,
point_id: writeForm.pointID,
value: writeForm.value
})
测试验证
✅ 后端编译成功(无错误) ✅ 后端启动成功(第一个通道正常启动) ✅ Web 服务器在 8080 端口启动 ✅ 前端可以访问(http://127.0.0.1:8080) ✅ 所有 API 端点正确映射
架构一致性
后端 API 结构 (现有)
GET /api/channels # → []Channel
GET /api/channels/:id/devices # → []Device
GET /api/channels/:cid/devices/:did/points # → []PointData
POST /api/write # 请求体: {channel_id, device_id, point_id, value}
WS /api/ws/values # WebSocket 消息: {channel_id, device_id, point_id, value, quality, timestamp}
前端期望 (已匹配)
- ✅ 采集通道列表:
/api/channels - ✅ 设备列表:
/api/channels/{id}/devices - ✅ 点位数据:
/api/channels/{cid}/devices/{did}/points - ✅ 实时更新: WebSocket
/api/ws/values - ✅ 点位写入: POST
/api/writewith {channel_id, device_id, point_id, value}
数据模型对齐
Channel JSON
{
"id": "...",
"name": "...",
"protocol": "modbus-tcp",
"enable": true,
"config": {...},
"devices": [...]
}
Device JSON
{
"id": "...",
"name": "...",
"enable": true,
"interval": 5000000000,
"config": {...},
"points": [...]
}
PointData JSON (返回给前端)
{
"id": "...",
"name": "...",
"address": "...",
"datatype": "int16",
"value": 123.45,
"quality": "Good",
"timestamp": "2026-01-22T10:38:11Z",
"unit": "°C"
}
文件变更摘要
| 文件 | 行数 | 修改类型 | 说明 |
|---|---|---|---|
| internal/model/types.go | 4-85 | 修改 | 添加 JSON 标签、新增 PointData 结构 |
| internal/core/channel_manager.go | 180-229 | 修改 | GetDevicePoints 返回 []PointData |
| ui/index.html | 287, 303, 326, 341, 204, 161, 348, 377, 276 | 修改 | API 端点、表格绑定、数据处理更新 |
后续改进建议
- 错误处理: 添加更详细的错误日志和用户提示
- 数据缓存: 实现前端数据缓存以减少 API 请求
- 实时监听: 优化 WebSocket 只订阅当前设备的更新
- 批量写入: 支持批量写入多个点位
- 数据导出: 实现点位数据导出功能
- 历史查询: 添加历史数据查询接口
验证清单
- 后端编译无误
- 所有 API 端点正确
- JSON 序列化字段名一致
- 前端 API 调用路径正确
- 前端表格绑定字段正确
- WebSocket 连接地址正确
- 写入请求格式正确
- 三级导航正确映射
最终状态
✅ 修复完成 - 前端与后端三级架构 API 完全对齐
前端现在正确调用:
- 获取采集通道列表 (
/api/channels) - 获取指定通道的设备列表 (
/api/channels/{id}/devices) - 获取指定设备的点位数据 (
/api/channels/{cid}/devices/{did}/points) - 实时接收点位更新 (WebSocket
/api/ws/values) - 写入点位数据 (POST
/api/write)
所有数据字段名已匹配后端 JSON 标签的命名约定(snake_case)。