From 23e63904e4c2b734f92bdfd5aac0e16948af72b3 Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期一, 14 四月 2025 09:21:21 +0800 Subject: [PATCH] no message --- rsf-admin/src/page/orders/purchase/PurchaseList.jsx | 170 +++++++ rsf-admin/src/page/orders/purchase/PurchaseEdit.jsx | 152 ++++++ rsf-admin/src/layout/MyMenu.jsx | 2 rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx | 54 +- rsf-admin/src/page/orders/purchase/PurchaseItemEdit.jsx | 198 ++++++++ rsf-admin/src/page/orders/purchase/index.jsx | 18 rsf-admin/src/page/orders/purchase/PurchaseItemList.jsx | 171 +++++++ rsf-admin/src/layout/SubMenu.jsx | 4 rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx | 2 rsf-admin/src/page/orders/purchase/PurchaseItemCreate.jsx | 201 ++++++++ rsf-admin/src/page/ResourceContent.js | 4 rsf-admin/src/page/orders/purchase/PurchaseCreate.jsx | 194 ++++++++ rsf-admin/src/page/orders/purchase/PurchasePanel.jsx | 182 +++++++ 13 files changed, 1,317 insertions(+), 35 deletions(-) diff --git a/rsf-admin/src/layout/MyMenu.jsx b/rsf-admin/src/layout/MyMenu.jsx index 547f65a..5338309 100644 --- a/rsf-admin/src/layout/MyMenu.jsx +++ b/rsf-admin/src/layout/MyMenu.jsx @@ -58,6 +58,8 @@ const IconComponent = getIconComponent(iconStr); if (IconComponent) { return <IconComponent />; + } else { + return <KeyboardArrowDownIcon /> } }; diff --git a/rsf-admin/src/layout/SubMenu.jsx b/rsf-admin/src/layout/SubMenu.jsx index d79867e..e09b22d 100644 --- a/rsf-admin/src/layout/SubMenu.jsx +++ b/rsf-admin/src/layout/SubMenu.jsx @@ -15,14 +15,12 @@ const SubMenu = (props) => { const { handleToggle, isOpen, name, icon, children, dense } = props; const translate = useTranslate(); - const [sidebarIsOpen] = useSidebarState(); const header = ( <MenuItem dense={dense} onClick={handleToggle} sx={{ display: 'flex', alignItems: 'center' }}> <ListItemIcon sx={{ minWidth: 40, color: 'text.secondary', display: 'flex', alignItems: 'center' }}> - {/* {isOpen ? <ExpandMore /> : icon} */} - {isOpen ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />} + {icon ? icon : isOpen ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />} </ListItemIcon> <Typography variant="inherit" color="textSecondary" sx={{ ml: 1, display: 'flex', alignItems: 'center' }}> {translate(name)} diff --git a/rsf-admin/src/page/ResourceContent.js b/rsf-admin/src/page/ResourceContent.js index 5a90285..3a81c8e 100644 --- a/rsf-admin/src/page/ResourceContent.js +++ b/rsf-admin/src/page/ResourceContent.js @@ -80,8 +80,6 @@ return contract; case 'qlyInspect': return qlyInspect; - case 'qlyIsptItem': - return qlyIsptItem; case 'dictType': return dictType; case 'companys': @@ -92,8 +90,6 @@ return whMat; case 'asnOrder': return asnOrder; - case 'asnOrderItem': - return asnOrderItem; case 'asnOrderLog': return asnOrderLog; case 'purchase': diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx index 07570e0..0ed7504 100644 --- a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx @@ -55,33 +55,33 @@ if (data == null || data == undefined) { return } return ( - <EditBase - id={record?.id} - resource="asnOrderItem" - mutationMode={EDIT_MODE} - actions={<CustomerTopToolBar />} + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="md" > - <Dialog - open={open} - onClose={handleClose} - aria-labelledby="form-dialog-title" - fullWidth - disableRestoreFocus - maxWidth="md" + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }} > - <DialogTitle id="form-dialog-title" sx={{ - position: 'sticky', - top: 0, - backgroundColor: 'background.paper', - zIndex: 1000 - }} + {translate('update.title')} + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <EditBase + id={record?.id} + resource="asnOrderItem" + mutationMode={EDIT_MODE} + actions={<CustomerTopToolBar />} > - {translate('update.title')} - <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> - <DialogCloseButton onClose={handleClose} /> - </Box> - </DialogTitle> - <DialogContent sx={{ mt: 2 }}> <Form shouldUnregister warnWhenUnsavedChanges @@ -190,9 +190,9 @@ </Toolbar> </DialogActions> </Form> - </DialogContent> - </Dialog> - </EditBase > + </EditBase > + </DialogContent> + </Dialog> ) } diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx index 085e065..ef8db15 100644 --- a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx @@ -102,7 +102,7 @@ const [drawerVal, setDrawerVal] = useState(false); const [select, setSelect] = useState({}); const asnId = useGetRecordId(); - const { data: dicts, isPending, error } = useGetOne('asnOrder', { id: asnId }); const creatCode = () => { }; + const { data: dicts, isPending, error } = useGetOne('asnOrder', { id: asnId }); return ( <> diff --git a/rsf-admin/src/page/orders/purchase/PurchaseCreate.jsx b/rsf-admin/src/page/orders/purchase/PurchaseCreate.jsx new file mode 100644 index 0000000..f44ae47 --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/PurchaseCreate.jsx @@ -0,0 +1,194 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + CreateBase, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + DateInput, + SaveButton, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + Toolbar, + required, + useDataProvider, + useNotify, + Form, + useCreateController, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + Box, +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import StatusSelectInput from "../../components/StatusSelectInput"; +import MemoInput from "../../components/MemoInput"; + +const PurchaseCreate = (props) => { + const { open, setOpen } = props; + + const translate = useTranslate(); + const notify = useNotify(); + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const handleSuccess = async (data) => { + setOpen(false); + notify('common.response.success'); + }; + + const handleError = async (error) => { + notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } }); + }; + + return ( + <> + <CreateBase + record={{}} + transform={(data) => { + return data; + }} + mutationOptions={{ onSuccess: handleSuccess, onError: handleError }} + > + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + > + <Form> + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }} + > + {translate('create.title')} + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <Grid container rowSpacing={2} columnSpacing={2}> + {/* <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchase.code" + source="code" + parse={v => v} + autoFocus + /> + </Grid> */} + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchase.type" + source="type" + parse={v => v} + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchase.source" + source="source" + parse={v => v} + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <DateInput + label="table.field.purchase.preArr" + source="preArr" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchase.anfme" + source="anfme" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchase.qty" + source="qty" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchase.workQty" + source="workQty" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchase.channel" + source="channel" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchase.platCode" + source="platCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <DateInput + label="table.field.purchase.startTime" + source="startTime" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <DateInput + label="table.field.purchase.endTime" + source="endTime" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchase.project" + source="project" + parse={v => v} + /> + </Grid> + + <Grid item xs={6} display="flex" gap={1}> + <StatusSelectInput /> + </Grid> + <Grid item xs={12} display="flex" gap={1}> + <Stack direction="column" spacing={1} width={'100%'}> + <MemoInput /> + </Stack> + </Grid> + </Grid> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} > + <SaveButton /> + </Toolbar> + </DialogActions> + </Form> + </Dialog> + </CreateBase> + </> + ) +} + +export default PurchaseCreate; diff --git a/rsf-admin/src/page/orders/purchase/PurchaseEdit.jsx b/rsf-admin/src/page/orders/purchase/PurchaseEdit.jsx new file mode 100644 index 0000000..759b842 --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/PurchaseEdit.jsx @@ -0,0 +1,152 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + Edit, + SimpleForm, + FormDataConsumer, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + DateInput, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + SaveButton, + Toolbar, + Labeled, + NumberField, + required, + useRecordContext, + DeleteButton, +} from 'react-admin'; +import { useWatch, useFormContext } from "react-hook-form"; +import { Stack, Grid, Box, Typography } from '@mui/material'; +import * as Common from '@/utils/common'; +import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; +import EditBaseAside from "../../components/EditBaseAside"; +import CustomerTopToolBar from "../../components/EditTopToolBar"; +import MemoInput from "../../components/MemoInput"; +import StatusSelectInput from "../../components/StatusSelectInput"; +import PurchaseItemList from "./PurchaseItemList"; + +const FormToolbar = () => { + const { getValues } = useFormContext(); + return ( + <Toolbar sx={{ justifyContent: 'end' }}> + <SaveButton /> + <DeleteButton mutationMode="optimistic" /> + </Toolbar> + ) +} + +const PurchaseEdit = () => { + const translate = useTranslate(); + + return ( + <> + <Edit + redirect="list" + mutationMode={EDIT_MODE} + actions={<CustomerTopToolBar />} + aside={<EditBaseAside />} + > + <SimpleForm + shouldUnregister + warnWhenUnsavedChanges + toolbar={<FormToolbar />} + mode="onTouched" + defaultValues={{}} + // validate={(values) => { }} + > + <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}> + <Grid item xs={18} md={10}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.main')} + </Typography> + {/* <Stack direction='row' gap={2}> + <TextInput + label="table.field.purchase.code" + source="code" + parse={v => v} + autoFocus + /> + </Stack> */} + <Stack direction='row' gap={2}> + <TextInput + label="table.field.purchase.type" + source="type$" + parse={v => v} + validate={required()} + /> + <TextInput + label="table.field.purchase.source" + source="source" + parse={v => v} + validate={required()} + /> + <DateInput + label="table.field.purchase.preArr" + source="preArr" + /> + <NumberInput + label="table.field.purchase.anfme" + source="anfme" + validate={required()} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.purchase.qty" + source="qty" + validate={required()} + /> + <NumberInput + label="table.field.purchase.workQty" + source="workQty" + validate={required()} + /> + <TextInput + label="table.field.purchase.channel" + source="channel" + parse={v => v} + /> + <TextInput + label="table.field.purchase.platCode" + source="platCode" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <DateInput + label="table.field.purchase.startTime" + source="startTime" + /> + <DateInput + label="table.field.purchase.endTime" + source="endTime" + /> + <TextInput + label="table.field.purchase.project" + source="project" + parse={v => v} + /> + </Stack> + </Grid> + <Grid item xs={6} md={2}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.common')} + </Typography> + <StatusSelectInput /> + <Box mt="2em" /> + <MemoInput /> + </Grid> + </Grid> + </SimpleForm> + </Edit > + <PurchaseItemList /> + </> + ) +} + +export default PurchaseEdit; diff --git a/rsf-admin/src/page/orders/purchase/PurchaseItemCreate.jsx b/rsf-admin/src/page/orders/purchase/PurchaseItemCreate.jsx new file mode 100644 index 0000000..4afa238 --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/PurchaseItemCreate.jsx @@ -0,0 +1,201 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + CreateBase, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + DateInput, + SaveButton, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + Toolbar, + required, + useDataProvider, + useNotify, + Form, + useCreateController, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + Box, +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import StatusSelectInput from "../../components/StatusSelectInput"; +import MemoInput from "../../components/MemoInput"; + +const PurchaseItemCreate = (props) => { + const { open, setOpen, row } = props; + + const translate = useTranslate(); + const notify = useNotify(); + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const handleSuccess = async (data) => { + setOpen(false); + notify('common.response.success'); + }; + + const handleError = async (error) => { + notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } }); + }; + + return ( + <> + <CreateBase + record={{}} + transform={(data) => { + return data; + }} + mutationOptions={{ onSuccess: handleSuccess, onError: handleError }} + > + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + > + <Form> + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }} + > + {translate('create.title')} + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <Grid container rowSpacing={2} columnSpacing={2}> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchaseItem.purchaseId" + source="purchaseId" + defaultValue={row.poId} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchaseItem.platItemId" + source="platItemId" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchaseItem.matnrCode" + source="matnrCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchaseItem.matnrName" + source="matnrName" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchaseItem.unit" + source="unit" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchaseItem.anfme" + source="anfme" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchaseItem.qty" + source="qty" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchaseItem.nromQty" + source="nromQty" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchaseItem.asnQty" + source="asnQty" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.purchaseItem.printQty" + source="printQty" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchaseItem.splrName" + source="splrName" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchaseItem.splrCode" + source="splrCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.purchaseItem.splrBatch" + source="splrBatch" + parse={v => v} + /> + </Grid> + + <Grid item xs={6} display="flex" gap={1}> + <StatusSelectInput /> + </Grid> + <Grid item xs={12} display="flex" gap={1}> + <Stack direction="column" spacing={1} width={'100%'}> + <MemoInput /> + </Stack> + </Grid> + </Grid> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} > + <SaveButton /> + </Toolbar> + </DialogActions> + </Form> + </Dialog> + </CreateBase> + </> + ) +} + +export default PurchaseItemCreate; diff --git a/rsf-admin/src/page/orders/purchase/PurchaseItemEdit.jsx b/rsf-admin/src/page/orders/purchase/PurchaseItemEdit.jsx new file mode 100644 index 0000000..be298d4 --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/PurchaseItemEdit.jsx @@ -0,0 +1,198 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + Edit, + SimpleForm, + FormDataConsumer, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + DateInput, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + SaveButton, + Toolbar, + Labeled, + NumberField, + required, + useGetOne, + useRecordContext, + DeleteButton, + Form, + EditBase, +} from 'react-admin'; +import { useWatch, useFormContext } from "react-hook-form"; +import { Stack, Grid, Box, Typography, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material'; +import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; +import CustomerTopToolBar from "../../components/EditTopToolBar"; +import DialogCloseButton from "../../components/DialogCloseButton"; +import StatusSelectInput from "../../components/StatusSelectInput"; +import MemoInput from "../../components/MemoInput"; + + +const FormToolbar = () => { + const { getValues } = useFormContext(); + + return ( + <Toolbar sx={{ justifyContent: 'space-between' }}> + <SaveButton /> + <DeleteButton mutationMode="optimistic" /> + </Toolbar> + ) +} + +const PurchaseItemEdit = (props) => { + const { open, setOpen, record } = props; + const translate = useTranslate(); + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + const { data, isPending, } = useGetOne('purchaseItem', { id: record?.id }); + if (data == null || data == undefined) { return } + + return ( + <> + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="md" + > + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }} + > + {translate('update.title')} + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <EditBase + resource="purchaseItem" + mutationMode={EDIT_MODE} + actions={<CustomerTopToolBar />} + > + <Form + shouldUnregister + warnWhenUnsavedChanges + toolbar={<FormToolbar />} + mode="onTouched" + defaultValues={{}} + > + <DialogContent sx={{ mt: 2 }}> + + <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3}> + <Grid item xs={12} md={8} gap={2}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.main')} + </Typography> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.purchaseItem.purchaseId" + source="purchaseId" + defaultValue={record?.id} + /> + <TextInput + label="table.field.purchaseItem.platItemId" + source="platItemId" + parse={v => v} + /> + <TextInput + label="table.field.purchaseItem.matnrCode" + source="matnrCode" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.purchaseItem.matnrName" + source="matnrName" + parse={v => v} + /> + <TextInput + label="table.field.purchaseItem.unit" + source="unit" + parse={v => v} + /> + <NumberInput + label="table.field.purchaseItem.anfme" + source="anfme" + validate={required()} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.purchaseItem.qty" + source="qty" + validate={required()} + /> + <NumberInput + label="table.field.purchaseItem.nromQty" + source="nromQty" + validate={required()} + /> + <NumberInput + label="table.field.purchaseItem.asnQty" + source="asnQty" + validate={required()} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.purchaseItem.printQty" + source="printQty" + validate={required()} + /> + <TextInput + label="table.field.purchaseItem.splrName" + source="splrName" + parse={v => v} + /> + <TextInput + label="table.field.purchaseItem.splrCode" + source="splrCode" + parse={v => v} + /> + <TextInput + label="table.field.purchaseItem.splrBatch" + source="splrBatch" + parse={v => v} + /> + </Stack> + </Grid> + <Grid item xs={12} md={4} > + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.common')} + </Typography> + <StatusSelectInput /> + <Box mt="2em" /> + <MemoInput /> + </Grid> + </Grid> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > + <SaveButton type="button" mutationOptions={{ + onSuccess: () => { + setOpen(false) + } + }} /> + </Toolbar> + </DialogActions> + </Form> + </EditBase > + </Dialog> + </> + ) +} + +export default PurchaseItemEdit; diff --git a/rsf-admin/src/page/orders/purchase/PurchaseItemList.jsx b/rsf-admin/src/page/orders/purchase/PurchaseItemList.jsx new file mode 100644 index 0000000..13222c9 --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/PurchaseItemList.jsx @@ -0,0 +1,171 @@ +import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; +import { + List, + DatagridConfigurable, + SearchInput, + TopToolbar, + SelectColumnsButton, + EditButton, + FilterButton, + BulkDeleteButton, + WrapperField, + useTranslate, + TextField, + NumberField, + DateField, + BooleanField, + TextInput, + SelectInput, + NumberInput, + DeleteButton, + useGetRecordId, + Button, + useGetOne +} from 'react-admin'; +import { Box, Typography, Card, Stack } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import PurchaseItemCreate from "./PurchaseItemCreate"; +import EmptyData from "../../components/EmptyData"; +import MyCreateButton from "../../components/MyCreateButton"; +import MyExportButton from '../../components/MyExportButton'; +import PageDrawer from "../../components/PageDrawer"; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import PurchaseItemEdit from "./PurchaseItemEdit"; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 200 + }, +})); + +const filters = [ + <SearchInput source="condition" alwaysOn />, + <NumberInput source="purchaseId" label="table.field.purchaseItem.purchaseId" />, + <TextInput source="platItemId" label="table.field.purchaseItem.platItemId" />, + <TextInput source="matnrCode" label="table.field.purchaseItem.matnrCode" />, + <TextInput source="matnrName" label="table.field.purchaseItem.matnrName" />, + <TextInput source="unit" label="table.field.purchaseItem.unit" />, + <NumberInput source="anfme" label="table.field.purchaseItem.anfme" />, + <NumberInput source="qty" label="table.field.purchaseItem.qty" />, + <NumberInput source="nromQty" label="table.field.purchaseItem.nromQty" />, + <NumberInput source="asnQty" label="table.field.purchaseItem.asnQty" />, + <NumberInput source="printQty" label="table.field.purchaseItem.printQty" />, + <TextInput source="splrName" label="table.field.purchaseItem.splrName" />, + <TextInput source="splrCode" label="table.field.purchaseItem.splrCode" />, + <TextInput source="splrBatch" label="table.field.purchaseItem.splrBatch" />, + <TextInput label="common.field.memo" source="memo" />, + <SelectInput + label="common.field.status" + source="status" + choices={[ + { id: '1', name: 'common.enums.statusTrue' }, + { id: '0', name: 'common.enums.statusFalse' }, + ]} + resettable + />, +] + +const PurchaseItemList = () => { + const translate = useTranslate(); + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const [editDialog, setEditDialog] = useState(false); + const [select, setSelect] = useState({}); + const poId = useGetRecordId(); + const { data: purchase, isPending, error } = useGetOne('purchase', { id: poId }); + + return ( + <> + <Box display="flex"> + <List + resource="purchaseItem" + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + }} + title={"menu.purchaseItem"} + empty={false} + filters={filters} + filter={{ purchaseId: poId }} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + <MyCreateButton onClick={() => { setCreateDialog(true) }} /> + <SelectColumnsButton preferenceKey='purchaseItem' /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='purchaseItem' + bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />} + rowClick={(id, resource, record) => { + setSelect(record) + setEditDialog(true) + }} + omit={['id', 'createTime', 'purchaseId', 'platItemId', 'createBy', 'memo']} + > + <NumberField source="id" /> + <NumberField source="purchaseId" label="table.field.purchaseItem.purchaseId" /> + <TextField source="platItemId" label="table.field.purchaseItem.platItemId" /> + <TextField source="matnrCode" label="table.field.purchaseItem.matnrCode" /> + <TextField source="matnrName" label="table.field.purchaseItem.matnrName" /> + <TextField source="unit" label="table.field.purchaseItem.unit" /> + <NumberField source="anfme" label="table.field.purchaseItem.anfme" /> + <NumberField source="qty" label="table.field.purchaseItem.qty" /> + <NumberField source="nromQty" label="table.field.purchaseItem.nromQty" /> + <NumberField source="asnQty" label="table.field.purchaseItem.asnQty" /> + <NumberField source="printQty" label="table.field.purchaseItem.printQty" /> + <TextField source="splrName" label="table.field.purchaseItem.splrName" /> + <TextField source="splrCode" label="table.field.purchaseItem.splrCode" /> + <TextField source="splrBatch" label="table.field.purchaseItem.splrBatch" /> + <TextField source="updateBy$" label="common.field.updateBy" reference="user" /> + <DateField source="updateTime" label="common.field.updateTime" showTime /> + <TextField source="createBy$" label="common.field.createBy" /> + <DateField source="createTime" label="common.field.createTime" showTime /> + <BooleanField source="statusBool" label="common.field.status" sortable={false} /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + <WrapperField cellClassName="opt" label="common.field.opt"> + <Button label="ra.action.edit" onClick={(id, resource, record) => { + setEditDialog(true) + setSelect(record) + }} /> + <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} /> + </WrapperField> + </StyledDatagrid> + </List> + <PurchaseItemEdit + open={editDialog} + setOpen={setEditDialog} + record={select} + /> + <PurchaseItemCreate + open={createDialog} + setOpen={setCreateDialog} + row={{ poId }} + /> + <PageDrawer + title='PurchaseItem Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box></> + ) +} + +export default PurchaseItemList; diff --git a/rsf-admin/src/page/orders/purchase/PurchaseList.jsx b/rsf-admin/src/page/orders/purchase/PurchaseList.jsx new file mode 100644 index 0000000..3cbbd27 --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/PurchaseList.jsx @@ -0,0 +1,170 @@ +import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; +import { useNavigate } from 'react-router-dom'; +import { + List, + DatagridConfigurable, + SearchInput, + TopToolbar, + SelectColumnsButton, + EditButton, + FilterButton, + CreateButton, + ExportButton, + BulkDeleteButton, + WrapperField, + useRecordContext, + useTranslate, + useNotify, + useListContext, + FunctionField, + TextField, + NumberField, + DateField, + BooleanField, + ReferenceField, + TextInput, + DateTimeInput, + DateInput, + SelectInput, + NumberInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + DeleteButton, +} from 'react-admin'; +import { Box, Typography, Card, Stack } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import PurchaseCreate from "./PurchaseCreate"; +import PurchasePanel from "./PurchasePanel"; +import EmptyData from "../../components/EmptyData"; +import MyCreateButton from "../../components/MyCreateButton"; +import MyExportButton from '../../components/MyExportButton'; +import PageDrawer from "../../components/PageDrawer"; +import MyField from "../../components/MyField"; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import * as Common from '@/utils/common'; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 200 + }, +})); + +const filters = [ + <SearchInput source="condition" alwaysOn />, + <TextInput source="code" label="table.field.purchase.code" />, + <TextInput source="type" label="table.field.purchase.type" />, + <TextInput source="source" label="table.field.purchase.source" />, + <DateInput source="preArr" label="table.field.purchase.preArr" />, + <NumberInput source="anfme" label="table.field.purchase.anfme" />, + <NumberInput source="qty" label="table.field.purchase.qty" />, + <NumberInput source="workQty" label="table.field.purchase.workQty" />, + <TextInput source="channel" label="table.field.purchase.channel" />, + <TextInput source="platCode" label="table.field.purchase.platCode" />, + <DateInput source="startTime" label="table.field.purchase.startTime" />, + <DateInput source="endTime" label="table.field.purchase.endTime" />, + <TextInput source="project" label="table.field.purchase.project" />, + <TextInput label="common.field.memo" source="memo" />, + <SelectInput + label="common.field.status" + source="status" + choices={[ + { id: '1', name: 'common.enums.statusTrue' }, + { id: '0', name: 'common.enums.statusFalse' }, + ]} + resettable + />, +] + +const PurchaseList = () => { + const translate = useTranslate(); + + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + + const navigate = useNavigate(); + const assign = (record) => { + navigate(`/purchaseItem?poId=${record.id}`); + }; + + return ( + <Box display="flex"> + <List + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + }} + title={"menu.purchase"} + empty={<EmptyData onClick={() => { setCreateDialog(true) }} />} + filters={filters} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + <MyCreateButton onClick={() => { setCreateDialog(true) }} /> + <SelectColumnsButton preferenceKey='purchase' /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='purchase' + bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />} + rowClick={'edit'} + expand={false} + expandSingle={true} + omit={['id', 'createTime', 'createBy', 'memo', 'preArr', 'channel','startTime','workQty', 'endTime']} + > + <NumberField source="id" /> + <TextField source="code" label="table.field.purchase.code" /> + <TextField source="type$" label="table.field.purchase.type" /> + <TextField source="source" label="table.field.purchase.source" /> + <DateField source="preArr" label="table.field.purchase.preArr" showTime /> + <NumberField source="anfme" label="table.field.purchase.anfme" /> + <NumberField source="qty" label="table.field.purchase.qty" /> + <NumberField source="workQty" label="table.field.purchase.workQty" /> + <TextField source="channel" label="table.field.purchase.channel" /> + <TextField source="platCode" label="table.field.purchase.platCode" /> + <DateField source="startTime" label="table.field.purchase.startTime" showTime /> + <DateField source="endTime" label="table.field.purchase.endTime" showTime /> + <TextField source="project" label="table.field.purchase.project" /> + <TextField source="updateBy$" label="common.field.updateBy" /> + <DateField source="updateTime" label="common.field.updateTime" showTime /> + <TextField source="createBy$" label="common.field.createBy" /> + <DateField source="createTime" label="common.field.createTime" showTime /> + <BooleanField source="statusBool" label="common.field.status" sortable={false} /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + <WrapperField cellClassName="opt" label="common.field.opt"> + <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} /> + <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} /> + </WrapperField> + </StyledDatagrid> + </List> + <PurchaseCreate + open={createDialog} + setOpen={setCreateDialog} + /> + <PageDrawer + title='Purchase Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box> + ) +} + +export default PurchaseList; diff --git a/rsf-admin/src/page/orders/purchase/PurchasePanel.jsx b/rsf-admin/src/page/orders/purchase/PurchasePanel.jsx new file mode 100644 index 0000000..0793a58 --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/PurchasePanel.jsx @@ -0,0 +1,182 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { Box, Card, CardContent, Grid, Typography, Tooltip, Paper, TableContainer, Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material'; +import { + useTranslate, + useRecordContext, + useNotify +} from 'react-admin'; +import PanelTypography from "../../components/PanelTypography"; +import * as Common from '@/utils/common' +import { styled } from "@mui/material/styles"; +import request from '@/utils/request'; +const PurchasePanel = () => { + const record = useRecordContext(); + if (!record) return null; + const translate = useTranslate(); + const notify = useNotify(); + const [rows, setRows] = useState([]); + const poId = record.id; + + useEffect(() => { + http(); + }, [poId]); + + const http = async () => { + const res = await request.post('/purchaseItem/page', { purchaseId: poId }); + if (res?.data?.code === 200) { + setRows(res.data.data.records) + } else { + notify(res.data.msg); + } + } + + const StyledTable = styled(TableRow)(({ theme }) => ({ + "& .MuiButtonBase-root.": { + padding: "0px 0px", + }, + })); + + const StyledTableRow = styled(TableRow)(({ theme }) => ({ + "& .MuiButtonBase-root.": { + padding: "0px 0px", + }, + })); + + const StyledTableCell = styled(TableCell)(({ theme }) => ({ + "& .MuiButtonBase-root": { + padding: "0px 0px", + }, + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + maxWidth: 600, + })); + + const columns = [ + { + id: 'purchaseId', + label: 'table.field.purchaseItem.purchaseId', + minWidth: 100 + }, + { + id: 'platItemId', + label: 'table.field.purchaseItem.platItemId', + minWidth: 100 + }, + { + id: 'matnrCode', + label: 'table.field.purchaseItem.matnrCode', + minWidth: 100 + }, + { + id: 'matnrName', + label: 'table.field.purchaseItem.matnrName', + minWidth: 100 + }, + { + id: 'unit', + label: 'table.field.purchaseItem.unit', + minWidth: 100 + }, + { + id: 'anfme', + label: 'table.field.purchaseItem.anfme', + minWidth: 100 + }, + { + id: 'qty', + label: 'table.field.purchaseItem.qty', + minWidth: 100 + }, + { + id: 'nromQty', + label: 'table.field.purchaseItem.nromQty', + minWidth: 100 + }, + { + id: 'asnQty', + label: 'table.field.purchaseItem.asnQty', + minWidth: 100 + }, + { + id: 'printQty', + label: 'table.field.purchaseItem.printQty', + minWidth: 100 + }, + { + id: 'splrName', + label: 'table.field.purchaseItem.splrName', + minWidth: 100 + }, + { + id: 'splrCode', + label: 'table.field.purchaseItem.splrCode', + minWidth: 100 + }, + { + id: 'splrBatch', + label: 'table.field.purchaseItem.splrBatch', + minWidth: 100 + }, + { + id: 'statusBool', + label: 'common.field.status', + minWidth: 100, + formatter: (value) => value ? 'Yes' : 'No' + }, + { + id: 'memo', + label: 'common.field.memo', + minWidth: 100 + } + ]; + + + return ( + + <Box sx={{ + position: 'relative', + padding: '5px 10px' + }}> + <TableContainer component={Paper} > + <Table size="small" > + <TableHead> + <StyledTableRow key={'head'}> + {columns.map((column, idx) => { + const value = column.label; + return ( + <> + <StyledTableCell + key={column.id} + align={column.align || "left"} + // style={{ paddingLeft: idx === 0 && (depth * 16 + 16) }} + > + {column.format ? column.format(value) : translate(value)} + </StyledTableCell> + </> + ); + + })} + </StyledTableRow> + </TableHead> + + <TableBody> + {rows.map((row) => ( + <StyledTableRow key={row.id || Math.random()}> + {columns.map((column) => ( + <StyledTableCell key={column.id} > + {row[column.id]} + </StyledTableCell> + ))} + </StyledTableRow> + ))} + + </TableBody> + </Table> + </TableContainer> + </Box> + + ); +}; + +export default PurchasePanel; diff --git a/rsf-admin/src/page/orders/purchase/index.jsx b/rsf-admin/src/page/orders/purchase/index.jsx new file mode 100644 index 0000000..a03738a --- /dev/null +++ b/rsf-admin/src/page/orders/purchase/index.jsx @@ -0,0 +1,18 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + ListGuesser, + EditGuesser, + ShowGuesser, +} from "react-admin"; + +import PurchaseList from "./PurchaseList"; +import PurchaseEdit from "./PurchaseEdit"; + +export default { + list: PurchaseList, + edit: PurchaseEdit, + show: ShowGuesser, + recordRepresentation: (record) => { + return `${record.id}` + } +}; -- Gitblit v1.9.1