feat(contribution): 添加系统账户算力来源类型字段
- 添加 sourceType 字段区分算力来源类型: - FIXED_RATE: 固定比例分配(OPERATION 12%、PROVINCE 1%、CITY 2%) - LEVEL_OVERFLOW: 层级溢出归总部(上线未解锁该级别) - LEVEL_NO_ANCESTOR: 无上线归总部(该级无上线) - BONUS_TIER_1/2/3: 团队奖励未解锁归总部 - 添加 levelDepth 字段记录层级深度(1-15级) - 更新前端表格显示来源类型列 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e89c3166bf
commit
e7260be219
|
|
@ -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");
|
||||
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<ContributionSourceType, string> = {
|
||||
FIXED_RATE: '固定比例',
|
||||
LEVEL_OVERFLOW: '层级溢出',
|
||||
LEVEL_NO_ANCESTOR: '无上线',
|
||||
BONUS_TIER_1: '团队T1',
|
||||
BONUS_TIER_2: '团队T2',
|
||||
BONUS_TIER_3: '团队T3',
|
||||
};
|
||||
|
||||
// 来源类型颜色映射
|
||||
const SOURCE_TYPE_COLORS: Record<ContributionSourceType, string> = {
|
||||
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({
|
|||
<TableRow>
|
||||
<TableHead>认种订单</TableHead>
|
||||
<TableHead>认种用户</TableHead>
|
||||
<TableHead>来源类型</TableHead>
|
||||
<TableHead className="text-right">认种树数</TableHead>
|
||||
<TableHead className="text-right">分配比例</TableHead>
|
||||
<TableHead className="text-right">算力金额</TableHead>
|
||||
|
|
@ -121,7 +150,7 @@ export function ContributionRecordsTable({
|
|||
{isLoading ? (
|
||||
[...Array(5)].map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
{[...Array(7)].map((_, j) => (
|
||||
{[...Array(8)].map((_, j) => (
|
||||
<TableCell key={j}>
|
||||
<Skeleton className="h-4 w-full" />
|
||||
</TableCell>
|
||||
|
|
@ -131,7 +160,7 @@ export function ContributionRecordsTable({
|
|||
) : records.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={7}
|
||||
colSpan={8}
|
||||
className="text-center text-muted-foreground py-8"
|
||||
>
|
||||
暂无算力来源记录
|
||||
|
|
@ -164,6 +193,14 @@ export function ContributionRecordsTable({
|
|||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className={`text-xs ${SOURCE_TYPE_COLORS[record.sourceType] || 'bg-gray-100 text-gray-800'}`}
|
||||
>
|
||||
{getSourceTypeDisplay(record.sourceType, record.levelDepth)}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<span className="font-mono text-sm">
|
||||
{record.adoptionTreeCount > 0 ? record.adoptionTreeCount : '-'}
|
||||
|
|
|
|||
Loading…
Reference in New Issue