import React, { useState } from 'react'; import { Search, Plus, Link2, History, Upload, Download, Edit } from 'lucide-react'; import { Button } from '../ui/button'; import { Input } from '../ui/input'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '../ui/table'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select'; import { Label } from '../ui/label'; import { Switch } from '../ui/switch'; // --- Types & Rules --- // 1. 新增设备必须与 Location 绑定 // 2. Sensor(温度湿度传感器)可批量绑定/导入/导出/编辑 // 3. E-label(电子标签)可批量绑定/导入/导出/编辑 // 4. 后台可查看所有设备运行状况;打印机可查看剩余打印米数及充值记录 // 5. Printer、Scale 可批量导入/导出/编辑 // 6. 已创建捆绑的设备可编辑为 Active/Inactive export type DeviceCategory = 'Printer' | 'Sensor' | 'Scale' | 'E-label'; export interface RechargeRecord { id: string; date: string; amount: string; // e.g. "100 meters" note?: string; } export interface Device { id: string; locationId: string; category: DeviceCategory; device: string; deviceId: string; balance: string; // 打印机剩余米数,其他类型为空 status: 'Online' | 'Offline'; active: boolean; // Active / Inactive rechargeRecords?: RechargeRecord[]; // 打印机充值记录 } const MOCK_LOCATIONS = [ { id: '12345', name: 'Location 12345 - Downtown' }, { id: '67890', name: 'Location 67890 - Uptown' }, ]; const CATEGORY_LABELS: Record = { Printer: 'Printer', Sensor: 'Sensor (Temp. & Humidity)', Scale: 'Scale', 'E-label': 'E-label (Electronic Label)', }; const INITIAL_DEVICES: Device[] = [ { id: '1', locationId: '12345', category: 'Printer', device: 'printer 1', deviceId: '123456789', balance: '51 meters', status: 'Online', active: true, rechargeRecords: [{ id: 'r1', date: '2025-01-15', amount: '200 meters', note: 'Initial' }, { id: 'r2', date: '2025-02-01', amount: '100 meters' }] }, { id: '2', locationId: '12345', category: 'Printer', device: 'printer2', deviceId: '113456789', balance: '155 meters', status: 'Online', active: true, rechargeRecords: [{ id: 'r3', date: '2025-01-20', amount: '300 meters' }] }, { id: '3', locationId: '12345', category: 'Sensor', device: 'sensor 1', deviceId: '103456789', balance: '', status: 'Online', active: true }, { id: '4', locationId: '12345', category: 'Sensor', device: 'sensor 2', deviceId: '093456789', balance: '', status: 'Online', active: true }, { id: '5', locationId: '12345', category: 'Sensor', device: 'sensor 3', deviceId: '083456789', balance: '', status: 'Online', active: false }, { id: '6', locationId: '12345', category: 'Scale', device: 'Scale 1', deviceId: '073456789', balance: '', status: 'Online', active: true }, { id: '7', locationId: '12345', category: 'E-label', device: 'e-label 1', deviceId: '063456789', balance: '', status: 'Online', active: true }, { id: '8', locationId: '12345', category: 'E-label', device: 'e-label 2', deviceId: '053456789', balance: '', status: 'Online', active: true }, { id: '9', locationId: '12345', category: 'E-label', device: 'e-label 3', deviceId: '043456789', balance: '', status: 'Offline', active: true }, { id: '10', locationId: '12345', category: 'E-label', device: 'e-label 4', deviceId: '033456789', balance: '', status: 'Offline', active: false }, { id: '11', locationId: '12345', category: 'E-label', device: 'e-label 5', deviceId: '023456789', balance: '', status: 'Online', active: true }, { id: '12', locationId: '12345', category: 'E-label', device: 'e-label 6', deviceId: '013456789', balance: '', status: 'Online', active: true }, { id: '13', locationId: '12345', category: 'E-label', device: 'e-label 7', deviceId: '003456789', balance: '', status: 'Online', active: true }, ]; export function DevicesView() { const [search, setSearch] = useState(''); const [devices, setDevices] = useState(INITIAL_DEVICES); const [filterCategory, setFilterCategory] = useState('all'); const [newDialogOpen, setNewDialogOpen] = useState(false); const [rechargeDialogDevice, setRechargeDialogDevice] = useState(null); // 新增设备:必须与 Location 绑定 const [newLocationId, setNewLocationId] = useState(''); const [newCategory, setNewCategory] = useState('Printer'); const [newDeviceName, setNewDeviceName] = useState(''); const [newDeviceId, setNewDeviceId] = useState(''); const filteredDevices = devices.filter((d) => { const matchSearch = !search || d.device.toLowerCase().includes(search.toLowerCase()) || d.deviceId.includes(search); const matchCategory = filterCategory === 'all' || d.category === filterCategory; return matchSearch && matchCategory; }); const handleAddDevice = () => { if (!newLocationId.trim()) return; // 规则1:必须选择 Location const loc = MOCK_LOCATIONS.find((l) => l.id === newLocationId); setDevices((prev) => [ ...prev, { id: String(prev.length + 1), locationId: newLocationId, category: newCategory, device: newDeviceName || `${newCategory} ${prev.filter((d) => d.category === newCategory).length + 1}`, deviceId: newDeviceId || String(100000000 + prev.length), balance: newCategory === 'Printer' ? '0 meters' : '', status: 'Online', active: true, rechargeRecords: newCategory === 'Printer' ? [] : undefined, }, ]); setNewLocationId(''); setNewCategory('Printer'); setNewDeviceName(''); setNewDeviceId(''); setNewDialogOpen(false); }; const toggleActive = (id: string) => { setDevices((prev) => prev.map((d) => (d.id === id ? { ...d, active: !d.active } : d))); }; const canBulkBind = filterCategory === 'Sensor' || filterCategory === 'E-label'; const canBulkImportExportEdit = ['Printer', 'Scale', 'Sensor', 'E-label'].includes(filterCategory) || filterCategory === 'all'; return (
{/* Toolbar:与 Products 一致样式 — Search 在前,Partner/Group/Location/Device Category 下拉,右侧 Bulk 与 New+ */}
setSearch(e.target.value)} className="pl-9 h-9 rounded-lg border border-black bg-white text-black" />
{canBulkBind && ( )} {canBulkImportExportEdit && ( <> )}
{/* Content Area:与 Products 一致 — 无内边距、bg-gray-50,表格包在白色圆角框内 */}
Location ID Device Category Device Device ID Balance Recharge Running Status Active {filteredDevices.map((row) => ( {row.locationId} {CATEGORY_LABELS[row.category]} {row.device} {row.deviceId} {row.balance || '—'} {row.category === 'Printer' ? ( ) : ( '—' )} {row.status}
toggleActive(row.id)} /> {row.active ? 'Active' : 'Inactive'}
))}
{/* New Device Dialog - 规则1:必须与 Location 绑定 */} Add New Device New devices must be bound to a location. Select a location first, then fill in device details.
setNewDeviceName(e.target.value)} />
setNewDeviceId(e.target.value)} />
{/* Printer Recharge Records Dialog - 规则4 */} !open && setRechargeDialogDevice(null)}> Recharge Records — {rechargeDialogDevice?.device} Balance: {rechargeDialogDevice?.balance ?? '—'}
{rechargeDialogDevice?.rechargeRecords?.length ? ( Date Amount Note {rechargeDialogDevice.rechargeRecords.map((r) => ( {r.date} {r.amount} {r.note ?? '—'} ))}
) : (

No recharge records yet.

)}
); }