From 88a31d5a960bd10f3799bc00f8aa24461567d06e Mon Sep 17 00:00:00 2001
From: shimai <shimai@example.com>
Date: Tue, 07 Apr 2026 15:23:43 +0800
Subject: [PATCH] Merge branch 'test/tony.cheng/260312' of http://120.79.193.119:9090/r/~chengmw/cloud-melody-front into test/shimai.huang/260309

---
 web-app/src/components/dashboard/PartyInfoCard.jsx |  142 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 142 insertions(+), 0 deletions(-)

diff --git a/web-app/src/components/dashboard/PartyInfoCard.jsx b/web-app/src/components/dashboard/PartyInfoCard.jsx
new file mode 100644
index 0000000..af4b002
--- /dev/null
+++ b/web-app/src/components/dashboard/PartyInfoCard.jsx
@@ -0,0 +1,142 @@
+/**
+ * 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;

--
Gitblit v1.8.0