浏览代码

fix(order-management): 优化订单详情对话框宽度和布局

- 增加对话框宽度从max-w-6xl到max-w-7xl
- 优化订单信息卡片布局,使用3列网格布局
- 修复JSX语法错误和标签不匹配问题
- 所有测试通过

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 4 小时之前
父节点
当前提交
b4ca259bcb
共有 1 个文件被更改,包括 184 次插入100 次删除
  1. 184 100
      allin-packages/order-management-ui/src/components/OrderDetailModal.tsx

+ 184 - 100
allin-packages/order-management-ui/src/components/OrderDetailModal.tsx

@@ -1,6 +1,6 @@
-import React, { useState, useEffect } from 'react';
-import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
-import { Button } from '@d8d/shared-ui-components/components/ui/button';
+import React, { useState, useEffect } from "react";
+import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
+import { Button } from "@d8d/shared-ui-components/components/ui/button";
 import {
   Dialog,
   DialogContent,
@@ -8,14 +8,14 @@ import {
   DialogFooter,
   DialogHeader,
   DialogTitle,
-} from '@d8d/shared-ui-components/components/ui/dialog';
+} from "@d8d/shared-ui-components/components/ui/dialog";
 import {
   Card,
   CardContent,
   CardDescription,
   CardHeader,
   CardTitle,
-} from '@d8d/shared-ui-components/components/ui/card';
+} from "@d8d/shared-ui-components/components/ui/card";
 import {
   Table,
   TableBody,
@@ -23,24 +23,29 @@ import {
   TableHead,
   TableHeader,
   TableRow,
-} from '@d8d/shared-ui-components/components/ui/table';
+} from "@d8d/shared-ui-components/components/ui/table";
 import {
   Select,
   SelectContent,
   SelectItem,
   SelectTrigger,
   SelectValue,
-} from '@d8d/shared-ui-components/components/ui/select';
-import { Badge } from '@d8d/shared-ui-components/components/ui/badge';
-import { Input } from '@d8d/shared-ui-components/components/ui/input';
-import { Separator } from '@d8d/shared-ui-components/components/ui/separator';
-import { toast } from 'sonner';
-import { Users, FileText, Calendar, Play, CheckCircle, X } from 'lucide-react';
-import { OrderStatus, WorkStatus, getOrderStatusLabel, getWorkStatusLabel } from '@d8d/allin-enums';
-import { orderClient, orderClientManager } from '../api/orderClient';
-import PersonSelector from './PersonSelector';
-import OrderPersonAssetAssociation from './OrderPersonAssetAssociation';
-import type { OrderDetail } from '../api/types';
+} from "@d8d/shared-ui-components/components/ui/select";
+import { Badge } from "@d8d/shared-ui-components/components/ui/badge";
+import { Input } from "@d8d/shared-ui-components/components/ui/input";
+import { Separator } from "@d8d/shared-ui-components/components/ui/separator";
+import { toast } from "sonner";
+import { Users, FileText, Calendar, Play, CheckCircle, X } from "lucide-react";
+import {
+  OrderStatus,
+  WorkStatus,
+  getOrderStatusLabel,
+  getWorkStatusLabel,
+} from "@d8d/allin-enums";
+import { orderClient, orderClientManager } from "../api/orderClient";
+import PersonSelector from "./PersonSelector";
+import OrderPersonAssetAssociation from "./OrderPersonAssetAssociation";
+import type { OrderDetail } from "../api/types";
 
 interface OrderDetailModalProps {
   open: boolean;
@@ -62,16 +67,21 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
   const [isActionLoading, setIsActionLoading] = useState(false);
 
   // 查询订单详情
-  const { data: order, isLoading, error, refetch } = useQuery({
-    queryKey: ['orderDetail', orderId],
+  const {
+    data: order,
+    isLoading,
+    error,
+    refetch,
+  } = useQuery({
+    queryKey: ["orderDetail", orderId],
     queryFn: async () => {
       if (!orderId) return null;
-      const response = await orderClientManager.get().detail[':id'].$get({
+      const response = await orderClientManager.get().detail[":id"].$get({
         param: { id: orderId },
       });
       if (!response.ok) {
         const errorData = await response.json();
-        throw new Error(errorData.message || '获取订单详情失败');
+        throw new Error(errorData.message || "获取订单详情失败");
       }
       return await response.json();
     },
@@ -81,61 +91,71 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
   // 激活订单
   const activateMutation = useMutation({
     mutationFn: async (orderId: number) => {
-      const response = await orderClientManager.get().activate[':orderId'].$post({
-        param: { orderId },
-      });
+      const response = await orderClientManager
+        .get()
+        .activate[":orderId"].$post({
+          param: { orderId },
+        });
       if (!response.ok) {
         const errorData = await response.json();
-        throw new Error(errorData.message || '激活订单失败');
+        throw new Error(errorData.message || "激活订单失败");
       }
       return await response.json();
     },
     onSuccess: () => {
-      toast.success('订单激活成功');
+      toast.success("订单激活成功");
       refetch();
       onSuccess?.();
     },
     onError: (error) => {
-      toast.error(error.message || '激活订单失败');
+      toast.error(error.message || "激活订单失败");
     },
   });
 
   // 关闭订单
   const closeMutation = useMutation({
     mutationFn: async (orderId: number) => {
-      const response = await orderClientManager.get().close[':orderId'].$post({
+      const response = await orderClientManager.get().close[":orderId"].$post({
         param: { orderId },
       });
       if (!response.ok) {
         const errorData = await response.json();
-        throw new Error(errorData.message || '关闭订单失败');
+        throw new Error(errorData.message || "关闭订单失败");
       }
       return await response.json();
     },
     onSuccess: () => {
-      toast.success('订单关闭成功');
+      toast.success("订单关闭成功");
       refetch();
       onSuccess?.();
     },
     onError: (error) => {
-      toast.error(error.message || '关闭订单失败');
+      toast.error(error.message || "关闭订单失败");
     },
   });
 
   // 更新人员工作状态
   const updateWorkStatusMutation = useMutation({
-    mutationFn: async ({ orderId, personId, workStatus }: { orderId: number; personId: number; workStatus: WorkStatus }) => {
+    mutationFn: async ({
+      orderId,
+      personId,
+      workStatus,
+    }: {
+      orderId: number;
+      personId: number;
+      workStatus: WorkStatus;
+    }) => {
       // 注意:这里需要根据实际API调整
       // 原系统使用updatePersonWorkStatus,当前系统可能需要调用不同的API
       // 暂时使用toast提示,实际实现需要根据后端API调整
-      throw new Error('更新工作状态API未实现');
+      throw new Error("更新工作状态API未实现");
     },
     onSuccess: () => {
-      toast.success('工作状态更新成功');
+      toast.success("工作状态更新成功");
       refetch();
     },
     onError: (error) => {
-      toast.error(error.message || '工作状态更新失败');
+      toast.error(error.message || "工作状态更新失败");
     },
   });
 
@@ -178,41 +198,37 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
   // 获取订单状态徽章样式
   const getOrderStatusBadge = (status: OrderStatus) => {
     const variants = {
-      [OrderStatus.DRAFT]: 'secondary',
-      [OrderStatus.CONFIRMED]: 'default',
-      [OrderStatus.IN_PROGRESS]: 'default',
-      [OrderStatus.COMPLETED]: 'outline',
-      [OrderStatus.CANCELLED]: 'destructive',
+      [OrderStatus.DRAFT]: "secondary",
+      [OrderStatus.CONFIRMED]: "default",
+      [OrderStatus.IN_PROGRESS]: "default",
+      [OrderStatus.COMPLETED]: "outline",
+      [OrderStatus.CANCELLED]: "destructive",
     } as const;
 
     return (
-      <Badge variant={variants[status]}>
-        {getOrderStatusLabel(status)}
-      </Badge>
+      <Badge variant={variants[status]}>{getOrderStatusLabel(status)}</Badge>
     );
   };
 
   // 获取工作状态徽章样式
   const getWorkStatusBadge = (status: WorkStatus) => {
     const variants = {
-      [WorkStatus.NOT_WORKING]: 'secondary',
-      [WorkStatus.PRE_WORKING]: 'default',
-      [WorkStatus.WORKING]: 'default',
-      [WorkStatus.RESIGNED]: 'destructive',
+      [WorkStatus.NOT_WORKING]: "secondary",
+      [WorkStatus.PRE_WORKING]: "default",
+      [WorkStatus.WORKING]: "default",
+      [WorkStatus.RESIGNED]: "destructive",
     } as const;
 
     return (
-      <Badge variant={variants[status]}>
-        {getWorkStatusLabel(status)}
-      </Badge>
+      <Badge variant={variants[status]}>{getWorkStatusLabel(status)}</Badge>
     );
   };
 
   // 格式化日期
   const formatDate = (dateString?: string) => {
-    if (!dateString) return '-';
+    if (!dateString) return "-";
     try {
-      return new Date(dateString).toLocaleDateString('zh-CN');
+      return new Date(dateString).toLocaleDateString("zh-CN");
     } catch {
       return dateString;
     }
@@ -220,23 +236,28 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
 
   // 人员列表表格列
   const personColumns = [
-    { key: 'personId', label: 'ID', width: '60px' },
-    { key: 'personName', label: '姓名' },
-    { key: 'gender', label: '性别', width: '80px' },
-    { key: 'disabilityType', label: '残疾类型' },
-    { key: 'phone', label: '联系电话' },
-    { key: 'joinDate', label: '入职日期', width: '120px' },
-    { key: 'leaveDate', label: '离职日期', width: '120px' },
-    { key: 'workStatus', label: '工作状态', width: '120px' },
-    { key: 'salaryDetail', label: '薪资', width: '100px' },
+    { key: "personId", label: "ID", width: "60px" },
+    { key: "personName", label: "姓名" },
+    { key: "gender", label: "性别", width: "80px" },
+    { key: "disabilityType", label: "残疾类型" },
+    { key: "phone", label: "联系电话" },
+    { key: "joinDate", label: "入职日期", width: "120px" },
+    { key: "leaveDate", label: "离职日期", width: "120px" },
+    { key: "workStatus", label: "工作状态", width: "120px" },
+    { key: "salaryDetail", label: "薪资", width: "100px" },
   ];
 
   return (
     <>
       <Dialog open={open} onOpenChange={onOpenChange}>
-        <DialogContent className="max-w-6xl max-h-[90vh] overflow-y-auto" data-testid="order-detail-dialog">
+        <DialogContent
+          className="max-w-7xl max-h-[90vh] overflow-y-auto"
+          data-testid="order-detail-dialog"
+        >
           <DialogHeader>
-            <DialogTitle data-testid="order-detail-dialog-title">订单详情</DialogTitle>
+            <DialogTitle data-testid="order-detail-dialog-title">
+              订单详情
+            </DialogTitle>
             <DialogDescription data-testid="order-detail-dialog-description">
               查看订单完整信息和管理相关资源
             </DialogDescription>
@@ -257,7 +278,7 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                   <CardDescription>订单基本信息和状态</CardDescription>
                 </CardHeader>
                 <CardContent>
-                  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+                  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
                     <div className="space-y-2">
                       <div className="flex items-center justify-between">
                         <span className="text-sm font-medium">订单ID:</span>
@@ -265,53 +286,88 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                       </div>
                       <div className="flex items-center justify-between">
                         <span className="text-sm font-medium">订单名称:</span>
-                        <span data-testid="order-detail-name">{order.orderName}</span>
+                        <span data-testid="order-detail-name">
+                          {order.orderName}
+                        </span>
                       </div>
                       <div className="flex items-center justify-between">
                         <span className="text-sm font-medium">平台:</span>
-                        <span data-testid="order-detail-platform">平台{order.platformId}</span>
+                        <span data-testid="order-detail-platform">
+                          平台{order.platformId}
+                        </span>
                       </div>
+                    </div>
+                    <div className="space-y-2">
                       <div className="flex items-center justify-between">
                         <span className="text-sm font-medium">公司:</span>
-                        <span data-testid="order-detail-company">公司{order.companyId}</span>
+                        <span data-testid="order-detail-company">
+                          公司{order.companyId}
+                        </span>
                       </div>
                       <div className="flex items-center justify-between">
                         <span className="text-sm font-medium">渠道:</span>
-                        <span data-testid="order-detail-channel">渠道{order.channelId || '-'}</span>
+                        <span data-testid="order-detail-channel">
+                          渠道{order.channelId || "-"}
+                        </span>
                       </div>
-                    </div>
-                    <div className="space-y-2">
                       <div className="flex items-center justify-between">
                         <span className="text-sm font-medium">订单状态:</span>
-                        <span data-testid="order-detail-status">{getOrderStatusBadge(order.orderStatus)}</span>
+                        <span data-testid="order-detail-status">
+                          {getOrderStatusBadge(order.orderStatus)}
+                        </span>
                       </div>
+                    </div>
+                    <div className="space-y-2">
                       <div className="flex items-center justify-between">
                         <span className="text-sm font-medium">工作状态:</span>
-                        <span data-testid="order-detail-work-status">{getWorkStatusBadge(order.workStatus)}</span>
+                        <span data-testid="order-detail-work-status">
+                          {getWorkStatusBadge(order.workStatus)}
+                        </span>
                       </div>
                       <div className="flex items-center justify-between">
-                        <span className="text-sm font-medium">预计开始日期:</span>
-                        <span data-testid="order-detail-expected-start">{formatDate(order.expectedStartDate)}</span>
+                        <span className="text-sm font-medium">
+                          预计开始日期:
+                        </span>
+                        <span data-testid="order-detail-expected-start">
+                          {formatDate(order.expectedStartDate)}
+                        </span>
                       </div>
                       <div className="flex items-center justify-between">
-                        <span className="text-sm font-medium">实际开始日期:</span>
-                        <span data-testid="order-detail-actual-start">{formatDate(order.actualStartDate)}</span>
+                        <span className="text-sm font-medium">
+                          实际开始日期:
+                        </span>
+                        <span data-testid="order-detail-actual-start">
+                          {formatDate(order.actualStartDate)}
+                        </span>
                       </div>
+                    </div>
+                  </div>
+                  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-4">
+                    <div className="space-y-2">
                       <div className="flex items-center justify-between">
-                        <span className="text-sm font-medium">实际结束日期:</span>
-                        <span data-testid="order-detail-actual-end">{formatDate(order.actualEndDate)}</span>
+                        <span className="text-sm font-medium">
+                          实际结束日期:
+                        </span>
+                        <span data-testid="order-detail-actual-end">
+                          {formatDate(order.actualEndDate)}
+                        </span>
                       </div>
                     </div>
-                  </div>
-                  <Separator className="my-4" />
-                  <div className="space-y-2">
-                    <div className="flex items-center justify-between">
-                      <span className="text-sm font-medium">创建时间:</span>
-                      <span data-testid="order-detail-create-time">{formatDate(order.createTime)}</span>
+                    <div className="space-y-2">
+                      <div className="flex items-center justify-between">
+                        <span className="text-sm font-medium">创建时间:</span>
+                        <span data-testid="order-detail-create-time">
+                          {formatDate(order.createTime)}
+                        </span>
+                      </div>
                     </div>
-                    <div className="flex items-center justify-between">
-                      <span className="text-sm font-medium">更新时间:</span>
-                      <span data-testid="order-detail-update-time">{formatDate(order.updateTime)}</span>
+                    <div className="space-y-2">
+                      <div className="flex items-center justify-between">
+                        <span className="text-sm font-medium">更新时间:</span>
+                        <span data-testid="order-detail-update-time">
+                          {formatDate(order.updateTime)}
+                        </span>
+                      </div>
                     </div>
                   </div>
                 </CardContent>
@@ -342,7 +398,10 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                         <TableHeader>
                           <TableRow>
                             {personColumns.map((column) => (
-                              <TableHead key={column.key} style={{ width: column.width }}>
+                              <TableHead
+                                key={column.key}
+                                style={{ width: column.width }}
+                              >
                                 {column.label}
                               </TableHead>
                             ))}
@@ -350,34 +409,58 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                         </TableHeader>
                         <TableBody>
                           {order.orderPersons.map((person) => (
-                            <TableRow key={person.personId} data-testid={`order-detail-person-${person.personId}`}>
+                            <TableRow
+                              key={person.personId}
+                              data-testid={`order-detail-person-${person.personId}`}
+                            >
                               <TableCell>{person.personId}</TableCell>
                               <TableCell>{person.personName}</TableCell>
                               <TableCell>{person.gender}</TableCell>
                               <TableCell>{person.disabilityType}</TableCell>
                               <TableCell>{person.phone}</TableCell>
-                              <TableCell>{formatDate(person.joinDate)}</TableCell>
-                              <TableCell>{formatDate(person.leaveDate)}</TableCell>
+                              <TableCell>
+                                {formatDate(person.joinDate)}
+                              </TableCell>
+                              <TableCell>
+                                {formatDate(person.leaveDate)}
+                              </TableCell>
                               <TableCell>
                                 <Select
                                   value={person.workStatus?.toString()}
-                                  onValueChange={(value) => handleUpdateWorkStatus(person.personId, parseInt(value) as WorkStatus)}
+                                  onValueChange={(value) =>
+                                    handleUpdateWorkStatus(
+                                      person.personId,
+                                      parseInt(value) as WorkStatus,
+                                    )
+                                  }
                                   data-testid={`order-detail-work-status-select-${person.personId}`}
                                 >
                                   <SelectTrigger className="w-full">
                                     <SelectValue placeholder="选择状态" />
                                   </SelectTrigger>
                                   <SelectContent>
-                                    <SelectItem value={WorkStatus.NOT_WORKING} data-testid={`work-status-option-not-working-${person.personId}`}>
+                                    <SelectItem
+                                      value={WorkStatus.NOT_WORKING}
+                                      data-testid={`work-status-option-not-working-${person.personId}`}
+                                    >
                                       未入职
                                     </SelectItem>
-                                    <SelectItem value={WorkStatus.PRE_WORKING} data-testid={`work-status-option-pre-working-${person.personId}`}>
+                                    <SelectItem
+                                      value={WorkStatus.PRE_WORKING}
+                                      data-testid={`work-status-option-pre-working-${person.personId}`}
+                                    >
                                       已入职
                                     </SelectItem>
-                                    <SelectItem value={WorkStatus.WORKING} data-testid={`work-status-option-working-${person.personId}`}>
+                                    <SelectItem
+                                      value={WorkStatus.WORKING}
+                                      data-testid={`work-status-option-working-${person.personId}`}
+                                    >
                                       工作中
                                     </SelectItem>
-                                    <SelectItem value={WorkStatus.RESIGNED} data-testid={`work-status-option-resigned-${person.personId}`}>
+                                    <SelectItem
+                                      value={WorkStatus.RESIGNED}
+                                      data-testid={`work-status-option-resigned-${person.personId}`}
+                                    >
                                       已离职
                                     </SelectItem>
                                   </SelectContent>
@@ -445,10 +528,11 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                   data-testid="order-detail-activate-button"
                 >
                   <Play className="mr-2 h-4 w-4" />
-                  {isActionLoading ? '激活中...' : '激活订单'}
+                  {isActionLoading ? "激活中..." : "激活订单"}
                 </Button>
               )}
-              {(order?.orderStatus === OrderStatus.CONFIRMED || order?.orderStatus === OrderStatus.IN_PROGRESS) && (
+              {(order?.orderStatus === OrderStatus.CONFIRMED ||
+                order?.orderStatus === OrderStatus.IN_PROGRESS) && (
                 <Button
                   onClick={handleCloseOrder}
                   variant="destructive"
@@ -456,7 +540,7 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                   data-testid="order-detail-close-order-button"
                 >
                   <CheckCircle className="mr-2 h-4 w-4" />
-                  {isActionLoading ? '关闭中...' : '关闭订单'}
+                  {isActionLoading ? "关闭中..." : "关闭订单"}
                 </Button>
               )}
             </div>
@@ -497,4 +581,4 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
   );
 };
 
-export default OrderDetailModal;
+export default OrderDetailModal;