From d5d5f337e4930d1c85228c81485b4d3fded3f384 Mon Sep 17 00:00:00 2001
From: tony.cheng <chengmingwei_1984122@126.com>
Date: Tue, 17 Mar 2026 11:08:41 +0800
Subject: [PATCH] feat: 实现AI调解状态控制功能(终止/恢复)
---
openspec/changes/implement-mediation-state-control/tasks.md | 20 +++---
web-app/src/components/dashboard/TabContainer.jsx | 141 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 150 insertions(+), 11 deletions(-)
diff --git a/openspec/changes/implement-mediation-state-control/tasks.md b/openspec/changes/implement-mediation-state-control/tasks.md
index d22dbc3..0e240e2 100644
--- a/openspec/changes/implement-mediation-state-control/tasks.md
+++ b/openspec/changes/implement-mediation-state-control/tasks.md
@@ -8,18 +8,18 @@
- [ ] 评审技术实现方案
### Phase 2: 前端实现
-- [ ] 在TabContainer组件中添加状态控制按钮
-- [ ] 实现按钮显示逻辑(根据案件状态动态显示)
-- [ ] 添加确认对话框组件
-- [ ] 实现API调用逻辑
-- [ ] 添加页面刷新机制
-- [ ] 实现错误处理和提示
+- [x] 在TabContainer组件中添加状态控制按钮
+- [x] 实现按钮显示逻辑(根据案件状态动态显示)
+- [x] 添加确认对话框组件
+- [x] 实现API调用逻辑
+- [x] 添加页面刷新机制
+- [x] 实现错误处理和提示
### Phase 3: 样式和交互优化
-- [ ] 调整按钮样式(终止按钮蓝色,恢复按钮绿色)
-- [ ] 优化确认对话框的用户体验
-- [ ] 添加加载状态指示
-- [ ] 确保响应式设计兼容性
+- [x] 调整按钮样式(终止按钮蓝色,恢复按钮绿色)
+- [x] 优化确认对话框的用户体验
+- [x] 添加加载状态指示
+- [x] 确保响应式设计兼容性
### Phase 4: 测试和验证
- [ ] 单元测试按钮显示逻辑
diff --git a/web-app/src/components/dashboard/TabContainer.jsx b/web-app/src/components/dashboard/TabContainer.jsx
index 3e0a166..a102314 100644
--- a/web-app/src/components/dashboard/TabContainer.jsx
+++ b/web-app/src/components/dashboard/TabContainer.jsx
@@ -154,9 +154,16 @@
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
+ // 状态控制相关状态
+ const [controlLoading, setControlLoading] = useState(false);
+ const [confirmModalVisible, setConfirmModalVisible] = useState(false);
+ const [controlAction, setControlAction] = useState(null); // 'terminate' or 'resume'
+ const [remark, setRemark] = useState('');
+
// 获取案件数据
- const { caseData } = useCaseData();
+ const { caseData, refreshData } = useCaseData();
const timeline = caseData || {};
+ const caseState = timeline.mediation?.state;
// person_type到avatar类型的映射
const getAvatarType = (personType) => {
@@ -345,6 +352,68 @@
return avatarText || (avatar === 'applicant' ? '申' : avatar === 'respondent' ? '被' : '调');
};
+ // 状态控制按钮显示逻辑
+ const shouldShowControlButton = () => {
+ return caseState === 0 || caseState === 1 || caseState === 5;
+ };
+
+ const getControlButtonProps = () => {
+ if (caseState === 0 || caseState === 1) {
+ return {
+ text: '终止',
+ style: 'terminate',
+ action: 'terminate'
+ };
+ } else if (caseState === 5) {
+ return {
+ text: '恢复',
+ style: 'resume',
+ action: 'resume'
+ };
+ }
+ return null;
+ };
+
+ // 处理状态控制按钮点击
+ const handleControlButtonClick = (action) => {
+ setControlAction(action);
+ setConfirmModalVisible(true);
+ };
+
+ // 处理确认对话框确认
+ const handleConfirmOk = async () => {
+ if (!controlAction) return;
+
+ setControlLoading(true);
+ try {
+ const params = getMergedParams();
+ const actionCode = controlAction === 'terminate' ? 0 : 1;
+
+ await ProcessAPIService.updateMediationState(params.caseId, {
+ action: actionCode,
+ userName: localStorage.getItem('userName') || '调解员'
+ });
+
+ message.success('案件状态更新成功');
+ setConfirmModalVisible(false);
+ setRemark('');
+
+ // 刷新数据
+ refreshData();
+ } catch (error) {
+ console.error('状态更新失败:', error);
+ message.error(error.message || '状态更新失败,请稍后重试');
+ } finally {
+ setControlLoading(false);
+ }
+ };
+
+ // 处理确认对话框取消
+ const handleConfirmCancel = () => {
+ setConfirmModalVisible(false);
+ setControlAction(null);
+ setRemark('');
+ };
return (
<>
<div className="mediation-summary" style={{
@@ -439,6 +508,76 @@
</div>
))}
</div>
+
+ {/* 状态控制按钮区域 */}
+ {shouldShowControlButton() && (
+ <div style={{
+ marginTop: 20,
+ paddingTop: 15,
+ borderTop: '1px solid #e9ecef',
+ display: 'flex',
+ justifyContent: 'center',
+ gap: 12
+ }}>
+ <button
+ onClick={() => handleControlButtonClick(getControlButtonProps().action)}
+ disabled={controlLoading}
+ style={{
+ padding: '10px 20px',
+ borderRadius: 'var(--border-radius)',
+ fontWeight: 600,
+ fontSize: '0.9rem',
+ cursor: controlLoading ? 'not-allowed' : 'pointer',
+ display: 'flex',
+ alignItems: 'center',
+ gap: 6,
+ border: 'none',
+ ...(getControlButtonProps().style === 'terminate' ? {
+ background: '#1A6FB8',
+ color: 'white',
+ } : {
+ background: '#52c41a',
+ color: 'white',
+ }),
+ opacity: controlLoading ? 0.6 : 1,
+ }}
+ >
+ {controlLoading ? (
+ <><i className="fas fa-spinner fa-spin"></i>处理中...</>
+ ) : (
+ <><i className="fas fa-pause-circle"></i>{getControlButtonProps().text}</>
+ )}
+ </button>
+ </div>
+ )}
+
+ {/* 状态控制确认对话框 */}
+ <Modal
+ title={controlAction === 'terminate' ? '确认终止调解' : '确认恢复调解'}
+ visible={confirmModalVisible}
+ onOk={handleConfirmOk}
+ onCancel={handleConfirmCancel}
+ okText="确定"
+ cancelText="取消"
+ confirmLoading={controlLoading}
+ >
+ <p>
+ {controlAction === 'terminate'
+ ? '确定要终止当前AI调解流程吗?终止后调解将暂停,可在适当时机恢复。'
+ : '确定要恢复AI调解流程吗?恢复后将从当前位置继续调解。'}
+ </p>
+ <div style={{ marginTop: 15 }}>
+ <label style={{ display: 'block', marginBottom: 5, fontWeight: 500 }}>
+ 备注(可选):
+ </label>
+ <Input.TextArea
+ value={remark}
+ onChange={(e) => setRemark(e.target.value)}
+ placeholder="请输入操作备注..."
+ rows={3}
+ />
+ </div>
+ </Modal>
</>
);
};
--
Gitblit v1.8.0