Add hub usage help page with settings nav toggle.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8652,6 +8652,82 @@ body.funds-fullscreen-open {
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 使用说明 ── */
|
||||
.help-toolbar {
|
||||
margin-bottom: 12px;
|
||||
min-height: 1.2em;
|
||||
}
|
||||
.help-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(180px, 220px) minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
.help-toc-card {
|
||||
padding: 16px 14px 18px;
|
||||
position: sticky;
|
||||
top: 72px;
|
||||
}
|
||||
.help-toc-title {
|
||||
margin: 0 0 12px;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--text-soft);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.help-toc-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.help-toc-item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 8px 10px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
color: var(--text-soft);
|
||||
font-size: 0.88rem;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.help-toc-item:hover {
|
||||
background: var(--surface-2, rgba(255, 255, 255, 0.04));
|
||||
color: var(--text);
|
||||
}
|
||||
.help-toc-item.is-active {
|
||||
background: var(--accent-soft, rgba(59, 130, 246, 0.12));
|
||||
color: var(--accent, #3b82f6);
|
||||
font-weight: 600;
|
||||
}
|
||||
.help-doc-card {
|
||||
padding: 18px 20px 20px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.help-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.help-toc-card {
|
||||
position: static;
|
||||
}
|
||||
.help-toc-nav {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.help-toc-item {
|
||||
width: auto;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.help-doc-card .strategy-doc-body {
|
||||
max-height: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 监控页:永续 / 期权分块 ── */
|
||||
.hub-monitor-block {
|
||||
margin-bottom: 4px;
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
return displayPref("show_nav_strategy", true);
|
||||
}
|
||||
|
||||
function showNavHelpPref() {
|
||||
return displayPref("show_nav_help", true);
|
||||
}
|
||||
|
||||
function showNavLogsPref() {
|
||||
return displayPref("show_nav_logs", true);
|
||||
}
|
||||
@@ -54,6 +58,7 @@
|
||||
const navAi = document.getElementById("nav-ai");
|
||||
const navCalc = document.getElementById("nav-calculator");
|
||||
const navStrategy = document.getElementById("nav-strategy");
|
||||
const navHelp = document.getElementById("nav-help");
|
||||
const navLogs = document.getElementById("nav-logs");
|
||||
if (navFunds) navFunds.classList.toggle("nav-hidden", d.show_nav_funds === false);
|
||||
if (navDash) navDash.classList.toggle("nav-hidden", d.show_nav_dashboard === false);
|
||||
@@ -62,6 +67,7 @@
|
||||
if (navAi) navAi.classList.toggle("nav-hidden", d.show_nav_ai === false);
|
||||
if (navCalc) navCalc.classList.toggle("nav-hidden", d.show_nav_calculator === false);
|
||||
if (navStrategy) navStrategy.classList.toggle("nav-hidden", d.show_nav_strategy === false);
|
||||
if (navHelp) navHelp.classList.toggle("nav-hidden", d.show_nav_help === false);
|
||||
if (navLogs) navLogs.classList.toggle("nav-hidden", d.show_nav_logs === false);
|
||||
}
|
||||
|
||||
@@ -73,6 +79,7 @@
|
||||
if (page === "ai") return showNavAiPref();
|
||||
if (page === "calculator") return showNavCalculatorPref();
|
||||
if (page === "strategy") return showNavStrategyPref();
|
||||
if (page === "help") return showNavHelpPref();
|
||||
if (page === "logs") return showNavLogsPref();
|
||||
return true;
|
||||
}
|
||||
@@ -87,6 +94,7 @@
|
||||
const aiCb = document.getElementById("pref-show-nav-ai");
|
||||
const calcCb = document.getElementById("pref-show-nav-calculator");
|
||||
const strategyCb = document.getElementById("pref-show-nav-strategy");
|
||||
const helpCb = document.getElementById("pref-show-nav-help");
|
||||
const logsCb = document.getElementById("pref-show-nav-logs");
|
||||
if (pnlCb) pnlCb.checked = d.show_account_pnl !== false;
|
||||
if (fundsCb) fundsCb.checked = d.show_nav_funds !== false;
|
||||
@@ -96,6 +104,7 @@
|
||||
if (aiCb) aiCb.checked = d.show_nav_ai !== false;
|
||||
if (calcCb) calcCb.checked = d.show_nav_calculator !== false;
|
||||
if (strategyCb) strategyCb.checked = d.show_nav_strategy !== false;
|
||||
if (helpCb) helpCb.checked = d.show_nav_help !== false;
|
||||
if (logsCb) logsCb.checked = d.show_nav_logs !== false;
|
||||
syncNavVisibility(data);
|
||||
}
|
||||
@@ -1208,6 +1217,7 @@
|
||||
if (p.includes("funds")) return "funds";
|
||||
if (p.includes("plan")) return "plan";
|
||||
if (p.includes("calculator")) return "calculator";
|
||||
if (p.includes("help")) return "help";
|
||||
if (p.includes("strategy")) return "strategy";
|
||||
if (p.includes("logs")) return "logs";
|
||||
if (p.includes("market")) return "market";
|
||||
@@ -1222,6 +1232,7 @@
|
||||
if (page === "funds") return "page-funds";
|
||||
if (page === "plan") return "page-plan";
|
||||
if (page === "calculator") return "page-calculator";
|
||||
if (page === "help") return "page-help";
|
||||
if (page === "strategy") return "page-strategy";
|
||||
if (page === "logs") return "page-logs";
|
||||
if (page === "market") return "page-market";
|
||||
@@ -1283,6 +1294,11 @@
|
||||
} else if (window.hubStrategyPage && window.hubStrategyPage.destroy) {
|
||||
window.hubStrategyPage.destroy();
|
||||
}
|
||||
if (page === "help" && window.hubHelpPage) {
|
||||
window.hubHelpPage.init();
|
||||
} else if (window.hubHelpPage && window.hubHelpPage.destroy) {
|
||||
window.hubHelpPage.destroy();
|
||||
}
|
||||
if (page === "logs" && window.hubLogsPage) {
|
||||
window.hubLogsPage.init();
|
||||
} else if (window.hubLogsPage && window.hubLogsPage.destroy) {
|
||||
@@ -4706,6 +4722,7 @@
|
||||
const aiCb = document.getElementById("pref-show-nav-ai");
|
||||
const calcCb = document.getElementById("pref-show-nav-calculator");
|
||||
const strategyCb = document.getElementById("pref-show-nav-strategy");
|
||||
const helpCb = document.getElementById("pref-show-nav-help");
|
||||
const logsCb = document.getElementById("pref-show-nav-logs");
|
||||
const supEnabled = document.getElementById("supervisor-enabled");
|
||||
const supProg = document.getElementById("supervisor-wechat-program");
|
||||
@@ -4727,6 +4744,7 @@
|
||||
show_nav_ai: aiCb ? !!aiCb.checked : true,
|
||||
show_nav_calculator: calcCb ? !!calcCb.checked : true,
|
||||
show_nav_strategy: strategyCb ? !!strategyCb.checked : true,
|
||||
show_nav_help: helpCb ? !!helpCb.checked : true,
|
||||
show_nav_logs: logsCb ? !!logsCb.checked : true,
|
||||
},
|
||||
supervisor: {
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 使用说明:中控 docs/help MD 章节.
|
||||
*/
|
||||
(function () {
|
||||
const page = document.getElementById("page-help");
|
||||
if (!page) return;
|
||||
|
||||
const tocEl = document.getElementById("help-toc-nav");
|
||||
const statusEl = document.getElementById("help-load-status");
|
||||
const docBody = document.getElementById("help-doc-body");
|
||||
const docSource = document.getElementById("help-doc-source");
|
||||
|
||||
let sectionsMeta = [];
|
||||
let activeKey = "quickstart";
|
||||
let cache = {};
|
||||
let bound = false;
|
||||
|
||||
async function apiFetch(url) {
|
||||
const r = await fetch(url, { credentials: "same-origin" });
|
||||
const data = await r.json();
|
||||
if (!r.ok || !data.ok) throw new Error((data && data.msg) || r.statusText || "请求失败");
|
||||
return data;
|
||||
}
|
||||
|
||||
function esc(s) {
|
||||
return String(s ?? "")
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
|
||||
function sectionFromHash() {
|
||||
const h = (window.location.hash || "").replace(/^#/, "").trim().toLowerCase();
|
||||
if (!h) return null;
|
||||
return sectionsMeta.some((s) => s.key === h) ? h : null;
|
||||
}
|
||||
|
||||
function setHash(key) {
|
||||
const next = `#${key}`;
|
||||
if (window.location.hash !== next) {
|
||||
history.replaceState(null, "", `/help${next}`);
|
||||
}
|
||||
}
|
||||
|
||||
function renderToc() {
|
||||
if (!tocEl) return;
|
||||
tocEl.innerHTML = sectionsMeta
|
||||
.map(
|
||||
(s) =>
|
||||
`<button type="button" class="help-toc-item${s.key === activeKey ? " is-active" : ""}" data-key="${esc(s.key)}">${esc(s.label)}</button>`
|
||||
)
|
||||
.join("");
|
||||
tocEl.querySelectorAll(".help-toc-item").forEach((btn) => {
|
||||
btn.addEventListener("click", () => {
|
||||
const key = btn.getAttribute("data-key");
|
||||
if (!key || key === activeKey) return;
|
||||
activeKey = key;
|
||||
setHash(key);
|
||||
renderToc();
|
||||
void loadSection(key);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderSection(data) {
|
||||
if (docBody) docBody.innerHTML = data.content_html || "";
|
||||
if (docSource) {
|
||||
docSource.textContent = data.md_source ? `来源: ${data.md_source}` : "";
|
||||
}
|
||||
if (statusEl) statusEl.textContent = "";
|
||||
}
|
||||
|
||||
async function loadSection(key) {
|
||||
if (cache[key]) {
|
||||
renderSection(cache[key]);
|
||||
return;
|
||||
}
|
||||
if (statusEl) statusEl.textContent = "加载中…";
|
||||
try {
|
||||
const data = await apiFetch(`/api/help/${encodeURIComponent(key)}`);
|
||||
cache[key] = data;
|
||||
renderSection(data);
|
||||
} catch (err) {
|
||||
if (statusEl) statusEl.textContent = "";
|
||||
if (docBody) docBody.innerHTML = `<p class="muted">${esc(err.message || "加载失败")}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMeta() {
|
||||
const data = await apiFetch("/api/help/meta");
|
||||
sectionsMeta = data.sections || [];
|
||||
const fromHash = sectionFromHash();
|
||||
if (fromHash) activeKey = fromHash;
|
||||
else if (sectionsMeta.length && !sectionsMeta.some((s) => s.key === activeKey)) {
|
||||
activeKey = sectionsMeta[0].key;
|
||||
}
|
||||
renderToc();
|
||||
await loadSection(activeKey);
|
||||
if (!sectionFromHash() && activeKey) setHash(activeKey);
|
||||
}
|
||||
|
||||
function bindOnce() {
|
||||
if (bound) return;
|
||||
bound = true;
|
||||
window.addEventListener("hashchange", () => {
|
||||
const key = sectionFromHash();
|
||||
if (!key || key === activeKey) return;
|
||||
activeKey = key;
|
||||
renderToc();
|
||||
void loadSection(key);
|
||||
});
|
||||
}
|
||||
|
||||
window.hubHelpPage = {
|
||||
init() {
|
||||
bindOnce();
|
||||
void loadMeta().catch((err) => {
|
||||
if (statusEl) statusEl.textContent = "";
|
||||
if (docBody) docBody.innerHTML = `<p class="muted">${esc(err.message || "加载失败")}</p>`;
|
||||
});
|
||||
},
|
||||
destroy() {},
|
||||
};
|
||||
})();
|
||||
@@ -52,6 +52,7 @@
|
||||
<a href="/plan" id="nav-plan">开仓计划</a>
|
||||
<a href="/monitor" id="nav-monitor">监控区</a>
|
||||
<a href="/strategy" id="nav-strategy">策略说明</a>
|
||||
<a href="/help" id="nav-help">使用说明</a>
|
||||
<a href="/market" id="nav-market">行情区</a>
|
||||
<a href="/calculator" id="nav-calculator">计算器</a>
|
||||
<a href="/archive" id="nav-archive">内照明心</a>
|
||||
@@ -890,6 +891,28 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="page-help" class="page hidden">
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1><span class="head-tag">HLP</span> 使用说明</h1>
|
||||
<p class="page-desc">中控与实例 · 日常操作指南(不含部署说明)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="help-toolbar">
|
||||
<span id="help-load-status" class="toolbar-meta"></span>
|
||||
</div>
|
||||
<div class="help-layout">
|
||||
<aside class="card help-toc-card">
|
||||
<h3 class="help-toc-title">目录</h3>
|
||||
<nav id="help-toc-nav" class="help-toc-nav" aria-label="使用说明目录"></nav>
|
||||
</aside>
|
||||
<section class="card help-doc-card">
|
||||
<div id="help-doc-body" class="strategy-doc-body prose"></div>
|
||||
<p id="help-doc-source" class="strategy-doc-source"></p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="page-logs" class="page hidden">
|
||||
<div class="page-head hub-logs-page-head">
|
||||
<div>
|
||||
@@ -1010,6 +1033,10 @@
|
||||
<input type="checkbox" id="pref-show-nav-strategy" checked />
|
||||
顶栏显示「策略说明」
|
||||
</label>
|
||||
<label class="chk-label settings-display-chk">
|
||||
<input type="checkbox" id="pref-show-nav-help" checked />
|
||||
顶栏显示「使用说明」
|
||||
</label>
|
||||
<label class="chk-label settings-display-chk">
|
||||
<input type="checkbox" id="pref-show-nav-logs" checked />
|
||||
顶栏显示「系统日志」
|
||||
@@ -1233,6 +1260,7 @@
|
||||
<script src="/assets/funds.js?v=20260707-hub-options-funds"></script>
|
||||
<script src="/assets/dashboard.js?v=20260708-options-expiry-cd"></script>
|
||||
<script src="/assets/strategy.js?v=3"></script>
|
||||
<script src="/assets/help.js?v=1"></script>
|
||||
<script src="/assets/logs.js?v=1"></script>
|
||||
<script src="/assets/ai_review_render.js?v=3"></script>
|
||||
<script src="/assets/time_close_ui.js?v=3"></script>
|
||||
|
||||
Reference in New Issue
Block a user