| New file |
| | |
| | | /** |
| | | * PartyInfoCard 组件 - 申请双方信息 |
| | | * 展示申请人和被申请人信息,包含头像、姓名和情绪标签 |
| | | */ |
| | | |
| | | import React, { useState, useEffect, useCallback } from 'react'; |
| | | import { Tag } from 'antd'; |
| | | import { useCaseData } from '../../contexts/CaseDataContext'; |
| | | import MediationTimelineAPIService from '../../services/MediationTimelineAPIService'; |
| | | import './PartyInfoCard.css'; |
| | | |
| | | // 申请人头像图片 |
| | | const APPLICANT_AVATAR = '/in_person.png'; |
| | | // 被申请人头像图片 |
| | | const RESPONDENT_AVATAR = '/to_person.png'; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 根据per_type判断是申请方还是被申请方 |
| | | */ |
| | | const isApplicant = (perType) => { |
| | | return perType?.includes('15_020008-1') || perType?.toLowerCase().includes('applicant'); |
| | | }; |
| | | |
| | | /** |
| | | * 获取标签颜色样式 |
| | | */ |
| | | const getTagColor = (tagStyle) => { |
| | | const colorMap = { |
| | | red: 'red', |
| | | orange: 'orange', |
| | | yellow: 'gold', |
| | | green: 'green', |
| | | blue: 'blue', |
| | | warning: 'orange', |
| | | danger: 'red', |
| | | success: 'green', |
| | | primary: 'blue' |
| | | }; |
| | | return colorMap[tagStyle] || 'default'; |
| | | }; |
| | | |
| | | /** |
| | | * 当事人信息卡片 |
| | | */ |
| | | const PartyCard = ({ person, isApplicantSide }) => { |
| | | const avatarSrc = isApplicantSide ? APPLICANT_AVATAR : RESPONDENT_AVATAR; |
| | | |
| | | return ( |
| | | <div className={`party-card ${isApplicantSide ? 'applicant' : 'respondent'}`}> |
| | | {/* 标签 */} |
| | | {person.tag_name && ( |
| | | <Tag color={getTagColor(person.tag_style)} className="party-tag"> |
| | | {person.tag_name} |
| | | </Tag> |
| | | )} |
| | | |
| | | {/* 头像 */} |
| | | <img |
| | | src={avatarSrc} |
| | | alt={isApplicantSide ? '申请人' : '被申请人'} |
| | | className="party-avatar-img" |
| | | /> |
| | | |
| | | {/* 角色标签 */} |
| | | <span className="party-role"> |
| | | {isApplicantSide ? '申请人' : '被申请人'} |
| | | </span> |
| | | |
| | | {/* 姓名/公司名 */} |
| | | <span className="party-name">{person.true_name}</span> |
| | | </div> |
| | | ); |
| | | }; |
| | | |
| | | // VS分隔符图片 |
| | | const VS_ICON = '/join.png'; |
| | | |
| | | /** |
| | | * VS分隔符 |
| | | */ |
| | | const VSSeparator = () => ( |
| | | <div className="vs-separator"> |
| | | <div className="vs-line vs-line-left"></div> |
| | | <img src={VS_ICON} alt="VS" className="vs-icon-img" /> |
| | | <div className="vs-line vs-line-right"></div> |
| | | </div> |
| | | ); |
| | | |
| | | /** |
| | | * PartyInfoCard 主组件 |
| | | */ |
| | | const PartyInfoCard = () => { |
| | | const { caseData } = useCaseData(); |
| | | const [persons, setPersons] = useState([]); |
| | | const [loading, setLoading] = useState(false); |
| | | |
| | | const caseId = caseData?.caseId || caseData?.case_id; |
| | | |
| | | // 加载当事人数据 |
| | | const loadPersons = useCallback(async () => { |
| | | if (!caseId) return; |
| | | |
| | | setLoading(true); |
| | | try { |
| | | const response = await MediationTimelineAPIService.getPersonList(caseId); |
| | | setPersons(response.data || []); |
| | | } catch (err) { |
| | | console.error('加载当事人列表失败:', err); |
| | | setPersons([]); |
| | | } finally { |
| | | setLoading(false); |
| | | } |
| | | }, [caseId]); |
| | | |
| | | // 组件挂载时加载数据 |
| | | useEffect(() => { |
| | | loadPersons(); |
| | | }, [loadPersons]); |
| | | |
| | | // 分离申请方和被申请方 |
| | | const applicant = persons.find(p => isApplicant(p.per_type)); |
| | | const respondent = persons.find(p => !isApplicant(p.per_type)); |
| | | |
| | | if (loading || persons.length === 0) { |
| | | return null; |
| | | } |
| | | |
| | | return ( |
| | | <div className="party-info-card"> |
| | | <div className="party-info-title">申请双方</div> |
| | | <div className="party-info-content"> |
| | | {applicant && <PartyCard person={applicant} isApplicantSide={true} />} |
| | | <VSSeparator /> |
| | | {respondent && <PartyCard person={respondent} isApplicantSide={false} />} |
| | | </div> |
| | | </div> |
| | | ); |
| | | }; |
| | | |
| | | export default PartyInfoCard; |