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 3aba403b..8bfab135 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 @@ -383,8 +383,12 @@ export class SystemAccountsService { */ async getSystemAccountContributionStats(accountType: string, regionCode: string | null) { // 获取算力账户信息 - const contribution = await this.prisma.syncedSystemContribution.findUnique({ - where: { accountType_regionCode: { accountType, regionCode } }, + // 使用 findFirst 替代 findUnique,因为 regionCode 可以为 null + const contribution = await this.prisma.syncedSystemContribution.findFirst({ + where: { + accountType, + regionCode: regionCode === null ? { equals: null } : regionCode, + }, }); const whereClause = regionCode 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 c29f58dc..d3babc9a 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 @@ -540,20 +540,37 @@ export class CdcSyncService implements OnModuleInit { private async handleSystemContributionUpdated(event: ServiceEvent, tx: TransactionClient): Promise { const { payload } = event; - await tx.syncedSystemContribution.upsert({ - where: { accountType: payload.accountType }, - create: { - accountType: payload.accountType, - name: payload.name, - contributionBalance: payload.contributionBalance || 0, - contributionNeverExpires: payload.contributionNeverExpires || false, - }, - update: { - name: payload.name, - contributionBalance: payload.contributionBalance, - contributionNeverExpires: payload.contributionNeverExpires, + const accountType = payload.accountType; + const regionCode = payload.regionCode || null; + + // 使用 findFirst + create/update 替代 upsert,因为 regionCode 可以为 null + const existing = await tx.syncedSystemContribution.findFirst({ + where: { + accountType, + regionCode: regionCode === null ? { equals: null } : regionCode, }, }); + + if (existing) { + await tx.syncedSystemContribution.update({ + where: { id: existing.id }, + data: { + name: payload.name, + contributionBalance: payload.contributionBalance, + contributionNeverExpires: payload.contributionNeverExpires, + }, + }); + } else { + await tx.syncedSystemContribution.create({ + data: { + accountType, + regionCode, + name: payload.name, + contributionBalance: payload.contributionBalance || 0, + contributionNeverExpires: payload.contributionNeverExpires || false, + }, + }); + } } /** @@ -567,23 +584,33 @@ export class CdcSyncService implements OnModuleInit { const accountType = payload.accountType; // OPERATION / PROVINCE / CITY / HEADQUARTERS const regionCode = payload.regionCode || null; - // 使用 accountType + regionCode 作为复合唯一键 - await tx.syncedSystemContribution.upsert({ + // 使用 findFirst + create/update 替代 upsert,因为 regionCode 可以为 null + const existing = await tx.syncedSystemContribution.findFirst({ where: { - accountType_regionCode: { accountType, regionCode }, - }, - create: { accountType, - regionCode, - name: payload.name, - contributionBalance: payload.contributionBalance || 0, - contributionNeverExpires: true, // 系统账户算力永不过期 - }, - update: { - name: payload.name, - contributionBalance: payload.contributionBalance, + regionCode: regionCode === null ? { equals: null } : regionCode, }, }); + + if (existing) { + await tx.syncedSystemContribution.update({ + where: { id: existing.id }, + data: { + name: payload.name, + contributionBalance: payload.contributionBalance, + }, + }); + } else { + await tx.syncedSystemContribution.create({ + data: { + accountType, + regionCode, + name: payload.name, + contributionBalance: payload.contributionBalance || 0, + contributionNeverExpires: true, // 系统账户算力永不过期 + }, + }); + } } /** diff --git a/backend/services/mining-service/src/api/controllers/admin.controller.ts b/backend/services/mining-service/src/api/controllers/admin.controller.ts index b102e165..38a61082 100644 --- a/backend/services/mining-service/src/api/controllers/admin.controller.ts +++ b/backend/services/mining-service/src/api/controllers/admin.controller.ts @@ -199,12 +199,12 @@ export class AdminController { const skip = (pageNum - 1) * pageSizeNum; // 先通过 accountType + regionCode 查找系统账户 - const account = await this.prisma.systemMiningAccount.findUnique({ + // 使用 findFirst 替代 findUnique,因为 regionCode 可以为 null + const regionCodeValue = regionCode || null; + const account = await this.prisma.systemMiningAccount.findFirst({ where: { - accountType_regionCode: { - accountType, - regionCode: regionCode || null, - }, + accountType, + regionCode: regionCodeValue === null ? { equals: null } : regionCodeValue, }, }); @@ -215,7 +215,7 @@ export class AdminController { page: pageNum, pageSize: pageSizeNum, accountType, - regionCode: regionCode || null, + regionCode: regionCodeValue, }; } @@ -247,7 +247,7 @@ export class AdminController { page: pageNum, pageSize: pageSizeNum, accountType, - regionCode: regionCode || null, + regionCode: regionCodeValue, }; } @@ -269,12 +269,12 @@ export class AdminController { const skip = (pageNum - 1) * pageSizeNum; // 先通过 accountType + regionCode 查找系统账户 - const account = await this.prisma.systemMiningAccount.findUnique({ + // 使用 findFirst 替代 findUnique,因为 regionCode 可以为 null + const regionCodeValue = regionCode || null; + const account = await this.prisma.systemMiningAccount.findFirst({ where: { - accountType_regionCode: { - accountType, - regionCode: regionCode || null, - }, + accountType, + regionCode: regionCodeValue === null ? { equals: null } : regionCodeValue, }, }); @@ -285,7 +285,7 @@ export class AdminController { page: pageNum, pageSize: pageSizeNum, accountType, - regionCode: regionCode || null, + regionCode: regionCodeValue, }; } @@ -305,7 +305,7 @@ export class AdminController { transactions: transactions.map((tx) => ({ id: tx.id, accountType, - regionCode: regionCode || null, + regionCode: regionCodeValue, type: tx.type, amount: tx.amount.toString(), balanceBefore: tx.balanceBefore.toString(), @@ -319,7 +319,7 @@ export class AdminController { page: pageNum, pageSize: pageSizeNum, accountType, - regionCode: regionCode || null, + regionCode: regionCodeValue, }; } diff --git a/backend/services/mining-service/src/application/services/mining-distribution.service.ts b/backend/services/mining-service/src/application/services/mining-distribution.service.ts index f409f723..be197f12 100644 --- a/backend/services/mining-service/src/application/services/mining-distribution.service.ts +++ b/backend/services/mining-service/src/application/services/mining-distribution.service.ts @@ -531,7 +531,8 @@ export class MiningDistributionService { let systemParticipantCount = 0; let pendingParticipantCount = 0; const systemRedisData: Array<{ - accountType: string; // 改为字符串支持组合键 + accountType: string; + regionCode: string | null; reward: ShareAmount; contribution: ShareAmount; }> = []; diff --git a/backend/services/mining-service/src/infrastructure/persistence/repositories/system-mining-account.repository.ts b/backend/services/mining-service/src/infrastructure/persistence/repositories/system-mining-account.repository.ts index 805a9413..67ba2ebb 100644 --- a/backend/services/mining-service/src/infrastructure/persistence/repositories/system-mining-account.repository.ts +++ b/backend/services/mining-service/src/infrastructure/persistence/repositories/system-mining-account.repository.ts @@ -24,9 +24,11 @@ export class SystemMiningAccountRepository { accountType: SystemAccountType, regionCode: string | null, ): Promise { - const record = await this.prisma.systemMiningAccount.findUnique({ + // 使用 findFirst 替代 findUnique,因为 regionCode 可以为 null + const record = await this.prisma.systemMiningAccount.findFirst({ where: { - accountType_regionCode: { accountType, regionCode }, + accountType, + regionCode: regionCode === null ? { equals: null } : regionCode, }, }); @@ -67,20 +69,26 @@ export class SystemMiningAccountRepository { ]; for (const account of accounts) { - await this.prisma.systemMiningAccount.upsert({ + // 使用 findFirst + create 替代 upsert,因为 regionCode 可以为 null + const existing = await this.prisma.systemMiningAccount.findFirst({ where: { - accountType_regionCode: { accountType: account.accountType, regionCode: null }, - }, - create: { accountType: account.accountType, - regionCode: null, - name: account.name, - totalMined: 0, - availableBalance: 0, - totalContribution: 0, + regionCode: { equals: null }, }, - update: {}, }); + + if (!existing) { + await this.prisma.systemMiningAccount.create({ + data: { + accountType: account.accountType, + regionCode: null, + name: account.name, + totalMined: 0, + availableBalance: 0, + totalContribution: 0, + }, + }); + } } } @@ -93,22 +101,33 @@ export class SystemMiningAccountRepository { name: string, contribution: ShareAmount, ): Promise { - await this.prisma.systemMiningAccount.upsert({ + // 使用 findFirst + create/update 替代 upsert,因为 regionCode 可以为 null + const existing = await this.prisma.systemMiningAccount.findFirst({ where: { - accountType_regionCode: { accountType, regionCode }, - }, - create: { accountType, - regionCode, - name, - totalContribution: contribution.value, - lastSyncedAt: new Date(), - }, - update: { - totalContribution: contribution.value, - lastSyncedAt: new Date(), + regionCode: regionCode === null ? { equals: null } : regionCode, }, }); + + if (existing) { + await this.prisma.systemMiningAccount.update({ + where: { id: existing.id }, + data: { + totalContribution: contribution.value, + lastSyncedAt: new Date(), + }, + }); + } else { + await this.prisma.systemMiningAccount.create({ + data: { + accountType, + regionCode, + name, + totalContribution: contribution.value, + lastSyncedAt: new Date(), + }, + }); + } } async getTotalContribution(): Promise { @@ -130,9 +149,11 @@ export class SystemMiningAccountRepository { tx?: TransactionClient, ): Promise { const executeInTx = async (client: TransactionClient) => { - const account = await client.systemMiningAccount.findUnique({ + // 使用 findFirst 替代 findUnique,因为 regionCode 可以为 null + const account = await client.systemMiningAccount.findFirst({ where: { - accountType_regionCode: { accountType, regionCode }, + accountType, + regionCode: regionCode === null ? { equals: null } : regionCode, }, }); @@ -180,9 +201,11 @@ export class SystemMiningAccountRepository { secondDistribution: ShareAmount, minedAmount: ShareAmount, ): Promise { - const account = await this.prisma.systemMiningAccount.findUnique({ + // 使用 findFirst 替代 findUnique,因为 regionCode 可以为 null + const account = await this.prisma.systemMiningAccount.findFirst({ where: { - accountType_regionCode: { accountType, regionCode }, + accountType, + regionCode: regionCode === null ? { equals: null } : regionCode, }, });