refactor: 收敛 iot rule/scene API 的重复类型声明(P1)
- antd / ele api/iot/rule/scene,删除外层重复的 4 个 interface - createSceneRule / updateSceneRule 入参改用 RuleSceneApi.SceneRule - 业务文件 import 统一改用 RuleSceneApi.SceneRule / Trigger / TriggerCondition / Action - 清理 2 处 TODO @haohao 残留注释 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>pull/345/head
parent
df720b2c1a
commit
057ca0bfde
|
|
@ -50,53 +50,6 @@ export namespace RuleSceneApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @haohao:貌似下面的,和 RuleSceneApi 重复了。
|
|
||||||
/** IoT 场景联动规则 */
|
|
||||||
export interface IotSceneRule {
|
|
||||||
id?: number;
|
|
||||||
name?: string;
|
|
||||||
description?: string;
|
|
||||||
status?: number;
|
|
||||||
triggers?: Trigger[];
|
|
||||||
actions?: Action[];
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IoT 场景联动规则触发器 */
|
|
||||||
export interface Trigger {
|
|
||||||
type?: number;
|
|
||||||
productId?: number;
|
|
||||||
deviceId?: number;
|
|
||||||
identifier?: string;
|
|
||||||
operator?: string;
|
|
||||||
value?: any;
|
|
||||||
cronExpression?: string;
|
|
||||||
// 后端结构:List<List<TriggerCondition>>;外层「或」、组内「且」
|
|
||||||
conditionGroups?: TriggerCondition[][];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IoT 场景联动规则触发条件 */
|
|
||||||
export interface TriggerCondition {
|
|
||||||
productId?: number;
|
|
||||||
deviceId?: number;
|
|
||||||
identifier?: string;
|
|
||||||
operator?: string;
|
|
||||||
value?: any;
|
|
||||||
type?: number;
|
|
||||||
param?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IoT 场景联动规则动作 */
|
|
||||||
export interface Action {
|
|
||||||
type?: number;
|
|
||||||
productId?: number;
|
|
||||||
deviceId?: number;
|
|
||||||
identifier?: string;
|
|
||||||
value?: any;
|
|
||||||
alertConfigId?: number;
|
|
||||||
params?: Record<string, any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询场景联动规则分页 */
|
/** 查询场景联动规则分页 */
|
||||||
export function getSceneRulePage(params: PageParam) {
|
export function getSceneRulePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<RuleSceneApi.SceneRule>>(
|
return requestClient.get<PageResult<RuleSceneApi.SceneRule>>(
|
||||||
|
|
@ -113,12 +66,12 @@ export function getSceneRule(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增场景联动规则 */
|
/** 新增场景联动规则 */
|
||||||
export function createSceneRule(data: IotSceneRule) {
|
export function createSceneRule(data: RuleSceneApi.SceneRule) {
|
||||||
return requestClient.post('/iot/scene-rule/create', data);
|
return requestClient.post('/iot/scene-rule/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改场景联动规则 */
|
/** 修改场景联动规则 */
|
||||||
export function updateSceneRule(data: IotSceneRule) {
|
export function updateSceneRule(data: RuleSceneApi.SceneRule) {
|
||||||
return requestClient.put('/iot/scene-rule/update', data);
|
return requestClient.put('/iot/scene-rule/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +81,6 @@ export function deleteSceneRule(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除场景联动规则 */
|
/** 批量删除场景联动规则 */
|
||||||
// TODO @haohao:貌似用上。
|
|
||||||
export function deleteSceneRuleList(ids: number[]) {
|
export function deleteSceneRuleList(ids: number[]) {
|
||||||
return requestClient.delete('/iot/scene-rule/delete-list', {
|
return requestClient.delete('/iot/scene-rule/delete-list', {
|
||||||
params: { ids: ids.join(',') },
|
params: { ids: ids.join(',') },
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 单个条件配置组件 -->
|
<!-- 单个条件配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -25,12 +25,12 @@ import CurrentTimeConditionConfig from './current-time-condition-config.vue';
|
||||||
defineOptions({ name: 'ConditionConfig' });
|
defineOptions({ name: 'ConditionConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: TriggerCondition;
|
modelValue: RuleSceneApi.TriggerCondition;
|
||||||
triggerType: number;
|
triggerType: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
/** 获取设备状态选项 */
|
/** 获取设备状态选项 */
|
||||||
|
|
@ -84,7 +84,7 @@ function updateConditionField(field: any, value: any) {
|
||||||
* 更新整个条件对象
|
* 更新整个条件对象
|
||||||
* @param newCondition 新的条件对象
|
* @param newCondition 新的条件对象
|
||||||
*/
|
*/
|
||||||
function updateCondition(newCondition: TriggerCondition) {
|
function updateCondition(newCondition: RuleSceneApi.TriggerCondition) {
|
||||||
condition.value = newCondition;
|
condition.value = newCondition;
|
||||||
emit('update:modelValue', condition.value);
|
emit('update:modelValue', condition.value);
|
||||||
}
|
}
|
||||||
|
|
@ -163,10 +163,12 @@ function handleOperatorChange() {
|
||||||
<Form.Item label="条件类型" required>
|
<Form.Item label="条件类型" required>
|
||||||
<Select
|
<Select
|
||||||
:value="condition.type"
|
:value="condition.type"
|
||||||
@change="(value: any) => {
|
@change="
|
||||||
|
(value: any) => {
|
||||||
updateConditionField('type', value);
|
updateConditionField('type', value);
|
||||||
handleConditionTypeChange(value);
|
handleConditionTypeChange(value);
|
||||||
}"
|
}
|
||||||
|
"
|
||||||
placeholder="请选择条件类型"
|
placeholder="请选择条件类型"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
|
|
@ -212,8 +214,7 @@ function handleOperatorChange() {
|
||||||
<!-- 设备状态条件配置 -->
|
<!-- 设备状态条件配置 -->
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="
|
||||||
condition.type ===
|
condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS
|
||||||
IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS
|
|
||||||
"
|
"
|
||||||
class="gap-[16px] flex flex-col"
|
class="gap-[16px] flex flex-col"
|
||||||
>
|
>
|
||||||
|
|
@ -224,10 +225,7 @@ function handleOperatorChange() {
|
||||||
<Form.Item label="操作符" required>
|
<Form.Item label="操作符" required>
|
||||||
<Select
|
<Select
|
||||||
:value="condition.operator"
|
:value="condition.operator"
|
||||||
@change="
|
@change="(value: any) => updateConditionField('operator', value)"
|
||||||
(value: any) => updateConditionField('operator', value)
|
|
||||||
|
|
||||||
"
|
|
||||||
placeholder="请选择操作符"
|
placeholder="请选择操作符"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
|
|
@ -247,10 +245,7 @@ function handleOperatorChange() {
|
||||||
<Form.Item label="设备状态" required>
|
<Form.Item label="设备状态" required>
|
||||||
<Select
|
<Select
|
||||||
:value="condition.param"
|
:value="condition.param"
|
||||||
@change="
|
@change="(value: any) => updateConditionField('param', value)"
|
||||||
(value: any) => updateConditionField('param', value)
|
|
||||||
|
|
||||||
"
|
|
||||||
placeholder="请选择设备状态"
|
placeholder="请选择设备状态"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
|
|
@ -270,8 +265,7 @@ function handleOperatorChange() {
|
||||||
<!-- 设备属性条件配置 -->
|
<!-- 设备属性条件配置 -->
|
||||||
<div
|
<div
|
||||||
v-else-if="
|
v-else-if="
|
||||||
condition.type ===
|
condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY
|
||||||
IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY
|
|
||||||
"
|
"
|
||||||
class="space-y-[16px]"
|
class="space-y-[16px]"
|
||||||
>
|
>
|
||||||
|
|
@ -327,8 +321,7 @@ function handleOperatorChange() {
|
||||||
<!-- 当前时间条件配置 -->
|
<!-- 当前时间条件配置 -->
|
||||||
<CurrentTimeConditionConfig
|
<CurrentTimeConditionConfig
|
||||||
v-else-if="
|
v-else-if="
|
||||||
condition.type ===
|
condition.type === IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME
|
||||||
IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME
|
|
||||||
"
|
"
|
||||||
:model-value="condition"
|
:model-value="condition"
|
||||||
@update:model-value="updateCondition"
|
@update:model-value="updateCondition"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 当前时间条件配置组件 -->
|
<!-- 当前时间条件配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
|
|
||||||
|
|
@ -22,11 +22,11 @@ import {
|
||||||
defineOptions({ name: 'CurrentTimeConditionConfig' });
|
defineOptions({ name: 'CurrentTimeConditionConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: TriggerCondition;
|
modelValue: RuleSceneApi.TriggerCondition;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const condition = useVModel(props, 'modelValue', emit);
|
const condition = useVModel(props, 'modelValue', emit);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 设备控制配置组件 -->
|
<!-- 设备控制配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Action } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
import type { ThingModelApi } from '#/api/iot/thingmodel';
|
import type { ThingModelApi } from '#/api/iot/thingmodel';
|
||||||
|
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
import { computed, onMounted, ref, watch } from 'vue';
|
||||||
|
|
@ -25,11 +25,11 @@ import ProductSelector from '../selectors/product-selector.vue';
|
||||||
defineOptions({ name: 'DeviceControlConfig' });
|
defineOptions({ name: 'DeviceControlConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: Action;
|
modelValue: RuleSceneApi.Action;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: Action): void;
|
(e: 'update:modelValue', value: RuleSceneApi.Action): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const action = useVModel(props, 'modelValue', emit);
|
const action = useVModel(props, 'modelValue', emit);
|
||||||
|
|
@ -58,18 +58,12 @@ const paramsValue = computed({
|
||||||
|
|
||||||
// 计算属性:是否为属性设置类型
|
// 计算属性:是否为属性设置类型
|
||||||
const isPropertySetAction = computed(() => {
|
const isPropertySetAction = computed(() => {
|
||||||
return (
|
return action.value.type === IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET;
|
||||||
action.value.type ===
|
|
||||||
IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算属性:是否为服务调用类型
|
// 计算属性:是否为服务调用类型
|
||||||
const isServiceInvokeAction = computed(() => {
|
const isServiceInvokeAction = computed(() => {
|
||||||
return (
|
return action.value.type === IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE;
|
||||||
action.value.type ===
|
|
||||||
IotRuleSceneActionTypeEnum.DEVICE_SERVICE_INVOKE
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -358,7 +352,10 @@ watch(
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<!-- 服务选择 - 服务调用类型时显示 -->
|
<!-- 服务选择 - 服务调用类型时显示 -->
|
||||||
<div v-if="action.productId && isServiceInvokeAction" class="space-y-[16px]">
|
<div
|
||||||
|
v-if="action.productId && isServiceInvokeAction"
|
||||||
|
class="space-y-[16px]"
|
||||||
|
>
|
||||||
<Form.Item label="服务" required>
|
<Form.Item label="服务" required>
|
||||||
<Select
|
<Select
|
||||||
v-model:value="action.identifier"
|
v-model:value="action.identifier"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Trigger } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -25,12 +25,12 @@ import PropertySelector from '../selectors/property-selector.vue';
|
||||||
defineOptions({ name: 'MainConditionInnerConfig' });
|
defineOptions({ name: 'MainConditionInnerConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: Trigger;
|
modelValue: RuleSceneApi.Trigger;
|
||||||
triggerType: number;
|
triggerType: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: Trigger): void;
|
(e: 'update:modelValue', value: RuleSceneApi.Trigger): void;
|
||||||
(e: 'triggerTypeChange', value: number): void;
|
(e: 'triggerTypeChange', value: number): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|
@ -325,9 +325,7 @@ function handlePropertyChange(propertyInfo: any) {
|
||||||
<Form.Item label="操作符" required>
|
<Form.Item label="操作符" required>
|
||||||
<Select
|
<Select
|
||||||
:value="condition.operator"
|
:value="condition.operator"
|
||||||
@change="
|
@change="(value: any) => updateConditionField('operator', value)"
|
||||||
(value: any) => updateConditionField('operator', value)
|
|
||||||
"
|
|
||||||
placeholder="请选择操作符"
|
placeholder="请选择操作符"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
|
|
@ -347,9 +345,7 @@ function handlePropertyChange(propertyInfo: any) {
|
||||||
<Form.Item label="参数" required>
|
<Form.Item label="参数" required>
|
||||||
<Select
|
<Select
|
||||||
:value="condition.value"
|
:value="condition.value"
|
||||||
@change="
|
@change="(value: any) => updateConditionField('value', value)"
|
||||||
(value: any) => updateConditionField('value', value)
|
|
||||||
"
|
|
||||||
placeholder="请选择操作符"
|
placeholder="请选择操作符"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
|
|
@ -371,7 +367,9 @@ function handlePropertyChange(propertyInfo: any) {
|
||||||
<p class="mb-1 text-sm text-muted-foreground">
|
<p class="mb-1 text-sm text-muted-foreground">
|
||||||
当前触发事件类型:{{ getTriggerTypeLabel(triggerType) }}
|
当前触发事件类型:{{ getTriggerTypeLabel(triggerType) }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs text-muted-foreground">此触发类型暂不需要配置额外条件</p>
|
<p class="text-xs text-muted-foreground">
|
||||||
|
此触发类型暂不需要配置额外条件
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, nextTick } from 'vue';
|
import { computed, nextTick } from 'vue';
|
||||||
|
|
||||||
|
|
@ -19,12 +19,12 @@ defineOptions({ name: 'SubConditionGroupConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
maxConditions?: number;
|
maxConditions?: number;
|
||||||
modelValue: TriggerCondition[];
|
modelValue: RuleSceneApi.TriggerCondition[];
|
||||||
triggerType: number;
|
triggerType: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition[]): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const subGroup = useVModel(props, 'modelValue', emit);
|
const subGroup = useVModel(props, 'modelValue', emit);
|
||||||
|
|
@ -43,7 +43,7 @@ async function addCondition() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCondition: TriggerCondition = {
|
const newCondition: RuleSceneApi.TriggerCondition = {
|
||||||
type: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY, // 默认为设备属性
|
type: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY, // 默认为设备属性
|
||||||
productId: undefined,
|
productId: undefined,
|
||||||
deviceId: undefined,
|
deviceId: undefined,
|
||||||
|
|
@ -74,7 +74,10 @@ function removeCondition(index: number) {
|
||||||
* @param index 条件索引
|
* @param index 条件索引
|
||||||
* @param condition 条件对象
|
* @param condition 条件对象
|
||||||
*/
|
*/
|
||||||
function updateCondition(index: number, condition: TriggerCondition) {
|
function updateCondition(
|
||||||
|
index: number,
|
||||||
|
condition: RuleSceneApi.TriggerCondition,
|
||||||
|
) {
|
||||||
if (subGroup.value) {
|
if (subGroup.value) {
|
||||||
subGroup.value[index] = condition;
|
subGroup.value[index] = condition;
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +141,7 @@ function updateCondition(index: number, condition: TriggerCondition) {
|
||||||
<ConditionConfig
|
<ConditionConfig
|
||||||
:model-value="condition"
|
:model-value="condition"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value: TriggerCondition) =>
|
(value: RuleSceneApi.TriggerCondition) =>
|
||||||
updateCondition(conditionIndex, value)
|
updateCondition(conditionIndex, value)
|
||||||
"
|
"
|
||||||
:trigger-type="triggerType"
|
:trigger-type="triggerType"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
|
|
@ -12,11 +12,11 @@ import { Button, Tag } from 'ant-design-vue';
|
||||||
import SubConditionGroupConfig from './sub-condition-group-config.vue';
|
import SubConditionGroupConfig from './sub-condition-group-config.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue?: TriggerCondition[][];
|
modelValue?: RuleSceneApi.TriggerCondition[][];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition[][]): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition[][]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const conditionGroups = useVModel(props, 'modelValue', emit);
|
const conditionGroups = useVModel(props, 'modelValue', emit);
|
||||||
|
|
@ -46,7 +46,10 @@ function removeConditionGroup(index: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新条件组 */
|
/** 更新条件组 */
|
||||||
function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
function updateConditionGroup(
|
||||||
|
index: number,
|
||||||
|
group: RuleSceneApi.TriggerCondition[],
|
||||||
|
) {
|
||||||
if (conditionGroups.value) {
|
if (conditionGroups.value) {
|
||||||
conditionGroups.value[index] = group;
|
conditionGroups.value[index] = group;
|
||||||
}
|
}
|
||||||
|
|
@ -117,9 +120,7 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
<Tag color="warning" class="font-medium">
|
<Tag color="warning" class="font-medium">
|
||||||
组内条件为「且」关系
|
组内条件为「且」关系
|
||||||
</Tag>
|
</Tag>
|
||||||
<Tag color="default">
|
<Tag color="default"> {{ group?.length || 0 }} 个条件 </Tag>
|
||||||
{{ group?.length || 0 }} 个条件
|
|
||||||
</Tag>
|
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
|
|
@ -138,7 +139,7 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
:trigger-type="IotRuleSceneTriggerTypeEnum.TIMER"
|
:trigger-type="IotRuleSceneTriggerTypeEnum.TIMER"
|
||||||
:max-conditions="maxConditionsPerGroup"
|
:max-conditions="maxConditionsPerGroup"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value: TriggerCondition[]) =>
|
(value: RuleSceneApi.TriggerCondition[]) =>
|
||||||
updateConditionGroup(groupIndex, value)
|
updateConditionGroup(groupIndex, value)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|
@ -150,13 +151,19 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
class="py-[12px] flex items-center justify-center"
|
class="py-[12px] flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<div class="gap-[8px] flex items-center">
|
<div class="gap-[8px] flex items-center">
|
||||||
<div class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"></div>
|
<div
|
||||||
|
class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"
|
||||||
|
></div>
|
||||||
<div
|
<div
|
||||||
class="px-[14px] py-[3px] rounded-full border border-orange-300 bg-orange-100 dark:border-orange-800 dark:bg-orange-950/50"
|
class="px-[14px] py-[3px] rounded-full border border-orange-300 bg-orange-100 dark:border-orange-800 dark:bg-orange-950/50"
|
||||||
>
|
>
|
||||||
<span class="text-[13px] font-semibold text-orange-600 dark:text-orange-300">或</span>
|
<span
|
||||||
|
class="text-[13px] font-semibold text-orange-600 dark:text-orange-300"
|
||||||
|
>或</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"></div>
|
<div
|
||||||
|
class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -168,7 +175,10 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
class="p-[24px] rounded-[8px] border-2 border-dashed border-blue-200 bg-blue-50/40 text-center dark:border-blue-900/40 dark:bg-blue-950/10"
|
class="p-[24px] rounded-[8px] border-2 border-dashed border-blue-200 bg-blue-50/40 text-center dark:border-blue-900/40 dark:bg-blue-950/10"
|
||||||
>
|
>
|
||||||
<div class="gap-[10px] flex flex-col items-center">
|
<div class="gap-[10px] flex flex-col items-center">
|
||||||
<IconifyIcon icon="lucide:plus" class="text-[28px] text-blue-400 dark:text-blue-300" />
|
<IconifyIcon
|
||||||
|
icon="lucide:plus"
|
||||||
|
class="text-[28px] text-blue-400 dark:text-blue-300"
|
||||||
|
/>
|
||||||
<div class="text-blue-600 dark:text-blue-300">
|
<div class="text-blue-600 dark:text-blue-300">
|
||||||
<p class="text-[13px] font-medium mb-[2px]">暂无附加条件</p>
|
<p class="text-[13px] font-medium mb-[2px]">暂无附加条件</p>
|
||||||
<p class="text-[12px]">定时触发时将直接执行动作</p>
|
<p class="text-[12px]">定时触发时将直接执行动作</p>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 执行器配置组件 -->
|
<!-- 执行器配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Action } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getActionTypeLabel,
|
getActionTypeLabel,
|
||||||
|
|
@ -19,11 +19,11 @@ import DeviceControlConfig from '../configs/device-control-config.vue';
|
||||||
defineOptions({ name: 'ActionSection' });
|
defineOptions({ name: 'ActionSection' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
actions: Action[];
|
actions: RuleSceneApi.Action[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:actions', value: Action[]): void;
|
(e: 'update:actions', value: RuleSceneApi.Action[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const actions = useVModel(props, 'actions', emit);
|
const actions = useVModel(props, 'actions', emit);
|
||||||
|
|
@ -66,7 +66,7 @@ function isAlertAction(type: number): boolean {
|
||||||
* 创建默认的执行器数据
|
* 创建默认的执行器数据
|
||||||
* @returns 默认执行器对象
|
* @returns 默认执行器对象
|
||||||
*/
|
*/
|
||||||
function createDefaultActionData(): Action {
|
function createDefaultActionData(): RuleSceneApi.Action {
|
||||||
return {
|
return {
|
||||||
type: IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET, // 默认为设备属性设置
|
type: IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET, // 默认为设备属性设置
|
||||||
productId: undefined,
|
productId: undefined,
|
||||||
|
|
@ -100,7 +100,7 @@ function removeAction(index: number) {
|
||||||
*/
|
*/
|
||||||
function updateActionType(index: number, type: number) {
|
function updateActionType(index: number, type: number) {
|
||||||
actions.value[index]!.type = type;
|
actions.value[index]!.type = type;
|
||||||
onActionTypeChange(actions.value[index] as Action, type);
|
onActionTypeChange(actions.value[index] as RuleSceneApi.Action, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,7 +108,7 @@ function updateActionType(index: number, type: number) {
|
||||||
* @param index 执行器索引
|
* @param index 执行器索引
|
||||||
* @param action 执行器对象
|
* @param action 执行器对象
|
||||||
*/
|
*/
|
||||||
function updateAction(index: number, action: Action) {
|
function updateAction(index: number, action: RuleSceneApi.Action) {
|
||||||
actions.value[index] = action;
|
actions.value[index] = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,12 +126,12 @@ function updateActionAlertConfig(index: number, alertConfigId?: number) {
|
||||||
* @param action 执行器对象
|
* @param action 执行器对象
|
||||||
* @param type 执行器类型
|
* @param type 执行器类型
|
||||||
*/
|
*/
|
||||||
function onActionTypeChange(action: Action, type: number) {
|
function onActionTypeChange(action: RuleSceneApi.Action, type: number) {
|
||||||
if (isDeviceAction(type)) {
|
if (isDeviceAction(type)) {
|
||||||
// 设备控制类型:清理告警配置,确保设备参数存在
|
// 设备控制类型:清理告警配置,确保设备参数存在
|
||||||
action.alertConfigId = undefined;
|
action.alertConfigId = undefined;
|
||||||
if (!action.params) {
|
if (!action.params) {
|
||||||
action.params = {};
|
action.params = '';
|
||||||
}
|
}
|
||||||
// 切换到设备控制类型时清空 identifier,让用户重新选择
|
// 切换到设备控制类型时清空 identifier,让用户重新选择
|
||||||
if (action.identifier && type !== action.type) {
|
if (action.identifier && type !== action.type) {
|
||||||
|
|
@ -153,7 +153,9 @@ function onActionTypeChange(action: Action, type: number) {
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="gap-[8px] flex items-center">
|
<div class="gap-[8px] flex items-center">
|
||||||
<IconifyIcon icon="ep:setting" class="text-[18px] text-primary" />
|
<IconifyIcon icon="ep:setting" class="text-[18px] text-primary" />
|
||||||
<span class="text-[16px] font-semibold text-foreground"> 执行器配置 </span>
|
<span class="text-[16px] font-semibold text-foreground">
|
||||||
|
执行器配置
|
||||||
|
</span>
|
||||||
<Tag color="default"> {{ actions.length }} 个执行器 </Tag>
|
<Tag color="default"> {{ actions.length }} 个执行器 </Tag>
|
||||||
</div>
|
</div>
|
||||||
<div class="gap-[8px] flex items-center">
|
<div class="gap-[8px] flex items-center">
|
||||||
|
|
@ -251,10 +253,7 @@ function onActionTypeChange(action: Action, type: number) {
|
||||||
|
|
||||||
<!-- 告警配置 - 只有恢复告警时才显示 -->
|
<!-- 告警配置 - 只有恢复告警时才显示 -->
|
||||||
<AlertConfig
|
<AlertConfig
|
||||||
v-if="
|
v-if="action.type === IotRuleSceneActionTypeEnum.ALERT_RECOVER"
|
||||||
action.type ===
|
|
||||||
IotRuleSceneActionTypeEnum.ALERT_RECOVER
|
|
||||||
"
|
|
||||||
:model-value="action.alertConfigId"
|
:model-value="action.alertConfigId"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => updateActionAlertConfig(index, value)
|
(value) => updateActionAlertConfig(index, value)
|
||||||
|
|
@ -263,10 +262,7 @@ function onActionTypeChange(action: Action, type: number) {
|
||||||
|
|
||||||
<!-- 触发告警提示 - 触发告警时显示 -->
|
<!-- 触发告警提示 - 触发告警时显示 -->
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="action.type === IotRuleSceneActionTypeEnum.ALERT_TRIGGER"
|
||||||
action.type ===
|
|
||||||
IotRuleSceneActionTypeEnum.ALERT_TRIGGER
|
|
||||||
"
|
|
||||||
class="bg-fill-color-blank rounded-lg border border-border p-4"
|
class="bg-fill-color-blank rounded-lg border border-border p-4"
|
||||||
>
|
>
|
||||||
<div class="mb-2 flex items-center gap-2">
|
<div class="mb-2 flex items-center gap-2">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 基础信息配置组件 -->
|
<!-- 基础信息配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { IotSceneRule } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
import { getDictOptions } from '@vben/hooks';
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
@ -15,11 +15,11 @@ import { DictTag } from '#/components/dict-tag';
|
||||||
defineOptions({ name: 'BasicInfoSection' });
|
defineOptions({ name: 'BasicInfoSection' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: IotSceneRule;
|
modelValue: RuleSceneApi.SceneRule;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: IotSceneRule): void;
|
(e: 'update:modelValue', value: RuleSceneApi.SceneRule): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const formData = useVModel(props, 'modelValue', emit); // 表单数据
|
const formData = useVModel(props, 'modelValue', emit); // 表单数据
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Trigger, TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
|
|
||||||
|
|
@ -22,11 +22,11 @@ import TimerConditionGroupConfig from '../configs/timer-condition-group-config.v
|
||||||
defineOptions({ name: 'TriggerSection' });
|
defineOptions({ name: 'TriggerSection' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
triggers: Trigger[];
|
triggers: RuleSceneApi.Trigger[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:triggers', value: Trigger[]): void;
|
(e: 'update:triggers', value: RuleSceneApi.Trigger[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const triggers = useVModel(props, 'triggers', emit);
|
const triggers = useVModel(props, 'triggers', emit);
|
||||||
|
|
@ -43,7 +43,7 @@ function getTriggerTagColor(
|
||||||
|
|
||||||
/** 添加触发器 */
|
/** 添加触发器 */
|
||||||
function addTrigger() {
|
function addTrigger() {
|
||||||
const newTrigger: Trigger = {
|
const newTrigger: RuleSceneApi.Trigger = {
|
||||||
type: IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE,
|
type: IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE,
|
||||||
productId: undefined,
|
productId: undefined,
|
||||||
deviceId: undefined,
|
deviceId: undefined,
|
||||||
|
|
@ -70,7 +70,10 @@ function updateTriggerType(index: number, type: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新触发器设备配置 */
|
/** 更新触发器设备配置 */
|
||||||
function updateTriggerDeviceConfig(index: number, newTrigger: Trigger) {
|
function updateTriggerDeviceConfig(
|
||||||
|
index: number,
|
||||||
|
newTrigger: RuleSceneApi.Trigger,
|
||||||
|
) {
|
||||||
triggers.value[index] = newTrigger;
|
triggers.value[index] = newTrigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +85,7 @@ function updateTriggerCronConfig(index: number, cronExpression?: string) {
|
||||||
/** 更新触发器条件组配置 */
|
/** 更新触发器条件组配置 */
|
||||||
function updateTriggerConditionGroups(
|
function updateTriggerConditionGroups(
|
||||||
index: number,
|
index: number,
|
||||||
conditionGroups: TriggerCondition[][],
|
conditionGroups: RuleSceneApi.TriggerCondition[][],
|
||||||
) {
|
) {
|
||||||
triggers.value[index]!.conditionGroups = conditionGroups;
|
triggers.value[index]!.conditionGroups = conditionGroups;
|
||||||
}
|
}
|
||||||
|
|
@ -183,10 +186,7 @@ onMounted(() => {
|
||||||
|
|
||||||
<!-- 定时触发配置 -->
|
<!-- 定时触发配置 -->
|
||||||
<div
|
<div
|
||||||
v-else-if="
|
v-else-if="triggerItem.type === IotRuleSceneTriggerTypeEnum.TIMER"
|
||||||
triggerItem.type ===
|
|
||||||
IotRuleSceneTriggerTypeEnum.TIMER
|
|
||||||
"
|
|
||||||
class="gap-[16px] flex flex-col"
|
class="gap-[16px] flex flex-col"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IotSceneRule, RuleSceneApi } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, nextTick, reactive, ref } from 'vue';
|
import { computed, nextTick, reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ defineOptions({ name: 'IoTRuleSceneForm' });
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formData = ref<IotSceneRule>(buildEmptyFormData());
|
const formData = ref<RuleSceneApi.SceneRule>(buildEmptyFormData());
|
||||||
|
|
||||||
const getTitle = computed(() =>
|
const getTitle = computed(() =>
|
||||||
formData.value.id
|
formData.value.id
|
||||||
|
|
@ -46,7 +46,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
|
||||||
}
|
}
|
||||||
drawerApi.lock();
|
drawerApi.lock();
|
||||||
try {
|
try {
|
||||||
const data = { ...formData.value } as IotSceneRule;
|
const data = { ...formData.value } as RuleSceneApi.SceneRule;
|
||||||
await (data.id ? updateSceneRule(data) : createSceneRule(data));
|
await (data.id ? updateSceneRule(data) : createSceneRule(data));
|
||||||
await drawerApi.close();
|
await drawerApi.close();
|
||||||
emit('success');
|
emit('success');
|
||||||
|
|
@ -78,7 +78,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 构造空白表单数据 */
|
/** 构造空白表单数据 */
|
||||||
function buildEmptyFormData(): IotSceneRule {
|
function buildEmptyFormData(): RuleSceneApi.SceneRule {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
|
|
@ -100,7 +100,7 @@ function buildEmptyFormData(): IotSceneRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
||||||
function normalizeFormData(result: any): IotSceneRule {
|
function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
triggers: result.triggers?.length
|
triggers: result.triggers?.length
|
||||||
|
|
|
||||||
|
|
@ -51,53 +51,6 @@ export namespace RuleSceneApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @haohao:貌似下面的,和 RuleSceneApi 重复了。
|
|
||||||
/** IoT 场景联动规则 */
|
|
||||||
export interface IotSceneRule {
|
|
||||||
id?: number;
|
|
||||||
name?: string;
|
|
||||||
description?: string;
|
|
||||||
status?: number;
|
|
||||||
triggers?: Trigger[];
|
|
||||||
actions?: Action[];
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IoT 场景联动规则触发器 */
|
|
||||||
export interface Trigger {
|
|
||||||
type?: number;
|
|
||||||
productId?: number;
|
|
||||||
deviceId?: number;
|
|
||||||
identifier?: string;
|
|
||||||
operator?: string;
|
|
||||||
value?: any;
|
|
||||||
cronExpression?: string;
|
|
||||||
// 后端结构:List<List<TriggerCondition>>;外层「或」、组内「且」
|
|
||||||
conditionGroups?: TriggerCondition[][];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IoT 场景联动规则触发条件 */
|
|
||||||
export interface TriggerCondition {
|
|
||||||
productId?: number;
|
|
||||||
deviceId?: number;
|
|
||||||
identifier?: string;
|
|
||||||
operator?: string;
|
|
||||||
value?: any;
|
|
||||||
type?: number;
|
|
||||||
param?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IoT 场景联动规则动作 */
|
|
||||||
export interface Action {
|
|
||||||
type?: number;
|
|
||||||
productId?: number;
|
|
||||||
deviceId?: number;
|
|
||||||
identifier?: string;
|
|
||||||
value?: any;
|
|
||||||
alertConfigId?: number;
|
|
||||||
params?: Record<string, any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询场景联动规则分页 */
|
/** 查询场景联动规则分页 */
|
||||||
export function getSceneRulePage(params: PageParam) {
|
export function getSceneRulePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<RuleSceneApi.SceneRule>>(
|
return requestClient.get<PageResult<RuleSceneApi.SceneRule>>(
|
||||||
|
|
@ -114,12 +67,12 @@ export function getSceneRule(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增场景联动规则 */
|
/** 新增场景联动规则 */
|
||||||
export function createSceneRule(data: IotSceneRule) {
|
export function createSceneRule(data: RuleSceneApi.SceneRule) {
|
||||||
return requestClient.post('/iot/scene-rule/create', data);
|
return requestClient.post('/iot/scene-rule/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改场景联动规则 */
|
/** 修改场景联动规则 */
|
||||||
export function updateSceneRule(data: IotSceneRule) {
|
export function updateSceneRule(data: RuleSceneApi.SceneRule) {
|
||||||
return requestClient.put('/iot/scene-rule/update', data);
|
return requestClient.put('/iot/scene-rule/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +82,6 @@ export function deleteSceneRule(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除场景联动规则 */
|
/** 批量删除场景联动规则 */
|
||||||
// TODO @haohao:貌似用上。
|
|
||||||
export function deleteSceneRuleList(ids: number[]) {
|
export function deleteSceneRuleList(ids: number[]) {
|
||||||
return requestClient.delete('/iot/scene-rule/delete-list', {
|
return requestClient.delete('/iot/scene-rule/delete-list', {
|
||||||
params: { ids: ids.join(',') },
|
params: { ids: ids.join(',') },
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 单个条件配置组件 -->
|
<!-- 单个条件配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -12,13 +12,7 @@ import {
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import {
|
import { ElCol, ElFormItem, ElOption, ElRow, ElSelect } from 'element-plus';
|
||||||
ElCol,
|
|
||||||
ElFormItem,
|
|
||||||
ElOption,
|
|
||||||
ElRow,
|
|
||||||
ElSelect,
|
|
||||||
} from 'element-plus';
|
|
||||||
|
|
||||||
import ValueInput from '../inputs/value-input.vue';
|
import ValueInput from '../inputs/value-input.vue';
|
||||||
import DeviceSelector from '../selectors/device-selector.vue';
|
import DeviceSelector from '../selectors/device-selector.vue';
|
||||||
|
|
@ -31,12 +25,12 @@ import CurrentTimeConditionConfig from './current-time-condition-config.vue';
|
||||||
defineOptions({ name: 'ConditionConfig' });
|
defineOptions({ name: 'ConditionConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: TriggerCondition;
|
modelValue: RuleSceneApi.TriggerCondition;
|
||||||
triggerType: number;
|
triggerType: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
/** 获取设备状态选项 */
|
/** 获取设备状态选项 */
|
||||||
|
|
@ -90,7 +84,7 @@ function updateConditionField(field: any, value: any) {
|
||||||
* 更新整个条件对象
|
* 更新整个条件对象
|
||||||
* @param newCondition 新的条件对象
|
* @param newCondition 新的条件对象
|
||||||
*/
|
*/
|
||||||
function updateCondition(newCondition: TriggerCondition) {
|
function updateCondition(newCondition: RuleSceneApi.TriggerCondition) {
|
||||||
condition.value = newCondition;
|
condition.value = newCondition;
|
||||||
emit('update:modelValue', condition.value);
|
emit('update:modelValue', condition.value);
|
||||||
}
|
}
|
||||||
|
|
@ -217,8 +211,7 @@ function handleOperatorChange() {
|
||||||
<!-- 设备状态条件配置 -->
|
<!-- 设备状态条件配置 -->
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="
|
||||||
condition.type ===
|
condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS
|
||||||
IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS
|
|
||||||
"
|
"
|
||||||
class="gap-16px flex flex-col"
|
class="gap-16px flex flex-col"
|
||||||
>
|
>
|
||||||
|
|
@ -271,8 +264,7 @@ function handleOperatorChange() {
|
||||||
<!-- 设备属性条件配置 -->
|
<!-- 设备属性条件配置 -->
|
||||||
<div
|
<div
|
||||||
v-else-if="
|
v-else-if="
|
||||||
condition.type ===
|
condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY
|
||||||
IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY
|
|
||||||
"
|
"
|
||||||
class="space-y-16px"
|
class="space-y-16px"
|
||||||
>
|
>
|
||||||
|
|
@ -328,8 +320,7 @@ function handleOperatorChange() {
|
||||||
<!-- 当前时间条件配置 -->
|
<!-- 当前时间条件配置 -->
|
||||||
<CurrentTimeConditionConfig
|
<CurrentTimeConditionConfig
|
||||||
v-else-if="
|
v-else-if="
|
||||||
condition.type ===
|
condition.type === IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME
|
||||||
IotRuleSceneTriggerConditionTypeEnum.CURRENT_TIME
|
|
||||||
"
|
"
|
||||||
:model-value="condition"
|
:model-value="condition"
|
||||||
@update:model-value="updateCondition"
|
@update:model-value="updateCondition"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 当前时间条件配置组件 -->
|
<!-- 当前时间条件配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
|
|
||||||
|
|
@ -23,11 +23,11 @@ import {
|
||||||
defineOptions({ name: 'CurrentTimeConditionConfig' });
|
defineOptions({ name: 'CurrentTimeConditionConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: TriggerCondition;
|
modelValue: RuleSceneApi.TriggerCondition;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const condition = useVModel(props, 'modelValue', emit);
|
const condition = useVModel(props, 'modelValue', emit);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 设备控制配置组件 -->
|
<!-- 设备控制配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Action } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
import type { ThingModelApi } from '#/api/iot/thingmodel';
|
import type { ThingModelApi } from '#/api/iot/thingmodel';
|
||||||
|
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
import { computed, onMounted, ref, watch } from 'vue';
|
||||||
|
|
@ -32,11 +32,11 @@ import ProductSelector from '../selectors/product-selector.vue';
|
||||||
defineOptions({ name: 'DeviceControlConfig' });
|
defineOptions({ name: 'DeviceControlConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: Action;
|
modelValue: RuleSceneApi.Action;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: Action): void;
|
(e: 'update:modelValue', value: RuleSceneApi.Action): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const action = useVModel(props, 'modelValue', emit);
|
const action = useVModel(props, 'modelValue', emit);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Trigger } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -12,13 +12,7 @@ import {
|
||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import {
|
import { ElCol, ElFormItem, ElOption, ElRow, ElSelect } from 'element-plus';
|
||||||
ElCol,
|
|
||||||
ElFormItem,
|
|
||||||
ElOption,
|
|
||||||
ElRow,
|
|
||||||
ElSelect,
|
|
||||||
} from 'element-plus';
|
|
||||||
|
|
||||||
import JsonParamsInput from '../inputs/json-params-input.vue';
|
import JsonParamsInput from '../inputs/json-params-input.vue';
|
||||||
import ValueInput from '../inputs/value-input.vue';
|
import ValueInput from '../inputs/value-input.vue';
|
||||||
|
|
@ -31,12 +25,12 @@ import PropertySelector from '../selectors/property-selector.vue';
|
||||||
defineOptions({ name: 'MainConditionInnerConfig' });
|
defineOptions({ name: 'MainConditionInnerConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: Trigger;
|
modelValue: RuleSceneApi.Trigger;
|
||||||
triggerType: number;
|
triggerType: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: Trigger): void;
|
(e: 'update:modelValue', value: RuleSceneApi.Trigger): void;
|
||||||
(e: 'triggerTypeChange', value: number): void;
|
(e: 'triggerTypeChange', value: number): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, nextTick } from 'vue';
|
import { computed, nextTick } from 'vue';
|
||||||
|
|
||||||
|
|
@ -19,12 +19,12 @@ defineOptions({ name: 'SubConditionGroupConfig' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
maxConditions?: number;
|
maxConditions?: number;
|
||||||
modelValue: TriggerCondition[];
|
modelValue: RuleSceneApi.TriggerCondition[];
|
||||||
triggerType: number;
|
triggerType: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition[]): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const subGroup = useVModel(props, 'modelValue', emit);
|
const subGroup = useVModel(props, 'modelValue', emit);
|
||||||
|
|
@ -43,7 +43,7 @@ async function addCondition() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCondition: TriggerCondition = {
|
const newCondition: RuleSceneApi.TriggerCondition = {
|
||||||
type: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY, // 默认为设备属性
|
type: IotRuleSceneTriggerConditionTypeEnum.DEVICE_PROPERTY, // 默认为设备属性
|
||||||
productId: undefined,
|
productId: undefined,
|
||||||
deviceId: undefined,
|
deviceId: undefined,
|
||||||
|
|
@ -74,7 +74,10 @@ function removeCondition(index: number) {
|
||||||
* @param index 条件索引
|
* @param index 条件索引
|
||||||
* @param condition 条件对象
|
* @param condition 条件对象
|
||||||
*/
|
*/
|
||||||
function updateCondition(index: number, condition: TriggerCondition) {
|
function updateCondition(
|
||||||
|
index: number,
|
||||||
|
condition: RuleSceneApi.TriggerCondition,
|
||||||
|
) {
|
||||||
if (subGroup.value) {
|
if (subGroup.value) {
|
||||||
subGroup.value[index] = condition;
|
subGroup.value[index] = condition;
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +141,7 @@ function updateCondition(index: number, condition: TriggerCondition) {
|
||||||
<ConditionConfig
|
<ConditionConfig
|
||||||
:model-value="condition"
|
:model-value="condition"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value: TriggerCondition) =>
|
(value: RuleSceneApi.TriggerCondition) =>
|
||||||
updateCondition(conditionIndex, value)
|
updateCondition(conditionIndex, value)
|
||||||
"
|
"
|
||||||
:trigger-type="triggerType"
|
:trigger-type="triggerType"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { TriggerCondition } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
|
|
@ -12,11 +12,11 @@ import { ElButton, ElTag } from 'element-plus';
|
||||||
import SubConditionGroupConfig from './sub-condition-group-config.vue';
|
import SubConditionGroupConfig from './sub-condition-group-config.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue?: TriggerCondition[][];
|
modelValue?: RuleSceneApi.TriggerCondition[][];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: TriggerCondition[][]): void;
|
(e: 'update:modelValue', value: RuleSceneApi.TriggerCondition[][]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const conditionGroups = useVModel(props, 'modelValue', emit);
|
const conditionGroups = useVModel(props, 'modelValue', emit);
|
||||||
|
|
@ -46,7 +46,10 @@ function removeConditionGroup(index: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新条件组 */
|
/** 更新条件组 */
|
||||||
function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
function updateConditionGroup(
|
||||||
|
index: number,
|
||||||
|
group: RuleSceneApi.TriggerCondition[],
|
||||||
|
) {
|
||||||
if (conditionGroups.value) {
|
if (conditionGroups.value) {
|
||||||
conditionGroups.value[index] = group;
|
conditionGroups.value[index] = group;
|
||||||
}
|
}
|
||||||
|
|
@ -117,9 +120,7 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
<ElTag type="warning" class="font-medium">
|
<ElTag type="warning" class="font-medium">
|
||||||
组内条件为「且」关系
|
组内条件为「且」关系
|
||||||
</ElTag>
|
</ElTag>
|
||||||
<ElTag type="info">
|
<ElTag type="info"> {{ group?.length || 0 }} 个条件 </ElTag>
|
||||||
{{ group?.length || 0 }} 个条件
|
|
||||||
</ElTag>
|
|
||||||
</div>
|
</div>
|
||||||
<ElButton
|
<ElButton
|
||||||
link
|
link
|
||||||
|
|
@ -138,7 +139,7 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
:trigger-type="IotRuleSceneTriggerTypeEnum.TIMER"
|
:trigger-type="IotRuleSceneTriggerTypeEnum.TIMER"
|
||||||
:max-conditions="maxConditionsPerGroup"
|
:max-conditions="maxConditionsPerGroup"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value: TriggerCondition[]) =>
|
(value: RuleSceneApi.TriggerCondition[]) =>
|
||||||
updateConditionGroup(groupIndex, value)
|
updateConditionGroup(groupIndex, value)
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|
@ -150,13 +151,19 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
class="py-[12px] flex items-center justify-center"
|
class="py-[12px] flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<div class="gap-[8px] flex items-center">
|
<div class="gap-[8px] flex items-center">
|
||||||
<div class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"></div>
|
<div
|
||||||
|
class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"
|
||||||
|
></div>
|
||||||
<div
|
<div
|
||||||
class="px-[14px] py-[3px] rounded-full border border-orange-300 bg-orange-100 dark:border-orange-800 dark:bg-orange-950/50"
|
class="px-[14px] py-[3px] rounded-full border border-orange-300 bg-orange-100 dark:border-orange-800 dark:bg-orange-950/50"
|
||||||
>
|
>
|
||||||
<span class="text-[13px] font-semibold text-orange-600 dark:text-orange-300">或</span>
|
<span
|
||||||
|
class="text-[13px] font-semibold text-orange-600 dark:text-orange-300"
|
||||||
|
>或</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"></div>
|
<div
|
||||||
|
class="w-[32px] h-[1px] bg-orange-300 dark:bg-orange-800"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -168,7 +175,10 @@ function updateConditionGroup(index: number, group: TriggerCondition[]) {
|
||||||
class="p-[24px] rounded-[8px] border-2 border-dashed border-blue-200 bg-blue-50/40 text-center dark:border-blue-900/40 dark:bg-blue-950/10"
|
class="p-[24px] rounded-[8px] border-2 border-dashed border-blue-200 bg-blue-50/40 text-center dark:border-blue-900/40 dark:bg-blue-950/10"
|
||||||
>
|
>
|
||||||
<div class="gap-[10px] flex flex-col items-center">
|
<div class="gap-[10px] flex flex-col items-center">
|
||||||
<IconifyIcon icon="lucide:plus" class="text-[28px] text-blue-400 dark:text-blue-300" />
|
<IconifyIcon
|
||||||
|
icon="lucide:plus"
|
||||||
|
class="text-[28px] text-blue-400 dark:text-blue-300"
|
||||||
|
/>
|
||||||
<div class="text-blue-600 dark:text-blue-300">
|
<div class="text-blue-600 dark:text-blue-300">
|
||||||
<p class="text-[13px] font-medium mb-[2px]">暂无附加条件</p>
|
<p class="text-[13px] font-medium mb-[2px]">暂无附加条件</p>
|
||||||
<p class="text-[12px]">定时触发时将直接执行动作</p>
|
<p class="text-[12px]">定时触发时将直接执行动作</p>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 执行器配置组件 -->
|
<!-- 执行器配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Action } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getActionTypeLabel,
|
getActionTypeLabel,
|
||||||
|
|
@ -27,11 +27,11 @@ import DeviceControlConfig from '../configs/device-control-config.vue';
|
||||||
defineOptions({ name: 'ActionSection' });
|
defineOptions({ name: 'ActionSection' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
actions: Action[];
|
actions: RuleSceneApi.Action[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:actions', value: Action[]): void;
|
(e: 'update:actions', value: RuleSceneApi.Action[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const actions = useVModel(props, 'actions', emit);
|
const actions = useVModel(props, 'actions', emit);
|
||||||
|
|
@ -74,7 +74,7 @@ function isAlertAction(type: number): boolean {
|
||||||
* 创建默认的执行器数据
|
* 创建默认的执行器数据
|
||||||
* @returns 默认执行器对象
|
* @returns 默认执行器对象
|
||||||
*/
|
*/
|
||||||
function createDefaultActionData(): Action {
|
function createDefaultActionData(): RuleSceneApi.Action {
|
||||||
return {
|
return {
|
||||||
type: IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET, // 默认为设备属性设置
|
type: IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET, // 默认为设备属性设置
|
||||||
productId: undefined,
|
productId: undefined,
|
||||||
|
|
@ -108,7 +108,7 @@ function removeAction(index: number) {
|
||||||
*/
|
*/
|
||||||
function updateActionType(index: number, type: number) {
|
function updateActionType(index: number, type: number) {
|
||||||
actions.value[index]!.type = type;
|
actions.value[index]!.type = type;
|
||||||
onActionTypeChange(actions.value[index] as Action, type);
|
onActionTypeChange(actions.value[index] as RuleSceneApi.Action, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,7 +116,7 @@ function updateActionType(index: number, type: number) {
|
||||||
* @param index 执行器索引
|
* @param index 执行器索引
|
||||||
* @param action 执行器对象
|
* @param action 执行器对象
|
||||||
*/
|
*/
|
||||||
function updateAction(index: number, action: Action) {
|
function updateAction(index: number, action: RuleSceneApi.Action) {
|
||||||
actions.value[index] = action;
|
actions.value[index] = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,7 +137,7 @@ function updateActionAlertConfig(index: number, alertConfigId?: number) {
|
||||||
* @param action 执行器对象
|
* @param action 执行器对象
|
||||||
* @param type 执行器类型
|
* @param type 执行器类型
|
||||||
*/
|
*/
|
||||||
function onActionTypeChange(action: Action, type: any) {
|
function onActionTypeChange(action: RuleSceneApi.Action, type: any) {
|
||||||
// 清理不相关的配置,确保数据结构干净
|
// 清理不相关的配置,确保数据结构干净
|
||||||
if (isDeviceAction(type)) {
|
if (isDeviceAction(type)) {
|
||||||
// 设备控制类型:清理告警配置,确保设备参数存在
|
// 设备控制类型:清理告警配置,确保设备参数存在
|
||||||
|
|
@ -166,7 +166,9 @@ function onActionTypeChange(action: Action, type: any) {
|
||||||
<div class="gap-8px flex items-center">
|
<div class="gap-8px flex items-center">
|
||||||
<IconifyIcon icon="ep:setting" class="text-18px text-primary" />
|
<IconifyIcon icon="ep:setting" class="text-18px text-primary" />
|
||||||
<span class="text-16px font-600 text-primary"> 执行器配置 </span>
|
<span class="text-16px font-600 text-primary"> 执行器配置 </span>
|
||||||
<ElTag size="small" type="info"> {{ actions.length }} 个执行器 </ElTag>
|
<ElTag size="small" type="info">
|
||||||
|
{{ actions.length }} 个执行器
|
||||||
|
</ElTag>
|
||||||
</div>
|
</div>
|
||||||
<div class="gap-8px flex items-center">
|
<div class="gap-8px flex items-center">
|
||||||
<ElButton type="primary" size="small" @click="addAction">
|
<ElButton type="primary" size="small" @click="addAction">
|
||||||
|
|
@ -268,10 +270,7 @@ function onActionTypeChange(action: Action, type: any) {
|
||||||
|
|
||||||
<!-- 告警配置 - 只有恢复告警时才显示 -->
|
<!-- 告警配置 - 只有恢复告警时才显示 -->
|
||||||
<AlertConfig
|
<AlertConfig
|
||||||
v-if="
|
v-if="action.type === IotRuleSceneActionTypeEnum.ALERT_RECOVER"
|
||||||
action.type ===
|
|
||||||
IotRuleSceneActionTypeEnum.ALERT_RECOVER
|
|
||||||
"
|
|
||||||
:model-value="action.alertConfigId"
|
:model-value="action.alertConfigId"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => updateActionAlertConfig(index, value)
|
(value) => updateActionAlertConfig(index, value)
|
||||||
|
|
@ -280,10 +279,7 @@ function onActionTypeChange(action: Action, type: any) {
|
||||||
|
|
||||||
<!-- 触发告警提示 - 触发告警时显示 -->
|
<!-- 触发告警提示 - 触发告警时显示 -->
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="action.type === IotRuleSceneActionTypeEnum.ALERT_TRIGGER"
|
||||||
action.type ===
|
|
||||||
IotRuleSceneActionTypeEnum.ALERT_TRIGGER
|
|
||||||
"
|
|
||||||
class="bg-fill-color-blank rounded-lg border border-border p-4"
|
class="bg-fill-color-blank rounded-lg border border-border p-4"
|
||||||
>
|
>
|
||||||
<div class="mb-2 flex items-center gap-2">
|
<div class="mb-2 flex items-center gap-2">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 基础信息配置组件 -->
|
<!-- 基础信息配置组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { IotSceneRule } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
import { getDictOptions } from '@vben/hooks';
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
@ -23,12 +23,12 @@ import { DictTag } from '#/components/dict-tag';
|
||||||
defineOptions({ name: 'BasicInfoSection' });
|
defineOptions({ name: 'BasicInfoSection' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: IotSceneRule;
|
modelValue: RuleSceneApi.SceneRule;
|
||||||
rules?: any;
|
rules?: any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: IotSceneRule): void;
|
(e: 'update:modelValue', value: RuleSceneApi.SceneRule): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const formData = useVModel(props, 'modelValue', emit); // 表单数据
|
const formData = useVModel(props, 'modelValue', emit); // 表单数据
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Trigger } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
|
|
||||||
|
|
@ -11,13 +11,7 @@ import {
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
import {
|
import { ElButton, ElCard, ElEmpty, ElFormItem, ElTag } from 'element-plus';
|
||||||
ElButton,
|
|
||||||
ElCard,
|
|
||||||
ElEmpty,
|
|
||||||
ElFormItem,
|
|
||||||
ElTag,
|
|
||||||
} from 'element-plus';
|
|
||||||
|
|
||||||
import { CronTab } from '#/components/cron-tab';
|
import { CronTab } from '#/components/cron-tab';
|
||||||
|
|
||||||
|
|
@ -27,11 +21,11 @@ import DeviceTriggerConfig from '../configs/device-trigger-config.vue';
|
||||||
defineOptions({ name: 'TriggerSection' });
|
defineOptions({ name: 'TriggerSection' });
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
triggers: Trigger[];
|
triggers: RuleSceneApi.Trigger[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:triggers', value: Trigger[]): void;
|
(e: 'update:triggers', value: RuleSceneApi.Trigger[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const triggers = useVModel(props, 'triggers', emit);
|
const triggers = useVModel(props, 'triggers', emit);
|
||||||
|
|
@ -48,7 +42,7 @@ function getTriggerTagType(
|
||||||
|
|
||||||
/** 添加触发器 */
|
/** 添加触发器 */
|
||||||
function addTrigger() {
|
function addTrigger() {
|
||||||
const newTrigger: Trigger = {
|
const newTrigger: RuleSceneApi.Trigger = {
|
||||||
type: IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE,
|
type: IotRuleSceneTriggerTypeEnum.DEVICE_STATE_UPDATE,
|
||||||
productId: undefined,
|
productId: undefined,
|
||||||
deviceId: undefined,
|
deviceId: undefined,
|
||||||
|
|
@ -86,7 +80,10 @@ function updateTriggerType(index: number, type: number) {
|
||||||
* @param index 触发器索引
|
* @param index 触发器索引
|
||||||
* @param newTrigger 新的触发器对象
|
* @param newTrigger 新的触发器对象
|
||||||
*/
|
*/
|
||||||
function updateTriggerDeviceConfig(index: number, newTrigger: Trigger) {
|
function updateTriggerDeviceConfig(
|
||||||
|
index: number,
|
||||||
|
newTrigger: RuleSceneApi.Trigger,
|
||||||
|
) {
|
||||||
triggers.value[index] = newTrigger;
|
triggers.value[index] = newTrigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +127,9 @@ onMounted(() => {
|
||||||
<div class="gap-8px flex items-center">
|
<div class="gap-8px flex items-center">
|
||||||
<IconifyIcon icon="ep:lightning" class="text-18px text-primary" />
|
<IconifyIcon icon="ep:lightning" class="text-18px text-primary" />
|
||||||
<span class="text-16px font-600 text-primary">触发器配置</span>
|
<span class="text-16px font-600 text-primary">触发器配置</span>
|
||||||
<ElTag size="small" type="info"> {{ triggers.length }} 个触发器 </ElTag>
|
<ElTag size="small" type="info">
|
||||||
|
{{ triggers.length }} 个触发器
|
||||||
|
</ElTag>
|
||||||
</div>
|
</div>
|
||||||
<ElButton type="primary" size="small" @click="addTrigger">
|
<ElButton type="primary" size="small" @click="addTrigger">
|
||||||
<IconifyIcon icon="lucide:plus" />
|
<IconifyIcon icon="lucide:plus" />
|
||||||
|
|
@ -200,10 +199,7 @@ onMounted(() => {
|
||||||
|
|
||||||
<!-- 定时触发配置 -->
|
<!-- 定时触发配置 -->
|
||||||
<div
|
<div
|
||||||
v-else-if="
|
v-else-if="triggerItem.type === IotRuleSceneTriggerTypeEnum.TIMER"
|
||||||
triggerItem.type ===
|
|
||||||
IotRuleSceneTriggerTypeEnum.TIMER
|
|
||||||
"
|
|
||||||
class="gap-16px flex flex-col"
|
class="gap-16px flex flex-col"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IotSceneRule, RuleSceneApi } from '#/api/iot/rule/scene';
|
import type { RuleSceneApi } from '#/api/iot/rule/scene';
|
||||||
|
|
||||||
import { computed, nextTick, reactive, ref } from 'vue';
|
import { computed, nextTick, reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ defineOptions({ name: 'IoTRuleSceneForm' });
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formData = ref<IotSceneRule>(buildEmptyFormData());
|
const formData = ref<RuleSceneApi.SceneRule>(buildEmptyFormData());
|
||||||
|
|
||||||
const getTitle = computed(() =>
|
const getTitle = computed(() =>
|
||||||
formData.value.id
|
formData.value.id
|
||||||
|
|
@ -46,7 +46,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
|
||||||
}
|
}
|
||||||
drawerApi.lock();
|
drawerApi.lock();
|
||||||
try {
|
try {
|
||||||
const data = { ...formData.value } as IotSceneRule;
|
const data = { ...formData.value } as RuleSceneApi.SceneRule;
|
||||||
await (data.id ? updateSceneRule(data) : createSceneRule(data));
|
await (data.id ? updateSceneRule(data) : createSceneRule(data));
|
||||||
await drawerApi.close();
|
await drawerApi.close();
|
||||||
emit('success');
|
emit('success');
|
||||||
|
|
@ -78,7 +78,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 构造空白表单数据 */
|
/** 构造空白表单数据 */
|
||||||
function buildEmptyFormData(): IotSceneRule {
|
function buildEmptyFormData(): RuleSceneApi.SceneRule {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
|
|
@ -100,7 +100,7 @@ function buildEmptyFormData(): IotSceneRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
/** 回显时兜底,保证触发器/执行器数组不为空 */
|
||||||
function normalizeFormData(result: any): IotSceneRule {
|
function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
triggers: result.triggers?.length
|
triggers: result.triggers?.length
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue