Prechádzať zdrojové kódy

fix(order-management-ui): 替换window.confirm为共享UI包AlertDialog组件

- 修复OrderManagement组件中的window.confirm使用问题
- 使用@d8d/shared-ui-components/components/ui/alert-dialog组件替换原生window.confirm
- 为删除、激活、关闭操作分别创建独立的AlertDialog状态管理
- 添加适当的data-testid属性用于测试
- 更新集成测试验证AlertDialog的显示和交互
- 修复测试中的mock结构,参照平台管理UI包的写法
- 更新故事008.007文档,标记任务8为完成

🤖 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 dní pred
rodič
commit
8b790e084f

+ 112 - 8
allin-packages/order-management-ui/src/components/OrderManagement.tsx

@@ -34,6 +34,16 @@ import {
 } from '@d8d/shared-ui-components/components/ui/select';
 import { Badge } from '@d8d/shared-ui-components/components/ui/badge';
 import { toast } from 'sonner';
+import {
+  AlertDialog,
+  AlertDialogAction,
+  AlertDialogCancel,
+  AlertDialogContent,
+  AlertDialogDescription,
+  AlertDialogFooter,
+  AlertDialogHeader,
+  AlertDialogTitle,
+} from '@d8d/shared-ui-components/components/ui/alert-dialog';
 import {
   Plus,
   Search,
@@ -69,6 +79,12 @@ export const OrderManagement: React.FC = () => {
   const [selectedOrderId, setSelectedOrderId] = useState<number | null>(null);
   const [selectedPersonId, setSelectedPersonId] = useState<number | null>(null);
 
+  // 确认对话框状态
+  const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
+  const [activateConfirmOpen, setActivateConfirmOpen] = useState(false);
+  const [closeConfirmOpen, setCloseConfirmOpen] = useState(false);
+  const [pendingOrderId, setPendingOrderId] = useState<number | null>(null);
+
   // 查询订单列表
   const { data: ordersData, isLoading, error } = useQuery({
     queryKey: ['orders', searchParams],
@@ -162,22 +178,46 @@ export const OrderManagement: React.FC = () => {
 
   // 处理删除订单
   const handleDeleteOrder = (id: number) => {
-    if (window.confirm('确定要删除这个订单吗?')) {
-      deleteMutation.mutate(id);
-    }
+    setPendingOrderId(id);
+    setDeleteConfirmOpen(true);
   };
 
   // 处理激活订单
   const handleActivateOrder = (orderId: number) => {
-    if (window.confirm('确定要激活这个订单吗?')) {
-      activateMutation.mutate(orderId);
-    }
+    setPendingOrderId(orderId);
+    setActivateConfirmOpen(true);
   };
 
   // 处理关闭订单
   const handleCloseOrder = (orderId: number) => {
-    if (window.confirm('确定要关闭这个订单吗?')) {
-      closeMutation.mutate(orderId);
+    setPendingOrderId(orderId);
+    setCloseConfirmOpen(true);
+  };
+
+  // 确认删除订单
+  const confirmDeleteOrder = () => {
+    if (pendingOrderId) {
+      deleteMutation.mutate(pendingOrderId);
+      setDeleteConfirmOpen(false);
+      setPendingOrderId(null);
+    }
+  };
+
+  // 确认激活订单
+  const confirmActivateOrder = () => {
+    if (pendingOrderId) {
+      activateMutation.mutate(pendingOrderId);
+      setActivateConfirmOpen(false);
+      setPendingOrderId(null);
+    }
+  };
+
+  // 确认关闭订单
+  const confirmCloseOrder = () => {
+    if (pendingOrderId) {
+      closeMutation.mutate(pendingOrderId);
+      setCloseConfirmOpen(false);
+      setPendingOrderId(null);
     }
   };
 
@@ -506,6 +546,70 @@ export const OrderManagement: React.FC = () => {
           }}
         />
       )}
+
+      {/* 删除订单确认对话框 */}
+      <AlertDialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>
+        <AlertDialogContent data-testid="delete-confirm-dialog">
+          <AlertDialogHeader>
+            <AlertDialogTitle data-testid="delete-confirm-dialog-title">删除订单</AlertDialogTitle>
+            <AlertDialogDescription data-testid="delete-confirm-dialog-description">
+              确定要删除这个订单吗?此操作不可撤销。
+            </AlertDialogDescription>
+          </AlertDialogHeader>
+          <AlertDialogFooter>
+            <AlertDialogCancel data-testid="delete-confirm-dialog-cancel">取消</AlertDialogCancel>
+            <AlertDialogAction
+              onClick={confirmDeleteOrder}
+              data-testid="delete-confirm-dialog-confirm"
+              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
+            >
+              删除
+            </AlertDialogAction>
+          </AlertDialogFooter>
+        </AlertDialogContent>
+      </AlertDialog>
+
+      {/* 激活订单确认对话框 */}
+      <AlertDialog open={activateConfirmOpen} onOpenChange={setActivateConfirmOpen}>
+        <AlertDialogContent data-testid="activate-confirm-dialog">
+          <AlertDialogHeader>
+            <AlertDialogTitle data-testid="activate-confirm-dialog-title">激活订单</AlertDialogTitle>
+            <AlertDialogDescription data-testid="activate-confirm-dialog-description">
+              确定要激活这个订单吗?订单激活后将进入进行中状态。
+            </AlertDialogDescription>
+          </AlertDialogHeader>
+          <AlertDialogFooter>
+            <AlertDialogCancel data-testid="activate-confirm-dialog-cancel">取消</AlertDialogCancel>
+            <AlertDialogAction
+              onClick={confirmActivateOrder}
+              data-testid="activate-confirm-dialog-confirm"
+            >
+              激活
+            </AlertDialogAction>
+          </AlertDialogFooter>
+        </AlertDialogContent>
+      </AlertDialog>
+
+      {/* 关闭订单确认对话框 */}
+      <AlertDialog open={closeConfirmOpen} onOpenChange={setCloseConfirmOpen}>
+        <AlertDialogContent data-testid="close-confirm-dialog">
+          <AlertDialogHeader>
+            <AlertDialogTitle data-testid="close-confirm-dialog-title">关闭订单</AlertDialogTitle>
+            <AlertDialogDescription data-testid="close-confirm-dialog-description">
+              确定要关闭这个订单吗?订单关闭后将无法再添加人员或资产。
+            </AlertDialogDescription>
+          </AlertDialogHeader>
+          <AlertDialogFooter>
+            <AlertDialogCancel data-testid="close-confirm-dialog-cancel">取消</AlertDialogCancel>
+            <AlertDialogAction
+              onClick={confirmCloseOrder}
+              data-testid="close-confirm-dialog-confirm"
+            >
+              关闭
+            </AlertDialogAction>
+          </AlertDialogFooter>
+        </AlertDialogContent>
+      </AlertDialog>
     </div>
   );
 };

+ 95 - 12
allin-packages/order-management-ui/tests/integration/order.integration.test.tsx

@@ -296,14 +296,14 @@ vi.mock('../../src/api/orderClient', () => {
     },
   };
 
+  const mockOrderClientManager = {
+    get: vi.fn(() => mockOrderClient),
+    reset: vi.fn(),
+  };
+
   return {
+    orderClientManager: mockOrderClientManager,
     orderClient: mockOrderClient,
-    orderClientManager: {
-      getInstance: vi.fn(() => ({
-        get: vi.fn(() => mockOrderClient),
-        reset: vi.fn(),
-      })),
-    },
   };
 });
 
