nest 列表参数解析装饰器

1,775 阅读3分钟

列表查询是后台最常见的操作,一般有3类参数,

  • 页码参数,
  • where查询条件
  • order排序参数

我希望在nest控制器接收到前端参数后做一个统一的处理, 下面借助nest提供的createParamDecorator封装一个统一的列表参数解析装饰器


list-params.decorator.ts

import { createParamDecorator } from '@nestjs/common';
import * as lodash from 'lodash';
/**自定义查询的 where和order条件 */
export interface IParamsConfig {
  whereOptions?: string[];
  defaultOrder?: {
    [key: string]: 'DESC' | 'ASC'
  }
}
/**
 * 返回结构
 * pageParams页码参数;where条件;order条件;
 */
export interface IParamsResult {
  pageParams: {
    everyPage: number;
    currentPage: number
  };
  where: any;
  order: { [key: string]: 'DESC' | 'ASC' };
}
/**
 * 分页列表参数解析装饰器 必须是 get请求
 * 前端传参示例{currentPage:2,everyPage:10,orderBy:'createTime',orderValue:'ASC',...其他where条件}
 */
export const ListParams = createParamDecorator((customConfig: IParamsConfig, req): IParamsResult => {
  const query = req.query
  const pageParams = {
    everyPage: Number(query.everyPage || 10),
    currentPage: Number(query.currentPage || 1)
  }
  let where = {}
  let order = {}
  // customConfig 是自定义的查询配置
  if (lodash.isObject(customConfig)) {
    // 处理where条件
    if (lodash.isArray(customConfig.whereOptions)) {
      customConfig.whereOptions.forEach(item => {
        if (!lodash.isUndefined(query[item]) && query[item] !== '') {
          where[item] = query[item]
        }
      })
    }
    // 处理order默认条件
    if (lodash.isObject(customConfig.defaultOrder)) {
      order = customConfig.defaultOrder
    }
    // 处理前端传来的order条件
    if (lodash.isString(query.orderBy)) {
      const verifyOrderValue = ['DESC', 'ASC'].includes(query.orderValue)
      if (verifyOrderValue) {
        order = { [query.orderBy]: query.orderValue }
      }
    }
  }
  return { pageParams, where, order }
});

在控制器和服务中使用示例

question.controllor.ts

import { Controller, Get } from "@nestjs/common";
import { ListParams, IParamsResult } from '@/decorator/list-params.decorator'
import { QuestionService } from "./question.service";
@Controller('question')
export class QuestionControllor {
  constructor(
    private readonly questionService: QuestionService,
  ) { }
  /**查询问题列表 分页+条件查询 */
  @Get('list')
  async queryFileList(@ListParams({
    // 条件查询字段
    whereOptions: ['positionId''questionType'],
    // 默认排序
    defaultOrder: { 'createTime''DESC' }
  }) params: IParamsResult) {
    return await this.questionService.find(params)
  }
}

question.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { IParamsResult } from '@/decorator/list-params.decorator'
import { QuestionEntity } from './question.entity';
@Injectable()
export class QuestionService {
  constructor(
    @InjectRepository(QuestionEntity)
    private readonly questionEntity: Repository<QuestionEntity>
  ) { }
  /**查询列表 分页 */
  async find({ pageParams, where, order }: IParamsResult) {
    const [rows, totalRecords] = await this.questionEntity.findAndCount({
      where,
      order,
      relations: ['options'],
      skip: (pageParams.currentPage - 1) * pageParams.everyPage,
      take: pageParams.everyPage,
    })
    return {
      page: { totalRecords, ...pageParams },
      rows
    }
  }
}