---
description: "检查并修正筛选表单指令"
---
# 筛选表单检查与修复指南
## 问题描述
在使用 React Hook Form 和状态管理进行筛选表单开发时,常见的同步问题包括:
1. **表单状态与查询参数不同步**:重置操作只清除查询参数,但表单字段值保持不变
2. **表单验证问题**:字段验证规则不完整或错误
3. **UI状态不一致**:筛选条件显示与实际查询条件不符
## 检查步骤
### 1. 检查表单重置功能
```bash
# 检查 handleReset 函数是否同时重置表单和查询参数
grep -n "handleReset" src/**/*.tsx
```
### 2. 检查表单字段同步
```bash
# 检查表单字段是否与查询参数正确映射
grep -n "setSearchParams\|form.reset" src/**/*.tsx
```
### 3. 验证表单字段定义
```bash
# 检查所有表单字段是否正确定义
grep -n "FormField\|control" src/**/*.tsx | head -10
```
## 常见问题及修复方案
### 问题1: 重置功能不完整
**症状**:点击重置按钮后,查询参数被清除但表单字段值保持不变
**修复方案**:
```typescript
// 错误示例 - 只重置查询参数
const handleReset = () => {
setSearchParams({
status: undefined,
keyword: undefined,
// ...其他参数
});
};
// 正确示例 - 同时重置表单和查询参数
const handleReset = () => {
// 重置表单字段值
form.reset({
status: undefined,
keyword: undefined,
dateRange: undefined,
// ...所有表单字段
});
// 重置搜索参数
setSearchParams({
status: undefined,
keyword: undefined,
startDate: undefined,
endDate: undefined,
// ...对应查询参数
});
};
```
### 问题2: Select组件缺少"全部"选项
**症状**:筛选表单中的Select组件缺少"全部"选项,用户无法取消筛选
**修复方案**:
```typescript
// 错误示例 - 缺少全部选项
{Object.values(StatusEnum).map(status => (
{StatusNameMap[status]}
))}
// 正确示例 - 添加全部选项(使用特殊值"all"并转换为undefined)
```
**注意事项**:
- Radix UI Select组件不允许使用空字符串作为SelectItem的value
- 使用特殊值"all"来表示全部选项,在onChange时转换为undefined
- 在value prop中使用 `field.value || "all"` 来确保选中状态正确显示
### 问题2: 表单字段映射错误
**症状**:表单字段名称与查询参数名称不一致
**修复方案**:
```typescript
// 确保表单字段名与查询参数名正确映射
const handleSearch = (values: any) => {
setSearchParams({
status: values.status, // 表单字段名 -> 查询参数名
keyword: values.keyword, // 保持一致
startDate: values.dateRange?.[0]?.toISOString(), // 复杂映射
endDate: values.dateRange?.[1]?.toISOString(),
});
};
```
### 问题3: 初始状态不一致
**症状**:组件挂载时表单初始值与查询参数不匹配
**修复方案**:
```typescript
// 使用 useEffect 同步初始状态
useEffect(() => {
const initialValues = {
status: searchParams.status || undefined,
keyword: searchParams.keyword || undefined,
dateRange: searchParams.startDate && searchParams.endDate
? [new Date(searchParams.startDate), new Date(searchParams.endDate)]
: undefined,
};
form.reset(initialValues);
}, []);
```
## 通用CRUD filters参数使用指南
### 问题4: 未使用通用CRUD的filters参数
**症状**:页面使用独立的查询参数而不是通用CRUD的标准filters参数
**修复方案**:
```typescript
// 错误示例 - 使用独立参数
const res = await client.$get({
query: {
page: 1,
pageSize: 10,
status: searchParams.status,
problemType: searchParams.problemType,
keyword: searchParams.keyword,
startDate: searchParams.startDate,
endDate: searchParams.endDate,
}
});
// 正确示例 - 使用通用CRUD filters参数
const filters: any = {};
if (searchParams.status) filters.status = searchParams.status;
if (searchParams.problemType) filters.problemType = searchParams.problemType;
if (searchParams.startDate && searchParams.endDate) {
filters.createdAt = {
between: [searchParams.startDate, searchParams.endDate]
};
}
const res = await client.$get({
query: {
page: 1,
pageSize: 10,
keyword: searchParams.keyword, // 独立的关键词参数
filters: Object.keys(filters).length > 0 ? JSON.stringify(filters) : undefined,
}
});
```
### 问题5: 关联字段搜索与筛选不支持
**症状**:无法通过关联实体的字段进行搜索和筛选(如设备名称、用户名称等)
**修复方案**:
1. **配置searchFields和relations**:
```typescript
const routes = createCrudRoutes({
entity: YourEntity,
searchFields: ['title', 'description', 'device.zichanInfo.assetName'], // 支持关联字段搜索(格式:relation.field 或 relation.nestedRelation.field)
relations: ['device.zichanInfo'], // 确保关联数据被加载
// ...其他配置
});
```
2. **使用关联字段筛选**:
```typescript
// 在filters参数中使用关联字段进行精确筛选
const filters = {
'device.zichanInfo.assetName': '服务器001', // 精确匹配
'device.zichanInfo.status': { gte: 1 }, // 范围查询
'device.zichanInfo.department.name': '%IT%' // 模糊匹配
};
const res = await client.$get({
query: {
page: 1,
pageSize: 10,
filters: JSON.stringify(filters)
}
});
```
**别名生成规则**:
- 单级关联:`device.zichanInfo` → 别名:`device_zichanInfo`
- 嵌套关联:`device.zichanInfo.department` → 别名:`device_zichanInfo_department`
- 字段引用:`device_zichanInfo.assetName`, `device_zichanInfo_department.name`
**支持的筛选操作**:
- 精确匹配:`{ "relation.field": "value" }`
- 模糊匹配:`{ "relation.field": "%value%" }`
- 范围查询:`{ "relation.field": { "gte": min, "lte": max } }`
- IN查询:`{ "relation.field": [value1, value2, ...] }`
## 完整代码示例
### 修复后的筛选表单组件(使用通用CRUD filters)
```typescript
import React from 'react';
import { useForm } from 'react-hook-form';
import { Form, FormField, FormItem, FormLabel, FormControl } from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Button } from '@/components/ui/button';
import { workOrderClient } from '@/client/api';
export function FilterForm() {
const [searchParams, setSearchParams] = useState({});
const form = useForm();
// 搜索处理 - 使用通用CRUD filters参数
const handleSearch = (values: any) => {
// 构建filters对象
const filters: any = {};
if (values.status) filters.status = values.status;
if (values.problemType) filters.problemType = values.problemType;
if (values.dateRange?.[0] && values.dateRange?.[1]) {
filters.createdAt = {
between: [values.dateRange[0], values.dateRange[1]]
};
}
setSearchParams({
keyword: values.keyword,
filters: Object.keys(filters).length > 0 ? JSON.stringify(filters) : undefined,
});
};
// 重置处理 - 修复后的版本
const handleReset = () => {
// 重置表单字段值
form.reset({
status: undefined,
keyword: undefined,
problemType: undefined,
dateRange: undefined,
});
// 重置搜索参数
setSearchParams({
keyword: undefined,
filters: undefined,
});
};
return (
);
}
```
## 最佳实践
1. **保持同步**:始终确保表单状态与查询参数同步
2. **完整重置**:重置操作应同时清除表单字段和查询参数
3. **类型安全**:为表单值和查询参数定义明确的 TypeScript 类型
4. **测试验证**:编写测试用例验证重置功能正常工作
5. **用户体验**:重置后应自动触发数据重新加载
## 自动化检查脚本
```bash
#!/bin/bash
# 检查筛选表单常见问题
echo "=== 筛选表单检查 ==="
# 检查 handleReset 函数
echo "1. 检查 handleReset 函数:"
grep -A 10 -B 2 "handleReset" src/**/*.tsx | grep -E "setSearchParams|form.reset"
# 检查表单字段映射
echo "2. 检查表单字段映射:"
grep -A 5 -B 5 "handleSearch" src/**/*.tsx
# 检查初始状态同步
echo "3. 检查初始状态同步:"
grep -A 10 -B 2 "useEffect.*searchParams" src/**/*.tsx
# 检查通用CRUD filters参数使用
echo "4. 检查通用CRUD filters参数使用:"
grep -A 5 -B 5 "filters.*JSON.stringify" src/**/*.tsx
# 检查关联字段搜索配置
echo "5. 检查关联字段搜索配置:"
grep -A 3 -B 3 "searchFields.*\." src/server/api/**/index.ts
echo "=== 检查完成 ==="
```
## 最佳实践更新
6. **标准接口**:优先使用通用CRUD的filters参数而不是独立参数
7. **关联搜索**:合理配置searchFields和relations支持关联字段搜索
8. **性能优化**:避免在filters中使用过多关联查询,必要时使用自定义服务方法
使用此指令可以快速识别和修复筛选表单中的常见同步问题,包括通用CRUD filters参数的使用和关联字段搜索功能。
使用此指令可以快速识别和修复筛选表单中的常见同步问题。