创建任务

This commit is contained in:
mmc
2026-05-25 12:52:02 +08:00
parent a23f7e19aa
commit f86e4a2800
2 changed files with 195 additions and 76 deletions

View File

@@ -355,21 +355,17 @@ export default function CesiumMap({ realtimePosition, pathPoints = [], devices =
const [workspace, layerName] = layerFullName.split(':');
if (!workspace || !layerName) return;
const wmsUrl = `${baseUrl}/wms`;
console.log("addLayerFromList", wmsUrl, workspace, layerName, index)
addWmsLayerToCesium(wmsUrl, workspace, layerName, index);
}
function getLayerBoundsAndFit(wmsUrl, layerName) {
console.log('=== 获取图层范围开始 ===');
console.log('参数:', { wmsUrl, layerName });
const getCapabilitiesUrl = `${wmsUrl}?service=WMS&version=1.1.1&request=GetCapabilities`;
console.log('GetCapabilities URL:', getCapabilitiesUrl);
fetch(getCapabilitiesUrl)
.then(response => response.text())
.then(xmlText => {
console.log('GetCapabilities响应:', xmlText);
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
const layerElements = xmlDoc.getElementsByTagName('Layer');
@@ -435,7 +431,6 @@ export default function CesiumMap({ realtimePosition, pathPoints = [], devices =
const layerIdentifier = `${workspace}:${layerName}`;
let baseUrl = wmsUrl;
const cesiumLayers = [];
console.log(wmsUrl, workspace, layerName, index, "wmsUrl, workspace, layerName, index")
//if (index == 2) {
// flyToLayer(layerIdentifier, baseUrl);
//}

View File

@@ -70,12 +70,40 @@ export default function WayLinePage({ planedevices }) {
min_battery_capacity: 50,
task_type: 'immediate',
repeat_type: 'nonrepeating',
repeat_option: { interval: 1 },
repeat_option: {
interval: 1,
days_of_week: [],
days_of_month: [],
week_of_month: 1,
},
time_zone: Intl.DateTimeFormat().resolvedOptions().timeZone,
begin_at: null,
end_at: null,
recurring_task_start_time_list: [],
});
// 根据 repeat_type 自动构建接口需要的 repeat_option
const buildRepeatOption = () => {
const { repeat_type, repeat_option } = taskForm;
const { interval, days_of_week, days_of_month, week_of_month } = repeat_option;
if (repeat_type === 'nonrepeating') return undefined;
switch (repeat_type) {
case 'daily':
return { interval: Math.max(1, interval) };
case 'weekly':
return { interval, days_of_week };
case 'absolute_monthly':
return { interval, days_of_month };
case 'relative_monthly':
return { interval, week_of_month, days_of_week };
default:
return undefined;
}
};
const fetchWaylineList = async () => {
try {
@@ -130,9 +158,10 @@ export default function WayLinePage({ planedevices }) {
const payload = {
...taskForm,
wayline_uuid: waylineUuid,
// 如果是立即任务,begin_at 为 null 或当前时间戳
begin_at: taskForm.task_type === 'immediate' ? null : (taskForm.begin_at ? dayjs(taskForm.begin_at).unix() : null),
end_at: taskForm.end_at ? dayjs(taskForm.end_at).unix() : null,
//task_type: 'recurring',
repeat_type: taskForm.repeat_type,
// ✅ 直接传入处理好的对象
repeat_option: buildRepeatOption(),
recurring_task_start_time_list: taskForm.recurring_task_start_time_list.map(t => dayjs(t).unix()),
};
@@ -922,56 +951,68 @@ export default function WayLinePage({ planedevices }) {
</Row>
{/* ============================================== */}
{/* ✅ 创建航线任务弹窗(已放在页面底部) */}
{/* ============================================== */}
<Modal open={createTaskModal} title="创建航线任务" onCancel={resetModals} footer={null} maskClosable={false} width={600} scrollable>
<Modal
open={createTaskModal}
title="创建航线任务"
onCancel={resetModals}
footer={null}
maskClosable={false}
width={650}
>
<div className="py-4 space-y-4">
{/* 基础信息 */}
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1 text-black">航线名称 <span className="text-red-500">*</span></label>
<Input value={taskForm.name} onChange={(e) => setTaskForm({ ...taskForm, name: e.target.value })} placeholder="请输入航线名称" />
<label className="text-sm block mb-1">航线名称 <span className="text-red-500">*</span></label>
<Input
value={taskForm.name}
onChange={(e) => setTaskForm({ ...taskForm, name: e.target.value })}
placeholder="请输入"
/>
</div>
<div>
<label className="text-sm block mb-1 text-black">选择航线 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">选择航线 <span className="text-red-500">*</span></label>
<Select
showSearch
placeholder="请选择航线"
value={waylineUuid}
onChange={setWaylineUuid}
options={waylineList}
style={{ width: '100%' }}
locale={{ emptyText: '暂无数据' }}
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1 text-black">机场SN <span className="text-red-500">*</span></label>
<Input value={taskForm.sn} onChange={(e) => setTaskForm({ ...taskForm, sn: e.target.value })} placeholder="机场SN" disabled />
<label className="text-sm block mb-1">机场SN <span className="text-red-500">*</span></label>
<Input value={taskForm.sn} disabled />
</div>
<div>
<label className="text-sm block mb-1 text-black">降落地场SN</label>
<Input value={taskForm.landing_dock_sn} onChange={(e) => setTaskForm({ ...taskForm, landing_dock_sn: e.target.value })} placeholder="可不填" />
<label className="text-sm block mb-1">降落地场SN</label>
<Input
value={taskForm.landing_dock_sn}
onChange={(e) => setTaskForm({ ...taskForm, landing_dock_sn: e.target.value })}
/>
</div>
</div>
{/* 飞行参数 */}
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1 text-black">返航高度(m) <span className="text-red-500">*</span></label>
<InputNumber min={0} value={taskForm.rth_altitude} onChange={(val) => setTaskForm({ ...taskForm, rth_altitude: val || 0 })} style={{ width: '100%' }} />
<label className="text-sm block mb-1">返航高度(m)</label>
<InputNumber
min={0}
value={taskForm.rth_altitude}
onChange={(v) => setTaskForm({ ...taskForm, rth_altitude: v })}
style={{ width: '100%' }}
/>
</div>
<div>
<label className="text-sm block mb-1 text-black">返航模式 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">返航模式</label>
<Select
value={taskForm.rth_mode}
onChange={(val) => setTaskForm({ ...taskForm, rth_mode: val })}
options={[
{ label: '智能高度', value: 'optimal' },
{ label: '设定高度', value: 'preset' }
]}
onChange={(v) => setTaskForm({ ...taskForm, rth_mode: v })}
options={[{ label: '智能', value: 'optimal' }, { label: '预设', value: 'preset' }]}
style={{ width: '100%' }}
/>
</div>
@@ -979,26 +1020,20 @@ export default function WayLinePage({ planedevices }) {
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1 text-black">航线精度 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">航线精度</label>
<Select
value={taskForm.wayline_precision_type}
onChange={(val) => setTaskForm({ ...taskForm, wayline_precision_type: val })}
options={[
{ label: 'GPS模式(无需RTK收敛)', value: 'gps' },
{ label: 'RTK高精度(需等待收敛)', value: 'rtk' }
]}
onChange={(v) => setTaskForm({ ...taskForm, wayline_precision_type: v })}
options={[{ label: 'GPS', value: 'gps' }, { label: 'RTK', value: 'rtk' }]}
style={{ width: '100%' }}
/>
</div>
<div>
<label className="text-sm block mb-1 text-black">自动断点续飞 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">断点续飞</label>
<Select
value={taskForm.resumable_status}
onChange={(val) => setTaskForm({ ...taskForm, resumable_status: val })}
options={[
{ label: '自动断点续飞', value: 'auto' },
{ label: '手动断点续飞', value: 'manual' }
]}
onChange={(v) => setTaskForm({ ...taskForm, resumable_status: v })}
options={[{ label: '自动', value: 'auto' }, { label: '手动', value: 'manual' }]}
style={{ width: '100%' }}
/>
</div>
@@ -1006,102 +1041,191 @@ export default function WayLinePage({ planedevices }) {
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1 text-black">最低执行电量(%) <span className="text-red-500">*</span></label>
<InputNumber min={50} max={100} value={taskForm.min_battery_capacity} onChange={(val) => setTaskForm({ ...taskForm, min_battery_capacity: val || 50 })} style={{ width: '100%' }} />
<label className="text-sm block mb-1">最低电量(%)</label>
<InputNumber
min={50}
max={100}
value={taskForm.min_battery_capacity}
onChange={(v) => setTaskForm({ ...taskForm, min_battery_capacity: v })}
style={{ width: '100%' }}
/>
</div>
<div>
<label className="text-sm block mb-1 text-black">任务航线类型 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">任务类型</label>
<Select
value={taskForm.task_type}
onChange={(val) => setTaskForm({ ...taskForm, task_type: val })}
onChange={(v) => setTaskForm({ ...taskForm, task_type: v })}
options={[
{ label: '立即任务', value: 'immediate' },
{ label: '单次定时任务', value: 'timed' },
{ label: '重复任务', value: 'recurring' },
{ label: '连续任务', value: 'continuous' },
{ label: '立即', value: 'immediate' },
//{ label: '单次定时', value: 'timed' },
//{ label: '重复', value: 'recurring' },
//{ label: '连续', value: 'continuous' },
]}
style={{ width: '100%' }}
/>
</div>
</div>
{/* 根据任务类型显示不同字段 */}
{/* 时间选择 */}
{(taskForm.task_type === 'timed' || taskForm.task_type === 'recurring' || taskForm.task_type === 'continuous') && (
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1 text-black">开始时间 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">开始时间</label>
<DatePicker
showTime
placeholder="开始时间"
value={taskForm.begin_at}
onChange={(v) => setTaskForm({ ...taskForm, begin_at: v })}
style={{ width: '100%' }}
value={taskForm.begin_at ? dayjs(taskForm.begin_at) : null}
onChange={(val) => setTaskForm({ ...taskForm, begin_at: val })}
/>
</div>
{(taskForm.task_type === 'recurring' || taskForm.task_type === 'continuous') && (
<div>
<label className="text-sm block mb-1 text-black">结束时间 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">结束时间</label>
<DatePicker
showTime
placeholder="结束时间"
value={taskForm.end_at}
onChange={(v) => setTaskForm({ ...taskForm, end_at: v })}
style={{ width: '100%' }}
value={taskForm.end_at ? dayjs(taskForm.end_at) : null}
onChange={(val) => setTaskForm({ ...taskForm, end_at: val })}
/>
</div>
)}
</div>
)}
{/* 重复任务配置 repeat_option 对象绑定 */}
{taskForm.task_type === 'recurring' && (
<>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1 text-black">重复模式 <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">重复模式</label>
<Select
value={taskForm.repeat_type}
onChange={(val) => setTaskForm({ ...taskForm, repeat_type: val })}
onChange={(v) => setTaskForm({ ...taskForm, repeat_type: v })}
options={[
{ label: '不重复', value: 'nonrepeating' },
{ label: '每天', value: 'daily' },
{ label: '每周', value: 'weekly' },
{ label: '每月(按日期)', value: 'absolute_monthly' },
{ label: '每月(按星期)', value: 'relative_monthly' },
{ label: '每月(日期)', value: 'absolute_monthly' },
{ label: '每月(星期)', value: 'relative_monthly' },
]}
style={{ width: '100%' }}
/>
</div>
<div>
<label className="text-sm block mb-1 text-black">重复间隔(天/周/月) <span className="text-red-500">*</span></label>
<label className="text-sm block mb-1">重复间隔</label>
<InputNumber
min={1}
value={taskForm.repeat_option.interval}
onChange={(val) => setTaskForm({ ...taskForm, repeat_option: { ...taskForm.repeat_option, interval: val || 1 } })}
onChange={(v) => setTaskForm({
...taskForm,
repeat_option: { ...taskForm.repeat_option, interval: v }
})}
style={{ width: '100%' }}
/>
</div>
</div>
{/* 每周 */}
{taskForm.repeat_type === 'weekly' && (
<div>
<label className="text-sm block mb-1">周几执行</label>
<Select
mode="multiple"
value={taskForm.repeat_option.days_of_week}
onChange={(v) => setTaskForm({
...taskForm,
repeat_option: { ...taskForm.repeat_option, days_of_week: v }
})}
options={[
{ label: '周日', value: 0 },
{ label: '周一', value: 1 },
{ label: '周二', value: 2 },
{ label: '周三', value: 3 },
{ label: '周四', value: 4 },
{ label: '周五', value: 5 },
{ label: '周六', value: 6 }
]}
style={{ width: '100%' }}
/>
</div>
)}
{/* 按月日期 */}
{taskForm.repeat_type === 'absolute_monthly' && (
<div>
<label className="text-sm block mb-1">每月几日</label>
<Select
mode="multiple"
value={taskForm.repeat_option.days_of_month}
onChange={(v) => setTaskForm({
...taskForm,
repeat_option: { ...taskForm.repeat_option, days_of_month: v }
})}
options={Array.from({ length: 31 }, (_, i) => ({ label: i + 1, value: i + 1 }))}
style={{ width: '100%' }}
/>
</div>
)}
{/* 按月星期 */}
{taskForm.repeat_type === 'relative_monthly' && (
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm block mb-1">第几周</label>
<Select
value={taskForm.repeat_option.week_of_month}
onChange={(v) => setTaskForm({
...taskForm,
repeat_option: { ...taskForm.repeat_option, week_of_month: v }
})}
options={[1, 2, 3, 4].map(w => ({ label: `第${w}周`, value: w }))}
style={{ width: '100%' }}
/>
</div>
<div>
<label className="text-sm block mb-1">周几</label>
<Select
mode="multiple"
value={taskForm.repeat_option.days_of_week}
onChange={(v) => setTaskForm({
...taskForm,
repeat_option: { ...taskForm.repeat_option, days_of_week: v }
})}
options={[
{ label: '周日', value: 0 },
{ label: '周一', value: 1 },
{ label: '周二', value: 2 },
{ label: '周三', value: 3 },
{ label: '周四', value: 4 },
{ label: '周五', value: 5 },
{ label: '周六', value: 6 }
]}
style={{ width: '100%' }}
/>
</div>
</div>
)}
<div>
<label className="text-sm block mb-1 text-black">执行时间点列表</label>
<label className="text-sm block mb-1">执行时间点</label>
<Select
mode="tags"
placeholder="输入秒级时间戳或选择时间 (多选)"
style={{ width: '100%' }}
value={taskForm.recurring_task_start_time_list}
onChange={(val) => setTaskForm({ ...taskForm, recurring_task_start_time_list: val })}
onChange={(v) => setTaskForm({
...taskForm,
recurring_task_start_time_list: v
})}
placeholder="输入时间戳"
style={{ width: '100%' }}
/>
<Text type="secondary" style={{ fontSize: 11 }}>注:重复任务需指定具体执行的时间点列表。</Text>
</div>
</>
)}
<div className="text-xs text-slate-400 mt-2">
<div>绑定无人机:{listDrone?.drone_callsign || '-'}({listDrone?.gateway_sn || '-'})</div>
</div>
{/* 按钮 */}
<div className="flex justify-end gap-2 mt-4">
<Button onClick={resetModals}>取消</Button>
<Button type="primary" loading={loading} onClick={createFlightTask}>创建航线</Button>
<Button type="primary" loading={loading} onClick={createFlightTask}>确认创建</Button>
</div>
</div>
</Modal>