feat: replace ASCII architecture diagram with drawio SVG in gen2D deck

This commit is contained in:
2026-05-30 22:10:23 +08:00
parent 19075592e5
commit 1a297e57a9
3 changed files with 258 additions and 25 deletions
+2 -25
View File
@@ -1,28 +1,5 @@
# 系统架构全景
<div class="text-sm mt-2">
```
┌─────────────────────────────────────────────────────┐
│ Frontend (React + Vite + TypeScript) │
│ 项目画廊 · 工作台 · 结果预览 · 风格编辑器 │
│ Zustand 状态管理 · react-router v7 │
└─────────────────────────┬───────────────────────────┘
│ HTTP / WebSocket
┌─────────────────────────▼───────────────────────────┐
│ Backend (Go + Gin + Eino) │
│ │
│ Handler: JWT 中间件 · 请求校验 · 错误处理 │
│ ↓ │
│ Service: Eino compose.Graph Pipeline │
│ PromptOptimizer → AssetGenerator │
│ → QualitySupervisor → FormatAdapter │
│ 项目管理 · 风格系统 · 用户认证 │
│ ↓ │
│ Data: GORM + SQLite · sync.Map 缓存 │
│ │
│ 外部: DeepSeek LLM · Stability AI · 七牛云 Kodo │
└──────────────────────────────────────────────────────┘
```
<div class="mt-2 flex justify-center">
<img src="/architecture.svg" class="w-full max-h-[500px] object-contain" />
</div>
+146
View File
@@ -0,0 +1,146 @@
<mxfile host="app.diagrams.net" modified="2026-05-30T00:00:00.000Z" agent="Claude" version="21.0.0">
<diagram id="architecture" name="系统架构全景">
<mxGraphModel dx="1200" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1200" pageHeight="800" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<!-- Frontend 外框 -->
<mxCell id="fe-box" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=8;shadow=1;" vertex="1" parent="1">
<mxGeometry x="100" y="40" width="1000" height="140" as="geometry" />
</mxCell>
<mxCell id="fe-title" value="&lt;b&gt;Frontend&lt;/b&gt; &lt;span style=&quot;color:#666&quot;&gt;React + Vite + TypeScript&lt;/span&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="420" y="50" width="360" height="30" as="geometry" />
</mxCell>
<mxCell id="fe-mod1" value="项目画廊" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="140" y="95" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="fe-mod2" value="工作台" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="290" y="95" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="fe-mod3" value="结果预览" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="440" y="95" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="fe-mod4" value="风格编辑器" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="590" y="95" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="fe-tech" value="Zustand 状态管理 · react-router v7" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=11;fontColor=#666666;" vertex="1" parent="1">
<mxGeometry x="750" y="100" width="310" height="30" as="geometry" />
</mxCell>
<!-- 连接线 -->
<mxCell id="conn" value="HTTP / WebSocket" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=12;fontColor=#666666;" vertex="1" parent="1">
<mxGeometry x="500" y="195" width="200" height="25" as="geometry" />
</mxCell>
<mxCell id="conn-arrow" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#6c8ebf;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="fe-box" target="be-box">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- Backend 外框 -->
<mxCell id="be-box" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;arcSize=8;shadow=1;" vertex="1" parent="1">
<mxGeometry x="100" y="230" width="1000" height="300" as="geometry" />
</mxCell>
<mxCell id="be-title" value="&lt;b&gt;Backend&lt;/b&gt; &lt;span style=&quot;color:#666&quot;&gt;Go + Gin + Eino&lt;/span&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="440" y="240" width="320" height="30" as="geometry" />
</mxCell>
<!-- Handler 层 -->
<mxCell id="handler-box" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;arcSize=10;" vertex="1" parent="1">
<mxGeometry x="130" y="280" width="940" height="50" as="geometry" />
</mxCell>
<mxCell id="handler-label" value="&lt;b&gt;Handler&lt;/b&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="140" y="287" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="handler-items" value="JWT 中间件 · 请求校验 · 错误处理" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=12;fontColor=#555;" vertex="1" parent="1">
<mxGeometry x="350" y="287" width="400" height="30" as="geometry" />
</mxCell>
<!-- 箭头 Handler → Service -->
<mxCell id="hs-arrow" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#9673a6;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="handler-box" target="service-box">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- Service 层 -->
<mxCell id="service-box" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;arcSize=10;" vertex="1" parent="1">
<mxGeometry x="130" y="345" width="940" height="100" as="geometry" />
</mxCell>
<mxCell id="service-label" value="&lt;b&gt;Service&lt;/b&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="140" y="350" width="70" height="25" as="geometry" />
</mxCell>
<!-- Eino Pipeline 流程 -->
<mxCell id="pipe1" value="Prompt&lt;br&gt;Optimizer" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="280" y="380" width="110" height="45" as="geometry" />
</mxCell>
<mxCell id="pipe2" value="Asset&lt;br&gt;Generator" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="430" y="380" width="110" height="45" as="geometry" />
</mxCell>
<mxCell id="pipe3" value="Quality&lt;br&gt;Supervisor" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="580" y="380" width="110" height="45" as="geometry" />
</mxCell>
<mxCell id="pipe4" value="Format&lt;br&gt;Adapter" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
<mxGeometry x="730" y="380" width="110" height="45" as="geometry" />
</mxCell>
<!-- Pipeline 箭头 -->
<mxCell id="p12" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#b85450;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="pipe1" target="pipe2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="p23" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#b85450;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="pipe2" target="pipe3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="p34" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#b85450;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="pipe3" target="pipe4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="pipe-label" value="Eino compose.Graph Pipeline" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=11;fontColor=#b85450;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="870" y="393" width="190" height="25" as="geometry" />
</mxCell>
<!-- 项目管理等 -->
<mxCell id="svc-extra" value="项目管理 · 风格系统 · 用户认证" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=11;fontColor=#555;" vertex="1" parent="1">
<mxGeometry x="140" y="385" width="130" height="30" as="geometry" />
</mxCell>
<!-- 箭头 Service → Data -->
<mxCell id="sd-arrow" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#d6b656;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="service-box" target="data-box">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- Data 层 -->
<mxCell id="data-box" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;arcSize=10;" vertex="1" parent="1">
<mxGeometry x="130" y="460" width="940" height="50" as="geometry" />
</mxCell>
<mxCell id="data-label" value="&lt;b&gt;Data&lt;/b&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="140" y="467" width="50" height="30" as="geometry" />
</mxCell>
<mxCell id="data-items" value="GORM + SQLite · sync.Map 缓存" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=12;fontColor=#555;" vertex="1" parent="1">
<mxGeometry x="400" y="467" width="400" height="30" as="geometry" />
</mxCell>
<!-- External Services -->
<mxCell id="ext-box" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;arcSize=8;shadow=1;dashed=1;" vertex="1" parent="1">
<mxGeometry x="100" y="560" width="1000" height="80" as="geometry" />
</mxCell>
<mxCell id="ext-title" value="&lt;b&gt;外部服务&lt;/b&gt;" style="text;html=1;align=left;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="120" y="565" width="80" height="25" as="geometry" />
</mxCell>
<mxCell id="ext1" value="DeepSeek LLM" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="200" y="595" width="160" height="35" as="geometry" />
</mxCell>
<mxCell id="ext2" value="Stability AI" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="460" y="595" width="160" height="35" as="geometry" />
</mxCell>
<mxCell id="ext3" value="七牛云 Kodo" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;" vertex="1" parent="1">
<mxGeometry x="720" y="595" width="160" height="35" as="geometry" />
</mxCell>
<!-- Backend → External 箭头 -->
<mxCell id="be-ext" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#999;dashed=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="be-box" target="ext-box">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+110
View File
@@ -0,0 +1,110 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 680" font-family="Microsoft YaHei, PingFang SC, Helvetica, Arial, sans-serif">
<defs>
<filter id="shadow" x="-2%" y="-2%" width="104%" height="104%">
<feDropShadow dx="2" dy="2" stdDeviation="3" flood-opacity="0.15"/>
</filter>
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#6c8ebf"/>
</marker>
<marker id="arrow-gray" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#999"/>
</marker>
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#b85450"/>
</marker>
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#9673a6"/>
</marker>
</defs>
<!-- Frontend 外框 -->
<rect x="30" y="20" width="940" height="130" rx="10" fill="#dae8fc" stroke="#6c8ebf" stroke-width="1.5" filter="url(#shadow)"/>
<text x="420" y="50" font-size="15" font-weight="bold" fill="#333">Frontend</text>
<text x="490" y="50" font-size="13" fill="#666">React + Vite + TypeScript</text>
<rect x="60" y="65" width="130" height="40" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1"/>
<text x="125" y="90" font-size="12" fill="#333" text-anchor="middle">项目画廊</text>
<rect x="210" y="65" width="130" height="40" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1"/>
<text x="275" y="90" font-size="12" fill="#333" text-anchor="middle">工作台</text>
<rect x="360" y="65" width="130" height="40" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1"/>
<text x="425" y="90" font-size="12" fill="#333" text-anchor="middle">结果预览</text>
<rect x="510" y="65" width="130" height="40" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1"/>
<text x="575" y="90" font-size="12" fill="#333" text-anchor="middle">风格编辑器</text>
<text x="790" y="90" font-size="11" fill="#666" text-anchor="middle">Zustand 状态管理 · react-router v7</text>
<!-- 连接线 Frontend → Backend -->
<text x="500" y="172" font-size="12" fill="#666" text-anchor="middle">HTTP / WebSocket</text>
<line x1="500" y1="155" x2="500" y2="195" stroke="#6c8ebf" stroke-width="2" marker-end="url(#arrow)"/>
<!-- Backend 外框 -->
<rect x="30" y="200" width="940" height="290" rx="10" fill="#d5e8d4" stroke="#82b366" stroke-width="1.5" filter="url(#shadow)"/>
<text x="420" y="230" font-size="15" font-weight="bold" fill="#333">Backend</text>
<text x="487" y="230" font-size="13" fill="#666">Go + Gin + Eino</text>
<!-- Handler 层 -->
<rect x="60" y="245" width="880" height="45" rx="8" fill="#e1d5e7" stroke="#9673a6" stroke-width="1"/>
<text x="80" y="272" font-size="12" font-weight="bold" fill="#333">Handler</text>
<text x="400" y="272" font-size="12" fill="#555" text-anchor="middle">JWT 中间件 · 请求校验 · 错误处理</text>
<!-- Handler → Service 箭头 -->
<line x1="500" y1="292" x2="500" y2="305" stroke="#9673a6" stroke-width="2" marker-end="url(#arrow-purple)"/>
<!-- Service 层 -->
<rect x="60" y="308" width="880" height="100" rx="8" fill="#fff2cc" stroke="#d6b656" stroke-width="1"/>
<text x="80" y="333" font-size="12" font-weight="bold" fill="#333">Service</text>
<!-- Eino Pipeline -->
<text x="80" y="380" font-size="11" fill="#b85450" font-weight="bold">Eino compose.Graph Pipeline</text>
<rect x="280" y="345" width="110" height="45" rx="6" fill="#f8cecc" stroke="#b85450" stroke-width="1"/>
<text x="335" y="363" font-size="11" fill="#333" text-anchor="middle">Prompt</text>
<text x="335" y="378" font-size="11" fill="#333" text-anchor="middle">Optimizer</text>
<rect x="420" y="345" width="110" height="45" rx="6" fill="#f8cecc" stroke="#b85450" stroke-width="1"/>
<text x="475" y="363" font-size="11" fill="#333" text-anchor="middle">Asset</text>
<text x="475" y="378" font-size="11" fill="#333" text-anchor="middle">Generator</text>
<rect x="560" y="345" width="110" height="45" rx="6" fill="#f8cecc" stroke="#b85450" stroke-width="1"/>
<text x="615" y="363" font-size="11" fill="#333" text-anchor="middle">Quality</text>
<text x="615" y="378" font-size="11" fill="#333" text-anchor="middle">Supervisor</text>
<rect x="700" y="345" width="110" height="45" rx="6" fill="#f8cecc" stroke="#b85450" stroke-width="1"/>
<text x="755" y="363" font-size="11" fill="#333" text-anchor="middle">Format</text>
<text x="755" y="378" font-size="11" fill="#333" text-anchor="middle">Adapter</text>
<!-- Pipeline 箭头 -->
<line x1="392" y1="367" x2="418" y2="367" stroke="#b85450" stroke-width="2" marker-end="url(#arrow-red)"/>
<line x1="532" y1="367" x2="558" y2="367" stroke="#b85450" stroke-width="2" marker-end="url(#arrow-red)"/>
<line x1="672" y1="367" x2="698" y2="367" stroke="#b85450" stroke-width="2" marker-end="url(#arrow-red)"/>
<!-- 项目管理等 -->
<text x="120" y="420" font-size="11" fill="#555">项目管理 · 风格系统 · 用户认证</text>
<!-- Service → Data 箭头 -->
<line x1="500" y1="410" x2="500" y2="425" stroke="#d6b656" stroke-width="2" marker-end="url(#arrow-purple)"/>
<!-- Data 层 -->
<rect x="60" y="428" width="880" height="45" rx="8" fill="#e1d5e7" stroke="#9673a6" stroke-width="1"/>
<text x="80" y="455" font-size="12" font-weight="bold" fill="#333">Data</text>
<text x="400" y="455" font-size="12" fill="#555" text-anchor="middle">GORM + SQLite · sync.Map 缓存</text>
<!-- Backend → External 箭头 -->
<line x1="500" y1="492" x2="500" y2="520" stroke="#999" stroke-width="2" stroke-dasharray="6,3" marker-end="url(#arrow-gray)"/>
<!-- External Services -->
<rect x="30" y="525" width="940" height="80" rx="10" fill="#f5f5f5" stroke="#999" stroke-width="1" stroke-dasharray="6,3" filter="url(#shadow)"/>
<text x="80" y="550" font-size="12" font-weight="bold" fill="#333">外部服务</text>
<rect x="120" y="560" width="180" height="35" rx="6" fill="#f5f5f5" stroke="#999" stroke-width="1"/>
<text x="210" y="582" font-size="12" fill="#333" text-anchor="middle">DeepSeek LLM</text>
<rect x="410" y="560" width="180" height="35" rx="6" fill="#f5f5f5" stroke="#999" stroke-width="1"/>
<text x="500" y="582" font-size="12" fill="#333" text-anchor="middle">Stability AI</text>
<rect x="700" y="560" width="180" height="35" rx="6" fill="#f5f5f5" stroke="#999" stroke-width="1"/>
<text x="790" y="582" font-size="12" fill="#333" text-anchor="middle">七牛云 Kodo</text>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB