feat(dashboard): add boss dashboard H5 and APIs
Implement the mobile dashboard frontend, admin overview APIs, report archive export, and local dev proxy so the boss dashboard can run against real backend data while preserving MSW demos. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import { CapsuleTabs, Tag } from 'antd-mobile'
|
||||
import { useState } from 'react'
|
||||
import { formatMoney, formatNumber } from '../../../utils/format'
|
||||
import type { SnapshotSlot, TodaySnapshot } from '../types'
|
||||
|
||||
type TodaySnapshotSectionProps = {
|
||||
snapshots: TodaySnapshot[]
|
||||
}
|
||||
|
||||
const statusMap = {
|
||||
pending: { color: 'default', label: '待生成' },
|
||||
success: { color: 'success', label: '已生成' },
|
||||
failed: { color: 'danger', label: '生成失败' },
|
||||
temporary: { color: 'warning', label: '临时数据' },
|
||||
} as const
|
||||
|
||||
export function TodaySnapshotSection({ snapshots }: TodaySnapshotSectionProps) {
|
||||
const [activeSlot, setActiveSlot] = useState<SnapshotSlot>('1015')
|
||||
const activeSnapshot = snapshots.find((snapshot) => snapshot.slot === activeSlot) ?? snapshots[0]
|
||||
const status = statusMap[activeSnapshot.status]
|
||||
|
||||
return (
|
||||
<section className="section-block snapshot-section">
|
||||
<div className="section-title-row">
|
||||
<div>
|
||||
<p className="section-kicker">今日节点</p>
|
||||
<h2>抢购 / 寄卖快报</h2>
|
||||
</div>
|
||||
<Tag color={status.color}>{status.label}</Tag>
|
||||
</div>
|
||||
|
||||
<CapsuleTabs activeKey={activeSlot} onChange={(key) => setActiveSlot(key as SnapshotSlot)}>
|
||||
{snapshots.map((snapshot) => (
|
||||
<CapsuleTabs.Tab title={snapshot.title.replace(' ', '')} key={snapshot.slot} />
|
||||
))}
|
||||
</CapsuleTabs>
|
||||
|
||||
<div className="snapshot-card">
|
||||
<p className="snapshot-message">{activeSnapshot.message}</p>
|
||||
{activeSnapshot.generatedAt && <p className="snapshot-time">生成时间:{activeSnapshot.generatedAt}</p>}
|
||||
<div className="snapshot-grid">
|
||||
<span>
|
||||
采购用户<strong>{formatNumber(activeSnapshot.purchaseUsers)}人</strong>
|
||||
</span>
|
||||
<span>
|
||||
订单数<strong>{formatNumber(activeSnapshot.orderCount)}单</strong>
|
||||
</span>
|
||||
<span>
|
||||
成交额<strong>{formatMoney(activeSnapshot.dealAmount)}</strong>
|
||||
</span>
|
||||
<span>
|
||||
支付额<strong>{formatMoney(activeSnapshot.paidAmount)}</strong>
|
||||
</span>
|
||||
<span>
|
||||
新增商品<strong>{formatNumber(activeSnapshot.newMerchandiseCount)}件</strong>
|
||||
</span>
|
||||
<span>
|
||||
奖金变化<strong>{formatMoney(Number(activeSnapshot.selfBonusChange) + Number(activeSnapshot.shareBonusChange))}</strong>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user