存
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 64px;
|
min-height: 64px;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
.headerLeft {
|
.headerLeft {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export interface PowerNavigationProps {
|
|||||||
onBackClick?: () => void;
|
onBackClick?: () => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
rightContent?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PowerNavigation: React.FC<PowerNavigationProps> = ({
|
const PowerNavigation: React.FC<PowerNavigationProps> = ({
|
||||||
@@ -23,6 +24,7 @@ const PowerNavigation: React.FC<PowerNavigationProps> = ({
|
|||||||
onBackClick,
|
onBackClick,
|
||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
|
rightContent,
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -57,6 +59,7 @@ const PowerNavigation: React.FC<PowerNavigationProps> = ({
|
|||||||
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
{subtitle && <span className={styles.subtitle}>{subtitle}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={styles.headerRight}>{rightContent}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,39 +5,289 @@
|
|||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
// 导出按钮样式
|
||||||
margin-bottom: 24px;
|
.exportButton {
|
||||||
|
height: 36px;
|
||||||
h1 {
|
border-radius: 6px;
|
||||||
font-size: 24px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
color: #262626;
|
|
||||||
margin: 0 0 8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #8c8c8c;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
// 顶部搜索和筛选区域
|
||||||
|
.headerSection {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding: 16px 0;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterButtons {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.ant-btn {
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导航栏样式
|
||||||
|
.navigationTabs {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
.ant-tabs-nav {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-tabs-tab {
|
||||||
|
padding: 12px 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-tabs-tab-active {
|
||||||
|
color: #1890ff;
|
||||||
|
|
||||||
|
.ant-tabs-tab-btn {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-tabs-ink-bar {
|
||||||
|
background: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录列表样式
|
||||||
|
.recordsList {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recordCard {
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
border-color: #d9d9d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-body {
|
||||||
|
padding: 16px 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardContent {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardLeft {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recordInfo {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nameAndType {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #262626;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.statusAndTime {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.dateTime {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.directionAndSubject {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.subject {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #262626;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #595959;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
font-size: 11px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
color: #8c8c8c;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 1px 6px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachments {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
margin-top: 6px;
|
||||||
|
|
||||||
|
.attachmentsLabel {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
background: #fafafa;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
.attachmentIcon {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachmentName {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #262626;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.downloadIcon {
|
||||||
|
color: #8c8c8c;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardRight {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 300px;
|
width: 28px;
|
||||||
background: #fafafa;
|
height: 28px;
|
||||||
border: 1px dashed #d9d9d9;
|
|
||||||
border-radius: 6px;
|
.viewIcon {
|
||||||
|
font-size: 14px;
|
||||||
p {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #8c8c8c;
|
color: #8c8c8c;
|
||||||
margin: 0;
|
cursor: pointer;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.headerSection {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterButtons {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardContent {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardRight {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,323 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
|
import { Input, Button, Tabs, Tag, Avatar, Card } from "antd";
|
||||||
|
import {
|
||||||
|
SearchOutlined,
|
||||||
|
FilterOutlined,
|
||||||
|
CalendarOutlined,
|
||||||
|
MessageOutlined,
|
||||||
|
PhoneOutlined,
|
||||||
|
VideoCameraOutlined,
|
||||||
|
MailOutlined,
|
||||||
|
EyeOutlined,
|
||||||
|
DownloadOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
import PowerNavigation from "@/components/PowerNavtion";
|
import PowerNavigation from "@/components/PowerNavtion";
|
||||||
import styles from "./index.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
|
const { Search } = Input;
|
||||||
|
|
||||||
|
interface CommunicationRecord {
|
||||||
|
id: string;
|
||||||
|
avatar: string;
|
||||||
|
name: string;
|
||||||
|
type: "chat" | "call" | "video" | "email";
|
||||||
|
status: "completed" | "pending" | "cancelled";
|
||||||
|
dateTime: string;
|
||||||
|
duration?: string;
|
||||||
|
direction: "incoming" | "outgoing";
|
||||||
|
subject?: string;
|
||||||
|
content: string;
|
||||||
|
tags: string[];
|
||||||
|
attachments?: Array<{
|
||||||
|
name: string;
|
||||||
|
type: "pdf" | "xlsx" | "doc" | "other";
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
const CommunicationRecord: React.FC = () => {
|
const CommunicationRecord: React.FC = () => {
|
||||||
|
const [activeTab, setActiveTab] = useState("chat");
|
||||||
|
const [searchValue, setSearchValue] = useState("");
|
||||||
|
|
||||||
|
// 模拟数据
|
||||||
|
const mockData: CommunicationRecord[] = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
avatar: "李",
|
||||||
|
name: "李先生",
|
||||||
|
type: "chat",
|
||||||
|
status: "completed",
|
||||||
|
dateTime: "2024/3/5 14:30:00",
|
||||||
|
direction: "incoming",
|
||||||
|
content: "咨询AI营销产品的详细功能和价格",
|
||||||
|
tags: ["产品咨询", "价格询问"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
avatar: "张",
|
||||||
|
name: "张总",
|
||||||
|
type: "call",
|
||||||
|
status: "completed",
|
||||||
|
dateTime: "2024/3/5 10:15:00",
|
||||||
|
duration: "25分钟",
|
||||||
|
direction: "outgoing",
|
||||||
|
subject: "产品演示预约",
|
||||||
|
content: "与客户确认产品演示时间,讨论具体需求",
|
||||||
|
tags: ["产品演示", "需求确认"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
avatar: "王",
|
||||||
|
name: "王女士",
|
||||||
|
type: "video",
|
||||||
|
status: "completed",
|
||||||
|
dateTime: "2024/3/4 16:45:00",
|
||||||
|
duration: "45分钟",
|
||||||
|
direction: "incoming",
|
||||||
|
subject: "产品功能演示",
|
||||||
|
content: "详细演示AI客服功能,客户表示很满意",
|
||||||
|
tags: ["产品演示", "功能介绍"],
|
||||||
|
attachments: [
|
||||||
|
{ name: "产品介绍.pdf", type: "pdf" },
|
||||||
|
{ name: "报价单.xlsx", type: "xlsx" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const getTypeIcon = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case "chat":
|
||||||
|
return <MessageOutlined />;
|
||||||
|
case "call":
|
||||||
|
return <PhoneOutlined />;
|
||||||
|
case "video":
|
||||||
|
return <VideoCameraOutlined />;
|
||||||
|
case "email":
|
||||||
|
return <MailOutlined />;
|
||||||
|
default:
|
||||||
|
return <MessageOutlined />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusColor = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case "completed":
|
||||||
|
return "success";
|
||||||
|
case "pending":
|
||||||
|
return "processing";
|
||||||
|
case "cancelled":
|
||||||
|
return "error";
|
||||||
|
default:
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDirectionColor = (direction: string) => {
|
||||||
|
return direction === "incoming" ? "green" : "blue";
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDirectionText = (direction: string) => {
|
||||||
|
return direction === "incoming" ? "来电/来信" : "去电/去信";
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusText = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case "completed":
|
||||||
|
return "已完成";
|
||||||
|
case "pending":
|
||||||
|
return "进行中";
|
||||||
|
case "cancelled":
|
||||||
|
return "已取消";
|
||||||
|
default:
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAttachmentIcon = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case "pdf":
|
||||||
|
return "📄";
|
||||||
|
case "xlsx":
|
||||||
|
return "📊";
|
||||||
|
case "doc":
|
||||||
|
return "📝";
|
||||||
|
default:
|
||||||
|
return "📎";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredData = mockData.filter(
|
||||||
|
record =>
|
||||||
|
record.type === activeTab &&
|
||||||
|
(searchValue === "" ||
|
||||||
|
record.name.includes(searchValue) ||
|
||||||
|
record.content.includes(searchValue) ||
|
||||||
|
record.tags.some(tag => tag.includes(searchValue))),
|
||||||
|
);
|
||||||
|
|
||||||
|
const tabItems = [
|
||||||
|
{
|
||||||
|
key: "chat",
|
||||||
|
label: (
|
||||||
|
<span>
|
||||||
|
<MessageOutlined />
|
||||||
|
聊天(1)
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "call",
|
||||||
|
label: (
|
||||||
|
<span>
|
||||||
|
<PhoneOutlined />
|
||||||
|
通话(2)
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "video",
|
||||||
|
label: (
|
||||||
|
<span>
|
||||||
|
<VideoCameraOutlined />
|
||||||
|
视频(1)
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "email",
|
||||||
|
label: (
|
||||||
|
<span>
|
||||||
|
<MailOutlined />
|
||||||
|
邮件(1)
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 导出记录处理函数
|
||||||
|
const handleExportRecords = () => {
|
||||||
|
console.log("导出记录功能");
|
||||||
|
// TODO: 实现导出功能
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<PowerNavigation
|
<PowerNavigation
|
||||||
title="沟通记录"
|
title="沟通记录"
|
||||||
subtitle="完整记录客户沟通历史,支持多维度查询分析"
|
subtitle="查看和管理所有客户沟通记录"
|
||||||
showBackButton={true}
|
showBackButton={true}
|
||||||
backButtonText="返回功能中心"
|
backButtonText="返回功能中心"
|
||||||
|
rightContent={
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<DownloadOutlined />}
|
||||||
|
onClick={handleExportRecords}
|
||||||
|
className={styles.exportButton}
|
||||||
|
>
|
||||||
|
导出记录
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
{/* 功能内容待开发 */}
|
{/* 顶部搜索和筛选区域 */}
|
||||||
<div className={styles.placeholder}>
|
<div className={styles.headerSection}>
|
||||||
<p>沟通记录功能正在开发中...</p>
|
<div className={styles.searchBar}>
|
||||||
|
<Search
|
||||||
|
placeholder="搜索客户、内容或标签..."
|
||||||
|
value={searchValue}
|
||||||
|
onChange={e => setSearchValue(e.target.value)}
|
||||||
|
style={{ width: 300 }}
|
||||||
|
prefix={<SearchOutlined />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.filterButtons}>
|
||||||
|
<Button icon={<FilterOutlined />}>筛选</Button>
|
||||||
|
<Button icon={<CalendarOutlined />}>日期范围</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 通信类型导航栏 */}
|
||||||
|
<div className={styles.navigationTabs}>
|
||||||
|
<Tabs
|
||||||
|
activeKey={activeTab}
|
||||||
|
onChange={setActiveTab}
|
||||||
|
items={tabItems}
|
||||||
|
className={styles.tabs}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 通信记录列表 */}
|
||||||
|
<div className={styles.recordsList}>
|
||||||
|
{filteredData.map(record => (
|
||||||
|
<Card key={record.id} className={styles.recordCard}>
|
||||||
|
<div className={styles.cardContent}>
|
||||||
|
<div className={styles.cardLeft}>
|
||||||
|
<Avatar className={styles.avatar}>{record.avatar}</Avatar>
|
||||||
|
<div className={styles.recordInfo}>
|
||||||
|
<div className={styles.nameAndType}>
|
||||||
|
<span className={styles.name}>{record.name}</span>
|
||||||
|
<span className={styles.type}>
|
||||||
|
{getTypeIcon(record.type)}
|
||||||
|
{record.type === "chat"
|
||||||
|
? "聊天"
|
||||||
|
: record.type === "call"
|
||||||
|
? "通话"
|
||||||
|
: record.type === "video"
|
||||||
|
? "视频"
|
||||||
|
: "邮件"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.statusAndTime}>
|
||||||
|
<Tag color={getStatusColor(record.status)}>
|
||||||
|
{getStatusText(record.status)}
|
||||||
|
</Tag>
|
||||||
|
<span className={styles.dateTime}>{record.dateTime}</span>
|
||||||
|
{record.duration && (
|
||||||
|
<span className={styles.duration}>
|
||||||
|
时长:{record.duration}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={styles.directionAndSubject}>
|
||||||
|
<Tag color={getDirectionColor(record.direction)}>
|
||||||
|
{getDirectionText(record.direction)}
|
||||||
|
</Tag>
|
||||||
|
{record.subject && (
|
||||||
|
<span className={styles.subject}>{record.subject}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={styles.content}>{record.content}</div>
|
||||||
|
<div className={styles.tags}>
|
||||||
|
{record.tags.map((tag, index) => (
|
||||||
|
<Tag key={index} className={styles.tag}>
|
||||||
|
{tag}
|
||||||
|
</Tag>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{record.attachments && record.attachments.length > 0 && (
|
||||||
|
<div className={styles.attachments}>
|
||||||
|
<span className={styles.attachmentsLabel}>附件:</span>
|
||||||
|
{record.attachments.map((attachment, index) => (
|
||||||
|
<div key={index} className={styles.attachment}>
|
||||||
|
<span className={styles.attachmentIcon}>
|
||||||
|
{getAttachmentIcon(attachment.type)}
|
||||||
|
</span>
|
||||||
|
<span className={styles.attachmentName}>
|
||||||
|
{attachment.name}
|
||||||
|
</span>
|
||||||
|
<DownloadOutlined className={styles.downloadIcon} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.cardRight}>
|
||||||
|
<EyeOutlined className={styles.viewIcon} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user