From 92f07afcc63f7675dde38d6d36d92bb05aed7c81 Mon Sep 17 00:00:00 2001 From: verou <857149855@qq.com> Date: 星期五, 14 三月 2025 10:27:41 +0800 Subject: [PATCH] feat:po asn单据查询 --- rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx | 447 +++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 315 insertions(+), 132 deletions(-) diff --git a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx index b7ee747..8436018 100644 --- a/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx +++ b/rsf-admin/src/page/basicInfo/matnrGroup/MatnrGroupList.jsx @@ -1,156 +1,339 @@ -import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; -import { useNavigate } from 'react-router-dom'; +import React from 'react'; import { - List, - DatagridConfigurable, - SearchInput, - TopToolbar, - SelectColumnsButton, - EditButton, - FilterButton, - CreateButton, - ExportButton, - BulkDeleteButton, - WrapperField, - useRecordContext, + Title, useTranslate, useNotify, - useListContext, - FunctionField, - TextField, - NumberField, - DateField, - BooleanField, - ReferenceField, - TextInput, - DateTimeInput, - DateInput, - SelectInput, - NumberInput, - ReferenceInput, - ReferenceArrayInput, - AutocompleteInput, - DeleteButton, + useRedirect, + useRefresh, + useDelete, } from 'react-admin'; -import { Box, Typography, Card, Stack } from '@mui/material'; import { styled } from '@mui/material/styles'; -import MatnrGroupCreate from "./MatnrGroupCreate"; -import MatnrGroupPanel from "./MatnrGroupPanel"; -import EmptyData from "@/page/components/EmptyData"; -import MyCreateButton from "@/page/components/MyCreateButton"; -import MyExportButton from '@/page/components/MyExportButton'; -import PageDrawer from "@/page/components/PageDrawer"; -import MyField from "@/page/components/MyField"; -import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; -import * as Common from '@/utils/common'; +import { + Box, + Collapse, + IconButton, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Card, + Typography, + TextField, + Tooltip, + Button, + Chip, + LinearProgress, +} from '@mui/material'; +import { Add, Edit, Delete } from '@mui/icons-material'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import request from '@/utils/request'; +import MatnrGroupEdit from "./MatnrGroupEdit"; +import * as Icons from '@mui/icons-material'; -const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ - '& .css-1vooibu-MuiSvgIcon-root': { - height: '.9em' +const RESOURCE = 'matnrGroup'; +const TITLE = 'menu.matnrGroup'; + +const columns = [ + { + id: 'name', + label: 'table.field.matnrGroup.name', + minWidth: 200, }, - '& .RaDatagrid-row': { - cursor: 'auto' + { + id: 'code', + label: 'table.field.matnrGroup.code', + minWidth: 80, }, - '& .column-name': { - }, - '& .opt': { - width: 200 - }, + { + id: 'parentId', + label: 'table.field.matnrGroup.parentId', + minWidth: 100, + } +]; + +const getIconComponent = (iconStr) => { + return Icons[iconStr] || null; +}; + +const StyledTableRow = styled(TableRow)(({ theme }) => ({ + '& .MuiButtonBase-root': { + padding: '0px 8px' + } })); -const filters = [ - <SearchInput source="condition" alwaysOn />, - <DateInput label='common.time.after' source="timeStart" alwaysOn />, - <DateInput label='common.time.before' source="timeEnd" alwaysOn />, +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + maxWidth: 600, +})); - <TextInput source="name" label="table.field.matnrGroup.name" />, - <TextInput source="code" label="table.field.matnrGroup.code" />, - <NumberInput source="parentId" label="table.field.matnrGroup.parentId" />, +const TreeTableRow = (props) => { + const { row, depth = 0, openNodes, setOpenNodes, onEdit, onDelete } = props; + const translate = useTranslate(); - <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 toggleNode = (id) => { + setOpenNodes(prevState => ({ ...prevState, [id]: !prevState[id] })); + }; + + const isOpen = openNodes[row.id] || false; + + return ( + <React.Fragment> + <StyledTableRow hover tabIndex={-1} key={row.id}> + <StyledTableCell sx={{ padding: 0 }}> + {row.children && ( + <IconButton + aria-label="expand row" + size="small" + onClick={() => toggleNode(row.id)} + > + {isOpen ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />} + </IconButton> + )} + </StyledTableCell> + {columns.map((column, idx) => { + if (column.id !== 'actions') { + let value = row[column.id]; + if (column.id === 'name' && row['type'] === 0) { + value = translate(value); + } + return ( + <StyledTableCell + key={column.id} + align={column.align || 'left'} + style={{ + paddingLeft: idx === 0 && (depth * 16 + 16), + opacity: column.id === 'icon' && .6 + }} + onClick={() => toggleNode(row.id)} + > + {column.format ? column.format(value) : value} + </StyledTableCell> + ) + } + })} + <StyledTableCell> + <Tooltip title="Edit"> + <IconButton onClick={() => onEdit(row)}> + <Edit /> + </IconButton> + </Tooltip> + <Tooltip title="Delete"> + <IconButton onClick={() => onDelete(row)}> + <Delete /> + </IconButton> + </Tooltip> + </StyledTableCell> + </StyledTableRow> + {row.children && isOpen && ( + row.children.map((child) => ( + <TreeTableRow + key={child.id} + row={child} + depth={depth + 1} + onEdit={onEdit} + onDelete={onDelete} + openNodes={openNodes} + setOpenNodes={setOpenNodes} + /> + )) + )} + </React.Fragment> + ); +}; const MatnrGroupList = () => { const translate = useTranslate(); + const notify = useNotify(); + const redirect = useRedirect(); + const refresh = useRefresh(); + const [deleteOne] = useDelete(); - const [createDialog, setCreateDialog] = useState(false); - const [drawerVal, setDrawerVal] = useState(false); + const [treeData, setTreeData] = React.useState(null); + const [filter, setFilter] = React.useState(""); + const [createDialog, setCreateDialog] = React.useState(false); + const [editRecord, setEditRecord] = React.useState(null); + const [openNodes, setOpenNodes] = React.useState({}); + const [expandAll, setExpandAll] = React.useState(false); + + const http = async () => { + const res = await request.post(RESOURCE + '/tree', { + condition: filter + }); + if (res?.data?.code === 200) { + setTreeData(res.data.data); + } else { + notify(res.data.msg); + } + } + + React.useEffect(() => { + http(); + }, [filter]); + + const handleRefresh = () => { + http(); + }; + + const handleAdd = () => { + setEditRecord(null); + setCreateDialog(true); + }; + + const handleEdit = (node) => { + setEditRecord(node); + setCreateDialog(true); + }; + + const handleDelete = (node) => { + if (window.confirm(translate('ra.message.delete_content'))) { + deleteOne( + RESOURCE, + { id: node.id }, + { + onSuccess: () => { + handleRefresh(); + notify('Department deleted successfully', { type: 'info', messageArgs: { _: 'Department deleted successfully' } }); + }, + onError: (error) => { + notify(`Error: ${error.message}`, { type: 'warning', messageArgs: { _: `Error: ${error.message}` } }); + }, + } + ); + } + }; + + const toggleExpandAll = () => { + setExpandAll(prevExpandAll => { + const newExpandAll = !prevExpandAll; + const newOpenNodes = {}; + const updateOpenNodes = (nodes) => { + nodes.forEach(node => { + newOpenNodes[node.id] = newExpandAll; + if (node.children) { + updateOpenNodes(node.children); + } + }); + }; + updateOpenNodes(treeData); + setOpenNodes(newOpenNodes); + return newExpandAll; + }); + }; 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.matnrGroup"} - empty={<EmptyData onClick={() => { setCreateDialog(true) }} />} - filters={filters} - sort={{ field: "create_time", order: "desc" }} - actions={( - <TopToolbar> - <FilterButton /> - <MyCreateButton onClick={() => { setCreateDialog(true) }} /> - <SelectColumnsButton preferenceKey='matnrGroup' /> - <MyExportButton /> - </TopToolbar> - )} - perPage={DEFAULT_PAGE_SIZE} - > - <StyledDatagrid - preferenceKey='matnrGroup' - bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />} - rowClick={(id, resource, record) => false} - expand={() => <MatnrGroupPanel />} - expandSingle={true} - omit={['id', 'createTime', 'createBy', 'memo']} - > - <NumberField source="id" /> - <TextField source="name" label="table.field.matnrGroup.name" /> - <TextField source="code" label="table.field.matnrGroup.code" /> - <NumberField source="parentId" label="table.field.matnrGroup.parentId" /> - - <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> - <MatnrGroupCreate + <div> + <MatnrGroupEdit + editRecord={editRecord} open={createDialog} setOpen={setCreateDialog} + callback={() => { + handleRefresh(); + }} + resource={RESOURCE} /> - <PageDrawer - title='MatnrGroup Detail' - drawerVal={drawerVal} - setDrawerVal={setDrawerVal} - > - </PageDrawer> - </Box> - ) + <Title title={TITLE} /> + <Box sx={{ mt: 2, mr: 3, mb: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> + <Box width={300} > + <Button + variant="outlined" + color="primary" + startIcon={expandAll ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />} + onClick={toggleExpandAll} + sx={{ ml: 1 }} + > + {expandAll ? translate('common.action.collapseAll') : translate('common.action.expandAll')} + </Button> + {/* <TextField + label="Search" + value={filter} + onChange={({ target }) => { + setFilter(target.value) + }} + variant="filled" + size="small" + margin="dense" + fullWidth + /> */} + </Box> + <Box> + <Button + variant="outlined" + color="primary" + startIcon={<RefreshIcon />} + onClick={handleRefresh} + sx={{ ml: 1 }} + > + {translate('ra.action.refresh')} + </Button> + <Button + variant="outlined" + color="primary" + startIcon={<Add />} + onClick={handleAdd} + sx={{ ml: 1 }} + > + {translate('ra.action.add')} + </Button> + </Box> + </Box> + <Card sx={{ + position: 'relative', + }}> + {!treeData && ( + <LinearProgress + sx={{ + height: "3px", + position: 'absolute', + top: 0, + left: 0, + right: 0, + }} + /> + )} + <TableContainer component={Paper}> + <Table size="small"> + <TableHead> + <TableRow> + <StyledTableCell sx={{ padding: 0, width: 60 }} /> + {columns.map((column, idx) => ( + <StyledTableCell + key={idx} + align={column.align || 'left'} + style={{ + minWidth: column.minWidth + }} + > + {translate(column.label)} + </StyledTableCell> + ))} + </TableRow> + </TableHead> + <TableBody> + {treeData && treeData.length > 0 && ( + treeData.map((row) => ( + <TreeTableRow + key={row.id} + row={row} + onEdit={handleEdit} + onDelete={handleDelete} + openNodes={openNodes} + setOpenNodes={setOpenNodes} + /> + )) + )} + </TableBody> + </Table> + </TableContainer> + </Card> + </div> + ); } export default MatnrGroupList; -- Gitblit v1.9.1