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