feat: 全页面增加营业收入/优惠指标 + 修复趋势预测空数据 + 区域对比口径统一 + StorePage最新经营日概览
- 后端: 所有API的discount改为从bill_fact累计discount_total - 后端: revenue/daily-summary增加consumption字段 - 后端: situational-awareness/forecast修复c175字符串比较为timestamp - 后端: region/comparison去掉未知区域排除,统一口径 - 后端: daily-card增加营业收入/优惠指标,返回target_date/baseline_date - 前端: BossPage/DashboardPage/BankPage/StorePage/ExpenseOverviewTab/RegionalPage/RegionComparisonPage/RevenuePage 均增加营业收入和优惠指标卡 - 前端: StorePage日均经营概览改为最新经营日概览,显示具体对比日期 - 前端: 日期格式统一截取YYYY-MM-DD显示
This commit is contained in:
@@ -266,32 +266,41 @@ export function StorePage() {
|
||||
{/* KPI达成率 */}
|
||||
<KPISection month={month} level="store" storeCode={storeCode} />
|
||||
|
||||
{/* 最新经营概览 + 本周指标进度 一行 */}
|
||||
<div className="grid gap-4 lg:grid-cols-2">
|
||||
{/* 经营概览 */}
|
||||
<div className="rounded-lg border bg-card p-4">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h2 className="text-sm font-bold">日均经营概览({month})</h2>
|
||||
{anomalyCount > 0 && (
|
||||
<span className="rounded-md bg-red-100 px-2 py-0.5 text-xs font-medium text-red-700">{anomalyCount} 项异常</span>
|
||||
)}
|
||||
{/* 最新经营概览 */}
|
||||
<div className="rounded-lg border bg-card p-4">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-sm font-bold">最新经营日概览</h2>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{card?.target_date ? `${String(card.target_date).substring(0, 10)} 当日数据 vs ${String(card.baseline_date).substring(0, 10)} 一周前同日对比` : `${month} 月末单日 vs 一周前同日对比`}
|
||||
</p>
|
||||
</div>
|
||||
{allAnomalyItems.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground">暂无数据</p>
|
||||
) : (
|
||||
<div className="grid gap-2 md:grid-cols-3">
|
||||
{allAnomalyItems.map((item, idx) => (
|
||||
<div key={idx} className={`rounded-md border p-3 ${item.is_anomaly ? 'border-red-200 bg-red-50/50' : ''}`}>
|
||||
<p className="text-xs text-muted-foreground">{item.metric}</p>
|
||||
<p className={`mt-1 text-lg font-bold ${item.is_anomaly ? 'text-red-600' : ''}`}>
|
||||
{item.metric === '实收' ? formatCurrency(item.value) : formatNumber(item.value)}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">日基准: {item.metric === '实收' ? formatCurrency(item.baseline) : formatNumber(item.baseline)}{item.is_anomaly && <span className="text-red-500"> ⚠</span>}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{anomalyCount > 0 && (
|
||||
<span className="rounded-md bg-red-100 px-2 py-0.5 text-xs font-medium text-red-700">{anomalyCount} 项异常</span>
|
||||
)}
|
||||
</div>
|
||||
{allAnomalyItems.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground">暂无数据</p>
|
||||
) : (
|
||||
<div className="grid gap-2 grid-cols-5">
|
||||
{allAnomalyItems.map((item, idx) => {
|
||||
const isCurrency = item.metric === '实收' || item.metric === '营业收入' || item.metric === '优惠'
|
||||
return (
|
||||
<div key={idx} className={`rounded-md border p-3 ${item.is_anomaly ? 'border-red-200 bg-red-50/50' : ''}`}>
|
||||
<p className="text-xs text-muted-foreground">{item.metric}</p>
|
||||
<p className={`mt-1 text-lg font-bold ${item.is_anomaly ? 'text-red-600' : ''}`}>
|
||||
{isCurrency ? formatCurrency(item.value) : formatNumber(item.value)}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">日基准: {isCurrency ? formatCurrency(item.baseline) : formatNumber(item.baseline)}{item.is_anomaly && <span className="text-red-500"> ⚠</span>}</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 本周指标进度 */}
|
||||
<div className="grid gap-4 lg:grid-cols-2">
|
||||
|
||||
{/* 本周指标进度条 */}
|
||||
{followup && (
|
||||
@@ -515,7 +524,9 @@ export function StorePage() {
|
||||
{sc && Number(sc.received) > 0 && (
|
||||
<>
|
||||
{/* 核心指标 - 月度汇总 */}
|
||||
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-6">
|
||||
<div className="grid grid-cols-2 gap-3 md:grid-cols-4 lg:grid-cols-8">
|
||||
<MetricCard title="营业收入" value={sc.consumption} format="currency" />
|
||||
<MetricCard title="优惠" value={sc.discount} format="currency" />
|
||||
<MetricCard title="月度实收" value={sc.received} format="currency" />
|
||||
<MetricCard title="月度账单数" value={sc.bill_count} format="number" />
|
||||
<MetricCard title="客单价" value={sc.avg_bill_value} format="currency" />
|
||||
|
||||
Reference in New Issue
Block a user