mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-02 03:02:19 +08:00
fix: autoflow not rerun if render by render function directly
This commit is contained in:
parent
c6e9e9ba79
commit
b643c9a330
@ -309,4 +309,13 @@ export class FlowEngine {
|
||||
}
|
||||
return modelClasses;
|
||||
}
|
||||
|
||||
static generateApplyFlowCacheKey(
|
||||
prefix: string,
|
||||
flowKey: string,
|
||||
modelUid: string,
|
||||
params: Record<string, any>,
|
||||
): string {
|
||||
return `${prefix}:${flowKey}:${modelUid}:${JSON.stringify(params)}`;
|
||||
}
|
||||
}
|
||||
|
@ -13,77 +13,7 @@ import { FlowModel } from '../models';
|
||||
import { useFlowEngine } from '../provider';
|
||||
import { FlowExtraContext } from '../types';
|
||||
import { uid } from 'uid/secure';
|
||||
|
||||
// 生成稳定的缓存键
|
||||
function generateCacheKey(prefix: string, flowKey: string, modelUid: string): string {
|
||||
return `${prefix}:${flowKey}:${modelUid}`;
|
||||
}
|
||||
|
||||
// 安全序列化对象的函数
|
||||
function safeStringify(obj: any, visited = new Set(), depth = 0, maxDepth = 5): string {
|
||||
// 深度限制,防止过深递归
|
||||
if (depth > maxDepth) {
|
||||
return '[MaxDepthExceeded]';
|
||||
}
|
||||
|
||||
// 处理基本类型
|
||||
if (obj === null || obj === undefined) {
|
||||
return String(obj);
|
||||
}
|
||||
|
||||
if (typeof obj !== 'object' && typeof obj !== 'function') {
|
||||
return String(obj);
|
||||
}
|
||||
|
||||
// 处理函数
|
||||
if (typeof obj === 'function') {
|
||||
// 对于函数,可以使用函数名或为匿名函数生成一个标识符
|
||||
return `function:${obj.name || 'anonymous'}`;
|
||||
}
|
||||
|
||||
// 处理循环引用
|
||||
if (visited.has(obj)) {
|
||||
return '[Circular]';
|
||||
}
|
||||
|
||||
// 添加到已访问集合
|
||||
visited.add(obj);
|
||||
|
||||
// 处理数组
|
||||
if (Array.isArray(obj)) {
|
||||
try {
|
||||
// 限制处理的数组元素数量
|
||||
const maxItems = 100;
|
||||
const items = obj.slice(0, maxItems);
|
||||
const result =
|
||||
'[' +
|
||||
items.map((item) => safeStringify(item, visited, depth + 1, maxDepth)).join(',') +
|
||||
(obj.length > maxItems ? ',...' : '') +
|
||||
']';
|
||||
return result;
|
||||
} catch (e) {
|
||||
return '[Array]';
|
||||
}
|
||||
}
|
||||
|
||||
// 处理普通对象
|
||||
try {
|
||||
const keys = Object.keys(obj).sort(); // 排序确保稳定性
|
||||
// 限制处理的属性数量
|
||||
const maxKeys = 50;
|
||||
const limitedKeys = keys.slice(0, maxKeys);
|
||||
|
||||
const pairs = limitedKeys.map((key) => {
|
||||
const value = obj[key];
|
||||
return `${key}:${safeStringify(value, visited, depth + 1, maxDepth)}`;
|
||||
});
|
||||
|
||||
return '{' + pairs.join(',') + (keys.length > maxKeys ? ',...' : '') + '}';
|
||||
} catch (e) {
|
||||
// 如果无法序列化,返回一个简单的标识
|
||||
return '[Object]';
|
||||
}
|
||||
}
|
||||
import { FlowEngine } from '../flowEngine';
|
||||
|
||||
/**
|
||||
* 通用的流程执行 Hook
|
||||
@ -105,8 +35,8 @@ function useFlowExecutor<T, TModel extends FlowModel = FlowModel>(
|
||||
): T {
|
||||
const engine = useFlowEngine();
|
||||
const cacheKey = useMemo(
|
||||
() => generateCacheKey(model['forkId'] ?? cacheKeyPrefix, flowKey, model.uid),
|
||||
[cacheKeyPrefix, flowKey, model.uid, model['forkId']],
|
||||
() => FlowEngine.generateApplyFlowCacheKey(model['forkId'] ?? cacheKeyPrefix, flowKey, model.uid, model.stepParams),
|
||||
[cacheKeyPrefix, flowKey, model.uid, model['forkId'], model.stepParams],
|
||||
);
|
||||
const [, forceUpdate] = useState({});
|
||||
const isMounted = useRef(false);
|
||||
|
@ -325,6 +325,7 @@ export class FlowModel<Structure extends { parent?: any; subModels?: any } = Def
|
||||
}
|
||||
}
|
||||
}
|
||||
this.applyAutoFlows(); // 参数变化时自动重新执行 autoFlows
|
||||
}
|
||||
|
||||
getStepParams(flowKey: string, stepKey: string): any | undefined;
|
||||
@ -518,9 +519,10 @@ export class FlowModel<Structure extends { parent?: any; subModels?: any } = Def
|
||||
/**
|
||||
* 执行所有自动应用流程
|
||||
* @param {FlowExtraContext} [extra] 可选的额外上下文
|
||||
* @param {boolean} [useCache=true] 是否使用缓存机制,默认为 true
|
||||
* @returns {Promise<any[]>} 所有自动应用流程的执行结果数组
|
||||
*/
|
||||
async applyAutoFlows(extra?: FlowExtraContext): Promise<any[]> {
|
||||
async applyAutoFlows(extra?: FlowExtraContext, useCache = true): Promise<any[]> {
|
||||
const autoApplyFlows = this.getAutoFlows();
|
||||
|
||||
if (autoApplyFlows.length === 0) {
|
||||
@ -528,6 +530,26 @@ export class FlowModel<Structure extends { parent?: any; subModels?: any } = Def
|
||||
return [];
|
||||
}
|
||||
|
||||
// 生成缓存键,包含 stepParams 的序列化版本以确保参数变化时重新执行
|
||||
const cacheKey = useCache
|
||||
? FlowEngine.generateApplyFlowCacheKey(this['forkId'] ?? 'autoFlow', 'all', this.uid, this.stepParams)
|
||||
: null;
|
||||
|
||||
// 检查缓存
|
||||
if (cacheKey && this.flowEngine) {
|
||||
const cachedEntry = this.flowEngine.applyFlowCache.get(cacheKey);
|
||||
if (cachedEntry) {
|
||||
if (cachedEntry.status === 'resolved') {
|
||||
console.log(`[FlowEngine.applyAutoFlows] Using cached result for model: ${this.uid}`);
|
||||
return cachedEntry.data;
|
||||
}
|
||||
if (cachedEntry.status === 'rejected') throw cachedEntry.error;
|
||||
if (cachedEntry.status === 'pending') return await cachedEntry.promise;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行 autoFlows
|
||||
const executeAutoFlows = async (): Promise<any[]> => {
|
||||
const results: any[] = [];
|
||||
for (const flow of autoApplyFlows) {
|
||||
try {
|
||||
@ -538,8 +560,35 @@ export class FlowModel<Structure extends { parent?: any; subModels?: any } = Def
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
// 如果不使用缓存,直接执行
|
||||
if (!cacheKey || !this.flowEngine) {
|
||||
return await executeAutoFlows();
|
||||
}
|
||||
|
||||
// 使用缓存机制
|
||||
const promise = executeAutoFlows()
|
||||
.then((result) => {
|
||||
this.flowEngine.applyFlowCache.set(cacheKey, {
|
||||
status: 'resolved',
|
||||
data: result,
|
||||
promise: Promise.resolve(result),
|
||||
});
|
||||
return result;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.flowEngine.applyFlowCache.set(cacheKey, {
|
||||
status: 'rejected',
|
||||
error: err,
|
||||
promise: Promise.reject(err),
|
||||
});
|
||||
throw err;
|
||||
});
|
||||
|
||||
this.flowEngine.applyFlowCache.set(cacheKey, { status: 'pending', promise });
|
||||
return await promise;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user