@@ -433,10 +433,23 @@ describe('订单管理集成测试', () => {
       const deleteButton = screen.getByTestId('delete-order-button-1');
       await userEvent.click(deleteButton);
 
-      // 这里会触发window.confirm,在测试环境中需要mock
-      // 实际测试中应该验证API调用
-      // Mock window.confirm
-      const mockConfirm = vi.spyOn(window, 'confirm').mockReturnValue(true);
+      // 验证删除确认对话框显示
+      await waitFor(() => {
+        expect(screen.getByTestId('delete-confirm-dialog')).toBeInTheDocument();
+        expect(screen.getByTestId('delete-confirm-dialog-title')).toHaveTextContent('删除订单');
+        expect(screen.getByTestId('delete-confirm-dialog-description')).toHaveTextContent('确定要删除这个订单吗?此操作不可撤销。');
+      });
+
+      // 点击确认按钮
+      const confirmButton = screen.getByTestId('delete-confirm-dialog-confirm');
+      await userEvent.click(confirmButton);
+
+      // 验证API调用
+      await waitFor(() => {
+        expect(orderClientManager.get().delete[':id'].$delete).toHaveBeenCalledWith({
+          param: { id: 1 },
+        });
+      });
     });
 
     it('应该成功激活订单', async () => {
@@ -461,8 +474,23 @@ describe('订单管理集成测试', () => {
       const activateButton = screen.getByTestId('activate-order-button-1');
       await userEvent.click(activateButton);
 
+      // 验证激活确认对话框显示
+      await waitFor(() => {
+        expect(screen.getByTestId('activate-confirm-dialog')).toBeInTheDocument();
+        expect(screen.getByTestId('activate-confirm-dialog-title')).toHaveTextContent('激活订单');
+        expect(screen.getByTestId('activate-confirm-dialog-description')).toHaveTextContent('确定要激活这个订单吗?订单激活后将进入进行中状态。');
+      });
+
+      // 点击确认按钮
+      const confirmButton = screen.getByTestId('activate-confirm-dialog-confirm');
+      await userEvent.click(confirmButton);
+
       // 验证API调用
-      // 实际测试中应该验证API调用
+      await waitFor(() => {
+        expect(orderClientManager.get().activate[':orderId'].$post).toHaveBeenCalledWith({
+          param: { orderId: 1 },
+        });
+      });
     });
 
     it('应该成功关闭订单', async () => {
@@ -487,8 +515,63 @@ describe('订单管理集成测试', () => {
       const closeButton = screen.getByTestId('close-order-button-2');
       await userEvent.click(closeButton);
 
+      // 验证关闭确认对话框显示
+      await waitFor(() => {
+        expect(screen.getByTestId('close-confirm-dialog')).toBeInTheDocument();
+        expect(screen.getByTestId('close-confirm-dialog-title')).toHaveTextContent('关闭订单');
+        expect(screen.getByTestId('close-confirm-dialog-description')).toHaveTextContent('确定要关闭这个订单吗?订单关闭后将无法再添加人员或资产。');
+      });
+
+      // 点击确认按钮
+      const confirmButton = screen.getByTestId('close-confirm-dialog-confirm');
+      await userEvent.click(confirmButton);
+
       // 验证API调用
-      // 实际测试中应该验证API调用
+      await waitFor(() => {
+        expect(orderClientManager.get().close[':orderId'].$post).toHaveBeenCalledWith({
+          param: { orderId: 2 },
+        });
+      });
+    });
+
+    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 deleteButton = screen.getByTestId('delete-order-button-1');
+        expect(deleteButton).toBeInTheDocument();
+      });
+
+      const deleteButton = screen.getByTestId('delete-order-button-1');
+      await userEvent.click(deleteButton);
+
+      // 验证删除确认对话框显示
+      await waitFor(() => {
+        expect(screen.getByTestId('delete-confirm-dialog')).toBeInTheDocument();
+      });
+
+      // 点击取消按钮
+      const cancelButton = screen.getByTestId('delete-confirm-dialog-cancel');
+      await userEvent.click(cancelButton);
+
+      // 验证对话框关闭
+      await waitFor(() => {
+        expect(screen.queryByTestId('delete-confirm-dialog')).not.toBeInTheDocument();
+      });
+
+      // 验证API没有被调用
+      expect(orderClientManager.get().delete[':id'].$delete).not.toHaveBeenCalled();
     });
   });
 

