179 lines
4.5 KiB
TypeScript
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',
|
|
},
|
|
});
|