feat:新增起点,终点,库位 ,机器人动作 下拉选择功能。
This commit is contained in:
parent
5ecb12a679
commit
a4372a12fc
@ -21,12 +21,15 @@ const TaskCard: React.FC<TaskCardProps> = ({ task, onPress }) => {
|
|||||||
return (
|
return (
|
||||||
<Card style={styles.card} onPress={() => onPress(task.id)}>
|
<Card style={styles.card} onPress={() => onPress(task.id)}>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Text variant="titleMedium" style={styles.title}>{task.name}</Text>
|
<Text variant="titleMedium" style={styles.title}>
|
||||||
<Chip
|
{task.name}
|
||||||
icon="information"
|
</Text>
|
||||||
|
<Chip
|
||||||
|
icon="information"
|
||||||
mode="outlined"
|
mode="outlined"
|
||||||
selectedColor={statusColors[task.status]}
|
selectedColor={statusColors[task.status]}
|
||||||
style={[styles.chip, {backgroundColor: theme.colors.surface}]}
|
style={[styles.chip, { backgroundColor: theme.colors.surface }]}
|
||||||
|
textStyle={{ fontSize: 12 }}
|
||||||
>
|
>
|
||||||
{task.status}
|
{task.status}
|
||||||
</Chip>
|
</Chip>
|
||||||
@ -46,7 +49,7 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
chip: {
|
chip: {
|
||||||
alignSelf: 'flex-start',
|
alignSelf: 'flex-start',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default TaskCard;
|
export default TaskCard;
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
import { View, StyleSheet, ScrollView } from 'react-native';
|
||||||
import { TextInput } from 'react-native-paper';
|
import { TextInput, Menu, Button, Divider, Text } from 'react-native-paper';
|
||||||
import DropDown from "react-native-paper-dropdown";
|
|
||||||
import { Task, RobotAction } from '../types/task';
|
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 {
|
interface TaskFormProps {
|
||||||
task: Task;
|
task: Task;
|
||||||
@ -11,138 +10,91 @@ interface TaskFormProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TaskForm: React.FC<TaskFormProps> = ({ task, onTaskChange }) => {
|
const TaskForm: React.FC<TaskFormProps> = ({ task, onTaskChange }) => {
|
||||||
const [showStartLocation, setShowStartLocation] = useState(false);
|
const [menuVisible, setMenuVisible] = useState<{ [key: string]: boolean }>({});
|
||||||
const [showEndLocation, setShowEndLocation] = useState(false);
|
|
||||||
const [showRobotAction, setShowRobotAction] = useState(false);
|
|
||||||
const [showPayload, setShowPayload] = useState(false);
|
|
||||||
|
|
||||||
const handleParamChange = (field: string, value: string | RobotAction) => {
|
const openMenu = (name: string) => setMenuVisible(prev => ({ ...prev, [name]: true }));
|
||||||
const updatedTask = {
|
const closeMenu = (name: string) => setMenuVisible(prev => ({ ...prev, [name]: false }));
|
||||||
...task,
|
|
||||||
parameters: {
|
const handleParamChange = (field: string, value: string | RobotAction) => {
|
||||||
...task.parameters,
|
const updatedTask = {
|
||||||
[field]: value,
|
...task,
|
||||||
},
|
parameters: {
|
||||||
|
...task.parameters,
|
||||||
|
[field]: value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
onTaskChange(updatedTask);
|
||||||
};
|
};
|
||||||
onTaskChange(updatedTask);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
const renderDropdown = (
|
||||||
<ScrollView contentContainerStyle={styles.container}>
|
name: string,
|
||||||
<TextInput
|
label: string,
|
||||||
label="任务名称"
|
value: string,
|
||||||
value={task.name}
|
items: { label: string, value: string }[]
|
||||||
onChangeText={text => onTaskChange({ ...task, name: text })}
|
) => (
|
||||||
style={styles.input}
|
<View style={styles.input}>
|
||||||
mode="outlined"
|
<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
|
return (
|
||||||
label={"起点"}
|
<ScrollView contentContainerStyle={styles.container}>
|
||||||
mode={"outlined"}
|
<TextInput
|
||||||
visible={showStartLocation}
|
label="任务名称"
|
||||||
showDropDown={() => setShowStartLocation(true)}
|
value={task.name}
|
||||||
onDismiss={() => setShowStartLocation(false)}
|
onChangeText={text => onTaskChange({ ...task, name: text })}
|
||||||
value={task.parameters.startLocation}
|
style={styles.input}
|
||||||
setValue={(value) => handleParamChange('startLocation', value)}
|
mode="outlined"
|
||||||
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"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* <DropDown
|
{renderDropdown('startLocation', '起点', task.parameters.startLocation, LOCATIONS)}
|
||||||
label={"终点"}
|
{renderDropdown('endLocation', '终点', task.parameters.endLocation, LOCATIONS)}
|
||||||
mode={"outlined"}
|
|
||||||
visible={showEndLocation}
|
<TextInput
|
||||||
showDropDown={() => setShowEndLocation(true)}
|
label="途经点 (可选)"
|
||||||
onDismiss={() => setShowEndLocation(false)}
|
value={task.parameters.waypoint || ''}
|
||||||
value={task.parameters.endLocation}
|
onChangeText={text => handleParamChange('waypoint', text)}
|
||||||
setValue={(value) => handleParamChange('endLocation', value)}
|
style={styles.input}
|
||||||
list={LOCATIONS.map((location) => ({
|
mode="outlined"
|
||||||
label: location.label,
|
/>
|
||||||
value: location.value,
|
|
||||||
}))}
|
{renderDropdown('robotAction', '机器人动作', task.parameters.robotAction, ROBOT_ACTIONS)}
|
||||||
dropDownStyle={styles.input}
|
{renderDropdown('payload', '载荷', task.parameters.payload, PAYLOADS)}
|
||||||
/> */}
|
{renderDropdown('locationBay', '库位', task.parameters.locationBay, LOCATIONS_BAYS)}
|
||||||
<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"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* <DropDown
|
</ScrollView>
|
||||||
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>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
padding: 16,
|
padding: 16,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default TaskForm;
|
export default TaskForm;
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
import { Task, RobotAction } from '../types/task';
|
import { Task, RobotAction } from '../types/task';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export const LOCATIONS = [
|
export const LOCATIONS = Array.from({ length: 100 }, (_, i) => ({
|
||||||
{ label: '炉前缓存区', value: '炉前缓存区' },
|
label: `AP-${i + 1}`,
|
||||||
{ label: '热处理上料交接区', value: '热处理上料交接区' },
|
value: `AP-${i + 1}`,
|
||||||
{ label: '空料架缓存区', value: '空料架缓存区' },
|
}));
|
||||||
{ label: '焊接空料架交接区', value: '焊接空料架交接区' },
|
|
||||||
{ label: '热后区', value: '热后区' },
|
|
||||||
{ label: 'ALD上料区', value: 'ALD上料区' },
|
|
||||||
{ label: '空车区', value: '空车区' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const ROBOT_ACTIONS: { label: string; value: RobotAction }[] = [
|
export const ROBOT_ACTIONS: { label: string; value: RobotAction }[] = [
|
||||||
{ label: '运输', value: 'TRANSPORT' },
|
{ label: '运输', value: 'TRANSPORT' },
|
||||||
{ label: '取货', value: 'PICKUP' },
|
{ label: '取货', value: 'PICKUP' },
|
||||||
{ label: '卸货', value: 'DROPOFF' },
|
{ label: '卸货', value: 'DROPOFF' },
|
||||||
{ label: '等待', value: 'WAIT' },
|
{ 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 = [
|
export const PAYLOADS = [
|
||||||
{ label: '满料架-A1', value: '满料架-A1' },
|
{ label: '满料架-A1', value: '满料架-A1' },
|
||||||
{ label: '空料架-B2', value: '空料架-B2' },
|
{ label: '空料架-B2', value: '空料架-B2' },
|
||||||
@ -25,53 +27,27 @@ export const PAYLOADS = [
|
|||||||
{ label: '空车', value: '空车' },
|
{ label: '空车', value: '空车' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const MOCK_TASKS: Task[] = [
|
const getRandomElement = <T>(arr: T[]): T => arr[Math.floor(Math.random() * arr.length)];
|
||||||
{
|
|
||||||
id: uuidv4(),
|
export const MOCK_TASKS: Task[] = Array.from({ length: 15 }, (_, i) => {
|
||||||
name: '炉前缓存区到热处理上料交接区运输',
|
const startLocation = getRandomElement(LOCATIONS);
|
||||||
status: 'IDLE',
|
const endLocation = getRandomElement(LOCATIONS.filter(l => l.value !== startLocation.value));
|
||||||
createdAt: new Date().toISOString(),
|
const robotAction = getRandomElement(ROBOT_ACTIONS);
|
||||||
parameters: {
|
const payload = getRandomElement(PAYLOADS);
|
||||||
startLocation: '炉前缓存区',
|
const statusOptions: Task['status'][] = ['IDLE', 'RUNNING', 'COMPLETED', 'ERROR'];
|
||||||
endLocation: '热处理上料交接区',
|
const status = getRandomElement(statusOptions);
|
||||||
robotAction: 'TRANSPORT',
|
|
||||||
payload: '满料架-A1',
|
return {
|
||||||
},
|
id: uuidv4(),
|
||||||
},
|
name: `任务 ${i + 1}: 从 ${startLocation.label} 到 ${endLocation.label}`,
|
||||||
{
|
status: status,
|
||||||
id: uuidv4(),
|
createdAt: new Date(new Date().getTime() - Math.random() * 1000 * 60 * 60 * 24).toISOString(),
|
||||||
name: '空料架到焊接空料架交接区运输',
|
parameters: {
|
||||||
status: 'RUNNING',
|
startLocation: startLocation.value,
|
||||||
createdAt: new Date().toISOString(),
|
endLocation: endLocation.value,
|
||||||
parameters: {
|
robotAction: robotAction.value,
|
||||||
startLocation: '空料架缓存区',
|
payload: payload.value,
|
||||||
endLocation: '焊接空料架交接区',
|
locationBay: getRandomElement(LOCATIONS_BAYS).value,
|
||||||
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: '空车',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
@ -11,6 +11,7 @@ export interface TaskParameters {
|
|||||||
waypoint?: string; // 途经点 (可选)
|
waypoint?: string; // 途经点 (可选)
|
||||||
robotAction: RobotAction; // 机器人动作
|
robotAction: RobotAction; // 机器人动作
|
||||||
payload: string; // 载荷,比如 '空料架' 或具体的物料ID
|
payload: string; // 载荷,比如 '空料架' 或具体的物料ID
|
||||||
|
locationBay?: string; // 库位 (可选)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 核心任务对象
|
// 核心任务对象
|
||||||
|
Loading…
x
Reference in New Issue
Block a user