14-crud-filtering.md 5.0 KB

通用CRUD筛选规范

概述

本规范定义了通用CRUD模块的增强筛选功能,支持多种查询模式和灵活的筛选条件。

新增功能

1. 筛选参数支持

  • 参数名: filters
  • 类型: JSON字符串
  • 位置: 查询参数
  • 可选: 是

2. 支持的筛选操作

操作类型 语法格式 示例 说明
精确匹配 "字段名": 值 {"status": 1} 等于指定值
模糊匹配 "字段名": "%值%" {"name": "%张%"} LIKE查询,包含指定值
大于 "字段名": {"gt": 值} {"age": {"gt": 18}} 大于指定值
大于等于 "字段名": {"gte": 值} {"age": {"gte": 18}} 大于等于指定值
小于 "字段名": {"lt": 值} {"score": {"lt": 60}} 小于指定值
小于等于 "字段名": {"lte": 值} {"score": {"lte": 60}} 小于等于指定值
范围查询 "字段名": {"between": [最小值, 最大值]} {"createdAt": {"between": ["2024-01-01", "2024-12-31"]}} 在指定范围内
IN查询 "字段名": [值1, 值2, ...] {"status": [1, 2, 3]} 值在指定数组中
NULL匹配 "字段名": null {"deletedAt": null} 字段为NULL

3. 组合查询

支持多个条件同时筛选,所有条件为AND关系:

{
  "status": 1,
  "name": "%张%",
  "createdAt": {"gte": "2024-01-01"}
}

API使用规范

请求格式

GET /api/v1/entities?filters={"status":1,"name":"%张%","createdAt":{"gte":"2024-01-01"}}

响应格式

{
  "data": [...],
  "pagination": {
    "total": 100,
    "current": 1,
    "pageSize": 10
  }
}

错误处理

  • 格式错误:返回400状态码,message为"筛选条件格式错误"
  • 字段不存在:安全忽略,不影响查询
  • 类型不匹配:安全处理,返回空结果

前端集成规范

React Hook示例

const useEntityList = () => {
  const [data, setData] = useState([]);
  
  const fetchData = async (filters = {}) => {
    const response = await client.$get({
      query: {
        page: 1,
        pageSize: 10,
        filters: JSON.stringify(filters)
      }
    });
    // 处理响应...
  };
  
  return { data, fetchData };
};

ProTable集成

const columns = [
  {
    title: '状态',
    dataIndex: 'status',
    valueType: 'select',
    valueEnum: { 0: '禁用', 1: '启用' },
  },
  {
    title: '创建时间',
    dataIndex: 'createdAt',
    valueType: 'dateRange',
  },
];

const handleRequest = async (params) => {
  const filters = {};
  
  if (params.status !== undefined) filters.status = params.status;
  if (params.createdAt?.length === 2) {
    filters.createdAt = { between: params.createdAt };
  }
  
  return client.$get({
    query: {
      page: params.current,
      pageSize: params.pageSize,
      keyword: params.keyword,
      filters: JSON.stringify(filters)
    }
  });
};

后端实现规范

GenericCrudService使用

// 直接使用(无需修改)
const service = new GenericCrudService(dataSource, UserEntity);
const [data, total] = await service.getList(
  page, pageSize, keyword, searchFields, where, relations, order, filters
);

// 自定义实现
export class UserService extends GenericCrudService<User> {
  async getList(
    page: number = 1,
    pageSize: number = 10,
    keyword?: string,
    searchFields?: string[],
    where?: Partial<User>,
    relations: string[] = [],
    order: any = {},
    filters?: any
  ) {
    // 添加业务特定的筛选
    const customFilters = {
      ...filters,
      isDeleted: 0
    };
    
    return super.getList(page, pageSize, keyword, searchFields, where, relations, order, customFilters);
  }
}

最佳实践

1. 性能优化

  • 为常用筛选字段添加数据库索引
  • 避免对大字段进行模糊查询
  • 合理使用分页参数

2. 安全考虑

  • 避免传递敏感字段到filters
  • 验证用户权限相关的筛选条件
  • 限制查询结果集大小

3. 类型安全

// 推荐:定义筛选类型
interface UserFilters {
  status?: number;
  name?: string;
  age?: { gte?: number; lte?: number };
  createdAt?: { between?: [string, string] };
}

// 使用时
const filters: UserFilters = { status: 1 };

4. 错误处理

try {
  const filters = JSON.parse(query.filters);
  // 验证filters结构...
} catch (error) {
  return { code: 400, message: '筛选条件格式错误' };
}

常见问题

Q: 如何忽略大小写的模糊匹配?

A: 使用标准SQL LIKE语法,数据库层面处理大小写

Q: 是否支持OR条件?

A: 当前版本仅支持AND关系,OR条件需要自定义实现

Q: 如何处理空字符串?

A: 空字符串会被自动忽略,不会加入筛选条件

Q: 是否支持嵌套对象筛选?

A: 支持,使用点表示法:{"related.field": "value"}

版本兼容

  • 完全向后兼容,不影响现有API调用
  • 新增参数为可选,不传递时保持原有行为
  • 错误时返回标准化错误响应