import { useEffect, useState, useCallback } from 'react'; import { Card, Table, Tag, Button, Modal, Form, Input, Select, InputNumber, Space, message } from 'antd'; import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; import { getChargingPiles, createChargingPile, updateChargingPile, deleteChargingPile, getChargingStations, getChargingBrands } from '../../services/api'; const workStatusMap: Record = { idle: { color: 'green', text: '空闲' }, charging: { color: 'blue', text: '充电中' }, fault: { color: 'red', text: '故障' }, offline: { color: 'default', text: '离线' }, }; const typeOptions = [ { label: '交流慢充', value: 'AC_slow' }, { label: '直流快充', value: 'DC_fast' }, { label: '直流超充', value: 'DC_superfast' }, ]; const connectorOptions = [ { label: 'GB/T', value: 'GB_T' }, { label: 'CCS', value: 'CCS' }, { label: 'CHAdeMO', value: 'CHAdeMO' }, ]; export default function Piles() { const [data, setData] = useState({ total: 0, items: [] }); const [stations, setStations] = useState([]); const [brands, setBrands] = useState([]); const [loading, setLoading] = useState(true); const [showModal, setShowModal] = useState(false); const [editing, setEditing] = useState(null); const [form] = Form.useForm(); const [filters, setFilters] = useState>({ page: 1, page_size: 20 }); const loadData = useCallback(async () => { setLoading(true); try { const cleanQuery: Record = {}; Object.entries(filters).forEach(([k, v]) => { if (v !== undefined && v !== null && v !== '') cleanQuery[k] = v; }); const res = await getChargingPiles(cleanQuery); setData(res as any); } catch { message.error('加载充电桩失败'); } finally { setLoading(false); } }, [filters]); const loadMeta = async () => { try { const [st, br] = await Promise.all([ getChargingStations({ page_size: 100 }), getChargingBrands(), ]); setStations((st as any).items || []); setBrands(br as any[]); } catch {} }; useEffect(() => { loadMeta(); }, []); useEffect(() => { loadData(); }, [filters, loadData]); const handleFilterChange = (key: string, value: any) => { setFilters(prev => ({ ...prev, [key]: value, page: 1 })); }; const openAddModal = () => { setEditing(null); form.resetFields(); form.setFieldsValue({ status: 'active', work_status: 'offline' }); setShowModal(true); }; const openEditModal = (record: any) => { setEditing(record); form.setFieldsValue(record); setShowModal(true); }; const handleSubmit = async (values: any) => { try { if (editing) { await updateChargingPile(editing.id, values); message.success('充电桩更新成功'); } else { await createChargingPile(values); message.success('充电桩创建成功'); } setShowModal(false); form.resetFields(); loadData(); } catch (e: any) { message.error(e?.detail || '操作失败'); } }; const handleDelete = async (id: number) => { try { await deleteChargingPile(id); message.success('已停用'); loadData(); } catch { message.error('操作失败'); } }; const columns = [ { title: '终端编码', dataIndex: 'encoding', width: 140 }, { title: '名称', dataIndex: 'name', width: 150, ellipsis: true }, { title: '所属充电站', dataIndex: 'station_id', width: 150, render: (id: number) => { const s = stations.find((st: any) => st.id === id); return s ? s.name : id; }}, { title: '类型', dataIndex: 'type', width: 100, render: (v: string) => typeOptions.find(o => o.value === v)?.label || v || '-' }, { title: '额定功率(kW)', dataIndex: 'rated_power_kw', width: 120, render: (v: number) => v != null ? v : '-' }, { title: '品牌', dataIndex: 'brand', width: 100 }, { title: '型号', dataIndex: 'model', width: 100 }, { title: '接口类型', dataIndex: 'connector_type', width: 100 }, { title: '工作状态', dataIndex: 'work_status', width: 100, render: (s: string) => { const st = workStatusMap[s] || { color: 'default', text: s || '-' }; return {st.text}; }}, { title: '状态', dataIndex: 'status', width: 80, render: (s: string) => ( {s === 'active' ? '启用' : '停用'} )}, { title: '操作', key: 'action', width: 150, fixed: 'right' as const, render: (_: any, record: any) => ( )}, ]; return ( } onClick={openAddModal}>添加充电桩 }> handleFilterChange('type', v)} /> ({ label: s.name, value: s.id }))} /> ({ label: b.brand_name, value: b.brand_name }))} />