diff --git a/app/frontend/m/js/pages.js b/app/frontend/m/js/pages.js index b6a8fda..0f5e8a0 100644 --- a/app/frontend/m/js/pages.js +++ b/app/frontend/m/js/pages.js @@ -109,6 +109,7 @@ seq: 0, calCursor: null, sort: { key: "", dir: null }, + sortTable: { cols: null, reapply: null }, detail: null, sentimentHistory: null, sentimentRange: 20, @@ -189,10 +190,9 @@ } function toggleSort(key) { - const cfg = pageConfig(state.key); - if (!cfg) return; - const cols = columnsFor(cfg); - const col = findColumn(cols, key); + const active = state.sortTable; + if (!active || !active.cols) return; + const col = findColumn(active.cols, key); if (!col || !sortableColumn(col)) return; const firstDir = isNumericType(col.type) ? "desc" : "asc"; if (state.sort.key !== key) { @@ -202,7 +202,7 @@ } else { state.sort = { key: "", dir: null }; } - renderTableBody(); + active.reapply(); } /* ---------------------------------------------------------------- cells */ @@ -670,6 +670,7 @@ const cfg = pageConfig(key); if (!cfg) return; const cols = columnsFor(cfg); + state.sortTable = { cols: cols, reapply: renderTableBody }; const rows = sortedRows(prepareRows(key), cols); const scroll = document.getElementById("m-table-scroll"); if (!scroll) return; @@ -728,11 +729,21 @@ return cfg || null; } - function tableScrollHtml(subKey, rows, opts) { + function mountSortableTable(containerId, subKey, rowsProvider, opts) { const cols = columnsForKey(subKey); - if (!cols) return emptyHtml(); - if (!rows || !rows.length) return emptyHtml(); - return '
' + buildTable(cols, rows, opts || {}) + "
"; + if (!cols) return; + const reapply = function () { + const container = document.getElementById(containerId); + if (!container) return; + const rows = sortedRows(rowsProvider() || [], cols); + if (!rows.length) { + container.innerHTML = emptyHtml(); + return; + } + container.innerHTML = buildTable(cols, rows, opts || {}); + }; + state.sortTable = { cols: cols, reapply: reapply }; + reapply(); } function complexFrame(key, bodyHtml) { @@ -750,6 +761,7 @@ state.popularity = null; state.calCursor = null; state.sort = { key: "", dir: null }; + state.sortTable = { cols: null, reapply: null }; state.detail = null; state.sentimentHistory = null; state.rotation = null; @@ -876,7 +888,6 @@ const history = state.sentimentHistory || {}; const rawRows = history.rows || []; const latest = rawRows.length ? rawRows[rawRows.length - 1] : null; - const tableRows = rawRows.slice().reverse(); let card = ""; if (latest) { @@ -908,13 +919,15 @@ return '"; }).join(""); - const histRows = tableRows.map(function (r) { - return Object.assign({}, r, { trade_date: displayCompactDate(r.trade_date) }); - }); - scroll.innerHTML = card + '
历史明细 ' + rangeTabs + "
" + - tableScrollHtml("market/sentiment/history", histRows, {}); + '
'; + mountSortableTable("m-sentiment-hist", "market/sentiment/history", function () { + const raw = (state.sentimentHistory && state.sentimentHistory.rows) || []; + return raw.slice().reverse().map(function (r) { + return Object.assign({}, r, { trade_date: displayCompactDate(r.trade_date) }); + }); + }, {}); } function sentMetric(label, valueHtml, tone) { @@ -1109,10 +1122,12 @@ if (!body) return; if (payload.error) { body.innerHTML = emptyHtml(); return; } const meta = payload.meta || {}; - const rows = payload.rows || []; const metaLine = '
' + escapeHtml(displayCompactDate(meta.trade_date) || "--") + " · " + number(meta.quoted_count) + " / " + number(meta.member_count) + " 只
"; - body.innerHTML = metaLine + tableScrollHtml("market/rotation/members", rows, { noLink: true }); + body.innerHTML = metaLine + '
'; + mountSortableTable("m-rotation-members-table", "market/rotation/members", function () { + return (state.rotationMembers && state.rotationMembers.rows) || []; + }, { noLink: true }); } /* ----- 竞价 ----- */ @@ -1226,11 +1241,7 @@ } function renderAuctionTable() { - const table = document.getElementById("m-auction-table"); - if (!table) return; - const rows = auctionRows(); - if (!rows.length) { table.innerHTML = emptyHtml(); return; } - table.innerHTML = buildTable(columnsForKey("market/auction"), rows); + mountSortableTable("m-auction-table", "market/auction", auctionRows, {}); } /* ----- 题材库 ----- */ @@ -1325,7 +1336,10 @@ '
' + escapeHtml(theme.code || "--") + " · " + escapeHtml(displayCompactDate(meta.trade_date) || "--") + "
" + '
' + metrics + "
" + '
成分股
' + - tableScrollHtml("market/themes/members", payload.members || [], { noLink: true }); + '
'; + mountSortableTable("m-theme-members-table", "market/themes/members", function () { + return (state.themesDetail && state.themesDetail.members) || []; + }, { noLink: true }); } /* ----- 龙虎榜 ----- */ @@ -1466,10 +1480,11 @@ totRow("卖出", trader.sell_million, "down") + totRow("净额", trader.net_buy_million, changeClass(trader.net_buy_million)) + "" + - tableScrollHtml("market/dragon/operations", ops, { noLink: true }) + + '
' + "", { detail: true } ); + mountSortableTable("m-dragon-ops-table", "market/dragon/operations", function () { return ops; }, { noLink: true }); } function totRow(label, value, cls) {