子仓库提交
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Card } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { format } from 'date-fns';
|
||||
import { zhCN } from 'date-fns/locale';
|
||||
import { MessageSendRecord } from '@/types/message';
|
||||
|
||||
interface MessagePreviewDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
record: MessageSendRecord | null;
|
||||
getTypeIcon: (type: string) => JSX.Element;
|
||||
getTypeLabel: (type: string) => string;
|
||||
getTypeBadge: (type: string) => string;
|
||||
getStatusBadge: (status: string) => JSX.Element;
|
||||
}
|
||||
|
||||
export function MessagePreviewDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
record,
|
||||
getTypeIcon,
|
||||
getTypeLabel,
|
||||
getTypeBadge,
|
||||
getStatusBadge
|
||||
}: MessagePreviewDialogProps) {
|
||||
if (!record) return null;
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>消息详情</DialogTitle>
|
||||
<DialogDescription className="sr-only">
|
||||
查看消息发送详情
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Label>消息模版</Label>
|
||||
<div className="field-value-inline">{record.templateName}</div>
|
||||
</div>
|
||||
<div>
|
||||
<Label>消息类型</Label>
|
||||
<div className="mt-2">
|
||||
<Badge className={getTypeBadge(record.type)}>
|
||||
<span className="flex items-center gap-1">
|
||||
{getTypeIcon(record.type)}
|
||||
{getTypeLabel(record.type)}
|
||||
</span>
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Label>发送方式</Label>
|
||||
<div className="field-value-inline">
|
||||
{record.sendType === 'immediate' ? '实时发送' : '定时发送'}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Label>发送状态</Label>
|
||||
<div className="mt-2">
|
||||
{getStatusBadge(record.status)}
|
||||
</div>
|
||||
</div>
|
||||
{record.scheduledTime && (
|
||||
<div>
|
||||
<Label>定时发送时间</Label>
|
||||
<div className="field-value-inline">
|
||||
{format(new Date(record.scheduledTime), 'yyyy-MM-dd HH:mm', { locale: zhCN })}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<Label>创建时间</Label>
|
||||
<div className="field-value-inline">
|
||||
{format(new Date(record.createdAt), 'yyyy-MM-dd HH:mm', { locale: zhCN })}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{record.subject && (
|
||||
<div>
|
||||
<Label>消息主题</Label>
|
||||
<div className="field-value-inline">{record.subject}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<Label>接收人列表(共 {record.recipientCount} 人)</Label>
|
||||
<Card className="p-3 bg-gray-50 mt-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{record.recipients.map((recipient, index) => (
|
||||
<Badge key={index} variant="outline">
|
||||
{recipient}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>消息内容</Label>
|
||||
<Card className="p-4 bg-blue-50 border-blue-200 mt-2">
|
||||
<pre className="text-sm whitespace-pre-wrap">
|
||||
{record.content}
|
||||
</pre>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button onClick={() => onOpenChange(false)}>
|
||||
关闭
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user