[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:zh:database-foreign-key-diagram":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# 固定数据库表卡片中的列级外键连线\n\n## 这个示例构建了什么\n\n这个示例在一个全高的 relation-graph 画布中构建了一个固定布局的数据库结构查看器。界面上会显示六张橙色表卡片，每张卡片都列出字段和数据类型，紫色或蓝色的弧形关系线会连接到具体的字段行，而不仅仅是连接整个节点。\n\n用户可以查看预设好的 schema，拖动或最小化浮动辅助窗口，打开设置面板来修改滚轮和画布拖拽行为，并将当前图谱导出为图片。这里的主要技术点是列级连线：自定义表格标记不只是装饰，它还为 relation-graph 提供了外键连线所需的精确 DOM 目标。\n\n## 数据是如何组织的\n\n数据集在 `initializeGraph()` 中以内联方式声明为三个数组：`tables`、`tableCols` 和 `columnRelations`。`tables` 定义了表 id、可见标签，以及手工编写的 `x` 和 `y` 坐标。`tableCols` 保存每张表的字段列表，`columnRelations` 则描述源列、目标列和关系类型。\n\n在调用 `setJsonData(...)` 之前，这个示例会先执行一次小型预处理。它先把 `tables` 映射为包含 `data.columns` 的图节点，再把 `columnRelations` 映射为 `fakeLines`，其中 `from` 和 `to` 会指向生成的端点 id，例如 `col-name-SYS_USER-dept_id`。普通的 `lines` 会保持为空，因为这些关系是附着在每个节点槽位内部渲染出的 DOM 元素上，而不是附着在默认节点锚点上。\n\n在真实应用中，同样的数据结构可以来自数据库元数据、ORM 模型定义、API schema 注册表、字段映射目录，或数据血缘记录。固定坐标既可以继续由人工维护，用于生成经过整理的参考图，也可以在最终载荷传入 relation-graph 之前由其他地方生成。\n\n## relation-graph 是如何使用的\n\n`index.tsx` 用 `RGProvider` 包裹这个示例，`MyGraph.tsx` 则通过 `RGHooks.useGraphInstance()` 在挂载后加载图谱。图谱配置让 relation-graph 保持 `layoutName: 'fixed'`，设置 `defaultJunctionPoint: RGJunctionPoint.border`，移除默认节点边框，设置橙色默认节点颜色，并定义一个自定义三角形连线标记。JSON 加载完成后，示例会调用 `moveToCenter()` 和 `zoomToFit()`，让预设 schema 立即铺满视口。\n\n主要定制发生在 `RGSlotOnNode` 中。每个节点都会变成一个 300 像素的表卡片，包含一个表头和一个字段 HTML 表格。在每个列名单元格内部，`RGConnectTarget` 会注册一个由表 id 和列名推导出的 `targetId`。随后 `fakeLines` 载荷就会连接到这些 id，这正是让外键曲线准确落到对应字段行上的关键。\n\n这个示例并没有实现编辑、编排或运行时图谱变更。节点和连线点击处理器虽然存在，但只会记录被点击的对象。额外的实用行为来自共享的 `DraggableWindow` 和 `CanvasSettingsPanel`：设置面板通过 `RGHooks.useGraphStore()` 读取当前拖拽和滚轮模式，再通过 `graphInstance.setOptions(...)` 更新这些配置，并使用 `prepareForImageGeneration()` 与 `restoreAfterImageGeneration()` 将图谱导出为图片。本地样式表则补充了平铺背景、选中态强调效果，以及橙色表格样式。\n\n## 关键交互\n\n- 图谱会在挂载时初始化，然后重新居中并适配预设 schema，使查看器打开时就能看到完整图示。\n- 浮动辅助窗口可以通过标题栏拖动，也可以最小化，这样说明和工具就能移动，而不会固定压在画布某个区域上。\n- 打开设置面板后，可以实时切换滚轮模式和拖拽模式，每次选择都会立即更新已挂载的 relation-graph 实例。\n- 下载操作会先为截图准备图谱，把画布 DOM 渲染成图片 blob，下载之后再恢复图谱状态。\n- 点击节点或关系线只会记录相关对象，因此这个示例仍然是一个只读查看视图，而不是 schema 编辑器。\n\n## 关键代码片段\n\n这段代码展示了如何把表元数据转换为固定位置的图节点，并将每张表的列数据附加到 `node.data` 上：\n\n```tsx\nconst graphNodes = tables.map(table => {\n    const { tableName, tableComents, x, y } = table;\n    return {\n        id: tableName,\n        text: tableComents,\n        x,\n        y,\n        nodeShape: RGNodeShape.rect,\n        nodeShape: RGNodeShape.rect,\n        data: {\n            columns: tableCols.filter(col => col.tableName === table.tableName)\n        }\n    };\n});\n```\n\n这段代码展示了关键的预处理步骤：每个外键定义都会变成一条弧形 `fakeLine`，其端点是列级目标 id：\n\n```tsx\nconst myFakeLines = columnRelations.map((relation, index) => {\n    return {\n        id: `rel-line-${index}`,\n        from: `col-name-${relation.sourceTableName}-${relation.sourceColumnName}`,\n        to: `col-name-${relation.targetTableName}-${relation.targetColumnName}`,\n        color: relation.type === 'ONE_TO_ONE' ? 'rgba(29,169,245,0.76)' : 'rgba(159,23,227,0.65)',\n        text: '',\n        fromJunctionPoint: RGJunctionPoint.left,\n        toJunctionPoint: RGJunctionPoint.lr,\n        lineShape: RGLineShape.StandardCurve,\n        lineWidth: 3\n    };\n});\n```\n\n这段代码展示了已加载的载荷会刻意让普通 `lines` 保持为空，转而依赖 `fakeLines`：\n\n```tsx\nconst myJsonData: RGJsonData = {\n    nodes: graphNodes,\n    lines: [],\n    fakeLines: myFakeLines\n};\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\n这段代码展示了固定布局的图谱配置，以及 schema 查看器使用的自定义连线标记：\n\n```tsx\nconst graphOptions: RGOptions = {\n    debug: false,\n    defaultJunctionPoint: RGJunctionPoint.border,\n    defaultNodeColor: '#f39930',\n    defaultNodeBorderWidth: 0,\n    defaultLineMarker: {\n        markerWidth: 20,\n        markerHeight: 20,\n        refX: 3,\n        refY: 3,\n        viewBox: '0 0 6 6',\n        data: \"M 0 0, V 6, L 4 3, Z\"\n    },\n    layout: {\n        layoutName: 'fixed'\n    }\n};\n```\n\n这段代码展示了自定义节点槽位如何渲染表格行，并把每个列名注册为连线端点：\n\n```tsx\n\u003CRGConnectTarget\n    targetId={`col-name-${node.id}-${column.columnName}`}\n    junctionPoint={RGJunctionPoint.lr}\n>\n    \u003Cdiv className=\"w-fit px-2\">{column.columnName}\u003C/div>\n\u003C/RGConnectTarget>\n```\n\n这段代码展示了运行时设置模式：共享面板会读取当前图谱 store 中的值，并通过 `setOptions(...)` 推送更新：\n\n```tsx\nconst { options } = RGHooks.useGraphStore();\nconst dragMode = options.dragEventAction;\nconst wheelMode = options.wheelEventAction;\n\n\u003CSettingRow\n    label=\"Wheel Event:\"\n    options={[\n        { label: 'Scroll', value: 'scroll' },\n        { label: 'Zoom', value: 'zoom' },\n        { label: 'None', value: 'none' },\n    ]}\n    value={wheelMode}\n    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}\n/>\n```\n\n这段代码展示了导出流程：先让 relation-graph 为截图做好准备，再渲染画布 DOM，最后恢复图谱状态：\n\n```tsx\nconst canvasDom = await graphInstance.prepareForImageGeneration();\nlet graphBackgroundColor = graphInstance.getOptions().backgroundColor;\nif (!graphBackgroundColor || graphBackgroundColor === 'transparent') {\n    graphBackgroundColor = '#ffffff';\n}\nconst imageBlob = await domToImageByModernScreenshot(canvasDom, {\n    backgroundColor: graphBackgroundColor\n});\nawait graphInstance.restoreAfterImageGeneration();\n```\n\n## 这个示例有什么独特之处\n\n结合对比数据后，可以更清楚地看到差异。与 `drag-and-wheel-event` 和 `layout-center` 相比，这里的浮动设置面板只是次要部分。那些相邻示例主要关注画布行为调节或运行时样式调整，而这个示例则借助同样的共享工具外壳来讲解一个更专门的主题：把 schema 关系连到自定义节点内容中的精确行。\n\n与 `node` 和 `use-d3-layout` 相比，这里的槽位 HTML 是结构性的，而不是纯视觉性的。自定义标记存在的目的，是让 `RGConnectTarget` 能暴露每一列的端点，并让 `fakeLines` 落到这些端点上，而不是主要为了展示皮肤样式或在外部重新布局过程中继续生效。与 `adv-dynamic-data` 相比，这里的复杂度集中在一个预处理步骤中，即把表元数据转换为一个固定快照；挂载后不会再进行分阶段增长。\n\n在已整理的分析中，那个少见的组合才是最重要的结论：`layoutName = 'fixed'`、重复出现的表卡片节点槽位、列级 DOM 端点、带颜色区分的弧形 `fakeLines`、平铺的技术风格画布、图例，以及共享的导出或画布设置工具共同组成了一个只读查看器。这个组合使得该示例非常适合作为 schema 风格图示的起点，特别是在关系必须连接到嵌入字段、而不是整个节点的场景中。\n\n## 这种模式还适用于哪里\n\n这种模式很适合用于数据库文档页面、实体关系查看器，以及需要人工整理固定排布而不是自动布局的内部 schema 浏览器。同样的预处理方式也可以适配 API 载荷对比、ETL 字段映射、权限到资源矩阵，或数据血缘视图，这些场景都需要让连线终止在较大卡片内部的命名行上。\n\n当产品需要的是技术参考界面而不是编辑器时，这种模式也很有用。团队可以保留这种行级端点技术，替换成不同的元数据，同时继续使用浮动导出或画布设置工具，用于分析师工作台、架构评审，或支持文档快照。\n",false,500,1782615397721]