2025-01-25 19:51:08 +08:00
|
|
|
import {
|
2025-01-25 21:22:20 +08:00
|
|
|
EyeOutlined,
|
|
|
|
LikeOutlined,
|
|
|
|
LikeFilled,
|
|
|
|
UserOutlined,
|
|
|
|
BankOutlined,
|
|
|
|
CalendarOutlined,
|
|
|
|
FileTextOutlined,
|
|
|
|
SendOutlined,
|
2025-01-25 19:51:08 +08:00
|
|
|
} from "@ant-design/icons";
|
|
|
|
import { Button, Typography, Space, Tooltip } from "antd";
|
2025-01-25 22:32:46 +08:00
|
|
|
import { PostDto, PostStateLabels } from "@nice/common";
|
2025-01-25 19:51:08 +08:00
|
|
|
import dayjs from "dayjs";
|
2025-01-25 21:22:20 +08:00
|
|
|
import PostLikeButton from "./detail/PostHeader/PostLikeButton";
|
2025-01-25 22:32:46 +08:00
|
|
|
import { LetterBadge } from "./LetterBadge";
|
2025-01-24 15:05:03 +08:00
|
|
|
const { Title, Paragraph, Text } = Typography;
|
2025-01-22 23:19:58 +08:00
|
|
|
|
|
|
|
interface LetterCardProps {
|
2025-01-25 21:22:20 +08:00
|
|
|
letter: PostDto;
|
2025-01-22 23:19:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export function LetterCard({ letter }: LetterCardProps) {
|
2025-01-25 21:22:20 +08:00
|
|
|
return (
|
2025-01-25 22:32:46 +08:00
|
|
|
<div onClick={() => {
|
|
|
|
window.open(`/${letter.id}/detail`)
|
|
|
|
}}
|
|
|
|
className=" cursor-pointer w-full p-6 bg-white rounded-xl group relative overflow-hidden duration-300 hover:-translate-y-1 transition-all ease-in-out "
|
|
|
|
>
|
|
|
|
<div className="flex flex-col gap-4">
|
2025-01-25 21:22:20 +08:00
|
|
|
<div className="flex justify-between items-start">
|
2025-01-25 22:32:46 +08:00
|
|
|
<Title level={4} className="!mb-0 flex-1 font-serif tracking-tight text-gray-800">
|
2025-01-25 21:22:20 +08:00
|
|
|
<a
|
2025-01-25 21:22:30 +08:00
|
|
|
href={`/${letter.id}/detail`}
|
2025-01-25 21:22:20 +08:00
|
|
|
target="_blank"
|
2025-01-25 22:32:46 +08:00
|
|
|
|
|
|
|
className="text-primary hover:text-primary-600 transition-colors duration-200 hover:underline">
|
2025-01-25 21:22:20 +08:00
|
|
|
{letter.title}
|
|
|
|
</a>
|
|
|
|
</Title>
|
|
|
|
</div>
|
|
|
|
{/* Meta Info */}
|
2025-01-25 22:32:46 +08:00
|
|
|
<div className="flex justify-between items-center text-sm text-gray-500">
|
|
|
|
<div className="flex items-center gap-6">
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
<UserOutlined className="text-secondary-400 text-base" />
|
|
|
|
<Text className="text-gray-600 font-medium">
|
2025-01-25 21:22:20 +08:00
|
|
|
{letter.author?.showname || '匿名用户'}
|
|
|
|
</Text>
|
2025-01-25 22:32:46 +08:00
|
|
|
</div>
|
|
|
|
|
|
|
|
{letter.receivers.some(item => item.department?.name) && (
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
<BankOutlined className="text-secondary-400 text-base" />
|
|
|
|
<Tooltip title={letter.receivers.map(item => item.department?.name).filter(Boolean).join(', ')}>
|
|
|
|
<Text className="text-gray-600">
|
|
|
|
{letter.receivers
|
|
|
|
.map(item => item.department?.name)
|
|
|
|
.filter(Boolean)
|
|
|
|
.slice(0, 2)
|
|
|
|
.join('、')}
|
|
|
|
{letter.receivers.filter(item => item.department?.name).length > 2 && ' 等'}
|
|
|
|
</Text>
|
|
|
|
</Tooltip>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{letter.receivers.some(item => item.showname) && (
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
<SendOutlined className="text-secondary-400 text-base" />
|
|
|
|
<Tooltip title={letter.receivers.map(item => item.showname).filter(Boolean).join(', ')}>
|
|
|
|
<Text className="text-gray-600">
|
|
|
|
{letter.receivers
|
|
|
|
.map(item => item.showname)
|
|
|
|
.filter(Boolean)
|
|
|
|
.slice(0, 2)
|
|
|
|
.join('、')}
|
|
|
|
{letter.receivers.filter(item => item.showname).length > 2 && ' 等'}
|
|
|
|
</Text>
|
|
|
|
</Tooltip>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
<CalendarOutlined className="text-secondary-400 text-base" />
|
|
|
|
<Text className="text-gray-500">
|
2025-01-25 21:22:20 +08:00
|
|
|
{dayjs(letter.createdAt).format("YYYY-MM-DD")}
|
|
|
|
</Text>
|
2025-01-25 22:32:46 +08:00
|
|
|
</div>
|
2025-01-25 21:22:20 +08:00
|
|
|
</div>
|
2025-01-22 23:19:58 +08:00
|
|
|
|
2025-01-25 21:22:20 +08:00
|
|
|
{/* Content Preview */}
|
|
|
|
{letter.content && (
|
2025-01-25 22:32:46 +08:00
|
|
|
<Paragraph
|
|
|
|
ellipsis={{ rows: 2 }}
|
|
|
|
className="!mb-4 text-gray-600 flex-1 leading-relaxed text-sm font-sans">
|
|
|
|
{letter.content}
|
|
|
|
</Paragraph>
|
2025-01-25 21:22:20 +08:00
|
|
|
)}
|
2025-01-25 22:32:46 +08:00
|
|
|
<div className="flex flex-wrap gap-2">
|
|
|
|
<LetterBadge type="state" value={letter.state} />
|
|
|
|
{letter.meta.tags.map(tag => (
|
|
|
|
<LetterBadge key={tag} type="tag" value={tag} />
|
|
|
|
))}
|
|
|
|
</div>
|
2025-01-25 21:22:20 +08:00
|
|
|
{/* Badges & Interactions */}
|
2025-01-25 22:32:46 +08:00
|
|
|
<div className="flex justify-between items-center ">
|
|
|
|
<div className="flex flex-wrap gap-2">
|
|
|
|
{letter.terms.map(term => (
|
|
|
|
<LetterBadge key={term.name} type="category" value={term.name} />
|
|
|
|
))}
|
|
|
|
</div>
|
2025-01-24 15:05:03 +08:00
|
|
|
|
2025-01-25 21:22:20 +08:00
|
|
|
<div className="flex items-center gap-4">
|
2025-01-25 22:32:46 +08:00
|
|
|
<Button
|
|
|
|
type="default"
|
|
|
|
shape="round"
|
|
|
|
icon={<EyeOutlined />}
|
|
|
|
>
|
|
|
|
{letter.views}
|
|
|
|
</Button>
|
2025-01-25 21:22:20 +08:00
|
|
|
<PostLikeButton post={letter as any}></PostLikeButton>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
2025-01-22 23:19:58 +08:00
|
|
|
}
|