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
6d641177
authored
Oct 01, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【代码评审】IoT:产品、设备、物模型的代码
parent
4b2800f7
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
114 additions
and
149 deletions
+114
-149
src/api/iot/device/index.ts
+14
-14
src/api/iot/product/index.ts
+18
-17
src/api/iot/thinkmodelfunction/index.ts
+13
-13
src/views/iot/device/DeviceForm.vue
+3
-4
src/views/iot/device/detail/DeviceDetailsHeader.vue
+1
-0
src/views/iot/device/detail/DeviceDetailsInfo.vue
+29
-42
src/views/iot/device/index.vue
+4
-3
src/views/iot/product/ProductForm.vue
+7
-21
src/views/iot/product/detail/ProductDetailsHeader.vue
+8
-9
src/views/iot/product/detail/ProductDetailsInfo.vue
+3
-3
src/views/iot/product/detail/ProductTopic.vue
+1
-0
src/views/iot/product/detail/ThinkModelFunction.vue
+2
-1
src/views/iot/product/detail/ThinkModelFunctionForm.vue
+4
-3
src/views/iot/product/detail/index.vue
+6
-1
src/views/iot/product/index.vue
+1
-18
No files found.
src/api/iot/device/index.ts
View file @
6d641177
import
request
from
'@/config/axios'
import
request
from
'@/config/axios'
// 设备 VO
//
IoT
设备 VO
export
interface
DeviceVO
{
export
interface
DeviceVO
{
id
:
number
// 设备 ID,主键,自增
id
:
number
// 设备 ID,主键,自增
deviceKey
:
string
// 设备唯一标识符
,全局唯一,用于识别设备
deviceKey
:
string
// 设备唯一标识符
deviceName
:
string
// 设备名称
,在产品内唯一,用于标识设备
deviceName
:
string
// 设备名称
productId
:
number
// 产品
ID,关联 iot_product 表的 id
productId
:
number
// 产品
编号
productKey
:
string
// 产品
Key,关联 iot_product 表的 product_key
productKey
:
string
// 产品
标识
deviceType
:
number
// 设备类型
:0 - 直连设备,1 - 网关子设备,2 - 网关设备
deviceType
:
number
// 设备类型
nickname
:
string
// 设备备注名称
,供用户自定义备注
nickname
:
string
// 设备备注名称
gatewayId
:
number
// 网关设备 ID
,子设备需要关联的网关设备 ID
gatewayId
:
number
// 网关设备 ID
status
:
number
// 设备状态
:0 - 未激活,1 - 在线,2 - 离线,3 - 已禁用
status
:
number
// 设备状态
statusLastUpdateTime
:
Date
// 设备状态最后更新时间
statusLastUpdateTime
:
Date
// 设备状态最后更新时间
lastOnlineTime
:
Date
// 最后上线时间
lastOnlineTime
:
Date
// 最后上线时间
lastOfflineTime
:
Date
// 最后离线时间
lastOfflineTime
:
Date
// 最后离线时间
...
@@ -22,17 +22,17 @@ export interface DeviceVO {
...
@@ -22,17 +22,17 @@ export interface DeviceVO {
mqttClientId
:
string
// MQTT 客户端 ID
mqttClientId
:
string
// MQTT 客户端 ID
mqttUsername
:
string
// MQTT 用户名
mqttUsername
:
string
// MQTT 用户名
mqttPassword
:
string
// MQTT 密码
mqttPassword
:
string
// MQTT 密码
authType
:
string
// 认证类型
(如一机一密、动态注册)
authType
:
string
// 认证类型
latitude
:
number
// 设备位置的纬度
,范围 -90.000000 ~ 90.000000
latitude
:
number
// 设备位置的纬度
longitude
:
number
// 设备位置的经度
,范围 -180.000000 ~ 180.000000
longitude
:
number
// 设备位置的经度
areaId
:
number
// 地区编码
,符合国家地区编码标准,关联地区表
areaId
:
number
// 地区编码
address
:
string
// 设备详细地址
address
:
string
// 设备详细地址
serialNumber
:
string
// 设备序列号
serialNumber
:
string
// 设备序列号
}
}
export
interface
DeviceUpdateStatusVO
{
export
interface
DeviceUpdateStatusVO
{
id
:
number
// 设备 ID,主键,自增
id
:
number
// 设备 ID,主键,自增
status
:
number
// 设备状态
:0 - 未激活,1 - 在线,2 - 离线,3 - 已禁用
status
:
number
// 设备状态
}
}
// 设备 API
// 设备 API
...
...
src/api/iot/product/index.ts
View file @
6d641177
import
request
from
'@/config/axios'
import
request
from
'@/config/axios'
//
iot
产品 VO
//
IoT
产品 VO
export
interface
ProductVO
{
export
interface
ProductVO
{
id
:
number
// 产品编号
name
:
string
// 产品名称
name
:
string
// 产品名称
id
:
number
// 产品ID
productKey
:
string
// 产品标识
productKey
:
string
// 产品标识
protocolId
:
number
// 协议编号
(脚本解析 id)
protocolId
:
number
// 协议编号
categoryId
:
number
// 产品所属品类标识符
categoryId
:
number
// 产品所属品类标识符
description
:
string
// 产品描述
description
:
string
// 产品描述
validateType
:
number
// 数据校验级别
, 0: 强校验, 1: 弱校验, 2: 免校验
validateType
:
number
// 数据校验级别
status
:
number
// 产品状态
, 0: DEVELOPMENT_STATUS, 1: RELEASE_STATUS
status
:
number
// 产品状态
deviceType
:
number
// 设备类型
, 0: 直连设备, 1: 网关子设备, 2: 网关设备
deviceType
:
number
// 设备类型
netType
:
number
// 联网方式
, 0: Wi-Fi, 1: Cellular, 2: Ethernet, 3: 其他
netType
:
number
// 联网方式
protocolType
:
number
// 接入网关协议
, 0: modbus, 1: opc-ua, 2: customize, 3: ble, 4: zigbee
protocolType
:
number
// 接入网关协议
dataFormat
:
number
// 数据格式
, 0: 透传模式, 1: Alink JSON
dataFormat
:
number
// 数据格式
deviceCount
:
number
// 设备数量
deviceCount
:
number
// 设备数量
createTime
:
Date
// 创建时间
}
}
//
iot
产品 API
//
IoT
产品 API
export
const
ProductApi
=
{
export
const
ProductApi
=
{
// 查询
iot
产品分页
// 查询产品分页
getProductPage
:
async
(
params
:
any
)
=>
{
getProductPage
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/iot/product/page`
,
params
})
return
await
request
.
get
({
url
:
`/iot/product/page`
,
params
})
},
},
// 查询
iot
产品详情
// 查询产品详情
getProduct
:
async
(
id
:
number
)
=>
{
getProduct
:
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
`/iot/product/get?id=`
+
id
})
return
await
request
.
get
({
url
:
`/iot/product/get?id=`
+
id
})
},
},
// 新增
iot
产品
// 新增产品
createProduct
:
async
(
data
:
ProductVO
)
=>
{
createProduct
:
async
(
data
:
ProductVO
)
=>
{
return
await
request
.
post
({
url
:
`/iot/product/create`
,
data
})
return
await
request
.
post
({
url
:
`/iot/product/create`
,
data
})
},
},
// 修改
iot
产品
// 修改产品
updateProduct
:
async
(
data
:
ProductVO
)
=>
{
updateProduct
:
async
(
data
:
ProductVO
)
=>
{
return
await
request
.
put
({
url
:
`/iot/product/update`
,
data
})
return
await
request
.
put
({
url
:
`/iot/product/update`
,
data
})
},
},
// 删除
iot
产品
// 删除产品
deleteProduct
:
async
(
id
:
number
)
=>
{
deleteProduct
:
async
(
id
:
number
)
=>
{
return
await
request
.
delete
({
url
:
`/iot/product/delete?id=`
+
id
})
return
await
request
.
delete
({
url
:
`/iot/product/delete?id=`
+
id
})
},
},
// 导出
iot
产品 Excel
// 导出产品 Excel
exportProduct
:
async
(
params
)
=>
{
exportProduct
:
async
(
params
)
=>
{
return
await
request
.
download
({
url
:
`/iot/product/export-excel`
,
params
})
return
await
request
.
download
({
url
:
`/iot/product/export-excel`
,
params
})
},
},
...
@@ -54,7 +55,7 @@ export const ProductApi = {
...
@@ -54,7 +55,7 @@ export const ProductApi = {
return
await
request
.
put
({
url
:
`/iot/product/update-status?id=`
+
id
+
`&status=`
+
status
})
return
await
request
.
put
({
url
:
`/iot/product/update-status?id=`
+
id
+
`&status=`
+
status
})
},
},
// 查询产品(精简
)
列表
// 查询产品(精简
)
列表
getSimpleProductList
()
{
getSimpleProductList
()
{
return
request
.
get
({
url
:
'/iot/product/list-all-simple'
})
return
request
.
get
({
url
:
'/iot/product/list-all-simple'
})
}
}
...
...
src/api/iot/thinkmodelfunction/index.ts
View file @
6d641177
...
@@ -6,21 +6,21 @@ export interface ThinkModelFunctionVO {
...
@@ -6,21 +6,21 @@ export interface ThinkModelFunctionVO {
identifier
:
string
// 功能标识
identifier
:
string
// 功能标识
name
:
string
// 功能名称
name
:
string
// 功能名称
description
:
string
// 功能描述
description
:
string
// 功能描述
productId
:
number
// 产品
ID(关联 IotProductDO 的 id)
productId
:
number
// 产品
编号
productKey
:
string
// 产品
Key(关联 IotProductDO 的 productKey)
productKey
:
string
// 产品
标识
type
:
number
// 功能类型
(1 - 属性,2 - 服务,3 - 事件)
type
:
number
// 功能类型
property
:
string
// 属性
(存储 ThingModelProperty 的 JSON 数据)
property
:
string
// 属性
event
:
string
// 事件
(存储 ThingModelEvent 的 JSON 数据)
event
:
string
// 事件
service
:
string
// 服务
(存储服务的 JSON 数据)
service
:
string
// 服务
}
}
// IoT 产品物模型 API
// IoT 产品物模型 API
export
const
ThinkModelFunctionApi
=
{
export
const
ThinkModelFunctionApi
=
{
// 查询
IoT
产品物模型分页
// 查询产品物模型分页
getThinkModelFunctionPage
:
async
(
params
:
any
)
=>
{
getThinkModelFunctionPage
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/iot/think-model-function/page`
,
params
})
return
await
request
.
get
({
url
:
`/iot/think-model-function/page`
,
params
})
},
},
// 获得
IoT
产品物模型
// 获得产品物模型
getThinkModelFunctionListByProductId
:
async
(
params
:
any
)
=>
{
getThinkModelFunctionListByProductId
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
return
await
request
.
get
({
url
:
`/iot/think-model-function/list-by-product-id`
,
url
:
`/iot/think-model-function/list-by-product-id`
,
...
@@ -28,27 +28,27 @@ export const ThinkModelFunctionApi = {
...
@@ -28,27 +28,27 @@ export const ThinkModelFunctionApi = {
})
})
},
},
// 查询
IoT
产品物模型详情
// 查询产品物模型详情
getThinkModelFunction
:
async
(
id
:
number
)
=>
{
getThinkModelFunction
:
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
`/iot/think-model-function/get?id=`
+
id
})
return
await
request
.
get
({
url
:
`/iot/think-model-function/get?id=`
+
id
})
},
},
// 新增
IoT
产品物模型
// 新增产品物模型
createThinkModelFunction
:
async
(
data
:
ThinkModelFunctionVO
)
=>
{
createThinkModelFunction
:
async
(
data
:
ThinkModelFunctionVO
)
=>
{
return
await
request
.
post
({
url
:
`/iot/think-model-function/create`
,
data
})
return
await
request
.
post
({
url
:
`/iot/think-model-function/create`
,
data
})
},
},
// 修改
IoT
产品物模型
// 修改产品物模型
updateThinkModelFunction
:
async
(
data
:
ThinkModelFunctionVO
)
=>
{
updateThinkModelFunction
:
async
(
data
:
ThinkModelFunctionVO
)
=>
{
return
await
request
.
put
({
url
:
`/iot/think-model-function/update`
,
data
})
return
await
request
.
put
({
url
:
`/iot/think-model-function/update`
,
data
})
},
},
// 删除
IoT
产品物模型
// 删除产品物模型
deleteThinkModelFunction
:
async
(
id
:
number
)
=>
{
deleteThinkModelFunction
:
async
(
id
:
number
)
=>
{
return
await
request
.
delete
({
url
:
`/iot/think-model-function/delete?id=`
+
id
})
return
await
request
.
delete
({
url
:
`/iot/think-model-function/delete?id=`
+
id
})
},
},
// 导出
IoT
产品物模型 Excel
// 导出产品物模型 Excel
exportThinkModelFunction
:
async
(
params
)
=>
{
exportThinkModelFunction
:
async
(
params
)
=>
{
return
await
request
.
download
({
url
:
`/iot/think-model-function/export-excel`
,
params
})
return
await
request
.
download
({
url
:
`/iot/think-model-function/export-excel`
,
params
})
}
}
...
...
src/views/iot/device/DeviceForm.vue
View file @
6d641177
...
@@ -57,8 +57,7 @@ const formData = ref({
...
@@ -57,8 +57,7 @@ const formData = ref({
id
:
undefined
,
id
:
undefined
,
productId
:
undefined
,
productId
:
undefined
,
deviceName
:
undefined
,
deviceName
:
undefined
,
nickname
:
undefined
,
nickname
:
undefined
serialNumber
:
undefined
})
})
const
formRules
=
reactive
({
const
formRules
=
reactive
({
productId
:
[{
required
:
true
,
message
:
'产品不能为空'
,
trigger
:
'blur'
}],
productId
:
[{
required
:
true
,
message
:
'产品不能为空'
,
trigger
:
'blur'
}],
...
@@ -66,7 +65,7 @@ const formRules = reactive({
...
@@ -66,7 +65,7 @@ const formRules = reactive({
{
{
pattern
:
/^
[
a-zA-Z0-9_.
\-
:@
]{4,32}
$/
,
pattern
:
/^
[
a-zA-Z0-9_.
\-
:@
]{4,32}
$/
,
message
:
message
:
'支持英文字母、数字、下划线(_)、中划线(-)、点号(.)、半角冒号(:)和特殊字符@,长度限制为
4~32
个字符'
,
'支持英文字母、数字、下划线(_)、中划线(-)、点号(.)、半角冒号(:)和特殊字符@,长度限制为
4~32
个字符'
,
trigger
:
'blur'
trigger
:
'blur'
}
}
],
],
...
@@ -79,7 +78,7 @@ const formRules = reactive({
...
@@ -79,7 +78,7 @@ const formRules = reactive({
}
}
const
length
=
value
.
replace
(
/
[\u
4e00-
\u
9fa5
\u
3040-
\u
30ff
]
/g
,
'aa'
).
length
const
length
=
value
.
replace
(
/
[\u
4e00-
\u
9fa5
\u
3040-
\u
30ff
]
/g
,
'aa'
).
length
if
(
length
<
4
||
length
>
64
)
{
if
(
length
<
4
||
length
>
64
)
{
callback
(
new
Error
(
'备注名称长度限制为
4~64个字符,中文及日文算2
个字符'
))
callback
(
new
Error
(
'备注名称长度限制为
4~64 个字符,中文及日文算 2
个字符'
))
}
else
if
(
!
/^
[\u
4e00-
\u
9fa5
\u
3040-
\u
30ff_a-zA-Z0-9
]
+$/
.
test
(
value
))
{
}
else
if
(
!
/^
[\u
4e00-
\u
9fa5
\u
3040-
\u
30ff_a-zA-Z0-9
]
+$/
.
test
(
value
))
{
callback
(
new
Error
(
'备注名称只能包含中文、英文字母、日文、数字和下划线(_)'
))
callback
(
new
Error
(
'备注名称只能包含中文、英文字母、日文、数字和下划线(_)'
))
}
else
{
}
else
{
...
...
src/views/iot/device/detail/DeviceDetailsHeader.vue
View file @
6d641177
...
@@ -59,6 +59,7 @@ const emit = defineEmits(['refresh'])
...
@@ -59,6 +59,7 @@ const emit = defineEmits(['refresh'])
* @param text 需要复制的文本
* @param text 需要复制的文本
*/
*/
const
copyToClipboard
=
(
text
:
string
)
=>
{
const
copyToClipboard
=
(
text
:
string
)
=>
{
// TODO @haohao:可以考虑用 await 异步转同步哈
navigator
.
clipboard
.
writeText
(
text
).
then
(()
=>
{
navigator
.
clipboard
.
writeText
(
text
).
then
(()
=>
{
message
.
success
(
'复制成功'
)
message
.
success
(
'复制成功'
)
})
})
...
...
src/views/iot/device/detail/DeviceDetailsInfo.vue
View file @
6d641177
...
@@ -3,33 +3,33 @@
...
@@ -3,33 +3,33 @@
<el-collapse
v-model=
"activeNames"
>
<el-collapse
v-model=
"activeNames"
>
<el-descriptions
:column=
"3"
title=
"设备信息"
>
<el-descriptions
:column=
"3"
title=
"设备信息"
>
<el-descriptions-item
label=
"产品名称"
>
{{
product
.
name
}}
</el-descriptions-item>
<el-descriptions-item
label=
"产品名称"
>
{{
product
.
name
}}
</el-descriptions-item>
<el-descriptions-item
label=
"ProductKey"
<el-descriptions-item
label=
"ProductKey"
>
>
{{
product
.
productKey
}}
{{
product
.
productKey
}}
<el-button
@
click=
"copyToClipboard(product.productKey)"
>
复制
</el-button>
<el-button
@
click=
"copyToClipboard(product.productKey)"
>
复制
</el-button>
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"设备类型"
>
<el-descriptions-item
label=
"设备类型"
>
<dict-tag
:type=
"DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE"
:value=
"product.deviceType"
/>
<dict-tag
:type=
"DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE"
:value=
"product.deviceType"
/>
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"DeviceName"
<el-descriptions-item
label=
"DeviceName"
>
>
{{
device
.
deviceName
}}
{{
device
.
deviceName
}}
<el-button
@
click=
"copyToClipboard(device.deviceName)"
>
复制
</el-button>
<el-button
@
click=
"copyToClipboard(device.deviceName)"
>
复制
</el-button>
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"备注名称"
>
{{
device
.
nickname
}}
</el-descriptions-item>
<el-descriptions-item
label=
"备注名称"
>
{{
device
.
nickname
}}
</el-descriptions-item>
<el-descriptions-item
label=
"创建时间"
>
{{
<el-descriptions-item
label=
"创建时间"
>
formatDate
(
device
.
createTime
)
{{
formatDate
(
device
.
createTime
)
}}
}}
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"激活时间"
>
{{
<el-descriptions-item
label=
"激活时间"
>
formatDate
(
device
.
activeTime
)
{{
formatDate
(
device
.
activeTime
)
}}
}}
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"最后上线时间"
>
{{
<el-descriptions-item
label=
"最后上线时间"
>
formatDate
(
device
.
lastOnlineTime
)
{{
formatDate
(
device
.
lastOnlineTime
)
}}
}}
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"当前状态"
>
<el-descriptions-item
label=
"当前状态"
>
<dict-tag
:type=
"DICT_TYPE.IOT_DEVICE_STATUS"
:value=
"device.status"
/>
<dict-tag
:type=
"DICT_TYPE.IOT_DEVICE_STATUS"
:value=
"device.status"
/>
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"最后离线时间"
:span=
"3"
>
{{
<el-descriptions-item
label=
"最后离线时间"
:span=
"3"
>
formatDate
(
device
.
lastOfflineTime
)
{{
formatDate
(
device
.
lastOfflineTime
)
}}
}}
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"MQTT 连接参数"
>
<el-descriptions-item
label=
"MQTT 连接参数"
>
<el-button
type=
"primary"
@
click=
"openMqttParams"
>
查看
</el-button>
<el-button
type=
"primary"
@
click=
"openMqttParams"
>
查看
</el-button>
</el-descriptions-item>
</el-descriptions-item>
...
@@ -53,7 +53,6 @@
...
@@ -53,7 +53,6 @@
</
template
>
</
template
>
</el-input>
</el-input>
</el-form-item>
</el-form-item>
<el-form-item
label=
"username"
>
<el-form-item
label=
"username"
>
<el-input
v-model=
"mqttParams.mqttUsername"
readonly
>
<el-input
v-model=
"mqttParams.mqttUsername"
readonly
>
<
template
#
append
>
<
template
#
append
>
...
@@ -63,7 +62,6 @@
...
@@ -63,7 +62,6 @@
</
template
>
</
template
>
</el-input>
</el-input>
</el-form-item>
</el-form-item>
<el-form-item
label=
"passwd"
>
<el-form-item
label=
"passwd"
>
<el-input
v-model=
"mqttParams.mqttPassword"
readonly
type=
"password"
>
<el-input
v-model=
"mqttParams.mqttPassword"
readonly
type=
"password"
>
<
template
#
append
>
<
template
#
append
>
...
@@ -87,39 +85,28 @@ import { ProductVO } from '@/api/iot/product'
...
@@ -87,39 +85,28 @@ import { ProductVO } from '@/api/iot/product'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
DeviceVO
}
from
'@/api/iot/device'
import
{
DeviceVO
}
from
'@/api/iot/device'
// 消息提示
const
message
=
useMessage
()
// 消息提示
const
message
=
useMessage
()
// 路由实例
const
router
=
useRouter
()
// 定义 Props
const
{
product
,
device
}
=
defineProps
<
{
product
:
ProductVO
;
device
:
DeviceVO
}
>
()
// 定义 Props
const
{
product
,
device
}
=
defineProps
<
{
product
:
ProductVO
;
device
:
DeviceVO
}
>
()
// 定义 Emits
const
emit
=
defineEmits
([
'refresh'
])
// 定义 Emits
const
emit
=
defineEmits
([
'refresh'
])
// 展示的折叠面板
const
activeNames
=
ref
([
'basicInfo'
])
// 展示的折叠面板
const
activeNames
=
ref
([
'basicInfo'
])
const
mqttDialogVisible
=
ref
(
false
)
// 定义 MQTT 弹框的可见性
const
mqttParams
=
ref
({
mqttClientId
:
''
,
mqttUsername
:
''
,
mqttPassword
:
''
})
// 定义 MQTT 参数对象
/
/ 复制到剪贴板方法
/
** 复制到剪贴板方法 */
const
copyToClipboard
=
(
text
:
string
)
=>
{
const
copyToClipboard
=
(
text
:
string
)
=>
{
navigator
.
clipboard
.
writeText
(
text
).
then
(()
=>
{
navigator
.
clipboard
.
writeText
(
text
).
then
(()
=>
{
message
.
success
(
'复制成功'
)
message
.
success
(
'复制成功'
)
})
})
}
}
// 定义 MQTT 弹框的可见性
/** 打开 MQTT 参数弹框的方法 */
const
mqttDialogVisible
=
ref
(
false
)
// 定义 MQTT 参数对象
const
mqttParams
=
ref
({
mqttClientId
:
''
,
mqttUsername
:
''
,
mqttPassword
:
''
})
// 打开 MQTT 参数弹框的方法
const
openMqttParams
=
()
=>
{
const
openMqttParams
=
()
=>
{
mqttParams
.
value
=
{
mqttParams
.
value
=
{
mqttClientId
:
device
.
mqttClientId
||
'N/A'
,
mqttClientId
:
device
.
mqttClientId
||
'N/A'
,
...
@@ -129,7 +116,7 @@ const openMqttParams = () => {
...
@@ -129,7 +116,7 @@ const openMqttParams = () => {
mqttDialogVisible
.
value
=
true
mqttDialogVisible
.
value
=
true
}
}
/
/ 关闭 MQTT 弹框的方法
/
** 关闭 MQTT 弹框的方法 */
const
handleCloseMqttDialog
=
()
=>
{
const
handleCloseMqttDialog
=
()
=>
{
mqttDialogVisible
.
value
=
false
mqttDialogVisible
.
value
=
false
}
}
...
...
src/views/iot/device/index.vue
View file @
6d641177
...
@@ -192,9 +192,8 @@ const queryParams = reactive({
...
@@ -192,9 +192,8 @@ const queryParams = reactive({
status
:
undefined
status
:
undefined
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
/** 产品
ID到
名称的映射 */
/** 产品
标号和
名称的映射 */
const
productMap
=
reactive
({})
const
productMap
=
reactive
({})
/** 查询列表 */
/** 查询列表 */
...
@@ -207,6 +206,7 @@ const getList = async () => {
...
@@ -207,6 +206,7 @@ const getList = async () => {
// 获取产品ID列表
// 获取产品ID列表
const
productIds
=
[...
new
Set
(
data
.
list
.
map
((
device
)
=>
device
.
productId
))]
const
productIds
=
[...
new
Set
(
data
.
list
.
map
((
device
)
=>
device
.
productId
))]
// 获取产品名称
// 获取产品名称
// TODO @haohao:最好后端拼接哈
const
products
=
await
Promise
.
all
(
productIds
.
map
((
id
)
=>
ProductApi
.
getProduct
(
id
)))
const
products
=
await
Promise
.
all
(
productIds
.
map
((
id
)
=>
ProductApi
.
getProduct
(
id
)))
products
.
forEach
((
product
)
=>
{
products
.
forEach
((
product
)
=>
{
productMap
[
product
.
id
]
=
product
.
name
productMap
[
product
.
id
]
=
product
.
name
...
@@ -235,7 +235,7 @@ const openForm = (type: string, id?: number) => {
...
@@ -235,7 +235,7 @@ const openForm = (type: string, id?: number) => {
}
}
/** 打开详情 */
/** 打开详情 */
const
{
currentRoute
,
push
}
=
useRouter
()
const
{
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'IoTDeviceDetail'
,
params
:
{
id
}
})
push
({
name
:
'IoTDeviceDetail'
,
params
:
{
id
}
})
}
}
...
@@ -252,6 +252,7 @@ const handleDelete = async (id: number) => {
...
@@ -252,6 +252,7 @@ const handleDelete = async (id: number) => {
await
getList
()
await
getList
()
}
catch
{}
}
catch
{}
}
}
/** 查询字典下拉列表 */
/** 查询字典下拉列表 */
const
products
=
ref
()
const
products
=
ref
()
const
getProducts
=
async
()
=>
{
const
getProducts
=
async
()
=>
{
...
...
src/views/iot/product/ProductForm.vue
View file @
6d641177
...
@@ -128,15 +128,10 @@ const formData = ref({
...
@@ -128,15 +128,10 @@ const formData = ref({
})
})
const
formRules
=
reactive
({
const
formRules
=
reactive
({
name
:
[{
required
:
true
,
message
:
'产品名称不能为空'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'产品名称不能为空'
,
trigger
:
'blur'
}],
deviceType
:
[
deviceType
:
[{
required
:
true
,
message
:
'设备类型不能为空'
,
trigger
:
'change'
}],
{
required
:
true
,
message
:
'设备类型不能为空'
,
trigger
:
'change'
}
],
netType
:
[
netType
:
[
{
{
// TODO @haohao:0、1、/2 最好前端也枚举下;另外,这里的 required 可以直接设置为 true。然后表单那些 v-if。只要不存在,它自动就不校验了哈
required
:
formData
.
deviceType
===
0
||
formData
.
deviceType
===
2
,
required
:
formData
.
deviceType
===
0
||
formData
.
deviceType
===
2
,
message
:
'联网方式不能为空'
,
message
:
'联网方式不能为空'
,
trigger
:
'change'
trigger
:
'change'
...
@@ -145,23 +140,12 @@ const formRules = reactive({
...
@@ -145,23 +140,12 @@ const formRules = reactive({
protocolType
:
[
protocolType
:
[
{
required
:
formData
.
deviceType
===
1
,
message
:
'接入网关协议不能为空'
,
trigger
:
'change'
}
{
required
:
formData
.
deviceType
===
1
,
message
:
'接入网关协议不能为空'
,
trigger
:
'change'
}
],
],
dataFormat
:
[
dataFormat
:
[{
required
:
true
,
message
:
'数据格式不能为空'
,
trigger
:
'change'
}],
{
validateType
:
[{
required
:
true
,
message
:
'数据校验级别不能为空'
,
trigger
:
'change'
}]
required
:
true
,
message
:
'数据格式不能为空'
,
trigger
:
'change'
}
],
validateType
:
[
{
required
:
true
,
message
:
'数据校验级别不能为空'
,
trigger
:
'change'
}
]
})
})
const
formRef
=
ref
()
const
formRef
=
ref
()
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
dialogTitle
.
value
=
t
(
'action.'
+
type
)
dialogTitle
.
value
=
t
(
'action.'
+
type
)
...
@@ -178,6 +162,7 @@ const open = async (type: string, id?: number) => {
...
@@ -178,6 +162,7 @@ const open = async (type: string, id?: number) => {
}
}
defineExpose
({
open
,
close
:
()
=>
(
dialogVisible
.
value
=
false
)
})
defineExpose
({
open
,
close
:
()
=>
(
dialogVisible
.
value
=
false
)
})
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
const
emit
=
defineEmits
([
'success'
])
const
submitForm
=
async
()
=>
{
const
submitForm
=
async
()
=>
{
await
formRef
.
value
.
validate
()
await
formRef
.
value
.
validate
()
...
@@ -198,6 +183,7 @@ const submitForm = async () => {
...
@@ -198,6 +183,7 @@ const submitForm = async () => {
}
}
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
const
resetForm
=
()
=>
{
formData
.
value
=
{
formData
.
value
=
{
name
:
undefined
,
name
:
undefined
,
...
...
src/views/iot/product/detail/ProductDetailsHeader.vue
View file @
6d641177
...
@@ -58,19 +58,24 @@ import ProductForm from '@/views/iot/product/ProductForm.vue'
...
@@ -58,19 +58,24 @@ import ProductForm from '@/views/iot/product/ProductForm.vue'
import
{
ProductApi
,
ProductVO
}
from
'@/api/iot/product'
import
{
ProductApi
,
ProductVO
}
from
'@/api/iot/product'
const
message
=
useMessage
()
const
message
=
useMessage
()
const
{
product
}
=
defineProps
<
{
product
:
ProductVO
}
>
()
// 定义 Props
/** 处理复制 */
const
copyToClipboard
=
(
text
:
string
)
=>
{
const
copyToClipboard
=
(
text
:
string
)
=>
{
navigator
.
clipboard
.
writeText
(
text
).
then
(()
=>
{
navigator
.
clipboard
.
writeText
(
text
).
then
(()
=>
{
message
.
success
(
'复制成功'
)
message
.
success
(
'复制成功'
)
})
})
}
}
/
/ 路由跳转到设备管理
/
** 路由跳转到设备管理 */
const
{
currentRoute
,
push
}
=
useRouter
()
const
{
push
}
=
useRouter
()
const
goToManagement
=
(
productId
:
string
)
=>
{
const
goToManagement
=
(
productId
:
string
)
=>
{
push
({
name
:
'IoTDevice'
,
query
:
{
productId
}
})
push
({
name
:
'IoTDevice'
,
query
:
{
productId
}
})
}
}
// 操作修改
/** 操作修改 */
const
emit
=
defineEmits
([
'refresh'
])
// 定义 Emits
const
formRef
=
ref
()
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
formRef
.
value
.
open
(
type
,
id
)
...
@@ -95,10 +100,4 @@ const confirmUnpublish = async (id: number) => {
...
@@ -95,10 +100,4 @@ const confirmUnpublish = async (id: number) => {
message
.
error
(
'撤销发布失败'
)
message
.
error
(
'撤销发布失败'
)
}
}
}
}
// 定义 Props
const
{
product
}
=
defineProps
<
{
product
:
ProductVO
}
>
()
// 定义 Emits
const
emit
=
defineEmits
([
'refresh'
])
</
script
>
</
script
>
src/views/iot/product/detail/ProductDetailsInfo.vue
View file @
6d641177
...
@@ -6,9 +6,9 @@
...
@@ -6,9 +6,9 @@
<el-descriptions-item
label=
"设备类型"
>
<el-descriptions-item
label=
"设备类型"
>
<dict-tag
:type=
"DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE"
:value=
"product.deviceType"
/>
<dict-tag
:type=
"DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE"
:value=
"product.deviceType"
/>
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"创建时间"
>
{{
<el-descriptions-item
label=
"创建时间"
>
formatDate
(
product
.
createTime
)
{{
formatDate
(
product
.
createTime
)
}}
}}
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"数据格式"
>
<el-descriptions-item
label=
"数据格式"
>
<dict-tag
:type=
"DICT_TYPE.IOT_DATA_FORMAT"
:value=
"product.dataFormat"
/>
<dict-tag
:type=
"DICT_TYPE.IOT_DATA_FORMAT"
:value=
"product.dataFormat"
/>
</el-descriptions-item>
</el-descriptions-item>
...
...
src/views/iot/product/detail/ProductTopic.vue
View file @
6d641177
...
@@ -44,6 +44,7 @@ const columns2 = reactive([
...
@@ -44,6 +44,7 @@ const columns2 = reactive([
{
label
:
'描述'
,
field
:
'description'
}
{
label
:
'描述'
,
field
:
'description'
}
])
])
// TODO @haohao:这个,有没可能写到一个枚举里,方便后续维护? /Users/yunai/Java/yudao-ui-admin-vue3/src/views/ai/utils/constants.ts
const
data1
=
computed
(()
=>
{
const
data1
=
computed
(()
=>
{
if
(
!
props
.
product
||
!
props
.
product
.
productKey
)
return
[]
if
(
!
props
.
product
||
!
props
.
product
.
productKey
)
return
[]
return
[
return
[
...
...
src/views/iot/product/detail/ThinkModelFunction.vue
View file @
6d641177
...
@@ -88,6 +88,7 @@ import ThinkModelFunctionForm from '@/views/iot/product/detail/ThinkModelFunctio
...
@@ -88,6 +88,7 @@ import ThinkModelFunctionForm from '@/views/iot/product/detail/ThinkModelFunctio
const
props
=
defineProps
<
{
product
:
ProductVO
}
>
()
const
props
=
defineProps
<
{
product
:
ProductVO
}
>
()
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
message
=
useMessage
()
// 消息弹窗
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
...
@@ -97,7 +98,7 @@ const queryParams = reactive({
...
@@ -97,7 +98,7 @@ const queryParams = reactive({
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
type
:
undefined
,
type
:
undefined
,
productId
:
undefined
productId
:
-
1
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
...
...
src/views/iot/product/detail/ThinkModelFunctionForm.vue
View file @
6d641177
...
@@ -46,7 +46,6 @@
...
@@ -46,7 +46,6 @@
<span
class=
"mx-2"
>
~
</span>
<span
class=
"mx-2"
>
~
</span>
<el-input
v-model=
"formData.property.dataType.specs.max"
placeholder=
"请输入最大值"
/>
<el-input
v-model=
"formData.property.dataType.specs.max"
placeholder=
"请输入最大值"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"步长"
prop=
"step"
>
<el-form-item
label=
"步长"
prop=
"step"
>
<el-input
v-model=
"formData.property.dataType.specs.step"
placeholder=
"请输入步长"
/>
<el-input
v-model=
"formData.property.dataType.specs.step"
placeholder=
"请输入步长"
/>
</el-form-item>
</el-form-item>
...
@@ -77,7 +76,6 @@
...
@@ -77,7 +76,6 @@
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ProductVO
}
from
'@/api/iot/product'
import
{
ProductVO
}
from
'@/api/iot/product'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
ThinkModelFunctionApi
,
ThinkModelFunctionVO
}
from
'@/api/iot/thinkmodelfunction'
import
{
ThinkModelFunctionApi
,
ThinkModelFunctionVO
}
from
'@/api/iot/thinkmodelfunction'
const
props
=
defineProps
<
{
product
:
ProductVO
}
>
()
const
props
=
defineProps
<
{
product
:
ProductVO
}
>
()
...
@@ -159,6 +157,7 @@ const formRules = reactive({
...
@@ -159,6 +157,7 @@ const formRules = reactive({
})
})
const
formRef
=
ref
()
const
formRef
=
ref
()
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
dialogTitle
.
value
=
t
(
'action.'
+
type
)
dialogTitle
.
value
=
t
(
'action.'
+
type
)
...
@@ -175,6 +174,7 @@ const open = async (type: string, id?: number) => {
...
@@ -175,6 +174,7 @@ const open = async (type: string, id?: number) => {
}
}
defineExpose
({
open
,
close
:
()
=>
(
dialogVisible
.
value
=
false
)
})
defineExpose
({
open
,
close
:
()
=>
(
dialogVisible
.
value
=
false
)
})
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
const
emit
=
defineEmits
([
'success'
])
const
submitForm
=
async
()
=>
{
const
submitForm
=
async
()
=>
{
await
formRef
.
value
.
validate
()
await
formRef
.
value
.
validate
()
...
@@ -197,6 +197,7 @@ const submitForm = async () => {
...
@@ -197,6 +197,7 @@ const submitForm = async () => {
}
}
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
const
resetForm
=
()
=>
{
formData
.
value
=
{
formData
.
value
=
{
id
:
undefined
,
id
:
undefined
,
...
@@ -205,7 +206,7 @@ const resetForm = () => {
...
@@ -205,7 +206,7 @@ const resetForm = () => {
identifier
:
undefined
,
identifier
:
undefined
,
name
:
undefined
,
name
:
undefined
,
description
:
undefined
,
description
:
undefined
,
type
:
'1'
,
type
:
'1'
,
// todo @HAOHAO:看看枚举下
property
:
{
property
:
{
identifier
:
undefined
,
identifier
:
undefined
,
name
:
undefined
,
name
:
undefined
,
...
...
src/views/iot/product/detail/index.vue
View file @
6d641177
...
@@ -23,9 +23,14 @@ import ProductDetailsHeader from '@/views/iot/product/detail/ProductDetailsHeade
...
@@ -23,9 +23,14 @@ import ProductDetailsHeader from '@/views/iot/product/detail/ProductDetailsHeade
import
ProductDetailsInfo
from
'@/views/iot/product/detail/ProductDetailsInfo.vue'
import
ProductDetailsInfo
from
'@/views/iot/product/detail/ProductDetailsInfo.vue'
import
ProductTopic
from
'@/views/iot/product/detail/ProductTopic.vue'
import
ProductTopic
from
'@/views/iot/product/detail/ProductTopic.vue'
import
ThinkModelFunction
from
'@/views/iot/product/detail/ThinkModelFunction.vue'
import
ThinkModelFunction
from
'@/views/iot/product/detail/ThinkModelFunction.vue'
import
{
useTagsViewStore
}
from
'@/store/modules/tagsView'
import
{
useRouter
}
from
'vue-router'
defineOptions
({
name
:
'IoTProductDetail'
})
defineOptions
({
name
:
'IoTProductDetail'
})
const
{
delView
}
=
useTagsViewStore
()
// 视图操作
const
{
currentRoute
}
=
useRouter
()
const
route
=
useRoute
()
const
route
=
useRoute
()
const
message
=
useMessage
()
const
message
=
useMessage
()
const
id
=
Number
(
route
.
params
.
id
)
// 编号
const
id
=
Number
(
route
.
params
.
id
)
// 编号
...
@@ -45,7 +50,7 @@ const getProductData = async (id: number) => {
...
@@ -45,7 +50,7 @@ const getProductData = async (id: number) => {
}
}
// 查询设备数量
// 查询设备数量
const
getDeviceCount
=
async
(
productId
:
string
)
=>
{
const
getDeviceCount
=
async
(
productId
:
number
)
=>
{
try
{
try
{
const
count
=
await
DeviceApi
.
getDeviceCount
(
productId
)
const
count
=
await
DeviceApi
.
getDeviceCount
(
productId
)
console
.
log
(
'Device count response:'
,
count
)
console
.
log
(
'Device count response:'
,
count
)
...
...
src/views/iot/product/index.vue
View file @
6d641177
...
@@ -104,7 +104,6 @@
...
@@ -104,7 +104,6 @@
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
download
from
'@/utils/download'
import
{
ProductApi
,
ProductVO
}
from
'@/api/iot/product'
import
{
ProductApi
,
ProductVO
}
from
'@/api/iot/product'
import
ProductForm
from
'./ProductForm.vue'
import
ProductForm
from
'./ProductForm.vue'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
DICT_TYPE
}
from
'@/utils/dict'
...
@@ -135,7 +134,6 @@ const queryParams = reactive({
...
@@ -135,7 +134,6 @@ const queryParams = reactive({
dataFormat
:
undefined
dataFormat
:
undefined
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
...
@@ -168,7 +166,7 @@ const openForm = (type: string, id?: number) => {
...
@@ -168,7 +166,7 @@ const openForm = (type: string, id?: number) => {
}
}
/** 打开详情 */
/** 打开详情 */
const
{
currentRoute
,
push
}
=
useRouter
()
const
{
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'IoTProductDetail'
,
params
:
{
id
}
})
push
({
name
:
'IoTProductDetail'
,
params
:
{
id
}
})
}
}
...
@@ -186,21 +184,6 @@ const handleDelete = async (id: number) => {
...
@@ -186,21 +184,6 @@ const handleDelete = async (id: number) => {
}
catch
{}
}
catch
{}
}
}
/** 导出按钮操作 */
const
handleExport
=
async
()
=>
{
try
{
// 导出的二次确认
await
message
.
exportConfirm
()
// 发起导出
exportLoading
.
value
=
true
const
data
=
await
ProductApi
.
exportProduct
(
queryParams
)
download
.
excel
(
data
,
'iot 产品.xls'
)
}
catch
{
}
finally
{
exportLoading
.
value
=
false
}
}
/** 初始化 **/
/** 初始化 **/
onMounted
(()
=>
{
onMounted
(()
=>
{
getList
()
getList
()
...
...
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