generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================ // 龙虎榜排名表 (聚合根1) // 存储各周期榜单的实际排名数据 // ============================================ model LeaderboardRanking { id BigInt @id @default(autoincrement()) @map("ranking_id") // === 榜单信息 === leaderboardType String @map("leaderboard_type") @db.VarChar(30) // DAILY/WEEKLY/MONTHLY periodKey String @map("period_key") @db.VarChar(20) // 2024-01-15 / 2024-W03 / 2024-01 // === 用户信息 === userId BigInt @map("user_id") isVirtual Boolean @default(false) @map("is_virtual") // 是否虚拟账户 // === 排名信息 === rankPosition Int @map("rank_position") // 实际排名 displayPosition Int @map("display_position") // 显示排名(含虚拟) previousRank Int? @map("previous_rank") // 上次排名 // === 分值信息 === totalTeamPlanting Int @default(0) @map("total_team_planting") // 团队总认种 maxDirectTeamPlanting Int @default(0) @map("max_direct_team_planting") // 最大直推团队认种 effectiveScore Int @default(0) @map("effective_score") // 有效分值 // === 用户快照 === userSnapshot Json @map("user_snapshot") // { nickname, avatar, accountNo } // === 时间戳 === periodStartAt DateTime @map("period_start_at") periodEndAt DateTime @map("period_end_at") calculatedAt DateTime @default(now()) @map("calculated_at") createdAt DateTime @default(now()) @map("created_at") @@unique([leaderboardType, periodKey, userId], name: "uk_type_period_user") @@map("leaderboard_rankings") @@index([leaderboardType, periodKey, displayPosition], name: "idx_display_rank") @@index([leaderboardType, periodKey, effectiveScore(sort: Desc)], name: "idx_score") @@index([userId], name: "idx_ranking_user") @@index([periodKey], name: "idx_period") @@index([isVirtual], name: "idx_virtual") } // ============================================ // 龙虎榜配置表 (聚合根2) // 管理榜单开关、虚拟数量、显示设置 // ============================================ model LeaderboardConfig { id BigInt @id @default(autoincrement()) @map("config_id") configKey String @unique @map("config_key") @db.VarChar(50) // GLOBAL / DAILY / WEEKLY / MONTHLY // === 榜单开关 === dailyEnabled Boolean @default(true) @map("daily_enabled") weeklyEnabled Boolean @default(true) @map("weekly_enabled") monthlyEnabled Boolean @default(true) @map("monthly_enabled") // === 虚拟排名设置 === virtualRankingEnabled Boolean @default(false) @map("virtual_ranking_enabled") virtualAccountCount Int @default(0) @map("virtual_account_count") // 虚拟账户数量 // === 显示设置 === displayLimit Int @default(30) @map("display_limit") // 前端显示数量 // === 刷新设置 === refreshIntervalMinutes Int @default(5) @map("refresh_interval_minutes") // === 时间戳 === createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("leaderboard_configs") } // ============================================ // 虚拟账户表 // 存储系统生成的虚拟排名账户 // ============================================ model VirtualAccount { id BigInt @id @default(autoincrement()) @map("virtual_account_id") // === 账户信息 === accountType String @map("account_type") @db.VarChar(30) // RANKING_VIRTUAL / SYSTEM_PROVINCE / SYSTEM_CITY / HEADQUARTERS displayName String @map("display_name") @db.VarChar(100) avatar String? @map("avatar") @db.VarChar(255) // === 区域信息(省市公司用)=== provinceCode String? @map("province_code") @db.VarChar(10) cityCode String? @map("city_code") @db.VarChar(10) // === 虚拟分值范围(排名虚拟账户用)=== minScore Int? @map("min_score") maxScore Int? @map("max_score") currentScore Int @default(0) @map("current_score") // === 账户余额(省市公司用)=== usdtBalance Decimal @default(0) @map("usdt_balance") @db.Decimal(20, 8) hashpowerBalance Decimal @default(0) @map("hashpower_balance") @db.Decimal(20, 8) // === 状态 === isActive Boolean @default(true) @map("is_active") // === 时间戳 === createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("virtual_accounts") @@index([accountType], name: "idx_va_type") @@index([provinceCode], name: "idx_va_province") @@index([cityCode], name: "idx_va_city") @@index([isActive], name: "idx_va_active") } // ============================================ // 虚拟排名条目表 // 每个周期的虚拟排名数据 // ============================================ model VirtualRankingEntry { id BigInt @id @default(autoincrement()) @map("entry_id") // === 关联虚拟账户 === virtualAccountId BigInt @map("virtual_account_id") // === 榜单信息 === leaderboardType String @map("leaderboard_type") @db.VarChar(30) periodKey String @map("period_key") @db.VarChar(20) // === 排名信息 === displayPosition Int @map("display_position") // 占据的显示位置 generatedScore Int @map("generated_score") // 生成的分值 // === 显示信息 === displayName String @map("display_name") @db.VarChar(100) avatar String? @map("avatar") @db.VarChar(255) // === 时间戳 === createdAt DateTime @default(now()) @map("created_at") @@unique([leaderboardType, periodKey, displayPosition], name: "uk_vr_type_period_pos") @@map("virtual_ranking_entries") @@index([virtualAccountId], name: "idx_vr_va") @@index([leaderboardType, periodKey], name: "idx_vr_type_period") } // ============================================ // 榜单历史快照表 // 保存每个周期结束时的完整榜单数据 // ============================================ model LeaderboardSnapshot { id BigInt @id @default(autoincrement()) @map("snapshot_id") // === 榜单信息 === leaderboardType String @map("leaderboard_type") @db.VarChar(30) periodKey String @map("period_key") @db.VarChar(20) // === 快照数据 === rankingsData Json @map("rankings_data") // 完整排名数据 // === 统计信息 === totalParticipants Int @map("total_participants") // 参与人数 topScore Int @map("top_score") // 最高分 averageScore Int @map("average_score") // 平均分 // === 时间戳 === periodStartAt DateTime @map("period_start_at") periodEndAt DateTime @map("period_end_at") snapshotAt DateTime @default(now()) @map("snapshot_at") @@unique([leaderboardType, periodKey], name: "uk_snapshot_type_period") @@map("leaderboard_snapshots") @@index([leaderboardType], name: "idx_snapshot_type") @@index([periodKey], name: "idx_snapshot_period") } // ============================================ // 虚拟账户交易记录表 // 记录省市公司账户的资金变动 // ============================================ model VirtualAccountTransaction { id BigInt @id @default(autoincrement()) @map("transaction_id") virtualAccountId BigInt @map("virtual_account_id") // === 交易信息 === transactionType String @map("transaction_type") @db.VarChar(30) // INCOME / EXPENSE amount Decimal @map("amount") @db.Decimal(20, 8) currency String @map("currency") @db.VarChar(10) // USDT / HASHPOWER // === 来源信息 === sourceType String? @map("source_type") @db.VarChar(50) // PLANTING_REWARD / MANUAL sourceId String? @map("source_id") @db.VarChar(100) sourceUserId BigInt? @map("source_user_id") // === 备注 === memo String? @map("memo") @db.VarChar(500) // === 时间戳 === createdAt DateTime @default(now()) @map("created_at") @@map("virtual_account_transactions") @@index([virtualAccountId], name: "idx_vat_account") @@index([transactionType], name: "idx_vat_type") @@index([createdAt(sort: Desc)], name: "idx_vat_created") } // ============================================ // 龙虎榜事件表 // ============================================ model LeaderboardEvent { id BigInt @id @default(autoincrement()) @map("event_id") eventType String @map("event_type") @db.VarChar(50) // 聚合根信息 aggregateId String @map("aggregate_id") @db.VarChar(100) aggregateType String @map("aggregate_type") @db.VarChar(50) // 事件数据 eventData Json @map("event_data") // 元数据 userId BigInt? @map("user_id") occurredAt DateTime @default(now()) @map("occurred_at") @db.Timestamp(6) version Int @default(1) @map("version") @@map("leaderboard_events") @@index([aggregateType, aggregateId], name: "idx_lb_event_aggregate") @@index([eventType], name: "idx_lb_event_type") @@index([occurredAt], name: "idx_lb_event_occurred") }