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
5391720b
authored
Dec 25, 2024
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【功能完善】IOT: ThingModel 服务和事件
parent
d7c33b45
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
331 additions
and
86 deletions
+331
-86
src/api/iot/thingmodel/index.ts
+0
-53
src/views/iot/thingmodel/ThingModelEvent.vue
+16
-8
src/views/iot/thingmodel/ThingModelForm.vue
+14
-4
src/views/iot/thingmodel/ThingModelInputOutputParam.vue
+153
-0
src/views/iot/thingmodel/ThingModelProperty.vue
+10
-14
src/views/iot/thingmodel/ThingModelService.vue
+15
-1
src/views/iot/thingmodel/config.ts
+61
-1
src/views/iot/thingmodel/index.vue
+62
-5
No files found.
src/api/iot/thingmodel/index.ts
View file @
5391720b
...
...
@@ -38,59 +38,6 @@ export interface ThingModelService {
[
key
:
string
]:
any
}
// IOT 产品物模型类型枚举类
export
const
ThingModelType
=
{
PROPERTY
:
1
,
// 属性
SERVICE
:
2
,
// 服务
EVENT
:
3
// 事件
}
as
const
// IOT 产品物模型访问模式枚举类
export
const
ThingModelAccessMode
=
{
READ_WRITE
:
{
label
:
'读写'
,
value
:
'rw'
},
READ_ONLY
:
{
label
:
'只读'
,
value
:
'r'
}
}
as
const
// IOT 产品物模型服务调用方式枚举
export
const
ThingModelServiceCallType
=
{
ASYNC
:
{
label
:
'异步调用'
,
value
:
'async'
},
SYNC
:
{
label
:
'同步调用'
,
value
:
'sync'
}
}
as
const
// IOT 产品物模型事件类型枚举
export
const
ThingModelServiceEventType
=
{
INFO
:
{
label
:
'信息'
,
value
:
'info'
},
ALERT
:
{
label
:
'告警'
,
value
:
'alert'
},
ERROR
:
{
label
:
'故障'
,
value
:
'error'
}
}
as
const
// IOT 产品物模型参数是输入参数还是输出参数
export
const
ThingModelParamDirection
=
{
INPUT
:
'input'
,
// 输入参数
OUTPUT
:
'output'
// 输出参数
}
as
const
// IoT 产品物模型 API
export
const
ThingModelApi
=
{
// 查询产品物模型分页
...
...
src/views/iot/thingmodel/ThingModelEvent.vue
View file @
5391720b
...
...
@@ -2,25 +2,33 @@
<el-form-item
:rules=
"[
{ required: true, message: '请选择事件类型', trigger: 'change' }]"
label="事件类型"
prop="
thingModelE
vent.type"
prop="
e
vent.type"
>
<el-radio-group
v-model=
"thingModelEvent.type"
>
<el-radio
:value=
"ThingModel
Service
EventType.INFO.value"
>
{{
ThingModel
Service
EventType
.
INFO
.
label
}}
<el-radio
:value=
"ThingModelEventType.INFO.value"
>
{{
ThingModelEventType
.
INFO
.
label
}}
</el-radio>
<el-radio
:value=
"ThingModel
Service
EventType.ALERT.value"
>
{{
ThingModel
Service
EventType
.
ALERT
.
label
}}
<el-radio
:value=
"ThingModelEventType.ALERT.value"
>
{{
ThingModelEventType
.
ALERT
.
label
}}
</el-radio>
<el-radio
:value=
"ThingModel
Service
EventType.ERROR.value"
>
{{
ThingModel
Service
EventType
.
ERROR
.
label
}}
<el-radio
:value=
"ThingModelEventType.ERROR.value"
>
{{
ThingModelEventType
.
ERROR
.
label
}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"输出参数"
>
<ThingModelInputOutputParam
v-model=
"thingModelEvent.outputParams"
:direction=
"ThingModelParamDirection.OUTPUT"
/>
</el-form-item>
</
template
>
<
script
lang=
"ts"
setup
>
import
ThingModelInputOutputParam
from
'./ThingModelInputOutputParam.vue'
import
{
useVModel
}
from
'@vueuse/core'
import
{
ThingModelEvent
,
ThingModelServiceEventType
}
from
'@/api/iot/thingmodel'
import
{
ThingModelEvent
}
from
'@/api/iot/thingmodel'
import
{
ThingModelParamDirection
,
ThingModelEventType
}
from
'./config'
/** IoT 物模型事件 */
defineOptions
({
name
:
'ThingModelEvent'
})
...
...
src/views/iot/thingmodel/ThingModelForm.vue
View file @
5391720b
...
...
@@ -36,6 +36,15 @@
/>
<!-- 事件配置 -->
<ThingModelEvent
v-if=
"formData.type === ThingModelType.EVENT"
v-model=
"formData.event"
/>
<el-form-item
label=
"描述"
prop=
"description"
>
<el-input
v-model=
"formData.description"
:maxlength=
"200"
:rows=
"3"
placeholder=
"请输入属性描述"
type=
"textarea"
/>
</el-form-item>
</el-form>
<template
#
footer
>
...
...
@@ -50,9 +59,9 @@ import { ProductVO } from '@/api/iot/product/product'
import
ThingModelProperty
from
'./ThingModelProperty.vue'
import
ThingModelService
from
'./ThingModelService.vue'
import
ThingModelEvent
from
'./ThingModelEvent.vue'
import
{
ThingModelApi
,
ThingModelData
,
ThingModelType
}
from
'@/api/iot/thingmodel'
import
{
ThingModelApi
,
ThingModelData
}
from
'@/api/iot/thingmodel'
import
{
IOT_PROVIDE_KEY
}
from
'@/views/iot/utils/constants'
import
{
DataSpecsDataType
,
ThingModelFormRules
}
from
'./config'
import
{
DataSpecsDataType
,
ThingModelFormRules
,
ThingModelType
}
from
'./config'
import
{
cloneDeep
}
from
'lodash-es'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
isEmpty
}
from
'@/utils/is'
...
...
@@ -111,7 +120,6 @@ const submitForm = async () => {
// 信息补全
data
.
productId
=
product
!
.
value
.
id
data
.
productKey
=
product
!
.
value
.
productKey
data
.
description
=
data
.
property
.
description
data
.
dataType
=
data
.
property
.
dataType
data
.
property
.
identifier
=
data
.
identifier
data
.
property
.
name
=
data
.
name
...
...
@@ -164,7 +172,9 @@ const resetForm = () => {
dataSpecs
:
{
dataType
:
DataSpecsDataType
.
INT
}
}
},
service
:
{},
event
:
{}
}
formRef
.
value
?.
resetFields
()
}
...
...
src/views/iot/thingmodel/ThingModelInputOutputParam.vue
0 → 100644
View file @
5391720b
<
template
>
<div
v-for=
"(item, index) in thingModelParams"
:key=
"index"
class=
"w-1/1 param-item flex justify-between px-10px mb-10px"
>
<span>
参数名称:
{{
item
.
name
}}
</span>
<div
class=
"btn"
>
<el-button
link
type=
"primary"
@
click=
"openParamForm(item)"
>
编辑
</el-button>
<el-divider
direction=
"vertical"
/>
<el-button
link
type=
"danger"
@
click=
"deleteParamItem(index)"
>
删除
</el-button>
</div>
</div>
<el-button
link
type=
"primary"
@
click=
"openParamForm(null)"
>
+新增参数
</el-button>
<!-- param 表单 -->
<Dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
append-to-body
>
<el-form
ref=
"paramFormRef"
v-loading=
"formLoading"
:model=
"formData"
:rules=
"ThingModelFormRules"
label-width=
"100px"
>
<el-form-item
label=
"参数名称"
prop=
"name"
>
<el-input
v-model=
"formData.name"
placeholder=
"请输入功能名称"
/>
</el-form-item>
<el-form-item
label=
"标识符"
prop=
"identifier"
>
<el-input
v-model=
"formData.identifier"
placeholder=
"请输入标识符"
/>
</el-form-item>
<!-- 属性配置 -->
<ThingModelProperty
v-model=
"formData.property"
is-params
/>
</el-form>
<template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
{
useVModel
}
from
'@vueuse/core'
import
ThingModelProperty
from
'./ThingModelProperty.vue'
import
{
DataSpecsDataType
,
ThingModelFormRules
}
from
'./config'
import
{
isEmpty
}
from
'@/utils/is'
/** 输入输出参数配置组件 */
defineOptions
({
name
:
'ThingModelInputOutputParam'
})
const
props
=
defineProps
<
{
modelValue
:
any
;
direction
:
string
}
>
()
const
emits
=
defineEmits
([
'update:modelValue'
])
const
thingModelParams
=
useVModel
(
props
,
'modelValue'
,
emits
)
as
Ref
<
any
[]
>
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
dialogTitle
=
ref
(
'新增参数'
)
// 弹窗的标题
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
paramFormRef
=
ref
()
// 表单 ref
const
formData
=
ref
<
any
>
({
dataType
:
DataSpecsDataType
.
INT
,
property
:
{
dataType
:
DataSpecsDataType
.
INT
,
dataSpecs
:
{
dataType
:
DataSpecsDataType
.
INT
}
}
})
/** 打开 param 表单 */
const
openParamForm
=
(
val
:
any
)
=>
{
dialogVisible
.
value
=
true
resetForm
()
if
(
isEmpty
(
val
))
{
return
}
// 编辑时回显数据
formData
.
value
=
{
identifier
:
val
.
identifier
,
name
:
val
.
name
,
description
:
val
.
description
,
property
:
{
dataType
:
val
.
dataType
,
dataSpecs
:
val
.
dataSpecs
,
dataSpecsList
:
val
.
dataSpecsList
}
}
}
/** 删除 param 项 */
const
deleteParamItem
=
(
index
:
number
)
=>
{
thingModelParams
.
value
.
splice
(
index
,
1
)
}
/** 添加参数 */
const
submitForm
=
async
()
=>
{
// 初始化参数列表
if
(
isEmpty
(
thingModelParams
.
value
))
{
thingModelParams
.
value
=
[]
}
// 校验参数
await
paramFormRef
.
value
.
validate
()
try
{
const
data
=
unref
(
formData
)
// 构建数据对象
const
item
=
{
identifier
:
data
.
identifier
,
name
:
data
.
name
,
description
:
data
.
description
,
dataType
:
data
.
property
.
dataType
,
paraOrder
:
0
,
// TODO @puhui999: 先写死默认看看后续
direction
:
props
.
direction
,
dataSpecs
:
!!
data
.
property
.
dataSpecs
&&
Object
.
keys
(
data
.
property
.
dataSpecs
).
length
>
1
?
data
.
property
.
dataSpecs
:
undefined
,
dataSpecsList
:
isEmpty
(
data
.
property
.
dataSpecsList
)
?
undefined
:
data
.
property
.
dataSpecsList
}
// 查找是否已有相同 identifier 的项
const
existingIndex
=
thingModelParams
.
value
.
findIndex
(
(
spec
)
=>
spec
.
identifier
===
data
.
identifier
)
if
(
existingIndex
>
-
1
)
{
// 更新已有项
thingModelParams
.
value
[
existingIndex
]
=
item
}
else
{
// 添加新项
thingModelParams
.
value
.
push
(
item
)
}
}
finally
{
// 隐藏对话框
dialogVisible
.
value
=
false
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
formData
.
value
=
{
dataType
:
DataSpecsDataType
.
INT
,
property
:
{
dataType
:
DataSpecsDataType
.
INT
,
dataSpecs
:
{
dataType
:
DataSpecsDataType
.
INT
}
}
}
paramFormRef
.
value
?.
resetFields
()
}
</
script
>
<
style
lang=
"scss"
scoped
>
.param-item
{
background-color
:
#e4f2fd
;
}
</
style
>
src/views/iot/thingmodel/ThingModelProperty.vue
View file @
5391720b
...
...
@@ -75,7 +75,7 @@
v-if=
"property.dataType === DataSpecsDataType.STRUCT"
v-model=
"property.dataSpecsList"
/>
<el-form-item
v-if=
"!isStructDataSpecs"
label=
"读写类型"
prop=
"property.accessMode"
>
<el-form-item
v-if=
"!isStructDataSpecs
&& !isParams
"
label=
"读写类型"
prop=
"property.accessMode"
>
<el-radio-group
v-model=
"property.accessMode"
>
<el-radio
:label=
"ThingModelAccessMode.READ_WRITE.value"
>
{{ ThingModelAccessMode.READ_WRITE.label }}
...
...
@@ -85,32 +85,28 @@
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"属性描述"
prop=
"description"
>
<el-input
v-model=
"property.description"
:maxlength=
"200"
:rows=
"3"
placeholder=
"请输入属性描述"
type=
"textarea"
/>
</el-form-item>
</template>
<
script
lang=
"ts"
setup
>
import
{
useVModel
}
from
'@vueuse/core'
import
{
DataSpecsDataType
,
dataTypeOptions
,
validateBoolName
}
from
'./config'
import
{
DataSpecsDataType
,
dataTypeOptions
,
ThingModelAccessMode
,
validateBoolName
}
from
'./config'
import
{
ThingModelArrayDataSpecs
,
ThingModelEnumDataSpecs
,
ThingModelNumberDataSpecs
,
ThingModelStructDataSpecs
}
from
'./dataSpecs'
import
{
ThingModel
AccessMode
,
ThingModel
Property
}
from
'@/api/iot/thingmodel'
import
{
ThingModelProperty
}
from
'@/api/iot/thingmodel'
/** IoT 物模型
数据
*/
/** IoT 物模型
属性
*/
defineOptions
({
name
:
'ThingModelProperty'
})
const
props
=
defineProps
<
{
modelValue
:
any
;
isStructDataSpecs
?:
boolean
}
>
()
const
props
=
defineProps
<
{
modelValue
:
any
;
isStructDataSpecs
?:
boolean
;
isParams
?:
boolean
}
>
()
const
emits
=
defineEmits
([
'update:modelValue'
])
const
property
=
useVModel
(
props
,
'modelValue'
,
emits
)
as
Ref
<
ThingModelProperty
>
const
getDataTypeOptions
=
computed
(()
=>
{
...
...
src/views/iot/thingmodel/ThingModelService.vue
View file @
5391720b
...
...
@@ -13,11 +13,25 @@
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"输入参数"
>
<ThingModelInputOutputParam
v-model=
"service.inputParams"
:direction=
"ThingModelParamDirection.INPUT"
/>
</el-form-item>
<el-form-item
label=
"输出参数"
>
<ThingModelInputOutputParam
v-model=
"service.outputParams"
:direction=
"ThingModelParamDirection.OUTPUT"
/>
</el-form-item>
</
template
>
<
script
lang=
"ts"
setup
>
import
ThingModelInputOutputParam
from
'./ThingModelInputOutputParam.vue'
import
{
useVModel
}
from
'@vueuse/core'
import
{
ThingModelService
,
ThingModelServiceCallType
}
from
'@/api/iot/thingmodel'
import
{
ThingModelService
}
from
'@/api/iot/thingmodel'
import
{
ThingModelParamDirection
,
ThingModelServiceCallType
}
from
'./config'
/** IoT 物模型服务 */
defineOptions
({
name
:
'ThingModelService'
})
...
...
src/views/iot/thingmodel/config.ts
View file @
5391720b
import
{
isEmpty
}
from
'@/utils/is'
import
{
isEmpty
}
from
'@/utils/is'
/** dataSpecs 数值型数据结构 */
export
interface
DataSpecsNumberDataVO
{
...
...
@@ -48,9 +48,69 @@ export const dataTypeOptions = [
/** 获得物体模型数据类型配置项名称 */
export
const
getDataTypeOptionsLabel
=
(
value
:
string
)
=>
{
if
(
isEmpty
(
value
))
{
return
value
}
return
dataTypeOptions
.
find
((
option
)
=>
option
.
value
===
value
)?.
label
}
// IOT 产品物模型类型枚举类
export
const
ThingModelType
=
{
PROPERTY
:
1
,
// 属性
SERVICE
:
2
,
// 服务
EVENT
:
3
// 事件
}
as
const
// IOT 产品物模型访问模式枚举类
export
const
ThingModelAccessMode
=
{
READ_WRITE
:
{
label
:
'读写'
,
value
:
'rw'
},
READ_ONLY
:
{
label
:
'只读'
,
value
:
'r'
}
}
as
const
// IOT 产品物模型服务调用方式枚举
export
const
ThingModelServiceCallType
=
{
ASYNC
:
{
label
:
'异步调用'
,
value
:
'async'
},
SYNC
:
{
label
:
'同步调用'
,
value
:
'sync'
}
}
as
const
export
const
getCallTypeByValue
=
(
value
:
string
):
string
|
undefined
=>
Object
.
values
(
ThingModelServiceCallType
).
find
((
type
)
=>
type
.
value
===
value
)?.
label
// IOT 产品物模型事件类型枚举
export
const
ThingModelEventType
=
{
INFO
:
{
label
:
'信息'
,
value
:
'info'
},
ALERT
:
{
label
:
'告警'
,
value
:
'alert'
},
ERROR
:
{
label
:
'故障'
,
value
:
'error'
}
}
as
const
export
const
getEventTypeByValue
=
(
value
:
string
):
string
|
undefined
=>
Object
.
values
(
ThingModelEventType
).
find
((
type
)
=>
type
.
value
===
value
)?.
label
// IOT 产品物模型参数是输入参数还是输出参数
export
const
ThingModelParamDirection
=
{
INPUT
:
'input'
,
// 输入参数
OUTPUT
:
'output'
// 输出参数
}
as
const
/** 公共校验规则 */
export
const
ThingModelFormRules
=
{
name
:
[
...
...
src/views/iot/thingmodel/index.vue
View file @
5391720b
...
...
@@ -56,13 +56,63 @@
<el-table-column
align=
"center"
label=
"标识符"
prop=
"identifier"
/>
<el-table-column
align=
"center"
label=
"数据类型"
prop=
"identifier"
>
<
template
#
default=
"{ row }"
>
{{
dataTypeOptionsLabel
(
row
.
property
.
dataType
)
??
'-'
}}
{{
dataTypeOptionsLabel
(
row
.
property
?
.
dataType
)
??
'-'
}}
</
template
>
</el-table-column>
<el-table-column
align=
"
center
"
label=
"数据定义"
prop=
"identifier"
>
<el-table-column
align=
"
left
"
label=
"数据定义"
prop=
"identifier"
>
<
template
#
default=
"{ row }"
>
<!-- TODO puhui999: 数据定义展示待完善 -->
{{
row
.
property
.
dataSpecs
??
row
.
property
.
dataSpecsList
}}
<!-- 属性 -->
<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
align
=
"center"
label
=
"操作"
>
...
...
@@ -104,7 +154,14 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import
ThingModelForm
from
'./ThingModelForm.vue'
import
{
ProductVO
}
from
'@/api/iot/product/product'
import
{
IOT_PROVIDE_KEY
}
from
'@/views/iot/utils/constants'
import
{
getDataTypeOptionsLabel
}
from
'@/views/iot/thingmodel/config'
import
{
DataSpecsDataType
,
getCallTypeByValue
,
getDataTypeOptionsLabel
,
getEventTypeByValue
,
ThingModelType
}
from
'./config'
import
{
ThingModelNumberDataSpecs
}
from
'@/views/iot/thingmodel/dataSpecs'
defineOptions
({
name
:
'IoTProductThingModel'
}
)
...
...
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