- Introduced `build_all.py` script to automate the assembly of course modules into a single `index.html` file. - Created `index.html` for the main course overview, featuring a structured layout and navigation for various modules. - Developed `_base.html` and `_footer.html` templates for the advisor module, ensuring consistent styling and structure. - Added `build.sh` script for individual module assembly, enhancing modularity and ease of updates. - Implemented multiple module HTML files detailing specific training scenarios and functionalities for advisors, including interactive elements and quizzes. This update significantly enhances the course delivery framework, providing a comprehensive and interactive learning experience for advisors.
97 lines
5.5 KiB
HTML
97 lines
5.5 KiB
HTML
<section class="module" id="module-1">
|
||
<div class="module-inner">
|
||
<p class="eyebrow animate-in">模块 1 · 路由与登录</p>
|
||
<h1 class="module-title animate-in">四角色路由、HashRouter<br>与 Demo 账号</h1>
|
||
<p class="module-lead animate-in">
|
||
前端在 <code>web/</code>,用 React +
|
||
<span class="term" data-definition="HashRouter = URL 里 # 后面的路径由浏览器本地切换,不请求服务器新页面,适合静态部署。">HashRouter</span>
|
||
做四角色工作台。登录后按角色跳进不同「家」——改路由时先对 <code>App.tsx</code> 和 <code>demoAccounts.ts</code>。
|
||
</p>
|
||
|
||
<div class="screen animate-in">
|
||
<h2>四角色默认入口</h2>
|
||
<div class="badge-list">
|
||
<div class="badge-item"><span class="badge-code">CUST-9527</span><span class="badge-desc">客户 → /app/customer/home</span></div>
|
||
<div class="badge-item"><span class="badge-code">STAFF-10086</span><span class="badge-desc">理财师 → /app/advisor/home</span></div>
|
||
<div class="badge-item"><span class="badge-code">STAFF-20001</span><span class="badge-desc">分析员 → /app/analyst/home</span></div>
|
||
<div class="badge-item"><span class="badge-code">STAFF-30001</span><span class="badge-desc">风控 → /app/risk/home</span></div>
|
||
</div>
|
||
<p>登录页一键 Demo:<code>LoginPage</code> 调 <code>POST /api/auth/login</code> 拿 JWT,<code>saveAuth</code> 写入 localStorage,再 <code>navigate(defaultRoute)</code>。</p>
|
||
</div>
|
||
|
||
<div class="screen animate-in">
|
||
<h2>路由树(<code>App.tsx</code>)</h2>
|
||
<div class="pattern-cards">
|
||
<div class="pattern-card">
|
||
<h3>customer/*</h3>
|
||
<p>home、profile、holdings、trades、chat。持仓/流水走平台 API,对话走 ChatPanel。</p>
|
||
</div>
|
||
<div class="pattern-card">
|
||
<h3>advisor/*</h3>
|
||
<p>home、customers、chat。顾问助手 SSE,可指定 customer_id 查名下客户。</p>
|
||
</div>
|
||
<div class="pattern-card">
|
||
<h3>analyst/*</h3>
|
||
<p>home、analytics/query(问数)、analytics/assets、analytics/chat。问数走 /api/analyst/*。</p>
|
||
</div>
|
||
<div class="pattern-card">
|
||
<h3>risk/*</h3>
|
||
<p>home、alerts、simulate、chat。台账 REST + 风控对话,JWT 须带 risk 角色。</p>
|
||
</div>
|
||
</div>
|
||
<div class="callout callout-accent">
|
||
<strong>HashRouter 为什么?</strong> 构建产物是纯静态文件,<code>#/app/customer/home</code> 不依赖服务端路由重写,双击 <code>dist/index.html</code> 也能跑(API 仍要 proxy 或同域)。
|
||
</div>
|
||
</div>
|
||
|
||
<div class="screen animate-in">
|
||
<div class="translation-block">
|
||
<div class="translation-code">
|
||
<span class="translation-label">main.tsx + App.tsx</span>
|
||
<pre><code><span class="code-line"><span class="code-comment">// main.tsx</span></span>
|
||
<span class="code-line"><HashRouter></span>
|
||
<span class="code-line"> <AppRoutes /></span>
|
||
<span class="code-line"></HashRouter></span>
|
||
<span class="code-line"></span>
|
||
<span class="code-line"><span class="code-comment">// demoAccounts.ts</span></span>
|
||
<span class="code-line">defaultRoute: <span class="code-string">'#/app/customer/home'</span></span>
|
||
<span class="code-line"></span>
|
||
<span class="code-line"><span class="code-comment">// App.tsx · RequireAuth</span></span>
|
||
<span class="code-line"><span class="code-keyword">if</span> (!auth) <span class="code-keyword">return</span> <Navigate to=<span class="code-string">"/login"</span> /></span></code></pre>
|
||
</div>
|
||
<div class="translation-english">
|
||
<span class="translation-label">白话</span>
|
||
<div class="translation-lines">
|
||
<p class="tl">整站包在 HashRouter 里,路径变化不刷新整页。</p>
|
||
<p class="tl">每个 Demo 账号绑好「登录后跳哪」——带 # 前缀,和 Hash 路由一致。</p>
|
||
<p class="tl">/app 下子路由都要过 RequireAuth:没 token 踢回登录页。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="quiz-container" id="quiz-frontend-m1">
|
||
<div class="quiz-question-block"
|
||
data-correct="option-b"
|
||
data-explanation-right="STAFF-20001 登录后 defaultRoute 是 #/app/analyst/home,见 demoAccounts.ts。"
|
||
data-explanation-wrong="四角色各有独立 home,分析员不会进 customer 或 risk 路径。">
|
||
<h3 class="quiz-question">分析员 Demo 登录成功,默认打开哪条路径?</h3>
|
||
<div class="quiz-options">
|
||
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
|
||
<div class="quiz-option-radio"></div><span>/app/customer/home</span>
|
||
</button>
|
||
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
|
||
<div class="quiz-option-radio"></div><span>/app/analyst/home</span>
|
||
</button>
|
||
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
|
||
<div class="quiz-option-radio"></div><span>/app/risk/alerts</span>
|
||
</button>
|
||
</div>
|
||
<div class="quiz-feedback"></div>
|
||
</div>
|
||
<button class="quiz-check-btn" onclick="checkQuiz('quiz-frontend-m1')">检查答案</button>
|
||
<button class="quiz-reset-btn" onclick="resetQuiz('quiz-frontend-m1')">重做</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|