import { memo } from 'react'; import { CLINICAL_COLORS } from './chartColors'; export interface BoxRow { label: string; p25: number; median: number; p75: number; n: number; } interface BoxPlotRowsProps { rows: BoxRow[]; /** 数值单位后缀,如 "天" / ""。 */ unit?: string; /** 标签列宽(px)。 */ labelWidth?: number; } /** * 横向箱线图(p25–中位–p75)。Recharts 无原生 box plot, * 故用纯 div 渲染:每行一条从 p25 到 p75 的横条,中位处一根竖向刻度。 * 复用于「各病种住院天数」与「年龄别BMI」。 */ export const BoxPlotRows = memo(function BoxPlotRows({ rows, unit = '', labelWidth = 96, }: BoxPlotRowsProps) { if (!rows || rows.length === 0) { return
暂无数据
; } // 统一横轴域:覆盖所有行的 p25..p75,留一点边距。 const domainMin = Math.min(...rows.map((r) => r.p25)); const domainMax = Math.max(...rows.map((r) => r.p75)); const span = domainMax - domainMin || 1; const pct = (v: number) => ((v - domainMin) / span) * 100; return (
{rows.map((r) => { const left = pct(r.p25); const right = pct(r.p75); const width = Math.max(right - left, 0.5); const medianLeft = pct(r.median); return (
{r.label}
{/* p25–p75 箱体 */}
{/* 中位刻度 */}
{r.p25}–{r.median}–{r.p75} {unit} n={r.n}
); })}
); });