| document/原型/index.html | ●●●●● patch | view | raw | blame | history | |
| web-app/src/components/dashboard/FloatingControlPanel.jsx | ●●●●● patch | view | raw | blame | history | |
| web-app/src/components/dashboard/TabContainer.jsx | ●●●●● patch | view | raw | blame | history |
document/原型/index.html
@@ -1997,6 +1997,10 @@ <i class="fas fa-user-tie"></i> 人工接管 </button> <button class="floating-control-btn" id="floatingStopBtn"> <i class="fas fa-user-tie"></i> 人工接管 </button> </div> </div> web-app/src/components/dashboard/FloatingControlPanel.jsx
@@ -1,14 +1,17 @@ import React, { useState } from 'react'; import { Modal, message } from 'antd'; import { Modal, message, Input } from 'antd'; import { useCaseData } from '../../contexts/CaseDataContext'; import { translateMediationState } from '../../utils/stateTranslator'; import { useTaskTimer } from '../../hooks/useTaskTimer'; import ProcessAPIService from '../../services/ProcessAPIService'; import { getMergedParams } from '../../utils/urlParams'; const { TextArea } = Input; // 终态状态(不显示人工接管按钮) const TERMINAL_STATES = [2, 3]; // 调解成功、调解失败 const TAKEOVER_STATE = 4; // 人工接管 const PAUSED_STATE = 5; // 已终止/暂停状态 /** * 获取案件ID @@ -90,6 +93,12 @@ const [takeoverLoading, setTakeoverLoading] = useState(false); const [confirmVisible, setConfirmVisible] = useState(false); // 状态控制相关状态 const [controlLoading, setControlLoading] = useState(false); const [controlConfirmVisible, setControlConfirmVisible] = useState(false); const [controlAction, setControlAction] = useState(null); // 'terminate' or 'resume' const [remark, setRemark] = useState(''); const timeline = caseData || {}; const state = timeline.mediation?.state; const nodeName = timeline.current_node?.node_name || ''; @@ -101,6 +110,98 @@ const statusText = state === 1 ? `调解进行中-阶段${orderNo}:${nodeName}` : (translateMediationState(state) || '调解进行中'); // ==================== 状态控制按钮逻辑 ==================== /** * 判断是否显示状态控制按钮 * 状态为0(未开始)、1(进行中)、5(已终止)时显示 */ const shouldShowControlButton = () => { const stateNum = Number(state); // 进行中(1)显示终止按钮,已终止(5)显示恢复按钮 return stateNum === 1 || stateNum === 5; }; /** * 获取状态控制按钮属性 */ const getControlButtonProps = () => { const stateNum = Number(state); if (stateNum === 1) { return { text: '终止', style: 'terminate', action: 'terminate' }; } else if (stateNum === 5) { return { text: '恢复', style: 'resume', action: 'resume' }; } return null; }; /** * 处理状态控制按钮点击 */ const handleControlButtonClick = () => { const buttonProps = getControlButtonProps(); if (!buttonProps) return; setControlAction(buttonProps.action); setControlConfirmVisible(true); }; /** * 处理状态控制确认 */ const handleControlConfirmOk = async () => { if (!controlAction) return; setControlLoading(true); try { const params = getMergedParams(); const actionCode = controlAction === 'terminate' ? 0 : 1; if (!params.caseId) { throw new Error('案件ID不能为空'); } await ProcessAPIService.updateMediationState(params.caseId, { action: actionCode, userName: localStorage.getItem('userName') || '调解员', remark: remark || '' }); message.success(controlAction === 'terminate' ? '调解已终止' : '调解已恢复'); setControlConfirmVisible(false); setRemark(''); setControlAction(null); refreshData(); } catch (error) { console.error('状态更新失败:', error); message.error(error.message || '状态更新失败,请稍后重试'); } finally { setControlLoading(false); } }; /** * 处理状态控制取消 */ const handleControlConfirmCancel = () => { setControlConfirmVisible(false); setRemark(''); setControlAction(null); }; // ==================== 人工接管逻辑 ==================== /** * 处理接管API调用 @@ -178,6 +279,40 @@ }; /** * 渲染状态控制按钮(终止/恢复) */ const renderStateControlButton = () => { if (!shouldShowControlButton()) return null; const buttonProps = getControlButtonProps(); if (!buttonProps) return null; const isTerminate = buttonProps.style === 'terminate'; return ( <button className="floating-control-btn" onClick={handleControlButtonClick} disabled={controlLoading} style={{ ...(isTerminate ? { background: '#1A6FB8', } : { background: '#52c41a', }), ...(controlLoading ? { opacity: 0.6, cursor: 'not-allowed' } : {}) }} > {controlLoading ? ( <><i className="fas fa-spinner fa-spin"></i>处理中...</> ) : ( <><i className={isTerminate ? "fas fa-pause-circle" : "fas fa-play-circle"}></i>{buttonProps.text}</> )} </button> ); }; /** * 渲染控制区域(按钮或印章) */ const renderControlAction = () => { @@ -186,8 +321,18 @@ return <TakeoverStamp state={state} />; } // 调解中:显示接管按钮 return <TakeoverButton loading={takeoverLoading} onClick={handleTakeover} />; // 已终止状态(5):只显示恢复按钮 if (Number(state) === PAUSED_STATE) { return renderStateControlButton(); } // 调解中(1):显示终止按钮和人工接管按钮 return ( <> {renderStateControlButton()} <TakeoverButton loading={takeoverLoading} onClick={handleTakeover} /> </> ); }; return ( @@ -211,6 +356,34 @@ </div> </div> {/* 状态控制确认对话框(终止/恢复) */} <Modal title={controlAction === 'terminate' ? '确认终止调解' : '确认恢复调解'} visible={controlConfirmVisible} onOk={handleControlConfirmOk} onCancel={handleControlConfirmCancel} okText="确定" cancelText="取消" confirmLoading={controlLoading} > <p> {controlAction === 'terminate' ? '确定要终止当前AI调解流程吗?终止后调解将暂停,可在适当时机恢复。' : '确定要恢复AI调解流程吗?恢复后将从当前位置继续调解。'} </p> <div style={{ marginTop: 15 }}> <label style={{ display: 'block', marginBottom: 5, fontWeight: 500 }}> 备注(可选): </label> <TextArea value={remark} onChange={(e) => setRemark(e.target.value)} placeholder="请输入操作备注..." rows={3} /> </div> </Modal> {/* 人工接管确认对话框 */} <Modal title="人工接管确认" web-app/src/components/dashboard/TabContainer.jsx
@@ -154,26 +154,10 @@ 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, refreshData } = useCaseData(); const { caseData } = useCaseData(); const timeline = caseData || {}; const caseState = timeline.mediation?.state; // 调试日志:输出关键数据 useEffect(() => { console.log('===== MediationBoard 数据状态 ====='); console.log('caseData:', caseData); console.log('timeline:', timeline); console.log('caseState:', caseState); console.log('mediation:', timeline.mediation); console.log('================================'); }, [caseData, caseState, timeline]); // person_type到avatar类型的映射 const getAvatarType = (personType) => { @@ -362,114 +346,6 @@ return avatarText || (avatar === 'applicant' ? '申' : avatar === 'respondent' ? '被' : '调'); }; // 状态控制按钮显示逻辑 const shouldShowControlButton = () => { // 转换为数字类型进行比较,兼容字符串和数字 const stateNum = Number(caseState); const show = stateNum === 0 || stateNum === 1 || stateNum === 5; console.log('状态控制按钮显示检查:', { caseState, caseStateType: typeof caseState, stateNum, show, conditions: { 'stateNum === 0': stateNum === 0, 'stateNum === 1': stateNum === 1, 'stateNum === 5': stateNum === 5 } }); return show; }; const getControlButtonProps = () => { // 转换为数字类型进行比较 const stateNum = Number(caseState); console.log('获取按钮属性:', { caseState, caseStateType: typeof caseState, stateNum }); if (stateNum === 0 || stateNum === 1) { return { text: '终止', style: 'terminate', action: 'terminate' }; } else if (stateNum === 5) { return { text: '恢复', style: 'resume', action: 'resume' }; } console.log('未匹配到按钮属性,返回null'); return null; }; // 处理状态控制按钮点击 const handleControlButtonClick = (action) => { console.log('状态控制按钮点击:', { action }); setControlAction(action); setConfirmModalVisible(true); }; // 处理确认对话框确认 const handleConfirmOk = async () => { 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') || '调解员', remark: remark || '' }); message.success('案件状态更新成功'); setConfirmModalVisible(false); setRemark(''); setControlAction(null); // 刷新数据 refreshData(); } catch (error) { console.error('状态更新失败:', error); const errorMessage = error.message || '状态更新失败,请稍后重试'; message.error(errorMessage); // 如果是网络错误,提供更多帮助信息 if (errorMessage.includes('网络') || errorMessage.includes('Network')) { message.info('请检查网络连接或联系管理员'); } } finally { setControlLoading(false); } }; // 处理确认对话框取消 const handleConfirmCancel = () => { setConfirmModalVisible(false); setControlAction(null); setRemark(''); }; return ( <> <div className="mediation-summary" style={{ @@ -564,81 +440,6 @@ </div> ))} </div> {/* 状态控制按钮区域 */} {shouldShowControlButton() && (() => { const buttonProps = getControlButtonProps(); if (!buttonProps) return null; return ( <div style={{ marginTop: 20, paddingTop: 15, borderTop: '1px solid #e9ecef', display: 'flex', justifyContent: 'center', gap: 12 }}> <button onClick={() => handleControlButtonClick(buttonProps.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', ...(buttonProps.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>{buttonProps.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> </> ); };