import React, { useState, useEffect } from 'react'; import { Plus, Edit, Trash2, Search, X, Monitor, Smartphone, Tablet, Power, RefreshCw } from 'lucide-react'; import apiClient from '../../utils/apiClient'; import { buildApiUrl, API_ENDPOINTS } from '../../config/api'; import ConfirmDialog from '../../components/ConfirmDialog'; import Toast from '../../components/Toast'; import PageLoading from '../../components/PageLoading'; import FormModal from '../../components/FormModal'; import ListTable from '../../components/ListTable'; import ToggleSwitch from '../../components/ToggleSwitch'; import './TerminalManagement.css'; const TerminalManagement = () => { const [terminals, setTerminals] = useState([]); // All terminals const [terminalTypes, setTerminalTypes] = useState([]); const [loading, setLoading] = useState(true); // Local state for filtering/pagination const [keyword, setKeyword] = useState(''); const [filterType, setFilterType] = useState(''); const [filterStatus, setFilterStatus] = useState(''); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(20); const [showModal, setShowModal] = useState(false); const [isEditing, setIsEditing] = useState(false); const [selectedTerminal, setSelectedTerminal] = useState(null); const [deleteConfirmInfo, setDeleteConfirmInfo] = useState(null); const [toasts, setToasts] = useState([]); const [formData, setFormData] = useState({ imei: '', terminal_name: '', terminal_type: '', description: '', status: 1 }); // Toast helper const showToast = (message, type = 'info') => { const id = Date.now(); setToasts(prev => [...prev, { id, message, type }]); }; const removeToast = (id) => { setToasts(prev => prev.filter(toast => toast.id !== id)); }; useEffect(() => { fetchTerminalTypes(); fetchTerminals(); }, []); const fetchTerminalTypes = async () => { try { const response = await apiClient.get( buildApiUrl(API_ENDPOINTS.DICT_DATA.BY_TYPE('client_platform')), { params: { parent_code: 'TERMINAL' } } ); if (response.code === '200') { setTerminalTypes(response.data.items || []); } } catch (error) { console.error('Failed to fetch terminal types:', error); } }; const fetchTerminals = async () => { setLoading(true); try { // Fetch all terminals (using a large size) const params = { page: 1, size: 10000 }; const response = await apiClient.get(buildApiUrl(API_ENDPOINTS.TERMINALS.LIST), { params }); if (response.code === '200') { setTerminals(response.data.items); } } catch (error) { console.error('Failed to fetch terminals:', error); showToast('获取终端列表失败', 'error'); } finally { setLoading(false); } }; // Local Filtering const filteredTerminals = terminals.filter(terminal => { const matchesKeyword = !keyword || terminal.imei.toLowerCase().includes(keyword.toLowerCase()) || (terminal.terminal_name && terminal.terminal_name.toLowerCase().includes(keyword.toLowerCase())); const matchesType = !filterType || terminal.terminal_type === filterType; const matchesStatus = filterStatus === '' || terminal.status === parseInt(filterStatus); return matchesKeyword && matchesType && matchesStatus; }); // Local Pagination const total = filteredTerminals.length; const paginatedTerminals = filteredTerminals.slice((page - 1) * pageSize, page * pageSize); const handleReset = () => { setKeyword(''); setFilterType(''); setFilterStatus(''); setPage(1); }; const handleOpenCreate = () => { setIsEditing(false); setSelectedTerminal(null); setFormData({ imei: '', terminal_name: '', terminal_type: terminalTypes.length > 0 ? terminalTypes[0].dict_code : '', description: '', status: 1 }); setShowModal(true); }; const handleOpenEdit = (terminal) => { setIsEditing(true); setSelectedTerminal(terminal); setFormData({ imei: terminal.imei, terminal_name: terminal.terminal_name || '', terminal_type: terminal.terminal_type, description: terminal.description || '', status: terminal.status }); setShowModal(true); }; const handleSubmit = async (e) => { e.preventDefault(); if (!formData.imei) { showToast('请输入IMEI号', 'error'); return; } if (!formData.terminal_type) { showToast('请选择终端类型', 'error'); return; } try { if (isEditing) { await apiClient.put( buildApiUrl(API_ENDPOINTS.TERMINALS.UPDATE(selectedTerminal.id)), formData ); showToast('更新成功', 'success'); } else { await apiClient.post(buildApiUrl(API_ENDPOINTS.TERMINALS.CREATE), formData); showToast('创建成功', 'success'); } setShowModal(false); fetchTerminals(); } catch (error) { const msg = error.response?.data?.message || '操作失败'; showToast(msg, 'error'); } }; const handleDelete = async () => { if (!deleteConfirmInfo) return; try { await apiClient.delete(buildApiUrl(API_ENDPOINTS.TERMINALS.DELETE(deleteConfirmInfo.id))); showToast('删除成功', 'success'); fetchTerminals(); } catch (error) { const msg = error.response?.data?.message || '删除失败'; showToast(msg, 'error'); } finally { setDeleteConfirmInfo(null); } }; const handleToggleStatus = async (terminal) => { try { const newStatus = terminal.status === 1 ? 0 : 1; await apiClient.post( buildApiUrl(API_ENDPOINTS.TERMINALS.STATUS(terminal.id)), null, { params: { status: newStatus } } ); showToast(`已${newStatus === 1 ? '启用' : '停用'}终端`, 'success'); // Update local state directly for better UX setTerminals(prev => prev.map(t => t.id === terminal.id ? { ...t, status: newStatus } : t )); } catch (error) { showToast('状态更新失败', 'error'); } }; const getTerminalTypeLabel = (code) => { const type = terminalTypes.find(t => t.dict_code === code); return type ? type.label_cn : code; }; const columns = [ { title: 'IMEI', dataIndex: 'imei', key: 'imei', minWidth: '160px', render: (item) => {item.imei} }, { title: '终端名称', dataIndex: 'terminal_name', key: 'terminal_name', minWidth: '150px', render: (item) => {item.terminal_name || '-'} }, { title: '类型', key: 'terminal_type', render: (item) => ( {getTerminalTypeLabel(item.terminal_type)} ) }, { title: '当前绑定账号', key: 'current_user', render: (item) => ( item.current_user_caption ? (
{item.current_user_caption} {item.current_username && ({item.current_username})}
) : ( - ) ) }, { title: '状态', key: 'status', render: (item) => ( handleToggleStatus(item)} size="medium" /> ) }, { title: '激活状态', key: 'is_activated', render: (item) => ( <> {item.is_activated === 1 ? '已激活' : '未激活'} ) }, { title: '最后在线', key: 'last_online_at', render: (item) => item.last_online_at ? new Date(item.last_online_at).toLocaleString() : '-' }, { title: '创建时间', key: 'created_at', render: (item) => new Date(item.created_at).toLocaleDateString() }, { title: '操作', key: 'action', fixed: 'right', width: '110px', render: (item) => (
) } ]; if (loading && terminals.length === 0) { return ; } return (

终端管理

管理专用终端设备的接入与状态

setKeyword(e.target.value)} /> {keyword && ( )}
setPage(p) }} showPagination={true} /> {/* 弹窗 */} setShowModal(false)} title={isEditing ? '编辑终端' : '添加终端'} actions={ <> } >
setFormData({...formData, imei: e.target.value})} placeholder="请输入设备IMEI号" disabled={isEditing} // IMEI通常不可修改 required />
setFormData({...formData, terminal_name: e.target.value})} placeholder="给设备起个名字" />