// ============================================================================= // Admin Service - Prisma Schema // ============================================================================= generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // ============================================================================= // App Version Management // ============================================================================= model AppVersion { id String @id @default(uuid()) platform Platform versionCode Int // Android: versionCode, iOS: CFBundleVersion versionName String // 用户可见版本号,如 "1.2.3" buildNumber String // 构建号 downloadUrl String // APK/IPA 下载地址 fileSize BigInt // 文件大小(字节) fileSha256 String // 文件 SHA-256 校验和 minOsVersion String? // 最低操作系统版本要求 changelog String // 更新日志 isForceUpdate Boolean @default(false) // 是否强制更新 isEnabled Boolean @default(true) // 是否启用 releaseDate DateTime? // 发布日期 createdAt DateTime @default(now()) updatedAt DateTime @updatedAt createdBy String // 创建人ID updatedBy String? // 更新人ID @@index([platform, isEnabled]) @@index([platform, versionCode]) @@map("app_versions") } enum Platform { ANDROID IOS } // ============================================================================= // Notification System (通知系统) // ============================================================================= /// 系统通知 - 管理员发布的公告/通知 model Notification { id String @id @default(uuid()) title String // 通知标题 content String // 通知内容 type NotificationType // 通知类型 priority NotificationPriority @default(NORMAL) // 优先级 targetType TargetType @default(ALL) // 目标用户类型 targetLogic TargetLogic @default(ANY) @map("target_logic") // 多标签匹配逻辑 imageUrl String? // 可选的图片URL linkUrl String? // 可选的跳转链接 isEnabled Boolean @default(true) // 是否启用 publishedAt DateTime? // 发布时间(null表示草稿) expiresAt DateTime? // 过期时间(null表示永不过期) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt createdBy String // 创建人ID // 关联 readRecords NotificationRead[] targetTags NotificationTagTarget[] // BY_TAG 时使用 targetUsers NotificationUserTarget[] // SPECIFIC 时使用 @@index([isEnabled, publishedAt]) @@index([type]) @@index([targetType]) @@map("notifications") } /// 用户已读记录 model NotificationRead { id String @id @default(uuid()) notificationId String userSerialNum String // 用户序列号 readAt DateTime @default(now()) notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade) @@unique([notificationId, userSerialNum]) @@index([userSerialNum]) @@map("notification_reads") } /// 通知类型 enum NotificationType { SYSTEM // 系统通知 ACTIVITY // 活动通知 REWARD // 收益通知 UPGRADE // 升级通知 ANNOUNCEMENT // 公告 } /// 通知优先级 enum NotificationPriority { LOW NORMAL HIGH URGENT } /// 目标用户类型 enum TargetType { ALL // 所有用户 BY_TAG // 按标签匹配 SPECIFIC // 指定用户列表 } /// 多标签匹配逻辑 enum TargetLogic { ANY // 匹配任一标签 ALL // 匹配所有标签 } /// 通知-标签关联 model NotificationTagTarget { id String @id @default(uuid()) notificationId String @map("notification_id") tagId String @map("tag_id") notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade) tag UserTag @relation(fields: [tagId], references: [id], onDelete: Cascade) @@unique([notificationId, tagId]) @@index([tagId]) @@map("notification_tag_targets") } /// 通知-用户关联 (指定用户) model NotificationUserTarget { id String @id @default(uuid()) notificationId String @map("notification_id") accountSequence String @map("account_sequence") @db.VarChar(12) notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade) @@unique([notificationId, accountSequence]) @@index([accountSequence]) @@map("notification_user_targets") } // ============================================================================= // User Profile System (用户画像系统) - 面向通知 + 广告 // ============================================================================= // ----------------------------------------------------------------------------- // 标签分类 (Tag Category) - 标签的分组管理 // ----------------------------------------------------------------------------- /// 标签分类 model TagCategory { id String @id @default(uuid()) code String @unique @db.VarChar(50) // "lifecycle", "value", "behavior" name String @db.VarChar(100) // "生命周期", "价值分层", "行为特征" description String? @db.Text sortOrder Int @default(0) @map("sort_order") isEnabled Boolean @default(true) @map("is_enabled") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") tags UserTag[] @@index([code]) @@index([isEnabled]) @@map("tag_categories") } // ----------------------------------------------------------------------------- // 用户标签 (User Tag) - 增强版 // ----------------------------------------------------------------------------- /// 标签类型 enum TagType { MANUAL // 手动打标 (管理员操作) AUTO // 自动打标 (规则驱动) COMPUTED // 计算型 (实时计算,不存储关联) SYSTEM // 系统内置 (不可删除) } /// 标签值类型 enum TagValueType { BOOLEAN // 布尔型: 有/无 ENUM // 枚举型: 高/中/低 NUMBER // 数值型: 0-100分 STRING // 字符串型 } /// 用户标签定义 model UserTag { id String @id @default(uuid()) categoryId String? @map("category_id") code String @unique @db.VarChar(50) // "vip", "new_user", "whale" name String @db.VarChar(100) // "VIP用户", "新用户", "大客户" description String? @db.Text color String? @db.VarChar(20) // "#FF5722" type TagType @default(MANUAL) // 标签类型 valueType TagValueType @default(BOOLEAN) @map("value_type") // 标签值类型 // 枚举型标签的可选值 // 例如: ["高", "中", "低"] 或 ["活跃", "沉默", "流失"] enumValues Json? @map("enum_values") // 关联的自动规则 (type=AUTO 时使用) ruleId String? @unique @map("rule_id") rule UserClassificationRule? @relation(fields: [ruleId], references: [id], onDelete: SetNull) // 广告相关 isAdvertisable Boolean @default(true) @map("is_advertisable") // 是否可用于广告定向 estimatedUsers Int? @map("estimated_users") // 预估覆盖用户数 isEnabled Boolean @default(true) @map("is_enabled") sortOrder Int @default(0) @map("sort_order") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关联 category TagCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull) assignments UserTagAssignment[] notifications NotificationTagTarget[] @@index([categoryId]) @@index([code]) @@index([type]) @@index([isEnabled]) @@index([isAdvertisable]) @@map("user_tags") } // ----------------------------------------------------------------------------- // 用户-标签关联 - 支持标签值 // ----------------------------------------------------------------------------- /// 用户-标签关联 model UserTagAssignment { id String @id @default(uuid()) accountSequence String @map("account_sequence") @db.VarChar(12) tagId String @map("tag_id") // 标签值 (根据 valueType) // BOOLEAN: null (存在即为true) // ENUM: "高" / "中" / "低" // NUMBER: "85" (字符串存储) // STRING: 任意字符串 value String? @db.VarChar(100) assignedAt DateTime @default(now()) @map("assigned_at") assignedBy String? @map("assigned_by") // null=系统自动, 否则为管理员ID expiresAt DateTime? @map("expires_at") // 可选过期时间 source String? @db.VarChar(50) // 来源: "rule:xxx", "import", "manual", "kafka" tag UserTag @relation(fields: [tagId], references: [id], onDelete: Cascade) @@unique([accountSequence, tagId]) @@index([accountSequence]) @@index([tagId]) @@index([value]) @@index([expiresAt]) @@map("user_tag_assignments") } // ----------------------------------------------------------------------------- // 用户分类规则 (Classification Rule) // ----------------------------------------------------------------------------- /// 用户分类规则 model UserClassificationRule { id String @id @default(uuid()) name String @db.VarChar(100) // "30天内新用户" description String? @db.Text // 规则条件 (JSON) // 示例: // { // "type": "AND", // "rules": [ // { "field": "registeredAt", "operator": "within_days", "value": 30 }, // { "field": "kycStatus", "operator": "eq", "value": "VERIFIED" } // ] // } conditions Json isEnabled Boolean @default(true) @map("is_enabled") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // 关联的自动标签 tag UserTag? @@map("user_classification_rules") } // ----------------------------------------------------------------------------- // 用户特征 (User Features) - 数值型指标 // ----------------------------------------------------------------------------- /// 用户特征 - 计算后的用户画像指标 model UserFeature { id String @id @default(uuid()) accountSequence String @unique @map("account_sequence") @db.VarChar(12) // RFM 模型 rfmRecency Int? @map("rfm_recency") // 最近一次活跃距今天数 rfmFrequency Int? @map("rfm_frequency") // 过去30天活跃天数 rfmMonetary Decimal? @map("rfm_monetary") @db.Decimal(18, 2) // 累计消费金额 rfmScore Int? @map("rfm_score") // RFM综合分 (0-100) // 活跃度 activeLevel String? @map("active_level") @db.VarChar(20) // "高活跃", "中活跃", "低活跃", "沉默" lastActiveAt DateTime? @map("last_active_at") // 价值分层 valueLevel String? @map("value_level") @db.VarChar(20) // "高价值", "中价值", "低价值", "潜力" lifetimeValue Decimal? @map("lifetime_value") @db.Decimal(18, 2) // 用户生命周期价值 LTV // 生命周期 lifecycleStage String? @map("lifecycle_stage") @db.VarChar(20) // "新用户", "成长期", "成熟期", "衰退期", "流失" // 自定义特征 (JSON扩展) customFeatures Json? @map("custom_features") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([rfmScore]) @@index([activeLevel]) @@index([valueLevel]) @@index([lifecycleStage]) @@map("user_features") } // ----------------------------------------------------------------------------- // 人群包 (Audience Segment) - 复杂定向 // ----------------------------------------------------------------------------- /// 人群包用途 enum SegmentUsageType { GENERAL // 通用 NOTIFICATION // 通知定向 ADVERTISING // 广告定向 ANALYTICS // 数据分析 } /// 人群包 - 多条件组合的用户群 model AudienceSegment { id String @id @default(uuid()) name String @db.VarChar(100) // "高价值活跃用户" description String? @db.Text // 定向条件 (JSON) // { // "type": "AND", // "conditions": [ // { "type": "tag", "tagCode": "vip", "operator": "eq", "value": true }, // { "type": "feature", "field": "rfmScore", "operator": "gte", "value": 80 }, // { "type": "profile", "field": "province", "operator": "in", "value": ["广东", "浙江"] } // ] // } conditions Json // 预估数据 estimatedUsers Int? @map("estimated_users") lastCalculated DateTime? @map("last_calculated") // 用途 usageType SegmentUsageType @default(GENERAL) @map("usage_type") isEnabled Boolean @default(true) @map("is_enabled") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") createdBy String @map("created_by") @@index([usageType]) @@index([isEnabled]) @@map("audience_segments") } // ----------------------------------------------------------------------------- // 标签变更日志 (审计追踪) // ----------------------------------------------------------------------------- /// 标签变更操作 enum TagAction { ASSIGN // 打标签 UPDATE // 更新标签值 REMOVE // 移除标签 EXPIRE // 过期移除 } /// 标签变更日志 model UserTagLog { id String @id @default(uuid()) accountSequence String @map("account_sequence") @db.VarChar(12) tagCode String @map("tag_code") @db.VarChar(50) action TagAction oldValue String? @map("old_value") @db.VarChar(100) newValue String? @map("new_value") @db.VarChar(100) reason String? @db.VarChar(200) // "规则触发", "管理员操作", "导入", "过期清理" operatorId String? @map("operator_id") createdAt DateTime @default(now()) @map("created_at") @@index([accountSequence, createdAt]) @@index([tagCode]) @@index([action]) @@index([createdAt]) @@map("user_tag_logs") } // ============================================================================= // User Query View (用户查询视图 - 通过 Kafka 事件同步) // ============================================================================= /// 用户查询视图 - 本地物化视图,通过消费 Kafka 事件同步维护 /// 用于 admin-web 用户管理页面的查询,避免跨服务 HTTP 调用 model UserQueryView { userId BigInt @id @map("user_id") accountSequence String @unique @map("account_sequence") @db.VarChar(12) // 基本信息 (来自 identity-service 事件) nickname String? @db.VarChar(100) avatarUrl String? @map("avatar_url") @db.Text phoneNumberMasked String? @map("phone_number_masked") @db.VarChar(20) // 脱敏: 138****8888 // 推荐关系 inviterSequence String? @map("inviter_sequence") @db.VarChar(12) // KYC 状态 kycStatus String @default("NOT_VERIFIED") @map("kyc_status") @db.VarChar(20) // 认种统计 (来自 planting-service 事件) personalAdoptionCount Int @default(0) @map("personal_adoption_count") teamAddressCount Int @default(0) @map("team_address_count") teamAdoptionCount Int @default(0) @map("team_adoption_count") // 授权统计 (来自 authorization-service 事件) provinceAdoptionCount Int @default(0) @map("province_adoption_count") cityAdoptionCount Int @default(0) @map("city_adoption_count") // 排名 leaderboardRank Int? @map("leaderboard_rank") // 状态 status String @default("ACTIVE") @db.VarChar(20) isOnline Boolean @default(false) @map("is_online") // 时间戳 registeredAt DateTime @map("registered_at") lastActiveAt DateTime? @map("last_active_at") syncedAt DateTime @default(now()) @map("synced_at") @@index([accountSequence]) @@index([nickname]) @@index([status]) @@index([registeredAt]) @@index([personalAdoptionCount]) @@index([inviterSequence]) @@map("user_query_view") } // ============================================================================= // Kafka Event Tracking (事件消费追踪) // ============================================================================= /// 事件消费位置追踪 - 用于幂等性和断点续传 model EventConsumerOffset { id BigInt @id @default(autoincrement()) consumerGroup String @map("consumer_group") @db.VarChar(100) topic String @db.VarChar(100) partition Int offset BigInt updatedAt DateTime @default(now()) @map("updated_at") @@unique([consumerGroup, topic, partition]) @@map("event_consumer_offsets") } /// 已处理事件记录 - 用于幂等性检查 model ProcessedEvent { id BigInt @id @default(autoincrement()) eventId String @unique @map("event_id") @db.VarChar(100) eventType String @map("event_type") @db.VarChar(50) processedAt DateTime @default(now()) @map("processed_at") @@index([eventType]) @@index([processedAt]) @@map("processed_events") } // ============================================================================= // System Config (系统配置) // ============================================================================= /// 系统配置 - 键值对存储,用于存储各种系统设置 model SystemConfig { id String @id @default(uuid()) key String @unique @db.VarChar(100) // 配置键 value String @db.Text // 配置值 (JSON 格式) description String? @db.VarChar(255) // 配置描述 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") updatedBy String? @map("updated_by") // 更新人ID @@index([key]) @@map("system_configs") } // ============================================================================= // System Maintenance (系统维护公告) // ============================================================================= /// 系统维护公告 - 用于系统升级/维护期间阻断用户操作 model SystemMaintenance { id String @id @default(uuid()) title String @db.VarChar(100) // 标题:如"系统升级中" message String @db.Text // 说明:如"预计10:00恢复,请稍候" startTime DateTime @map("start_time") // 维护开始时间 endTime DateTime @map("end_time") // 维护结束时间 isActive Boolean @default(false) @map("is_active") // 是否激活 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") createdBy String @map("created_by") // 创建人ID updatedBy String? @map("updated_by") // 更新人ID @@index([isActive]) @@index([startTime, endTime]) @@map("system_maintenances") } // ============================================================================= // Co-Managed Wallet System (共管钱包系统) // ============================================================================= /// 共管钱包会话状态 enum WalletSessionStatus { WAITING // 等待参与方加入 READY // 所有参与方已就绪 PROCESSING // 密钥生成中 COMPLETED // 创建完成 FAILED // 创建失败 CANCELLED // 已取消 } /// 共管钱包会话 - 钱包创建过程的会话记录 model CoManagedWalletSession { id String @id @default(uuid()) walletName String @map("wallet_name") @db.VarChar(100) // 钱包名称 thresholdT Int @map("threshold_t") // 签名阈值 T thresholdN Int @map("threshold_n") // 参与方总数 N inviteCode String @unique @map("invite_code") @db.VarChar(20) // 邀请码 status WalletSessionStatus @default(WAITING) // 会话状态 participants String @db.Text // 参与方列表 (JSON) currentRound Int @default(0) @map("current_round") // 当前密钥生成轮次 totalRounds Int @default(3) @map("total_rounds") // 总轮次 publicKey String? @map("public_key") @db.VarChar(200) // 生成的公钥 error String? @db.Text // 错误信息 createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") createdBy String @map("created_by") @db.VarChar(100) // 创建者 @@index([inviteCode]) @@index([status]) @@index([createdBy]) @@index([createdAt]) @@map("co_managed_wallet_sessions") } /// 共管钱包 - 创建成功后的钱包记录 model CoManagedWallet { id String @id @default(uuid()) sessionId String @unique @map("session_id") // 关联的会话 ID name String @db.VarChar(100) // 钱包名称 publicKey String @map("public_key") @db.VarChar(200) // 钱包公钥 thresholdT Int @map("threshold_t") // 签名阈值 T thresholdN Int @map("threshold_n") // 参与方总数 N participants String @db.Text // 参与方列表 (JSON) createdAt DateTime @default(now()) @map("created_at") createdBy String @map("created_by") @db.VarChar(100) // 创建者 @@index([sessionId]) @@index([publicKey]) @@index([createdBy]) @@index([createdAt]) @@map("co_managed_wallets") }