# 通用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关系: ```json { "status": 1, "name": "%张%", "createdAt": {"gte": "2024-01-01"} } ``` ## API使用规范 ### 请求格式 ```http GET /api/v1/entities?filters={"status":1,"name":"%张%","createdAt":{"gte":"2024-01-01"}} ``` ### 响应格式 ```json { "data": [...], "pagination": { "total": 100, "current": 1, "pageSize": 10 } } ``` ### 错误处理 - 格式错误:返回400状态码,message为"筛选条件格式错误" - 字段不存在:安全忽略,不影响查询 - 类型不匹配:安全处理,返回空结果 ## 前端集成规范 ### React Hook示例 ```typescript 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集成 ```typescript 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使用 ```typescript // 直接使用(无需修改) 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 { async getList( page: number = 1, pageSize: number = 10, keyword?: string, searchFields?: string[], where?: Partial, 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. 类型安全 ```typescript // 推荐:定义筛选类型 interface UserFilters { status?: number; name?: string; age?: { gte?: number; lte?: number }; createdAt?: { between?: [string, string] }; } // 使用时 const filters: UserFilters = { status: 1 }; ``` ### 4. 错误处理 ```typescript 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调用 - 新增参数为可选,不传递时保持原有行为 - 错误时返回标准化错误响应