|
|
@@ -5,7 +5,6 @@ import { PersonInfo } from '../entities/person-info.entity'
|
|
|
import { PetInfo } from '../entities/pet-info.entity'
|
|
|
import { GoodsInfo } from '../entities/goods-info.entity'
|
|
|
import { PaginationResponse } from '../dto/common.dto'
|
|
|
-import { randomBytes } from 'crypto'
|
|
|
import { FileService } from './file.service'
|
|
|
|
|
|
export class QrCodeService {
|
|
|
@@ -26,12 +25,17 @@ export class QrCodeService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 生成唯一的二维码编号
|
|
|
+ * 生成唯一二维码
|
|
|
*/
|
|
|
- private generateQrCode(): string {
|
|
|
- const timestamp = Date.now().toString(36)
|
|
|
- const random = randomBytes(8).toString('hex')
|
|
|
- return `QR${timestamp}${random}`.toUpperCase()
|
|
|
+ private generateRandomQrCode(length = 12): string {
|
|
|
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
|
|
+ let code = ''
|
|
|
+
|
|
|
+ for (let i = 0; i < length; i++) {
|
|
|
+ code += chars.charAt(Math.floor(Math.random() * chars.length))
|
|
|
+ }
|
|
|
+
|
|
|
+ return code
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -49,30 +53,59 @@ export class QrCodeService {
|
|
|
/**
|
|
|
* 生成二维码
|
|
|
*/
|
|
|
+ /**
|
|
|
+ * 批量生成二维码(自动处理数据库重复)
|
|
|
+ */
|
|
|
async generateQrCodes(
|
|
|
qrType: QrType,
|
|
|
- quantity: number = 1
|
|
|
+ quantity: number = 1,
|
|
|
+ batchSize: number = 1000
|
|
|
): Promise<Array<{ qrCode: string; maintenanceCode: string }>> {
|
|
|
const result = []
|
|
|
|
|
|
- for (let i = 0; i < quantity; i++) {
|
|
|
- const qrCode = this.generateQrCode()
|
|
|
- const maintenanceCode = this.generateMaintenanceCode()
|
|
|
+ let remaining = quantity
|
|
|
+ let round = 0
|
|
|
+
|
|
|
+ while (remaining > 0) {
|
|
|
+ round++
|
|
|
|
|
|
- const entity = this.qrCodeRepository.create({
|
|
|
- qrCode,
|
|
|
- maintenanceCode,
|
|
|
- qrType,
|
|
|
- isActivated: false,
|
|
|
- scanCount: 0
|
|
|
- })
|
|
|
+ const rows = []
|
|
|
+ const localSet = new Set<string>()
|
|
|
|
|
|
- await this.qrCodeRepository.save(entity)
|
|
|
+ while (rows.length < remaining) {
|
|
|
+ const qrCode = this.generateRandomQrCode(12)
|
|
|
+ if (localSet.has(qrCode)) continue
|
|
|
+ localSet.add(qrCode)
|
|
|
+
|
|
|
+ const maintenanceCode = this.generateMaintenanceCode()
|
|
|
+
|
|
|
+ rows.push({
|
|
|
+ qrCode,
|
|
|
+ maintenanceCode,
|
|
|
+ qrType,
|
|
|
+ isActivated: false,
|
|
|
+ scanCount: 0
|
|
|
+ })
|
|
|
+
|
|
|
+ result.push({ qrCode, maintenanceCode })
|
|
|
+ }
|
|
|
+
|
|
|
+ let insertedCount = 0
|
|
|
+
|
|
|
+ for (let i = 0; i < rows.length; i += batchSize) {
|
|
|
+ const chunk = rows.slice(i, i + batchSize)
|
|
|
+
|
|
|
+ try {
|
|
|
+ const result = await this.qrCodeRepository.createQueryBuilder().insert().into(QrCode).values(chunk).execute()
|
|
|
+
|
|
|
+ insertedCount += result.raw?.affectedRows ?? chunk.length
|
|
|
+ } catch (err) {
|
|
|
+ this.app.log.warn('数据库唯一性冲突,已忽略,自动补足剩余数量')
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- result.push({
|
|
|
- qrCode,
|
|
|
- maintenanceCode
|
|
|
- })
|
|
|
+ const failed = remaining - insertedCount
|
|
|
+ remaining = failed
|
|
|
}
|
|
|
|
|
|
return result
|