فهرست منبع

feat: 添加订单人员入职/离职日期交叉验证

- 添加 Toast 错误提示(入职日期不能晚于离职日期等)
- 日历动态禁用无效日期(基于另一个日期)
- 移除未来日期限制,允许预招聘和预离职
- 修复 TypeScript 可选链错误

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 5 روز پیش
والد
کامیت
98413ec7ab
1فایلهای تغییر یافته به همراه29 افزوده شده و 5 حذف شده
  1. 29 5
      allin-packages/order-management-ui/src/components/OrderDetailModal.tsx

+ 29 - 5
allin-packages/order-management-ui/src/components/OrderDetailModal.tsx

@@ -40,7 +40,7 @@ import { Calendar as CalendarComponent } from "@d8d/shared-ui-components/compone
 import { Badge } from "@d8d/shared-ui-components/components/ui/badge";
 import { Input } from "@d8d/shared-ui-components/components/ui/input";
 import { toast } from "sonner";
-import { format } from "date-fns";
+import { format, isAfter, isBefore } from "date-fns";
 import { Users, FileText, Calendar as CalendarIcon, Play, CheckCircle, X } from "lucide-react";
 import {
   OrderStatus,
@@ -454,7 +454,18 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
   // 处理更新入职日期
   const handleUpdateJoinDate = (personId: number, date: Date | undefined) => {
     if (!orderId || !date) return;
-    // 使用 date-fns format 确保本地时区正确格式化
+
+    // 获取当前人员的离职日期进行验证
+    const person = order?.orderPersons?.find(p => p.personId === personId);
+    if (person?.leaveDate) {
+      const leaveDateObj = new Date(person.leaveDate);
+      // 入职日期不能晚于离职日期
+      if (isAfter(date, leaveDateObj)) {
+        toast.error('入职日期不能晚于离职日期');
+        return;
+      }
+    }
+
     const joinDate = format(date, 'yyyy-MM-dd');
     updateJoinDateMutation.mutate({ orderId, personId, joinDate });
   };
@@ -462,7 +473,18 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
   // 处理更新离职日期
   const handleUpdateLeaveDate = (personId: number, date: Date | undefined) => {
     if (!orderId) return;
-    // 使用 date-fns format 确保本地时区正确格式化
+
+    // 获取当前人员的入职日期进行验证
+    const person = order?.orderPersons?.find(p => p.personId === personId);
+    if (date && person?.joinDate) {
+      const joinDateObj = new Date(person.joinDate);
+      // 离职日期不能早于入职日期
+      if (isBefore(date, joinDateObj)) {
+        toast.error('离职日期不能早于入职日期');
+        return;
+      }
+    }
+
     const leaveDate = date ? format(date, 'yyyy-MM-dd') : null;
     updateLeaveDateMutation.mutate({ orderId, personId, leaveDate });
   };
@@ -781,7 +803,8 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                                       selected={person.joinDate ? new Date(person.joinDate) : undefined}
                                       onSelect={(date) => handleUpdateJoinDate(person.personId, date)}
                                       disabled={(date) =>
-                                        date > new Date() || date < new Date("1900-01-01")
+                                        date < new Date("1900-01-01") ||
+                                        (person.leaveDate ? isAfter(date, new Date(person.leaveDate)) : false)
                                       }
                                       data-testid={`join-date-calendar-${person.personId}`}
                                     />
@@ -807,7 +830,8 @@ const OrderDetailModal: React.FC<OrderDetailModalProps> = ({
                                       selected={person.leaveDate ? new Date(person.leaveDate) : undefined}
                                       onSelect={(date) => handleUpdateLeaveDate(person.personId, date)}
                                       disabled={(date) =>
-                                        date > new Date() || date < new Date("1900-01-01")
+                                        date < new Date("1900-01-01") ||
+                                        (person.joinDate ? isBefore(date, new Date(person.joinDate)) : false)
                                       }
                                       data-testid={`leave-date-calendar-${person.personId}`}
                                     />