|
|
@@ -0,0 +1,161 @@
|
|
|
+import { Repository } from 'typeorm'
|
|
|
+import { FastifyInstance } from 'fastify'
|
|
|
+import { LinkInfo } from '../entities/link-info.entity'
|
|
|
+import { QrCodeService } from './qr-code.service'
|
|
|
+import { QrType } from '../entities/qr-code.entity'
|
|
|
+import { PaginationResponse } from '../dto/common.dto'
|
|
|
+import { AdminUpdateLinkInfoDto } from '../dto/link-info.dto'
|
|
|
+
|
|
|
+export class LinkInfoService {
|
|
|
+ private linkInfoRepository: Repository<LinkInfo>
|
|
|
+ private qrCodeService: QrCodeService
|
|
|
+
|
|
|
+ constructor(app: FastifyInstance) {
|
|
|
+ this.linkInfoRepository = app.dataSource.getRepository(LinkInfo)
|
|
|
+ this.qrCodeService = new QrCodeService(app)
|
|
|
+ }
|
|
|
+
|
|
|
+ async create(qrCode: string, data: Partial<LinkInfo>): Promise<LinkInfo> {
|
|
|
+ const qrCodeEntity = await this.qrCodeService.findByQrCode(qrCode)
|
|
|
+ if (!qrCodeEntity) {
|
|
|
+ throw new Error('二维码不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qrCodeEntity.qrType !== QrType.LINK) {
|
|
|
+ throw new Error('二维码类型不匹配')
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qrCodeEntity.isActivated) {
|
|
|
+ throw new Error('二维码已激活,无法重复填写')
|
|
|
+ }
|
|
|
+
|
|
|
+ const linkInfo = this.linkInfoRepository.create({
|
|
|
+ ...data,
|
|
|
+ qrCodeId: qrCodeEntity.id
|
|
|
+ })
|
|
|
+
|
|
|
+ const result = await this.linkInfoRepository.save(linkInfo)
|
|
|
+
|
|
|
+ await this.qrCodeService.activateQrCode(qrCodeEntity.id)
|
|
|
+
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ async update(qrCode: string, maintenanceCode: string, data: Partial<LinkInfo>): Promise<LinkInfo | null> {
|
|
|
+ const isValid = await this.qrCodeService.verifyMaintenanceCode(qrCode, maintenanceCode)
|
|
|
+ if (!isValid) {
|
|
|
+ throw new Error('维护码错误')
|
|
|
+ }
|
|
|
+
|
|
|
+ const qrCodeEntity = await this.qrCodeService.findByQrCode(qrCode)
|
|
|
+ if (!qrCodeEntity) {
|
|
|
+ throw new Error('二维码不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ const linkInfo = await this.linkInfoRepository.findOne({
|
|
|
+ where: { qrCodeId: qrCodeEntity.id }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!linkInfo) {
|
|
|
+ const created = this.linkInfoRepository.create({
|
|
|
+ ...data,
|
|
|
+ qrCodeId: qrCodeEntity.id
|
|
|
+ })
|
|
|
+ const result = await this.linkInfoRepository.save(created)
|
|
|
+ await this.qrCodeService.activateQrCode(qrCodeEntity.id)
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ await this.linkInfoRepository.update(linkInfo.id, data)
|
|
|
+
|
|
|
+ const updated = await this.linkInfoRepository.findOne({ where: { id: linkInfo.id } })
|
|
|
+ if (!updated) {
|
|
|
+ throw new Error('更新后无法找到链接信息')
|
|
|
+ }
|
|
|
+ return updated
|
|
|
+ }
|
|
|
+
|
|
|
+ async findByQrCodeId(qrCodeId: number): Promise<LinkInfo | null> {
|
|
|
+ return this.linkInfoRepository.findOne({ where: { qrCodeId } })
|
|
|
+ }
|
|
|
+
|
|
|
+ async findByQrCode(qrCode: string): Promise<LinkInfo | null> {
|
|
|
+ const qrCodeEntity = await this.qrCodeService.findByQrCode(qrCode)
|
|
|
+ if (!qrCodeEntity) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ return this.findByQrCodeId(qrCodeEntity.id)
|
|
|
+ }
|
|
|
+
|
|
|
+ async adminUpdate(qrCodeId: number, data: Omit<AdminUpdateLinkInfoDto, 'qrCodeId'>): Promise<LinkInfo> {
|
|
|
+ const linkInfo = await this.linkInfoRepository.findOne({
|
|
|
+ where: { qrCodeId }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!linkInfo) {
|
|
|
+ throw new Error('链接信息不存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ await this.linkInfoRepository.update(linkInfo.id, data)
|
|
|
+ const updated = await this.linkInfoRepository.findOne({ where: { id: linkInfo.id } })
|
|
|
+ if (!updated) {
|
|
|
+ throw new Error('更新后无法找到链接信息')
|
|
|
+ }
|
|
|
+ return updated
|
|
|
+ }
|
|
|
+
|
|
|
+ async query(
|
|
|
+ jumpUrl?: string,
|
|
|
+ remark?: string,
|
|
|
+ startDate?: string,
|
|
|
+ endDate?: string,
|
|
|
+ page: number = 0,
|
|
|
+ pageSize: number = 20
|
|
|
+ ): Promise<PaginationResponse<LinkInfo>> {
|
|
|
+ const queryBuilder = this.linkInfoRepository.createQueryBuilder('linkInfo')
|
|
|
+
|
|
|
+ if (jumpUrl) {
|
|
|
+ queryBuilder.andWhere('linkInfo.jumpUrl LIKE :jumpUrl', { jumpUrl: `%${jumpUrl}%` })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (remark) {
|
|
|
+ queryBuilder.andWhere('linkInfo.remark LIKE :remark', { remark: `%${remark}%` })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (startDate && endDate) {
|
|
|
+ queryBuilder.andWhere('DATE(linkInfo.createdAt) BETWEEN :startDate AND :endDate', { startDate, endDate })
|
|
|
+ } else if (startDate) {
|
|
|
+ queryBuilder.andWhere('DATE(linkInfo.createdAt) >= :startDate', { startDate })
|
|
|
+ } else if (endDate) {
|
|
|
+ queryBuilder.andWhere('DATE(linkInfo.createdAt) <= :endDate', { endDate })
|
|
|
+ }
|
|
|
+
|
|
|
+ const [content, total] = await queryBuilder
|
|
|
+ .skip(page * pageSize)
|
|
|
+ .take(pageSize)
|
|
|
+ .orderBy('linkInfo.createdAt', 'DESC')
|
|
|
+ .getManyAndCount()
|
|
|
+
|
|
|
+ return {
|
|
|
+ content,
|
|
|
+ metadata: {
|
|
|
+ total: Number(total),
|
|
|
+ page: Number(page),
|
|
|
+ size: Number(pageSize)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async adminGetDetail(qrCodeId: number): Promise<LinkInfo | null> {
|
|
|
+ const linkInfo = await this.linkInfoRepository.findOne({
|
|
|
+ where: { qrCodeId }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!linkInfo) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ return linkInfo
|
|
|
+ }
|
|
|
+}
|
|
|
+
|