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/scene/form/RuleSceneForm.vue | 330 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 330 insertions(+), 0 deletions(-)
diff --git a/src/views/iot/rule/scene/form/RuleSceneForm.vue b/src/views/iot/rule/scene/form/RuleSceneForm.vue
new file mode 100644
index 0000000..22ba268
--- /dev/null
+++ b/src/views/iot/rule/scene/form/RuleSceneForm.vue
@@ -0,0 +1,330 @@
+<template>
+ <el-drawer
+ v-model="drawerVisible"
+ :title="drawerTitle"
+ size="80%"
+ direction="rtl"
+ :close-on-click-modal="false"
+ :close-on-press-escape="false"
+ @close="handleClose"
+ >
+ <el-form ref="formRef" :model="formData" :rules="formRules" label-width="110px">
+ <!-- 鍩虹淇℃伅閰嶇疆 -->
+ <BasicInfoSection v-model="formData" :rules="formRules" />
+ <!-- 瑙﹀彂鍣ㄩ厤缃� -->
+ <TriggerSection v-model:triggers="formData.triggers" />
+ <!-- 鎵ц鍣ㄩ厤缃� -->
+ <ActionSection v-model:actions="formData.actions" />
+ </el-form>
+ <template #footer>
+ <div class="drawer-footer">
+ <el-button :disabled="submitLoading" type="primary" @click="handleSubmit">
+ <Icon icon="ep:check" />
+ 纭� 瀹�
+ </el-button>
+ <el-button @click="handleClose">
+ <Icon icon="ep:close" />
+ 鍙� 娑�
+ </el-button>
+ </div>
+ </template>
+ </el-drawer>
+</template>
+
+<script setup lang="ts">
+import { useVModel } from '@vueuse/core'
+import BasicInfoSection from './sections/BasicInfoSection.vue'
+import TriggerSection from './sections/TriggerSection.vue'
+import ActionSection from './sections/ActionSection.vue'
+import { IotSceneRule } from '@/api/iot/rule/scene'
+import { RuleSceneApi } from '@/api/iot/rule/scene'
+import {
+ IotRuleSceneTriggerTypeEnum,
+ IotRuleSceneActionTypeEnum,
+ isDeviceTrigger
+} from '@/views/iot/utils/constants'
+import { ElMessage } from 'element-plus'
+import { CommonStatusEnum } from '@/utils/constants'
+
+/** IoT 鍦烘櫙鑱斿姩瑙勫垯琛ㄥ崟 - 涓昏〃鍗曠粍浠� */
+defineOptions({ name: 'RuleSceneForm' })
+
+/** 缁勪欢灞炴�у畾涔� */
+const props = defineProps<{
+ /** 鎶藉眽鏄剧ず鐘舵�� */
+ modelValue: boolean
+ /** 缂栬緫鐨勫満鏅仈鍔ㄨ鍒欐暟鎹� */
+ ruleScene?: IotSceneRule
+}>()
+
+/** 缁勪欢浜嬩欢瀹氫箟 */
+const emit = defineEmits<{
+ (e: 'update:modelValue', value: boolean): void
+ (e: 'success'): void
+}>()
+
+const drawerVisible = useVModel(props, 'modelValue', emit) // 鎶藉眽鏄剧ず鐘舵��
+
+/**
+ * 鍒涘缓榛樿鐨勮〃鍗曟暟鎹�
+ * @returns 榛樿琛ㄥ崟鏁版嵁瀵硅薄
+ */
+const createDefaultFormData = (): IotSceneRule => {
+ return {
+ name: '',
+ description: '',
+ status: CommonStatusEnum.ENABLE, // 榛樿鍚敤鐘舵��
+ triggers: [
+ {
+ type: IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST,
+ productId: undefined,
+ deviceId: undefined,
+ identifier: undefined,
+ operator: undefined,
+ value: undefined,
+ cronExpression: undefined,
+ conditionGroups: [] // 绌虹殑鏉′欢缁勬暟缁�
+ }
+ ],
+ actions: []
+ }
+}
+
+const formRef = ref() // 琛ㄥ崟寮曠敤
+const formData = ref<IotSceneRule>(createDefaultFormData()) // 琛ㄥ崟鏁版嵁
+
+/**
+ * 瑙﹀彂鍣ㄦ牎楠屽櫒
+ * @param _rule 鏍¢獙瑙勫垯锛堟湭浣跨敤锛�
+ * @param value 鏍¢獙鍊�
+ * @param callback 鍥炶皟鍑芥暟
+ */
+const validateTriggers = (_rule: any, value: any, callback: any) => {
+ if (!value || !Array.isArray(value) || value.length === 0) {
+ callback(new Error('鑷冲皯闇�瑕佷竴涓Е鍙戝櫒'))
+ return
+ }
+
+ for (let i = 0; i < value.length; i++) {
+ const trigger = value[i]
+
+ // 鏍¢獙瑙﹀彂鍣ㄧ被鍨�
+ if (!trigger.type) {
+ callback(new Error(`瑙﹀彂鍣� ${i + 1}: 瑙﹀彂鍣ㄧ被鍨嬩笉鑳戒负绌篳))
+ return
+ }
+
+ // 鏍¢獙璁惧瑙﹀彂鍣�
+ if (isDeviceTrigger(trigger.type)) {
+ if (!trigger.productId) {
+ callback(new Error(`瑙﹀彂鍣� ${i + 1}: 浜у搧涓嶈兘涓虹┖`))
+ return
+ }
+ if (!trigger.deviceId) {
+ callback(new Error(`瑙﹀彂鍣� ${i + 1}: 璁惧涓嶈兘涓虹┖`))
+ return
+ }
+ if (!trigger.identifier) {
+ callback(new Error(`瑙﹀彂鍣� ${i + 1}: 鐗╂ā鍨嬫爣璇嗙涓嶈兘涓虹┖`))
+ return
+ }
+ if (!trigger.operator) {
+ callback(new Error(`瑙﹀彂鍣� ${i + 1}: 鎿嶄綔绗︿笉鑳戒负绌篳))
+ return
+ }
+ if (trigger.value === undefined || trigger.value === null || trigger.value === '') {
+ callback(new Error(`瑙﹀彂鍣� ${i + 1}: 鍙傛暟鍊间笉鑳戒负绌篳))
+ return
+ }
+ }
+
+ // 鏍¢獙瀹氭椂瑙﹀彂鍣�
+ if (trigger.type === IotRuleSceneTriggerTypeEnum.TIMER) {
+ if (!trigger.cronExpression) {
+ callback(new Error(`瑙﹀彂鍣� ${i + 1}: CRON琛ㄨ揪寮忎笉鑳戒负绌篳))
+ return
+ }
+ }
+ }
+
+ callback()
+}
+
+/**
+ * 鎵ц鍣ㄦ牎楠屽櫒
+ * @param _rule 鏍¢獙瑙勫垯锛堟湭浣跨敤锛�
+ * @param value 鏍¢獙鍊�
+ * @param callback 鍥炶皟鍑芥暟
+ */
+const validateActions = (_rule: any, value: any, callback: any) => {
+ if (!value || !Array.isArray(value) || value.length === 0) {
+ callback(new Error('鑷冲皯闇�瑕佷竴涓墽琛屽櫒'))
+ return
+ }
+
+ for (let i = 0; i < value.length; i++) {
+ const action = value[i]
+
+ // 鏍¢獙鎵ц鍣ㄧ被鍨�
+ if (!action.type) {
+ callback(new Error(`鎵ц鍣� ${i + 1}: 鎵ц鍣ㄧ被鍨嬩笉鑳戒负绌篳))
+ return
+ }
+
+ // 鏍¢獙璁惧鎺у埗鎵ц鍣�
+ if (
+ action.type === IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET ||
+ action.type === IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE
+ ) {
+ if (!action.productId) {
+ callback(new Error(`鎵ц鍣� ${i + 1}: 浜у搧涓嶈兘涓虹┖`))
+ return
+ }
+ if (!action.deviceId) {
+ callback(new Error(`鎵ц鍣� ${i + 1}: 璁惧涓嶈兘涓虹┖`))
+ return
+ }
+
+ // 鏈嶅姟璋冪敤闇�瑕侀獙璇佹湇鍔℃爣璇嗙
+ if (action.type === IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE) {
+ if (!action.identifier) {
+ callback(new Error(`鎵ц鍣� ${i + 1}: 鏈嶅姟涓嶈兘涓虹┖`))
+ return
+ }
+ }
+
+ if (!action.params || Object.keys(action.params).length === 0) {
+ callback(new Error(`鎵ц鍣� ${i + 1}: 鍙傛暟閰嶇疆涓嶈兘涓虹┖`))
+ return
+ }
+ }
+
+ // 鏍¢獙鍛婅鎵ц鍣�
+ if (
+ action.type === IotRuleSceneActionTypeEnum.ALERT_TRIGGER ||
+ action.type === IotRuleSceneActionTypeEnum.ALERT_RECOVER
+ ) {
+ if (!action.alertConfigId) {
+ callback(new Error(`鎵ц鍣� ${i + 1}: 鍛婅閰嶇疆涓嶈兘涓虹┖`))
+ return
+ }
+ }
+ }
+
+ callback()
+}
+
+const formRules = reactive({
+ name: [
+ { required: true, message: '鍦烘櫙鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' },
+ { type: 'string', min: 1, max: 50, message: '鍦烘櫙鍚嶇О闀垮害搴斿湪1-50涓瓧绗︿箣闂�', trigger: 'blur' }
+ ],
+ status: [
+ { required: true, message: '鍦烘櫙鐘舵�佷笉鑳戒负绌�', trigger: 'change' },
+ {
+ type: 'enum',
+ enum: [CommonStatusEnum.ENABLE, CommonStatusEnum.DISABLE],
+ message: '鐘舵�佸�煎繀椤讳负鍚敤鎴栫鐢�',
+ trigger: 'change'
+ }
+ ],
+ description: [
+ { type: 'string', max: 200, message: '鍦烘櫙鎻忚堪涓嶈兘瓒呰繃200涓瓧绗�', trigger: 'blur' }
+ ],
+ triggers: [{ required: true, validator: validateTriggers, trigger: 'change' }],
+ actions: [{ required: true, validator: validateActions, trigger: 'change' }]
+}) // 琛ㄥ崟鏍¢獙瑙勫垯
+
+const submitLoading = ref(false) // 鎻愪氦鍔犺浇鐘舵��
+const isEdit = ref(false) // 鏄惁涓虹紪杈戞ā寮�
+const drawerTitle = computed(() => (isEdit.value ? '缂栬緫鍦烘櫙鑱斿姩瑙勫垯' : '鏂板鍦烘櫙鑱斿姩瑙勫垯')) // 鎶藉眽鏍囬
+
+/** 鎻愪氦琛ㄥ崟 */
+const handleSubmit = async () => {
+ // 鏍¢獙琛ㄥ崟
+ if (!formRef.value) return
+ const valid = await formRef.value.validate()
+ if (!valid) return
+
+ // 鎻愪氦璇锋眰
+ submitLoading.value = true
+ try {
+ if (isEdit.value) {
+ // 鏇存柊鍦烘櫙鑱斿姩瑙勫垯
+ await RuleSceneApi.updateRuleScene(formData.value)
+ ElMessage.success('鏇存柊鎴愬姛')
+ } else {
+ // 鍒涘缓鍦烘櫙鑱斿姩瑙勫垯
+ await RuleSceneApi.createRuleScene(formData.value)
+ ElMessage.success('鍒涘缓鎴愬姛')
+ }
+
+ // 鍏抽棴鎶藉眽骞惰Е鍙戞垚鍔熶簨浠�
+ drawerVisible.value = false
+ emit('success')
+ } catch (error) {
+ console.error('淇濆瓨澶辫触:', error)
+ ElMessage.error(isEdit.value ? '鏇存柊澶辫触' : '鍒涘缓澶辫触')
+ } finally {
+ submitLoading.value = false
+ }
+}
+
+/** 澶勭悊鎶藉眽鍏抽棴浜嬩欢 */
+const handleClose = () => {
+ drawerVisible.value = false
+}
+
+/** 鍒濆鍖栬〃鍗曟暟鎹� */
+const initFormData = () => {
+ if (props.ruleScene) {
+ // 缂栬緫妯″紡锛氭暟鎹粨鏋勫凡瀵归綈锛岀洿鎺ヤ娇鐢ㄥ悗绔暟鎹�
+ isEdit.value = true
+ formData.value = {
+ ...props.ruleScene,
+ // 纭繚瑙﹀彂鍣ㄦ暟缁勪笉涓虹┖
+ triggers: props.ruleScene.triggers?.length
+ ? props.ruleScene.triggers
+ : [
+ {
+ type: IotRuleSceneTriggerTypeEnum.DEVICE_PROPERTY_POST,
+ productId: undefined,
+ deviceId: undefined,
+ identifier: undefined,
+ operator: undefined,
+ value: undefined,
+ cronExpression: undefined,
+ conditionGroups: []
+ }
+ ],
+ // 纭繚鎵ц鍣ㄦ暟缁勪笉涓虹┖
+ actions: props.ruleScene.actions || []
+ }
+ } else {
+ // 鏂板妯″紡锛氫娇鐢ㄩ粯璁ゆ暟鎹�
+ isEdit.value = false
+ formData.value = createDefaultFormData()
+ }
+}
+
+/** 鐩戝惉鎶藉眽鏄剧ず */
+watch(drawerVisible, async (visible) => {
+ if (visible) {
+ initFormData()
+ // 閲嶇疆琛ㄥ崟楠岃瘉鐘舵��
+ await nextTick()
+ formRef.value?.clearValidate()
+ }
+})
+
+/** 鐩戝惉缂栬緫鏁版嵁鍙樺寲 */
+watch(
+ () => props.ruleScene,
+ () => {
+ if (drawerVisible.value) {
+ initFormData()
+ }
+ },
+ { deep: true }
+)
+</script>
--
Gitblit v1.8.0