diff --git a/backend/services/contribution-service/prisma/migrations/0003_add_source_type_to_system_contribution_records/migration.sql b/backend/services/contribution-service/prisma/migrations/0003_add_source_type_to_system_contribution_records/migration.sql new file mode 100644 index 00000000..dd787ec7 --- /dev/null +++ b/backend/services/contribution-service/prisma/migrations/0003_add_source_type_to_system_contribution_records/migration.sql @@ -0,0 +1,12 @@ +-- AlterTable: Add source_type and level_depth columns to system_contribution_records +-- source_type: FIXED_RATE(固定比例分配) / LEVEL_OVERFLOW(层级溢出) / LEVEL_NO_ANCESTOR(无上线) / BONUS_TIER_1/2/3(团队奖励未解锁) +-- level_depth: 层级深度(1-15),仅对 LEVEL_OVERFLOW 和 LEVEL_NO_ANCESTOR 类型有效 + +ALTER TABLE "system_contribution_records" ADD COLUMN "source_type" VARCHAR(30) NOT NULL DEFAULT 'FIXED_RATE'; +ALTER TABLE "system_contribution_records" ADD COLUMN "level_depth" INTEGER; + +-- Remove default after adding column (existing records are FIXED_RATE) +ALTER TABLE "system_contribution_records" ALTER COLUMN "source_type" DROP DEFAULT; + +-- CreateIndex +CREATE INDEX "system_contribution_records_source_type_idx" ON "system_contribution_records"("source_type"); diff --git a/backend/services/contribution-service/prisma/schema.prisma b/backend/services/contribution-service/prisma/schema.prisma index f63775b1..84810b53 100644 --- a/backend/services/contribution-service/prisma/schema.prisma +++ b/backend/services/contribution-service/prisma/schema.prisma @@ -327,6 +327,11 @@ model SystemContributionRecord { sourceAdoptionId BigInt @map("source_adoption_id") sourceAccountSequence String @map("source_account_sequence") @db.VarChar(20) + // 来源类型:FIXED_RATE(固定比例分配) / LEVEL_OVERFLOW(层级溢出) / LEVEL_NO_ANCESTOR(无上线) / BONUS_TIER_1/2/3(团队奖励未解锁) + sourceType String @map("source_type") @db.VarChar(30) + // 层级深度:对于 LEVEL_OVERFLOW 和 LEVEL_NO_ANCESTOR 类型,表示第几级(1-15) + levelDepth Int? @map("level_depth") + distributionRate Decimal @map("distribution_rate") @db.Decimal(10, 6) amount Decimal @map("amount") @db.Decimal(30, 10) @@ -342,6 +347,7 @@ model SystemContributionRecord { @@index([systemAccountId]) @@index([sourceAdoptionId]) @@index([deletedAt]) + @@index([sourceType]) @@map("system_contribution_records") } diff --git a/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts b/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts index 51b1e138..0f4ca3d6 100644 --- a/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts +++ b/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts @@ -293,11 +293,17 @@ export class ContributionCalculationService { // 为每笔未分配算力创建 HEADQUARTERS 明细记录 for (const unallocated of result.unallocatedContributions) { + // 确定来源类型和层级深度 + const sourceType = unallocated.type as string; // LEVEL_OVERFLOW / LEVEL_NO_ANCESTOR / BONUS_TIER_1/2/3 + const levelDepth = unallocated.levelDepth; + const savedRecord = await this.systemAccountRepository.saveContributionRecord({ accountType: 'HEADQUARTERS', regionCode: null, sourceAdoptionId, sourceAccountSequence, + sourceType, + levelDepth, distributionRate: 0, // 未分配算力没有固定比例 amount: unallocated.amount, effectiveDate, @@ -311,6 +317,8 @@ export class ContributionCalculationService { null, sourceAdoptionId, sourceAccountSequence, + sourceType as any, + levelDepth, 0, unallocated.amount.value.toString(), effectiveDate, @@ -382,6 +390,8 @@ export class ContributionCalculationService { regionCode: sys.regionCode, sourceAdoptionId, sourceAccountSequence, + sourceType: 'FIXED_RATE', // 固定比例分配 + levelDepth: null, distributionRate: sys.rate.value.toNumber(), amount: sys.amount, effectiveDate, @@ -415,6 +425,8 @@ export class ContributionCalculationService { sys.regionCode, // 传递区域代码 sourceAdoptionId, sourceAccountSequence, + 'FIXED_RATE', // 固定比例分配 + null, // 无层级深度 sys.rate.value.toNumber(), sys.amount.value.toString(), effectiveDate, diff --git a/backend/services/contribution-service/src/domain/events/system-contribution-record-created.event.ts b/backend/services/contribution-service/src/domain/events/system-contribution-record-created.event.ts index 6ca1b87b..57375760 100644 --- a/backend/services/contribution-service/src/domain/events/system-contribution-record-created.event.ts +++ b/backend/services/contribution-service/src/domain/events/system-contribution-record-created.event.ts @@ -1,3 +1,18 @@ +/** + * 来源类型枚举 + * - FIXED_RATE: 固定比例分配(OPERATION 12%、PROVINCE 1%、CITY 2%) + * - LEVEL_OVERFLOW: 层级溢出归总部(上线未解锁该级别) + * - LEVEL_NO_ANCESTOR: 无上线归总部(该级无上线) + * - BONUS_TIER_1/2/3: 团队奖励未解锁归总部 + */ +export type SystemContributionSourceType = + | 'FIXED_RATE' + | 'LEVEL_OVERFLOW' + | 'LEVEL_NO_ANCESTOR' + | 'BONUS_TIER_1' + | 'BONUS_TIER_2' + | 'BONUS_TIER_3'; + /** * 系统账户算力明细创建事件 * 用于将系统账户的每笔算力来源明细同步到 mining-admin-service @@ -12,6 +27,8 @@ export class SystemContributionRecordCreatedEvent { public readonly regionCode: string | null, // 区域代码(省/市代码,如 440000, 440100) public readonly sourceAdoptionId: bigint, // 来源认种ID public readonly sourceAccountSequence: string, // 认种人账号 + public readonly sourceType: SystemContributionSourceType, // 来源类型 + public readonly levelDepth: number | null, // 层级深度(1-15),仅对 LEVEL_OVERFLOW/LEVEL_NO_ANCESTOR 有效 public readonly distributionRate: number, // 分配比例 public readonly amount: string, // 算力金额 public readonly effectiveDate: Date, // 生效日期 @@ -27,6 +44,8 @@ export class SystemContributionRecordCreatedEvent { regionCode: this.regionCode, sourceAdoptionId: this.sourceAdoptionId.toString(), sourceAccountSequence: this.sourceAccountSequence, + sourceType: this.sourceType, + levelDepth: this.levelDepth, distributionRate: this.distributionRate, amount: this.amount, effectiveDate: this.effectiveDate.toISOString(), diff --git a/backend/services/contribution-service/src/infrastructure/persistence/repositories/system-account.repository.ts b/backend/services/contribution-service/src/infrastructure/persistence/repositories/system-account.repository.ts index 4a4f3d4c..579a69a2 100644 --- a/backend/services/contribution-service/src/infrastructure/persistence/repositories/system-account.repository.ts +++ b/backend/services/contribution-service/src/infrastructure/persistence/repositories/system-account.repository.ts @@ -21,6 +21,8 @@ export interface SystemContributionRecord { systemAccountId: bigint; sourceAdoptionId: bigint; sourceAccountSequence: string; + sourceType: string; // 来源类型:FIXED_RATE / LEVEL_OVERFLOW / LEVEL_NO_ANCESTOR / BONUS_TIER_1/2/3 + levelDepth: number | null; // 层级深度(1-15),仅对层级相关类型有效 distributionRate: number; amount: ContributionAmount; effectiveDate: Date; @@ -224,6 +226,8 @@ export class SystemAccountRepository { regionCode: string | null; sourceAdoptionId: bigint; sourceAccountSequence: string; + sourceType: string; // 来源类型 + levelDepth?: number | null; // 层级深度 distributionRate: number; amount: ContributionAmount; effectiveDate: Date; @@ -239,6 +243,8 @@ export class SystemAccountRepository { systemAccountId: systemAccount.id, sourceAdoptionId: record.sourceAdoptionId, sourceAccountSequence: record.sourceAccountSequence, + sourceType: record.sourceType, + levelDepth: record.levelDepth ?? null, distributionRate: record.distributionRate, amount: record.amount.value, effectiveDate: record.effectiveDate, @@ -303,6 +309,8 @@ export class SystemAccountRepository { systemAccountId: record.systemAccountId, sourceAdoptionId: record.sourceAdoptionId, sourceAccountSequence: record.sourceAccountSequence, + sourceType: record.sourceType, + levelDepth: record.levelDepth, distributionRate: record.distributionRate, amount: new ContributionAmount(record.amount), effectiveDate: record.effectiveDate, diff --git a/backend/services/mining-admin-service/prisma/migrations/0001_init/migration.sql b/backend/services/mining-admin-service/prisma/migrations/0001_init/migration.sql index bd6a5060..6ff48a88 100644 --- a/backend/services/mining-admin-service/prisma/migrations/0001_init/migration.sql +++ b/backend/services/mining-admin-service/prisma/migrations/0001_init/migration.sql @@ -876,6 +876,10 @@ CREATE TABLE "synced_system_contribution_records" ( "region_code" TEXT, "source_adoption_id" BIGINT NOT NULL, "source_account_sequence" TEXT NOT NULL, + -- 来源类型: FIXED_RATE(固定比例) / LEVEL_OVERFLOW(层级溢出) / LEVEL_NO_ANCESTOR(无上线) / BONUS_TIER_1/2/3(团队奖励未解锁) + "source_type" VARCHAR(30) NOT NULL, + -- 层级深度(1-15),仅对 LEVEL_OVERFLOW 和 LEVEL_NO_ANCESTOR 类型有效 + "level_depth" INTEGER, "distribution_rate" DECIMAL(10,6) NOT NULL, "amount" DECIMAL(30,10) NOT NULL, "effective_date" DATE NOT NULL, @@ -893,4 +897,5 @@ CREATE UNIQUE INDEX "synced_system_contribution_records_original_record_id_key" CREATE INDEX "synced_system_contribution_records_account_type_region_code_idx" ON "synced_system_contribution_records"("account_type", "region_code"); CREATE INDEX "synced_system_contribution_records_source_adoption_id_idx" ON "synced_system_contribution_records"("source_adoption_id"); CREATE INDEX "synced_system_contribution_records_source_account_sequence_idx" ON "synced_system_contribution_records"("source_account_sequence"); +CREATE INDEX "synced_system_contribution_records_source_type_idx" ON "synced_system_contribution_records"("source_type"); CREATE INDEX "synced_system_contribution_records_created_at_idx" ON "synced_system_contribution_records"("created_at" DESC); diff --git a/backend/services/mining-admin-service/prisma/schema.prisma b/backend/services/mining-admin-service/prisma/schema.prisma index 828a01cb..0083602d 100644 --- a/backend/services/mining-admin-service/prisma/schema.prisma +++ b/backend/services/mining-admin-service/prisma/schema.prisma @@ -452,6 +452,11 @@ model SyncedSystemContributionRecord { sourceAdoptionId BigInt @map("source_adoption_id") // 来源认种ID sourceAccountSequence String @map("source_account_sequence") // 认种人账号 + // 来源类型: FIXED_RATE(固定比例) / LEVEL_OVERFLOW(层级溢出) / LEVEL_NO_ANCESTOR(无上线) / BONUS_TIER_1/2/3(团队奖励未解锁) + sourceType String @map("source_type") @db.VarChar(30) + // 层级深度(1-15),仅对 LEVEL_OVERFLOW 和 LEVEL_NO_ANCESTOR 类型有效 + levelDepth Int? @map("level_depth") + // 分配参数 distributionRate Decimal @map("distribution_rate") @db.Decimal(10, 6) // 分配比例 amount Decimal @map("amount") @db.Decimal(30, 10) // 算力金额 @@ -468,6 +473,7 @@ model SyncedSystemContributionRecord { @@index([accountType, regionCode]) @@index([sourceAdoptionId]) @@index([sourceAccountSequence]) + @@index([sourceType]) @@index([createdAt(sort: Desc)]) @@map("synced_system_contribution_records") } diff --git a/backend/services/mining-admin-service/src/application/services/system-accounts.service.ts b/backend/services/mining-admin-service/src/application/services/system-accounts.service.ts index 6191c0ca..98923e77 100644 --- a/backend/services/mining-admin-service/src/application/services/system-accounts.service.ts +++ b/backend/services/mining-admin-service/src/application/services/system-accounts.service.ts @@ -444,6 +444,9 @@ export class SystemAccountsService { regionCode: record.regionCode, sourceAdoptionId: record.sourceAdoptionId.toString(), sourceAccountSequence: record.sourceAccountSequence, + // 来源类型 + sourceType: record.sourceType, + levelDepth: record.levelDepth, // 认种订单详情 adoptionTreeCount: adoption?.treeCount || 0, adoptionDate: adoption?.adoptionDate || null, diff --git a/backend/services/mining-admin-service/src/infrastructure/kafka/cdc-sync.service.ts b/backend/services/mining-admin-service/src/infrastructure/kafka/cdc-sync.service.ts index a1a56a09..501dc8e7 100644 --- a/backend/services/mining-admin-service/src/infrastructure/kafka/cdc-sync.service.ts +++ b/backend/services/mining-admin-service/src/infrastructure/kafka/cdc-sync.service.ts @@ -673,6 +673,8 @@ export class CdcSyncService implements OnModuleInit { regionCode, sourceAdoptionId: BigInt(payload.sourceAdoptionId), sourceAccountSequence: payload.sourceAccountSequence, + sourceType: payload.sourceType || 'FIXED_RATE', // 来源类型 + levelDepth: payload.levelDepth ?? null, // 层级深度 distributionRate: payload.distributionRate, amount: payload.amount, effectiveDate: new Date(payload.effectiveDate), @@ -685,6 +687,8 @@ export class CdcSyncService implements OnModuleInit { regionCode, sourceAdoptionId: BigInt(payload.sourceAdoptionId), sourceAccountSequence: payload.sourceAccountSequence, + sourceType: payload.sourceType || 'FIXED_RATE', + levelDepth: payload.levelDepth ?? null, distributionRate: payload.distributionRate, amount: payload.amount, effectiveDate: new Date(payload.effectiveDate), diff --git a/frontend/mining-admin-web/src/features/system-accounts/api/system-accounts.api.ts b/frontend/mining-admin-web/src/features/system-accounts/api/system-accounts.api.ts index 95a58313..525d08bf 100644 --- a/frontend/mining-admin-web/src/features/system-accounts/api/system-accounts.api.ts +++ b/frontend/mining-admin-web/src/features/system-accounts/api/system-accounts.api.ts @@ -43,14 +43,25 @@ export interface SystemTransactionsResponse { pageSize: number; } +// 来源类型枚举 +export type ContributionSourceType = + | 'FIXED_RATE' // 固定比例分配(OPERATION 12%、PROVINCE 1%、CITY 2%) + | 'LEVEL_OVERFLOW' // 层级溢出归总部(上线未解锁该级别) + | 'LEVEL_NO_ANCESTOR' // 无上线归总部(该级无上线) + | 'BONUS_TIER_1' // 团队奖励T1未解锁归总部 + | 'BONUS_TIER_2' // 团队奖励T2未解锁归总部 + | 'BONUS_TIER_3'; // 团队奖励T3未解锁归总部 + // 算力来源明细记录 export interface SystemContributionRecord { - id: string; originalRecordId: string; accountType: string; regionCode: string | null; sourceAdoptionId: string; sourceAccountSequence: string; + // 来源类型 + sourceType: ContributionSourceType; + levelDepth: number | null; // 层级深度(1-15),仅对 LEVEL_OVERFLOW 和 LEVEL_NO_ANCESTOR 有效 // 认种订单详情 adoptionTreeCount: number; adoptionDate: string | null; diff --git a/frontend/mining-admin-web/src/features/system-accounts/components/contribution-records-table.tsx b/frontend/mining-admin-web/src/features/system-accounts/components/contribution-records-table.tsx index ae43b7e7..3430b6a7 100644 --- a/frontend/mining-admin-web/src/features/system-accounts/components/contribution-records-table.tsx +++ b/frontend/mining-admin-web/src/features/system-accounts/components/contribution-records-table.tsx @@ -16,7 +16,35 @@ import { formatDecimal } from '@/lib/utils/format'; import { format } from 'date-fns'; import { zhCN } from 'date-fns/locale'; import { ChevronLeft, ChevronRight, Users, FileStack, TrendingUp } from 'lucide-react'; -import type { SystemContributionRecord, SystemContributionStats } from '../api/system-accounts.api'; +import type { SystemContributionRecord, SystemContributionStats, ContributionSourceType } from '../api/system-accounts.api'; + +// 来源类型显示名称映射 +const SOURCE_TYPE_LABELS: Record = { + FIXED_RATE: '固定比例', + LEVEL_OVERFLOW: '层级溢出', + LEVEL_NO_ANCESTOR: '无上线', + BONUS_TIER_1: '团队T1', + BONUS_TIER_2: '团队T2', + BONUS_TIER_3: '团队T3', +}; + +// 来源类型颜色映射 +const SOURCE_TYPE_COLORS: Record = { + FIXED_RATE: 'bg-green-100 text-green-800', + LEVEL_OVERFLOW: 'bg-orange-100 text-orange-800', + LEVEL_NO_ANCESTOR: 'bg-red-100 text-red-800', + BONUS_TIER_1: 'bg-purple-100 text-purple-800', + BONUS_TIER_2: 'bg-purple-100 text-purple-800', + BONUS_TIER_3: 'bg-purple-100 text-purple-800', +}; + +// 获取来源类型显示文本 +function getSourceTypeDisplay(sourceType: ContributionSourceType, levelDepth: number | null): string { + if (sourceType === 'LEVEL_OVERFLOW' || sourceType === 'LEVEL_NO_ANCESTOR') { + return `${SOURCE_TYPE_LABELS[sourceType]}(第${levelDepth}级)`; + } + return SOURCE_TYPE_LABELS[sourceType] || sourceType; +} interface ContributionRecordsTableProps { records: SystemContributionRecord[]; @@ -110,6 +138,7 @@ export function ContributionRecordsTable({ 认种订单 认种用户 + 来源类型 认种树数 分配比例 算力金额 @@ -121,7 +150,7 @@ export function ContributionRecordsTable({ {isLoading ? ( [...Array(5)].map((_, i) => ( - {[...Array(7)].map((_, j) => ( + {[...Array(8)].map((_, j) => ( @@ -131,7 +160,7 @@ export function ContributionRecordsTable({ ) : records.length === 0 ? ( 暂无算力来源记录 @@ -164,6 +193,14 @@ export function ContributionRecordsTable({ )} + + + {getSourceTypeDisplay(record.sourceType, record.levelDepth)} + + {record.adoptionTreeCount > 0 ? record.adoptionTreeCount : '-'} diff --git a/挖矿.xlsx b/挖矿.xlsx new file mode 100644 index 00000000..98cf3306 Binary files /dev/null and b/挖矿.xlsx differ