模块 1 · 路由与登录
四角色路由、HashRouter
与 Demo 账号
前端在 web/,用 React +
HashRouter
做四角色工作台。登录后按角色跳进不同「家」——改路由时先对 App.tsx 和 demoAccounts.ts。
四角色默认入口
登录页一键 Demo:LoginPage 调 POST /api/auth/login 拿 JWT,saveAuth 写入 localStorage,再 navigate(defaultRoute)。
路由树(App.tsx)
customer/*
home、profile、holdings、trades、chat。持仓/流水走平台 API,对话走 ChatPanel。
advisor/*
home、customers、chat。顾问助手 SSE,可指定 customer_id 查名下客户。
analyst/*
home、analytics/query(问数)、analytics/assets、analytics/chat。问数走 /api/analyst/*。
risk/*
home、alerts、simulate、chat。台账 REST + 风控对话,JWT 须带 risk 角色。
#/app/customer/home 不依赖服务端路由重写,双击 dist/index.html 也能跑(API 仍要 proxy 或同域)。
// main.tsx
<HashRouter>
<AppRoutes />
</HashRouter>
// demoAccounts.ts
defaultRoute: '#/app/customer/home'
// App.tsx · RequireAuth
if (!auth) return <Navigate to="/login" />
整站包在 HashRouter 里,路径变化不刷新整页。
每个 Demo 账号绑好「登录后跳哪」——带 # 前缀,和 Hash 路由一致。
/app 下子路由都要过 RequireAuth:没 token 踢回登录页。
分析员 Demo 登录成功,默认打开哪条路径?
模块 2 · 对话与鉴权
ChatPanel / useChatPanel:
三条 API 线的头不一样
对话 UI 统一用 ChatPanel + useChatPanel,但后端入口分三条:
/api/chat(四 Agent)、/api/analyst/*(问数平台)、风控台账 REST。
指挥 AI 接新页面时,先对表再写 headers。
鉴权差异对照
| 前端模块 | API | Authorization | X-Agent-Type |
|---|---|---|---|
api/chat.ts | /api/chat, /stream, sessions | Bearer | 必须(与 prop agentType 一致) |
api/analyst.ts | /api/analyst/chat 等 | Bearer(apiFetch) | 不要 |
api/risk.ts | /api/risk/* | Bearer | 必须 risk |
| 持仓/产品页 | /api/customers/* 等 | Bearer | 不要 |
risk.ts 曾漏 X-Agent-Type: risk,JWT 正确也 401。接新风控页先 grep 这个头。
数据流:理财师打开顾问助手
对比:问数走 analyst.ts,无 X-Agent-Type
// chat.ts — 对话线
function chatHeaders(token, agentType) {
return {
Authorization: `Bearer ${token}`,
'X-Agent-Type': agentType,
}
}
// analyst.ts — 问数平台线
apiFetch('/api/analyst/chat', { method: 'POST', token, body })
// apiFetch 只加 Authorization,不加 X-Agent-Type
Chat 相关请求:token 证明身份,agentType 证明走哪条 Agent 线。
useChatPanel 把 agentType 从页面 prop 一路传到每次 list/send/close。
问数用 apiFetch 通用封装,后端走 get_platform_auth_context,不需要 Agent 头。
customer 线 mode 常用 sync(后端 LangGraph 整图跑完再推);advisor/risk 用 stream SSE。
RiskChatPage 发消息,请求头应长什么样?
模块 3 · 本地调试
npm run dev、Vite proxy
与 401 排障
前端 dev 服务器跑在 5173,API 在 8000。
Vite proxy
帮你转发——没起后端或头带错,Network 面板一眼 401。
启动顺序
main.py):uvicorn app.main:app --reload --port 8000(Core 模拟库 + Redis 6380 按需)cd web && npm run dev → 打开 http://localhost:5173server: {
port: 5173,
proxy: {
'/api': {
target: 'http://127.0.0.1:8000',
changeOrigin: true,
},
},
},
浏览器请求 localhost:5173/api/... 时,Vite 偷偷转给 8000 端口。
前端代码里写相对路径 /api 即可,不用硬编码 :8000。
生产构建没有 proxy,要 Nginx 或同域部署反代。
常见 401 速查
AUTH_401_MISSING_BEARER
没登录或 token 过期 → 重新点 Demo 登录;改过后端角色也要重登拿新 JWT。
AUTH_401_MISSING_AGENT_TYPE
走了 /api/chat 但没带 X-Agent-Type → 查 ChatPanel 的 agentType 和 chat.ts headers。
AUTH_403_AGENT_MISMATCH
JWT 角色和 X-Agent-Type 不配,如客户 token 却带 advisor → 换账号或改 prop。
连不上 API
8000 没起或 proxy 失效 → curl http://127.0.0.1:8000/health 先确认后端活着。
客户持仓页 401,响应 AUTH_401_MISSING_AGENT_TYPE,最可能原因是?
npm run dev 时,/api/chat 实际打到哪?
模块 4 · 未接线
菜单有 ≠ API 已接
Chat 还有 B 方案三端点
前端 P0 主链路已真接(含风控三页 · 问数标签 · Dashboard hooks),但仍有分析对话占位、看板无钻取等缝。
开发态若 Dashboard「先闪错再正常」,多半是 StrictMode 双请求——已用 useAsyncSequence 丢弃过期响应。
仍开放 / 已修清单(2026-09-10)
风控 UI
台账筛选 · 适当性校验 · AML 扫描页已接 REST;高级运营能力仍简版。
问数
AnalystChatShell 占位 · 真问数在 AnalystQueryPage(模板/缓存标签 + dashboard/assets)。
竞态修复
useAsyncSequence 用于 Dashboard hooks、ChatPanel、风控/客户列表页等。
游客
VisitorChatWidget 首页试聊 · 与登录 ChatPanel 不同 API。
Chat 方案 B:三端点 + SSE 注意点
GET /api/chat/sessions
GET /api/chat/sessions/{id}/messages
POST /api/chat/sessions/{id}/close
POST /api/chat/stream → customer SSE
列表/历史/关闭与发消息共用同一套鉴权(Bearer + X-Agent-Type)。
SSE 无心跳:断连可能留下半空回合——排障时查 session 表 + 是否 uvicorn 重启。
HashRouter:URL 带 #,生产 Nginx 要配 SPA fallback。
改 URL 进别人工作台
RequireAuth 只验「有没有 token」,不验「这个角色能不能进 /app/risk」。菜单隐藏 ≠ 安全——后端 AGENT_ACCESS_MATRIX 和平台 RBAC 才拒 403。