diff --git a/config.json b/config.json index 7eb412b..6be8fcd 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,7 @@ { "version": "1.0.0", "serverUrl": "http://192.168.189.206:8000", + "taskServerUrl": "http://192.168.189.206:8080/jeecg-boot", "headers": { "x-access-token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NTIzMzQ5MjEsInVzZXJuYW1lIjoiYWRtaW4ifQ.dKvKIJOU5FxFeFNI3ucJTPLhHmUFZkv8HA2S_VO6klY", "x-tenant-id": 1000 @@ -9,5 +10,16 @@ "getTasks": "/api/vwed-task/list", "getTaskDetail": "/api/vwed-task/{taskId}", "runTask": "/api/vwed-task-edit/run" + }, + "taskApiEndpoints": { + "getTaskList": "/task", + "createTask": "/task", + "getTaskDetail": "/task/{id}", + "getTaskProgress": "/task/proce", + "adjustTaskPriority": "/task/{id}/priority", + "pauseTask": "/task/{id}/paused", + "continueTask": "/task/{id}/continue", + "terminateTask": "/task/{id}/terminated", + "exportTask": "/task/exportXls" } } diff --git a/src/components/TaskCard.tsx b/src/components/TaskCard.tsx index f39a565..078d757 100644 --- a/src/components/TaskCard.tsx +++ b/src/components/TaskCard.tsx @@ -7,57 +7,27 @@ interface TaskCardProps { onPress: (id: string) => void; } -const statusMap: { [key: number]: { text: string; color: string } } = { - 0: { text: '待机', color: '#9E9E9E' }, // Grey - 1: { text: '运行中', color: '#2196F3' }, // Blue - 2: { text: '完成', color: '#4CAF50' }, // Green - 3: { text: '失败', color: '#F44336' }, // Red -}; +// 主页任务卡片不需要显示状态,因为都是未运行的任务模板 const TaskCard: React.FC = ({ task, onPress }) => { - const statusInfo = statusMap[task.status] || statusMap[0]; - return ( onPress(task.id)} style={styles.container}> - - - {task.label} - + {task.description || '暂无描述'} - - - {statusInfo.text} - - ); }; const styles = StyleSheet.create({ container: { - flexDirection: 'row', - alignItems: 'center', backgroundColor: '#1a1a1a', paddingVertical: 16, paddingHorizontal: 16, }, - indicatorContainer: { - marginRight: 16, - }, - statusIndicator: { - width: 12, - height: 12, - borderRadius: 6, - }, contentContainer: { flex: 1, }, @@ -65,18 +35,12 @@ const styles = StyleSheet.create({ color: '#FFFFFF', fontSize: 16, fontWeight: 'bold', - marginBottom: 4, + marginBottom: 8, }, description: { color: '#999999', fontSize: 14, - }, - statusContainer: { - marginLeft: 16, - }, - statusText: { - fontSize: 14, - fontWeight: 'bold', + lineHeight: 20, }, }); diff --git a/src/screens/RunScreen.tsx b/src/screens/RunScreen.tsx index f09d2b9..c1943d5 100644 --- a/src/screens/RunScreen.tsx +++ b/src/screens/RunScreen.tsx @@ -1,30 +1,684 @@ -import React from 'react'; -import { StyleSheet, Text, View } from 'react-native'; +import React, { useState, useEffect, useCallback } from 'react'; +import { + StyleSheet, + Text, + View, + FlatList, + TouchableOpacity, + ActivityIndicator, + Alert, + TextInput, +} from 'react-native'; +import { Picker } from '@react-native-picker/picker'; +import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; +import { TaskStatus } from '../types/task'; +import { getTaskRunList, terminateTask } from '../services/taskService'; + +// 任务状态选项 +const statusOptions = [ + { label: '全部', value: undefined }, + { label: '待分配', value: TaskStatus.WAITING }, + { label: '执行中', value: TaskStatus.RUNNING }, + { label: '已暂停', value: TaskStatus.PAUSED }, + { label: '已完成', value: TaskStatus.COMPLETED }, + { label: '已失败', value: TaskStatus.FAILED }, + { label: '已终止', value: TaskStatus.TERMINATED }, +]; + +// 状态显示配置 +const statusDisplayMap: { [key: number]: { text: string; color: string } } = { + [TaskStatus.WAITING]: { text: '待分配', color: '#9E9E9E' }, + [TaskStatus.RUNNING]: { text: '执行中', color: '#2196F3' }, + [TaskStatus.PAUSED]: { text: '已暂停', color: '#FF9800' }, + [TaskStatus.COMPLETED]: { text: '已完成', color: '#4CAF50' }, + [TaskStatus.FAILED]: { text: '已失败', color: '#F44336' }, + [TaskStatus.TERMINATED]: { text: '已终止', color: '#9C27B0' }, +}; + +interface TaskRunItem { + id: string; + parentId: string; + vwedTaskId: string; + vwedTaskParentId: string; + sceneId: string; + name: string; + description?: string; + priority: number; + isPeriodic: number; + needAmr: number; + amrName: string; + status: TaskStatus; + stopReason?: string; + createBy: string; + createTime: string; + startTime?: string; + endTime?: string; + runDuration: number; +} export default function RunScreen() { + const [tasks, setTasks] = useState([]); + const [loading, setLoading] = useState(false); + const [refreshing, setRefreshing] = useState(false); + + // 筛选状态 + const [filterStatus, setFilterStatus] = useState( + undefined, + ); + const [filterName, setFilterName] = useState(''); + + // 操作状态 + const [operatingTaskId, setOperatingTaskId] = useState(null); + + // 批量操作状态 + const [selectedTasks, setSelectedTasks] = useState>(new Set()); + const [isSelectionMode, setIsSelectionMode] = useState(false); + const [batchOperating, setBatchOperating] = useState(false); + + // 加载任务列表 + const loadTasks = useCallback( + async (isRefresh = false) => { + if (isRefresh) { + setRefreshing(true); + } else { + setLoading(true); + } + + try { + const params = { + status: filterStatus, + name: filterName.trim() || undefined, + pageNum: 1, + pageSize: 100, + }; + + const response = await getTaskRunList(params); + setTasks(response || []); + } catch (error) { + console.error('加载任务列表失败:', error); + Alert.alert('错误', '加载任务列表失败,请重试'); + setTasks([]); + } finally { + setLoading(false); + setRefreshing(false); + } + }, + [filterStatus, filterName], + ); + + // 初始加载 + useEffect(() => { + loadTasks(); + }, [loadTasks]); + + // 刷新任务列表 + const handleRefresh = () => { + loadTasks(true); + }; + + // 重置筛选 + const handleResetFilter = () => { + setFilterStatus(undefined); + setFilterName(''); + }; + + // 切换选择模式 + const toggleSelectionMode = () => { + setIsSelectionMode(!isSelectionMode); + setSelectedTasks(new Set()); + }; + + // 选择/取消选择任务 + const toggleTaskSelection = (taskId: string) => { + const newSelection = new Set(selectedTasks); + if (newSelection.has(taskId)) { + newSelection.delete(taskId); + } else { + newSelection.add(taskId); + } + setSelectedTasks(newSelection); + }; + + // 全选/取消全选 + const toggleSelectAll = () => { + if (selectedTasks.size === tasks.length) { + setSelectedTasks(new Set()); + } else { + setSelectedTasks(new Set(tasks.map(task => task.id))); + } + }; + + // 批量终止任务 + const handleBatchTerminate = async () => { + if (selectedTasks.size === 0) { + Alert.alert('提示', '请先选择要终止的任务'); + return; + } + + Alert.alert( + '确认操作', + `确定要终止选中的 ${selectedTasks.size} 个任务吗?`, + [ + { text: '取消', style: 'cancel' }, + { + text: '确定', + style: 'destructive', + onPress: async () => { + setBatchOperating(true); + try { + const promises = Array.from(selectedTasks).map(taskId => + terminateTask(taskId), + ); + await Promise.all(promises); + Alert.alert('成功', `已成功终止 ${selectedTasks.size} 个任务`); + setSelectedTasks(new Set()); + setIsSelectionMode(false); + loadTasks(); + } catch (error) { + console.error('批量终止任务失败:', error); + Alert.alert('错误', '批量终止任务失败,请重试'); + } finally { + setBatchOperating(false); + } + }, + }, + ], + ); + }; + + // 任务操作 - 只保留终止操作 + const handleTaskOperation = async (taskId: string) => { + setOperatingTaskId(taskId); + + try { + await terminateTask(taskId); + Alert.alert('成功', '终止任务成功'); + // 重新加载任务列表 + loadTasks(); + } catch (error) { + console.error('终止任务失败:', error); + Alert.alert('错误', '终止任务失败,请重试'); + } finally { + setOperatingTaskId(null); + } + }; + + // 格式化时间 + const formatTime = (timeString?: string) => { + if (!timeString) return '--'; + try { + return new Date(timeString).toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + }); + } catch { + return timeString; + } + }; + + // 渲染任务项 + const renderTaskItem = ({ item }: { item: TaskRunItem }) => { + const statusInfo = + statusDisplayMap[item.status] || statusDisplayMap[TaskStatus.WAITING]; + const isOperating = operatingTaskId === item.id; + const isSelected = selectedTasks.has(item.id); + + return ( + { + if (isSelectionMode) { + toggleTaskSelection(item.id); + } + }} + activeOpacity={isSelectionMode ? 0.7 : 1} + > + + + {isSelectionMode && ( + toggleTaskSelection(item.id)} + > + + + )} + + {item.name} + + + {statusInfo.text} + + + + + + + {item.description || '暂无描述'} + + + + 创建时间: + {formatTime(item.createTime)} + + + {item.startTime && ( + + 开始时间: + {formatTime(item.startTime)} + + )} + + {item.endTime && ( + + 结束时间: + {formatTime(item.endTime)} + + )} + + + {!isSelectionMode && ( + + {(item.status === TaskStatus.RUNNING || + item.status === TaskStatus.PAUSED) && ( + handleTaskOperation(item.id)} + disabled={isOperating} + > + {isOperating ? ( + + ) : ( + <> + + 终止 + + )} + + )} + + )} + + ); + }; + return ( - - 任务运行状态列表 - 此功能正在开发中... + + {/* 顶部操作区域 */} + + + + + + {isSelectionMode ? '取消选择' : '批量选择'} + + + + {isSelectionMode && ( + <> + + + + {selectedTasks.size === tasks.length ? '取消全选' : '全选'} + + + + + {batchOperating ? ( + + ) : ( + + )} + + 终止 ({selectedTasks.size}) + + + + )} + + + + {/* 筛选区域 */} + + + + 任务状态: + + setFilterStatus(value)} + style={styles.picker} + dropdownIconColor="#ffffff" + mode="dropdown" + > + {statusOptions.map(option => ( + + ))} + + + + + + + 重置 + + + + + loadTasks()} + /> + loadTasks()} + > + + + + + + {/* 任务列表 */} + {loading ? ( + + + 加载中... + + ) : ( + item.id} + refreshing={refreshing} + onRefresh={handleRefresh} + ItemSeparatorComponent={() => } + ListEmptyComponent={() => ( + + + 暂无任务数据 + + )} + contentContainerStyle={ + tasks.length === 0 ? styles.emptyList : undefined + } + /> + )} ); } const styles = StyleSheet.create({ - screenContainer: { + container: { + flex: 1, + backgroundColor: '#121212', + }, + filterContainer: { + backgroundColor: '#1a1a1a', + padding: 16, + borderBottomWidth: 1, + borderBottomColor: '#333', + }, + filterRow: { + flexDirection: 'row', + alignItems: 'center', + marginBottom: 12, + }, + statusFilterContainer: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + }, + filterLabel: { + color: '#ffffff', + fontSize: 14, + marginRight: 8, + }, + pickerContainer: { + flex: 1, + backgroundColor: '#333', + borderRadius: 4, + marginRight: 12, + height: 40, + justifyContent: 'center', + }, + picker: { + color: '#ffffff', + height: 40, + width: '100%', + }, + resetButton: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: '#666', + paddingHorizontal: 12, + paddingVertical: 8, + borderRadius: 4, + }, + resetButtonText: { + color: '#ffffff', + fontSize: 12, + marginLeft: 4, + }, + nameFilterContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + nameInput: { + flex: 1, + backgroundColor: '#333', + color: '#ffffff', + paddingHorizontal: 12, + paddingVertical: 8, + borderRadius: 4, + marginRight: 8, + }, + searchButton: { + backgroundColor: '#2196F3', + padding: 8, + borderRadius: 4, + }, + loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', - backgroundColor: '#121212', }, - text: { - fontSize: 22, - fontWeight: 'bold', + loadingText: { color: '#ffffff', - marginBottom: 10, + marginTop: 8, }, - subText: { + taskItem: { + backgroundColor: '#1a1a1a', + padding: 16, + }, + taskHeader: { + marginBottom: 8, + }, + taskTitleContainer: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + taskName: { + flex: 1, + color: '#ffffff', fontSize: 16, - color: '#b0b0b0', + fontWeight: 'bold', + marginRight: 8, + }, + statusBadge: { + paddingHorizontal: 8, + paddingVertical: 4, + borderRadius: 12, + }, + statusText: { + color: '#ffffff', + fontSize: 12, + fontWeight: 'bold', + }, + taskDetails: { + marginBottom: 12, + }, + taskDescription: { + color: '#ccc', + fontSize: 14, + marginBottom: 8, + }, + timeContainer: { + flexDirection: 'row', + marginBottom: 4, + }, + timeLabel: { + color: '#999', + fontSize: 12, + minWidth: 60, + }, + timeValue: { + color: '#ccc', + fontSize: 12, + flex: 1, + }, + actionContainer: { + flexDirection: 'row', + justifyContent: 'flex-end', + }, + actionButton: { + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 12, + paddingVertical: 6, + borderRadius: 4, + marginLeft: 8, + }, + pauseButton: { + backgroundColor: '#FF9800', + }, + continueButton: { + backgroundColor: '#4CAF50', + }, + terminateButton: { + backgroundColor: '#F44336', + }, + actionButtonText: { + color: '#ffffff', + fontSize: 12, + marginLeft: 4, + }, + separator: { + height: 1, + backgroundColor: '#333', + }, + emptyContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + paddingTop: 100, + }, + emptyText: { + color: '#666', + fontSize: 16, + marginTop: 16, + }, + emptyList: { + flex: 1, + }, + topActionContainer: { + backgroundColor: '#1a1a1a', + paddingHorizontal: 16, + paddingVertical: 12, + borderBottomWidth: 1, + borderBottomColor: '#333', + }, + actionButtonsContainer: { + flexDirection: 'row', + alignItems: 'center', + flexWrap: 'wrap', + }, + actionBtn: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: '#2196F3', + paddingHorizontal: 12, + paddingVertical: 8, + borderRadius: 4, + marginRight: 8, + marginBottom: 4, + }, + actionBtnActive: { + backgroundColor: '#4CAF50', + }, + actionBtnText: { + color: '#ffffff', + fontSize: 12, + marginLeft: 4, + }, + terminateBtn: { + backgroundColor: '#F44336', + }, + taskItemSelected: { + backgroundColor: '#2a2a2a', + borderLeftWidth: 4, + borderLeftColor: '#4CAF50', + }, + checkboxContainer: { + marginRight: 12, + padding: 4, + }, + taskNameWithCheckbox: { + flex: 1, }, }); diff --git a/src/services/api.ts b/src/services/api.ts index b02bfe0..06c0895 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -56,16 +56,32 @@ api.interceptors.response.use( if (response.data && response.data.code && response.data.code !== 200) { throw new Error(`API 错误: ${response.data.message}`); } - // 优先处理嵌套的 data 字段 - if (response.data && typeof response.data.data !== 'undefined') { - // 如果 data 字段中有 list,则返回 list - if (Array.isArray(response.data.data.list)) { - return response.data.data.list; + + // 处理不同的响应数据格式 + if (response.data) { + // 格式1: { success: true, result: { records: [...] } } - 新的任务管理API格式 + if (response.data.success && response.data.result) { + if ( + response.data.result.records && + Array.isArray(response.data.result.records) + ) { + return response.data.result.records; + } + return response.data.result; } - // 否则返回 data 字段本身 - return response.data.data; + + // 格式2: { data: { list: [...] } } - 原有格式 + if (typeof response.data.data !== 'undefined') { + if (Array.isArray(response.data.data.list)) { + return response.data.data.list; + } + return response.data.data; + } + + // 格式3: 直接返回整个响应数据 + return response.data; } - // 如果没有嵌套的 data 字段,直接返回整个响应数据 + return response.data; }, error => { diff --git a/src/services/taskService.ts b/src/services/taskService.ts index e0ca21c..ce78e39 100644 --- a/src/services/taskService.ts +++ b/src/services/taskService.ts @@ -1,6 +1,12 @@ import { getConfig } from './configService'; -import { RunTaskRequest, RunTaskApiResponse, Task } from '../types/task'; +import { + RunTaskRequest, + RunTaskApiResponse, + Task, + TaskStatus, +} from '../types/task'; import api from './api'; +import axios from 'axios'; // 获取任务列表 export const getTasks = async (params: { @@ -52,3 +58,267 @@ export const runTask = async ( throw error; } }; + +// ============ 任务管理相关API ============ + +// 创建任务管理API实例 +const createTaskApi = () => { + return axios.create({ + timeout: 10000, + }); +}; + +// 请求拦截器 - 为任务管理API配置 +const setupTaskApiInterceptors = async (apiInstance: any) => { + const config = await getConfig(); + + apiInstance.interceptors.request.use( + async (requestConfig: any) => { + const taskServerUrl = config?.taskServerUrl; + if (!taskServerUrl) { + throw new Error('任务管理服务器地址未配置'); + } + + requestConfig.baseURL = taskServerUrl.replace(/\/$/, ''); + requestConfig.headers = { + 'Content-Type': 'application/json', + ...config?.headers, + ...requestConfig.headers, + }; + + console.log( + `[Task API Request] ${requestConfig.method?.toUpperCase()} ${ + requestConfig.baseURL + }${requestConfig.url}`, + { params: requestConfig.params, data: requestConfig.data }, + ); + return requestConfig; + }, + (error: any) => { + console.error('[Task API Request Error]', error); + return Promise.reject(error); + }, + ); + + apiInstance.interceptors.response.use( + (response: any) => { + console.log( + `[Task API Response] ${response.config.method?.toUpperCase()} ${ + response.config.url + }`, + response.data, + ); + + if (response.data && response.data.code && response.data.code !== 200) { + throw new Error(`API 错误: ${response.data.message}`); + } + + // 处理任务管理API的响应格式: { success: true, result: { records: [...] } } + if (response.data && response.data.success && response.data.result) { + // 如果result中有records数组,返回records + if ( + response.data.result.records && + Array.isArray(response.data.result.records) + ) { + return response.data.result.records; + } + // 否则返回整个result对象 + return response.data.result; + } + + return response.data; + }, + (error: any) => { + if (error.response) { + console.error( + `[Task API Response Error] Status: ${error.response.status}`, + error.response.data, + ); + const httpError = new Error( + `HTTP ${error.response.status}: ${ + error.response.statusText || 'Unknown Error' + }`, + ); + return Promise.reject(httpError); + } else if (error.request) { + console.error('[Task API Network Error]', error.request); + return Promise.reject(new Error('网络错误,请检查您的连接')); + } else { + console.error('[Task API Request Setup Error]', error.message); + return Promise.reject(error); + } + }, + ); + + return apiInstance; +}; + +/** + * 获取任务运行列表 + * @param params 查询参数 + */ +export const getTaskRunList = async (params?: { + status?: TaskStatus; + name?: string; + pageNum?: number; + pageSize?: number; +}): Promise => { + try { + const config = await getConfig(); + const endpoint = config?.taskApiEndpoints?.getTaskList; + if (!endpoint) throw new Error('获取任务列表的API端点未配置'); + + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.get(endpoint, { params }); + return response || []; + } catch (error) { + console.error('获取任务运行列表失败:', error); + throw error; + } +}; + +/** + * 创建任务 + * @param params 任务参数 + */ +export const createTaskRun = async (params: any): Promise => { + try { + const config = await getConfig(); + const endpoint = config?.taskApiEndpoints?.createTask; + if (!endpoint) throw new Error('创建任务的API端点未配置'); + + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.post(endpoint, params); + return response; + } catch (error) { + console.error('创建任务失败:', error); + throw error; + } +}; + +/** + * 获取任务运行详情 + * @param id 任务ID + */ +export const getTaskRunDetail = async (id: string): Promise => { + try { + const config = await getConfig(); + let endpoint = config?.taskApiEndpoints?.getTaskDetail; + if (!endpoint) throw new Error('获取任务详情的API端点未配置'); + + endpoint = endpoint.replace('{id}', id); + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.get(endpoint); + return response; + } catch (error) { + console.error(`获取任务运行详情失败 (ID: ${id}):`, error); + throw error; + } +}; + +/** + * 获取任务进度和动作列表 + * @param ids 任务ID数组 + */ +export const getTaskProgress = async (ids: string[]): Promise => { + try { + const config = await getConfig(); + const endpoint = config?.taskApiEndpoints?.getTaskProgress; + if (!endpoint) throw new Error('获取任务进度的API端点未配置'); + + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.get(endpoint, { + params: { + ids: ids.join(','), + }, + }); + return response; + } catch (error) { + console.error('获取任务进度失败:', error); + throw error; + } +}; + +/** + * 调整任务优先级 + * @param id 任务ID + * @param priority 新优先级 + */ +export const adjustTaskPriority = async ( + id: string, + priority: number, +): Promise => { + try { + const config = await getConfig(); + let endpoint = config?.taskApiEndpoints?.adjustTaskPriority; + if (!endpoint) throw new Error('调整任务优先级的API端点未配置'); + + endpoint = endpoint.replace('{id}', id); + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.put(endpoint, { priority }); + return response; + } catch (error) { + console.error(`调整任务优先级失败 (ID: ${id}):`, error); + throw error; + } +}; + +/** + * 暂停任务 + * @param id 任务ID + */ +export const pauseTask = async (id: string): Promise => { + try { + const config = await getConfig(); + let endpoint = config?.taskApiEndpoints?.pauseTask; + if (!endpoint) throw new Error('暂停任务的API端点未配置'); + + endpoint = endpoint.replace('{id}', id); + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.put(endpoint); + return response; + } catch (error) { + console.error(`暂停任务失败 (ID: ${id}):`, error); + throw error; + } +}; + +/** + * 继续任务 + * @param id 任务ID + */ +export const continueTask = async (id: string): Promise => { + try { + const config = await getConfig(); + let endpoint = config?.taskApiEndpoints?.continueTask; + if (!endpoint) throw new Error('继续任务的API端点未配置'); + + endpoint = endpoint.replace('{id}', id); + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.put(endpoint); + return response; + } catch (error) { + console.error(`继续任务失败 (ID: ${id}):`, error); + throw error; + } +}; + +/** + * 终止任务 + * @param id 任务ID + */ +export const terminateTask = async (id: string): Promise => { + try { + const config = await getConfig(); + let endpoint = config?.taskApiEndpoints?.terminateTask; + if (!endpoint) throw new Error('终止任务的API端点未配置'); + + endpoint = endpoint.replace('{id}', id); + const taskApi = await setupTaskApiInterceptors(createTaskApi()); + const response = await taskApi.put(endpoint); + return response; + } catch (error) { + console.error(`终止任务失败 (ID: ${id}):`, error); + throw error; + } +}; diff --git a/src/types/config.ts b/src/types/config.ts index c1cf7ea..f680d25 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -2,11 +2,23 @@ export interface AppConfig { version: string; serverUrl?: string; // 服务器地址 + taskServerUrl?: string; // 任务管理服务器地址 apiEndpoints?: { getTasks: string; getTaskDetail: string; runTask: string; }; + taskApiEndpoints?: { + getTaskList: string; + createTask: string; + getTaskDetail: string; + getTaskProgress: string; + adjustTaskPriority: string; + pauseTask: string; + continueTask: string; + terminateTask: string; + exportTask: string; + }; headers?: { [key: string]: string | number; }; diff --git a/src/types/task.ts b/src/types/task.ts index 7e0d298..8eebe8e 100644 --- a/src/types/task.ts +++ b/src/types/task.ts @@ -1,3 +1,15 @@ +/** + * 任务状态枚举 + */ +export enum TaskStatus { + WAITING = 0, // 待分配 + RUNNING = 1, // 执行中 + PAUSED = 2, // 已暂停 + COMPLETED = 3, // 已完成 + FAILED = 4, // 已失败 + TERMINATED = 5, // 已终止 +} + // 机器人的具体动作,现在是一个对象 export interface RobotAction { name: string;