| | |
| | | List, |
| | | ListItemButton, |
| | | ListItemText, |
| | | ListItemAvatar, |
| | | Avatar, |
| | | CircularProgress, |
| | | } from '@mui/material'; |
| | | import CloseIcon from '@mui/icons-material/Close'; |
| | | import { PAGE_DRAWER_WIDTH } from '@/config/setting'; |
| | | import { fetchAreaList } from './http'; |
| | | import * as Tool from './tool'; |
| | | |
| | | const AreaList = ({ |
| | | open, |
| | | onClose, |
| | | zoneId, |
| | | width = PAGE_DRAWER_WIDTH, |
| | | onSelect, |
| | | setCurSprite, |
| | | }) => { |
| | | const translate = useTranslate(); |
| | | const theme = useTheme(); |
| | |
| | | }, [open, zoneId]); |
| | | |
| | | const handleItemClick = (area) => { |
| | | onSelect?.(area); |
| | | if (!area?.id) { |
| | | return; |
| | | } |
| | | const sprite = Tool.findAreaSpriteById(area.id); |
| | | if (sprite) { |
| | | Tool.focusAreaSprite(sprite, 570); |
| | | onClose(); |
| | | setCurSprite(sprite); |
| | | } |
| | | }; |
| | | |
| | | return ( |
| | |
| | | sx={{ zIndex: 100, opacity: 0.95 }} |
| | | > |
| | | {open && ( |
| | | <Box pt={12} width={{ xs: '100vW', sm: width }} height={'calc(100vh - 200px);'} mt={{ xs: 2, sm: 1 }} sx={{ |
| | | }}> |
| | | <Box pt={12} width={{ xs: '100vw', sm: width }} height={'calc(100vh - 200px)'} mt={{ xs: 2, sm: 1 }}> |
| | | <Stack direction="row" alignItems="center" px={3} py={2}> |
| | | <Typography variant="h6" flex={1}> |
| | | {translate('page.map.action.areaList')} |
| | |
| | | {translate('page.map.area.form.codesEmpty')} |
| | | </Typography> |
| | | )} |
| | | {areas.map((area) => ( |
| | | <ListItemButton |
| | | key={area.id} |
| | | onClick={() => handleItemClick(area)} |
| | | sx={{ |
| | | borderRadius: 2, |
| | | mb: 1, |
| | | boxShadow: |
| | | themeMode === 'light' |
| | | ? '0 2px 8px rgba(0,0,0,0.07)' |
| | | : '0 2px 8px rgba(255,255,255,0.12)', |
| | | }} |
| | | > |
| | | <ListItemAvatar> |
| | | <Avatar |
| | | variant="rounded" |
| | | {areas.map((area) => { |
| | | const agvCount = Array.isArray(area.agvList) ? area.agvList.length : 0; |
| | | const width = Math.abs((area?.end?.x ?? 0) - (area?.start?.x ?? 0)); |
| | | const height = Math.abs((area?.end?.y ?? 0) - (area?.start?.y ?? 0)); |
| | | const areaSize = (width * height) / 1_000_000; |
| | | const formattedSize = areaSize > 0 ? areaSize.toFixed(2) : '0.00'; |
| | | return ( |
| | | <ListItemButton |
| | | key={area.id} |
| | | onClick={() => handleItemClick(area)} |
| | | sx={{ |
| | | borderRadius: 2, |
| | | mb: 1, |
| | | px: 2, |
| | | py: 1.5, |
| | | background: |
| | | themeMode === 'light' |
| | | ? 'linear-gradient(145deg, #f8f9fa, #ffffff)' |
| | | : 'linear-gradient(145deg, #2d3436, #353b48)', |
| | | border: `1px solid ${theme.palette.divider}`, |
| | | display: 'flex', |
| | | gap: 1.5, |
| | | alignItems: 'center', |
| | | justifyContent: 'space-between', |
| | | transition: 'transform 0.2s ease, box-shadow 0.2s ease', |
| | | boxShadow: |
| | | themeMode === 'light' |
| | | ? '0 6px 12px rgba(0,0,0,0.06)' |
| | | : '0 6px 12px rgba(0,0,0,0.25)', |
| | | '&:hover': { |
| | | transform: 'translateY(-2px)', |
| | | boxShadow: |
| | | themeMode === 'light' |
| | | ? '0 12px 24px rgba(0,0,0,0.08)' |
| | | : '0 12px 24px rgba(0,0,0,0.35)', |
| | | }, |
| | | }} |
| | | > |
| | | <Box |
| | | sx={{ |
| | | bgcolor: area.color ? Number(area.color) : theme.palette.grey[400], |
| | | color: theme.palette.getContrastText( |
| | | area.color ? Number(area.color) : theme.palette.grey[400] |
| | | ), |
| | | width: 12, |
| | | height: 12, |
| | | borderRadius: '50%', |
| | | bgcolor: area.color ? Number(area.color) : theme.palette.info.light, |
| | | border: `1px solid ${theme.palette.common.white}`, |
| | | boxShadow: '0 0 4px rgba(0,0,0,0.2)', |
| | | }} |
| | | > |
| | | {area.name?.slice(0, 1)?.toUpperCase() || 'A'} |
| | | </Avatar> |
| | | </ListItemAvatar> |
| | | <ListItemText |
| | | primary={area.name || translate('page.map.area.form.name')} |
| | | secondary={area.code ? `${translate('page.map.area.form.code')}: ${area.code}` : ''} |
| | | /> |
| | | </ListItemButton> |
| | | ))} |
| | | /> |
| | | <ListItemText |
| | | primary={area.name || translate('page.map.area.form.name')} |
| | | primaryTypographyProps={{ |
| | | fontWeight: 600, |
| | | fontSize: 16, |
| | | }} |
| | | /> |
| | | <Box textAlign="right"> |
| | | <Typography variant="body2" fontWeight={500}> |
| | | {translate('page.map.area.form.agvCount', { count: agvCount })} |
| | | </Typography> |
| | | <Typography variant="caption" color="text.secondary"> |
| | | {translate('page.map.area.form.areaSize', { size: formattedSize })} |
| | | </Typography> |
| | | </Box> |
| | | </ListItemButton> |
| | | ); |
| | | })} |
| | | </List> |
| | | )} |
| | | </Box> |