Files
nanocode/fumamxCRM/frontend/public/fumamx_crm_architecture.html
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

321 lines
24 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.7); border-radius: 0.75rem;
border: 1px solid rgba(148, 163, 184, 0.15); padding: 1rem 1.25rem;
backdrop-filter: blur(8px);
}
.card-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; }
.card-dot { width: 6px; height: 6px; border-radius: 50%; box-shadow: 0 0 6px currentColor; }
.card h3 { font-size: 0.8rem; font-weight: 500; color: #e2e8f0; letter-spacing: -0.01em; }
.card ul { list-style: none; font-size: 0.75rem; color: #94a3b8; line-height: 1.85; margin: 0; padding: 0; }
.card li { position: relative; padding-left: 0.75rem; }
.card li::before { content: "•"; position: absolute; left: 0; 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 1320 860" 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="1320" height="860" fill="url(#grid)"/>
<rect x="40" y="30" width="1180" height="725" rx="10" fill="rgba(15, 23, 42, 0.3)" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="5,3"/>
<rect x="55" y="22" width="138" height="16" fill="#0f172a"/>
<text x="124" y="33" fill="#94a3b8" font-size="9" font-weight="500" text-anchor="middle">fumamxCRM System</text>
<rect x="60" y="360" width="1130" height="230" rx="10" fill="rgba(15, 23, 42, 0.3)" stroke="#34d399" stroke-width="1.5" stroke-dasharray="5,3"/>
<rect x="75" y="352" width="234" height="16" fill="#0f172a"/>
<text x="192" y="363" fill="#34d399" font-size="9" font-weight="500" text-anchor="middle">FastAPI Backend (Port 10001)</text>
<rect x="240" y="180" width="520" height="115" rx="10" fill="rgba(15, 23, 42, 0.3)" stroke="#22d3ee" stroke-width="1.5" stroke-dasharray="5,3"/>
<rect x="255" y="172" width="178" height="16" fill="#0f172a"/>
<text x="344" y="183" fill="#22d3ee" font-size="9" font-weight="500" text-anchor="middle">Frontend (Port 10000)</text>
<rect x="240" y="600" width="500" height="115" rx="10" fill="rgba(15, 23, 42, 0.3)" stroke="#a78bfa" stroke-width="1.5" stroke-dasharray="5,3"/>
<rect x="255" y="592" width="90" height="16" fill="#0f172a"/>
<text x="300" y="603" fill="#a78bfa" font-size="9" font-weight="500" text-anchor="middle">Data Layer</text>
<rect x="770" y="600" width="310" height="115" rx="10" fill="rgba(15, 23, 42, 0.3)" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="5,3"/>
<rect x="785" y="592" width="146" height="16" fill="#0f172a"/>
<text x="858" y="603" fill="#fbbf24" font-size="9" font-weight="500" text-anchor="middle">External Services</text>
<rect x="80" y="60" width="110" height="70" rx="6" fill="#0f172a" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<rect x="80" y="60" width="110" height="70" rx="6" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<text x="135" y="78" fill="white" font-size="11" font-weight="600" text-anchor="middle">Browser</text>
<text x="135" y="92" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">User</text>
<text x="135" y="106" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">Chrome/Firefox/Safari</text>
<rect x="260" y="200" width="130" height="70" rx="6" fill="#0f172a" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<rect x="260" y="200" width="130" height="70" rx="6" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<text x="325" y="218" fill="white" font-size="11" font-weight="600" text-anchor="middle">React 18</text>
<text x="325" y="232" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Port 10000</text>
<text x="325" y="246" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">Vite + React Router</text>
<rect x="450" y="200" width="140" height="70" rx="6" fill="#0f172a" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<rect x="450" y="200" width="140" height="70" rx="6" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<text x="520" y="218" fill="white" font-size="11" font-weight="600" text-anchor="middle">Pages</text>
<text x="520" y="232" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">UI</text>
<text x="520" y="246" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">Login/Dashboard/Discover
Customers/Analysis</text>
<rect x="640" y="200" width="100" height="70" rx="6" fill="#0f172a" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<rect x="640" y="200" width="100" height="70" rx="6" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1.5" opacity="1.0"/>
<text x="690" y="218" fill="white" font-size="11" font-weight="600" text-anchor="middle">Axios</text>
<text x="690" y="232" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">HTTP Client</text>
<text x="690" y="246" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">REST API 调用</text>
<rect x="80" y="380" width="120" height="75" rx="6" fill="#0f172a" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<rect x="80" y="380" width="120" height="75" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="140" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">FastAPI</text>
<text x="140" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Port 10001</text>
<text x="140" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">FastAPI 0.110
Uvicorn</text>
<rect x="80" y="500" width="100" height="65" rx="6" fill="#0f172a" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<rect x="80" y="500" width="100" height="65" rx="6" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<text x="130" y="518" fill="white" font-size="11" font-weight="600" text-anchor="middle">CORS</text>
<text x="130" y="532" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Middleware</text>
<text x="130" y="546" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">跨域配置</text>
<rect x="240" y="380" width="100" height="75" rx="6" fill="#0f172a" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<rect x="240" y="380" width="100" height="75" rx="6" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1.5" opacity="1.0"/>
<text x="290" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">Auth</text>
<text x="290" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">JWT</text>
<text x="290" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">登录/验证
python-jose</text>
<rect x="370" y="380" width="110" height="75" rx="6" fill="#0f172a" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<rect x="370" y="380" width="110" height="75" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="425" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">Customers</text>
<text x="425" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">CRUD</text>
<text x="425" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">本地客户管理
增删改查</text>
<rect x="510" y="380" width="110" height="75" rx="6" fill="#0f172a" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<rect x="510" y="380" width="110" height="75" rx="6" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<text x="565" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">Discover</text>
<text x="565" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Search</text>
<text x="565" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">公司搜索
数据发现</text>
<rect x="650" y="380" width="110" height="75" rx="6" fill="#0f172a" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<rect x="650" y="380" width="110" height="75" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="705" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">Import</text>
<text x="705" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Background</text>
<text x="705" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">导入任务队列
线程管理</text>
<rect x="790" y="380" width="110" height="75" rx="6" fill="#0f172a" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<rect x="790" y="380" width="110" height="75" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="845" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">Potential</text>
<text x="845" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Leads</text>
<text x="845" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">潜在客户
联系人管理</text>
<rect x="930" y="380" width="110" height="75" rx="6" fill="#0f172a" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<rect x="930" y="380" width="110" height="75" rx="6" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<text x="985" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">Analysis</text>
<text x="985" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">AI</text>
<text x="985" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">深度分析
LLM调用</text>
<rect x="1070" y="380" width="100" height="75" rx="6" fill="#0f172a" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<rect x="1070" y="380" width="100" height="75" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" opacity="1.0"/>
<text x="1120" y="398" fill="white" font-size="11" font-weight="600" text-anchor="middle">Settings</text>
<text x="1120" y="412" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Config</text>
<text x="1120" y="426" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">系统设置
API密钥</text>
<rect x="260" y="620" width="120" height="70" rx="6" fill="#0f172a" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<rect x="260" y="620" width="120" height="70" rx="6" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<text x="320" y="638" fill="white" font-size="11" font-weight="600" text-anchor="middle">SQLAlchemy</text>
<text x="320" y="652" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">ORM</text>
<text x="320" y="666" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">SQLAlchemy 2.0
Pydantic v2</text>
<rect x="430" y="620" width="110" height="70" rx="6" fill="#0f172a" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<rect x="430" y="620" width="110" height="70" rx="6" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<text x="485" y="638" fill="white" font-size="11" font-weight="600" text-anchor="middle">SQLite</text>
<text x="485" y="652" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">Local DB</text>
<text x="485" y="666" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">fumamx_crm.db
8张表</text>
<rect x="600" y="620" width="120" height="70" rx="6" fill="#0f172a" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<rect x="600" y="620" width="120" height="70" rx="6" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1.5" opacity="1.0"/>
<text x="660" y="638" fill="white" font-size="11" font-weight="600" text-anchor="middle">Reports</text>
<text x="660" y="652" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">File Storage</text>
<text x="660" y="666" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">analysis_reports/
Markdown</text>
<rect x="790" y="620" width="120" height="70" rx="6" fill="#0f172a" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<rect x="790" y="620" width="120" height="70" rx="6" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<text x="850" y="638" fill="white" font-size="11" font-weight="600" text-anchor="middle">fumamxCLI</text>
<text x="850" y="652" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">External CLI</text>
<text x="850" y="666" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">fumamx API
Cookie认证</text>
<rect x="950" y="620" width="110" height="70" rx="6" fill="#0f172a" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<rect x="950" y="620" width="110" height="70" rx="6" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1.5" opacity="1.0"/>
<text x="1005" y="638" fill="white" font-size="11" font-weight="600" text-anchor="middle">LLM API</text>
<text x="1005" y="652" fill="#94a3b8" font-size="8" font-weight="normal" text-anchor="middle">External</text>
<text x="1005" y="666" fill="#cbd5e1" font-size="8" font-weight="normal" text-anchor="middle">Kimi K2.5
DeepSeek</text>
<line x1="135" y1="130" x2="325" y2="200" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="216" y="157" width="28" height="14" fill="#0f172a" rx="2"/>
<text x="230" y="168" fill="#64748b" font-size="8" font-weight="normal" text-anchor="middle">HTTP</text>
<line x1="390" y1="235" x2="450" y2="235" stroke="#22d3ee" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="399" y="227" width="42" height="14" fill="#0f172a" rx="2"/>
<text x="420" y="238" fill="#22d3ee" font-size="8" font-weight="normal" text-anchor="middle">Router</text>
<line x1="590" y1="235" x2="640" y2="235" stroke="#22d3ee" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="601" y="227" width="28" height="14" fill="#0f172a" rx="2"/>
<text x="615" y="238" fill="#22d3ee" font-size="8" font-weight="normal" text-anchor="middle">HTTP</text>
<line x1="690" y1="270" x2="140" y2="380" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="387" y="317" width="56" height="14" fill="#0f172a" rx="2"/>
<text x="415" y="328" fill="#64748b" font-size="8" font-weight="normal" text-anchor="middle">REST API</text>
<line x1="140" y1="455" x2="130" y2="500" stroke="#34d399" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="100" y="469" width="70" height="14" fill="#0f172a" rx="2"/>
<text x="135" y="480" fill="#34d399" font-size="8" font-weight="normal" text-anchor="middle">Middleware</text>
<line x1="520" y1="270" x2="290" y2="380" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#arrowhead-rose)"/>
<rect x="374" y="317" width="63" height="14" fill="#0f172a" rx="2"/>
<text x="405" y="328" fill="#fbbf24" font-size="8" font-weight="normal" text-anchor="middle">JWT Token</text>
<line x1="425" y1="455" x2="320" y2="620" stroke="#34d399" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="362" y="529" width="21" height="14" fill="#0f172a" rx="2"/>
<text x="372" y="540" fill="#34d399" font-size="8" font-weight="normal" text-anchor="middle">ORM</text>
<line x1="845" y1="455" x2="320" y2="620" stroke="#34d399" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="572" y="529" width="21" height="14" fill="#0f172a" rx="2"/>
<text x="582" y="540" fill="#34d399" font-size="8" font-weight="normal" text-anchor="middle">ORM</text>
<line x1="1120" y1="455" x2="320" y2="620" stroke="#34d399" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="710" y="529" width="21" height="14" fill="#0f172a" rx="2"/>
<text x="720" y="540" fill="#34d399" font-size="8" font-weight="normal" text-anchor="middle">ORM</text>
<line x1="380" y1="655" x2="430" y2="655" stroke="#a78bfa" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="395" y="647" width="21" height="14" fill="#0f172a" rx="2"/>
<text x="405" y="658" fill="#a78bfa" font-size="8" font-weight="normal" text-anchor="middle">SQL</text>
<line x1="565" y1="455" x2="850" y2="620" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="700" y="529" width="14" height="14" fill="#0f172a" rx="2"/>
<text x="707" y="540" fill="#fbbf24" font-size="8" font-weight="normal" text-anchor="middle">搜索</text>
<line x1="705" y1="455" x2="850" y2="620" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="770" y="529" width="14" height="14" fill="#0f172a" rx="2"/>
<text x="777" y="540" fill="#fbbf24" font-size="8" font-weight="normal" text-anchor="middle">导入</text>
<line x1="985" y1="455" x2="1005" y2="620" stroke="#a78bfa" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="981" y="529" width="28" height="14" fill="#0f172a" rx="2"/>
<text x="995" y="540" fill="#a78bfa" font-size="8" font-weight="normal" text-anchor="middle">AI分析</text>
<line x1="985" y1="455" x2="660" y2="620" stroke="#a78bfa" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<rect x="794" y="529" width="56" height="14" fill="#0f172a" rx="2"/>
<text x="822" y="540" fill="#a78bfa" font-size="8" font-weight="normal" text-anchor="middle">Markdown</text>
<rect x="30" y="790" 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="810" fill="#64748b" font-size="10" font-weight="normal" text-anchor="start">组件类型:</text>
<rect x="120" y="798" 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="810" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">前端</text>
<rect x="195" y="798" 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="810" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">后端</text>
<rect x="270" y="798" 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="810" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">数据库</text>
<rect x="345" y="798" 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="810" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">外部API</text>
<rect x="420" y="798" 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="810" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">认证</text>
<rect x="495" y="798" 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="810" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">通用</text>
<text x="45" y="835" fill="#64748b" font-size="10" font-weight="normal" text-anchor="start">连接类型:</text>
<line x1="120" y1="830" x2="140" y2="830" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrowhead)"/>
<text x="148" y="834" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">数据流</text>
<line x1="195" y1="830" x2="215" y2="830" stroke="#fb7185" stroke-width="1.5" marker-end="url(#arrowhead-rose)"/>
<text x="223" y="834" fill="#94a3b8" font-size="9" font-weight="normal" text-anchor="start">认证流</text>
<line x1="270" y1="830" x2="290" y2="830" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#arrowhead-amber)"/>
<text x="298" y="834" 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>前端组件 (Port 10000)</h3>
</div>
<ul><li>React 18 + Vite + React Router</li>
<li>页面: Login / Dashboard / Discover / Customers</li>
<li>DeepAnalysis / PotentialCustomers / Settings</li>
<li>axios HTTP 客户端</li></ul>
</div>
<div class="card">
<div class="card-header">
<div class="card-dot" style="background: #94a3b8;"></div>
<h3>后端服务 (Port 10001)</h3>
</div>
<ul><li>FastAPI 0.110 + Uvicorn + CORS</li>
<li>JWT Auth (python-jose + bcrypt)</li>
<li>7 个路由: auth/customers/discover/import/potential/analysis/settings</li>
<li>SQLAlchemy 2.0 + Pydantic v2</li></ul>
</div>
<div class="card">
<div class="card-header">
<div class="card-dot" style="background: #94a3b8;"></div>
<h3>数据层</h3>
</div>
<ul><li>SQLite (fumamx_crm.db) 单文件</li>
<li>8 张表: User/Customer/Country/ImportTask</li>
<li>PotentialCustomer/PotentialContact/DeepAnalysis/SystemSetting</li>
<li>analysis_reports/ 目录存储 Markdown</li></ul>
</div>
<div class="card">
<div class="card-header">
<div class="card-dot" style="background: #94a3b8;"></div>
<h3>外部服务</h3>
</div>
<ul><li>fumamxCLI - 公司搜索与批量导入</li>
<li>Cookie 认证机制</li>
<li>LLM API - Kimi K2.5 / DeepSeek</li>
<li>深度分析报告生成</li></ul>
</div></div>
<div class="footer">
生成时间: 2026-04-18 12:32 | Hand-Drawn Diagram · Zero Token Cost
</div>
</div>
</body>
</html>