| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- 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,
- ResetMaintenanceCodeDto,
- AddUserQrCodeDto,
- DeleteUserQrCodeDto,
- QueryUserQrCodeDto,
- UpdateQrCodeDto
- } from '../dto/qr-code.dto'
- export class QrCodeController {
- private qrCodeService: QrCodeService
- private scanRecordService: ScanRecordService
- constructor(app: FastifyInstance) {
- this.qrCodeService = new QrCodeService(app)
- this.scanRecordService = new ScanRecordService(app)
- }
- /**
- * 生成二维码
- */
- async generate(request: FastifyRequest<{ Body: GenerateQrCodeDto }>, reply: FastifyReply) {
- try {
- const { qrType, quantity } = request.body
- const result = await this.qrCodeService.generateQrCodes(qrType, quantity || 1)
- return reply.code(201).send({
- message: '二维码生成成功',
- data: result
- })
- } catch (error) {
- const message = error instanceof Error ? error.message : '生成失败'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 分页列表
- */
- async list(request: FastifyRequest<{ Querystring: QueryQrCodeDto }>, reply: FastifyReply) {
- try {
- const { qrCode, qrType, isActivated, startDate, endDate, page, pageSize } = request.query
- const result = await this.qrCodeService.queryQrCodes(
- qrCode,
- qrType,
- isActivated,
- startDate,
- endDate,
- page,
- pageSize
- )
- return reply.send(result)
- } catch (error) {
- const message = error instanceof Error ? error.message : '查询失败'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 按日期下载
- */
- async downloadByDate(request: FastifyRequest<{ Querystring: { date: string } }>, reply: FastifyReply) {
- try {
- const { date } = request.query
- if (!date) {
- return reply.code(400).send({ message: '请提供日期参数' })
- }
- const qrCodes = await this.qrCodeService.getQrCodesByDate(date)
- return reply.send({
- date,
- count: qrCodes.length,
- data: qrCodes
- })
- } catch (error) {
- const message = error instanceof Error ? error.message : '下载失败'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 验证维护码
- */
- async verifyMaintenanceCode(request: FastifyRequest<{ Body: VerifyMaintenanceCodeDto }>, reply: FastifyReply) {
- try {
- const { qrCode, maintenanceCode } = request.body
- const isValid = await this.qrCodeService.verifyMaintenanceCode(qrCode, maintenanceCode)
- if (!isValid) {
- return reply.code(401).send({ message: '维护码错误' })
- }
- return reply.send({ message: '验证成功', valid: true })
- } catch (error) {
- const message = error instanceof Error ? error.message : '验证失败'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 验证维护码并返回二维码信息
- */
- async verifyMaintenanceCodeInfo(request: FastifyRequest<{ Body: VerifyMaintenanceCodeDto }>, reply: FastifyReply) {
- try {
- const { qrCode, maintenanceCode } = request.body
- const isValid = await this.qrCodeService.verifyMaintenanceCode(qrCode, maintenanceCode)
- if (!isValid) {
- return reply.code(401).send({ message: '维护码错误' })
- }
- const qrCodeInfo = await this.qrCodeService.getQrCodeInfo(qrCode, undefined, true)
- return reply.send({
- message: '验证成功',
- valid: true,
- ...qrCodeInfo
- })
- } catch (error) {
- const message = error instanceof Error ? error.message : '验证失败'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 前台获取二维码信息
- */
- async getInfo(request: FastifyRequest<{ Querystring: GetQrCodeInfoDto }>, reply: FastifyReply) {
- try {
- const { qrCode, id } = request.query
- if (!qrCode && !id) {
- return reply.code(400).send({ message: '请提供参数' })
- }
- // 记录扫描 - 获取真实IP地址
- let ipAddress = request.headers['x-forwarded-for'] as string
- if (ipAddress) {
- // x-forwarded-for 可能包含多个IP,取第一个(真实客户端IP)
- ipAddress = ipAddress.split(',')[0].trim()
- } else {
- // 如果没有 x-forwarded-for,尝试其他常见的代理头
- ipAddress = (request.headers['x-real-ip'] as string) ||
- (request.headers['cf-connecting-ip'] as string) ||
- request.ip ||
- request.socket.remoteAddress ||
- 'unknown'
- }
- const userAgent = request.headers['user-agent']
- // 如果通过 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 : '获取信息失败'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 后台获取二维码信息
- */
- async adminGetInfo(request: FastifyRequest<{ Querystring: GetQrCodeInfoDto }>, reply: FastifyReply) {
- try {
- const { qrCode, id } = request.query
- if (!qrCode && !id) {
- return reply.code(400).send({ message: '请提供参数' })
- }
- // 后台查询,不判断 isVisible,返回所有信息
- const info = await this.qrCodeService.getQrCodeInfo(qrCode, id, true)
- return reply.send(info)
- } catch (error) {
- const message = error instanceof Error ? error.message : '获取信息失败'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 获取扫描记录
- */
- async getScanRecords(
- request: FastifyRequest<{ Querystring: { qrCode: string; limit?: number } }>,
- reply: FastifyReply
- ) {
- try {
- const { qrCode, limit } = request.query
- if (!qrCode) {
- return reply.code(400).send({ message: '请提供二维码参数' })
- }
- const records = await this.scanRecordService.getRecentRecords(qrCode, limit || 10)
- return reply.send({
- qrCode,
- count: records.length,
- records
- })
- } catch (error) {
- const message = error instanceof Error ? error.message : '获取记录失败'
- 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 })
- }
- }
- /**
- * 绑定二维码
- */
- async bindQrCode(request: FastifyRequest<{ Body: AddUserQrCodeDto }>, reply: FastifyReply) {
- try {
- const userId = request.user.id
- const { qrCodeId, qrCode, maintenanceCode } = request.body
- const userQrCode = await this.qrCodeService.bindQrCode(userId, qrCodeId, qrCode, maintenanceCode)
- return reply.code(201).send({
- message: 'Bound successfully'
- })
- } catch (error) {
- const message = error instanceof Error ? error.message : 'Binding failed'
- const clientErrorKeywords = [
- 'not found',
- 'already bound',
- 'Please provide',
- 'Maintenance code cannot be empty',
- 'Maintenance code error'
- ]
- const isClientError = clientErrorKeywords.some(keyword => message.includes(keyword))
- const statusCode = isClientError ? 400 : 500
- return reply.code(statusCode).send({ message })
- }
- }
- /**
- * 取消绑定二维码
- */
- async unbindQrCode(request: FastifyRequest<{ Body: DeleteUserQrCodeDto }>, reply: FastifyReply) {
- try {
- const userId = request.user.id
- const { id, qrCodeId } = request.body
- await this.qrCodeService.unbindQrCode(userId, id, qrCodeId)
- return reply.send({
- message: 'Unbound successfully'
- })
- } catch (error) {
- const message = error instanceof Error ? error.message : 'Unbinding failed'
- const statusCode =
- message.includes('not found') || message.includes('already deleted') || message.includes('Please provide') ? 400 : 500
- return reply.code(statusCode).send({ message })
- }
- }
- /**
- * 查询用户的关联二维码列表
- */
- async getUserQrCodes(request: FastifyRequest<{ Querystring: QueryUserQrCodeDto }>, reply: FastifyReply) {
- try {
- const userId = request.user.id
- const { page = 0, pageSize = 20 } = request.query
- const result = await this.qrCodeService.getUserQrCodes(userId, page, pageSize)
- return reply.send(result)
- } catch (error) {
- const message = error instanceof Error ? error.message : 'Query failed'
- return reply.code(500).send({ message })
- }
- }
- /**
- * 更新二维码信息
- */
- async update(request: FastifyRequest<{ Body: UpdateQrCodeDto }>, reply: FastifyReply) {
- try {
- const { qrCode, maintenanceCode, remark } = request.body
- const updated = await this.qrCodeService.updateQrCode(qrCode, maintenanceCode, { remark })
- return reply.send({
- message: '更新成功',
- data: {
- qrCode: updated.qrCode,
- remark: updated.remark
- }
- })
- } catch (error) {
- const message = error instanceof Error ? error.message : '更新失败'
- const clientErrorKeywords = ['维护码错误', '二维码不存在']
- const isClientError = clientErrorKeywords.some(keyword => message.includes(keyword))
- const statusCode = isClientError ? 400 : 500
- return reply.code(statusCode).send({ message })
- }
- }
- }
|