Explorar el Código

添加重置维护码功能,包括新的 DTO、服务方法和路由配置,支持管理员重置二维码的维护码。

wuyi hace 1 mes
padre
commit
4291e90201

+ 32 - 4
src/controllers/qr-code.controller.ts

@@ -1,7 +1,13 @@
 import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify'
 import { QrCodeService } from '../services/qr-code.service'
 import { ScanRecordService } from '../services/scan-record.service'
-import { GenerateQrCodeDto, QueryQrCodeDto, VerifyMaintenanceCodeDto, GetQrCodeInfoDto } from '../dto/qr-code.dto'
+import {
+  GenerateQrCodeDto,
+  QueryQrCodeDto,
+  VerifyMaintenanceCodeDto,
+  GetQrCodeInfoDto,
+  ResetMaintenanceCodeDto
+} from '../dto/qr-code.dto'
 
 export class QrCodeController {
   private qrCodeService: QrCodeService
@@ -106,14 +112,14 @@ export class QrCodeController {
       const ipAddress = request.ip
       const userAgent = request.headers['user-agent']
 
-      // 获取二维码信息
-      const info = await this.qrCodeService.getQrCodeInfo(qrCode, id)
-
       // 如果通过 qrCode 查询,记录扫描
       if (qrCode) {
         await this.scanRecordService.create(qrCode, undefined, undefined, undefined, ipAddress, userAgent)
       }
 
+      // 获取二维码信息
+      const info = await this.qrCodeService.getQrCodeInfo(qrCode, id)
+
       return reply.send(info)
     } catch (error) {
       const message = error instanceof Error ? error.message : '获取信息失败'
@@ -147,4 +153,26 @@ export class QrCodeController {
       return reply.code(500).send({ message })
     }
   }
+
+  /**
+   * 重置维护码
+   */
+  async resetMaintenanceCode(request: FastifyRequest<{ Body: ResetMaintenanceCodeDto }>, reply: FastifyReply) {
+    try {
+      const { qrCode, maintenanceCode } = request.body
+
+      const newMaintenanceCode = await this.qrCodeService.resetMaintenanceCode(qrCode, maintenanceCode)
+
+      return reply.send({
+        message: '维护码重置成功',
+        data: {
+          qrCode,
+          maintenanceCode: newMaintenanceCode
+        }
+      })
+    } catch (error) {
+      const message = error instanceof Error ? error.message : '重置失败'
+      return reply.code(500).send({ message })
+    }
+  }
 }

+ 12 - 1
src/dto/qr-code.dto.ts

@@ -1,4 +1,4 @@
-import { IsString, IsEnum, IsOptional, IsNumber, IsBoolean, IsDateString, Min } from 'class-validator'
+import { IsString, IsEnum, IsOptional, IsNumber, IsBoolean, IsDateString, Min, Matches, MinLength, MaxLength } from 'class-validator'
 import { QrType } from '../entities/qr-code.entity'
 
 export class GenerateQrCodeDto {
@@ -56,3 +56,14 @@ export class GetQrCodeInfoDto {
   @IsNumber()
   id?: number
 }
+
+export class ResetMaintenanceCodeDto {
+  @IsString()
+  qrCode: string
+
+  @IsString()
+  @MinLength(8, { message: '维护码最少8位字符' })
+  @MaxLength(20, { message: '维护码最多20位字符' })
+  @Matches(/^[a-zA-Z0-9]+$/, { message: '维护码只能包含字母和数字' })
+  maintenanceCode: string
+}

+ 18 - 6
src/routes/qr-code.routes.ts

@@ -2,11 +2,24 @@ import { FastifyInstance } from 'fastify'
 import { QrCodeController } from '../controllers/qr-code.controller'
 import { hasRole } from '../middlewares/auth.middleware'
 import { UserRole } from '../entities/user.entity'
-import { GenerateQrCodeDto, QueryQrCodeDto, VerifyMaintenanceCodeDto, GetQrCodeInfoDto } from '../dto/qr-code.dto'
+import {
+  GenerateQrCodeDto,
+  QueryQrCodeDto,
+  VerifyMaintenanceCodeDto,
+  GetQrCodeInfoDto,
+  ResetMaintenanceCodeDto
+} from '../dto/qr-code.dto'
 
 export default async function qrCodeRoutes(fastify: FastifyInstance) {
   const qrCodeController = new QrCodeController(fastify)
 
+  fastify.get<{ Querystring: GetQrCodeInfoDto }>('/info', qrCodeController.getInfo.bind(qrCodeController))
+
+  fastify.post<{ Body: VerifyMaintenanceCodeDto }>(
+    '/verify',
+    qrCodeController.verifyMaintenanceCode.bind(qrCodeController)
+  )
+
   fastify.post<{ Body: GenerateQrCodeDto }>(
     '/generate',
     { onRequest: [hasRole(UserRole.ADMIN)] },
@@ -31,10 +44,9 @@ export default async function qrCodeRoutes(fastify: FastifyInstance) {
     qrCodeController.getScanRecords.bind(qrCodeController)
   )
 
-  fastify.get<{ Querystring: GetQrCodeInfoDto }>('/info', qrCodeController.getInfo.bind(qrCodeController))
-
-  fastify.post<{ Body: VerifyMaintenanceCodeDto }>(
-    '/verify',
-    qrCodeController.verifyMaintenanceCode.bind(qrCodeController)
+  fastify.post<{ Body: ResetMaintenanceCodeDto }>(
+    '/reset',
+    { onRequest: [hasRole(UserRole.ADMIN)] },
+    qrCodeController.resetMaintenanceCode.bind(qrCodeController)
   )
 }

+ 31 - 9
src/services/qr-code.service.ts

@@ -184,15 +184,7 @@ export class QrCodeService {
     }
 
     const [content, total] = await queryBuilder
-      .select([
-        'qrCode.id',
-        'qrCode.qrCode',
-        'qrCode.qrType',
-        'qrCode.isActivated',
-        'qrCode.scanCount',
-        'qrCode.createdAt',
-        'qrCode.updatedAt'
-      ])
+      .select()
       .skip(page * pageSize)
       .take(pageSize)
       .orderBy('qrCode.createdAt', 'DESC')
@@ -232,4 +224,34 @@ export class QrCodeService {
   async findByQrCode(qrCode: string): Promise<QrCode | null> {
     return this.qrCodeRepository.findOne({ where: { qrCode } })
   }
+
+  /**
+   * 验证维护码格式
+   */
+  private validateMaintenanceCodeFormat(code: string): boolean {
+    if (code.length < 8 || code.length > 20) {
+      return false
+    }
+    const regex = /^[a-zA-Z0-9]+$/
+    return regex.test(code)
+  }
+
+  /**
+   * 重置维护码
+   */
+  async resetMaintenanceCode(qrCode: string, newMaintenanceCode: string): Promise<string> {
+    if (!this.validateMaintenanceCodeFormat(newMaintenanceCode)) {
+      throw new Error('维护码格式错误:最少8位,最多20位,只能包含字母和数字')
+    }
+
+    const entity = await this.qrCodeRepository.findOne({ where: { qrCode } })
+    if (!entity) {
+      throw new Error('二维码不存在')
+    }
+
+    entity.maintenanceCode = newMaintenanceCode
+    await this.qrCodeRepository.save(entity)
+
+    return newMaintenanceCode
+  }
 }