import React, { useRef, useEffect, useState } from 'react';
|
import * as THREE from 'three';
|
import { useTranslate } from 'react-admin';
|
import {
|
Box,
|
CircularProgress,
|
Grid,
|
Typography,
|
Paper,
|
Button,
|
Divider,
|
Stack,
|
useTheme,
|
} from '@mui/material';
|
import AgvThree from './AgvThree';
|
import { getAgvInfo } from '../../http';
|
import BoolValueIcon from '../BoolValueIcon';
|
import ConfirmButton from '../../../page/components/ConfirmButton';
|
|
let three;
|
|
const startThree = (dom) => {
|
three = new AgvThree(dom);
|
three.startup();
|
}
|
|
const endThree = () => {
|
if (three) {
|
three.destroy();
|
three = null;
|
}
|
}
|
|
const renderThree = (info, curAgvNo) => {
|
if (info && three) {
|
three.generateMesh((loader, addObject) => {
|
const loadModel = (path) => {
|
return new Promise((resolve, reject) => {
|
loader.load(path, (mesh) => {
|
resolve(mesh);
|
}, undefined, (error) => {
|
reject(error);
|
});
|
});
|
};
|
|
Promise.all([
|
loadModel('model/agv/body.fbx'),
|
loadModel('model/agv/loader.fbx'),
|
loadModel('model/agv/fork.fbx'),
|
]).then(([bodyMesh, loaderMesh, forkMesh]) => {
|
const scaleVal = 1;
|
bodyMesh.scale.set(scaleVal, scaleVal, scaleVal);
|
loaderMesh.scale.set(scaleVal, scaleVal, scaleVal);
|
forkMesh.scale.set(scaleVal, scaleVal, scaleVal);
|
|
bodyMesh.position.set(55, 0, 0);;
|
loaderMesh.position.set(55, 150, 0);;
|
forkMesh.position.set(55, 165, 0);;
|
|
const agvGroup = new THREE.Group();
|
agvGroup.add(bodyMesh);
|
agvGroup.add(loaderMesh);
|
agvGroup.add(forkMesh);
|
|
agvGroup.name = curAgvNo;
|
|
addObject(agvGroup);
|
|
three.rePerspective(350, 450);
|
|
}).catch((error) => {
|
console.error(error);
|
});
|
});
|
}
|
}
|
|
const AgvMain = (props) => {
|
const { data, curAgvNo, setCurAgvNo } = props;
|
const theme = useTheme();
|
const translate = useTranslate();
|
const containerRef = useRef();
|
const [loading, setLoading] = useState(true);
|
const [info, setInfo] = useState(null);
|
|
useEffect(() => {
|
if (data) {
|
getAgvInfo(data.no, (response) => {
|
setInfo(response);
|
setCurAgvNo(data.no);
|
});
|
}
|
}, [data]);
|
|
useEffect(() => {
|
if (info) {
|
// console.log(info);
|
endThree();
|
setLoading(true);
|
setTimeout(() => {
|
startThree(containerRef.current);
|
three.handleClick = (objName) => {
|
setCurAgvNo(objName);
|
};
|
renderThree(info, curAgvNo);
|
setLoading(false);
|
}, 200);
|
}
|
return endThree;
|
}, [info]);
|
|
const handleReset = () => {
|
alert(1)
|
}
|
|
return (
|
<Box display="flex" height="100%">
|
<Box
|
position="relative"
|
width="50%"
|
height="100%"
|
ref={containerRef}
|
style={{ backgroundColor: '#7a7a7a' }}
|
>
|
{loading && (
|
<Box
|
position="absolute"
|
top="50%"
|
left="50%"
|
style={{ transform: 'translate(-50%, -50%)' }}
|
>
|
<CircularProgress />
|
</Box>
|
)}
|
</Box>
|
<Box width="50%" height="100%" overflow="auto" pl={1}>
|
<Paper elevation={1} style={{
|
height: "100%",
|
padding: '16px',
|
display: 'flex',
|
flexDirection: 'column',
|
justifyContent: 'space-between',
|
}}>
|
<Box>
|
<Grid container spacing={2} style={{ marginTop: '0px' }}>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agv.uuid')} value={info?.agvNo} />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agvDetail.online')} value={info?.online} bool />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agvDetail.pos')} value={info?.pos} bool />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('common.field.status')} value={info?.agvStatus} />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agvDetail.vol')} value={info?.vol} />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agvDetail.soc')} value={info?.soc} />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agvDetail.agvAngle')} value={info?.direction} />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agvDetail.backpack')} value={info?.backpack.filter(item => item.loaded === true).length} />
|
</Grid>
|
<Grid item xs={12}>
|
<KeyValuePair label={translate('table.field.agvDetail.task')} value={info?.taskIds?.join(',')} />
|
</Grid>
|
</Grid>
|
</Box>
|
|
<Grid container spacing={2} style={{ marginTop: '0px' }}>
|
<Grid item xs={12}>
|
<Stack spacing={2} mt={2}>
|
<ConfirmButton
|
label="page.map.action.reset"
|
color="primary"
|
variant="contained"
|
onConfirm={() => {
|
handleReset();
|
}}
|
/>
|
{info && (
|
info.status === 1
|
? <Button variant="contained" color="error" fullWidth>
|
{translate('page.map.action.disable')}
|
</Button>
|
: <Button variant="contained" fullWidth>
|
{translate('page.map.action.enable')}
|
</Button>
|
)}
|
</Stack>
|
</Grid>
|
</Grid>
|
</Paper>
|
</Box>
|
</Box>
|
);
|
}
|
|
const KeyValuePair = ({ label, value, bool }) => {
|
return (
|
<>
|
<Stack direction="row" alignItems="center" spacing={1} sx={{ mb: 1 }}>
|
<Typography
|
variant="body2"
|
sx={{ width: '80px', fontWeight: 'bold', color: 'text.secondary', textAlign: 'left' }}
|
>
|
{label}:
|
</Typography>
|
{bool
|
? <BoolValueIcon
|
value={value}
|
/>
|
: <Typography
|
variant="body2"
|
sx={{ flexGrow: 1, color: 'text.primary', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}
|
>
|
{value}
|
</Typography>
|
}
|
</Stack>
|
<Divider />
|
</>
|
)
|
};
|
|
export default AgvMain;
|