完善数据流转配置
This commit is contained in:
parent
6873c6aa97
commit
5ac3633606
@ -3,7 +3,7 @@ import type { DataPushRule } from '#/api-client';
|
||||
|
||||
import { ref, toRaw, watch } from 'vue';
|
||||
|
||||
import { Button, Input, Select, Switch } from 'ant-design-vue';
|
||||
import { Input, Select } from 'ant-design-vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'DataPushRuleEditor',
|
||||
@ -19,150 +19,142 @@ const emit = defineEmits<{
|
||||
(e: 'update:rules', value: DataPushRule[]): void;
|
||||
}>();
|
||||
|
||||
// 数据类型 / 推送方式:与后端字符串枚举一一对应(生成的契约为字符串字面量)
|
||||
// 枚举以数值传输(与后端一致;生成的字符串字面量类型仅为 Swagger 展示)
|
||||
const dataTypeOptions = [
|
||||
{ label: '属性', value: 'Property' },
|
||||
{ label: '事件', value: 'Event' },
|
||||
{ label: '状态', value: 'Status' },
|
||||
{ label: '属性', value: 1 },
|
||||
{ label: '事件', value: 2 },
|
||||
{ label: '状态', value: 3 },
|
||||
];
|
||||
const pushTypeOptions = [
|
||||
{ label: 'HTTP POST', value: 'HttpPost' },
|
||||
{ label: 'Redis 普通订阅', value: 'NormalReisSubscription' },
|
||||
{ label: 'Redis 可靠订阅', value: 'ReliableReisSubscription' },
|
||||
{ label: 'Redis List', value: 'RedisListPush' },
|
||||
{ label: 'HTTP POST', value: 1 },
|
||||
{ label: 'Redis 普通订阅', value: 2 },
|
||||
{ label: 'Redis 可靠订阅', value: 3 },
|
||||
{ label: 'Redis List', value: 4 },
|
||||
];
|
||||
|
||||
// 内部维护一份可编辑副本,变更后回抛给父级
|
||||
let seed = 0;
|
||||
// 记录最近一次抛出的数组引用:用于识别 v-model 回环,避免重建 list 导致输入框失焦
|
||||
// 统一推送:整个产品/设备只有一种推送方式 + 一个目的地,数据类型可多选。
|
||||
// 后端仍存多规则(每个类型一条、同目的地),此处负责"统一配置 ⇄ 多规则"互转。
|
||||
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 比较)
|
||||
let lastEmitted: DataPushRule[] | null = null;
|
||||
const list = ref<(DataPushRule & { _key: number })[]>([]);
|
||||
|
||||
// 兼容后端可能返回数值或字符串形式的枚举
|
||||
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);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.rules,
|
||||
(val) => {
|
||||
// 跳过自身 emit 造成的回环,仅在外部真正替换数据时重建。
|
||||
// 注意:父级用 ref 存储时会把数组包成 reactive 代理,故须用 toRaw 比较原始引用。
|
||||
if (toRaw(val) === lastEmitted) {
|
||||
return;
|
||||
}
|
||||
list.value = Array.isArray(val)
|
||||
? val.map((r) => ({ ...r, _key: seed++ }))
|
||||
: [];
|
||||
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 ?? '';
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
function emitChange() {
|
||||
// 抛出时剥离内部 _key,仅回传契约字段
|
||||
const out = list.value.map((r) => ({
|
||||
ruleName: r.ruleName,
|
||||
enabled: r.enabled,
|
||||
dataType: r.dataType,
|
||||
includeNames: r.includeNames ?? null,
|
||||
pushType: r.pushType,
|
||||
pushServer: r.pushServer,
|
||||
pushInfo: r.pushInfo,
|
||||
}));
|
||||
lastEmitted = out;
|
||||
emit('update:rules', out);
|
||||
}
|
||||
|
||||
function addRule() {
|
||||
list.value.push({
|
||||
_key: seed++,
|
||||
ruleName: '',
|
||||
// 把"多选类型 + 单一目的地"展开为多条同目的地规则
|
||||
const out = selectedTypes.value.map((t) => ({
|
||||
ruleName: ruleName.value,
|
||||
enabled: true,
|
||||
dataType: 'Property',
|
||||
dataType: t,
|
||||
includeNames: null,
|
||||
pushType: 'HttpPost',
|
||||
pushServer: '',
|
||||
pushInfo: '',
|
||||
});
|
||||
emitChange();
|
||||
}
|
||||
|
||||
function removeRule(index: number) {
|
||||
list.value.splice(index, 1);
|
||||
emitChange();
|
||||
pushType: pushType.value,
|
||||
pushServer: pushServer.value,
|
||||
pushInfo: pushInfo.value,
|
||||
}));
|
||||
lastEmitted = out as unknown as DataPushRule[];
|
||||
emit('update:rules', lastEmitted);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- 表头 -->
|
||||
<div class="mb-1 flex items-center gap-2 text-xs text-gray-500">
|
||||
<span class="w-[44px] flex-shrink-0">启用</span>
|
||||
<span class="w-[96px] flex-shrink-0">数据类型</span>
|
||||
<span class="w-[150px] flex-shrink-0">推送方式</span>
|
||||
<span class="flex-1">服务地址</span>
|
||||
<span class="flex-1">路径 / 主题 / KEY</span>
|
||||
<span class="w-[120px] flex-shrink-0">备注</span>
|
||||
<span class="w-[48px] flex-shrink-0">操作</span>
|
||||
</div>
|
||||
<!-- 规则行:用稳定 key 的 v-for,避免输入时被重建导致失焦 -->
|
||||
<div
|
||||
v-for="(item, index) in list"
|
||||
:key="item._key"
|
||||
class="mb-2 flex items-center gap-2"
|
||||
>
|
||||
<span class="w-[44px] flex-shrink-0">
|
||||
<Switch
|
||||
v-model:checked="item.enabled"
|
||||
size="small"
|
||||
:disabled="disabled"
|
||||
@change="emitChange"
|
||||
/>
|
||||
</span>
|
||||
<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>
|
||||
<Select
|
||||
v-model:value="item.dataType"
|
||||
v-model:value="selectedTypes"
|
||||
mode="multiple"
|
||||
:options="dataTypeOptions"
|
||||
:disabled="disabled"
|
||||
class="w-[96px] flex-shrink-0"
|
||||
class="flex-1"
|
||||
placeholder="选择要推送的数据类型(可多选)"
|
||||
@change="emitChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-28 flex-shrink-0 text-sm text-gray-600">推送方式</span>
|
||||
<Select
|
||||
v-model:value="item.pushType"
|
||||
v-model:value="pushType"
|
||||
:options="pushTypeOptions"
|
||||
:disabled="disabled"
|
||||
class="w-[150px] flex-shrink-0"
|
||||
class="flex-1"
|
||||
@change="emitChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-28 flex-shrink-0 text-sm text-gray-600">服务地址</span>
|
||||
<Input
|
||||
v-model:value="item.pushServer"
|
||||
v-model:value="pushServer"
|
||||
:disabled="disabled"
|
||||
class="flex-1"
|
||||
placeholder="HTTP:http://ip:port,Redis:ip:port"
|
||||
@change="emitChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-28 flex-shrink-0 text-sm text-gray-600">路径 / 主题 / KEY</span>
|
||||
<Input
|
||||
v-model:value="item.pushInfo"
|
||||
v-model:value="pushInfo"
|
||||
:disabled="disabled"
|
||||
class="flex-1"
|
||||
placeholder="HTTP 为路径,Redis 为主题或 key"
|
||||
placeholder="HTTP 为推送路径,Redis 为主题或 key"
|
||||
@change="emitChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-28 flex-shrink-0 text-sm text-gray-600">备注</span>
|
||||
<Input
|
||||
v-model:value="item.ruleName"
|
||||
v-model:value="ruleName"
|
||||
:disabled="disabled"
|
||||
class="w-[120px] flex-shrink-0"
|
||||
class="flex-1"
|
||||
placeholder="可空"
|
||||
@change="emitChange"
|
||||
/>
|
||||
<span class="w-[48px] flex-shrink-0">
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
size="small"
|
||||
:disabled="disabled"
|
||||
@click="removeRule(index)"
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
<Button type="dashed" block :disabled="disabled" @click="addRule">
|
||||
+ 添加推送规则
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -3086,7 +3086,7 @@ async function submitDeviceDataFlowConfig() {
|
||||
// 仅在开启覆盖且需要推送时校验规则
|
||||
if (override && needPush) {
|
||||
if (rules.length === 0) {
|
||||
Message.error('请至少添加一条推送规则');
|
||||
Message.error('请至少选择要推送的数据类型');
|
||||
return;
|
||||
}
|
||||
const invalid = rules.some(
|
||||
|
||||
@ -383,7 +383,7 @@ async function submitDataFlowConfig() {
|
||||
// 开启推送时校验:至少一条规则,且启用的规则必须填服务地址与推送信息
|
||||
if (values.isNeedPushData) {
|
||||
if (rules.length === 0) {
|
||||
Message.error('请至少添加一条推送规则');
|
||||
Message.error('请至少选择要推送的数据类型');
|
||||
return;
|
||||
}
|
||||
const invalid = rules.some(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user