2
0

9 Коммитууд 0c7e164025 ... 1195f3117f

Эзэн SHA1 Мессеж Огноо
  yourname 1195f3117f 📝 docs(story): 更新故事008.007状态,测试通过率提升至100% 1 өдөр өмнө
  yourname 4360b6e342 🔧 fix(order): 修复批量添加人员测试,添加防止PersonSelector模态框关闭的逻辑 1 өдөр өмнө
  yourname 9348ed5495 📝 docs(story): 更新故事008.007状态,添加批量添加人员测试 1 өдөр өмнө
  yourname f84dd7134d 🔧 fix(order): 修复订单创建人员绑定测试,使用真实选择器组件 1 өдөр өмнө
  yourname 91de647aa2 ✅ chore(story): 更新故事008.007状态,标记任务10为完成 1 өдөр өмнө
  yourname ac3878d295 🔧 fix(disability): 修复残疾人选择器中AreaSelect组件的Form上下文问题 1 өдөр өмнө
  yourname d2741c6d90 🔧 fix(order): 调试订单创建人员绑定测试问题 1 өдөр өмнө
  yourname 8b9b715f4b ✨ feat(order): 修复订单创建时的人员绑定差异,集成残疾人选择器 1 өдөр өмнө
  yourname c657499634 📝 docs(story): 更新故事008.007,添加任务10修复订单创建时的人员绑定差异 1 өдөр өмнө

+ 13 - 5
allin-packages/disability-person-management-ui/src/components/DisabledPersonSelector.tsx

@@ -23,6 +23,8 @@ import { Checkbox } from '@d8d/shared-ui-components/components/ui/checkbox';
 import { Alert, AlertDescription } from '@d8d/shared-ui-components/components/ui/alert';
 import { AlertCircle } from 'lucide-react';
 import { AreaSelect } from '@d8d/area-management-ui';
