doc-forge-reds/web/src/pages/TemplateList.tsx

118 lines
3.3 KiB
TypeScript

import { useEffect, useState, useCallback } from "react";
import { Table, Button, Upload, Space, message, Popconfirm } from "antd";
import { EditOutlined, DeleteOutlined, DownloadOutlined, PlusOutlined } from "@ant-design/icons";
import { useNavigate } from "react-router-dom";
import type { TemplateListItem } from "../types";
import * as templateApi from "../api/templates";
export default function TemplateList() {
const navigate = useNavigate();
const [templates, setTemplates] = useState<TemplateListItem[]>([]);
const [loading, setLoading] = useState(false);
const fetchTemplates = useCallback(async () => {
setLoading(true);
try {
const data = await templateApi.listTemplates();
setTemplates(data);
} catch {
message.error("获取模板列表失败");
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
fetchTemplates();
}, [fetchTemplates]);
const handleDelete = async (id: string) => {
await templateApi.deleteTemplate(id);
message.success("删除成功");
fetchTemplates();
};
const columns = [
{ title: "模板名称", dataIndex: "name", key: "name" },
{
title: "创建时间",
dataIndex: "created_at",
key: "created_at",
render: (v: string) => new Date(v).toLocaleString(),
},
{
title: "更新时间",
dataIndex: "updated_at",
key: "updated_at",
render: (v: string) => new Date(v).toLocaleString(),
},
{
title: "操作",
key: "actions",
width: 240,
render: (_: unknown, record: TemplateListItem) => (
<Space>
<Button
type="primary"
size="small"
icon={<EditOutlined />}
onClick={() => navigate(`/editor/${record.id}`)}
>
</Button>
<Button
size="small"
icon={<DownloadOutlined />}
onClick={() => window.open(templateApi.getDownloadUrl(record.id))}
>
DOCX
</Button>
<Button
size="small"
onClick={() => window.open(templateApi.getDownloadUrl(record.id, "pdf"))}
>
PDF
</Button>
<Popconfirm title="确定删除此模板?" onConfirm={() => handleDelete(record.id)}>
<Button size="small" danger icon={<DeleteOutlined />} />
</Popconfirm>
</Space>
),
},
];
return (
<div>
<div style={{ marginBottom: 16, display: "flex", justifyContent: "space-between" }}>
<h2></h2>
<Upload
accept=".docx"
showUploadList={false}
customRequest={async ({ file, onSuccess, onError }: any) => {
try {
await templateApi.uploadTemplate(file as File);
message.success("上传成功");
fetchTemplates();
onSuccess?.("ok");
} catch {
message.error("上传失败");
onError?.(new Error("上传失败"));
}
}}
>
<Button type="primary" icon={<PlusOutlined />}>
</Button>
</Upload>
</div>
<Table
columns={columns}
dataSource={templates}
rowKey="id"
loading={loading}
pagination={false}
/>
</div>
);
}