diff --git a/config.json b/config.json index f13371c..7eb412b 100644 --- a/config.json +++ b/config.json @@ -1,42 +1,10 @@ { "version": "1.0.0", - "locations": [ - { "label": "AP-1", "value": "AP-1" }, - { "label": "AP-2", "value": "AP-2" }, - { "label": "AP-3", "value": "AP-3" }, - { "label": "AP-4", "value": "AP-4" }, - { "label": "AP-5", "value": "AP-5" }, - { "label": "炉前缓存区", "value": "FURNACE_BUFFER" }, - { "label": "热处理上料交接区", "value": "HEAT_TREATMENT_LOADING" }, - { "label": "成品存储区", "value": "FINISHED_STORAGE" }, - { "label": "原料仓库", "value": "RAW_MATERIAL_WAREHOUSE" }, - { "label": "质检区", "value": "QUALITY_INSPECTION" } - ], - "locationsBays": [ - { "label": "AS2_2_001", "value": "AS2_2_001" }, - { "label": "AS2_2_002", "value": "AS2_2_002" }, - { "label": "AS2_2_003", "value": "AS2_2_003" }, - { "label": "AS2_2_004", "value": "AS2_2_004" }, - { "label": "AS2_2_005", "value": "AS2_2_005" } - ], - "payloads": [ - { "label": "满料架-A1", "value": "满料架-A1" }, - { "label": "满料架-A2", "value": "满料架-A2" }, - { "label": "空料架-B1", "value": "空料架-B1" }, - { "label": "空料架-B2", "value": "空料架-B2" }, - { "label": "空车", "value": "空车" }, - { "label": "钢材-Q235", "value": "钢材-Q235" }, - { "label": "铝合金-6061", "value": "铝合金-6061" } - ], - "robotActions": [ - { "label": "运输", "value": "TRANSPORT" }, - { "label": "取货", "value": "PICKUP" }, - { "label": "卸货", "value": "DROPOFF" }, - { "label": "等待", "value": "WAIT" }, - { "label": "充电", "value": "CHARGE" }, - { "label": "清洁", "value": "CLEAN" } - ], "serverUrl": "http://192.168.189.206:8000", + "headers": { + "x-access-token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NTIzMzQ5MjEsInVzZXJuYW1lIjoiYWRtaW4ifQ.dKvKIJOU5FxFeFNI3ucJTPLhHmUFZkv8HA2S_VO6klY", + "x-tenant-id": 1000 + }, "apiEndpoints": { "getTasks": "/api/vwed-task/list", "getTaskDetail": "/api/vwed-task/{taskId}", diff --git a/src/components/TaskForm.tsx b/src/components/TaskForm.tsx index 2004114..5d7d5f6 100644 --- a/src/components/TaskForm.tsx +++ b/src/components/TaskForm.tsx @@ -1,9 +1,6 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { Input, Slider } from '@rneui/themed'; -// @ts-ignore -import { Picker } from '@react-native-picker/picker'; -import { useTasks } from '../context/TasksContext'; import { Task, RobotAction, InputParam } from '../types/task'; interface TaskFormProps { @@ -12,8 +9,6 @@ interface TaskFormProps { } const TaskForm: React.FC = ({ task, onTaskChange }) => { - const { locations, payloads, robotActions, locationsBays } = useTasks(); - const handleParamChange = ( field: string, value: string | number | RobotAction, @@ -58,92 +53,6 @@ const TaskForm: React.FC = ({ task, onTaskChange }) => { /> ); - case 'location': - case 'location_bay': - const locationData = - param.type.toLowerCase() === 'location' ? locations : locationsBays; - return ( - - {label} - - - handleParamChange(param.name, itemValue) - } - style={styles.picker} - dropdownIconColor="#00ff00" - > - {locationData.map(loc => ( - - ))} - - - - ); - case 'payload': - return ( - - {label} - - - handleParamChange(param.name, itemValue) - } - style={styles.picker} - dropdownIconColor="#00ff00" - > - {payloads.map(p => ( - - ))} - - - - ); - case 'robotaction': - return ( - - {label} - - { - const selectedAction = robotActions.find( - a => a.value === itemValue, - ); - if (selectedAction) { - handleParamChange(param.name, { - name: selectedAction.label, - actionId: selectedAction.actionId, - }); - } - }} - style={styles.picker} - dropdownIconColor="#00ff00" - > - {robotActions.map(action => ( - - ))} - - - - ); case 'number': return ( diff --git a/src/context/TasksContext.tsx b/src/context/TasksContext.tsx index 51f829d..c6b98f7 100644 --- a/src/context/TasksContext.tsx +++ b/src/context/TasksContext.tsx @@ -8,24 +8,18 @@ import React, { useCallback, } from 'react'; import { Task } from '../types/task'; +import { AppConfig } from '../types/config'; +import { getConfig } from '../services/configService'; import { - AppConfig, - LocationOption, - PayloadOption, - RobotActionOption, -} from '../types/config'; -import { getConfig, executeTask } from '../services/configService'; + getTasks as getTasksService, + getTaskDetail as getTaskDetailService, +} from '../services/taskService'; interface TasksContextData { tasks: Task[]; - locations: LocationOption[]; - locationsBays: LocationOption[]; - payloads: PayloadOption[]; - robotActions: RobotActionOption[]; serverUrl: string | null; getTaskById: (id: string) => Task | undefined; updateTask: (updatedTask: Task) => void; - runTask: (id: string) => void; refreshConfig: () => Promise; isConfigLoaded: boolean; fetchTaskDetail: (taskId: string) => Promise; @@ -37,59 +31,19 @@ export const TasksProvider: React.FC<{ children: ReactNode }> = ({ children, }) => { const [tasks, setTasks] = useState([]); - const [locations, setLocations] = useState([]); - const [locationsBays, setLocationsBays] = useState([]); - const [payloads, setPayloads] = useState([]); - const [robotActions, setRobotActions] = useState([]); const [isConfigLoaded, setIsConfigLoaded] = useState(false); const [serverUrl, setServerUrl] = useState(null); - const fetchTasks = useCallback(async (baseUrl: string, endpoint: string) => { + const fetchTasks = useCallback(async () => { + if (!isConfigLoaded) return; try { - if (baseUrl && endpoint) { - const fetchUrl = `${baseUrl}${endpoint}?pageNum=1&pageSize=100`; - console.log('Fetching tasks from:', fetchUrl); - const response = await fetch(fetchUrl); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const responseData = await response.json(); - console.log('responseData', responseData); - - if (responseData && responseData.code === 200) { - const fetchedTasks = responseData.data.list.map((task: any) => { - let detail = task.detail; - if (detail && typeof detail === 'string') { - try { - detail = JSON.parse(detail); - } catch (e) { - console.error('解析任务详情失败 (list):', e); - detail = null; - } - } - return { - ...task, - name: task.label, - parameters: task.parameters || {}, - detail: detail, - }; - }); - setTasks(fetchedTasks); - } else { - console.error('获取任务列表失败: responseData.code is not 200'); - setTasks([]); - } - } + const fetchedTasks = await getTasksService({ pageNum: 1, pageSize: 100 }); + setTasks(fetchedTasks); } catch (error) { - console.error('获取任务列表失败:', error); - if (error instanceof Error) { - console.error('Error message:', error.message); - } + console.error('获取任务列表失败 (context):', error); setTasks([]); } - }, []); // Empty dependency array as it has no external dependencies from component scope + }, [isConfigLoaded]); useEffect(() => { const loadApp = async () => { @@ -98,9 +52,6 @@ export const TasksProvider: React.FC<{ children: ReactNode }> = ({ if (config) { applyConfig(config); setIsConfigLoaded(true); - if (config.serverUrl && config.apiEndpoints) { - await fetchTasks(config.serverUrl, config.apiEndpoints.getTasks); - } } else { console.log('没有找到配置文件,使用空数据'); setIsConfigLoaded(false); @@ -112,37 +63,26 @@ export const TasksProvider: React.FC<{ children: ReactNode }> = ({ }; loadApp(); - }, [fetchTasks]); + }, []); - const [apiEndpoints, setApiEndpoints] = useState<{ - getTasks: string; - getTaskDetail: string; - runTask: string; - } | null>(null); + useEffect(() => { + if (isConfigLoaded) { + fetchTasks(); + } + }, [isConfigLoaded, fetchTasks]); const applyConfig = (config: AppConfig) => { - setLocations(config.locations || []); - setLocationsBays(config.locationsBays || []); - setPayloads(config.payloads || []); - setRobotActions(config.robotActions || []); if (config.serverUrl) { setServerUrl(config.serverUrl); } - if (config.apiEndpoints) { - setApiEndpoints(config.apiEndpoints); - } }; const refreshConfig = useCallback(async () => { try { - // await clearCachedConfig(); // 通常刷新不需要清除缓存 const config = await getConfig(); if (config) { applyConfig(config); - setIsConfigLoaded(true); - if (config.serverUrl && config.apiEndpoints) { - await fetchTasks(config.serverUrl, config.apiEndpoints.getTasks); - } + setIsConfigLoaded(true); // 确保配置加载后再次触发任务获取 } else { console.log('刷新配置时没有找到配置文件'); setIsConfigLoaded(false); @@ -151,63 +91,28 @@ export const TasksProvider: React.FC<{ children: ReactNode }> = ({ console.error('刷新配置失败:', error); setIsConfigLoaded(false); } - }, [fetchTasks]); + }, []); const getTaskById = useCallback( (id: string) => { const task = tasks.find(t => t.id === id); - if (task && !task.detail) { - // fetchTaskDetail(id); // 详情在编辑页面获取 - } return task; }, [tasks], ); - const fetchTaskDetail = useCallback( - async (taskId: string) => { - try { - if (serverUrl && apiEndpoints) { - const endpoint = apiEndpoints.getTaskDetail.replace( - '{taskId}', - taskId, - ); - const url = `${serverUrl}${endpoint}`; - console.log('Fetching task detail from:', url); - const response = await fetch(url); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const responseData = await response.json(); - console.log('task detail responseData', responseData); - - if (responseData && responseData.code === 200) { - let taskDetail = responseData.data.detail; - if (taskDetail && typeof taskDetail === 'string') { - try { - taskDetail = JSON.parse(taskDetail); - } catch (e) { - console.error('解析任务详情失败 (detail):', e); - taskDetail = null; - } - } - setTasks(prevTasks => - prevTasks.map(task => - task.id === taskId ? { ...task, detail: taskDetail } : task, - ), - ); - } else { - console.error('获取任务详情失败: responseData.code is not 200'); - } - } - } catch (error) { - console.error('获取任务详情失败:', error); - } - }, - [serverUrl, apiEndpoints], - ); + const fetchTaskDetail = useCallback(async (taskId: string) => { + try { + const taskDetail = await getTaskDetailService(taskId); + setTasks(prevTasks => + prevTasks.map(task => + task.id === taskId ? { ...task, detail: taskDetail.detail } : task, + ), + ); + } catch (error) { + console.error('获取任务详情失败 (context):', error); + } + }, []); const updateTask = useCallback((updatedTask: Task) => { setTasks(prevTasks => @@ -215,72 +120,21 @@ export const TasksProvider: React.FC<{ children: ReactNode }> = ({ ); }, []); - const runTask = useCallback( - async (id: string) => { - const task = tasks.find(t => t.id === id); - if (!task || !serverUrl || !apiEndpoints) return; - - setTasks(prevTasks => - prevTasks.map(t => (t.id === id ? { ...t, status: 1 } : t)), - ); - - try { - const parameters = Object.entries(task.parameters).reduce( - (acc, [key, param]) => { - if (param) { - acc[key] = param.value; - } - return acc; - }, - {} as { [key: string]: any }, - ); - - const endpoint = apiEndpoints.runTask.replace('{taskId}', task.id); - await executeTask(serverUrl, endpoint, { - name: task.name, - parameters: parameters, - }); - - setTimeout(() => { - setTasks(prevTasks => - prevTasks.map(t => (t.id === id ? { ...t, status: 2 } : t)), - ); - }, 5000); - } catch (error) { - console.error('任务执行失败:', error); - setTasks(prevTasks => - prevTasks.map(t => (t.id === id ? { ...t, status: 3 } : t)), - ); - } - }, - [tasks, serverUrl, apiEndpoints], - ); - const contextValue = useMemo( () => ({ tasks, - locations, - locationsBays, - payloads, - robotActions, serverUrl, getTaskById, updateTask, - runTask, refreshConfig, isConfigLoaded, fetchTaskDetail, }), [ tasks, - locations, - locationsBays, - payloads, - robotActions, serverUrl, getTaskById, updateTask, - runTask, refreshConfig, isConfigLoaded, fetchTaskDetail, diff --git a/src/screens/TaskListScreen.tsx b/src/screens/TaskListScreen.tsx index d98f94a..69c7e18 100644 --- a/src/screens/TaskListScreen.tsx +++ b/src/screens/TaskListScreen.tsx @@ -17,6 +17,8 @@ type TaskListNavigationProp = StackNavigationProp< export default function TaskListScreen() { const { tasks } = useTasks(); + console.log('tasks', tasks); + const navigation = useNavigation(); const handlePressTask = (id: string) => { diff --git a/src/services/taskService.ts b/src/services/taskService.ts index 2b68a11..c819307 100644 --- a/src/services/taskService.ts +++ b/src/services/taskService.ts @@ -1,8 +1,20 @@ import { getSettings, getConfig } from './configService'; import { RunTaskRequest, RunTaskApiResponse, Task } from '../types/task'; +// 获取通用请求头 +const getHeaders = async () => { + const config = await getConfig(); + return { + 'Content-Type': 'application/json', + ...config?.headers, + }; +}; + // 获取任务列表 -export const getTasks = async (): Promise => { +export const getTasks = async (params: { + pageNum: number; + pageSize: number; +}): Promise => { try { const config = await getConfig(); const endpoint = config?.apiEndpoints?.getTasks; @@ -18,10 +30,14 @@ export const getTasks = async (): Promise => { throw new Error('服务器地址未配置'); } - const url = `${serverUrl.replace(/\/$/, '')}${endpoint}`; + const urlObj = new URL(`${serverUrl.replace(/\/$/, '')}${endpoint}`); + urlObj.searchParams.append('pageNum', String(params.pageNum)); + urlObj.searchParams.append('pageSize', String(params.pageSize)); + const url = urlObj.toString(); console.log('获取任务列表:', url); - const response = await fetch(url); + const headers = await getHeaders(); + const response = await fetch(url, { headers }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } @@ -31,7 +47,15 @@ export const getTasks = async (): Promise => { throw new Error(`API 错误: ${result.message}`); } - return result.data; + // 兼容两种可能的数据结构: result.data.list or result.data + if (result.data && Array.isArray(result.data.list)) { + return result.data.list; + } + if (Array.isArray(result.data)) { + return result.data; + } + console.warn('任务列表数据格式不正确', result.data); + return []; } catch (error) { console.error('获取任务列表失败:', error); throw error; @@ -59,7 +83,8 @@ export const getTaskDetail = async (taskId: string): Promise => { const url = `${serverUrl.replace(/\/$/, '')}${endpoint}`; console.log('获取任务详情:', url); - const response = await fetch(url); + const headers = await getHeaders(); + const response = await fetch(url, { headers }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } @@ -98,11 +123,10 @@ export const runTask = async ( const url = `${serverUrl.replace(/\/$/, '')}${endpoint}`; console.log('运行任务请求:', url, JSON.stringify(taskData, null, 2)); + const headers = await getHeaders(); const response = await fetch(url, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: headers, body: JSON.stringify(taskData), }); diff --git a/src/types/config.ts b/src/types/config.ts index c40783f..c1cf7ea 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,35 +1,15 @@ -// 配置文件中的位置选项 -export interface LocationOption { - label: string; - value: string; -} - -// 配置文件中的载荷选项 -export interface PayloadOption { - label: string; - value: string; -} - -// 配置文件中的机器人动作选项 -export interface RobotActionOption { - label: string; - value: string; // 动作的名称,作为 Picker 的 value - actionId: string; -} - // 完整的配置文件结构 export interface AppConfig { version: string; - locations: LocationOption[]; - locationsBays: LocationOption[]; - payloads: PayloadOption[]; - robotActions: RobotActionOption[]; serverUrl?: string; // 服务器地址 apiEndpoints?: { getTasks: string; getTaskDetail: string; runTask: string; }; + headers?: { + [key: string]: string | number; + }; } // 设置存储接口