| | |
| | | import React from 'react'; |
| | | import React, { useEffect } from 'react'; |
| | | import { useTranslate } from "react-admin"; |
| | | import { useForm, Controller } from 'react-hook-form'; |
| | | import { |
| | | Button, |
| | |
| | | ToggleButton, |
| | | ToggleButtonGroup, |
| | | Typography, |
| | | Divider, |
| | | Toolbar, |
| | | useTheme, |
| | | Autocomplete, |
| | | CircularProgress, |
| | | } from '@mui/material'; |
| | | import CheckOutlinedIcon from '@mui/icons-material/CheckOutlined'; |
| | | import RestartAltIcon from '@mui/icons-material/RestartAlt'; |
| | | import useCoolHook from './useCoolHook'; |
| | | import { handleControlAgv } from '../../http'; |
| | | |
| | | function AgvControl({ open, onClose }) { |
| | | const { control, handleSubmit, reset, watch } = useForm({ |
| | | function AgvControl(props) { |
| | | const { curAgvNo } = props; |
| | | const theme = useTheme(); |
| | | const translate = useTranslate(); |
| | | |
| | | const { control, handleSubmit, reset, watch, setValue } = useForm({ |
| | | defaultValues: { |
| | | taskMode: 'MOVE', |
| | | startCode: '', |
| | | endCode: '', |
| | | startLocNo: '', |
| | | endLocNo: '', |
| | | startStaNo: '', |
| | | endStaNo: '', |
| | | }, |
| | | }); |
| | | |
| | | const taskModes = [ |
| | | { value: 'MOVE', label: '移动' }, |
| | | { value: 'TO_CHARGE', label: '去充电' }, |
| | | { value: 'TO_STANDBY', label: '去待机位' }, |
| | | { value: 'LOC_TO_LOC', label: '库位到库位' }, |
| | | { value: 'LOC_TO_STA', label: '库位到站点' }, |
| | | { value: 'STA_TO_LOC', label: '站点到库位' }, |
| | | { value: 'STA_TO_STA', label: '站点到站点' }, |
| | | { value: 'MOVE', label: translate('page.map.insight.control.type.MOVE') }, |
| | | { value: 'TO_CHARGE', label: translate('page.map.insight.control.type.TO_CHARGE') }, |
| | | { value: 'TO_STANDBY', label: translate('page.map.insight.control.type.TO_STANDBY') }, |
| | | { value: 'LOC_TO_LOC', label: translate('page.map.insight.control.type.LOC_TO_LOC') }, |
| | | { value: 'LOC_TO_STA', label: translate('page.map.insight.control.type.LOC_TO_STA') }, |
| | | { value: 'STA_TO_LOC', label: translate('page.map.insight.control.type.STA_TO_LOC') }, |
| | | { value: 'STA_TO_STA', label: translate('page.map.insight.control.type.STA_TO_STA') }, |
| | | ]; |
| | | |
| | | useEffect(() => { |
| | | reset(); |
| | | }, [curAgvNo, reset]); |
| | | |
| | | const onSubmit = (data) => { |
| | | console.log(data); |
| | | if (curAgvNo) { |
| | | handleControlAgv({ agvNo: curAgvNo, ...data }, () => { |
| | | |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const taskMode = watch('taskMode'); |
| | |
| | | } |
| | | }; |
| | | |
| | | const { |
| | | options: endCodeOptions, |
| | | setInputValue: setEndCodeInputValue, |
| | | resetInput: resetEndCodeInput, |
| | | } = useCoolHook('/code/page', 'data'); |
| | | |
| | | const { |
| | | options: startLocOptions, |
| | | setInputValue: setStartLocInputValue, |
| | | resetInput: resetStartLocInput, |
| | | } = useCoolHook('/loc/page', 'locNo'); |
| | | |
| | | const { |
| | | options: endLocOptions, |
| | | setInputValue: setEndLocInputValue, |
| | | resetInput: resetEndLocInput, |
| | | } = useCoolHook('/loc/page', 'locNo'); |
| | | |
| | | const { |
| | | options: startStaOptions, |
| | | setInputValue: setStartStaInputValue, |
| | | resetInput: resetStartStaInput, |
| | | } = useCoolHook('/sta/page', 'staNo'); |
| | | |
| | | const { |
| | | options: endStaOptions, |
| | | setInputValue: setEndStaInputValue, |
| | | resetInput: resetEndStaInput, |
| | | } = useCoolHook('/sta/page', 'staNo'); |
| | | |
| | | useEffect(() => { |
| | | const fieldsToClear = ['endCode', 'startLocNo', 'endLocNo', 'startStaNo', 'endStaNo']; |
| | | |
| | | fieldsToClear.forEach(field => { |
| | | if (!showField(field)) { |
| | | setValue(field, ''); |
| | | |
| | | switch (field) { |
| | | case 'endCode': |
| | | resetEndCodeInput(); |
| | | break; |
| | | case 'startLocNo': |
| | | resetStartLocInput(); |
| | | break; |
| | | case 'endLocNo': |
| | | resetEndLocInput(); |
| | | break; |
| | | case 'startStaNo': |
| | | resetStartStaInput(); |
| | | break; |
| | | case 'endStaNo': |
| | | resetEndStaInput(); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | }); |
| | | }, [ |
| | | taskMode, |
| | | setValue, |
| | | showField, |
| | | resetEndCodeInput, |
| | | resetStartLocInput, |
| | | resetEndLocInput, |
| | | resetStartStaInput, |
| | | resetEndStaInput |
| | | ]); |
| | | return ( |
| | | <Box display="flex" height="100%" p={2}> |
| | | <> |
| | | <form onSubmit={handleSubmit(onSubmit)}> |
| | | <Grid container spacing={2}> |
| | | <Box display="flex" flexDirection="row" height="100%" justifyContent="space-around" p={2}> |
| | | {/* left */} |
| | | <Grid item xs={4}> |
| | | <Box |
| | | position="relative" |
| | | width="35%" |
| | | height="100%" |
| | | > |
| | | <Controller |
| | | name="taskMode" |
| | | control={control} |
| | |
| | | </ToggleButtonGroup> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | </Box> |
| | | |
| | | {/* right */} |
| | | <Grid item xs={8}> |
| | | <Box |
| | | position="relative" |
| | | width="55%" |
| | | height="100%" |
| | | > |
| | | <Grid container spacing={2}> |
| | | {showField('startCode') && ( |
| | | <Grid item xs={12}> |
| | | <Controller |
| | | name="startCode" |
| | | control={control} |
| | | rules={{ required: '起始地面码不能为空' }} |
| | | rules={{ required: translate('ra.validation.required') }} |
| | | render={({ field, fieldState }) => ( |
| | | <TextField |
| | | {...field} |
| | | fullWidth |
| | | label="起始地面码" |
| | | label={translate('page.map.insight.control.startCode')} |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | |
| | | <Controller |
| | | name="endCode" |
| | | control={control} |
| | | rules={{ required: '目标地面码不能为空' }} |
| | | render={({ field, fieldState }) => ( |
| | | <TextField |
| | | {...field} |
| | | fullWidth |
| | | label="目标地面码" |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | rules={{ required: translate('ra.validation.required') }} |
| | | render={({ field, fieldState }) => { |
| | | const selectedOption = endCodeOptions.find(option => option.id === field.value) || null; |
| | | return ( |
| | | <Autocomplete |
| | | options={endCodeOptions} |
| | | getOptionLabel={(option) => option.label} |
| | | isOptionEqualToValue={(option, value) => option.id === value.id} |
| | | value={selectedOption} |
| | | onInputChange={(event, value) => { |
| | | setEndCodeInputValue(value); |
| | | }} |
| | | onChange={(event, value) => { |
| | | field.onChange(value ? value.id : null); |
| | | }} |
| | | renderInput={(params) => ( |
| | | <TextField |
| | | {...params} |
| | | label={translate('page.map.insight.control.endCode')} |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | /> |
| | | ); |
| | | }} |
| | | /> |
| | | </Grid> |
| | | )} |
| | |
| | | <Controller |
| | | name="startLocNo" |
| | | control={control} |
| | | rules={{ required: '起始库位不能为空' }} |
| | | render={({ field, fieldState }) => ( |
| | | <TextField |
| | | {...field} |
| | | fullWidth |
| | | label="起始库位" |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | rules={{ required: translate('ra.validation.required') }} |
| | | render={({ field, fieldState }) => { |
| | | const selectedOption = startLocOptions.find(option => option.id === field.value) || null; |
| | | return ( |
| | | <Autocomplete |
| | | options={startLocOptions} |
| | | getOptionLabel={(option) => option.label} |
| | | isOptionEqualToValue={(option, value) => option.id === value.id} |
| | | value={selectedOption} |
| | | onInputChange={(event, value) => { |
| | | setStartLocInputValue(value); |
| | | }} |
| | | onChange={(event, value) => { |
| | | field.onChange(value ? value.id : null); |
| | | }} |
| | | renderInput={(params) => ( |
| | | <TextField |
| | | {...params} |
| | | label={translate('page.map.insight.control.startLoc')} |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | /> |
| | | ); |
| | | }} |
| | | /> |
| | | </Grid> |
| | | )} |
| | |
| | | <Controller |
| | | name="endLocNo" |
| | | control={control} |
| | | rules={{ required: '目标库位不能为空' }} |
| | | render={({ field, fieldState }) => ( |
| | | <TextField |
| | | {...field} |
| | | fullWidth |
| | | label="目标库位" |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | rules={{ required: translate('ra.validation.required') }} |
| | | render={({ field, fieldState }) => { |
| | | const selectedOption = endLocOptions.find(option => option.id === field.value) || null; |
| | | return ( |
| | | <Autocomplete |
| | | options={endLocOptions} |
| | | getOptionLabel={(option) => option.label} |
| | | isOptionEqualToValue={(option, value) => option.id === value.id} |
| | | value={selectedOption} |
| | | onInputChange={(event, value) => { |
| | | setEndLocInputValue(value); |
| | | }} |
| | | onChange={(event, value) => { |
| | | field.onChange(value ? value.id : null); |
| | | }} |
| | | renderInput={(params) => ( |
| | | <TextField |
| | | {...params} |
| | | label={translate('page.map.insight.control.endLoc')} |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | /> |
| | | ); |
| | | }} |
| | | /> |
| | | </Grid> |
| | | )} |
| | |
| | | <Controller |
| | | name="startStaNo" |
| | | control={control} |
| | | rules={{ required: '起始站点不能为空' }} |
| | | render={({ field, fieldState }) => ( |
| | | <TextField |
| | | {...field} |
| | | fullWidth |
| | | label="起始站点" |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | rules={{ required: translate('ra.validation.required') }} |
| | | render={({ field, fieldState }) => { |
| | | const selectedOption = startStaOptions.find(option => option.id === field.value) || null; |
| | | return ( |
| | | <Autocomplete |
| | | options={startStaOptions} |
| | | getOptionLabel={(option) => option.label} |
| | | isOptionEqualToValue={(option, value) => option.id === value.id} |
| | | value={selectedOption} |
| | | onInputChange={(event, value) => { |
| | | setStartStaInputValue(value); |
| | | }} |
| | | onChange={(event, value) => { |
| | | field.onChange(value ? value.id : null); |
| | | }} |
| | | renderInput={(params) => ( |
| | | <TextField |
| | | {...params} |
| | | label={translate('page.map.insight.control.startSta')} |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | /> |
| | | ); |
| | | }} |
| | | /> |
| | | </Grid> |
| | | )} |
| | |
| | | <Controller |
| | | name="endStaNo" |
| | | control={control} |
| | | rules={{ required: '目标站点不能为空' }} |
| | | render={({ field, fieldState }) => ( |
| | | <TextField |
| | | {...field} |
| | | fullWidth |
| | | label="目标站点" |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | rules={{ required: translate('ra.validation.required') }} |
| | | render={({ field, fieldState }) => { |
| | | const selectedOption = endStaOptions.find(option => option.id === field.value) || null; |
| | | return ( |
| | | <Autocomplete |
| | | options={endStaOptions} |
| | | getOptionLabel={(option) => option.label} |
| | | isOptionEqualToValue={(option, value) => option.id === value.id} |
| | | value={selectedOption} |
| | | onInputChange={(event, value) => { |
| | | setEndStaInputValue(value); |
| | | }} |
| | | onChange={(event, value) => { |
| | | field.onChange(value ? value.id : null); |
| | | }} |
| | | renderInput={(params) => ( |
| | | <TextField |
| | | {...params} |
| | | label={translate('page.map.insight.control.endSta')} |
| | | error={!!fieldState.error} |
| | | helperText={fieldState.error?.message} |
| | | /> |
| | | )} |
| | | /> |
| | | ); |
| | | }} |
| | | /> |
| | | </Grid> |
| | | )} |
| | | |
| | | {/* button group */} |
| | | <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'flex-end', mt: 2 }}> |
| | | <Button variant="contained" color="primary" type="submit" sx={{ mr: 2 }}> |
| | | 确认 |
| | | </Button> |
| | | <Button variant="outlined" color="secondary" onClick={() => reset()}> |
| | | 重置 |
| | | </Button> |
| | | </Grid> |
| | | </Grid> |
| | | </Grid> |
| | | </Grid> |
| | | </Box> |
| | | </Box> |
| | | <Box pl={5} pr={5}> |
| | | <Divider sx={{ |
| | | marginBottom: '16px' |
| | | }} /> |
| | | <Toolbar sx={{ |
| | | display: 'flex', |
| | | justifyContent: 'space-between', |
| | | minHeight: { sm: 0 }, |
| | | }}> |
| | | <Button |
| | | variant="outlined" |
| | | color="primary" |
| | | type="submit" |
| | | sx={{ |
| | | borderColor: theme => theme.palette.primary.main, |
| | | color: theme => theme.palette.primary.main, |
| | | }} |
| | | startIcon={ |
| | | <CheckOutlinedIcon sx={{ color: theme => theme.palette.primary.main }} /> |
| | | } |
| | | > |
| | | {translate('ra.action.confirm')} |
| | | </Button> |
| | | |
| | | <Button |
| | | variant="outlined" |
| | | color="primary" |
| | | onClick={() => { |
| | | reset(); |
| | | }} |
| | | sx={{ |
| | | borderColor: theme => theme.palette.warning.main, |
| | | color: theme => theme.palette.warning.main, |
| | | }} |
| | | startIcon={ |
| | | <RestartAltIcon sx={{ color: theme => theme.palette.warning.main }} /> |
| | | } |
| | | > |
| | | {translate('common.action.reset')} |
| | | </Button> |
| | | </Toolbar> |
| | | </Box> |
| | | </form> |
| | | </Box> |
| | | </> |
| | | ); |
| | | } |
| | | |