From fa1bc9ee550d197ef2aa52bf8601dd488cba09cd Mon Sep 17 00:00:00 2001 From: DESKTOP-LMJ82IJ\Eno <creaycat@gmail.com> Date: 星期日, 13 四月 2025 18:40:39 +0800 Subject: [PATCH] #修改 1. 组拖界面优化 2. 质检界面优化 --- rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx | 114 + rsf-admin/src/page/qlyInspect/QlyIsptItemEdit.jsx | 162 ++ rsf-admin/src/page/orders/asnOrder/AsnOrderItemCreate.jsx | 204 ++ rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx | 316 ++++ rsf-admin/src/page/qlyInspect/QlyIsptItemList.jsx | 167 ++ rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx | 199 ++ rsf-admin/src/page/orders/asnOrder/AsnOrderCreate.jsx | 184 ++ rsf-admin/src/page/orders/asnOrder/index.jsx | 18 rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogPanel.jsx | 143 + rsf-admin/src/page/waitPakin/WaitPakinItemCreate.jsx | 176 ++ rsf-admin/src/page/orders/asnOrderLog/AsnOrderItemLogList.jsx | 177 ++ rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogEdit.jsx | 144 + rsf-admin/src/page/waitPakin/WaitPakinItemList.jsx | 166 ++ rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx | 202 ++ rsf-admin/src/page/orders/asnOrder/AsnWareModal.jsx | 258 +++ rsf-admin/src/page/waitPakin/WaitPakinItemEdit.jsx | 148 ++ rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogCreate.jsx | 195 ++ rsf-admin/src/page/orders/asnOrderLog/index.jsx | 18 rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx | 514 ++++++ rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx | 239 +++ rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogList.jsx | 170 ++ rsf-admin/src/page/orders/asnOrder/PrintModal.jsx | 310 ++++ rsf-admin/src/page/qlyInspect/QlyIsptItemCreate.jsx | 182 ++ 23 files changed, 4,406 insertions(+), 0 deletions(-) diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderCreate.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderCreate.jsx new file mode 100644 index 0000000..6ace1c2 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderCreate.jsx @@ -0,0 +1,184 @@ +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 AsnOrderCreate = (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.asnOrder.code" + source="code" + parse={v => v} + autoFocus + /> + </Grid> */} + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrder.poCode" + source="poCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrder.poId" + source="poId" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrder.type" + source="type" + parse={v => v} + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrder.wkType" + source="wkType" + parse={v => v} + validate={required()} + /> + </Grid> + {/* <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrder.anfme" + source="anfme" + validate={required()} + /> + </Grid> */} + {/* <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrder.qty" + source="qty" + validate={required()} + /> + </Grid> */} + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrder.logisNo" + source="logisNo" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <DateInput + label="table.field.asnOrder.arrTime" + source="arrTime" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <SelectInput + label="table.field.asnOrder.rleStatus" + source="rleStatus" + choices={[ + { id: 0, name: ' 姝e父' }, + { id: 1, name: ' 宸查噴鏀�' }, + ]} + /> + </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 AsnOrderCreate; diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx new file mode 100644 index 0000000..93bced9 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderEdit.jsx @@ -0,0 +1,114 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + Edit, + SimpleForm, + useTranslate, + TextInput, + DateInput, + SelectInput, + AutocompleteInput, + SaveButton, + Toolbar, + required, + DeleteButton, +} from 'react-admin'; +import { useWatch, useFormContext } from "react-hook-form"; +import { Stack, Grid, Box, Typography } from '@mui/material'; +import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; +import EditBaseAside from "../../components/EditBaseAside"; +import CustomerTopToolBar from "../../components/EditTopToolBar"; +import AsnOrderItemList from "./AsnOrderItemList"; + +const FormToolbar = () => { + const { getValues } = useFormContext(); + + return ( + <Toolbar sx={{ justifyContent: 'end' }}> + <SaveButton /> + <DeleteButton mutationMode="optimistic" /> + </Toolbar> + ) +} + +const AsnOrderEdit = () => { + const translate = useTranslate(); + const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_order_type')) || []; + const business = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || []; + + return ( + <> + <Edit + redirect="list" + mutationMode={EDIT_MODE} + actions={<CustomerTopToolBar />} + aside={<EditBaseAside />} + > + <SimpleForm + shouldUnregister + warnWhenUnsavedChanges + toolbar={<FormToolbar />} + mode="onTouched" + defaultValues={{}} + > + <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}> + <Grid item xs={24} md={12}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.main')} + </Typography> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.asnOrder.code" + source="code" + readOnly + parse={v => v} + /> + <TextInput + label="table.field.asnOrder.poCode" + source="poCode" + parse={v => v} + /> + <AutocompleteInput + choices={dicts} + optionText="label" + label="table.field.asnOrder.type" + source="type" + optionValue="value" + parse={v => v} + /> + <AutocompleteInput + choices={business} + optionText="label" + label="table.field.asnOrder.wkType" + source="wkType" + optionValue="value" + parse={v => v} + /> + <TextInput + label="table.field.asnOrder.logisNo" + source="logisNo" + parse={v => v} + /> + <DateInput + label="table.field.asnOrder.arrTime" + source="arrTime" + /> + <SelectInput + label="table.field.asnOrder.rleStatus" + source="rleStatus" + choices={[ + { id: 0, name: ' 姝e父' }, + { id: 1, name: ' 宸查噴鏀�' }, + ]} + validate={required()} + /> + </Stack> + </Grid> + </Grid> + </SimpleForm> + </Edit > + <AsnOrderItemList /> + </> + ) +} + +export default AsnOrderEdit; diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemCreate.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemCreate.jsx new file mode 100644 index 0000000..87c76dd --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemCreate.jsx @@ -0,0 +1,204 @@ +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 AsnOrderItemCreate = (props) => { + const { open, setOpen, record } = 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 + resource="asnOrderItem" + 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> + <Grid item xs={6} display="flex" gap={2}> + <NumberInput + label="table.field.asnOrderItem.asnId" + source="asnId" + readOnly + hidden + defaultValue={record?.id} + /> + <TextInput + label="table.field.asnOrderItem.asnCode" + source="asnCode" + readOnly + defaultValue={record?.code} + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={2}> + <TextInput + label="table.field.asnOrderItem.poDetlId" + source="poDetlId" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.poDetlCode" + source="poDetlCode" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.matnrId" + source="matnrId" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrderItem.maktx" + source="maktx" + parse={v => v} + /> + <NumberInput + label="table.field.asnOrderItem.anfme" + source="anfme" + validate={required()} + /> + <TextInput + label="table.field.asnOrderItem.stockUnit" + source="stockUnit" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrderItem.purQty" + source="purQty" + validate={required()} + /> + <TextInput + label="table.field.asnOrderItem.purUnit" + source="purUnit" + parse={v => v} + /> + <NumberInput + label="table.field.asnOrderItem.qty" + source="qty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrderItem.splrCode" + source="splrCode" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.splrName" + source="splrName" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.qrcode" + source="qrcode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrderItem.barcode" + source="barcode" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.packName" + source="packName" + 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 AsnOrderItemCreate; diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx new file mode 100644 index 0000000..07570e0 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemEdit.jsx @@ -0,0 +1,199 @@ +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, + Form, + useRecordContext, + useGetOne, + DeleteButton, + 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 DialogCloseButton from "../../components/DialogCloseButton"; +import EditBaseAside from "../../components/EditBaseAside"; +import CustomerTopToolBar from "../../components/EditTopToolBar"; +import MemoInput from "../../components/MemoInput"; +import StatusSelectInput from "../../components/StatusSelectInput"; + +const FormToolbar = () => { + const { getValues } = useFormContext(); + + return ( + <Toolbar sx={{ justifyContent: 'end' }}> + <SaveButton /> + <DeleteButton mutationMode="optimistic" /> + </Toolbar> + ) +} + +const AsnOrderItemEdit = (props) => { + const { open, setOpen, record } = props; + const translate = useTranslate(); + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + const { data, isPending, } = useGetOne('asnOrderItem', { id: record?.id }); + 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" + > + <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 }}> + <Form + shouldUnregister + warnWhenUnsavedChanges + mode="onTouched" + defaultValues={{}} + > + <Grid container width={{ xs: '100%', xl: '100%' }}> + <Grid item xs={24} md={14}> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.asnOrderItem.asnId" + source="asnId" + readOnly + /> + <TextInput + label="table.field.asnOrderItem.asnCode" + source="asnCode" + readOnly + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.poDetlId" + source="poDetlId" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.poDetlCode" + source="poDetlCode" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.asnOrderItem.matnrId" + source="matnrId" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.maktx" + source="maktx" + parse={v => v} + /> + <NumberInput + label="table.field.asnOrderItem.anfme" + source="anfme" + validate={required()} + /> + <TextInput + label="table.field.asnOrderItem.stockUnit" + source="stockUnit" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.asnOrderItem.purQty" + source="purQty" + validate={required()} + /> + <TextInput + label="table.field.asnOrderItem.purUnit" + source="purUnit" + parse={v => v} + /> + <NumberInput + label="table.field.asnOrderItem.qty" + source="qty" + /> + <TextInput + label="table.field.asnOrderItem.splrCode" + source="splrCode" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.asnOrderItem.splrName" + source="splrName" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.qrcode" + source="qrcode" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.barcode" + source="barcode" + parse={v => v} + /> + <TextInput + label="table.field.asnOrderItem.packName" + source="packName" + parse={v => v} + /> + </Stack> + </Grid> + </Grid> + <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> + </DialogContent> + </Dialog> + </EditBase > + ) +} + +export default AsnOrderItemEdit; diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx new file mode 100644 index 0000000..085e065 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderItemList.jsx @@ -0,0 +1,202 @@ +import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; +import { useNavigate, useLocation } 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, + Button, + useEditContext, + useGetRecordId, + useGetOne +} from 'react-admin'; +import { Box, Typography, Card, Stack, Dialog, DialogActions, DialogTitle } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import AsnOrderItemCreate from "./AsnOrderItemCreate"; +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, DEFAULT_ITEM_PAGE_SIZE } from '@/config/setting'; +import AsnOrderItemEdit from "./AsnOrderItemEdit"; +import QrCodeIcon from "@mui/icons-material/QrCode"; +import ImportButton from "../../components/ImportButton"; + +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="asnId" label="table.field.asnOrderItem.asnId" />, + <TextInput source="asnCode" label="table.field.asnOrderItem.asnCode" />, + <TextInput source="poDetlId" label="table.field.asnOrderItem.poDetlId" />, + <TextInput source="poDetlCode" label="table.field.asnOrderItem.poDetlCode" />, + <TextInput source="matnrId" label="table.field.asnOrderItem.matnrId" />, + <TextInput source="maktx" label="table.field.asnOrderItem.maktx" />, + <NumberInput source="anfme" label="table.field.asnOrderItem.anfme" />, + <TextInput source="stockUnit" label="table.field.asnOrderItem.stockUnit" />, + <NumberInput source="purQty" label="table.field.asnOrderItem.purQty" />, + <TextInput source="purUnit" label="table.field.asnOrderItem.purUnit" />, + <NumberInput source="qty" label="table.field.asnOrderItem.qty" />, + <TextInput source="splrCode" label="table.field.asnOrderItem.splrCode" />, + <TextInput source="splrName" label="table.field.asnOrderItem.splrName" />, + <TextInput source="qrcode" label="table.field.asnOrderItem.qrcode" />, + <TextInput source="barcode" label="table.field.asnOrderItem.barcode" />, + <TextInput source="packName" label="table.field.asnOrderItem.packName" />, + + <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 AsnOrderItemList = () => { + const translate = useTranslate(); + const [createDialog, setCreateDialog] = useState(false); + const [editDialog, setEditDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const [select, setSelect] = useState({}); + const asnId = useGetRecordId(); + const { data: dicts, isPending, error } = useGetOne('asnOrder', { id: asnId }); const creatCode = () => { }; + + return ( + <> + <Box display="flex"> + <List + resource="asnOrderItem" + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + }} + title={"menu.asnOrderItem"} + empty={<EmptyData onClick={() => { setCreateDialog(true) }} />} + filter={{ asnId: asnId }} + filters={filters} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <Button onClick={creatCode} label={"toolbar.creatcode"}> + <QrCodeIcon /> + </Button> + <FilterButton /> + <MyCreateButton onClick={() => { setCreateDialog(true) }} /> + <SelectColumnsButton preferenceKey='asnOrderItem' /> + <ImportButton value={'asnOrder'} parmas={{ asnId: asnId }} /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_ITEM_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='asnOrderItem' + bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />} + rowClick={(id, resource, record) => { + setSelect(record) + setEditDialog(true) + }} + omit={['id', 'createTime', 'createBy', 'memo', 'poDetlId', 'matnrId', 'asnId']} + > + <NumberField source="id" /> + <NumberField source="asnId" label="table.field.asnOrderItem.asnId" /> + <TextField source="asnCode" label="table.field.asnOrderItem.asnCode" /> + <TextField source="poDetlId" label="table.field.asnOrderItem.poDetlId" /> + <TextField source="poDetlCode" label="table.field.asnOrderItem.poDetlCode" /> + <TextField source="matnrId" label="table.field.asnOrderItem.matnrId" /> + <TextField source="maktx" label="table.field.asnOrderItem.maktx" /> + <NumberField source="anfme" label="table.field.asnOrderItem.anfme" /> + <TextField source="stockUnit" label="table.field.asnOrderItem.stockUnit" /> + <NumberField source="purQty" label="table.field.asnOrderItem.purQty" /> + <TextField source="purUnit" label="table.field.asnOrderItem.purUnit" /> + <NumberField source="qty" label="table.field.asnOrderItem.qty" /> + <TextField source="splrCode" label="table.field.asnOrderItem.splrCode" /> + <TextField source="splrName" label="table.field.asnOrderItem.splrName" /> + <TextField source="qrcode" label="table.field.asnOrderItem.qrcode" /> + <TextField source="barcode" label="table.field.asnOrderItem.barcode" /> + <TextField source="packName" label="table.field.asnOrderItem.packName" /> + <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="status$" 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' }} /> */} + <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> + <AsnOrderItemCreate + open={createDialog} + setOpen={setCreateDialog} + record={dicts} + /> + <AsnOrderItemEdit + open={editDialog} + setOpen={setEditDialog} + record={select} + /> + <PageDrawer + title='AsnOrderItem Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box> + </> + ) +} +AsnOrderItemList.Context = React.createContext() + +export default AsnOrderItemList; diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx new file mode 100644 index 0000000..ccd61f5 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderList.jsx @@ -0,0 +1,316 @@ +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, + useRefresh, + useListContext, + FunctionField, + TextField, + NumberField, + DateField, + BooleanField, + ReferenceField, + TextInput, + DateTimeInput, + DateInput, + SelectInput, + NumberInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + DeleteButton, + Button, +} from 'react-admin'; +import { Box, Typography, Card, Stack } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import AsnOrderModal from "./AsnOrderModal"; +import AsnOrderPanel from "./AsnOrderPanel"; +import EmptyData from "../../components/EmptyData"; +import MyCreateButton from "../../components/MyCreateButton"; +import MyExportButton from '../../components/MyExportButton'; +import BillStatusField from '../../components/BillStatusField'; +import ConfirmButton from '../../components/ConfirmButton'; +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'; +import ConstructionIcon from "@mui/icons-material/Construction"; +import FileDownloadIcon from '@mui/icons-material/FileDownload'; +import EditIcon from '@mui/icons-material/Edit'; +import TaskIcon from '@mui/icons-material/Task'; +import CloseIcon from '@mui/icons-material/Close'; +import request from '@/utils/request'; +import DictionarySelect from "../../components/DictionarySelect"; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 320 + }, + '& .status': { + width: 100 + }, +})); + +const filters = [ + <SearchInput source="condition" alwaysOn />, + <TextInput source="code" label="table.field.asnOrder.code" />, + <TextInput source="poCode" label="table.field.asnOrder.poCode" />, + <NumberInput source="poId" label="table.field.asnOrder.poId" />, + <TextInput source="type" label="table.field.asnOrder.type" />, + <ReferenceInput source="wkType" reference="dictData" filter={{dictTypeCode: 'sys_business_type'}} label="table.field.asnOrder.wkType"> + <AutocompleteInput label="table.field.asnOrder.wkType" optionValue="value" /> + </ReferenceInput>, + <NumberInput source="anfme" label="table.field.asnOrder.anfme" />, + <NumberInput source="qty" label="table.field.asnOrder.qty" />, + <TextInput source="logisNo" label="table.field.asnOrder.logisNo" />, + <DateInput source="arrTime" label="table.field.asnOrder.arrTime" />, + <SelectInput source="rleStatus" label="table.field.asnOrder.rleStatus" + choices={[ + { id: 0, name: ' 姝e父' }, + { id: 1, name: ' 宸查噴鏀�' }, + ]} + />, + + <TextInput label="common.field.memo" source="memo" />, + <DictionarySelect + label='table.field.asnOrder.exceStatus' + name="exceStatus" + dictTypeCode="sys_asn_exce_status" + alwaysOn + />, + +] + +const AsnOrderList = () => { + const translate = useTranslate(); + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const [modalType, setmodalType] = useState(0); + const billReload = useRef(); + const navigate = useNavigate(); + const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || []; + const assign = (record) => { + navigate(`/asnOrderItem?asnId=${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.asnOrder"} + empty={<EmptyData onClick={() => { setCreateDialog(true); setmodalType(0) }} />} + filters={filters} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + <MyCreateButton onClick={() => { setCreateDialog(true); setmodalType(0) }} /> + <SelectColumnsButton preferenceKey='asnOrder' /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + sx={{ width: '100%' }} + preferenceKey='asnOrder' + bulkActionButtons={<> <InspectionsButton /><BulkDeleteButton mutationMode={OPERATE_MODE} /></>} + rowClick={() => 'edit'} + expandSingle={true} + omit={['id', 'createTime', 'createBy', 'memo', 'poId']} + > + <NumberField source="id" /> + <TextField source="code" label="table.field.asnOrder.code" /> + <TextField source="poCode" label="table.field.asnOrder.poCode" /> + <NumberField source="poId" label="table.field.asnOrder.poId" /> + <TextField source="type$" label="table.field.asnOrder.type" /> + <TextField source="wkType$" label="table.field.asnOrder.wkType" /> + <NumberField source="anfme" label="table.field.asnOrder.anfme" /> + <NumberField source="qty" label="table.field.asnOrder.qty" /> + <TextField source="logisNo" label="table.field.asnOrder.logisNo" /> + <DateField source="arrTime" label="table.field.asnOrder.arrTime" showTime /> + <TextField source="rleStatus$" label="table.field.asnOrder.rleStatus" sortable={false} /> + <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 /> + <BillStatusField cellClassName="status" source="exceStatus" label="table.field.asnOrder.exceStatus" /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + <WrapperField cellClassName="opt" label="common.field.opt" width={300} > + <MyButton setCreateDialog={setCreateDialog} setmodalType={setmodalType} /> + <InspectionButton /> + <CompleteButton /> + <CloseButton /> + </WrapperField> + </StyledDatagrid> + </List> + <AsnOrderModal + open={createDialog} + setOpen={setCreateDialog} + asnId={modalType} + billReload={billReload} + /> + <PageDrawer + title='AsnOrder Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box > + ) +} +export default AsnOrderList; + +const MyButton = ({ setCreateDialog, setmodalType }) => { + const record = useRecordContext(); + const handleEditClick = () => { + const id = record.id; + setmodalType(id); + setCreateDialog(true); + + }; + return ( + <Button + color="primary" + startIcon={<EditIcon />} + onClick={() => handleEditClick()} + sx={{ ml: 1 }} + label={'ra.action.edit'} + > + </Button> + ) +} + +const InspectionButton = () => { + const record = useRecordContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const inspection = () => { + requestInspect([record]) + }; + + const requestInspect = async (rows) => { + const { data: { code, data, msg } } = await request.post(`/asnOrder/inspect`, rows); + + if (code === 200) { + notify(msg); + refresh() + } else { + notify(msg); + } + } + + + return ( + <Button onClick={inspection} label={"toolbar.inspection"}> + <ConstructionIcon /> + </Button> + ) +} + +const InspectionsButton = () => { + const { selectedIds, onUnselectItems, data } = useListContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const inspection = () => { + if (selectedIds.length === 0) { + notify('璇烽�夋嫨閫氱煡鍗�'); + return; + } else { + const rows = data.filter((item) => selectedIds.includes(item.id)) + requestInspect(rows) + } + }; + + const requestInspect = async (rows) => { + const { data: { code, data, msg } } = await request.post(`/asnOrder/inspect`, rows); + + if (code === 200) { + notify(msg); + refresh() + } else { + notify(msg); + } + } + + + return ( + <Button onClick={inspection} label={"toolbar.inspection"}> + <ConstructionIcon /> + </Button> + ) +} + +const CompleteButton = () => { + const record = useRecordContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const requestComplete = async () => { + const { data: { code, data, msg } } = await request.post(`/asnOrder/complete/${record.id}`); + + if (code === 200) { + notify(msg); + refresh() + } else { + notify(msg); + } + } + + + return ( + record.exceStatus === 1 && (record.anfme === record.qty ? <Button onClick={requestComplete} label={"toolbar.complete"} color="success"> + <TaskIcon /> + </Button> : <ConfirmButton label={"toolbar.complete"} color="success" data={'褰撳墠鏀惰揣鏁伴噺灏忎簬璁″垝鏁伴噺锛屾槸鍚︾‘璁ゅ畬鎴�'} startIcon={<TaskIcon />} onConfirm={requestComplete} />) + + ) + + +} + +const CloseButton = () => { + const record = useRecordContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const requestClose = async () => { + const { data: { code, data, msg } } = await request.post(`/asnOrder/close/${record.id}`); + + if (code === 200) { + notify(msg); + refresh() + } else { + notify(msg); + } + } + + return ( + <ConfirmButton label={"toolbar.close"} color="error" data={'纭鏄惁鍏抽棴锛�'} startIcon={<CloseIcon />} onConfirm={requestClose} /> + ) +} diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx new file mode 100644 index 0000000..7302abe --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderModal.jsx @@ -0,0 +1,514 @@ +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, + useListContext, + useRefresh, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + TextField, + Box, + Button, + Paper, + TableContainer, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + Tooltip, + IconButton, + styled + + +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import StatusSelectInput from "../../components/StatusSelectInput"; +import ConfirmButton from "../../components/ConfirmButton"; +import AsnWareModal from "./AsnWareModal"; +import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; +import SaveIcon from '@mui/icons-material/Save'; +import request from '@/utils/request'; +import { Add, Edit, Delete } from '@mui/icons-material'; +import _, { set } from 'lodash'; +import { DataGrid, useGridApiRef } from '@mui/x-data-grid'; +import DictionarySelect from "../../components/DictionarySelect"; +import DictSelect from "../../components/DictSelect"; + +const AsnOrderModal = (props) => { + const { open, setOpen, asnId, billReload } = props; + + const translate = useTranslate(); + const notify = useNotify(); + const refresh = useRefresh(); + const [disabled, setDisabled] = useState(false) + + const [createDialog, setCreateDialog] = useState(false); + + const tableRef = useRef(); + + useEffect(() => { + if (open && asnId !== 0) { + requestGetHead() + requestGetBody() + } + setDisabled(false) + }, [open]) + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + refresh(); + setFormData({ type: '', wkType: '' }) + setTableData([]) + } + }; + + const [formData, setFormData] = useState({ + type: '', + wkType: '', + poCode: '', + logisNo: '', + arrTime: '' + }); + + const [tabelData, setTableData] = useState([]); + + + const handleChange = (value, name) => { + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); + }; + + const resetData = () => { + setFormData({ + type: '', + wkType: '', + poCode: '', + logisNo: '', + arrTime: '' + }) + setTableData([]) + } + + const setFinally = () => { + const rows = tableRef.current.state.editRows; + for (const key in rows) { + const find = tabelData.find(item => item.matnrId === +key); + find.anfme = rows[key].anfme.value; + } + setTableData([...tabelData]); + } + + const handleSubmit = async () => { + setFinally() + setDisabled(true) + + if (asnId === 0) { + const parmas = { + "orders": formData, + "items": tabelData, + } + + const res = await request.post(`/asnOrder/items/save`, parmas); + if (res?.data?.code === 200) { + setOpen(false); + refresh(); + billReload?.current() + resetData() + } else { + notify(res.data.msg); + } + } else { + const parmas = { + "orders": formData, + "items": tabelData, + } + const res = await request.post(`/asnOrder/items/update`, parmas); + if (res?.data?.code === 200) { + setOpen(false); + refresh(); + billReload?.current() + resetData() + } else { + notify(res.data.msg); + } + } + setDisabled(false) + + }; + + + const handleDelete = async () => { + const res = await request.post(`/asnOrder/remove/${asnId}`); + if (res?.data?.code === 200) { + setOpen(false); + refresh(); + } else { + notify(res.data.msg); + } + }; + + const requestGetHead = async () => { + const res = await request.get(`/asnOrder/${asnId}`); + if (res?.data?.code === 200) { + setFormData(res.data.data) + } else { + notify(res.data.msg); + } + } + + const requestGetBody = async () => { + const res = await request.post(`/asnOrderItem/page`, { asnId }); + if (res?.data?.code === 200) { + setTableData(res.data.data.records) + } else { + notify(res.data.msg); + } + } + + const [selectedRows, setSelectedRows] = useState([]); + + + + const handleDeleteItem = () => { + const newTableData = _.filter(tabelData, (item) => !selectedRows.includes(item.matnrId)); + setTableData(newTableData); + } + + return ( + <> + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + aria-hidden + fullWidth + disableRestoreFocus + maxWidth="lg" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + > + <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 }}> + <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> + <Form> + <Grid container spacing={2}> + <Grid item md={3}> + <DictSelect + label={translate("table.field.asnOrder.type")} + value={formData.type} + onChange={(e) => handleChange(e.target.value, 'type')} + dictTypeCode="sys_order_type" + required + /> + </Grid> + <Grid item md={3}> + <DictSelect + label={translate("table.field.asnOrder.wkType")} + value={formData.wkType} + onChange={(e) => handleChange(e.target.value, 'wkType')} + dictTypeCode="sys_business_type" + required + /> + </Grid> + <Grid item md={3}> + <TextField + label={translate("table.field.asnOrder.poCode")} + value={formData.poCode} + onChange={(e) => handleChange(e.target.value, 'poCode')} + /> + </Grid> + <Grid item md={3}> + <TextField + label={translate("table.field.asnOrder.logisNo")} + value={formData.logisNo} + onChange={(e) => handleChange(e.target.value, 'logisNo')} + /> + </Grid> + + <Grid item md={3}> + {/* <TextField + label={translate("table.field.asnOrder.arrTime")} + value={formData.arrTime} + onChange={(e) => handleChange(e.target.value, 'arrTime')} + /> */} + <DateInput + source="arrTime" + label="table.field.asnOrder.arrTime" + value={formData.arrTime} + onChange={(e) => handleChange(e.target.value, 'arrTime')} + /> + + </Grid> + </Grid> + </Form> + </Box> + + <Box sx={{ mt: 2 }}> + <Stack direction="row" spacing={2}> + <Button variant="contained" onClick={() => setCreateDialog(true)}>鏂板鐗╂枡</Button> + {/* {asnId !== '' && <ConfirmButton label={'鍒犻櫎'} variant="outlined" color="error" onConfirm={handleDelete} />} */} + <ConfirmButton label={'鍒犻櫎'} variant="outlined" color="error" onConfirm={handleDeleteItem} /> + </Stack> + + </Box> + + <Box sx={{ mt: 2 }}> + <AsnOrderModalTable tabelData={tabelData} setTableData={setTableData} asnId={asnId} selectedRows={selectedRows} setSelectedRows={setSelectedRows} tableRef={tableRef}></AsnOrderModalTable> + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} > + <Button disabled={disabled} onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Toolbar> + </DialogActions> + + </Dialog> + + <AsnWareModal + open={createDialog} + setOpen={setCreateDialog} + data={tabelData} + setData={setTableData} + /> + </> + ) +} + +export default AsnOrderModal; + +const AsnOrderModalTable = ({ tabelData, setTableData, asnId, selectedRows, setSelectedRows, tableRef }) => { + const translate = useTranslate(); + const notify = useNotify(); + + const [columns, setColumns] = useState([ + + { + field: 'maktx', + headerName: translate('table.field.asnOrderItem.maktx'), + width: 250, + editable: false, + }, + { + field: 'matnrCode', + headerName: translate('table.field.asnOrderItem.matnrCode'), + width: 130, + editable: false, + }, + { + field: 'anfme', + headerName: translate('table.field.asnOrderItem.purQty'), + type: 'number', + minWidth: 100, + flex: 1, + editable: true, + valueFormatter: (val) => val < 0 ? 0 : val + }, + { + field: 'splrCode', + headerName: translate('table.field.asnOrderItem.splrCode'), + minWidth: 100, + flex: 1, + editable: true, + }, + { + field: 'splrName', + headerName: translate('table.field.asnOrderItem.splrName'), + minWidth: 100, + flex: 1, + editable: true, + }, + // { + // field: 'packName', + // headerName: translate('table.field.asnOrderItem.packName'), + // minWidth: 100, + // flex: 1, + // editable: true, + // }, + // { + // field: 'poDetlId', + // headerName: translate('table.field.asnOrderItem.poDetlId'), + // minWidth: 100, + // flex: 1, + // }, + { + field: 'poCode', + headerName: translate('table.field.asnOrderItem.poDetlCode'), + minWidth: 100, + flex: 1, + editable: true, + }, + + { + field: 'stockUnit', + headerName: translate('table.field.asnOrderItem.stockUnit'), + minWidth: 100, + flex: 1, + editable: false, + }, + // { + // field: 'purQty', + // headerName: translate('table.field.asnOrderItem.purQty'), + // minWidth: 100, + // flex: 1, + // editable: true, + // }, + { + field: 'purUnit', + headerName: translate('table.field.asnOrderItem.purUnit'), + minWidth: 100, + flex: 1, + editable: false, + }, + + + + ]) + + const action = { + field: 'action', + headerName: '鎿嶄綔', + width: 70, + lockPosition: 'left', + renderCell: (params) => ( + <Tooltip title="Delete"> + <IconButton onClick={() => handleDelete(params.row)}> + <Delete /> + </IconButton> + </Tooltip> + ), + + } + + let cdata = useRef([]); + + + useEffect(() => { + getDynamicFields(); + }, []); + + useEffect(() => { + cdata.current = tabelData + }, [tabelData]); + + + const getDynamicFields = async () => { + const { + data: { code, data, msg }, + } = await request.get("/fields/enable/list"); + if (code === 200) { + const cols = data.map(el => ({ + field: el.fields, + headerName: el.fieldsAlise, + minWidth: 100, + flex: 1, + editable: false + })) + setColumns([...columns, ...cols, action]) + } else { + notify(msg); + } + } + + + + const handleDelete = (row) => { + const newData = _.filter(cdata.current, (item) => item.matnrId !== row.matnrId); + setTableData(newData); + }; + + + const processRowUpdate = (newRow, oldRow) => { + const rows = tabelData.map((r) => + r.matnrId === newRow.matnrId ? { ...newRow } : r + ) + setTableData(rows) + // setTableData((prevData) => + // prevData.map((r) => + // r.matnrId === newRow.matnrId ? { ...newRow } : r + // ) + + // ); + + return newRow; + }; + + + + const handleSelectionChange = (ids) => { + setSelectedRows(ids) + + }; + + tableRef.current = useGridApiRef(); + + + return ( + <div style={{ height: 400, width: '100%' }}> + <DataGrid + apiRef={tableRef} + rows={tabelData} + columns={columns} + disableRowSelectionOnClick + getRowId={(row) => row.matnrId} + disableColumnFilter + disableColumnSelector + disableColumnSorting + disableMultipleColumnsSorting + processRowUpdate={processRowUpdate} + initialState={{ + pagination: { + paginationModel: { + pageSize: 25, + }, + }, + }} + pageSizeOptions={[10, 25, 50, 100]} + editMode="row" + checkboxSelection + onRowSelectionModelChange={handleSelectionChange} + selectionModel={selectedRows} + sx={{ + '& .MuiDataGrid-cell input': { + border: '1px solid #ccc' + }, + }} + /> + </div> + ); +}; + diff --git a/rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx b/rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx new file mode 100644 index 0000000..4649e7f --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnOrderPanel.jsx @@ -0,0 +1,239 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { Box, Card, CardContent, Grid, Typography, Button, TextField, Tooltip, Paper, TableContainer, Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material'; +import { + useTranslate, + useRecordContext, + useNotify, + useRefresh, + useListContext, +} 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'; +import debounce from 'lodash/debounce'; +import { DataGrid } from '@mui/x-data-grid'; +import PrintModal from './PrintModal'; +import PrintIcon from '@mui/icons-material/Print'; +const AsnOrderPanel = ({ billReload }) => { + const record = useRecordContext(); + if (!record) return null; + const translate = useTranslate(); + const notify = useNotify(); + const [rows, setRows] = useState([]); + const [maktx, setMaktx] = useState(''); + const asnId = record.id; + + useEffect(() => { + debouncedHttp({ maktx }); + }, [asnId, maktx]); + + const http = async (parmas) => { + const res = await request.post('/asnOrderItem/page', { ...parmas, asnId }); + if (res?.data?.code === 200) { + setRows(res.data.data.records) + } else { + notify(res.data.msg); + } + } + + + useEffect(() => { + billReload.current = http + }, []); + + + const debouncedHttp = useMemo(() => debounce(http, 300), []); + + const columns = [ + { + field: 'asnId', + headerName: translate('table.field.asnOrderItem.asnId') + }, + { + field: 'asnCode', + headerName: translate('table.field.asnOrderItem.asnCode'), + width: 150, + }, + // { + // field: 'poDetlId', + // headerName: translate('table.field.asnOrderItem.poDetlId') + // }, + { + field: 'poCode', + headerName: translate('table.field.asnOrderItem.poDetlCode') + }, + { + field: 'matnrCode', + headerName: translate('table.field.asnOrderItem.matnrCode'), + width: 150, + }, + { + field: 'maktx', + headerName: translate('table.field.asnOrderItem.maktx'), + width: 200, + }, + { + field: 'anfme', + headerName: translate('table.field.asnOrderItem.purQty') + }, + { + field: 'stockUnit', + headerName: translate('table.field.asnOrderItem.stockUnit') + }, + // { + // field: 'purQty', + // headerName: translate('table.field.asnOrderItem.purQty') + // }, + { + field: 'purUnit', + headerName: translate('table.field.asnOrderItem.purUnit') + }, + { + field: 'qty', + headerName: translate('table.field.asnOrderItem.qty') + }, + { + field: 'splrBatch', + headerName: translate('table.field.asnOrderItem.splrBatch') + }, + { + field: 'splrCode', + headerName: translate('table.field.asnOrderItem.splrCode') + }, + { + field: 'splrName', + headerName: translate('table.field.asnOrderItem.splrName') + }, + { + field: 'trackCode', + headerName: translate('table.field.asnOrderItem.barcode'), + width: 150 + }, + { + field: 'prodTime', + headerName: translate('table.field.asnOrderItem.prodTime') + }, + { + field: 'packName', + headerName: translate('table.field.asnOrderItem.packName') + }, + { + field: 'action', + headerName: '鎿嶄綔', + width: 70, + lockPosition: 'left', + renderCell: (params) => ( + <PrintButton rows={[params.row.id]} /> + ), + + },] + + const [selectedRows, setSelectedRows] = useState([]); + + const handleSelectionChange = (ids) => { + setSelectedRows(ids) + + }; + const maktxChange = (value) => { + setMaktx(value) + } + + + return ( + <Box sx={{ + position: 'relative', + padding: '5px 10px' + }}> + <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px', alignItems: 'center' }}> + <TextField value={maktx} onChange={(e) => maktxChange(e.target.value)} label="鎼滅储鐗╂枡" sx={{ width: '300px' }} size="small" /> + + <div style={{ display: 'flex', gap: '10px' }}> + <PrintsButton rows={selectedRows} /> + </div> + </div> + + + <DataGrid + sx={{ width: 'calc(100vw - 280px)' }} + size="small" + rows={rows} + columns={columns} + disableRowSelectionOnClick + checkboxSelection + onRowSelectionModelChange={handleSelectionChange} + selectionModel={selectedRows} + disableColumnMenu={true} + disableColumnSorting + disableMultipleColumnsSorting + columnHeaderHeight={40} + rowHeight={42} + initialState={{ + pagination: { + paginationModel: { + pageSize: 10, + }, + }, + }} + pageSizeOptions={[10, 25, 50]} + /> + </Box > + + ); +}; + +export default AsnOrderPanel; + +const PrintsButton = ({ rows }) => { + const record = useRecordContext(); + const { resource, selectedIds } = useListContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const translate = useTranslate(); + + const [createDialog, setCreateDialog] = useState(false); + + const modalChange = () => { + if (rows?.length === 0) { + notify('璇烽�夋嫨鐗╂枡'); + return; + } else { + setCreateDialog(true) + } + + } + + return ( + <> + <Button size="small" color="secondary" onClick={modalChange} startIcon={<PrintIcon />}>{translate("toolbar.batchPrint")}</Button> + + <PrintModal + open={createDialog} + setOpen={setCreateDialog} + rows={rows} + /> + </> + ) +} + +const PrintButton = ({ rows }) => { + const record = useRecordContext(); + + const notify = useNotify(); + const refresh = useRefresh(); + + const [createDialog, setCreateDialog] = useState(false); + const translate = useTranslate(); + + return ( + <> + <Button size="small" color="secondary" onClick={() => setCreateDialog(true)} startIcon={<PrintIcon />}>{translate("toolbar.print")}</Button> + + <PrintModal + open={createDialog} + setOpen={setCreateDialog} + rows={rows} + /> + </> + ) +} diff --git a/rsf-admin/src/page/orders/asnOrder/AsnWareModal.jsx b/rsf-admin/src/page/orders/asnOrder/AsnWareModal.jsx new file mode 100644 index 0000000..5a74996 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/AsnWareModal.jsx @@ -0,0 +1,258 @@ +import React, { useState, useEffect } from "react"; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + TextField, + Box, + Button, + Paper, + styled +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import ConfirmButton from "../../components/ConfirmButton"; +import { useTranslate, useNotify, useRefresh } from 'react-admin'; +import request from '@/utils/request'; +import { DataGrid } from '@mui/x-data-grid'; +import SaveIcon from '@mui/icons-material/Save'; +import TreeSelectInput from "@/page/components/TreeSelectInput"; +const AsnWareModal = (props) => { + const { open, setOpen, data, setData } = props; + + const translate = useTranslate(); + const notify = useNotify(); + const refresh = useRefresh(); + + const asnId = ''; + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const [formData, setFormData] = useState({ + name: '', + code: '', + groupId: 0 + }); + + const [tableData, setTableData] = useState([]); + const [dyFields, setDyFields] = useState([]); + const [selectedRows, setSelectedRows] = useState([]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); + }; + + const reset = () => { + setFormData({ + name: '', + code: '', + groupId: 0 + }) + } + + const handleSubmit = () => { + const hasarr = data.map(el => +el.matnrId) + const selectedData = selectedRows.filter(item => !hasarr.includes(item)).map(id => (tableData.find(row => row.id === id))); + const value = selectedData.map((el => { + const dynamicFields = dyFields.reduce((acc, item) => { + acc[item.fields] = el['extendFields']?.[item.fields] || ''; + return acc; + }, {}); + return { + matnrId: el.id, + maktx: el.name, + matnrCode: el.code, + stockUnit: el.stockUnit || '', + purUnit: el.purchaseUnit || '', + ...dynamicFields + } + })) + setData([...data, ...value]); + setOpen(false); + reset(); + }; + + const getData = async () => { + const res = await request.post(`/matnr/page`, { + ...formData, + current: 1, + pageSize: 100, + orderBy: "create_time desc" + }); + if (res?.data?.code === 200) { + setTableData(res.data.data.records); + } else { + notify(res.data.msg); + } + }; + + useEffect(() => { + getData(); + }, [open]); + + const handleSearch = () => { + getData() + }; + + return ( + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + fullWidth + disableRestoreFocus + maxWidth="lg" + > + <DialogTitle id="form-dialog-title" sx={{ + position: 'sticky', + top: 0, + backgroundColor: 'background.paper', + zIndex: 1000 + }}> + 閫夋嫨鐗╂枡 + <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> + <DialogCloseButton onClose={handleClose} /> + </Box> + </DialogTitle> + <DialogContent sx={{ mt: 2 }}> + <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}> + <Grid container spacing={2}> + <Grid item md={4}> + <TextField + label={translate('table.field.matnr.name')} + name="name" + value={formData.name} + onChange={handleChange} + size="small" + /> + </Grid> + <Grid item md={4}> + <TextField + label={translate('table.field.matnr.code')} + name="code" + value={formData.code} + onChange={handleChange} + size="small" + /> + </Grid> + <Grid item md={4}> + <TreeSelectInput + label="table.field.matnr.groupId" + value={formData.groupId} + resource={'matnrGroup'} + source="groupId" + name="groupId" + onChange={handleChange} + /> + </Grid> + </Grid> + </Box> + <Box sx={{ mt: 2 }}> + <Stack direction="row" spacing={2}> + <Button variant="contained" onClick={handleSearch}>鎼滅储</Button> + </Stack> + </Box> + <Box sx={{ mt: 2, height: 400, width: '100%' }}> + <AsnWareModalTable + tableData={tableData} + setTableData={setTableData} + dyFields={dyFields} + setDyFields={setDyFields} + selectedRows={selectedRows} + setSelectedRows={setSelectedRows} + /> + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}> + <Button onClick={handleSubmit} variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Box> + </DialogActions> + </Dialog> + ); +}; + +export default AsnWareModal; + +const AsnWareModalTable = ({ tableData, setTableData, selectedRows, setSelectedRows, dyFields, setDyFields }) => { + const translate = useTranslate(); + const notify = useNotify(); + + const [columns, setColumns] = useState([ + // { field: 'id', headerName: 'ID', width: 100 }, + { field: 'name', headerName: translate('table.field.matnr.name'), width: 300 }, + { field: 'code', headerName: translate('table.field.matnr.code'), width: 200 }, + { field: 'groupId$', headerName: translate('table.field.matnr.groupId'), width: 100 }, + { field: 'spec', headerName: translate('table.field.matnr.spec'), width: 100 }, + { field: 'model', headerName: translate('table.field.matnr.model'), width: 100 }, + { field: 'weight', headerName: translate('table.field.matnr.weight'), width: 100 }, + + { field: 'describle', headerName: translate('table.field.matnr.describle'), width: 100 }, + { field: 'nromNum', headerName: translate('table.field.matnr.nromNum'), width: 100 }, + { field: 'unit', headerName: translate('table.field.matnr.unit'), width: 100 }, + { field: 'purchaseUnit', headerName: translate('table.field.matnr.purUnit'), width: 100 }, + { field: 'stockUnit', headerName: translate('table.field.matnr.stockUnit'), width: 100 }, + { field: 'stockLeval$', headerName: translate('table.field.matnr.stockLevel'), width: 100, sortable: false }, + ]) + + + + const handleSelectionChange = (ids) => { + setSelectedRows(ids) + + }; + + useEffect(() => { + getDynamicFields(); + }, []); + + const getDynamicFields = async () => { + const { + data: { code, data, msg }, + } = await request.get("/fields/enable/list"); + if (code === 200) { + const cols = data.map(el => ({ + field: el.fields, + headerName: el.fieldsAlise, + minWidth: 100, + flex: 1, + editable: el.unique, + valueGetter: (value, row) => { + return row.extendFields?.[el.fields] || ''; + }, + })) + setDyFields(data) + setColumns([...columns, ...cols]) + } else { + notify(msg); + } + } + + return ( + <div style={{ height: 400, width: '100%' }}> + <DataGrid + size="small" + rows={tableData} + columns={columns} + checkboxSelection + onRowSelectionModelChange={handleSelectionChange} + selectionModel={selectedRows} + disableColumnMenu={true} + disableColumnSorting + disableMultipleColumnsSorting + /> + </div> + ); +}; \ No newline at end of file diff --git a/rsf-admin/src/page/orders/asnOrder/PrintModal.jsx b/rsf-admin/src/page/orders/asnOrder/PrintModal.jsx new file mode 100644 index 0000000..2ad47fd --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/PrintModal.jsx @@ -0,0 +1,310 @@ +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, + useListContext, + useRefresh, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Grid, + TextField, + Box, + Button, + Radio, + RadioGroup, + FormControlLabel, + FormControl, + FormLabel, + TableRow, + TableCell, + Tooltip, + IconButton, + styled + + +} from '@mui/material'; +import DialogCloseButton from "@/page/components/DialogCloseButton"; +import DictionarySelect from "@/page/components/DictionarySelect"; +import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; +import SaveIcon from '@mui/icons-material/Save'; +import request from '@/utils/request'; +import { Add, Edit, Delete } from '@mui/icons-material'; +import _ from 'lodash'; +import { DataGrid } from '@mui/x-data-grid'; +import StatusSelectInput from "@/page/components/StatusSelectInput"; + +import { useReactToPrint } from "react-to-print"; +import jsbarcode from 'jsbarcode' +import { el } from "date-fns/locale"; + +const PrintModal = ({ open, setOpen, rows }) => { + const refresh = useRefresh(); + const translate = useTranslate(); + const notify = useNotify(); + const contentRef = useRef(null); + const reactToPrintFn = useReactToPrint({ contentRef }); + + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + + const [value, setValue] = useState('temp1'); + + const handleChange = (event) => { + setValue(event.target.value); + }; + + const handlePrint = () => { + // handleClose() + reactToPrintFn() + }; + + return ( + <Dialog open={open} maxWidth="sm" fullWidth> + <DialogCloseButton onClose={handleClose} /> + <DialogTitle>{translate('toolbar.print')}</DialogTitle> + <DialogContent > + <FormControl > + <RadioGroup + row + aria-labelledby="demo-controlled-radio-buttons-group" + name="controlled-radio-buttons-group" + value={value} + onChange={handleChange} + size="small" + sx={{ justifyContent: 'center' }} + > + <FormControlLabel value="temp1" control={<Radio />} label="妯℃澘1" size="small" /> + </RadioGroup> + </FormControl> + + <Box> + <div style={{ textAlign: 'center', display: 'flex', justifyContent: 'center' }}> + <table + className="contain" + style={{ + overflow: 'hidden', + fontSize: 'small', + tableLayout: 'fixed', + width: '280px', + borderCollapse: 'collapse', // 鍚堝苟杈规 + border: '1px solid black' // 璁剧疆琛ㄦ牸鏁翠綋杈规 + }} + > + <tbody> + <tr style={{ height: '74px' }}> + <td + align="center" + colSpan={3} + style={{ border: '1px solid black' }} // 璁剧疆鍗曞厓鏍艰竟妗� + > + 鍟嗗搧缂栫爜 + </td> + <td + align="center" + className="barcode" + colSpan={9} + style={{ border: '1px solid black' }} + > + <img className="template-code" src={'/img/barcode.jpeg'} style={{ width: '90%' }} alt="Barcode" /> + <div style={{ letterSpacing: '2px', marginTop: '1px', textAlign: 'center' }}> + <span>{'xxxxxx'}</span> + </div> + </td> + </tr> + <tr style={{ height: '74px' }}> + <td + align="center" + colSpan={3} + style={{ border: '1px solid black' }} + > + 鍟嗗搧 + </td> + <td + align="center" + colSpan={5} + style={{ + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + border: '1px solid black' + }} + > + {'xxxxxxxx'} + </td> + <td + align="center" + colSpan={2} + style={{ border: '1px solid black' }} + > + 澶囨敞 + </td> + <td + align="center" + colSpan={2} + style={{ border: '1px solid black' }} + > + {'xx'} + </td> + </tr> + </tbody> + </table> + </div> + <style>{` + @media print { + .print-content { + display: block!important; + } + }`} </style> + <div ref={contentRef} className="print-content" style={{ textAlign: 'center', display: 'none' }}> + <PrintTemp key={'bb'} rows={rows} /> + </div> + </Box> + </DialogContent> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Box sx={{ width: '100%', display: 'flex', justifyContent: 'space-between' }}> + <Button onClick={handlePrint} variant="contained" startIcon={<SaveIcon />}> + {translate('toolbar.confirm')} + </Button> + </Box> + </DialogActions> + </Dialog > + ); +} + +export default PrintModal; + +const PrintTemp = ({ rows }) => { + const notify = useNotify(); + const [data, setData] = useState([]); + const http = async () => { + const res = await request.post(`/asnOrderItem/many/${rows?.join()}`); + if (res?.data?.code === 200) { + let val = res.data.data.map((el => { + return { + barcode: '/img/barcode.jpeg', + code: el.trackCode, + name: el.maktx, + memo: el.memo || '' + } + })) + setData(val) + setTimeout(() => { + val.forEach((el) => { + jsbarcode(`#barcode${el.code}`, el.code, { height: 30 }); + }); + }, 10); + + } else { + notify(res.data.msg); + } + } + + useEffect(() => { + if (rows?.length > 0) { + http(); + } + + }, [rows]); + + + return ( + <> + {data.map((item, index) => ( + <table + key={index} + className="contain" + style={{ + overflow: 'hidden', + fontSize: 'small', + tableLayout: 'fixed', + width: '520px', + borderCollapse: 'collapse', + borderSpacing: 0, + margin: '0 auto', + marginTop: '10px', + }} + > + <tbody> + <tr style={{ height: '74px' }}> + <td align="center" colSpan={3} style={{ border: '1px solid black' }} > + 鍟嗗搧缂栫爜 + </td> + <td + align="center" + className="barcode" + colSpan={9} + style={{ border: '1px solid black' }} + > + <img id={"barcode" + item.code} style={{ width: '70%', verticalAlign: 'middle' }} /> + {/* <img className="template-code" src={item.barcode} style={{ width: '90%', verticalAlign: 'middle' }} alt="Barcode" /> */} + {/* <div style={{ letterSpacing: '2px', marginTop: '1px', textAlign: 'center' }}> + <span>{item.code}</span> + </div> */} + </td> + </tr> + <tr style={{ height: '74px' }}> + <td + align="center" + colSpan={3} + style={{ border: '1px solid black' }} + > + 鍟嗗搧 + </td> + <td + align="center" + colSpan={5} + style={{ + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + border: '1px solid black' + }} + > + {item.name} + </td> + <td + align="center" + colSpan={2} + style={{ border: '1px solid black' }} + > + 澶囨敞 + </td> + <td + align="center" + colSpan={2} + style={{ border: '1px solid black' }} + > + {item.memo} + </td> + </tr> + </tbody> + </table> + ))} + + </> + ) +} + + diff --git a/rsf-admin/src/page/orders/asnOrder/index.jsx b/rsf-admin/src/page/orders/asnOrder/index.jsx new file mode 100644 index 0000000..efc23bb --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrder/index.jsx @@ -0,0 +1,18 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + ListGuesser, + EditGuesser, + ShowGuesser, +} from "react-admin"; + +import AsnOrderList from "./AsnOrderList"; +import AsnOrderEdit from "./AsnOrderEdit"; + +export default { + list: AsnOrderList, + edit: AsnOrderEdit, + show: ShowGuesser, + recordRepresentation: (record) => { + return `${record.name}` + } +}; diff --git a/rsf-admin/src/page/orders/asnOrderLog/AsnOrderItemLogList.jsx b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderItemLogList.jsx new file mode 100644 index 0000000..8d966b2 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderItemLogList.jsx @@ -0,0 +1,177 @@ +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, + useGetRecordId, +} from 'react-admin'; +import { Box, Typography, Card, Stack } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import EmptyData from "../../components/EmptyData"; +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 />, + + <NumberInput source="asnId" label="table.field.asnOrderItemLog.asnId" />, + <TextInput source="asnCode" label="table.field.asnOrderItemLog.asnCode" />, + <TextInput source="platItemId" label="table.field.asnOrderItemLog.platItemId" />, + <NumberInput source="poDetlId" label="table.field.asnOrderItemLog.poDetlId" />, + <TextInput source="poCode" label="table.field.asnOrderItemLog.poCode" />, + <TextInput source="fieldsIndex" label="table.field.asnOrderItemLog.fieldsIndex" />, + <TextInput source="matnrId" label="table.field.asnOrderItemLog.matnrId" />, + <TextInput source="matnrCode" label="table.field.asnOrderItemLog.matnrCode" />, + <TextInput source="maktx" label="table.field.asnOrderItemLog.maktx" />, + <NumberInput source="anfme" label="table.field.asnOrderItemLog.anfme" />, + <TextInput source="stockUnit" label="table.field.asnOrderItemLog.stockUnit" />, + <NumberInput source="purQty" label="table.field.asnOrderItemLog.purQty" />, + <TextInput source="purUnit" label="table.field.asnOrderItemLog.purUnit" />, + <NumberInput source="qty" label="table.field.asnOrderItemLog.qty" />, + <TextInput source="splrCode" label="table.field.asnOrderItemLog.splrCode" />, + <TextInput source="splrBatch" label="table.field.asnOrderItemLog.splrBatch" />, + <TextInput source="splrName" label="table.field.asnOrderItemLog.splrName" />, + <TextInput source="qrcode" label="table.field.asnOrderItemLog.qrcode" />, + <TextInput source="trackCode" label="table.field.asnOrderItemLog.trackCode" />, + <TextInput source="barcode" label="table.field.asnOrderItemLog.barcode" />, + <TextInput source="packName" label="table.field.asnOrderItemLog.packName" />, + <SelectInput source="ntyStatus" label="table.field.asnOrderItemLog.ntyStatus" + choices={[ + { id: 0, name: ' 鏈笂鎶�' }, + { id: 1, name: ' 宸蹭笂鎶�' }, + ]} + />, + + <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 AsnOrderItemLogList = () => { + const translate = useTranslate(); + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const recodeId = useGetRecordId(); + + return ( + <Box display="flex"> + <List + resource="asnOrderItemLog" + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + }} + title={"menu.asnOrderItemLog"} + empty={false} + filters={filters} + filter={{ logId: recodeId }} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + <SelectColumnsButton preferenceKey='asnOrderItemLog' /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='asnOrderItemLog' + bulkActionButtons={false} + rowClick={(id, resource, record) => false} + omit={['id', 'asnId', 'poDetlId', 'poCode', 'qrcode', 'packName', 'createTime', 'memo', 'fieldsIndex', 'matnrId', 'splrCode', 'status', 'createBy$']} + > + <NumberField source="id" /> + <NumberField source="asnId" label="table.field.asnOrderItemLog.asnId" /> + <TextField source="asnCode" label="table.field.asnOrderItemLog.asnCode" /> + <TextField source="platItemId" label="table.field.asnOrderItemLog.platItemId" /> + <NumberField source="poDetlId" label="table.field.asnOrderItemLog.poDetlId" /> + <TextField source="poCode" label="table.field.asnOrderItemLog.poCode" /> + <TextField source="fieldsIndex" label="table.field.asnOrderItemLog.fieldsIndex" /> + <TextField source="matnrId" label="table.field.asnOrderItemLog.matnrId" /> + <TextField source="matnrCode" label="table.field.asnOrderItemLog.matnrCode" /> + <TextField source="maktx" label="table.field.asnOrderItemLog.maktx" /> + <NumberField source="anfme" label="table.field.asnOrderItemLog.anfme" /> + <NumberField source="purQty" label="table.field.asnOrderItemLog.purQty" /> + <TextField source="purUnit" label="table.field.asnOrderItemLog.purUnit" /> + <NumberField source="qty" label="table.field.asnOrderItemLog.qty" /> + <TextField source="splrCode" label="table.field.asnOrderItemLog.splrCode" /> + <TextField source="splrBatch" label="table.field.asnOrderItemLog.splrBatch" /> + <TextField source="splrName" label="table.field.asnOrderItemLog.splrName" /> + <TextField source="qrcode" label="table.field.asnOrderItemLog.qrcode" /> + <TextField source="trackCode" label="table.field.asnOrderItemLog.trackCode" /> + <TextField source="packName" label="table.field.asnOrderItemLog.packName" /> + <TextField source="ntyStatus$" label="table.field.asnOrderItemLog.ntyStatus" sortable={false} /> + <TextField source="updateBy$" label="common.field.updateBy" /> + <TextField source="createBy$" label="common.field.createBy" /> + <DateField source="createTime" label="common.field.createTime" showTime /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + </StyledDatagrid> + </List> + <PageDrawer + title='AsnOrderItemLog Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box> + ) +} + +export default AsnOrderItemLogList; diff --git a/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogCreate.jsx b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogCreate.jsx new file mode 100644 index 0000000..4598f98 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogCreate.jsx @@ -0,0 +1,195 @@ +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 AsnOrderLogCreate = (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.asnOrderLog.code" + source="code" + parse={v => v} + autoFocus + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrderLog.poCode" + source="poCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrderLog.poId" + source="poId" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrderLog.type" + source="type" + parse={v => v} + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrderLog.wkType" + source="wkType" + parse={v => v} + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrderLog.anfme" + source="anfme" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrderLog.qty" + source="qty" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.asnOrderLog.logisNo" + source="logisNo" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <DateInput + label="table.field.asnOrderLog.arrTime" + source="arrTime" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <SelectInput + label="table.field.asnOrderLog.rleStatus" + source="rleStatus" + choices={[ + { id: 0, name: ' 姝e父' }, + { id: 1, name: ' 宸查噴鏀�' }, + ]} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <SelectInput + label="table.field.asnOrderLog.ntyStatus" + source="ntyStatus" + choices={[ + { id: 0, name: ' 鏈笂鎶�' }, + { id: 1, name: ' 宸蹭笂鎶�' }, + { id: 2, name: ' 閮ㄥ垎涓婃姤' }, + ]} + /> + </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 AsnOrderLogCreate; diff --git a/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogEdit.jsx b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogEdit.jsx new file mode 100644 index 0000000..c9a73e8 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogEdit.jsx @@ -0,0 +1,144 @@ +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, Card } from '@mui/material'; +import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting'; +import EditBaseAside from "../../components/EditBaseAside"; +import CustomerTopToolBar from "../../components/EditTopToolBar"; +import AsnOrderItemLogList from "./AsnOrderItemLogList" +const FormToolbar = () => { + return ( + <Toolbar sx={{ justifyContent: 'end' }}> + <SaveButton /> + </Toolbar> + ) +} + +const AsnOrderLogEdit = () => { + 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={24} md={12}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.main')} + </Typography> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.asnOrderLog.code" + source="code" + parse={v => v} + readOnly + /> + <TextInput + label="table.field.asnOrderLog.poCode" + source="poCode" + readOnly + parse={v => v} + /> + <NumberInput + label="table.field.asnOrderLog.poId" + readOnly + source="poId" + /> + <TextInput + label="table.field.asnOrderLog.type" + source="type" + readOnly + parse={v => v} + validate={required()} + /> + <TextInput + label="table.field.asnOrderLog.wkType" + source="wkType" + readOnly + parse={v => v} + validate={required()} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.asnOrderLog.anfme" + source="anfme" + readOnly + validate={required()} + /> + <NumberInput + label="table.field.asnOrderLog.qty" + source="qty" + readOnly + validate={required()} + /> + <TextInput + label="table.field.asnOrderLog.logisNo" + source="logisNo" + readOnly + parse={v => v} + /> + <DateInput + label="table.field.asnOrderLog.arrTime" + readOnly + source="arrTime" + /> + <SelectInput + label="table.field.asnOrderLog.ntyStatus" + source="ntyStatus" + readOnly + choices={[ + { id: 0, name: ' 鏈笂鎶�' }, + { id: 1, name: ' 宸蹭笂鎶�' }, + { id: 2, name: ' 閮ㄥ垎涓婃姤' }, + ]} + validate={required()} + /> + </Stack> + </Grid> + </Grid> + </SimpleForm> + </Edit > + <Grid item xs={24} md={16} sx={{ marginTop: '1em' }}> + <Typography variant="h6" gutterBottom > + {translate('common.edit.title.common')} + </Typography> + </Grid> + <AsnOrderItemLogList /> + </> + ) +} + +export default AsnOrderLogEdit; diff --git a/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogList.jsx b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogList.jsx new file mode 100644 index 0000000..3cb07de --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogList.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 AsnOrderLogCreate from "./AsnOrderLogCreate"; +import AsnOrderLogPanel from "./AsnOrderLogPanel"; +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.asnOrderLog.code" />, + <TextInput source="poCode" label="table.field.asnOrderLog.poCode" />, + <NumberInput source="poId" label="table.field.asnOrderLog.poId" />, + <TextInput source="type" label="table.field.asnOrderLog.type" />, + <TextInput source="wkType" label="table.field.asnOrderLog.wkType" />, + <NumberInput source="anfme" label="table.field.asnOrderLog.anfme" />, + <NumberInput source="qty" label="table.field.asnOrderLog.qty" />, + <TextInput source="logisNo" label="table.field.asnOrderLog.logisNo" />, + <DateInput source="arrTime" label="table.field.asnOrderLog.arrTime" />, + <SelectInput source="rleStatus" label="table.field.asnOrderLog.rleStatus" + choices={[ + { id: 0, name: ' 姝e父' }, + { id: 1, name: ' 宸查噴鏀�' }, + ]} + />, + <SelectInput source="ntyStatus" label="table.field.asnOrderLog.ntyStatus" + choices={[ + { id: 0, name: ' 鏈笂鎶�' }, + { id: 1, name: ' 宸蹭笂鎶�' }, + { id: 2, name: ' 閮ㄥ垎涓婃姤' }, + ]} + />, + + <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 AsnOrderLogList = () => { + const translate = useTranslate(); + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + + 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.asnOrderLog"} + empty={<EmptyData onClick={() => { setCreateDialog(true) }} />} + filters={filters} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */} + <SelectColumnsButton preferenceKey='asnOrderLog' /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='asnOrderLog' + bulkActionButtons={false} + rowClick={'edit'} + expand={false} + expandSingle={true} + omit={['id', 'createTime', 'createBy', 'memo', 'rleStatus']} + > + <NumberField source="id" /> + <TextField source="code" label="table.field.asnOrderLog.code" /> + <TextField source="poCode" label="table.field.asnOrderLog.poCode" /> + <NumberField source="poId" label="table.field.asnOrderLog.poId" /> + <TextField source="type$" label="table.field.asnOrderLog.type" /> + <TextField source="wkType$" label="table.field.asnOrderLog.wkType" /> + <NumberField source="anfme" label="table.field.asnOrderLog.anfme" /> + <NumberField source="qty" label="table.field.asnOrderLog.qty" /> + <TextField source="logisNo" label="table.field.asnOrderLog.logisNo" /> + <DateField source="arrTime" label="table.field.asnOrderLog.arrTime" showTime /> + <TextField source="rleStatus$" label="table.field.asnOrderLog.rleStatus" sortable={false} /> + <TextField source="ntyStatus$" label="table.field.asnOrderLog.ntyStatus" sortable={false} /> + <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} /> + </StyledDatagrid> + </List> + <AsnOrderLogCreate + open={createDialog} + setOpen={setCreateDialog} + /> + <PageDrawer + title='AsnOrderLog Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box> + ) +} + +export default AsnOrderLogList; diff --git a/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogPanel.jsx b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogPanel.jsx new file mode 100644 index 0000000..a335119 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrderLog/AsnOrderLogPanel.jsx @@ -0,0 +1,143 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { Box, Card, CardContent, Grid, Typography, Button, TextField, Tooltip, Paper, TableContainer, Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material'; +import { + useTranslate, + useRecordContext, + useNotify, + useRefresh, + useListContext, +} 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'; +import debounce from 'lodash/debounce'; +import { DataGrid } from '@mui/x-data-grid'; + +const AsnOrderLogPanel = () => { + const record = useRecordContext(); + if (!record) return null; + const translate = useTranslate(); + const notify = useNotify(); + const [rows, setRows] = useState([]); + const [maktx, setMaktx] = useState(''); + const asnId = record.asnId; + + useEffect(() => { + debouncedHttp({ maktx }); + }, [asnId, maktx]); + + + const http = async (parmas) => { + const res = await request.post('/asnOrderItemLog/page', { ...parmas, asnId }); + if (res?.data?.code === 200) { + setRows(res.data.data.records) + } else { + notify(res.data.msg); + } + } + + const debouncedHttp = useMemo(() => debounce(http, 300), []); + + const columns = [ + { + field: 'asnId', + headerName: translate('table.field.asnOrderItemLog.asnId') + }, + { + field: 'asnCode', + headerName: translate('table.field.asnOrderItemLog.asnCode') + }, + { + field: 'poDetlId', + headerName: translate('table.field.asnOrderItemLog.poDetlId') + }, + { + field: 'poCode', + headerName: translate('table.field.asnOrderItemLog.poDetlCode') + }, + { + field: 'matnrId', + headerName: translate('table.field.asnOrderItemLog.matnrId') + }, + { + field: 'matnrCode', + headerName: translate('table.field.asnOrderItemLog.matnrCode') + }, + { + field: 'maktx', + headerName: translate('table.field.asnOrderItemLog.maktx') + }, + { + field: 'anfme', + headerName: translate('table.field.asnOrderItemLog.purQty') + }, + { + field: 'purUnit', + headerName: translate('table.field.asnOrderItemLog.purUnit') + }, + { + field: 'qty', + headerName: translate('table.field.asnOrderItemLog.qty') + }, + { + field: 'splrBatch', + headerName: translate('table.field.asnOrderItem.splrBatch') + }, + { + field: 'splrCode', + headerName: translate('table.field.asnOrderItemLog.splrCode') + }, + { + field: 'splrName', + headerName: translate('table.field.asnOrderItemLog.splrName') + }, + { + field: 'trackCode', + headerName: translate('table.field.asnOrderItemLog.barcode') + }, + { + field: 'prodTime', + headerName: translate('table.field.asnOrderItem.prodTime') + }, + { + field: 'packName', + headerName: translate('table.field.asnOrderItemLog.packName') + }, + { + field: 'ntyStatus$', + headerName: translate('table.field.asnOrderItemLog.ntyStatus') + }] + + const maktxChange = (value) => { + setMaktx(value) + } + + return ( + <Box sx={{ + position: 'relative', + padding: '5px 10px' + }}> + + <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px', alignItems: 'center' }}> + <TextField value={maktx} onChange={(e) => maktxChange(e.target.value)} label="鎼滅储鐗╂枡" variant="outlined" sx={{ width: '300px' }} size="small" /> + + <div style={{ display: 'flex', gap: '10px' }}> + </div> + </div> + + + <DataGrid + size="small" + rows={rows} + columns={columns} + disableRowSelectionOnClick + disableColumnMenu={true} + disableColumnSorting + disableMultipleColumnsSorting + /> + </Box > + ); +}; + +export default AsnOrderLogPanel; diff --git a/rsf-admin/src/page/orders/asnOrderLog/index.jsx b/rsf-admin/src/page/orders/asnOrderLog/index.jsx new file mode 100644 index 0000000..e292c57 --- /dev/null +++ b/rsf-admin/src/page/orders/asnOrderLog/index.jsx @@ -0,0 +1,18 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + ListGuesser, + EditGuesser, + ShowGuesser, +} from "react-admin"; + +import AsnOrderLogList from "./AsnOrderLogList"; +import AsnOrderLogEdit from "./AsnOrderLogEdit"; + +export default { + list: AsnOrderLogList, + edit: AsnOrderLogEdit, + show: ShowGuesser, + recordRepresentation: (record) => { + return `${record.id}` + } +}; diff --git a/rsf-admin/src/page/qlyInspect/QlyIsptItemCreate.jsx b/rsf-admin/src/page/qlyInspect/QlyIsptItemCreate.jsx new file mode 100644 index 0000000..230af01 --- /dev/null +++ b/rsf-admin/src/page/qlyInspect/QlyIsptItemCreate.jsx @@ -0,0 +1,182 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + CreateBase, + useTranslate, + TextInput, + NumberInput, + SaveButton, + Toolbar, + useNotify, + Form, +} 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 QlyIsptItemCreate = (props) => { + const { open, setOpen, record } = 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={{}} + resource="qlyIsptItem" + 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={2}> + <NumberInput + label="table.field.qlyIsptItem.ispectId" + source="ispectId" + readOnly + defaultValue={record?.id} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.qlyIsptItem.matnrCode" + source="matnrCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.qlyIsptItem.maktx" + source="maktx" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.qlyIsptItem.label" + source="label" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.qlyIsptItem.splrName" + source="splrName" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.qlyIsptItem.splrBatch" + source="splrBatch" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.qlyIsptItem.stockBatch" + source="stockBatch" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.qlyIsptItem.rcptQty" + source="rcptQty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.qlyIsptItem.dlyQty" + source="dlyQty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.qlyIsptItem.disQty" + source="disQty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.qlyIsptItem.safeQty" + source="safeQty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.qlyIsptItem.picPath" + source="picPath" + 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 QlyIsptItemCreate; diff --git a/rsf-admin/src/page/qlyInspect/QlyIsptItemEdit.jsx b/rsf-admin/src/page/qlyInspect/QlyIsptItemEdit.jsx new file mode 100644 index 0000000..43944ab --- /dev/null +++ b/rsf-admin/src/page/qlyInspect/QlyIsptItemEdit.jsx @@ -0,0 +1,162 @@ +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"; + +const FormToolbar = () => { + const { getValues } = useFormContext(); + + return ( + <Toolbar sx={{ justifyContent: 'space-between' }}> + <SaveButton /> + <DeleteButton mutationMode="optimistic" /> + </Toolbar> + ) +} + +const QlyIsptItemEdit = () => { + 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={12} md={8}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.main')} + </Typography> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.qlyIsptItem.ispectId" + source="ispectId" + autoFocus + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.qlyIsptItem.matnrCode" + source="matnrCode" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.qlyIsptItem.maktx" + source="maktx" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.qlyIsptItem.label" + source="label" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.qlyIsptItem.splrName" + source="splrName" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.qlyIsptItem.splrBatch" + source="splrBatch" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.qlyIsptItem.stockBatch" + source="stockBatch" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.qlyIsptItem.rcptQty" + source="rcptQty" + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.qlyIsptItem.dlyQty" + source="dlyQty" + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.qlyIsptItem.disQty" + source="disQty" + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.qlyIsptItem.safeQty" + source="safeQty" + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.qlyIsptItem.picPath" + source="picPath" + 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> + </SimpleForm> + </Edit > + ) +} + +export default QlyIsptItemEdit; diff --git a/rsf-admin/src/page/qlyInspect/QlyIsptItemList.jsx b/rsf-admin/src/page/qlyInspect/QlyIsptItemList.jsx new file mode 100644 index 0000000..9721c0e --- /dev/null +++ b/rsf-admin/src/page/qlyInspect/QlyIsptItemList.jsx @@ -0,0 +1,167 @@ +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, + useGetOne, + useGetRecordId, +} from 'react-admin'; +import { Box, Typography, Card, Stack } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import QlyIsptItemCreate from "./QlyIsptItemCreate"; +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_ITEM_PAGE_SIZE } from '@/config/setting'; + +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="ispectId" label="table.field.qlyIsptItem.ispectId" />, + <TextInput source="matnrCode" label="table.field.qlyIsptItem.matnrCode" />, + <TextInput source="maktx" label="table.field.qlyIsptItem.maktx" />, + <TextInput source="label" label="table.field.qlyIsptItem.label" />, + <TextInput source="splrName" label="table.field.qlyIsptItem.splrName" />, + <TextInput source="splrBatch" label="table.field.qlyIsptItem.splrBatch" />, + <TextInput source="stockBatch" label="table.field.qlyIsptItem.stockBatch" />, + <NumberInput source="rcptQty" label="table.field.qlyIsptItem.rcptQty" />, + <NumberInput source="dlyQty" label="table.field.qlyIsptItem.dlyQty" />, + <NumberInput source="disQty" label="table.field.qlyIsptItem.disQty" />, + <NumberInput source="safeQty" label="table.field.qlyIsptItem.safeQty" />, + <TextInput source="picPath" label="table.field.qlyIsptItem.picPath" />, + + <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 QlyIsptItemList = () => { + const translate = useTranslate(); + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const isptId = useGetRecordId(); + const { data: dicts, isPending, error } = useGetOne('qlyInspect', { id: isptId }); + if (dicts == null) {return} + + return ( + <Box display="flex"> + <List + resource="qlyIsptItem" + filter={{ispectId: isptId}} + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + }} + title={"menu.qlyIsptItem"} + empty={false} + filters={filters} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */} + <SelectColumnsButton preferenceKey='qlyIsptItem' /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_ITEM_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='qlyIsptItem' + bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />} + rowClick={false} + omit={['id', 'createTime', 'createBy', 'memo', 'ispectId']} + > + <NumberField source="id" /> + <NumberField source="ispectId" label="table.field.qlyIsptItem.ispectId" /> + <TextField source="matnrCode" label="table.field.qlyIsptItem.matnrCode" /> + <TextField source="maktx" label="table.field.qlyIsptItem.maktx" /> + <TextField source="label" label="table.field.qlyIsptItem.label" /> + <TextField source="splrName" label="table.field.qlyIsptItem.splrName" /> + <TextField source="splrBatch" label="table.field.qlyIsptItem.splrBatch" /> + <TextField source="stockBatch" label="table.field.qlyIsptItem.stockBatch" /> + <NumberField source="rcptQty" label="table.field.qlyIsptItem.rcptQty" /> + <NumberField source="isptResult$" label="table.field.qlyIsptItem.isptResult" /> + <NumberField source="dlyQty" label="table.field.qlyIsptItem.dlyQty" /> + <NumberField source="disQty" label="table.field.qlyIsptItem.disQty" /> + <NumberField source="safeQty" label="table.field.qlyIsptItem.safeQty" /> + <TextField source="picPath" label="table.field.qlyIsptItem.picPath" /> + <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} /> + + </StyledDatagrid> + </List> + <QlyIsptItemCreate + open={createDialog} + record={dicts} + setOpen={setCreateDialog} + /> + <PageDrawer + title='QlyIsptItem Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box> + ) +} + +export default QlyIsptItemList; diff --git a/rsf-admin/src/page/waitPakin/WaitPakinItemCreate.jsx b/rsf-admin/src/page/waitPakin/WaitPakinItemCreate.jsx new file mode 100644 index 0000000..208cedd --- /dev/null +++ b/rsf-admin/src/page/waitPakin/WaitPakinItemCreate.jsx @@ -0,0 +1,176 @@ +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 WaitPakinItemCreate = (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}> + <NumberInput + label="table.field.waitPakinItem.pakinId" + source="pakinId" + autoFocus + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.waitPakinItem.maktx" + source="maktx" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.waitPakinItem.matnrId" + source="matnrId" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.waitPakinItem.matnrCode" + source="matnrCode" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.waitPakinItem.anfme" + source="anfme" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.waitPakinItem.workQty" + source="workQty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.waitPakinItem.unit" + source="unit" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.waitPakinItem.fieldsIndex" + source="fieldsIndex" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.waitPakinItem.qty" + source="qty" + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.waitPakinItem.batch" + source="batch" + 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 WaitPakinItemCreate; diff --git a/rsf-admin/src/page/waitPakin/WaitPakinItemEdit.jsx b/rsf-admin/src/page/waitPakin/WaitPakinItemEdit.jsx new file mode 100644 index 0000000..7e1238a --- /dev/null +++ b/rsf-admin/src/page/waitPakin/WaitPakinItemEdit.jsx @@ -0,0 +1,148 @@ +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"; + +const FormToolbar = () => { + const { getValues } = useFormContext(); + + return ( + <Toolbar sx={{ justifyContent: 'space-between' }}> + <SaveButton /> + <DeleteButton mutationMode="optimistic" /> + </Toolbar> + ) +} + +const WaitPakinItemEdit = () => { + 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={12} md={8}> + <Typography variant="h6" gutterBottom> + {translate('common.edit.title.main')} + </Typography> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.waitPakinItem.pakinId" + source="pakinId" + autoFocus + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.waitPakinItem.maktx" + source="maktx" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.waitPakinItem.matnrId" + source="matnrId" + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.waitPakinItem.matnrCode" + source="matnrCode" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.waitPakinItem.anfme" + source="anfme" + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.waitPakinItem.workQty" + source="workQty" + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.waitPakinItem.unit" + source="unit" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.waitPakinItem.fieldsIndex" + source="fieldsIndex" + parse={v => v} + /> + </Stack> + <Stack direction='row' gap={2}> + <NumberInput + label="table.field.waitPakinItem.qty" + source="qty" + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.waitPakinItem.batch" + source="batch" + 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> + </SimpleForm> + </Edit > + ) +} + +export default WaitPakinItemEdit; diff --git a/rsf-admin/src/page/waitPakin/WaitPakinItemList.jsx b/rsf-admin/src/page/waitPakin/WaitPakinItemList.jsx new file mode 100644 index 0000000..6cbc531 --- /dev/null +++ b/rsf-admin/src/page/waitPakin/WaitPakinItemList.jsx @@ -0,0 +1,166 @@ +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 WaitPakinItemCreate from "./WaitPakinItemCreate"; +import WaitPakinItemPanel from "./WaitPakinItemPanel"; +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 />, + + <NumberInput source="pakinId" label="table.field.waitPakinItem.pakinId" />, + <TextInput source="maktx" label="table.field.waitPakinItem.maktx" />, + <NumberInput source="matnrId" label="table.field.waitPakinItem.matnrId" />, + <TextInput source="matnrCode" label="table.field.waitPakinItem.matnrCode" />, + <NumberInput source="anfme" label="table.field.waitPakinItem.anfme" />, + <NumberInput source="workQty" label="table.field.waitPakinItem.workQty" />, + <TextInput source="unit" label="table.field.waitPakinItem.unit" />, + <TextInput source="fieldsIndex" label="table.field.waitPakinItem.fieldsIndex" />, + <NumberInput source="qty" label="table.field.waitPakinItem.qty" />, + <TextInput source="batch" label="table.field.waitPakinItem.batch" />, + + <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 WaitPakinItemList = () => { + const translate = useTranslate(); + + const [createDialog, setCreateDialog] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + + 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.waitPakinItem"} + empty={<EmptyData onClick={() => { setCreateDialog(true) }} />} + filters={filters} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */} + <SelectColumnsButton preferenceKey='waitPakinItem' /> + <MyExportButton /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='waitPakinItem' + bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />} + rowClick={(id, resource, record) => false} + omit={['id', 'createTime', 'createBy', 'memo']} + > + <NumberField source="id" /> + <NumberField source="pakinId" label="table.field.waitPakinItem.pakinId" /> + <TextField source="maktx" label="table.field.waitPakinItem.maktx" /> + <NumberField source="matnrId" label="table.field.waitPakinItem.matnrId" /> + <TextField source="matnrCode" label="table.field.waitPakinItem.matnrCode" /> + <NumberField source="anfme" label="table.field.waitPakinItem.anfme" /> + <NumberField source="workQty" label="table.field.waitPakinItem.workQty" /> + <TextField source="unit" label="table.field.waitPakinItem.unit" /> + <TextField source="fieldsIndex" label="table.field.waitPakinItem.fieldsIndex" /> + <NumberField source="qty" label="table.field.waitPakinItem.qty" /> + <TextField source="batch" label="table.field.waitPakinItem.batch" /> + + <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}> + <TextField source="nickname" /> + </ReferenceField> + <DateField source="updateTime" label="common.field.updateTime" showTime /> + <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}> + <TextField source="nickname" /> + </ReferenceField> + <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> + <WaitPakinItemCreate + open={createDialog} + setOpen={setCreateDialog} + /> + <PageDrawer + title='WaitPakinItem Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box> + ) +} + +export default WaitPakinItemList; -- Gitblit v1.9.1