Spaces:
Sleeping
Sleeping
File size: 6,100 Bytes
e85fa50 4fc8eae e85fa50 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
import React, { useState } from 'react';
import { PromptGroup } from '../../types';
import Card, { CardHeader, CardContent, CardFooter } from '../common/Card';
import Button from '../common/Button';
import CategoryBadge from '../Category/CategoryBadge';
import { useApp } from '../../contexts/AppContext';
import Modal, { ModalFooter, ModalButton } from '../common/Modal';
import { exportPromptGroupToZip } from '../../utils/exportUtils';
interface PromptGroupDetailProps {
promptGroup: PromptGroup;
onEdit: () => void;
onDelete: () => void;
className?: string;
}
const PromptGroupDetail: React.FC<PromptGroupDetailProps> = ({
promptGroup,
onEdit,
onDelete,
className = ''
}) => {
const { categories } = useApp();
const [showDeleteModal, setShowDeleteModal] = useState(false);
// 查找分类对象 - 支持两种可能的数据结构
const categoryId = typeof promptGroup.category === 'object'
? promptGroup.category._id
: promptGroup.category;
const category = categories.find(c => c._id === categoryId);
const formatDate = (date: string | Date) => {
const dateObj = typeof date === 'string' ? new Date(date) : date;
return dateObj.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
const handleExport = () => {
exportPromptGroupToZip(promptGroup);
};
const handleDelete = () => {
setShowDeleteModal(true);
};
const confirmDelete = () => {
onDelete();
setShowDeleteModal(false);
};
return (
<div className={className}>
<Card>
<CardContent className="pt-4">
<div className="flex justify-between items-start">
<div>
<div className="flex items-center mb-2">
<h1 className="text-2xl font-bold mr-2">{promptGroup.name}</h1>
{category && <CategoryBadge category={category} />}
</div>
<p className="text-gray-600 mb-4">{promptGroup.description || '无描述'}</p>
<div className="flex items-center text-sm text-gray-500 mb-4">
<div className="flex items-center mr-6">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-1">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
{promptGroup.prompts.length} 个提示词
</div>
<div className="flex items-center mr-6">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-1">
<path d="M22 12h-4l-3 9L9 3l-3 9H2"></path>
</svg>
{promptGroup.workflows.length} 个工作流
</div>
<div className="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-1">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
{promptGroup.dslFiles.length} 个DSL文件
</div>
</div>
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<p className="text-xs text-gray-500">创建时间</p>
<p>{formatDate(promptGroup.createdAt)}</p>
</div>
<div>
<p className="text-xs text-gray-500">更新时间</p>
<p>{formatDate(promptGroup.updatedAt)}</p>
</div>
</div>
</div>
</div>
</CardContent>
<CardFooter className="flex justify-end space-x-2">
<Button
variant="secondary"
onClick={handleExport}
>
导出
</Button>
<Button
variant="secondary"
onClick={onEdit}
>
编辑
</Button>
<Button
variant="danger"
onClick={handleDelete}
>
删除
</Button>
</CardFooter>
</Card>
<Modal
isOpen={showDeleteModal}
onClose={() => setShowDeleteModal(false)}
title="删除提示词组"
footer={
<ModalFooter>
<ModalButton
variant="secondary"
onClick={() => setShowDeleteModal(false)}
>
取消
</ModalButton>
<ModalButton
variant="danger"
onClick={confirmDelete}
>
删除
</ModalButton>
</ModalFooter>
}
>
<p className="text-center mb-4">您确定要删除这个提示词组吗?</p>
<p className="text-center text-gray-500 text-sm">此操作不可撤销。所有关联的提示词和DSL文件也将被删除。</p>
</Modal>
</div>
);
};
export default PromptGroupDetail; |