AttrTemplateModelProperty.vue 5.6 KB

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