feat:必硕1.0页面迁移
parent
d4b8bc4c94
commit
f84277c967
@ -1,43 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// IoT 设备分组 VO
|
||||
export interface DeviceGroupVO {
|
||||
id: number // 分组 ID
|
||||
name: string // 分组名字
|
||||
status: number // 分组状态
|
||||
description: string // 分组描述
|
||||
deviceCount?: number // 设备数量
|
||||
}
|
||||
|
||||
// IoT 设备分组 API
|
||||
export const DeviceGroupApi = {
|
||||
// 查询设备分组分页
|
||||
getDeviceGroupPage: async (params: any) => {
|
||||
return await request.get({ url: `/iot/device-group/page`, params })
|
||||
},
|
||||
|
||||
// 查询设备分组详情
|
||||
getDeviceGroup: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device-group/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增设备分组
|
||||
createDeviceGroup: async (data: DeviceGroupVO) => {
|
||||
return await request.post({ url: `/iot/device-group/create`, data })
|
||||
},
|
||||
|
||||
// 修改设备分组
|
||||
updateDeviceGroup: async (data: DeviceGroupVO) => {
|
||||
return await request.put({ url: `/iot/device-group/update`, data })
|
||||
},
|
||||
|
||||
// 删除设备分组
|
||||
deleteDeviceGroup: async (id: number) => {
|
||||
return await request.delete({ url: `/iot/device-group/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 获取设备分组的精简信息列表
|
||||
getSimpleDeviceGroupList: async () => {
|
||||
return await request.get({ url: `/iot/device-group/simple-list` })
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,202 @@
|
||||
import request from '@/config/axios'
|
||||
import qs from 'qs'
|
||||
|
||||
// 物联设备 VO
|
||||
export interface DeviceVO {
|
||||
id: number // ID
|
||||
deviceCode: string // 设备编号
|
||||
deviceName: string // 设备名称
|
||||
deviceType: string // 设备类型
|
||||
status: string // 状态
|
||||
isConnect?: string | number
|
||||
operatingStatus?: string | number
|
||||
readTopic: string // 读主题
|
||||
writeTopic: string // 写主题
|
||||
gatewayId: number // 网关id
|
||||
deviceBrandId: number // 设备品牌id
|
||||
offLineDuration: number // 离线间隔
|
||||
lastOnlineTime: Date // 最后上线时间
|
||||
remark: string // 备注
|
||||
isEnable: boolean // 是否启用
|
||||
deviceModelId: number // 关联设备模型
|
||||
protocol: string // 通讯协议
|
||||
sampleCycle: number // 采集周期
|
||||
url: string // 端点url
|
||||
username: string // 用户名
|
||||
password: string // 密码
|
||||
certificate?: string // 证书
|
||||
secretKey?: string // 秘钥
|
||||
collectionTime?: string | number
|
||||
}
|
||||
|
||||
export interface DeviceConnectParams {
|
||||
id: string | number
|
||||
isConnect: string | number
|
||||
}
|
||||
|
||||
export interface LineDeviceVO {
|
||||
id?: string | number
|
||||
lineNode?: string
|
||||
lineName?: string
|
||||
deviceCode?: string
|
||||
deviceName?: string
|
||||
status?: string | number
|
||||
collectionTime?: string | number
|
||||
}
|
||||
|
||||
export interface LineDevicePageParams {
|
||||
pageNo: number
|
||||
pageSize: number
|
||||
id?: string | number
|
||||
lineNode?: string
|
||||
lineName?: string
|
||||
deviceCode?: string
|
||||
deviceName?: string
|
||||
status?: string | number
|
||||
collectionTime?: string | number
|
||||
collectionTimeStart?: string
|
||||
collectionTimeEnd?: string
|
||||
}
|
||||
|
||||
export interface SingleDeviceParams {
|
||||
deviceId: string | number
|
||||
}
|
||||
|
||||
export interface HistoryRecordParams {
|
||||
deviceId: string | number
|
||||
collectionStartTime?: string
|
||||
collectionEndTime?: string
|
||||
attributeCodes?: string[]
|
||||
}
|
||||
|
||||
export interface DeviceContactModelVO {
|
||||
id: number
|
||||
attributeCode?: string
|
||||
attributeName?: string
|
||||
attributeType?: string
|
||||
dataType?: string
|
||||
dataUnit?: string
|
||||
}
|
||||
|
||||
|
||||
// 物联设备 API
|
||||
export const DeviceApi = {
|
||||
// 查询物联设备分页
|
||||
getDevicePage: async (params: any) => {
|
||||
return await request.get({ url: `/iot/device/page`, params })
|
||||
},
|
||||
// 查询物联设备
|
||||
getDeviceList: async () => {
|
||||
return await request.get({ url: `/iot/device/deviceList` })
|
||||
},
|
||||
// 查询物联设备详情
|
||||
getDevice: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device/get?id=` + id })
|
||||
},
|
||||
getDeviceListByNoUsed: async () => {
|
||||
return await request.get({ url: `/iot/device/noUsedlist` })
|
||||
},
|
||||
getDeviceList2ByNoUsed: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device/noUsedlist2?id=` + id })
|
||||
},
|
||||
// 新增物联设备
|
||||
createDevice: async (data: DeviceVO) => {
|
||||
return await request.post({ url: `/iot/device/create`, data })
|
||||
},
|
||||
|
||||
// 批量获取设备属性列表
|
||||
getDeviceAttributeBatchList: async (params: { goviewId: number | string; orgId?: number | string }) => {
|
||||
return await request.get({ url: `/iot/device/device-attribute/batchList`, params })
|
||||
},
|
||||
// 修改物联设备
|
||||
updateDevice: async (data: DeviceVO) => {
|
||||
return await request.put({ url: `/iot/device/update`, data })
|
||||
},
|
||||
|
||||
// 删除物联设备
|
||||
deleteDevice: async (ids: string) => {
|
||||
return await request.delete({ url: `/iot/device/delete?ids=` + ids })
|
||||
},
|
||||
|
||||
// 复制物联设备
|
||||
copyDevice: async (id: number) => {
|
||||
return await request.post({ url: `/iot/device/copy`, params: { id } })
|
||||
},
|
||||
|
||||
connectDevice: async (params: DeviceConnectParams) => {
|
||||
return await request.post({ url: `/iot/device/connect`, data: params })
|
||||
},
|
||||
|
||||
// 导出物联设备 Excel
|
||||
exportDevice: async (params) => {
|
||||
return await request.download({ url: `/iot/device/export-excel`, params })
|
||||
},
|
||||
|
||||
exportLineDevice: async (params) => {
|
||||
return await request.download({ url: `/iot/device/export-line-device`, params })
|
||||
},
|
||||
|
||||
getLineDevicePage: async (params: LineDevicePageParams) => {
|
||||
return await request.get({ url: `/iot/device/lineDevicePage`, params })
|
||||
},
|
||||
|
||||
getSingleDevice: async (params: SingleDeviceParams) => {
|
||||
return await request.get({ url: `/iot/device/singleDevice`, params })
|
||||
},
|
||||
|
||||
getHistoryRecord: async (params: HistoryRecordParams) => {
|
||||
return await request.get({
|
||||
url: `/iot/device/historyRecord`,
|
||||
params,
|
||||
paramsSerializer: (p) => qs.stringify(p, { allowDots: true, arrayFormat: 'repeat' })
|
||||
})
|
||||
},
|
||||
|
||||
devicePointList: async () => {
|
||||
return await request.get({ url: `/iot/device/devicePointList` })
|
||||
},
|
||||
|
||||
updateDeviceEnabled: async (id: number | string, enabled: string) => {
|
||||
const data = { id, enabled }
|
||||
return await request.put({ url: `/iot/device/update-enabled`, data })
|
||||
},
|
||||
|
||||
// ==================== 子表(设备属性) ====================
|
||||
|
||||
// 获得设备属性分页
|
||||
getDeviceAttributePage: async (params) => {
|
||||
return await request.get({ url: `/iot/device/device-attribute/page`, params })
|
||||
},
|
||||
// 获得设备属性列表
|
||||
getDeviceAttributeList: async (deviceId: number | string) => {
|
||||
return await request.get({ url: `/iot/device/device-attribute/list?deviceId=` + deviceId })
|
||||
},
|
||||
|
||||
getDeviceContactModelPage: async () => {
|
||||
return await request.get({ url: `/iot/device-contact-model/page` })
|
||||
},
|
||||
// 新增设备属性
|
||||
createDeviceAttribute: async (data) => {
|
||||
return await request.post({ url: `/iot/device-contact-model/create`, data })
|
||||
},
|
||||
|
||||
// 修改设备属性
|
||||
updateDeviceAttribute: async (data) => {
|
||||
return await request.put({ url: `/iot/device-contact-model/update`, data })
|
||||
},
|
||||
|
||||
// 删除设备属性
|
||||
deleteDeviceAttribute: async (ids: string) => {
|
||||
return await request.delete({ url: `/iot/device-contact-model/delete?ids=` + ids })
|
||||
},
|
||||
|
||||
// 导出设备属性 Excel
|
||||
exportDeviceContactModel: async (params) => {
|
||||
return await request.download({ url: `/iot/device-contact-model/export-excel`, params })
|
||||
},
|
||||
|
||||
// 获得设备属性
|
||||
getDeviceAttribute: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device-contact-model/get?id=` + id })
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
/** Modbus 连接配置 VO */
|
||||
export interface DeviceModbusConfigVO {
|
||||
id?: number // 主键
|
||||
deviceId: number // 设备编号
|
||||
ip: string // Modbus 服务器 IP 地址
|
||||
port: number // Modbus 服务器端口
|
||||
slaveId: number // 从站地址
|
||||
timeout: number // 连接超时时间,单位:毫秒
|
||||
retryInterval: number // 重试间隔,单位:毫秒
|
||||
mode: number // 模式
|
||||
frameFormat: number // 帧格式
|
||||
status: number // 状态
|
||||
}
|
||||
|
||||
/** Modbus 连接配置 API */
|
||||
export const DeviceModbusConfigApi = {
|
||||
/** 获取设备的 Modbus 连接配置 */
|
||||
getModbusConfig: async (deviceId: number) => {
|
||||
return await request.get<DeviceModbusConfigVO>({
|
||||
url: `/iot/device-modbus-config/get`,
|
||||
params: { deviceId }
|
||||
})
|
||||
},
|
||||
|
||||
/** 保存 Modbus 连接配置 */
|
||||
saveModbusConfig: async (data: DeviceModbusConfigVO) => {
|
||||
return await request.post({ url: `/iot/device-modbus-config/save`, data })
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
/** Modbus 点位配置 VO */
|
||||
export interface DeviceModbusPointVO {
|
||||
id?: number // 主键
|
||||
deviceId: number // 设备编号
|
||||
thingModelId?: number // 物模型属性编号
|
||||
identifier: string // 属性标识符
|
||||
name: string // 属性名称
|
||||
functionCode?: number // Modbus 功能码
|
||||
registerAddress?: number // 寄存器起始地址
|
||||
registerCount?: number // 寄存器数量
|
||||
byteOrder?: string // 字节序
|
||||
rawDataType?: string // 原始数据类型
|
||||
scale: number // 缩放因子
|
||||
pollInterval: number // 轮询间隔,单位:毫秒
|
||||
status: number // 状态
|
||||
}
|
||||
|
||||
/** Modbus 点位配置 API */
|
||||
export const DeviceModbusPointApi = {
|
||||
/** 获取设备的 Modbus 点位分页 */
|
||||
getModbusPointPage: async (params: any) => {
|
||||
return await request.get({ url: `/iot/device-modbus-point/page`, params })
|
||||
},
|
||||
|
||||
/** 获取 Modbus 点位详情 */
|
||||
getModbusPoint: async (id: number) => {
|
||||
return await request.get<DeviceModbusPointVO>({
|
||||
url: `/iot/device-modbus-point/get?id=${id}`
|
||||
})
|
||||
},
|
||||
|
||||
/** 创建 Modbus 点位配置 */
|
||||
createModbusPoint: async (data: DeviceModbusPointVO) => {
|
||||
return await request.post({ url: `/iot/device-modbus-point/create`, data })
|
||||
},
|
||||
|
||||
/** 更新 Modbus 点位配置 */
|
||||
updateModbusPoint: async (data: DeviceModbusPointVO) => {
|
||||
return await request.put({ url: `/iot/device-modbus-point/update`, data })
|
||||
},
|
||||
|
||||
/** 删除 Modbus 点位配置 */
|
||||
deleteModbusPoint: async (id: number) => {
|
||||
return await request.delete({ url: `/iot/device-modbus-point/delete?id=${id}` })
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 采集点分类 VO
|
||||
export interface DeviceAttributeTypeVO {
|
||||
id: number // ID
|
||||
code: string // 分类编码
|
||||
name: string // 分类名称
|
||||
sort: number // 分类顺序
|
||||
remark: string // 备注
|
||||
}
|
||||
|
||||
// 采集点分类 API
|
||||
export const DeviceAttributeTypeApi = {
|
||||
// 查询采集点分类分页
|
||||
getDeviceAttributeTypePage: async (params: any) => {
|
||||
return await request.get({ url: `/iot/device-attribute-type/page`, params })
|
||||
},
|
||||
|
||||
// 查询采集点分类详情
|
||||
getDeviceAttributeType: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device-attribute-type/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增采集点分类
|
||||
createDeviceAttributeType: async (data: DeviceAttributeTypeVO) => {
|
||||
return await request.post({ url: `/iot/device-attribute-type/create`, data })
|
||||
},
|
||||
|
||||
// 修改采集点分类
|
||||
updateDeviceAttributeType: async (data: DeviceAttributeTypeVO) => {
|
||||
return await request.put({ url: `/iot/device-attribute-type/update`, data })
|
||||
},
|
||||
|
||||
// 删除采集点分类
|
||||
deleteDeviceAttributeType: async (ids: string) => {
|
||||
return await request.delete({ url: `/iot/device-attribute-type/delete?ids=` + ids })
|
||||
},
|
||||
|
||||
// 导出采集点分类 Excel
|
||||
exportDeviceAttributeType: async (params) => {
|
||||
return await request.download({ url: `/iot/device-attribute-type/export-excel`, params })
|
||||
},
|
||||
|
||||
// 获得采集点分类列表
|
||||
getDeviceAttributeTypeList: async () => {
|
||||
return await request.get({ url: `/iot/device-attribute-type/list` })
|
||||
},
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 采集设备模型 VO
|
||||
export interface DeviceModelVO {
|
||||
id: number // ID
|
||||
code: string // 分类编码
|
||||
name: string // 分类名称
|
||||
protocol: string // 通讯协议
|
||||
remark: string // 备注
|
||||
}
|
||||
|
||||
// 采集设备模型 API
|
||||
export const DeviceModelApi = {
|
||||
// 查询采集设备模型分页
|
||||
getDeviceModelPage: async (params: any) => {
|
||||
return await request.get({ url: `/iot/device-model/page`, params })
|
||||
},
|
||||
|
||||
// 查询采集设备模型详情
|
||||
getDeviceModel: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device-model/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增采集设备模型
|
||||
createDeviceModel: async (data: DeviceModelVO) => {
|
||||
return await request.post({ url: `/iot/device-model/create`, data })
|
||||
},
|
||||
|
||||
// 修改采集设备模型
|
||||
updateDeviceModel: async (data: DeviceModelVO) => {
|
||||
return await request.put({ url: `/iot/device-model/update`, data })
|
||||
},
|
||||
|
||||
// 删除采集设备模型
|
||||
deleteDeviceModel: async (ids: string) => {
|
||||
return await request.delete({ url: `/iot/device-model/delete?ids=` + ids })
|
||||
},
|
||||
|
||||
// 复制采集设备模型
|
||||
copyDeviceModel: async (id: number) => {
|
||||
return await request.post({ url: `/iot/device-model/copy`, params: { id } })
|
||||
},
|
||||
|
||||
// 导出采集设备模型 Excel
|
||||
exportDeviceModel: async (params) => {
|
||||
return await request.download({ url: `/iot/device-model/export-excel`, params })
|
||||
},
|
||||
|
||||
// 获得采集设备模型列表
|
||||
getDeviceModelList: async () => {
|
||||
return await request.get({ url: `/iot/device-model/list` })
|
||||
},
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 采集设备模型-点位管理 VO
|
||||
export interface DeviceModelAttributeVO {
|
||||
id: number // ID
|
||||
attributeCode: string // 点位编码
|
||||
attributeName: string // 点位名称
|
||||
attributeType: string // 点位类型
|
||||
dataType: string // 数据类型
|
||||
address: string // 寄存器地址
|
||||
dataUnit: string // 单位
|
||||
ratio: number // 倍率
|
||||
remark: string // 备注
|
||||
deviceModelId: number // 采集设备模型id
|
||||
}
|
||||
|
||||
// 采集设备模型-点位管理 API
|
||||
export const DeviceModelAttributeApi = {
|
||||
// 查询采集设备模型-点位管理分页
|
||||
getDeviceModelAttributePage: async (params: any) => {
|
||||
return await request.get({ url: `/iot/device-model-attribute/page`, params })
|
||||
},
|
||||
|
||||
// 查询采集设备模型-点位管理列表(当前设备模型下的点位)
|
||||
getDeviceModelAttributeList: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device-model-attribute/list`, params: { id } })
|
||||
},
|
||||
|
||||
// 查询采集设备模型-点位管理详情
|
||||
getDeviceModelAttribute: async (id: number) => {
|
||||
return await request.get({ url: `/iot/device-model-attribute/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增采集设备模型-点位管理
|
||||
createDeviceModelAttribute: async (data) => {
|
||||
return await request.post({ url: `/iot/device-model-attribute/create`, data })
|
||||
},
|
||||
|
||||
// 修改采集设备模型-点位管理
|
||||
updateDeviceModelAttribute: async (data) => {
|
||||
return await request.put({ url: `/iot/device-model-attribute/update`, data })
|
||||
},
|
||||
|
||||
// 删除采集设备模型-点位管理
|
||||
deleteDeviceModelAttribute: async (ids: string) => {
|
||||
return await request.delete({ url: `/iot/device-model-attribute/delete?ids=` + ids })
|
||||
},
|
||||
|
||||
// 导出采集设备模型-点位管理 Excel
|
||||
exportDeviceModelAttribute: async (params) => {
|
||||
return await request.download({ url: `/iot/device-model-attribute/export-excel`, params })
|
||||
},
|
||||
|
||||
// 下载采集设备模型-点位管理导入模板
|
||||
importDeviceModelAttributeTemplate: async () => {
|
||||
return await request.download({ url: `/iot/device-model-attribute/get-import-template` })
|
||||
},
|
||||
|
||||
operationAnalysisDetails: async (params: {
|
||||
deviceId: number
|
||||
modelId?: number
|
||||
collectionStartTime?: string
|
||||
collectionEndTime?: string
|
||||
}) => {
|
||||
return await request.get({ url: `/iot/device-model-attribute/operationAnalysisDetails`, params })
|
||||
}
|
||||
}
|
||||
@ -1,201 +0,0 @@
|
||||
<!-- 设备消息列表 -->
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索区域 -->
|
||||
<el-form :model="queryParams" inline>
|
||||
<el-form-item>
|
||||
<el-select v-model="queryParams.method" placeholder="所有方法" class="!w-160px" clearable>
|
||||
<el-option
|
||||
v-for="item in methodOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select
|
||||
v-model="queryParams.upstream"
|
||||
placeholder="上行/下行"
|
||||
class="!w-160px"
|
||||
clearable
|
||||
>
|
||||
<el-option label="上行" value="true" />
|
||||
<el-option label="下行" value="false" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||
</el-button>
|
||||
<el-switch
|
||||
size="large"
|
||||
width="80"
|
||||
v-model="autoRefresh"
|
||||
class="ml-20px"
|
||||
inline-prompt
|
||||
active-text="定时刷新"
|
||||
inactive-text="定时刷新"
|
||||
style="--el-switch-on-color: #13ce66"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 消息列表 -->
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" class="whitespace-nowrap">
|
||||
<el-table-column label="时间" align="center" prop="ts" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatDate(scope.row.ts) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上行/下行" align="center" prop="upstream" width="140">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.upstream ? 'primary' : 'success'">
|
||||
{{ scope.row.upstream ? '上行' : '下行' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否回复" align="center" prop="reply" width="140">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.reply" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请求编号" align="center" prop="requestId" width="300" />
|
||||
<el-table-column label="请求方法" align="center" prop="method" width="140">
|
||||
<template #default="scope">
|
||||
{{ methodOptions.find((item) => item.value === scope.row.method)?.label }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="请求/响应数据"
|
||||
align="center"
|
||||
prop="params"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.reply">
|
||||
{{ `{"code":${scope.row.code},"msg":"${scope.row.msg}","data":${scope.row.data}\}` }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.params }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="mt-10px flex justify-end">
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getMessageList"
|
||||
/>
|
||||
</div>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { DeviceApi } from '@/api/iot/device/device'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import { IotDeviceMessageMethodEnum } from '@/views/iot/utils/constants'
|
||||
|
||||
const props = defineProps<{
|
||||
deviceId: number
|
||||
}>()
|
||||
|
||||
// 查询参数
|
||||
const queryParams = reactive({
|
||||
deviceId: props.deviceId,
|
||||
method: undefined,
|
||||
upstream: undefined,
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
|
||||
// 列表数据
|
||||
const loading = ref(false)
|
||||
const total = ref(0)
|
||||
const list = ref([])
|
||||
const autoRefresh = ref(false) // 自动刷新开关
|
||||
let autoRefreshTimer: any = null // 自动刷新定时器
|
||||
|
||||
// 消息方法选项
|
||||
const methodOptions = computed(() => {
|
||||
return Object.values(IotDeviceMessageMethodEnum).map((item) => ({
|
||||
label: item.name,
|
||||
value: item.method
|
||||
}))
|
||||
})
|
||||
|
||||
/** 查询消息列表 */
|
||||
const getMessageList = async () => {
|
||||
if (!props.deviceId) return
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await DeviceApi.getDeviceMessagePage(queryParams)
|
||||
total.value = data.total
|
||||
list.value = data.list
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getMessageList()
|
||||
}
|
||||
|
||||
/** 监听自动刷新 */
|
||||
watch(autoRefresh, (newValue) => {
|
||||
if (newValue) {
|
||||
autoRefreshTimer = setInterval(() => {
|
||||
getMessageList()
|
||||
}, 5000)
|
||||
} else {
|
||||
clearInterval(autoRefreshTimer)
|
||||
autoRefreshTimer = null
|
||||
}
|
||||
})
|
||||
|
||||
/** 监听设备标识变化 */
|
||||
watch(
|
||||
() => props.deviceId,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
handleQuery()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/** 组件卸载时清除定时器 */
|
||||
onBeforeUnmount(() => {
|
||||
if (autoRefreshTimer) {
|
||||
clearInterval(autoRefreshTimer)
|
||||
autoRefreshTimer = null
|
||||
}
|
||||
})
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
if (props.deviceId) {
|
||||
getMessageList()
|
||||
}
|
||||
})
|
||||
|
||||
/** 刷新消息列表 */
|
||||
const refresh = (delay = 0) => {
|
||||
if (delay > 0) {
|
||||
setTimeout(() => {
|
||||
handleQuery()
|
||||
}, delay)
|
||||
} else {
|
||||
handleQuery()
|
||||
}
|
||||
}
|
||||
|
||||
/** 暴露方法给父组件 */
|
||||
defineExpose({
|
||||
refresh
|
||||
})
|
||||
</script>
|
||||
@ -1,192 +0,0 @@
|
||||
<!-- 设备事件管理 -->
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item label="标识符" prop="identifier">
|
||||
<el-select
|
||||
v-model="queryParams.identifier"
|
||||
placeholder="请选择事件标识符"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="event in eventThingModels"
|
||||
:key="event.identifier"
|
||||
:label="`${event.name}(${event.identifier})`"
|
||||
:value="event.identifier!"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间范围" prop="times">
|
||||
<el-date-picker
|
||||
v-model="queryParams.times"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
|
||||
class="!w-360px"
|
||||
:shortcuts="defaultShortcuts"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" />
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" />
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<ContentWrap>
|
||||
<!-- 事件列表 -->
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="上报时间" align="center" prop="reportTime" width="180px">
|
||||
<template #default="scope">
|
||||
{{ scope.row.request?.reportTime ? formatDate(scope.row.request.reportTime) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标识符" align="center" prop="identifier" width="160px">
|
||||
<template #default="scope">
|
||||
<el-tag type="primary" size="small">
|
||||
{{ scope.row.request?.identifier }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="事件名称" align="center" prop="eventName" width="160px">
|
||||
<template #default="scope">
|
||||
{{ getEventName(scope.row.request?.identifier) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="事件类型" align="center" prop="eventType" width="100px">
|
||||
<template #default="scope">
|
||||
{{ getEventType(scope.row.request?.identifier) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="输入参数" align="center" prop="params">
|
||||
<template #default="scope"> {{ parseParams(scope.row.request.params) }} </template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DeviceApi } from '@/api/iot/device/device'
|
||||
import { ThingModelData } from '@/api/iot/thingmodel'
|
||||
import { formatDate, defaultShortcuts } from '@/utils/formatTime'
|
||||
import {
|
||||
getEventTypeLabel,
|
||||
IotDeviceMessageMethodEnum,
|
||||
IoTThingModelTypeEnum
|
||||
} from '@/views/iot/utils/constants'
|
||||
|
||||
const props = defineProps<{
|
||||
deviceId: number
|
||||
thingModelList: ThingModelData[]
|
||||
}>()
|
||||
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([] as any[]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
deviceId: props.deviceId,
|
||||
method: IotDeviceMessageMethodEnum.EVENT_POST.method, // 固定筛选事件消息
|
||||
identifier: '',
|
||||
times: [] as any[],
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
||||
/** 事件类型的物模型数据 */
|
||||
const eventThingModels = computed(() => {
|
||||
return props.thingModelList.filter(
|
||||
(item: ThingModelData) => item.type === IoTThingModelTypeEnum.EVENT
|
||||
)
|
||||
})
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
if (!props.deviceId) return
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await DeviceApi.getDeviceMessagePairPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.length
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields()
|
||||
queryParams.identifier = ''
|
||||
queryParams.times = []
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 获取事件名称 */
|
||||
const getEventName = (identifier: string | undefined) => {
|
||||
if (!identifier) return '-'
|
||||
const event = eventThingModels.value.find(
|
||||
(item: ThingModelData) => item.identifier === identifier
|
||||
)
|
||||
return event?.name || identifier
|
||||
}
|
||||
|
||||
/** 获取事件类型 */
|
||||
const getEventType = (identifier: string | undefined) => {
|
||||
if (!identifier) return '-'
|
||||
const event = eventThingModels.value.find(
|
||||
(item: ThingModelData) => item.identifier === identifier
|
||||
)
|
||||
if (!event?.event?.type) return '-'
|
||||
return getEventTypeLabel(event.event.type) || '-'
|
||||
}
|
||||
|
||||
/** 解析参数 */
|
||||
const parseParams = (params: string) => {
|
||||
try {
|
||||
const parsed = JSON.parse(params)
|
||||
if (parsed.params) {
|
||||
return parsed.params
|
||||
}
|
||||
return parsed
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
@ -1,208 +0,0 @@
|
||||
<!-- 设备服务调用 -->
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item label="标识符" prop="identifier">
|
||||
<el-select
|
||||
v-model="queryParams.identifier"
|
||||
placeholder="请选择服务标识符"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="service in serviceThingModels"
|
||||
:key="service.identifier"
|
||||
:label="`${service.name}(${service.identifier})`"
|
||||
:value="service.identifier!"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间范围" prop="times">
|
||||
<el-date-picker
|
||||
v-model="queryParams.times"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
|
||||
class="!w-360px"
|
||||
:shortcuts="defaultShortcuts"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" />
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" />
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<ContentWrap>
|
||||
<!-- 服务调用列表 -->
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="调用时间" align="center" prop="requestTime" width="180px">
|
||||
<template #default="scope">
|
||||
{{ scope.row.request?.reportTime ? formatDate(scope.row.request.reportTime) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="响应时间" align="center" prop="responseTime" width="180px">
|
||||
<template #default="scope">
|
||||
{{ scope.row.reply?.reportTime ? formatDate(scope.row.reply.reportTime) : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标识符" align="center" prop="identifier" width="160px">
|
||||
<template #default="scope">
|
||||
<el-tag type="primary" size="small">
|
||||
{{ scope.row.request?.identifier }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="服务名称" align="center" prop="serviceName" width="160px">
|
||||
<template #default="scope">
|
||||
{{ getServiceName(scope.row.request?.identifier) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="调用方式" align="center" prop="callType" width="100px">
|
||||
<template #default="scope">
|
||||
{{ getCallType(scope.row.request?.identifier) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="输入参数" align="center" prop="inputParams">
|
||||
<template #default="scope"> {{ parseParams(scope.row.request?.params) }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column label="输出参数" align="center" prop="outputParams">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.reply">
|
||||
{{
|
||||
`{"code":${scope.row.reply.code},"msg":"${scope.row.reply.msg}","data":${scope.row.reply.data}\}`
|
||||
}}
|
||||
</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DeviceApi } from '@/api/iot/device/device'
|
||||
import { ThingModelData } from '@/api/iot/thingmodel'
|
||||
import { formatDate, defaultShortcuts } from '@/utils/formatTime'
|
||||
import {
|
||||
getThingModelServiceCallTypeLabel,
|
||||
IotDeviceMessageMethodEnum,
|
||||
IoTThingModelTypeEnum
|
||||
} from '@/views/iot/utils/constants'
|
||||
|
||||
const props = defineProps<{
|
||||
deviceId: number
|
||||
thingModelList: ThingModelData[]
|
||||
}>()
|
||||
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([] as any[]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
deviceId: props.deviceId,
|
||||
method: IotDeviceMessageMethodEnum.SERVICE_INVOKE.method, // 固定筛选服务调用消息
|
||||
identifier: '',
|
||||
times: [] as any[],
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
||||
/** 服务类型的物模型数据 */
|
||||
const serviceThingModels = computed(() => {
|
||||
return props.thingModelList.filter(
|
||||
(item: ThingModelData) => item.type === IoTThingModelTypeEnum.SERVICE
|
||||
)
|
||||
})
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
if (!props.deviceId) return
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await DeviceApi.getDeviceMessagePairPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.length
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields()
|
||||
queryParams.identifier = ''
|
||||
queryParams.times = []
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 获取服务名称 */
|
||||
const getServiceName = (identifier: string | undefined) => {
|
||||
if (!identifier) return '-'
|
||||
const service = serviceThingModels.value.find(
|
||||
(item: ThingModelData) => item.identifier === identifier
|
||||
)
|
||||
return service?.name || identifier
|
||||
}
|
||||
|
||||
/** 获取调用方式 */
|
||||
const getCallType = (identifier: string | undefined) => {
|
||||
if (!identifier) return '-'
|
||||
const service = serviceThingModels.value.find(
|
||||
(item: ThingModelData) => item.identifier === identifier
|
||||
)
|
||||
if (!service?.service?.callType) return '-'
|
||||
return getThingModelServiceCallTypeLabel(service.service.callType) || '-'
|
||||
}
|
||||
|
||||
/** 解析参数 */
|
||||
const parseParams = (params: string) => {
|
||||
if (!params) return '-'
|
||||
try {
|
||||
const parsed = JSON.parse(params)
|
||||
if (parsed.params) {
|
||||
return JSON.stringify(parsed.params, null, 2)
|
||||
}
|
||||
return JSON.stringify(parsed, null, 2)
|
||||
} catch (error) {
|
||||
return params
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
@ -1,292 +0,0 @@
|
||||
<!-- Modbus 配置 -->
|
||||
<template>
|
||||
<div>
|
||||
<!-- 连接配置区域 -->
|
||||
<ContentWrap>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="text-lg font-medium">连接配置</span>
|
||||
<el-button type="primary" @click="handleEditConfig" v-hasPermi="['iot:device:create']">
|
||||
编辑
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 详情展示 -->
|
||||
<el-descriptions :column="3" border direction="horizontal">
|
||||
<!-- Client 模式专有字段 -->
|
||||
<template v-if="isClient">
|
||||
<el-descriptions-item label="IP 地址">
|
||||
{{ modbusConfig.ip || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="端口">
|
||||
{{ modbusConfig.port || '-' }}
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
<!-- 公共字段 -->
|
||||
<el-descriptions-item label="从站地址">
|
||||
{{ modbusConfig.slaveId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<!-- Client 模式专有字段 -->
|
||||
<template v-if="isClient">
|
||||
<el-descriptions-item label="连接超时">
|
||||
{{ modbusConfig.timeout ? `${modbusConfig.timeout} ms` : '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="重试间隔">
|
||||
{{ modbusConfig.retryInterval ? `${modbusConfig.retryInterval} ms` : '-' }}
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
<!-- Server 模式专有字段 -->
|
||||
<template v-if="isServer">
|
||||
<el-descriptions-item label="工作模式">
|
||||
<dict-tag :type="DICT_TYPE.IOT_MODBUS_MODE" :value="modbusConfig.mode" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="帧格式">
|
||||
<dict-tag :type="DICT_TYPE.IOT_MODBUS_FRAME_FORMAT" :value="modbusConfig.frameFormat" />
|
||||
</el-descriptions-item>
|
||||
</template>
|
||||
<!-- 公共字段 -->
|
||||
<el-descriptions-item label="状态">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="modbusConfig.status" />
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 点位配置区域 -->
|
||||
<ContentWrap class="mt-4">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span class="text-lg font-medium">点位配置</span>
|
||||
<el-button type="primary" @click="handleAddPoint" v-hasPermi="['iot:device:create']">
|
||||
<Icon icon="ep:plus" class="mr-1" />
|
||||
新增点位
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<el-form :model="queryParams" :inline="true" class="-mb-15px">
|
||||
<el-form-item label="属性名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入属性名称"
|
||||
clearable
|
||||
class="!w-200px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="标识符" prop="identifier">
|
||||
<el-input
|
||||
v-model="queryParams.identifier"
|
||||
placeholder="请输入标识符"
|
||||
clearable
|
||||
class="!w-200px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" />
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" />
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 点位列表 -->
|
||||
<el-table v-loading="pointLoading" :data="pointList" :stripe="true" class="mt-4">
|
||||
<el-table-column label="属性名称" align="center" prop="name" min-width="100" />
|
||||
<el-table-column label="标识符" align="center" prop="identifier" min-width="100">
|
||||
<template #default="scope">
|
||||
<el-tag size="small" type="primary">{{ scope.row.identifier }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="功能码" align="center" prop="functionCode" min-width="140">
|
||||
<template #default="scope">
|
||||
{{ formatFunctionCode(scope.row.functionCode) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="寄存器地址" align="center" prop="registerAddress" min-width="100">
|
||||
<template #default="scope">
|
||||
{{ formatRegisterAddress(scope.row.registerAddress) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="寄存器数量" align="center" prop="registerCount" min-width="90" />
|
||||
<el-table-column label="数据类型" align="center" prop="rawDataType" min-width="90">
|
||||
<template #default="scope">
|
||||
<el-tag size="small" type="info">{{ scope.row.rawDataType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="字节序" align="center" prop="byteOrder" min-width="80" />
|
||||
<el-table-column label="缩放因子" align="center" prop="scale" min-width="80" />
|
||||
<el-table-column label="轮询间隔" align="center" prop="pollInterval" min-width="90">
|
||||
<template #default="scope"> {{ scope.row.pollInterval }} ms </template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status" min-width="80">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right" width="120">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleEditPoint(scope.row)"
|
||||
v-hasPermi="['iot:device:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDeletePoint(scope.row.id, scope.row.name)"
|
||||
v-hasPermi="['iot:device:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getPointPage"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 连接配置弹窗 -->
|
||||
<DeviceModbusConfigForm
|
||||
ref="configFormRef"
|
||||
:device-id="device.id"
|
||||
:protocol-type="product.protocolType"
|
||||
@success="getModbusConfig"
|
||||
/>
|
||||
|
||||
<!-- 点位表单弹窗 -->
|
||||
<DeviceModbusPointForm
|
||||
ref="pointFormRef"
|
||||
:device-id="device.id"
|
||||
:thing-model-list="thingModelList"
|
||||
@success="getPointPage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { DeviceVO } from '@/api/iot/device/device'
|
||||
import { ProductVO, ProtocolTypeEnum } from '@/api/iot/product/product'
|
||||
import { ThingModelData } from '@/api/iot/thingmodel'
|
||||
import { DeviceModbusConfigApi, DeviceModbusConfigVO } from '@/api/iot/device/modbus/config'
|
||||
import { DeviceModbusPointApi, DeviceModbusPointVO } from '@/api/iot/device/modbus/point'
|
||||
import { ModbusFunctionCodeOptions } from '@/views/iot/utils/constants'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import DeviceModbusConfigForm from './DeviceModbusConfigForm.vue'
|
||||
import DeviceModbusPointForm from './DeviceModbusPointForm.vue'
|
||||
|
||||
defineOptions({ name: 'DeviceModbusConfig' })
|
||||
|
||||
const props = defineProps<{
|
||||
device: DeviceVO
|
||||
product: ProductVO
|
||||
thingModelList: ThingModelData[]
|
||||
}>()
|
||||
|
||||
const message = useMessage()
|
||||
|
||||
// ======================= 连接配置 =======================
|
||||
const isClient = computed(() => props.product.protocolType === ProtocolTypeEnum.MODBUS_TCP_CLIENT) // 是否为 Client 模式
|
||||
const isServer = computed(() => props.product.protocolType === ProtocolTypeEnum.MODBUS_TCP_SERVER) // 是否为 Server 模式
|
||||
const modbusConfig = ref<DeviceModbusConfigVO>({} as DeviceModbusConfigVO)
|
||||
|
||||
/** 获取连接配置 */
|
||||
const getModbusConfig = async () => {
|
||||
modbusConfig.value = await DeviceModbusConfigApi.getModbusConfig(props.device.id)
|
||||
}
|
||||
|
||||
/** 编辑连接配置 */
|
||||
const configFormRef = ref()
|
||||
const handleEditConfig = () => {
|
||||
configFormRef.value?.open(modbusConfig.value)
|
||||
}
|
||||
|
||||
// ======================= 点位配置 =======================
|
||||
const pointLoading = ref(false)
|
||||
const pointList = ref<DeviceModbusPointVO[]>([])
|
||||
const total = ref(0)
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
deviceId: props.device.id,
|
||||
name: undefined as string | undefined,
|
||||
identifier: undefined as string | undefined
|
||||
})
|
||||
|
||||
/** 获取点位分页 */
|
||||
const getPointPage = async () => {
|
||||
pointLoading.value = true
|
||||
try {
|
||||
const data = await DeviceModbusPointApi.getModbusPointPage(queryParams)
|
||||
pointList.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
pointLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getPointPage()
|
||||
}
|
||||
|
||||
/** 重置搜索 */
|
||||
const resetQuery = () => {
|
||||
queryParams.name = undefined
|
||||
queryParams.identifier = undefined
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 格式化功能码 */
|
||||
const formatFunctionCode = (code: number) => {
|
||||
const option = ModbusFunctionCodeOptions.find((item) => item.value === code)
|
||||
return option ? option.label : `${code}`
|
||||
}
|
||||
|
||||
/** 格式化寄存器地址为十六进制 */
|
||||
const formatRegisterAddress = (address: number) => {
|
||||
return '0x' + address.toString(16).toUpperCase().padStart(4, '0')
|
||||
}
|
||||
|
||||
/** 新增点位 */
|
||||
const pointFormRef = ref()
|
||||
const handleAddPoint = () => {
|
||||
pointFormRef.value?.open('create')
|
||||
}
|
||||
|
||||
/** 编辑点位 */
|
||||
const handleEditPoint = (row: DeviceModbusPointVO) => {
|
||||
pointFormRef.value?.open('update', row.id)
|
||||
}
|
||||
|
||||
/** 删除点位 */
|
||||
const handleDeletePoint = async (id: number, name: string) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm('确定要删除点位【' + name + '】吗?')
|
||||
// 发起删除
|
||||
await DeviceModbusPointApi.deleteModbusPoint(id)
|
||||
message.success('删除成功')
|
||||
// 刷新列表
|
||||
await getPointPage()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await getModbusConfig()
|
||||
await getPointPage()
|
||||
})
|
||||
</script>
|
||||
@ -1,132 +0,0 @@
|
||||
<template>
|
||||
<DeviceDetailsHeader
|
||||
:loading="loading"
|
||||
:product="product"
|
||||
:device="device"
|
||||
@refresh="getDeviceData"
|
||||
/>
|
||||
<el-col>
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="设备信息" name="info">
|
||||
<DeviceDetailsInfo v-if="activeTab === 'info'" :product="product" :device="device" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="物模型数据" name="model">
|
||||
<DeviceDetailsThingModel
|
||||
v-if="activeTab === 'model'"
|
||||
:device-id="device.id"
|
||||
:thing-model-list="thingModelList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
label="子设备管理"
|
||||
name="subDevice"
|
||||
v-if="product.deviceType === DeviceTypeEnum.GATEWAY"
|
||||
>
|
||||
<DeviceDetailsSubDevice v-if="activeTab === 'subDevice'" :gateway-id="device.id" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="设备消息" name="log">
|
||||
<DeviceDetailsMessage v-if="activeTab === 'log'" :device-id="device.id" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="模拟设备" name="simulator">
|
||||
<DeviceDetailsSimulator
|
||||
v-if="activeTab === 'simulator'"
|
||||
:product="product"
|
||||
:device="device"
|
||||
:thing-model-list="thingModelList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="设备配置" name="config">
|
||||
<DeviceDetailConfig
|
||||
v-if="activeTab === 'config'"
|
||||
:device="device"
|
||||
@success="getDeviceData"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
label="Modbus 配置"
|
||||
name="modbus"
|
||||
v-if="
|
||||
[ProtocolTypeEnum.MODBUS_TCP_CLIENT, ProtocolTypeEnum.MODBUS_TCP_SERVER].includes(
|
||||
product.protocolType as ProtocolTypeEnum
|
||||
)
|
||||
"
|
||||
>
|
||||
<DeviceModbusConfig
|
||||
v-if="activeTab === 'modbus'"
|
||||
:device="device"
|
||||
:product="product"
|
||||
:thing-model-list="thingModelList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||
import { DeviceApi, DeviceVO } from '@/api/iot/device/device'
|
||||
import { DeviceTypeEnum, ProductApi, ProductVO, ProtocolTypeEnum } from '@/api/iot/product/product'
|
||||
import { ThingModelApi, ThingModelData } from '@/api/iot/thingmodel'
|
||||
import DeviceDetailsHeader from './DeviceDetailsHeader.vue'
|
||||
import DeviceDetailsInfo from './DeviceDetailsInfo.vue'
|
||||
import DeviceDetailsThingModel from './DeviceDetailsThingModel.vue'
|
||||
import DeviceDetailsMessage from './DeviceDetailsMessage.vue'
|
||||
import DeviceDetailsSimulator from './DeviceDetailsSimulator.vue'
|
||||
import DeviceDetailConfig from './DeviceDetailConfig.vue'
|
||||
import DeviceModbusConfig from './DeviceModbusConfig.vue'
|
||||
import DeviceDetailsSubDevice from './DeviceDetailsSubDevice.vue'
|
||||
|
||||
defineOptions({ name: 'IoTDeviceDetail' })
|
||||
|
||||
const route = useRoute()
|
||||
const message = useMessage()
|
||||
const id = Number(route.params.id) // 将字符串转换为数字
|
||||
const loading = ref(true) // 加载中
|
||||
const product = ref<ProductVO>({} as ProductVO) // 产品详情
|
||||
const device = ref<DeviceVO>({} as DeviceVO) // 设备详情
|
||||
const activeTab = ref('info') // 默认激活的标签页
|
||||
const thingModelList = ref<ThingModelData[]>([]) // 物模型列表数据
|
||||
|
||||
/** 获取设备详情 */
|
||||
const getDeviceData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
device.value = await DeviceApi.getDevice(id)
|
||||
await getProductData(device.value.productId)
|
||||
await getThingModelList(device.value.productId)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取产品详情 */
|
||||
const getProductData = async (id: number) => {
|
||||
product.value = await ProductApi.getProduct(id)
|
||||
}
|
||||
|
||||
/** 获取物模型列表 */
|
||||
const getThingModelList = async (productId: number) => {
|
||||
try {
|
||||
const data = await ThingModelApi.getThingModelList({
|
||||
productId: productId
|
||||
})
|
||||
thingModelList.value = data || []
|
||||
} catch (error) {
|
||||
console.error('获取物模型列表失败:', error)
|
||||
thingModelList.value = []
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
const { delView } = useTagsViewStore() // 视图操作
|
||||
const router = useRouter() // 路由
|
||||
const { currentRoute } = router
|
||||
onMounted(async () => {
|
||||
if (!id) {
|
||||
message.warning('参数错误,产品不能为空!')
|
||||
delView(unref(currentRoute))
|
||||
return
|
||||
}
|
||||
await getDeviceData()
|
||||
activeTab.value = (route.query.tab as string) || 'info'
|
||||
})
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue