feat:新增起点,终点,库位 ,机器人动作 下拉选择功能。

This commit is contained in:
xudan 2025-07-21 15:59:44 +08:00
parent 5ecb12a679
commit a4372a12fc
4 changed files with 122 additions and 190 deletions

View File

@ -21,12 +21,15 @@ const TaskCard: React.FC<TaskCardProps> = ({ task, onPress }) => {
return (
<Card style={styles.card} onPress={() => onPress(task.id)}>
<Card.Content>
<Text variant="titleMedium" style={styles.title}>{task.name}</Text>
<Chip
icon="information"
<Text variant="titleMedium" style={styles.title}>
{task.name}
</Text>
<Chip
icon="information"
mode="outlined"
selectedColor={statusColors[task.status]}
style={[styles.chip, {backgroundColor: theme.colors.surface}]}
style={[styles.chip, { backgroundColor: theme.colors.surface }]}
textStyle={{ fontSize: 12 }}
>
{task.status}
</Chip>
@ -46,7 +49,7 @@ const styles = StyleSheet.create({
},
chip: {
alignSelf: 'flex-start',
}
},
});
export default TaskCard;

View File

@ -1,9 +1,8 @@
import React, { useState } from 'react';
import { View, StyleSheet, ScrollView } from 'react-native';
import { TextInput } from 'react-native-paper';
import DropDown from "react-native-paper-dropdown";
import { TextInput, Menu, Button, Divider, Text } from 'react-native-paper';
import { Task, RobotAction } from '../types/task';
import { LOCATIONS, ROBOT_ACTIONS, PAYLOADS } from '../data/mockData';
import { LOCATIONS, ROBOT_ACTIONS, PAYLOADS, LOCATIONS_BAYS } from '../data/mockData';
interface TaskFormProps {
task: Task;
@ -11,138 +10,91 @@ interface TaskFormProps {
}
const TaskForm: React.FC<TaskFormProps> = ({ task, onTaskChange }) => {
const [showStartLocation, setShowStartLocation] = useState(false);
const [showEndLocation, setShowEndLocation] = useState(false);
const [showRobotAction, setShowRobotAction] = useState(false);
const [showPayload, setShowPayload] = useState(false);
const [menuVisible, setMenuVisible] = useState<{ [key: string]: boolean }>({});
const handleParamChange = (field: string, value: string | RobotAction) => {
const updatedTask = {
...task,
parameters: {
...task.parameters,
[field]: value,
},
const openMenu = (name: string) => setMenuVisible(prev => ({ ...prev, [name]: true }));
const closeMenu = (name: string) => setMenuVisible(prev => ({ ...prev, [name]: false }));
const handleParamChange = (field: string, value: string | RobotAction) => {
const updatedTask = {
...task,
parameters: {
...task.parameters,
[field]: value,
},
};
onTaskChange(updatedTask);
};
onTaskChange(updatedTask);
};
return (
<ScrollView contentContainerStyle={styles.container}>
<TextInput
label="任务名称"
value={task.name}
onChangeText={text => onTaskChange({ ...task, name: text })}
style={styles.input}
mode="outlined"
/>
const renderDropdown = (
name: string,
label: string,
value: string,
items: { label: string, value: string }[]
) => (
<View style={styles.input}>
<Text>{label}</Text>
<Menu
visible={menuVisible[name]}
onDismiss={() => closeMenu(name)}
anchor={
<Button onPress={() => openMenu(name)} mode="outlined">
{value || `选择${label}`}
</Button>
}
>
<ScrollView style={{ maxHeight: 200 }}>
{items.map(item => (
<Menu.Item
key={item.value}
onPress={() => {
handleParamChange(name, item.value);
closeMenu(name);
}}
title={item.label}
/>
))}
</ScrollView>
</Menu>
</View>
);
{/* <DropDown
label={"起点"}
mode={"outlined"}
visible={showStartLocation}
showDropDown={() => setShowStartLocation(true)}
onDismiss={() => setShowStartLocation(false)}
value={task.parameters.startLocation}
setValue={(value) => handleParamChange('startLocation', value)}
list={LOCATIONS.map((location) => ({
label: location.label,
value: location.value,
}))}
dropDownStyle={styles.input}
/> */}
<TextInput
label="起点"
value={task.parameters.startLocation}
onChangeText={text => handleParamChange('startLocation', text)}
style={styles.input}
mode="outlined"
/>
return (
<ScrollView contentContainerStyle={styles.container}>
<TextInput
label="任务名称"
value={task.name}
onChangeText={text => onTaskChange({ ...task, name: text })}
style={styles.input}
mode="outlined"
/>
{/* <DropDown
label={"终点"}
mode={"outlined"}
visible={showEndLocation}
showDropDown={() => setShowEndLocation(true)}
onDismiss={() => setShowEndLocation(false)}
value={task.parameters.endLocation}
setValue={(value) => handleParamChange('endLocation', value)}
list={LOCATIONS.map((location) => ({
label: location.label,
value: location.value,
}))}
dropDownStyle={styles.input}
/> */}
<TextInput
label="终点"
value={task.parameters.endLocation}
onChangeText={text => handleParamChange('endLocation', text)}
style={styles.input}
mode="outlined"
/>
<TextInput
label="途经点 (可选)"
value={task.parameters.waypoint || ''}
onChangeText={text => handleParamChange('waypoint', text)}
style={styles.input}
mode="outlined"
/>
{/* <DropDown
label={"机器人动作"}
mode={"outlined"}
visible={showRobotAction}
showDropDown={() => setShowRobotAction(true)}
onDismiss={() => setShowRobotAction(false)}
value={task.parameters.robotAction}
setValue={(value) => handleParamChange('robotAction', value)}
list={ROBOT_ACTIONS.map((action) => ({
label: action.label,
value: action.value,
}))}
dropDownStyle={styles.input}
/> */}
<TextInput
label="机器人动作"
value={task.parameters.robotAction}
onChangeText={text => handleParamChange('robotAction', text)}
style={styles.input}
mode="outlined"
/>
{renderDropdown('startLocation', '起点', task.parameters.startLocation, LOCATIONS)}
{renderDropdown('endLocation', '终点', task.parameters.endLocation, LOCATIONS)}
<TextInput
label="途经点 (可选)"
value={task.parameters.waypoint || ''}
onChangeText={text => handleParamChange('waypoint', text)}
style={styles.input}
mode="outlined"
/>
{renderDropdown('robotAction', '机器人动作', task.parameters.robotAction, ROBOT_ACTIONS)}
{renderDropdown('payload', '载荷', task.parameters.payload, PAYLOADS)}
{renderDropdown('locationBay', '库位', task.parameters.locationBay, LOCATIONS_BAYS)}
{/* <DropDown
label={"载荷"}
mode={"outlined"}
visible={showPayload}
showDropDown={() => setShowPayload(true)}
onDismiss={() => setShowPayload(false)}
value={task.parameters.payload}
setValue={(value) => handleParamChange('payload', value)}
list={PAYLOADS.map((payload) => ({
label: payload.label,
value: payload.value,
}))}
dropDownStyle={styles.input}
/> */}
<TextInput
label="载荷"
value={task.parameters.payload}
onChangeText={text => handleParamChange('payload', text)}
style={styles.input}
mode="outlined"
/>
</ScrollView>
);
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
padding: 16,
},
input: {
marginBottom: 16,
},
container: {
padding: 16,
},
input: {
marginBottom: 16,
},
});
export default TaskForm;

View File

@ -1,23 +1,25 @@
import { Task, RobotAction } from '../types/task';
import { v4 as uuidv4 } from 'uuid';
export const LOCATIONS = [
{ label: '炉前缓存区', value: '炉前缓存区' },
{ label: '热处理上料交接区', value: '热处理上料交接区' },
{ label: '空料架缓存区', value: '空料架缓存区' },
{ label: '焊接空料架交接区', value: '焊接空料架交接区' },
{ label: '热后区', value: '热后区' },
{ label: 'ALD上料区', value: 'ALD上料区' },
{ label: '空车区', value: '空车区' },
];
export const LOCATIONS = Array.from({ length: 100 }, (_, i) => ({
label: `AP-${i + 1}`,
value: `AP-${i + 1}`,
}));
export const ROBOT_ACTIONS: { label: string; value: RobotAction }[] = [
{ label: '运输', value: 'TRANSPORT' },
{ label: '取货', value: 'PICKUP' },
{ label: '卸货', value: 'DROPOFF' },
{ label: '等待', value: 'WAIT' },
{ label: '充电', value: 'CHARGE' },
{ label: '清洁', value: 'CLEAN' },
];
export const LOCATIONS_BAYS = Array.from({ length: 100 }, (_, i) => ({
label: `AS2_2_${String(i + 1).padStart(3, '0')}`,
value: `AS2_2_${String(i + 1).padStart(3, '0')}`,
}));
export const PAYLOADS = [
{ label: '满料架-A1', value: '满料架-A1' },
{ label: '空料架-B2', value: '空料架-B2' },
@ -25,53 +27,27 @@ export const PAYLOADS = [
{ label: '空车', value: '空车' },
];
export const MOCK_TASKS: Task[] = [
{
id: uuidv4(),
name: '炉前缓存区到热处理上料交接区运输',
status: 'IDLE',
createdAt: new Date().toISOString(),
parameters: {
startLocation: '炉前缓存区',
endLocation: '热处理上料交接区',
robotAction: 'TRANSPORT',
payload: '满料架-A1',
},
},
{
id: uuidv4(),
name: '空料架到焊接空料架交接区运输',
status: 'RUNNING',
createdAt: new Date().toISOString(),
parameters: {
startLocation: '空料架缓存区',
endLocation: '焊接空料架交接区',
robotAction: 'TRANSPORT',
payload: '空料架-B2',
},
},
{
id: uuidv4(),
name: '热后空料架返回交接区',
status: 'COMPLETED',
createdAt: new Date().toISOString(),
parameters: {
startLocation: '热后区',
endLocation: '空料架缓存区',
robotAction: 'TRANSPORT',
payload: '空料架-C3',
},
},
{
id: uuidv4(),
name: 'ALD上料空车运输到空车区',
status: 'IDLE',
createdAt: new Date().toISOString(),
parameters: {
startLocation: 'ALD上料区',
endLocation: '空车区',
robotAction: 'TRANSPORT',
payload: '空车',
},
},
];
const getRandomElement = <T>(arr: T[]): T => arr[Math.floor(Math.random() * arr.length)];
export const MOCK_TASKS: Task[] = Array.from({ length: 15 }, (_, i) => {
const startLocation = getRandomElement(LOCATIONS);
const endLocation = getRandomElement(LOCATIONS.filter(l => l.value !== startLocation.value));
const robotAction = getRandomElement(ROBOT_ACTIONS);
const payload = getRandomElement(PAYLOADS);
const statusOptions: Task['status'][] = ['IDLE', 'RUNNING', 'COMPLETED', 'ERROR'];
const status = getRandomElement(statusOptions);
return {
id: uuidv4(),
name: `任务 ${i + 1}: 从 ${startLocation.label}${endLocation.label}`,
status: status,
createdAt: new Date(new Date().getTime() - Math.random() * 1000 * 60 * 60 * 24).toISOString(),
parameters: {
startLocation: startLocation.value,
endLocation: endLocation.value,
robotAction: robotAction.value,
payload: payload.value,
locationBay: getRandomElement(LOCATIONS_BAYS).value,
},
};
});

View File

@ -11,6 +11,7 @@ export interface TaskParameters {
waypoint?: string; // 途经点 (可选)
robotAction: RobotAction; // 机器人动作
payload: string; // 载荷,比如 '空料架' 或具体的物料ID
locationBay?: string; // 库位 (可选)
}
// 核心任务对象