import React, { useState, useEffect } from 'react'; import { Table, Input, Button, Form, Select, Space, Tag, Modal, Checkbox, Tooltip, Typography, App, } from 'antd'; const { Text } = Typography; import { ReloadOutlined, LinkOutlined, DisconnectOutlined, } from '@ant-design/icons'; import { getPlaneDeviceList, bindDrone, unbindDrone, } from '@/api/device'; import { getOrgList } from '@/api/organization/index'; import { getSiteByOrgId, getStationList } from '@/api/stationManage/index'; import { getUser } from '@/api/user/index'; import { useSelector } from 'react-redux'; import { RootState } from '@/src/store'; import utils from '@/lib/utils'; interface DroneManagementProps { allOrgOptions: any[]; allSiteOptions: any[]; allUserOptions: any[]; onAllDataNeedRefresh?: () => void; } export default function DroneManagement({ allOrgOptions, allSiteOptions, allUserOptions, onAllDataNeedRefresh, }: DroneManagementProps) { const { modal } = App.useApp(); const { userInfo } = useSelector((state: RootState) => state.user); const { stationId, currentStation } = useSelector((state: RootState) => state.station); const [loading, setLoading] = useState(false); const [droneList, setDroneList] = useState([]); const [bindModalVisible, setBindModalVisible] = useState(false); const [bindForm] = Form.useForm(); const [selectedDroneKeys, setSelectedDroneKeys] = useState([]); const [droneParams, setDroneParams] = useState({ pageNum: 1, pageSize: 20, sn: '', status: '' }); const [droneTotal, setDroneTotal] = useState(0); const [droneOrgOptions, setDroneOrgOptions] = useState([]); const [droneSiteOptions, setDroneSiteOptions] = useState([]); const [droneUserOptions, setDroneUserOptions] = useState([]); const isAdmin = userInfo?.roleKey === 'admin'; const isManager = userInfo?.roleKey === 'manager' || userInfo?.roleKey === 'Manager'; const orgFieldDisabled = !isAdmin; const siteFieldDisabled = !(isAdmin || isManager); const userFieldDisabled = false; const defaultOrgId = currentStation?.orgId || userInfo?.orgId; const defaultSiteId = stationId || currentStation?.siteId || currentStation?.id; const defaultUserId = userInfo?.userId; const fetchDroneList = async () => { setLoading(true); try { const res = await getPlaneDeviceList(droneParams); if (res.code === 200) { setDroneList(res.rows || []); setDroneTotal(res.total || res.rows?.length || 0); } } catch (err) { utils.message.error('获取无人机列表失败'); } finally { setLoading(false); } }; const fetchOrgs = async () => { try { const res = await getOrgList({}); if (res.code === 200) { setDroneOrgOptions(res.rows || []); } return res; } catch (err) { console.error('获取组织列表失败', err); return null; } }; const fetchSites = async (orgId) => { try { const res = await getSiteByOrgId({ id: orgId }); if (res.code === 200) { setDroneSiteOptions(res.data || []); } return res; } catch (err) { console.error(err); return null; } }; const fetchUsers = async (siteId) => { try { const res = await getUser({ siteId, pageNum: 1, pageSize: 1000 }); if (res.code === 200) { setDroneUserOptions(res.rows || []); } return res; } catch (err) { console.error(err); return null; } }; useEffect(() => { fetchDroneList(); }, [droneParams]); const openBindModal = async () => { if (!selectedDroneKeys.length) { return utils.message.warning('请先在列表中选中需要绑定的无人机'); } bindForm.resetFields(); setBindModalVisible(true); setDroneOrgOptions([]); setDroneSiteOptions([]); setDroneUserOptions([]); }; useEffect(() => { if (!bindModalVisible) { bindForm.resetFields(); return; } const fetchAndSetForm = async () => { const orgRes = await fetchOrgs(); const orgList = orgRes?.code === 200 ? (orgRes?.rows || []) : []; setDroneOrgOptions(orgList); const finalOrgId = defaultOrgId && orgList.some(o => (o.id || o.orgId) == defaultOrgId) ? defaultOrgId : (orgList[0]?.id || orgList[0]?.orgId); let siteList = []; if (finalOrgId) { const siteRes = await fetchSites(finalOrgId); siteList = siteRes?.code === 200 ? (siteRes?.data || []) : []; } setDroneSiteOptions(siteList); const finalSiteId = defaultSiteId && siteList.some(s => (s.id || s.siteId) == defaultSiteId) ? defaultSiteId : (siteList[0]?.id || siteList[0]?.siteId); let userList = []; if (finalSiteId) { const userRes = await fetchUsers(finalSiteId); userList = userRes?.code === 200 ? (userRes?.rows || []) : []; } setDroneUserOptions(userList); const finalUserId = defaultUserId && userList.some(u => u.userId == defaultUserId) ? defaultUserId : (userList[0]?.userId); requestAnimationFrame(() => { bindForm.setFieldsValue({ sns: selectedDroneKeys.join(', '), orgId: finalOrgId, siteId: finalSiteId, userId: finalUserId, }); }); }; fetchAndSetForm(); }, [bindModalVisible, defaultOrgId, defaultSiteId, defaultUserId, selectedDroneKeys]); const handleBind = async (values) => { try { const payload = { siteId: values.siteId, orgId: values.orgId, userId: values.userId, sns: values.sns.split(',').map(s => s.trim()), }; const res = await bindDrone(payload); if (res.code === 200 && res.data == true) { utils.message.success('绑定成功'); setBindModalVisible(false); setSelectedDroneKeys([]); bindForm.resetFields(); fetchDroneList(); onAllDataNeedRefresh?.(); } else { utils.message.error(res.msg || '绑定失败'); } } catch (err) { utils.message.error('操作异常'); } }; const handleUnbind = (sns, type) => { const validSns = (sns || []).filter(item => item !== null && item !== undefined && item !== '' && item.trim() !== '' ); if (validSns.length === 0) { return utils.message.warning('未选择有效设备,无法解绑'); } const typeText = { 1: '人员', 2: '场站', 3: '组织' }[type]; modal.confirm({ title: '确认解绑', content: `确定要为选中的无人机清除${typeText}绑定吗?`, okText: '确定', cancelText: '取消', onOk: async () => { try { const res = await unbindDrone({ sns: validSns, type }); if (res.code === 200) { utils.message.success('解绑成功'); fetchDroneList(); setSelectedDroneKeys([]); onAllDataNeedRefresh?.(); } else { utils.message.error(res.msg || '解绑失败'); } } catch (err) { utils.message.error('操作异常'); } } }); }; const droneColumns = [ { title: '设备名称', width: 150, dataIndex: 'drone_callsign', key: 'name' }, { title: 'SN码', width: 180, dataIndex: 'device_sn', key: 'sn' }, { title: '机场SN', width: 150, dataIndex: 'gateway_sn', key: 'gsn' }, { title: '所属组织', width: 150, key: 'orgName', render: (_, record) => { const org = allOrgOptions.find(o => (o.orgId || o.id) == record.orgId); return org ? (org.orgName || org.name) : 未绑定; }, }, { title: '所属场站', width: 150, key: 'siteName', render: (_, record) => { const site = allSiteOptions.find(s => (s.siteId || s.id) == record.siteId); return site ? (site.siteName || site.name) : 未绑定; }, }, { title: '负责人', width: 150, key: 'userName', render: (_, record) => { const user = allUserOptions.find(u => u.userId == record.userId); return user ? (user.nickName || user.userName) : 未绑定; }, }, { title: '状态', width: 150, dataIndex: 'onlineStatus', key: 'status', render: s => {s === 1 ? '在线' : '离线'} }, { title: '操作', key: 'action', fixed: 'right' as const, width: 250, render: (_, record: any) => ( ), }, ]; const selectorgId = Form.useWatch('orgId', bindForm); const selectsiteId = Form.useWatch('siteId', bindForm); useEffect(() => { if (selectorgId) { fetchSites(selectorgId); } }, [selectorgId]); useEffect(() => { if (selectsiteId) { fetchUsers(selectsiteId); } }, [selectsiteId]); return ( <>
setDroneParams({ ...droneParams, sn: e.target.value })} />
`共 ${t} 条`, onChange: (page, pageSize) => { setDroneParams({ ...droneParams, pageNum: page, pageSize }); }, }} scroll={{ y: 'auto', x: '700px' }} /> 绑定无人机 } open={bindModalVisible} onCancel={() => { setBindModalVisible(false); setDroneOrgOptions([]); setDroneSiteOptions([]); setDroneUserOptions([]); bindForm.resetFields(); }} destroyOnClose={false} onOk={() => bindForm.submit()} width={540} >
已选无人机({selectedDroneKeys.length}台)SN} name="sns" rules={[{ required: true, message: '请输入 SN' }]}> 所属组织 } name="orgId" rules={[{ required: true, message: '请选择组织' }]} > 所属场站 } name="siteId" rules={[{ required: !siteFieldDisabled, message: '请选择场站' }]} >
); }