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
63a0e5dc
authored
Sep 22, 2024
by
安浩浩
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【优化】 IOT 设备管理
parent
b69a784e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
95 additions
and
62 deletions
+95
-62
src/api/iot/device/index.ts
+19
-10
src/views/iot/device/DeviceForm.vue
+39
-3
src/views/iot/device/index.vue
+37
-49
No files found.
src/api/iot/device/index.ts
View file @
63a0e5dc
import
request
from
'@/config/axios'
import
request
from
'@/config/axios'
//
IoT
设备 VO
// 设备 VO
export
interface
DeviceVO
{
export
interface
DeviceVO
{
id
:
number
// 设备 ID,主键,自增
id
:
number
// 设备 ID,主键,自增
deviceKey
:
string
// 设备唯一标识符,全局唯一,用于识别设备
deviceKey
:
string
// 设备唯一标识符,全局唯一,用于识别设备
...
@@ -29,35 +29,45 @@ export interface DeviceVO {
...
@@ -29,35 +29,45 @@ export interface DeviceVO {
serialNumber
:
string
// 设备序列号
serialNumber
:
string
// 设备序列号
}
}
// IoT 设备 API
export
interface
DeviceUpdateStatusVO
{
id
:
number
// 设备 ID,主键,自增
status
:
number
// 设备状态:0 - 未激活,1 - 在线,2 - 离线,3 - 已禁用
}
// 设备 API
export
const
DeviceApi
=
{
export
const
DeviceApi
=
{
// 查询
IoT
设备分页
// 查询设备分页
getDevicePage
:
async
(
params
:
any
)
=>
{
getDevicePage
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/iot/device/page`
,
params
})
return
await
request
.
get
({
url
:
`/iot/device/page`
,
params
})
},
},
// 查询
IoT
设备详情
// 查询设备详情
getDevice
:
async
(
id
:
number
)
=>
{
getDevice
:
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
`/iot/device/get?id=`
+
id
})
return
await
request
.
get
({
url
:
`/iot/device/get?id=`
+
id
})
},
},
// 新增
IoT
设备
// 新增设备
createDevice
:
async
(
data
:
DeviceVO
)
=>
{
createDevice
:
async
(
data
:
DeviceVO
)
=>
{
return
await
request
.
post
({
url
:
`/iot/device/create`
,
data
})
return
await
request
.
post
({
url
:
`/iot/device/create`
,
data
})
},
},
// 修改
IoT
设备
// 修改设备
updateDevice
:
async
(
data
:
DeviceVO
)
=>
{
updateDevice
:
async
(
data
:
DeviceVO
)
=>
{
return
await
request
.
put
({
url
:
`/iot/device/update`
,
data
})
return
await
request
.
put
({
url
:
`/iot/device/update`
,
data
})
},
},
// 删除IoT 设备
// 修改设备状态
updateDeviceStatus
:
async
(
data
:
DeviceUpdateStatusVO
)
=>
{
return
await
request
.
put
({
url
:
`/iot/device/update-status`
,
data
})
},
// 删除设备
deleteDevice
:
async
(
id
:
number
)
=>
{
deleteDevice
:
async
(
id
:
number
)
=>
{
return
await
request
.
delete
({
url
:
`/iot/device/delete?id=`
+
id
})
return
await
request
.
delete
({
url
:
`/iot/device/delete?id=`
+
id
})
},
},
// 导出
IoT
设备 Excel
// 导出设备 Excel
exportDevice
:
async
(
params
)
=>
{
exportDevice
:
async
(
params
)
=>
{
return
await
request
.
download
({
url
:
`/iot/device/export-excel`
,
params
})
return
await
request
.
download
({
url
:
`/iot/device/export-excel`
,
params
})
}
}
}
}
\ No newline at end of file
src/views/iot/device/DeviceForm.vue
View file @
63a0e5dc
...
@@ -8,7 +8,12 @@
...
@@ -8,7 +8,12 @@
v-loading=
"formLoading"
v-loading=
"formLoading"
>
>
<el-form-item
label=
"产品"
prop=
"productId"
>
<el-form-item
label=
"产品"
prop=
"productId"
>
<el-select
v-model=
"formData.productId"
placeholder=
"请选择产品"
clearable
>
<el-select
v-model=
"formData.productId"
placeholder=
"请选择产品"
:disabled=
"formType === 'update'"
clearable
>
<el-option
<el-option
v-for=
"product in products"
v-for=
"product in products"
:key=
"product.id"
:key=
"product.id"
...
@@ -18,7 +23,11 @@
...
@@ -18,7 +23,11 @@
</el-select>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"DeviceName"
prop=
"deviceName"
>
<el-form-item
label=
"DeviceName"
prop=
"deviceName"
>
<el-input
v-model=
"formData.deviceName"
placeholder=
"请输入 DeviceName"
/>
<el-input
v-model=
"formData.deviceName"
placeholder=
"请输入 DeviceName"
:disabled=
"formType === 'update'"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"备注名称"
prop=
"nickname"
>
<el-form-item
label=
"备注名称"
prop=
"nickname"
>
<el-input
v-model=
"formData.nickname"
placeholder=
"请输入备注名称"
/>
<el-input
v-model=
"formData.nickname"
placeholder=
"请输入备注名称"
/>
...
@@ -52,7 +61,34 @@ const formData = ref({
...
@@ -52,7 +61,34 @@ const formData = ref({
serialNumber
:
undefined
serialNumber
:
undefined
})
})
const
formRules
=
reactive
({
const
formRules
=
reactive
({
productId
:
[{
required
:
true
,
message
:
'产品不能为空'
,
trigger
:
'blur'
}]
productId
:
[{
required
:
true
,
message
:
'产品不能为空'
,
trigger
:
'blur'
}],
deviceName
:
[
{
pattern
:
/^
[
a-zA-Z0-9_.
\-
:@
]{4,32}
$/
,
message
:
'支持英文字母、数字、下划线(_)、中划线(-)、点号(.)、半角冒号(:)和特殊字符@,长度限制为4~32个字符'
,
trigger
:
'blur'
}
],
nickname
:
[
{
validator
:
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
undefined
||
value
===
null
)
{
callback
()
return
}
const
length
=
value
.
replace
(
/
[\u
4e00-
\u
9fa5
\u
3040-
\u
30ff
]
/g
,
'aa'
).
length
if
(
length
<
4
||
length
>
64
)
{
callback
(
new
Error
(
'备注名称长度限制为4~64个字符,中文及日文算2个字符'
))
}
else
if
(
!
/^
[\u
4e00-
\u
9fa5
\u
3040-
\u
30ff_a-zA-Z0-9
]
+$/
.
test
(
value
))
{
callback
(
new
Error
(
'备注名称只能包含中文、英文字母、日文、数字和下划线(_)'
))
}
else
{
callback
()
}
},
trigger
:
'blur'
}
]
})
})
const
formRef
=
ref
()
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
...
...
src/views/iot/device/index.vue
View file @
63a0e5dc
...
@@ -72,24 +72,22 @@
...
@@ -72,24 +72,22 @@
</el-select>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
><Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"handleQuery"
>
<el-button
@
click=
"resetQuery"
><Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
<el-button
type=
"primary"
type=
"primary"
plain
plain
@
click=
"openForm('create')"
@
click=
"openForm('create')"
v-hasPermi=
"['iot:device:create']"
v-hasPermi=
"['iot:device:create']"
>
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
新增
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
</el-button>
新增
<el-button
type=
"success"
plain
@
click=
"handleExport"
:loading=
"exportLoading"
v-hasPermi=
"['iot:device:export']"
>
<Icon
icon=
"ep:download"
class=
"mr-5px"
/>
导出
</el-button>
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
...
@@ -100,9 +98,21 @@
...
@@ -100,9 +98,21 @@
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table-column
label=
"DeviceName"
align=
"center"
prop=
"deviceName"
/>
<el-table-column
label=
"DeviceName"
align=
"center"
prop=
"deviceName"
/>
<el-table-column
label=
"备注名称"
align=
"center"
prop=
"nickname"
/>
<el-table-column
label=
"备注名称"
align=
"center"
prop=
"nickname"
/>
<el-table-column
label=
"设备所属产品"
align=
"center"
prop=
"productName"
/>
<el-table-column
label=
"设备所属产品"
align=
"center"
prop=
"productId"
>
<el-table-column
label=
"设备类型"
align=
"center"
prop=
"deviceType"
/>
<template
#
default=
"scope"
>
<el-table-column
label=
"设备状态"
align=
"center"
prop=
"status"
/>
{{
productMap
[
scope
.
row
.
productId
]
}}
</
template
>
</el-table-column>
<el-table-column
label=
"设备类型"
align=
"center"
prop=
"deviceType"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE"
:value=
"scope.row.deviceType"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"设备状态"
align=
"center"
prop=
"status"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.IOT_DEVICE_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
<el-table-column
<el-table-column
label=
"最后上线时间"
label=
"最后上线时间"
align=
"center"
align=
"center"
...
@@ -110,18 +120,6 @@
...
@@ -110,18 +120,6 @@
:formatter=
"dateFormatter"
:formatter=
"dateFormatter"
width=
"180px"
width=
"180px"
/>
/>
<el-table-column
label=
"启用禁用"
>
<template
#
default=
"scope"
>
<el-switch
v-model=
"scope.row.status"
active-value=
"1"
inactive-value=
"0"
active-text=
"启用"
inactive-text=
"禁用"
@
change=
"handleUpdate(scope.row)"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
min-width=
"120px"
>
<el-table-column
label=
"操作"
align=
"center"
min-width=
"120px"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<el-button
<el-button
...
@@ -160,7 +158,7 @@
...
@@ -160,7 +158,7 @@
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
download
from
'@/utils/download'
import
download
from
'@/utils/download'
import
{
DeviceApi
,
DeviceVO
}
from
'@/api/iot/device'
import
{
DeviceApi
,
Device
UpdateStatusVO
,
Device
VO
}
from
'@/api/iot/device'
import
DeviceForm
from
'./DeviceForm.vue'
import
DeviceForm
from
'./DeviceForm.vue'
import
{
ProductApi
}
from
'@/api/iot/product'
import
{
ProductApi
}
from
'@/api/iot/product'
...
@@ -176,35 +174,18 @@ const total = ref(0) // 列表的总页数
...
@@ -176,35 +174,18 @@ const total = ref(0) // 列表的总页数
const
queryParams
=
reactive
({
const
queryParams
=
reactive
({
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
deviceKey
:
undefined
,
deviceName
:
undefined
,
deviceName
:
undefined
,
productId
:
undefined
,
productId
:
undefined
,
productKey
:
undefined
,
deviceType
:
undefined
,
deviceType
:
undefined
,
nickname
:
undefined
,
nickname
:
undefined
,
gatewayId
:
undefined
,
status
:
undefined
status
:
undefined
,
statusLastUpdateTime
:
[],
lastOnlineTime
:
[],
lastOfflineTime
:
[],
activeTime
:
[],
ip
:
undefined
,
firmwareVersion
:
undefined
,
deviceSecret
:
undefined
,
mqttClientId
:
undefined
,
mqttUsername
:
undefined
,
mqttPassword
:
undefined
,
authType
:
undefined
,
latitude
:
undefined
,
longitude
:
undefined
,
areaId
:
undefined
,
address
:
undefined
,
serialNumber
:
undefined
,
createTime
:
[]
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
exportLoading
=
ref
(
false
)
// 导出的加载中
/** 产品ID到名称的映射 */
const
productMap
=
reactive
({})
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
loading
.
value
=
true
loading
.
value
=
true
...
@@ -212,6 +193,13 @@ const getList = async () => {
...
@@ -212,6 +193,13 @@ const getList = async () => {
const
data
=
await
DeviceApi
.
getDevicePage
(
queryParams
)
const
data
=
await
DeviceApi
.
getDevicePage
(
queryParams
)
list
.
value
=
data
.
list
list
.
value
=
data
.
list
total
.
value
=
data
.
total
total
.
value
=
data
.
total
// 获取产品ID列表
const
productIds
=
[...
new
Set
(
data
.
list
.
map
((
device
)
=>
device
.
productId
))]
// 获取产品名称
const
products
=
await
Promise
.
all
(
productIds
.
map
((
id
)
=>
ProductApi
.
getProduct
(
id
)))
products
.
forEach
((
product
)
=>
{
productMap
[
product
.
id
]
=
product
.
name
})
}
finally
{
}
finally
{
loading
.
value
=
false
loading
.
value
=
false
}
}
...
...
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