# 区域侦查任务前端集成文档 ## 📋 概述 本文档详细说明前端如何集成区域侦查任务API,包括接口调用、数据格式、错误处理等完整的前端集成方案。 ## 🚀 快速开始 ### 基础配置 ```javascript // API基础配置 const API_BASE_URL = 'http://localhost:8080/api/v1/region-reconnaissance'; // 动态获取鉴权头(如有需要) function getAuthHeaders() { const token = window.localStorage.getItem('token'); return token ? { Authorization: `Bearer ${token}` } : {}; } // 统一请求方法(基于 fetch) async function request(path, options = {}) { const url = path.startsWith('http') ? path : `${API_BASE_URL}${path}`; const headers = { 'Content-Type': 'application/json', ...getAuthHeaders(), ...(options.headers || {}) }; const response = await fetch(url, { ...options, headers }); // 尝试解析响应体(可能为 204 无内容) let payload = null; if (response.status !== 204) { try { payload = await response.json(); } catch { // 非 JSON 响应体容忍 } } if (!response.ok) { const message = payload?.message || `HTTP ${response.status}`; throw new Error(message); } // 兼容 204 的删除等请求 return payload ?? { code: 200, message: 'OK', data: null }; } ``` ## 📡 API接口集成 ### 1. 创建区域侦查任务 #### 接口信息 - **URL**: `POST /api/v1/region-reconnaissance/tasks` - **功能**: 创建新的区域侦查任务 - **返回**: 任务ID和创建结果 #### 前端实现 ```javascript /** * 创建区域侦查任务 * @param {Object} taskData - 任务数据 * @returns {Promise} 创建结果 */ async function createRegionReconnaissanceTask(taskData) { try { const result = await request('/tasks', { method: 'POST', body: JSON.stringify(taskData) }); console.log('任务创建成功:', result); return result; } catch (error) { console.error('创建任务失败:', error); throw error; } } ``` #### 请求数据格式 ```javascript // 完整的任务创建数据示例(区域闭合由后端自动处理,前端无需首尾重复) const taskData = { taskName: "测试区域侦查任务", taskType: 1, // 1-区域侦查, 2-航线侦查 regionZone: { pointList: [ { latitude: 39.9042, longitude: 116.4074, altitude: 100.0 }, { latitude: 39.9142, longitude: 116.4174, altitude: 100.0 }, { latitude: 39.9242, longitude: 116.4274, altitude: 100.0 } ] }, description: "这是一个测试任务", executeTime: "2025-01-27T10:00:00Z" // 使用 ISO 8601(UTC) }; ``` > 说明 > - 区域闭合规则:后端会基于点列表自动闭合多边形,前端不需要重复首尾点。 > - 时间与时区:所有时间字段使用 ISO 8601 UTC(例如 `2025-01-27T10:00:00Z`)。服务端按 UTC 存储与计算,前端展示时可按本地时区格式化。 ### 2. 获取任务列表 #### 接口信息 - **URL**: `GET /api/v1/region-reconnaissance/tasks` - **功能**: 获取区域侦查任务列表 - **支持分页**: 是 #### 前端实现 ```javascript /** * 获取任务列表 * @param {Object} params - 查询参数 * @returns {Promise} 任务列表 */ async function getRegionReconnaissanceTasks(params = {}) { try { const qp = Object.fromEntries( Object.entries({ page: params.page ?? 1, size: params.size ?? 10, ...params }) .filter(([, v]) => v !== undefined && v !== null && v !== '') ); const queryParams = new URLSearchParams(qp).toString(); const result = await request(`/tasks?${queryParams}`, { method: 'GET' }); return result; } catch (error) { console.error('获取任务列表失败:', error); throw error; } } ``` ### 3. 获取任务详情 #### 接口信息 - **URL**: `GET /api/v1/region-reconnaissance/tasks/{taskId}` - **功能**: 获取指定任务的详细信息 #### 前端实现 ```javascript /** * 获取任务详情 * @param {string} taskId - 任务ID * @returns {Promise} 任务详情 */ async function getRegionReconnaissanceTaskDetail(taskId) { try { const result = await request(`/tasks/${taskId}`, { method: 'GET' }); return result; } catch (error) { console.error('获取任务详情失败:', error); throw error; } } ``` ### 4. 更新任务状态 #### 接口信息 - **URL**: `PUT /api/v1/region-reconnaissance/tasks/{taskId}/status` - **功能**: 更新任务状态 #### 前端实现 ```javascript /** * 更新任务状态 * @param {string} taskId - 任务ID * @param {number} status - 新状态 * @returns {Promise} 更新结果 */ async function updateTaskStatus(taskId, status) { try { const result = await request(`/tasks/${taskId}/status`, { method: 'PUT', body: JSON.stringify({ status }) }); return result; } catch (error) { console.error('更新任务状态失败:', error); throw error; } } ``` ### 5. 删除任务 #### 接口信息 - **URL**: `DELETE /api/v1/region-reconnaissance/tasks/{taskId}` - **功能**: 删除指定任务 #### 前端实现 ```javascript /** * 删除任务 * @param {string} taskId - 任务ID * @returns {Promise} 删除结果 */ async function deleteRegionReconnaissanceTask(taskId) { try { const result = await request(`/tasks/${taskId}`, { method: 'DELETE' }); return result; // 兼容 204,无内容时返回 { code: 200, message: 'OK', data: null } } catch (error) { console.error('删除任务失败:', error); throw error; } } ``` ## 🎨 前端组件示例 ### React组件示例 ```jsx import React, { useState, useEffect } from 'react'; const RegionReconnaissanceTaskManager = () => { const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // 获取任务列表 const fetchTasks = async () => { setLoading(true); try { const result = await getRegionReconnaissanceTasks(); setTasks(result.data?.records ?? []); } catch (err) { setError(err.message); } finally { setLoading(false); } }; // 创建任务 const handleCreateTask = async (taskData) => { try { await createRegionReconnaissanceTask(taskData); await fetchTasks(); // 刷新列表 alert('任务创建成功!'); } catch (err) { alert(`创建失败: ${err.message}`); } }; // 删除任务 const handleDeleteTask = async (taskId) => { if (window.confirm('确定要删除这个任务吗?')) { try { await deleteRegionReconnaissanceTask(taskId); await fetchTasks(); // 刷新列表 alert('任务删除成功!'); } catch (err) { alert(`删除失败: ${err.message}`); } } }; useEffect(() => { fetchTasks(); }, []); return (

