feat: 复用设备编辑模态框实现设备添加功能

This commit is contained in:
BenjaminNH 2025-07-01 16:06:17 +08:00
parent dc0451529e
commit c9d0bb88b3
3 changed files with 91 additions and 36 deletions

View File

@ -1,12 +1,24 @@
import { UploadOutlined } from "@ant-design/icons"; import { UploadOutlined } from "@ant-design/icons";
import { Button, Form, Image, Input, Modal, Select, Upload } from "antd"; import {
Button,
Form,
Image,
Input,
message,
Modal,
Select,
Upload,
} from "antd";
import TextArea from "antd/es/input/TextArea"; import TextArea from "antd/es/input/TextArea";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import axiosInstance, { baseURL } from "../../api/axios"; import axiosInstance, { baseURL } from "../../api/axios";
import { deviceStatusOptions } from "../../config/DeviceStatusConfig"; import { deviceStatusOptions } from "../../config/DeviceStatusConfig";
import { selectUserId } from "../../features/auth/authSlice";
export default function DeviceDetailModal({ export default function DeviceDetailModal({
visiable, visiable,
mode = "create",
device, device,
onclose, onclose,
onSuccess, onSuccess,
@ -15,57 +27,74 @@ export default function DeviceDetailModal({
const [imageFile, setImageFile] = useState(null); const [imageFile, setImageFile] = useState(null);
const [initialValues, setInitialValues] = useState({}); const [initialValues, setInitialValues] = useState({});
const [fileList, setFileList] = useState(); const [fileList, setFileList] = useState();
const userId = useSelector(selectUserId);
useEffect(() => { useEffect(() => {
if (device) { if (visiable) {
const values = { setFileList([]);
name: device.name, if (mode === "edit") {
location: device.location, const values = {
usageRequirement: device.usageRequirement, name: device.name,
status: device.status, location: device.location,
}; usageRequirement: device.usageRequirement,
form.setFieldsValue(values); status: device.status,
setInitialValues(values); };
form.setFieldsValue(values);
setInitialValues(values);
} else {
const values = {
name: undefined,
location: undefined,
usageRequirement: undefined,
status: undefined,
};
form.setFieldsValue(values);
setInitialValues(values);
}
} }
}, [device]); }, [visiable, mode, device, form]);
const handleEdit = async () => { const handleOk = async () => {
const values = await form.validateFields(); const values = await form.validateFields();
const updates = {}; const data = {};
Object.keys(initialValues).forEach((key) => { Object.keys(initialValues).forEach((key) => {
if (values[key] !== initialValues[key]) { if (values[key] !== initialValues[key]) {
updates[key] = values[key]; data[key] = values[key];
} }
}); });
if (Object.keys(updates).length > 0) { if (Object.keys(data).length > 0) {
await axiosInstance.put(`/device/${device.deviceId}`, updates); if (mode === "edit") {
await axiosInstance.put(`/device/${device.deviceId}`, data);
message.success("编辑成功");
} else {
device = await axiosInstance.post(`/device/${userId}`, data);
console.log(device);
message.success("添加成功");
}
} }
if (imageFile) { if (imageFile) {
const formData = new FormData(); const formData = new FormData();
formData.append("image", imageFile); formData.append("image", imageFile);
await axiosInstance.post(`device/${device.deviceId}/image`, formData, { await axiosInstance.post(`device/${device.id}/image`, formData, {
headers: { headers: {
"Content-Type": "multipart/form-data", "Content-Type": "multipart/form-data",
}, },
}); });
} }
onSuccess(); onSuccess();
setFileList([]);
form.resetFields();
onclose(); onclose();
}; };
return ( return (
<Modal <Modal
title="编辑设备" title={mode === "edit" ? "编辑设备" : "添加设备"}
open={visiable} open={visiable}
onCancel={() => { onCancel={() => {
setFileList([]);
form.resetFields();
onclose(); onclose();
}} }}
onOk={handleEdit} onOk={handleOk}
okText="保存" okText="保存"
> >
<Form form={form} layout="vertical" initialValues={initialValues}> <Form form={form} layout="vertical" initialValues={initialValues}>
@ -99,6 +128,7 @@ export default function DeviceDetailModal({
}} }}
showUploadList={{ showRemoveIcon: true }} showUploadList={{ showRemoveIcon: true }}
onChange={({ fileList }) => setFileList(fileList)} onChange={({ fileList }) => setFileList(fileList)}
maxCount={1}
> >
<Button icon={<UploadOutlined />}>点击上传</Button> <Button icon={<UploadOutlined />}>点击上传</Button>
</Upload> </Upload>

View File

@ -1,4 +1,4 @@
import { Button, Input, message, Space, Table, Tag } from "antd"; import { Button, Flex, Input, message, Space, Table, Tag } from "antd";
import Column from "antd/es/table/Column"; import Column from "antd/es/table/Column";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
@ -10,6 +10,8 @@ import DeviceDetailModal from "./DeviceDetailModal";
export default function DeviceManage() { export default function DeviceManage() {
const [devices, setDevices] = useState([]); const [devices, setDevices] = useState([]);
const [selectedDevice, setSelectedDevice] = useState(null); const [selectedDevice, setSelectedDevice] = useState(null);
const [modalOpen, setModalOpen] = useState(false);
const [modalMode, setModalMode] = useState(null);
const [searchName, setSearchName] = useState(null); const [searchName, setSearchName] = useState(null);
const [pagination, setPagination] = useState({ const [pagination, setPagination] = useState({
current: 1, current: 1,
@ -44,6 +46,7 @@ export default function DeviceManage() {
const handleDelete = async (deviceId) => { const handleDelete = async (deviceId) => {
await axiosInstance.delete(`/device/${deviceId}`); await axiosInstance.delete(`/device/${deviceId}`);
message.success("删除成功");
const newPagination = { const newPagination = {
...pagination, ...pagination,
current: 1, current: 1,
@ -65,13 +68,26 @@ export default function DeviceManage() {
// 使 // 使
return ( return (
<> <>
<Input.Search <Flex justify="space-between">
placeholder="请输入设备名称" <Input.Search
enterButton="搜索" placeholder="请输入设备名称"
onSearch={handleSearch} onSearch={handleSearch}
style={{ width: "200px" }} style={{ width: "200px" }}
className="m-4" className="m-4"
/> />
<Button
className="m-4"
type="primary"
onClick={() => {
setModalMode("create");
setSelectedDevice(null);
setModalOpen(true);
}}
>
添加设备
</Button>
</Flex>
<Table <Table
rowKey="deviceId" rowKey="deviceId"
dataSource={devices} dataSource={devices}
@ -106,7 +122,14 @@ export default function DeviceManage() {
render={(_, record) => { render={(_, record) => {
return ( return (
<Space> <Space>
<Button size="small" onClick={() => setSelectedDevice(record)}> <Button
size="small"
onClick={() => {
setSelectedDevice(record);
setModalOpen(true);
setModalMode("edit");
}}
>
编辑 编辑
</Button> </Button>
<Button <Button
@ -123,11 +146,14 @@ export default function DeviceManage() {
/> />
</Table> </Table>
<DeviceDetailModal <DeviceDetailModal
visiable={!!selectedDevice} visiable={modalOpen}
device={selectedDevice} device={selectedDevice}
onclose={() => setSelectedDevice(null)} mode={modalMode}
onclose={() => {
setModalOpen(false);
setSelectedDevice(null);
}}
onSuccess={async () => { onSuccess={async () => {
message.success("编辑成功");
await fetchData(pagination); await fetchData(pagination);
}} }}
/> />

View File

@ -59,7 +59,6 @@ export default function Reserve() {
<> <>
<Input.Search <Input.Search
placeholder="请输入设备名称" placeholder="请输入设备名称"
enterButton="搜索"
onSearch={handleSearch} onSearch={handleSearch}
style={{ width: "200px" }} style={{ width: "200px" }}
className="m-4" className="m-4"