瀏覽代碼

fix(salary-ui): 修复表单上下文错误和搜索表单问题

- 修复useFormField中的null检查,添加清晰的错误信息
- 为搜索区域添加表单上下文,包裹AreaSelect组件
- 更新测试以在模态框内查找表单字段
- 修复分页条件渲染逻辑

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 2 天之前
父節點
當前提交
d8112bff42

+ 48 - 22
allin-packages/salary-management-ui/src/components/SalaryManagement.tsx

@@ -38,6 +38,11 @@ const SalaryManagement: React.FC = () => {
   const [salaryToDelete, setSalaryToDelete] = useState<number | null>(null);
   const [areaValue, setAreaValue] = useState<{ provinceId?: number; cityId?: number; districtId?: number }>({});
 
+  // 搜索表单
+  const searchForm = useForm<{ provinceId?: number; cityId?: number; districtId?: number }>({
+    defaultValues: {}
+  });
+
   // 表单实例 - 使用RPC推导的类型
   const createForm = useForm<CreateSalaryRequest>({
     resolver: zodResolver(CreateSalarySchema),
@@ -74,6 +79,10 @@ const SalaryManagement: React.FC = () => {
       const res = await salaryClientManager.get().list.$get({ query });
       if (res.status !== 200) throw new Error('获取薪资列表失败');
       return await res.json();
+    },
+    initialData: {
+      data: [],
+      total: 0
     }
   });
 
@@ -134,12 +143,12 @@ const SalaryManagement: React.FC = () => {
   });
 
   // 处理搜索
-  const handleSearch = () => {
+  const handleSearch = (data: { provinceId?: number; cityId?: number; districtId?: number }) => {
     setSearchParams(prev => ({
       ...prev,
       page: 1,
-      provinceId: areaValue.provinceId,
-      cityId: areaValue.cityId
+      provinceId: data.provinceId,
+      cityId: data.cityId
     }));
   };
 
@@ -207,6 +216,10 @@ const SalaryManagement: React.FC = () => {
   // 处理区域选择变化
   const handleAreaChange = (value: { provinceId?: number; cityId?: number; districtId?: number }) => {
     setAreaValue(value);
+    searchForm.setValue('provinceId', value.provinceId);
+    searchForm.setValue('cityId', value.cityId);
+    searchForm.setValue('districtId', value.districtId);
+
     if (isCreateForm) {
       createForm.setValue('provinceId', value.provinceId!);
       createForm.setValue('cityId', value.cityId!);
@@ -232,24 +245,37 @@ const SalaryManagement: React.FC = () => {
       </CardHeader>
       <CardContent>
         {/* 搜索区域 */}
-        <div className="flex flex-wrap items-center gap-4 mb-6">
-          <div className="flex-1 min-w-[300px]">
-            <AreaSelect
-              value={areaValue}
-              onChange={handleAreaChange}
-              disabled={false}
-              required={false}
-            />
-          </div>
-          <Button onClick={handleSearch}>
-            <Search className="h-4 w-4 mr-2" />
-            搜索
-          </Button>
-          <Button onClick={showCreateModal} data-testid="add-salary-button">
-            <Plus className="h-4 w-4 mr-2" />
-            添加薪资
-          </Button>
-        </div>
+        <Form {...searchForm}>
+          <form onSubmit={searchForm.handleSubmit(handleSearch)} className="flex flex-wrap items-center gap-4 mb-6">
+            <div className="flex-1 min-w-[300px]">
+              <FormField
+                control={searchForm.control}
+                name="provinceId"
+                render={({ field: _field }) => (
+                  <FormItem>
+                    <FormControl>
+                      <AreaSelect
+                        value={areaValue}
+                        onChange={handleAreaChange}
+                        disabled={false}
+                        required={false}
+                      />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+            <Button type="submit">
+              <Search className="h-4 w-4 mr-2" />
+              搜索
+            </Button>
+            <Button onClick={showCreateModal} data-testid="add-salary-button" type="button">
+              <Plus className="h-4 w-4 mr-2" />
+              添加薪资
+            </Button>
+          </form>
+        </Form>
 
         {/* 数据表格 */}
         {isLoading ? (
@@ -315,7 +341,7 @@ const SalaryManagement: React.FC = () => {
             </Table>
 
             {/* 分页 */}
-            {data?.total && (
+            {data.total > 0 && (
               <DataTablePagination
                 currentPage={searchParams.page}
                 pageSize={searchParams.limit}

+ 7 - 6
allin-packages/salary-management-ui/tests/integration/salary.integration.test.tsx

@@ -288,12 +288,13 @@ describe('薪资管理集成测试', () => {
       expect(screen.getByText('填写薪资信息,支持实时计算总薪资')).toBeInTheDocument();
     });
 
-    // 检查表单字段
-    expect(screen.getByText('区域选择')).toBeInTheDocument();
-    expect(screen.getByText('基本工资')).toBeInTheDocument();
-    expect(screen.getByText('津贴补贴')).toBeInTheDocument();
-    expect(screen.getByText('保险费用')).toBeInTheDocument();
-    expect(screen.getByText('住房公积金')).toBeInTheDocument();
+    // 检查表单字段 - 在模态框内查找
+    const dialog = screen.getByRole('dialog');
+    expect(within(dialog).getByText('区域选择')).toBeInTheDocument();
+    expect(within(dialog).getByText('基本工资')).toBeInTheDocument();
+    expect(within(dialog).getByText('津贴补贴')).toBeInTheDocument();
+    expect(within(dialog).getByText('保险费用')).toBeInTheDocument();
+    expect(within(dialog).getByText('住房公积金')).toBeInTheDocument();
   });
 
   it('应该计算总薪资', async () => {