+ 32 - 8
docs/stories/008.007.transplant-order-management-ui.story.md

@@ -174,7 +174,20 @@ Draft
     - **测试场景**:API错误、网络错误、表单验证错误
     - **参考模式**:平台管理集成测试中的错误处理
 
-- [ ] 任务8:验证和测试 (AC: 11)
+- [x] 任务8:修复window.confirm使用问题 (AC: 11)
+  - [x] 分析OrderManagement组件中的window.confirm使用情况
+    - **问题位置**:`allin-packages/order-management-ui/src/components/OrderManagement.tsx`
+    - **问题函数**:`handleDeleteOrder`、`handleActivateOrder`、`handleCloseOrder`
+    - **问题描述**:使用原生`window.confirm`,不符合UI包开发规范,在测试环境中会报错
+  - [x] 替换为共享UI包AlertDialog组件
+    - **组件来源**:`@d8d/shared-ui-components/components/ui/alert-dialog`
+    - **实现方式**:为每个确认操作创建独立的AlertDialog状态管理
+    - **确认类型**:删除确认、激活确认、关闭确认
+  - [x] 更新测试以验证AlertDialog正常工作
+    - **测试更新**:更新集成测试,验证AlertDialog的显示和交互
+    - **测试ID**:为AlertDialog添加适当的data-testid属性
+
+- [ ] 任务9:验证和测试 (AC: 11)
   - [ ] 运行`pnpm typecheck`确保无类型错误
   - [ ] 运行`pnpm test`确保所有集成测试通过
   - [ ] 验证文件上传组件集成正常工作
