列表查询是后台最常见的操作,一般有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
}
}
}