|
14 | 14 | let activeView = "dashboard"; |
15 | 15 | let txTab = "all"; |
16 | 16 | let isGuest = false; // 游客模式(US-1:未登录可浏览市场) |
| 17 | + let pendingHashView = null; // URL hash 路由(rant 20:39:30 A):刷新后登录时恢复上次视图 |
17 | 18 |
|
18 | 19 | // MRT 风格表格状态(页面级变量:切换页面不丢失排序/筛选/分页) |
19 | 20 | const txTable = { sort: [], filters: {}, page: 1, pageSize: 10 }; |
|
300 | 301 | // 游客可见的页面(US-1:仅市场;其余需登录) |
301 | 302 | const GUEST_VIEWS = ["marketplace"]; |
302 | 303 |
|
| 304 | + const VALID_VIEWS = Object.keys(VIEW_TITLE); |
| 305 | + |
| 306 | + /* --- URL hash 路由(rant 20:39:30 A:刷新/前进后退保持视图;非法 hash 回仪表盘) --- */ |
| 307 | + |
| 308 | + // 从 location.hash 解析视图 id:空 hash → null(不动作);非法 hash → "dashboard" |
| 309 | + function viewFromHash() { |
| 310 | + const h = (window.location && window.location.hash) || ""; |
| 311 | + if (!h || h === "#") return null; |
| 312 | + const m = h.match(/^#\/([\w-]+)/); |
| 313 | + const id = m ? m[1] : null; |
| 314 | + return VALID_VIEWS.includes(id) ? id : "dashboard"; |
| 315 | + } |
| 316 | + |
| 317 | + // 当前 hash 是否为合法视图 hash(非法 hash 回退仪表盘时避免重写 URL、污染历史) |
| 318 | + function hashIsValid() { |
| 319 | + const h = (window.location && window.location.hash) || ""; |
| 320 | + const m = h.match(/^#\/([\w-]+)/); |
| 321 | + return !!m && VALID_VIEWS.includes(m[1]); |
| 322 | + } |
| 323 | + |
| 324 | + // 视图切换后同步 URL(pushState 不触发 hashchange,避免回环;已相同则跳过不重复入栈) |
| 325 | + function syncHash(id) { |
| 326 | + if (!window.history || !window.history.pushState) return; |
| 327 | + const h = "#/" + id; |
| 328 | + if ((window.location && window.location.hash) === h) return; |
| 329 | + try { window.history.pushState(null, "", h); } catch (e) { /* file:// 下个别浏览器限制,忽略 */ } |
| 330 | + } |
| 331 | + |
303 | 332 | function renderNav() { |
304 | 333 | const nav = $("#nav"); |
305 | 334 | nav.innerHTML = ""; |
|
334 | 363 | $("#mode-label").textContent = isGuest ? "游客模式 · 仅浏览市场" : "共享市场 · 角色视图"; |
335 | 364 | } |
336 | 365 |
|
337 | | - function switchView(id) { |
| 366 | + function switchView(id, opts) { |
338 | 367 | // 游客限制(US-1):非市场页面 → 提示需登录 |
339 | 368 | if (isGuest && !GUEST_VIEWS.includes(id)) { |
340 | 369 | toast("请先登录后再访问「" + (VIEW_TITLE[id] || id) + "」", "error"); |
|
348 | 377 | $("#main").scrollTop = 0; |
349 | 378 | // 动态文档标题(rant 18:06:09 F:视图切换跟随「视图 · AITokenPool」,未知视图回默认) |
350 | 379 | document.title = VIEW_TITLE[id] ? VIEW_TITLE[id] + " · AITokenPool" : "AITokenPool"; |
| 380 | + // URL hash 路由(rant 20:39:30 A:视图切换同步 #/视图;非法 hash 回退时不清 URL,避免污染历史) |
| 381 | + if (!opts || opts.sync !== false) syncHash(id); |
351 | 382 | } |
352 | 383 |
|
353 | 384 | /* ---------------- 视图渲染 ---------------- */ |
|
1391 | 1422 |
|
1392 | 1423 | function enterGuest() { |
1393 | 1424 | isGuest = true; |
| 1425 | + pendingHashView = null; |
1394 | 1426 | activeView = "marketplace"; |
1395 | 1427 | $("#login-view").classList.add("hidden"); |
1396 | 1428 | $("#app").classList.remove("hidden"); |
|
1420 | 1452 | document.querySelector(".user-chip").classList.remove("hidden"); |
1421 | 1453 | $("#login-view").classList.add("hidden"); |
1422 | 1454 | $("#app").classList.remove("hidden"); |
1423 | | - switchView("dashboard"); |
| 1455 | + // URL hash 路由:登录后恢复刷新前的视图(无 hash 则仪表盘) |
| 1456 | + switchView(pendingHashView || "dashboard"); |
| 1457 | + pendingHashView = null; |
1424 | 1458 | toast("欢迎回来,阿零(演示账号)", "info"); |
1425 | 1459 | }); |
1426 | 1460 |
|
|
1661 | 1695 |
|
1662 | 1696 | document.addEventListener("DOMContentLoaded", () => { |
1663 | 1697 | document.title = "AITokenPool"; // 默认标题(rant 18:06:09 F:无视图时回「AITokenPool」) |
| 1698 | + // URL hash 路由(rant 20:39:30 A):加载时记录 hash 视图(登录后恢复);前进/后退触发 hashchange |
| 1699 | + pendingHashView = viewFromHash(); |
| 1700 | + window.addEventListener("hashchange", () => { |
| 1701 | + const id = viewFromHash(); |
| 1702 | + // 非法 hash → 回仪表盘但不重写 URL(避免 pushState 新增历史条目、后退需两次) |
| 1703 | + if (id && id !== activeView) switchView(id, { sync: hashIsValid() }); |
| 1704 | + }); |
1664 | 1705 | renderNav(); |
1665 | 1706 | bindEvents(); |
1666 | 1707 | renderView("dashboard"); |
|
0 commit comments