window.XiaobaiPageModules.register("popularity", ["popularityView"], { enter: ["loadPopularity"], }); /* PRESERVATION-SOURCE-BEGIN app.js:2584-2659 */ async function loadPopularity(force = false) { if (state.popularityLoading) return; state.popularityLoading = true; const button = document.querySelector("#popularityRefreshButton"); button.disabled = true; setText("popularityDateLabel", "正在读取人气榜"); try { const query = new URLSearchParams({ trade_date: elements.tradeDate.value }); if (force) query.set("force", "1"); state.popularityData = await apiRequest(`/api/popularity?${query}`); renderPopularity(); } catch (error) { setText("popularityDateLabel", error.message || "人气榜暂不可用"); document.querySelector("#popularityTableBody").innerHTML = ""; document.querySelector("#popularityEmpty").hidden = false; showToast(error.message || "人气榜加载失败"); } finally { state.popularityLoading = false; button.disabled = false; } } function renderPopularity() { const payload = state.popularityData; if (!payload) return; const summary = payload.summary || {}; setText("popularityDateLabel", `${payload.meta?.carried_forward ? "最近有效榜单" : "榜单日期"} ${payload.meta?.trade_date || "--"}`); const topNames = (rows) => (rows || []).slice(0, 3).map((item) => item.name).filter(Boolean).join(" · ") || "--"; document.querySelector("#popularitySummary").innerHTML = [ ["同花顺热度 Top3", topNames(payload.ths), `共 ${number(summary.ths_count)} 只上榜`], ["东方财富热度 Top3", topNames(payload.dc), `共 ${number(summary.dc_count)} 只上榜`], ["双榜共识", `${number(summary.dual_count)} 只`, "同时进入两榜,共识度更高"], ].map(([label, value, detail], index) => `
${label}${escapeHtml(value)}${escapeHtml(detail)}
`).join(""); renderPopularityTable(); } function renderPopularityTable() { const source = state.popularitySource; let rows = [...(state.popularityData?.[source] || [])]; if (state.popularityQuery) { rows = rows.filter((item) => `${item.code} ${item.name} ${(item.concepts || []).join(" ")}`.toLocaleLowerCase("zh-CN").includes(state.popularityQuery)); } const combined = source === "combined"; const sourceName = source === "ths" ? "同花顺" : source === "dc" ? "东方财富" : "双榜综合"; setText("popularityTableTitle", `${sourceName}榜`); setText("popularityTableNote", combined ? "按双榜排名综合排序 · 已隐藏重复的榜单状态" : "按榜单名次排序 · 状态显示是否同时进入另一榜"); const headers = [ ["排名", "number num"], ["股票", ""], ["最新价(元)", "number num"], ["涨跌幅(%)", "number num"], ...(source !== "dc" ? [["同花顺", "number num"]] : []), ...(source !== "ths" ? [["东方财富", "number num"]] : []), ["排名变化", "number num"], ["热门概念", ""], ...(!combined ? [["榜单状态", ""]] : []), ]; document.querySelector("#popularityTableHead").innerHTML = headers.map(([label, className]) => `${label}`).join(""); const body = document.querySelector("#popularityTableBody"); body.innerHTML = rows.map((row, index) => { const thsRank = source === "ths" ? row.rank : row.ths_rank; const dcRank = source === "dc" ? row.rank : row.dc_rank; const move = row.rank_change; const movement = move === null || move === undefined ? "新" : number(move) > 0 ? `↑${number(move)}` : number(move) < 0 ? `↓${Math.abs(number(move))}` : "持平"; return ` ${index + 1}${index < 3 ? '' : ""}
${escapeHtml(row.name)}${escapeHtml(row.code)}
${row.price == null ? "" : formatNumber(row.price, 2)} ${row.change == null ? "" : signed(row.change)} ${source !== "dc" ? `${thsRank ? number(thsRank) : ""}` : ""} ${source !== "ths" ? `${dcRank ? number(dcRank) : ""}` : ""} ${movement} ${escapeHtml((row.concepts || []).slice(0, 3).join("、"))} ${!combined ? `${row.dual_source ? "双榜共识" : "单榜入选"}` : ""} `; }).join(""); bindStockRows(body); markAutoSortableHeaders(body.closest("table")); document.querySelector("#popularityEmpty").hidden = rows.length > 0; } /* PRESERVATION-SOURCE-END app.js:2584-2659 */