From 85f3f863950fa1d807697da437591062868e782c Mon Sep 17 00:00:00 2001
From: chengmw <chengmingwei_1984122@126.com>
Date: Thu, 26 Mar 2026 17:27:54 +0800
Subject: [PATCH] feat: 添加通话记录查看器功能模块
---
web-app/src/components/dashboard/TabContainer.jsx | 93 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 81 insertions(+), 12 deletions(-)
diff --git a/web-app/src/components/dashboard/TabContainer.jsx b/web-app/src/components/dashboard/TabContainer.jsx
index e732c80..ca215e3 100644
--- a/web-app/src/components/dashboard/TabContainer.jsx
+++ b/web-app/src/components/dashboard/TabContainer.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
+import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { useCaseData } from '../../contexts/CaseDataContext';
import { formatDuration, formatSuccessRate, formatRoundCount } from '../../utils/stateTranslator';
import ProcessAPIService from '../../services/ProcessAPIService';
@@ -6,6 +6,8 @@
import MediationAgreementAPIService from '../../services/MediationAgreementAPIService';
import { getMergedParams } from '../../utils/urlParams';
import { message, Spin, Tag, Modal, Button, Input, Image } from 'antd';
+import { PhoneOutlined } from '@ant-design/icons';
+import { CallRecordModal } from '../call-record';
const { TextArea } = Input;
@@ -153,18 +155,36 @@
const [records, setRecords] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
+ // 通话记录弹窗状态
+ const [callRecordVisible, setCallRecordVisible] = useState(false);
+ const [currentRecord, setCurrentRecord] = useState(null);
// 获取案件数据
const { caseData } = useCaseData();
const timeline = caseData || {};
const caseState = timeline.mediation?.state;
-
+
+
+ // 格式化时间戳为 YYYY-MM-DD HH:MM:SS
+ const formatTimestamp = (timestamp) => {
+ if (!timestamp) return '';
+ const date = new Date(timestamp);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ const hours = String(date.getHours()).padStart(2, '0');
+ const minutes = String(date.getMinutes()).padStart(2, '0');
+ const seconds = String(date.getSeconds()).padStart(2, '0');
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+ };
+
// person_type到avatar类型的映射
+ // 1: 申请人, 2: 被申请人, 3: AI调解员, 4: 调解员
const getAvatarType = (personType) => {
const typeMap = {
- '1': 'ai',
- '2': 'applicant',
- '3': 'respondent',
+ '1': 'applicant',
+ '2': 'respondent',
+ '3': 'ai',
'4': 'mediator'
};
return typeMap[personType] || 'ai';
@@ -182,23 +202,25 @@
};
// 获取角色显示名称
+ // 1: 申请人, 2: 被申请人, 3: AI调解员, 4: 调解员
const getRoleDisplayName = (personType, creatorName) => {
const roleMap = {
- '1': 'AI调解员',
- '2': `申请人(${creatorName})`,
- '3': `被申请人(${creatorName})`,
+ '1': `申请人(${creatorName})`,
+ '2': `被申请人(${creatorName})`,
+ '3': 'AI调解员',
'4': `调解员(${creatorName})`
};
return roleMap[personType] || creatorName;
};
- // 数据格式化函数
+ // 数据格式化函数(保留原始数据字段用于通话记录功能)
const formatRecordData = (apiRecords) => {
return apiRecords.map(record => ({
+ ...record, // 保留原始数据字段(person_id, job_id, creator等)
avatar: getAvatarType(record.person_type),
name: getRoleDisplayName(record.person_type, record.creator),
- avatarText: record.creator?.charAt(0) || '', // 头像显示名字第一个字
- time: record.create_time,
+ avatarText: record.creator?.charAt(0) || '',
+ time: formatTimestamp(record.create_time),
content: record.result,
tags: record.tagList?.map(tag => ({
text: tag.tag_name,
@@ -394,7 +416,40 @@
{getAvatarContent(item.avatar, item.avatarText)}
</div>
<div className="item-source">
- <div style={{ fontWeight: 600, fontSize: '0.95rem', color: 'var(--dark-color)', marginBottom: 2 }}>{item.name}</div>
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 2 }}>
+ <span style={{ fontWeight: 600, fontSize: '0.95rem', color: 'var(--dark-color)' }}>{item.name}</span>
+ {item.avatar !== 'ai' && item.avatar !== 'mediator' && (
+ <span
+ className="call-record-btn"
+ style={{
+ display: 'inline-flex',
+ alignItems: 'center',
+ gap: 4,
+ padding: '2px 8px',
+ fontSize: '0.75rem',
+ background: '#e3f2fd',
+ color: '#1890ff',
+ borderRadius: 12,
+ cursor: 'pointer',
+ transition: 'all 0.2s'
+ }}
+ onClick={(e) => {
+ e.stopPropagation();
+ setCurrentRecord(item);
+ setCallRecordVisible(true);
+ }}
+ onMouseEnter={(e) => {
+ e.target.style.background = '#bbdefb';
+ }}
+ onMouseLeave={(e) => {
+ e.target.style.background = '#e3f2fd';
+ }}
+ >
+ <PhoneOutlined style={{ fontSize: 12 }} />
+ 通话记录
+ </span>
+ )}
+ </div>
<div style={{ fontSize: '0.8rem', color: 'var(--gray-color)', display: 'flex', alignItems: 'center', gap: 6 }}>
<i className="far fa-clock"></i>
<span>{item.time}</span>
@@ -440,6 +495,13 @@
</div>
))}
</div>
+
+ {/* 通话记录弹窗 */}
+ <CallRecordModal
+ visible={callRecordVisible}
+ onClose={() => setCallRecordVisible(false)}
+ record={currentRecord}
+ />
</>
);
};
@@ -1659,3 +1721,10 @@
};
export default TabContainer;
+
+
+
+
+
+
+
--
Gitblit v1.8.0