2026-07-02 16:23:15 +08:00
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import type { DataPushRule } from '#/api-client';
|
|
|
|
|
|
|
|
|
|
|
|
import { ref, toRaw, watch } from 'vue';
|
|
|
|
|
|
|
2026-07-03 10:29:08 +08:00
|
|
|
|
import { Input, Select } from 'ant-design-vue';
|
2026-07-02 16:23:15 +08:00
|
|
|
|
|
|
|
|
|
|
defineOptions({
|
|
|
|
|
|
name: 'DataPushRuleEditor',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
|
// 是否禁用编辑(如设备未开启"覆盖产品配置"时)
|
|
|
|
|
|
disabled?: boolean;
|
|
|
|
|
|
rules?: DataPushRule[] | null;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
|
|
(e: 'update:rules', value: DataPushRule[]): void;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
|
2026-07-03 10:29:08 +08:00
|
|
|
|
// 枚举以数值传输(与后端一致;生成的字符串字面量类型仅为 Swagger 展示)
|
2026-07-02 16:23:15 +08:00
|
|
|
|
const dataTypeOptions = [
|
2026-07-03 10:29:08 +08:00
|
|
|
|
{ label: '属性', value: 1 },
|
|
|
|
|
|
{ label: '事件', value: 2 },
|
|
|
|
|
|
{ label: '状态', value: 3 },
|
2026-07-02 16:23:15 +08:00
|
|
|
|
];
|
|
|
|
|
|
const pushTypeOptions = [
|
2026-07-03 10:29:08 +08:00
|
|
|
|
{ label: 'HTTP POST', value: 1 },
|
|
|
|
|
|
{ label: 'Redis 普通订阅', value: 2 },
|
|
|
|
|
|
{ label: 'Redis 可靠订阅', value: 3 },
|
|
|
|
|
|
{ label: 'Redis List', value: 4 },
|
2026-07-02 16:23:15 +08:00
|
|
|
|
];
|
|
|
|
|
|
|
2026-07-03 10:29:08 +08:00
|
|
|
|
// 统一推送:整个产品/设备只有一种推送方式 + 一个目的地,数据类型可多选。
|
|
|
|
|
|
// 后端仍存多规则(每个类型一条、同目的地),此处负责"统一配置 ⇄ 多规则"互转。
|
|
|
|
|
|
const selectedTypes = ref<number[]>([]);
|
|
|
|
|
|
const pushType = ref<number>(1);
|
|
|
|
|
|
const pushServer = ref<string>('');
|
|
|
|
|
|
const pushInfo = ref<string>('');
|
|
|
|
|
|
const ruleName = ref<string>('');
|
|
|
|
|
|
|
|
|
|
|
|
// 记录最近一次抛出的数组引用,识别 v-model 回环,避免重置输入框(父级用 ref 存储会包 reactive 代理,故用 toRaw 比较)
|
2026-07-02 16:23:15 +08:00
|
|
|
|
let lastEmitted: DataPushRule[] | null = null;
|
2026-07-03 10:29:08 +08:00
|
|
|
|
|
|
|
|
|
|
// 兼容后端可能返回数值或字符串形式的枚举
|
|
|
|
|
|
function toNum(value: any): number {
|
|
|
|
|
|
if (typeof value === 'number') {
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
const map: Record<string, number> = {
|
|
|
|
|
|
Property: 1,
|
|
|
|
|
|
Event: 2,
|
|
|
|
|
|
Status: 3,
|
|
|
|
|
|
HttpPost: 1,
|
|
|
|
|
|
NormalReisSubscription: 2,
|
|
|
|
|
|
ReliableReisSubscription: 3,
|
|
|
|
|
|
RedisListPush: 4,
|
|
|
|
|
|
};
|
|
|
|
|
|
return map[value] ?? Number(value);
|
|
|
|
|
|
}
|
2026-07-02 16:23:15 +08:00
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
() => props.rules,
|
|
|
|
|
|
(val) => {
|
|
|
|
|
|
if (toRaw(val) === lastEmitted) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-07-03 10:29:08 +08:00
|
|
|
|
const list = Array.isArray(val) ? val : [];
|
|
|
|
|
|
if (list.length === 0) {
|
|
|
|
|
|
selectedTypes.value = [];
|
|
|
|
|
|
pushType.value = 1;
|
|
|
|
|
|
pushServer.value = '';
|
|
|
|
|
|
pushInfo.value = '';
|
|
|
|
|
|
ruleName.value = '';
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 统一模式:各规则推送方式/目的地一致,取首条;数据类型收集去重
|
|
|
|
|
|
const first = list[0];
|
|
|
|
|
|
selectedTypes.value = [...new Set(list.map((r) => toNum(r.dataType)))];
|
|
|
|
|
|
pushType.value = toNum(first.pushType);
|
|
|
|
|
|
pushServer.value = first.pushServer ?? '';
|
|
|
|
|
|
pushInfo.value = first.pushInfo ?? '';
|
|
|
|
|
|
ruleName.value = first.ruleName ?? '';
|
2026-07-02 16:23:15 +08:00
|
|
|
|
},
|
|
|
|
|
|
{ immediate: true },
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
function emitChange() {
|
2026-07-03 10:29:08 +08:00
|
|
|
|
// 把"多选类型 + 单一目的地"展开为多条同目的地规则
|
|
|
|
|
|
const out = selectedTypes.value.map((t) => ({
|
|
|
|
|
|
ruleName: ruleName.value,
|
2026-07-02 16:23:15 +08:00
|
|
|
|
enabled: true,
|
2026-07-03 10:29:08 +08:00
|
|
|
|
dataType: t,
|
2026-07-02 16:23:15 +08:00
|
|
|
|
includeNames: null,
|
2026-07-03 10:29:08 +08:00
|
|
|
|
pushType: pushType.value,
|
|
|
|
|
|
pushServer: pushServer.value,
|
|
|
|
|
|
pushInfo: pushInfo.value,
|
|
|
|
|
|
}));
|
|
|
|
|
|
lastEmitted = out as unknown as DataPushRule[];
|
|
|
|
|
|
emit('update:rules', lastEmitted);
|
2026-07-02 16:23:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
2026-07-03 10:29:08 +08:00
|
|
|
|
<div class="space-y-3">
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<span class="w-28 flex-shrink-0 text-sm text-gray-600">数据类型</span>
|
2026-07-02 16:23:15 +08:00
|
|
|
|
<Select
|
2026-07-03 10:29:08 +08:00
|
|
|
|
v-model:value="selectedTypes"
|
|
|
|
|
|
mode="multiple"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
:options="dataTypeOptions"
|
|
|
|
|
|
:disabled="disabled"
|
2026-07-03 10:29:08 +08:00
|
|
|
|
class="flex-1"
|
|
|
|
|
|
placeholder="选择要推送的数据类型(可多选)"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
@change="emitChange"
|
|
|
|
|
|
/>
|
2026-07-03 10:29:08 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<span class="w-28 flex-shrink-0 text-sm text-gray-600">推送方式</span>
|
2026-07-02 16:23:15 +08:00
|
|
|
|
<Select
|
2026-07-03 10:29:08 +08:00
|
|
|
|
v-model:value="pushType"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
:options="pushTypeOptions"
|
|
|
|
|
|
:disabled="disabled"
|
2026-07-03 10:29:08 +08:00
|
|
|
|
class="flex-1"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
@change="emitChange"
|
|
|
|
|
|
/>
|
2026-07-03 10:29:08 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<span class="w-28 flex-shrink-0 text-sm text-gray-600">服务地址</span>
|
2026-07-02 16:23:15 +08:00
|
|
|
|
<Input
|
2026-07-03 10:29:08 +08:00
|
|
|
|
v-model:value="pushServer"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
:disabled="disabled"
|
|
|
|
|
|
class="flex-1"
|
|
|
|
|
|
placeholder="HTTP:http://ip:port,Redis:ip:port"
|
|
|
|
|
|
@change="emitChange"
|
|
|
|
|
|
/>
|
2026-07-03 10:29:08 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<span class="w-28 flex-shrink-0 text-sm text-gray-600">路径 / 主题 / KEY</span>
|
2026-07-02 16:23:15 +08:00
|
|
|
|
<Input
|
2026-07-03 10:29:08 +08:00
|
|
|
|
v-model:value="pushInfo"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
:disabled="disabled"
|
|
|
|
|
|
class="flex-1"
|
2026-07-03 10:29:08 +08:00
|
|
|
|
placeholder="HTTP 为推送路径,Redis 为主题或 key"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
@change="emitChange"
|
|
|
|
|
|
/>
|
2026-07-03 10:29:08 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
|
<span class="w-28 flex-shrink-0 text-sm text-gray-600">备注</span>
|
2026-07-02 16:23:15 +08:00
|
|
|
|
<Input
|
2026-07-03 10:29:08 +08:00
|
|
|
|
v-model:value="ruleName"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
:disabled="disabled"
|
2026-07-03 10:29:08 +08:00
|
|
|
|
class="flex-1"
|
2026-07-02 16:23:15 +08:00
|
|
|
|
placeholder="可空"
|
|
|
|
|
|
@change="emitChange"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|