feat(statistics): 恢复榴莲树认种数量趋势图表
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
24bcc45d5a
commit
4f3660f05e
|
|
@ -367,6 +367,58 @@ model ProcessedEvent {
|
||||||
@@index([processedAt])
|
@@index([processedAt])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 系统账户转出订单表
|
||||||
|
// 用于记录从系统账户(S开头/区域账户)转出到用户账户的订单
|
||||||
|
// ============================================
|
||||||
|
model SystemWithdrawalOrder {
|
||||||
|
id BigInt @id @default(autoincrement()) @map("order_id")
|
||||||
|
orderNo String @unique @map("order_no") @db.VarChar(50)
|
||||||
|
|
||||||
|
// 转出方(系统账户)
|
||||||
|
fromAccountSequence String @map("from_account_sequence") @db.VarChar(20) // 系统账户序列号
|
||||||
|
fromAccountName String @map("from_account_name") @db.VarChar(100) // 系统账户名称
|
||||||
|
|
||||||
|
// 接收方(用户账户)
|
||||||
|
toAccountSequence String @map("to_account_sequence") @db.VarChar(20) // 用户充值ID
|
||||||
|
toUserId BigInt @map("to_user_id") // 用户ID
|
||||||
|
toUserName String? @map("to_user_name") @db.VarChar(100) // 用户姓名
|
||||||
|
toAddress String @map("to_address") @db.VarChar(100) // 用户区块链地址
|
||||||
|
|
||||||
|
// 金额
|
||||||
|
amount Decimal @map("amount") @db.Decimal(20, 8)
|
||||||
|
chainType String @default("KAVA") @map("chain_type") @db.VarChar(20)
|
||||||
|
|
||||||
|
// 交易信息
|
||||||
|
txHash String? @map("tx_hash") @db.VarChar(100)
|
||||||
|
|
||||||
|
// 状态: PENDING -> FROZEN -> BROADCASTED -> CONFIRMED / FAILED
|
||||||
|
status String @default("PENDING") @map("status") @db.VarChar(20)
|
||||||
|
errorMessage String? @map("error_message") @db.VarChar(500)
|
||||||
|
|
||||||
|
// 操作者
|
||||||
|
operatorId String @map("operator_id") @db.VarChar(100)
|
||||||
|
operatorName String? @map("operator_name") @db.VarChar(100)
|
||||||
|
|
||||||
|
// 备注
|
||||||
|
memo String? @map("memo") @db.Text
|
||||||
|
|
||||||
|
// 时间戳
|
||||||
|
frozenAt DateTime? @map("frozen_at")
|
||||||
|
broadcastedAt DateTime? @map("broadcasted_at")
|
||||||
|
confirmedAt DateTime? @map("confirmed_at")
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
|
||||||
|
@@map("system_withdrawal_orders")
|
||||||
|
@@index([fromAccountSequence])
|
||||||
|
@@index([toAccountSequence])
|
||||||
|
@@index([toUserId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([txHash])
|
||||||
|
@@index([operatorId])
|
||||||
|
@@index([createdAt])
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 线下结算扣减记录表
|
// 线下结算扣减记录表
|
||||||
// 记录哪些 REWARD_SETTLED 流水已被"线下结算"扣减过
|
// 记录哪些 REWARD_SETTLED 流水已被"线下结算"扣减过
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,6 @@ export enum LedgerEntryType {
|
||||||
UNFREEZE = 'UNFREEZE',
|
UNFREEZE = 'UNFREEZE',
|
||||||
SYSTEM_ALLOCATION = 'SYSTEM_ALLOCATION', // 系统账户分配
|
SYSTEM_ALLOCATION = 'SYSTEM_ALLOCATION', // 系统账户分配
|
||||||
FEE_COLLECTION = 'FEE_COLLECTION', // 手续费归集
|
FEE_COLLECTION = 'FEE_COLLECTION', // 手续费归集
|
||||||
|
SYSTEM_TRANSFER_OUT = 'SYSTEM_TRANSFER_OUT', // 系统账户转出(从系统账户转到用户)
|
||||||
|
SYSTEM_TRANSFER_IN = 'SYSTEM_TRANSFER_IN', // 系统账户转入(用户收到系统账户的转账)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ function formatAmount(amount: string): string {
|
||||||
export default function StatisticsPage() {
|
export default function StatisticsPage() {
|
||||||
// [2026-01-04] 新增:主Tab切换 - 数据统计 vs 系统账户
|
// [2026-01-04] 新增:主Tab切换 - 数据统计 vs 系统账户
|
||||||
const [mainTab, setMainTab] = useState<'statistics' | 'system-accounts'>('statistics');
|
const [mainTab, setMainTab] = useState<'statistics' | 'system-accounts'>('statistics');
|
||||||
|
// 趋势图时间维度
|
||||||
|
const [trendPeriod, setTrendPeriod] = useState<'day' | 'week' | 'month' | 'quarter' | 'year'>('day');
|
||||||
|
|
||||||
// [2026-01-06] 新增:认种统计数据状态
|
// [2026-01-06] 新增:认种统计数据状态
|
||||||
const [plantingStats, setPlantingStats] = useState<PlantingGlobalStats | null>(null);
|
const [plantingStats, setPlantingStats] = useState<PlantingGlobalStats | null>(null);
|
||||||
|
|
@ -149,6 +151,25 @@ export default function StatisticsPage() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{/* 榴莲树认种数量趋势 */}
|
||||||
|
<section className={styles.statistics__card}>
|
||||||
|
<div className={styles.statistics__cardHeader}>
|
||||||
|
<b className={styles.statistics__cardTitle}>榴莲树认种数量趋势</b>
|
||||||
|
<div className={styles.statistics__periodTabs}>
|
||||||
|
{(['day', 'week', 'month', 'quarter', 'year'] as const).map((period) => (
|
||||||
|
<button
|
||||||
|
key={period}
|
||||||
|
className={cn(styles.statistics__periodTab, trendPeriod === period && styles['statistics__periodTab--active'])}
|
||||||
|
onClick={() => setTrendPeriod(period)}
|
||||||
|
>
|
||||||
|
{period === 'day' ? '日' : period === 'week' ? '周' : period === 'month' ? '月' : period === 'quarter' ? '季度' : '年度'}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.statistics__chartArea}>Chart Placeholder</div>
|
||||||
|
</section>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue