From 6b14010e1765842acc437ab130e5815bc623788d Mon Sep 17 00:00:00 2001
From: chengmw <chengmingwei_1984122@126.com>
Date: Thu, 02 Apr 2026 14:59:59 +0800
Subject: [PATCH] feat: 优化警告提示和调解流程 UI,新增 AI 背景和图片资源

---
 web-app/src/components/dashboard/PartyInfoCard.jsx       |   25 +++--
 web-app/src/components/common/WarningAlert.css           |   14 ++
 web-app/public/to_person.png                             |    0 
 web-app/src/components/dashboard/AISuggestionCard.css    |   39 +++++++--
 web-app/public/ai-bg.png                                 |    0 
 web-app/public/warning.png                               |    0 
 web-app/src/components/dashboard/AISuggestionCard.jsx    |    3 
 web-app/src/components/dashboard/NegotiationProgress.css |   20 +++--
 web-app/public/join.png                                  |    0 
 web-app/src/components/common/WarningAlert.jsx           |    9 +
 web-app/public/mom.png                                   |    0 
 web-app/public/in_person.png                             |    0 
 web-app/src/components/dashboard/PartyInfoCard.css       |   26 ++++--
 web-app/src/components/dashboard/TabContainer.jsx        |   22 ++++-
 web-app/src/App.css                                      |   47 +++++++++--
 15 files changed, 147 insertions(+), 58 deletions(-)

diff --git a/web-app/public/ai-bg.png b/web-app/public/ai-bg.png
new file mode 100644
index 0000000..d46f006
--- /dev/null
+++ b/web-app/public/ai-bg.png
Binary files differ
diff --git a/web-app/public/in_person.png b/web-app/public/in_person.png
new file mode 100644
index 0000000..45aac2c
--- /dev/null
+++ b/web-app/public/in_person.png
Binary files differ
diff --git a/web-app/public/join.png b/web-app/public/join.png
new file mode 100644
index 0000000..37a56fb
--- /dev/null
+++ b/web-app/public/join.png
Binary files differ
diff --git a/web-app/public/mom.png b/web-app/public/mom.png
new file mode 100644
index 0000000..f0eda19
--- /dev/null
+++ b/web-app/public/mom.png
Binary files differ
diff --git a/web-app/public/to_person.png b/web-app/public/to_person.png
new file mode 100644
index 0000000..ebd83f1
--- /dev/null
+++ b/web-app/public/to_person.png
Binary files differ
diff --git a/web-app/public/warning.png b/web-app/public/warning.png
new file mode 100644
index 0000000..74daa3a
--- /dev/null
+++ b/web-app/public/warning.png
Binary files differ
diff --git a/web-app/src/App.css b/web-app/src/App.css
index 2afd4ed..59fba74 100644
--- a/web-app/src/App.css
+++ b/web-app/src/App.css
@@ -720,8 +720,8 @@
   background: #f8f9fa;
   border-radius: 8px;
   padding: 14px 16px;
-  margin-bottom: 16px;
-  text-align: center;
+  margin-bottom: 10px;
+  text-align: left;
 }
 
 .success-rate-label {
@@ -730,25 +730,30 @@
   margin-bottom: 8px;
 }
 
+.success-rate-row {
+  display: flex;
+  align-items: baseline;
+  gap: 10px;
+  margin-bottom: 10px;
+}
+
 .success-rate-value {
   font-size: 2.2rem;
   font-weight: 700;
   color: #1a6fb8;
   line-height: 1;
-  margin-bottom: 8px;
 }
 
 .success-rate-yoy {
   display: flex;
   align-items: center;
-  justify-content: center;
-  gap: 6px;
+  gap: 4px;
   font-size: 0.8rem;
 }
 
-.yoy-icon {
-  color: #52c41a;
-  font-size: 0.75rem;
+.yoy-icon-img {
+  width: 12px;
+  height: 7px;
 }
 
 .yoy-rate {
@@ -757,7 +762,27 @@
 }
 
 .yoy-time {
-  color: #999;
+  color: #52c41a;
+}
+
+/* 进度条 */
+.success-rate-progress {
+  width: 100%;
+}
+
+.progress-bar-bg {
+  width: 100%;
+  height: 6px;
+  background: #e8e8e8;
+  border-radius: 3px;
+  overflow: hidden;
+}
+
+.progress-bar-fill {
+  height: 100%;
+  background: #1a6fb8;
+  border-radius: 3px;
+  transition: width 0.3s ease;
 }
 
 /* 调解数据看板 - 左右分栏布局 */
@@ -771,10 +796,10 @@
   flex-direction: column;
   padding: 0;
   background: transparent;
-  gap: 0;
+  gap: 0px;
 }
 
-.metric-card.right-column > * {
+.metric-card.right-column > *:last-child {
   margin-bottom: 0;
 }
 
diff --git a/web-app/src/components/common/WarningAlert.css b/web-app/src/components/common/WarningAlert.css
index 2308984..ec36c75 100644
--- a/web-app/src/components/common/WarningAlert.css
+++ b/web-app/src/components/common/WarningAlert.css
@@ -23,10 +23,18 @@
   min-width: 0;
 }
 
-.warning-icon {
-  color: #faad14;
-  font-size: 1rem;
+.warning-icon-img {
+  width: 16px;
+  height: 16px;
   flex-shrink: 0;
+  margin-right: 6px;
+}
+
+.warning-modal-icon {
+  width: 16px;
+  height: 16px;
+  margin-right: 8px;
+  vertical-align: middle;
 }
 
 .warning-label {
diff --git a/web-app/src/components/common/WarningAlert.jsx b/web-app/src/components/common/WarningAlert.jsx
index 42acb4b..656f7b1 100644
--- a/web-app/src/components/common/WarningAlert.jsx
+++ b/web-app/src/components/common/WarningAlert.jsx
@@ -5,17 +5,20 @@
 
 import React, { useState, useEffect, useCallback } from 'react';
 import { Modal, List } from 'antd';
-import { WarningOutlined, RightOutlined } from '@ant-design/icons';
+import { RightOutlined } from '@ant-design/icons';
 import { useCaseData } from '../../contexts/CaseDataContext';
 import MediationTimelineAPIService from '../../services/MediationTimelineAPIService';
 import './WarningAlert.css';
+
+// 警告图标图片
+const WARNING_ICON = '/warning.png';
 
 /**
  * 预警消息列表弹窗
  */
 const WarningModal = ({ visible, warnings, onClose }) => (
   <Modal
-    title={<span><WarningOutlined style={{ color: '#faad14', marginRight: 8 }} />预警消息列表</span>}
+    title={<span><img src={WARNING_ICON} alt="warning" className="warning-modal-icon" />预警消息列表</span>}
     open={visible}
     onCancel={onClose}
     footer={null}
@@ -90,7 +93,7 @@
   return (
     <div className="warning-alert">
       <div className="warning-alert-content">
-        <WarningOutlined className="warning-icon" />
+        <img src={WARNING_ICON} alt="warning" className="warning-icon-img" />
         <span className="warning-label">预警:</span>
         <span className="warning-text">{firstWarning.content}</span>
       </div>
diff --git a/web-app/src/components/dashboard/AISuggestionCard.css b/web-app/src/components/dashboard/AISuggestionCard.css
index 01b6a3b..6137f5b 100644
--- a/web-app/src/components/dashboard/AISuggestionCard.css
+++ b/web-app/src/components/dashboard/AISuggestionCard.css
@@ -4,11 +4,23 @@
  */
 
 .ai-suggestion-card {
-  background: linear-gradient(135deg, #e6f4ff, #f0f7ff);
-  border-radius: 8px;
+  background: #1a6fb8;
+  border-radius: 12px;
   padding: 14px 16px;
   margin-top: 12px;
-  border-left: 4px solid #1a6fb8;
+  box-shadow: 0px 4px 6px -4px rgba(0,0,0,0.10), 0px 10px 15px -3px rgba(0,0,0,0.10);
+  position: relative;
+  overflow: hidden;
+}
+
+.ai-suggestion-bg {
+  position: absolute;
+  top: 15px;
+  right: 15px;
+  width: 48px;
+  height: 50px;
+  opacity: 0.1;
+  pointer-events: none;
 }
 
 .ai-suggestion-header {
@@ -20,19 +32,19 @@
 
 .ai-suggestion-icon {
   font-size: 1rem;
-  color: #1a6fb8;
+  color: #fff;
 }
 
 .ai-suggestion-title {
   font-size: 0.9rem;
   font-weight: 600;
-  color: #0d4a8a;
+  color: #fff;
 }
 
 .ai-suggestion-content {
   font-size: 0.85rem;
   line-height: 1.6;
-  color: #333;
+  color: #fff;
   max-height: 80px;
   overflow: hidden;
   text-overflow: ellipsis;
@@ -47,11 +59,22 @@
 }
 
 .ai-suggestion-btn {
-  padding: 0;
+  padding: 8px 24px;
   font-size: 0.85rem;
-  color: #1a6fb8;
+  color: #FFFFFF;
+  background: rgba(255, 255, 255, 0.9);
+  border-radius: 20px;
+  border: none;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+  height: auto;
+  line-height: 1.5;
+  margin: 10px;
+  width: 90%;
+  background: rgba(255, 255, 255, 0.20);
+  border-radius: 8px;
 }
 
 .ai-suggestion-btn:hover {
   color: #0d4a8a;
+  background: rgba(255, 255, 255, 1);
 }
diff --git a/web-app/src/components/dashboard/AISuggestionCard.jsx b/web-app/src/components/dashboard/AISuggestionCard.jsx
index 4663f36..f326727 100644
--- a/web-app/src/components/dashboard/AISuggestionCard.jsx
+++ b/web-app/src/components/dashboard/AISuggestionCard.jsx
@@ -22,6 +22,9 @@
 
   return (
     <div className="ai-suggestion-card">
+      {/* 背景图标 */}
+      <img src="/ai-bg.png" alt="" className="ai-suggestion-bg" />
+      
       {/* 标题 */}
       <div className="ai-suggestion-header">
         <BulbOutlined className="ai-suggestion-icon" />
diff --git a/web-app/src/components/dashboard/NegotiationProgress.css b/web-app/src/components/dashboard/NegotiationProgress.css
index d2d6c83..111229b 100644
--- a/web-app/src/components/dashboard/NegotiationProgress.css
+++ b/web-app/src/components/dashboard/NegotiationProgress.css
@@ -7,7 +7,6 @@
   background: #f8f9fa;
   border-radius: 8px;
   padding: 12px 16px;
-  border-top: 3px solid #1a6fb8;
 }
 
 .negotiation-header {
@@ -40,21 +39,26 @@
 .progress-dot-wrapper {
   display: flex;
   align-items: center;
-  flex: 1;
+  justify-content: flex-start;
 }
 
 .progress-dot-wrapper.last {
   flex: 0;
 }
 
-/* 进度点 */
+/* 进度短横线 */
 .progress-dot {
-  width: 10px;
-  height: 10px;
-  border-radius: 50%;
+  width: 16px;
+  height: 4px;
+  border-radius: 2px;
   background: #d9d9d9;
   flex-shrink: 0;
   transition: background 0.3s;
+  margin-left: 5px;
+}
+
+.progress-dot-wrapper:first-child .progress-dot {
+  margin-left: 0;
 }
 
 .progress-dot.active {
@@ -64,9 +68,9 @@
 /* 连接线 */
 .progress-line {
   flex: 1;
-  height: 3px;
+  height: 2px;
   background: #d9d9d9;
-  margin: 0 2px;
+  margin: 0 4px;
   transition: background 0.3s;
 }
 
diff --git a/web-app/src/components/dashboard/PartyInfoCard.css b/web-app/src/components/dashboard/PartyInfoCard.css
index 0a34ebe..b6538c4 100644
--- a/web-app/src/components/dashboard/PartyInfoCard.css
+++ b/web-app/src/components/dashboard/PartyInfoCard.css
@@ -7,7 +7,7 @@
   background: #f8f9fa;
   border-radius: 8px;
   padding: 12px 16px;
-  margin-bottom: 16px;
+  margin-bottom: 10px;
 }
 
 .party-info-title {
@@ -34,21 +34,28 @@
   padding: 8px;
 }
 
-/* 情绪标签 */
+/* 情绪标签 - 实心红背景白字 */
 .party-tag {
   position: absolute;
   top: -4px;
   left: 50%;
   transform: translateX(-50%);
   font-size: 0.7rem;
-  padding: 0 6px;
-  line-height: 18px;
-  border-radius: 4px;
+  padding: 2px 8px;
+  line-height: 16px;
+  border-radius: 10px;
+  background-color: #ff4d4f !important;
+  color: white !important;
+  border: none !important;
 }
 
-.party-avatar {
+.party-avatar-img {
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
   margin-top: 12px;
   margin-bottom: 8px;
+  object-fit: cover;
 }
 
 .party-role {
@@ -76,7 +83,8 @@
   padding: 0 8px;
 }
 
-.vs-icon {
-  font-size: 1.5rem;
-  color: #d9d9d9;
+.vs-icon-img {
+  width: 24px;
+  height: 24px;
+  object-fit: contain;
 }
diff --git a/web-app/src/components/dashboard/PartyInfoCard.jsx b/web-app/src/components/dashboard/PartyInfoCard.jsx
index c04a606..f33980d 100644
--- a/web-app/src/components/dashboard/PartyInfoCard.jsx
+++ b/web-app/src/components/dashboard/PartyInfoCard.jsx
@@ -4,11 +4,15 @@
  */
 
 import React, { useState, useEffect, useCallback } from 'react';
-import { Avatar, Tag } from 'antd';
-import { UserOutlined, TeamOutlined } from '@ant-design/icons';
+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';
 
 
 
@@ -41,8 +45,7 @@
  * 当事人信息卡片
  */
 const PartyCard = ({ person, isApplicantSide }) => {
-  const avatarIcon = isApplicantSide ? <UserOutlined /> : <TeamOutlined />;
-  const avatarBg = isApplicantSide ? '#1a6fb8' : '#faad14';
+  const avatarSrc = isApplicantSide ? APPLICANT_AVATAR : RESPONDENT_AVATAR;
 
   return (
     <div className={`party-card ${isApplicantSide ? 'applicant' : 'respondent'}`}>
@@ -54,11 +57,10 @@
       )}
       
       {/* 头像 */}
-      <Avatar 
-        size={48}
-        icon={avatarIcon}
-        style={{ backgroundColor: avatarBg }}
-        className="party-avatar"
+      <img 
+        src={avatarSrc}
+        alt={isApplicantSide ? '申请人' : '被申请人'}
+        className="party-avatar-img"
       />
       
       {/* 角色标签 */}
@@ -72,12 +74,15 @@
   );
 };
 
+// VS分隔符图片
+const VS_ICON = '/join.png';
+
 /**
  * VS分隔符
  */
 const VSSeparator = () => (
   <div className="vs-separator">
-    <span className="vs-icon">⚖</span>
+    <img src={VS_ICON} alt="VS" className="vs-icon-img" />
   </div>
 );
 
diff --git a/web-app/src/components/dashboard/TabContainer.jsx b/web-app/src/components/dashboard/TabContainer.jsx
index 4e8c3a6..e390898 100644
--- a/web-app/src/components/dashboard/TabContainer.jsx
+++ b/web-app/src/components/dashboard/TabContainer.jsx
@@ -6,7 +6,7 @@
 import MediationAgreementAPIService from '../../services/MediationAgreementAPIService';
 import { getMergedParams } from '../../utils/urlParams';
 import { message, Spin, Tag, Modal, Button, Input, Image } from 'antd';
-import { PhoneOutlined, ArrowUpOutlined } from '@ant-design/icons';
+import { PhoneOutlined } from '@ant-design/icons';
 import { CallRecordModal } from '../call-record';
 
 // 新增组件导入
@@ -129,6 +129,9 @@
   const updateTime = formatDuration(timeline.before_duration);
   const successRate = formatSuccessRate(mediation.success_rate);
   
+  // 获取成功率数值(用于进度条)
+  const successRateValue = (mediation.success_rate || 0) * 100;
+  
   // 获取同比数据
   const yoyData = getSuccessRateYoY(mediation);
   const yoyRate = yoyData.rate >= 0 ? `+${yoyData.rate.toFixed(0)}%` : `${yoyData.rate.toFixed(0)}%`;
@@ -166,11 +169,18 @@
         {/* 预计调解成功率 */}
         <div className="success-rate-section">
           <div className="success-rate-label">预计调解成功率</div>
-          <div className="success-rate-value">{successRate}</div>
-          <div className="success-rate-yoy">
-            <ArrowUpOutlined className="yoy-icon" />
-            <span className="yoy-rate">{yoyRate}</span>
-            <span className="yoy-time">较{yoyHours}小时前</span>
+          <div className="success-rate-row">
+            <span className="success-rate-value">{successRate}</span>
+            <div className="success-rate-yoy">
+              <img src="/mom.png" alt="" className="yoy-icon-img" />
+              <span className="yoy-rate">{yoyRate}</span>
+              <span className="yoy-time">较{yoyHours}小时前</span>
+            </div>
+          </div>
+          <div className="success-rate-progress">
+            <div className="progress-bar-bg">
+              <div className="progress-bar-fill" style={{ width: `${successRateValue}%` }}></div>
+            </div>
           </div>
         </div>
         

--
Gitblit v1.8.0