(function (global) { "use strict"; const ICONS = { "chevron-left": '', "chevron-right": '', "sun": '', "moon": '', "bar-chart-3": '', "wand-2": '', "notebook-pen": '', "message-square": '', "settings": '', "inbox": '' }; function icon(name, size) { const body = ICONS[name] || ""; return '"; } function escapeHtml(value) { return String(value == null ? "" : value).replace(/[&<>"']/g, function (ch) { return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[ch]; }); } const stack = []; let internalNav = 0; let authMode = "login"; function currentHash() { let hash = window.location.hash || ""; if (!hash || hash === "#" || hash === "#/") return "#/home"; if (hash.charAt(0) !== "#") hash = "#" + hash; return hash; } function routeOf(hash) { const path = hash.replace(/^#\/?/, ""); const parts = path.split("/").filter(Boolean); return { name: parts[0] || "home", params: parts.slice(1) }; } function currentRoute() { return routeOf(stack.length ? stack[stack.length - 1] : currentHash()); } function setHash(hash) { internalNav++; window.location.hash = hash; } function navigate(hash) { stack.push(hash); setHash(hash); render(); } function replace(hash) { if (stack.length) stack[stack.length - 1] = hash; else stack.push(hash); setHash(hash); render(); } function parentRoute(route) { if (route.name === "hub") return "#/home"; if (route.name === "feature") return "#/hub/" + route.params[0]; if (route.name === "assistant") return "#/home"; return null; } function back() { if (stack.length > 1) { stack.pop(); setHash(stack[stack.length - 1]); render(); return; } const parent = parentRoute(currentRoute()); replace(parent || "#/home"); } function updateHeader(options) { document.getElementById("m-title").textContent = options.title || "小白复盘"; document.getElementById("m-back").hidden = !options.back; document.getElementById("m-actions").innerHTML = options.actions || ""; } function themeToggleHtml() { const dark = document.getElementById("m-app").dataset.theme === "dark"; const label = dark ? "切换到日间模式" : "切换到夜间模式"; return '"; } function placeholderHtml(title, subtitle) { return '
' + '' + icon("inbox", 26) + "" + "

" + escapeHtml(title) + "

" + "

" + escapeHtml(subtitle || "该页面将在后续批次实现,返回即可继续浏览。") + "

" + "
"; } function findFeatureLabel(key) { const hubs = global.MobileNav.hubs; for (const hubKey in hubs) { const items = hubs[hubKey].items || []; for (const item of items) { if (item.key === key) return item.label; } } return null; } function renderHome() { updateHeader({ title: "小白复盘", back: false, actions: themeToggleHtml() }); const items = global.MobileNav.entries.map(function (entry) { const route = entry.key === "assistant" ? "#/assistant/chat" : "#/hub/" + entry.key; return '
  • ' + '
  • "; }).join(""); document.getElementById("m-view").innerHTML = '
      ' + items + "
    "; } function renderHub(key) { const hub = global.MobileNav.hubs[key]; const title = hub ? hub.title : key; updateHeader({ title: title, back: true }); document.getElementById("m-view").innerHTML = placeholderHtml(title, "该入口的图标页将在后续批次实现。"); } function renderFeature(key) { const title = findFeatureLabel(key) || key; updateHeader({ title: title, back: true }); document.getElementById("m-view").innerHTML = placeholderHtml(title, "该功能页将在后续批次实现。"); } function renderAssistant() { updateHeader({ title: "复盘助手", back: true }); document.getElementById("m-view").innerHTML = placeholderHtml("复盘助手", "聊天工作台将在后续批次实现。"); } function renderAuth() { updateHeader({ title: "小白复盘", back: false, actions: "" }); document.getElementById("m-view").innerHTML = [ '
    ', '
    ', '', '

    小白复盘

    ', '

    登录后进入你的复盘空间

    ', "
    ", '
    ', '', '', "
    ", '
    ', '', '', '', '', '', "
    ", "
    " ].join(""); authMode = "login"; bindAuth(); } function setAuthMode(mode) { authMode = mode === "register" ? "register" : "login"; document.querySelectorAll("[data-auth-mode]").forEach(function (button) { button.classList.toggle("active", button.dataset.authMode === authMode); }); document.getElementById("m-auth-confirm-field").hidden = authMode !== "register"; document.getElementById("m-auth-confirm").required = authMode === "register"; document.getElementById("m-auth-password").autocomplete = authMode === "register" ? "new-password" : "current-password"; document.getElementById("m-auth-submit").textContent = authMode === "register" ? "注册并进入" : "登录"; document.getElementById("m-auth-error").hidden = true; } function bindAuth() { document.querySelectorAll("[data-auth-mode]").forEach(function (button) { button.addEventListener("click", function () { setAuthMode(button.dataset.authMode); }); }); document.getElementById("m-auth-form").addEventListener("submit", submitAuth); } async function submitAuth(event) { event.preventDefault(); const username = document.getElementById("m-auth-username").value.trim(); const password = document.getElementById("m-auth-password").value; const errorElement = document.getElementById("m-auth-error"); if (authMode === "register" && password !== document.getElementById("m-auth-confirm").value) { errorElement.textContent = "两次输入的密码不一致。"; errorElement.hidden = false; return; } const submit = document.getElementById("m-auth-submit"); submit.disabled = true; try { if (authMode === "register") { await global.MobileSession.register(username, password); } else { await global.MobileSession.login(username, password); } replace("#/home"); } catch (error) { errorElement.textContent = error.message || "账号操作失败"; errorElement.hidden = false; } finally { submit.disabled = false; } } function render() { const route = currentRoute(); if (route.name === "hub") renderHub(route.params[0]); else if (route.name === "feature") renderFeature(route.params.join("/")); else if (route.name === "assistant") renderAssistant(); else if (route.name === "auth") renderAuth(); else renderHome(); } function bindGlobalEvents() { document.getElementById("m-view").addEventListener("click", function (event) { const entry = event.target.closest("[data-route]"); if (entry) { navigate(entry.dataset.route); } }); document.getElementById("m-back").addEventListener("click", back); document.addEventListener("click", function (event) { const toggle = event.target.closest("[data-theme-toggle]"); if (!toggle) return; global.MobileTheme.toggle(); if (currentRoute().name === "home") { document.getElementById("m-actions").innerHTML = themeToggleHtml(); } }); window.addEventListener("hashchange", function () { if (internalNav > 0) { internalNav--; return; } const hash = currentHash(); if (stack.length > 1 && hash === stack[stack.length - 2]) { stack.pop(); } else if (hash !== stack[stack.length - 1]) { stack.push(hash); } render(); }); } function init() { bindGlobalEvents(); stack.length = 0; stack.push(currentHash()); render(); } global.MobileRouter = { init: init, navigate: navigate, replace: replace, back: back, render: render, currentRoute: currentRoute }; })(window);