From 3060671bbaa7fe72dd47b7c7b30e385cfdf11802 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期日, 04 一月 2026 14:36:13 +0800
Subject: [PATCH] #

---
 zy-acs-flow/src/page/sta/StaPanel.jsx |  283 ++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 234 insertions(+), 49 deletions(-)

diff --git a/zy-acs-flow/src/page/sta/StaPanel.jsx b/zy-acs-flow/src/page/sta/StaPanel.jsx
index 13638dd..367bb32 100644
--- a/zy-acs-flow/src/page/sta/StaPanel.jsx
+++ b/zy-acs-flow/src/page/sta/StaPanel.jsx
@@ -1,31 +1,90 @@
-import React, { useState, useRef, useEffect, useMemo } from "react";
-import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
+import React, { useState, useEffect } from "react";
+import {
+    Box,
+    Card,
+    CardContent,
+    Grid,
+    Typography,
+    Table,
+    TableBody,
+    TableCell,
+    TableHead,
+    TableRow,
+    Divider,
+    CircularProgress,
+    Stack,
+} from '@mui/material';
 import {
     useTranslate,
     useRecordContext,
+    useDataProvider,
 } from 'react-admin';
+import { format } from 'date-fns';
 import PanelTypography from "../components/PanelTypography";
 import * as Common from '@/utils/common'
 
