webapp/src/screens/TaskEditScreen.tsx

179 lines
4.5 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import {
View,
StyleSheet,
Alert,
ScrollView,
ActivityIndicator,
Text,
} from 'react-native';
import { useRoute, useNavigation } from '@react-navigation/native';
import { RouteProp } from '@react-navigation/native';
import { useTasks } from '../context/TasksContext';
import TaskForm from '../components/TaskForm';
import BottomActionBar from '../components/BottomActionBar';
import { Task, RunTaskRequest, RunTaskApiResponse } from '../types/task';
import { runTask as runTaskService } from '../services/taskService';
type RootStackParamList = {
TaskEdit: { taskId: string };
};
type TaskEditRouteProp = RouteProp<RootStackParamList, 'TaskEdit'>;
export default function TaskEditScreen() {
const route = useRoute<TaskEditRouteProp>();
const navigation = useNavigation();
const { taskId } = route.params;
const { getTaskById, updateTask, tasks, fetchTaskDetail } = useTasks();
const [task, setTask] = useState<Task | null>(null);
const [originalTask, setOriginalTask] = useState<Task | null>(null);
const [isModified, setIsModified] = useState(false);
const [isRunLoading, setIsRunLoading] = useState(false);
const [runResponse, setRunResponse] = useState<RunTaskApiResponse | null>(
null,
);
useEffect(() => {
const loadTask = async () => {
let taskData = getTaskById(taskId);
debugger;
if (taskData && !taskData.detail) {
await fetchTaskDetail(taskId);
taskData = getTaskById(taskId);
}
if (taskData) {
setTask(taskData);
setOriginalTask(taskData);
}
};
loadTask();
}, [taskId, getTaskById, tasks, fetchTaskDetail]);
const handleTaskChange = (updatedTask: Task) => {
setTask(updatedTask);
if (!isModified) {
setIsModified(true);
}
};
const handleSave = () => {
if (task) {
updateTask(task);
setOriginalTask(task);
setIsModified(false);
Alert.alert('已保存', `任务 "${task.name}" 已被保存。`);
}
};
const handleRun = async () => {
if (!task || !task.detail || !task.detail.inputParams) {
Alert.alert('错误', '任务数据不完整,无法运行。');
return;
}
setIsRunLoading(true);
setRunResponse(null);
try {
const params = task.detail.inputParams.map(p => ({
name: p.name,
type: p.type,
label: p.label,
required: p.required,
defaultValue: p.defaultValue,
remark: p.remark,
}));
const request: RunTaskRequest = {
taskId: task.id,
params: params,
source_type: 1,
source_system: 'SYSTEM',
source_device: '666',
};
const result = await runTaskService(request);
setRunResponse(result);
Alert.alert('成功', `任务已启动, 记录ID: ${result.data.taskRecordId}`);
} catch (error: any) {
Alert.alert('运行失败', error.message || '发生未知错误');
} finally {
setIsRunLoading(false);
}
};
const handleUndo = () => {
setTask(originalTask);
setIsModified(false);
};
if (!task) {
return (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#00ff00" />
</View>
);
}
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.scrollContainer}>
<TaskForm task={task} onTaskChange={handleTaskChange} />
{runResponse && (
<View style={styles.responseContainer}>
<Text style={styles.responseTitle}>:</Text>
<Text style={styles.responseText}>
{JSON.stringify(runResponse, null, 2)}
</Text>
</View>
)}
</ScrollView>
<BottomActionBar
onRun={handleRun}
onSave={handleSave}
onUndo={handleUndo}
onBack={() => navigation.goBack()}
isSaveDisabled={!isModified}
isRunLoading={isRunLoading}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#1a1a1a',
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#1a1a1a',
},
scrollContainer: {
padding: 16,
paddingBottom: 80,
},
responseContainer: {
marginTop: 20,
padding: 15,
backgroundColor: '#2c2c2c',
borderRadius: 8,
},
responseTitle: {
fontSize: 16,
fontWeight: 'bold',
color: '#ffffff',
marginBottom: 10,
},
responseText: {
fontSize: 14,
color: '#e0e0e0',
fontFamily: 'monospace',
},
});