Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c7c34cda2 | ||
|
|
b0ee58a1b5 | ||
|
|
c3915dc8f5 | ||
|
|
ff4a197436 | ||
|
|
ad2d94a893 | ||
|
|
030e84ae16 | ||
|
|
60112e84e3 | ||
|
|
8f12d0e03e | ||
|
|
49ded8c568 | ||
|
|
a39ad579f9 | ||
|
|
657d357159 | ||
|
|
0d7d5722c1 | ||
|
|
36496e5825 | ||
|
|
5caffc9cc9 | ||
|
|
15bef7b17f | ||
|
|
4ac32753f1 | ||
|
|
131adc81a7 | ||
|
|
3135f76a2f | ||
|
|
08d81f724f | ||
|
|
29ef22c9b7 | ||
|
|
7738d7d153 | ||
|
|
20bc6e3ab5 | ||
|
|
2ea0557f4e | ||
|
|
1a35510801 | ||
|
|
5ad3029e0b | ||
|
|
cd51cfb052 | ||
|
|
4415eb30b2 | ||
|
|
78d094e4a2 | ||
|
|
8f5642d0b5 | ||
|
|
6c191aa96f | ||
|
|
f2d7156b4f | ||
|
|
d44c79f7b8 | ||
|
|
964ba77f8a | ||
|
|
7c1f135e99 | ||
|
|
1982ccd7ff | ||
|
|
5abaa743c0 | ||
|
|
52a8095334 | ||
|
|
654c997607 | ||
|
|
b31efb9ede | ||
|
|
195b58d798 | ||
|
|
0423de2683 |
@@ -54,13 +54,13 @@ webSocket:
|
|||||||
port: 7778
|
port: 7778
|
||||||
|
|
||||||
#源参数下发,暂态数据默认值
|
#源参数下发,暂态数据默认值
|
||||||
Dip:
|
#Dip:
|
||||||
# 暂态前时间(s)
|
# 暂态前时间(s)
|
||||||
# fPreTime: 2f
|
# fPreTime: 2f
|
||||||
#写入时间(s)
|
#写入时间(s)
|
||||||
fRampIn: 0.001f
|
# fRampIn: 0.001f
|
||||||
#写出时间(s)
|
#写出时间(s)
|
||||||
fRampOut: 0.001f
|
# fRampOut: 0.001f
|
||||||
# 暂态后时间(s)
|
# 暂态后时间(s)
|
||||||
# fAfterTime: 3f
|
# fAfterTime: 3f
|
||||||
|
|
||||||
@@ -97,6 +97,8 @@ qr:
|
|||||||
db:
|
db:
|
||||||
type: mysql
|
type: mysql
|
||||||
|
|
||||||
|
icd:
|
||||||
|
txt-dir: ..\..\..\9100\DeviceControl\Config
|
||||||
|
|
||||||
# 比对录波需要的配置,晚点再做优化
|
# 比对录波需要的配置,晚点再做优化
|
||||||
# 系统配置
|
# 系统配置
|
||||||
@@ -118,3 +120,5 @@ activate:
|
|||||||
public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFMmIVanMxsW5S/qP8Wcxf/J3/i4631BP3UtWkRzO7jAw9HIAgK4Y7X53hXj6zMbfme1vMjQc0mq7m/KrH4WlTYpFexLO6Gnk8oH40F04tp+ABZIq93zNOydPEaVoZeTPH/LlkwrrxVGAMNNIKuebcqapp25JiWtlSFMv4kH/nDAj+2m8+P4zYVM1Ed6gO01eKDEYE3SBA1Ket2BfHTgviR/F8WKwlXh11enywsJnrHTM5dJQdlUxCjHy214TpheYOz/cv9elQnDfFAbmZW8mH5/hgMSTkm3h4uR7ITin6Erg+yc/t1kGaTWrzloyBRMSiFN/Pwr5yQjj+1wQqqUkwIDAQAB"
|
public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFMmIVanMxsW5S/qP8Wcxf/J3/i4631BP3UtWkRzO7jAw9HIAgK4Y7X53hXj6zMbfme1vMjQc0mq7m/KrH4WlTYpFexLO6Gnk8oH40F04tp+ABZIq93zNOydPEaVoZeTPH/LlkwrrxVGAMNNIKuebcqapp25JiWtlSFMv4kH/nDAj+2m8+P4zYVM1Ed6gO01eKDEYE3SBA1Ket2BfHTgviR/F8WKwlXh11enywsJnrHTM5dJQdlUxCjHy214TpheYOz/cv9elQnDfFAbmZW8mH5/hgMSTkm3h4uR7ITin6Erg+yc/t1kGaTWrzloyBRMSiFN/Pwr5yQjj+1wQqqUkwIDAQAB"
|
||||||
|
|
||||||
|
|
||||||
|
dataCheck:
|
||||||
|
enable: false
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo51
Normal file
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo51
Normal file
Binary file not shown.
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo52
Normal file
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo52
Normal file
Binary file not shown.
Binary file not shown.
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo53
Normal file
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo53
Normal file
Binary file not shown.
Binary file not shown.
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo54
Normal file
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo54
Normal file
Binary file not shown.
Binary file not shown.
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo55
Normal file
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo55
Normal file
Binary file not shown.
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo56
Normal file
BIN
build/extraResources/mysql/data/#innodb_redo/#ib_redo56
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
116212
|
51248
|
||||||
|
|||||||
Binary file not shown.
BIN
build/extraResources/mysql/data/binlog.000041
Normal file
BIN
build/extraResources/mysql/data/binlog.000041
Normal file
Binary file not shown.
BIN
build/extraResources/mysql/data/binlog.000042
Normal file
BIN
build/extraResources/mysql/data/binlog.000042
Normal file
Binary file not shown.
@@ -16,3 +16,5 @@
|
|||||||
.\binlog.000038
|
.\binlog.000038
|
||||||
.\binlog.000039
|
.\binlog.000039
|
||||||
.\binlog.000040
|
.\binlog.000040
|
||||||
|
.\binlog.000041
|
||||||
|
.\binlog.000042
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/extraResources/mysql/data/pqs9100/pq_dev_check_history.ibd
Normal file
BIN
build/extraResources/mysql/data/pqs9100/pq_dev_check_history.ibd
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/extraResources/mysql/data/pqs9100/pq_pqdif_path.ibd
Normal file
BIN
build/extraResources/mysql/data/pqs9100/pq_pqdif_path.ibd
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
211
docs/superpowers/specs/2026-07-10-time-check-design.md
Normal file
211
docs/superpowers/specs/2026-07-10-time-check-design.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# 守时检测设计
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
现有守时页面 `frontend/src/views/home/components/timeTest.vue` 是演示式页面,包含假数据、步骤条和旧的“标准时间/上送时刻”展示方式,不符合新的业务流程。新的守时检测需要同时支持多台装置,动态展示每台装置的暂态触发时刻、守时误差和结果,并与现有检测弹窗、后端 `startPreTest` 流程联动。
|
||||||
|
|
||||||
|
后端项目位于 `D:\njcn\test\CN_Gather`。本设计覆盖前端与后端协同修改。
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
- 守时页面只展示守时检测用时和设备结果表,不展示源连接、设备连接、协议校验、相序校验等前置阶段。
|
||||||
|
- 表格列固定为:装置名称、暂态1触发时刻、暂态2触发时刻、守时误差、结果。
|
||||||
|
- 未收到对应数据时,单元格显示 loading 转圈状态。
|
||||||
|
- 守时检测计时格式为 `HH:mm:ss`。
|
||||||
|
- 支持多台设备同时检测。
|
||||||
|
- 守时检测过程要像 `factorTest.vue` 一样监听并拦截 WebSocket 错误,错误时终止流程。
|
||||||
|
- 守时完成后,如果后续还有正式检测,前后端自动流向正式检测且保持组件状态;如果没有正式检测,则清理连接和 WebSocket 资源。
|
||||||
|
|
||||||
|
## 检测项契约
|
||||||
|
|
||||||
|
`PreDetectionParam.testItemList` 从 3 位改为 4 位:
|
||||||
|
|
||||||
|
1. 第 1 位:预检测
|
||||||
|
2. 第 2 位:系数校准
|
||||||
|
3. 第 3 位:守时校验
|
||||||
|
4. 第 4 位:正式检测
|
||||||
|
|
||||||
|
前端所有调用 `startPreTest` 的位置都必须发送 4 位数组,例如:
|
||||||
|
|
||||||
|
- 只做守时检测:`[false, false, true, false]`
|
||||||
|
- 预检测 + 守时检测:`[true, false, true, false]`
|
||||||
|
- 守时检测 + 正式检测:`[false, false, true, true]`
|
||||||
|
- 预检测 + 守时检测 + 正式检测:`[true, false, true, true]`
|
||||||
|
|
||||||
|
后端所有读取 `testItemList` 的逻辑同步使用新索引,不能继续把第三位解释为正式检测。
|
||||||
|
|
||||||
|
## 前端流程
|
||||||
|
|
||||||
|
### 启动规则
|
||||||
|
|
||||||
|
`testPopup.vue` 继续作为检测弹窗流程编排入口。
|
||||||
|
|
||||||
|
只勾选守时检测时,前端调用现有 `startPreTest`。接口成功返回后,认为守时检测开始,`timeTest.vue` 开始计时。后端随后执行源连接、设备连接、协议校验、相序校验,再进入守时暂态流程。
|
||||||
|
|
||||||
|
勾选预检测 + 守时检测时,守时检测不在 `startPreTest` 成功后立刻开始计时。预检测包含源连接、设备连接、协议校验、相序校验四个阶段;这四个阶段完成后,后端推送守时开始/暂态数据相关消息,前端开始守时计时并展示表格更新。
|
||||||
|
|
||||||
|
### 页面结构
|
||||||
|
|
||||||
|
`timeTest.vue` 改为轻量结果页:
|
||||||
|
|
||||||
|
- 顶部为紧凑计时区域,显示 `守时检测用时:HH:mm:ss`。
|
||||||
|
- 下方为结果表格,列为 `装置名称 / 暂态1触发时刻 / 暂态2触发时刻 / 守时误差 / 结果`。
|
||||||
|
- 行数据初始化自 `checkStore.devices`。
|
||||||
|
- 未收到数据的字段显示 Element Plus loading 转圈。
|
||||||
|
- `time_waiting_second` 消息只触发轻量提示,例如“已收到第一组暂态数据,等待第二组暂态数据”,不增加页面状态区和统计区。
|
||||||
|
|
||||||
|
### Step 切换与状态保活
|
||||||
|
|
||||||
|
守时检测完成且后续进入正式检测后,用户可以点击弹窗顶部 step 切回守时检测页。此时守时页只读展示已完成结果,不重启监听、不重置 loading、不重新计时。
|
||||||
|
|
||||||
|
用户再切回正式检测页时,正式检测组件的表格信息、计时信息、日志进度和当前检测步骤不能初始化。实现上应保持组件实例存活,只切换 `stepsActiveView` 的显示状态,避免因 step 切换触发正式检测组件重建或初始化。
|
||||||
|
|
||||||
|
### 错误处理
|
||||||
|
|
||||||
|
`timeTest.vue` 需要接收并监听 `webMsgSend`,与 `factorTest.vue` 保持一致的错误拦截思路:
|
||||||
|
|
||||||
|
- 通用错误码如 `10520`、`10521`、`10522`、`10523`、`10524`、`10525`、`10527`、`10528`、`10529`、`10550`、`10551`、`10552`、`-1`。
|
||||||
|
- WebSocket 连接类错误,如 `socket_timeout`、`server_error`、`device_error`、`connect/Source`、`connect/Dev`。
|
||||||
|
- 源连接、设备连接、协议校验、相序校验阶段虽然不展示在页面中,但这些阶段的错误必须被守时页捕获,弹窗提示后 `emit('update:testStatus', 'error')`,父流程终止。
|
||||||
|
|
||||||
|
## 后端流程
|
||||||
|
|
||||||
|
### 总体接入
|
||||||
|
|
||||||
|
后端采用复用现有检测链路的方案。`startPreTest` 仍作为统一入口,守时校验作为现有检测链路中的独立业务阶段插入。
|
||||||
|
|
||||||
|
单独勾选守时检测时,后端需要执行完整前置阶段:
|
||||||
|
|
||||||
|
1. 源连接
|
||||||
|
2. 设备连接
|
||||||
|
3. 协议校验
|
||||||
|
4. 相序校验
|
||||||
|
5. 守时检测暂态流程
|
||||||
|
|
||||||
|
勾选预检测 + 守时检测时,预检测已经包含前四个阶段。后端不重复执行、不关闭源连接和设备连接,直接进入守时检测暂态流程。
|
||||||
|
|
||||||
|
### 守时业务规则
|
||||||
|
|
||||||
|
守时检测使用后端内置的两段守时专用暂态脚本,不由前端传脚本编号。
|
||||||
|
|
||||||
|
业务过程:
|
||||||
|
|
||||||
|
1. 下发暂态脚本 1。
|
||||||
|
2. 收取每台装置的一组暂态数据。
|
||||||
|
3. 两次暂态触发时刻均从 `DevData.time` 读取。
|
||||||
|
4. 同一设备存在多个监测点数据时,以第一条数据为准。
|
||||||
|
5. 第一组数据收齐后,后端推送 `time_waiting_second` 事件。
|
||||||
|
6. 后端等待 `waitTime - 暂态持续时间1 - fRampOut - fPreTime - fRampIn`。
|
||||||
|
7. 下发暂态脚本 2。
|
||||||
|
8. 收取每台装置第二组暂态数据。
|
||||||
|
9. 计算 `dtMs = 暂态1触发时刻 - 暂态2触发时刻 - waitTime`。
|
||||||
|
10. `dtMs <= 10ms` 为合格,否则不合格。
|
||||||
|
|
||||||
|
结果判定完全由后端负责。前端只展示后端推送的守时误差和结果,不自行计算合格性。
|
||||||
|
|
||||||
|
### 守时结束后的资源处理
|
||||||
|
|
||||||
|
如果 `testItemList[3]` 为 `true`,守时检测完成后自动流向正式检测:
|
||||||
|
|
||||||
|
- 后端不关闭源连接。
|
||||||
|
- 后端不关闭设备连接。
|
||||||
|
- 后端不清理正式检测需要的流程上下文。
|
||||||
|
- 前端不关闭 WebSocket,不重建正式检测组件。
|
||||||
|
- 前端收到守时成功后自动切到正式检测步骤。
|
||||||
|
|
||||||
|
如果 `testItemList[3]` 为 `false`,守时检测后没有正式检测:
|
||||||
|
|
||||||
|
- 后端在守时结束后断开设备连接和源连接。
|
||||||
|
- 后端清理检测流程上下文。
|
||||||
|
- 前端停止计时,展示最终结果,状态置为 `success` 或 `error`。
|
||||||
|
- 弹窗关闭时清理 WebSocket 回调或连接。
|
||||||
|
|
||||||
|
如果守时检测失败,无论是否勾选正式检测,都终止流程,不进入正式检测,并按错误流程释放资源。
|
||||||
|
|
||||||
|
## WebSocket 消息
|
||||||
|
|
||||||
|
守时阶段使用独立的守时消息语义,避免前端混在正式检测或系数校准消息里猜状态。推荐 `requestId` 使用 `Time_Check`。
|
||||||
|
|
||||||
|
### `time_first_data`
|
||||||
|
|
||||||
|
收到某台设备第一次暂态数据。
|
||||||
|
|
||||||
|
`data` 建议字段:
|
||||||
|
|
||||||
|
- `deviceId`
|
||||||
|
- `deviceName`
|
||||||
|
- `monitorId` 或监测点标识
|
||||||
|
- `firstTriggerTime`
|
||||||
|
|
||||||
|
### `time_waiting_second`
|
||||||
|
|
||||||
|
第一组暂态数据已收齐,后端已进入等待第二次暂态数据阶段。
|
||||||
|
|
||||||
|
该消息只作为事件触发标志,前端只做提示,不依赖业务字段。
|
||||||
|
|
||||||
|
### `time_second_data`
|
||||||
|
|
||||||
|
收到某台设备第二次暂态数据。
|
||||||
|
|
||||||
|
`data` 建议字段:
|
||||||
|
|
||||||
|
- `deviceId`
|
||||||
|
- `deviceName`
|
||||||
|
- `monitorId` 或监测点标识
|
||||||
|
- `secondTriggerTime`
|
||||||
|
|
||||||
|
### `time_result`
|
||||||
|
|
||||||
|
某台设备守时结果计算完成。
|
||||||
|
|
||||||
|
`data` 建议字段:
|
||||||
|
|
||||||
|
- `deviceId`
|
||||||
|
- `deviceName`
|
||||||
|
- `firstTriggerTime`
|
||||||
|
- `secondTriggerTime`
|
||||||
|
- `waitTimeMs`
|
||||||
|
- `dtMs`
|
||||||
|
- `result`
|
||||||
|
- `message`
|
||||||
|
|
||||||
|
`result` 可以使用后端现有结果约定,也可以明确为 `passed` / `failed`。前端需统一映射为“合格 / 不合格”。
|
||||||
|
|
||||||
|
### `time_finish`
|
||||||
|
|
||||||
|
全部守时检测完成。
|
||||||
|
|
||||||
|
`data` 建议字段:
|
||||||
|
|
||||||
|
- `allPassed`
|
||||||
|
- `results`
|
||||||
|
- `hasFormalTest`
|
||||||
|
|
||||||
|
前端收到后停止守时计时。如果 `hasFormalTest` 为 `true`,自动流向正式检测;否则结束当前检测流程。
|
||||||
|
|
||||||
|
## 涉及文件
|
||||||
|
|
||||||
|
前端:
|
||||||
|
|
||||||
|
- `frontend/src/views/home/components/timeTest.vue`
|
||||||
|
- `frontend/src/views/home/components/testPopup.vue`
|
||||||
|
- `frontend/src/api/socket/socket.ts`
|
||||||
|
- 必要时检查 `frontend/src/views/home/components/compareTestPopup.vue` 是否存在同类 `testItemList` 构造逻辑。
|
||||||
|
|
||||||
|
后端:
|
||||||
|
|
||||||
|
- `D:\njcn\test\CN_Gather\detection\src\main\java\com\njcn\gather\detection\pojo\param\PreDetectionParam.java`
|
||||||
|
- `D:\njcn\test\CN_Gather\detection\src\main\java\com\njcn\gather\detection\controller\PreDetectionController.java`
|
||||||
|
- `D:\njcn\test\CN_Gather\detection\src\main\java\com\njcn\gather\detection\service\impl\PreDetectionServiceImpl.java`
|
||||||
|
- `D:\njcn\test\CN_Gather\detection\src\main\java\com\njcn\gather\detection\handler\SocketDevResponseService.java`
|
||||||
|
- `D:\njcn\test\CN_Gather\detection\src\main\java\com\njcn\gather\detection\pojo\enums\SourceOperateCodeEnum.java`
|
||||||
|
|
||||||
|
## 测试建议
|
||||||
|
|
||||||
|
- 单独勾选守时检测:验证 `startPreTest` 成功后计时立即开始,前置四阶段错误可被前端拦截,最终无正式检测时资源被清理。
|
||||||
|
- 勾选预检测 + 守时检测:验证前置四阶段不重复执行、不关闭连接,守时计时从预检测四阶段完成后开始。
|
||||||
|
- 勾选守时检测 + 正式检测:验证守时成功后自动进入正式检测,连接和 WebSocket 不被清理。
|
||||||
|
- 正式检测中点击 step 切回守时页,再切回正式检测页:验证正式检测表格、计时、日志和进度不初始化。
|
||||||
|
- 多设备且多监测点:验证每台设备只取第一条监测点数据参与守时计算。
|
||||||
|
- 守时失败:验证不进入正式检测,并按错误流程释放资源。
|
||||||
|
- `time_waiting_second`:验证只提示,不改变表格结构。
|
||||||
@@ -12,3 +12,10 @@ VITE_REPORT=false
|
|||||||
|
|
||||||
# 浏览器是否显示vue的告警信息
|
# 浏览器是否显示vue的告警信息
|
||||||
VUE_APP_SILENCE_WARNINGS=true
|
VUE_APP_SILENCE_WARNINGS=true
|
||||||
|
|
||||||
|
VITE_COMPANY_WEBSITE=http://www.shining-electric.com/
|
||||||
|
VITE_COMPANY_NAME=南京灿能电力自动化股份有限公司
|
||||||
|
|
||||||
|
VITE_IS_SHOW_RAW_DATA=true
|
||||||
|
# 开启激活验证
|
||||||
|
VITE_ACTIVATE_OPEN=true
|
||||||
|
|||||||
@@ -22,7 +22,3 @@ VITE_API_URL=/api
|
|||||||
VITE_PROXY=[["/api","http://127.0.0.1:18092/"]]
|
VITE_PROXY=[["/api","http://127.0.0.1:18092/"]]
|
||||||
#VITE_PROXY=[["/api","http://192.168.1.124:18092/"]]
|
#VITE_PROXY=[["/api","http://192.168.1.124:18092/"]]
|
||||||
#VITE_PROXY=[["/api","http://192.168.2.125:18092/"]]
|
#VITE_PROXY=[["/api","http://192.168.2.125:18092/"]]
|
||||||
# VITE_PROXY=[["/api","http://192.168.1.138:8080/"]]张文
|
|
||||||
VITE_IS_SHOW_RAW_DATA=true
|
|
||||||
# 开启激活验证
|
|
||||||
VITE_ACTIVATE_OPEN=false
|
|
||||||
|
|||||||
@@ -24,6 +24,4 @@ VITE_PWA=true
|
|||||||
# 线上环境接口地址
|
# 线上环境接口地址
|
||||||
#VITE_API_URL="/api" # 打包时用
|
#VITE_API_URL="/api" # 打包时用
|
||||||
VITE_API_URL="http://127.0.0.1:18092/"
|
VITE_API_URL="http://127.0.0.1:18092/"
|
||||||
VITE_IS_SHOW_RAW_DATA=true
|
|
||||||
# 开启激活验证
|
|
||||||
VITE_ACTIVATE_OPEN=false
|
|
||||||
|
|||||||
@@ -1,269 +0,0 @@
|
|||||||
const data = [
|
|
||||||
{
|
|
||||||
id: 'device1',
|
|
||||||
deviceName:"模拟装置1",
|
|
||||||
deviceType:"PQS882B4电能质量监测装置",
|
|
||||||
deviceChannels:"4",
|
|
||||||
planName: "沧州220kV留古等4座变电站电能质量检测",
|
|
||||||
deviceUn: "57.74",
|
|
||||||
deviceIn: "5",
|
|
||||||
deviceCompany: "南京灿能电力自动化股份有限公司",
|
|
||||||
deviceModel: "模拟式",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'device2',
|
|
||||||
deviceName:"模拟装置2",
|
|
||||||
deviceType:"PQS882A电能质量监测装置",
|
|
||||||
deviceChannels:"1",
|
|
||||||
planName: "邯郸220kV团城站等4座站电能质量检测",
|
|
||||||
deviceUn: "57.74",
|
|
||||||
deviceIn: "5",
|
|
||||||
deviceCompany: "南京灿能电力自动化股份有限公司",
|
|
||||||
deviceModel: "模拟式",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'device3',
|
|
||||||
deviceName:"模拟装置3",
|
|
||||||
deviceType:"PQS882A电能质量监测装置",
|
|
||||||
deviceChannels:"1",
|
|
||||||
planName: "衡水冀州光伏电站配套出口工程",
|
|
||||||
deviceUn: "57.74",
|
|
||||||
deviceIn: "1",
|
|
||||||
deviceCompany: "南京灿能电力自动化股份有限公司",
|
|
||||||
deviceModel: "模拟式",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'device4',
|
|
||||||
deviceName:"模拟装置4",
|
|
||||||
deviceType:"PMC-680M-22-22-00-115ANBC电能质量监测装置",
|
|
||||||
deviceChannels:"4",
|
|
||||||
planName: "深圳市中电软件有限公司委托送检",
|
|
||||||
deviceUn: "57.74",
|
|
||||||
deviceIn: "5",
|
|
||||||
deviceCompany: "深圳中电电力技术股份有限公司",
|
|
||||||
deviceModel: "模拟式",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const plan_devicedata = [
|
|
||||||
{
|
|
||||||
id: '1', //装置序号ID
|
|
||||||
name: '240001', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2', //装置序号ID
|
|
||||||
name: '240002', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3', //装置序号ID
|
|
||||||
name: '240003', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4', //装置序号ID
|
|
||||||
name: '240004', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '5', //装置序号ID
|
|
||||||
name: '240005', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '不符合', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 1, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '6', //装置序号ID
|
|
||||||
name: '240006', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '不符合', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 1, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '7', //装置序号ID
|
|
||||||
name: '240007', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '符合', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 1, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '8', //装置序号ID
|
|
||||||
name: '240008', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '符合', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 1, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '9', //装置序号ID
|
|
||||||
name: '240009', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '不符合', //检测结果
|
|
||||||
report_State: '已生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 1, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '10', //装置序号ID
|
|
||||||
name: '240010', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '符合', //检测结果
|
|
||||||
report_State: '已生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 2, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '11', //装置序号ID
|
|
||||||
name: '240011', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '符合', //检测结果
|
|
||||||
report_State: '已生成', //报告状态
|
|
||||||
document_State: '已归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 1, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '12', //装置序号ID
|
|
||||||
name: '240012', //设备名称
|
|
||||||
dev_Type: 'PQS-882B4',//设备类型
|
|
||||||
dev_Chns: 4, //设备通道数
|
|
||||||
check_Result: '符合', //检测结果
|
|
||||||
report_State: '已生成', //报告状态
|
|
||||||
document_State: '已归档', //归档状态
|
|
||||||
check_State:'检测完成',//检测状态
|
|
||||||
reCheck_Num: 2, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '13', //装置序号ID
|
|
||||||
name: '240013', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '14', //装置序号ID
|
|
||||||
name: '240014', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '15', //装置序号ID
|
|
||||||
name: '240015', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '16', //装置序号ID
|
|
||||||
name: '240016', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '17', //装置序号ID
|
|
||||||
name: '240017', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '18', //装置序号ID
|
|
||||||
name: '240018', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '19', //装置序号ID
|
|
||||||
name: '240019', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '20', //装置序号ID
|
|
||||||
name: '240020', //设备名称
|
|
||||||
dev_Type: 'PQS-882A',//设备类型
|
|
||||||
dev_Chns: 1, //设备通道数
|
|
||||||
check_Result: '未检', //检测结果
|
|
||||||
report_State: '未生成', //报告状态
|
|
||||||
document_State: '未归档', //归档状态
|
|
||||||
check_State:'未检',//检测状态
|
|
||||||
reCheck_Num: 0, //复检次数
|
|
||||||
},
|
|
||||||
]
|
|
||||||
export default {data,plan_devicedata}
|
|
||||||
91
frontend/src/api/device/device/formData.ts
Normal file
91
frontend/src/api/device/device/formData.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import type { Device } from '@/api/device/interface/device'
|
||||||
|
import type { Monitor } from '@/api/device/interface/monitor'
|
||||||
|
|
||||||
|
const DEVICE_FIELD_NAMES = [
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'pattern',
|
||||||
|
'devType',
|
||||||
|
'manufacturer',
|
||||||
|
'createDate',
|
||||||
|
'createId',
|
||||||
|
'hardwareVersion',
|
||||||
|
'softwareVersion',
|
||||||
|
'protocol',
|
||||||
|
'ip',
|
||||||
|
'port',
|
||||||
|
'encryptionFlag',
|
||||||
|
'series',
|
||||||
|
'devKey',
|
||||||
|
'sampleId',
|
||||||
|
'arrivedDate',
|
||||||
|
'cityName',
|
||||||
|
'gdName',
|
||||||
|
'subName',
|
||||||
|
'reportPath',
|
||||||
|
'icdId',
|
||||||
|
'planId',
|
||||||
|
'factorFlag',
|
||||||
|
'preinvestmentPlan',
|
||||||
|
'delegate',
|
||||||
|
'inspectChannel',
|
||||||
|
'inspectDate',
|
||||||
|
'harmSysId',
|
||||||
|
'importFlag'
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const MONITOR_FIELD_NAMES = [
|
||||||
|
'id',
|
||||||
|
'devId',
|
||||||
|
'busbar',
|
||||||
|
'name',
|
||||||
|
'num',
|
||||||
|
'pt',
|
||||||
|
'ct',
|
||||||
|
'connection',
|
||||||
|
'statInterval',
|
||||||
|
'harmSysId',
|
||||||
|
'checkFlag'
|
||||||
|
] as const
|
||||||
|
|
||||||
|
function appendIfPresent(formData: FormData, key: string, value: unknown) {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.append(key, String(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendMonitorFields(formData: FormData, monitorList: Monitor.ResPqMon[]) {
|
||||||
|
monitorList.forEach((monitor, index) => {
|
||||||
|
MONITOR_FIELD_NAMES.forEach(fieldName => {
|
||||||
|
appendIfPresent(formData, `monitorList[${index}].${fieldName}`, monitor[fieldName])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildPqDevFormData(device: Device.ResPqDev, imageFile?: File | null) {
|
||||||
|
const formData = new FormData()
|
||||||
|
|
||||||
|
DEVICE_FIELD_NAMES.forEach(fieldName => {
|
||||||
|
appendIfPresent(formData, fieldName, device[fieldName])
|
||||||
|
})
|
||||||
|
|
||||||
|
appendMonitorFields(formData, device.monitorList ?? [])
|
||||||
|
|
||||||
|
if (imageFile) {
|
||||||
|
formData.append('image', imageFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
return formData
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildDeviceImagePreviewSrc(
|
||||||
|
hasImage?: boolean,
|
||||||
|
imageBase64?: string | null,
|
||||||
|
imageContentType?: string | null
|
||||||
|
) {
|
||||||
|
if (!hasImage || !imageBase64 || !imageContentType) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return `data:${imageContentType};base64,${imageBase64}`
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type {Device} from '@/api/device/interface/device'
|
import type {Device} from '@/api/device/interface/device'
|
||||||
import http from '@/api'
|
import http from '@/api'
|
||||||
|
import { buildPqDevFormData } from './formData'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name 被检设备管理模块
|
* @name 被检设备管理模块
|
||||||
@@ -11,13 +12,13 @@ export const getPqDevList = (params: Device.ReqPqDevParams) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//添加被检设备
|
//添加被检设备
|
||||||
export const addPqDev = (params: Device.ResPqDev) => {
|
export const addPqDev = (params: Device.ResPqDev, imageFile?: File | null) => {
|
||||||
return http.post(`/pqDev/add`, params)
|
return http.upload(`/pqDev/add`, buildPqDevFormData(params, imageFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
//编辑被检设备
|
//编辑被检设备
|
||||||
export const updatePqDev = (params: Device.ResPqDev) => {
|
export const updatePqDev = (params: Device.ResPqDev, imageFile?: File | null) => {
|
||||||
return http.post(`/pqDev/update`, params)
|
return http.upload(`/pqDev/update`, buildPqDevFormData(params, imageFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除被检设备
|
//删除被检设备
|
||||||
@@ -71,3 +72,7 @@ export const getPqDev = () => {
|
|||||||
export const getSelectOptions = (params:{ pattern: string }) => {
|
export const getSelectOptions = (params:{ pattern: string }) => {
|
||||||
return http.get(`/pqDev/getSelectOptions`, params)
|
return http.get(`/pqDev/getSelectOptions`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const downloadDeviceImage = (id: string) => {
|
||||||
|
return http.downloadGetWithHeaders(`/pqDev/image/download?id=${id}`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,34 +4,38 @@ import http from '@/api'
|
|||||||
/**
|
/**
|
||||||
* @name ICD管理模块
|
* @name ICD管理模块
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//获取ICD分页
|
|
||||||
export const getICDList = (params: ICD.ReqICDParams) => {
|
export const getICDList = (params: ICD.ReqICDParams) => {
|
||||||
return http.post(`/icd/list`,params)
|
return http.post<ICD.ResICDPage>(`/icd/list`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getICDAllList = () => {
|
||||||
//获取ICD
|
return http.get<ICD.ResICD[]>(`/icd/listAll`)
|
||||||
export const getICDAllList = (params: ICD.ResICD) => {
|
|
||||||
return http.get(`/icd/listAll`,params)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//添加ICD
|
export const getStandardICDList = () => {
|
||||||
export const addICD = (params: ICD.ResICD) => {
|
return http.get<ICD.StandardOption[]>(`/icd/standard-list`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getICDById = (id: string) => {
|
||||||
|
return http.get<ICD.ResICD>(`/icd/getById`, { id })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addICD = (params: FormData) => {
|
||||||
return http.upload(`/icd/add`, params)
|
return http.upload(`/icd/add`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
//编辑ICD
|
export const updateICD = (params: FormData) => {
|
||||||
export const updateICD = (params: ICD.ResICD) => {
|
|
||||||
return http.upload(`/icd/update`, params)
|
return http.upload(`/icd/update`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除ICD
|
export const importICDJson = (params: FormData) => {
|
||||||
export const deleteICD = (params: string[]) => {
|
return http.upload(`/icd/import/json`, params, { loading: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteICD = (params: string[]) => {
|
||||||
return http.post(`/icd/delete`, params)
|
return http.post(`/icd/delete`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const exportICD = (id: string) => {
|
||||||
|
return http.downloadGetWithHeaders(`/icd/export/${id}`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export namespace DevType {
|
|||||||
id: string; //设备类型ID
|
id: string; //设备类型ID
|
||||||
name: string;//设备类型名称
|
name: string;//设备类型名称
|
||||||
icd: string| null;//设备关联的ICD
|
icd: string| null;//设备关联的ICD
|
||||||
|
pqdif: string| null;//设备关联的PQDIF
|
||||||
power: string| null;//工作电源
|
power: string| null;//工作电源
|
||||||
devVolt: number; //额定电压(V)
|
devVolt: number; //额定电压(V)
|
||||||
devCurr: number; //额定电流(A)
|
devCurr: number; //额定电流(A)
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ export namespace Device {
|
|||||||
monitorList: Monitor.ResPqMon[]
|
monitorList: Monitor.ResPqMon[]
|
||||||
checked?: boolean // 是否已选择
|
checked?: boolean // 是否已选择
|
||||||
disabled?: boolean // 是否禁用
|
disabled?: boolean // 是否禁用
|
||||||
|
hasImage?: boolean // 是否存在设备图片
|
||||||
|
imageBase64?: string | null // 设备图片 Base64,用于详情回显
|
||||||
|
imageContentType?: string | null // 设备图片 MIME 类型
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectOption {
|
export interface SelectOption {
|
||||||
|
|||||||
@@ -1,38 +1,36 @@
|
|||||||
import type { ReqPage, ResPage } from '@/api/interface'
|
import type { ReqPage, ResPage } from '@/api/interface'
|
||||||
|
|
||||||
// ICD模块
|
|
||||||
export namespace ICD {
|
export namespace ICD {
|
||||||
|
export interface ReqICDParams extends ReqPage {
|
||||||
|
name?: string
|
||||||
|
type?: number
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
export interface StandardOption {
|
||||||
* ICD表格分页查询参数
|
id: string
|
||||||
*/
|
name: string
|
||||||
export interface ReqICDParams extends ReqPage {
|
type?: number
|
||||||
id: string; // 装置序号id 必填
|
}
|
||||||
devType?: string; // 设备名称
|
|
||||||
createTime?: string; //创建时间
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
export interface ResICD {
|
||||||
* ICD新增、修改、根据id查询返回的对象
|
id: string
|
||||||
*/
|
name: string
|
||||||
export interface ResICD {
|
state: number
|
||||||
id: string; //icdID
|
createBy?: string | null
|
||||||
name: string;//icd名称
|
createTime?: string | null
|
||||||
path: string;//icd存储地址
|
updateBy?: string | null
|
||||||
state: number;
|
updateTime?: string | null
|
||||||
createBy?: string| null; //创建用户
|
angle: number
|
||||||
createTime?: string| null; //创建时间
|
usePhaseIndex: number
|
||||||
updateBy?: string| null; //更新用户
|
jsonStr: string
|
||||||
updateTime?: string| null; //更新时间
|
xmlStr: string
|
||||||
angle: number; // 是否支持电压相角、电流相角指标
|
result: number
|
||||||
usePhaseIndex: number; // 角型接线时是否使用相别的指标来进行检测
|
msg: string | null
|
||||||
mappingFile: string | null;//映射文件
|
type: number
|
||||||
}
|
referenceIcdId: string | null
|
||||||
|
referenceIcdName?: string | null
|
||||||
|
hasIcdFile?: boolean | null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
export interface ResICDPage extends ResPage<ResICD> {}
|
||||||
* ICD表格查询分页返回的对象;
|
|
||||||
*/
|
|
||||||
export interface ResICDPage extends ResPage<ResICD> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
26
frontend/src/api/device/interface/pqdif.ts
Normal file
26
frontend/src/api/device/interface/pqdif.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import type { ReqPage, ResPage } from '@/api/interface'
|
||||||
|
|
||||||
|
export namespace PQDIF {
|
||||||
|
export interface ReqPQDIFParams extends ReqPage {
|
||||||
|
name?: string
|
||||||
|
result?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResPQDIF {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
filePath?: string | null
|
||||||
|
recordCount?: number | null
|
||||||
|
observationCount?: number | null
|
||||||
|
sampleValueCount?: number | null
|
||||||
|
result?: number | null
|
||||||
|
msg?: string | null
|
||||||
|
state: number
|
||||||
|
createBy?: string | null
|
||||||
|
createTime?: string | null
|
||||||
|
updateBy?: string | null
|
||||||
|
updateTime?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResPQDIFPage extends ResPage<ResPQDIF> {}
|
||||||
|
}
|
||||||
@@ -1,39 +1,34 @@
|
|||||||
import type { ReqPage, ResPage } from '@/api/interface'
|
import type { ReqPage, ResPage } from '@/api/interface'
|
||||||
import type { UploadFile } from 'element-plus';
|
|
||||||
|
|
||||||
// 报告模版接口
|
|
||||||
export namespace PqReport {
|
export namespace PqReport {
|
||||||
|
|
||||||
/**
|
|
||||||
* 报告模版表格分页查询参数
|
|
||||||
*/
|
|
||||||
export interface ReqReportParams extends ReqPage {
|
export interface ReqReportParams extends ReqPage {
|
||||||
id: string; // 装置序号id 必填
|
id: string
|
||||||
name?: string; // 设备名称
|
name?: string
|
||||||
createTime?: string; //创建时间
|
createTime?: string
|
||||||
|
pattern: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 报告模版新增、修改、根据id查询返回的对象
|
|
||||||
*/
|
|
||||||
export interface ResReport {
|
export interface ResReport {
|
||||||
id: string; //报告模板id
|
id: string
|
||||||
name: string;//报告模板名称
|
name: string
|
||||||
version:string;//版本号
|
version: string
|
||||||
baseFile?:string;//基础模板文件路径
|
pattern: string
|
||||||
detailFile?:string;//检测项模版文件路径
|
baseFile?: string
|
||||||
description:string;//描述信息
|
detailFile?: string
|
||||||
state:number;//状态:8-删除 1-正常
|
description: string
|
||||||
createBy?: string| null; //创建用户
|
state: number
|
||||||
createTime?: string| null; //创建时间
|
createBy?: string | null
|
||||||
updateBy?: string| null; //更新用户
|
createTime?: string | null
|
||||||
updateTime?: string| null; //更新时间
|
updateBy?: string | null
|
||||||
|
updateTime?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export interface ResReportOption {
|
||||||
* 报告模版表格查询分页返回的对象;
|
id: string
|
||||||
*/
|
name: string
|
||||||
export interface ResReportPage extends ResPage<ResReport> {
|
version: string
|
||||||
|
displayName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ResReportPage extends ResPage<ResReport> {}
|
||||||
}
|
}
|
||||||
14
frontend/src/api/device/pqdif/index.ts
Normal file
14
frontend/src/api/device/pqdif/index.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import type { PQDIF } from '@/api/device/interface/pqdif'
|
||||||
|
import http from '@/api'
|
||||||
|
|
||||||
|
export const getPQDIFList = (params: PQDIF.ReqPQDIFParams) => {
|
||||||
|
return http.post<PQDIF.ResPQDIFPage>('/pqdif/list', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getPQDIFAllList = () => {
|
||||||
|
return http.get<PQDIF.ResPQDIF[]>('/pqdif/listAll')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const importPQDIFJson = (params: FormData) => {
|
||||||
|
return http.upload('/pqdif/import/json', params, { loading: false })
|
||||||
|
}
|
||||||
@@ -1,51 +1,49 @@
|
|||||||
import type {PqReport} from '@/api/device/interface/report'
|
import type { PqReport } from '@/api/device/interface/report'
|
||||||
import http from '@/api'
|
import http from '@/api'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name 报告模版模块
|
* @name 报告模版模块
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//获取报告模版
|
//获取报告模版
|
||||||
export const getPqReportList = (params: PqReport.ReqReportParams) => {
|
export const getPqReportList = (params: PqReport.ReqReportParams) => {
|
||||||
return http.post(`/report/list`, params)
|
return http.post(`/report/list`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
//新增报告模版
|
//新增报告模版
|
||||||
export const addPqReport = (params: PqReport.ResReport) => {
|
export const addPqReport = (params: PqReport.ResReport) => {
|
||||||
return http.upload(`/report/add`, params)
|
return http.upload(`/report/add`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除报告模版
|
//删除报告模版
|
||||||
export const deletePqReport = (params: string[]) => {
|
export const deletePqReport = (params: string[]) => {
|
||||||
return http.post(`/report/delete`, params)
|
return http.post(`/report/delete`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
//查询报告模板详情
|
//查询报告模板详情
|
||||||
export const getPqReportById = (params: PqReport.ResReport) => {
|
export const getPqReportById = (params: PqReport.ResReport) => {
|
||||||
return http.get(`/report/getById?id=${params.id}`)
|
return http.get(`/report/getById?id=${params.id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
//修改报告模板
|
//修改报告模板
|
||||||
export const updatePqReport = (params: PqReport.ResReport) => {
|
export const updatePqReport = (params: PqReport.ResReport) => {
|
||||||
return http.upload(`/report/update`, params)
|
return http.upload(`/report/update`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
//查询所有报告模板名称
|
export const getPqReportOptions = (params: { pattern: string }) => {
|
||||||
export const getPqReportAllName = () => {
|
return http.get(`/report/listOptions?pattern=${params.pattern}`)
|
||||||
return http.get(`/report/listAllName`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//根据名称查询指定报告模板的所有版本
|
//根据名称查询指定报告模板的所有版本
|
||||||
export const getPqReportAllVersion = (params:any) => {
|
export const getPqReportAllVersion = (params: any) => {
|
||||||
return http.get(`/report/listAllVersion?name=${params.name}`)
|
return http.get(`/report/listAllVersion?name=${params.name}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
//被检设备归档
|
//被检设备归档
|
||||||
export const documentedPqDev = (ids: string[]) => {
|
export const documentedPqDev = (ids: string[]) => {
|
||||||
return http.post(`/report/documented`, ids)
|
return http.post(`/report/documented`, ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
//上传报告到云端
|
//上传报告到云端
|
||||||
export const uploadReportToCloud = (deviceIds: string[]) => {
|
export const uploadReportToCloud = (deviceIds: string[]) => {
|
||||||
return http.post(`/report/uploadReportToCloud`, deviceIds)
|
return http.post(`/report/uploadReportToCloud`, deviceIds)
|
||||||
}
|
}
|
||||||
@@ -214,6 +214,10 @@ class RequestHttp {
|
|||||||
return this.service.post(url, params, { ..._object, responseType: 'blob' })
|
return this.service.post(url, params, { ..._object, responseType: 'blob' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downloadGetWithHeaders(url: string, _object = {}): Promise<AxiosResponse<Blob>> {
|
||||||
|
return this.service.get(url, { ..._object, responseType: 'blob' })
|
||||||
|
}
|
||||||
|
|
||||||
upload(url: string, params?: object, _object = {}): Promise<BlobPart> {
|
upload(url: string, params?: object, _object = {}): Promise<BlobPart> {
|
||||||
return this.service.post(url, params, {
|
return this.service.post(url, params, {
|
||||||
..._object,
|
..._object,
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
import http from '@/api'
|
import http from '@/api'
|
||||||
|
|
||||||
|
export interface SntpTimeMessage {
|
||||||
|
type: string
|
||||||
|
deviceIp?: string
|
||||||
|
computerTime?: string
|
||||||
|
deviceTime?: string
|
||||||
|
computerTimestampMs?: number
|
||||||
|
deviceTimestampMs?: number
|
||||||
|
errorMs?: number
|
||||||
|
}
|
||||||
|
|
||||||
export const startSntpService = () => {
|
export const startSntpService = () => {
|
||||||
return http.post('/sntp/start', {})
|
return http.post('/sntp/start', {})
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
171
frontend/src/components/JsonImportDialog/index.vue
Normal file
171
frontend/src/components/JsonImportDialog/index.vue
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:title="title"
|
||||||
|
width="460px"
|
||||||
|
destroy-on-close
|
||||||
|
:close-on-click-modal="!loading"
|
||||||
|
:show-close="!loading"
|
||||||
|
>
|
||||||
|
<div v-loading="loading" :element-loading-text="loadingText" class="json-import-content">
|
||||||
|
<el-upload
|
||||||
|
ref="uploadRef"
|
||||||
|
action="#"
|
||||||
|
class="upload"
|
||||||
|
:auto-upload="false"
|
||||||
|
:limit="1"
|
||||||
|
accept=".json,application/json"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:on-change="handleChange"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
:disabled="loading"
|
||||||
|
>
|
||||||
|
<el-button type="primary" :icon="Upload" :disabled="loading">选择文件</el-button>
|
||||||
|
<template #tip>
|
||||||
|
<div class="el-upload__tip">{{ tip }}</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
<div v-if="loading" class="json-import-loading-text">{{ loadingText }}</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button :disabled="loading" @click="close">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="loading" @click="submit">开始导入</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { Upload } from '@element-plus/icons-vue'
|
||||||
|
import {
|
||||||
|
ElMessage,
|
||||||
|
ElNotification,
|
||||||
|
genFileId,
|
||||||
|
type UploadFile,
|
||||||
|
type UploadInstance,
|
||||||
|
type UploadProps,
|
||||||
|
type UploadRawFile
|
||||||
|
} from 'element-plus'
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
title: string
|
||||||
|
requestApi: (params: FormData) => Promise<unknown>
|
||||||
|
tip?: string
|
||||||
|
loadingText?: string
|
||||||
|
successMessage?: string
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
tip: '请上传 .json 文件',
|
||||||
|
loadingText: '导入中,请稍候...',
|
||||||
|
successMessage: '导入成功'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'success'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const uploadRef = ref<UploadInstance | null>(null)
|
||||||
|
const selectedFile = ref<File | null>(null)
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
if (loading.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dialogVisible.value = false
|
||||||
|
selectedFile.value = null
|
||||||
|
uploadRef.value?.clearFiles()
|
||||||
|
}
|
||||||
|
|
||||||
|
const isJsonFile = (file: UploadRawFile | File) => {
|
||||||
|
return file.name.toLowerCase().endsWith('.json') || file.type === 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
const notifyInvalidFile = () => {
|
||||||
|
ElNotification({
|
||||||
|
title: '温馨提示',
|
||||||
|
message: '上传文件只能是 json 格式!',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const setSelectedFile = (file: UploadRawFile | File | undefined) => {
|
||||||
|
if (!file) {
|
||||||
|
selectedFile.value = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!isJsonFile(file)) {
|
||||||
|
notifyInvalidFile()
|
||||||
|
selectedFile.value = null
|
||||||
|
uploadRef.value?.clearFiles()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selectedFile.value = file
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleExceed: UploadProps['onExceed'] = files => {
|
||||||
|
uploadRef.value?.clearFiles()
|
||||||
|
const file = files[0] as UploadRawFile
|
||||||
|
file.uid = genFileId()
|
||||||
|
uploadRef.value?.handleStart(file)
|
||||||
|
setSelectedFile(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChange = (uploadFile: UploadFile) => {
|
||||||
|
setSelectedFile(uploadFile.raw as File | undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRemove = () => {
|
||||||
|
selectedFile.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
if (loading.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!selectedFile.value) {
|
||||||
|
ElMessage.warning('请选择文件!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', selectedFile.value)
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
await props.requestApi(formData)
|
||||||
|
ElMessage.success(props.successMessage)
|
||||||
|
dialogVisible.value = false
|
||||||
|
selectedFile.value = null
|
||||||
|
uploadRef.value?.clearFiles()
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
close
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.json-import-content {
|
||||||
|
min-height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-import-loading-text {
|
||||||
|
margin-top: 12px;
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<el-header>
|
<el-header>
|
||||||
<div class="logo flx-center">
|
<div class="logo flx-center">
|
||||||
<!-- <img class="logo-img" src="@/assets/images/logo.svg" alt="logo" /> -->
|
<!-- <img class="logo-img" src="@/assets/images/logo.svg" alt="logo" /> -->
|
||||||
<img class="logo-img" src="@/assets/images/cn_pms9100_logo.png" alt="logo" />
|
<img class="logo-img" src="@/assets/images/logo.png" alt="logo" />
|
||||||
<span class="logo-text">{{ title }}</span>
|
<span class="logo-text">{{ title }}</span>
|
||||||
</div>
|
</div>
|
||||||
<el-menu v-if="showMenuFlag" trigger="click" mode="horizontal" :router="false" :default-active="activeMenu">
|
<el-menu v-if="showMenuFlag" trigger="click" mode="horizontal" :router="false" :default-active="activeMenu">
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user