From 4569eabda7537d7b3c18e4c1f25ac3ec4acfd53b Mon Sep 17 00:00:00 2001
From: zhang1106 <849185023@qq.com>
Date: Thu, 12 Mar 2026 12:40:12 +0800
Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E6=B7=BB=E5=8A=A0=E8=87=AA?=
=?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=85=B3=E9=97=AD=E6=8C=89=E9=92=AE=E7=BB=84?=
=?UTF-8?q?=E4=BB=B6=E5=B9=B6=E5=BA=94=E7=94=A8=E5=88=B0=E6=89=80=E6=9C=89?=
=?UTF-8?q?=E6=A8=A1=E6=80=81=E6=A1=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
frontend/src/components/CableCreateModal.jsx | 2 ++
frontend/src/components/CloseButton.jsx | 36 +++++++++++++++++++
.../src/components/NetworkCardCreateModal.jsx | 2 ++
frontend/src/components/PortCreateModal.jsx | 2 ++
.../src/components/ServerBackplanePanel.jsx | 2 ++
frontend/src/index.css | 31 ++++++++++++++--
frontend/src/pages/CableManagement.jsx | 8 +++++
frontend/src/pages/CategoryManagement.jsx | 2 ++
frontend/src/pages/ConsumableLogs.jsx | 5 +++
frontend/src/pages/ConsumableManagement.jsx | 5 +++
frontend/src/pages/DeviceFieldManagement.jsx | 2 ++
frontend/src/pages/InventoryManagement.jsx | 2 ++
frontend/src/pages/InventoryTaskExecution.jsx | 3 ++
.../src/pages/PendingDeviceManagement.jsx | 2 ++
frontend/src/pages/PortManagement.jsx | 4 +++
frontend/src/pages/Rack3DVisualization.jsx | 7 ++++
frontend/src/pages/RackManagement.jsx | 3 ++
frontend/src/pages/RoomManagement.jsx | 2 ++
.../src/pages/TicketCategoryManagement.jsx | 2 ++
frontend/src/pages/TicketFieldManagement.jsx | 2 ++
frontend/src/pages/TicketManagement.jsx | 4 +++
frontend/src/pages/UserManagement.jsx | 4 +++
22 files changed, 129 insertions(+), 3 deletions(-)
create mode 100644 frontend/src/components/CloseButton.jsx
diff --git a/frontend/src/components/CableCreateModal.jsx b/frontend/src/components/CableCreateModal.jsx
index 518fd7f..6c7564d 100644
--- a/frontend/src/components/CableCreateModal.jsx
+++ b/frontend/src/components/CableCreateModal.jsx
@@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback, useRef } from 'react';
import { Modal, Form, Select, Input, Button, message, Space, Spin } from 'antd';
import { SwapOutlined } from '@ant-design/icons';
import axios from 'axios';
+import CloseButton from './CloseButton';
import { debounce } from '../utils/common';
const { Option } = Select;
@@ -148,6 +149,7 @@ const CableCreateModal = ({ visible, onClose, onSuccess, sourceDevice }) => {
}
open={visible}
+ closeIcon={}
onCancel={onClose}
onOk={handleSubmit}
confirmLoading={loading}
diff --git a/frontend/src/components/CloseButton.jsx b/frontend/src/components/CloseButton.jsx
new file mode 100644
index 0000000..b1d3bb7
--- /dev/null
+++ b/frontend/src/components/CloseButton.jsx
@@ -0,0 +1,36 @@
+import React from 'react';
+
+const CloseButton = ({ size = 32, iconSize = 16, className = 'modal-close-btn' }) => {
+ return (
+
+
+
+ );
+};
+
+export default CloseButton;
diff --git a/frontend/src/components/NetworkCardCreateModal.jsx b/frontend/src/components/NetworkCardCreateModal.jsx
index 0e080b2..8b097e0 100644
--- a/frontend/src/components/NetworkCardCreateModal.jsx
+++ b/frontend/src/components/NetworkCardCreateModal.jsx
@@ -3,6 +3,7 @@ import { Modal, Form, Input, InputNumber, Select, message, Space, Tooltip } from
import { PlusOutlined, InfoCircleOutlined, CloudServerOutlined } from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
+import CloseButton from './CloseButton';
const { Option } = Select;
const { TextArea } = Input;
@@ -55,6 +56,7 @@ function NetworkCardCreateModal({ device, visible, onClose, onSuccess }) {
}
open={visible}
+ closeIcon={}
onOk={handleSubmit}
onCancel={handleCancel}
confirmLoading={loading}
diff --git a/frontend/src/components/PortCreateModal.jsx b/frontend/src/components/PortCreateModal.jsx
index 3d60f58..3ee90e6 100644
--- a/frontend/src/components/PortCreateModal.jsx
+++ b/frontend/src/components/PortCreateModal.jsx
@@ -15,6 +15,7 @@ import {
import { PlusOutlined, InfoCircleOutlined } from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
+import CloseButton from './CloseButton';
const { Option } = Select;
const { TextArea } = Input;
@@ -201,6 +202,7 @@ function PortCreateModal({ device, visible, onClose, onSuccess, defaultNicId, ne
}
open={visible}
+ closeIcon={}
onOk={handleSubmit}
onCancel={handleCancel}
confirmLoading={loading}
diff --git a/frontend/src/components/ServerBackplanePanel.jsx b/frontend/src/components/ServerBackplanePanel.jsx
index b02caae..74bbe25 100644
--- a/frontend/src/components/ServerBackplanePanel.jsx
+++ b/frontend/src/components/ServerBackplanePanel.jsx
@@ -14,6 +14,7 @@ import {
import PortPanel from './PortPanel';
import axios from 'axios';
import { designTokens } from '../config/theme';
+import CloseButton from './CloseButton';
const { Text } = Typography;
@@ -620,6 +621,7 @@ const ServerBackplanePanel = ({
}
open={!!selectedSlot}
+ closeIcon={}
onCancel={() => setSelectedSlot(null)}
footer={null}
width={700}
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 761d6d6..64659c3 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -630,9 +630,34 @@ body {
}
.ant-modal-close-x {
- width: 56px !important;
- height: 56px !important;
- line-height: 56px !important;
+ width: 56px;
+ height: 56px;
+ line-height: 56px;
+}
+
+.ant-modal-close {
+ background: transparent !important;
+}
+
+.ant-modal-close:hover {
+ background: transparent !important;
+}
+
+.modal-close-btn {
+ color: rgba(0, 0, 0, 0.45);
+}
+
+.modal-close-btn:hover {
+ background: rgba(0, 0, 0, 0.06);
+ color: rgba(0, 0, 0, 0.88);
+}
+
+.modal-close-btn:hover svg {
+ transform: rotate(90deg);
+}
+
+.modal-close-btn:active {
+ background: rgba(0, 0, 0, 0.1);
}
.ant-message-notice-content {
diff --git a/frontend/src/pages/CableManagement.jsx b/frontend/src/pages/CableManagement.jsx
index f90c155..7c10576 100644
--- a/frontend/src/pages/CableManagement.jsx
+++ b/frontend/src/pages/CableManagement.jsx
@@ -53,6 +53,7 @@ import Papa from 'papaparse';
import { motion, AnimatePresence } from 'framer-motion';
import { designTokens } from '../config/theme';
import { debounce } from '../utils/common';
+import CloseButton from '../components/CloseButton';
const { Option } = Select;
const { Panel } = Collapse;
@@ -1235,6 +1236,11 @@ function CableManagement() {
width={700}
okText="确定"
cancelText="取消"
+ closeIcon={}
+ styles={{
+ content: { padding: '24px' },
+ header: { marginBottom: 16 },
+ }}
okButtonProps={{
style: {
background: designTokens.colors.primary.gradient,
@@ -1446,6 +1452,7 @@ function CableManagement() {
}
open={importModalVisible}
+ closeIcon={}
onCancel={() => {
setImportModalVisible(false);
setImportPreview([]);
@@ -1595,6 +1602,7 @@ function CableManagement() {
}
open={conflictModalVisible}
+ closeIcon={}
onCancel={() => {
setConflictModalVisible(false);
setConflictInfo(null);
diff --git a/frontend/src/pages/CategoryManagement.jsx b/frontend/src/pages/CategoryManagement.jsx
index 21d2d9b..30ace43 100644
--- a/frontend/src/pages/CategoryManagement.jsx
+++ b/frontend/src/pages/CategoryManagement.jsx
@@ -16,6 +16,7 @@ import {
} from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined } from '@ant-design/icons';
import axios from 'axios';
+import CloseButton from '../components/CloseButton';
import {
inputStyles,
selectStyles,
@@ -222,6 +223,7 @@ function CategoryManagement() {
}
onCancel={handleCancel}
footer={null}
width={500}
diff --git a/frontend/src/pages/ConsumableLogs.jsx b/frontend/src/pages/ConsumableLogs.jsx
index 1ce21a9..0045581 100644
--- a/frontend/src/pages/ConsumableLogs.jsx
+++ b/frontend/src/pages/ConsumableLogs.jsx
@@ -36,6 +36,7 @@ import {
EyeOutlined,
} from '@ant-design/icons';
import axios from 'axios';
+import CloseButton from '../components/CloseButton';
import dayjs from 'dayjs';
import * as XLSX from 'xlsx';
import {
@@ -671,6 +672,7 @@ function ConsumableLogs() {
}
onCancel={() => {
setImportModalVisible(false);
setImportType('excel');
@@ -721,6 +723,7 @@ function ConsumableLogs() {
}
onCancel={() => {
setEditModalVisible(false);
form.resetFields();
@@ -753,6 +756,7 @@ function ConsumableLogs() {
}
onCancel={() => {
setHistoryModalVisible(false);
setLogHistory([]);
@@ -832,6 +836,7 @@ function ConsumableLogs() {
}
onCancel={() => {
setArchiveModalVisible(false);
setCurrentArchive(null);
diff --git a/frontend/src/pages/ConsumableManagement.jsx b/frontend/src/pages/ConsumableManagement.jsx
index 2e862e8..1b6e328 100644
--- a/frontend/src/pages/ConsumableManagement.jsx
+++ b/frontend/src/pages/ConsumableManagement.jsx
@@ -49,6 +49,7 @@ import {
import axios from 'axios';
import { motion, AnimatePresence } from 'framer-motion';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
import {
inputStyles,
selectStyles,
@@ -1191,6 +1192,7 @@ function ConsumableManagement() {
}
open={modalVisible}
+ closeIcon={}
onCancel={handleCancel}
footer={null}
width={900}
@@ -1750,6 +1752,7 @@ function ConsumableManagement() {
}
open={importModalVisible}
+ closeIcon={}
onCancel={handleImportCancel}
footer={null}
width={700}
@@ -1885,6 +1888,7 @@ function ConsumableManagement() {
}
open={stockModalVisible}
+ closeIcon={}
onCancel={handleStockCancel}
footer={null}
width={500}
@@ -2040,6 +2044,7 @@ function ConsumableManagement() {
}
onCancel={handleScanCancel}
footer={null}
width={500}
diff --git a/frontend/src/pages/DeviceFieldManagement.jsx b/frontend/src/pages/DeviceFieldManagement.jsx
index ccf4a71..aff89a7 100644
--- a/frontend/src/pages/DeviceFieldManagement.jsx
+++ b/frontend/src/pages/DeviceFieldManagement.jsx
@@ -29,6 +29,7 @@ import {
} from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
const { Option = Select.Option } = Select;
@@ -444,6 +445,7 @@ function DeviceFieldManagement() {
{editingField ? '编辑字段' : '添加字段'}}
open={modalVisible}
+ closeIcon={}
onCancel={handleCancel}
footer={null}
width={600}
diff --git a/frontend/src/pages/InventoryManagement.jsx b/frontend/src/pages/InventoryManagement.jsx
index 3dcb548..d74aa9c 100644
--- a/frontend/src/pages/InventoryManagement.jsx
+++ b/frontend/src/pages/InventoryManagement.jsx
@@ -39,6 +39,7 @@ import axios from 'axios';
import dayjs from 'dayjs';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
const { RangePicker } = DatePicker;
const { TabPane } = Tabs;
@@ -600,6 +601,7 @@ const InventoryManagement = () => {
}
open={modalVisible}
+ closeIcon={}
onCancel={() => setModalVisible(false)}
footer={null}
width={640}
diff --git a/frontend/src/pages/InventoryTaskExecution.jsx b/frontend/src/pages/InventoryTaskExecution.jsx
index be2c415..43c5fef 100644
--- a/frontend/src/pages/InventoryTaskExecution.jsx
+++ b/frontend/src/pages/InventoryTaskExecution.jsx
@@ -38,6 +38,7 @@ import axios from 'axios';
import dayjs from 'dayjs';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
const api = axios.create({
baseURL: '/api',
@@ -1501,6 +1502,7 @@ const InventoryTaskExecution = () => {
}
onCancel={() => setCheckModalVisible(false)}
footer={null}
width={600}
@@ -1572,6 +1574,7 @@ const InventoryTaskExecution = () => {
}
onCancel={() => {
setQuickAddModalVisible(false);
setSelectedRoomId(null);
diff --git a/frontend/src/pages/PendingDeviceManagement.jsx b/frontend/src/pages/PendingDeviceManagement.jsx
index 1daaf64..48d1d87 100644
--- a/frontend/src/pages/PendingDeviceManagement.jsx
+++ b/frontend/src/pages/PendingDeviceManagement.jsx
@@ -36,6 +36,7 @@ import axios from 'axios';
import dayjs from 'dayjs';
import { useNavigate } from 'react-router-dom';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
const api = axios.create({
baseURL: '/api',
@@ -779,6 +780,7 @@ const PendingDeviceManagement = () => {
}
onCancel={() => {
setEditModalVisible(false);
setSelectedRoomId(null);
diff --git a/frontend/src/pages/PortManagement.jsx b/frontend/src/pages/PortManagement.jsx
index aae5c9b..393a9ca 100644
--- a/frontend/src/pages/PortManagement.jsx
+++ b/frontend/src/pages/PortManagement.jsx
@@ -54,6 +54,7 @@ import VirtualDeviceList from '../components/VirtualDeviceList';
import NetworkCardPanel from '../components/NetworkCardPanel';
import NetworkCardCreateModal from '../components/NetworkCardCreateModal';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
import { debounce } from '../utils/common';
const { Option } = Select;
@@ -1155,6 +1156,7 @@ function PortManagement() {
}
open={modalVisible}
+ closeIcon={}
onOk={handleSubmit}
onCancel={() => {
setModalVisible(false);
@@ -1293,6 +1295,7 @@ function PortManagement() {
}
open={importModalVisible}
+ closeIcon={}
onCancel={() => {
setImportModalVisible(false);
setImportPreview([]);
@@ -1457,6 +1460,7 @@ function PortManagement() {
}
open={networkCardModalVisible}
+ closeIcon={}
onCancel={() => {
setNetworkCardModalVisible(false);
setSelectedDeviceForNic(null);
diff --git a/frontend/src/pages/Rack3DVisualization.jsx b/frontend/src/pages/Rack3DVisualization.jsx
index 6398134..8afc0bc 100644
--- a/frontend/src/pages/Rack3DVisualization.jsx
+++ b/frontend/src/pages/Rack3DVisualization.jsx
@@ -39,6 +39,7 @@ import NetworkCardCreateModal from '../components/NetworkCardCreateModal';
import PortCreateModal from '../components/PortCreateModal';
import CableCreateModal from '../components/CableCreateModal';
import DeviceDetailDrawer from '../components/DeviceDetailDrawer';
+import CloseButton from '../components/CloseButton';
import { useScene3D } from '../context/Scene3DContext';
const { Header, Content, Sider } = Layout;
@@ -914,6 +915,7 @@ const Rack3DVisualization = () => {
}
open={modalVisible}
onCancel={handleModalCancel}
+ closeIcon={}
footer={null}
width={700}
>
@@ -990,8 +992,13 @@ const Rack3DVisualization = () => {
}
open={showTooltipConfig}
onCancel={() => setShowTooltipConfig(false)}
+ closeIcon={}
footer={null}
width={520}
+ styles={{
+ content: { padding: '24px' },
+ header: { marginBottom: 16 },
+ }}
>
{loadingTooltipFields ? (
diff --git a/frontend/src/pages/RackManagement.jsx b/frontend/src/pages/RackManagement.jsx
index 0aa59b4..a52648d 100644
--- a/frontend/src/pages/RackManagement.jsx
+++ b/frontend/src/pages/RackManagement.jsx
@@ -51,6 +51,7 @@ import {
} from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
const { Option } = Select;
const { Title, Text } = Typography;
@@ -956,6 +957,7 @@ function RackManagement() {
}
open={modalVisible}
+ closeIcon={}
onCancel={handleCancel}
footer={null}
width={600}
@@ -1225,6 +1227,7 @@ function RackManagement() {
}
open={importModalVisible}
+ closeIcon={}
onCancel={() => {
setImportModalVisible(false);
setImportProgress(0);
diff --git a/frontend/src/pages/RoomManagement.jsx b/frontend/src/pages/RoomManagement.jsx
index 5e2e55d..f51b1f5 100644
--- a/frontend/src/pages/RoomManagement.jsx
+++ b/frontend/src/pages/RoomManagement.jsx
@@ -46,6 +46,7 @@ import {
} from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
+import CloseButton from '../components/CloseButton';
const { Option } = Select;
const { Title, Text } = Typography;
@@ -756,6 +757,7 @@ function RoomManagement() {
}
open={modalVisible}
+ closeIcon={}
onCancel={handleCancel}
footer={null}
width={600}
diff --git a/frontend/src/pages/TicketCategoryManagement.jsx b/frontend/src/pages/TicketCategoryManagement.jsx
index 240eee2..48c66fe 100644
--- a/frontend/src/pages/TicketCategoryManagement.jsx
+++ b/frontend/src/pages/TicketCategoryManagement.jsx
@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import { Table, Button, Modal, Form, Input, Select, message, Card, Space, Popconfirm } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons';
import axios from 'axios';
+import CloseButton from '../components/CloseButton';
const { Option } = Select;
@@ -191,6 +192,7 @@ function TicketCategoryManagement() {
}
onCancel={handleCancel}
footer={null}
width={600}
diff --git a/frontend/src/pages/TicketFieldManagement.jsx b/frontend/src/pages/TicketFieldManagement.jsx
index cd65731..e27af3d 100644
--- a/frontend/src/pages/TicketFieldManagement.jsx
+++ b/frontend/src/pages/TicketFieldManagement.jsx
@@ -14,6 +14,7 @@ import {
} from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import axios from 'axios';
+import CloseButton from '../components/CloseButton';
const { Option } = Select;
@@ -198,6 +199,7 @@ function TicketFieldManagement() {
}
onCancel={handleCancel}
footer={null}
width={600}
diff --git a/frontend/src/pages/TicketManagement.jsx b/frontend/src/pages/TicketManagement.jsx
index 0564d5d..c2e1fe7 100644
--- a/frontend/src/pages/TicketManagement.jsx
+++ b/frontend/src/pages/TicketManagement.jsx
@@ -43,6 +43,7 @@ import {
TagOutlined,
} from '@ant-design/icons';
import axios from 'axios';
+import CloseButton from '../components/CloseButton';
import dayjs from 'dayjs';
import { useSearchParams } from 'react-router-dom';
import { debounce, getUserFromStorage } from '../utils/common';
@@ -1047,6 +1048,7 @@ function TicketManagement() {
}
onCancel={handleCancel}
footer={null}
width={700}
@@ -1067,6 +1069,7 @@ function TicketManagement() {
}
onCancel={() => setProcessingModalVisible(false)}
footer={null}
width={600}
@@ -1114,6 +1117,7 @@ function TicketManagement() {
}
onCancel={() => setDetailModalVisible(false)}
footer={[