refactor(editor): 优化dsl更新后画布更新逻辑

This commit is contained in:
roymondchen 2025-01-10 19:44:40 +08:00
parent 895c461e2b
commit ab7df6c21e
2 changed files with 112 additions and 67 deletions

View File

@ -1,6 +1,7 @@
import { computed, onBeforeUnmount, reactive, toRaw, watch } from 'vue';
import { cloneDeep } from 'lodash-es';
import type TMagicCore from '@tmagic/core';
import type {
CodeBlockContent,
DataSourceSchema,
@ -263,67 +264,46 @@ export const initServiceEvents = (
if (!node) return;
collectIdle([node], true).then(() => {
afterUpdateNodes([node]);
});
collectIdle([node], true);
updateStage([node]);
});
});
const getApp = () => stage.value?.renderer?.runtime?.getApp?.();
const updateDataSourceSchema = (nodes: MNode[], deep: boolean) => {
const root = editorService.get('root');
const app = getApp();
if (root && app?.dsl) {
app.dsl.dataSourceDeps = root.dataSourceDeps;
app.dsl.dataSourceCondDeps = root.dataSourceCondDeps;
app.dsl.dataSources = root.dataSources;
const getApp = () => {
const renderer = stage.value?.renderer;
if (!renderer) {
return undefined;
}
if (root?.dataSources) {
getApp()?.dataSourceManager?.updateSchema(root.dataSources);
if (renderer.runtime) {
return renderer.runtime.getApp?.();
}
if (!root || !stage.value) return;
return new Promise<TMagicCore | undefined>((resolve) => {
const timeout = globalThis.setTimeout(() => {
resolve(undefined);
}, 10000);
const allNodes: MNode[] = [];
if (deep) {
nodes.forEach((node) => {
traverseNode<MNode>(node, (node) => {
if (!allNodes.includes(node)) {
allNodes.push(node);
}
});
});
} else {
allNodes.push(...nodes);
}
const deps = Object.values(root.dataSourceDeps || {});
deps.forEach((dep) => {
Object.keys(dep).forEach((id) => {
const node = allNodes.find((node) => node.id === id);
node &&
stage.value?.update({
config: cloneDeep(node),
parentId: editorService.getParentById(node.id)?.id,
root: cloneDeep(root),
});
renderer.on('runtime-ready', () => {
if (timeout) {
globalThis.clearTimeout(timeout);
}
resolve(renderer.runtime?.getApp?.());
});
});
};
const afterUpdateNodes = (nodes: MNode[]) => {
const updateDataSourceSchema = async () => {
const root = editorService.get('root');
if (!root) return;
for (const node of nodes) {
stage.value?.update({
config: cloneDeep(node),
parentId: editorService.getParentById(node.id)?.id,
root: cloneDeep(root),
});
const app = await getApp();
if (root && app?.dsl) {
app.dsl.dataSourceDeps = root.dataSourceDeps;
app.dsl.dataSources = root.dataSources;
}
if (root?.dataSources) {
app?.dataSourceManager?.updateSchema(root.dataSources);
}
};
@ -360,18 +340,72 @@ export const initServiceEvents = (
}
};
const depCollectedHandler = () => {
/**
* dsl后会执行依赖收集并调用此方法
* updateStage应当时一次inDeps参数来区分调用时机
* inDeps为true是则更新依赖收集到的节点
* @param nodes
* @param inDeps
* @returns
*/
const updateStage = (nodes: MNode[], inDeps = false) => {
const root = editorService.get('root');
if (!root) return;
const app = getApp();
const update = (node: MNode) =>
stage.value?.update({
config: cloneDeep(node),
parentId: editorService.getParentById(node.id)?.id,
root: cloneDeep(root),
});
nodes.forEach((node) => {
const inDepsNodeId: Id[] = [];
const deps = Object.values(root.dataSourceDeps || {});
deps.forEach((dep) => {
Object.keys(dep).forEach((id) => {
inDepsNodeId.push(id);
});
});
if (inDeps) {
if (inDepsNodeId.includes(node.id)) {
update(node);
}
} else {
if (!inDepsNodeId.includes(node.id)) {
update(node);
}
}
});
};
const dsDepCollectedHandler = async (nodes: MNode[], deep: boolean) => {
const root = editorService.get('root');
if (!root) return;
const app = await getApp();
if (app?.dsl) {
app.dsl.dataSourceDeps = root.dataSourceDeps;
}
if (deep) {
nodes.forEach((node) => {
traverseNode<MNode>(
node,
(node) => {
updateStage([node], true);
},
[],
true,
);
});
} else {
updateStage(nodes, true);
}
};
depService.on('add-target', targetAddHandler);
depService.on('remove-target', targetRemoveHandler);
depService.on('collected', depCollectedHandler);
depService.on('ds-collected', dsDepCollectedHandler);
const initDataSourceDepTarget = (ds: DataSourceSchema) => {
depService.addTarget(createDataSourceTarget(ds, reactive({})));
@ -396,9 +430,9 @@ export const initServiceEvents = (
// 新增节点,收集依赖
const nodeAddHandler = (nodes: MNode[]) => {
collectIdle(nodes, true).then(() => {
afterUpdateNodes(nodes);
});
collectIdle(nodes, true);
updateStage(nodes);
};
// 节点更新,收集依赖
@ -430,11 +464,10 @@ export const initServiceEvents = (
});
if (needRecollectNodes.length) {
collectIdle(needRecollectNodes, true).then(() => {
afterUpdateNodes(needRecollectNodes);
});
collectIdle(needRecollectNodes, true);
updateStage(needRecollectNodes);
} else if (normalNodes.length) {
afterUpdateNodes(normalNodes);
updateStage(normalNodes);
}
};
@ -446,7 +479,7 @@ export const initServiceEvents = (
// 由于历史记录变化是更新整个page所以历史记录变化时需要重新收集依赖
const historyChangeHandler = (page: MPage | MPageFragment) => {
collectIdle([page], true).then(() => {
updateDataSourceSchema([page], true);
updateDataSourceSchema();
});
};
@ -472,12 +505,16 @@ export const initServiceEvents = (
codeBlockService.on('addOrUpdate', codeBlockAddOrUpdateHandler);
codeBlockService.on('remove', codeBlockRemoveHandler);
const dataSourceAddHandler = (config: DataSourceSchema) => {
const dataSourceAddHandler = async (config: DataSourceSchema) => {
initDataSourceDepTarget(config);
getApp()?.dataSourceManager?.addDataSource(config);
const app = await getApp();
app?.dataSourceManager?.addDataSource(config);
};
const dataSourceUpdateHandler = (config: DataSourceSchema, { changeRecords }: { changeRecords: ChangeRecord[] }) => {
const dataSourceUpdateHandler = async (
config: DataSourceSchema,
{ changeRecords }: { changeRecords: ChangeRecord[] },
) => {
let needRecollectDep = false;
for (const changeRecord of changeRecords) {
if (!changeRecord.propPath) {
@ -506,11 +543,12 @@ export const initServiceEvents = (
initDataSourceDepTarget(config);
collectIdle(root.items, true).then(() => {
updateDataSourceSchema(root?.items || [], true);
updateDataSourceSchema();
});
}
} else if (root?.dataSources) {
getApp()?.dataSourceManager?.updateSchema(root.dataSources);
const app = await getApp();
app?.dataSourceManager?.updateSchema(root.dataSources);
}
};
@ -525,7 +563,7 @@ export const initServiceEvents = (
const nodeIds = Object.keys(root?.dataSourceDeps?.[id] || {});
const nodes = getNodes(nodeIds, root?.items);
collectIdle(nodes, false).then(() => {
updateDataSourceSchema(nodes, false);
updateDataSourceSchema();
});
removeDataSourceTarget(id);
@ -538,7 +576,7 @@ export const initServiceEvents = (
onBeforeUnmount(() => {
depService.off('add-target', targetAddHandler);
depService.off('remove-target', targetRemoveHandler);
depService.off('collected', depCollectedHandler);
depService.off('ds-collected', dsDepCollectedHandler);
editorService.off('history-change', historyChangeHandler);
editorService.off('root-change', rootChangeHandler);

View File

@ -499,8 +499,11 @@ export const traverseNode = <T extends NodeItem = NodeItem>(
node: T,
cb: (node: T, parents: T[]) => void,
parents: T[] = [],
evalCbAfter = false,
) => {
cb(node, parents);
if (!evalCbAfter) {
cb(node, parents);
}
if (Array.isArray(node.items) && node.items.length) {
parents.push(node);
@ -508,6 +511,10 @@ export const traverseNode = <T extends NodeItem = NodeItem>(
traverseNode(item as T, cb, [...parents]);
});
}
if (evalCbAfter) {
cb(node, parents);
}
};
export const isValueIncludeDataSource = (value: any) => {