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() { 添加设备 }> + {/* 搜索和筛选区域 */} + +
+ + } + style={{ width: 300 }} + value={keyword} + onChange={(e) => setKeyword(e.target.value)} + /> + + + + + + + + + + + + + + + + +
+
+