diff --git a/.env b/.env index 0f9c97e2..5a7a24a2 100644 --- a/.env +++ b/.env @@ -34,4 +34,4 @@ VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883 # VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ== # 百度地图 -VITE_BAIDU_MAP_KEY = 'efHIw2qmH8RzHPxK0z0rbCgzDVLup9LD' \ No newline at end of file +VITE_BAIDU_MAP_KEY = 'Y2aJXiswwPxy6mwFs1z9c7U5gwX9WfUN' \ No newline at end of file diff --git a/src/api/iot/device/device/index.ts b/src/api/iot/device/device/index.ts index 2311a9a6..1804628c 100644 --- a/src/api/iot/device/device/index.ts +++ b/src/api/iot/device/device/index.ts @@ -5,6 +5,7 @@ export interface DeviceVO { id: number // 设备 ID,主键,自增 deviceName: string // 设备名称 productId: number // 产品编号 + productName?: string // 产品名称(只有部分接口返回,例如 getDeviceLocationList) productKey: string // 产品标识 deviceType: number // 设备类型 nickname: string // 设备备注名称 @@ -21,7 +22,6 @@ export interface DeviceVO { mqttUsername: string // MQTT 用户名 mqttPassword: string // MQTT 密码 authType: string // 认证类型 - locationType: number // 定位类型 latitude?: number // 设备位置的纬度 longitude?: number // 设备位置的经度 areaId: number // 地区编码 @@ -49,14 +49,6 @@ export interface IotDevicePropertyRespVO { updateTime: Date // 更新时间 } -// TODO @芋艿:调整到 constants -// IoT 设备状态枚举 -export enum DeviceStateEnum { - INACTIVE = 0, // 未激活 - ONLINE = 1, // 在线 - OFFLINE = 2 // 离线 -} - // 设备认证参数 VO export interface IotDeviceAuthInfoVO { clientId: string // 客户端 ID @@ -123,6 +115,11 @@ export const DeviceApi = { return await request.get({ url: `/iot/device/simple-list?`, params: { deviceType, productId } }) }, + // 获取设备位置列表(用于地图展示) + getDeviceLocationList: async () => { + return await request.get({ url: `/iot/device/location-list` }) + }, + // 根据产品编号,获取设备的精简信息列表 getDeviceListByProductId: async (productId: number) => { return await request.get({ url: `/iot/device/simple-list?`, params: { productId } }) diff --git a/src/api/iot/product/product/index.ts b/src/api/iot/product/product/index.ts index c9f273eb..a34efaeb 100644 --- a/src/api/iot/product/product/index.ts +++ b/src/api/iot/product/product/index.ts @@ -13,7 +13,6 @@ export interface ProductVO { description: string // 产品描述 status: number // 产品状态 deviceType: number // 设备类型 - locationType: number // 设备类型 netType: number // 联网方式 codecType: string // 数据格式(编解码器类型) deviceCount: number // 设备数量 @@ -26,12 +25,6 @@ export enum DeviceTypeEnum { GATEWAY_SUB = 1, // 网关子设备 GATEWAY = 2 // 网关设备 } -// IOT 产品定位类型枚举类 0: 手动定位, 1: IP 定位, 2: 定位模块定位 -export enum LocationTypeEnum { - IP = 1, // IP 定位 - MODULE = 2, // 设备定位 - MANUAL = 3 // 手动定位 -} // IOT 数据格式(编解码器类型)枚举类 export enum CodecTypeEnum { ALINK = 'Alink' // 阿里云 Alink 协议 diff --git a/src/api/iot/rule/data/sink/index.ts b/src/api/iot/rule/data/sink/index.ts index 3e2755e0..31a2659a 100644 --- a/src/api/iot/rule/data/sink/index.ts +++ b/src/api/iot/rule/data/sink/index.ts @@ -10,6 +10,8 @@ export interface DataSinkVO { type?: number // 桥梁类型 config?: | HttpConfig + | TcpConfig + | WebSocketConfig | MqttConfig | RocketMQConfig | KafkaMQConfig @@ -30,6 +32,38 @@ export interface HttpConfig extends Config { body: string } +/** TCP 配置 */ +export interface TcpConfig extends Config { + host: string + port: number + connectTimeoutMs: number + readTimeoutMs: number + ssl: boolean + sslCertPath: string + dataFormat: string + heartbeatIntervalMs: number + reconnectIntervalMs: number + maxReconnectAttempts: number +} + +/** WebSocket 配置 */ +export interface WebSocketConfig extends Config { + serverUrl: string + connectTimeoutMs: number + sendTimeoutMs: number + heartbeatIntervalMs: number + heartbeatMessage: string + subprotocols: string + customHeaders: string + verifySslCert: boolean + dataFormat: string + reconnectIntervalMs: number + maxReconnectAttempts: number + enableCompression: boolean + sendRetryCount: number + sendRetryIntervalMs: number +} + /** MQTT 配置 */ export interface MqttConfig extends Config { url: string diff --git a/src/api/iot/statistics/index.ts b/src/api/iot/statistics/index.ts index cdcb94d2..30360785 100644 --- a/src/api/iot/statistics/index.ts +++ b/src/api/iot/statistics/index.ts @@ -16,18 +16,6 @@ export interface IotStatisticsSummaryRespVO { productCategoryDeviceCounts: Record } -/** 时间戳-数值的键值对类型 */ -interface TimeValueItem { - [key: string]: number -} - -/** IoT 消息统计数据类型 */ -export interface IotStatisticsDeviceMessageSummaryRespVO { - statType: number - upstreamCounts: TimeValueItem[] - downstreamCounts: TimeValueItem[] -} - /** 新的消息统计数据项 */ export interface IotStatisticsDeviceMessageSummaryByDateRespVO { time: string @@ -41,6 +29,17 @@ export interface IotStatisticsDeviceMessageReqVO { times?: string[] } +/** 设备位置数据 VO */ +export interface DeviceLocationRespVO { + id: number + deviceName: string + nickname?: string + productName?: string + state: number + longitude: number + latitude: number +} + // IoT 数据统计 API export const StatisticsApi = { // 查询全局的数据统计 diff --git a/src/components/Map/index.ts b/src/components/Map/index.ts new file mode 100644 index 00000000..3ac8c7bc --- /dev/null +++ b/src/components/Map/index.ts @@ -0,0 +1,4 @@ +import MapDialog from './src/MapDialog.vue' +export { loadBaiduMapSdk } from './src/utils' + +export { MapDialog } diff --git a/src/components/Map/index.vue b/src/components/Map/index.vue deleted file mode 100644 index 86010b26..00000000 --- a/src/components/Map/index.vue +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - - diff --git a/src/components/Map/src/MapDialog.vue b/src/components/Map/src/MapDialog.vue new file mode 100644 index 00000000..9b6ecdce --- /dev/null +++ b/src/components/Map/src/MapDialog.vue @@ -0,0 +1,259 @@ + + + + diff --git a/src/components/Map/src/utils.ts b/src/components/Map/src/utils.ts new file mode 100644 index 00000000..23fa2936 --- /dev/null +++ b/src/components/Map/src/utils.ts @@ -0,0 +1,62 @@ +/** + * 百度地图 SDK 加载工具 + */ + +// 扩展 Window 接口以包含百度地图 GL API +declare global { + interface Window { + BMapGL: any + } +} + +// 全局回调名称 +const CALLBACK_NAME = '__BAIDU_MAP_LOAD_CALLBACK__' + +// SDK 加载状态 +let loadPromise: Promise | null = null + +/** + * 加载百度地图 GL SDK + * @param timeout 超时时间(毫秒),默认 10000 + * @returns Promise + */ +export const loadBaiduMapSdk = (timeout = 10000): Promise => { + // 已加载完成 + if (window.BMapGL) { + return Promise.resolve() + } + + // 正在加载中,返回同一个 Promise + if (loadPromise) { + return loadPromise + } + + loadPromise = new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + loadPromise = null + reject(new Error('百度地图 SDK 加载超时')) + }, timeout) + + // 全局回调 + ;(window as any)[CALLBACK_NAME] = () => { + clearTimeout(timeoutId) + delete (window as any)[CALLBACK_NAME] + resolve() + } + + // 创建 script 标签 + const script = document.createElement('script') + script.src = `https://api.map.baidu.com/api?v=1.0&type=webgl&ak=${ + import.meta.env.VITE_BAIDU_MAP_KEY + }&callback=${CALLBACK_NAME}` + script.onerror = () => { + clearTimeout(timeoutId) + loadPromise = null + delete (window as any)[CALLBACK_NAME] + reject(new Error('百度地图 SDK 加载失败')) + } + document.body.appendChild(script) + }) + + return loadPromise +} diff --git a/src/views/iot/device/device/DeviceForm.vue b/src/views/iot/device/device/DeviceForm.vue index dfed0c63..0ddbf2af 100644 --- a/src/views/iot/device/device/DeviceForm.vue +++ b/src/views/iot/device/device/DeviceForm.vue @@ -66,44 +66,17 @@ - - - - {{ dict.label }} - - - - - + @@ -112,14 +85,15 @@ 取 消 + + diff --git a/src/views/iot/device/device/detail/DeviceDetailsInfo.vue b/src/views/iot/device/device/detail/DeviceDetailsInfo.vue index e3beda75..b03c0d3e 100644 --- a/src/views/iot/device/device/detail/DeviceDetailsInfo.vue +++ b/src/views/iot/device/device/detail/DeviceDetailsInfo.vue @@ -2,83 +2,45 @@ diff --git a/src/views/iot/rule/data/sink/config/WebSocketConfigForm.vue b/src/views/iot/rule/data/sink/config/WebSocketConfigForm.vue new file mode 100644 index 00000000..0da9034b --- /dev/null +++ b/src/views/iot/rule/data/sink/config/WebSocketConfigForm.vue @@ -0,0 +1,117 @@ + + diff --git a/src/views/iot/rule/data/sink/config/index.ts b/src/views/iot/rule/data/sink/config/index.ts index b3927dc9..f04808f5 100644 --- a/src/views/iot/rule/data/sink/config/index.ts +++ b/src/views/iot/rule/data/sink/config/index.ts @@ -1,4 +1,6 @@ import HttpConfigForm from './HttpConfigForm.vue' +import TcpConfigForm from './TcpConfigForm.vue' +import WebSocketConfigForm from './WebSocketConfigForm.vue' import MqttConfigForm from './MqttConfigForm.vue' import RocketMQConfigForm from './RocketMQConfigForm.vue' import KafkaMQConfigForm from './KafkaMQConfigForm.vue' @@ -7,6 +9,8 @@ import RedisStreamConfigForm from './RedisStreamConfigForm.vue' export { HttpConfigForm, + TcpConfigForm, + WebSocketConfigForm, MqttConfigForm, RocketMQConfigForm, KafkaMQConfigForm, diff --git a/src/views/iot/utils/constants.ts b/src/views/iot/utils/constants.ts index fe6db188..f25bb7de 100644 --- a/src/views/iot/utils/constants.ts +++ b/src/views/iot/utils/constants.ts @@ -5,6 +5,13 @@ export const IOT_PROVIDE_KEY = { PRODUCT: 'IOT_PRODUCT' } +/** IoT 设备状态枚举 */ +export enum DeviceStateEnum { + INACTIVE = 0, // 未激活 + ONLINE = 1, // 在线 + OFFLINE = 2 // 离线 +} + /** IoT 产品物模型类型枚举类 */ export const IoTThingModelTypeEnum = { PROPERTY: 1, // 属性