From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/views/iot/device/device/detail/DeviceDetailsSimulator.vue |  420 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 420 insertions(+), 0 deletions(-)

diff --git a/src/views/iot/device/device/detail/DeviceDetailsSimulator.vue b/src/views/iot/device/device/detail/DeviceDetailsSimulator.vue
new file mode 100644
index 0000000..599de70
--- /dev/null
+++ b/src/views/iot/device/device/detail/DeviceDetailsSimulator.vue
@@ -0,0 +1,420 @@
+<!-- 妯℃嫙璁惧 -->
+<template>
+  <ContentWrap>
+    <el-row :gutter="20">
+      <!-- 宸︿晶鎸囦护璋冭瘯鍖哄煙 -->
+      <el-col :span="12">
+        <el-tabs v-model="activeTab" type="border-card">
+          <!-- 涓婅鎸囦护璋冭瘯 -->
+          <el-tab-pane label="涓婅鎸囦护璋冭瘯" name="upstream">
+            <el-tabs v-if="activeTab === 'upstream'" v-model="upstreamTab">
+              <!-- 灞炴�т笂鎶� -->
+              <el-tab-pane label="灞炴�т笂鎶�" :name="IotDeviceMessageMethodEnum.PROPERTY_POST.method">
+                <ContentWrap>
+                  <el-table :data="propertyList" :show-overflow-tooltip="true" :stripe="true">
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鍔熻兘鍚嶇О"
+                      prop="name"
+                      width="120"
+                    />
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鏍囪瘑绗�"
+                      prop="identifier"
+                      width="120"
+                    />
+                    <el-table-column align="center" label="鏁版嵁绫诲瀷" width="100">
+                      <template #default="{ row }">
+                        {{ row.property?.dataType ?? '-' }}
+                      </template>
+                    </el-table-column>
+                    <el-table-column align="left" label="鏁版嵁瀹氫箟" min-width="200">
+                      <template #default="{ row }">
+                        <DataDefinition :data="row" />
+                      </template>
+                    </el-table-column>
+                    <el-table-column fixed="right" align="center" label="鍊�" width="150">
+                      <template #default="scope">
+                        <el-input
+                          :model-value="getFormValue(scope.row.identifier)"
+                          @update:model-value="setFormValue(scope.row.identifier, $event)"
+                          placeholder="杈撳叆鍊�"
+                          size="small"
+                        />
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                  <div class="flex justify-between items-center mt-4">
+                    <span class="text-sm text-gray-600">
+                      璁剧疆灞炴�у�煎悗锛岀偣鍑汇�屽彂閫佸睘鎬т笂鎶ャ�嶆寜閽�
+                    </span>
+                    <el-button type="primary" @click="handlePropertyPost">鍙戦�佸睘鎬т笂鎶�</el-button>
+                  </div>
+                </ContentWrap>
+              </el-tab-pane>
+
+              <!-- 浜嬩欢涓婃姤 -->
+              <el-tab-pane label="浜嬩欢涓婃姤" :name="IotDeviceMessageMethodEnum.EVENT_POST.method">
+                <ContentWrap>
+                  <el-table :data="eventList" :show-overflow-tooltip="true" :stripe="true">
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鍔熻兘鍚嶇О"
+                      prop="name"
+                      width="120"
+                    />
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鏍囪瘑绗�"
+                      prop="identifier"
+                      width="120"
+                    />
+                    <el-table-column align="center" label="鏁版嵁绫诲瀷" width="100">
+                      <template #default="{ row }">
+                        {{ row.event?.dataType ?? '-' }}
+                      </template>
+                    </el-table-column>
+                    <el-table-column align="left" label="鏁版嵁瀹氫箟" min-width="200">
+                      <template #default="{ row }">
+                        <DataDefinition :data="row" />
+                      </template>
+                    </el-table-column>
+                    <el-table-column align="center" label="鍊�" width="200">
+                      <template #default="scope">
+                        <el-input
+                          :model-value="getFormValue(scope.row.identifier)"
+                          @update:model-value="setFormValue(scope.row.identifier, $event)"
+                          type="textarea"
+                          :rows="3"
+                          placeholder="杈撳叆浜嬩欢鍙傛暟锛圝SON鏍煎紡锛�"
+                          size="small"
+                        />
+                      </template>
+                    </el-table-column>
+                    <el-table-column fixed="right" align="center" label="鎿嶄綔" width="100">
+                      <template #default="scope">
+                        <el-button type="primary" size="small" @click="handleEventPost(scope.row)">
+                          涓婃姤浜嬩欢
+                        </el-button>
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                </ContentWrap>
+              </el-tab-pane>
+
+              <!-- 鐘舵�佸彉鏇� -->
+              <el-tab-pane label="鐘舵�佸彉鏇�" :name="IotDeviceMessageMethodEnum.STATE_UPDATE.method">
+                <ContentWrap>
+                  <div class="flex gap-4">
+                    <el-button type="primary" @click="handleDeviceState(DeviceStateEnum.ONLINE)">
+                      璁惧涓婄嚎
+                    </el-button>
+                    <el-button type="danger" @click="handleDeviceState(DeviceStateEnum.OFFLINE)">
+                      璁惧涓嬬嚎
+                    </el-button>
+                  </div>
+                </ContentWrap>
+              </el-tab-pane>
+            </el-tabs>
+          </el-tab-pane>
+
+          <!-- 涓嬭鎸囦护璋冭瘯 -->
+          <el-tab-pane label="涓嬭鎸囦护璋冭瘯" name="downstream">
+            <el-tabs v-if="activeTab === 'downstream'" v-model="downstreamTab">
+              <!-- 灞炴�ц皟璇� -->
+              <el-tab-pane label="灞炴�ц缃�" :name="IotDeviceMessageMethodEnum.PROPERTY_SET.method">
+                <ContentWrap>
+                  <el-table :data="propertyList" :show-overflow-tooltip="true" :stripe="true">
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鍔熻兘鍚嶇О"
+                      prop="name"
+                      width="120"
+                    />
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鏍囪瘑绗�"
+                      prop="identifier"
+                      width="120"
+                    />
+                    <el-table-column align="center" label="鏁版嵁绫诲瀷" width="100">
+                      <template #default="{ row }">
+                        {{ row.property?.dataType ?? '-' }}
+                      </template>
+                    </el-table-column>
+                    <el-table-column align="left" label="鏁版嵁瀹氫箟" min-width="200">
+                      <template #default="{ row }">
+                        <DataDefinition :data="row" />
+                      </template>
+                    </el-table-column>
+                    <el-table-column fixed="right" align="center" label="鍊�" width="150">
+                      <template #default="scope">
+                        <el-input
+                          :model-value="getFormValue(scope.row.identifier)"
+                          @update:model-value="setFormValue(scope.row.identifier, $event)"
+                          placeholder="杈撳叆鍊�"
+                          size="small"
+                        />
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                  <div class="flex justify-between items-center mt-4">
+                    <span class="text-sm text-gray-600">
+                      璁剧疆灞炴�у�煎悗锛岀偣鍑汇�屽彂閫佸睘鎬ц缃�嶆寜閽�
+                    </span>
+                    <el-button type="primary" @click="handlePropertySet">鍙戦�佸睘鎬ц缃�</el-button>
+                  </div>
+                </ContentWrap>
+              </el-tab-pane>
+
+              <!-- 鏈嶅姟璋冪敤 -->
+              <el-tab-pane
+                label="璁惧鏈嶅姟璋冪敤"
+                :name="IotDeviceMessageMethodEnum.SERVICE_INVOKE.method"
+              >
+                <ContentWrap>
+                  <el-table :data="serviceList" :show-overflow-tooltip="true" :stripe="true">
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鏈嶅姟鍚嶇О"
+                      prop="name"
+                      width="120"
+                    />
+                    <el-table-column
+                      fixed="left"
+                      align="center"
+                      label="鏍囪瘑绗�"
+                      prop="identifier"
+                      width="120"
+                    />
+                    <el-table-column align="left" label="杈撳叆鍙傛暟" min-width="200">
+                      <template #default="{ row }">
+                        <DataDefinition :data="row" />
+                      </template>
+                    </el-table-column>
+                    <el-table-column align="center" label="鍙傛暟鍊�" width="200">
+                      <template #default="scope">
+                        <el-input
+                          :model-value="getFormValue(scope.row.identifier)"
+                          @update:model-value="setFormValue(scope.row.identifier, $event)"
+                          type="textarea"
+                          :rows="3"
+                          placeholder="杈撳叆鏈嶅姟鍙傛暟锛圝SON鏍煎紡锛�"
+                          size="small"
+                        />
+                      </template>
+                    </el-table-column>
+                    <el-table-column fixed="right" align="center" label="鎿嶄綔" width="100">
+                      <template #default="scope">
+                        <el-button
+                          type="primary"
+                          size="small"
+                          @click="handleServiceInvoke(scope.row)"
+                        >
+                          鏈嶅姟璋冪敤
+                        </el-button>
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                </ContentWrap>
+              </el-tab-pane>
+            </el-tabs>
+          </el-tab-pane>
+        </el-tabs>
+      </el-col>
+
+      <!-- 鍙充晶璁惧鏃ュ織鍖哄煙 -->
+      <el-col :span="12">
+        <ContentWrap title="璁惧娑堟伅">
+          <DeviceDetailsMessage ref="deviceMessageRef" :device-id="device.id" />
+        </ContentWrap>
+      </el-col>
+    </el-row>
+  </ContentWrap>
+</template>
+
+<script lang="ts" setup>
+import { ProductVO } from '@/api/iot/product/product'
+import { ThingModelData } from '@/api/iot/thingmodel'
+import { DeviceApi, DeviceStateEnum, DeviceVO } from '@/api/iot/device/device'
+import DeviceDetailsMessage from './DeviceDetailsMessage.vue'
+import { DataDefinition } from '@/views/iot/thingmodel/components'
+import { IotDeviceMessageMethodEnum, IoTThingModelTypeEnum } from '@/views/iot/utils/constants'
+
+const props = defineProps<{
+  product: ProductVO
+  device: DeviceVO
+  thingModelList: ThingModelData[]
+}>()
+
+const message = useMessage() // 娑堟伅寮圭獥
+const activeTab = ref('upstream') // 涓婅upstream銆佷笅琛宒ownstream
+const upstreamTab = ref(IotDeviceMessageMethodEnum.PROPERTY_POST.method) // 涓婅瀛愭爣绛�
+const downstreamTab = ref(IotDeviceMessageMethodEnum.PROPERTY_SET.method) // 涓嬭瀛愭爣绛�
+const deviceMessageRef = ref() // 璁惧娑堟伅缁勪欢寮曠敤
+const deviceMessageRefreshDelay = 2000 // 寤惰繜 N 绉掞紝淇濊瘉妯℃嫙涓婅鐨勬秷鎭澶勭悊
+
+// 琛ㄥ崟鏁版嵁锛氬瓨鍌ㄧ敤鎴疯緭鍏ョ殑妯℃嫙鍊�
+const formData = ref<Record<string, string>>({})
+
+// 鏍规嵁绫诲瀷杩囨护鐗╂ā鍨嬫暟鎹�
+const getFilteredThingModelList = (type: number) => {
+  return props.thingModelList.filter((item) => item.type === type)
+}
+const propertyList = computed(() => getFilteredThingModelList(IoTThingModelTypeEnum.PROPERTY))
+const eventList = computed(() => getFilteredThingModelList(IoTThingModelTypeEnum.EVENT))
+const serviceList = computed(() => getFilteredThingModelList(IoTThingModelTypeEnum.SERVICE))
+
+/** 鑾峰彇琛ㄥ崟鍊肩殑杈呭姪鍑芥暟 */
+const getFormValue = (identifier: string | number | undefined) => {
+  if (!identifier) return ''
+  return formData.value[String(identifier)] || ''
+}
+/** 璁剧疆琛ㄥ崟鍊肩殑杈呭姪鍑芥暟 */
+const setFormValue = (identifier: string | number | undefined, value: string) => {
+  if (!identifier) return
+  formData.value[String(identifier)] = value
+}
+
+/** 妯℃嫙灞炴�т笂鎶� */
+const handlePropertyPost = async () => {
+  const data: Record<string, any> = {}
+  propertyList.value.forEach((item) => {
+    const value = getFormValue(item.identifier)
+    if (value && item.identifier) {
+      data[String(item.identifier)] = value
+    }
+  })
+  if (Object.keys(data).length === 0) {
+    message.warning('璇疯嚦灏戣缃竴涓睘鎬у��')
+    return
+  }
+
+  try {
+    await DeviceApi.sendDeviceMessage({
+      deviceId: props.device.id,
+      method: IotDeviceMessageMethodEnum.PROPERTY_POST.method,
+      params: data
+    })
+    message.success('灞炴�т笂鎶ユ垚鍔�')
+    deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
+  } catch (error) {
+    message.error('灞炴�т笂鎶ュけ璐�')
+  }
+}
+
+/** 妯℃嫙浜嬩欢涓婃姤 */
+const handleEventPost = async (eventItem: ThingModelData) => {
+  const value = getFormValue(eventItem.identifier)
+  if (!value) {
+    message.warning('璇疯緭鍏ヤ簨浠跺弬鏁�')
+    return
+  }
+  let eventParams: any
+  try {
+    eventParams = JSON.parse(value)
+  } catch {
+    message.error('浜嬩欢鍙傛暟鏍煎紡涓嶆纭紝璇疯緭鍏ユ湁鏁堢殑JSON鏍煎紡')
+    return
+  }
+
+  try {
+    await DeviceApi.sendDeviceMessage({
+      deviceId: props.device.id,
+      method: IotDeviceMessageMethodEnum.EVENT_POST.method,
+      params: {
+        identifier: String(eventItem.identifier),
+        value: eventParams,
+        time: Date.now()
+      }
+    })
+    message.success(`浜嬩欢銆�${String(eventItem.name)}銆戜笂鎶ユ垚鍔焋)
+    deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
+  } catch (error) {
+    message.error(`浜嬩欢銆�${String(eventItem.name)}銆戜笂鎶ュけ璐)
+  }
+}
+
+/** 妯℃嫙璁惧鐘舵�� */
+const handleDeviceState = async (state: number) => {
+  try {
+    await DeviceApi.sendDeviceMessage({
+      deviceId: props.device.id,
+      method: IotDeviceMessageMethodEnum.STATE_UPDATE.method,
+      params: {
+        state: state
+      }
+    })
+    message.success(`璁惧${state === DeviceStateEnum.ONLINE ? '涓婄嚎' : '涓嬬嚎'}鎴愬姛`)
+    deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
+  } catch (error) {
+    message.error(`璁惧${state === DeviceStateEnum.ONLINE ? '涓婄嚎' : '涓嬬嚎'}澶辫触`)
+  }
+}
+
+/** 妯℃嫙灞炴�ц缃� */
+const handlePropertySet = async () => {
+  const data: Record<string, any> = {}
+  propertyList.value.forEach((item) => {
+    const value = getFormValue(item.identifier)
+    if (value && item.identifier) {
+      data[String(item.identifier)] = value
+    }
+  })
+  if (Object.keys(data).length === 0) {
+    message.warning('璇疯嚦灏戣缃竴涓睘鎬у��')
+    return
+  }
+
+  try {
+    await DeviceApi.sendDeviceMessage({
+      deviceId: props.device.id,
+      method: IotDeviceMessageMethodEnum.PROPERTY_SET.method,
+      params: data
+    })
+    message.success('灞炴�ц缃垚鍔�')
+    deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
+  } catch (error) {
+    message.error('灞炴�ц缃け璐�')
+  }
+}
+
+/** 妯℃嫙鏈嶅姟璋冪敤 */
+const handleServiceInvoke = async (serviceItem: ThingModelData) => {
+  const value = getFormValue(serviceItem.identifier)
+  if (!value) {
+    message.warning('璇疯緭鍏ユ湇鍔″弬鏁�')
+    return
+  }
+  let serviceParams: any
+  try {
+    serviceParams = JSON.parse(value)
+  } catch {
+    message.error('鏈嶅姟鍙傛暟鏍煎紡涓嶆纭紝璇疯緭鍏ユ湁鏁堢殑JSON鏍煎紡')
+    return
+  }
+
+  try {
+    await DeviceApi.sendDeviceMessage({
+      deviceId: props.device.id,
+      method: IotDeviceMessageMethodEnum.SERVICE_INVOKE.method,
+      params: {
+        identifier: String(serviceItem.identifier),
+        inputParams: serviceParams
+      }
+    })
+    message.success(`鏈嶅姟銆�${String(serviceItem.name)}銆戣皟鐢ㄦ垚鍔焋)
+    deviceMessageRef.value.refresh(deviceMessageRefreshDelay)
+  } catch (error) {
+    message.error(`鏈嶅姟銆�${String(serviceItem.name)}銆戣皟鐢ㄥけ璐)
+  }
+}
+</script>

--
Gitblit v1.8.0