Эх сурвалжийг харах

【功能完善】IoT: 场景联动执行器 array、struct 类型数据编辑

puhui999 1 жил өмнө
parent
commit
1bc2978bc6

+ 5 - 1
src/components/JsonEditor/src/JsonEditor.vue

@@ -12,7 +12,7 @@ import { JsonEditorEmits, JsonEditorExpose, JsonEditorProps } from '../types'
 defineOptions({ name: 'JsonEditor' })
 
 const props = withDefaults(defineProps<JsonEditorProps>(), {
-  mode: 'tree' as JSONEditorMode,
+  mode: 'view' as JSONEditorMode,
   height: '400px',
   showModeSelection: false,
   showNavigationBar: false,
@@ -58,6 +58,10 @@ const initJsonEditor = () => {
   if (jsonObj.value) {
     jsonEditor.set(jsonObj.value)
   }
+
+  if (props.mode === 'view') {
+    jsonEditor?.expandAll() // 默认展开全部
+  }
 }
 
 // 监听数据变化

+ 81 - 0
src/views/iot/rule/scene/components/ThingModelDualView.vue

@@ -0,0 +1,81 @@
+<template>
+  <Dialog v-model="dialogVisible" :title="dialogTitle" :appendToBody="true" v-loading="loading">
+    <div class="flex h-600px">
+      <!-- 左侧物模型属性(view模式) -->
+      <div class="w-1/2 border-r border-gray-200 pr-2 overflow-auto">
+        <JsonEditor :model-value="thingModel" mode="view" height="600px" />
+      </div>
+
+      <!-- 右侧JSON编辑器(code模式) -->
+      <div class="w-1/2 pl-2 overflow-auto">
+        <JsonEditor v-model="editableModelTSL" mode="code" height="600px" @error="handleError" />
+      </div>
+    </div>
+
+    <template #footer>
+      <el-button @click="dialogVisible = false">取消</el-button>
+      <el-button type="primary" @click="handleSave" :disabled="hasJsonError">保存</el-button>
+    </template>
+  </Dialog>
+</template>
+
+<script setup lang="ts">
+import { isEmpty } from '@/utils/is'
+
+defineOptions({ name: 'ThingModelDualView' })
+
+const props = defineProps<{
+  modelValue: any // 物模型的值
+  thingModel: any[] // 物模型
+}>()
+const emits = defineEmits(['update:modelValue', 'change'])
+
+const message = useMessage()
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('物模型编辑器') // 弹窗的标题
+const editableModelTSL = ref([
+  {
+    identifier: '对应左侧 identifier 属性值',
+    value: '如果 identifier 是 int 类型则输入数字,具体查看产品物模型定义'
+  }
+]) // 物模型数据
+const hasJsonError = ref(false) // 是否有 JSON 格式错误
+const loading = ref(false) // 加载状态
+
+/** 打开弹窗 */
+const open = () => {
+  try {
+    // 数据回显
+    if (props.modelValue) {
+      editableModelTSL.value = JSON.parse(props.modelValue)
+    }
+  } catch (e) {
+    message.error('物模型编辑器参数')
+    console.error(e)
+  } finally {
+    dialogVisible.value = true
+    // 重置状态
+    hasJsonError.value = false
+  }
+}
+defineExpose({ open }) // 暴露方法供父组件调用
+
+/** 保存修改 */
+const handleSave = async () => {
+  try {
+    await message.confirm('确定要保存物模型参数吗?')
+    emits('update:modelValue', JSON.stringify(editableModelTSL.value))
+    message.success('保存成功')
+    dialogVisible.value = false
+  } catch {}
+}
+
+/** 处理 JSON 编辑器错误的函数 */
+const handleError = (errors: any) => {
+  if (isEmpty(errors)) {
+    hasJsonError.value = false
+    return
+  }
+  hasJsonError.value = true
+}
+</script>

+ 24 - 4
src/views/iot/rule/scene/components/ThingModelParamInput.vue

@@ -59,7 +59,17 @@
 
     <!-- array、struct 直接输入 -->
     <template v-else>
-      <el-input class="w-1/1!" v-model="value" placeholder="请输入值" />
+      <el-input class="w-1/1!" :model-value="value" disabled placeholder="请输入值">
+        <template #append>
+          <el-button type="primary" @click="openJsonEditor">编辑</el-button>
+        </template>
+      </el-input>
+      <!-- array、struct 类型数据编辑 -->
+      <ThingModelDualView
+        ref="thingModelDualViewRef"
+        v-model="value"
+        :thing-model="dataSpecsList"
+      />
     </template>
   </div>
 </template>
@@ -68,6 +78,7 @@
 import { computed } from 'vue'
 import { useVModel } from '@vueuse/core'
 import { DataSpecsDataType } from '@/views/iot/thingmodel/config'
+import ThingModelDualView from './ThingModelDualView.vue'
 
 /** 物模型属性参数输入组件 */
 defineOptions({ name: 'ThingModelParamInput' })
@@ -80,6 +91,11 @@ const props = defineProps<{
 const emits = defineEmits(['update:modelValue', 'change'])
 const value = useVModel(props, 'modelValue', emits)
 
+const thingModelDualViewRef = ref<InstanceType<typeof ThingModelDualView>>()
+const openJsonEditor = () => {
+  thingModelDualViewRef.value?.open()
+}
+
 /** 计算属性:判断数据类型 */
 const isNumeric = computed(() =>
   [DataSpecsDataType.INT, DataSpecsDataType.FLOAT, DataSpecsDataType.DOUBLE].includes(
@@ -93,13 +109,17 @@ const isText = computed(() => props.thingModel?.dataType === DataSpecsDataType.T
 /** 获取数据规格 */
 const dataSpecs = computed(() => {
   if (isNumeric.value || isDate.value || isText.value) {
-    return props.thingModel?.dataSpecs
+    return props.thingModel?.dataSpecs || {}
   }
   return {}
 })
 const dataSpecsList = computed(() => {
-  if (isBool.value || isEnum.value) {
-    return props.thingModel?.dataSpecsList
+  if (
+    isBool.value ||
+    isEnum.value ||
+    [DataSpecsDataType.ARRAY, DataSpecsDataType.STRUCT].includes(props.thingModel?.dataType)
+  ) {
+    return props.thingModel?.dataSpecsList || []
   }
   return []
 })