This commit is contained in:
hailin 2025-11-24 02:38:15 -08:00
parent 77725bd769
commit c6c2545095
3 changed files with 67 additions and 48 deletions

View File

@ -96,8 +96,9 @@ export class UserAccount {
params.initialDeviceId, params.deviceName || '未命名设备', new Date(), new Date(), params.initialDeviceId, params.deviceName || '未命名设备', new Date(), new Date(),
)); ));
// UserID将由数据库自动生成(autoincrement)这里使用临时值0
const account = new UserAccount( const account = new UserAccount(
UserId.generate(), params.accountSequence, devices, null, UserId.create(0), params.accountSequence, devices, null,
`用户${params.accountSequence.value}`, null, params.inviterSequence, `用户${params.accountSequence.value}`, null, params.inviterSequence,
ReferralCode.generate(), params.province, params.city, null, ReferralCode.generate(), params.province, params.city, null,
new Map(), null, KYCStatus.NOT_VERIFIED, AccountStatus.ACTIVE, new Map(), null, KYCStatus.NOT_VERIFIED, AccountStatus.ACTIVE,

View File

@ -5,21 +5,27 @@ import { wordlist } from '@scure/bip39/wordlists/english';
// ============ UserId ============ // ============ UserId ============
export class UserId { export class UserId {
constructor(public readonly value: string) { constructor(public readonly value: bigint) {
if (!value) throw new DomainError('UserId不能为空'); if (!value) throw new DomainError('UserId不能为空');
} }
static generate(): UserId { static create(value: bigint | string | number): UserId {
return new UserId(crypto.randomUUID()); if (typeof value === 'string') {
} return new UserId(BigInt(value));
}
static create(value: string): UserId { if (typeof value === 'number') {
return new UserId(BigInt(value));
}
return new UserId(value); return new UserId(value);
} }
equals(other: UserId): boolean { equals(other: UserId): boolean {
return this.value === other.value; return this.value === other.value;
} }
toString(): string {
return this.value.toString();
}
} }
// ============ AccountSequence ============ // ============ AccountSequence ============

View File

@ -14,54 +14,66 @@ export class UserAccountRepositoryImpl implements UserAccountRepository {
async save(account: UserAccount): Promise<void> { async save(account: UserAccount): Promise<void> {
const devices = account.getAllDevices(); const devices = account.getAllDevices();
const wallets = account.getAllWalletAddresses(); const isNewAccount = account.userId.value === BigInt(0);
await this.prisma.$transaction(async (tx) => { await this.prisma.$transaction(async (tx) => {
await tx.userAccount.upsert({ let savedUserId: bigint;
where: { userId: BigInt(account.userId.value) },
create: { if (isNewAccount) {
userId: BigInt(account.userId.value), // 新账户让数据库自动生成userId
accountSequence: BigInt(account.accountSequence.value), const created = await tx.userAccount.create({
phoneNumber: account.phoneNumber?.value || null, data: {
nickname: account.nickname, accountSequence: BigInt(account.accountSequence.value),
avatarUrl: account.avatarUrl, phoneNumber: account.phoneNumber?.value || null,
inviterSequence: account.inviterSequence ? BigInt(account.inviterSequence.value) : null, nickname: account.nickname,
referralCode: account.referralCode.value, avatarUrl: account.avatarUrl,
provinceCode: account.province.value, inviterSequence: account.inviterSequence ? BigInt(account.inviterSequence.value) : null,
cityCode: account.city.value, referralCode: account.referralCode.value,
address: account.addressDetail, provinceCode: account.province.value,
kycStatus: account.kycStatus, cityCode: account.city.value,
realName: account.kycInfo?.realName || null, address: account.addressDetail,
idCardNumber: account.kycInfo?.idCardNumber || null, kycStatus: account.kycStatus,
idCardFrontUrl: account.kycInfo?.idCardFrontUrl || null, realName: account.kycInfo?.realName || null,
idCardBackUrl: account.kycInfo?.idCardBackUrl || null, idCardNumber: account.kycInfo?.idCardNumber || null,
status: account.status, idCardFrontUrl: account.kycInfo?.idCardFrontUrl || null,
registeredAt: account.registeredAt, idCardBackUrl: account.kycInfo?.idCardBackUrl || null,
lastLoginAt: account.lastLoginAt, status: account.status,
}, registeredAt: account.registeredAt,
update: { lastLoginAt: account.lastLoginAt,
phoneNumber: account.phoneNumber?.value || null, },
nickname: account.nickname, });
avatarUrl: account.avatarUrl, savedUserId = created.userId;
provinceCode: account.province.value, // 更新聚合根的userId
cityCode: account.city.value, (account as any)._userId = UserId.create(savedUserId);
address: account.addressDetail, } else {
kycStatus: account.kycStatus, // 已存在的账户,更新
realName: account.kycInfo?.realName || null, await tx.userAccount.update({
idCardNumber: account.kycInfo?.idCardNumber || null, where: { userId: BigInt(account.userId.value) },
idCardFrontUrl: account.kycInfo?.idCardFrontUrl || null, data: {
idCardBackUrl: account.kycInfo?.idCardBackUrl || null, phoneNumber: account.phoneNumber?.value || null,
status: account.status, nickname: account.nickname,
lastLoginAt: account.lastLoginAt, avatarUrl: account.avatarUrl,
}, provinceCode: account.province.value,
}); cityCode: account.city.value,
address: account.addressDetail,
kycStatus: account.kycStatus,
realName: account.kycInfo?.realName || null,
idCardNumber: account.kycInfo?.idCardNumber || null,
idCardFrontUrl: account.kycInfo?.idCardFrontUrl || null,
idCardBackUrl: account.kycInfo?.idCardBackUrl || null,
status: account.status,
lastLoginAt: account.lastLoginAt,
},
});
savedUserId = account.userId.value;
}
// Sync devices // Sync devices
await tx.userDevice.deleteMany({ where: { userId: BigInt(account.userId.value) } }); await tx.userDevice.deleteMany({ where: { userId: savedUserId } });
if (devices.length > 0) { if (devices.length > 0) {
await tx.userDevice.createMany({ await tx.userDevice.createMany({
data: devices.map((d) => ({ data: devices.map((d) => ({
userId: BigInt(account.userId.value), userId: savedUserId,
deviceId: d.deviceId, deviceId: d.deviceId,
deviceName: d.deviceName, deviceName: d.deviceName,
addedAt: d.addedAt, addedAt: d.addedAt,