Logo
热心市民王先生

技术架构与创新点

技术架构 创新点 系统设计

系统架构、核心组件、数据流与创新技术点深度分析

系统架构概览

整体架构图

┌─────────────────────────────────────────────────────────────────┐
│                        用户自然语言输入                           │
│         "创建展示 AG-UI 协议事件流的 Excalidraw 图表"              │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                    Claude Code + SKILL.md                        │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ 设计方法论引擎(24KB 核心指令)                              │   │
│  │ - 深度评估(简单 vs 综合)                                   │   │
│  │ - 研究强制要求(查找真实规范)                               │   │
│  │ - 视觉模式映射(扇出、收敛、时间线等)                        │   │
│  │ - 分区块构建策略                                            │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                   参考文件层 (references/)                       │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐            │
│  │color-palette │ │element-      │ │json-schema   │            │
│  │.md           │ │templates.md  │ │.md           │            │
│  │品牌颜色配置   │ │元素 JSON 模板  │ │Excalidraw格式 │            │
│  └──────────────┘ └──────────────┘ └──────────────┘            │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                  .excalidraw JSON 文件生成                       │
│  { type: "excalidraw", version: 2, elements: [...], ... }       │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│              渲染验证管道 (render_excalidraw.py)                 │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐         │
│  │ Playwright  │ →  │  headless   │ →  │  PNG 输出   │         │
│  │ Chromium    │    │  Chromium   │    │  视觉检查   │         │
│  └─────────────┘    └─────────────┘    └─────────────┘         │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                    迭代修复循环                                   │
│         JSON → 渲染 → 检查 → 修复 → 重新渲染 → ...               │
└─────────────────────────────────────────────────────────────────┘

技术栈分解

层级技术版本用途
Skill 定义Markdown + YAML frontmatter-Claude Code 技能注册
依赖管理uv + pyproject.tomlPython 3.11+轻量级 Python 包管理
渲染引擎Playwright≥1.40.0无头浏览器自动化
浏览器Chromium-SVG 渲染
Excalidraw 库@excalidraw/excalidrawCDN (esm.sh)SVG 导出功能
集成目标.claude/skills/-Claude Code、OpenCode

核心组件详解

1. SKILL.md(技能定义文件 - 24KB)

这是项目的核心大脑,包含完整的设计方法论和执行工作流。

结构分析:

# Excalidraw Diagram Creator

## Customization          → 指向 color-palette.md 为唯一品牌配置点
## Core Philosophy        → "Diagrams that argue, not display"
## Depth Assessment       → 简单/综合图表决策框架
## Research Mandate       → 技术图表必须先研究真实规范
## Evidence Artifacts     → 证据工件类型表(代码片段、JSON 示例等)
## Multi-Zoom Architecture→ 三层次设计方法论
## Design Process         → 6 步工作流(理解→映射→草图→JSON→验证)
## Large Diagram Strategy → 分区块 JSON 构建策略
## Visual Pattern Library → 扇出、收敛、时间线等模式库
## Shape Meaning          → 语义形状映射
## Color as Meaning       → 颜色语义系统
## Modern Aesthetics      → 粗糙度、线宽、透明度指南
## Layout Principles      → 层级、留白、连接
## JSON Structure         → Excalidraw 格式要求
## Render & Validate      → 强制渲染验证循环
## Quality Checklist      → 27 点验证清单

关键设计决策:

设计选择原因影响
Markdown 而非 JSON/YAML可读性高,便于 AI 理解文件大小但语义清晰
24KB 详细指令覆盖所有边缘情况和设计原则确保输出质量一致性
强制渲染验证JSON 无法直观判断视觉缺陷防止生成不可用的图表
单一品牌配置点降低定制门槛非技术用户也能改颜色

2. 参考文件层

color-palette.md(品牌颜色配置)

三套颜色系统:

