From 2ec02fb0578dff3340e6ccc85356a4ffba5a84b5 Mon Sep 17 00:00:00 2001
From: zhang1106 <849185023@qq.com>
Date: Thu, 18 Dec 2025 13:04:32 +0800
Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=9A=84=E6=90=9C=E7=B4=A2?=
=?UTF-8?q?=EF=BC=8C=E8=87=AA=E5=AE=9A=E4=B9=89=E7=AD=89=E5=9F=BA=E7=A1=80?=
=?UTF-8?q?=E5=86=85=E5=AE=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/routes/devices.js | 49 ++++++++++-
frontend/src/pages/Dashboard.jsx | 12 ++-
frontend/src/pages/DeviceManagement.jsx | 110 ++++++++++++++++++++++--
3 files changed, 158 insertions(+), 13 deletions(-)
diff --git a/backend/routes/devices.js b/backend/routes/devices.js
index dfac721..b18db74 100644
--- a/backend/routes/devices.js
+++ b/backend/routes/devices.js
@@ -1,17 +1,58 @@
const express = require('express');
const router = express.Router();
+const { Op } = require('sequelize');
const Device = require('../models/Device');
const Rack = require('../models/Rack');
-// 获取所有设备
+// 获取所有设备(支持搜索和筛选)
router.get('/', async (req, res) => {
try {
- const devices = await Device.findAll({
+ const { keyword, status, type, page = 1, pageSize = 10 } = req.query;
+ const offset = (page - 1) * pageSize;
+
+ // 构建查询条件
+ const where = {};
+
+ // 关键词搜索(所有文本字段)
+ if (keyword) {
+ where[Op.or] = [
+ { deviceId: { [Op.like]: `%${keyword}%` } },
+ { name: { [Op.like]: `%${keyword}%` } },
+ { type: { [Op.like]: `%${keyword}%` } },
+ { model: { [Op.like]: `%${keyword}%` } },
+ { serialNumber: { [Op.like]: `%${keyword}%` } },
+ { position: { [Op.like]: `%${keyword}%` } },
+ { ipAddress: { [Op.like]: `%${keyword}%` } },
+ { description: { [Op.like]: `%${keyword}%` } }
+ ];
+ }
+
+ // 状态筛选
+ if (status && status !== 'all') {
+ where.status = status;
+ }
+
+ // 分类筛选
+ if (type && type !== 'all') {
+ where.type = type;
+ }
+
+ // 执行查询
+ const { count, rows } = await Device.findAndCountAll({
+ where,
include: [
{ model: Rack }
- ]
+ ],
+ offset,
+ limit: parseInt(pageSize)
+ });
+
+ res.json({
+ total: count,
+ devices: rows,
+ page: parseInt(page),
+ pageSize: parseInt(pageSize)
});
- res.json(devices);
} catch (error) {
res.status(500).json({ error: error.message });
}
diff --git a/frontend/src/pages/Dashboard.jsx b/frontend/src/pages/Dashboard.jsx
index 75b0e17..6910143 100644
--- a/frontend/src/pages/Dashboard.jsx
+++ b/frontend/src/pages/Dashboard.jsx
@@ -20,16 +20,20 @@ function Dashboard() {
// 获取所有设备
const devicesRes = await axios.get('/api/devices');
- const totalDevices = devicesRes.data.length;
- const faultDevices = devicesRes.data.filter(device => device.status === 'fault').length;
+ // 设备API返回的是包含devices数组的对象
+ const devices = devicesRes.data.devices || devicesRes.data;
+ const totalDevices = devices.length;
+ const faultDevices = devices.filter(device => device.status === 'fault').length;
// 获取所有机柜
const racksRes = await axios.get('/api/racks');
- const totalRacks = racksRes.data.length;
+ const racks = racksRes.data;
+ const totalRacks = racks.length;
// 获取所有机房
const roomsRes = await axios.get('/api/rooms');
- const totalRooms = roomsRes.data.length;
+ const rooms = roomsRes.data;
+ const totalRooms = rooms.length;
setStats({
totalDevices,
diff --git a/frontend/src/pages/DeviceManagement.jsx b/frontend/src/pages/DeviceManagement.jsx
index 7c57a7f..6e18ab1 100644
--- a/frontend/src/pages/DeviceManagement.jsx
+++ b/frontend/src/pages/DeviceManagement.jsx
@@ -14,6 +14,13 @@ function DeviceManagement() {
const [modalVisible, setModalVisible] = useState(false);
const [editingDevice, setEditingDevice] = useState(null);
const [form] = Form.useForm();
+ // 搜索和筛选状态
+ const [keyword, setKeyword] = useState('');
+ const [status, setStatus] = useState('all');
+ const [type, setType] = useState('all');
+ const [searchForm] = Form.useForm();
+ // 分页状态
+ const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 });
// 自定义字段状态
const [customFieldName, setCustomFieldName] = useState('');
const [customFieldValue, setCustomFieldValue] = useState('');
@@ -21,14 +28,25 @@ function DeviceManagement() {
const [deviceFields, setDeviceFields] = useState([]);
const [loadingFields, setLoadingFields] = useState(true);
- // 获取所有设备
- const fetchDevices = async () => {
+ // 获取所有设备(支持搜索、筛选和分页)
+ const fetchDevices = async (page = 1, pageSize = 10, searchParams = {}) => {
try {
setLoading(true);
- const response = await axios.get('/api/devices');
+
+ // 构建查询参数
+ const params = {
+ page,
+ pageSize,
+ keyword: searchParams.keyword || keyword,
+ status: searchParams.status || status,
+ type: searchParams.type || type
+ };
+
+ const response = await axios.get('/api/devices', { params });
+ const { devices, total } = response.data;
// 将customFields中的字段值映射为设备对象的直接属性
- const processedDevices = response.data.map(device => {
+ const processedDevices = devices.map(device => {
const deviceWithFields = { ...device };
// 如果有自定义字段,将其展开为设备对象的直接属性
@@ -42,6 +60,7 @@ function DeviceManagement() {
});
setDevices(processedDevices);
+ setPagination(prev => ({ ...prev, current: page, pageSize, total }));
} catch (error) {
message.error('获取设备列表失败');
console.error('获取设备列表失败:', error);
@@ -189,6 +208,26 @@ function DeviceManagement() {
}
};
+ // 搜索处理函数
+ const handleSearch = (values) => {
+ fetchDevices(1, 10, values);
+ };
+
+ // 重置筛选条件
+ const handleReset = () => {
+ setKeyword('');
+ setStatus('all');
+ setType('all');
+ searchForm.resetFields();
+ fetchDevices(1, 10, { keyword: '', status: 'all', type: 'all' });
+ };
+
+ // 表格分页变化处理
+ const handleTableChange = (pagination) => {
+ setPagination(pagination);
+ fetchDevices(pagination.current, pagination.pageSize);
+ };
+
// 删除设备
const handleDelete = async (deviceId) => {
Modal.confirm({
@@ -308,12 +347,73 @@ function DeviceManagement() {
添加设备
}>
+ {/* 搜索和筛选区域 */}
+