Files
group_xinghuo_jinrong/docs/course/jinrong-module-frontend/modules/03-dev-debug.html
T

115 lines
5.9 KiB
HTML
Raw Normal View History

<section class="module" id="module-3">
<div class="module-inner">
<p class="eyebrow animate-in">模块 3 · 本地调试</p>
<h1 class="module-title animate-in">npm run dev、Vite proxy<br>与 401 排障</h1>
<p class="module-lead animate-in">
前端 dev 服务器跑在 <code>5173</code>,API 在 <code>8000</code>。
<span class="term" data-definition="Vite proxy = 开发时把 /api 请求转发到后端,浏览器以为 API 和页面同域,避免跨域 CORS 麻烦。">Vite proxy</span>
帮你转发——没起后端或头带错,Network 面板一眼 401。
</p>
<div class="screen animate-in">
<h2>启动顺序</h2>
<div class="numbered-steps">
<div class="step-card">
<span class="step-num">1</span>
<div><strong>后端</strong> · 应用入口(<code>main.py</code>):<code>uvicorn app.main:app --reload --port 8000</code>(Core 模拟库 + Redis 6380 按需)</div>
</div>
<div class="step-card">
<span class="step-num">2</span>
<div><strong>前端</strong>:<code>cd web && npm run dev</code> → 打开 <code>http://localhost:5173</code></div>
</div>
<div class="step-card">
<span class="step-num">3</span>
<div><strong>登录</strong>:点 Demo 账号 → 看 localStorage 里 token → 再点各角色菜单</div>
</div>
</div>
</div>
<div class="screen animate-in">
<div class="translation-block">
<div class="translation-code">
<span class="translation-label">vite.config.ts</span>
<pre><code><span class="code-line">server: {</span>
<span class="code-line"> port: <span class="code-number">5173</span>,</span>
<span class="code-line"> proxy: {</span>
<span class="code-line"> <span class="code-string">'/api'</span>: {</span>
<span class="code-line"> target: <span class="code-string">'http://127.0.0.1:8000'</span>,</span>
<span class="code-line"> changeOrigin: <span class="code-keyword">true</span>,</span>
<span class="code-line"> },</span>
<span class="code-line"> },</span>
<span class="code-line">},</span></code></pre>
</div>
<div class="translation-english">
<span class="translation-label">白话</span>
<div class="translation-lines">
<p class="tl">浏览器请求 localhost:5173/api/... 时,Vite 偷偷转给 8000 端口。</p>
<p class="tl">前端代码里写相对路径 /api 即可,不用硬编码 :8000。</p>
<p class="tl">生产构建没有 proxy,要 Nginx 或同域部署反代。</p>
</div>
</div>
</div>
</div>
<div class="screen animate-in">
<h2>常见 401 速查</h2>
<div class="pattern-cards">
<div class="pattern-card">
<h3>AUTH_401_MISSING_BEARER</h3>
<p>没登录或 token 过期 → 重新点 Demo 登录;改过后端角色也要重登拿新 JWT。</p>
</div>
<div class="pattern-card">
<h3>AUTH_401_MISSING_AGENT_TYPE</h3>
<p>走了 /api/chat 但没带 X-Agent-Type → 查 ChatPanel 的 agentType 和 chat.ts headers。</p>
</div>
<div class="pattern-card">
<h3>AUTH_403_AGENT_MISMATCH</h3>
<p>JWT 角色和 X-Agent-Type 不配,如客户 token 却带 advisor → 换账号或改 prop。</p>
</div>
<div class="pattern-card">
<h3>连不上 API</h3>
<p>8000 没起或 proxy 失效 → curl http://127.0.0.1:8000/health 先确认后端活着。</p>
</div>
</div>
<div class="quiz-container" id="quiz-frontend-m3">
<div class="quiz-question-block"
data-correct="option-b"
data-explanation-right="持仓页走平台 API,只需 Bearer;缺的是 X-Agent-Type 才会在 chat 线 401。"
data-explanation-wrong="平台读接口不要 X-Agent-Type;401 missing bearer 才是没 token。">
<h3 class="quiz-question">客户持仓页 401,响应 AUTH_401_MISSING_AGENT_TYPE,最可能原因是?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>平台 API 忘了带 X-Agent-Type(正常不该带)</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>请求误打到 /api/chat 或混用了 chat 封装</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>vite proxy 端口写错</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="option-a"
data-explanation-right="对。/api → 127.0.0.1:8000,前端 dev 标准配置。"
data-explanation-wrong="proxy target 是 8000 不是 5173;5173 是 Vite 自己。">
<h3 class="quiz-question">npm run dev 时,/api/chat 实际打到哪?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>http://127.0.0.1:8000/api/chat</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>http://127.0.0.1:5173/api/chat(Vite 自己处理)</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<button class="quiz-check-btn" onclick="checkQuiz('quiz-frontend-m3')">检查答案</button>
<button class="quiz-reset-btn" onclick="resetQuiz('quiz-frontend-m3')">重做</button>
</div>
</div>
</div>
</section>