2026-06-28 15:11:48 +08:00

102 lines
3.0 KiB
JavaScript

import { EChart } from "../charts/EChart.jsx";
import { trendLabels } from "../data.js";
import { formatPercent, formatUsd } from "../format.js";
export function MoneyTrendPanel({ summary }) {
return (
<section className="money-analysis">
<article className="money-panel money-panel--chart">
<PanelHead label="充值与流水趋势" meta="近 7 日" value={formatUsd(summary.revenueUsd)} />
<EChart className="money-trend-chart" option={createTrendOption(summary)} />
</article>
<article className="money-panel money-panel--targets">
<PanelHead label="目标达成" meta="当日 / 当月" value={formatPercent(summary.monthProgress)} />
<ProgressRow label="当日充值" percent={summary.dayProgress} value={`${formatUsd(summary.rechargeUsd)} / ${formatUsd(summary.dayTargetUsd)}`} />
<ProgressRow label="当月充值" percent={summary.monthProgress} value={`${formatUsd(summary.monthActualUsd)} / ${formatUsd(summary.monthTargetUsd)}`} />
<div className="money-retention">
<span>次留 {formatPercent(summary.retention1)}</span>
<span>7 {formatPercent(summary.retention7)}</span>
<span>30 {formatPercent(summary.retention30)}</span>
</div>
</article>
</section>
);
}
export function PanelHead({ label, meta, value }) {
return (
<div className="money-panel-head">
<div>
<h2>{label}</h2>
<span>{meta}</span>
</div>
<strong>{value}</strong>
</div>
);
}
function ProgressRow({ label, percent, value }) {
return (
<div className="money-progress">
<div>
<span>{label}</span>
<strong>{formatPercent(percent)}</strong>
</div>
<i>
<b style={{ width: `${Math.min(Number(percent) || 0, 100)}%` }} />
</i>
<small>{value}</small>
</div>
);
}
function createTrendOption(summary) {
return {
animationDuration: 520,
color: ["#2563eb", "#16a34a"],
grid: { bottom: 30, containLabel: true, left: 6, right: 16, top: 24 },
legend: {
bottom: 0,
icon: "roundRect",
itemHeight: 8,
itemWidth: 16,
textStyle: { color: "#64748b" }
},
tooltip: {
backgroundColor: "#ffffff",
borderColor: "#d8e0ec",
trigger: "axis",
textStyle: { color: "#0f172a" },
valueFormatter: (value) => formatUsd(value)
},
xAxis: {
axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.18)" } },
axisTick: { show: false },
data: trendLabels,
type: "category"
},
yAxis: {
axisLabel: { formatter: (value) => `${Math.round(value / 1000)}k` },
splitLine: { lineStyle: { color: "rgba(100, 116, 139, 0.16)" } },
type: "value"
},
series: [
{
areaStyle: { opacity: 0.12 },
data: summary.rechargeTrend,
name: "充值",
smooth: true,
symbol: "circle",
symbolSize: 6,
type: "line"
},
{
barMaxWidth: 18,
data: summary.revenueTrend,
name: "流水",
type: "bar"
}
]
};
}