列表代码
import React, { useState, useMemo } from "react";
import { Space, Table, Tag, Form, Input, Button, Pagination } from "antd";
import type { TableProps, FormProps } from "antd";
import EditModal from "./components/EditModal";
interface DataType {
key: string;
name: string;
age: number;
address: string;
tags: string[];
}
// 扩展 data 数据
const generateData = (): DataType[] => {
const names = [
"John Brown",
"Jim Green",
"Joe Black",
"Alice Smith",
"Bob Johnson",
"Eva Williams",
];
const addresses = [
"New York No. 1 Lake Park",
"London No. 1 Lake Park",
"Sydney No. 1 Lake Park",
"Tokyo No. 1 Lake Park",
"Paris No. 1 Lake Park",
"Berlin No. 1 Lake Park",
];
const tagsList = [
["nice", "developer"],
["loser"],
["cool", "teacher"],
["coder"],
["designer"],
["manager"],
];
const result: DataType[] = [];
for (let i = 1; i <= 50; i++) {
const name = names[i % names.length];
const address = addresses[i % addresses.length];
const tags = tagsList[i % tagsList.length];
result.push({
key: `${i}`,
name,
age: 25 + (i % 20),
address,
tags,
});
}
return result;
};
const data: DataType[] = generateData();
// 新增 SearchForm 组件
interface SearchFormProps {
onFinish: FormProps["onFinish"];
onReset: () => void;
}
const SearchForm: React.FC<SearchFormProps> = ({ onFinish, onReset }) => {
const [form] = Form.useForm();
return (
<Form
form={form}
name="search"
layout="inline"
onFinish={onFinish}
style={{ marginBottom: 16 }}
>
<Form.Item label="Name" name="name">
<Input placeholder="Search by name" />
</Form.Item>
<Form.Item label="Tag" name="tag">
<Input placeholder="Search by tag" />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Search
</Button>
</Form.Item>
<Form.Item>
<Button htmlType="button" onClick={onReset}>
Reset
</Button>
</Form.Item>
</Form>
);
};
const App: React.FC = () => {
const [filteredData, setFilteredData] = useState<DataType[]>(data);
const [searchParams, setSearchParams] = useState({
name: "",
tag: "",
});
const [currentPage, setCurrentPage] = useState(1);
const pageSize = 10;
const [editingItem, setEditingItem] = useState<DataType | null>(null);
const [isModalVisible, setIsModalVisible] = useState(false);
const handleAdd = () => {
setIsModalVisible(true);
setEditingItem({
key: `${filteredData.length + 1}`,
name: "",
age: 20,
address: "New Address",
tags: ["new"],
});
};
const handleEdit = (record: DataType) => {
setEditingItem(record);
setIsModalVisible(true);
};
const handleModalOk = (values: {
name: string;
age: number;
address: string;
tags: string[];
}) => {
if (editingItem) {
setFilteredData((prev) =>
prev.map((item) =>
item.key === editingItem.key ? { ...item, ...values } : item
)
);
}
};
const handleModalCancel = () => {
setIsModalVisible(false);
setEditingItem(null);
};
const handleFinish = (values: any) => {
setSearchParams(values);
const filtered = data.filter((item) => {
return (
(!values.name ||
item.name.toLowerCase().includes(values.name.toLowerCase())) &&
(!values.tag ||
item.tags.some((t) =>
t.toLowerCase().includes(values.tag.toLowerCase())
))
);
});
setFilteredData(filtered);
setCurrentPage(1); // 重置为第一页
};
const handleReset = () => {
setSearchParams({
name: "",
tag: "",
});
setFilteredData(data);
setCurrentPage(1);
};
const handleDelete = (key: string) => {
if (window.confirm("确定要删除该条目吗?")) {
setFilteredData((prev) => prev.filter((item) => item.key !== key));
}
};
// 分页数据切片
const paginatedData = useMemo(() => {
return filteredData.slice(
(currentPage - 1) * pageSize,
currentPage * pageSize
);
}, [filteredData, currentPage, pageSize]);
const columns = [
{
title: "Name",
dataIndex: "name",
key: "name",
render: (text: string) => <a>{text}</a>,
},
{
title: "Age",
dataIndex: "age",
key: "age",
},
{
title: "Address",
dataIndex: "address",
key: "address",
},
{
title: "Tags",
key: "tags",
dataIndex: "tags",
render: (_: any, { tags }: { tags: string[] }) => (
<>
{tags.map((tag) => {
let color = tag.length > 5 ? "geekblue" : "green";
if (tag === "loser") {
color = "volcano";
}
return (
<Tag color={color} key={tag}>
{tag.toUpperCase()}
</Tag>
);
})}
</>
),
},
{
title: "Action",
key: "action",
render: (_, record: DataType) => (
<Space size="middle">
<Button type="link" onClick={() => handleEdit(record)}>
Edit
</Button>
<Button type="link" danger onClick={() => handleDelete(record.key)}>
Delete
</Button>
</Space>
),
},
];
return (
<div style={{ padding: 24 }}>
<SearchForm onFinish={handleFinish} onReset={handleReset} />
<div style={{ marginBottom: 16 }}>
<Button type="primary" onClick={handleAdd}>
新增
</Button>
</div>
<Table<DataType>
columns={columns}
dataSource={paginatedData}
pagination={false}
/>
<EditModal
visible={isModalVisible}
onCancel={handleModalCancel}
onOk={handleModalOk}
initialValues={editingItem || undefined}
/>
<Pagination
current={currentPage}
pageSize={pageSize}
total={filteredData.length}
onChange={(page) => setCurrentPage(page)}
style={{ marginTop: 16, textAlign: "right" }}
/>
</div>
);
};
export default App;
弹窗代码
import React, { useEffect, useState } from "react";
import { Modal, Form, Input, Select, Tag } from "antd";
interface EditModalProps {
visible: boolean;
onCancel: () => void;
onOk: (values: {
name: string;
age: number;
address: string;
tags: string[];
}) => void;
initialValues?: {
name: string;
age: number;
address: string;
tags: string[];
};
}
const { Option } = Select;
const EditModal: React.FC<EditModalProps> = ({
visible,
onCancel,
onOk,
initialValues,
}) => {
const [form] = Form.useForm();
// 新增 useEffect 强制更新表单字段
useEffect(() => {
if (visible && initialValues) {
form.setFieldsValue(initialValues);
}
}, [initialValues, visible, form]);
const handleOk = () => {
form.validateFields().then((values) => {
onOk(values);
form.resetFields();
});
};
useEffect(() => {
console.log(initialValues, "initialValues");
}, [visible]);
return (
<Modal
title="编辑数据"
visible={visible}
onCancel={() => {
form.resetFields();
onCancel();
}}
onOk={handleOk}
>
<Form form={form} layout="vertical" initialValues={initialValues}>
<Form.Item label="Name" name="name" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item
label="Age"
name="age"
rules={[{ required: true, type: "number", min: 0 }]}
>
<Input type="number" />
</Form.Item>
<Form.Item label="Address" name="address" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item label="Tags" name="tags" rules={[{ required: true }]}>
<Select mode="tags" style={{ width: "100%" }} tokenSeparators={[","]}>
{[
"nice",
"developer",
"loser",
"cool",
"teacher",
"coder",
"designer",
"manager",
].map((tag) => (
<Option key={tag} value={tag}>
{tag}
</Option>
))}
</Select>
</Form.Item>
</Form>
</Modal>
);
};
export default EditModal;
前端工程师、程序员

浙公网安备 33010602011771号