|
@@ -1,6 +1,5 @@
|
|
<template>
|
|
<template>
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
- <!-- TODO @super:建议每个 tab 做成一个小的组件。命名为了排版整齐点,可以叫 DeviceDetailsSimulatorPropertyUpstream、DeviceDetailsSimulatorEventUpstream -->
|
|
|
|
<el-row :gutter="20">
|
|
<el-row :gutter="20">
|
|
<!-- 左侧指令调试区域 -->
|
|
<!-- 左侧指令调试区域 -->
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
@@ -17,6 +16,7 @@
|
|
:show-overflow-tooltip="true"
|
|
:show-overflow-tooltip="true"
|
|
:stripe="true"
|
|
:stripe="true"
|
|
>
|
|
>
|
|
|
|
+ <!-- TODO @super:每个 colum 搞下宽度,避免 table 每一列最后有个 . -->
|
|
<el-table-column align="center" label="功能名称" prop="name" />
|
|
<el-table-column align="center" label="功能名称" prop="name" />
|
|
<el-table-column align="center" label="标识符" prop="identifier" />
|
|
<el-table-column align="center" label="标识符" prop="identifier" />
|
|
<el-table-column align="center" label="数据类型" prop="identifier">
|
|
<el-table-column align="center" label="数据类型" prop="identifier">
|
|
@@ -38,9 +38,8 @@
|
|
].includes(row.property.dataType)
|
|
].includes(row.property.dataType)
|
|
"
|
|
"
|
|
>
|
|
>
|
|
- 取值范围:{{
|
|
|
|
- `${row.property.dataSpecs.min}~${row.property.dataSpecs.max}`
|
|
|
|
- }}
|
|
|
|
|
|
+ 取值范围:
|
|
|
|
+ {{ `${row.property.dataSpecs.min}~${row.property.dataSpecs.max}` }}
|
|
</div>
|
|
</div>
|
|
<!-- 非列表型:文本 -->
|
|
<!-- 非列表型:文本 -->
|
|
<div v-if="DataSpecsDataType.TEXT === row.property.dataType">
|
|
<div v-if="DataSpecsDataType.TEXT === row.property.dataType">
|
|
@@ -95,12 +94,19 @@
|
|
</el-table-column>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-table>
|
|
<div class="mt-10px">
|
|
<div class="mt-10px">
|
|
- <el-button type="primary" @click="handlePropertyReport">发送</el-button>
|
|
|
|
|
|
+ <el-button
|
|
|
|
+ type="primary"
|
|
|
|
+ @click="handlePropertyReport"
|
|
|
|
+ v-hasPermi="['iot:device:simulation-report']"
|
|
|
|
+ >
|
|
|
|
+ 发送
|
|
|
|
+ </el-button>
|
|
</div>
|
|
</div>
|
|
</ContentWrap>
|
|
</ContentWrap>
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
<!-- 事件上报 -->
|
|
<!-- 事件上报 -->
|
|
|
|
+ <!-- TODO @super:待实现 -->
|
|
<el-tab-pane label="事件上报" name="event">
|
|
<el-tab-pane label="事件上报" name="event">
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
<!-- <el-table v-loading="loading" :data="eventList" :stripe="true">
|
|
<!-- <el-table v-loading="loading" :data="eventList" :stripe="true">
|
|
@@ -129,12 +135,12 @@
|
|
<el-tab-pane label="状态变更" name="status">
|
|
<el-tab-pane label="状态变更" name="status">
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
<div class="flex gap-4">
|
|
<div class="flex gap-4">
|
|
- <el-button type="primary" @click="handleDeviceState('online')"
|
|
|
|
- >设备上线</el-button
|
|
|
|
- >
|
|
|
|
- <el-button type="primary" @click="handleDeviceState('offline')"
|
|
|
|
- >设备下线</el-button
|
|
|
|
- >
|
|
|
|
|
|
+ <el-button type="primary" @click="handleDeviceState('online')">
|
|
|
|
+ 设备上线
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button type="primary" @click="handleDeviceState('offline')">
|
|
|
|
+ 设备下线
|
|
|
|
+ </el-button>
|
|
</div>
|
|
</div>
|
|
</ContentWrap>
|
|
</ContentWrap>
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
@@ -142,6 +148,7 @@
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
<!-- 下行指令调试 -->
|
|
<!-- 下行指令调试 -->
|
|
|
|
+ <!-- TODO @super:待实现 -->
|
|
<el-tab-pane label="下行指令调试" name="down">
|
|
<el-tab-pane label="下行指令调试" name="down">
|
|
<el-tabs v-model="subTab" v-if="activeTab === 'down'">
|
|
<el-tabs v-model="subTab" v-if="activeTab === 'down'">
|
|
<!-- 属性调试 -->
|
|
<!-- 属性调试 -->
|
|
@@ -170,6 +177,7 @@
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
|
|
|
|
<!-- 服务调用 -->
|
|
<!-- 服务调用 -->
|
|
|
|
+ <!-- TODO @super:待实现 -->
|
|
<el-tab-pane label="服务调用" name="service">
|
|
<el-tab-pane label="服务调用" name="service">
|
|
<ContentWrap>
|
|
<ContentWrap>
|
|
<!-- 服务调用相关内容 -->
|
|
<!-- 服务调用相关内容 -->
|
|
@@ -184,7 +192,7 @@
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
<el-tabs type="border-card">
|
|
<el-tabs type="border-card">
|
|
<el-tab-pane label="设备日志">
|
|
<el-tab-pane label="设备日志">
|
|
- <DeviceDetailsLog :deviceKey="device.deviceKey" />
|
|
|
|
|
|
+ <DeviceDetailsLog :device-key="device.deviceKey" />
|
|
</el-tab-pane>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</el-tabs>
|
|
</el-col>
|
|
</el-col>
|
|
@@ -195,7 +203,7 @@
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
import { ProductVO } from '@/api/iot/product/product'
|
|
import { ProductVO } from '@/api/iot/product/product'
|
|
import { ThingModelApi, SimulatorData } from '@/api/iot/thingmodel'
|
|
import { ThingModelApi, SimulatorData } from '@/api/iot/thingmodel'
|
|
-import { DeviceApi, DeviceVO, SimulatorDataVO } from '@/api/iot/device/device'
|
|
|
|
|
|
+import { DeviceApi, DeviceVO } from '@/api/iot/device/device'
|
|
import DeviceDetailsLog from './DeviceDetailsLog.vue'
|
|
import DeviceDetailsLog from './DeviceDetailsLog.vue'
|
|
import {
|
|
import {
|
|
DataSpecsDataType,
|
|
DataSpecsDataType,
|
|
@@ -205,26 +213,33 @@ import {
|
|
ThingModelType
|
|
ThingModelType
|
|
} from '@/views/iot/thingmodel/config'
|
|
} from '@/views/iot/thingmodel/config'
|
|
|
|
|
|
|
|
+const props = defineProps<{
|
|
|
|
+ product: ProductVO
|
|
|
|
+ device: DeviceVO
|
|
|
|
+}>()
|
|
|
|
+
|
|
const message = useMessage() // 消息弹窗
|
|
const message = useMessage() // 消息弹窗
|
|
-const loading = ref(false)
|
|
|
|
-const activeTab = ref('up')
|
|
|
|
-const subTab = ref('property')
|
|
|
|
|
|
+const activeTab = ref('up') // TODO @super:upstream 上行、downstream 下行
|
|
|
|
+const subTab = ref('property') // TODO @super:upstreamTab
|
|
|
|
|
|
|
|
+const loading = ref(false)
|
|
const queryParams = reactive({
|
|
const queryParams = reactive({
|
|
- type: undefined,
|
|
|
|
|
|
+ type: undefined, // TODO @super:type 默认给个第一个 tab 对应的,避免下面 watch 爆红
|
|
productId: -1
|
|
productId: -1
|
|
})
|
|
})
|
|
|
|
+const list = ref<SimulatorData[]>([]) // 物模型列表的数据 TODO @super:thingModelList
|
|
|
|
+// TODO @super:dataTypeOptionsLabel 是不是不用定义,直接用 getDataTypeOptionsLabel 在 template 中使用即可?
|
|
const dataTypeOptionsLabel = computed(() => (value: string) => getDataTypeOptionsLabel(value)) // 解析数据类型
|
|
const dataTypeOptionsLabel = computed(() => (value: string) => getDataTypeOptionsLabel(value)) // 解析数据类型
|
|
-const props = defineProps<{ product: ProductVO; device: DeviceVO }>()
|
|
|
|
-const list = ref<SimulatorData[]>([]) // 物模型列表的数据
|
|
|
|
|
|
|
|
-/** 查询列表 */
|
|
|
|
|
|
+/** 查询物模型列表 */
|
|
|
|
+// TODO @super:getThingModelList 更精准
|
|
const getList = async () => {
|
|
const getList = async () => {
|
|
loading.value = true
|
|
loading.value = true
|
|
try {
|
|
try {
|
|
queryParams.productId = props.product?.id || -1
|
|
queryParams.productId = props.product?.id || -1
|
|
const data = await ThingModelApi.getThingModelList(queryParams)
|
|
const data = await ThingModelApi.getThingModelList(queryParams)
|
|
// 转换数据,添加 simulateValue 字段
|
|
// 转换数据,添加 simulateValue 字段
|
|
|
|
+ // TODO @super:貌似下面的 simulateValue 不设置也可以?
|
|
list.value = data.map((item) => ({
|
|
list.value = data.map((item) => ({
|
|
...item,
|
|
...item,
|
|
simulateValue: ''
|
|
simulateValue: ''
|
|
@@ -262,7 +277,8 @@ const getList = async () => {
|
|
// }))
|
|
// }))
|
|
// })
|
|
// })
|
|
|
|
|
|
-// 监听标签页变化 todo:后续改成查询字典
|
|
|
|
|
|
+/** 监听标签页变化 */
|
|
|
|
+// todo:后续改成查询字典
|
|
watch(
|
|
watch(
|
|
[activeTab, subTab],
|
|
[activeTab, subTab],
|
|
([newActiveTab, newSubTab]) => {
|
|
([newActiveTab, newSubTab]) => {
|
|
@@ -294,36 +310,26 @@ watch(
|
|
{ immediate: true }
|
|
{ immediate: true }
|
|
)
|
|
)
|
|
|
|
|
|
-// interface ReportData {
|
|
|
|
-// productKey: string
|
|
|
|
-// deviceKey: string
|
|
|
|
-// type: string
|
|
|
|
-// subType: string
|
|
|
|
-// reportTime: string
|
|
|
|
-// content: string // 改为 string 类型,存储 JSON 字符串
|
|
|
|
-// }
|
|
|
|
-
|
|
|
|
-// 处理属性上报 TODO:数据类型效验
|
|
|
|
|
|
+/** 处理属性上报 */
|
|
const handlePropertyReport = async () => {
|
|
const handlePropertyReport = async () => {
|
|
- const contentObj: Record<string, any> = {}
|
|
|
|
|
|
+ // TODO @super:数据类型效验
|
|
|
|
+ const data: Record<string, object> = {}
|
|
list.value.forEach((item) => {
|
|
list.value.forEach((item) => {
|
|
// 只有当 simulateValue 有值时才添加到 content 中
|
|
// 只有当 simulateValue 有值时才添加到 content 中
|
|
|
|
+ // TODO @super:直接 if (item.simulateValue) 就可以哈,js 这块还是比较灵活的
|
|
if (item.simulateValue !== undefined && item.simulateValue !== '') {
|
|
if (item.simulateValue !== undefined && item.simulateValue !== '') {
|
|
- contentObj[item.identifier] = item.simulateValue
|
|
|
|
|
|
+ // TODO @super:这里有个红色的 idea 告警,觉得去除下
|
|
|
|
+ data[item.identifier] = item.simulateValue
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
|
|
- const reportData: SimulatorDataVO = {
|
|
|
|
- productKey: props.product.productKey,
|
|
|
|
- deviceKey: props.device.deviceKey,
|
|
|
|
- type: 'property',
|
|
|
|
- subType: 'report',
|
|
|
|
- reportTime: Date.now(), // 将 reportTime 变为数字类型的时间戳
|
|
|
|
- content: JSON.stringify(contentObj) // 转换为 JSON 字符串
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
try {
|
|
try {
|
|
- await DeviceApi.simulatorDevice(reportData)
|
|
|
|
|
|
+ await DeviceApi.simulationReportDevice({
|
|
|
|
+ id: props.device.id,
|
|
|
|
+ type: 'property',
|
|
|
|
+ identifier: 'report',
|
|
|
|
+ data: data
|
|
|
|
+ })
|
|
message.success('属性上报成功')
|
|
message.success('属性上报成功')
|
|
} catch (error) {
|
|
} catch (error) {
|
|
message.error('属性上报失败')
|
|
message.error('属性上报失败')
|