wuyi hace 2 años
padre
commit
b093626ce0

+ 3 - 1
src/app.module.ts

@@ -25,6 +25,7 @@ import { LabelModule } from './label/label.module'
 import { MomentsModule } from './moments/moments.module'
 import { CommentModule } from './comment/comment.module'
 import { ChatPdfModule } from './chat-pdf/chat-pdf.module';
+import { LikesModule } from './likes/likes.module'
 @Module({
     imports: [
         DevtoolsModule.register({
@@ -101,7 +102,8 @@ import { ChatPdfModule } from './chat-pdf/chat-pdf.module';
         LabelModule,
         MomentsModule,
         CommentModule,
-        ChatPdfModule
+        ChatPdfModule,
+        LikesModule
     ],
     controllers: [],
     providers: [

+ 15 - 0
src/comment/comment.controller.ts

@@ -13,6 +13,7 @@ import { CommentService } from './comment.service'
 import { Comment } from './entities/comment.entity'
 import { PageRequest } from '../common/dto/page-request'
 import { CommentDto } from './dto/comment.dto'
+import { LikesDto } from 'src/likes/dto/likes.dto'
 
 @ApiTags('comment')
 @Controller('/comment')
@@ -44,4 +45,18 @@ export class CommentController {
         }
     }
 
+
+    @Post('/like')
+    public async likes(@Body() likesDto: LikesDto) {
+        try {
+            await this.commentService.like(likesDto.targetId, likesDto.userId)
+            return {
+                message: 'successes!',
+                status: HttpStatus.OK
+            }
+        } catch (err) {
+            throw new BadRequestException(err, 'Error: false!')
+        }
+    }
+
 }

+ 2 - 1
src/comment/comment.module.ts

@@ -3,9 +3,10 @@ import { TypeOrmModule } from '@nestjs/typeorm'
 import { Comment } from './entities/comment.entity'
 import { CommentService } from './comment.service'
 import { CommentController } from './comment.controller'
+import { LikesModule } from 'src/likes/likes.module'
 
 @Module({
-    imports: [TypeOrmModule.forFeature([Comment])],
+    imports: [TypeOrmModule.forFeature([Comment]), LikesModule],
     controllers: [CommentController],
     providers: [CommentService],
     exports: [CommentService]

+ 16 - 3
src/comment/comment.service.ts

@@ -6,16 +6,16 @@ import { InjectRepository } from '@nestjs/typeorm'
 import { paginate, Pagination } from 'nestjs-typeorm-paginate'
 import { PageRequest } from '../common/dto/page-request'
 import { Comment } from './entities/comment.entity'
-import { number } from 'yup'
 import { CommentDto } from './dto/comment.dto'
-import { el, ro } from 'date-fns/locale'
+import { LikesService } from 'src/likes/likes.service'
 
 @Injectable()
 export class CommentService {
 
     constructor(
         @InjectRepository(Comment)
-        private readonly commentRepository: Repository<Comment>
+        private readonly commentRepository: Repository<Comment>,
+        private readonly likesService: LikesService
     ) { }
 
 
@@ -91,4 +91,17 @@ export class CommentService {
         }
     }
 
+    public async like(id: number, userId: number): Promise<void> {
+        const comment = await this.commentRepository.findOneBy({ id: +id })
+        if (comment) {
+            const likes = await this.likesService.like(id, userId, 2)
+            if (likes.isValid) {
+                comment.commentLikeCount += 1
+            } else {
+                comment.commentLikeCount -= 1
+            }
+            await this.commentRepository.save(comment)
+        }
+    }
+
 }

+ 12 - 0
src/likes/dto/likes.dto.ts

@@ -0,0 +1,12 @@
+import BigNumber from "bignumber.js";
+import { IsNumber, IsString } from "class-validator";
+
+export class LikesDto {
+
+    @IsNumber()
+    userId: number
+
+    @IsNumber()
+    targetId: number
+
+}

+ 25 - 0
src/likes/entities/likes.entity.ts

@@ -0,0 +1,25 @@
+import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from "typeorm";
+
+@Entity()
+export class Likes {
+
+    @PrimaryGeneratedColumn()
+    id: number;
+
+    @Index()
+    @Column()
+    userId: number;
+
+    @Column()
+    targetId: number;
+
+    @Column()
+    type: number;
+
+    @Column({ default: true })
+    isValid: boolean
+
+    @CreateDateColumn()
+    createdAt: Date
+
+}

+ 4 - 0
src/likes/enum/targetType.enum.ts

@@ -0,0 +1,4 @@
+enum TargetType {
+    Moments = 1,
+    Comment = 2
+}

+ 23 - 0
src/likes/likes.controller.ts

@@ -0,0 +1,23 @@
+import {
+    Body,
+    Controller,
+    Post
+} from '@nestjs/common'
+import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'
+import { LikesService } from './likes.service'
+import { PageRequest } from 'src/common/dto/page-request'
+import { Likes } from './entities/likes.entity'
+
+@ApiTags('likes')
+@Controller('/likes')
+@ApiBearerAuth()
+export class LikesController {
+
+    constructor(private readonly likesService: LikesService) { }
+
+    @Post()
+    public async list(@Body() page: PageRequest<Likes>) {
+        return await this.likesService.findAll(page)
+    }
+
+}

+ 14 - 0
src/likes/likes.module.ts

@@ -0,0 +1,14 @@
+import { Module } from '@nestjs/common'
+import { TypeOrmModule } from '@nestjs/typeorm'
+import { Likes } from 'src/likes/entities/likes.entity'
+import { LikesController } from 'src/likes/likes.controller'
+import { LikesService } from 'src/likes/likes.service'
+import { UsersModule } from 'src/users/users.module'
+
+@Module({
+    imports: [TypeOrmModule.forFeature([Likes]), UsersModule],
+    controllers: [LikesController],
+    providers: [LikesService],
+    exports: [LikesService]
+})
+export class LikesModule { }

+ 78 - 0
src/likes/likes.service.ts

@@ -0,0 +1,78 @@
+import {
+    Injectable
+} from '@nestjs/common'
+import { FindManyOptions, Repository } from 'typeorm'
+import { InjectRepository } from '@nestjs/typeorm'
+import { Likes } from './entities/likes.entity'
+import { PageRequest } from 'src/common/dto/page-request'
+import { Users } from 'src/users/entities/users.entity'
+import { Pagination, paginate } from 'nestjs-typeorm-paginate'
+import { UsersService } from 'src/users/users.service'
+import { el, tr } from 'date-fns/locale'
+
+@Injectable()
+export class LikesService {
+    constructor(
+        @InjectRepository(Likes)
+        private readonly likesRepository: Repository<Likes>,
+        private readonly usersService: UsersService
+    ) { }
+
+    async findAll(req: PageRequest<Likes>): Promise<Pagination<Users>> {
+        const query = await this.likesRepository.createQueryBuilder()
+            .select()
+            .where('likes.isValid = true')
+
+        if (req.search) {
+            const searchOptions = req.search as FindManyOptions<Likes>;
+            if ('where' in req.search) {
+                if ('where' in searchOptions && searchOptions.where) {
+                    for (const [key, value] of Object.entries(searchOptions.where)) {
+                        query.andWhere(`likes.${key} = ${value}`);
+                    }
+                }
+            }
+
+            if ('order' in req.search) {
+                if ('order' in searchOptions && searchOptions.order) {
+                    for (const [key, value] of Object.entries(searchOptions.order)) {
+                        query.addOrderBy(`likes.${key}`, value as 'ASC' | 'DESC');
+                    }
+                }
+            }
+        }
+
+        const page = await paginate<Likes>(query, { ...req.page })
+
+        const userIds: number[] = []
+        page.items.forEach(likes => {
+            userIds.push(likes.userId)
+        })
+
+        const newItems = await this.usersService.findInfoByIds(userIds)
+        const result: Pagination<Users> = {
+            items: newItems,
+            meta: page.meta
+        };
+
+        return result
+    }
+
+    async like(targetId: number, userId: number, type: number): Promise<Likes> {
+        let likes = await this.likesRepository.createQueryBuilder()
+            .where('userId = :userId', { userId })
+            .andWhere('targetId = :targetId', { targetId })
+            .andWhere('type = :type', { type })
+            .getOne()
+        if (likes) {
+            likes.isValid = !likes.isValid
+        } else {
+            likes = new Likes
+            likes.targetId = targetId
+            likes.userId = userId
+            likes.type = type
+        }
+        return await this.likesRepository.save(likes)
+    }
+
+}

+ 16 - 2
src/moments/moments.controller.ts

@@ -1,8 +1,9 @@
-import { BadRequestException, Body, Controller, Get, Param, Post } from "@nestjs/common";
+import { BadRequestException, Body, Controller, Get, HttpStatus, Param, Post } from "@nestjs/common";
 import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
 import { MomentsService } from "./moments.service";
 import { PageRequest } from "../common/dto/page-request";
 import { Moments } from "./entities/moments.entity";
+import { LikesDto } from "src/likes/dto/likes.dto";
 
 @ApiTags('moments')
 @Controller('/moments')
@@ -21,7 +22,20 @@ export class MomentsController {
         try {
             return await this.momentsService.findById(Number(id))
         } catch (err) {
-            throw  new BadRequestException(err, 'Error: Moments not existent!')
+            throw new BadRequestException(err, 'Error: Moments not existent!')
+        }
+    }
+
+    @Post('/like')
+    public async likes(@Body() likesDto: LikesDto) {
+        try {
+            await this.momentsService.like(likesDto.targetId, likesDto.userId)
+            return {
+                message: 'successes!',
+                status: HttpStatus.OK
+            }
+        } catch (err) {
+            throw new BadRequestException(err, 'Error: false!')
         }
     }
 

+ 2 - 2
src/moments/moments.module.ts

@@ -4,10 +4,10 @@ import { Moments } from './entities/moments.entity'
 import { MomentsController } from './moments.controller'
 import { MomentsService } from './moments.service'
 import { ChatRoleModule } from '../chat-role/chat-role.module'
-import { ChatRoleService } from '../chat-role/chat-role.service'
+import { LikesModule } from 'src/likes/likes.module'
 
 @Module({
-    imports: [TypeOrmModule.forFeature([Moments]), ChatRoleModule],
+    imports: [TypeOrmModule.forFeature([Moments]), ChatRoleModule, LikesModule],
     controllers: [MomentsController],
     providers: [MomentsService],
     exports: [MomentsService]

+ 16 - 2
src/moments/moments.service.ts

@@ -14,14 +14,15 @@ import { Moments } from './entities/moments.entity'
 import { paginate, Pagination } from 'nestjs-typeorm-paginate'
 import { PageRequest } from '../common/dto/page-request'
 import { ChatRoleService } from '../chat-role/chat-role.service'
-import { ro } from 'date-fns/locale'
+import { LikesService } from 'src/likes/likes.service'
 
 @Injectable()
 export class MomentsService {
     constructor(
         @InjectRepository(Moments)
         private readonly momentsRepository: Repository<Moments>,
-        private readonly chatRoleService: ChatRoleService
+        private readonly chatRoleService: ChatRoleService,
+        private readonly likesService: LikesService
     ) { }
 
     async findAll(req: PageRequest<Moments>): Promise<Pagination<Moments>> {
@@ -48,4 +49,17 @@ export class MomentsService {
         return moments
     }
 
+    public async like(id: number, userId: number): Promise<void> {
+        const moments = await this.momentsRepository.findOneBy({ id: +id })
+        if (moments) {
+            const likes = await this.likesService.like(id, userId, 2)
+            if (likes.isValid) {
+                moments.momentsLikeCount += 1
+            } else {
+                moments.momentsLikeCount -= 1
+            }
+            await this.momentsRepository.save(moments)
+        }
+    }
+
 }

+ 12 - 2
src/users/users.service.ts

@@ -7,7 +7,7 @@ import {
     InternalServerErrorException,
     UnauthorizedException
 } from '@nestjs/common'
-import { Repository, UpdateResult } from 'typeorm'
+import { In, Repository, UpdateResult } from 'typeorm'
 import { InjectRepository } from '@nestjs/typeorm'
 import { Users } from './entities/users.entity'
 import { IUsers } from './interfaces/users.interface'
@@ -30,7 +30,7 @@ export class UsersService {
         private readonly hashingService: HashingService,
         private readonly smsService: SmsService,
         private readonly membershipService: MembershipService
-    ) {}
+    ) { }
 
     async findAll(req: PageRequest<Users>): Promise<Pagination<Users>> {
         return await paginate<Users>(this.userRepository, req.page, req.search)
@@ -60,6 +60,16 @@ export class UsersService {
         return user
     }
 
+    async findInfoByIds(userIds: number[]): Promise<Users[]> {
+        const userList = await this.userRepository.createQueryBuilder('users')
+            .select(['users.id', 'users.name'])
+            .where({
+                id: In(userIds),
+            }).getMany()
+
+        return userList
+    }
+
     public async loginByPhone(phone: string, code: string, invitor: number | null): Promise<Users> {
         const verified = await this.smsService.verify(phone, code)
         if (!verified) {