---
description: "Shadcn-ui 管理页表单创建/编辑表单分离指令"
---

将 创建/编辑表单分离
不要 <Form {...(isCreateForm ? createForm : updateForm)}></Form>
要     
{isCreateForm ? (
  // 创建表单（独立渲染）
  <Form {...createForm}>
  </Form>
) : (
  // 编辑表单（独立渲染）
  <Form {...updateForm}>
  </Form>
)}


### 创建/编辑表单分离模式（推荐）

基于 `src/client/admin-shadcn/pages/Users.tsx` 的最佳实践，创建/编辑表单分离模式通过以下方式解决创建/编辑时数据对象类型差异问题：

#### 核心优势
1. **类型安全**：创建使用 `CreateEntityDto`，编辑使用 `UpdateEntityDto`，避免类型冲突
2. **字段差异处理**：创建时的必填字段在编辑时自动变为可选
3. **敏感字段处理**：密码等敏感字段在编辑时可设为可选
4. **状态隔离**：两种模式完全独立，避免状态污染

#### 完整实现模板
```typescript
// 1. 类型定义（使用真实后端类型）
type CreateRequest = InferRequestType<typeof apiClient.$post>['json'];
type UpdateRequest = InferRequestType<typeof apiClient[':id']['$put']>['json'];
type EntityResponse = InferResponseType<typeof apiClient.$get, 200>['data'][0];

// 2. 状态管理
const [isModalOpen, setIsModalOpen] = useState(false);
const [editingEntity, setEditingEntity] = useState<EntityResponse | null>(null);
const [isCreateForm, setIsCreateForm] = useState(true);

// 3. 分离的表单实例
const createForm = useForm<CreateRequest>({
  resolver: zodResolver(CreateEntityDto),
  defaultValues: {
    // 创建时必须提供的默认值
  },
});

const updateForm = useForm<UpdateRequest>({
  resolver: zodResolver(UpdateEntityDto),
  defaultValues: {
    // 更新时的默认值（会被实际数据覆盖）
  },
});

// 4. 表单操作函数
const handleCreate = () => {
  setEditingEntity(null);
  setIsCreateForm(true);
  createForm.reset({
    // 创建时的初始值
    status: 1, // 示例：默认启用
  });
  setIsModalOpen(true);
};

const handleEdit = (entity: EntityResponse) => {
  setEditingEntity(entity);
  setIsCreateForm(false);
  updateForm.reset({
    ...entity,
    // 关键：处理创建/编辑字段差异
    password: undefined, // 密码在更新时可选
    confirmPassword: undefined,
    // 其他需要特殊处理的字段
  });
  setIsModalOpen(true);
};

// 5. 提交处理
const handleCreateSubmit = async (data: CreateRequest) => {
  try {
    const res = await apiClient.$post({ json: data });
    if (res.status !== 201) throw new Error('创建失败');
    toast.success('创建成功');
    setIsModalOpen(false);
    refetch();
  } catch (error) {
    toast.error('创建失败，请重试');
  }
};

const handleUpdateSubmit = async (data: UpdateRequest) => {
  if (!editingEntity) return;
  
  try {
    const res = await apiClient[':id']['$put']({
      param: { id: editingEntity.id },
      json: data
    });
    if (res.status !== 200) throw new Error('更新失败');
    toast.success('更新成功');
    setIsModalOpen(false);
    refetch();
  } catch (error) {
    toast.error('更新失败，请重试');
  }
};
```

#### 对话框渲染模板
```tsx
<Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>
  <DialogContent className="sm:max-w-[500px] max-h-[90vh] overflow-y-auto">
    <DialogHeader>
      <DialogTitle>{isCreateForm ? '创建实体' : '编辑实体'}</DialogTitle>
      <DialogDescription>
        {isCreateForm ? '创建一个新的实体' : '编辑现有实体信息'}
      </DialogDescription>
    </DialogHeader>
    
    {isCreateForm ? (
      // 创建表单（独立渲染）
      <Form {...createForm}>
        <form onSubmit={createForm.handleSubmit(handleCreateSubmit)} className="space-y-4">
          {/* 创建专用字段 - 必填 */}
          <FormField
            control={createForm.control}
            name="username"
            render={({ field }) => (
              <FormItem>
                <FormLabel className="flex items-center">
                  用户名
                  <span className="text-red-500 ml-1">*</span>
                </FormLabel>
                <FormControl>
                  <Input placeholder="请输入用户名" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          
          {/* 创建时必填的密码 */}
          <FormField
            control={createForm.control}
            name="password"
            render={({ field }) => (
              <FormItem>
                <FormLabel className="flex items-center">
                  密码
                  <span className="text-red-500 ml-1">*</span>
                </FormLabel>
                <FormControl>
                  <Input type="password" placeholder="请输入密码" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          
          <DialogFooter>
            <Button type="button" variant="outline" onClick={() => setIsModalOpen(false)}>
              取消
            </Button>
            <Button type="submit">创建</Button>
          </DialogFooter>
        </form>
      </Form>
    ) : (
      // 编辑表单（独立渲染）
      <Form {...updateForm}>
        <form onSubmit={updateForm.handleSubmit(handleUpdateSubmit)} className="space-y-4">
          {/* 编辑专用字段 - 可选 */}
          <FormField
            control={updateForm.control}
            name="username"
            render={({ field }) => (
              <FormItem>
                <FormLabel className="flex items-center">
                  用户名
                  <span className="text-red-500 ml-1">*</span>
                </FormLabel>
                <FormControl>
                  <Input placeholder="请输入用户名" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          
          {/* 编辑时可选的密码 */}
          <FormField
            control={updateForm.control}
            name="password"
            render={({ field }) => (
              <FormItem>
                <FormLabel>新密码</FormLabel>
                <FormControl>
                  <Input type="password" placeholder="留空则不修改密码" {...field} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          
          <DialogFooter>
            <Button type="button" variant="outline" onClick={() => setIsModalOpen(false)}>
              取消
            </Button>
            <Button type="submit">更新</Button>
          </DialogFooter>
        </form>
      </Form>
    )}
  </DialogContent>
</Dialog>
```

