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/rule/data/rule/components/SourceConfigForm.vue | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 262 insertions(+), 0 deletions(-)
diff --git a/src/views/iot/rule/data/rule/components/SourceConfigForm.vue b/src/views/iot/rule/data/rule/components/SourceConfigForm.vue
new file mode 100644
index 0000000..4e10138
--- /dev/null
+++ b/src/views/iot/rule/data/rule/components/SourceConfigForm.vue
@@ -0,0 +1,262 @@
+<template>
+ <el-form
+ ref="formRef"
+ :model="formData"
+ :rules="formRules"
+ label-width="0px"
+ :inline-message="true"
+ >
+ <el-table :data="formData" class="-mt-10px">
+ <el-table-column label="浜у搧" min-width="150">
+ <template #default="{ row, $index }">
+ <el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
+ <el-select
+ v-model="row.productId"
+ placeholder="璇烽�夋嫨浜у搧"
+ @change="handleProductChange(row, $index)"
+ clearable
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="product in productList"
+ :key="product.id"
+ :label="product.name"
+ :value="product.id"
+ />
+ </el-select>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="璁惧" min-width="150">
+ <template #default="{ row, $index }">
+ <el-form-item :prop="`${$index}.deviceId`" :rules="formRules.deviceId" class="mb-0px!">
+ <el-select
+ v-model="row.deviceId"
+ placeholder="璇烽�夋嫨璁惧"
+ clearable
+ filterable
+ style="width: 100%"
+ >
+ <el-option label="鍏ㄩ儴璁惧" :value="0" />
+ <el-option
+ v-for="device in getFilteredDevices(row.productId)"
+ :key="device.id"
+ :label="device.deviceName"
+ :value="device.id"
+ />
+ </el-select>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="娑堟伅" min-width="150">
+ <template #default="{ row, $index }">
+ <el-form-item :prop="`${$index}.method`" :rules="formRules.method" class="mb-0px!">
+ <el-select
+ v-model="row.method"
+ placeholder="璇烽�夋嫨娑堟伅"
+ @change="handleMethodChange(row, $index)"
+ clearable
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="method in upstreamMethods"
+ :key="method.method"
+ :label="method.name"
+ :value="method.method"
+ />
+ </el-select>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏍囪瘑绗�" min-width="200">
+ <template #default="{ row, $index }">
+ <el-form-item :prop="`${$index}.identifier`" class="mb-0px!">
+ <el-select
+ v-if="shouldShowIdentifierSelect(row)"
+ v-model="row.identifier"
+ placeholder="璇烽�夋嫨鏍囪瘑绗�"
+ clearable
+ filterable
+ style="width: 100%"
+ v-loading="row.identifierLoading"
+ >
+ <el-option
+ v-for="item in getThingModelOptions(row)"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </template>
+ </el-table-column>
+ <el-table-column align="center" fixed="right" label="鎿嶄綔" width="60">
+ <template #default="{ $index }">
+ <el-button @click="handleDelete($index)" link type="danger">鈥�</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <el-row justify="center" class="mt-3">
+ <el-button @click="handleAdd" type="primary" plain round>+ 娣诲姞鏁版嵁婧�</el-button>
+ </el-row>
+ </el-form>
+</template>
+
+<script setup lang="ts">
+import { ProductApi } from '@/api/iot/product/product'
+import { DeviceApi } from '@/api/iot/device/device'
+import { ThingModelApi } from '@/api/iot/thingmodel'
+import { IotDeviceMessageMethodEnum, IoTThingModelTypeEnum } from '@/views/iot/utils/constants'
+
+const formData = ref<any[]>([])
+const productList = ref<any[]>([]) // 浜у搧鍒楄〃
+const deviceList = ref<any[]>([]) // 璁惧鍒楄〃
+const thingModelCache = ref<Map<number, any[]>>(new Map()) // 缂撳瓨鐗╂ā鍨嬫暟鎹紝key 涓� productId
+
+const formRules = reactive({
+ productId: [{ required: true, message: '浜у搧涓嶈兘涓虹┖', trigger: 'change' }],
+ deviceId: [{ required: true, message: '璁惧涓嶈兘涓虹┖', trigger: 'change' }],
+ method: [{ required: true, message: '娑堟伅鏂规硶涓嶈兘涓虹┖', trigger: 'change' }]
+})
+const formRef = ref() // 琛ㄥ崟 Ref
+
+// 鑾峰彇涓婅娑堟伅鏂规硶鍒楄〃
+const upstreamMethods = computed(() => {
+ return Object.values(IotDeviceMessageMethodEnum).filter((item) => item.upstream)
+})
+
+/** 鏍规嵁浜у搧 ID 杩囨护璁惧 */
+const getFilteredDevices = (productId: number) => {
+ if (!productId) return []
+ return deviceList.value.filter((device: any) => device.productId === productId)
+}
+
+/** 鍒ゆ柇鏄惁闇�瑕佹樉绀烘爣璇嗙閫夋嫨鍣� */
+const shouldShowIdentifierSelect = (row: any) => {
+ return [
+ IotDeviceMessageMethodEnum.EVENT_POST.method,
+ IotDeviceMessageMethodEnum.PROPERTY_POST.method
+ ].includes(row.method)
+}
+
+/** 鑾峰彇鐗╂ā鍨嬮�夐」 */
+const getThingModelOptions = (row: any) => {
+ if (!row.productId || !shouldShowIdentifierSelect(row)) {
+ return []
+ }
+ const thingModels: any[] = thingModelCache.value.get(row.productId) || []
+ let filteredModels: any[] = []
+ if (row.method === IotDeviceMessageMethodEnum.EVENT_POST.method) {
+ filteredModels = thingModels.filter((item: any) => item.type === IoTThingModelTypeEnum.EVENT)
+ } else if (row.method === IotDeviceMessageMethodEnum.PROPERTY_POST.method) {
+ filteredModels = thingModels.filter((item: any) => item.type === IoTThingModelTypeEnum.PROPERTY)
+ }
+ return filteredModels.map((item: any) => ({
+ label: `${item.name} (${item.identifier})`,
+ value: item.identifier
+ }))
+}
+
+/** 鍔犺浇浜у搧鍒楄〃 */
+const loadProductList = async () => {
+ try {
+ productList.value = await ProductApi.getSimpleProductList()
+ } catch (error) {
+ console.error('鍔犺浇浜у搧鍒楄〃澶辫触:', error)
+ }
+}
+
+/** 鍔犺浇璁惧鍒楄〃 */
+const loadDeviceList = async () => {
+ try {
+ deviceList.value = await DeviceApi.getSimpleDeviceList()
+ } catch (error) {
+ console.error('鍔犺浇璁惧鍒楄〃澶辫触:', error)
+ }
+}
+
+/** 鍔犺浇鐗╂ā鍨嬫暟鎹� */
+const loadThingModel = async (productId: number) => {
+ // 宸茬紦瀛橈紝鏃犻渶閲嶅鍔犺浇
+ if (thingModelCache.value.has(productId)) {
+ return
+ }
+ try {
+ const thingModels = await ThingModelApi.getThingModelList({ productId })
+ thingModelCache.value.set(productId, thingModels)
+ } catch (error) {
+ console.error('鍔犺浇鐗╂ā鍨嬪け璐�:', error)
+ }
+}
+
+/** 浜у搧鍙樺寲鏃跺鐞� */
+const handleProductChange = async (row: any, _index: number) => {
+ row.deviceId = 0
+ row.method = undefined
+ row.identifier = undefined
+ row.identifierLoading = false
+}
+
+/** 娑堟伅鏂规硶鍙樺寲鏃跺鐞� */
+const handleMethodChange = async (row: any, _index: number) => {
+ // 娓呯┖鏍囪瘑绗�
+ row.identifier = undefined
+ // 濡傛灉闇�瑕佸姞杞界墿妯″瀷鏁版嵁
+ if (shouldShowIdentifierSelect(row) && row.productId) {
+ row.identifierLoading = true
+ await loadThingModel(row.productId)
+ row.identifierLoading = false
+ }
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+const handleAdd = () => {
+ const row = {
+ productId: undefined,
+ deviceId: undefined,
+ method: undefined,
+ identifier: undefined,
+ identifierLoading: false
+ }
+ formData.value.push(row)
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+const handleDelete = (index: number) => {
+ formData.value.splice(index, 1)
+}
+
+/** 琛ㄥ崟鏍¢獙 */
+const validate = () => {
+ return formRef.value.validate()
+}
+
+/** 琛ㄥ崟鍊� */
+const getData = () => {
+ return formData.value
+}
+
+/** 璁剧疆琛ㄥ崟鍊� */
+const setData = (data: any[]) => {
+ // 纭繚姣忎釜椤归兘鏈夊繀瑕佺殑瀛楁
+ formData.value = (data || []).map((item) => ({
+ ...item,
+ identifierLoading: false
+ }))
+ // 涓哄凡鏈夋暟鎹鍔犺浇鐗╂ā鍨�
+ data?.forEach(async (item) => {
+ if (item.productId && shouldShowIdentifierSelect(item)) {
+ await loadThingModel(item.productId)
+ }
+ })
+}
+
+/** 鍒濆鍖� */
+onMounted(async () => {
+ await Promise.all([loadProductList(), loadDeviceList()])
+})
+
+defineExpose({ validate, getData, setData })
+</script>
--
Gitblit v1.8.0