数据同步bug修改
This commit is contained in:
parent
38e2a1868a
commit
0235db5279
|
|
@ -88,7 +88,7 @@ export class X6Graph {
|
|||
|
||||
private createMenuElement() {
|
||||
this.menuElement = document.getElementById("ant-x6-menu4");
|
||||
if(this.menuElement){
|
||||
if (this.menuElement) {
|
||||
this.menuElement.remove();
|
||||
}
|
||||
this.menuElement = document.createElement("div");
|
||||
|
|
@ -304,7 +304,7 @@ export class X6Graph {
|
|||
label: targetNode.attr("label/text") || "",
|
||||
level: nodeLevel,
|
||||
allParents: allParentsOrdered, // 包含父级+当前节点(均有label)
|
||||
isTbsl:false,
|
||||
isTbsl: false,
|
||||
});
|
||||
}
|
||||
this.hideMenu();
|
||||
|
|
@ -346,7 +346,7 @@ export class X6Graph {
|
|||
id: nodeId,
|
||||
label: targetNode.attr("label/text") || "",
|
||||
level: nodeLevel,
|
||||
isTbsl:true,
|
||||
isTbsl: true,
|
||||
});
|
||||
}
|
||||
this.hideMenu();
|
||||
|
|
@ -634,6 +634,7 @@ export class X6Graph {
|
|||
addChildNode(
|
||||
parentId: string,
|
||||
config: ChildNodeConfig,
|
||||
skipRearrange = false,
|
||||
): { node: Node; edge: Edge } {
|
||||
const graph = this.getGraph();
|
||||
|
||||
|
|
@ -682,11 +683,23 @@ export class X6Graph {
|
|||
throw new Error(`创建连线(${parentId}→${childNode.id})失败`);
|
||||
}
|
||||
|
||||
// 重排同层级节点
|
||||
this.rearrangeLevelNodes(config.level);
|
||||
// 新增:如果添加的是第三层级,同步重排第二层级
|
||||
if (config.level === "level3") {
|
||||
this.rearrangeLevelNodes("level2");
|
||||
// // 重排同层级节点
|
||||
// this.rearrangeLevelNodes(config.level);
|
||||
// // 新增:如果添加的是第三层级,同步重排第二层级
|
||||
// if (config.level === "level3") {
|
||||
// this.rearrangeLevelNodes("level2");
|
||||
// }
|
||||
|
||||
if (!skipRearrange) {
|
||||
this.rearrangeLevelNodes(config.level);
|
||||
// 新增:如果添加的是第三层级,同步重排第二层级
|
||||
if (config.level === "level3") {
|
||||
this.rearrangeLevelNodes("level2");
|
||||
}
|
||||
// 如果新增level4,要重排level3(父层级),父节点位置可能变化
|
||||
if (config.level === "level4") {
|
||||
this.rearrangeLevelNodes("level3");
|
||||
}
|
||||
}
|
||||
return { node: childNode, edge: edge as Edge };
|
||||
}
|
||||
|
|
@ -697,9 +710,8 @@ export class X6Graph {
|
|||
private rearrangeLevelNodes(level: NodeLevel): void {
|
||||
const graph = this.getGraph();
|
||||
const containerHeight = graph.container.clientHeight;
|
||||
const centerY = (containerHeight - this.nodeStyle.height) / 2; // 画布中心点
|
||||
const centerY = (containerHeight - this.nodeStyle.height) / 2;
|
||||
|
||||
// 获取当前层级的所有节点(按标签排序)
|
||||
const levelNodes = graph
|
||||
.getNodes()
|
||||
.filter((node) => node.getData().level === level)
|
||||
|
|
@ -709,16 +721,12 @@ export class X6Graph {
|
|||
return labelA.localeCompare(labelB, undefined, { numeric: true });
|
||||
});
|
||||
const totalNodes = levelNodes.length;
|
||||
|
||||
if (totalNodes === 0) return;
|
||||
|
||||
// ======================== 第二层级:间距根据自身第三层级子节点数量动态调整 ========================
|
||||
if (level === "level2") {
|
||||
// 1. 统计每个第二层级节点的第三层级子节点数量
|
||||
const level2ChildCount = new Map<string, number>();
|
||||
levelNodes.forEach((node) => {
|
||||
const childIds = this.getChildNodeIds(node.id);
|
||||
// 筛选出属于第三层级的子节点
|
||||
const level3ChildCount = childIds.filter((childId) => {
|
||||
const childNode = graph.getCellById(childId) as Node;
|
||||
return childNode?.getData().level === "level3";
|
||||
|
|
@ -726,45 +734,34 @@ export class X6Graph {
|
|||
level2ChildCount.set(node.id, level3ChildCount);
|
||||
});
|
||||
|
||||
// 2. 计算每个第二层级节点的动态间距(自身子节点越多,间距越大)
|
||||
const baseGap = 100; // 基础间距
|
||||
const factor = 30; // 比例因子(每个子节点增加30px间距)
|
||||
let currentY = centerY; // 起始Y坐标(后续会调整为整体居中)
|
||||
const nodePositions = new Map<string, number>(); // 记录每个节点的Y坐标
|
||||
const baseGap = 100;
|
||||
const factor = 30;
|
||||
let currentY = centerY;
|
||||
const nodePositions = new Map<string, number>();
|
||||
|
||||
// 先计算第一个节点的位置(以画布中心为基准)
|
||||
const firstNode = levelNodes[0];
|
||||
nodePositions.set(firstNode.id, currentY);
|
||||
|
||||
// 计算后续节点的位置(根据前一个节点的子节点数量动态调整间距)
|
||||
for (let i = 1; i < totalNodes; i++) {
|
||||
const prevNode = levelNodes[i - 1];
|
||||
const prevChildCount = level2ChildCount.get(prevNode.id) || 0;
|
||||
// 间距 = 基础间距 + 前一个节点的子节点数 × 因子
|
||||
const dynamicGap = baseGap + prevChildCount * factor;
|
||||
// 下一个节点Y坐标 = 当前Y + 节点高度 + 动态间距
|
||||
currentY += this.nodeStyle.height + dynamicGap;
|
||||
nodePositions.set(levelNodes[i].id, currentY);
|
||||
}
|
||||
|
||||
// 3. 计算整体偏移量,让第二层级节点整体垂直居中
|
||||
const lastNodeY = nodePositions.get(levelNodes[totalNodes - 1].id) || 0;
|
||||
const totalHeight =
|
||||
lastNodeY - nodePositions.get(levelNodes[0].id) ||
|
||||
0 + this.nodeStyle.height;
|
||||
const offset =
|
||||
centerY - (nodePositions.get(levelNodes[0].id) || 0) - totalHeight / 2;
|
||||
// ✅修复括号优先级
|
||||
const firstY = nodePositions.get(levelNodes[0].id) ?? 0;
|
||||
const lastNodeY = nodePositions.get(levelNodes[totalNodes - 1].id) ?? 0;
|
||||
const totalHeight = lastNodeY - firstY + this.nodeStyle.height;
|
||||
const offset = centerY - firstY - totalHeight / 2;
|
||||
|
||||
// 4. 应用最终位置(加上偏移量,确保整体居中)
|
||||
levelNodes.forEach((node) => {
|
||||
const nodeY = (nodePositions.get(node.id) || 0) + offset;
|
||||
const nodeX = this.levelXMap.get("level2") || 300;
|
||||
node.setPosition(nodeX, nodeY);
|
||||
});
|
||||
}
|
||||
|
||||
// ======================== 第三层级:跟随父节点垂直分布 ========================
|
||||
else if (level === "level3") {
|
||||
} else if (level === "level3") {
|
||||
const parentGroups = new Map<string, Node[]>();
|
||||
levelNodes.forEach((node) => {
|
||||
const parentEdge = graph
|
||||
|
|
@ -785,7 +782,7 @@ export class X6Graph {
|
|||
|
||||
const parentY = parentNode.getPosition().y;
|
||||
const childCount = children.length;
|
||||
const verticalGap = 20; // 第三层级内部固定间距
|
||||
const verticalGap = 20;
|
||||
|
||||
const totalChildHeight =
|
||||
this.nodeStyle.height * childCount + verticalGap * (childCount - 1);
|
||||
|
|
@ -801,46 +798,53 @@ export class X6Graph {
|
|||
});
|
||||
});
|
||||
} else if (level === "level4") {
|
||||
// 1. 按父节点(level3)分组(每个level3只对应1个level4)
|
||||
const parentGroups = new Map<string, Node[]>();
|
||||
levelNodes.forEach((node) => {
|
||||
const parentEdge = graph
|
||||
.getEdges()
|
||||
.find((edge) => edge.getTargetCellId() === node.id);
|
||||
if (parentEdge) {
|
||||
const parentId = parentEdge.getSourceCellId();
|
||||
// 只保留level3的父节点(确保父节点层级正确)
|
||||
const parentNode = graph.getCellById(parentId) as Node;
|
||||
if (parentNode?.getData().level === "level3") {
|
||||
parentGroups.set(parentId, [
|
||||
...(parentGroups.get(parentId) || []),
|
||||
node,
|
||||
]);
|
||||
const levelNodes = this.graph.getCells().filter((cell) => {
|
||||
return cell.isNode() && cell.getData()?.level === level;
|
||||
}) as Node[];
|
||||
if (!levelNodes.length) return;
|
||||
|
||||
const allEdges = this.graph.getEdges();
|
||||
//按照父节点Y排序,保证顺序和左侧level3从上到下保持一致
|
||||
levelNodes.sort((a, b) => {
|
||||
let ay = 0,
|
||||
by = 0;
|
||||
for (const e of allEdges) {
|
||||
if (e.getTargetCellId() === a.id) {
|
||||
const p = this.graph.getCellById(e.getSourceCellId()) as Node;
|
||||
ay = p.getPosition().y;
|
||||
}
|
||||
if (e.getTargetCellId() === b.id) {
|
||||
const p = this.graph.getCellById(e.getSourceCellId()) as Node;
|
||||
by = p.getPosition().y;
|
||||
}
|
||||
}
|
||||
return ay - by;
|
||||
});
|
||||
|
||||
// 2. 每个level3父节点的level4子节点:放在父节点右侧(固定间距)
|
||||
parentGroups.forEach((children, parentId) => {
|
||||
const parentNode = graph.getCellById(parentId) as Node;
|
||||
if (!parentNode) return;
|
||||
const nodeH = this.nodeStyle.height;
|
||||
const verticalGap = 20;
|
||||
const totalHeight =
|
||||
levelNodes.length * nodeH + (levelNodes.length - 1) * verticalGap;
|
||||
|
||||
// level4固定在level3父节点右侧,X坐标=level3X + 节点宽度 + 间距(20px)
|
||||
const parentPos = parentNode.getPosition();
|
||||
const level4X = this.levelXMap.get("level4") || 800;
|
||||
// Y坐标与父节点完全对齐(上下居中)
|
||||
const level4Y = parentPos.y;
|
||||
//参考level3整体的中心点
|
||||
const level3Nodes = this.graph
|
||||
.getCells()
|
||||
.filter((c) => c.isNode() && c.getData()?.level === "level3") as Node[];
|
||||
let refCenterY = 300;
|
||||
if (level3Nodes.length > 0) {
|
||||
const topY = Math.min(...level3Nodes.map((n) => n.getPosition().y));
|
||||
const botY =
|
||||
Math.max(...level3Nodes.map((n) => n.getPosition().y)) + nodeH;
|
||||
refCenterY = (topY + botY) / 2;
|
||||
}
|
||||
|
||||
// 只保留第一个level4节点(确保仅一个子节点)
|
||||
const targetChild = children[0];
|
||||
if (targetChild) {
|
||||
targetChild.setPosition(level4X, level4Y);
|
||||
// 多余节点直接删除(避免多个level4)
|
||||
if (children.length > 1) {
|
||||
children.slice(1).forEach((excessNode) => excessNode.remove());
|
||||
this.resetLevelCount("level4"); // 重置数量统计
|
||||
}
|
||||
}
|
||||
const startY = refCenterY - totalHeight / 2;
|
||||
const level4X = this.levelXMap.get("level4") || 800;
|
||||
|
||||
let currentY = startY;
|
||||
levelNodes.forEach((node) => {
|
||||
node.setPosition(level4X, currentY);
|
||||
currentY += nodeH + verticalGap;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -853,6 +857,37 @@ export class X6Graph {
|
|||
const cell = graph.getCellById(nodeId);
|
||||
if (!cell || !graph.isNode(cell)) return;
|
||||
|
||||
// if (targetNode.getData().tbslFlag) {
|
||||
// // 1、拿到被删节点的直接父节点
|
||||
// const inEdges = graph.getIncomingEdges(graph.getCellById(nodeId));
|
||||
// inEdges[0].setData({ ...inEdges[0].getData(), syncCount: null });
|
||||
|
||||
// inEdges[0].setAttrs({
|
||||
// label: {
|
||||
// text: 22222,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
|
||||
if (cell.data.tbslFlag) {
|
||||
graph.getEdges().forEach((edge) => {
|
||||
const sourceNode = edge.getSourceNode();
|
||||
const targetNode = edge.getTargetNode();
|
||||
if (targetNode.id == cell.id) {
|
||||
sourceNode.setData({ syncCount: null });
|
||||
}
|
||||
});
|
||||
|
||||
const inEdges = graph.getIncomingEdges(cell);
|
||||
inEdges[0].setData({ ...inEdges[0].getData(), syncCount: null });
|
||||
|
||||
inEdges[0].setAttrs({
|
||||
label: {
|
||||
text: 22222,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const node = cell as Node;
|
||||
const nodeLevel = node.getData().level as NodeLevel;
|
||||
|
||||
|
|
@ -880,28 +915,61 @@ export class X6Graph {
|
|||
// 3. 遍历灌库数据,创建 level2→level3→level4 层级
|
||||
importData.forEach((item) => {
|
||||
// 3.1 创建 level2 节点(userName 作为 label,父节点是根节点)
|
||||
const { node: level2Node } = this.addChildNode(rootId, {
|
||||
id: uuidv4(),
|
||||
label: item.userName,
|
||||
level: "level2",
|
||||
});
|
||||
const { node: level2Node } = this.addChildNode(
|
||||
rootId,
|
||||
{
|
||||
id: uuidv4(),
|
||||
label: item.userName,
|
||||
level: "level2",
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
// 3.2 遍历当前 level2 的 tables,创建 level3 和 level4 节点
|
||||
item.tables.forEach((table) => {
|
||||
// 3.2.1 创建 level3 节点(tableName 作为 label,父节点是当前 level2)
|
||||
const { node: level3Node } = this.addChildNode(level2Node.id, {
|
||||
id: uuidv4(),
|
||||
label: table.tableName,
|
||||
level: "level3",
|
||||
});
|
||||
const { node: level3Node } = this.addChildNode(
|
||||
level2Node.id,
|
||||
{
|
||||
id: uuidv4(),
|
||||
label: table.tableName,
|
||||
level: "level3",
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
// 3.2.2 创建 level4 节点(columnName 作为 label,父节点是当前 level3)
|
||||
this.addChildNode(level3Node.id, {
|
||||
id: uuidv4(),
|
||||
label: table.columnName,
|
||||
level: "level4",
|
||||
});
|
||||
});
|
||||
this.addChildNode(
|
||||
level3Node.id,
|
||||
{
|
||||
id: uuidv4(),
|
||||
label: table.columnName,
|
||||
level: "level4",
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
if (table.syncCount) {
|
||||
level3Node.data.syncCount = table.syncCount;
|
||||
console.log(level3Node, "3333");
|
||||
this.addChildNode(level3Node.id, {
|
||||
id: uuidv4(),
|
||||
label: table.syncCount.toString(),
|
||||
level: "level4",
|
||||
});
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
// // 全部节点循环创建完成后,统一执行全套重排
|
||||
this.rearrangeLevelNodes("level2");
|
||||
this.rearrangeLevelNodes("level3");
|
||||
this.rearrangeLevelNodes("level4");
|
||||
|
||||
this.graph.zoomToFit({
|
||||
padding: 40, // 四周留白,节点不会贴边框
|
||||
maxZoom: 1, // 最大缩放比例,不要放太大;数据多时会缩小
|
||||
minZoom: 0.3,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -956,7 +1024,7 @@ export class X6Graph {
|
|||
};
|
||||
}
|
||||
|
||||
const syncCount = level3Node.getData().syncCount||"";
|
||||
const syncCount = level3Node.getData().syncCount || "";
|
||||
|
||||
// 2.2.1 校验 level3 是否有子级(必须包含 level4)
|
||||
const level3ChildIds = this.getChildNodeIds(level3Node.id);
|
||||
|
|
@ -986,7 +1054,7 @@ export class X6Graph {
|
|||
targetOwner: name, // 传入的name字段作为targetOwner
|
||||
tableName,
|
||||
columnName,
|
||||
syncCount
|
||||
syncCount,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,45 +220,42 @@ onMounted(() => {
|
|||
},
|
||||
(res) => {
|
||||
initGraph();
|
||||
getModelList((value: any) => {
|
||||
console.log(value);
|
||||
if (res.result.userInfos.length) {
|
||||
graph.value?.importData(res.result.userInfos, formData.sourceId);
|
||||
if (res.result.userInfos.length) {
|
||||
graph.value?.importData(res.result.userInfos, formData.sourceId);
|
||||
|
||||
res.result.userInfos.forEach((item: any) => {
|
||||
const graphSl = graph.value?.getGraph();
|
||||
res.result.userInfos.forEach((item: any) => {
|
||||
const graphSl = graph.value?.getGraph();
|
||||
|
||||
// 获取全部节点实例
|
||||
const allNodes = graphSl.getNodes();
|
||||
console.log(allNodes, "allNodes");
|
||||
// 过滤:根据你存名称的字段,这里假设字段是 label;如果你的字段是 name,就改成 item.name
|
||||
const matchNodesData = allNodes
|
||||
.map((node) => {
|
||||
return {
|
||||
label: node.label,
|
||||
id: node.id,
|
||||
};
|
||||
})
|
||||
.filter((item1) => {
|
||||
return item1.label == item.userName;
|
||||
});
|
||||
const exists = modeList.value.find(
|
||||
(item1: any) => item1.label === item.userName
|
||||
);
|
||||
|
||||
if (!exists) {
|
||||
const newItem = {
|
||||
value: matchNodesData[0].id,
|
||||
label: item.userName,
|
||||
// 获取全部节点实例
|
||||
const allNodes = graphSl.getNodes();
|
||||
console.log(allNodes, "allNodes");
|
||||
// 过滤:根据你存名称的字段,这里假设字段是 label;如果你的字段是 name,就改成 item.name
|
||||
const matchNodesData = allNodes
|
||||
.map((node) => {
|
||||
return {
|
||||
label: node.label,
|
||||
id: node.id,
|
||||
};
|
||||
modeList.value.push(newItem);
|
||||
formData.mode.push(newItem.value);
|
||||
} else {
|
||||
formData.mode.push(exists.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
.filter((item1) => {
|
||||
return item1.label == item.userName;
|
||||
});
|
||||
const exists = modeList.value.find(
|
||||
(item1: any) => item1.label === item.userName
|
||||
);
|
||||
|
||||
if (!exists) {
|
||||
const newItem = {
|
||||
value: matchNodesData[0].id,
|
||||
label: item.userName,
|
||||
};
|
||||
modeList.value.push(newItem);
|
||||
formData.mode.push(newItem.value);
|
||||
} else {
|
||||
formData.mode.push(exists.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// mindMap.value = res.result;
|
||||
}
|
||||
|
|
@ -306,7 +303,7 @@ onMounted(() => {
|
|||
const jdItem = graphSl.getCellById(res.id);
|
||||
nowPzTbslId.value = res.id;
|
||||
|
||||
const oldSyncCount = jdItem.getData().syncCount;
|
||||
const oldSyncCount = jdItem?.getData().syncCount;
|
||||
pztbslFlag.value = true;
|
||||
if (oldSyncCount) {
|
||||
pztbslValue.value = oldSyncCount;
|
||||
|
|
@ -332,7 +329,41 @@ function paTbslMethod() {
|
|||
|
||||
const graphSl = graph.value?.getGraph();
|
||||
const jdItem = graphSl.getCellById(nowPzTbslId.value);
|
||||
jdItem.setData({ ...jdItem.getData(), syncCount:pztbslValue.value })
|
||||
|
||||
if (jdItem.data.syncCount) {
|
||||
jdItem.setData({ syncCount: pztbslValue.value });
|
||||
const outEdges = graphSl.getOutgoingEdges(jdItem);
|
||||
const children = outEdges
|
||||
.map((edge) => edge.getTargetNode())
|
||||
.filter((n): n is Node => !!n);
|
||||
|
||||
const fhtjNode = children.find((node) => {
|
||||
const d = node.getData();
|
||||
// 这里写你的判断条件
|
||||
return d?.tbslFlag;
|
||||
});
|
||||
if (fhtjNode) {
|
||||
fhtjNode.setLabel(pztbslValue.value);
|
||||
fhtjNode.setAttrs({
|
||||
label: {
|
||||
text: pztbslValue.value,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
jdItem.setData({ ...jdItem.getData(), syncCount: pztbslValue.value });
|
||||
let id = uuidv4();
|
||||
graph.value?.addChildNode(nowPzTbslId.value, {
|
||||
id,
|
||||
label: pztbslValue.value,
|
||||
level: "level4", // 单选节点层级为level4
|
||||
});
|
||||
let node = graphSl.getCellById(id);
|
||||
node.setData({
|
||||
...node.getData(),
|
||||
tbslFlag: true,
|
||||
});
|
||||
}
|
||||
pztbslFlag.value = false;
|
||||
pztbslValue.value = "";
|
||||
nowPzTbslId.value = null;
|
||||
|
|
@ -351,18 +382,18 @@ function getTargetUserName(taskId: any) {
|
|||
});
|
||||
}
|
||||
|
||||
// 根据源数据库id获取用户
|
||||
function getModelList(callback?: (data: any) => void) {
|
||||
getUser({ sourceId: formData.sourceId }, (res) => {
|
||||
modeList.value = res.result.map((item: any) => {
|
||||
return {
|
||||
value: uuidv4(),
|
||||
label: item,
|
||||
};
|
||||
});
|
||||
callback?.(res);
|
||||
});
|
||||
}
|
||||
// // 根据源数据库id获取用户
|
||||
// function getModelList(callback?: (data: any) => void) {
|
||||
// getUser({ sourceId: formData.sourceId }, (res) => {
|
||||
// modeList.value = res.result.map((item: any) => {
|
||||
// return {
|
||||
// value: uuidv4(),
|
||||
// label: item,
|
||||
// };
|
||||
// });
|
||||
// callback?.(res);
|
||||
// });
|
||||
// }
|
||||
|
||||
// 根据源数据库id以及用户名称获取所有表名称
|
||||
function getDataListById(name: any) {
|
||||
|
|
@ -581,12 +612,18 @@ function handleCancel() {
|
|||
width="20vw"
|
||||
class="config-dialog"
|
||||
>
|
||||
<el-input
|
||||
v-model="pztbslValue"
|
||||
style="width: 240px"
|
||||
type="number"
|
||||
placeholder="请配置同步数量"
|
||||
/>
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
"
|
||||
>
|
||||
<span style="color: #fff">同步数量:</span>
|
||||
<el-input v-model="pztbslValue" style="width: 240px" type="number" />
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<ElButton
|
||||
type="text"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user