jbxl-workflow
Version:
流程图
128 lines (115 loc) • 5.09 kB
JavaScript
// utils/proxy.js
import { Graph } from "@antv/x6";
// import { createX6Binder } from "@/utils/common";
const whiteList = ['setZIndex'] // 在白名单内的方法不进行代理
export function createX6Binder(data, x6Node, options = {}) {
const { exclude = [], mapping = {}, direction = 'both' } = options;
const x6Properties = new Set(['id', 'shape', 'ports', 'zIndex']);
let isSyncing = false;
// 深度克隆并合并数据(避免引用问题)
const mergeData = (target, source) => {
return { ...target, ...source };
};
// 创建深层代理
const createDeepProxy = (target, isX6) => {
return new Proxy(target, {
get(t, prop) {
// 处理属性映射
const mappedProp = mapping[prop] || prop;
const value = Reflect.get(t, mappedProp);
// 跳过 X6 特殊属性
if (isX6 && x6Properties.has(mappedProp)) {
return value;
}
// 自动代理嵌套对象
if (typeof value === 'object' && value !== null && !exclude.includes(mappedProp)) {
return createDeepProxy(value, isX6);
}
return value;
},
set(t, prop, value) {
if (isSyncing) return true;
const mappedProp = mapping[prop] || prop;
if (exclude.includes(mappedProp)) return true;
try {
isSyncing = true;
// 双向同步逻辑
if (direction !== 'toData') {
// 更新数据对象
Reflect.set(t, mappedProp, value);
}
if (direction !== 'toX6') {
// 关键修改:调用 setData 而不是直接修改属性
// const targetObj = isX6 ? data : x6Node;
const targetKey = Object.entries(mapping)
.find(([k, v]) => v === mappedProp)?.[0] || mappedProp;
// 获取当前数据并合并更新
const currentData = isX6 ? data : x6Node.getData();
const newData = mergeData(currentData, { [targetKey]: value });
// 调用 setData 触发 X6 更新
if (isX6) {
x6Node.setData(newData);
} else {
const {data, self} = newData || {}
self.setData(data)
// TODO: 这里的逻辑有待优化,可能需要更精确地处理嵌套属性的更新,如果x6更新有问题的话,可能要将这个targetObj改回来,或者直接改成X6的setData方法
/**
* targetObj.setData(newData);
* */
// x6Node.setData(newData);
}
}
return true;
} finally {
isSyncing = false;
}
}
});
};
return [
createDeepProxy(data, false),
createDeepProxy(x6Node, true)
];
}
const nodeProxyMap = new WeakMap();
// 创建代理后的 Graph 实例
export const createGraph = (options) => {
// 初始化原始 X6 实例
const rawGraph = new Graph(options);
// 创建代理实例
const graphProxy = createGraphProxy(rawGraph);
window.customGraph = graphProxy;
return graphProxy;
};
// 代理工厂
export const createGraphProxy = (graph) => {
return new Proxy(graph, {
get(target, prop) {
// 拦截 addNode:绑定业务对象
if (prop === 'addNode') {
return (params) => {
// 从参数中提取业务对象
const businessObj = params.data?.self;
if (!businessObj) throw new Error('Missing self object in node data');
// 创建原始 X6 节点
const rawNode = target.addNode(params);
businessObj.nodeId = rawNode.id; // 设置节点 ID 以便后续引用
// 创建一个特殊的代理,处理 setZIndex 等方法
// 创建双向绑定代理
const [businessProxy, x6Proxy] = createX6Binder(businessObj, rawNode);
// 缓存代理关系
nodeProxyMap.set(rawNode, businessProxy);
return [businessProxy, x6Proxy]; // 返回业务代理对象
};
}
// 拦截 getNode:返回业务代理对象
if (prop === 'getNode') {
return (nodeId) => {
const rawNode = target.getNode(nodeId);
return nodeProxyMap.get(rawNode) || null;
};
}
return Reflect.get(target, prop);
}
});
};