无人机 管理 绑定逻辑
This commit is contained in:
@@ -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({
|
||||
|
||||
@@ -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 => <Tag color={s === 1 ? 'green' : 'default'}>{s === 1 ? '在线' : '离线'}</Tag> },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (_, record) => (
|
||||
<Space>
|
||||
<Tooltip title="清除人员绑定">
|
||||
<Button size="small" icon={<DisconnectOutlined />} onClick={() => handleUnbind([record.device_sn], 1)}>人</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="清除场站绑定">
|
||||
<Button size="small" icon={<DisconnectOutlined />} onClick={() => handleUnbind([record.device_sn], 2)}>场</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="清除组织绑定">
|
||||
<Button size="small" icon={<DisconnectOutlined />} onClick={() => handleUnbind([record.device_sn], 3)}>组</Button>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// 根据 Tab 过滤数据
|
||||
const filteredByTab = deviceList.filter(tabs.find(t => t.key === activeTab)?.filter || (() => false));
|
||||
|
||||
@@ -149,12 +254,65 @@ export default function DeviceManagementPage() {
|
||||
<Tabs.TabPane key="all" tab="设备管理" />
|
||||
<Tabs.TabPane key="camera" tab="摄像头管理" />
|
||||
<Tabs.TabPane key="smart" tab="智能装备" />
|
||||
<Tabs.TabPane key="drone" tab="无人机管理" />
|
||||
<Tabs.TabPane key="serialGenerate" tab="机器人生成" />
|
||||
</Tabs>
|
||||
|
||||
{/* ====================== 判断显示内容 ====================== */}
|
||||
{activeTab === 'serialGenerate' ? (
|
||||
<SerialNumGenerate />
|
||||
) : activeTab === 'drone' ? (
|
||||
<>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<Space>
|
||||
<Button type="primary" icon={<LinkOutlined />} onClick={() => setBindModalVisible(true)}>绑定无人机</Button>
|
||||
<Button disabled={selectedDroneKeys.length === 0} onClick={() => handleUnbind(selectedDroneKeys, 1)}>批量解绑(人)</Button>
|
||||
<Button disabled={selectedDroneKeys.length === 0} onClick={() => handleUnbind(selectedDroneKeys, 2)}>批量解绑(场)</Button>
|
||||
<Button disabled={selectedDroneKeys.length === 0} onClick={() => handleUnbind(selectedDroneKeys, 3)}>批量解绑(组)</Button>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<Table
|
||||
rowSelection={{
|
||||
selectedRowKeys: selectedDroneKeys,
|
||||
onChange: setSelectedDroneKeys,
|
||||
}}
|
||||
rowKey="device_sn"
|
||||
columns={droneColumns}
|
||||
dataSource={droneList}
|
||||
loading={loading}
|
||||
pagination={{ showSizeChanger: true, showTotal: t => `共 ${t} 条` }}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
title="绑定无人机"
|
||||
open={bindModalVisible}
|
||||
onCancel={() => setBindModalVisible(false)}
|
||||
onOk={() => bindForm.submit()}
|
||||
width={500}
|
||||
>
|
||||
<Form form={bindForm} layout="vertical" onFinish={handleBind} initialValues={{ userId: userInfo?.userId }}>
|
||||
<Form.Item label="无人机 SN (多个用逗号隔开)" name="sns" rules={[{ required: true, message: '请输入 SN' }]}>
|
||||
<Input.TextArea placeholder="例如: SN001, SN002" rows={3} />
|
||||
</Form.Item>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item label="场站 ID (siteId)" name="siteId" rules={[{ required: true, message: '请输入场站 ID' }]}>
|
||||
<InputNumber style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item label="组织 ID (orgId)" name="orgId" rules={[{ required: true, message: '请输入组织 ID' }]}>
|
||||
<InputNumber style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form.Item label="用户 ID (userId)" name="userId">
|
||||
<InputNumber style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
) : (
|
||||
// 显示原来的设备列表
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user