130 lines
3.8 KiB
TypeScript
130 lines
3.8 KiB
TypeScript
import {
|
|
EyeOutlined,
|
|
LikeOutlined,
|
|
LikeFilled,
|
|
UserOutlined,
|
|
BankOutlined,
|
|
CalendarOutlined,
|
|
FileTextOutlined,
|
|
SendOutlined,
|
|
MailOutlined,
|
|
} from "@ant-design/icons";
|
|
import { Button, Typography, Space, Tooltip } from "antd";
|
|
import { PostDto, PostStateLabels } from "@nice/common";
|
|
import dayjs from "dayjs";
|
|
import PostLikeButton from "./detail/PostHeader/PostLikeButton";
|
|
import { LetterBadge } from "./LetterBadge";
|
|
import PostHateButton from "./detail/PostHeader/PostHateButton";
|
|
const { Title, Paragraph, Text } = Typography;
|
|
|
|
interface LetterCardProps {
|
|
letter: PostDto;
|
|
}
|
|
|
|
export function LetterCard({ letter }: LetterCardProps) {
|
|
return (
|
|
<div
|
|
onClick={() => {
|
|
window.open(`/${letter.id}/detail`);
|
|
}}
|
|
className="cursor-pointer p-6 bg-slate-100/80 rounded-xl hover:ring-white hover:ring-1 transition-all
|
|
duration-300 ease-in-out hover:-translate-y-0.5
|
|
active:scale-[0.98] border border-white
|
|
group relative overflow-hidden">
|
|
<div className="flex flex-col gap-4">
|
|
<div className=" text-xl text-primary font-bold">
|
|
{letter.title}
|
|
</div>
|
|
{/* Meta Info */}
|
|
<div className="flex justify-between items-center text-sm text-gray-600 gap-4 flex-wrap">
|
|
<div className="flex items-center gap-4 flex-1 min-w-[300px]">
|
|
{letter.author?.department?.name && (
|
|
<div className="flex items-center gap-2">
|
|
<BankOutlined className="text-secondary-400 text-base" />
|
|
<Text className="text-gray-600 font-medium">
|
|
{letter.author?.department?.name}
|
|
</Text>
|
|
</div>
|
|
)}
|
|
<div className="flex items-center gap-2">
|
|
<UserOutlined className="text-primary text-base" />
|
|
<Text className="text-primary font-medium">
|
|
{letter?.meta?.signature ||
|
|
letter.author?.showname ||
|
|
"匿名用户"}
|
|
</Text>
|
|
</div>
|
|
|
|
{letter.receivers.some((item) => item.showname) && (
|
|
<div className="flex items-center gap-2">
|
|
<MailOutlined className="text-primary-400 text-base" />
|
|
<Tooltip
|
|
title={letter?.receivers
|
|
?.map((item) => item.showname)
|
|
.filter(Boolean)
|
|
.join(", ")}>
|
|
<Text className="text-primary-400">
|
|
{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">
|
|
{dayjs(letter.createdAt).format("YYYY-MM-DD")}
|
|
</Text>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Content Preview */}
|
|
{letter.content && (
|
|
<div className="flex-1 leading-relaxed text-sm">
|
|
<div
|
|
dangerouslySetInnerHTML={{ __html: letter.content }}
|
|
className="line-clamp-2"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{/* Badges & Interactions */}
|
|
<div className="flex justify-between items-center ">
|
|
<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} />
|
|
))}
|
|
{letter.terms.map((term) => (
|
|
<LetterBadge
|
|
key={term.name}
|
|
type="category"
|
|
value={term.name}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<div className="flex items-center gap-4">
|
|
<Button
|
|
type="default"
|
|
shape="round"
|
|
icon={<EyeOutlined />}>
|
|
<span className="mr-1">浏览量</span>
|
|
{letter.views}
|
|
</Button>
|
|
<PostHateButton post={letter as any}></PostHateButton>
|
|
<PostLikeButton post={letter as any}></PostLikeButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|