# 形状颜色(语义编码)
Semantic Purpose → Fill/Stroke Pair:
  Start/Trigger:    fill: #fed7aa, stroke: #c2410c
  End/Success:      fill: #a7f3d0, stroke: #047857
  Decision:         fill: #fef3c7, stroke: #b45309
  AI/LLM:           fill: #ddd6fe, stroke: #6d28d9
  Error:            fill: #fecaca, stroke: #b91c1c
  Primary/Neutral:  fill: #3b82f6, stroke: #1e3a5f

# 文本层级颜色(替代容器)
Text Hierarchy:
  Title:       #1e40af  (章节标题)
  Subtitle:    #3b82f6  (副标题)
  Body/Detail: #64748b  (描述文本)

# 证据工件颜色(代码片段主题)
Evidence Artifacts:
  Code snippet background:   #1e293b
  JSON/data text:            #22c55e (green)

创新点: 颜色不是装饰,而是信息编码。每个语义目的都有固定的填充/描边对,确保图表一致性。

element-templates.md(元素模板库)

提供 6 种核心 Excalidraw 元素的复制粘贴模板:

  1. 自由浮动文本(无容器)
  2. 结构线(非箭头,用于时间线/树结构)
  3. 标记点(10-20px 椭圆)
  4. 矩形(带圆角 roundness: {type: 3}
  5. 容器内文本(带 containerId
  6. 箭头(带 startBinding/endBindingpoints 数组)

每个模板包含所有必需的 Excalidraw 属性(seedversionversionNonce 等),AI 只需替换坐标和颜色。

json-schema.md(格式参考)

Excalidraw JSON 格式的速查手册,包含:

  • 元素类型定义(rectangle、ellipse、diamond、arrow、text、line、frame)
  • 通用属性(id、x/y、width/height、颜色、填充/描边样式)
  • 文本专用属性(fontSize、fontFamily、textAlign、containerId)
  • 箭头专用属性(points 数组、binding 格式、箭头类型)

3. 渲染管道(render_excalidraw.py)

6.6KB Python 脚本,实现 JSON → PNG 的完整渲染流程。

核心函数:

函数行数功能
validate_excalidraw(data)~15验证 JSON 结构(type=excalidraw、elements 数组非空)
compute_bounding_box(elements)~30计算所有元素的包围盒(处理箭头的 points 相对坐标)
render(...)~80主渲染逻辑:启动 Playwright → 加载模板 → 调用 renderDiagram → 截图
main()~20CLI 入口(argparse 处理—output、—scale、—width 参数)

渲染流程详解:

# 1. 读取并验证 JSON
raw = excalidraw_path.read_text()
data = json.loads(raw)
errors = validate_excalidraw(data)  # 提前失败,避免无效渲染

# 2. 计算视口大小
min_x, min_y, max_x, max_y = compute_bounding_box(elements)
padding = 80
vp_width = min(max_x - min_x + padding * 2, 1920)  #  capped at 1920
vp_height = max(max_y - min_y + padding * 2, 600)

# 3. 启动无头 Chromium
with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page(
        viewport={"width": vp_width, "height": vp_height},
        device_scale_factor=scale  # 默认 2x 分辨率
    )
    
    # 4. 加载 HTML 模板(包含 Excalidraw 库从 esm.sh CDN)
    page.goto(template_url)
    page.wait_for_function("window.__moduleReady === true", timeout=30000)
    
    # 5. 注入 JSON 并渲染
    result = page.evaluate(f"window.renderDiagram({json_str})")
    page.wait_for_function("window.__renderComplete === true", timeout=15000)
    
    # 6. 截图 SVG 元素
    svg_el = page.query_selector("#root svg")
    svg_el.screenshot(path=str(output_path))

创新设计:

  1. 提前验证 - 在启动浏览器前验证 JSON 结构,避免浪费资源
  2. 动态视口计算 - 根据内容自动调整大小,而非固定尺寸
  3. 信号驱动等待 - 使用 __moduleReady__renderComplete 信号,而非固定延迟
  4. SVG 直接截图 - 截图 SVG 元素而非整个页面,确保输出纯净

4. HTML 模板(render_template.html)

1.7KB 单文件,提供浏览器渲染环境。

关键实现:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Excalidraw Render</title>
  <style>#root { width: 100%; height: 100vh; }</style>
</head>
<body>
  <div id="root"></div>
  <script type="module">
    // 从 CDN 加载 Excalidraw 库(bundle 版本包含所有导出函数)
    import { exportToSvg } from "https://esm.sh/@excalidraw/excalidraw?bundle";
    
    // 暴露全局函数供 Python 调用
    window.renderDiagram = async function(jsonData) {
      const svg = await exportToSvg({
        elements: jsonData.elements,
        appState: { 
          viewBackgroundColor: "#ffffff",
          exportBackground: true,
          gridSize: 20
        },
        files: jsonData.files,
      });
      document.getElementById("root").appendChild(svg);
      window.__renderComplete = true;  // 信号通知完成
    };
    
    window.__moduleReady = true;  // 信号通知模块加载完成
  </script>
</body>
</html>

设计亮点:

  • 零构建步骤 - 直接从 esm.sh CDN 加载,无需 npm install
  • 全局函数暴露 - window.renderDiagram 供 Playwright 调用
  • 信号机制 - __moduleReady__renderComplete 实现异步同步

数据流分析

端到端流程

1. 用户输入

   "创建展示微服务架构的图表"

2. AI 理解(SKILL.md 指导)

   - 深度评估:这是综合技术图表 → 需要证据工件
   - 研究 mandate:查找真实微服务组件名、API 格式
   - 视觉模式:扇出(API Gateway→Services)、收敛(Services→DB)

3. 颜色选择(color-palette.md)

   - API Gateway: Primary (fill: #3b82f6, stroke: #1e3a5f)
   - Services: Secondary (fill: #60a5fa)
   - Database: End/Success (fill: #a7f3d0, stroke: #047857)

4. 元素生成(element-templates.md)

   - 复制矩形模板,替换坐标、颜色、文本
   - 复制箭头模板,设置 startBinding/endBinding
   - 添加自由浮动文本(标题、描述)

5. JSON 构建(分区块策略)

   第一遍:基础结构 + Section 1(入口点)
   第二遍:Section 2(决策/路由)
   第三遍:Section 3(主内容区)
   ...

6. 渲染验证

   render_excalidraw.py diagram.excalidraw → diagram.png

   AI 读取 PNG 检查:
   - 文本是否溢出容器?
   - 箭头是否交叉元素?
   - 间距是否均匀?

   如有问题 → 修复 JSON → 重新渲染

7. 输出

   - diagram.excalidraw(可编辑)
   - diagram.png(预览)

JSON 结构详解

{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [
    {
      "id": "trigger_rect",           // 描述性 ID(非随机)
      "type": "rectangle",
      "x": 100, "y": 100,
      "width": 180, "height": 90,
      "strokeColor": "#1e3a5f",       // 来自 color-palette.md
      "backgroundColor": "#3b82f6",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 0,                 // 0=现代简洁,1=手绘风格
      "opacity": 100,                 // 始终 100(用颜色/大小创建层级)
      "angle": 0,
      "seed": 100001,                 // 按区命名空间(100xxx, 200xxx)
      "version": 1,
      "versionNonce": 67890,
      "isDeleted": false,
      "groupIds": [],
      "boundElements": [              // 绑定到此元素的子元素(如文本)
        {"id": "trigger_text", "type": "text"}
      ],
      "link": null,
      "locked": false,
      "roundness": {"type": 3}        // 圆角
    },
    {
      "id": "trigger_text",
      "type": "text",
      "x": 130, "y": 132,
      "width": 120, "height": 25,
      "text": "API Gateway",
      "originalText": "API Gateway",
      "fontSize": 16,
      "fontFamily": 3,                // 3=等宽字体
      "textAlign": "center",
      "verticalAlign": "middle",
      "strokeColor": "#1e3a5f",
      "backgroundColor": "transparent",
      "containerId": "trigger_rect",  // 容器绑定
      "lineHeight": 1.25
    },
    {
      "id": "arrow_to_service",
      "type": "arrow",
      "x": 282, "y": 145,
      "points": [[0, 0], [118, 0]],   // 相对坐标路径
      "startBinding": {
        "elementId": "trigger_rect",
        "focus": 0,
        "gap": 2
      },
      "endBinding": {
        "elementId": "service_rect",
        "focus": 0,
        "gap": 2
      },
      "startArrowhead": null,
      "endArrowhead": "arrow"
    }
  ],
  "appState": {
    "viewBackgroundColor": "#ffffff",
    "gridSize": 20
  },
  "files": {}
}

创新技术点

1. 分区块 JSON 构建策略

问题: LLM 单次输出有~32K token 限制,综合图表 JSON 轻松超限。

解决方案:

第一遍:创建基础文件包装器 + Section 1 元素
第二遍:追加 Section 2 元素
第三遍:追加 Section 3 元素
...
最终遍:审查跨区绑定、更新 boundElements

关键技巧:

  • 使用描述性字符串 ID("trigger_rect"而非"elem_1")便于跨区引用
  • 按区命名空间 seed 值(Section 1: 100xxx, Section 2: 200xxx)避免碰撞
  • 每追加新区时,同步更新前区的 cross-section binding

优势:

  • 规避 token 限制
  • 每区可专注设计,质量更高
  • 便于调试(单区问题不影响全局)

2. 渲染 - 视图 - 修复循环

核心理念: JSON 无法直观判断视觉缺陷,必须渲染后检查。

循环流程:

生成 JSON → render_excalidraw.py → 读取 PNG → 检查缺陷 → 修复 JSON → 重新渲染 → ...

检查清单:

  • 文本是否被容器裁剪?
  • 元素是否重叠?
  • 箭头是否穿过元素而非绕过?
  • 标签是否模糊(未明确锚定到描述对象)?
  • 间距是否均匀?
  • 整体构图是否平衡?

典型迭代次数: 2-4 次

优势:

  • 防止交付有视觉缺陷的图表
  • AI 可从渲染结果学习改进
  • 用户可看到中间结果并提供反馈

3. 语义化颜色系统

传统做法: 随意选择颜色,或基于美学。

本项目做法: 颜色编码语义,每个目的有固定填充/描边对。

Start/Trigger → fill: #fed7aa, stroke: #c2410c(暖色=起点)
End/Success   → fill: #a7f3d0, stroke: #047857(绿色=完成)
Decision      → fill: #fef3c7, stroke: #b45309(黄色=注意)
AI/LLM        → fill: #ddd6fe, stroke: #6d28d9(紫色=智能)
Error         → fill: #fecaca, stroke: #b91c1c(红色=错误)

优势:

  • 跨图表一致性
  • 降低认知负荷(颜色=含义)
  • 非技术用户只需改 color-palette.md 即可定制品牌

4. <30% 容器化原则

观察: 传统图表过度使用容器(每个文本都在框内)。

本项目原则:

  • 默认使用自由浮动文本
  • 仅当以下情况添加容器:
    • 是章节焦点
    • 需要视觉分组
    • 箭头需要连接
    • 形状本身承载语义(决策菱形等)

实现技巧:

  • 用字号/颜色创建层级(标题 28px #1e40af,副标题 20px #3b82f6,正文 16px #64748b)
  • 用结构线(line 类型)替代框(时间线、树结构)
  • 用小标记点(10-20px 椭圆)替代大形状

目标: <30% 的文本元素在容器内


本章小结

架构亮点:

  1. 分层设计 - Skill 定义层、参考文件层、渲染管道层职责清晰
  2. 提前验证 - JSON 结构验证在渲染前完成,避免资源浪费
  3. 信号驱动 - 使用 __moduleReady/__renderComplete 实现异步同步
  4. 零构建步骤 - CDN 加载 Excalidraw 库,无需 npm install

创新点总结:

  • 分区块 JSON 构建(规避 LLM token 限制)
  • 渲染验证循环(强制视觉质量)
  • 语义化颜色系统(颜色=信息)
  • <30% 容器化原则(自由浮动文本优先)

下一章将深入分析实现细节和设计模式。