From c73bfe563e19aee0fcf2465a0982bb307cc4c249 Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期五, 11 七月 2025 17:09:44 +0800 Subject: [PATCH] no message --- rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java | 6 rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java | 3 rsf-admin/src/page/orders/check/CheckOrderList.jsx | 313 ++++++ rsf-admin/src/page/orders/check/CheckOrderCreate.jsx | 221 ++++ rsf-admin/src/page/orders/check/OutOrderPreview.jsx | 141 ++ rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx | 127 ++ rsf-admin/src/page/orders/check/CheckOrderItemCreate.jsx | 200 ++++ rsf-admin/src/page/orders/check/SelectMatnrModal.jsx | 585 +++++++++++ rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckOrderController.java | 125 ++ rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/CheckOrderMapper.java | 12 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/CheckOrderService.java | 8 rsf-admin/src/page/orders/check/index.jsx | 18 rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java | 12 rsf-admin/src/page/orders/check/CheckOrderItemList.jsx | 185 +++ rsf-admin/src/i18n/zh.js | 17 rsf-admin/src/page/orders/check/CheckOrderEdit.jsx | 138 ++ rsf-admin/src/i18n/en.js | 15 rsf-admin/src/page/ResourceContent.js | 3 rsf-admin/src/page/orders/check/OutOrderModal.jsx | 279 +++++ rsf-admin/src/page/orders/check/OutStockPublic.jsx | 480 +++++++++ rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java | 1 rsf-server/src/main/resources/application-dev.yml | 2 22 files changed, 2,859 insertions(+), 32 deletions(-) diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js index 8dcd005..f78e81e 100644 --- a/rsf-admin/src/i18n/en.js +++ b/rsf-admin/src/i18n/en.js @@ -606,6 +606,21 @@ ntyStatus: "Notify", exceStatus: 'bill status' }, + checkOrder: { + code: "Check Code", + poCode: "Po Code", + poId: "Po Id", + type: "Type", + wkType: "Work Type", + anfme: "Anfme", + workQty: 'Work Qty', + qty: "Qty", + logisNo: "Logis No", + arrTime: "arrived Time", + rleStatus: "閲婃斁鐘舵��", + ntyStatus: "涓婃姤鐘舵��", + exceStatus: '鍗曟嵁鐘舵��' + }, outStockItem: { asnId: "ID", asnCode: "Out Code", diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index 18807a3..331427a 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/rsf-admin/src/i18n/zh.js @@ -213,7 +213,7 @@ checkOutBound: '鐩樼偣鍑哄簱', stockTransfer: '搴撲綅杞Щ', waveRule: '娉㈡绛栫暐', - + checkOrder: '鐩樼偣鍗�', }, table: { field: { @@ -631,6 +631,21 @@ ntyStatus: "涓婃姤鐘舵��", exceStatus: '鍗曟嵁鐘舵��' }, + checkOrder: { + code: "鐩樼偣鍗曞彿", + poCode: "DO鍗曞彿", + poId: "DO鏍囪瘑", + type: "绫诲瀷", + wkType: "涓氬姟绫诲瀷", + anfme: "鏁伴噺", + workQty: '鎵ц鏁�', + qty: "瀹屾垚鏁�", + logisNo: "鐗╂祦鍗曞彿", + arrTime: "棰勮鍒拌揪鏃堕棿", + rleStatus: "閲婃斁鐘舵��", + ntyStatus: "涓婃姤鐘舵��", + exceStatus: '鍗曟嵁鐘舵��' + }, asnOrderItem: { asnId: "涓诲崟鏍囪瘑", asnCode: "鍗曞彿", diff --git a/rsf-admin/src/page/ResourceContent.js b/rsf-admin/src/page/ResourceContent.js index 34a1747..6ff29cf 100644 --- a/rsf-admin/src/page/ResourceContent.js +++ b/rsf-admin/src/page/ResourceContent.js @@ -53,6 +53,7 @@ import checkOutBound from "./work/checkOutBound"; import stockTransfer from "./work/stockTransfer"; import waveRule from './waveRule'; +import check from './orders/check'; const ResourceContent = (node) => { switch (node.component) { @@ -154,6 +155,8 @@ return stockTransfer; case 'waveRule': return waveRule; + case 'check': + return check; default: return { list: ListGuesser, diff --git a/rsf-admin/src/page/orders/check/CheckOrderCreate.jsx b/rsf-admin/src/page/orders/check/CheckOrderCreate.jsx new file mode 100644 index 0000000..40fba47 --- /dev/null +++ b/rsf-admin/src/page/orders/check/CheckOrderCreate.jsx @@ -0,0 +1,221 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + CreateBase, + useTranslate, + TextInput, + NumberInput, + BooleanInput, + TextField, + WrapperField, + NumberField, + DateInput, + TopToolbar, + SelectColumnsButton, + DatagridConfigurable, + SaveButton, + SelectInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + Toolbar, + required, + useDataProvider, + useNotify, + Form, + useCreateController, + useGetList, + useList, + ListContextProvider, + useListContext, + Button, + useRecordContext, +} from 'react-admin'; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Stack, + Grid, + Box, +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import { styled } from '@mui/material/styles'; +import StatusSelectInput from "../../components/StatusSelectInput"; +import OutOrderItemList from "./OutOrderItemList"; +import MemoInput from "../../components/MemoInput"; +import AddIcon from '@mui/icons-material/Add'; +import SelectMatnrModal from "./SelectMatnrModal"; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 200 + }, +})); + + +const OutOrderCreate = (props) => { + const { open, setOpen, record } = props; + 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')) || []; + const translate = useTranslate(); + const notify = useNotify(); + const [drawerVal, setDrawerVal] = useState(false); + const [matCreate, setMatCreate] = useState(false); + + 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 } }); + }; + + const { data, total, isPending, error, refetch, meta } = useGetList('/wave/locs/preview', { filter: { waveId: record?.id } }); + const listContext = useList({ data, isPending }); + + 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="xl" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' + > + <Form + resource="outStock" + > + <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> + <Grid item xs={12} display="flex" gap={1}> + <TextInput + label="table.field.asnOrder.poCode" + source="poCode" + parse={v => v} + /> + <NumberInput + label="table.field.asnOrder.poId" + source="poId" + /> + {/* <AutocompleteInput + choices={dicts} + optionText="label" + label="table.field.asnOrder.type" + source="type" + optionValue="value" + validate={required()} + parse={v => v} + /> */} + <AutocompleteInput + choices={business} + optionText="label" + label="table.field.asnOrder.wkType" + source="wkType" + optionValue="value" + validate={required()} + parse={v => v} + /> + <NumberInput + label="table.field.asnOrder.anfme" + source="anfme" + validate={required()} + /> + + </Grid> + <Grid item xs={12} display="flex" gap={1}> + <NumberInput + label="table.field.asnOrder.qty" + source="qty" + /> + <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: ' 宸查噴鏀�' }, + ]} + /> + </Grid> + </Grid> + <SelectMatnrModal open={matCreate} setOpen={setMatCreate} /> + <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> + <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > + <AddOutOrderButton setMatCreate={setMatCreate} /> + <SaveButton /> + </Toolbar> + </DialogActions> + <Box> + + </Box> + </> + </DialogContent> + </Form> + </Dialog> + </CreateBase> + </> + ) +} + +export default OutOrderCreate; + + +const AddOutOrderButton = (setMatCreate) => { + const record = useRecordContext(); + const addMats = (event) => { + event.stopPropagation(); + setMatCreate(true) + } + + return ( + <Button label={"common.action.newAddMats"} onClick={addMats} variant="contained" sx={{ padding: '0.6em', marginRight: '1em' }}> + <AddIcon /> + </Button> + ); +} diff --git a/rsf-admin/src/page/orders/check/CheckOrderEdit.jsx b/rsf-admin/src/page/orders/check/CheckOrderEdit.jsx new file mode 100644 index 0000000..0844f23 --- /dev/null +++ b/rsf-admin/src/page/orders/check/CheckOrderEdit.jsx @@ -0,0 +1,138 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + Edit, + SimpleForm, + useTranslate, + TextInput, + DateInput, + SelectInput, + AutocompleteInput, + SaveButton, + Toolbar, + required, + DeleteButton, +} from 'react-admin'; +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 CheckOrderItemList from "./CheckOrderItemList"; + + +const CheckOrderEdit = () => { + 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={false} + mode="onTouched" + defaultValues={{}} + > + <Grid container width={{ xs: '100%', xl: '100%' }} rowSpacing={3} columnSpacing={3} + sx={{ + "& .MuiFormLabel-root.MuiInputLabel-root.Mui-disabled": { + bgcolor: 'white', + WebkitTextFillColor: "rgba(0, 0, 0)" + }, + + "& .MuiInputBase-input.MuiFilledInput-input.Mui-disabled": { + bgcolor: 'white', + WebkitTextFillColor: "rgba(0, 0, 0)" + }, + "& .MuiFilledInput-root.MuiInputBase-sizeSmall": { + bgcolor: 'white', + } + }} + > + <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.outStock.code" + source="code" + readOnly + parse={v => v} + /> + <TextInput + label="table.field.outStock.poCode" + source="poCode" + readOnly + parse={v => v} + /> + <AutocompleteInput + choices={dicts} + optionText="label" + label="table.field.outStock.type" + source="type" + optionValue="value" + parse={v => v} + readOnly + /> + <AutocompleteInput + choices={business} + optionText="label" + label="table.field.outStock.wkType" + source="wkType" + optionValue="value" + parse={v => v} + readOnly + /> + </Stack> + <Stack direction='row' gap={2}> + <TextInput + label="table.field.outStock.logisNo" + source="logisNo" + readOnly + parse={v => v} + /> + <TextInput + label="table.field.outStock.anfme" + source="anfme" + readOnly + parse={v => v} + /> + <TextInput + label="table.field.outStock.qty" + source="qty" + readOnly + parse={v => v} + /> + <DateInput + label="table.field.outStock.arrTime" + source="arrTime" + readOnly + /> + <SelectInput + label="table.field.outStock.rleStatus" + source="rleStatus" + readOnly + choices={[ + { id: 0, name: ' 姝e父' }, + { id: 1, name: ' 宸查噴鏀�' }, + ]} + validate={required()} + /> + </Stack> + </Grid> + </Grid> + </SimpleForm> + </Edit > + <CheckOrderItemList /> + </> + ) +} + +export default CheckOrderEdit; diff --git a/rsf-admin/src/page/orders/check/CheckOrderItemCreate.jsx b/rsf-admin/src/page/orders/check/CheckOrderItemCreate.jsx new file mode 100644 index 0000000..f77b096 --- /dev/null +++ b/rsf-admin/src/page/orders/check/CheckOrderItemCreate.jsx @@ -0,0 +1,200 @@ +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 CheckOrderItemCreate = (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="outStockItem" + 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.outStockItem.asnId" + source="asnId" + readOnly + hidden + defaultValue={record?.id} + /> + <TextInput + label="table.field.outStockItem.asnCode" + source="asnCode" + readOnly + defaultValue={record?.code} + parse={v => v} + /> + <TextInput + label="table.field.outStockItem.poDetlId" + source="poDetlId" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.outStockItem.matnrId" + source="matnrId" + parse={v => v} + /> + <TextInput + label="table.field.outStockItem.maktx" + source="maktx" + parse={v => v} + /> + <NumberInput + label="table.field.outStockItem.anfme" + source="anfme" + validate={required()} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.outStockItem.stockUnit" + source="stockUnit" + parse={v => v} + /> + <NumberInput + label="table.field.outStockItem.purQty" + source="purQty" + validate={required()} + /> + <TextInput + label="table.field.outStockItem.purUnit" + source="purUnit" + parse={v => v} + /> + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <NumberInput + label="table.field.outStockItem.qty" + source="qty" + /> + <TextInput + label="table.field.outStockItem.splrCode" + source="splrCode" + parse={v => v} + /> + <TextInput + label="table.field.outStockItem.splrName" + source="splrName" + parse={v => v} + /> + + </Grid> + <Grid item xs={6} display="flex" gap={1}> + <TextInput + label="table.field.outStockItem.qrcode" + source="qrcode" + parse={v => v} + /> + <TextInput + label="table.field.outStockItem.barcode" + source="barcode" + parse={v => v} + /> + <TextInput + label="table.field.outStockItem.packName" + source="packName" + parse={v => v} + /> + </Grid> + + <Grid item xs={4} display="flex" gap={1}> + <StatusSelectInput /> + </Grid> + <Grid item xs={4} display="flex" gap={1}> + <Stack direction="column" spacing={1}> + <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 CheckOrderItemCreate; diff --git a/rsf-admin/src/page/orders/check/CheckOrderItemList.jsx b/rsf-admin/src/page/orders/check/CheckOrderItemList.jsx new file mode 100644 index 0000000..095f269 --- /dev/null +++ b/rsf-admin/src/page/orders/check/CheckOrderItemList.jsx @@ -0,0 +1,185 @@ +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 PageDrawer from "../../components/PageDrawer"; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, 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="asnId" label="table.field.outStockItem.asnId" />, + <TextInput source="asnCode" label="table.field.outStockItem.asnCode" alwaysOn />, + <TextInput source="poDetlId" label="table.field.outStockItem.poDetlId" />, + <TextInput source="matnrId" label="table.field.outStockItem.matnrId" />, + <TextInput source="maktx" label="table.field.outStockItem.maktx" alwaysOn />, + <TextInput source="matnrCode" label="table.field.outStockItem.matnrCode" alwaysOn />, + <NumberInput source="anfme" label="table.field.outStockItem.anfme" />, + <TextInput source="stockUnit" label="table.field.outStockItem.stockUnit" />, + <NumberInput source="purQty" label="table.field.outStockItem.purQty" />, + <TextInput source="purUnit" label="table.field.outStockItem.purUnit" />, + <NumberInput source="qty" label="table.field.outStockItem.qty" />, + <TextInput source="splrCode" label="table.field.outStockItem.splrCode" />, + <TextInput source="splrName" label="table.field.outStockItem.splrName" />, + <TextInput source="qrcode" label="table.field.outStockItem.qrcode" />, + <TextInput source="trackCode" label="table.field.outStockItem.barcode" />, + <TextInput source="packName" label="table.field.outStockItem.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 OutOrderItemList = () => { + 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('outStock', { id: asnId }); + + return ( + <> + <Box display="flex"> + <List + resource="outStockItem" + storeKey='outStockItem' + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + }} + title={"menu.outStockItem"} + empty={false} + filter={{ asnId: asnId, deleted: 0 }} + filters={filters} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + <SelectColumnsButton preferenceKey='outStockItem' /> + </TopToolbar> + )} + perPage={DEFAULT_ITEM_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='outStockItem' + bulkActionButtons={false} + rowClick={false} + omit={['id', 'createTime', 'createBy', 'memo', 'poDetlId', 'purQty', 'purUnit', 'trackCode', 'packName', 'qrcode', 'splrName', 'matnrId', 'asnId']} + > + <NumberField source="id" /> + <NumberField source="asnId" label="table.field.outStockItem.asnId" /> + <TextField source="asnCode" label="table.field.outStockItem.asnCode" /> + <TextField source="poCode" label="table.field.outStockItem.poCode" /> + <TextField source="poDetlId" label="table.field.outStockItem.poDetlId" /> + <TextField source="matnrId" label="table.field.outStockItem.matnrId" /> + <TextField source="matnrCode" label="table.field.outStockItem.matnrCode" /> + <TextField source="maktx" label="table.field.outStockItem.maktx" /> + <TextField source="platOrderCode" label="table.field.outStockItem.platOrderCode" /> + <NumberField source="anfme" label="table.field.outStockItem.anfme" /> + <NumberField source="purQty" label="table.field.outStockItem.purQty" /> + <NumberField source="workQty" label="table.field.outStockItem.workQty" /> + <NumberField source="qty" label="table.field.outStockItem.qty" /> + <TextField source="stockUnit" label="table.field.outStockItem.stockUnit" /> + <TextField source="splrBatch" label="table.field.outStockItem.splrBatch" /> + <TextField source="purUnit" label="table.field.outStockItem.purUnit" /> + <TextField source="splrCode" label="table.field.outStockItem.splrCode" /> + <TextField source="splrName" label="table.field.outStockItem.splrName" /> + <TextField source="qrcode" label="table.field.outStockItem.qrcode" /> + <TextField source="trackCode" label="table.field.outStockItem.barcode" /> + <TextField source="packName" label="table.field.outStockItem.packName" /> + <DateField source="updateTime" label="common.field.updateTime" showTime /> + <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}> + <TextField source="nickname" /> + </ReferenceField>, + <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 /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + </StyledDatagrid> + </List> + {/* <OutOrderItemCreate + open={createDialog} + setOpen={setCreateDialog} + record={dicts} + /> + <OutOrderItemEdit + open={editDialog} + setOpen={setEditDialog} + record={select} + /> */} + <PageDrawer + title='OutStockItem Detail' + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + </PageDrawer> + </Box> + </> + ) +} +OutOrderItemList.Context = React.createContext() + +export default OutOrderItemList; diff --git a/rsf-admin/src/page/orders/check/CheckOrderList.jsx b/rsf-admin/src/page/orders/check/CheckOrderList.jsx new file mode 100644 index 0000000..36a9b6d --- /dev/null +++ b/rsf-admin/src/page/orders/check/CheckOrderList.jsx @@ -0,0 +1,313 @@ +import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; +import { useLocation, useNavigate } from 'react-router-dom'; +import { + List, + DatagridConfigurable, + SearchInput, + TopToolbar, + Toolbar, + SelectColumnsButton, + EditButton, + FilterButton, + CreateButton, + ExportButton, + BulkDeleteButton, + useDataProvider, + WrapperField, + useRecordContext, + useTranslate, + useNotify, + useRefresh, + useListContext, + FunctionField, + TextField, + NumberField, + DateField, + BooleanField, + ReferenceField, + TextInput, + DateTimeInput, + DateInput, + SelectInput, + NumberInput, + ReferenceInput, + ReferenceArrayInput, + AutocompleteInput, + DeleteButton, + Button, + useRedirect, + useUnselectAll, + useRecordSelection, +} from 'react-admin'; +import { styled } from '@mui/material/styles'; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; +import { Box, Typography, Card, Stack, Drawer } from '@mui/material'; +import DictionarySelect from "../../components/DictionarySelect"; +import BillStatusField from '../../components/BillStatusField'; +import MyCreateButton from "../../components/MyCreateButton"; +import ConfirmButton from '../../components/ConfirmButton'; +import ImportButton from "../../components/ImportButton"; +import DetailsIcon from '@mui/icons-material/Details'; +import AddTaskIcon from '@mui/icons-material/AddTask'; +import PublicIcon from '@mui/icons-material/Public'; +import EditIcon from '@mui/icons-material/Edit'; +import AddIcon from '@mui/icons-material/Add'; +import request from '@/utils/request'; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-name': { + }, + '& .opt': { + width: 220 + }, + '& .wkType': { + width: 110 + }, + '& .status': { + width: 90 + }, +})); + +const filters = [ + <SearchInput source="condition" alwaysOn />, + <TextInput source="code" label="table.field.outStock.code" alwaysOn />, + <TextInput source="poCode" label="table.field.outStock.poCode" />, + <NumberInput source="poId" label="table.field.outStock.poId" />, + <ReferenceInput source="type" reference="dictData" filter={{ dictTypeCode: 'sys_order_type', group: '2' }} label="table.field.outStock.type" alwaysOn> + <AutocompleteInput label="table.field.outStock.type" optionValue="value" /> + </ReferenceInput>, + <ReferenceInput source="wkType" reference="dictData" filter={{ dictTypeCode: 'sys_business_type', group: '2' }} label="table.field.outStock.wkType" alwaysOn> + <AutocompleteInput label="table.field.outStock.wkType" optionValue="value" /> + </ReferenceInput>, + <NumberInput source="anfme" label="table.field.outStock.anfme" />, + <NumberInput source="qty" label="table.field.outStock.qty" />, + <TextInput source="logisNo" label="table.field.outStock.logisNo" />, + <DateInput source="arrTime" label="table.field.outStock.arrTime" />, + <SelectInput source="rleStatus" label="table.field.outStock.rleStatus" + choices={[ + { id: 0, name: ' 姝e父' }, + { id: 1, name: ' 宸查噴鏀�' }, + ]} + />, + + <TextInput label="common.field.memo" source="memo" />, + <DictionarySelect + label='table.field.outStock.exceStatus' + name="exceStatus" + dictTypeCode="sys_asn_exce_status" + alwaysOn + />, +] + +const CheckOrderList = (props) => { + const translate = useTranslate(); + const refresh = useRefresh(); + const notify = useNotify(); + + const [createDialog, setCreateDialog] = useState(false); + const [manualDialog, setManualDialog] = useState(false); + const [selectIds, setSelectIds] = useState([]); + const [preview, setPreview] = useState(false); + const [waveRule, setWaveRule] = useState(false); + const [drawerVal, setDrawerVal] = useState(false); + const [modalType, setmodalType] = useState(0); + const [select, setSelect] = useState(0); + const billReload = useRef(); + const dicts = JSON.parse(localStorage.getItem('sys_dicts'))?.filter(dict => (dict.dictTypeCode == 'sys_business_type')) || []; + + //鑾峰彇娉㈡瑙勫垯 + // const closeDialog = async (value) => { + // setWaveRule(false) + // const res = await request.post(`/outStock/generate/wave`, { ids: selectIds, waveRuleId: value.id }); + // if (res?.data?.code === 200) { + // notify(res.data.msg); + // } else { + // notify(res.data.msg); + // } + // refresh() + // } + + return ( + <Box display="flex"> + <List + resource="check" + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + }} + title={"menu.checkOrder"} + empty={false} + filters={filters} + filter={{ deleted: 0, type: 'check' }} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <FilterButton /> + <CreateByOrderButton setCreateDialog={setCreateDialog} /> + <MyCreateButton onClick={() => { setManualDialog(true); setmodalType(0) }} /> + <SelectColumnsButton preferenceKey='check' /> + <ImportButton value={'outStockItem'} /> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <StyledDatagrid + preferenceKey='check' + bulkActionButtons={<PublicTaskButton setWaveRule={setWaveRule} setSelectIds={setSelectIds} />} + rowClick={false} + expandSingle={true} + omit={['id', 'createTime', 'createBy', 'memo', 'rleStatus$']} + > + <NumberField source="id" /> + <TextField source="code" label="table.field.checkOrder.code" /> + <TextField source="poCode" label="table.field.checkOrder.poCode" /> + <TextField source="type$" label="table.field.checkOrder.type" /> + <TextField cellClassName="wkType" source="wkType$" label="table.field.checkOrder.wkType" /> + <NumberField source="anfme" label="table.field.checkOrder.anfme" /> + <NumberField source="workQty" label="table.field.checkOrder.workQty" /> + <NumberField source="qty" label="table.field.checkOrder.qty" /> + <TextField source="logisNo" label="table.field.checkOrder.logisNo" /> + <TextField source="rleStatus$" label="table.field.checkOrder.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.checkOrder.exceStatus" /> + <TextField source="memo" label="common.field.memo" sortable={false} /> + <WrapperField cellClassName="opt" label="common.field.opt" > + <MyButton setCreateDialog={setManualDialog} setmodalType={setmodalType} /> + <EditButton label="toolbar.detail" icon={(<DetailsIcon />)}></EditButton> + <CancelButton /> + <PublicButton setDrawerVal={setDrawerVal} drawerVal={drawerVal} setSelect={setSelect} /> + </WrapperField> + </StyledDatagrid> + </List> + {/* <OutOrderCreate + open={manualDialog} + setOpen={setManualDialog} + /> */} + {/* <SelectMatnrModal + asnId={modalType} + billReload={billReload} + open={manualDialog} + setOpen={setManualDialog} + /> + <OutOrderModal + open={createDialog} + setOpen={setCreateDialog} + preview={preview} + setPreview={setPreview} + /> + <OutStockWaveDialog open={waveRule} setOpen={setWaveRule} onClose={closeDialog} /> + <OutOrderPreview open={preview} setOpen={setPreview} /> + <PageEditDrawer + title={"toolbar.publicWorking"} + drawerVal={drawerVal} + setDrawerVal={setDrawerVal} + > + <OutStockPublic record={select} open={drawerVal} setOpen={setDrawerVal} /> + </PageEditDrawer> */} + </Box > + ) +} +export default CheckOrderList; + + +const PublicTaskButton = ({ setWaveRule, setSelectIds }) => { + const record = useRecordContext(); + const { selectedIds, onUnselectItems } = useListContext(); + const notify = useNotify(); + const redirect = useRedirect(); + + const pubClick = async () => { + onUnselectItems(); + setWaveRule(true); + setSelectIds(selectedIds) + } + + return ( + <Button + onClick={pubClick} + label={"toolbar.createWave"} + startIcon={<PublicIcon />} + /> + ); +} + +const MyButton = ({ setCreateDialog, setmodalType }) => { + const record = useRecordContext(); + const handleEditClick = (btn) => { + btn.stopPropagation(); + const id = record.id; + setmodalType(id); + setCreateDialog(true); + }; + return ( + <Button + color="primary" + startIcon={<EditIcon />} + onClick={(btn) => handleEditClick(btn)} + sx={{ ml: 1 }} + label={'ra.action.edit'} + > + </Button> + ) +} + +const CreateByOrderButton = ({ setCreateDialog }) => { + const record = useRecordContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const createByOrder = async (event) => { + event.stopPropagation(); + setCreateDialog(true); + } + + return ( + <Button onClick={createByOrder} label={'toolbar.asnCreate'}> <AddIcon /> </Button> + ) +} + +const CancelButton = () => { + const record = useRecordContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const cancelOrder = async () => { + const { data: { code, data, msg } } = await request.get(`/outStock/cancel/${record?.id}`); + if (code === 200) { + notify(msg); + refresh() + } else { + notify(msg); + } + } + + return ( + record?.exceStatus == 10 ? <ConfirmButton label={"toolbar.cancel"} startIcon={<CancelOutlinedIcon />} onConfirm={cancelOrder} size={"small"} /> : <></> + ) +} + +//涓嬪彂鎵ц +const PublicButton = ({ setDrawerVal, setSelect }) => { + const record = useRecordContext(); + const refresh = useRefresh(); + const taskEvent = () => { + setDrawerVal(true) + setSelect(record) + refresh(); + } + + return ( + record.workQty < record.anfme ? <Button label={"toolbar.publicWorking"} startIcon={<AddTaskIcon />} onClick={taskEvent} size={"small"} /> : <></> + ) +} diff --git a/rsf-admin/src/page/orders/check/OutOrderModal.jsx b/rsf-admin/src/page/orders/check/OutOrderModal.jsx new file mode 100644 index 0000000..6bea1bd --- /dev/null +++ b/rsf-admin/src/page/orders/check/OutOrderModal.jsx @@ -0,0 +1,279 @@ +import { Dialog, DialogActions, DialogContent, DialogTitle, Box, LinearProgress } from "@mui/material"; +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + List, + DatagridConfigurable, + SearchInput, + TopToolbar, + Toolbar, + Button, + 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, + SimpleForm, + Form, + SaveButton, + useRefresh, + useGetList, +} from 'react-admin'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import { styled } from '@mui/material/styles'; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import { Grid, margin, Stack, width } from "@mui/system"; +import request from '@/utils/request'; +import SaveIcon from '@mui/icons-material/Save'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import EditableTextField from "../../components/EditableTextField"; +import OutOrderPreview from "./OutOrderPreview"; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .status': { + width: 90 + }, +})); + +const StyledForm = styled(Form)(({ theme }) => ({ + width: '100%', + marginBottom: '45px', + + '& .MuiGrid-root': { + margin: '0 10px' + } +})); + + +const filters = [ + <SearchInput source="condition" alwaysOn />, + <DateInput label='common.time.after' source="timeStart" />, + <DateInput label='common.time.before' source="timeEnd" />, + <TextInput source="code" label="table.field.delivery.code" />, + <TextInput source="platId" label="table.field.delivery.platId" />, + <TextInput source="type" label="table.field.delivery.type" />, + <TextInput source="wkType" label="table.field.delivery.wkType" />, + <TextInput source="source" label="table.field.delivery.source" />, + <SelectInput + label="common.field.status" + source="status" + choices={[ + { id: '1', name: 'common.enums.statusTrue' }, + { id: '0', name: 'common.enums.statusFalse' }, + ]} + resettable + />, +] + +const OutOrderModal = (props) => { + const { open, setOpen, preview, setPreview, record } = props; + const translate = useTranslate(); + const [params, setParams] = useState({}); + const [select, setSelect] = useState([]); + const [drawerVal, setDrawerVal] = useState(false); + const refresh = useRefresh(); + const handleClose = (event, reason) => { + if (reason !== "backdropClick") { + setOpen(false); + } + }; + const CustomFilter = () => { + const { filterValues, setFilters, refetch } = useListContext(); + const [formValues, setFormValues] = useState(filterValues); + const handleChange = (event) => { + if (event.target == undefined || event.target == null) { return } + setFormValues(formValues => ({ + ...formValues, + [event.target.name]: event.target.value, + })); + }; + + const handleSubmit = (event) => { + setParams(formValues) + }; + + return ( + <StyledForm> + <Grid container rowSpacing={3} columnSpacing={3} > + <Stack> + <TextInput + source="condition" + label="common.action.search" + resettable + defaultValue={params?.condition} + onChange={handleChange} /> + </Stack> + <Stack> + <TextInput + source="deliveryCode" + label="table.field.deliveryItem.deliveryCode" + defaultValue={params?.deliveryCode} + onChange={handleChange} + resettable + /> + </Stack> + <Stack> + <TextInput + source="maktx" + label="table.field.deliveryItem.matnrName" + defaultValue={params?.maktx} + onChange={handleChange} + resettable + /> + </Stack> + <Stack> + <TextInput + source="matnrCode" + label="table.field.deliveryItem.matnrCode" + defaultValue={params?.matnrCode} + resettable + onChange={handleChange} /> + </Stack> + <Stack> + <TextInput + source="splrName" + label="table.field.deliveryItem.splrName" + defaultValue={params?.splrName} + resettable + onChange={handleChange} /> + </Stack> + </Grid> + <DialogActions> + <Toolbar sx={{ width: '100%', justifyContent: 'end' }} > + <SaveButton onClick={handleSubmit} label={"toolbar.query"} /> + </Toolbar> + </DialogActions> + </StyledForm> + ); + }; + return ( + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + aria-hidden + fullWidth + disableRestoreFocus + maxWidth="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> + <Grid container rowSpacing={2} columnSpacing={2}> + <DialogContent> + <Grid item sx={24}> + <List + resource="/deliveryItem/filters" + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + }} + filters={<CustomFilter />} + queryOptions={{ meta: { ...params } }} + empty={false} + sort={{ field: "create_time", order: "desc" }} + actions={( + <TopToolbar> + <></> + </TopToolbar> + )} + perPage={DEFAULT_PAGE_SIZE} + > + <Box sx={{ position: 'relative', minHeight: "60vh", }}> + <LinearProgress + sx={{ height: "2px", position: 'absolute', top: 0, left: 0, right: 0, }} + /> + <StyledDatagrid + preferenceKey='deliveryItem' + bulkActionButtons={<AddOutStockButton setOpen={setOpen} setPreview={setPreview} setSelect={setSelect} />} + rowClick={(id, resource, record) => false} + expand={false} + expandSingle={true} + omit={['id', 'createTime', 'createBy', 'memo', 'startTime', 'endTime', 'updateBy', 'createTime']} + > + <NumberField source="id" /> + <TextField source="deliveryCode" label="table.field.deliveryItem.deliveryCode" /> + <TextField source="matnrCode" label="table.field.deliveryItem.matnrCode" /> + <TextField source="maktx" label="table.field.deliveryItem.matnrName" /> + <TextField source="unit" label="table.field.deliveryItem.unit" /> + <NumberField source="anfme" label="table.field.deliveryItem.anfme" /> + <NumberField source="workQty" label="table.field.outStockItem.workQty" /> + <TextField source="splrName" label="table.field.deliveryItem.splrName" /> + <TextField source="splrBatch" label="table.field.deliveryItem.splrBatch" /> + <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> + </Box> + </List> + </Grid> + </DialogContent> + </Grid> + <Grid> + <OutOrderPreview open={preview} setOpen={setPreview} selectedIds={select} setCloseParent={setOpen} /> + </Grid> + </Dialog > + ) +} + +export default OutOrderModal; + +const AddOutStockButton = (props) => { + const { setOpen, setPreview, setSelect } = props; + const { selectedIds, onUnselectItems } = useListContext(); + const notify = useNotify(); + const refresh = useRefresh(); + const confirm = async (event) => { + setPreview(true) + setSelect(selectedIds); + onUnselectItems(); + // refresh(); + } + + return ( + <Button label={"toolbar.confirmSelect"} onClick={confirm}> + <CheckCircleIcon /> + </Button> + ) +} \ No newline at end of file diff --git a/rsf-admin/src/page/orders/check/OutOrderPreview.jsx b/rsf-admin/src/page/orders/check/OutOrderPreview.jsx new file mode 100644 index 0000000..ea4cb20 --- /dev/null +++ b/rsf-admin/src/page/orders/check/OutOrderPreview.jsx @@ -0,0 +1,141 @@ +import { Dialog, DialogActions, DialogContent, DialogTitle, Box, LinearProgress, Grid, } from "@mui/material"; +import React, { useState, useRef, useEffect, useMemo, memo } from "react"; +import { + Toolbar, + Button, + useTranslate, + useNotify, + useRefresh, + useGetList, +} from 'react-admin'; +import request from '@/utils/request'; +import { styled } from '@mui/material/styles'; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; +import { DataGrid, useGridApiContext, GridActionsCellItem, useGridApiRef } from '@mui/x-data-grid'; +import DialogCloseButton from "../../components/DialogCloseButton"; + + +const OutOrderPreview = (props) => { + const { open, setOpen, record, selectedIds, setCloseParent } = props; + const translate = useTranslate(); + const gridRef = useGridApiRef(); + const [rows, setRows] = useState([]); + const notify = useNotify(); + const refresh = useRefresh(); + const handleClose = async (event, reason) => { + if (reason !== "backdropClick") { + // const res = await request.get(`/outStock/items/cancel/` + selectedIds); + setOpen(false); + setCloseParent(false) + } + }; + + if (!selectedIds) { return } + + const { data, isLoading, error } = useGetList('/deliveryItem/edit', { + pagination: { page: 1, perPage: 1000 }, + filter: { deleted: 0, ids: selectedIds } + }); + + return ( + <Dialog + open={open} + onClose={handleClose} + aria-labelledby="form-dialog-title" + aria-hidden + fullWidth + maxWidth="lg" + > + <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> + <Grid container xl={12}> + <Grid item xl={12}> + <Box display="flex" sx={{ height: 400, width: '100%', '& .RaConfigurable-root': { width: '100%' } }}> + <LinearProgress sx={{ height: "2px", position: 'absolute', top: 0, left: 0, right: 0, }} /> + <OrderPreview rows={data} gridRef={gridRef} /> + </Box > + </Grid> + </Grid> + <Toolbar sx={{ justifyContent: 'end' }}> + <ConfirmButton label="toolbar.confirm" variant="contained" size="large" gridRef={gridRef} setOpen={setOpen} setCloseParent={setCloseParent}/> + </Toolbar> + </DialogContent> + </Dialog> + ) +} + +export default OutOrderPreview; + +const ConfirmButton = ({ gridRef, setOpen, setCloseParent }) => { + const refresh = useRefresh(); + const notify = useNotify(); + const confirm = async () => { + const items = gridRef.current?.getSortedRows(); + const { data: { code, msg } } = await request.post(`/outStock/generate/orders`, { ids: items }); + if (code === 200) { + notify(msg); + refresh() + setOpen(false) + setCloseParent(false) + } else { + notify(msg); + } + } + + return ( + <Button label="toolbar.confirm" variant="contained" size="large" onClick={confirm} /> + ) +} + +const OrderPreview = ({ rows, gridRef }) => { + gridRef.current = useGridApiRef(); + + const columns = [ + { field: 'matnrCode', headerName: '鐗╂枡缂栫爜', width: 110 }, + { field: 'maktx', headerName: '鐗╂枡鍚嶇О', width: 190 }, + { + field: 'anfme', headerName: '鍑哄簱鏁伴噺', width: 110, type: 'number', editable: true, + valueGetter: (value, row) => { + return row.anfme - row.workQty - row.qty; + }, + }, + { + field: 'workQty', headerName: '鍓╀綑鏁伴噺', width: 110, type: 'number', + valueGetter: (value, row) => { + return row.anfme - row.workQty - row.qty; + }, + }, + { field: 'unit', headerName: '鍗曚綅', width: 110 }, + { field: 'splrBatch', headerName: '鎵规', width: 110 }, + { field: 'splrName', headerName: '渚涘簲鍟�', width: 110 }, + { field: 'updateTime', headerName: '鏇存柊鏃堕棿', width: 110 }, + { field: 'updateBy$', headerName: '鏇存柊浜哄憳', width: 110 }, + ] + + return ( + <DataGrid + storeKey={"outOrderItemPreview"} + rows={rows} + columns={columns} + apiRef={gridRef} + disableRowSelectionOnClick + hideFooterPagination={true} // 闅愯棌鍒嗛〉鎺т欢 + hideFooter={true} + onRowSelectionModelChange={(ids) => { + setSelectedIds(ids) + }} + /> + ) +} + + diff --git a/rsf-admin/src/page/orders/check/OutStockPublic.jsx b/rsf-admin/src/page/orders/check/OutStockPublic.jsx new file mode 100644 index 0000000..6bb6a6d --- /dev/null +++ b/rsf-admin/src/page/orders/check/OutStockPublic.jsx @@ -0,0 +1,480 @@ +import { Box, Card, Grid, LinearProgress, Select, MenuItem, ListItemText } from "@mui/material"; +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + List, + DatagridConfigurable, + SearchInput, + TopToolbar, + Button, + 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, + SimpleForm, + required, + Form, + useRefresh, + useRedirect, +} from 'react-admin'; +import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE, DEFAULT_ITEM_PAGE_SIZE, DEFAULT_TYPE } from '@/config/setting'; +import { styled } from '@mui/material/styles'; +import { DataGrid, useGridApiContext, GridActionsCellItem, useGridApiRef } from '@mui/x-data-grid'; +import request from '@/utils/request'; +import ConfirmationNumberOutlinedIcon from '@mui/icons-material/ConfirmationNumberOutlined'; +import CloseSharpIcon from '@mui/icons-material/CloseSharp'; +import ConfirmButton from '../../components/ConfirmButton'; +import { Delete, Edit, Add } from '@mui/icons-material'; +import OutStockSiteDialog from "./OutStockSiteDialog"; + +const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ + '& .css-1vooibu-MuiSvgIcon-root': { + height: '.9em' + }, + '& .RaDatagrid-row': { + cursor: 'auto' + }, + '& .column-maktx': { + width: 200 + }, + + mt: '60px' + // '& .RaBulkActionsToolbar-toolbar': { + // display: 'none' + // } + +})); + +const OutStockPublic = (props) => { + const { record, open, setOpen, setManualDialog } = props; + const notify = useNotify(); + const gridRef = useGridApiRef(); + const [rows, setRows] = useState([]); + const [fetchRows, setFetchRows] = useState([]); + const translate = useTranslate(); + const [rowSelectedIds, setRowSelectedIds] = useState([]); + const [selectedMatnr, setSelectedMatnr] = useState([]); + const [selectedIds, setSelectedIds] = useState([]); + const [formData, setFormData] = useState({ orderId: record?.id, waveId: DEFAULT_TYPE }); + const [dialog, setDialog] = useState(false); + const [selectedValue, setSelectedValue] = useState({}); + + useEffect(() => { + if (selectedMatnr.length < 1) { + setRows(fetchRows) + } else { + const mas = fetchRows.filter(item => selectedMatnr.includes(item.matnrCode)); + setRows(mas) + } + }, [selectedMatnr]) + + + const ComfirmButton = () => { + const { selectedIds, data } = useListContext(); + const handleRowClick = () => { + const ids = data.filter(item => selectedIds.includes(item.id)).map(item => item.id); + setRowSelectedIds(ids); + const mas = data.filter(item => selectedIds.includes(item.id)).map(item => item.matnrCode); + //璁剧疆搴撲綅淇℃伅绛涢�夋潯浠� + setSelectedMatnr(mas); + } + + return ( + <Button label="toolbar.confirm" size="medium" onClick={handleRowClick} /> + ) + }; + + const handleClickOpen = () => { + setDialog(true); + }; + + const handleClose = (value) => { + setDialog(false); + setSelectedValue(value); + if (selectedIds.length == 0) { + const newRows = rows.map(item => { + return { + ...item, + siteNo: value?.site + } + }) + setRows(newRows); + } else { + const newRows = rows.map(item => { + return selectedIds.includes(item?.id) ? { + ...item, + siteNo: value?.site + } : item + }) + setRows(newRows); + } + }; + + useEffect(() => { + getWaveRule() + }, [open]) + + const getWaveRule = async () => { + if (formData.waveId == null && formData.waveId == undefined) { + return + } + const { data: { code, data, msg } } = await request.post('/outStock/order/getOutTaskItems', { ...formData }); + if (code === 200) { + // setRows(data) + setFetchRows(data) + } else { + notify(msg); + } + } + + const handleChange = (value, name) => { + setFormData((prevData) => ({ + ...prevData, + [name]: value + })); + }; + + + return ( + <> + <Box> + <Grid sx={{ display: "flex" }} container rowSpacing={2} columnSpacing={2}> + <Grid item xl={5.7} gap={2} > + <Card> + <Form> + <ReferenceInput + source="type" + reference="waveRule" + > + <AutocompleteInput + label="table.field.waveRule.type" + onChange={(e) => handleChange(e, 'waveId')} + defaultValue={15} + value={formData.type} + validate={required()} + /> + </ReferenceInput> + </Form> + <List + resource="outStockItem" + storeKey='outStockItem' + sx={{ + flexGrow: 1, + transition: (theme) => + theme.transitions.create(['all'], { + duration: theme.transitions.duration.enteringScreen, + }), + }} + title={"menu.outStockItem"} + empty={false} + filter={{ asnId: record?.id, deleted: 0 }} + sort={{ field: "create_time", order: "desc" }} + actions={false} + pagination={false} + perPage={DEFAULT_ITEM_PAGE_SIZE} + > + <LinearProgress + sx={{ height: "2px", position: 'absolute', top: 0, left: 0, right: 0, }} + /> + <StyledDatagrid + storeKey={"outStockPublic"} + preferenceKey='outStockItem' + bulkActionButtons={<> + <ComfirmButton /> + </>} + omit={['id', 'splrName', 'qty', 'poCode',]} + > + <NumberField source="id" /> + <TextField source="asnCode" label="table.field.outStockItem.asnCode" /> + <TextField source="poCode" label="table.field.outStockItem.poCode" /> + <TextField source="matnrCode" label="table.field.outStockItem.matnrCode" /> + <TextField source="maktx" label="table.field.outStockItem.maktx" /> + <NumberField source="anfme" label="table.field.outStockItem.anfme" /> + <NumberField source="workQty" label="table.field.outStockItem.workQty" /> + <NumberField source="qty" label="table.field.outStockItem.qty" /> + <TextField source="stockUnit" label="table.field.outStockItem.stockUnit" /> + <TextField source="splrName" label="table.field.outStockItem.splrName" /> + </StyledDatagrid> + </List> + </Card> + </Grid> + <Grid item xl={6.3} gap={2}> + <Card sx={{ minHeight: 1050, height: 'calc(100% - 10px)', width: '100%' }}> + <Box> + <PreviewTable + rows={rows} + gridRef={gridRef} + setRows={setRows} + record={record} + formData={formData} + selectedIds={selectedIds} + setDialog={setDialog} + setSelectedIds={setSelectedIds} + /> + </Box> + <Box sx={{ textAlign: 'center' }}> + <CloseButton setOpen={setOpen} /> + <SubmitButton selectedIds={selectedIds} setSelectedIds={setSelectedIds} gridRef={gridRef} record={record} /> + </Box> + </Card> + </Grid> + </Grid> + <Grid> + <OutStockSiteDialog + selectedValue={selectedValue} + open={dialog} + onClose={handleClose} + /> + </Grid> + </Box> + </> + ); +} + +const PreviewTable = ({ rows, gridRef, setRows, record, selectedIds, setSelectedIds, setDialog, formData }) => { + gridRef.current = useGridApiRef(); + const translate = useTranslate(); + + useEffect(() => { + if (selectedIds.length > 0) { + console.log(selectedIds); + } + }, [selectedIds]) + + const baseColumns = [ + // { field: 'id', headerName: 'ID', width: 40 }, + { field: 'locCode', headerName: '搴撲綅', width: 110 }, + { field: 'barcode', headerName: '瀹瑰櫒', width: 120 }, + { field: 'matnrCode', headerName: '鐗╂枡缂栫爜', width: 120 }, + { field: 'batch', headerName: '鎵规', width: 90 }, + { field: 'unit', headerName: '鍗曚綅', width: 60 }, + { field: 'outQty', headerName: '鍑哄簱鏁伴噺', width: 110, }, + { + field: 'anfme', headerName: '搴撳瓨鏁伴噺', width: 110, + renderCell: (params) => ( + <OutStockAnfme value={params.value} /> + ) + }, + { + field: 'siteNo', + headerName: '鍑哄簱鍙�', + width: 90, + type: 'singleSelect', + editable: true, + renderCell: (params) => ( + <OutStockSiteNo value={params.value} /> + ), + renderEditCell: (params) => ( + <OutStockSite {...params} /> + ), + }, + ] + + const optAction = { + field: 'actions', + type: 'actions', + headerName: translate('common.field.opt'), + with: 120, + getActions: (params) => [ + <GridActionsCellItem + icon={<Delete />} + label="Delete" + onClick={() => handleDelete(params.row, rows, setRows)} + />, + ] + } + + const columns = (formData.waveId == 15 || formData.waveId == 16) ? [...baseColumns] : [...baseColumns, optAction]; + + /** + * 鍒犻櫎浜嬩欢 + * @param {*} params + */ + const handleDelete = (params, rows, setRows) => { + const outRows = rows.filter(row => { + return row.id !== params.id + }) + setRows(outRows) + } + + const OutStockAnfme = React.memo(function OutStockAnfme(props) { + const { value } = props; + return ( + value > 0 ? + <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> + <span>{value}</span> + </Box> + : + <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> + <span style={{ color: 'red' }}>{translate('common.edit.title.insuffInventory')}</span> + </Box> + ); + }); + + const OutStockSiteNo = React.memo(function OutStockSiteNo(props) { + const { value } = props; + if (!value) { + return null; + } + return ( + <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> + <span>{value}</span> + </Box> + ); + }); + + const CustomToolBar = () => { + const selectSiteNo = () => { + setDialog(true) + } + return ( + <Box sx={{ + p: 1, + display: 'flex', + justifyContent: 'flex-end', + borderTop: '1px solid rgba(224, 224, 224, 1)' + }}> + <Button + onClick={selectSiteNo} + variant="outlined" + label="toolbar.modiftySite" + size="medium" + sx={{ mr: 1 }} /> + </Box> + ); + } + + const OutStockSite = (params) => { + const { id, field, siteNo, row: { staNos } } = params; + const apiRef = useGridApiContext(); + const handleChange = async (event) => { + await apiRef.current.setEditCellValue( + { id, field, value: event.target.value }, + event, + ); + apiRef.current.stopCellEditMode({ id, field }); + }; + + const handleClose = (event, reason) => { + if (reason === 'backdropClick') { + apiRef.current.stopCellEditMode({ id, field }); + } + }; + + return ( + <Select + value={siteNo} + onChange={handleChange} + MenuProps={{ + onClose: handleClose, + }} + sx={{ + height: '100%', + '& .MuiSelect-select': { + display: 'flex', + alignItems: 'center', + pl: 1, + }, + }} + autoFocus + fullWidth + open + > + {staNos.map((option) => { + return ( + <MenuItem + key={option} + value={option.staNo} + > + <ListItemText sx={{ overflow: 'hidden' }} primary={option.staNo} /> + </MenuItem> + ); + })} + </Select > + ) + } + + return ( + <DataGrid + storeKey={"locItemPreview"} + rows={rows} + columns={columns} + slots={{ toolbar: CustomToolBar }} + apiRef={gridRef} + checkboxSelection + disableRowSelectionOnClick + hideFooterPagination={true} // 闅愯棌鍒嗛〉鎺т欢 + hideFooter={false} + onRowSelectionModelChange={(ids) => { + setSelectedIds(ids) + }} + /> + ) +} + + +//鎻愪氦鎸夐挳 +const SubmitButton = ({ selectedIds, setSelectedIds, gridRef, record }) => { + const notify = useNotify(); + const refresh = useRefresh(); + const redirect = useRedirect(); + const submit = async () => { + const items = gridRef.current?.getSortedRows(); + const { data: { code, data, msg } } = await request.post('/outStock/generate/tasks', { items, outId: record?.id }); + if (code == 200) { + refresh(); + redirect("/task") + } else { + notify(msg); + } + } + return ( + <ConfirmButton + label="toolbar.allComfirm" + variant="contained" + size="medium" + onConfirm={submit} + /> + ) +} + +//鍏抽棴鎸夐挳 +const CloseButton = ({ setOpen }) => { + const close = () => { + setOpen(false) + } + return ( + <Button + label="toolbar.close" + variant="outlined" + size="medium" + onClick={close} + startIcon={<CloseSharpIcon />} + sx={{ margin: '3.5em' }} /> + ) +} + +export default OutStockPublic; + + diff --git a/rsf-admin/src/page/orders/check/SelectMatnrModal.jsx b/rsf-admin/src/page/orders/check/SelectMatnrModal.jsx new file mode 100644 index 0000000..08e9a61 --- /dev/null +++ b/rsf-admin/src/page/orders/check/SelectMatnrModal.jsx @@ -0,0 +1,585 @@ +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, + Select, + MenuItem +} from '@mui/material'; +import DialogCloseButton from "../../components/DialogCloseButton"; +import StatusSelectInput from "../../components/StatusSelectInput"; +import ConfirmButton from "../../components/ConfirmButton"; +import MatnrInfoModal from "./MatnrInfoModal"; +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"; +import "./asnOrder.css"; + +const SelectMatnrModal = (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(`/outStock/items/save`, parmas); + if (res?.data?.code === 200) { + setOpen(false); + refresh(); + resetData() + } else { + notify(res.data.msg); + } + } else { + const parmas = { + "orders": formData, + "items": tabelData, + } + const res = await request.post(`/outStock/items/update`, parmas); + if (res?.data?.code === 200) { + setOpen(false); + refresh(); + resetData() + } else { + notify(res.data.msg); + } + } + setDisabled(false) + + }; + + + const handleDelete = async () => { + const res = await request.post(`/outStock/remove/${asnId}`); + if (res?.data?.code === 200) { + setOpen(false); + refresh(); + } else { + notify(res.data.msg); + } + }; + + const requestGetHead = async () => { + const res = await request.get(`/outStock/${asnId}`); + if (res?.data?.code === 200) { + setFormData(res.data.data) + } else { + notify(res.data.msg); + } + } + + const requestGetBody = async () => { + const res = await request.post(`/outStockItem/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 defaultValues={formData}> + <Grid container spacing={2}> + {/* <Grid item md={2}> + <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={2}> + <DictSelect + label={translate("table.field.outStock.wkType")} + value={formData.wkType} + variant="filled" + group='2' + onChange={(e) => handleChange(e.target.value, 'wkType')} + dictTypeCode="sys_business_type" + required + /> + </Grid> + <Grid item md={2}> + <TextField + label={translate("table.field.outStock.poCode")} + value={formData.poCode} + variant="filled" + size='small' + onChange={(e) => handleChange(e.target.value, 'poCode')} + /> + </Grid> + <Grid item md={2}> + <TextField + label={translate("table.field.outStock.logisNo")} + value={formData.logisNo} + variant="filled" + size='small' + onChange={(e) => handleChange(e.target.value, 'logisNo')} + /> + </Grid> + <Grid item md={2}> + <DateInput + source="arrTime" + label="table.field.outStock.arrTime" + size='small' + variant="filled" + 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> + <MatnrInfoModal + open={createDialog} + setOpen={setCreateDialog} + data={tabelData} + setData={setTableData} + /> + </> + ) +} + +export default SelectMatnrModal; + +const SelectInputSplrNameEditCell = (params) => { + const [formData, setFormData] = useState([{}]) + useEffect(() => { + getOptions(); + }, []); + const getOptions = async () => { + const parmas = { + "type": "supplier" + } + const { + data: { code, data, msg }, + } = await request.post("companys/page", parmas); + if (code === 200) { + setFormData(data.records) + } else { + notify(msg); + } + } + + return ( + <Select + value={params.value} + onChange={(e) => { + params.api.setEditCellValue({ + id: params.id, + field: params.field, + value: e.target.value, + }) + // 鎵惧埌閫変腑鐨勪緵搴斿晢璁板綍 + const selectedSupplier = formData.find(supplier => supplier.name === e.target.value); + + // 濡傛灉鎵惧埌瀵瑰簲鐨勪緵搴斿晢璁板綍锛屽悓鏃舵洿鏂皊plrCode瀛楁 + if (selectedSupplier) { + params.api.setEditCellValue({ + id: params.id, + field: 'splrCode', + value: selectedSupplier.id, + }); + } + }} + fullWidth + > + {formData.map(e => { + return ( + <MenuItem value={e.name} children={e.name} key={e.id} /> + ); + + })} + + </Select> + ); +}; + +const SelectInputSplrCodeEditCell = (params) => { + const [formData, setFormData] = useState([{}]) + useEffect(() => { + getOptions(); + }, []); + const getOptions = async () => { + const parmas = { + "type": "supplier" + } + const { + data: { code, data, msg }, + } = await request.post("companys/page", parmas); + if (code === 200) { + setFormData(data.records) + } else { + notify(msg); + } + } + + return ( + <Select + value={params.value} + onChange={(e) => { + params.api.setEditCellValue({ + id: params.id, + field: params.field, + value: e.target.value, + }) + const selectedSupplier = formData.find(supplier => supplier.id === e.target.value); + + // 濡傛灉鎵惧埌瀵瑰簲鐨勪緵搴斿晢璁板綍锛屽悓鏃舵洿鏂皊plrCode瀛楁 + if (selectedSupplier) { + params.api.setEditCellValue({ + id: params.id, + field: 'splrName', + value: selectedSupplier.name, + }); + } + }} + fullWidth + + > + {formData.map(e => { + return ( + <MenuItem value={e.id} children={e.name} key={e.id} /> + ); + + })} + + </Select> + ); +}; + + + + +const AsnOrderModalTable = ({ tabelData, setTableData, asnId, selectedRows, setSelectedRows, tableRef }) => { + const translate = useTranslate(); + const notify = useNotify(); + + const [columns, setColumns] = useState([ + { + field: 'maktx', + headerName: translate('table.field.outStockItem.maktx'), + width: 250, + editable: false, + }, + { + field: 'matnrCode', + headerName: translate('table.field.outStockItem.matnrCode'), + width: 130, + editable: false, + }, + { + field: 'anfme', + headerName: translate('table.field.outStockItem.anfme') + "*", + type: 'number', + minWidth: 100, + flex: 1, + editable: true, + valueFormatter: (val) => val < 0 ? 0 : val, + headerClassName: "custom", + }, + { + field: 'splrCode', + headerName: translate('table.field.outStockItem.splrCode') + "*", + minWidth: 100, + flex: 1, + editable: true, + renderEditCell: (params) => ( + <SelectInputSplrCodeEditCell {...params} /> + ), + headerClassName: "custom", + }, + { + field: 'splrName', + headerName: translate('table.field.outStockItem.splrName') + "*", + minWidth: 100, + flex: 1, + editable: true, + renderEditCell: (params) => ( + <SelectInputSplrNameEditCell {...params} /> + ), + headerClassName: "custom", + }, + { + field: 'splrBatch', + headerName: translate('table.field.outStockItem.splrBatch'), + minWidth: 100, + flex: 1, + editable: true, + }, + { + field: 'poCode', + headerName: translate('table.field.outStockItem.poDetlCode'), + minWidth: 100, + flex: 1, + editable: true, + }, + { + field: 'stockUnit', + headerName: translate('table.field.outStockItem.stockUnit'), + minWidth: 100, + flex: 1, + editable: true, + }, + ]) + + 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) + 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 ? row.matnrId : row.id} + disableColumnFilter + disableColumnSelector + disableColumnSorting + disableMultipleColumnsSorting + processRowUpdate={processRowUpdate} + initialState={{ + pagination: { + paginationModel: { + pageSize: 25, + }, + }, + }} + pageSizeOptions={[15, 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/check/index.jsx b/rsf-admin/src/page/orders/check/index.jsx new file mode 100644 index 0000000..7c2b86e --- /dev/null +++ b/rsf-admin/src/page/orders/check/index.jsx @@ -0,0 +1,18 @@ +import React, { useState, useRef, useEffect, useMemo } from "react"; +import { + ListGuesser, + EditGuesser, + ShowGuesser, +} from "react-admin"; + +import CheckOrderList from "./CheckOrderList"; +import CheckOrderEdit from "./CheckOrderEdit"; + +export default { + list: CheckOrderList, + edit: CheckOrderEdit, + show: ShowGuesser, + recordRepresentation: (record) => { + return `${record.name}` + } +}; diff --git a/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx b/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx index cf5d60c..9a4d3bd 100644 --- a/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx +++ b/rsf-admin/src/page/warehouseAreas/WarehouseAreasList.jsx @@ -31,6 +31,7 @@ ReferenceArrayInput, AutocompleteInput, DeleteButton, + Datagrid, useRefresh, Button } from 'react-admin'; @@ -44,21 +45,84 @@ import PageDrawer from "../components/PageDrawer"; import BatchModal from "./BatchModal"; import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; -import * as Common from '@/utils/common'; import EditIcon from '@mui/icons-material/Edit'; +import { minWidth } from "@mui/system"; + + +const ScrollableDatagrid = styled(Datagrid)(({ theme }) => ({ + '& .MuiTable-root': { + minWidth: '100%', // 纭繚琛ㄦ牸瀹藉害瓒冲 + tableLayout: 'fixed', // 鍥哄畾琛ㄦ牸甯冨眬 + }, + '& .RaDatagrid-rowCell': { + textAlign: 'center', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + }, + + '& .RaDatagrid-headerCell': { + whiteSpace: 'nowrap', + overflowX: 'auto', + }, + + '& .opt': { + width: 200, + position: 'sticky', + zIndex: 3, + right: 0, + + }, +})); + const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ - '& .css-1vooibu-MuiSvgIcon-root': { - height: '.9em' - }, - '& .RaDatagrid-row': { - cursor: 'auto' - }, - '& .column-name': { - }, + // height: '.9em' + // }, + // '& .RaDatagrid-row': { + // cursor: 'auto' + // }, '& .opt': { - width: 200 + width: 200, + position: 'sticky', + right: 0, }, + + '& .MuiTableContainer-root': { + overflowX: 'auto', + '&::-webkit-scrollbar': { + height: '8px', + }, + '&::-webkit-scrollbar-thumb': { + backgroundColor: theme.palette.action.hover, + borderRadius: '4px', + }, + }, + // '& .MuiTable-root': { + // minWidth: '100%', // 纭繚琛ㄦ牸瀹藉害瓒冲 + // tableLayout: 'fixed', // 鍥哄畾琛ㄦ牸甯冨眬 + // }, + // '& .MuiTableCell-root': { + // whiteSpace: 'nowrap', + // overflow: 'hidden', + // textOverflow: 'ellipsis', + // position: 'relative', // 涓哄浐瀹氬垪鎻愪緵瀹氫綅涓婁笅鏂� + // }, + // '& .MuiTableCell-actions': { + // position: 'sticky', + // right: 0, + // background: theme.palette.background.paper, + // zIndex: 2, + // width: '150px', + // minWidth: '150px', + // boxShadow: '-2px 0 4px rgba(0,0,0,0.1)', + // '& button': { + // marginLeft: theme.spacing(1), + // } + // }, + // '& .MuiTableHead-root .MuiTableCell-actions': { + // zIndex: 3, // 琛ㄥご姣斿唴瀹归珮涓�灞� + // } + })); const filters = [ @@ -127,6 +191,13 @@ duration: theme.transitions.duration.enteringScreen, }), marginRight: drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0, + '& .RaList-content': { + position: 'sticky', + overflow: 'auto', + width: 'auto', + righ: '0px', + minWidth: '100%' + } }} title={"menu.warehouseAreas"} empty={<EmptyData onClick={() => { setCreateDialog(true) }} />} @@ -142,7 +213,7 @@ )} perPage={DEFAULT_PAGE_SIZE} > - <StyledDatagrid + <ScrollableDatagrid preferenceKey='warehouseAreas' bulkActionButtons={ <> @@ -157,33 +228,33 @@ > <NumberField source="id" /> {/* <TextField source="uuid" label="table.field.warehouseAreas.uuid" /> */} - <TextField source="name" label="table.field.warehouseAreas.name" /> - <TextField source="code" label="table.field.warehouseAreas.code" /> - <TextField source="type$" label="table.field.warehouseAreas.type"/> + <TextField source="name" label="table.field.warehouseAreas.name" width="10%" /> + <TextField source="code" label="table.field.warehouseAreas.code" width="10%" /> + <TextField source="type$" label="table.field.warehouseAreas.type" width="10%" /> {/* <ReferenceField source="shipperId" label="table.field.warehouseAreas.shipperId" reference="shipper" link={false} sortable={false}> <TextField source="name" /> </ReferenceField> */} - <TextField source="warehouseId$" label="table.field.warehouseAreas.wareId" /> - <TextField source="shipperId$" label="table.field.warehouseAreas.shipperId" /> - <NumberField source="supplierId" label="table.field.warehouseAreas.supplierId" /> - <TextField source="flagMinus$" label="table.field.warehouseAreas.flagMinus" sortable={false} /> - <TextField source="flagLabelMange$" label="table.field.warehouseAreas.flagLabelMange" sortable={false} /> - <TextField source="flagMix$" label="table.field.warehouseAreas.flagMix" sortable={false} /> - <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}> + <TextField source="warehouseId$" label="table.field.warehouseAreas.wareId" width="10%" /> + <TextField source="shipperId$" label="table.field.warehouseAreas.shipperId" width="10%" /> + <NumberField source="supplierId" label="table.field.warehouseAreas.supplierId" width="10%" /> + <TextField source="flagMinus$" label="table.field.warehouseAreas.flagMinus" sortable={false} width="10%" /> + <TextField source="flagLabelMange$" label="table.field.warehouseAreas.flagLabelMange" sortable={false} width="10%" /> + <TextField source="flagMix$" label="table.field.warehouseAreas.flagMix" sortable={false} width="10%" /> + <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false} width="10%"> <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}> + <DateField source="updateTime" label="common.field.updateTime" showTime width="10%" /> + <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false} width="10%"> <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"> + <DateField source="createTime" label="common.field.createTime" showTime width="10%" /> + <BooleanField source="statusBool" label="common.field.status" sortable={false} width="10%" /> + <TextField source="memo" label="common.field.memo" sortable={false} width="10%" /> + <WrapperField source="opt" cellClassName="opt" label="common.field.opt"> <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} /> <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} /> </WrapperField> - </StyledDatagrid> + </ScrollableDatagrid> </List> <WarehouseAreasCreate open={createDialog} diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckOrderController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckOrderController.java new file mode 100644 index 0000000..51845f5 --- /dev/null +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/CheckOrderController.java @@ -0,0 +1,125 @@ +package com.vincent.rsf.server.manager.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.vincent.rsf.framework.common.Cools; +import com.vincent.rsf.framework.common.R; +import com.vincent.rsf.server.common.annotation.OperationLog; +import com.vincent.rsf.server.common.domain.BaseParam; +import com.vincent.rsf.server.common.domain.KeyValVo; +import com.vincent.rsf.server.common.domain.PageParam; +import com.vincent.rsf.server.common.utils.ExcelUtil; +import com.vincent.rsf.server.manager.entity.AsnOrder; +import com.vincent.rsf.server.manager.enums.OrderType; +import com.vincent.rsf.server.manager.service.CheckOrderService; +import com.vincent.rsf.server.system.constant.SerialRuleCode; +import com.vincent.rsf.server.system.controller.BaseController; +import com.vincent.rsf.server.system.utils.SerialRuleUtils; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.util.*; + +@Api("鐩樼偣") +@RestController +public class CheckOrderController extends BaseController { + + @Autowired + private CheckOrderService checkOrderService; + + + @PreAuthorize("hasAuthority('manager:check:list')") + @PostMapping("/check/page") + public R page(@RequestBody Map<String, Object> map) { + BaseParam baseParam = buildParam(map, BaseParam.class); + PageParam<AsnOrder, BaseParam> pageParam = new PageParam<>(baseParam, AsnOrder.class); + QueryWrapper<AsnOrder> wrapper = pageParam.buildWrapper(true); + wrapper.eq("type", OrderType.ORDER_CHECK.type); + return R.ok().add(checkOrderService.page(pageParam, wrapper)); + } + + @PreAuthorize("hasAuthority('manager:check:list')") + @PostMapping("/check/list") + public R list(@RequestBody Map<String, Object> map) { + return R.ok().add(checkOrderService.list()); + } + + @PreAuthorize("hasAuthority('manager:check:list')") + @PostMapping({"/check/many/{ids}", "/check/many/{ids}"}) + public R many(@PathVariable Long[] ids) { + return R.ok().add(checkOrderService.listByIds(Arrays.asList(ids))); + } + + @PreAuthorize("hasAuthority('manager:check:list')") + @GetMapping("/check/{id}") + public R get(@PathVariable("id") Long id) { + return R.ok().add(checkOrderService.getById(id)); + } + + @PreAuthorize("hasAuthority('manager:check:save')") + @OperationLog("Create 瀛楀吀鏁版嵁闆�") + @PostMapping("/check/save") + public R save(@RequestBody AsnOrder order) { + order.setType(OrderType.ORDER_CHECK.type); + String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_CHECK_RULE_CODE, order); + if (Objects.isNull(ruleCode)) { + throw new RuntimeException("鐩樼偣鍗曞彿鐢熸垚澶辫触锛侊紒"); + } + if (!checkOrderService.save(order)) { + return R.error("Save Fail"); + } + return R.ok("Save Success").add(order); + } + + @PreAuthorize("hasAuthority('manager:check:update')") + @OperationLog("Update 瀛楀吀鏁版嵁闆�") + @PostMapping("/check/update") + public R update(@RequestBody AsnOrder order) { + order.setUpdateTime(null); + order.setUpdateBy(getLoginUserId()); + if (!checkOrderService.updateById(order)) { + return R.error("Update Fail"); + } + return R.ok("Update Success").add(order); + } + + @PreAuthorize("hasAuthority('manager:check:remove')") + @OperationLog("Delete 瀛楀吀鏁版嵁闆�") + @PostMapping("/check/remove/{ids}") + public R remove(@PathVariable Long[] ids) { + if (!checkOrderService.removeByIds(Arrays.asList(ids))) { + return R.error("Delete Fail"); + } + return R.ok("Delete Success").add(ids); + } + + @PreAuthorize("hasAuthority('manager:check:list')") + @PostMapping("/check/query") + public R query(@RequestParam(required = false) String condition) { + List<KeyValVo> vos = new ArrayList<>(); + LambdaQueryWrapper<AsnOrder> wrapper = new LambdaQueryWrapper<>(); + if (!Cools.isEmpty(condition)) { + wrapper.like(AsnOrder::getCode, condition); + } + checkOrderService.page(new Page<>(1, 30), wrapper).getRecords().forEach( + item -> vos.add(new KeyValVo(item.getId(), item.getCode())) + ); + return R.ok().add(vos); + } + + @PreAuthorize("hasAuthority('manager:check:list')") + @PostMapping("/check/export") + public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception { + List<AsnOrder> orders = new ArrayList<>(); + if (!Objects.isNull(map.get("ids"))) { + orders = checkOrderService.list(new LambdaQueryWrapper<AsnOrder>().in(AsnOrder::getId, map.get("ids"))); + } else { + orders = checkOrderService.list(); + } + ExcelUtil.build(ExcelUtil.create(orders, AsnOrder.class), response); + } + +} diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java index 70eb44f..7a53b72 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/enums/OrderType.java @@ -11,6 +11,7 @@ //璁㈠崟绫诲瀷 ORDER_OUT("out", "鍑哄簱鍗�"), ORDER_IN("in", "鍏ュ簱鍗�"), + ORDER_CHECK("check", "鐩樼偣鍗�"); ; OrderType(String type, String desc) { diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/CheckOrderMapper.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/CheckOrderMapper.java new file mode 100644 index 0000000..24bbb88 --- /dev/null +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/CheckOrderMapper.java @@ -0,0 +1,12 @@ +package com.vincent.rsf.server.manager.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.vincent.rsf.server.manager.entity.AsnOrder; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Mapper +@Repository +public interface CheckOrderMapper extends BaseMapper<AsnOrder> { + +} diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java index dc2c516..396b10b 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java @@ -93,6 +93,7 @@ /** * 浠诲姟鑷姩涓嬪彂 + * * @throws Exception */ @Scheduled(cron = "0/5 * * * * ? ") @@ -101,8 +102,9 @@ Long loginUserId = SystemAuthUtils.getLoginUserId(); List<Integer> list = Arrays.asList(TaskType.TASK_TYPE_IN.type, TaskType.TASK_TYPE_OUT.type); List<Integer> integers = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id); - List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().in(Task::getTaskType, list) - .in(Task::getTaskStatus, integers) + List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>() + .in(Task::getTaskType, list) + .in(Task::getTaskStatus, integers) .orderByDesc(Task::getSort)); for (Task task : tasks) { Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, task.getBarcode())); diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/CheckOrderService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/CheckOrderService.java new file mode 100644 index 0000000..6f4fa8e --- /dev/null +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/CheckOrderService.java @@ -0,0 +1,8 @@ +package com.vincent.rsf.server.manager.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.vincent.rsf.server.manager.entity.AsnOrder; + +public interface CheckOrderService extends IService<AsnOrder> { + +} diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java new file mode 100644 index 0000000..2c31210 --- /dev/null +++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/CheckOrderServiceImpl.java @@ -0,0 +1,12 @@ +package com.vincent.rsf.server.manager.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.vincent.rsf.server.manager.entity.AsnOrder; +import com.vincent.rsf.server.manager.mapper.CheckOrderMapper; +import com.vincent.rsf.server.manager.service.CheckOrderService; +import org.springframework.stereotype.Service; + +@Service("checkOrderService") +public class CheckOrderServiceImpl extends ServiceImpl<CheckOrderMapper, AsnOrder> implements CheckOrderService { + +} diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java index 3d1d48c..c0e28de 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/constant/SerialRuleCode.java @@ -85,5 +85,8 @@ */ public final static String SYS_WAVE_RULE_CODE = "sys_wave_type"; + /**鐩樼偣鍗曞彿*/ + public final static String SYS_CHECK_RULE_CODE = "sys_check_rule_code"; + } diff --git a/rsf-server/src/main/resources/application-dev.yml b/rsf-server/src/main/resources/application-dev.yml index 203032b..95669f3 100644 --- a/rsf-server/src/main/resources/application-dev.yml +++ b/rsf-server/src/main/resources/application-dev.yml @@ -13,9 +13,9 @@ datasource: driver-class-name: com.mysql.jdbc.Driver # url: jdbc:mysql://47.76.147.249:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai +# username: rsf username: root url: jdbc:mysql://127.0.0.1:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai -# username: rsf password: 34821015 type: com.alibaba.druid.pool.DruidDataSource druid: -- Gitblit v1.9.1