diff --git a/src/api/device.ts b/src/api/device.ts
index c7c26f8..28380d5 100644
--- a/src/api/device.ts
+++ b/src/api/device.ts
@@ -139,7 +139,25 @@ export function changeCameraPlane(data) {
})
}
-//直播心跳
+// 绑定无人机
+export function bindDrone(data) {
+ return request({
+ url: '/iot/UAV/bind',
+ method: 'post',
+ data
+ })
+}
+
+// 解绑无人机
+export function unbindDrone(data) {
+ return request({
+ url: '/iot/UAV/unbind',
+ method: 'post',
+ data
+ })
+}
+
+// 直播心跳
export function postLiveHeartbeat(data) {
return request({
diff --git a/src/components/SystemSetting/DeviceManagement.tsx b/src/components/SystemSetting/DeviceManagement.tsx
index 327efa2..b15da1e 100644
--- a/src/components/SystemSetting/DeviceManagement.tsx
+++ b/src/components/SystemSetting/DeviceManagement.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
import {
Table,
Input,
@@ -12,6 +12,10 @@ import {
Tabs,
Card,
InputNumber,
+ Checkbox,
+ Tooltip,
+ Row,
+ Col,
} from 'antd';
import {
SearchOutlined,
@@ -19,8 +23,14 @@ import {
PlusOutlined,
EditOutlined,
DeleteOutlined,
+ LinkOutlined,
+ DisconnectOutlined,
} from '@ant-design/icons';
import SerialNumGenerate from "./SerialNumGenerate"
+import { getPlaneDeviceList, bindDrone, unbindDrone } from '@/api/device';
+import { useSelector } from 'react-redux';
+import { RootState } from '@/src/store';
+import utils from '@/lib/utils';
// 模拟数据
const allDeviceList = [
@@ -54,6 +64,101 @@ export default function DeviceManagementPage() {
const [loading, setLoading] = useState(false);
const [deviceList, setDeviceList] = useState(allDeviceList);
+ // 无人机相关状态
+ const { userInfo } = useSelector((state: RootState) => state.user);
+ const [droneList, setDroneList] = useState([]);
+ const [bindModalVisible, setBindModalVisible] = useState(false);
+ const [bindForm] = Form.useForm();
+ const [selectedDroneKeys, setSelectedDroneKeys] = useState([]);
+
+ const fetchDroneList = async () => {
+ setLoading(true);
+ try {
+ const res: any = await getPlaneDeviceList();
+ if (res.code == 200) {
+ setDroneList(res?.data?.detail || []);
+ }
+ } catch (err) {
+ utils.message.error('获取无人机列表失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ if (activeTab === 'drone') {
+ fetchDroneList();
+ }
+ }, [activeTab]);
+
+ const handleBind = async (values) => {
+ try {
+ const payload = {
+ siteId: values.siteId,
+ orgId: values.orgId,
+ userId: values.userId || userInfo?.userId,
+ sns: values.sns.split(',').map(s => s.trim()),
+ };
+ const res: any = await bindDrone(payload);
+ if (res.code === 200) {
+ utils.message.success('绑定成功');
+ setBindModalVisible(false);
+ bindForm.resetFields();
+ fetchDroneList();
+ } else {
+ utils.message.error(res.msg || '绑定失败');
+ }
+ } catch (err) {
+ utils.message.error('操作异常');
+ }
+ };
+
+ const handleUnbind = (sns, type) => {
+ const typeText = { 1: '人员', 2: '场站', 3: '组织' }[type];
+ Modal.confirm({
+ title: '确认解绑',
+ content: `确定要为选中的无人机清除${typeText}绑定吗?`,
+ onOk: async () => {
+ try {
+ const res: any = await unbindDrone({ sns, type });
+ if (res.code === 200) {
+ utils.message.success('解绑成功');
+ fetchDroneList();
+ setSelectedDroneKeys([]);
+ } else {
+ utils.message.error(res.msg || '解绑失败');
+ }
+ } catch (err) {
+ utils.message.error('操作异常');
+ }
+ }
+ });
+ };
+
+ const droneColumns = [
+ { title: '设备名称', dataIndex: 'drone_callsign', key: 'name' },
+ { title: 'SN码', dataIndex: 'device_sn', key: 'sn' },
+ { title: '网关SN', dataIndex: 'gateway_sn', key: 'gsn' },
+ { title: '状态', dataIndex: 'onlineStatus', key: 'status', render: s =>