+const STATUS_FIELDS = [
+    { key: 'autoing', labelKey: 'table.field.sta.autoing' },
+    { key: 'loading', labelKey: 'table.field.sta.loading' },
+    { key: 'inEnable', labelKey: 'table.field.sta.inEnable' },
+    { key: 'outEnable', labelKey: 'table.field.sta.outEnable' },
+];
+
 const StaPanel = () => {
     const record = useRecordContext();
-    if (!record) return null;
     const translate = useTranslate();
+    const dataProvider = useDataProvider();
+    const [reserves, setReserves] = useState([]);
+    const [isReservesLoading, setIsReservesLoading] = useState(false);
+
+    useEffect(() => {
+        if (!record?.id) {
+            setReserves([]);
+            setIsReservesLoading(false);
+            return;
+        }
+
+        let isMounted = true;
+        setIsReservesLoading(true);
+        dataProvider.getList('staReserve', {
+            pagination: { page: 1, perPage: 10 },
+            sort: { field: 'updateTime', order: 'DESC' },
+            filter: { staId: record.id },
+        })
+            .then(({ data }) => {
+                if (!isMounted) return;
+                setReserves(data || []);
+            })
+            .catch(() => {
+                if (!isMounted) return;
+                setReserves([]);
+            })
+            .finally(() => {
+                if (!isMounted) return;
+                setIsReservesLoading(false);
+            });
+
+        return () => {
+            isMounted = false;
+        };
+    }, [record?.id, dataProvider]);
+
+    if (!record) return null;
+
     return (
         <>
-            <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
+            <Card sx={{ width: { xs: 320, sm: 560, md: 680, lg: 900 }, margin: 'auto', mt: .5, mb: .5 }}>
                 <CardContent>
                     <Grid container spacing={2}>
                         <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
                             <Typography variant="h6" gutterBottom align="left" sx={{
-                                maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
+                                maxWidth: { xs: '140px', sm: '220px', md: '300px', lg: '360px' },
                                 whiteSpace: 'nowrap',
                                 overflow: 'hidden',
                                 textOverflow: 'ellipsis',
                             }}>
                                 {Common.camelToPascalWithSpaces(translate('table.field.sta.staNo'))}: {record.staNo}
                             </Typography>
-                            {/*  inherit, primary, secondary, textPrimary, textSecondary, error */}
                             <Typography variant="h6" gutterBottom align="right" >
                                 ID: {record.id}
                             </Typography>
@@ -34,96 +93,222 @@
                     <Grid container spacing={2}>
                         <Grid item xs={12} container alignContent="flex-end">
                             <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
-                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
+                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo || '-'}
                             </Typography>
                         </Grid>
                     </Grid>
-                    <Box height={20}>&nbsp;</Box>
+                    <Box height={16}>&nbsp;</Box>
                     <Grid container spacing={2}>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.uuid" 
+                                title="table.field.sta.uuid"
                                 property={record.uuid}
                             />
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.zoneId" 
+                                title="table.field.sta.zoneId"
                                 property={record.zoneId$}
                             />
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.staNo" 
-                                property={record.staNo}
-                            />
-                        </Grid>
-                        <Grid item xs={6}>
-                            <PanelTypography
-                                title="table.field.sta.name" 
-                                property={record.name}
-                            />
-                        </Grid>
-                        <Grid item xs={6}>
-                            <PanelTypography
-                                title="table.field.sta.staType" 
+                                title="table.field.sta.staType"
                                 property={record.staType$}
                             />
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.code" 
+                                title="table.field.sta.code"
                                 property={record.code$}
                             />
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.offset" 
+                                title="table.field.sta.capacity"
+                                property={record.capacity}
+                            />
+                        </Grid>
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.sta.offset"
                                 property={record.offset}
                             />
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.autoing" 
-                                property={record.autoing}
+                                title="table.field.sta.rsvInCnt"
+                                property={record.rsvInCnt}
                             />
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.loading" 
-                                property={record.loading}
+                                title="table.field.sta.rsvOutCnt"
+                                property={record.rsvOutCnt}
                             />
                         </Grid>
                         <Grid item xs={6}>
                             <PanelTypography
-                                title="table.field.sta.inEnable" 
-                                property={record.inEnable}
-                            />
-                        </Grid>
-                        <Grid item xs={6}>
-                            <PanelTypography
-                                title="table.field.sta.outEnable" 
-                                property={record.outEnable}
-                            />
-                        </Grid>
-                        <Grid item xs={6}>
-                            <PanelTypography
-                                title="table.field.sta.zpallet" 
-                                property={record.zpallet}
-                            />
-                        </Grid>
-                        <Grid item xs={6}>
-                            <PanelTypography
-                                title="table.field.sta.staSts" 
+                                title="table.field.sta.staSts"
                                 property={record.staSts$}
                             />
                         </Grid>
-
+                        <Grid item xs={6}>
+                            <PanelTypography
+                                title="table.field.sta.zpallet"
+                                property={record.zpallet}
+                            />
+                        </Grid>
                     </Grid>
+
+                    <Divider sx={{ my: 2 }} />
+
+                    <Typography variant="subtitle2" color="textSecondary" gutterBottom>
+                        {translate('common.field.status')} / {translate('table.field.sta.staNo')}
+                    </Typography>
+                    <Grid container spacing={2}>
+                        {STATUS_FIELDS.map(({ key, labelKey }) => (
+                            <Grid item xs={6} sm={3} key={key}>
+                                <StatusIndicator labelKey={labelKey} value={record[key]} />
+                            </Grid>
+                        ))}
+                    </Grid>
+
+                    <Divider sx={{ my: 2 }} />
+
+                    <Box>
+                        <Typography variant="subtitle1" gutterBottom>
+                            {translate('menu.staReserve')}
+                        </Typography>
+                        <Table size="small">
+                            <TableHead>
+                                <TableRow>
+                                    <TableCell>{translate('table.field.staReserve.name')}</TableCell>
+                                    <TableCell>{translate('table.field.staReserve.type')}</TableCell>
+                                    <TableCellRight>{translate('table.field.staReserve.qty')}</TableCellRight>
+                                    <TableCell>{translate('table.field.staReserve.state')}</TableCell>
+                                    <TableCell>{translate('table.field.staReserve.agvId')}</TableCell>
+                                    <TableCell>{translate('table.field.staReserve.waitingAt')}</TableCell>
+                                    <TableCell>{translate('table.field.staReserve.confirmedAt')}</TableCell>
+                                </TableRow>
+                            </TableHead>
+                            <TableBody>
+                                {isReservesLoading && (
+                                    <TableRow>
+                                        <TableCell colSpan={7}>
+                                            <Box display="flex" alignItems="center" gap={1}>
+                                                <CircularProgress size={16} />
+                                                <Typography variant="body2" color="textSecondary">
+                                                    {translate('common.loading', { _: 'Loading...' })}
+                                                </Typography>
+                                            </Box>
+                                        </TableCell>
+                                    </TableRow>
+                                )}
+                                {!isReservesLoading && reserves.length === 0 && (
+                                    <TableRow>
+                                        <TableCell colSpan={7}>
+                                            <Typography variant="body2" color="textSecondary">
+                                                No reservations
+                                            </Typography>
+                                        </TableCell>
+                                    </TableRow>
+                                )}
+                                {reserves.map((reserve) => (
+                                    <TableRow key={reserve.id}>
+                                        <TableCell>{reserve.name || '-'}</TableCell>
+                                        <TableCell>{reserve.type || '-'}</TableCell>
+                                        <TableCellRight>{reserve.qty ?? '-'}</TableCellRight>
+                                        <TableCell>{reserve.state || '-'}</TableCell>
+                                        <TableCell>{reserve.agvId$ || reserve.agvId || '-'}</TableCell>
+                                        <TableCell>{formatDateTime(reserve.waitingAt)}</TableCell>
+                                        <TableCell>{formatDateTime(reserve.confirmedAt)}</TableCell>
+                                    </TableRow>
+                                ))}
+                            </TableBody>
+                        </Table>
+                    </Box>
                 </CardContent>
             </Card >
         </>
     );
 };
 
