commit
67fb5ecf3a
@ -1,4 +1,4 @@
|
||||
import { toNumber } from 'lodash-es'
|
||||
import {toNumber} from 'lodash-es'
|
||||
|
||||
/**
|
||||
*
|
||||
@ -118,7 +118,7 @@ export function toAnyString() {
|
||||
|
||||
/**
|
||||
* 生成指定长度的随机字符串
|
||||
*
|
||||
*
|
||||
* @param length 字符串长度
|
||||
*/
|
||||
export function generateRandomStr(length: number): string {
|
||||
@ -459,7 +459,7 @@ export function jsonParse(str: string) {
|
||||
try {
|
||||
return JSON.parse(str)
|
||||
} catch (e) {
|
||||
console.error(`str[${str}] 不是一个 JSON 字符串`)
|
||||
// console.error(`str[${str}] 不是一个 JSON 字符串`)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<el-tabs v-model="activeTab" type="border-card">
|
||||
<!-- 上行指令调试 -->
|
||||
<el-tab-pane label="上行指令调试" name="up">
|
||||
<el-tabs v-model="subTab" v-if="activeTab === 'up'">
|
||||
<el-tabs v-if="activeTab === 'up'" v-model="subTab">
|
||||
<!-- 属性上报 -->
|
||||
<el-tab-pane label="属性上报" name="property">
|
||||
<ContentWrap>
|
||||
@ -29,70 +29,11 @@
|
||||
</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>
|
||||
<!-- TODO @super:要不要兜底下,没翻译的类型,直接展示 json? -->
|
||||
</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>
|
||||
<DataDefinition :data="row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- TODO @super:可以右侧 fixed -->
|
||||
<el-table-column label="值" align="center" width="80">
|
||||
<el-table-column align="center" label="值" width="80">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.simulateValue" class="!w-60px" />
|
||||
</template>
|
||||
@ -100,7 +41,7 @@
|
||||
</el-table>
|
||||
<!-- TODO @super:发送按钮,可以放在右侧哈。因为我们的 simulateValue 就在最右侧 -->
|
||||
<div class="mt-10px">
|
||||
<el-button type="primary" @click="handlePropertyReport"> 发送 </el-button>
|
||||
<el-button type="primary" @click="handlePropertyReport"> 发送</el-button>
|
||||
</div>
|
||||
</ContentWrap>
|
||||
</el-tab-pane>
|
||||
@ -151,7 +92,7 @@
|
||||
<!-- 下行指令调试 -->
|
||||
<!-- TODO @super:待实现 -->
|
||||
<el-tab-pane label="下行指令调试" name="down">
|
||||
<el-tabs v-model="subTab" v-if="activeTab === 'down'">
|
||||
<el-tabs v-if="activeTab === 'down'" v-model="subTab">
|
||||
<!-- 属性调试 -->
|
||||
<el-tab-pane label="属性调试" name="propertyDebug">
|
||||
<ContentWrap>
|
||||
@ -201,18 +142,13 @@
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { ProductVO } from '@/api/iot/product/product'
|
||||
import { ThingModelApi, SimulatorData } from '@/api/iot/thingmodel'
|
||||
import { SimulatorData, ThingModelApi } from '@/api/iot/thingmodel'
|
||||
import { DeviceApi, DeviceStateEnum, DeviceVO } from '@/api/iot/device/device'
|
||||
import DeviceDetailsLog from './DeviceDetailsLog.vue'
|
||||
import {
|
||||
DataSpecsDataType,
|
||||
getCallTypeByValue,
|
||||
getDataTypeOptionsLabel,
|
||||
getEventTypeByValue,
|
||||
ThingModelType
|
||||
} from '@/views/iot/thingmodel/config'
|
||||
import { getDataTypeOptionsLabel } from '@/views/iot/thingmodel/config'
|
||||
import { DataDefinition } from '@/views/iot/thingmodel/components'
|
||||
|
||||
const props = defineProps<{
|
||||
product: ProductVO
|
||||
|
@ -5,7 +5,6 @@
|
||||
label="事件类型"
|
||||
prop="event.type"
|
||||
>
|
||||
<!-- TODO @puhui999:默认选中,INFO 信息 -->
|
||||
<el-radio-group v-model="thingModelEvent.type">
|
||||
<el-radio :value="ThingModelEventType.INFO.value">
|
||||
{{ ThingModelEventType.INFO.label }}
|
||||
@ -30,7 +29,8 @@
|
||||
import ThingModelInputOutputParam from './ThingModelInputOutputParam.vue'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { ThingModelEvent } from '@/api/iot/thingmodel'
|
||||
import { ThingModelParamDirection, ThingModelEventType } from './config'
|
||||
import { ThingModelEventType, ThingModelParamDirection } from './config'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
|
||||
/** IoT 物模型事件 */
|
||||
defineOptions({ name: 'ThingModelEvent' })
|
||||
@ -38,6 +38,13 @@ defineOptions({ name: 'ThingModelEvent' })
|
||||
const props = defineProps<{ modelValue: any; isStructDataSpecs?: boolean }>()
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
const thingModelEvent = useVModel(props, 'modelValue', emits) as Ref<ThingModelEvent>
|
||||
|
||||
// 默认选中,INFO 信息
|
||||
watch(
|
||||
() => thingModelEvent.value.type,
|
||||
(val: string) => isEmpty(val) && (thingModelEvent.value.type = ThingModelEventType.INFO.value),
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<el-option
|
||||
v-for="option in getDataTypeOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:label="`${option.value}(${option.label})`"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
@ -76,7 +76,6 @@
|
||||
v-if="property.dataType === DataSpecsDataType.STRUCT"
|
||||
v-model="property.dataSpecsList"
|
||||
/>
|
||||
<!-- TODO @puhui999:默认选中第一个 -->
|
||||
<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">
|
||||
@ -104,6 +103,7 @@ import {
|
||||
ThingModelStructDataSpecs
|
||||
} from './dataSpecs'
|
||||
import { ThingModelProperty } from '@/api/iot/thingmodel'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
|
||||
/** IoT 物模型属性 */
|
||||
defineOptions({ name: 'ThingModelProperty' })
|
||||
@ -146,6 +146,18 @@ const handleChange = (dataType: any) => {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 默认选中读写
|
||||
watch(
|
||||
() => property.value.accessMode,
|
||||
(val: string) => {
|
||||
if (props.isStructDataSpecs || props.isParams) {
|
||||
return
|
||||
}
|
||||
isEmpty(val) && (property.value.accessMode = ThingModelAccessMode.READ_WRITE.value)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -5,7 +5,6 @@
|
||||
label="调用方式"
|
||||
prop="service.callType"
|
||||
>
|
||||
<!-- TODO @puhui999:默认选中,ASYNC 异步 -->
|
||||
<el-radio-group v-model="service.callType">
|
||||
<el-radio :value="ThingModelServiceCallType.ASYNC.value">
|
||||
{{ ThingModelServiceCallType.ASYNC.label }}
|
||||
@ -34,6 +33,7 @@ import ThingModelInputOutputParam from './ThingModelInputOutputParam.vue'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { ThingModelService } from '@/api/iot/thingmodel'
|
||||
import { ThingModelParamDirection, ThingModelServiceCallType } from './config'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
|
||||
/** IoT 物模型服务 */
|
||||
defineOptions({ name: 'ThingModelService' })
|
||||
@ -41,6 +41,13 @@ defineOptions({ name: 'ThingModelService' })
|
||||
const props = defineProps<{ modelValue: any; isStructDataSpecs?: boolean }>()
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
const service = useVModel(props, 'modelValue', emits) as Ref<ThingModelService>
|
||||
|
||||
// 默认选中,ASYNC 异步
|
||||
watch(
|
||||
() => service.value.callType,
|
||||
(val: string) => isEmpty(val) && (service.value.callType = ThingModelServiceCallType.ASYNC.value),
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
61
src/views/iot/thingmodel/components/DataDefinition.vue
Normal file
61
src/views/iot/thingmodel/components/DataDefinition.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<!-- 属性 -->
|
||||
<template v-if="data.type === ThingModelType.PROPERTY">
|
||||
<!-- 非列表型:数值 -->
|
||||
<div
|
||||
v-if="
|
||||
[DataSpecsDataType.INT, DataSpecsDataType.DOUBLE, DataSpecsDataType.FLOAT].includes(
|
||||
data.property.dataType
|
||||
)
|
||||
"
|
||||
>
|
||||
取值范围:{{ `${data.property.dataSpecs.min}~${data.property.dataSpecs.max}` }}
|
||||
</div>
|
||||
<!-- 非列表型:文本 -->
|
||||
<div v-if="DataSpecsDataType.TEXT === data.property.dataType">
|
||||
数据长度:{{ data.property.dataSpecs.length }}
|
||||
</div>
|
||||
<!-- 列表型: 数组、结构、时间(特殊) -->
|
||||
<div
|
||||
v-if="
|
||||
[DataSpecsDataType.ARRAY, DataSpecsDataType.STRUCT, DataSpecsDataType.DATE].includes(
|
||||
data.property.dataType
|
||||
)
|
||||
"
|
||||
>
|
||||
-
|
||||
</div>
|
||||
<!-- 列表型: 布尔值、枚举 -->
|
||||
<div v-if="[DataSpecsDataType.BOOL, DataSpecsDataType.ENUM].includes(data.property.dataType)">
|
||||
<div> {{ DataSpecsDataType.BOOL === data.property.dataType ? '布尔值' : '枚举值' }}:</div>
|
||||
<div v-for="item in data.property.dataSpecsList" :key="item.value">
|
||||
{{ `${item.name}-${item.value}` }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 服务 -->
|
||||
<div v-if="data.type === ThingModelType.SERVICE">
|
||||
调用方式:{{ getCallTypeByValue(data.service!.callType) }}
|
||||
</div>
|
||||
<!-- 事件 -->
|
||||
<div v-if="data.type === ThingModelType.EVENT">
|
||||
事件类型:{{ getEventTypeByValue(data.event!.type) }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
DataSpecsDataType,
|
||||
getCallTypeByValue,
|
||||
getEventTypeByValue,
|
||||
ThingModelType
|
||||
} from '@/views/iot/thingmodel/config'
|
||||
import { ThingModelData } from '@/api/iot/thingmodel'
|
||||
|
||||
/** 数据定义展示组件 */
|
||||
defineOptions({ name: 'DataDefinition' })
|
||||
|
||||
defineProps<{ data: ThingModelData }>()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
3
src/views/iot/thingmodel/components/index.ts
Normal file
3
src/views/iot/thingmodel/components/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import DataDefinition from './DataDefinition.vue'
|
||||
|
||||
export { DataDefinition }
|
@ -1,4 +1,4 @@
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import {isEmpty} from '@/utils/is'
|
||||
|
||||
/** dataSpecs 数值型数据结构 */
|
||||
export interface DataSpecsNumberDataVO {
|
||||
@ -21,7 +21,7 @@ export interface DataSpecsEnumOrBoolDataVO {
|
||||
}
|
||||
|
||||
/** 属性值的数据类型 */
|
||||
// TODO @puhui999:这个枚举类,要不放到 dict 里?
|
||||
// TODO @puhui999:这个枚举类,要不放到 dict 里? 这个全是当常量来使用的不好放 dict 里 🤣
|
||||
export const DataSpecsDataType = {
|
||||
INT: 'int',
|
||||
FLOAT: 'float',
|
||||
@ -37,15 +37,15 @@ export const DataSpecsDataType = {
|
||||
/** 物体模型数据类型配置项 */
|
||||
// TODO @puhui999:搞到字典里;label 只使用()部分,就是整数型、单精度浮点型等,这种哈。这样,拼接 value(label) 就可以渲染出来,通用性更强
|
||||
export const dataTypeOptions = [
|
||||
{ value: DataSpecsDataType.INT, label: 'int32 (整数型)' },
|
||||
{ value: DataSpecsDataType.FLOAT, label: 'float (单精度浮点型)' },
|
||||
{ value: DataSpecsDataType.DOUBLE, label: 'double (双精度浮点型)' },
|
||||
{ value: DataSpecsDataType.ENUM, label: 'enum(枚举型)' },
|
||||
{ value: DataSpecsDataType.BOOL, label: 'bool (布尔型)' },
|
||||
{ value: DataSpecsDataType.TEXT, label: 'text (文本型)' },
|
||||
{ value: DataSpecsDataType.DATE, label: 'date (时间型)' },
|
||||
{ value: DataSpecsDataType.STRUCT, label: 'struct (结构体)' },
|
||||
{ value: DataSpecsDataType.ARRAY, label: 'array (数组)' }
|
||||
{ value: DataSpecsDataType.INT, label: '整数型' },
|
||||
{ value: DataSpecsDataType.FLOAT, label: '单精度浮点型' },
|
||||
{ value: DataSpecsDataType.DOUBLE, label: '双精度浮点型' },
|
||||
{ value: DataSpecsDataType.ENUM, label: '枚举型' },
|
||||
{ value: DataSpecsDataType.BOOL, label: '布尔型' },
|
||||
{ value: DataSpecsDataType.TEXT, label: '文本型' },
|
||||
{ value: DataSpecsDataType.DATE, label: '时间型' },
|
||||
{ value: DataSpecsDataType.STRUCT, label: '结构体' },
|
||||
{ value: DataSpecsDataType.ARRAY, label: '数组' }
|
||||
]
|
||||
|
||||
/** 获得物体模型数据类型配置项名称 */
|
||||
@ -53,7 +53,8 @@ export const getDataTypeOptionsLabel = (value: string) => {
|
||||
if (isEmpty(value)) {
|
||||
return value
|
||||
}
|
||||
return dataTypeOptions.find((option) => option.value === value)?.label
|
||||
const dataType = dataTypeOptions.find((option) => option.value === value)
|
||||
return dataType && `${dataType.value}(${dataType.label})`
|
||||
}
|
||||
|
||||
// IOT 产品物模型类型枚举类
|
||||
|
@ -4,15 +4,15 @@
|
||||
<el-radio-group v-model="dataSpecs.childDataType" @change="handleChange">
|
||||
<template v-for="item in dataTypeOptions" :key="item.value">
|
||||
<el-radio
|
||||
class="w-1/3"
|
||||
v-if="
|
||||
!(
|
||||
[DataSpecsDataType.ENUM, DataSpecsDataType.ARRAY, DataSpecsDataType.DATE] as any[]
|
||||
).includes(item.value)
|
||||
"
|
||||
:value="item.value"
|
||||
class="w-1/3"
|
||||
>
|
||||
{{ item.label }}
|
||||
{{ `${item.value}(${item.label})` }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
|
@ -5,7 +5,6 @@
|
||||
:rules="[{ required: true, validator: validateList, trigger: 'change' }]"
|
||||
label="JSON 对象"
|
||||
>
|
||||
<!-- TODO @puhui999:编辑已经添加的结构体,里面的参数加不上 -->
|
||||
<div
|
||||
v-for="(item, index) in dataSpecsList"
|
||||
:key="index"
|
||||
@ -155,6 +154,13 @@ const validateList = (_: any, __: any, callback: any) => {
|
||||
}
|
||||
callback()
|
||||
}
|
||||
|
||||
/** 组件初始化 */
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
// 预防 dataSpecsList 空指针
|
||||
isEmpty(dataSpecsList.value) && (dataSpecsList.value = [])
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -64,59 +64,7 @@
|
||||
</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)
|
||||
"
|
||||
>
|
||||
<!-- TODO @puhui999:把数据定义,抽成一个方法?这样,其它地方也可以复用哈。 -->
|
||||
取值范围:{{ `${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>
|
||||
<DataDefinition :data="row" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作">
|
||||
@ -158,13 +106,8 @@ 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 {
|
||||
DataSpecsDataType,
|
||||
getCallTypeByValue,
|
||||
getDataTypeOptionsLabel,
|
||||
getEventTypeByValue,
|
||||
ThingModelType
|
||||
} from './config'
|
||||
import { getDataTypeOptionsLabel } from './config'
|
||||
import { DataDefinition } from './components'
|
||||
|
||||
defineOptions({ name: 'IoTThingModel' })
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user