118 lines
3.3 KiB
TypeScript
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>
|
|
);
|
|
}
|