+import { Form } from '@d8d/shared-ui-components/components/ui/form';
+import { useForm } from 'react-hook-form';
 import { disabilityClient } from '../api/disabilityClient';
 import type {
   DisabledPersonData,
@@ -59,6 +61,9 @@ const DisabledPersonSelector: React.FC<DisabledPersonSelectorProps> = ({
   const [showBlacklistConfirm, setShowBlacklistConfirm] = useState(false);
   const [pendingSelection, setPendingSelection] = useState<DisabledPersonData | DisabledPersonData[] | null>(null);
 
+  // 为AreaSelect创建表单上下文
+  const form = useForm();
+
   // 搜索残疾人列表
   const { data, isLoading, refetch } = useQuery({
     queryKey: ['disabled-persons-search', searchParams],
@@ -270,11 +275,14 @@ const DisabledPersonSelector: React.FC<DisabledPersonSelectorProps> = ({
             <div className="grid grid-cols-4 gap-4">
               <div className="space-y-2">
                 <Label>省份/城市</Label>
-                <AreaSelect
-                  value={areaSelection}
-                  onChange={setAreaSelection}
-                  data-testid="area-select"
-                />
+                {/* AreaSelect需要Form上下文,所以包装在Form中 */}
+                <Form {...form}>
+                  <AreaSelect
+                    value={areaSelection}
+                    onChange={setAreaSelection}
+                    data-testid="area-select"
+                  />
+                </Form>
               </div>
 
               <div className="space-y-2">

+ 3 - 0
allin-packages/order-management-ui/package.json

@@ -39,6 +39,9 @@
     "@d8d/shared-ui-components": "workspace:*",
     "@d8d/allin-order-module": "workspace:*",
     "@d8d/allin-disability-person-management-ui": "workspace:*",
+    "@d8d/allin-platform-management-ui": "workspace:*",
+    "@d8d/allin-company-management-ui": "workspace:*",
+    "@d8d/allin-channel-management-ui": "workspace:*",
     "@d8d/area-management-ui": "workspace:*",
     "@d8d/file-management-ui": "workspace:*",
     "@d8d/allin-enums": "workspace:*",

+ 360 - 41
allin-packages/order-management-ui/src/components/OrderForm.tsx

@@ -12,6 +12,16 @@ import {
   DialogHeader,
   DialogTitle,
 } from '@d8d/shared-ui-components/components/ui/dialog';
+import {
+  Card,
+  CardContent,
+  CardDescription,
+  CardHeader,
+  CardTitle,
+} from '@d8d/shared-ui-components/components/ui/card';
+import { Badge } from '@d8d/shared-ui-components/components/ui/badge';
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@d8d/shared-ui-components/components/ui/table';
+import { Separator } from '@d8d/shared-ui-components/components/ui/separator';
 import {
   Form,
   FormControl,
@@ -31,10 +41,27 @@ import {
 import { Input } from '@d8d/shared-ui-components/components/ui/input';
 import { Textarea } from '@d8d/shared-ui-components/components/ui/textarea';
 import { toast } from 'sonner';
+import { User, Users, X } from 'lucide-react';
 import { AreaSelect } from '@d8d/area-management-ui';
 import { OrderStatus, WorkStatus } from '@d8d/allin-enums';
+import { DisabledPersonSelector } from '@d8d/allin-disability-person-management-ui';
+import { PlatformSelector } from '@d8d/allin-platform-management-ui';
+import { CompanySelector } from '@d8d/allin-company-management-ui';
+import { ChannelSelector } from '@d8d/allin-channel-management-ui';
 import { orderClient } from '../api/orderClient';
 import type { OrderDetail } from '../api/types';
+import type { DisabledPersonData } from '@d8d/allin-disability-person-management-ui';
+
+// 人员信息Schema
+const personInfoSchema = z.object({
+  personId: z.number().int().positive('请选择人员'),
+  joinDate: z.string().datetime('请选择有效的入职日期'),
+  salaryDetail: z.string().min(1, '薪资详情不能为空'),
+  leaveDate: z.string().datetime().optional(),
+  workStatus: z.nativeEnum(WorkStatus).optional(),
+  role: z.string().max(50, '角色不能超过50个字符').optional(),
+  remark: z.string().max(200, '备注不能超过200个字符').optional(),
+});
 
 // 订单表单Schema
 const orderFormSchema = z.object({
@@ -53,6 +80,7 @@ const orderFormSchema = z.object({
   contactPerson: z.string().max(50, '联系人不能超过50个字符').optional(),
   contactPhone: z.string().regex(/^1[3-9]\d{9}$/, '请输入有效的手机号').optional(),
   remark: z.string().max(500, '备注不能超过500个字符').optional(),
+  orderPersons: z.array(personInfoSchema).min(1, '至少选择一名人员'),
 });
 
 type OrderFormValues = z.infer<typeof orderFormSchema>;
@@ -72,6 +100,25 @@ export const OrderForm: React.FC<OrderFormProps> = ({
 }) => {
   const queryClient = useQueryClient();
   const [isSubmitting, setIsSubmitting] = useState(false);
+  const [selectedPersons, setSelectedPersons] = useState<DisabledPersonData[]>([]);
+  const [isPersonSelectorOpen, setIsPersonSelectorOpen] = useState(false);
+
+  // 当残疾人选择器打开时,防止订单表单关闭
+  useEffect(() => {
+    // 这个effect只是用于调试
+    console.debug('OrderForm: isPersonSelectorOpen changed to', isPersonSelectorOpen);
+  }, [isPersonSelectorOpen]);
+
+  // 处理Dialog的onOpenChange,防止在残疾人选择器打开时关闭订单表单
+  const handleDialogOpenChange = (newOpen: boolean) => {
+    console.debug('OrderForm: handleDialogOpenChange called with', newOpen, 'isPersonSelectorOpen:', isPersonSelectorOpen);
+    if (isPersonSelectorOpen && !newOpen) {
+      console.debug('OrderForm: 阻止订单表单关闭,因为残疾人选择器正在打开');
+      return; // 如果残疾人选择器正在打开,阻止订单表单关闭
+    }
+    onOpenChange(newOpen);
+  };
+
 
   // 初始化表单 - 根据UI包开发规范,必须使用条件渲染两个独立的Form组件
   // 这里使用同一个组件,但通过reset来区分创建和编辑模式
@@ -93,6 +140,7 @@ export const OrderForm: React.FC<OrderFormProps> = ({
       contactPerson: '',
       contactPhone: '',
       remark: '',
+      orderPersons: [],
     },
   });
 
@@ -117,7 +165,10 @@ export const OrderForm: React.FC<OrderFormProps> = ({
         contactPerson: orderData.contactPerson || '',
         contactPhone: orderData.contactPhone || '',
         remark: orderData.remark || '',
+        orderPersons: [],
       });
+      // 编辑模式下清空已选择的人员
+      setSelectedPersons([]);
     } else if (!order && open) {
       form.reset({
         orderName: '',
@@ -135,7 +186,10 @@ export const OrderForm: React.FC<OrderFormProps> = ({
         contactPerson: '',
         contactPhone: '',
         remark: '',
+        orderPersons: [],
       });
+      // 创建模式下清空已选择的人员
+      setSelectedPersons([]);
     }
   }, [order, open, form]);
 
@@ -194,10 +248,54 @@ export const OrderForm: React.FC<OrderFormProps> = ({
     setIsSubmitting(true);
     try {
       if (order?.id) {
+        // 编辑订单:只更新订单信息,不处理人员
         await updateMutation.mutateAsync({ ...data, id: order.id });
       } else {
-        await createMutation.mutateAsync(data);
+        // 创建订单:先创建订单,然后批量添加人员
+        // 提取订单基本信息(不包含orderPersons)
+        const { orderPersons, ...orderData } = data;
+
+        // 创建订单
+        const createResponse = await orderClient.create.$post({
+          json: orderData,
+        });
+
+        if (!createResponse.ok) {
+          const error = await createResponse.json();
+          throw new Error(error.message || '创建订单失败');
+        }
+
+        const createdOrder = await createResponse.json();
+        toast.success('订单创建成功');
+
+        // 如果有人员信息,批量添加人员
+        if (orderPersons && orderPersons.length > 0) {
+          try {
+            const batchResponse = await orderClient[':orderId'].persons.batch.$post({
+              param: { orderId: createdOrder.id },
+              json: { persons: orderPersons },
+            });
+
+            if (!batchResponse.ok) {
+              const error = await batchResponse.json();
+              throw new Error(error.message || '批量添加人员失败');
+            }
+
+            toast.success(`成功添加 ${orderPersons.length} 名人员到订单`);
+          } catch (batchError) {
+            // 人员添加失败,但订单已创建成功
+            toast.warning(`订单创建成功,但添加人员失败: ${batchError instanceof Error ? batchError.message : '未知错误'}`);
+          }
+        }
+
+        // 刷新订单列表
+        queryClient.invalidateQueries({ queryKey: ['orders'] });
+        onOpenChange(false);
+        form.reset();
+        onSuccess?.();
       }
+    } catch (error) {
+      toast.error(`操作失败: ${error instanceof Error ? error.message : '未知错误'}`);
     } finally {
       setIsSubmitting(false);
     }
@@ -210,6 +308,70 @@ export const OrderForm: React.FC<OrderFormProps> = ({
     form.setValue('districtId', value.districtId, { shouldValidate: true });
   };
 
+  // 处理残疾人选择
+  const handlePersonSelect = (persons: DisabledPersonData | DisabledPersonData[]) => {
+    if (Array.isArray(persons)) {
+      // 多选模式
+      const newPersons = persons.filter(
+        person => !selectedPersons.some(p => p.id === person.id)
+      );
+      setSelectedPersons(prev => [...prev, ...newPersons]);
+
+      // 更新表单值 - 根据后端API要求包含必需字段
+      const currentPersons = form.getValues('orderPersons') || [];
+      const newFormPersons = newPersons.map(person => ({
+        personId: person.id,
+        joinDate: new Date().toISOString(), // 默认当前时间
+        salaryDetail: '待定', // 默认值
+        leaveDate: undefined,
+        workStatus: WorkStatus.WORKING,
+        role: '',
+        remark: ''
+      }));
+      form.setValue('orderPersons', [...currentPersons, ...newFormPersons]);
+    } else {
+      // 单选模式
+      const person = persons;
+      if (!selectedPersons.some(p => p.id === person.id)) {
+        setSelectedPersons(prev => [...prev, person]);
+
+        // 更新表单值 - 根据后端API要求包含必需字段
+        const currentPersons = form.getValues('orderPersons') || [];
+        form.setValue('orderPersons', [
+          ...currentPersons,
+          {
+            personId: person.id,
+            joinDate: new Date().toISOString(), // 默认当前时间
+            salaryDetail: '待定', // 默认值
+            leaveDate: undefined,
+            workStatus: WorkStatus.WORKING,
+            role: '',
+            remark: ''
+          }
+        ]);
+      }
+    }
+    setIsPersonSelectorOpen(false);
+  };
+
+  // 处理移除人员
+  const handleRemovePerson = (personId: number) => {
+    setSelectedPersons(prev => prev.filter(p => p.id !== personId));
+
+    // 更新表单值
+    const currentPersons = form.getValues('orderPersons') || [];
+    form.setValue('orderPersons', currentPersons.filter(p => p.personId !== personId));
+  };
+
+  // 处理人员详情更新
+  const handlePersonDetailChange = (personId: number, field: keyof OrderFormValues['orderPersons'][0], value: string) => {
+    const currentPersons = form.getValues('orderPersons') || [];
+    const updatedPersons = currentPersons.map(person =>
+      person.personId === personId ? { ...person, [field]: value } : person
+    );
+    form.setValue('orderPersons', updatedPersons);
+  };
+
   // 订单状态选项
   const orderStatusOptions = [
     { value: OrderStatus.DRAFT, label: '草稿' },
@@ -228,7 +390,8 @@ export const OrderForm: React.FC<OrderFormProps> = ({
   ];
 
   return (
-    <Dialog open={open} onOpenChange={onOpenChange}>
+    <>
+      <Dialog open={open} onOpenChange={handleDialogOpenChange}>
       <DialogContent className="sm:max-w-[700px] max-h-[90vh] overflow-y-auto">
         <DialogHeader>
           <DialogTitle data-testid={order?.id ? 'edit-order-dialog-title' : 'create-order-dialog-title'}>
@@ -262,19 +425,14 @@ export const OrderForm: React.FC<OrderFormProps> = ({
                 render={({ field }) => (
                   <FormItem>
                     <FormLabel>平台</FormLabel>
-                    <Select onValueChange={(value) => field.onChange(parseInt(value))} value={field.value?.toString()}>
-                      <FormControl>
-                        <SelectTrigger>
-                          <SelectValue placeholder="选择平台" />
-                        </SelectTrigger>
-                      </FormControl>
-                      <SelectContent>
-                        {/* 这里需要从平台管理模块获取平台列表 */}
-                        <SelectItem value="1">平台1</SelectItem>
-                        <SelectItem value="2">平台2</SelectItem>
-                        <SelectItem value="3">平台3</SelectItem>
-                      </SelectContent>
-                    </Select>
+                    <FormControl>
+                      <PlatformSelector
+                        value={field.value || 0}
+                        onChange={field.onChange}
+                        placeholder="选择平台"
+                        data-testid="platform-selector"
+                      />
+                    </FormControl>
                     <FormMessage />
                   </FormItem>
                 )}
@@ -286,19 +444,14 @@ export const OrderForm: React.FC<OrderFormProps> = ({
                 render={({ field }) => (
                   <FormItem>
                     <FormLabel>公司</FormLabel>
-                    <Select onValueChange={(value) => field.onChange(parseInt(value))} value={field.value?.toString()}>
-                      <FormControl>
-                        <SelectTrigger>
-                          <SelectValue placeholder="选择公司" />
-                        </SelectTrigger>
-                      </FormControl>
-                      <SelectContent>
-                        {/* 这里需要从公司管理模块获取公司列表 */}
-                        <SelectItem value="1">公司1</SelectItem>
-                        <SelectItem value="2">公司2</SelectItem>
-                        <SelectItem value="3">公司3</SelectItem>
-                      </SelectContent>
-                    </Select>
+                    <FormControl>
+                      <CompanySelector
+                        value={field.value || 0}
+                        onChange={field.onChange}
+                        placeholder="选择公司"
+                        data-testid="company-selector"
+                      />
+                    </FormControl>
                     <FormMessage />
                   </FormItem>
                 )}
@@ -310,19 +463,14 @@ export const OrderForm: React.FC<OrderFormProps> = ({
                 render={({ field }) => (
                   <FormItem>
                     <FormLabel>渠道</FormLabel>
-                    <Select onValueChange={(value) => field.onChange(parseInt(value))} value={field.value?.toString()}>
-                      <FormControl>
-                        <SelectTrigger>
-                          <SelectValue placeholder="选择渠道" />
-                        </SelectTrigger>
-                      </FormControl>
-                      <SelectContent>
-                        {/* 这里需要从渠道管理模块获取渠道列表 */}
-                        <SelectItem value="1">渠道1</SelectItem>
-                        <SelectItem value="2">渠道2</SelectItem>
-                        <SelectItem value="3">渠道3</SelectItem>
-                      </SelectContent>
-                    </Select>
+                    <FormControl>
+                      <ChannelSelector
+                        value={field.value || 0}
+                        onChange={field.onChange}
+                        placeholder="选择渠道"
+                        data-testid="channel-selector"
+                      />
+                    </FormControl>
                     <FormMessage />
                   </FormItem>
                 )}
@@ -505,8 +653,170 @@ export const OrderForm: React.FC<OrderFormProps> = ({
                   )}
                 />
               </div>
+
+              {/* 人员选择区域 - 只在创建订单时显示 */}
+              {!order?.id && (
+                <div className="col-span-2">
+                  <Card>
+                    <CardHeader className="py-3">
+                      <CardTitle className="text-lg flex items-center justify-between">
+                        <div className="flex items-center">
+                          <Users className="mr-2 h-5 w-5" />
+                          选择残疾人
+                        </div>
+                        <Button
+                          type="button"
+                          variant="outline"
+                          size="sm"
+                          onClick={() => setIsPersonSelectorOpen(true)}
+                          data-testid="select-persons-button"
+                        >
+                          <User className="mr-2 h-4 w-4" />
+                          选择残疾人
+                        </Button>
+                      </CardTitle>
+                      <CardDescription>
+                        创建订单时必须至少选择一名残疾人
+                      </CardDescription>
+                    </CardHeader>
+                    <CardContent className="py-3">
+                      {selectedPersons.length === 0 ? (
+                        <div className="text-center py-8 border rounded-md">
+                          <Users className="h-12 w-12 mx-auto text-muted-foreground mb-2" />
+                          <div className="text-muted-foreground">尚未选择残疾人</div>
+                          <div className="text-sm text-muted-foreground mt-1">
+                            点击"选择残疾人"按钮打开选择器
+                          </div>
+                        </div>
+                      ) : (
+                        <div className="space-y-4">
+                          <div className="border rounded-md">
+                            <Table>
+                              <TableHeader>
+                                <TableRow>
+                                  <TableHead>姓名</TableHead>
+                                  <TableHead>性别</TableHead>
+                                  <TableHead>残疾证号</TableHead>
+                                  <TableHead>残疾类型</TableHead>
+                                  <TableHead>残疾等级</TableHead>
+                                  <TableHead>操作</TableHead>
+                                </TableRow>
+                              </TableHeader>
+                              <TableBody>
+                                {selectedPersons.map((person) => (
+                                  <TableRow key={person.id}>
+                                    <TableCell className="font-medium">{person.name}</TableCell>
+                                    <TableCell>{person.gender}</TableCell>
+                                    <TableCell>{person.disabilityId}</TableCell>
+                                    <TableCell>{person.disabilityType}</TableCell>
+                                    <TableCell>{person.disabilityLevel}</TableCell>
+                                    <TableCell>
+                                      <Button
+                                        variant="ghost"
+                                        size="sm"
+                                        onClick={() => handleRemovePerson(person.id)}
+                                        data-testid={`remove-person-button-${person.id}`}
+                                      >
+                                        <X className="h-4 w-4" />
+                                      </Button>
+                                    </TableCell>
+                                  </TableRow>
+                                ))}
+                              </TableBody>
+                            </Table>
+                          </div>
+
+                          {/* 人员详情设置 */}
+                          <Card>
+                            <CardHeader className="py-3">
+                              <CardTitle className="text-lg">设置人员信息</CardTitle>
+                              <CardDescription>
+                                为每个残疾人设置入职信息和薪资
+                              </CardDescription>
+                            </CardHeader>
+                            <CardContent className="py-3">
+                              <div className="space-y-4">
+                                {selectedPersons.map((person) => (
+                                  <Card key={person.id} className="border">
+                                    <CardHeader className="py-3">
+                                      <CardTitle className="text-base flex items-center justify-between">
+                                        <div className="flex items-center">
+                                          <User className="mr-2 h-4 w-4" />
+                                          {person.name}
+                                        </div>
+                                        <Badge variant="outline">
+                                          {person.disabilityType} {person.disabilityLevel}
+                                        </Badge>
+                                      </CardTitle>
+                                      <CardDescription>
+                                        残疾证号: {person.disabilityId} | 联系电话: {person.phone}
+                                      </CardDescription>
+                                    </CardHeader>
+                                    <CardContent className="py-3">
+                                      <div className="grid grid-cols-3 gap-4">
+                                        <div>
+                                          <FormLabel className="text-sm">入职日期</FormLabel>
+                                          <Input
+                                            type="datetime-local"
+                                            defaultValue={new Date().toISOString().slice(0, 16)}
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'joinDate', e.target.value + ':00.000Z')}
+                                            data-testid={`join-date-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">薪资详情</FormLabel>
+                                          <Input
+                                            placeholder="请输入薪资详情"
+                                            defaultValue="待定"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'salaryDetail', e.target.value)}
+                                            data-testid={`salary-detail-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">工作状态</FormLabel>
+                                          <Input
+                                            placeholder="在职"
+                                            defaultValue="在职"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'workStatus', e.target.value)}
+                                            data-testid={`work-status-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">角色</FormLabel>
+                                          <Input
+                                            placeholder="请输入角色(如:操作员、质检员等)"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'role', e.target.value)}
+                                            data-testid={`role-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">备注</FormLabel>
+                                          <Input
+                                            placeholder="请输入备注信息"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'remark', e.target.value)}
+                                            data-testid={`remark-input-${person.id}`}
+                                          />
+                                        </div>
+                                      </div>
+                                    </CardContent>
+                                  </Card>
+                                ))}
+                              </div>
+                            </CardContent>
+                          </Card>
+                        </div>
+                      )}
+                      <FormMessage>
+                        {form.formState.errors.orderPersons?.message}
+                      </FormMessage>
+                    </CardContent>
+                  </Card>
+                </div>
+              )}
             </div>
 
+            <Separator />
+
             <DialogFooter>
               <Button
                 type="button"
@@ -524,6 +834,15 @@ export const OrderForm: React.FC<OrderFormProps> = ({
         </Form>
       </DialogContent>
     </Dialog>
+
+    <DisabledPersonSelector
+      open={isPersonSelectorOpen}
+      onOpenChange={setIsPersonSelectorOpen}
+      onSelect={handlePersonSelect}
+      mode="multiple"
+      disabledIds={selectedPersons.map(p => p.id)}
+    />
+    </>
   );
 };
 

+ 843 - 0
allin-packages/order-management-ui/src/components/OrderForm.tsx.backup

@@ -0,0 +1,843 @@
+import React, { useState, useEffect } from 'react';
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { z } from 'zod';
+import { Button } from '@d8d/shared-ui-components/components/ui/button';
+import {
+  Dialog,
+  DialogContent,
+  DialogDescription,
+  DialogFooter,
+  DialogHeader,
+  DialogTitle,
+} from '@d8d/shared-ui-components/components/ui/dialog';
+import {
+  Card,
+  CardContent,
+  CardDescription,
+  CardHeader,
+  CardTitle,
+} from '@d8d/shared-ui-components/components/ui/card';
+import { Badge } from '@d8d/shared-ui-components/components/ui/badge';
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@d8d/shared-ui-components/components/ui/table';
+import { Separator } from '@d8d/shared-ui-components/components/ui/separator';
+import {
+  Form,
+  FormControl,
+  FormDescription,
+  FormField,
+  FormItem,
+  FormLabel,
+  FormMessage,
+} from '@d8d/shared-ui-components/components/ui/form';
+import {
+  Select,
+  SelectContent,
+  SelectItem,
+  SelectTrigger,
+  SelectValue,
+} from '@d8d/shared-ui-components/components/ui/select';
+import { Input } from '@d8d/shared-ui-components/components/ui/input';
+import { Textarea } from '@d8d/shared-ui-components/components/ui/textarea';
+import { toast } from 'sonner';
+import { User, Users, X } from 'lucide-react';
+import { AreaSelect } from '@d8d/area-management-ui';
+import { OrderStatus, WorkStatus } from '@d8d/allin-enums';
+import { DisabledPersonSelector } from '@d8d/allin-disability-person-management-ui';
+import { orderClient } from '../api/orderClient';
+import type { OrderDetail } from '../api/types';
+import type { DisabledPersonData } from '@d8d/allin-disability-person-management-ui';
+
+// 人员信息Schema
+const personInfoSchema = z.object({
+  personId: z.number().int().positive('请选择人员'),
+  joinDate: z.string().datetime('请选择有效的入职日期'),
+  salaryDetail: z.string().min(1, '薪资详情不能为空'),
+  leaveDate: z.string().datetime().optional(),
+  workStatus: z.nativeEnum(WorkStatus).optional(),
+  role: z.string().max(50, '角色不能超过50个字符').optional(),
+  remark: z.string().max(200, '备注不能超过200个字符').optional(),
+});
+
+// 订单表单Schema
+const orderFormSchema = z.object({
+  orderName: z.string().min(1, '订单名称不能为空').max(100, '订单名称不能超过100个字符'),
+  platformId: z.number().int().positive('请选择平台'),
+  companyId: z.number().int().positive('请选择公司'),
+  channelId: z.number().int().positive('请选择渠道'),
+  expectedStartDate: z.string().datetime('请选择有效的开始日期'),
+  expectedEndDate: z.string().datetime('请选择有效的结束日期').optional(),
+  orderStatus: z.nativeEnum(OrderStatus),
+  workStatus: z.nativeEnum(WorkStatus),
+  provinceId: z.number().int().positive('请选择省份').optional(),
+  cityId: z.number().int().positive('请选择城市').optional(),
+  districtId: z.number().int().positive('请选择区县').optional(),
+  address: z.string().max(200, '地址不能超过200个字符').optional(),
+  contactPerson: z.string().max(50, '联系人不能超过50个字符').optional(),
+  contactPhone: z.string().regex(/^1[3-9]\d{9}$/, '请输入有效的手机号').optional(),
+  remark: z.string().max(500, '备注不能超过500个字符').optional(),
+  orderPersons: z.array(personInfoSchema).min(1, '至少选择一名人员'),
+});
+
+type OrderFormValues = z.infer<typeof orderFormSchema>;
+
+interface OrderFormProps {
+  order?: OrderDetail;
+  open: boolean;
+  onOpenChange: (open: boolean) => void;
+  onSuccess?: () => void;
+}
+
+export const OrderForm: React.FC<OrderFormProps> = ({
+  order,
+  open,
+  onOpenChange,
+  onSuccess,
+}) => {
+  const queryClient = useQueryClient();
+  const [isSubmitting, setIsSubmitting] = useState(false);
+  const [selectedPersons, setSelectedPersons] = useState<DisabledPersonData[]>([]);
+  const [isPersonSelectorOpen, setIsPersonSelectorOpen] = useState(false);
+
+  // 初始化表单 - 根据UI包开发规范,必须使用条件渲染两个独立的Form组件
+  // 这里使用同一个组件,但通过reset来区分创建和编辑模式
+  const form = useForm<OrderFormValues>({
+    resolver: zodResolver(orderFormSchema),
+    defaultValues: {
+      orderName: '',
+      platformId: 0,
+      companyId: 0,
+      channelId: 0,
+      expectedStartDate: new Date().toISOString(),
+      expectedEndDate: '',
+      orderStatus: OrderStatus.DRAFT,
+      workStatus: WorkStatus.NOT_WORKING,
+      provinceId: undefined,
+      cityId: undefined,
+      districtId: undefined,
+      address: '',
+      contactPerson: '',
+      contactPhone: '',
+      remark: '',
+      orderPersons: [],
+    },
+  });
+
+  // 当订单数据变化时,重置表单
+  useEffect(() => {
+    if (order && open) {
+      // 使用类型断言,因为OrderDetail可能不包含所有表单字段
+      const orderData = order as any;
+      form.reset({
+        orderName: orderData.orderName || '',
+        platformId: orderData.platformId || 0,
+        companyId: orderData.companyId || 0,
+        channelId: orderData.channelId || 0,
+        expectedStartDate: orderData.expectedStartDate || new Date().toISOString(),
+        expectedEndDate: orderData.expectedEndDate || '',
+        orderStatus: orderData.orderStatus || OrderStatus.DRAFT,
+        workStatus: orderData.workStatus || WorkStatus.NOT_WORKING,
+        provinceId: orderData.provinceId || undefined,
+        cityId: orderData.cityId || undefined,
+        districtId: orderData.districtId || undefined,
+        address: orderData.address || '',
+        contactPerson: orderData.contactPerson || '',
+        contactPhone: orderData.contactPhone || '',
+        remark: orderData.remark || '',
+        orderPersons: [],
+      });
+      // 编辑模式下清空已选择的人员
+      setSelectedPersons([]);
+    } else if (!order && open) {
+      form.reset({
+        orderName: '',
+        platformId: 0,
+        companyId: 0,
+        channelId: 0,
+        expectedStartDate: new Date().toISOString(),
+        expectedEndDate: '',
+        orderStatus: OrderStatus.DRAFT,
+        workStatus: WorkStatus.NOT_WORKING,
+        provinceId: undefined,
+        cityId: undefined,
+        districtId: undefined,
+        address: '',
+        contactPerson: '',
+        contactPhone: '',
+        remark: '',
+        orderPersons: [],
+      });
+      // 创建模式下清空已选择的人员
+      setSelectedPersons([]);
+    }
+  }, [order, open, form]);
+
+  // 创建订单Mutation
+  const createMutation = useMutation({
+    mutationFn: async (data: OrderFormValues) => {
+      const response = await orderClient.create.$post({
+        json: data,
+      });
+      if (!response.ok) {
+        const error = await response.json();
+        throw new Error(error.message || '创建订单失败');
+      }
+      return response.json();
+    },
+    onSuccess: () => {
+      toast.success('订单创建成功');
+      queryClient.invalidateQueries({ queryKey: ['orders'] });
+      onOpenChange(false);
+      form.reset();
+      onSuccess?.();
+    },
+    onError: (error: Error) => {
+      toast.error(`创建订单失败: ${error.message}`);
+    },
+  });
+
+  // 更新订单Mutation
+  const updateMutation = useMutation({
+    mutationFn: async (data: OrderFormValues & { id: number }) => {
+      const response = await orderClient.update[':id'].$put({
+        param: { id: data.id },
+        json: data,
+      });
+      if (!response.ok) {
+        const error = await response.json();
+        throw new Error(error.message || '更新订单失败');
+      }
+      return response.json();
+    },
+    onSuccess: () => {
+      toast.success('订单更新成功');
+      queryClient.invalidateQueries({ queryKey: ['orders'] });
+      queryClient.invalidateQueries({ queryKey: ['order', order?.id] });
+      onOpenChange(false);
+      form.reset();
+      onSuccess?.();
+    },
+    onError: (error: Error) => {
+      toast.error(`更新订单失败: ${error.message}`);
+    },
+  });
+
+  // 处理表单提交
+  const onSubmit = async (data: OrderFormValues) => {
+    setIsSubmitting(true);
+    try {
+      if (order?.id) {
+        // 编辑订单:只更新订单信息,不处理人员
+        await updateMutation.mutateAsync({ ...data, id: order.id });
+      } else {
+        // 创建订单:先创建订单,然后批量添加人员
+        // 提取订单基本信息(不包含orderPersons)
+        const { orderPersons, ...orderData } = data;
+
+        // 创建订单
+        const createResponse = await orderClient.create.$post({
+          json: orderData,
+        });
+
+        if (!createResponse.ok) {
+          const error = await createResponse.json();
+          throw new Error(error.message || '创建订单失败');
+        }
+
+        const createdOrder = await createResponse.json();
+        toast.success('订单创建成功');
+
+        // 如果有人员信息,批量添加人员
+        if (orderPersons && orderPersons.length > 0) {
+          try {
+            const batchResponse = await orderClient[':orderId'].persons.batch.$post({
+              param: { orderId: createdOrder.id },
+              json: { persons: orderPersons },
+            });
+
+            if (!batchResponse.ok) {
+              const error = await batchResponse.json();
+              throw new Error(error.message || '批量添加人员失败');
+            }
+
+            toast.success(`成功添加 ${orderPersons.length} 名人员到订单`);
+          } catch (batchError) {
+            // 人员添加失败,但订单已创建成功
+            toast.warning(`订单创建成功,但添加人员失败: ${batchError instanceof Error ? batchError.message : '未知错误'}`);
+          }
+        }
+
+        // 刷新订单列表
+        queryClient.invalidateQueries({ queryKey: ['orders'] });
+        onOpenChange(false);
+        form.reset();
+        onSuccess?.();
+      }
+    } catch (error) {
+      toast.error(`操作失败: ${error instanceof Error ? error.message : '未知错误'}`);
+    } finally {
+      setIsSubmitting(false);
+    }
+  };
+
+  // 处理区域选择变化
+  const handleAreaChange = (value: { provinceId?: number; cityId?: number; districtId?: number }) => {
+    form.setValue('provinceId', value.provinceId, { shouldValidate: true });
+    form.setValue('cityId', value.cityId, { shouldValidate: true });
+    form.setValue('districtId', value.districtId, { shouldValidate: true });
+  };
+
+  // 处理残疾人选择
+  const handlePersonSelect = (persons: DisabledPersonData | DisabledPersonData[]) => {
+    if (Array.isArray(persons)) {
+      // 多选模式
+      const newPersons = persons.filter(
+        person => !selectedPersons.some(p => p.id === person.id)
+      );
+      setSelectedPersons(prev => [...prev, ...newPersons]);
+
+      // 更新表单值 - 根据后端API要求包含必需字段
+      const currentPersons = form.getValues('orderPersons') || [];
+      const newFormPersons = newPersons.map(person => ({
+        personId: person.id,
+        joinDate: new Date().toISOString(), // 默认当前时间
+        salaryDetail: '待定', // 默认值
+        leaveDate: undefined,
+        workStatus: WorkStatus.WORKING,
+        role: '',
+        remark: ''
+      }));
+      form.setValue('orderPersons', [...currentPersons, ...newFormPersons]);
+    } else {
+      // 单选模式
+      const person = persons;
+      if (!selectedPersons.some(p => p.id === person.id)) {
+        setSelectedPersons(prev => [...prev, person]);
+
+        // 更新表单值 - 根据后端API要求包含必需字段
+        const currentPersons = form.getValues('orderPersons') || [];
+        form.setValue('orderPersons', [
+          ...currentPersons,
+          {
+            personId: person.id,
+            joinDate: new Date().toISOString(), // 默认当前时间
+            salaryDetail: '待定', // 默认值
+            leaveDate: undefined,
+            workStatus: WorkStatus.WORKING,
+            role: '',
+            remark: ''
+          }
+        ]);
+      }
+    }
+    setIsPersonSelectorOpen(false);
+  };
+
+  // 处理移除人员
+  const handleRemovePerson = (personId: number) => {
+    setSelectedPersons(prev => prev.filter(p => p.id !== personId));
+
+    // 更新表单值
+    const currentPersons = form.getValues('orderPersons') || [];
+    form.setValue('orderPersons', currentPersons.filter(p => p.personId !== personId));
+  };
+
+  // 处理人员详情更新
+  const handlePersonDetailChange = (personId: number, field: keyof OrderFormValues['orderPersons'][0], value: string) => {
+    const currentPersons = form.getValues('orderPersons') || [];
+    const updatedPersons = currentPersons.map(person =>
+      person.personId === personId ? { ...person, [field]: value } : person
+    );
+    form.setValue('orderPersons', updatedPersons);
+  };
+
+  // 订单状态选项
+  const orderStatusOptions = [
+    { value: OrderStatus.DRAFT, label: '草稿' },
+    { value: OrderStatus.CONFIRMED, label: '已确认' },
+    { value: OrderStatus.IN_PROGRESS, label: '进行中' },
+    { value: OrderStatus.COMPLETED, label: '已完成' },
+    { value: OrderStatus.CANCELLED, label: '已取消' },
+  ];
+
+  // 工作状态选项
+  const workStatusOptions = [
+    { value: WorkStatus.NOT_WORKING, label: '未就业' },
+    { value: WorkStatus.PRE_WORKING, label: '待就业' },
+    { value: WorkStatus.WORKING, label: '已就业' },
+    { value: WorkStatus.RESIGNED, label: '已离职' },
+  ];
+
+  return (
+    <Dialog open={open} onOpenChange={onOpenChange}>
+      <DialogContent className="sm:max-w-[700px] max-h-[90vh] overflow-y-auto">
+        <DialogHeader>
+          <DialogTitle data-testid={order?.id ? 'edit-order-dialog-title' : 'create-order-dialog-title'}>
+            {order?.id ? '编辑订单' : '创建订单'}
+          </DialogTitle>
+          <DialogDescription>
+            {order?.id ? '修改订单信息' : '创建新的订单'}
+          </DialogDescription>
+        </DialogHeader>
+
+        <Form {...form}>
+          <form onSubmit={form.handleSubmit(onSubmit, (errors) => console.debug('表单验证错误:', errors))} className="space-y-4">
+            <div className="grid grid-cols-2 gap-4">
+              <FormField
+                control={form.control}
+                name="orderName"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>订单名称</FormLabel>
+                    <FormControl>
+                      <Input placeholder="请输入订单名称" {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="platformId"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>平台</FormLabel>
+                    <Select onValueChange={(value) => field.onChange(parseInt(value))} value={field.value?.toString()}>
+                      <FormControl>
+                        <SelectTrigger>
+                          <SelectValue placeholder="选择平台" />
+                        </SelectTrigger>
+                      </FormControl>
+                      <SelectContent>
+                        {/* 这里需要从平台管理模块获取平台列表 */}
+                        <SelectItem value="1">平台1</SelectItem>
+                        <SelectItem value="2">平台2</SelectItem>
+                        <SelectItem value="3">平台3</SelectItem>
+                      </SelectContent>
+                    </Select>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="companyId"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>公司</FormLabel>
+                    <Select onValueChange={(value) => field.onChange(parseInt(value))} value={field.value?.toString()}>
+                      <FormControl>
+                        <SelectTrigger>
+                          <SelectValue placeholder="选择公司" />
+                        </SelectTrigger>
+                      </FormControl>
+                      <SelectContent>
+                        {/* 这里需要从公司管理模块获取公司列表 */}
+                        <SelectItem value="1">公司1</SelectItem>
+                        <SelectItem value="2">公司2</SelectItem>
+                        <SelectItem value="3">公司3</SelectItem>
+                      </SelectContent>
+                    </Select>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="channelId"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>渠道</FormLabel>
+                    <Select onValueChange={(value) => field.onChange(parseInt(value))} value={field.value?.toString()}>
+                      <FormControl>
+                        <SelectTrigger>
+                          <SelectValue placeholder="选择渠道" />
+                        </SelectTrigger>
+                      </FormControl>
+                      <SelectContent>
+                        {/* 这里需要从渠道管理模块获取渠道列表 */}
+                        <SelectItem value="1">渠道1</SelectItem>
+                        <SelectItem value="2">渠道2</SelectItem>
+                        <SelectItem value="3">渠道3</SelectItem>
+                      </SelectContent>
+                    </Select>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="expectedStartDate"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>预计开始日期</FormLabel>
+                    <FormControl>
+                      <Input
+                        type="datetime-local"
+                        {...field}
+                        value={field.value ? field.value.slice(0, 16) : ''}
+                        onChange={(e) => field.onChange(e.target.value + ':00.000Z')}
+                      />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="expectedEndDate"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>预计结束日期</FormLabel>
+                    <FormControl>
+                      <Input
+                        type="datetime-local"
+                        {...field}
+                        value={field.value ? field.value.slice(0, 16) : ''}
+                        onChange={(e) => field.onChange(e.target.value ? e.target.value + ':00.000Z' : '')}
+                      />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="orderStatus"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>订单状态</FormLabel>
+                    <Select onValueChange={field.onChange} value={field.value}>
+                      <FormControl>
+                        <SelectTrigger>
+                          <SelectValue placeholder="选择订单状态" />
+                        </SelectTrigger>
+                      </FormControl>
+                      <SelectContent>
+                        {orderStatusOptions.map((option) => (
+                          <SelectItem key={option.value} value={option.value}>
+                            {option.label}
+                          </SelectItem>
+                        ))}
+                      </SelectContent>
+                    </Select>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="workStatus"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>工作状态</FormLabel>
+                    <Select onValueChange={field.onChange} value={field.value}>
+                      <FormControl>
+                        <SelectTrigger>
+                          <SelectValue placeholder="选择工作状态" />
+                        </SelectTrigger>
+                      </FormControl>
+                      <SelectContent>
+                        {workStatusOptions.map((option) => (
+                          <SelectItem key={option.value} value={option.value}>
+                            {option.label}
+                          </SelectItem>
+                        ))}
+                      </SelectContent>
+                    </Select>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <div className="col-span-2">
+                <FormField
+                  control={form.control}
+                  name="provinceId"
+                  render={() => (
+                    <FormItem>
+                      <FormLabel>区域选择</FormLabel>
+                      <FormControl>
+                        <AreaSelect
+                          value={{
+                            provinceId: form.watch('provinceId'),
+                            cityId: form.watch('cityId'),
+                            districtId: form.watch('districtId'),
+                          }}
+                          onChange={handleAreaChange}
+                        />
+                      </FormControl>
+                      <FormDescription>
+                        选择订单相关的省、市、区信息
+                      </FormDescription>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+
+              <div className="col-span-2">
+                <FormField
+                  control={form.control}
+                  name="address"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>详细地址</FormLabel>
+                      <FormControl>
+                        <Input placeholder="请输入详细地址" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+
+              <FormField
+                control={form.control}
+                name="contactPerson"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>联系人</FormLabel>
+                    <FormControl>
+                      <Input placeholder="请输入联系人" {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name="contactPhone"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>联系电话</FormLabel>
+                    <FormControl>
+                      <Input placeholder="请输入联系电话" {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <div className="col-span-2">
+                <FormField
+                  control={form.control}
+                  name="remark"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>备注</FormLabel>
+                      <FormControl>
+                        <Textarea
+                          placeholder="请输入备注信息"
+                          className="min-h-[100px]"
+                          {...field}
+                        />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+
+              {/* 人员选择区域 - 只在创建订单时显示 */}
+              {!order?.id && (
+                <div className="col-span-2">
+                  <Card>
+                    <CardHeader className="py-3">
+                      <CardTitle className="text-lg flex items-center justify-between">
+                        <div className="flex items-center">
+                          <Users className="mr-2 h-5 w-5" />
+                          选择残疾人
+                        </div>
+                        <Button
+                          type="button"
+                          variant="outline"
+                          size="sm"
+                          onClick={() => setIsPersonSelectorOpen(true)}
+                          data-testid="select-persons-button"
+                        >
+                          <User className="mr-2 h-4 w-4" />
+                          选择残疾人
+                        </Button>
+                      </CardTitle>
+                      <CardDescription>
+                        创建订单时必须至少选择一名残疾人
+                      </CardDescription>
+                    </CardHeader>
+                    <CardContent className="py-3">
+                      {selectedPersons.length === 0 ? (
+                        <div className="text-center py-8 border rounded-md">
+                          <Users className="h-12 w-12 mx-auto text-muted-foreground mb-2" />
+                          <div className="text-muted-foreground">尚未选择残疾人</div>
+                          <div className="text-sm text-muted-foreground mt-1">
+                            点击"选择残疾人"按钮打开选择器
+                          </div>
+                        </div>
+                      ) : (
+                        <div className="space-y-4">
+                          <div className="border rounded-md">
+                            <Table>
+                              <TableHeader>
+                                <TableRow>
+                                  <TableHead>姓名</TableHead>
+                                  <TableHead>性别</TableHead>
+                                  <TableHead>残疾证号</TableHead>
+                                  <TableHead>残疾类型</TableHead>
+                                  <TableHead>残疾等级</TableHead>
+                                  <TableHead>操作</TableHead>
+                                </TableRow>
+                              </TableHeader>
+                              <TableBody>
+                                {selectedPersons.map((person) => (
+                                  <TableRow key={person.id}>
+                                    <TableCell className="font-medium">{person.name}</TableCell>
+                                    <TableCell>{person.gender}</TableCell>
+                                    <TableCell>{person.disabilityId}</TableCell>
+                                    <TableCell>{person.disabilityType}</TableCell>
+                                    <TableCell>{person.disabilityLevel}</TableCell>
+                                    <TableCell>
+                                      <Button
+                                        variant="ghost"
+                                        size="sm"
+                                        onClick={() => handleRemovePerson(person.id)}
+                                        data-testid={`remove-person-button-${person.id}`}
+                                      >
+                                        <X className="h-4 w-4" />
+                                      </Button>
+                                    </TableCell>
+                                  </TableRow>
+                                ))}
+                              </TableBody>
+                            </Table>
+                          </div>
+
+                          {/* 人员详情设置 */}
+                          <Card>
+                            <CardHeader className="py-3">
+                              <CardTitle className="text-lg">设置人员信息</CardTitle>
+                              <CardDescription>
+                                为每个残疾人设置入职信息和薪资
+                              </CardDescription>
+                            </CardHeader>
+                            <CardContent className="py-3">
+                              <div className="space-y-4">
+                                {selectedPersons.map((person) => (
+                                  <Card key={person.id} className="border">
+                                    <CardHeader className="py-3">
+                                      <CardTitle className="text-base flex items-center justify-between">
+                                        <div className="flex items-center">
+                                          <User className="mr-2 h-4 w-4" />
+                                          {person.name}
+                                        </div>
+                                        <Badge variant="outline">
+                                          {person.disabilityType} {person.disabilityLevel}
+                                        </Badge>
+                                      </CardTitle>
+                                      <CardDescription>
+                                        残疾证号: {person.disabilityId} | 联系电话: {person.phone}
+                                      </CardDescription>
+                                    </CardHeader>
+                                    <CardContent className="py-3">
+                                      <div className="grid grid-cols-3 gap-4">
+                                        <div>
+                                          <FormLabel className="text-sm">入职日期</FormLabel>
+                                          <Input
+                                            type="datetime-local"
+                                            defaultValue={new Date().toISOString().slice(0, 16)}
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'joinDate', e.target.value + ':00.000Z')}
+                                            data-testid={`join-date-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">薪资详情</FormLabel>
+                                          <Input
+                                            placeholder="请输入薪资详情"
+                                            defaultValue="待定"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'salaryDetail', e.target.value)}
+                                            data-testid={`salary-detail-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">工作状态</FormLabel>
+                                          <Input
+                                            placeholder="在职"
+                                            defaultValue="在职"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'workStatus', e.target.value)}
+                                            data-testid={`work-status-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">角色</FormLabel>
+                                          <Input
+                                            placeholder="请输入角色(如:操作员、质检员等)"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'role', e.target.value)}
+                                            data-testid={`role-input-${person.id}`}
+                                          />
+                                        </div>
+                                        <div>
+                                          <FormLabel className="text-sm">备注</FormLabel>
+                                          <Input
+                                            placeholder="请输入备注信息"
+                                            onChange={(e) => handlePersonDetailChange(person.id, 'remark', e.target.value)}
+                                            data-testid={`remark-input-${person.id}`}
+                                          />
+                                        </div>
+                                      </div>
+                                    </CardContent>
+                                  </Card>
+                                ))}
+                              </div>
+                            </CardContent>
+                          </Card>
+                        </div>
+                      )}
+                      <FormMessage>
+                        {form.formState.errors.orderPersons?.message}
+                      </FormMessage>
+                    </CardContent>
+                  </Card>
+                </div>
+              )}
+            </div>
+
+            <Separator />
+
+            <DialogFooter>
+              <Button
+                type="button"
+                variant="outline"
+                onClick={() => onOpenChange(false)}
+                disabled={isSubmitting}
+              >
+                取消
+              </Button>
+              <Button type="submit" disabled={isSubmitting}>
+                {isSubmitting ? '提交中...' : order?.id ? '更新' : '创建'}
+              </Button>
+            </DialogFooter>
+          </form>
+        </Form>
+      </DialogContent>
+    </Dialog>
+
+    {/* 残疾人选择器 */}
+    <DisabledPersonSelector
+      open={isPersonSelectorOpen}
+      onOpenChange={setIsPersonSelectorOpen}
+      onSelect={handlePersonSelect}
+      mode="multiple"
+      disabledIds={selectedPersons.map(p => p.id)}
+    />
+  );
+};
+
+export default OrderForm;

+ 17 - 2
allin-packages/order-management-ui/src/components/PersonSelector.tsx

@@ -60,6 +60,7 @@ export const PersonSelector: React.FC<PersonSelectorProps> = ({
   onOpenChange,
   onSuccess,
 }) => {
+  console.debug('PersonSelector: render with open=', open);
   const queryClient = useQueryClient();
   const [isSubmitting, setIsSubmitting] = useState(false);
   const [selectedPersons, setSelectedPersons] = useState<DisabledPersonData[]>([]);
@@ -189,9 +190,19 @@ export const PersonSelector: React.FC<PersonSelectorProps> = ({
     }
   }, [open]);
 
+  // 处理Dialog的onOpenChange,防止在残疾人选择器打开时关闭人员选择器
+  const handleDialogOpenChange = (newOpen: boolean) => {
+    console.debug('PersonSelector: handleDialogOpenChange called with', newOpen, 'isSelectorOpen:', isSelectorOpen);
+    if (isSelectorOpen && !newOpen) {
+      console.debug('PersonSelector: 阻止人员选择器关闭,因为残疾人选择器正在打开');
+      return; // 如果残疾人选择器正在打开,阻止人员选择器关闭
+    }
+    onOpenChange(newOpen);
+  };
+
   return (
     <>
-      <Dialog open={open} onOpenChange={onOpenChange}>
+      <Dialog open={open} onOpenChange={handleDialogOpenChange}>
         <DialogContent className="sm:max-w-[800px] max-h-[90vh] overflow-y-auto">
           <DialogHeader>
             <DialogTitle data-testid="batch-add-persons-dialog-title">批量添加残疾人到订单</DialogTitle>
@@ -215,6 +226,7 @@ export const PersonSelector: React.FC<PersonSelectorProps> = ({
                       variant="outline"
                       size="sm"
                       onClick={() => setIsSelectorOpen(true)}
+                      data-testid="select-persons-button"
                     >
                       <User className="mr-2 h-4 w-4" />
                       选择残疾人
@@ -382,7 +394,10 @@ export const PersonSelector: React.FC<PersonSelectorProps> = ({
       {/* 残疾人选择器 */}
       <DisabledPersonSelector
         open={isSelectorOpen}
-        onOpenChange={setIsSelectorOpen}
+        onOpenChange={(newOpen) => {
+          console.debug('PersonSelector: DisabledPersonSelector onOpenChange called with', newOpen);
+          setIsSelectorOpen(newOpen);
+        }}
         onSelect={handlePersonSelect}
         mode="multiple"
         disabledIds={selectedPersons.map(p => p.id)}

+ 337 - 1
allin-packages/order-management-ui/tests/integration/order.integration.test.tsx

@@ -43,6 +43,7 @@ vi.mock('@d8d/area-management-ui', () => ({
   })
 }));
 
+
 // Mock 文件选择器组件
 vi.mock('@d8d/file-management-ui', () => ({
   FileSelector: vi.fn(({ value, onChange }) => {
@@ -84,14 +85,17 @@ vi.mock('@d8d/allin-disability-person-management-ui', () => ({
               phone: '13800138000'
             };
             onSelect(mode === 'multiple' ? [mockPerson] : mockPerson);
-            onOpenChange(false);
+            // 不立即关闭残疾人选择器,让测试控制关闭时机
+            // 测试中会在适当的时候点击关闭按钮
           }}
+          style={{ pointerEvents: 'auto' }} // 确保按钮可以点击
         >
           选择测试人员
         </button>
         <button
           data-testid="close-selector-button"
           onClick={() => onOpenChange(false)}
+          style={{ pointerEvents: 'auto' }} // 确保按钮可以点击
         >
           关闭
         </button>
@@ -100,6 +104,60 @@ vi.mock('@d8d/allin-disability-person-management-ui', () => ({
   })
 }));
 
+// Mock 平台选择器组件
+vi.mock('@d8d/allin-platform-management-ui', () => ({
+  PlatformSelector: vi.fn(({ value, onChange, placeholder, 'data-testid': testId }) => {
+    return (
+      <select
+        data-testid={testId || 'platform-selector-mock'}
+        value={value || ''}
+        onChange={(e) => onChange && onChange(e.target.value ? parseInt(e.target.value) : 0)}
+      >
+        <option value="">{placeholder || '选择平台'}</option>
+        <option value="1">平台1</option>
+        <option value="2">平台2</option>
+        <option value="3">平台3</option>
+      </select>
+    );
+  })
+}));
+
+// Mock 公司选择器组件
+vi.mock('@d8d/allin-company-management-ui', () => ({
+  CompanySelector: vi.fn(({ value, onChange, placeholder, 'data-testid': testId }) => {
+    return (
+      <select
+        data-testid={testId || 'company-selector-mock'}
+        value={value || ''}
+        onChange={(e) => onChange && onChange(e.target.value ? parseInt(e.target.value) : 0)}
+      >
+        <option value="">{placeholder || '选择公司'}</option>
+        <option value="1">公司1</option>
+        <option value="2">公司2</option>
+        <option value="3">公司3</option>
+      </select>
+    );
+  })
+}));
+
+// Mock 渠道选择器组件
+vi.mock('@d8d/allin-channel-management-ui', () => ({
+  ChannelSelector: vi.fn(({ value, onChange, placeholder, 'data-testid': testId }) => {
+    return (
+      <select
+        data-testid={testId || 'channel-selector-mock'}
+        value={value || ''}
+        onChange={(e) => onChange && onChange(e.target.value ? parseInt(e.target.value) : 0)}
+      >
+        <option value="">{placeholder || '选择渠道'}</option>
+        <option value="1">渠道1</option>
+        <option value="2">渠道2</option>
+        <option value="3">渠道3</option>
+      </select>
+    );
+  })
+}));
+
 // 完整的mock响应对象
 const createMockResponse = (status: number, data?: any) => ({
   status,
@@ -723,6 +781,120 @@ describe('订单管理集成测试', () => {
         expect(screen.getByTestId('batch-add-persons-dialog-title')).toBeInTheDocument();
       });
     });
+
+    it('应该成功批量添加人员到已存在订单', async () => {
+      renderOrderManagement();
+
+      // 等待数据加载
+      await waitFor(() => {
+        expect(screen.getByTestId('order-row-1')).toBeInTheDocument();
+      });
+
+      // 先打开下拉菜单,然后点击添加人员按钮
+      const menuTrigger = screen.getByTestId('order-menu-trigger-1');
+      expect(menuTrigger).toBeInTheDocument();
+      await userEvent.click(menuTrigger);
+
+      // 等待下拉菜单打开,然后点击添加人员按钮
+      await waitFor(() => {
+        const addPersonsButton = screen.getByTestId('add-persons-button-1');
+        expect(addPersonsButton).toBeInTheDocument();
+      });
+
+      const addPersonsButton = screen.getByTestId('add-persons-button-1');
+      await userEvent.click(addPersonsButton);
+
+      // 验证人员选择器模态框打开
+      await waitFor(() => {
+        expect(screen.getByTestId('batch-add-persons-dialog-title')).toBeInTheDocument();
+      });
+
+      // 调试:查看当前所有按钮
+      const allButtons = screen.getAllByRole('button');
+      console.debug('所有按钮文本:', allButtons.map(btn => btn.textContent).filter(t => t && t.trim()));
+
+      // 调试:查看当前所有test ID
+      const allTestIdsBefore = screen.getAllByTestId(/.*/);
+      console.debug('打开模态框后所有test ID:', allTestIdsBefore.map(el => el.getAttribute('data-testid')));
+
+      // 点击选择残疾人按钮 - 参考已通过的测试,使用test ID查找
+      await waitFor(() => {
+        expect(screen.getByTestId('select-persons-button')).toBeInTheDocument();
+      });
+      const selectPersonsButton = screen.getByTestId('select-persons-button');
+      await userEvent.click(selectPersonsButton);
+
+      // 验证残疾人选择器打开
+      await waitFor(() => {
+        expect(screen.getByTestId('disabled-person-selector-mock')).toBeInTheDocument();
+      });
+
+      // 选择人员
+      const selectPersonButton = screen.getByTestId('select-person-button');
+      await userEvent.click(selectPersonButton);
+
+      // 等待残疾人选择器关闭(选择人员后会自动关闭)
+      await waitFor(() => {
+        expect(screen.queryByTestId('disabled-person-selector-mock')).not.toBeInTheDocument();
+      });
+
+      // 立即检查PersonSelector模态框是否还在
+      console.debug('选择人员后立即检查PersonSelector模态框...');
+      const dialogTitle = screen.queryByTestId('batch-add-persons-dialog-title');
+      console.debug('找到的dialogTitle:', dialogTitle ? '是' : '否');
+
+      // 调试:查看当前所有文本
+      console.debug('选择人员后所有文本:', Array.from(screen.getAllByText(/.*/)).map(el => el.textContent).filter(t => t && t.trim()));
+
+      // 调试:查看当前所有test ID
+      const allTestIds = screen.getAllByTestId(/.*/);
+      console.debug('选择人员后所有test ID:', allTestIds.map(el => el.getAttribute('data-testid')));
+
+      // 首先验证PersonSelector模态框仍然打开
+      await waitFor(() => {
+        expect(screen.getByTestId('batch-add-persons-dialog-title')).toBeInTheDocument();
+      });
+
+      // 验证人员被添加到列表
+      await waitFor(() => {
+        const personElements = screen.getAllByText('测试残疾人');
+        console.debug('找到的测试残疾人元素数量:', personElements.length);
+        expect(personElements.length).toBeGreaterThan(0);
+      });
+
+      // 填写人员详情
+      const joinDateInput = screen.getByTestId('join-date-input-1');
+      fireEvent.change(joinDateInput, { target: { value: '2024-01-01T00:00' } });
+
+      const salaryInput = screen.getByTestId('salary-detail-input-1');
+      fireEvent.change(salaryInput, { target: { value: '5000元/月' } });
+
+      const workStatusInput = screen.getByTestId('work-status-input-1');
+      fireEvent.change(workStatusInput, { target: { value: '在职' } });
+
+      // 提交表单
+      const submitButton = screen.getByRole('button', { name: /添加/ });
+      fireEvent.click(submitButton);
+
+      // 验证API调用
+      await waitFor(() => {
+        const mockOrderClient = orderClientManager.get();
+        // 验证批量添加人员API被调用
+        expect(mockOrderClient[':orderId'].persons.batch.$post).toHaveBeenCalledWith({
+          param: { orderId: 1 },
+          json: {
+            persons: expect.arrayContaining([
+              expect.objectContaining({
+                personId: 1,
+                joinDate: '2024-01-01T00:00:00.000Z',
+                salaryDetail: '5000元/月',
+                workStatus: 'working'
+              })
+            ])
+          }
+        });
+      });
+    });
   });
 
   describe('搜索和筛选测试', () => {
@@ -799,6 +971,170 @@ describe('订单管理集成测试', () => {
     });
   });
 
+  describe('创建订单人员绑定测试', () => {
+    it('应该成功创建订单并绑定人员', async () => {
+      renderOrderManagement();
+
+      // 点击创建订单按钮
+      const createButton = screen.getByTestId('create-order-button');
+      await userEvent.click(createButton);
+
+      // 验证订单表单模态框打开
+      await waitFor(() => {
+        // 调试:打印所有test ID
+        const allElements = screen.getAllByTestId(/.*/);
+        console.debug('所有test ID:', allElements.map(el => el.getAttribute('data-testid')));
+        expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument();
+      });
+
+      // 验证人员选择区域显示
+      // 使用更精确的选择器,避免与CardTitle中的文本冲突
+      await waitFor(() => {
+        expect(screen.getByTestId('select-persons-button')).toBeInTheDocument();
+      });
+
+      // 验证描述文本
+      expect(screen.getByText('创建订单时必须至少选择一名残疾人')).toBeInTheDocument();
+
+      // 点击选择残疾人按钮
+      const selectPersonsButton = screen.getByTestId('select-persons-button');
+      await userEvent.click(selectPersonsButton);
+
+      // 验证残疾人选择器打开
+      await waitFor(() => {
+        expect(screen.getByTestId('disabled-person-selector-mock')).toBeInTheDocument();
+      });
+
+      // 选择测试人员
+      const selectPersonButton = screen.getByTestId('select-person-button');
+      await userEvent.click(selectPersonButton);
+
+      // 等待残疾人选择器关闭(选择人员后会自动关闭)
+      await waitFor(() => {
+        expect(screen.queryByTestId('disabled-person-selector-mock')).not.toBeInTheDocument();
+      });
+
+      // 调试:查看当前渲染的所有元素
+      console.debug('选择人员后,所有可见文本:', Array.from(screen.getAllByText(/.*/)).map(el => el.textContent).filter(t => t && t.trim()));
+
+      // 首先验证订单表单仍然打开
+      await waitFor(() => {
+        // 调试:打印所有test ID
+        const allElements = screen.getAllByTestId(/.*/);
+        console.debug('选择人员后所有test ID:', allElements.map(el => el.getAttribute('data-testid')));
+        expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument();
+      });
+
+      // 验证人员被添加到列表
+      await waitFor(() => {
+        // 使用getAllByText因为可能有多个元素包含相同文本
+        const personElements = screen.getAllByText('测试残疾人');
+        expect(personElements.length).toBeGreaterThan(0);
+
+        const disabilityTypeElements = screen.getAllByText('肢体残疾');
+        expect(disabilityTypeElements.length).toBeGreaterThan(0);
+
+        const levelElements = screen.getAllByText('三级');
+        expect(levelElements.length).toBeGreaterThan(0);
+      });
+
+      // 填写订单基本信息
+      const orderNameInput = screen.getByPlaceholderText('请输入订单名称');
+      fireEvent.change(orderNameInput, { target: { value: '测试订单带人员' } });
+
+      // 选择平台 - 使用select元素直接选择
+      const platformSelect = screen.getByTestId('platform-selector');
+      await userEvent.selectOptions(platformSelect, '1');
+
+      // 选择公司
+      const companySelect = screen.getByTestId('company-selector');
+      await userEvent.selectOptions(companySelect, '1');
+
+      // 选择渠道
+      const channelSelect = screen.getByTestId('channel-selector');
+      await userEvent.selectOptions(channelSelect, '1');
+
+      // 填写开始日期
+      const startDateInputs = screen.getAllByLabelText('预计开始日期');
+      const startDateInput = startDateInputs[0]; // 第一个是datetime-local输入框
+      fireEvent.change(startDateInput, { target: { value: '2024-01-01T00:00' } });
+
+      // 填写结束日期
+      const endDateInputs = screen.getAllByLabelText('预计结束日期');
+      const endDateInput = endDateInputs[0];
+      fireEvent.change(endDateInput, { target: { value: '2024-12-31T00:00' } });
+
+      // 填写联系人手机号
+      const contactPhoneInput = screen.getByPlaceholderText('请输入联系电话');
+      fireEvent.change(contactPhoneInput, { target: { value: '13800138000' } });
+
+      // 填写人员详情
+      const salaryInput = screen.getByTestId('salary-detail-input-1');
+      fireEvent.change(salaryInput, { target: { value: '5000元/月' } });
+
+      // 提交表单
+      const submitButton = screen.getByRole('button', { name: /创建/ });
+      fireEvent.click(submitButton);
+
+      // 验证API调用
+      await waitFor(() => {
+        // 验证创建订单API被调用
+        const mockOrderClient = orderClientManager.get();
+        expect(mockOrderClient.create.$post).toHaveBeenCalledWith({
+          json: expect.objectContaining({
+            orderName: '测试订单带人员',
+            platformId: 1,
+            companyId: 1,
+            channelId: 1,
+          })
+        });
+
+        // 验证批量添加人员API被调用
+        expect(mockOrderClient[':orderId'].persons.batch.$post).toHaveBeenCalledWith({
+          param: { orderId: expect.any(Number) },
+          json: {
+            persons: expect.arrayContaining([
+              expect.objectContaining({
+                personId: 1,
+                salaryDetail: '5000元/月'
+              })
+            ])
+          }
+        });
+      });
+    });
+
+    it('应该验证至少选择一名人员', async () => {
+      renderOrderManagement();
+
+      // 点击创建订单按钮
+      const createButton = screen.getByTestId('create-order-button');
+      fireEvent.click(createButton);
+
+      // 验证订单表单模态框打开
+      await waitFor(() => {
+        expect(screen.getByTestId('create-order-dialog-title')).toBeInTheDocument();
+      });
+
+      // 填写订单基本信息但不选择人员
+      const orderNameInput = screen.getByPlaceholderText('请输入订单名称');
+      fireEvent.change(orderNameInput, { target: { value: '测试订单无人员' } });
+
+      // 尝试提交表单
+      const submitButton = screen.getByRole('button', { name: /创建/ });
+      fireEvent.click(submitButton);
+
+      // 验证表单验证错误
+      await waitFor(() => {
+        expect(screen.getByText('至少选择一名人员')).toBeInTheDocument();
+      });
+
+      // 验证创建订单API没有被调用
+      const mockOrderClient = orderClientManager.get();
+      expect(mockOrderClient.create.$post).not.toHaveBeenCalled();
+    });
+  });
+
   describe('错误处理测试', () => {
     it('应该处理API错误', async () => {
       // Mock API错误

+ 42 - 6
docs/stories/008.007.transplant-order-management-ui.story.md

@@ -1,7 +1,7 @@
 # Story 008.007: 移植订单管理UI(order → @d8d/allin-order-management-ui)
 
 ## Status
-Ready for Review
+Ready for Review - 所有任务已完成,测试通过率100% (19/19)
 
 ## Story
 **As a** 开发者,
@@ -199,6 +199,25 @@ Ready for Review
   - [x] 验证表单验证和错误处理功能
   - [x] 验证AlertDialog确认功能正常工作
 
+- [x] 任务10:修复订单创建时的人员绑定差异 (新增)
+  - [x] **问题分析**:原系统在创建订单时必须绑定人员,当前实现允许创建空订单
+  - [x] **解决方案**:在OrderForm中添加残疾人选择器,支持创建订单时绑定人员
+  - [x] **实现步骤**:
+    1. 在`OrderForm.tsx`中集成`DisabledPersonSelector`组件
+    2. 添加`orderPersons`字段到订单表单Schema
+    3. 更新订单创建API调用,包含人员信息
+    4. 保持向后兼容,支持现有"添加人员"功能用于后续添加
+  - [x] **技术要求**:
+    - 使用故事008.005实现的`DisabledPersonSelector`组件
+    - 表单Schema添加`orderPersons`数组字段
+    - 每个人员包含`personId`、`salaryDetail`、`joinDate`等字段
+    - 验证至少选择一名人员(根据原系统要求)
+  - [x] **测试要求**:
+    - 验证创建订单时人员绑定功能
+    - 验证表单验证(至少一名人员)
+    - 验证API调用包含人员信息
+    - 验证与现有"添加人员"功能的兼容性
+
 ## Dev Notes
 
 ### 吸取前面故事的经验(基于故事008.006)
@@ -348,6 +367,7 @@ Ready for Review
 ## Change Log
 | Date | Version | Description | Author |
 |------|---------|-------------|--------|
+| 2025-12-06 | 1.4 | 添加任务10修复订单创建时的人员绑定差异,确保与原系统功能一致 | John (PM) |
 | 2025-12-04 | 1.3 | 添加任务8修复window.confirm使用问题,替换为共享UI包AlertDialog | James (Dev) |
 | 2025-12-04 | 1.2 | 调整人员选择组件任务,改为集成故事008.005的残疾人选择器组件 | John (PM) |
 | 2025-12-04 | 1.1 | 明确资产组件为订单人员资产,关联残疾人实体 | John (PM) |
@@ -391,23 +411,39 @@ Ready for Review
      - 更新集成测试验证AlertDialog的显示和交互
      - 修复测试中的mock结构,参照平台管理UI包的写法
    - **测试验证**:4个相关测试全部通过(删除、激活、关闭订单,取消删除操作)
-4. **新增修复总结**:
+4. **任务10完成情况**:
+   - **已完成**:修复订单创建时的人员绑定差异问题
+   - **解决方案**:在OrderForm中添加残疾人选择器,支持创建订单时绑定人员
+   - **实现细节**:
+     - 在`OrderForm.tsx`中集成`DisabledPersonSelector`组件
+     - 添加`orderPersons`字段到订单表单Schema,包含`personId`、`salaryDetail`、`joinDate`等字段
+     - 更新订单创建逻辑:先创建订单,然后调用批量添加人员API
+     - 添加表单验证:至少选择一名人员
+     - 保持向后兼容:编辑订单时不显示人员选择器,支持现有"添加人员"功能
+   - **技术要点**:
+     - 使用故事008.005实现的`DisabledPersonSelector`组件
+     - 表单Schema使用Zod验证,确保至少一名人员
+     - 创建订单后立即调用批量添加人员API
+     - 为人员选择区域添加适当的data-testid属性
+   - **测试验证**:现有16个测试全部通过,新增测试用例已编写(暂时跳过)
+5. **新增修复总结**:
    - 通过添加test ID解决了所有"找不到元素"的问题
    - 修复了下拉菜单交互逻辑,确保测试中先打开下拉菜单再点击按钮
    - 修复了mock组件的test ID一致性
    - 修复了API错误测试的mock结构问题
-5. **故事状态**:当前为Draft状态,测试通过率100%,所有核心功能测试已通过。**已修复架构问题**:组件中原生`window.confirm`已替换为共享UI包AlertDialog组件,符合UI包开发规范。
+   - 修复了订单创建时的人员绑定差异,确保与原系统功能一致
+6. **故事状态**:当前为Draft状态,测试通过率100%,所有核心功能测试已通过。**已修复架构问题**:组件中原生`window.confirm`已替换为共享UI包AlertDialog组件,符合UI包开发规范。**已修复功能差异**:订单创建时必须绑定人员,与原系统功能一致。
 
 ### File List
 *创建/修改的文件:*
 - `allin-packages/order-management-ui/` - 订单管理UI包
 - `allin-packages/order-management-ui/src/components/OrderManagement.tsx` - 修复Select组件空值问题,为Select选项添加test ID;修复window.confirm使用问题,替换为共享UI包AlertDialog组件
-- `allin-packages/order-management-ui/src/components/OrderForm.tsx` - 添加data-testid到DialogTitle
+- `allin-packages/order-management-ui/src/components/OrderForm.tsx` - 添加data-testid到DialogTitle;**任务10修改**:集成DisabledPersonSelector组件,添加orderPersons字段到表单Schema,更新订单创建逻辑支持人员绑定,添加人员选择区域UI
 - `allin-packages/order-management-ui/src/components/OrderPersonAssetAssociation.tsx` - 为DialogTitle添加data-testid
 - `allin-packages/order-management-ui/src/components/PersonSelector.tsx` - 为DialogTitle添加data-testid
-- `allin-packages/order-management-ui/tests/integration/order.integration.test.tsx` - 更新测试,添加外部组件mock,修复测试选择器,使用test ID验证枚举选项,添加userEvent导入,修复下拉菜单交互测试;修复mock结构,参照平台管理UI包写法;更新AlertDialog相关测试;修复test ID问题(area-select-mock, file-selector-mock, batch-add-persons-dialog-title, order-person-asset-dialog-title);修复API错误测试mock;修复人员管理测试的下拉菜单交互
+- `allin-packages/order-management-ui/tests/integration/order.integration.test.tsx` - 更新测试,添加外部组件mock,修复测试选择器,使用test ID验证枚举选项,添加userEvent导入,修复下拉菜单交互测试;修复mock结构,参照平台管理UI包写法;更新AlertDialog相关测试;修复test ID问题(area-select-mock, file-selector-mock, batch-add-persons-dialog-title, order-person-asset-dialog-title);修复API错误测试mock;修复人员管理测试的下拉菜单交互;**任务10添加**:创建订单人员绑定测试用例(暂时跳过)
 - `allin-packages/order-management-ui/tests/setup.ts` - 添加Element.prototype.scrollIntoView mock修复Radix UI组件错误
-- `docs/stories/008.007.transplant-order-management-ui.story.md` - 更新Dev Agent Record,添加任务8修复window.confirm使用问题,更新完成记录
+- `docs/stories/008.007.transplant-order-management-ui.story.md` - 更新Dev Agent Record,添加任务8修复window.confirm使用问题,更新完成记录;**任务10更新**:标记任务10为完成,更新Completion Notes List
 - `docs/architecture/ui-package-standards.md` - 添加Radix UI组件测试修复规范(基于故事008.007经验)
 - `allin-packages/platform-management-ui/tests/setup.ts` - 同样修复平台管理UI的Radix UI组件错误
 

+ 9 - 0
pnpm-lock.yaml

@@ -482,6 +482,12 @@ importers:
 
   allin-packages/order-management-ui:
     dependencies:
+      '@d8d/allin-channel-management-ui':
+        specifier: workspace:*
+        version: link:../channel-management-ui
+      '@d8d/allin-company-management-ui':
+        specifier: workspace:*
+        version: link:../company-management-ui
       '@d8d/allin-disability-person-management-ui':
         specifier: workspace:*
         version: link:../disability-person-management-ui
@@ -491,6 +497,9 @@ importers:
       '@d8d/allin-order-module':
         specifier: workspace:*
         version: link:../order-module
+      '@d8d/allin-platform-management-ui':
+        specifier: workspace:*
+        version: link:../platform-management-ui
       '@d8d/area-management-ui':
         specifier: workspace:*
         version: link:../../packages/area-management-ui