Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
f2f414a9
authored
Jan 09, 2025
by
YunaiV
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/iot' of
https://gitee.com/alwayssuper/yudao-ui-admin-vue3
into feature/iot
# Conflicts: # pnpm-lock.yaml
parents
7639f34e
3c7521b5
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
591 additions
and
2 deletions
+591
-2
.vscode/settings.json
+1
-1
src/api/iot/device/device/index.ts
+19
-0
src/api/iot/thingmodel/index.ts
+12
-0
src/views/iot/device/device/detail/DeviceDetailsLog.vue
+164
-0
src/views/iot/device/device/detail/DeviceDetailsSimulator.vue
+387
-0
src/views/iot/device/device/detail/index.vue
+8
-1
No files found.
.vscode/settings.json
View file @
f2f414a9
...
@@ -87,7 +87,7 @@
...
@@ -87,7 +87,7 @@
"source.fixAll.stylelint"
:
"explicit"
"source.fixAll.stylelint"
:
"explicit"
},
},
"[vue]"
:
{
"[vue]"
:
{
"editor.defaultFormatter"
:
"
esbenp.prettier-vscode
"
"editor.defaultFormatter"
:
"
octref.vetur
"
},
},
"i18n-ally.localesPaths"
:
[
"src/locales"
],
"i18n-ally.localesPaths"
:
[
"src/locales"
],
"i18n-ally.keystyle"
:
"nested"
,
"i18n-ally.keystyle"
:
"nested"
,
...
...
src/api/iot/device/device/index.ts
View file @
f2f414a9
...
@@ -63,6 +63,16 @@ export enum DeviceStatusEnum {
...
@@ -63,6 +63,16 @@ export enum DeviceStatusEnum {
DISABLED
=
3
// 已禁用
DISABLED
=
3
// 已禁用
}
}
// IoT 模拟设备数据
export
interface
SimulatorDataVO
{
productKey
:
string
deviceKey
:
string
type
:
string
subType
:
string
reportTime
:
number
// 时间戳
content
:
string
// 存储 JSON 字符串
}
// 设备 API
// 设备 API
export
const
DeviceApi
=
{
export
const
DeviceApi
=
{
// 查询设备分页
// 查询设备分页
...
@@ -136,5 +146,14 @@ export const DeviceApi = {
...
@@ -136,5 +146,14 @@ export const DeviceApi = {
// 获取导入模板
// 获取导入模板
importDeviceTemplate
:
async
()
=>
{
importDeviceTemplate
:
async
()
=>
{
return
await
request
.
download
({
url
:
`/iot/device/get-import-template`
})
return
await
request
.
download
({
url
:
`/iot/device/get-import-template`
})
},
// 模拟设备
simulatorDevice
:
async
(
data
:
SimulatorDataVO
)
=>
{
return
await
request
.
post
({
url
:
`/iot/device/data/simulator`
,
data
})
},
//查询设备日志分页
getDeviceLogPage
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/iot/device/data/log/page`
,
params
})
}
}
}
}
src/api/iot/thingmodel/index.ts
View file @
f2f414a9
...
@@ -18,6 +18,13 @@ export interface ThingModelData {
...
@@ -18,6 +18,13 @@ export interface ThingModelData {
}
}
/**
/**
* IoT 模拟设备
*/
export
interface
SimulatorData
extends
ThingModelData
{
simulateValue
?:
string
|
number
// 用于存储模拟值
}
/**
* ThingModelProperty 类型
* ThingModelProperty 类型
*/
*/
export
interface
ThingModelProperty
{
export
interface
ThingModelProperty
{
...
@@ -45,6 +52,11 @@ export const ThingModelApi = {
...
@@ -45,6 +52,11 @@ export const ThingModelApi = {
return
await
request
.
get
({
url
:
`/iot/thing-model/page`
,
params
})
return
await
request
.
get
({
url
:
`/iot/thing-model/page`
,
params
})
},
},
// 获得产品物模型列表
getThingModelList
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/iot/thing-model/list`
,
params
})
},
// 获得产品物模型
// 获得产品物模型
getThingModelListByProductId
:
async
(
params
:
any
)
=>
{
getThingModelListByProductId
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
return
await
request
.
get
({
...
...
src/views/iot/device/device/detail/DeviceDetailsLog.vue
0 → 100644
View file @
f2f414a9
<
template
>
<ContentWrap>
<!-- 搜索区域 -->
<el-form
:model=
"queryParams"
inline
>
<el-form-item>
<el-select
v-model=
"queryParams.type"
placeholder=
"所有"
class=
"!w-120px"
>
<el-option
label=
"所有"
value=
""
/>
<el-option
label=
"状态"
value=
"state"
/>
<el-option
label=
"事件"
value=
"event"
/>
<el-option
label=
"属性"
value=
"property"
/>
<el-option
label=
"服务"
value=
"service"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-input
v-model=
"queryParams.keyword"
placeholder=
"日志识符"
class=
"!w-200px"
/>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"handleQuery"
>
<Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-switch
v-model=
"autoRefresh"
class=
"ml-10px"
/>
定时刷新
</el-form-item>
</el-form>
<!-- 日志列表 -->
<el-table
v-loading=
"loading"
:data=
"logList"
:stripe=
"true"
class=
"whitespace-nowrap"
>
<el-table-column
label=
"时间"
align=
"center"
prop=
"time"
width=
"180"
>
<template
#
default=
"scope"
>
{{
formatDate
(
scope
.
row
.
time
)
}}
</
template
>
</el-table-column>
<el-table-column
label=
"类型"
align=
"center"
prop=
"type"
width=
"120"
/>
<el-table-column
label=
"名称(标识符)"
align=
"center"
prop=
"subType"
width=
"120"
/>
<el-table-column
label=
"内容"
align=
"center"
prop=
"content"
:show-overflow-tooltip=
"true"
/>
</el-table>
<!-- 分页 -->
<div
class=
"mt-10px flex justify-end"
>
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getLogList"
/>
</div>
</ContentWrap>
</template>
<
script
setup
lang=
"ts"
>
import
{
DeviceApi
}
from
'@/api/iot/device/device'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
formatDate
}
from
'@/utils/formatTime'
const
props
=
defineProps
<
{
deviceKey
:
number
}
>
()
//TODO:后续看看使用什么查询条件 目前后端是留了时间范围 type subType
// 查询参数
const
queryParams
=
reactive
({
deviceKey
:
props
.
deviceKey
,
// type: '',
// keyword: '',
pageNo
:
1
,
pageSize
:
10
})
// 列表数据
const
loading
=
ref
(
false
)
const
total
=
ref
(
0
)
const
logList
=
ref
([])
const
autoRefresh
=
ref
(
false
)
let
timer
:
any
=
null
// 类型映射
const
typeMap
=
{
lifetime
:
'生命周期'
,
state
:
'设备状态'
,
property
:
'属性'
,
event
:
'事件'
,
service
:
'服务'
}
/** 查询日志列表 */
const
getLogList
=
async
()
=>
{
if
(
!
props
.
deviceKey
)
return
loading
.
value
=
true
try
{
const
res
=
await
DeviceApi
.
getDeviceLogPage
(
queryParams
)
total
.
value
=
res
.
total
logList
.
value
=
res
.
list
.
map
((
item
:
any
)
=>
{
const
log
=
{
time
:
item
.
reportTime
,
type
:
item
.
type
,
subType
:
item
.
subType
,
content
:
item
.
content
}
return
log
})
}
finally
{
loading
.
value
=
false
}
}
/** 获取日志名称 */
const
getLogName
=
(
log
:
any
)
=>
{
const
{
type
,
identifier
}
=
log
let
name
=
'未知'
if
(
type
===
'property'
)
{
if
(
identifier
===
'set_reply'
)
name
=
'设置回复'
else
if
(
identifier
===
'report'
)
name
=
'上报'
else
if
(
identifier
===
'set'
)
name
=
'设置'
}
else
if
(
type
===
'state'
)
{
name
=
identifier
===
'online'
?
'上线'
:
'下线'
}
else
if
(
type
===
'lifetime'
)
{
name
=
identifier
===
'register'
?
'注册'
:
name
}
return
`
${
name
}
(
${
identifier
}
)`
}
/** 搜索操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getLogList
()
}
/** 监听自动刷新 */
watch
(
autoRefresh
,
(
newValue
)
=>
{
if
(
newValue
)
{
timer
=
setInterval
(()
=>
{
getLogList
()
},
5000
)
}
else
{
clearInterval
(
timer
)
timer
=
null
}
})
/** 监听设备ID变化 */
watch
(
()
=>
props
.
deviceKey
,
(
newValue
)
=>
{
if
(
newValue
)
{
handleQuery
()
}
}
)
/** 组件卸载时清除定时器 */
onBeforeUnmount
(()
=>
{
if
(
timer
)
{
clearInterval
(
timer
)
}
})
/** 初始化 */
onMounted
(()
=>
{
if
(
props
.
deviceKey
)
{
getLogList
()
}
})
</
script
>
src/views/iot/device/device/detail/DeviceDetailsSimulator.vue
0 → 100644
View file @
f2f414a9
<
template
>
<ContentWrap>
<el-row
:gutter=
"20"
>
<!-- 左侧指令调试区域 -->
<el-col
:span=
"12"
>
<el-tabs
v-model=
"activeTab"
type=
"border-card"
>
<!-- 上行指令调试 -->
<el-tab-pane
label=
"上行指令调试"
name=
"up"
>
<el-tabs
v-model=
"subTab"
v-if=
"activeTab === 'up'"
>
<!-- 属性上报 -->
<el-tab-pane
label=
"属性上报"
name=
"property"
>
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table-column
align=
"center"
label=
"功能名称"
prop=
"name"
/>
<el-table-column
align=
"center"
label=
"标识符"
prop=
"identifier"
/>
<el-table-column
align=
"center"
label=
"数据类型"
prop=
"identifier"
>
<template
#
default=
"
{ row }">
{{
dataTypeOptionsLabel
(
row
.
property
?.
dataType
)
??
'-'
}}
</
template
>
</el-table-column>
<el-table-column
align=
"left"
label=
"数据定义"
prop=
"identifier"
>
<
template
#
default=
"{ row }"
>
<!-- 属性 -->
<template
v-if=
"row.type === ThingModelType.PROPERTY"
>
<!-- 非列表型:数值 -->
<div
v-if=
"
[
DataSpecsDataType.INT,
DataSpecsDataType.DOUBLE,
DataSpecsDataType.FLOAT
].includes(row.property.dataType)
"
>
取值范围:
{{
`${row.property.dataSpecs.min
}
~${row.property.dataSpecs.max
}
`
}}
<
/div
>
<!--
非列表型:文本
-->
<
div
v
-
if
=
"DataSpecsDataType.TEXT === row.property.dataType"
>
数据长度:
{{
row
.
property
.
dataSpecs
.
length
}}
<
/div
>
<!--
列表型
:
数组、结构、时间(特殊)
-->
<
div
v
-
if
=
"
[
DataSpecsDataType.ARRAY,
DataSpecsDataType.STRUCT,
DataSpecsDataType.DATE
].includes(row.property.dataType)
"
>
-
<
/div
>
<!--
列表型
:
布尔值、枚举
-->
<
div
v
-
if
=
"
[DataSpecsDataType.BOOL, DataSpecsDataType.ENUM].includes(
row.property.dataType
)
"
>
<
div
>
{{
DataSpecsDataType
.
BOOL
===
row
.
property
.
dataType
?
'布尔值'
:
'枚举值'
}}
:
<
/div
>
<
div
v
-
for
=
"item in row.property.dataSpecsList"
:
key
=
"item.value"
>
{{
`${item.name
}
-${item.value
}
`
}}
<
/div
>
<
/div
>
<
/template
>
<!--
服务
-->
<
div
v
-
if
=
"row.type === ThingModelType.SERVICE"
>
调用方式:
{{
getCallTypeByValue
(
row
.
service
.
callType
)
}}
<
/div
>
<!--
事件
-->
<
div
v
-
if
=
"row.type === ThingModelType.EVENT"
>
事件类型:
{{
getEventTypeByValue
(
row
.
event
.
type
)
}}
<
/div
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"值"
align
=
"center"
width
=
"80"
>
<
template
#
default
=
"scope"
>
<
el
-
input
v
-
model
=
"scope.row.simulateValue"
class
=
"!w-60px"
/>
<
/template
>
<
/el-table-column
>
<
/el-table
>
<
div
class
=
"mt-10px"
>
<
el
-
button
type
=
"primary"
@
click
=
"handlePropertyReport"
>
发送
<
/el-button
>
<
/div
>
<
/ContentWrap
>
<
/el-tab-pane
>
<!--
事件上报
-->
<
el
-
tab
-
pane
label
=
"事件上报"
name
=
"event"
>
<
ContentWrap
>
<!--
<
el
-
table
v
-
loading
=
"loading"
:
data
=
"eventList"
:
stripe
=
"true"
>
<
el
-
table
-
column
label
=
"功能名称"
align
=
"center"
prop
=
"name"
/>
<
el
-
table
-
column
label
=
"标识符"
align
=
"center"
prop
=
"identifier"
/>
<
el
-
table
-
column
label
=
"数据类型"
align
=
"center"
prop
=
"dataType"
/>
<
el
-
table
-
column
label
=
"数据定义"
align
=
"center"
prop
=
"specs"
:
show
-
overflow
-
tooltip
=
"true"
/>
<
el
-
table
-
column
label
=
"值"
align
=
"center"
width
=
"80"
>
<
template
#
default
=
"scope"
>
<
el
-
input
v
-
model
=
"scope.row.simulateValue"
class
=
"!w-60px"
/>
<
/template
>
<
/el-table-column
>
<
/el-table
>
<
div
class
=
"mt-10px"
>
<
el
-
button
type
=
"primary"
@
click
=
"handleEventReport"
>
发送
<
/el-button
>
<
/div> --
>
<
/ContentWrap
>
<
/el-tab-pane
>
<!--
状态变更
-->
<
el
-
tab
-
pane
label
=
"状态变更"
name
=
"status"
>
<
ContentWrap
>
<
div
class
=
"flex gap-4"
>
<
el
-
button
type
=
"primary"
@
click
=
"handleDeviceState('online')"
>
设备上线
<
/el-butto
n
>
<
el
-
button
type
=
"primary"
@
click
=
"handleDeviceState('offline')"
>
设备下线
<
/el-butto
n
>
<
/div
>
<
/ContentWrap
>
<
/el-tab-pane
>
<
/el-tabs
>
<
/el-tab-pane
>
<!--
下行指令调试
-->
<
el
-
tab
-
pane
label
=
"下行指令调试"
name
=
"down"
>
<
el
-
tabs
v
-
model
=
"subTab"
v
-
if
=
"activeTab === 'down'"
>
<!--
属性调试
-->
<
el
-
tab
-
pane
label
=
"属性调试"
name
=
"propertyDebug"
>
<
ContentWrap
>
<!--
<
el
-
table
v
-
loading
=
"loading"
:
data
=
"propertyList"
:
stripe
=
"true"
>
<
el
-
table
-
column
label
=
"功能名称"
align
=
"center"
prop
=
"name"
/>
<
el
-
table
-
column
label
=
"标识符"
align
=
"center"
prop
=
"identifier"
/>
<
el
-
table
-
column
label
=
"数据类型"
align
=
"center"
prop
=
"dataType"
/>
<
el
-
table
-
column
label
=
"数据定义"
align
=
"center"
prop
=
"specs"
:
show
-
overflow
-
tooltip
=
"true"
/>
<
el
-
table
-
column
label
=
"值"
align
=
"center"
width
=
"80"
>
<
template
#
default
=
"scope"
>
<
el
-
input
v
-
model
=
"scope.row.simulateValue"
class
=
"!w-60px"
/>
<
/template
>
<
/el-table-column
>
<
/el-table
>
<
div
class
=
"mt-10px"
>
<
el
-
button
type
=
"primary"
@
click
=
"handlePropertyGet"
>
获取
<
/el-button
>
<
/div> --
>
<
/ContentWrap
>
<
/el-tab-pane
>
<!--
服务调用
-->
<
el
-
tab
-
pane
label
=
"服务调用"
name
=
"service"
>
<
ContentWrap
>
<!--
服务调用相关内容
-->
<
/ContentWrap
>
<
/el-tab-pane
>
<
/el-tabs
>
<
/el-tab-pane
>
<
/el-tabs
>
<
/el-col
>
<!--
右侧设备日志区域
-->
<
el
-
col
:
span
=
"12"
>
<
el
-
tabs
type
=
"border-card"
>
<
el
-
tab
-
pane
label
=
"设备日志"
>
<
DeviceDetailsLog
:
deviceKey
=
"device.deviceKey"
/>
<
/el-tab-pane
>
<
/el-tabs
>
<
/el-col
>
<
/el-row
>
<
/ContentWrap
>
<
/template
>
<
script
setup
lang
=
"ts"
>
import
{
ProductVO
}
from
'@/api/iot/product/product'
import
{
ThingModelApi
,
ThingModelData
,
SimulatorData
}
from
'@/api/iot/thingmodel'
import
{
DeviceApi
,
DeviceVO
,
SimulatorDataVO
}
from
'@/api/iot/device/device'
import
DeviceDetailsLog
from
'./DeviceDetailsLog.vue'
import
{
DataSpecsDataType
,
getCallTypeByValue
,
getDataTypeOptionsLabel
,
getEventTypeByValue
,
ThingModelType
}
from
'@/views/iot/thingmodel/config'
const
message
=
useMessage
()
// 消息弹窗
const
loading
=
ref
(
false
)
const
activeTab
=
ref
(
'up'
)
const
subTab
=
ref
(
'property'
)
const
queryParams
=
reactive
({
type
:
undefined
,
productId
:
-
1
}
)
const
dataTypeOptionsLabel
=
computed
(()
=>
(
value
:
string
)
=>
getDataTypeOptionsLabel
(
value
))
// 解析数据类型
const
props
=
defineProps
<
{
product
:
ProductVO
;
device
:
DeviceVO
}
>
()
const
list
=
ref
<
SimulatorData
[]
>
([])
// 物模型列表的数据
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
queryParams
.
productId
=
props
.
product
?.
id
||
-
1
const
data
=
await
ThingModelApi
.
getThingModelList
(
queryParams
)
// 转换数据,添加 simulateValue 字段
list
.
value
=
data
.
map
(
item
=>
({
...
item
,
simulateValue
:
''
}
))
}
finally
{
loading
.
value
=
false
}
}
// // 功能列表数据结构定义
// interface TableItem
{
// name: string
// identifier: string
// value: string | number
//
}
// // 添加计算属性来过滤物模型数据
// const propertyList = computed(() =>
{
// return list.value
// .filter((item) => item.type === 'property')
// .map((item) => (
{
// name: item.name,
// identifier: item.identifier,
// value: ''
//
}
))
//
}
)
// const eventList = computed(() =>
{
// return list.value
// .filter((item) => item.type === 'event')
// .map((item) => (
{
// name: item.name,
// identifier: item.identifier,
// value: ''
//
}
))
//
}
)
// 监听标签页变化 todo:后续改成查询字典
watch
(
[
activeTab
,
subTab
],
([
newActiveTab
,
newSubTab
])
=>
{
// 根据标签页设置查询类型
if
(
newActiveTab
===
'up'
)
{
switch
(
newSubTab
)
{
case
'property'
:
queryParams
.
type
=
1
break
case
'event'
:
queryParams
.
type
=
3
break
// case 'status':
// queryParams.type = 'status'
// break
}
}
else
if
(
newActiveTab
===
'down'
)
{
switch
(
newSubTab
)
{
case
'propertyDebug'
:
queryParams
.
type
=
1
break
case
'service'
:
queryParams
.
type
=
2
break
}
}
getList
()
// 切换标签时重新获取数据
}
,
{
immediate
:
true
}
)
// interface ReportData
{
// productKey: string
// deviceKey: string
// type: string
// subType: string
// reportTime: string
// content: string // 改为 string 类型,存储 JSON 字符串
//
}
// 处理属性上报 TODO:数据类型效验
const
handlePropertyReport
=
async
()
=>
{
const
contentObj
:
Record
<
string
,
any
>
=
{
}
list
.
value
.
forEach
((
item
)
=>
{
// 只有当 simulateValue 有值时才添加到 content 中
if
(
item
.
simulateValue
!==
undefined
&&
item
.
simulateValue
!==
''
)
{
contentObj
[
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
{
await
DeviceApi
.
simulatorDevice
(
reportData
)
message
.
success
(
'属性上报成功'
)
}
catch
(
error
)
{
message
.
error
(
'属性上报失败'
)
}
}
// // 处理事件上报
// const handleEventReport = async () =>
{
// const contentObj: Record<string, any> =
{
}
// list.value
// .filter(item => item.type === 'event')
// .forEach((item) =>
{
// if (item.simulateValue !== undefined && item.simulateValue !== '')
{
// contentObj[item.identifier] = item.simulateValue
//
}
//
}
)
// const reportData: ReportData =
{
// productKey: props.product.productKey,
// deviceKey: props.device.deviceKey,
// type: 'event',
// subType: list.value.find(item => item.type === 'event')?.identifier || '',
// reportTime: new Date().toISOString(),
// content: JSON.stringify(contentObj) // 转换为 JSON 字符串
//
}
// try
{
// // TODO: 调用API发送数据
// console.log('上报数据:', reportData)
// message.success('事件上报成功')
//
}
catch
(
error
)
{
// message.error('事件上报失败')
//
}
//
}
// // 处理设备状态变更
// const handleDeviceState = async (state: 'online' | 'offline') =>
{
// const reportData: ReportData =
{
// productKey: props.product.productKey,
// deviceKey: props.device.deviceKey,
// type: 'status',
// subType: state,
// reportTime: new Date().toISOString(),
// content: JSON.stringify(
{
status
:
state
}
)
// 转换为 JSON 字符串
//
}
// try
{
// // TODO: 调用API发送数据
// console.log('状态变更数据:', reportData)
// console.log('reportData.content111111111', reportData.content)
// message.success(`设备$
{
state
===
'online'
?
'上线'
:
'下线'
}成功
`)
//
}
catch (error) {
// message.error(`
设备
$
{
state
===
'online'
?
'上线'
:
'下线'
}失败
`)
//
}
//
}
// 处理属性获取
const handlePropertyGet = async () => {
// TODO: 实现属性获取逻辑
message.success('属性获取成功')
}
// 初始化
onMounted(() => {
getList()
}
)
</script>
src/views/iot/device/device/detail/index.vue
View file @
f2f414a9
...
@@ -16,6 +16,12 @@
...
@@ -16,6 +16,12 @@
</el-tab-pane>
</el-tab-pane>
<el-tab-pane
label=
"子设备管理"
v-if=
"product.deviceType === DeviceTypeEnum.GATEWAY"
/>
<el-tab-pane
label=
"子设备管理"
v-if=
"product.deviceType === DeviceTypeEnum.GATEWAY"
/>
<el-tab-pane
label=
"设备影子"
/>
<el-tab-pane
label=
"设备影子"
/>
<el-tab-pane
label=
"设备日志"
name=
"log"
>
<DeviceDetailsLog
v-if=
"activeTab === 'log'"
:deviceKey=
"device.deviceKey"
/>
</el-tab-pane>
<el-tab-pane
label=
"模拟设备"
name=
"simulator"
>
<DeviceDetailsSimulator
v-if=
"activeTab === 'simulator'"
:product=
"product"
:device=
"device"
/>
</el-tab-pane>
</el-tabs>
</el-tabs>
</el-col>
</el-col>
</
template
>
</
template
>
...
@@ -26,7 +32,8 @@ import { DeviceTypeEnum, ProductApi, ProductVO } from '@/api/iot/product/product
...
@@ -26,7 +32,8 @@ import { DeviceTypeEnum, ProductApi, ProductVO } from '@/api/iot/product/product
import
DeviceDetailsHeader
from
'./DeviceDetailsHeader.vue'
import
DeviceDetailsHeader
from
'./DeviceDetailsHeader.vue'
import
DeviceDetailsInfo
from
'./DeviceDetailsInfo.vue'
import
DeviceDetailsInfo
from
'./DeviceDetailsInfo.vue'
import
DeviceDetailsModel
from
'./DeviceDetailsModel.vue'
import
DeviceDetailsModel
from
'./DeviceDetailsModel.vue'
import
DeviceDetailsLog
from
'./DeviceDetailsLog.vue'
import
DeviceDetailsSimulator
from
'./DeviceDetailsSimulator.vue'
defineOptions
({
name
:
'IoTDeviceDetail'
})
defineOptions
({
name
:
'IoTDeviceDetail'
})
const
route
=
useRoute
()
const
route
=
useRoute
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment