From 2461efdde98a2509c7ac5a9fd56629aaecb8b281 Mon Sep 17 00:00:00 2001
From: tony.cheng <chengmingwei_1984122@126.com>
Date: Tue, 17 Mar 2026 12:05:37 +0800
Subject: [PATCH] enhance: 增强AI调解状态控制功能的健壮性和调试能力

---
 web-app/src/__tests__/mediationStateControl.test.js |  149 +++++++++++++++++++++++++++++++++++++
 web-app/src/components/dashboard/TabContainer.jsx   |   48 +++++++++++-
 2 files changed, 193 insertions(+), 4 deletions(-)

diff --git a/web-app/src/__tests__/mediationStateControl.test.js b/web-app/src/__tests__/mediationStateControl.test.js
new file mode 100644
index 0000000..9f07b58
--- /dev/null
+++ b/web-app/src/__tests__/mediationStateControl.test.js
@@ -0,0 +1,149 @@
+import React from 'react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import { message } from 'antd';
+import TabContainer from '../components/dashboard/TabContainer';
+import ProcessAPIService from '../services/ProcessAPIService';
+import { getMergedParams } from '../utils/urlParams';
+
+// Mock依赖
+jest.mock('../services/ProcessAPIService');
+jest.mock('../utils/urlParams');
+jest.mock('antd', () => ({
+  message: {
+    success: jest.fn(),
+    error: jest.fn()
+  },
+  Spin: ({ children }) => <div data-testid="spin">{children}</div>,
+  Modal: ({ children, visible, onOk, onCancel, title, confirmLoading }) => (
+    visible ? (
+      <div data-testid="modal">
+        <h3>{title}</h3>
+        {children}
+        <button onClick={onOk} disabled={confirmLoading}>确定</button>
+        <button onClick={onCancel}>取消</button>
+      </div>
+    ) : null
+  )
+}));
+
+jest.mock('../contexts/CaseDataContext', () => ({
+  useCaseData: () => ({
+    caseData: {
+      mediation: {
+        state: 0, // 测试终止状态
+        id: 'test-mediation-id'
+      }
+    },
+    refreshData: jest.fn()
+  })
+}));
+
+describe('AI调解状态控制功能测试', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    getMergedParams.mockReturnValue({ caseId: 'test-case-id' });
+  });
+
+  test('应该显示终止按钮当caseState为0', () => {
+    render(<TabContainer activeTab="mediation-board" />);
+    
+    // 等待组件渲染完成
+    expect(screen.getByText('终止')).toBeInTheDocument();
+  });
+
+  test('应该显示恢复按钮当caseState为5', () => {
+    // 修改mock数据
+    jest.mock('../contexts/CaseDataContext', () => ({
+      useCaseData: () => ({
+        caseData: {
+          mediation: {
+            state: 5, // 恢复状态
+            id: 'test-mediation-id'
+          }
+        },
+        refreshData: jest.fn()
+      })
+    }));
+
+    render(<TabContainer activeTab="mediation-board" />);
+    
+    expect(screen.getByText('恢复')).toBeInTheDocument();
+  });
+
+  test('点击终止按钮应该显示确认对话框', () => {
+    render(<TabContainer activeTab="mediation-board" />);
+    
+    const terminateButton = screen.getByText('终止');
+    fireEvent.click(terminateButton);
+    
+    expect(screen.getByTestId('modal')).toBeInTheDocument();
+    expect(screen.getByText('确认终止调解')).toBeInTheDocument();
+  });
+
+  test('确认终止应该调用API并显示成功消息', async () => {
+    ProcessAPIService.updateMediationState.mockResolvedValue({ code: 200 });
+    
+    render(<TabContainer activeTab="mediation-board" />);
+    
+    // 点击终止按钮
+    const terminateButton = screen.getByText('终止');
+    fireEvent.click(terminateButton);
+    
+    // 点击确认按钮
+    const confirmButton = screen.getByText('确定');
+    fireEvent.click(confirmButton);
+    
+    // 验证API调用
+    await waitFor(() => {
+      expect(ProcessAPIService.updateMediationState).toHaveBeenCalledWith(
+        'test-case-id',
+        {
+          action: 0,
+          userName: '调解员'
+        }
+      );
+    });
+    
+    // 验证成功消息
+    expect(message.success).toHaveBeenCalledWith('案件状态更新成功');
+  });
+
+  test('API调用失败应该显示错误消息', async () => {
+    ProcessAPIService.updateMediationState.mockRejectedValue(new Error('网络错误'));
+    
+    render(<TabContainer activeTab="mediation-board" />);
+    
+    // 点击终止按钮
+    const terminateButton = screen.getByText('终止');
+    fireEvent.click(terminateButton);
+    
+    // 点击确认按钮
+    const confirmButton = screen.getByText('确定');
+    fireEvent.click(confirmButton);
+    
+    // 验证错误消息
+    await waitFor(() => {
+      expect(message.error).toHaveBeenCalledWith('网络错误');
+    });
+  });
+
+  test('不应该显示按钮当caseState为其他值', () => {
+    // 修改mock数据为不支持的状态
+    jest.mock('../contexts/CaseDataContext', () => ({
+      useCaseData: () => ({
+        caseData: {
+          mediation: {
+            state: 2, // 不支持的状态
+            id: 'test-mediation-id'
+          }
+        },
+        refreshData: jest.fn()
+      })
+    }));
+
+    render(<TabContainer activeTab="mediation-board" />);
+    
+    expect(screen.queryByText('终止')).not.toBeInTheDocument();
+    expect(screen.queryByText('恢复')).not.toBeInTheDocument();
+  });
+});
\ No newline at end of file
diff --git a/web-app/src/components/dashboard/TabContainer.jsx b/web-app/src/components/dashboard/TabContainer.jsx
index aaf5bc2..40b8521 100644
--- a/web-app/src/components/dashboard/TabContainer.jsx
+++ b/web-app/src/components/dashboard/TabContainer.jsx
@@ -354,10 +354,22 @@
 
   // 状态控制按钮显示逻辑
   const shouldShowControlButton = () => {
-    return caseState === 0 || caseState === 1 || caseState === 5;
+    const show = caseState === 0 || caseState === 1 || caseState === 5;
+    console.log('状态控制按钮显示检查:', {
+      caseState,
+      show,
+      conditions: {
+        'caseState === 0': caseState === 0,
+        'caseState === 1': caseState === 1,
+        'caseState === 5': caseState === 5
+      }
+    });
+    return show;
   };
 
   const getControlButtonProps = () => {
+    console.log('获取按钮属性:', { caseState });
+    
     if (caseState === 0 || caseState === 1) {
       return {
         text: '终止',
@@ -371,38 +383,66 @@
         action: 'resume'
       };
     }
+    
+    console.log('未匹配到按钮属性,返回null');
     return null;
   };
 
   // 处理状态控制按钮点击
   const handleControlButtonClick = (action) => {
+    console.log('状态控制按钮点击:', { action });
     setControlAction(action);
     setConfirmModalVisible(true);
   };
 
   // 处理确认对话框确认
   const handleConfirmOk = async () => {
-    if (!controlAction) return;
+    console.log('确认对话框确认:', { controlAction, remark });
+    
+    if (!controlAction) {
+      console.warn('控制动作为空');
+      return;
+    }
     
     setControlLoading(true);
     try {
       const params = getMergedParams();
       const actionCode = controlAction === 'terminate' ? 0 : 1;
       
+      console.log('准备调用API:', {
+        caseId: params.caseId,
+        actionCode,
+        userName: localStorage.getItem('userName') || '调解员',
+        remark: remark || ''
+      });
+      
+      // 验证必要参数
+      if (!params.caseId) {
+        throw new Error('案件ID不能为空');
+      }
+      
       await ProcessAPIService.updateMediationState(params.caseId, {
         action: actionCode,
-        userName: localStorage.getItem('userName') || '调解员'
+        userName: localStorage.getItem('userName') || '调解员',
+        remark: remark || ''
       });
       
       message.success('案件状态更新成功');
       setConfirmModalVisible(false);
       setRemark('');
+      setControlAction(null);
       
       // 刷新数据
       refreshData();
     } catch (error) {
       console.error('状态更新失败:', error);
-      message.error(error.message || '状态更新失败,请稍后重试');
+      const errorMessage = error.message || '状态更新失败,请稍后重试';
+      message.error(errorMessage);
+      
+      // 如果是网络错误,提供更多帮助信息
+      if (errorMessage.includes('网络') || errorMessage.includes('Network')) {
+        message.info('请检查网络连接或联系管理员');
+      }
     } finally {
       setControlLoading(false);
     }

--
Gitblit v1.8.0