feat: add auth strategy visualization
This commit is contained in:
@@ -178,6 +178,52 @@
|
||||
background: rgba(255,255,255,0.45);
|
||||
}
|
||||
.list-item p { margin-top: 8px; }
|
||||
.auth-board {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
.auth-card {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 20px;
|
||||
padding: 18px;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
.auth-highlight {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.auth-focus {
|
||||
font-size: 14px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.timeline {
|
||||
margin-top: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
.timeline-step {
|
||||
border-radius: 16px;
|
||||
border: 1px dashed var(--line);
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
.filter-pill {
|
||||
display: inline-flex;
|
||||
padding: 4px 10px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid rgba(15, 103, 181, 0.2);
|
||||
background: rgba(15, 103, 181, 0.08);
|
||||
color: var(--accent);
|
||||
font-size: 12px;
|
||||
margin-right: 6px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
@media (max-width: 1180px) {
|
||||
.hero-grid, .workspace, .triple, .flow, .stats { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
@@ -232,6 +278,32 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card" id="authStrategy">
|
||||
<div class="eyebrow" data-i18n="authBadge"></div>
|
||||
<h2 data-i18n="authTitle"></h2>
|
||||
<p data-i18n="authText"></p>
|
||||
<div class="auth-board">
|
||||
<div class="auth-card">
|
||||
<strong data-i18n="jwtLabel"></strong>
|
||||
<p data-i18n="jwtSummary"></p>
|
||||
<span class="auth-focus" data-i18n="jwtLearnMore"></span>
|
||||
</div>
|
||||
<div class="auth-card">
|
||||
<strong data-i18n="satokenLabel"></strong>
|
||||
<p data-i18n="satokenSummary"></p>
|
||||
<span class="auth-focus" data-i18n="satokenLearnMore"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="auth-highlight">
|
||||
<span data-i18n="filterLabel"></span>
|
||||
<div id="filterList"></div>
|
||||
</div>
|
||||
<div class="auth-highlight">
|
||||
<span data-i18n="tokenLabel"></span>
|
||||
</div>
|
||||
<div class="timeline" id="tokenTimeline"></div>
|
||||
</section>
|
||||
|
||||
<section class="card" style="margin-bottom:18px;">
|
||||
<div class="eyebrow" data-i18n="archBadge"></div>
|
||||
<h2 data-i18n="archTitle"></h2>
|
||||
@@ -464,6 +536,17 @@
|
||||
consolePlaceholder: "请选择上方一个实验动作来加载实时输出。",
|
||||
loadingPrefix: "正在加载 ",
|
||||
requestFailedPrefix: "请求失败:",
|
||||
authBadge: "鉴权策略学习站",
|
||||
authTitle: "从 JWT 到 Sa-Token 的学习空间",
|
||||
authText: "本区详细对比 JWT 和 Sa-Token,展示各自的拦截器、过滤器和请求链路,帮助你理解两套鉴权策略的生命周期。",
|
||||
jwtLabel: "JWT 登录",
|
||||
jwtSummary: "客户端调用 /access 获取 token,后续带 Authorization: Bearer header,适合 stateless API 学习。",
|
||||
jwtLearnMore: "查看 /api/users/stats 的 header 输出、触发 LearningJwtFilter",
|
||||
satokenLabel: "Sa-Token 流程",
|
||||
satokenSummary: "模拟 Sa-Token 里的 session 状态,观察拦截器、注解、认证缓存的运行差异。",
|
||||
satokenLearnMore: "关注 Sa-Token 注解与拦截器的控制流",
|
||||
filterLabel: "正在观察的过滤器:",
|
||||
tokenLabel: "token 生命周期示意:",
|
||||
exp1Badge: "实验 1",
|
||||
exp1Title: "追踪校验链路",
|
||||
exp1Text: "打开用户实验,先创建一个用户,再用同样邮箱重复创建。对比前端错误提示、DuplicateEmailException 和全局异常处理器。",
|
||||
@@ -552,6 +635,17 @@
|
||||
consolePlaceholder: "Select one experiment above to load live output.",
|
||||
loadingPrefix: "Loading ",
|
||||
requestFailedPrefix: "Request failed: ",
|
||||
authBadge: "Auth Strategy Studio",
|
||||
authTitle: "Explore JWT vs Sa-Token",
|
||||
authText: "This block contrasts the JWT and Sa-Token flows, visualizing filters, interceptors, and the request chain so you understand lifecycle differences.",
|
||||
jwtLabel: "JWT Login",
|
||||
jwtSummary: "Call /access, receive a bearer token, and include Authorization headers on protected calls to see stateless API behavior.",
|
||||
jwtLearnMore: "Trace headers via /api/users/stats and LearningJwtFilter logs",
|
||||
satokenLabel: "Sa-Token Flow",
|
||||
satokenSummary: "Simulate Sa-Token's session-aware interceptor to highlight how stateful auth handles refresh and annotations.",
|
||||
satokenLearnMore: "Observe how Sa-Token annotations and interceptors gate requests",
|
||||
filterLabel: "Filters in focus:",
|
||||
tokenLabel: "Token lifecycle:"
|
||||
exp1Badge: "Experiment 1",
|
||||
exp1Title: "Trace validation",
|
||||
exp1Text: "Open the user lab, create a user, then repeat with the same email. Compare the frontend error with DuplicateEmailException and the global exception handler.",
|
||||
@@ -640,6 +734,24 @@
|
||||
|
||||
window.learningShell.mountShell({ onLanguageChange: renderLanguage });
|
||||
renderLanguage();
|
||||
|
||||
function renderAuthBoard() {
|
||||
const insights = window.learningShell.getAuthInsights();
|
||||
document.querySelector("#authStrategy strong[data-i18n='jwtLabel']").textContent = insights.jwt.label;
|
||||
document.querySelector("#authStrategy strong[data-i18n='satokenLabel']").textContent = insights.satoken.label;
|
||||
document.querySelector("#authStrategy p[data-i18n='jwtSummary']").textContent = insights.jwt.summary;
|
||||
document.querySelector("#authStrategy p[data-i18n='satokenSummary']").textContent = insights.satoken.summary;
|
||||
document.querySelector("#authStrategy span[data-i18n='jwtLearnMore']").textContent = insights.jwt.learnMore;
|
||||
document.querySelector("#authStrategy span[data-i18n='satokenLearnMore']").textContent = insights.satoken.learnMore;
|
||||
document.querySelector("#filterList").innerHTML = insights.filters.map(f => `<span class="filter-pill">${f}</span>`).join("");
|
||||
const timeline = window.learningShell.getTokenTimeline();
|
||||
const timelineEl = document.getElementById("tokenTimeline");
|
||||
timelineEl.innerHTML = timeline.map(item => `<div class="timeline-step"><strong>${item.stage}</strong><small>${item.detail}</small></div>`).join("");
|
||||
}
|
||||
|
||||
renderAuthBoard();
|
||||
|
||||
window.addEventListener("learning-language-changed", renderAuthBoard);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user