| | |
| | | import React from 'react'; |
| | | import { useCaseData } from '../../contexts/CaseDataContext'; |
| | | import { mockTimelineData } from '../../mocks/timeline'; |
| | | |
| | | // 默认节点数据(从Mock获取) |
| | | const defaultNodes = mockTimelineData.data.nodes || []; |
| | | |
| | | /** |
| | | * AI调解进度组件 - 步骤条 |
| | | * 根据processNodes动态生成流程节点,通过nodeState判断状态 |
| | | */ |
| | | const MediationProgress = ({ currentStep = 1 }) => { |
| | | const steps = [ |
| | | { label: '意愿调查', key: 0 }, |
| | | { label: '材料核实', key: 1 }, |
| | | { label: '事实认定', key: 2 }, |
| | | { label: '达成协议', key: 3 }, |
| | | { label: '履约回访', key: 4 }, |
| | | ]; |
| | | const MediationProgress = () => { |
| | | const { processNodes } = useCaseData(); |
| | | |
| | | // 使用processNodes,如果为空则使用默认节点 |
| | | const nodes = (processNodes && processNodes.length > 0) ? processNodes : defaultNodes; |
| | | |
| | | console.log('MediationProgress - using nodes:', nodes); |
| | | |
| | | // 处理nodes为空的情况(理论上不会进入,因为已有默认值) |
| | | if (!nodes || nodes.length === 0) { |
| | | return ( |
| | | <div className="mediation-progress"> |
| | | <h3 className="section-title"> |
| | | <i className="fas fa-road"></i> AI调解进度 |
| | | </h3> |
| | | <div className="progress-steps"> |
| | | <p style={{ textAlign: 'center', color: '#999', padding: '20px' }}> |
| | | 暂无流程数据 |
| | | </p> |
| | | </div> |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | // 计算进度线宽度 |
| | | const progressWidth = `${(currentStep) * 20}%`; |
| | | // 按orderNo排序,兼容 orderNo 和 order_no 两种字段名 |
| | | const sortedNodes = [...nodes].sort((a, b) => { |
| | | const orderA = a.orderNo ?? a.order_no ?? 999; |
| | | const orderB = b.orderNo ?? b.order_no ?? 999; |
| | | return orderA - orderB; |
| | | }); |
| | | |
| | | const getStepClass = (stepKey) => { |
| | | if (stepKey < currentStep) return 'step completed'; |
| | | if (stepKey === currentStep) return 'step active'; |
| | | return 'step'; |
| | | // 转换为步骤数据格式,兼容 nodeName 和 node_name 两种字段名 |
| | | const steps = sortedNodes.map((node, index) => ({ |
| | | key: index, |
| | | label: node.nodeName || node.node_name || `步骤${index + 1}`, |
| | | nodeState: node.nodeState ?? -1 // 缺失时默认为-1(未激活) |
| | | })); |
| | | |
| | | // 计算已完成节点数量(nodeState === 2) |
| | | const completedCount = steps.filter(step => step.nodeState === 2).length; |
| | | |
| | | // 计算进度线宽度(根据已完成节点数量) |
| | | const totalSteps = steps.length; |
| | | const progressWidth = totalSteps > 0 ? `${(completedCount / totalSteps) * 100}%` : '0%'; |
| | | |
| | | // 根据nodeState判断步骤类名 |
| | | const getStepClass = (nodeState) => { |
| | | if (nodeState === 2) return 'step completed'; // 已完成 |
| | | if (nodeState === 1) return 'step active'; // 激活/进行中 |
| | | return 'step'; // 默认未激活 |
| | | }; |
| | | |
| | | const renderStepIndicator = (stepKey) => { |
| | | if (stepKey < currentStep) { |
| | | return <i className="fas fa-check"></i>; |
| | | // 根据nodeState渲染步骤指示器 |
| | | const renderStepIndicator = (nodeState, stepKey) => { |
| | | if (nodeState === 2) { |
| | | return <i className="fas fa-check"></i>; // 完成显示勾 |
| | | } |
| | | return stepKey + 1; |
| | | return stepKey + 1; // 激活/未激活显示数字 |
| | | }; |
| | | |
| | | return ( |
| | |
| | | <div className="progress-steps"> |
| | | <div className="progress-line" style={{ width: progressWidth }}></div> |
| | | {steps.map((step) => ( |
| | | <div key={step.key} className={getStepClass(step.key)}> |
| | | <div className="step-indicator">{renderStepIndicator(step.key)}</div> |
| | | <div key={step.key} className={getStepClass(step.nodeState)}> |
| | | <div className="step-indicator">{renderStepIndicator(step.nodeState, step.key)}</div> |
| | | <div className="step-label">{step.label}</div> |
| | | </div> |
| | | ))} |