diff --git a/src/app.module.ts b/src/app.module.ts index 5db822b..a0acc1c 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,4 +1,5 @@ import LoggerMiddleware from '@/middlewares/logger'; +import { AnalyzeModule } from '@/modules/analyze/analyze.module'; import { ArchivesModule } from '@/modules/archives/archives.module'; import { AuthModule } from '@/modules/auth/auth.module'; import { CategoryModule } from '@/modules/category/category.module'; @@ -23,6 +24,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; entities: ['src/**/**.entity{.ts,.js}'], synchronize: true }), + AnalyzeModule, UsersModule, AuthModule, PostModule, diff --git a/src/modules/analyze/analyze.controller.ts b/src/modules/analyze/analyze.controller.ts new file mode 100644 index 0000000..2174014 --- /dev/null +++ b/src/modules/analyze/analyze.controller.ts @@ -0,0 +1,44 @@ +import { Body, Controller, Get, Put, ValidationPipe } from '@nestjs/common'; +import { UpdatePvDto, UpdateUvDto } from './analyze.dto'; +import { AnalyzeService } from './analyze.service'; + +@Controller('analyze') +export class AnalyzeController { + constructor(private readonly analyzeService: AnalyzeService) {} + + @Get('pv') + public async pv() { + return { + message: 'ok', + data: { + pv: Number(await this.analyzeService.pv()) + } + }; + } + + @Put('pv') + public async updatePv(@Body(new ValidationPipe()) updatePvDto: UpdatePvDto) { + await this.analyzeService.updatePv(updatePvDto.from); + return { + message: 'ok' + }; + } + + @Get('uv') + public async uv() { + return { + message: 'ok', + data: { + uv: Number(await this.analyzeService.uv()) + } + }; + } + + @Put('uv') + public async updateUv(@Body(new ValidationPipe()) updateUvDto: UpdateUvDto) { + await this.analyzeService.updateUv(updateUvDto.from); + return { + message: 'ok' + }; + } +} diff --git a/src/modules/analyze/analyze.dto.ts b/src/modules/analyze/analyze.dto.ts new file mode 100644 index 0000000..1390e1c --- /dev/null +++ b/src/modules/analyze/analyze.dto.ts @@ -0,0 +1,11 @@ +import { IsString } from 'class-validator'; + +export class UpdatePvDto { + @IsString() + readonly from: string; +} + +export class UpdateUvDto { + @IsString() + readonly from: string; +} diff --git a/src/modules/analyze/analyze.entity.ts b/src/modules/analyze/analyze.entity.ts new file mode 100644 index 0000000..aaabd96 --- /dev/null +++ b/src/modules/analyze/analyze.entity.ts @@ -0,0 +1,16 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity() +export class Visit { + @PrimaryGeneratedColumn() + id: number; + + @Column({ length: 32 }) + type: string; + + @Column('bigint') + count: number; + + @Column('text') + from: string; +} diff --git a/src/modules/analyze/analyze.module.ts b/src/modules/analyze/analyze.module.ts new file mode 100644 index 0000000..6bb8f06 --- /dev/null +++ b/src/modules/analyze/analyze.module.ts @@ -0,0 +1,13 @@ +import { Visit } from '@/modules/analyze/analyze.entity'; +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AnalyzeController } from './analyze.controller'; +import { AnalyzeService } from './analyze.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([Visit])], + controllers: [AnalyzeController], + providers: [AnalyzeService], + exports: [AnalyzeService] +}) +export class AnalyzeModule {} diff --git a/src/modules/analyze/analyze.service.ts b/src/modules/analyze/analyze.service.ts new file mode 100644 index 0000000..d6ee196 --- /dev/null +++ b/src/modules/analyze/analyze.service.ts @@ -0,0 +1,62 @@ +import { Repository } from 'typeorm'; + +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Visit } from './analyze.entity'; + +export interface Archive { + title: string; + created: number; + id: string; +} + +@Injectable() +export class AnalyzeService { + constructor( + @InjectRepository(Visit) private readonly repository: Repository + ) {} + + public async pv (): Promise { + return this.repository.query(`SELECT sum(count) as count FROM visit where type = 'pv'`).then((res) => { + return res && res[0] && res[0].count || 0; + }); + } + + public async updatePv(from: string) { + let pv = await this.repository.findOne({ + type: 'pv', + from + }); + if (!pv) { + pv = new Visit(); + pv.type = 'pv'; + pv.count = 1; + pv.from = from; + } else { + pv.count++; + } + this.repository.save(pv); + } + + public async uv (): Promise { + return this.repository.query(`SELECT sum(count) as count FROM visit where type = 'uv'`).then((res) => { + return res && res[0] && res[0].count || 0; + }); + } + + public async updateUv(from: string) { + let uv = await this.repository.findOne({ + type: 'uv', + from + }); + if (!uv) { + uv = new Visit(); + uv.type = 'uv'; + uv.count = 1; + uv.from = from; + } else { + uv.count++; + } + this.repository.save(uv); + } +}