skyouc
昨天 beb003f8e8cd5ae31a0ac55d0624ed2b2ad862bb
Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop
7个文件已修改
1个文件已添加
613 ■■■■■ 已修改文件
rsf-admin/src/i18n/en.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/components/CardWithIcon.jsx 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/dashboard/NbCard.jsx 102 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/dashboard/NbChart.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/dashboard/NbList.jsx 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/dashboard/NbPie.jsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/page/dashboard/index.jsx 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js
@@ -1211,6 +1211,17 @@
            welcome: {
                title: 'Welcome to the WMS website',
            },
            header: {
                inStockQty: '',
                outStockQty: '',
                taskWorkQty: '',
            },
            chart: {
                histories: 'Orders Echart',
            },
            list: {
                stock: 'Stock Pie',
            }
        },
        welcome: {
            index: '    Welcome to the RSF Management System.',
rsf-admin/src/i18n/zh.js
@@ -1223,6 +1223,24 @@
            welcome: {
                title: '欢迎使用 WMS 系统',
            },
            header: {
                inStockQty: '今日入库单数据',
                outStockQty: '今日出库单数据',
                taskWorkQty: '待办任务提醒',
                planQty: '计划',
                realQty: '实际',
                waitQty: '待入',
                waitOutQty: '待出',
            },
            chart: {
                histories: '出入库趋势图',
            },
            list: {
                stock: '总库存量',
            },
        },
        welcome: {
            index: '  欢迎使用RSF管理系统',
rsf-admin/src/page/components/CardWithIcon.jsx
@@ -1,60 +1,85 @@
import * as React from 'react';
import { FC, createElement } from 'react';
import { Card, Box, Typography, Divider } from '@mui/material';
import { Card, Box, Typography, Divider, Stack } from '@mui/material';
import { useTranslate } from 'react-admin';
import { Link } from 'react-router-dom';
const CardWithIcon = ({ icon, title, subtitle, to, children }) => (
    <Card
        sx={{
            minHeight: 52,
            display: 'flex',
            flexDirection: 'column',
            flex: '1',
            '& a': {
                textDecoration: 'none',
                color: 'inherit',
            },
        }}
    >
        <Box
const CardWithIcon = ({ icon, title, subtitle, to, children, statistic, type }) => {
    const translate = useTranslate();
    return (
        <Card
            sx={{
                position: 'relative',
                overflow: 'hidden',
                padding: '16px',
                display: 'flex',
                justifyContent: 'space-between',
                alignItems: 'center',
                '& .icon': {
                    color: 'primary.main',
                },
                '&:before': {
                    position: 'absolute',
                    top: '50%',
                    left: 0,
                    display: 'block',
                    content: `''`,
                    height: '200%',
                    aspectRatio: '1',
                    transform: 'translate(-30%, -60%)',
                    borderRadius: '50%',
                    backgroundColor: 'primary.main',
                    opacity: 0.15,
                width: '100%',
                minHeight: 52,
                flexDirection: 'column',
                flex: '1',
                '& a': {
                    textDecoration: 'none',
                    color: 'inherit',
                },
            }}
        >
            <Box width="3em" className="icon">
                {createElement(icon, { fontSize: 'large' })}
            <Box
                sx={{
                    position: 'relative',
                    overflow: 'hidden',
                    padding: '16px',
                    display: 'flex',
                    justifyContent: 'space-between',
                    alignItems: 'center',
                    '& .icon': {
                        color: 'primary.main',
                    },
                    '&:before': {
                        position: 'absolute',
                        top: '50%',
                        left: 0,
                        display: 'block',
                        content: `''`,
                        height: '200%',
                        aspectRatio: '1',
                        transform: 'translate(-30%, -60%)',
                        borderRadius: '50%',
                        backgroundColor: 'primary.main',
                        opacity: 0.15,
                    },
                }}
            >
                <Box width="3em" className="icon">
                    {createElement(icon, { fontSize: 'large' })}
                </Box>
                <Box textAlign="right">
                    <Typography variant="h5" component="h2">
                        {subtitle || ' '}
                    </Typography>
                    {type ? <Box sx={{ display: "flex" }}>
                        <Box sx={{ display: 'flex', padding: '1em' }}>
                            <Typography color="textSecondary">{translate("page.dashboard.header.planQty")}:</Typography>
                            <Typography color="textSecondary">{statistic?.inAnf}</Typography>
                        </Box>
                        {!children && <Box sx={{ display: "flex" }}>
                            <Box sx={{ display: 'flex', padding: '1em' }}>
                                <Typography color="textSecondary">{translate("page.dashboard.header.realQty")}:</Typography>
                                <Typography color="textSecondary">{statistic?.taskIn}</Typography>
                            </Box>
                            <Box sx={{ display: 'flex', padding: '1em' }}>
                                <Typography color="textSecondary">{type == 'in' ? translate("page.dashboard.header.waitQty") : translate("page.dashboard.header.waitOutQty")}:</Typography>
                                <Typography color="textSecondary">{type == 'in' ? statistic?.taskIn : statistic?.taskOut}</Typography>
                            </Box>
                        </Box>}
                    </Box> : <Box>
                        <Typography  sx={{ display: 'flex', padding: '1em' }}>
                            {' 12234'}
                        </Typography>
                    </Box>}
                </Box>
            </Box>
            <Box textAlign="right">
                <Typography color="textSecondary">{title}</Typography>
                <Typography variant="h5" component="h2">
                    {subtitle || ' '}
                </Typography>
            </Box>
        </Box>
        {children && <Divider />}
        {children}
    </Card>
);
            {children && <Divider />}
            {children}
        </Card>
    )
};
export default CardWithIcon;
rsf-admin/src/page/dashboard/NbCard.jsx
@@ -37,21 +37,22 @@
    const newList = list.concat(list);
    return (
        <CardWithIcon
            icon={CommentIcon}
            title={translate('pos.dashboard.pending_reviews')}
            subtitle={total}
            {...rest}
        >
            <List sx={{ display }}>
                {newList?.map((record) => (
                    <ListItem key={record.id} disablePadding>
                        <ListItemButton
                            alignItems="flex-start"
                            component={Link}
                            to={`/task/${record.id}`}
                        >
                            {/* <ListItemAvatar>
        <>
            <CardWithIcon
                icon={CommentIcon}
                title={translate('page.dashboard.pending_reviews')}
                subtitle={total}
                {...rest}
            >
                <List sx={{ display }}>
                    {newList?.map((record) => (
                        <ListItem key={record.id} disablePadding>
                            <ListItemButton
                                alignItems="flex-start"
                                component={Link}
                                to={`/task/${record.id}`}
                            >
                                {/* <ListItemAvatar>
                                <Avatar
                                    sx={{
                                        // bgcolor: 'primary.main',
@@ -66,41 +67,42 @@
                                </Avatar>
                            </ListItemAvatar> */}
                            <ListItemText
                                // primary={
                                //     <StarRatingField
                                //         record={record}
                                //         source="rating"
                                //     />
                                // }
                                primary={record.date + record.date}
                                secondary={record.total}
                                sx={{
                                    overflowY: 'hidden',
                                    height: '3em',
                                    display: '-webkit-box',
                                    WebkitLineClamp: 2,
                                    WebkitBoxOrient: 'vertical',
                                    paddingRight: 0,
                                }}
                            />
                        </ListItemButton>
                    </ListItem>
                ))}
            </List>
            <Box flexGrow={1}>&nbsp;</Box>
            <Button
                sx={{ borderRadius: 0 }}
                component={Link}
                to="/task"
                size="small"
                color="primary"
            >
                <Box p={1} sx={{ color: 'primary.main' }}>
                    {translate('pos.dashboard.all_reviews')}
                </Box>
            </Button>
        </CardWithIcon>
                                <ListItemText
                                    // primary={
                                    //     <StarRatingField
                                    //         record={record}
                                    //         source="rating"
                                    //     />
                                    // }
                                    primary={record.date + record.date}
                                    secondary={record.total}
                                    sx={{
                                        overflowY: 'hidden',
                                        height: '3em',
                                        display: '-webkit-box',
                                        WebkitLineClamp: 2,
                                        WebkitBoxOrient: 'vertical',
                                        paddingRight: 0,
                                    }}
                                />
                            </ListItemButton>
                        </ListItem>
                    ))}
                </List>
                <Box flexGrow={1}>&nbsp;</Box>
                <Button
                    sx={{ borderRadius: 0 }}
                    component={Link}
                    to="/task"
                    size="small"
                    color="primary"
                >
                    <Box p={1} sx={{ color: 'primary.main' }}>
                        {translate('pos.dashboard.all_reviews')}
                    </Box>
                </Button>
            </CardWithIcon>
        </>
    );
};
rsf-admin/src/page/dashboard/NbChart.jsx
@@ -49,11 +49,12 @@
    return (
        <Card>
            <CardHeader title={translate('pos.dashboard.month_history')} />
            <CardHeader title={translate('page.dashboard.chart.histories')} />
            <CardContent>
                <div style={{ width: '100%', height: 300 }}>
                    <ResponsiveContainer>
                        <AreaChart data={getRevenuePerDay(orders)}>
                        <AreaChart data={orders?.trandItem
                        }>
                            <defs>
                                <linearGradient
                                    id="colorUv"
@@ -75,17 +76,15 @@
                                </linearGradient>
                            </defs>
                            <XAxis
                                dataKey="date"
                                name="Date"
                                type="number"
                                scale="time"
                                dataKey="orderTime"
                                domain={[
                                    addDays(aMonthAgo, 1).getTime(),
                                    new Date().getTime(),
                                ]}
                                tickFormatter={dateFormatter}
                            />
                            <YAxis dataKey="total" name="Revenue" unit="€" />
                            <YAxis dataKey="inQty" name="Revenue" unit="" />
                            <CartesianGrid strokeDasharray="3 3" />
                            <Tooltip
                                cursor={{ strokeDasharray: '3 3' }}
@@ -101,7 +100,14 @@
                            />
                            <Area
                                type="monotone"
                                dataKey="total"
                                dataKey="inQty"
                                stroke="#50911aff"
                                strokeWidth={2}
                                fill="url(#colorUv)"
                            />
                            <Area
                                type="monotone"
                                dataKey="outQty"
                                stroke="#5091abff"
                                strokeWidth={2}
                                fill="url(#colorUv)"
rsf-admin/src/page/dashboard/NbList.jsx
@@ -5,25 +5,25 @@
    ListItemSecondaryAction,
    ListItemAvatar,
    ListItemText,
    Typography,
    Avatar,
    Box,
    ListItemButton,
    Card,
    CardHeader,
    List,
    Grid,
} from '@mui/material';
import { Link } from 'react-router-dom';
const NbList = (props) => {
    const { orders = [] } = props;
const NbList = ({ deadStock }) => {
    const translate = useTranslate();
    return (
        <Card sx={{ flex: 1 }}>
            <CardHeader title={translate('pos.dashboard.pending_orders')} />
            <CardHeader title={translate('page.dashboard.list.stock')} />
            <List dense={true}>
                {orders.map(record => (
                    <PendingOrder key={record.id} order={record} />
                {deadStock.map(record => (
                    <PendingOrder key={`record?.id + ${Math.random().toString(36).substr(2, 9)} `} order={record} />
                ))}
            </List>
        </Card>
@@ -33,12 +33,11 @@
export const PendingOrder = (props) => {
    const { order } = props;
    console.log(order);
    const translate = useTranslate();
    const { referenceRecord: customer, isPending } = useReference({
        reference: 'customers',
        id: order.customer_id,
    });
    // const { referenceRecord: customer, isPending } = useReference({
    //     reference: 'customers',
    //     id: order.id,
    // });
    return (
        <ListItem disablePadding>
@@ -54,13 +53,41 @@
                        />
                    )}
                </ListItemAvatar> */}
                <ListItemText
                    primary={new Date(order.date).toLocaleString('en-GB')}
                    secondary={translate('pos.dashboard.order.items', {
                        name: order.name
                {/* <ListItemText
                    primary={new Date(order.createTime).toLocaleString('en-GB')}
                    secondary={translate('page.dashboard.list.stock', {
                        name: order.maktx
                    })}
                />
                <ListItemSecondaryAction>
                >
                </ListItemText> */}
                <Grid container item md={12}>
                    <Box sx={{ display: 'flex' }}>
                        <Box sx={{ display: 'flex', padding: '1em' }}>
                            <Typography color="textSecondary">{translate("table.field.asnOrderItem.matnrCode")}:</Typography>
                            <Typography color="textSecondary">{order?.matnrCode}</Typography>
                        </Box>
                    </Box>
                    <Box sx={{ display: 'flex' }}>
                        <Box sx={{ display: 'flex', padding: '1em' }}>
                            <Typography color="textSecondary">{translate("table.field.asnOrderItem.maktx")}:</Typography>
                            <Typography color="textSecondary" maxWidth="200" overflow="hidden">{order?.maktx}</Typography>
                        </Box>
                    </Box>
                    <Box sx={{ display: 'flex' }}>
                        <Box sx={{ display: 'flex', padding: '1em' }}>
                            <Typography color="textSecondary">{translate("table.field.asnOrderItem.anfme")}:</Typography>
                            <Typography color="textSecondary">{order?.anfme}</Typography>
                        </Box>
                    </Box>
                    <Box sx={{ display: 'flex' }}>
                        <Box sx={{ display: 'flex', padding: '1em' }}>
                            <Typography color="textSecondary">{translate("table.field.locItem.deadTime")}:</Typography>
                            <Typography color="textSecondary">{order?.deadTime}</Typography>
                        </Box>
                    </Box>
                </Grid>
                {/* <ListItemSecondaryAction>
                    <Box
                        component="span"
                        sx={{
@@ -68,9 +95,9 @@
                            color: 'text.primary',
                        }}
                    >
                        {order.total}$
                        {order.deadTime}
                    </Box>
                </ListItemSecondaryAction>
                </ListItemSecondaryAction> */}
            </ListItemButton>
        </ListItem>
    );
rsf-admin/src/page/dashboard/NbPie.jsx
New file
@@ -0,0 +1,53 @@
import * as React from 'react';
import { Pie, PieChart, ResponsiveContainer, Tooltip } from 'recharts';
import { Card } from "@mui/material";
import { useTranslate } from "react-admin";
const NbPie = ({ deadStock }) => {
    const translate = useTranslate();
    const data01 = [
        { name: 'Group A', value: 400 },
        { name: 'Group B', value: 300 },
        { name: 'Group C', value: 300 },
        { name: 'Group D', value: 200 },
        { name: 'Group E', value: 278 },
        { name: 'Group F', value: 189 },
    ];
    const data02 = [
        { name: 'Group A', value: 2400 },
        { name: 'Group B', value: 4567 },
        { name: 'Group C', value: 1398 },
        { name: 'Group D', value: 9800 },
        { name: 'Group E', value: 3908 },
        { name: 'Group F', value: 4800 },
    ];
    return (
        <>
            <Card>
                <ResponsiveContainer width="100%" height="100%">
                    <PieChart width={400} height={400}>
                        <Pie
                            dataKey="value"
                            isAnimationActive={false}
                            data={data01}
                            cx="50%"
                            cy="50%"
                            outerRadius={80}
                            fill="#8884d8"
                            label
                        />
                        <Pie dataKey="value" data={data02} cx={500} cy={200} innerRadius={40} outerRadius={80} fill="#82ca9d" />
                        <Tooltip />
                    </PieChart>
                </ResponsiveContainer>
            </Card>
        </>
    );
}
export default NbPie;
rsf-admin/src/page/dashboard/index.jsx
@@ -1,24 +1,26 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import { useNavigate } from 'react-router-dom';
import { useTheme } from '@mui/material/styles';
import { useTranslate, useAuthProvider, Title, useNotify } from 'react-admin';
import { WordEffect } from './WordEffect';
import { getSystemDicts } from '@/api/auth'
import Welcome from "./Welcome";
import CardWithIcon from '../components/CardWithIcon';
import { Box, Typography, LinearProgress, Stack, Grid } from '@mui/material';
import React, { useState, useRef, useEffect, useMemo } from "react";
import SensorOccupiedIcon from '@mui/icons-material/SensorOccupied';
import CardWithIcon from '../components/CardWithIcon';
import WifiIcon from '@mui/icons-material/Wifi';
import { useTheme } from '@mui/material/styles';
import { useNavigate } from 'react-router-dom';
import { getSystemDicts } from '@/api/auth'
import { WordEffect } from './WordEffect';
import request from '@/utils/request';
import { Box, Typography, LinearProgress, Stack } from '@mui/material';
import Welcome from "./Welcome";
import NbChart from "./NbChart";
import NbList from "./NbList";
import NbCard from "./NbCard";
import { orderBy } from 'lodash';
import NbPie from './NbPie';
const styles = {
    flex: { display: 'flex' },
    flexColumn: { display: 'flex', flexDirection: 'column' },
    leftCol: { flex: 1, marginRight: '0.5em' },
    rightCol: { flex: 1, marginLeft: '0.5em' },
    leftCol: { flex: 1, },
    rightCol: { flex: 1, },
    singleCol: { marginTop: '1em', marginBottom: '1em' },
};
@@ -70,139 +72,110 @@
const DashboardSummaryView = () => {
    const translate = useTranslate();
    const notify = useNotify();
    const [statistic, setStatistic] = useState(null);
    const [statistic, setStatistic] = useState({});
    const [stock, setStock] = useState([]);
    const [deadStock, setDeadStock] = useState([]);
    useEffect(() => {
        request.get('/dashboard/member/statistic', {
            params: {}
        }).then(res => {
            const { code, msg, data } = res.data;
        getDashBoardHeader()
        getRecentTrands()
        getRecentStocks()
    }, [])
    const getDashBoardHeader = async () => {
        await request.post('/asnOrder/dashbord/header').then(res => {
            const { code, msg, data } = res.data?.data;
            if (code === 200) {
                setStatistic(data);
            } else {
                // notify(msg, { type: 'error', messageArgs: { _: msg } });
                notify(msg, { type: 'error', messageArgs: { _: msg } });
            }
        }).catch((error) => {
            // notify(error.message, { type: 'error', messageArgs: { _: error.message } });
            console.error(error);
            notify(error.message, { type: 'error', messageArgs: { _: error.message } });
        })
    }, [])
    }
    const recentOrders = [
        {
            id: 1,
            name: 'a',
            date: "2025-08-10T12:23:56.959Z",
            total: 138.94
        },
        {
            id: 2,
            name: 'b',
            date: "2025-08-03T07:45:00.304Z",
            total: 214.66
        },
        {
            id: 3,
            name: 'c',
            date: "2025-07-28T00:20:10.968Z",
            total: 68.19
        },
        {
            id: 4,
            name: 'd',
            date: "2025-07-22T20:39:00.293Z",
            total: 36.56
        },
        {
            id: 5,
            name: 'e',
            date: "2025-07-16T17:40:24.791Z",
            total: 100.82
        },
    ]
    const getRecentStocks = async () => {
        await request.post('/locItem/page', { current: 1, pageSize: 10, orderBy: 'create_time asc' }).then(res => {
            const { code, msg, data } = res?.data;
            if (code === 200) {
                setDeadStock(data?.records);
            } else {
                notify(msg, { type: 'error', messageArgs: { _: msg } });
            }
        }).catch((error) => {
            notify(error.message, { type: 'error', messageArgs: { _: error.message } });
        })
    }
    /**
     * 获取库近一个月出入库信息
     */
    const getRecentTrands = async () => {
        await request.post('/asnOrder/stock/trand').then(res => {
            const { code, msg, data } = res.data?.data;
            if (code === 200) {
                setStock(data)
            } else {
                notify(msg, { type: 'error', messageArgs: { _: msg } });
            }
        }).catch((error) => {
            notify(error.message, { type: 'error', messageArgs: { _: error.message } });
        })
    }
    return (
        <>
            <div style={styles.flex}>
                <div style={styles.leftCol}>
                    <div style={styles.flex}>
            <Grid container md={12} item>
                <Grid item md={8}>
                    <Box sx={{ display: "flex" }}>
                        <CardWithIcon
                            icon={WifiIcon}
                            title={translate('page.member.header.onlineMembers')}
                            subtitle={`${statistic?.membersOnlineQua}`}
                            subtitle={translate('page.dashboard.header.inStockQty')}
                            title={`${statistic?.inAnf}`}
                            type={"in"}
                            statistic={statistic}
                        />
                        <Spacer />
                        <CardWithIcon
                            icon={SensorOccupiedIcon}
                            title={translate('page.member.header.totalMembers')}
                            subtitle={`${statistic?.membersTotalQua}`}
                            subtitle={translate('page.dashboard.header.outStockQty')}
                            title={`${statistic?.membersTotalQua}`}
                            type={"out"}
                            statistic={statistic}
                        />
                    </div>
                    <div style={styles.singleCol}>
                        <NbChart orders={recentOrders} />
                    </div>
                    <div style={styles.singleCol}>
                        <NbList orders={recentOrders} />
                    </div>
                </div>
                <div style={styles.rightCol}>
                    <div style={styles.flex}>
                        <NbCard
                            icon={WifiIcon}
                            title={translate('page.member.header.onlineMembers')}
                            subtitle={`${statistic?.membersOnlineQua}`}
                            to={{
                                pathname: '/task',
                                search: JSON.stringify({
                                    filter: JSON.stringify({ status: 1 }),
                                }),
                            }}
                            list={recentOrders}
                        />
                        <Spacer />
                        <NbCard
                            icon={SensorOccupiedIcon}
                            title={translate('page.member.header.totalMembers')}
                            subtitle={`${statistic?.membersTotalQua}`}
                            to={{
                                pathname: '/task',
                                search: JSON.stringify({
                                    filter: JSON.stringify({ status: 1 }),
                                }),
                            }}
                            list={recentOrders}
                        />
                    </div>
                </div>
            </div>
                    </Box>
                    <Spacer />
                    <Box>
                        <NbChart orders={stock} />
                    </Box>
                    <Spacer />
                    <Box sx={{ display: 'flex' }}>
                        <NbList deadStock={deadStock} />
                        <NbPie />
                    </Box>
                    <Spacer />
            {/* <Box sx={{
                display: 'flex',
                mt: 2,
                gap: 2,
                justifyContent: 'space-between',
            }}>
                <CardWithIcon
                    icon={WifiIcon}
                    title={translate('page.member.header.onlineMembers')}
                    subtitle={`${statistic?.membersOnlineQua}`}
                />
                <CardWithIcon
                    icon={SensorOccupiedIcon}
                    title={translate('page.member.header.totalMembers')}
                    subtitle={`${statistic?.membersTotalQua}`}
                />
                <CardWithIcon
                    icon={WifiIcon}
                    title={translate('page.member.header.onlineMembers')}
                    subtitle={`${statistic?.membersOnlineQua}`}
                />
                <CardWithIcon
                    icon={SensorOccupiedIcon}
                    title={translate('page.member.header.totalMembers')}
                    subtitle={`${statistic?.membersTotalQua}`}
                />
            </Box > */}
                </Grid>
                <Grid item md={4}>
                    <Box sx={{ display: 'flex' }}>
                        <Spacer />
                        <NbCard
                            icon={SensorOccupiedIcon}
                            subtitle={translate('page.dashboard.header.taskWorkQty')}
                            title={`${statistic?.membersTotalQua}`}
                            to={{
                                pathname: '/task',
                                search: JSON.stringify({
                                    filter: JSON.stringify({ status: 1 }),
                                }),
                            }}
                            list={deadStock}
                        />
                    </Box>
                </Grid>
            </Grid>
        </>
    )
}