83 lines
1.9 KiB
TypeScript
83 lines
1.9 KiB
TypeScript
import { Injectable, Inject, NotFoundException } from '@nestjs/common';
|
|
import {
|
|
AccountSequence,
|
|
Phone,
|
|
USER_REPOSITORY,
|
|
UserRepository,
|
|
} from '@/domain';
|
|
|
|
export interface UserProfileResult {
|
|
accountSequence: string;
|
|
phone: string;
|
|
source: 'V1' | 'V2';
|
|
status: string;
|
|
kycStatus: string;
|
|
realName?: string;
|
|
createdAt?: Date;
|
|
lastLoginAt?: Date;
|
|
}
|
|
|
|
@Injectable()
|
|
export class UserService {
|
|
constructor(
|
|
@Inject(USER_REPOSITORY)
|
|
private readonly userRepository: UserRepository,
|
|
) {}
|
|
|
|
/**
|
|
* 获取用户信息
|
|
*/
|
|
async getProfile(accountSequence: string): Promise<UserProfileResult> {
|
|
const user = await this.userRepository.findByAccountSequence(
|
|
AccountSequence.create(accountSequence),
|
|
);
|
|
|
|
if (!user) {
|
|
throw new NotFoundException('用户不存在');
|
|
}
|
|
|
|
return {
|
|
accountSequence: user.accountSequence.value,
|
|
phone: user.phone.masked,
|
|
source: user.source,
|
|
status: user.status,
|
|
kycStatus: user.kycStatus,
|
|
realName: user.isKycVerified ? this.maskName(user.realName!) : undefined,
|
|
createdAt: user.createdAt,
|
|
lastLoginAt: user.lastLoginAt,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 更换手机号
|
|
*/
|
|
async changePhone(accountSequence: string, newPhone: string): Promise<void> {
|
|
const user = await this.userRepository.findByAccountSequence(
|
|
AccountSequence.create(accountSequence),
|
|
);
|
|
|
|
if (!user) {
|
|
throw new NotFoundException('用户不存在');
|
|
}
|
|
|
|
const phone = Phone.create(newPhone);
|
|
|
|
// 检查新手机号是否已被使用
|
|
const exists = await this.userRepository.existsByPhone(phone);
|
|
if (exists) {
|
|
throw new Error('手机号已被使用');
|
|
}
|
|
|
|
user.changePhone(phone);
|
|
await this.userRepository.save(user);
|
|
}
|
|
|
|
/**
|
|
* 脱敏姓名
|
|
*/
|
|
private maskName(name: string): string {
|
|
if (name.length <= 1) return name;
|
|
return name[0] + '*'.repeat(name.length - 1);
|
|
}
|
|
}
|