@@ -184,6 +197,7 @@ Draft
   - [ ] 验证订单人员资产管理功能正常工作
   - [ ] 验证订单工作流状态转换正常工作
   - [ ] 验证表单验证和错误处理功能
+  - [ ] 验证AlertDialog确认功能正常工作
 
 ## Dev Notes
 
@@ -334,6 +348,7 @@ Draft
 ## Change Log
 | Date | Version | Description | Author |
 |------|---------|-------------|--------|
+| 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) |
 | 2025-12-04 | 1.0 | 初始创建故事008.007 | Bob (Scrum Master) |
@@ -361,21 +376,30 @@ Draft
    - **新增修复**:修复`userEvent is not defined`错误(添加userEvent导入)
    - **新增修复**:修复下拉菜单交互测试,使用userEvent.click代替fireEvent.click,正确等待下拉菜单打开
    - **新增修复**:修复编辑、删除、激活、关闭订单测试的下拉菜单交互问题
-3. **剩余问题**:
-   - `window.confirm`在测试环境中未实现错误(组件中使用了原生`window.confirm`,应该使用共享UI包的确认对话框组件)
+   - **新增修复**:修复`window.confirm`使用问题,替换为共享UI包AlertDialog组件
+3. **任务8完成情况**:
+   - **已完成**:修复OrderManagement组件中的`window.confirm`使用问题
+   - **解决方案**:使用`@d8d/shared-ui-components/components/ui/alert-dialog`组件替换原生`window.confirm`
+   - **实现细节**:
+     - 为删除、激活、关闭操作分别创建独立的AlertDialog状态管理
+     - 添加适当的data-testid属性用于测试
+     - 更新集成测试验证AlertDialog的显示和交互
+     - 修复测试中的mock结构,参照平台管理UI包的写法
+   - **测试验证**:4个相关测试全部通过(删除、激活、关闭订单,取消删除操作)
+4. **剩余问题**:
    - 资产关联模态框测试:找不到`add-asset-button-1`(需要先打开下拉菜单)
    - 订单表单测试:可能类似的下拉菜单交互问题
    - 人员选择器测试:找不到`add-persons-button-1`(需要先打开下拉菜单)
-4. **故事状态**:当前为Draft状态,测试通过率80%,显著提升,大部分核心功能测试已通过。**发现架构问题**:组件中使用了原生`window.confirm`,不符合UI包开发规范,应该使用共享UI包的确认对话框组件。
+5. **故事状态**:当前为Draft状态,测试通过率80%,显著提升,大部分核心功能测试已通过。**已修复架构问题**:组件中原生`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
+- `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/tests/integration/order.integration.test.tsx` - 更新测试,添加外部组件mock,修复测试选择器,使用test ID验证枚举选项,添加userEvent导入,修复下拉菜单交互测试
+- `allin-packages/order-management-ui/tests/integration/order.integration.test.tsx` - 更新测试,添加外部组件mock,修复测试选择器,使用test ID验证枚举选项,添加userEvent导入,修复下拉菜单交互测试;修复mock结构,参照平台管理UI包写法;更新AlertDialog相关测试
 - `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
+- `docs/stories/008.007.transplant-order-management-ui.story.md` - 更新Dev Agent Record,添加任务8修复window.confirm使用问题,更新完成记录
 - `docs/architecture/ui-package-standards.md` - 添加Radix UI组件测试修复规范(基于故事008.007经验)
 - `allin-packages/platform-management-ui/tests/setup.ts` - 同样修复平台管理UI的Radix UI组件错误
 
@@ -385,7 +409,7 @@ Draft
 - `allin-packages/order-management-ui/src/components/OrderPersonAssetAssociation.tsx` - 订单人员资产关联组件
 
 *发现需要重构的问题:*
-- `allin-packages/order-management-ui/src/components/OrderManagement.tsx` - 使用了原生`window.confirm`,不符合UI包开发规范,应该使用共享UI包的确认对话框组件
+- `allin-packages/order-management-ui/src/components/OrderManagement.tsx` - 使用了原生`window.confirm`,不符合UI包开发规范,应该使用共享UI包的确认对话框组件(**已在任务8中修复**)
 
 ## QA Results
 *来自QA代理对已完成故事实施的QA审查结果*