From 8e51994e713abd26d84141e5e10351d2047e5b8d Mon Sep 17 00:00:00 2001 From: richarjiang Date: Fri, 26 Sep 2025 08:48:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=BC=9A=E5=91=98?= =?UTF-8?q?=E7=BC=96=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql-scripts/add-member-number-migration.sql | 54 +++++++++++++++++++++ src/users/models/user.model.ts | 8 +++ src/users/users.controller.ts | 2 +- src/users/users.service.ts | 32 ++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 sql-scripts/add-member-number-migration.sql diff --git a/sql-scripts/add-member-number-migration.sql b/sql-scripts/add-member-number-migration.sql new file mode 100644 index 0000000..985765a --- /dev/null +++ b/sql-scripts/add-member-number-migration.sql @@ -0,0 +1,54 @@ +-- 会员编号字段迁移脚本 +-- 执行日期: 2025-09-26 +-- 描述: 为用户表添加会员编号字段,按照创建时间从1开始递增编号 + +-- Step 1: 添加会员编号字段 +ALTER TABLE `t_users` +ADD COLUMN `member_number` INT NULL COMMENT '会员编号(按注册时间递增)' AFTER `gender`; + +-- Step 2: 创建索引以提高查询性能 +CREATE INDEX `idx_member_number` ON `t_users` (`member_number`); + +-- Step 3: 为现有用户按照创建时间分配会员编号(从1开始递增) +SET @row_number = 0; +UPDATE `t_users` +SET `member_number` = (@row_number := @row_number + 1) +WHERE `member_number` IS NULL +ORDER BY `created_at` ASC; + +-- Step 4: 验证更新结果 +SELECT + COUNT(*) as total_users, + MIN(member_number) as min_member_number, + MAX(member_number) as max_member_number, + COUNT(DISTINCT member_number) as unique_member_numbers +FROM `t_users` +WHERE `member_number` IS NOT NULL; + +-- Step 5: 显示前10个用户的会员编号分配情况 +SELECT + `id`, + `name`, + `member_number`, + `created_at`, + `is_guest` +FROM `t_users` +WHERE `member_number` IS NOT NULL +ORDER BY `member_number` ASC +LIMIT 10; + +-- Step 6: 检查是否有重复的会员编号(应该为0) +SELECT + member_number, + COUNT(*) as count +FROM `t_users` +WHERE `member_number` IS NOT NULL +GROUP BY `member_number` +HAVING COUNT(*) > 1; + +-- 注意事项: +-- 1. 此脚本会为所有现有用户分配会员编号,按照创建时间排序 +-- 2. 会员编号从1开始递增 +-- 3. 包含游客用户也会分配编号 +-- 4. 如果只希望为正式用户(非游客)分配编号,请在更新语句中添加条件: WHERE `member_number` IS NULL AND `is_guest` = 0 +-- 5. 执行前请备份数据库 \ No newline at end of file diff --git a/src/users/models/user.model.ts b/src/users/models/user.model.ts index 57509a5..1804924 100644 --- a/src/users/models/user.model.ts +++ b/src/users/models/user.model.ts @@ -44,6 +44,14 @@ export class User extends Model { }) declare gender: Gender; + // 会员编号 + @Column({ + type: DataType.INTEGER, + allowNull: true, + comment: '会员编号(按注册时间递增)', + }) + declare memberNumber: number; + // 会员有效期 @Column({ type: DataType.DATE, diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 83eada1..af4ae53 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -57,7 +57,7 @@ export class UsersController { @UseGuards(JwtAuthGuard) @Get('/info') @HttpCode(HttpStatus.OK) - @ApiOperation({ summary: '创建用户' }) + @ApiOperation({ summary: '获取用户信息' }) @ApiBody({ type: CreateUserDto }) @ApiResponse({ type: UserResponseDto }) async getProfile(@CurrentUser() user: AccessTokenPayload): Promise { diff --git a/src/users/users.service.ts b/src/users/users.service.ts index ef98c0c..fb38db3 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -527,11 +527,14 @@ export class UsersService { throw new BadRequestException('无法获取用户邮箱信息'); } + const memberNumber = await this.assignMemberNumber(); + user = await this.userModel.create({ id: userId, name: userName, mail: userEmail, gender: Gender.MALE, + memberNumber, freeUsageCount: DEFAULT_FREE_USAGE_COUNT, lastLogin: new Date(), avatar: 'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/images/seal-avatar/1.jpeg' @@ -735,10 +738,13 @@ export class UsersService { if (!user) { // 创建新的游客用户 + const memberNumber = await this.assignMemberNumber(); + user = await this.userModel.create({ id: guestUserId, name: `游客_${deviceName}`, gender: Gender.MALE, // 默认性别 + memberNumber, isGuest: true, deviceId, deviceName, @@ -2529,4 +2535,30 @@ export class UsersService { return dayjsDate.format('YYYY-MM-DD'); } } + + /** + * 自动分配会员编号 + * @returns Promise 新的会员编号 + */ + private async assignMemberNumber(): Promise { + try { + // 查找当前最大的会员编号 + const result = await this.userModel.findOne({ + attributes: [[this.sequelize.fn('MAX', this.sequelize.col('member_number')), 'maxMemberNumber']], + raw: true + }); + + const maxMember = result as unknown as { maxMemberNumber: number | null }; + + // 返回下一个编号,如果没有现有编号则从1开始 + const nextMemberNumber = (maxMember?.maxMemberNumber || 0) + 1; + + this.logger.log(`分配新会员编号: ${nextMemberNumber}`); + return nextMemberNumber; + } catch (error) { + this.logger.error(`assignMemberNumber error: ${error instanceof Error ? error.message : String(error)}`); + // 如果查询失败,返回基于时间戳的编号作为备选 + return Math.floor(Date.now() / 1000) % 100000; + } + } }