From beb003f8e8cd5ae31a0ac55d0624ed2b2ad862bb Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期四, 14 八月 2025 11:21:49 +0800 Subject: [PATCH] Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop --- rsf-admin/src/page/dashboard/NbList.jsx | 65 ++++- rsf-admin/src/page/components/CardWithIcon.jsx | 123 ++++++---- rsf-admin/src/page/dashboard/NbCard.jsx | 102 ++++---- rsf-admin/src/i18n/zh.js | 18 + rsf-admin/src/i18n/en.js | 11 + rsf-admin/src/page/dashboard/index.jsx | 219 ++++++++----------- rsf-admin/src/page/dashboard/NbPie.jsx | 53 ++++ rsf-admin/src/page/dashboard/NbChart.jsx | 22 + 8 files changed, 364 insertions(+), 249 deletions(-) diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js index 33a5693..4312ccf 100644 --- a/rsf-admin/src/i18n/en.js +++ b/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.', diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index 2046fac..2ca1992 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/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绠$悊绯荤粺', diff --git a/rsf-admin/src/page/components/CardWithIcon.jsx b/rsf-admin/src/page/components/CardWithIcon.jsx index 606911e..567a0bb 100644 --- a/rsf-admin/src/page/components/CardWithIcon.jsx +++ b/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; \ No newline at end of file diff --git a/rsf-admin/src/page/dashboard/NbCard.jsx b/rsf-admin/src/page/dashboard/NbCard.jsx index eb22c20..4701aef 100644 --- a/rsf-admin/src/page/dashboard/NbCard.jsx +++ b/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}> </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}> </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> + </> ); }; diff --git a/rsf-admin/src/page/dashboard/NbChart.jsx b/rsf-admin/src/page/dashboard/NbChart.jsx index a0b6373..a154760 100644 --- a/rsf-admin/src/page/dashboard/NbChart.jsx +++ b/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)" diff --git a/rsf-admin/src/page/dashboard/NbList.jsx b/rsf-admin/src/page/dashboard/NbList.jsx index 9bb7024..4cb2005 100644 --- a/rsf-admin/src/page/dashboard/NbList.jsx +++ b/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> ); diff --git a/rsf-admin/src/page/dashboard/NbPie.jsx b/rsf-admin/src/page/dashboard/NbPie.jsx new file mode 100644 index 0000000..6b2d64e --- /dev/null +++ b/rsf-admin/src/page/dashboard/NbPie.jsx @@ -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; \ No newline at end of file diff --git a/rsf-admin/src/page/dashboard/index.jsx b/rsf-admin/src/page/dashboard/index.jsx index d8694e0..c2f7fd8 100644 --- a/rsf-admin/src/page/dashboard/index.jsx +++ b/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> </> ) } -- Gitblit v1.9.1