Explorar o código

通用物模型

yanghao hai 5 días
pai
achega
b0c478e807

+ 2 - 2
.env.local

@@ -3,8 +3,8 @@ NODE_ENV=development
 
 
 VITE_DEV=true
 VITE_DEV=true
 
 
-# 请求路径  http://192.168.188.200:48080  https://iot.deepoil.cc:5443  http://172.26.0.56:48080
-VITE_BASE_URL='http://192.168.188.198:48080'
+# 请求路径  http://192.168.188.200:48080  https://iot.deepoil.cc:5443  http://172.26.0.56:48080  http://192.168.188.198:48080
+VITE_BASE_URL='http://172.26.0.56:48080'
 
 
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
 VITE_UPLOAD_TYPE=server
 VITE_UPLOAD_TYPE=server

+ 329 - 0
src/views/iot/commonThing/CommonThingModelForm.vue

@@ -0,0 +1,329 @@
+<template>
+  <Dialog v-model="dialogVisible" :title="dialogTitle" width="900px">
+    <el-form
+      ref="formRef"
+      v-loading="formLoading"
+      :model="formData"
+      :rules="formRules"
+      label-width="100px"
+    >
+      <el-form-item label="功能标识" prop="identifier">
+        <el-input v-model="formData.identifier" placeholder="请输入功能标识" />
+      </el-form-item>
+      <el-form-item label="功能名称" prop="name">
+        <el-input v-model="formData.name" placeholder="请输入功能名称" />
+      </el-form-item>
+      <el-form-item label="功能描述" prop="description">
+        <el-input
+          v-model="formData.description"
+          type="textarea"
+          :rows="3"
+          :maxlength="200"
+          placeholder="请输入功能描述"
+        />
+      </el-form-item>
+      <el-form-item label="功能类型" prop="type">
+        <el-radio-group v-model="formData.type">
+          <el-radio-button
+            v-for="dict in getIntDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE)"
+            :key="dict.value"
+            :value="dict.value"
+          >
+            {{ dict.label }}
+          </el-radio-button>
+        </el-radio-group>
+      </el-form-item>
+
+      <el-form-item v-if="formData.type === 1" label="属性" prop="property">
+        <div class="json-editor-field">
+          <div class="json-editor-toolbar">
+            <span class="json-editor-toolbar__tip">请输入属性 JSON 数据</span>
+            <div class="json-editor-toolbar__actions">
+              <el-button text type="primary" @click="formatJsonField('property')">
+                美化 JSON
+              </el-button>
+              <el-button text @click="compressJsonField('property')">压缩 JSON</el-button>
+            </div>
+          </div>
+          <v-ace-editor
+            v-model:value="formData.property"
+            lang="json"
+            theme="monokai"
+            class="json-editor"
+            :options="editorOptions"
+          />
+        </div>
+      </el-form-item>
+
+      <el-form-item v-if="formData.type === 3" label="事件" prop="event">
+        <div class="json-editor-field">
+          <div class="json-editor-toolbar">
+            <span class="json-editor-toolbar__tip">请输入事件 JSON 数据</span>
+            <div class="json-editor-toolbar__actions">
+              <el-button text type="primary" @click="formatJsonField('event')">美化 JSON</el-button>
+              <el-button text @click="compressJsonField('event')">压缩 JSON</el-button>
+            </div>
+          </div>
+          <v-ace-editor
+            v-model:value="formData.event"
+            lang="json"
+            theme="monokai"
+            class="json-editor"
+            :options="editorOptions"
+          />
+        </div>
+      </el-form-item>
+
+      <el-form-item v-if="formData.type === 2" label="服务" prop="service">
+        <div class="json-editor-field">
+          <div class="json-editor-toolbar">
+            <span class="json-editor-toolbar__tip">请输入服务 JSON 数据</span>
+            <div class="json-editor-toolbar__actions">
+              <el-button text type="primary" @click="formatJsonField('service')">
+                美化 JSON
+              </el-button>
+              <el-button text @click="compressJsonField('service')">压缩 JSON</el-button>
+            </div>
+          </div>
+          <v-ace-editor
+            v-model:value="formData.service"
+            lang="json"
+            theme="monokai"
+            class="json-editor"
+            :options="editorOptions"
+          />
+        </div>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <el-button :disabled="formLoading" type="primary" @click="submitForm">确定</el-button>
+      <el-button @click="dialogVisible = false">取消</el-button>
+    </template>
+  </Dialog>
+</template>
+
+<script lang="ts" setup>
+import '@/components/mt-edit/ace-edit'
+import { VAceEditor } from 'vue3-ace-editor'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import {
+  ThingModelCommon,
+  type CommonThingModelData
+} from '@/api/iot/thingmodel'
+
+defineOptions({ name: 'CommonThingModelForm' })
+
+const { t } = useI18n()
+const message = useMessage()
+
+const dialogVisible = ref(false)
+const dialogTitle = ref('')
+const formLoading = ref(false)
+const formType = ref('')
+const formRef = ref()
+const editorOptions = {
+  useWorker: true,
+  tabSize: 2,
+  fontSize: 14,
+  wrap: true,
+  showPrintMargin: false,
+  enableBasicAutocompletion: true,
+  enableLiveAutocompletion: true
+}
+
+const createDefaultFormData = (): CommonThingModelData => ({
+  identifier: '',
+  name: '',
+  description: '',
+  type: 1,
+  property: '',
+  event: '',
+  service: ''
+})
+
+const formData = ref<CommonThingModelData>(createDefaultFormData())
+
+const getJsonFieldByType = () => {
+  if (formData.value.type === 1) return 'property'
+  if (formData.value.type === 2) return 'service'
+  return 'event'
+}
+
+const tryFormatJson = (value?: string, indent = 2) => {
+  if (!value) return ''
+  const trimmed = value.trim()
+  if (!trimmed) return ''
+  return JSON.stringify(JSON.parse(trimmed), null, indent)
+}
+
+const formatJsonField = (field: 'property' | 'event' | 'service') => {
+  try {
+    formData.value[field] = tryFormatJson(formData.value[field], 2)
+    message.success('JSON 已美化')
+  } catch {
+    message.warning('当前内容不是合法 JSON,无法美化')
+  }
+}
+
+const compressJsonField = (field: 'property' | 'event' | 'service') => {
+  try {
+    formData.value[field] = tryFormatJson(formData.value[field], 0)
+    message.success('JSON 已压缩')
+  } catch {
+    message.warning('当前内容不是合法 JSON,无法压缩')
+  }
+}
+
+const validateJsonField = (field: 'property' | 'event' | 'service', label: string) => {
+  return (_rule: any, value: string, callback: (error?: Error) => void) => {
+    const currentType = formData.value.type
+    const fieldTypeMap = {
+      property: 1,
+      service: 2,
+      event: 3
+    }
+
+    if (currentType !== fieldTypeMap[field]) {
+      callback()
+      return
+    }
+
+    if (!value) {
+      callback(new Error(`${label}不能为空`))
+      return
+    }
+
+    try {
+      JSON.parse(value)
+      callback()
+    } catch {
+      callback(new Error(`${label}必须是合法的 JSON`))
+    }
+  }
+}
+
+const formRules = reactive({
+  identifier: [
+    { required: true, message: '功能标识不能为空', trigger: 'blur' },
+    {
+      pattern: /^[a-zA-Z0-9_]{1,50}$/,
+      message: '功能标识支持字母、数字和下划线,长度不超过 50',
+      trigger: 'blur'
+    }
+  ],
+  name: [{ required: true, message: '功能名称不能为空', trigger: 'blur' }],
+  type: [{ required: true, message: '功能类型不能为空', trigger: 'change' }],
+  property: [{ validator: validateJsonField('property', '属性'), trigger: 'blur' }],
+  event: [{ validator: validateJsonField('event', '事件'), trigger: 'blur' }],
+  service: [{ validator: validateJsonField('service', '服务'), trigger: 'blur' }]
+})
+
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  if (!id) return
+
+  formLoading.value = true
+  try {
+    const data = await ThingModelCommon.getCommonThingModel(id)
+    formData.value = {
+      ...createDefaultFormData(),
+      ...data
+    }
+    const activeField = getJsonFieldByType()
+    if (formData.value[activeField]) {
+      formData.value[activeField] = tryFormatJson(formData.value[activeField], 2)
+    }
+  } finally {
+    formLoading.value = false
+  }
+}
+
+defineExpose({ open, close: () => (dialogVisible.value = false) })
+
+const emit = defineEmits(['success'])
+
+const submitForm = async () => {
+  await formRef.value.validate()
+  formLoading.value = true
+  try {
+    const payload: CommonThingModelData = {
+      ...formData.value,
+      property: formData.value.type === 1 ? formData.value.property : '',
+      service: formData.value.type === 2 ? formData.value.service : '',
+      event: formData.value.type === 3 ? formData.value.event : ''
+    }
+
+    if (formType.value === 'create') {
+      await ThingModelCommon.createCommonThingModel(payload)
+      message.success(t('common.createSuccess'))
+    } else {
+      await ThingModelCommon.updateCommonThingModel(payload)
+      message.success(t('common.updateSuccess'))
+    }
+
+    dialogVisible.value = false
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+const resetForm = () => {
+  formData.value = createDefaultFormData()
+  formRef.value?.resetFields()
+}
+
+watch(
+  () => formData.value.type,
+  () => {
+    const activeField = getJsonFieldByType()
+    if (formData.value[activeField]) {
+      try {
+        formData.value[activeField] = tryFormatJson(formData.value[activeField], 2)
+      } catch {
+        // Keep original input when JSON is incomplete during editing.
+      }
+    }
+  }
+)
+</script>
+
+<style scoped>
+.json-editor-field {
+  width: 100%;
+  border: 1px solid var(--el-border-color);
+  border-radius: 8px;
+  overflow: hidden;
+  background: #111827;
+}
+
+.json-editor-toolbar {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 12px;
+  padding: 10px 12px;
+  background: #1f2937;
+  border-bottom: 1px solid rgb(255 255 255 / 0.08);
+}
+
+.json-editor-toolbar__tip {
+  font-size: 12px;
+  color: rgb(255 255 255 / 0.72);
+}
+
+.json-editor-toolbar__actions {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.json-editor {
+  width: 100%;
+  height: 320px;
+}
+</style>

+ 67 - 86
src/views/iot/commonThing/index.vue

@@ -2,32 +2,17 @@
   <ContentWrap>
   <ContentWrap>
     <el-form
     <el-form
       ref="queryFormRef"
       ref="queryFormRef"
-      :model="queryParams"
       :inline="true"
       :inline="true"
+      :model="queryParams"
       class="-mb-15px"
       class="-mb-15px"
-      label-width="80px">
-      <el-form-item label="功能标识" prop="identifier">
-        <el-input
-          v-model="queryParams.identifier"
-          class="!w-150px"
-          clearable
-          placeholder="请输入功能标识"
-          @keyup.enter="handleQuery" />
-      </el-form-item>
-      <el-form-item label="功能名称" prop="name">
-        <el-input
-          v-model="queryParams.name"
-          class="!w-150px"
-          clearable
-          placeholder="请输入功能名称"
-          @keyup.enter="handleQuery" />
-      </el-form-item>
+      label-width="68px">
       <el-form-item label="功能类型" prop="type">
       <el-form-item label="功能类型" prop="type">
         <el-select
         <el-select
           v-model="queryParams.type"
           v-model="queryParams.type"
-          class="!w-150px"
+          class="!w-240px"
           clearable
           clearable
-          placeholder="请选择功能类型">
+          placeholder="请选择功能类型"
+          @change="handleQuery">
           <el-option
           <el-option
             v-for="dict in getIntDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE)"
             v-for="dict in getIntDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE)"
             :key="dict.value"
             :key="dict.value"
@@ -35,8 +20,24 @@
             :value="dict.value" />
             :value="dict.value" />
         </el-select>
         </el-select>
       </el-form-item>
       </el-form-item>
+      <el-form-item label="功能名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          class="!w-240px"
+          clearable
+          placeholder="请输入功能名称"
+          @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="功能标识" prop="identifier">
+        <el-input
+          v-model="queryParams.identifier"
+          class="!w-240px"
+          clearable
+          placeholder="请输入功能标识"
+          @keyup.enter="handleQuery" />
+      </el-form-item>
       <el-form-item>
       <el-form-item>
-        <el-button @click="handleQuery">
+        <el-button type="primary" @click="handleQuery">
           <Icon class="mr-5px" icon="ep:search" />
           <Icon class="mr-5px" icon="ep:search" />
           搜索
           搜索
         </el-button>
         </el-button>
@@ -46,44 +47,57 @@
         </el-button>
         </el-button>
         <el-button plain type="primary" @click="openForm('create')">
         <el-button plain type="primary" @click="openForm('create')">
           <Icon class="mr-5px" icon="ep:plus" />
           <Icon class="mr-5px" icon="ep:plus" />
-          新增
+          新增功能
         </el-button>
         </el-button>
       </el-form-item>
       </el-form-item>
     </el-form>
     </el-form>
   </ContentWrap>
   </ContentWrap>
 
 
   <ContentWrap>
   <ContentWrap>
-    <zm-table :loading="loading" :data="list">
-      <zm-table-column align="center" label="功能标识" prop="identifier" min-width="160" />
-      <zm-table-column align="center" label="功能名称" prop="name" min-width="160" />
-      <zm-table-column align="center" label="功能描述" prop="description" min-width="180" />
-      <zm-table-column align="center" label="功能类型" prop="type" width="120">
+    <el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
+      <el-table-column align="center" label="功能类型" prop="type" width="120">
         <template #default="{ row }">
         <template #default="{ row }">
           <dict-tag :type="DICT_TYPE.IOT_THING_MODEL_TYPE" :value="row.type" />
           <dict-tag :type="DICT_TYPE.IOT_THING_MODEL_TYPE" :value="row.type" />
         </template>
         </template>
-      </zm-table-column>
-      <zm-table-column align="left" label="属性 JSON" min-width="220">
+      </el-table-column>
+      <el-table-column align="center" label="功能名称" prop="name" min-width="180" />
+      <el-table-column align="center" label="功能标识" prop="identifier" min-width="180" />
+      <el-table-column align="center" label="描述" prop="description" min-width="220" />
+      <el-table-column align="left" label="属性" min-width="240" show-overflow-tooltip>
         <template #default="{ row }">
         <template #default="{ row }">
-          <JsonPreview :value="row.property" />
+          {{ row.property || '-' }}
         </template>
         </template>
-      </zm-table-column>
-      <zm-table-column align="left" label="事件 JSON" min-width="220">
+      </el-table-column>
+      <el-table-column align="left" label="事件" min-width="240" show-overflow-tooltip>
         <template #default="{ row }">
         <template #default="{ row }">
-          <JsonPreview :value="row.event" />
+          {{ row.event || '-' }}
         </template>
         </template>
-      </zm-table-column>
-      <zm-table-column align="left" label="服务 JSON" min-width="220">
+      </el-table-column>
+      <el-table-column align="left" label="服务" min-width="240" show-overflow-tooltip>
         <template #default="{ row }">
         <template #default="{ row }">
-          <JsonPreview :value="row.service" />
+          {{ row.service || '-' }}
         </template>
         </template>
-      </zm-table-column>
-      <zm-table-column align="center" label="操作" fixed="right" width="140">
+      </el-table-column>
+      <el-table-column align="center" label="操作" width="160" fixed="right">
         <template #default="{ row }">
         <template #default="{ row }">
-          <el-button link type="primary" @click="openForm('update', row.id)"> 编辑 </el-button>
-          <el-button link type="danger" @click="handleDelete(row.id)"> 删除 </el-button>
+          <el-button
+            v-hasPermi="['iot:thing-model-common:update']"
+            link
+            type="primary"
+            @click="openForm('update', row.id)">
+            编辑
+          </el-button>
+          <el-button
+            v-hasPermi="['iot:thing-model-common:delete']"
+            link
+            type="danger"
+            @click="handleDelete(row.id)">
+            删除
+          </el-button>
         </template>
         </template>
-      </zm-table-column>
-    </zm-table>
+      </el-table-column>
+    </el-table>
+
     <Pagination
     <Pagination
       v-model:limit="queryParams.pageSize"
       v-model:limit="queryParams.pageSize"
       v-model:page="queryParams.pageNo"
       v-model:page="queryParams.pageNo"
@@ -91,69 +105,39 @@
       @pagination="getList" />
       @pagination="getList" />
   </ContentWrap>
   </ContentWrap>
 
 
-  <ThingModelForm ref="formRef" mode="common" @success="getList" />
+  <CommonThingModelForm ref="formRef" @success="getList" />
 </template>
 </template>
 
 
-<script setup lang="ts">
-import { h } from 'vue'
-import { CommonThingModelData, ThingModelCommon } from '@/api/iot/thingmodel'
-import ThingModelForm from '@/views/iot/thingmodel/ThingModelFormCommon.vue'
+<script lang="ts" setup>
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { ThingModelCommon, type CommonThingModelData } from '@/api/iot/thingmodel'
+import CommonThingModelForm from './CommonThingModelForm.vue'
 
 
-defineOptions({ name: 'IoTCommonThingModel' })
+defineOptions({ name: 'CommonThingModel' })
 
 
 const { t } = useI18n()
 const { t } = useI18n()
 const message = useMessage()
 const message = useMessage()
 
 
 const loading = ref(false)
 const loading = ref(false)
-const total = ref(0)
 const list = ref<CommonThingModelData[]>([])
 const list = ref<CommonThingModelData[]>([])
+const total = ref(0)
 const queryFormRef = ref()
 const queryFormRef = ref()
 const formRef = ref()
 const formRef = ref()
 
 
 const queryParams = reactive({
 const queryParams = reactive({
   pageNo: 1,
   pageNo: 1,
   pageSize: 10,
   pageSize: 10,
-  identifier: '',
+  type: undefined as number | undefined,
   name: '',
   name: '',
-  type: undefined as number | undefined
+  identifier: ''
 })
 })
 
 
-const formatJsonText = (value: unknown) => {
-  if (!value) {
-    return '-'
-  }
-  if (typeof value === 'string') {
-    return value
-  }
-  try {
-    return JSON.stringify(value, null, 2)
-  } catch {
-    return String(value)
-  }
-}
-
-const JsonPreview = (props: { value?: unknown }) =>
-  h(
-    'div',
-    {
-      style: {
-        whiteSpace: 'pre-wrap',
-        wordBreak: 'break-all',
-        lineHeight: '20px',
-        maxHeight: '120px',
-        overflow: 'auto'
-      }
-    },
-    formatJsonText(props.value)
-  )
-
 const getList = async () => {
 const getList = async () => {
   loading.value = true
   loading.value = true
   try {
   try {
     const data = await ThingModelCommon.getCommonThingModelPage(queryParams)
     const data = await ThingModelCommon.getCommonThingModelPage(queryParams)
-    list.value = data.list
-    total.value = data.total
+    list.value = data?.list || []
+    total.value = data?.total || 0
   } finally {
   } finally {
     loading.value = false
     loading.value = false
   }
   }
@@ -173,10 +157,7 @@ const openForm = (type: string, id?: number) => {
   formRef.value?.open(type, id)
   formRef.value?.open(type, id)
 }
 }
 
 
-const handleDelete = async (id?: number) => {
-  if (!id) {
-    return
-  }
+const handleDelete = async (id: number) => {
   try {
   try {
     await message.delConfirm()
     await message.delConfirm()
     await ThingModelCommon.deleteCommonThingModel(id)
     await ThingModelCommon.deleteCommonThingModel(id)

+ 0 - 215
src/views/iot/thingmodel/ThingModelFormCommon.vue

@@ -1,215 +0,0 @@
-<!-- 产品的物模型表单 -->
-<template>
-  <Dialog v-model="dialogVisible" :title="dialogTitle">
-    <el-form
-      ref="formRef"
-      v-loading="formLoading"
-      :model="formData"
-      :rules="ThingModelFormRules"
-      label-width="100px">
-      <el-form-item label="功能类型" prop="type">
-        <el-radio-group v-model="formData.type">
-          <el-radio-button
-            v-for="dict in getIntDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE)"
-            :key="dict.value"
-            :value="dict.value">
-            {{ dict.label }}
-          </el-radio-button>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="功能名称" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入功能名称" />
-      </el-form-item>
-      <el-form-item label="标识符" prop="identifier">
-        <el-input v-model="formData.identifier" placeholder="请输入标识符" />
-      </el-form-item>
-      <!-- 属性配置 -->
-      <ThingModelProperty
-        v-if="formData.type === IoTThingModelTypeEnum.PROPERTY"
-        v-model="formData.property" />
-      <!-- 服务配置 -->
-      <ThingModelService
-        v-if="formData.type === IoTThingModelTypeEnum.SERVICE"
-        v-model="formData.service" />
-      <!-- 事件配置 -->
-      <ThingModelEvent
-        v-if="formData.type === IoTThingModelTypeEnum.EVENT"
-        v-model="formData.event" />
-      <el-form-item label="描述" prop="description">
-        <el-input
-          v-model="formData.description"
-          :maxlength="200"
-          :rows="3"
-          placeholder="请输入属性描述"
-          type="textarea" />
-      </el-form-item>
-    </el-form>
-
-    <template #footer>
-      <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-
-<script lang="ts" setup>
-import { ProductVO } from '@/api/iot/product/product'
-import ThingModelProperty from './ThingModelProperty.vue'
-import ThingModelService from './ThingModelService.vue'
-import ThingModelEvent from './ThingModelEvent.vue'
-import { ThingModelCommon, ThingModelData, ThingModelFormRules } from '@/api/iot/thingmodel'
-import {
-  IOT_PROVIDE_KEY,
-  IoTDataSpecsDataTypeEnum,
-  IoTThingModelTypeEnum
-} from '@/views/iot/utils/constants'
-import { cloneDeep } from 'lodash-es'
-import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
-import { isEmpty } from '@/utils/is'
-
-/** IoT 物模型数据表单 */
-defineOptions({ name: 'IoTThingModelForm' })
-
-const product = inject<Ref<ProductVO>>(IOT_PROVIDE_KEY.PRODUCT) // 注入产品信息
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref<ThingModelData>({
-  type: IoTThingModelTypeEnum.PROPERTY,
-  dataType: IoTDataSpecsDataTypeEnum.INT,
-  property: {
-    dataType: IoTDataSpecsDataTypeEnum.INT,
-    dataSpecs: {
-      dataType: IoTDataSpecsDataTypeEnum.INT
-    }
-  },
-  service: {},
-  event: {}
-})
-
-const formRef = ref() // 表单 Ref
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await ThingModelCommon.getCommonThingModel(id)
-      // 情况一:属性初始化
-      if (isEmpty(formData.value.property)) {
-        formData.value.dataType = IoTDataSpecsDataTypeEnum.INT
-        formData.value.property = {
-          dataType: IoTDataSpecsDataTypeEnum.INT,
-          dataSpecs: {
-            dataType: IoTDataSpecsDataTypeEnum.INT
-          }
-        }
-      }
-      // 情况二:服务初始化
-      if (isEmpty(formData.value.service)) {
-        formData.value.service = {}
-      }
-      // 情况三:事件初始化
-      if (isEmpty(formData.value.event)) {
-        formData.value.event = {}
-      }
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open, close: () => (dialogVisible.value = false) })
-
-/** 提交表单 */
-const emit = defineEmits(['success'])
-const submitForm = async () => {
-  await formRef.value.validate()
-  formLoading.value = true
-  try {
-    const data = cloneDeep(formData.value) as ThingModelData
-    // // 信息补全
-    // data.productId = product!.value.id
-    // data.productKey = product!.value.productKey
-    fillExtraAttributes(data)
-    if (formType.value === 'create') {
-      await ThingModelCommon.createCommonThingModel(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await ThingModelCommon.updateCommonThingModel(data)
-      message.success(t('common.updateSuccess'))
-    }
-    // 关闭弹窗
-    dialogVisible.value = false
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 填写额外的属性(处理不同类型的情况) */
-const fillExtraAttributes = (data: any) => {
-  // 属性
-  if (data.type === IoTThingModelTypeEnum.PROPERTY) {
-    removeDataSpecs(data.property)
-    data.dataType = data.property.dataType
-    data.property.identifier = data.identifier
-    data.property.name = data.name
-    delete data.service
-    delete data.event
-  }
-  // 服务
-  if (data.type === IoTThingModelTypeEnum.SERVICE) {
-    removeDataSpecs(data.service)
-    data.dataType = data.service.dataType
-    data.service.identifier = data.identifier
-    data.service.name = data.name
-    delete data.property
-    delete data.event
-  }
-  // 事件
-  if (data.type === IoTThingModelTypeEnum.EVENT) {
-    removeDataSpecs(data.event)
-    data.dataType = data.event.dataType
-    data.event.identifier = data.identifier
-    data.event.name = data.name
-    delete data.property
-    delete data.service
-  }
-}
-
-/** 处理 dataSpecs 为空的情况 */
-const removeDataSpecs = (val: any) => {
-  if (isEmpty(val.dataSpecs)) {
-    delete val.dataSpecs
-  }
-  if (isEmpty(val.dataSpecsList)) {
-    delete val.dataSpecsList
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    type: IoTThingModelTypeEnum.PROPERTY,
-    dataType: IoTDataSpecsDataTypeEnum.INT,
-    property: {
-      dataType: IoTDataSpecsDataTypeEnum.INT,
-      dataSpecs: {
-        dataType: IoTDataSpecsDataTypeEnum.INT
-      }
-    },
-    service: {},
-    event: {}
-  }
-  formRef.value?.resetFields()
-}
-</script>