Files
nanocode/skills/hand-drawn-diagram/examples/fumamxCRM_architecture.html
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

196 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>fumamxCRM - System Architecture</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'JetBrains Mono', monospace;
background: #020617;
min-height: 100vh;
padding: 2rem;
color: white;
}
.container { max-width: 1200px; margin: 0 auto; }
.header { margin-bottom: 2rem; }
.header-row { display: flex; align-items: center; gap: 1rem; margin-bottom: 0.5rem; }
.pulse-dot {
width: 12px; height: 12px; background: #22d3ee; border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
h1 { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.025em; }
.subtitle { color: #94a3b8; font-size: 0.875rem; margin-left: 1.75rem; }
.diagram-container {
background: rgba(15, 23, 42, 0.5); border-radius: 1rem;
border: 1px solid #1e293b; padding: 1.5rem; overflow-x: auto;
}
svg { width: 100%; min-width: 900px; display: block; }
.cards {
display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem; margin-top: 2rem;
}
.card {
background: rgba(15, 23, 42, 0.5); border-radius: 0.75rem;
border: 1px solid #1e293b; padding: 1.25rem;
}
.card-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; }
.card-dot { width: 8px; height: 8px; border-radius: 50%; }
.card h3 { font-size: 0.875rem; font-weight: 600; color: #e2e8f0; }
.card ul { list-style: none; font-size: 0.75rem; color: #94a3b8; line-height: 1.8; }
.card li::before { content: "• "; color: #64748b; }
.footer {
margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #1e293b;
font-size: 0.75rem; color: #64748b; text-align: center;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="header-row">
<div class="pulse-dot"></div>
<h1>fumamxCRM - System Architecture</h1>
</div>
<div class="subtitle">系统架构图 · Hand-Drawn SVG</div>
</div>
<div class="diagram-container">
<svg viewBox="0 0 1100 700" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="#1e293b" stroke-width="0.5"/>
</pattern>
<filter id="dropShadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-opacity="0.3"/>
</filter>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#64748b"/>
</marker>
<marker id="arrowhead-cyan" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#22d3ee"/>
</marker>
<marker id="arrowhead-green" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#34d399"/>
</marker>
<marker id="arrowhead-rose" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#fb7185"/>
</marker>
<marker id="arrowhead-amber" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#fbbf24"/>
</marker>
<marker id="arrowhead-purple" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#a78bfa"/>
</marker>
</defs>
<rect width="1100" height="700" fill="url(#grid)"/>
<rect x="80" y="160" width="310" height="210" rx="10" fill="rgba(15, 23, 42, 0.3)" stroke="#34d399" stroke-width="1.5" stroke-dasharray="5,3"/>
<rect x="95" y="152" width="130" height="16" fill="#0f172a"/>
<text x="160" y="163" fill="#34d399" font-size="9" font-weight="500" text-anchor="middle">FastAPI Backend</text>
<rect x="430" y="160" width="160" height="210" rx="10" fill="rgba(15, 23, 42, 0.3)" stroke="#fb7185" stroke-width="1.5" stroke-dasharray="5,3"/>
<rect x="445" y="152" width="98" height="16" fill="#0f172a"/>
<text x="494" y="163" fill="#fb7185" font-size="9" font-weight="500" text-anchor="middle">Auth Module</text>
<rect x="100" y="60" width="130" height="49" rx="6" fill="#0f172a" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<rect x="100" y="60" width="130" height="49" rx="6" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<text x="165" y="78" fill="white" font-size="11" font-weight="600" text-anchor="middle">React Frontend</text>
<text x="165" y="92" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Port 8888</text>
<text x="165" y="106" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">UI / State</text>
<rect x="100" y="180" width="130" height="49" rx="6" fill="#0f172a" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<rect x="100" y="180" width="130" height="49" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="165" y="198" fill="white" font-size="11" font-weight="600" text-anchor="middle">FastAPI Core</text>
<text x="165" y="212" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Port 8889</text>
<text x="165" y="226" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">REST API</text>
<rect x="450" y="180" width="120" height="49" rx="6" fill="#0f172a" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<rect x="450" y="180" width="120" height="49" rx="6" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<text x="510" y="198" fill="white" font-size="11" font-weight="600" text-anchor="middle">Auth Service</text>
<text x="510" y="212" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">Login / Register</text>
<rect x="100" y="300" width="110" height="49" rx="6" fill="#0f172a" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<rect x="100" y="300" width="110" height="49" rx="6" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<text x="155" y="318" fill="white" font-size="11" font-weight="600" text-anchor="middle">JWT Auth</text>
<text x="155" y="332" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">Token</text>
<rect x="260" y="300" width="110" height="49" rx="6" fill="#0f172a" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<rect x="260" y="300" width="110" height="49" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="315" y="318" fill="white" font-size="11" font-weight="600" text-anchor="middle">Pydantic</text>
<text x="315" y="332" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">Validation</text>
<rect x="450" y="300" width="120" height="49" rx="6" fill="#0f172a" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<rect x="450" y="300" width="120" height="49" rx="6" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<text x="510" y="318" fill="white" font-size="11" font-weight="600" text-anchor="middle">fumamxAuth</text>
<text x="510" y="332" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">External OAuth</text>
<rect x="280" y="420" width="110" height="50" rx="6" fill="#0f172a" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<rect x="280" y="420" width="110" height="50" rx="6" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<text x="335" y="438" fill="white" font-size="11" font-weight="600" text-anchor="middle">SQLite</text>
<text x="335" y="452" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Main DB</text>
<rect x="100" y="420" width="100" height="50" rx="6" fill="#0f172a" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<rect x="100" y="420" width="100" height="50" rx="6" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<text x="150" y="438" fill="white" font-size="11" font-weight="600" text-anchor="middle">Redis</text>
<text x="150" y="452" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Cache</text>
<line x1="165" y1="120" x2="165" y2="180" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<line x1="165" y1="240" x2="315" y2="300" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<line x1="165" y1="240" x2="155" y2="300" stroke="#fb7185" stroke-width="1.5" stroke-dasharray="5,3" marker-end="url(#arrowhead-rose)"/>
<rect x="139" y="262" width="42" height="14" fill="#0f172a" rx="2"/>
<text x="160" y="273" fill="#fb7185" font-size="8" font-weight="normal" text-anchor="middle">verify</text>
<line x1="165" y1="240" x2="335" y2="420" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<line x1="510" y1="235" x2="510" y2="300" stroke="#fb7185" stroke-width="1.5" stroke-dasharray="5,3" marker-end="url(#arrowhead-rose)"/>
<rect x="493" y="259" width="35" height="14" fill="#0f172a" rx="2"/>
<text x="510" y="270" fill="#fb7185" font-size="8" font-weight="normal" text-anchor="middle">OAuth</text>
<line x1="510" y1="235" x2="335" y2="420" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<line x1="450" y1="327" x2="210" y2="327" stroke="#fb7185" stroke-width="1.5" stroke-dasharray="5,3" marker-end="url(#arrowhead-rose)"/>
<rect x="313" y="319" width="35" height="14" fill="#0f172a" rx="2"/>
<text x="330" y="330" fill="#fb7185" font-size="8" font-weight="normal" text-anchor="middle">token</text>
<line x1="155" y1="355" x2="150" y2="420" stroke="#fb7185" stroke-width="1.5" stroke-dasharray="5,3" marker-end="url(#arrowhead-rose)"/>
<rect x="135" y="379" width="35" height="14" fill="#0f172a" rx="2"/>
<text x="152" y="390" fill="#fb7185" font-size="8" font-weight="normal" text-anchor="middle">token</text>
<line x1="315" y1="350" x2="335" y2="420" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="30" y="630" width="850" height="60" rx="6" fill="rgba(15, 23, 42, 0.8)" stroke="#1e293b" stroke-width="1.5" opacity="1.0"/>
<text x="45" y="650" fill="#64748b" font-size="10" font-weight="normal" text-anchor="start">组件类型:</text>
<rect x="120" y="638" width="16" height="16" rx="3" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<text x="142" y="650" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">前端</text>
<rect x="195" y="638" width="16" height="16" rx="3" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="217" y="650" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">后端</text>
<rect x="270" y="638" width="16" height="16" rx="3" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<text x="292" y="650" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">数据库</text>
<rect x="345" y="638" width="16" height="16" rx="3" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<text x="367" y="650" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">外部API</text>
<rect x="420" y="638" width="16" height="16" rx="3" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<text x="442" y="650" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">认证</text>
<rect x="495" y="638" width="16" height="16" rx="3" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5" opacity="1.0"/>
<text x="517" y="650" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">通用</text>
<text x="45" y="675" fill="#64748b" font-size="10" font-weight="normal" text-anchor="start">连接类型:</text>
<line x1="120" y1="670" x2="140" y2="670" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<text x="148" y="674" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">数据流</text>
<line x1="195" y1="670" x2="215" y2="670" stroke="#fb7185" stroke-width="1.5" marker-end="url(#arrowhead-rose)"/>
<text x="223" y="674" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">认证流</text>
<line x1="270" y1="670" x2="290" y2="670" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#arrowhead-amber)"/>
<text x="298" y="674" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">配置</text>
</svg>
</div>
<div class="cards">
<div class="card">
<div class="card-header">
<div class="card-dot" style="background: #94a3b8;"></div>
<h3>Frontend</h3>
</div>
<ul></ul>
</div>
<div class="card">
<div class="card-header">
<div class="card-dot" style="background: #94a3b8;"></div>
<h3>Backend</h3>
</div>
<ul></ul>
</div>
<div class="card">
<div class="card-header">
<div class="card-dot" style="background: #94a3b8;"></div>
<h3>Security</h3>
</div>
<ul></ul>
</div></div>
<div class="footer">
生成时间: 2026-04-18 10:26 | Hand-Drawn Diagram · Zero Token Cost
</div>
</div>
</body>
</html>