function renderMarketBreadth(overview) { const up = number(overview.up_count); const down = number(overview.down_count); const flat = Math.max(0, number(overview.flat_count)); const total = Math.max(1, up + down + flat); const upRate = up / total * 100; const flatRate = flat / total * 100; const downRate = down / total * 100; const panel = document.querySelector(".market-breadth-panel"); panel.classList.remove("breadth-enter"); void panel.offsetWidth; panel.classList.add("breadth-enter"); setText("breadthDataTime", dashboardDataTimestamp(state.dashboard?.meta || {})); animateMetric("breadthRatio", upRate, (value) => `${formatNumber(value, 1)}%`); animateMetric("breadthUpCount", up, (value) => formatNumber(Math.round(value))); animateMetric("breadthDownCount", down, (value) => formatNumber(Math.round(value))); setText("breadthUpLegend", `${formatNumber(up)}(${formatNumber(upRate, 1)}%)`); setText("breadthFlatLegend", `${formatNumber(flat)}(${formatNumber(flatRate, 1)}%)`); setText("breadthDownLegend", `${formatNumber(down)}(${formatNumber(downRate, 1)}%)`); document.querySelector("#breadthFlatLegendItem").hidden = flat === 0; const limitUp = number(overview.limit_up_count); const limitDown = number(overview.limit_down_count); const breadthLabel = upRate < 20 ? "宽度极差" : upRate < 40 ? "宽度偏弱" : upRate < 55 ? "宽度均衡" : "宽度偏强"; setText("breadthWarning", `△ ${breadthLabel},涨跌停 ${limitUp}:${limitDown}`); const bars = [ ["breadthUpBar", upRate], ["breadthFlatBar", flatRate], ["breadthDownBar", downRate], ]; bars.forEach(([id, width]) => { const bar = document.getElementById(id); const targetWidth = `${Math.max(width, width > 0 ? 0.8 : 0)}%`; bar.style.transition = "none"; bar.style.width = "0%"; requestAnimationFrame(() => requestAnimationFrame(() => { bar.style.transition = "width 760ms var(--ease-out)"; bar.style.width = targetWidth; })); bar.title = `${formatNumber(width, 1)}%`; }); }