From 3ea0d713d2ee834b1ade8e68af048f2c888a4757 Mon Sep 17 00:00:00 2001
From: mmc <1556375442@qq.com>
Date: Mon, 25 May 2026 09:27:20 +0800
Subject: [PATCH] =?UTF-8?q?=E6=89=A7=E8=A1=8C=E4=BB=BB=E5=8A=A1=E6=8E=A5?=
=?UTF-8?q?=E5=8F=A3=E5=A2=9E=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/devices/WayLinePage.tsx | 137 ++++++++++++++++++++++++-
1 file changed, 134 insertions(+), 3 deletions(-)
diff --git a/src/components/devices/WayLinePage.tsx b/src/components/devices/WayLinePage.tsx
index d2a1a6a..30cf379 100644
--- a/src/components/devices/WayLinePage.tsx
+++ b/src/components/devices/WayLinePage.tsx
@@ -14,9 +14,9 @@ import {
import {
Plane, Navigation, Wind, Thermometer, Droplets, Satellite,
LayoutGrid, Clock, CheckCircle2, AlertCircle, Zap, Waves,
- Calendar, User, TrendingUp, Maximize2
+ Calendar, User, TrendingUp, Maximize2, Play, Square, X, MapPin, RotateCw
} from 'lucide-react';
-import { getsinglePlan, getsinglePlanTrack } from '@/api/device';
+import { getsinglePlan, getsinglePlanTrack, updateFlightTaskStatus, postFlightCommmand } from '@/api/device';
import dayjs from 'dayjs';
import utils from '@/lib/utils';
import CesiumMap from '../Map';
@@ -44,6 +44,14 @@ export default function WayLinePage({ planedevices }) {
const [points, setPoints] = useState([]);
+ // 任务控制相关状态
+ const [selectedTask, setSelectedTask] = useState(null);
+ const [taskstatus, setTaskStatus] = useState('suspended');
+ const [isReturningHome, setIsReturningHome] = useState(false);
+ const [isTaskPaused, setIsTaskPaused] = useState(false);
+ const [flightCommandLoading, setFlightCommandLoading] = useState(false);
+ const [loading, setLoading] = useState(false);
+
// 顶部统计
const topCards = [
{ title: '今日航线计划', value: '18', unit: '条', trend: '较昨日 +2', trendColor: '#00B42A', icon: , color: '#165DFF' },
@@ -168,6 +176,7 @@ export default function WayLinePage({ planedevices }) {
// 表格行点击查看轨迹
const handleRowClick = async (record) => {
+ setSelectedTask(record); // 记录当前选中的任务
try {
const res = await getsinglePlanTrack(record);
if (res.code === 0 && res.data.track?.points?.length) {
@@ -204,6 +213,72 @@ export default function WayLinePage({ planedevices }) {
};
const { waitList, runList, finishList } = groupBoardData();
+ // 指令下发逻辑
+ const sendFlightCommand = async (command: 'return_home' | 'return_home_cancel' | 'flighttask_pause' | 'flighttask_recovery') => {
+ if (!listDrone?.device_sn) {
+ utils.message.warning('未选中无人机或无人机SN不存在');
+ return;
+ }
+
+ setFlightCommandLoading(true);
+ const data = {
+ command,
+ deviceSn: listDrone.device_sn,
+ }
+ try {
+ const res: any = await postFlightCommmand(data);
+ if (res.code === 200 || res.code === 0) {
+ utils.message.success('指令下发成功');
+ // 切换状态
+ if (command === 'return_home') setIsReturningHome(true);
+ if (command === 'return_home_cancel') setIsReturningHome(false);
+ if (command === 'flighttask_pause') setIsTaskPaused(true);
+ if (command === 'flighttask_recovery') setIsTaskPaused(false);
+ } else {
+ utils.message.error(res.msg || '指令下发失败');
+ }
+ } catch (err) {
+ utils.message.error('接口请求异常');
+ } finally {
+ setFlightCommandLoading(false);
+ }
+ };
+
+ // 任务状态更新逻辑
+ const updateTaskStatus = async (taskId: string, status: string) => {
+ if (!taskId) {
+ utils.message.warning('请先选择航线任务');
+ return;
+ }
+ setLoading(true);
+ try {
+ const res: any = await updateFlightTaskStatus(taskId, status);
+ if (res.code === 200 || res.code === 0) {
+ const statusText = {
+ executing: '任务执行成功',
+ suspended: '任务已挂起',
+ restored: '任务已继续',
+ return_home: '任务已返航'
+ }[status] || '状态更新成功';
+
+ if (status === "suspended") {
+ setTaskStatus('suspended');
+ } else {
+ setTaskStatus('restored');
+ }
+ utils.message.success(statusText);
+ // 刷新任务列表
+ getListTask();
+ } else {
+ utils.message.error(res.msg || '操作失败');
+ }
+ } catch (err) {
+ utils.message.error('操作接口异常');
+ } finally {
+ setLoading(false);
+ }
+ };
+
return (
@@ -310,7 +385,7 @@ export default function WayLinePage({ planedevices }) {
columns={taskColumns}
dataSource={taskList}
pagination={false}
- scroll={{ y: 260 }}
+ scroll={{ y: 'auto', maxHeight: 260 }}
style={{ height: '100%' }}
onRow={(record) => ({
onClick: () => handleRowClick(record),
@@ -401,6 +476,62 @@ export default function WayLinePage({ planedevices }) {
+
+
+ {/* 执行/挂起/继续 逻辑 */}
+ {selectedTask?.status === 'executing' || selectedTask?.status === 'running' || selectedTask?.status === 'restored' ? (
+ }
+ onClick={() => updateTaskStatus(selectedTask?.uuid, 'suspended')}
+ loading={loading}
+ // 统一样式:高度36 + 圆角18 + 字重600 + 图标文字居中
+ style={{ height: 36, borderRadius: 18, fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 4 }}
+ >
+ 挂起任务
+
+ ) : (
+ }
+ onClick={() => {
+ if (selectedTask?.status === 'suspended') {
+ updateTaskStatus(selectedTask?.uuid, 'restored');
+ } else {
+ updateTaskStatus(selectedTask?.uuid, 'executing');
+ }
+ }}
+ loading={loading}
+ // 统一样式:主色#165DFF + 高度36 + 圆角18 + 字重600
+ style={{ background: '#165DFF', height: 36, borderRadius: 18, fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 4 }}
+ >
+ {selectedTask?.status === 'suspended' ? '继续任务' : '执行任务'}
+
+ )}
+ {/* 返航逻辑 */}
+ : }
+ onClick={() => sendFlightCommand(isReturningHome ? 'return_home_cancel' : 'return_home')}
+ loading={flightCommandLoading}
+ style={{ background: '#165DFF', height: 36, borderRadius: 18, fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 4 }}
+ >
+ {isReturningHome ? '取消返航' : '返航'}
+
+
+ {/* 暂停/恢复逻辑 */}
+ : }
+ onClick={() => sendFlightCommand(isTaskPaused ? 'flighttask_recovery' : 'flighttask_pause')}
+ loading={flightCommandLoading}
+ style={{ height: 36, borderRadius: 18, fontWeight: 600, display: 'inline-flex', alignItems: 'center', gap: 4 }}
+ >
+ {isTaskPaused ? '恢复任务' : '暂停任务'}
+
+