+const StatusIndicator = ({ labelKey, value }) => {
+    const translate = useTranslate();
+    const color = getIndicatorColor(value);
+    return (
+        <Stack spacing={0.5}>
+            <Typography variant="caption" color="textSecondary">
+                {Common.camelToPascalWithSpaces(translate(labelKey))}
+            </Typography>
+            <Box display="flex" alignItems="center" gap={1}>
+                <Box sx={{
+                    width: 14,
+                    height: 14,
+                    borderRadius: '50%',
+                    backgroundColor: color,
+                    boxShadow: `0 0 6px ${color}`,
+                    border: '1px solid rgba(0,0,0,0.12)'
+                }} />
+                <Typography variant="body2">
+                    {formatIndicatorValue(value)}
+                </Typography>
+            </Box>
+        </Stack>
+    );
+};
+
+const getIndicatorColor = (value) => {
+    if (isTruthy(value)) {
+        return '#2e7d32';
+    }
+    if (isFalsy(value)) {
+        return '#9e9e9e';
+    }
+    return '#ff9800';
+};
+
+const isTruthy = (value) => {
+    if (typeof value === 'boolean') return value;
+    if (typeof value === 'number') return value > 0;
+    if (typeof value === 'string') {
+        const normalized = value.toLowerCase();
+        return ['1', 'true', 'y', 'yes', 'open', 'enable'].includes(normalized);
+    }
+    return false;
+};
+
+const isFalsy = (value) => {
+    if (typeof value === 'boolean') return !value;
+    if (typeof value === 'number') return value === 0;
+    if (typeof value === 'string') {
+        const normalized = value.toLowerCase();
+        return ['0', 'false', 'n', 'no', 'close', 'disable'].includes(normalized);
+    }
+    return false;
+};
+
+const formatIndicatorValue = (value) => {
+    if (value === null || value === undefined || value === '') {
+        return '-';
+    }
+    return String(value);
+};
+
+const formatDateTime = (value) => {
+    if (!value) return '-';
+    try {
+        const date = new Date(value);
+        if (Number.isNaN(date.getTime())) {
+            return value;
+        }
+        return format(date, 'MM-dd HH:mm');
+    } catch (error) {
+        return value;
+    }
+};
+
+const TableCellRight = (props) => <TableCell align="right" {...props} />;
+
 export default StaPanel;

--
Gitblit v1.9.1