diff --git a/src/api/api.ts b/src/api/api.ts index 2974290..87fdf5f 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -101,90 +101,7 @@ export function loginApi(data) { // 获取所有航线 -export function getsinglePlan(data) { - return api({ - url: `/iot/UAV/getFlightTask?sn=${data.gateway_sn}`, - method: 'get', - }) -} -// 获取航线轨迹 iot/UAV/getFlightTaskTrack - -export function getsinglePlanTrack(data) { - return api({ - url: `/iot/UAV/getFlightTaskTrack?taskId=${data.uuid}`, - method: 'get', - }) -} - -//上传航线 - -export function uploadWayLine(data) { - return api({ - url: '/iot/UAV/uploadWayline', - method: 'post', - data: data, // 上传文件必须用 data,不能用 params - headers: { - 'Content-Type': 'multipart/form-data' // 上传文件必加! - } - }) -} - -//创建航线任务 -export function createWaylineTask(data) { - return api({ - url: '/iot/UAV/createFlightTask', - method: 'post', - data: data, - }) -} - - - -export function updateFlightTaskStatus(taskId, status) { - return api({ - url: '/iot/UAV/updateFlightTaskStatus', - method: 'post', - params: { taskId, status } - }) -} - -export function getFlightTaskDetail(taskId) { - return api({ - url: '/iot/UAV/getFlightTaskDetail', - method: 'get', - params: { taskId } - }) -} - -/// 航线列表 -export function getWayLine() { - return api({ - url: '/iot/UAV/getWayline', - method: 'get', - }) -} -//直播流 - - -///iot/UAV/flightTaskCommand -export function postFlightCommmand(data) { - return api({ - url: '/iot/UAV/flightTaskCommand', - method: 'post', - data - }) -} - -//切换相机 - -export function changeCamera(data) { - return api({ - url: '/iot/UAV/changeCamera', - method: 'post', - data - }) -} //直播心跳 diff --git a/src/components/devices/WayLinePage.tsx b/src/components/devices/WayLinePage.tsx index 1ba0cbd..dca95c7 100644 --- a/src/components/devices/WayLinePage.tsx +++ b/src/components/devices/WayLinePage.tsx @@ -1,141 +1,120 @@ import React, { useState, useEffect } from 'react'; import { Row, Col, Card, Button, Space, Table, Tag, Typography, Progress, Badge, - Tabs, Input, Switch, Divider, Tooltip, Timeline + Tabs, Input, Switch, Divider, Tooltip, Timeline, Select, message } from 'antd'; import { - PlusOutlined, ImportOutlined, NodeIndexOutlined, SafetyCertificateOutlined, - SaveOutlined, FullscreenOutlined, EnvironmentOutlined, RobotOutlined, + PlusOutlined, ImportOutlined, NodeIndexOutlined, + SaveOutlined, FullscreenOutlined, EnvironmentOutlined, BranchesOutlined, CloudOutlined, ThunderboltOutlined, CheckCircleOutlined, - InfoCircleOutlined, ClockCircleOutlined, RiseOutlined, FallOutlined, - SettingOutlined, WarningOutlined, ArrowRightOutlined, CloudSyncOutlined, + InfoCircleOutlined, ClockCircleOutlined, + SettingOutlined, WarningOutlined, ArrowRightOutlined, SearchOutlined, MoreOutlined, AimOutlined } from '@ant-design/icons'; import { - Plane, - Navigation, - Wind, - Thermometer, - Droplets, - Satellite, - LayoutGrid, - Clock, - CheckCircle2, - AlertCircle, - Zap, - Waves, - Calendar, - User, - TrendingUp, - GripVertical, - Maximize2, - Target + Plane, Navigation, Wind, Thermometer, Droplets, Satellite, + LayoutGrid, Clock, CheckCircle2, AlertCircle, Zap, Waves, + Calendar, User, TrendingUp, Maximize2 } from 'lucide-react'; -import { getsinglePlan } from '@/src/api/api'; +import { getsinglePlan } from '@/api/device'; +import dayjs from 'dayjs'; const { Text, Title } = Typography; -export default function WayLinePage() { - // 响应式字体大小 +export default function WayLinePage({ planedevices }) { const fontSmall = 'clamp(10px, 0.7vw, 11px)'; const fontNormal = 'clamp(12px, 0.75vw, 13px)'; const fontTitle = 'clamp(14px, 0.85vw, 16px)'; const fontLarge = 'clamp(18px, 1.1vw, 24px)'; const cardStyle = { borderRadius: 12, border: 'none', boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }; + const [selectedDrone, setSelectedDrone] = useState(null); + const [taskList, setTaskList] = useState([]); // 真实任务列表 - // 顶部统计卡片数据 + // 顶部统计 const topCards = [ + { title: '今日航线计划', value: '18', unit: '条', trend: '较昨日 +2', trendColor: '#00B42A', icon: , color: '#165DFF' }, + { title: '执行中任务', value: '6', unit: '个', desc: '进行中', icon: , color: '#165DFF' }, + { title: '待审批任务', value: '4', unit: '个', trend: '较昨日 -1', trendColor: '#F53F3F', icon: , color: '#FF7D00' }, + { title: '任务完成率', value: '92', unit: '%', trend: '较昨日 +6%', trendColor: '#00B42A', icon: , color: '#00B42A' }, + { title: 'AI 优化收益', value: '+7.8', unit: '%', trend: '较昨日 +1.2%', trendColor: '#00B42A', icon: , color: '#722ED1' }, + { title: '覆盖装备', value: '4 类 / 9 台', unit: '', desc: '全部在线', icon: , color: '#165DFF' }, + ]; + + // 获取真实任务 + const getTaskList = async (drone) => { + if (!drone || !drone.device_sn) return; + try { + const res = await getsinglePlan(drone); + if (res?.code === 0) { + setTaskList(res.data?.list || []); + } + } catch (err) { + message.error('获取任务失败'); + } + }; + + // 默认选中第一个无人机 + useEffect(() => { + if (planedevices?.length) { + setSelectedDrone(planedevices[0]); + } + }, [planedevices]); + + // 切换无人机时刷新任务 + useEffect(() => { + getTaskList(selectedDrone); + }, [selectedDrone]); + + // 任务状态颜色 + const getStatusTag = (status) => { + const map = { + success: { color: 'green', text: '成功' }, + running: { color: 'blue', text: '执行中' }, + failed: { color: 'red', text: '失败' }, + }; + const item = map[status] || { color: 'default', text: status }; + return {item.text}; + }; + + // 任务表格列 + const taskColumns = [ + { title: '任务名称', dataIndex: 'name', width: 260, ellipsis: true, fixed: "left" }, + + { title: '任务UUID', dataIndex: 'uuid', width: 260, ellipsis: true }, + { title: '设备SN', dataIndex: 'sn', width: 140 }, + { title: '状态', dataIndex: 'status', width: 80, render: getStatusTag }, { - title: '今日航线计划', - value: '18', - unit: '条', - trend: '较昨日 +2', - trendColor: '#00B42A', - icon: , - color: '#165DFF', - bg: 'linear-gradient(135deg, #E8F3FF 0%, #BAE0FF 100%)' + title: '开始时间', + dataIndex: 'begin_at', + width: 170, + render: t => t ? dayjs(t).format('YYYY-MM-DD HH:mm:ss') : '-' }, { - title: '执行中任务', - value: '6', - unit: '个', - desc: '进行中', - icon: , - color: '#165DFF', - bg: 'linear-gradient(135deg, #E8F3FF 0%, #BAE0FF 100%)' - }, - { - title: '待审批任务', - value: '4', - unit: '个', - trend: '较昨日 -1', - trendColor: '#F53F3F', - icon: , - color: '#FF7D00', - bg: 'linear-gradient(135deg, #FFF7E6 0%, #FFE4BA 100%)' - }, - { - title: '任务完成率', - value: '92', - unit: '%', - trend: '较昨日 +6%', - trendColor: '#00B42A', - icon: , - color: '#00B42A', - bg: 'linear-gradient(135deg, #E8FFEA 0%, #AFF0B5 100%)' - }, - { - title: 'AI 优化收益', - value: '+7.8', - unit: '%', - trend: '较昨日 +1.2%', - trendColor: '#00B42A', - icon: , - color: '#722ED1', - bg: 'linear-gradient(135deg, #F9F0FF 0%, #EFDBFF 100%)' - }, - { - title: '覆盖装备', - value: '4 类 / 9 台', - unit: '', - desc: '全部在线', - icon: , - color: '#165DFF', - bg: 'linear-gradient(135deg, #E8F3FF 0%, #BAE0FF 100%)' + title: '结束时间', + dataIndex: 'completed_at', + width: 170, + render: t => t ? dayjs(t).format('YYYY-MM-DD HH:mm:ss') : '-' }, ]; -//useEffect(()=>{ -// getsinglePlan().then(res=>{ - -// }) -//}) return (
- - {topCards.map((item, index) => (
-
- {React.cloneElement(item.icon as React.ReactElement, { size: 18 })} +
+ {React.cloneElement(item.icon, { size: 18 })}
-
{item.title}
+
{item.title}
{item.value} {item.unit}
-
+
{item.trend || item.desc}
@@ -145,143 +124,92 @@ export default function WayLinePage() { ))} - {/* 中间主要内容区 */} - {/* 左侧:航线编辑与路径规划 */} + {/* 地图卡片 */} 航线编辑与路径规划} + title={航线编辑与路径规划} size="small" extra={ - - - - - + + + +