feat(flow): 添加单节点执行机器人选择记忆功能
- 引入 watch 监听器和相关变量用于缓存单节点机器人选择 - 实现按节点ID缓存机器人选择,新节点默认沿用最近一次选择 - 在单节点执行前后记录当前机器人选择到缓存中 - 修改NodeTitle组件传递节点ID用于按节点恢复机器人选择 - 添加试运行参数缓存功能,支持按流程缓存整套参数 - 实现参数层级缓存值恢复,兼容参数结构变化 - 优化试运行关闭和确认时的数据缓存处理逻辑
This commit is contained in:
parent
e6d379f571
commit
8e2afcbaa6
@ -159,7 +159,8 @@ const execute = () => {
|
||||
document.dispatchEvent(new CustomEvent("singleNodeExecution", {
|
||||
bubbles: false,
|
||||
cancelable: false,
|
||||
detail: { ...props.nodeProperties },
|
||||
// 携带节点 ID,供单节点执行弹窗按节点恢复上次选择的机器人。
|
||||
detail: { ...props.nodeProperties, nodeId: props.nodeId },
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
@ -90,14 +90,42 @@ const props = defineProps({
|
||||
const ruleFormRef = ref()
|
||||
const rules = ref({});
|
||||
const tableData = ref([])
|
||||
// 按流程缓存整套试运行参数,关闭或执行后再次打开时继续使用。
|
||||
const trialRunCache = new Map()
|
||||
const bindingLoading = ref(false)
|
||||
const emptyBindingSummary = (robotId = '') => ({ robotId, matched: 0, missing: 0, untouched: 0 })
|
||||
const bindingSummary = ref(emptyBindingSummary())
|
||||
|
||||
const emits = defineEmits(['close', 'changeState'])
|
||||
|
||||
const cloneData = (data) => JSON.parse(JSON.stringify(data || []))
|
||||
|
||||
// 根据参数层级恢复缓存值,同时兼容流程参数结构发生增删的情况。
|
||||
const mergeCachedValues = (source, cached) => {
|
||||
const cachedByName = new Map((cached || []).map(item => [item.name, item]))
|
||||
return (source || []).map((item, index) => {
|
||||
const cachedAtIndex = cached?.[index]
|
||||
const cachedItem = cachedAtIndex?.name === item.name ? cachedAtIndex : cachedByName.get(item.name)
|
||||
if (!cachedItem) return item
|
||||
const merged = { ...item, value: cachedItem.value }
|
||||
if (Array.isArray(item.children)) {
|
||||
merged.children = mergeCachedValues(item.children, cachedItem.children)
|
||||
}
|
||||
return merged
|
||||
})
|
||||
}
|
||||
|
||||
const cacheKey = () => props.flowId || '__new_flow__'
|
||||
|
||||
// 深拷贝快照,避免后续表单编辑直接修改缓存内容。
|
||||
const rememberTrialRunParams = () => {
|
||||
if (!tableData.value.length) return
|
||||
trialRunCache.set(cacheKey(), cloneData(tableData.value))
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
ruleFormRef.value?.resetFields()
|
||||
rememberTrialRunParams()
|
||||
ruleFormRef.value?.clearValidate()
|
||||
emits('close')
|
||||
}
|
||||
|
||||
@ -105,14 +133,17 @@ watch(() => props.drawer,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
const data = getStartNodeFormData()
|
||||
tableData.value = data
|
||||
bindingSummary.value = emptyBindingSummary()
|
||||
const cached = trialRunCache.get(cacheKey())
|
||||
tableData.value = mergeCachedValues(data, cached)
|
||||
const robotId = tableData.value.find(item => item.name === 'robotId')?.value || ''
|
||||
bindingSummary.value = emptyBindingSummary(robotId)
|
||||
loadRobotOptions()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const confirm = () => {
|
||||
rememberTrialRunParams()
|
||||
lf.fitView()
|
||||
ruleFormRef.value.validate().then(async () => {
|
||||
const formData = formatTableData(tableData.value)
|
||||
|
||||
@ -245,7 +245,7 @@
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, reactive, ref, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import { computed, reactive, ref, watch, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import { MarkerType, VueFlow, useVueFlow } from "@vue-flow/core";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { Background } from "@vue-flow/background";
|
||||
@ -899,6 +899,10 @@ const rules = reactive({});
|
||||
const executeForm = ref();
|
||||
const nodeAction = ref("");
|
||||
const singleNodeExecuting = ref(false);
|
||||
const activeSingleNodeId = ref("");
|
||||
// 单节点机器人选择按节点缓存;新节点默认沿用最近一次选择。
|
||||
const singleNodeRobotCache = new Map();
|
||||
let lastSingleNodeRobotId = "";
|
||||
const stationLoading = ref(false);
|
||||
const singleNodeRobotOptions = ref([]);
|
||||
const flattenSingleNodeParams = (params, parentPath = [], fields = []) => {
|
||||
@ -945,6 +949,16 @@ const singleNodeRobotId = computed(() =>
|
||||
const singleNodeDeviceId = computed(() =>
|
||||
formData.nodeParams.find((item) => item.name === "deviceId")?.input
|
||||
);
|
||||
// 在执行、关闭弹窗或切换节点前记录当前机器人选择。
|
||||
const rememberSingleNodeRobot = () => {
|
||||
if (!activeSingleNodeId.value || !singleNodeRobotId.value) return;
|
||||
lastSingleNodeRobotId = singleNodeRobotId.value;
|
||||
singleNodeRobotCache.set(activeSingleNodeId.value, singleNodeRobotId.value);
|
||||
};
|
||||
|
||||
watch(visible, (value) => {
|
||||
if (!value) rememberSingleNodeRobot();
|
||||
});
|
||||
|
||||
const handleSingleNodeRobotChange = async (robotId) => {
|
||||
const deviceParam = formData.nodeParams.find((item) => item.name === "deviceId");
|
||||
@ -1035,10 +1049,12 @@ const loadSingleNodeRobots = async () => {
|
||||
};
|
||||
|
||||
const singleNodeExecution = async (e) => {
|
||||
const { name, nodeType, nodeParams, action } = e.detail;
|
||||
rememberSingleNodeRobot();
|
||||
const { name, nodeType, nodeParams, action, nodeId } = e.detail;
|
||||
const executionParams = JSON.parse(JSON.stringify(nodeParams || []));
|
||||
const normalizedAction = String(action || "").toUpperCase();
|
||||
const effectiveNodeType = nodeType || (getDeviceKindForAction(normalizedAction) ? "EDGE" : "");
|
||||
activeSingleNodeId.value = nodeId || `${normalizedAction}:${name || ""}`;
|
||||
nodeName.value = name;
|
||||
visible.value = true;
|
||||
nodeAction.value = normalizedAction;
|
||||
@ -1057,6 +1073,11 @@ const singleNodeExecution = async (e) => {
|
||||
},
|
||||
...executionParams,
|
||||
];
|
||||
const cachedRobotId = singleNodeRobotCache.get(activeSingleNodeId.value) || lastSingleNodeRobotId;
|
||||
if (cachedRobotId) {
|
||||
formData.nodeParams[0].input = cachedRobotId;
|
||||
await handleSingleNodeRobotChange(cachedRobotId);
|
||||
}
|
||||
} else {
|
||||
formData.nodeParams = executionParams;
|
||||
}
|
||||
@ -1081,6 +1102,7 @@ const execute = async () => {
|
||||
}
|
||||
}
|
||||
if (!validateSingleNodeParams()) return;
|
||||
rememberSingleNodeRobot();
|
||||
singleNodeExecuting.value = true;
|
||||
try {
|
||||
const res = await flowAction({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user