区域侦查任务管理

{loading &&
加载中...
} {error &&
错误: {error}
}
{tasks.map(task => (

{task.taskName}

类型: {task.taskType === 1 ? '区域侦查' : '航线侦查'}

状态: {getStatusText(task.status)}

创建时间: {new Date(task.createTime).toLocaleString()}

))}
); }; // 状态文本转换 const getStatusText = (status) => { const statusMap = { 0: '待执行', 1: '执行中', 2: '已完成', 3: '已取消', 4: '执行失败' }; return statusMap[status] || '未知状态'; }; export default RegionReconnaissanceTaskManager; ``` ### Vue组件示例 ```vue ``` ## 📊 数据格式说明 ### 任务对象结构 ```typescript interface RegionReconnaissanceTask { taskId: string; // 任务ID taskName: string; // 任务名称 taskType: number; // 任务类型 (1-区域侦查, 2-航线侦查) status: number; // 任务状态 (0-待执行, 1-执行中, 2-已完成, 3-已取消, 4-执行失败) regionZone: RegionZone; // 区域信息 description?: string; // 任务描述 executeTime?: string; // 执行时间 createTime: string; // 创建时间 updateTime: string; // 更新时间 createUserId: string; // 创建用户ID mqttSendStatus: number; // MQTT发送状态 } interface RegionZone { pointList: Point[]; // 区域点列表 } interface Point { latitude: number; // 纬度 longitude: number; // 经度 altitude: number; // 高度 } ``` ### 响应数据格式 ```typescript // 成功响应 interface ApiResponse { code: number; // 响应码 (200-成功) message: string; // 响应消息 data: T; // 响应数据 timestamp: string; // 时间戳 } // 分页响应 interface PageResponse { code: number; message: string; data: { records: T[]; // 数据列表 total: number; // 总记录数 size: number; // 每页大小 current: number; // 当前页码 pages: number; // 总页数 }; timestamp: string; } ``` ## ⚠️ 错误处理 ### 常见错误码 ```javascript const ERROR_CODES = { 400: '请求参数错误', 401: '未授权访问', 403: '禁止访问', 404: '资源不存在', 500: '服务器内部错误', 1001: '任务名称不能为空', 1002: '区域点列表不能为空', 1003: '任务不存在', 1004: '任务状态不允许此操作' }; ``` ### 错误处理示例 ```javascript /** * 统一错误处理(配合 fetch 请求助手) * @param {Error} error - 错误对象 * @returns {string} 用户友好的错误信息 */ function handleApiError(error) { // request() 已将后端 message 或 HTTP 状态转为 Error(message) return error?.message || '请求失败'; } ``` ## 🔧 工具函数 ### 数据验证 ```javascript /** * 验证任务数据 * @param {Object} taskData - 任务数据 * @returns {Object} 验证结果 */ function validateTaskData(taskData) { const errors = []; if (!taskData.taskName || taskData.taskName.trim() === '') { errors.push('任务名称不能为空'); } if (![1, 2].includes(taskData.taskType)) { errors.push('任务类型必须是1(区域侦查)或2(航线侦查)'); } if (!taskData.regionZone || !Array.isArray(taskData.regionZone.pointList)) { errors.push('区域信息不能为空'); } else if (taskData.regionZone.pointList.length < 3) { errors.push('区域至少需要3个点'); } return { isValid: errors.length === 0, errors }; } ``` ### 数据转换 ```javascript /** * 转换区域数据为API格式 * @param {Array} points - 前端点数据 * @returns {Object} API格式的区域数据 */ function convertRegionData(points) { return { pointList: points.map(point => ({ latitude: parseFloat(point.latitude), longitude: parseFloat(point.longitude), altitude: parseFloat(point.altitude) || 0 })) }; } ``` ## 📱 移动端适配 ### 响应式设计 ```css /* 移动端适配 */ @media (max-width: 768px) { .task-manager { padding: 10px; } .task-item { margin-bottom: 15px; padding: 10px; border: 1px solid #ddd; border-radius: 5px; } .task-item h3 { font-size: 16px; margin-bottom: 8px; } .task-item p { font-size: 14px; margin: 4px 0; } .task-item button { width: 100%; padding: 8px; margin-top: 10px; } } ``` ## 🧪 测试示例 ### 单元测试 ```javascript // Jest测试示例 describe('RegionReconnaissanceTask API', () => { test('创建任务', async () => { const taskData = { taskName: '测试任务', taskType: 1, regionZone: { pointList: [ { latitude: 39.9042, longitude: 116.4074, altitude: 100 }, { latitude: 39.9142, longitude: 116.4174, altitude: 100 }, { latitude: 39.9242, longitude: 116.4274, altitude: 100 } ] } }; const result = await createRegionReconnaissanceTask(taskData); expect(result.code).toBe(200); expect(result.data.taskId).toBeDefined(); }); test('获取任务列表', async () => { const result = await getRegionReconnaissanceTasks(); expect(result.code).toBe(200); expect(Array.isArray(result.data.records)).toBe(true); }); }); ``` ## 📚 最佳实践 ### 1. 错误处理 - 始终使用try-catch包装API调用 - 提供用户友好的错误信息 - 记录详细的错误日志用于调试 ### 2. 数据验证 - 在发送请求前验证数据格式 - 使用TypeScript或PropTypes进行类型检查 - 提供实时验证反馈 ### 3. 用户体验 - 显示加载状态 - 提供操作确认 - 使用乐观更新提升响应速度 ### 4. 性能优化 - 实现数据缓存 - 使用分页加载大量数据 - 防抖处理用户输入 ## 🔗 相关资源 - [后端API接口说明](./后端API接口说明.md) - [前端对接指南](./前端对接指南.md) - [前端集成说明](./前端集成说明.md) ## 📞 技术支持 如有问题,请联系开发团队或查看项目文档。 --- *最后更新: 2025-01-27*