178 lines
5.8 KiB
JavaScript
178 lines
5.8 KiB
JavaScript
/**
|
|
* 实例手机壳: ≤720px 底栏 +「更多」,与 embed soft-nav 同步.
|
|
*/
|
|
(function (global) {
|
|
const PRIMARY = { trade: 1, key_monitor: 1, options: 1 };
|
|
const MQ = "(max-width: 720px)";
|
|
|
|
function isEmbedShell() {
|
|
return document.body && document.body.getAttribute("data-embed-shell") === "1";
|
|
}
|
|
|
|
function isMobileLayout() {
|
|
return window.matchMedia(MQ).matches;
|
|
}
|
|
|
|
function syncPhoneClass() {
|
|
if (!document.body) return;
|
|
document.body.classList.toggle("inst-phone", isMobileLayout());
|
|
}
|
|
|
|
function currentTab() {
|
|
if (global.InstanceEmbed && typeof global.InstanceEmbed.getTab === "function") {
|
|
return global.InstanceEmbed.getTab();
|
|
}
|
|
try {
|
|
const t = new URLSearchParams(location.search).get("tab");
|
|
if (t) return t;
|
|
} catch (_) {}
|
|
return (document.body && document.body.getAttribute("data-page")) || "trade";
|
|
}
|
|
|
|
function closeMore() {
|
|
document.body.classList.remove("inst-mobile-more-open");
|
|
const more = document.getElementById("inst-mobile-more");
|
|
const btn = document.getElementById("inst-m-tab-more");
|
|
if (more) more.setAttribute("aria-hidden", "true");
|
|
if (btn) btn.setAttribute("aria-expanded", "false");
|
|
syncTabActive(currentTab());
|
|
}
|
|
|
|
function openMore() {
|
|
if (!isMobileLayout()) return;
|
|
document.body.classList.add("inst-mobile-more-open");
|
|
const more = document.getElementById("inst-mobile-more");
|
|
const btn = document.getElementById("inst-m-tab-more");
|
|
if (more) more.setAttribute("aria-hidden", "false");
|
|
if (btn) btn.setAttribute("aria-expanded", "true");
|
|
syncTabActive(currentTab());
|
|
}
|
|
|
|
function toggleMore() {
|
|
if (document.body.classList.contains("inst-mobile-more-open")) closeMore();
|
|
else openMore();
|
|
}
|
|
|
|
function syncTabActive(tab) {
|
|
const page = tab || currentTab();
|
|
const primary = !!PRIMARY[page];
|
|
const moreOpen = document.body.classList.contains("inst-mobile-more-open");
|
|
document.querySelectorAll("#inst-mobile-tabbar .inst-m-tab").forEach((el) => {
|
|
const t = el.getAttribute("data-embed-tab") || "";
|
|
let on = false;
|
|
if (t === "more") on = moreOpen || !primary;
|
|
else on = !moreOpen && t === page;
|
|
el.classList.toggle("active", on);
|
|
});
|
|
document.querySelectorAll("#inst-mobile-more .inst-mobile-more-nav [data-embed-tab]").forEach((a) => {
|
|
a.classList.toggle("active", a.getAttribute("data-embed-tab") === page);
|
|
});
|
|
}
|
|
|
|
/** embed 切页时关闭「更多」并同步高亮 */
|
|
function onTabChange(tab) {
|
|
document.body.classList.remove("inst-mobile-more-open");
|
|
const more = document.getElementById("inst-mobile-more");
|
|
const btn = document.getElementById("inst-m-tab-more");
|
|
if (more) more.setAttribute("aria-hidden", "true");
|
|
if (btn) btn.setAttribute("aria-expanded", "false");
|
|
syncTabActive(tab);
|
|
}
|
|
|
|
function goTab(tab) {
|
|
if (!tab || tab === "more") return;
|
|
closeMore();
|
|
if (global.InstanceEmbed && typeof global.InstanceEmbed.loadTab === "function") {
|
|
if (tab === currentTab()) {
|
|
syncTabActive(tab);
|
|
return;
|
|
}
|
|
void global.InstanceEmbed.loadTab(tab);
|
|
return;
|
|
}
|
|
const pathMap = {
|
|
dashboard: "/dashboard",
|
|
key_monitor: "/key_monitor",
|
|
trade: "/trade",
|
|
strategy: "/strategy",
|
|
strategy_records: "/strategy/records",
|
|
options: "/options",
|
|
options_review: "/options/review",
|
|
hedge_plan: "/hedge-plan",
|
|
records: "/records",
|
|
stats: "/stats",
|
|
risk_policy: "/risk_policy",
|
|
system_guide: "/system_guide",
|
|
env_config: "/env_config",
|
|
settings: "/settings",
|
|
};
|
|
location.href = pathMap[tab] || "/trade";
|
|
}
|
|
|
|
function bindChrome() {
|
|
const moreBtn = document.getElementById("inst-m-tab-more");
|
|
const backdrop = document.getElementById("inst-mobile-more-backdrop");
|
|
const closeBtn = document.getElementById("inst-mobile-more-close");
|
|
if (moreBtn) {
|
|
moreBtn.addEventListener("click", (ev) => {
|
|
ev.preventDefault();
|
|
toggleMore();
|
|
});
|
|
}
|
|
if (backdrop) backdrop.addEventListener("click", closeMore);
|
|
if (closeBtn) closeBtn.addEventListener("click", closeMore);
|
|
document.addEventListener("keydown", (ev) => {
|
|
if (ev.key === "Escape" && document.body.classList.contains("inst-mobile-more-open")) {
|
|
closeMore();
|
|
}
|
|
});
|
|
|
|
document.querySelectorAll("#inst-mobile-tabbar .inst-m-tab[data-embed-tab]").forEach((el) => {
|
|
if (el.getAttribute("data-embed-tab") === "more") return;
|
|
el.addEventListener("click", (ev) => {
|
|
if (ev.ctrlKey || ev.metaKey || ev.shiftKey || ev.altKey) return;
|
|
ev.preventDefault();
|
|
goTab(el.getAttribute("data-embed-tab"));
|
|
});
|
|
});
|
|
document.querySelectorAll("#inst-mobile-more .inst-mobile-more-nav [data-embed-tab]").forEach((a) => {
|
|
a.addEventListener("click", (ev) => {
|
|
if (ev.ctrlKey || ev.metaKey || ev.shiftKey || ev.altKey) return;
|
|
ev.preventDefault();
|
|
goTab(a.getAttribute("data-embed-tab"));
|
|
});
|
|
});
|
|
}
|
|
|
|
function boot() {
|
|
if (!isEmbedShell()) return;
|
|
if (!document.getElementById("inst-mobile-tabbar")) return;
|
|
syncPhoneClass();
|
|
bindChrome();
|
|
syncTabActive(currentTab());
|
|
let resizeTimer = null;
|
|
window.addEventListener("resize", () => {
|
|
clearTimeout(resizeTimer);
|
|
resizeTimer = setTimeout(() => {
|
|
const was = document.body.classList.contains("inst-phone");
|
|
syncPhoneClass();
|
|
if (!isMobileLayout()) closeMore();
|
|
else if (!was) syncTabActive(currentTab());
|
|
}, 120);
|
|
});
|
|
}
|
|
|
|
global.InstanceMobileNav = {
|
|
syncTabActive,
|
|
onTabChange,
|
|
closeMore,
|
|
isMobileLayout,
|
|
};
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", boot);
|
|
} else {
|
|
boot();
|
|
}
|
|
})(typeof window !== "undefined" ? window : globalThis);
|