import { Body , Controller , Get , Param , Post , Query , Req , UseGuards } from '@nestjs/common' ; import * as _ from 'lodash' ; import { Permission } from '../../../common/generated-types' ; import { ID } from '../../../common/shared-types' ; import { EUserPostsBehavior } from '../../../common/types/common-types' ; import { formatAllMeta , formatOneMeta } from '../../../common/utils' ; import { HttpProcessor } from '../../../decorators/http.decorator' ; import { IQueryParamsResult , QueryParams } from '../../../decorators/query-params.decorator' ; import { Comment , Post as PostEntity } from '../../../entity' ; import { AttachmentService , CategoriesService , CommentService , OptionService , PostService , UserService } from '../../../service' ; import { Allow } from '../../decorators/allow.decorator' ; @ Controller ( 'posts' ) export class PostController { constructor ( private readonly userService , private readonly postService , private readonly optionService , private readonly categoriesService , private readonly attachmentService , private readonly commentService ) { } param page param limit @ Get ( ) @ Allow ( Permission . Authenticated ) async index ( @ Query ( 'page' ) page = 0 , @ Query ( 'limit' ) limit = 10 ) { limit = limit > 100 ? 100 : limit ; const data = await this . postService . paginate ( { page , limit , route : 'posts' , } ) ; await this . dealDataList ( data . items ) ; return data ; } @ Get ( 'categories/:category' ) @ Allow ( Permission . Authenticated ) async findByCategory ( @ Req ( ) req , @ Param ( 'category' ) category , @ Query ( 'page' ) page = 0 , @ Query ( 'limit' ) limit = 10 ) { const query = req . query ; let list ; switch ( category ) { case 'new' : { list = await this . postService . getNews ( 10 ) ; break ; } case 'popular' : { list = await this . postService . getPopular ( ) ; break ; } case 'featured' : { const options = await this . optionService . load ( true ) ; const stickys = options . stickys ; list = await this . postService . getStickys ( stickys . default ) ; break ; } default : { list = await this . postService . getFromCategory ( category , undefined , query ) ; } } list = await this . dealDataList ( list ) ; return list ; } param postId param req @ Get ( ':id/views' ) @ HttpProcessor . handle ( '获取单个内容数据' ) @ Allow ( Permission . Owner ) async getViews ( @ Param ( 'id' ) postId , @ Req ( ) req ) { const result = await this . postService . getUsersByBehavior ( EUserPostsBehavior . VIEW , postId ) ; let iView = false ; let found = 0 ; const views = [ ] ; if ( ! _ . isEmpty ( result ) ) { if ( ! _ . isEmpty ( result . value ) ) { const list = JSON . parse ( result . value ) ; const exists = _ . find ( list , [ 'id' , req . user . id ] ) ; if ( exists ) { iView = true ; } found = list . length ; const users = await this . userService . getUsersDetailByIds ( _ . filter ( list , 'id' ) ) ; views . push ( ... users ) ; } } if ( views . length > 0 ) { formatAllMeta ( views ) ; for ( const user of views ) { Reflect . deleteProperty ( user , 'meta' ) ; } } return { found , iView , postId , views , } ; } param postId param req param ip @ Post ( ':id/views/new' ) @ Allow ( Permission . Owner ) async newViewer ( @ Param ( 'id' ) postId , @ Req ( ) req , @ QueryParams ( ) params ) { const ip = params . visitors . ip ; const result = await this . postService . getUsersByBehavior ( EUserPostsBehavior . VIEW , postId ) ; let iView = false ; let viewCount = 0 ; let updateResult ; if ( ! _ . isEmpty ( result ) ) { if ( ! _ . isEmpty ( result . value ) ) { const list = JSON . parse ( result . value ) ; viewCount = list . length ; iView = _ . find ( list , item => { return item . id . toString ( ) === req . user . id . toString ( ) ; } ) ; if ( ! iView ) { updateResult = await this . postService . newViewer ( req . user . id , postId , ip ) ; if ( updateResult ) { viewCount ++ ; } } else { await this . postService . updateViewer ( req . user . id , postId , ip ) ; } } } else { updateResult = await this . postService . newViewer ( req . user . id , postId , ip ) ; if ( updateResult ) { viewCount ++ ; } } return { iView : true , viewCount , postId , } ; } param postId param req param page param limit @ Get ( ':id/comments' ) @ Allow ( Permission . Owner ) async getComments ( @ Param ( 'id' ) postId , @ Req ( ) req , @ Query ( 'page' ) page , @ Query ( 'limit' ) limit ) { limit = limit > 100 ? 100 : limit ; const data = await this . commentService . paginate ( { page , limit , route : 'posts' , } ) ; return data ; } /**
     * 新评论
     */ @ Post ( ':id/comments/new' ) @ Allow ( Permission . Owner ) async newComment ( @ Param ( 'id' ) postId , @ Req ( ) req , @ QueryParams ( ) params , @ Body ( ) comment ) { const ip = params . visitors . ip ; const commentInput = new Comment ( { ip , ... comment , } ) ; const data = await this . commentService . create ( commentInput ) ; return data ; } @ Get ( ':id' ) @ Allow ( Permission . Authenticated ) async one ( @ Param ( 'id' ) id ) { const post = await this . postService . findById ( id ) ; let data ; data = await this . decoratorTerms ( post ) ; switch ( post . type ) { case 'page' : { data = await this . decoratorIsPage ( data ) ; break ; } case 'post_format' : { data = await this . formatData ( data ) ; break ; } default : break ; } data = await this . dealBlock ( data ) ; data = await this . decoratorSingleData ( data ) ; Reflect . deleteProperty ( data , 'meta' ) ; return data ; } private async decoratorSingleData ( data ) { data = formatOneMeta ( data ) ; return await this . _formatOneData ( data ) ; } private async dealDataList ( list ) { formatAllMeta ( list ) ; for ( const item of list ) { await this . _formatOneData ( item ) ; } return list ; } private async _formatOneData ( item ) { if ( _ . has ( item . meta , '_items' ) ) { item . blockStatus = item . meta . _items ; } let result = { ... item } ; result . url = '' ; if ( ! Object . is ( result . meta . _audio_id , undefined ) ) { result . url = await this . attachmentService . getAttachment ( result . meta . _audio_id ) ; } result . authorInfo = await this . userService . getDetailById ( result . author ) ; formatOneMeta ( result . authorInfo ) ; if ( _ . has ( result . authorInfo , 'meta' ) ) { if ( _ . has ( result . authorInfo . meta , 'avatar' ) ) { result . authorInfo . avatarUrl = await this . attachmentService . getAttachment ( result . authorInfo . meta . avatar ) ; } if ( ! Object . is ( result . authorInfo . meta [ `_wechat` ] , undefined ) ) { result . authorInfo . avatarUrl = result . authorInfo . meta [ `_wechat` ] . avatarUrl ; } if ( _ . has ( result . authorInfo . meta , 'resume' ) ) { result . authorInfo . resume = result . authorInfo . meta . resume ; } Reflect . deleteProperty ( result . authorInfo , 'meta' ) ; } if ( _ . has ( result . authorInfo , 'liked' ) ) { Reflect . deleteProperty ( result . authorInfo , 'liked' ) ; } result . likeCount = await this . postService . countByBehavior ( EUserPostsBehavior . LIKE , result . id ) ; result . viewCount = await this . postService . countByBehavior ( EUserPostsBehavior . VIEW , result . id ) ; if ( _ . has ( result . meta , '_thumbnail_id' ) ) { const featured_image = await this . attachmentService . getAttachment ( result . meta . _thumbnail_id ) ; result = Object . assign ( result , { featured_image } ) ; } item = Object . assign ( item , result ) ; Reflect . deleteProperty ( item , 'meta' ) ; return item ; } param post private async decoratorTerms ( post ) { const data = { } ; data . categories = _ . map ( await this . categoriesService . findCategoriesByObject ( post . id ) , 'taxonomyId' ) ; const postTermFormat = await this . categoriesService . formatTermForObject ( post . id ) ; if ( postTermFormat && ! _ . isEmpty ( postTermFormat ) ) { post . type = postTermFormat . slug ; } return Object . assign ( { } , post , PostEntity ) ; } private async decoratorTags ( data ) { data . tags = await this . categoriesService . getTagsByObject ( data . id ) ; } param obj private async dealBlock ( post ) { if ( ! _ . isEmpty ( post . block ) ) { const blockList = await this . postService . loadBLock ( post . block ) ; post . block = blockList ; } return post ; } /**
     * 格式化数据
     */ private async formatData ( post ) { return await this . postService . getFormatData ( post ) ; } param post private async decoratorIsPage ( post ) { const options = await this . optionService . load ( ) ; const stickys = options . stickys ; const isSticky = _ . find ( stickys . default , id => { return post . id === id ; } ) ; let data ; if ( isSticky ) { data = Object . assign ( { } , post , { isSticky : true , } ) ; } else { data = Object . assign ( { } , post , { isSticky : false , } ) ; } return data ; } }