wwf
6 小时以前 a1d7e81859f554f3a53680cc35f0f49bf1f77098
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<!-- 产品的物模型表单(property 项) -->
<template>
  <el-form-item
    :rules="[{ required: true, message: '请选择数据类型', trigger: 'change' }]"
    label="数据类型"
    prop="property.dataType"
  >
    <el-select v-model="property.dataType" placeholder="请选择数据类型" @change="handleChange">
      <!-- ARRAY 和 STRUCT 类型数据相互嵌套时,最多支持递归嵌套 2 层(父和子) -->
      <el-option
        v-for="option in getDataTypeOptions2"
        :key="option.value"
        :label="`${option.value}(${option.label})`"
        :value="option.value"
      />
    </el-select>
  </el-form-item>
  <!-- 数值型配置 -->
  <ThingModelNumberDataSpecs
    v-if="
      [
        IoTDataSpecsDataTypeEnum.INT,
        IoTDataSpecsDataTypeEnum.DOUBLE,
        IoTDataSpecsDataTypeEnum.FLOAT
      ].includes(property.dataType || '')
    "
    v-model="property.dataSpecs"
  />
  <!-- 枚举型配置 -->
  <ThingModelEnumDataSpecs
    v-if="property.dataType === IoTDataSpecsDataTypeEnum.ENUM"
    v-model="property.dataSpecsList"
  />
  <!-- 布尔型配置 -->
  <el-form-item v-if="property.dataType === IoTDataSpecsDataTypeEnum.BOOL" label="布尔值">
    <template v-for="(item, index) in property.dataSpecsList" :key="item.value">
      <div class="flex items-center justify-start w-1/1 mb-5px">
        <span>{{ item.value }}</span>
        <span class="mx-2">-</span>
        <el-form-item
          :prop="`property.dataSpecsList[${index}].name`"
          :rules="[
            { required: true, message: '枚举描述不能为空' },
            { validator: validateBoolName, trigger: 'blur' }
          ]"
          class="flex-1 mb-0"
        >
          <el-input
            v-model="item.name"
            :placeholder="`如:${item.value === 0 ? '关' : '开'}`"
            class="w-255px!"
          />
        </el-form-item>
      </div>
    </template>
  </el-form-item>
  <!-- 文本型配置 -->
  <el-form-item
    v-if="property.dataType === IoTDataSpecsDataTypeEnum.TEXT"
    label="数据长度"
    prop="property.dataSpecs.length"
  >
    <el-input v-model="property.dataSpecs.length" class="w-255px!" placeholder="请输入文本字节长度">
      <template #append>字节</template>
    </el-input>
  </el-form-item>
  <!-- 时间型配置 -->
  <el-form-item
    v-if="property.dataType === IoTDataSpecsDataTypeEnum.DATE"
    label="时间格式"
    prop="date"
  >
    <el-input class="w-255px!" disabled placeholder="String 类型的 UTC 时间戳(毫秒)" />
  </el-form-item>
  <!-- 数组型配置-->
  <ThingModelArrayDataSpecs
    v-if="property.dataType === IoTDataSpecsDataTypeEnum.ARRAY"
    v-model="property.dataSpecs"
  />
  <!-- Struct 型配置-->
  <ThingModelStructDataSpecs
    v-if="property.dataType === IoTDataSpecsDataTypeEnum.STRUCT"
    v-model="property.dataSpecsList"
  />
  <el-form-item v-if="!isStructDataSpecs && !isParams" label="读写类型" prop="property.accessMode">
    <el-radio-group v-model="property.accessMode">
      <el-radio
        v-for="accessMode in Object.values(IoTThingModelAccessModeEnum)"
        :key="accessMode.value"
        :label="accessMode.value"
      >
        {{ accessMode.label }}
      </el-radio>
    </el-radio-group>
  </el-form-item>
</template>
 
<script lang="ts" setup>
import { useVModel } from '@vueuse/core'
import {
  ThingModelArrayDataSpecs,
  ThingModelEnumDataSpecs,
  ThingModelNumberDataSpecs,
  ThingModelStructDataSpecs
} from './dataSpecs'
import { ThingModelProperty, validateBoolName } from '@/api/iot/thingmodel'
import { isEmpty } from '@/utils/is'
import {
  getDataTypeOptions,
  IoTDataSpecsDataTypeEnum,
  IoTThingModelAccessModeEnum
} from '@/views/iot/utils/constants'
 
/** IoT 物模型属性 */
defineOptions({ name: 'ThingModelProperty' })
 
const props = defineProps<{ modelValue: any; isStructDataSpecs?: boolean; isParams?: boolean }>()
const emits = defineEmits(['update:modelValue'])
const property = useVModel(props, 'modelValue', emits) as Ref<ThingModelProperty>
const getDataTypeOptions2 = computed(() => {
  if (!props.isStructDataSpecs) {
    return getDataTypeOptions()
  }
  const excludedTypes = [IoTDataSpecsDataTypeEnum.STRUCT, IoTDataSpecsDataTypeEnum.ARRAY]
  return getDataTypeOptions().filter((item: any) => !excludedTypes.includes(item.value))
}) // 获得数据类型列表
 
/** 属性值的数据类型切换时初始化相关数据 */
const handleChange = (dataType: any) => {
  property.value.dataSpecs = {}
  property.value.dataSpecsList = []
  // 不是列表型数据才设置 dataSpecs.dataType
  ![
    IoTDataSpecsDataTypeEnum.ENUM,
    IoTDataSpecsDataTypeEnum.BOOL,
    IoTDataSpecsDataTypeEnum.STRUCT
  ].includes(dataType) && (property.value.dataSpecs.dataType = dataType)
  switch (dataType) {
    case IoTDataSpecsDataTypeEnum.ENUM:
      property.value.dataSpecsList.push({
        dataType: IoTDataSpecsDataTypeEnum.ENUM,
        name: '', // 枚举项的名称
        value: undefined // 枚举值
      })
      break
    case IoTDataSpecsDataTypeEnum.BOOL:
      for (let i = 0; i < 2; i++) {
        property.value.dataSpecsList.push({
          dataType: IoTDataSpecsDataTypeEnum.BOOL,
          name: '', // 布尔值的名称
          value: i // 布尔值
        })
      }
      break
  }
}
 
/** 默认选中读写 */
watch(
  () => property.value.accessMode,
  (val: string) => {
    if (props.isStructDataSpecs || props.isParams) {
      return
    }
    isEmpty(val) && (property.value.accessMode = IoTThingModelAccessModeEnum.READ_WRITE.value)
  },
  { immediate: true }
)
</script>
 
<style lang="scss" scoped>
:deep(.el-form-item) {
  .el-form-item {
    margin-bottom: 0;
  }
}
</style>