|
@@ -3,6 +3,7 @@ import { useQuery } from '@tanstack/react-query';
|
|
|
import { format } from 'date-fns';
|
|
import { format } from 'date-fns';
|
|
|
import { Plus, Search, Edit, Trash2, Download, Eye } from 'lucide-react';
|
|
import { Plus, Search, Edit, Trash2, Download, Eye } from 'lucide-react';
|
|
|
import { templateClient } from '@/client/api';
|
|
import { templateClient } from '@/client/api';
|
|
|
|
|
+import FilePreviewDialog from '@/client/admin/components/FilePreviewDialog';
|
|
|
import type { InferRequestType, InferResponseType } from 'hono/client';
|
|
import type { InferRequestType, InferResponseType } from 'hono/client';
|
|
|
import { Button } from '@/client/components/ui/button';
|
|
import { Button } from '@/client/components/ui/button';
|
|
|
import { Input } from '@/client/components/ui/input';
|
|
import { Input } from '@/client/components/ui/input';
|
|
@@ -45,6 +46,8 @@ export const TemplatesPage = () => {
|
|
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
|
const [templateToDelete, setTemplateToDelete] = useState<number | null>(null);
|
|
const [templateToDelete, setTemplateToDelete] = useState<number | null>(null);
|
|
|
const [isCreateForm, setIsCreateForm] = useState(true);
|
|
const [isCreateForm, setIsCreateForm] = useState(true);
|
|
|
|
|
+ const [previewDialogOpen, setPreviewDialogOpen] = useState(false);
|
|
|
|
|
+ const [previewFile, setPreviewFile] = useState<any>(null);
|
|
|
|
|
|
|
|
const createForm = useForm<CreateTemplateFormData>({
|
|
const createForm = useForm<CreateTemplateFormData>({
|
|
|
resolver: zodResolver(createTemplateFormSchema),
|
|
resolver: zodResolver(createTemplateFormSchema),
|
|
@@ -195,6 +198,16 @@ export const TemplatesPage = () => {
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ // 处理预览模板文件
|
|
|
|
|
+ const handlePreviewTemplate = (template: TemplateResponse) => {
|
|
|
|
|
+ if (!template.file) {
|
|
|
|
|
+ toast.warning('该模板没有关联文件');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ setPreviewFile(template.file);
|
|
|
|
|
+ setPreviewDialogOpen(true);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
// 渲染加载骨架
|
|
// 渲染加载骨架
|
|
|
if (isLoading) {
|
|
if (isLoading) {
|
|
|
return (
|
|
return (
|
|
@@ -308,10 +321,19 @@ export const TemplatesPage = () => {
|
|
|
</TableCell>
|
|
</TableCell>
|
|
|
<TableCell className="text-right">
|
|
<TableCell className="text-right">
|
|
|
<div className="flex justify-end gap-2">
|
|
<div className="flex justify-end gap-2">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ variant="ghost"
|
|
|
|
|
+ size="icon"
|
|
|
|
|
+ onClick={() => handlePreviewTemplate(template)}
|
|
|
|
|
+ title="预览文件"
|
|
|
|
|
+ >
|
|
|
|
|
+ <Eye className="h-4 w-4" />
|
|
|
|
|
+ </Button>
|
|
|
<Button
|
|
<Button
|
|
|
variant="ghost"
|
|
variant="ghost"
|
|
|
size="icon"
|
|
size="icon"
|
|
|
onClick={() => handleEditTemplate(template)}
|
|
onClick={() => handleEditTemplate(template)}
|
|
|
|
|
+ title="编辑模板"
|
|
|
>
|
|
>
|
|
|
<Edit className="h-4 w-4" />
|
|
<Edit className="h-4 w-4" />
|
|
|
</Button>
|
|
</Button>
|
|
@@ -319,6 +341,7 @@ export const TemplatesPage = () => {
|
|
|
variant="ghost"
|
|
variant="ghost"
|
|
|
size="icon"
|
|
size="icon"
|
|
|
onClick={() => handleDeleteTemplate(template.id)}
|
|
onClick={() => handleDeleteTemplate(template.id)}
|
|
|
|
|
+ title="删除模板"
|
|
|
>
|
|
>
|
|
|
<Trash2 className="h-4 w-4" />
|
|
<Trash2 className="h-4 w-4" />
|
|
|
</Button>
|
|
</Button>
|
|
@@ -617,6 +640,13 @@ export const TemplatesPage = () => {
|
|
|
</DialogFooter>
|
|
</DialogFooter>
|
|
|
</DialogContent>
|
|
</DialogContent>
|
|
|
</Dialog>
|
|
</Dialog>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 文件预览对话框 */}
|
|
|
|
|
+ <FilePreviewDialog
|
|
|
|
|
+ open={previewDialogOpen}
|
|
|
|
|
+ onOpenChange={setPreviewDialogOpen}
|
|
|
|
|
+ file={previewFile}
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|