ThingModelProperty.vue 5.4 KB

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