| | |
| | | import * as React from "react"; |
| | | import { useCallback } from "react"; |
| | | import DownloadIcon from "@mui/icons-material/GetApp"; |
| | | import { |
| | | Button, |
| | |
| | | useListContext, |
| | | useUnselectAll, |
| | | } from "react-admin"; |
| | | import { useListReportActionParams } from "./listReport/useListReportOutput"; |
| | | import { |
| | | downloadBlobFile, |
| | | resolveReportMeta, |
| | | } from "./listReport/listReportUtils"; |
| | | |
| | | const MyExportButton = (props) => { |
| | | const { |
| | |
| | | icon = defaultIcon, |
| | | exporter: customExporter, |
| | | meta, |
| | | reportConfig, |
| | | onExport, |
| | | loading = false, |
| | | filename, |
| | | ...rest |
| | | } = props; |
| | | |
| | | const { filter, selectedIds, filterValues, resource, sort, total } = useListContext(); |
| | | const { visibleColumns, params } = useListReportActionParams(reportConfig, { ids }); |
| | | const unSelect = useUnselectAll(resource); |
| | | const dataProvider = useDataProvider(); |
| | | const notify = useNotify(); |
| | | const handleClick = |
| | | // useCallback( |
| | | (event) => { |
| | | dataProvider |
| | | .export(resource, { |
| | | const handleClick = async (event) => { |
| | | try { |
| | | const hasReportConfig = Boolean(reportConfig?.resource && Array.isArray(reportConfig?.columns)); |
| | | if (hasReportConfig) { |
| | | const actionParams = { |
| | | ...params, |
| | | columns: visibleColumns, |
| | | }; |
| | | if (typeof onExport === "function") { |
| | | await onExport(actionParams, event); |
| | | } else { |
| | | const resolvedResource = reportConfig.resource || params.resource; |
| | | const response = await dataProvider.export(resolvedResource, { |
| | | sort: actionParams.sort, |
| | | ids: actionParams.ids, |
| | | filter: actionParams.filter |
| | | ? { ...actionParams.filterValues, ...actionParams.filter } |
| | | : actionParams.filterValues, |
| | | pagination: { page: 1, perPage: maxResults }, |
| | | meta, |
| | | columns: visibleColumns, |
| | | reportMeta: resolveReportMeta(reportConfig, actionParams), |
| | | }); |
| | | downloadBlobFile( |
| | | response, |
| | | filename || reportConfig.exportFileName || `${resolvedResource}.xlsx`, |
| | | ); |
| | | } |
| | | } else { |
| | | const response = await dataProvider.export(resource, { |
| | | sort, |
| | | ids: selectedIds, |
| | | ids: ids ?? selectedIds, |
| | | filter: filter ? { ...filterValues, ...filter } : filterValues, |
| | | pagination: { page: 1, perPage: maxResults }, |
| | | meta, |
| | | }) |
| | | .then((res) => { |
| | | const url = window.URL.createObjectURL( |
| | | new Blob([res.data], { type: res.headers["content-type"] }), |
| | | ); |
| | | const link = document.createElement("a"); |
| | | link.href = url; |
| | | link.setAttribute("download", `${resource}.xlsx`); |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | link.remove(); |
| | | unSelect(); |
| | | }) |
| | | .catch((error) => { |
| | | console.error(error); |
| | | notify("ra.notification.http_error", { type: "error" }); |
| | | }); |
| | | downloadBlobFile(response, filename || `${resource}.xlsx`); |
| | | } |
| | | unSelect(); |
| | | if (typeof onClick === "function") { |
| | | onClick(event); |
| | | } |
| | | } catch (error) { |
| | | console.error(error); |
| | | notify("ra.notification.http_error", { type: "error" }); |
| | | } |
| | | // [ |
| | | // dataProvider, |
| | | // filter, |
| | | // filterValues, |
| | | // maxResults, |
| | | // notify, |
| | | // onClick, |
| | | // resource, |
| | | // sort, |
| | | // meta, |
| | | // ], |
| | | // ); |
| | | }; |
| | | |
| | | const disabled = total === 0 || loading || (reportConfig?.columns && visibleColumns.length === 0); |
| | | |
| | | return ( |
| | | <Button |
| | | onClick={handleClick} |
| | | label={label} |
| | | disabled={total === 0} |
| | | disabled={disabled} |
| | | {...sanitizeRestProps(rest)} |
| | | > |
| | | {icon} |
| New file |
| | |
| | | import React from "react"; |
| | | import { FilterButton, SelectColumnsButton, TopToolbar } from "react-admin"; |
| | | import MyExportButton from "@/page/components/MyExportButton"; |
| | | import MyPrintButton from "./MyPrintButton"; |
| | | |
| | | export const ListReportActions = ({ |
| | | reportConfig, |
| | | loading = false, |
| | | onExport, |
| | | onPrintPreview, |
| | | showFilterButton = true, |
| | | showSelectColumnsButton = true, |
| | | children, |
| | | }) => ( |
| | | <TopToolbar> |
| | | {showFilterButton && <FilterButton />} |
| | | {showSelectColumnsButton && reportConfig?.preferenceKey && ( |
| | | <SelectColumnsButton preferenceKey={reportConfig.preferenceKey} /> |
| | | )} |
| | | {reportConfig?.enablePrint && ( |
| | | <MyPrintButton |
| | | reportConfig={reportConfig} |
| | | onPrintPreview={onPrintPreview} |
| | | loading={loading} |
| | | /> |
| | | )} |
| | | <MyExportButton |
| | | reportConfig={reportConfig} |
| | | onExport={onExport} |
| | | loading={loading} |
| | | /> |
| | | {children} |
| | | </TopToolbar> |
| | | ); |
| | | |
| | | export const ListReportBulkActions = ({ |
| | | reportConfig, |
| | | loading = false, |
| | | onExport, |
| | | onPrintPreview, |
| | | }) => ( |
| | | <> |
| | | {reportConfig?.enablePrint && ( |
| | | <MyPrintButton |
| | | reportConfig={reportConfig} |
| | | onPrintPreview={onPrintPreview} |
| | | loading={loading} |
| | | /> |
| | | )} |
| | | <MyExportButton |
| | | reportConfig={reportConfig} |
| | | onExport={onExport} |
| | | loading={loading} |
| | | /> |
| | | </> |
| | | ); |
| | | |
| | | export default ListReportActions; |
| New file |
| | |
| | | import React, { useEffect, useMemo, useRef, useState } from "react"; |
| | | import { useTranslate } from "react-admin"; |
| | | import { |
| | | Box, |
| | | Button, |
| | | CircularProgress, |
| | | Dialog, |
| | | DialogActions, |
| | | DialogContent, |
| | | DialogTitle, |
| | | ToggleButton, |
| | | ToggleButtonGroup, |
| | | Typography, |
| | | } from "@mui/material"; |
| | | import PrintOutlinedIcon from "@mui/icons-material/PrintOutlined"; |
| | | import { useReactToPrint } from "react-to-print"; |
| | | import DialogCloseButton from "@/page/components/DialogCloseButton"; |
| | | import { getListReportCellValue } from "./listReportUtils"; |
| | | |
| | | const PREVIEW_LAYOUT = { |
| | | landscape: { |
| | | width: "297mm", |
| | | height: "210mm", |
| | | }, |
| | | portrait: { |
| | | width: "210mm", |
| | | height: "297mm", |
| | | }, |
| | | }; |
| | | |
| | | const PRINT_PAGE_MARGIN = "12mm"; |
| | | |
| | | const buildPrintPageStyle = orientation => ` |
| | | @page { |
| | | size: A4 ${orientation}; |
| | | margin: 0; |
| | | } |
| | | @media print { |
| | | html, body { |
| | | width: auto; |
| | | min-height: auto; |
| | | height: auto; |
| | | margin: 0 !important; |
| | | padding: 0 !important; |
| | | -webkit-print-color-adjust: exact; |
| | | print-color-adjust: exact; |
| | | background: #ffffff; |
| | | } |
| | | table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | } |
| | | thead { |
| | | display: table-header-group; |
| | | } |
| | | .list-report-print-shell { |
| | | display: block !important; |
| | | padding: 0 !important; |
| | | width: 100% !important; |
| | | max-width: none !important; |
| | | margin: 0 auto !important; |
| | | } |
| | | .list-report-print-live-root { |
| | | position: static !important; |
| | | left: auto !important; |
| | | top: auto !important; |
| | | visibility: visible !important; |
| | | background: #ffffff !important; |
| | | } |
| | | .list-report-print-page { |
| | | box-shadow: none !important; |
| | | border: none !important; |
| | | margin: 0 auto !important; |
| | | break-after: page; |
| | | page-break-after: always; |
| | | overflow: hidden !important; |
| | | box-sizing: border-box !important; |
| | | } |
| | | .list-report-print-page:last-child { |
| | | break-after: auto; |
| | | page-break-after: auto; |
| | | } |
| | | .list-report-print-header { |
| | | page-break-inside: avoid !important; |
| | | break-inside: avoid !important; |
| | | } |
| | | .list-report-print-table-wrap { |
| | | overflow: visible !important; |
| | | } |
| | | .list-report-print-table { |
| | | width: 100% !important; |
| | | table-layout: fixed !important; |
| | | } |
| | | .list-report-print-table thead { |
| | | display: table-header-group !important; |
| | | } |
| | | .list-report-print-table tr { |
| | | page-break-inside: avoid !important; |
| | | break-inside: avoid !important; |
| | | } |
| | | } |
| | | `; |
| | | |
| | | const getPageBoxSx = (paperSize, printable = false) => ({ |
| | | display: "flex", |
| | | flexDirection: "column", |
| | | width: paperSize.width, |
| | | height: paperSize.height, |
| | | maxWidth: "100%", |
| | | mx: "auto", |
| | | p: PRINT_PAGE_MARGIN, |
| | | backgroundColor: "#fff", |
| | | boxShadow: printable ? "none" : "0 8px 24px rgba(15, 23, 42, 0.08)", |
| | | border: printable ? "none" : "1px solid #d7dce2", |
| | | boxSizing: "border-box", |
| | | overflow: "hidden", |
| | | }); |
| | | |
| | | const ReportHeader = ({ printedAt, reportMeta, totalCount }) => ( |
| | | <> |
| | | <Box className="list-report-print-header" sx={{ borderBottom: "2px solid #111", pb: 1.25 }}> |
| | | <Typography |
| | | variant="h5" |
| | | sx={{ |
| | | textAlign: "center", |
| | | fontWeight: 700, |
| | | letterSpacing: ".02em", |
| | | color: "#111827", |
| | | }} |
| | | > |
| | | {reportMeta?.title || "报表"} |
| | | </Typography> |
| | | </Box> |
| | | |
| | | <Box |
| | | className="list-report-print-header" |
| | | sx={{ |
| | | display: "flex", |
| | | justifyContent: "space-between", |
| | | gap: 2, |
| | | flexWrap: "wrap", |
| | | borderBottom: "1px solid #111", |
| | | pb: 1, |
| | | color: "#111827", |
| | | fontSize: 14, |
| | | }} |
| | | > |
| | | <Typography variant="body2">报表日期:{reportMeta?.reportDate || printedAt}</Typography> |
| | | <Typography variant="body2">打印人:{reportMeta?.printedBy || "-"}</Typography> |
| | | <Typography variant="body2">打印时间:{printedAt}</Typography> |
| | | <Typography variant="body2">记录数:{totalCount}</Typography> |
| | | </Box> |
| | | </> |
| | | ); |
| | | |
| | | const ReportTable = ({ displayColumns, pageRows, renderRow, tableWrapRef, theadRef, tbodyRef }) => ( |
| | | <Box ref={tableWrapRef} className="list-report-print-table-wrap" sx={{ overflow: "hidden", flex: 1 }}> |
| | | <table |
| | | className="list-report-print-table" |
| | | style={{ |
| | | width: "100%", |
| | | borderCollapse: "collapse", |
| | | tableLayout: "fixed", |
| | | fontSize: "12px", |
| | | }} |
| | | > |
| | | <thead ref={theadRef}> |
| | | <tr> |
| | | {displayColumns.map(column => ( |
| | | <th |
| | | key={column.key} |
| | | style={{ |
| | | padding: "8px 8px", |
| | | backgroundColor: "#f1f3f5", |
| | | textAlign: "center", |
| | | whiteSpace: "normal", |
| | | fontWeight: 700, |
| | | color: "#111827", |
| | | }} |
| | | > |
| | | {column.label} |
| | | </th> |
| | | ))} |
| | | </tr> |
| | | </thead> |
| | | <tbody ref={tbodyRef}> |
| | | {pageRows.map(renderRow)} |
| | | </tbody> |
| | | </table> |
| | | </Box> |
| | | ); |
| | | |
| | | const ReportPageFrame = ({ children, paperSize, printable = false }) => ( |
| | | <Box className="list-report-print-page" sx={getPageBoxSx(paperSize, printable)}> |
| | | <Box sx={{ display: "flex", flexDirection: "column", gap: 2, width: "100%", height: "100%" }}> |
| | | {children} |
| | | </Box> |
| | | </Box> |
| | | ); |
| | | |
| | | const ListReportPreviewDialog = ({ |
| | | open, |
| | | onClose, |
| | | rows = [], |
| | | columns = [], |
| | | reportMeta, |
| | | totalRows = 0, |
| | | loading = false, |
| | | allRowsLoaded = false, |
| | | loadedTransportPages = 0, |
| | | totalTransportPages = 0, |
| | | prefetching = false, |
| | | dialogTitle = "打印预览", |
| | | defaultOrientation = "landscape", |
| | | getCellValue = getListReportCellValue, |
| | | }) => { |
| | | const translate = useTranslate(); |
| | | const printContentRef = useRef(null); |
| | | const measurePageRef = useRef(null); |
| | | const measureContentRef = useRef(null); |
| | | const measureTableWrapRef = useRef(null); |
| | | const measureTheadRef = useRef(null); |
| | | const measureBodyRef = useRef(null); |
| | | const measureFooterRef = useRef(null); |
| | | const [orientation, setOrientation] = useState(defaultOrientation); |
| | | const [currentPage, setCurrentPage] = useState(1); |
| | | const [isPreparingPrint, setIsPreparingPrint] = useState(false); |
| | | const [measuring, setMeasuring] = useState(false); |
| | | const [paginatedRows, setPaginatedRows] = useState([]); |
| | | |
| | | const printedAt = useMemo( |
| | | () => |
| | | new Date().toLocaleString("zh-CN", { |
| | | hour12: false, |
| | | }), |
| | | [open] |
| | | ); |
| | | |
| | | const previewPaperSize = useMemo( |
| | | () => PREVIEW_LAYOUT[orientation] || PREVIEW_LAYOUT.landscape, |
| | | [orientation] |
| | | ); |
| | | |
| | | const displayColumns = useMemo( |
| | | () => [{ key: "__serialNo", label: "序号", source: "__serialNo" }, ...columns], |
| | | [columns] |
| | | ); |
| | | |
| | | const totalCount = totalRows || rows.length; |
| | | const currentPageRows = paginatedRows[Math.max(currentPage - 1, 0)] || []; |
| | | |
| | | useEffect(() => { |
| | | if (!open) { |
| | | setCurrentPage(1); |
| | | setPaginatedRows([]); |
| | | setIsPreparingPrint(false); |
| | | setOrientation(defaultOrientation); |
| | | } |
| | | }, [defaultOrientation, open]); |
| | | |
| | | useEffect(() => { |
| | | if (currentPage > paginatedRows.length) { |
| | | setCurrentPage(Math.max(paginatedRows.length, 1)); |
| | | } |
| | | }, [currentPage, paginatedRows.length]); |
| | | |
| | | useEffect(() => { |
| | | if (!open) { |
| | | return undefined; |
| | | } |
| | | if (rows.length === 0 || columns.length === 0) { |
| | | setPaginatedRows([]); |
| | | setMeasuring(false); |
| | | return undefined; |
| | | } |
| | | |
| | | setMeasuring(true); |
| | | const frameId = requestAnimationFrame(() => { |
| | | const pageElement = measurePageRef.current; |
| | | const contentElement = measureContentRef.current; |
| | | const tableWrapElement = measureTableWrapRef.current; |
| | | const tableHeadElement = measureTheadRef.current; |
| | | const tableBodyElement = measureBodyRef.current; |
| | | const footerElement = measureFooterRef.current; |
| | | |
| | | if (!pageElement || !contentElement || !tableWrapElement || !tableHeadElement || !tableBodyElement || !footerElement) { |
| | | setPaginatedRows([rows]); |
| | | setMeasuring(false); |
| | | return; |
| | | } |
| | | |
| | | const availableBodyHeight = Math.max( |
| | | contentElement.clientHeight - |
| | | tableWrapElement.offsetTop - |
| | | tableHeadElement.offsetHeight - |
| | | footerElement.offsetHeight, |
| | | 80 |
| | | ); |
| | | |
| | | const rowHeights = Array.from(tableBodyElement.querySelectorAll("tr")).map( |
| | | row => row.getBoundingClientRect().height || row.offsetHeight || 24 |
| | | ); |
| | | |
| | | const nextPages = []; |
| | | let pageRows = []; |
| | | let usedHeight = 0; |
| | | |
| | | rows.forEach((record, index) => { |
| | | const rowHeight = rowHeights[index] || 24; |
| | | const exceedsCurrentPage = |
| | | pageRows.length > 0 && usedHeight + rowHeight > availableBodyHeight; |
| | | |
| | | if (exceedsCurrentPage) { |
| | | nextPages.push(pageRows); |
| | | pageRows = [record]; |
| | | usedHeight = rowHeight; |
| | | return; |
| | | } |
| | | |
| | | pageRows.push(record); |
| | | usedHeight += rowHeight; |
| | | }); |
| | | |
| | | if (pageRows.length > 0) { |
| | | nextPages.push(pageRows); |
| | | } |
| | | |
| | | setPaginatedRows(nextPages); |
| | | setMeasuring(false); |
| | | }); |
| | | |
| | | return () => cancelAnimationFrame(frameId); |
| | | }, [columns.length, defaultOrientation, open, orientation, reportMeta?.printedBy, reportMeta?.reportDate, reportMeta?.title, rows]); |
| | | |
| | | const handlePrint = useReactToPrint({ |
| | | content: () => printContentRef.current, |
| | | documentTitle: reportMeta?.title || dialogTitle, |
| | | pageStyle: buildPrintPageStyle(orientation), |
| | | onAfterPrint: () => { |
| | | setIsPreparingPrint(false); |
| | | }, |
| | | }); |
| | | |
| | | useEffect(() => { |
| | | if (!isPreparingPrint || paginatedRows.length === 0) { |
| | | return undefined; |
| | | } |
| | | |
| | | const firstFrame = requestAnimationFrame(() => { |
| | | const secondFrame = requestAnimationFrame(() => { |
| | | handlePrint(); |
| | | }); |
| | | return () => cancelAnimationFrame(secondFrame); |
| | | }); |
| | | |
| | | return () => cancelAnimationFrame(firstFrame); |
| | | }, [handlePrint, isPreparingPrint, paginatedRows]); |
| | | |
| | | const renderDataRow = (record, rowIndex, serialStart, keyPrefix) => ( |
| | | <tr key={record.id ?? `${keyPrefix}-row-${rowIndex}`}> |
| | | {displayColumns.map(column => ( |
| | | <td |
| | | key={`${record.id ?? keyPrefix}-${column.key}-${rowIndex}`} |
| | | style={{ |
| | | padding: "6px 8px", |
| | | verticalAlign: "top", |
| | | whiteSpace: "normal", |
| | | wordBreak: "break-word", |
| | | textAlign: column.key === "__serialNo" ? "center" : "left", |
| | | color: "#111827", |
| | | }} |
| | | > |
| | | {column.key === "__serialNo" |
| | | ? String(serialStart + rowIndex + 1).padStart(3, "0") |
| | | : String(getCellValue(record, column.source))} |
| | | </td> |
| | | ))} |
| | | </tr> |
| | | ); |
| | | |
| | | const renderPage = (pageRows, pageIndex, pageCount, printable = false) => { |
| | | const serialStart = paginatedRows.slice(0, pageIndex).reduce((sum, page) => sum + page.length, 0); |
| | | return ( |
| | | <ReportPageFrame key={`preview-page-${pageIndex + 1}`} paperSize={previewPaperSize} printable={printable}> |
| | | <ReportHeader printedAt={printedAt} reportMeta={reportMeta} totalCount={totalCount} /> |
| | | <ReportTable |
| | | displayColumns={displayColumns} |
| | | pageRows={pageRows} |
| | | renderRow={(record, rowIndex) => |
| | | renderDataRow(record, rowIndex, serialStart, `page-${pageIndex + 1}`) |
| | | } |
| | | /> |
| | | <Box |
| | | sx={{ |
| | | display: "flex", |
| | | justifyContent: "flex-end", |
| | | color: "#6b7280", |
| | | fontSize: 12, |
| | | }} |
| | | > |
| | | 第 {pageIndex + 1} / {pageCount} 页 |
| | | </Box> |
| | | </ReportPageFrame> |
| | | ); |
| | | }; |
| | | |
| | | const printDisabled = |
| | | loading || |
| | | prefetching || |
| | | measuring || |
| | | isPreparingPrint || |
| | | !allRowsLoaded || |
| | | paginatedRows.length === 0 || |
| | | columns.length === 0; |
| | | |
| | | const printButtonLabel = (() => { |
| | | if (isPreparingPrint) { |
| | | return "准备打印中..."; |
| | | } |
| | | if (prefetching || !allRowsLoaded) { |
| | | return `加载打印数据中... ${loadedTransportPages}/${Math.max(totalTransportPages, 1)}`; |
| | | } |
| | | if (measuring) { |
| | | return "分页计算中..."; |
| | | } |
| | | return translate("toolbar.print"); |
| | | })(); |
| | | |
| | | return ( |
| | | <Dialog open={open} onClose={onClose} fullWidth maxWidth="xl"> |
| | | <DialogTitle |
| | | sx={{ |
| | | position: "sticky", |
| | | top: 0, |
| | | backgroundColor: "background.paper", |
| | | zIndex: 1, |
| | | textAlign: "center", |
| | | }} |
| | | > |
| | | {dialogTitle} |
| | | <Box sx={{ position: "absolute", right: 8, top: 8 }}> |
| | | <DialogCloseButton onClose={onClose} /> |
| | | </Box> |
| | | </DialogTitle> |
| | | <DialogContent dividers> |
| | | {loading ? ( |
| | | <Box |
| | | sx={{ |
| | | minHeight: 280, |
| | | display: "flex", |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | }} |
| | | > |
| | | <CircularProgress size={28} /> |
| | | </Box> |
| | | ) : ( |
| | | <Box |
| | | className="list-report-print-shell" |
| | | sx={{ |
| | | display: "flex", |
| | | flexDirection: "column", |
| | | gap: 2, |
| | | alignItems: "center", |
| | | py: 3, |
| | | }} |
| | | > |
| | | {paginatedRows.length > 0 |
| | | ? renderPage( |
| | | currentPageRows, |
| | | Math.max(currentPage - 1, 0), |
| | | Math.max(paginatedRows.length, 1) |
| | | ) |
| | | : ( |
| | | <Box |
| | | sx={{ |
| | | minHeight: 280, |
| | | display: "flex", |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | color: "#6b7280", |
| | | }} |
| | | > |
| | | {prefetching || measuring ? "正在生成预览..." : "暂无可打印数据"} |
| | | </Box> |
| | | )} |
| | | </Box> |
| | | )} |
| | | </DialogContent> |
| | | <DialogActions sx={{ px: 3, py: 2, justifyContent: "space-between", gap: 2, flexWrap: "wrap" }}> |
| | | <Box sx={{ display: "flex", gap: 2, alignItems: "center", flexWrap: "wrap" }}> |
| | | <ToggleButtonGroup |
| | | value={orientation} |
| | | exclusive |
| | | size="small" |
| | | onChange={(_, value) => { |
| | | if (value) { |
| | | setCurrentPage(1); |
| | | setOrientation(value); |
| | | } |
| | | }} |
| | | > |
| | | <ToggleButton value="landscape">横版</ToggleButton> |
| | | <ToggleButton value="portrait">竖版</ToggleButton> |
| | | </ToggleButtonGroup> |
| | | <Button |
| | | size="small" |
| | | onClick={() => setCurrentPage(page => Math.max(1, page - 1))} |
| | | disabled={loading || currentPage <= 1} |
| | | > |
| | | 上一页 |
| | | </Button> |
| | | <Typography variant="body2" sx={{ minWidth: 104, textAlign: "center" }}> |
| | | 第 {paginatedRows.length === 0 ? 0 : currentPage} / {paginatedRows.length} 页 |
| | | </Typography> |
| | | <Button |
| | | size="small" |
| | | onClick={() => setCurrentPage(page => Math.min(paginatedRows.length, page + 1))} |
| | | disabled={loading || paginatedRows.length === 0 || currentPage >= paginatedRows.length} |
| | | > |
| | | 下一页 |
| | | </Button> |
| | | {(prefetching || measuring) && ( |
| | | <Typography variant="body2" sx={{ color: "#6b7280" }}> |
| | | {prefetching |
| | | ? `正在加载完整打印数据 ${loadedTransportPages}/${Math.max(totalTransportPages, 1)}` |
| | | : "正在按纸张尺寸重新分页"} |
| | | </Typography> |
| | | )} |
| | | </Box> |
| | | <Button |
| | | variant="contained" |
| | | startIcon={ |
| | | isPreparingPrint || prefetching || measuring |
| | | ? <CircularProgress size={16} color="inherit" /> |
| | | : <PrintOutlinedIcon /> |
| | | } |
| | | onClick={() => setIsPreparingPrint(true)} |
| | | disabled={printDisabled} |
| | | > |
| | | {printButtonLabel} |
| | | </Button> |
| | | </DialogActions> |
| | | |
| | | {open && rows.length > 0 && columns.length > 0 && ( |
| | | <Box |
| | | sx={{ |
| | | position: "fixed", |
| | | left: "-20000px", |
| | | top: 0, |
| | | visibility: "hidden", |
| | | pointerEvents: "none", |
| | | backgroundColor: "#fff", |
| | | }} |
| | | > |
| | | <ReportPageFrame paperSize={previewPaperSize} printable> |
| | | <Box ref={measurePageRef} sx={{ width: "100%", height: "100%" }}> |
| | | <Box ref={measureContentRef} sx={{ display: "flex", flexDirection: "column", gap: 2, width: "100%", height: "100%" }}> |
| | | <ReportHeader printedAt={printedAt} reportMeta={reportMeta} totalCount={totalCount} /> |
| | | <ReportTable |
| | | displayColumns={displayColumns} |
| | | pageRows={rows} |
| | | renderRow={(record, rowIndex) => renderDataRow(record, rowIndex, 0, "measure")} |
| | | tableWrapRef={measureTableWrapRef} |
| | | theadRef={measureTheadRef} |
| | | tbodyRef={measureBodyRef} |
| | | /> |
| | | <Box |
| | | ref={measureFooterRef} |
| | | sx={{ |
| | | display: "flex", |
| | | justifyContent: "flex-end", |
| | | color: "#6b7280", |
| | | fontSize: 12, |
| | | }} |
| | | > |
| | | 第 1 / 1 页 |
| | | </Box> |
| | | </Box> |
| | | </Box> |
| | | </ReportPageFrame> |
| | | </Box> |
| | | )} |
| | | |
| | | {isPreparingPrint && ( |
| | | <Box |
| | | ref={printContentRef} |
| | | className="list-report-print-shell list-report-print-live-root" |
| | | sx={{ |
| | | position: "fixed", |
| | | left: "-10000px", |
| | | top: 0, |
| | | backgroundColor: "#fff", |
| | | px: 3, |
| | | py: 3, |
| | | }} |
| | | > |
| | | {paginatedRows.map((pageRows, pageIndex) => |
| | | renderPage(pageRows, pageIndex, paginatedRows.length, true) |
| | | )} |
| | | </Box> |
| | | )} |
| | | </Dialog> |
| | | ); |
| | | }; |
| | | |
| | | export default ListReportPreviewDialog; |
| New file |
| | |
| | | import React from "react"; |
| | | import PrintOutlinedIcon from "@mui/icons-material/PrintOutlined"; |
| | | import { Button } from "react-admin"; |
| | | import { useListReportActionParams } from "./useListReportOutput"; |
| | | |
| | | const MyPrintButton = ({ |
| | | reportConfig, |
| | | onPrintPreview, |
| | | label = "toolbar.print", |
| | | icon = <PrintOutlinedIcon />, |
| | | loading = false, |
| | | disabled, |
| | | ...rest |
| | | }) => { |
| | | const { visibleColumns, params } = useListReportActionParams(reportConfig); |
| | | const resolvedDisabled = disabled ?? ( |
| | | params.total === 0 || |
| | | loading || |
| | | visibleColumns.length === 0 |
| | | ); |
| | | |
| | | if (!reportConfig?.enablePrint) { |
| | | return null; |
| | | } |
| | | |
| | | return ( |
| | | <Button |
| | | onClick={() => onPrintPreview({ ...params, columns: visibleColumns })} |
| | | label={label} |
| | | disabled={resolvedDisabled} |
| | | {...rest} |
| | | > |
| | | {icon} |
| | | </Button> |
| | | ); |
| | | }; |
| | | |
| | | export default MyPrintButton; |
| New file |
| | |
| | | import * as Common from "@/utils/common"; |
| | | |
| | | export const DEFAULT_PRINT_PREVIEW_FETCH_PAGE_SIZE = 100; |
| | | |
| | | export const downloadBlobFile = (response, filename) => { |
| | | const blob = new Blob([response.data], { type: response.headers["content-type"] }); |
| | | const url = window.URL.createObjectURL(blob); |
| | | const link = document.createElement("a"); |
| | | link.href = url; |
| | | link.setAttribute("download", filename); |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | link.remove(); |
| | | window.URL.revokeObjectURL(url); |
| | | }; |
| | | |
| | | export const buildDefaultReportMeta = title => { |
| | | let user = null; |
| | | try { |
| | | const persistedUser = localStorage.getItem("user"); |
| | | user = persistedUser ? JSON.parse(persistedUser) : null; |
| | | } catch (error) { |
| | | console.warn("Failed to parse persisted user", error); |
| | | } |
| | | |
| | | const tenant = user?.tenant || {}; |
| | | const now = new Date(); |
| | | const year = now.getFullYear(); |
| | | const month = `${now.getMonth() + 1}`.padStart(2, "0"); |
| | | const day = `${now.getDate()}`.padStart(2, "0"); |
| | | |
| | | return { |
| | | companyName: |
| | | tenant?.name || |
| | | tenant?.tenantName || |
| | | tenant?.label || |
| | | user?.fullName || |
| | | "RSF", |
| | | printedBy: user?.fullName || user?.username || "系统用户", |
| | | reportDate: `${year}年${month}月${day}日`, |
| | | reportDateValue: `${year}-${month}-${day}`, |
| | | title, |
| | | }; |
| | | }; |
| | | |
| | | export const buildListReportRequestPayload = ({ |
| | | filter, |
| | | filterValues, |
| | | sort, |
| | | ids, |
| | | columns, |
| | | reportMeta, |
| | | extraPayload = {}, |
| | | }) => ({ |
| | | ...Common.integrateParams({ |
| | | sort, |
| | | filter: filter ? { ...filterValues, ...filter } : filterValues, |
| | | }), |
| | | ids: ids?.length ? ids : undefined, |
| | | columns, |
| | | reportMeta, |
| | | ...extraPayload, |
| | | }); |
| | | |
| | | const getColumnToken = column => column?.key || column?.source; |
| | | |
| | | const resolveColumnByToken = (columnDefs, token) => { |
| | | if (typeof token === "number" || /^\d+$/.test(String(token))) { |
| | | return columnDefs[Number(token)]; |
| | | } |
| | | |
| | | if (typeof token === "string") { |
| | | return columnDefs.find(column => column.key === token || column.source === token); |
| | | } |
| | | |
| | | if (token && typeof token === "object") { |
| | | if ("index" in token) { |
| | | return columnDefs[Number(token.index)]; |
| | | } |
| | | if ("source" in token) { |
| | | return columnDefs.find(column => column.source === token.source); |
| | | } |
| | | if ("key" in token) { |
| | | return columnDefs.find(column => column.key === token.key); |
| | | } |
| | | if ("id" in token) { |
| | | return columnDefs.find(column => column.key === token.id || column.source === token.id); |
| | | } |
| | | } |
| | | |
| | | return undefined; |
| | | }; |
| | | |
| | | const buildDefaultVisibleColumns = (columnDefs, omitSet) => |
| | | columnDefs.filter(column => !omitSet.has(column.source) && !omitSet.has(column.key)); |
| | | |
| | | export const resolveVisibleColumns = ({ |
| | | columnDefs = [], |
| | | storedColumns = [], |
| | | availableColumns = [], |
| | | storedOmit = [], |
| | | omit = [], |
| | | }) => { |
| | | if (!Array.isArray(columnDefs) || columnDefs.length === 0) { |
| | | return []; |
| | | } |
| | | |
| | | const omitSet = new Set([...(omit || []), ...(storedOmit || [])]); |
| | | const fallbackColumns = buildDefaultVisibleColumns(columnDefs, omitSet); |
| | | const storedOrder = Array.isArray(storedColumns) && storedColumns.length > 0 |
| | | ? storedColumns |
| | | : Array.isArray(availableColumns) && availableColumns.length > 0 |
| | | ? availableColumns |
| | | : []; |
| | | |
| | | const resolvedColumns = storedOrder |
| | | .map(token => resolveColumnByToken(columnDefs, token)) |
| | | .filter(Boolean) |
| | | .filter(column => !omitSet.has(column.source) && !omitSet.has(column.key)); |
| | | |
| | | const visibleColumns = resolvedColumns.length > 0 ? resolvedColumns : fallbackColumns; |
| | | |
| | | return visibleColumns.map(column => ({ |
| | | key: column.key, |
| | | source: column.source, |
| | | label: column.label, |
| | | isExtendField: Boolean(column.isExtendField), |
| | | })); |
| | | }; |
| | | |
| | | const getNestedValue = (record, source) => |
| | | source.split(".").reduce((accumulator, segment) => { |
| | | if (accumulator == null) { |
| | | return undefined; |
| | | } |
| | | return accumulator[segment]; |
| | | }, record); |
| | | |
| | | export const getListReportCellValue = (record, source) => { |
| | | if (!record || !source) { |
| | | return ""; |
| | | } |
| | | |
| | | const extendFieldMatch = source.match(/^extendFields\.\[(.+)\]$/); |
| | | if (extendFieldMatch) { |
| | | return record?.extendFields?.[extendFieldMatch[1]] ?? ""; |
| | | } |
| | | |
| | | if (Object.prototype.hasOwnProperty.call(record, source)) { |
| | | return record[source] ?? ""; |
| | | } |
| | | |
| | | const value = source.includes(".") ? getNestedValue(record, source) : record[source]; |
| | | return value ?? ""; |
| | | }; |
| | | |
| | | export const resolveReportMeta = (reportConfig, params) => { |
| | | if (typeof reportConfig?.buildReportMeta === "function") { |
| | | return reportConfig.buildReportMeta(params); |
| | | } |
| | | return reportConfig?.reportMeta || null; |
| | | }; |
| New file |
| | |
| | | import { useCallback, useMemo, useRef, useState } from "react"; |
| | | import { useListContext, useStore } from "react-admin"; |
| | | import request from "@/utils/request"; |
| | | import { |
| | | DEFAULT_PRINT_PREVIEW_FETCH_PAGE_SIZE, |
| | | downloadBlobFile, |
| | | resolveReportMeta, |
| | | resolveVisibleColumns, |
| | | } from "./listReportUtils"; |
| | | |
| | | const getPreferencePath = (preferenceKey, field) => |
| | | `preferences.${preferenceKey || "__listReport__"}.${field}`; |
| | | |
| | | export const useListReportActionParams = (reportConfig, options = {}) => { |
| | | const { ids: explicitIds } = options; |
| | | const { filter, filterValues, resource, selectedIds, sort, total } = useListContext(); |
| | | const [storedColumns] = useStore( |
| | | getPreferencePath(reportConfig?.preferenceKey, "columns"), |
| | | [] |
| | | ); |
| | | const [availableColumns] = useStore( |
| | | getPreferencePath(reportConfig?.preferenceKey, "availableColumns"), |
| | | [] |
| | | ); |
| | | const [storedOmit] = useStore( |
| | | getPreferencePath(reportConfig?.preferenceKey, "omit"), |
| | | [] |
| | | ); |
| | | |
| | | const visibleColumns = useMemo( |
| | | () => |
| | | resolveVisibleColumns({ |
| | | columnDefs: reportConfig?.columns, |
| | | storedColumns, |
| | | availableColumns, |
| | | storedOmit, |
| | | omit: reportConfig?.omit, |
| | | }), |
| | | [availableColumns, reportConfig?.columns, reportConfig?.omit, storedColumns, storedOmit] |
| | | ); |
| | | |
| | | return { |
| | | visibleColumns, |
| | | params: { |
| | | filter, |
| | | filterValues, |
| | | ids: explicitIds ?? selectedIds, |
| | | resource: reportConfig?.resource || resource, |
| | | sort, |
| | | total, |
| | | }, |
| | | }; |
| | | }; |
| | | |
| | | export const useListReportOutput = ({ |
| | | reportConfig, |
| | | buildRequestPayload, |
| | | notify, |
| | | }) => { |
| | | const [exportLoading, setExportLoading] = useState(false); |
| | | const [previewOpen, setPreviewOpen] = useState(false); |
| | | const [previewRows, setPreviewRows] = useState([]); |
| | | const [previewColumns, setPreviewColumns] = useState([]); |
| | | const [previewMeta, setPreviewMeta] = useState(null); |
| | | const [previewDataset, setPreviewDataset] = useState({ |
| | | loadedPages: 0, |
| | | transportPages: 0, |
| | | pageSize: reportConfig?.previewPageSize || DEFAULT_PRINT_PREVIEW_FETCH_PAGE_SIZE, |
| | | total: 0, |
| | | fullyLoaded: false, |
| | | }); |
| | | const [previewLoading, setPreviewLoading] = useState(false); |
| | | const [previewPrefetching, setPreviewPrefetching] = useState(false); |
| | | const requestIdRef = useRef(0); |
| | | const cacheRef = useRef(new Map()); |
| | | |
| | | const previewPageSize = reportConfig?.previewPageSize || DEFAULT_PRINT_PREVIEW_FETCH_PAGE_SIZE; |
| | | |
| | | const buildPayload = useCallback( |
| | | params => { |
| | | const payload = typeof buildRequestPayload === "function" |
| | | ? buildRequestPayload(params) |
| | | : {}; |
| | | if (payload.reportMeta) { |
| | | return payload; |
| | | } |
| | | return { |
| | | ...payload, |
| | | reportMeta: resolveReportMeta(reportConfig, params), |
| | | }; |
| | | }, |
| | | [buildRequestPayload, reportConfig] |
| | | ); |
| | | |
| | | const resetPreviewCache = useCallback(() => { |
| | | cacheRef.current = new Map(); |
| | | setPreviewRows([]); |
| | | setPreviewColumns([]); |
| | | setPreviewMeta(null); |
| | | setPreviewDataset({ |
| | | loadedPages: 0, |
| | | transportPages: 0, |
| | | pageSize: previewPageSize, |
| | | total: 0, |
| | | fullyLoaded: false, |
| | | }); |
| | | }, [previewPageSize]); |
| | | |
| | | const fetchPreviewPage = useCallback( |
| | | async ({ payload, current }) => { |
| | | const { data: { code, data, msg } } = await request.post( |
| | | `/${reportConfig.resource}/print/query`, |
| | | { |
| | | ...payload, |
| | | current, |
| | | pageSize: previewPageSize, |
| | | } |
| | | ); |
| | | |
| | | if (code !== 200) { |
| | | throw new Error(msg || "Print preview query failed"); |
| | | } |
| | | |
| | | return data || {}; |
| | | }, |
| | | [previewPageSize, reportConfig.resource] |
| | | ); |
| | | |
| | | const syncPreviewCache = useCallback( |
| | | ({ totalPages, totalRows }) => { |
| | | const nextRows = []; |
| | | for (let pageIndex = 1; pageIndex <= totalPages; pageIndex += 1) { |
| | | const pageRows = cacheRef.current.get(pageIndex); |
| | | if (Array.isArray(pageRows)) { |
| | | nextRows.push(...pageRows); |
| | | } |
| | | } |
| | | |
| | | setPreviewRows(nextRows); |
| | | setPreviewDataset({ |
| | | loadedPages: cacheRef.current.size, |
| | | transportPages: totalPages, |
| | | pageSize: previewPageSize, |
| | | total: totalRows, |
| | | fullyLoaded: cacheRef.current.size >= totalPages, |
| | | }); |
| | | }, |
| | | [previewPageSize] |
| | | ); |
| | | |
| | | const applyPreviewPage = useCallback( |
| | | ({ data, payload, openPreview = false }) => { |
| | | const current = Number(data.current) || 1; |
| | | const totalPages = Number(data.pages) || 0; |
| | | const totalRows = Number(data.total) || 0; |
| | | |
| | | setPreviewColumns(payload.columns || []); |
| | | setPreviewMeta(payload.reportMeta || null); |
| | | cacheRef.current.set(current, Array.isArray(data.records) ? data.records : []); |
| | | syncPreviewCache({ totalPages, totalRows }); |
| | | |
| | | if (openPreview) { |
| | | setPreviewOpen(true); |
| | | } |
| | | }, |
| | | [syncPreviewCache] |
| | | ); |
| | | |
| | | const prefetchPreviewPages = useCallback( |
| | | async ({ payload, totalPages, totalRows, requestId }) => { |
| | | if (totalPages <= 1) { |
| | | setPreviewPrefetching(false); |
| | | return; |
| | | } |
| | | |
| | | setPreviewPrefetching(true); |
| | | const pendingPages = Array.from({ length: totalPages - 1 }, (_, index) => index + 2); |
| | | const workerCount = Math.min(3, pendingPages.length); |
| | | let hasErrored = false; |
| | | |
| | | const worker = async () => { |
| | | while (pendingPages.length > 0 && requestIdRef.current === requestId) { |
| | | const nextPage = pendingPages.shift(); |
| | | if (!nextPage) { |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | const data = await fetchPreviewPage({ payload, current: nextPage }); |
| | | if (requestIdRef.current !== requestId) { |
| | | return; |
| | | } |
| | | cacheRef.current.set(nextPage, Array.isArray(data.records) ? data.records : []); |
| | | syncPreviewCache({ totalPages, totalRows }); |
| | | } catch (error) { |
| | | if (!hasErrored && requestIdRef.current === requestId) { |
| | | hasErrored = true; |
| | | console.error(error); |
| | | notify(error.message || "ra.notification.http_error", { type: "error" }); |
| | | } |
| | | return; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | await Promise.all(Array.from({ length: workerCount }, () => worker())); |
| | | if (requestIdRef.current === requestId) { |
| | | setPreviewPrefetching(false); |
| | | } |
| | | }, |
| | | [fetchPreviewPage, notify, syncPreviewCache] |
| | | ); |
| | | |
| | | const openPrintPreview = useCallback( |
| | | async params => { |
| | | if (!reportConfig?.enablePrint) { |
| | | return; |
| | | } |
| | | setPreviewLoading(true); |
| | | try { |
| | | requestIdRef.current += 1; |
| | | const requestId = requestIdRef.current; |
| | | resetPreviewCache(); |
| | | const payload = buildPayload(params); |
| | | const data = await fetchPreviewPage({ payload, current: 1 }); |
| | | applyPreviewPage({ data, payload, openPreview: true }); |
| | | prefetchPreviewPages({ |
| | | payload, |
| | | totalPages: Number(data.pages) || 0, |
| | | totalRows: Number(data.total) || 0, |
| | | requestId, |
| | | }); |
| | | } catch (error) { |
| | | console.error(error); |
| | | notify(error.message || "ra.notification.http_error", { type: "error" }); |
| | | } finally { |
| | | setPreviewLoading(false); |
| | | } |
| | | }, |
| | | [ |
| | | applyPreviewPage, |
| | | buildPayload, |
| | | fetchPreviewPage, |
| | | notify, |
| | | prefetchPreviewPages, |
| | | reportConfig?.enablePrint, |
| | | resetPreviewCache, |
| | | ] |
| | | ); |
| | | |
| | | const closePrintPreview = useCallback(() => { |
| | | requestIdRef.current += 1; |
| | | setPreviewPrefetching(false); |
| | | setPreviewOpen(false); |
| | | }, []); |
| | | |
| | | const exportReport = useCallback( |
| | | async params => { |
| | | setExportLoading(true); |
| | | try { |
| | | const payload = buildPayload(params); |
| | | const response = await request.post(`/${reportConfig.resource}/export`, payload, { |
| | | responseType: "blob", |
| | | }); |
| | | downloadBlobFile( |
| | | response, |
| | | reportConfig.exportFileName || `${reportConfig.resource}.xlsx` |
| | | ); |
| | | } catch (error) { |
| | | console.error(error); |
| | | notify("ra.notification.http_error", { type: "error" }); |
| | | } finally { |
| | | setExportLoading(false); |
| | | } |
| | | }, |
| | | [buildPayload, notify, reportConfig.exportFileName, reportConfig.resource] |
| | | ); |
| | | |
| | | return { |
| | | exportLoading, |
| | | previewOpen, |
| | | previewRows, |
| | | previewColumns, |
| | | previewMeta, |
| | | previewDataset, |
| | | previewLoading, |
| | | previewPrefetching, |
| | | openPrintPreview, |
| | | closePrintPreview, |
| | | exportReport, |
| | | }; |
| | | }; |
| | |
| | | import React, { useState, useRef, useEffect, useMemo, useCallback } from "react"; |
| | | import { useNavigate } from 'react-router-dom'; |
| | | import React, { useEffect, useMemo, useState } from "react"; |
| | | import { |
| | | List, |
| | | DatagridConfigurable, |
| | | SearchInput, |
| | | TopToolbar, |
| | | SelectColumnsButton, |
| | | EditButton, |
| | | FilterButton, |
| | | CreateButton, |
| | | ExportButton, |
| | | BulkDeleteButton, |
| | | WrapperField, |
| | | useRecordContext, |
| | | useTranslate, |
| | | useNotify, |
| | | List, |
| | | useListContext, |
| | | FunctionField, |
| | | TextField, |
| | | NumberField, |
| | | DateField, |
| | | BooleanField, |
| | | ReferenceField, |
| | | TextInput, |
| | | DateTimeInput, |
| | | DateInput, |
| | | SelectInput, |
| | | NumberInput, |
| | | ReferenceInput, |
| | | ReferenceArrayInput, |
| | | useRefresh, |
| | | AutocompleteInput, |
| | | DeleteButton, |
| | | } from 'react-admin'; |
| | | import { Box, Typography, Card, Stack, LinearProgress } from '@mui/material'; |
| | | import { styled } from '@mui/material/styles'; |
| | | import WarehouseAreasItemCreate from "./WarehouseAreasItemCreate"; |
| | | import WarehouseAreasItemPanel from "./WarehouseAreasItemPanel"; |
| | | import EmptyData from "../components/EmptyData"; |
| | | import request from '@/utils/request'; |
| | | import MyCreateButton from "../components/MyCreateButton"; |
| | | import MyExportButton from '../components/MyExportButton'; |
| | | import PageDrawer from "../components/PageDrawer"; |
| | | import MyField from "../components/MyField"; |
| | | import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; |
| | | import * as Common from '@/utils/common'; |
| | | import WarehouseIsptResult from "./WarehouseIsptResult" |
| | | useNotify, |
| | | useTranslate, |
| | | } from "react-admin"; |
| | | import { Box, LinearProgress } from "@mui/material"; |
| | | import { styled } from "@mui/material/styles"; |
| | | import { DEFAULT_PAGE_SIZE } from "@/config/setting"; |
| | | import ListReportActions, { |
| | | ListReportBulkActions, |
| | | } from "@/page/components/listReport/ListReportActions"; |
| | | import ListReportPreviewDialog from "@/page/components/listReport/ListReportPreviewDialog"; |
| | | import { useListReportOutput } from "@/page/components/listReport/useListReportOutput"; |
| | | import { buildListReportRequestPayload } from "@/page/components/listReport/listReportUtils"; |
| | | import request from "@/utils/request"; |
| | | import WarehouseIsptResult from "./WarehouseIsptResult"; |
| | | import { |
| | | buildWarehouseAreasItemBaseFilters, |
| | | buildWarehouseAreasItemDynamicFilters, |
| | | buildWarehouseAreasItemReportConfig, |
| | | } from "./warehouseAreasItemOutputUtils.jsx"; |
| | | |
| | | |
| | | const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ |
| | | '& .css-1vooibu-MuiSvgIcon-root': { |
| | | height: '.9em' |
| | | const StyledDatagrid = styled(DatagridConfigurable)(() => ({ |
| | | "& .css-1vooibu-MuiSvgIcon-root": { |
| | | height: ".9em", |
| | | }, |
| | | '& .RaDatagrid-row': { |
| | | cursor: 'auto' |
| | | "& .RaDatagrid-row": { |
| | | cursor: "auto", |
| | | }, |
| | | '& .column-name': { |
| | | "& .opt": { |
| | | width: 200, |
| | | }, |
| | | '& .opt': { |
| | | width: 200 |
| | | "& .MuiTableCell-root": { |
| | | whiteSpace: "nowrap", |
| | | overflow: "visible", |
| | | textOverflow: "unset", |
| | | }, |
| | | '& .MuiTableCell-root': { |
| | | whiteSpace: 'nowrap', |
| | | overflow: 'visible', |
| | | textOverflow: 'unset' |
| | | } |
| | | })); |
| | | |
| | | const filters = [ |
| | | <SearchInput source="condition" alwaysOn />, |
| | | <NumberInput source="areaId" label="table.field.warehouseAreasItem.areaId" />, |
| | | <TextInput source="asnCode" label="table.field.warehouseAreasItem.asnCode" />, |
| | | <TextInput source="areaName" label="table.field.warehouseAreasItem.areaName" />, |
| | | <NumberInput source="matnrId" label="table.field.warehouseAreasItem.matnrId" />, |
| | | <TextInput source="matnrName" label="table.field.warehouseAreasItem.matnrName" />, |
| | | <TextInput source="matnrCode" label="table.field.warehouseAreasItem.matnrCode" />, |
| | | <TextInput source="barcode" label="table.field.warehouseAreasItem.barcode" />, |
| | | <NumberInput source="anfme" label="table.field.warehouseAreasItem.anfme" />, |
| | | <TextInput source="batch" label="table.field.warehouseAreasItem.batch" />, |
| | | <TextInput source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, |
| | | <TextInput source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />, |
| | | <TextInput source="projectCode" label="table.field.asnOrderItem.projectCode" />, |
| | | <TextInput source="unit" label="table.field.warehouseAreasItem.unit" />, |
| | | <TextInput source="stockUnit" label="table.field.warehouseAreasItem.stockUnit" />, |
| | | <TextInput source="brand" label="table.field.warehouseAreasItem.brand" />, |
| | | <ReferenceInput source="shipperId" label="table.field.warehouseAreasItem.shipperId" reference="companys"> |
| | | <AutocompleteInput label="table.field.warehouseAreasItem.shipperId" optionText="name" filterToQuery={(val) => ({ name: val })} /> |
| | | </ReferenceInput>, |
| | | <TextInput source="splrId" label="table.field.warehouseAreasItem.splrId" />, |
| | | <NumberInput source="weight" label="table.field.warehouseAreasItem.weight" />, |
| | | <TextInput source="prodTime" label="table.field.warehouseAreasItem.prodTime" />, |
| | | <TextInput source="splrBtch" label="table.field.warehouseAreasItem.splrBtch" />, |
| | | |
| | | <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 WarehouseAreasItemList = () => { |
| | | const translate = useTranslate(); |
| | | const [itemInfo, setItemInfo] = useState({}) |
| | | const [createDialog, setCreateDialog] = useState(false); |
| | | const notify = useNotify(); |
| | | const [itemInfo] = useState({}); |
| | | const [drawerVal, setDrawerVal] = useState(false); |
| | | const { dynamicFields, dynamicFieldsLoading } = useWarehouseAreasItemDynamicFields(notify); |
| | | |
| | | const filters = useMemo( |
| | | () => [ |
| | | ...buildWarehouseAreasItemBaseFilters(), |
| | | ...buildWarehouseAreasItemDynamicFilters(dynamicFields), |
| | | ], |
| | | [dynamicFields] |
| | | ); |
| | | |
| | | const reportConfig = useMemo( |
| | | () => buildWarehouseAreasItemReportConfig(translate, dynamicFields), |
| | | [dynamicFields, translate] |
| | | ); |
| | | |
| | | const buildOutputPayload = params => buildListReportRequestPayload({ |
| | | ...params, |
| | | reportMeta: reportConfig.buildReportMeta?.(params), |
| | | }); |
| | | |
| | | const { |
| | | exportLoading, |
| | | previewOpen, |
| | | previewRows, |
| | | previewColumns, |
| | | previewMeta, |
| | | previewDataset, |
| | | previewLoading, |
| | | previewPrefetching, |
| | | openPrintPreview, |
| | | closePrintPreview, |
| | | exportReport, |
| | | } = useListReportOutput({ |
| | | reportConfig, |
| | | buildRequestPayload: buildOutputPayload, |
| | | notify, |
| | | }); |
| | | |
| | | const reportLoading = dynamicFieldsLoading || exportLoading || previewLoading; |
| | | |
| | | return ( |
| | | <Box display="flex"> |
| | | <List |
| | | title={"menu.warehouseAreasItem"} |
| | | title="menu.warehouseAreasItem" |
| | | empty={false} |
| | | filters={filters} |
| | | sort={{ field: "create_time", order: "desc" }} |
| | | sx={{ |
| | | flexGrow: 1, |
| | | transition: (theme) => |
| | | theme.transitions.create(['all'], { |
| | | transition: theme => |
| | | theme.transitions.create(["all"], { |
| | | duration: theme.transitions.duration.enteringScreen, |
| | | }), |
| | | }} |
| | | actions={( |
| | | <TopToolbar> |
| | | <FilterButton /> |
| | | <SelectColumnsButton preferenceKey='warehouseAreasItem' /> |
| | | <MyExportButton /> |
| | | </TopToolbar> |
| | | <ListReportActions |
| | | reportConfig={reportConfig} |
| | | loading={reportLoading} |
| | | onExport={exportReport} |
| | | onPrintPreview={openPrintPreview} |
| | | /> |
| | | )} |
| | | perPage={DEFAULT_PAGE_SIZE} |
| | | > |
| | | <DynamicFields |
| | | drawerVal={drawerVal} |
| | | setDrawerVal={setDrawerVal} |
| | | itemInfo={itemInfo} |
| | | setItemInfo={setItemInfo} /> |
| | | reportConfig={reportConfig} |
| | | loading={dynamicFieldsLoading} |
| | | onExport={exportReport} |
| | | onPrintPreview={openPrintPreview} |
| | | /> |
| | | </List> |
| | | <WarehouseAreasItemCreate |
| | | open={createDialog} |
| | | setOpen={setCreateDialog} |
| | | /> |
| | | |
| | | <WarehouseIsptResult |
| | | record={itemInfo} |
| | | drawerVal={drawerVal} |
| | | from="warehosueItem" |
| | | setDrawerVal={setDrawerVal} |
| | | > |
| | | </WarehouseIsptResult> |
| | | {/* <PageDrawer |
| | | title='WarehouseAreasItem Detail' |
| | | drawerVal={drawerVal} |
| | | setDrawerVal={setDrawerVal} |
| | | > |
| | | </PageDrawer> */} |
| | | /> |
| | | |
| | | <ListReportPreviewDialog |
| | | open={previewOpen} |
| | | onClose={closePrintPreview} |
| | | rows={previewRows} |
| | | columns={previewColumns} |
| | | reportMeta={previewMeta} |
| | | totalRows={previewDataset.total} |
| | | loading={previewLoading} |
| | | allRowsLoaded={previewDataset.fullyLoaded} |
| | | loadedTransportPages={previewDataset.loadedPages} |
| | | totalTransportPages={previewDataset.transportPages} |
| | | prefetching={previewPrefetching} |
| | | dialogTitle="收货库存打印预览" |
| | | defaultOrientation={reportConfig.defaultOrientation} |
| | | /> |
| | | </Box> |
| | | ) |
| | | } |
| | | ); |
| | | }; |
| | | |
| | | export default WarehouseAreasItemList; |
| | | |
| | | |
| | | const DynamicFields = (props) => { |
| | | const { drawerVal, setDrawerVal, itemInfo, setItemInfo } = props |
| | | const translate = useTranslate(); |
| | | const notify = useNotify(); |
| | | const [columns, setColumns] = useState([]); |
| | | const DynamicFields = ({ reportConfig, loading, onExport, onPrintPreview }) => { |
| | | const { isLoading } = useListContext(); |
| | | const refresh = useRefresh(); |
| | | useEffect(() => { |
| | | getDynamicFields(); |
| | | }, []); |
| | | |
| | | const getDynamicFields = async () => { |
| | | const { data: { code, data, msg }, } = await request.get("/fields/enable/list"); |
| | | if (code == 200) { |
| | | const arr = [ |
| | | <NumberField key="id" source="id" />, |
| | | // <NumberField key="areaId" source="areaId" label="table.field.warehouseAreasItem.areaId" />, |
| | | <TextField key="areaName" source="areaName" label="收货区名称" />, //table.field.warehouseAreasItem.areaName |
| | | <TextField key="asnCode" source="asnCode" label="table.field.warehouseAreasItem.asnCode" />, |
| | | <TextField source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />, |
| | | <TextField source="platItemId" label="table.field.deliveryItem.platItemId" />, |
| | | <NumberField key="matnrId" source="matnrId" label="table.field.warehouseAreasItem.matnrId" />, |
| | | <TextField key="matnrCode" source="matnrCode" label="table.field.warehouseAreasItem.matnrCode" />, |
| | | <TextField key="maktx" source="maktx" label="table.field.warehouseAreasItem.matnrName" />, |
| | | <TextField key="splrBatch" source="splrBatch" label="table.field.warehouseAreasItem.splrBtch" />, |
| | | <TextField key="batch" source="batch" label="table.field.warehouseAreasItem.batch" />, |
| | | <TextField key="trackCode" source="trackCode" label="table.field.warehouseAreasItem.barcode" />, |
| | | <TextField key="unit" source="unit" label="table.field.warehouseAreasItem.unit" />, |
| | | <NumberField key="anfme" source="anfme" label="table.field.warehouseAreasItem.anfme" />, |
| | | <NumberField key="workQty" source="workQty" label="table.field.warehouseAreasItem.workQty" />, |
| | | <NumberField key="ableQty" source="ableQty" label="table.field.warehouseAreasItem.qty" />, |
| | | <TextField source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, |
| | | <TextField source="projectCode" label="table.field.asnOrderItem.projectCode" />, |
| | | // <MyField source="isptQty" label="table.field.qlyIsptItem.anfme" |
| | | // onClick={(event, record, val) => { |
| | | // event.stopPropagation(); |
| | | // setItemInfo(record) |
| | | // setDrawerVal(!!drawerVal && drawerVal === val ? null : val); |
| | | // }} |
| | | // />, |
| | | |
| | | |
| | | // <TextField key="stockUnit" source="stockUnit" label="table.field.warehouseAreasItem.stockUnit" />, |
| | | <TextField key="brand" source="brand" label="table.field.warehouseAreasItem.brand" />, |
| | | <TextField key="shipperId" source="shipperId" label="table.field.warehouseAreasItem.shipperId" />, |
| | | <TextField key="splrId" source="splrId" label="table.field.warehouseAreasItem.splrId" />, |
| | | <TextField key="isptResult" source="isptResult$" label="table.field.warehouseAreasItem.isptResult" sortable={false} />, |
| | | <NumberField key="weight" source="weight" label="table.field.warehouseAreasItem.weight" />, |
| | | <TextField key="prodTime" source="prodTime" label="table.field.warehouseAreasItem.prodTime" />, |
| | | ] |
| | | const fields = data.map(el => <TextField key={el.fields} source={`extendFields.[${el.fields}]`} label={el.fieldsAlise} />) |
| | | const lastArr = [ |
| | | <TextField key="updateBy" source="updateBy$" label="common.field.updateBy" />, |
| | | <DateField key="updateTime" source="updateTime" label="common.field.updateTime" showTime />, |
| | | <TextField key="createBy" source="createBy$" label="common.field.createBy" />, |
| | | <DateField key="createTime" source="createTime" label="common.field.createTime" showTime />, |
| | | <BooleanField key="statusBool" source="statusBool" label="common.field.status" sortable={false} />, |
| | | <TextField key="memo" source="memo" label="common.field.memo" sortable={false} />, |
| | | ] |
| | | setColumns([...arr, ...fields, ...lastArr]); |
| | | //filters添加过滤字段 |
| | | data.map(el => { |
| | | var i = 0; |
| | | filters.map((item) => { |
| | | if (item.key === el.fields) { |
| | | i = 1; |
| | | } |
| | | }) |
| | | i === 0 && filters.push(<TextInput key={el.fields} source={el.fields} label={el.fieldsAlise} />) |
| | | }) |
| | | } else { |
| | | notify(msg); |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Box sx={{ position: 'relative', minHeight: "82vh", }}> |
| | | {isLoading && ( |
| | | <Box sx={{ position: "relative", minHeight: "82vh" }}> |
| | | {(isLoading || loading) && ( |
| | | <LinearProgress |
| | | sx={{ |
| | | height: "2px", |
| | | position: 'absolute', |
| | | position: "absolute", |
| | | top: 0, |
| | | left: 0, |
| | | right: 0, |
| | | }} |
| | | /> |
| | | )} |
| | | {columns.length > 0 && |
| | | |
| | | {reportConfig.columns.length > 0 && ( |
| | | <StyledDatagrid |
| | | preferenceKey='warehouseAreasItem' |
| | | bulkActionButtons={false} |
| | | rowClick={(id, resource, record) => false} |
| | | omit={['prodTime','platOrderCode','id', 'createTime', 'memo', 'areaId', 'brand', |
| | | 'weight', 'splrId', 'projectCode','statusBool', 'extendFields.[priceUnitId]', 'isptResult$', 'extendFields.[inStockType]', |
| | | 'matnrId', 'trackCode', 'workQty', 'batch', 'shipperId', 'isptResult', 'createBy$', 'createTime', 'extendFields.[baseUnitId]']} |
| | | preferenceKey={reportConfig.preferenceKey} |
| | | bulkActionButtons={( |
| | | <ListReportBulkActions |
| | | reportConfig={reportConfig} |
| | | loading={loading} |
| | | onExport={onExport} |
| | | onPrintPreview={onPrintPreview} |
| | | /> |
| | | )} |
| | | rowClick={false} |
| | | omit={reportConfig.omit} |
| | | > |
| | | {columns.map((column) => column)} |
| | | </StyledDatagrid>} |
| | | {reportConfig.columns.map(column => column.element)} |
| | | </StyledDatagrid> |
| | | )} |
| | | </Box> |
| | | ) |
| | | } |
| | | ); |
| | | }; |
| | | |
| | | const useWarehouseAreasItemDynamicFields = notify => { |
| | | const [dynamicFields, setDynamicFields] = useState([]); |
| | | const [dynamicFieldsLoading, setDynamicFieldsLoading] = useState(true); |
| | | |
| | | useEffect(() => { |
| | | let active = true; |
| | | |
| | | const loadDynamicFields = async () => { |
| | | setDynamicFieldsLoading(true); |
| | | try { |
| | | const { data: { code, data, msg } } = await request.get("/fields/enable/list"); |
| | | if (!active) { |
| | | return; |
| | | } |
| | | if (code === 200) { |
| | | setDynamicFields(Array.isArray(data) ? data : []); |
| | | return; |
| | | } |
| | | notify(msg, { type: "warning" }); |
| | | } catch (error) { |
| | | if (!active) { |
| | | return; |
| | | } |
| | | console.error(error); |
| | | notify("ra.notification.http_error", { type: "error" }); |
| | | } finally { |
| | | if (active) { |
| | | setDynamicFieldsLoading(false); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | loadDynamicFields(); |
| | | return () => { |
| | | active = false; |
| | | }; |
| | | }, [notify]); |
| | | |
| | | return { |
| | | dynamicFields, |
| | | dynamicFieldsLoading, |
| | | }; |
| | | }; |
| New file |
| | |
| | | export { default } from "@/page/components/listReport/ListReportPreviewDialog"; |
| New file |
| | |
| | | import React from "react"; |
| | | import { |
| | | BooleanField, |
| | | DateField, |
| | | NumberField, |
| | | SearchInput, |
| | | SelectInput, |
| | | TextField, |
| | | TextInput, |
| | | NumberInput, |
| | | ReferenceInput, |
| | | AutocompleteInput, |
| | | } from "react-admin"; |
| | | import { buildDefaultReportMeta } from "@/page/components/listReport/listReportUtils"; |
| | | |
| | | export const WAREHOUSE_AREAS_ITEM_PREFERENCE_KEY = "warehouseAreasItem"; |
| | | |
| | | export const WAREHOUSE_AREAS_ITEM_OMIT = [ |
| | | "prodTime", |
| | | "platOrderCode", |
| | | "id", |
| | | "createTime", |
| | | "memo", |
| | | "areaId", |
| | | "brand", |
| | | "weight", |
| | | "splrId", |
| | | "projectCode", |
| | | "statusBool", |
| | | "extendFields.[priceUnitId]", |
| | | "isptResult$", |
| | | "extendFields.[inStockType]", |
| | | "matnrId", |
| | | "trackCode", |
| | | "workQty", |
| | | "batch", |
| | | "shipperId", |
| | | "isptResult", |
| | | "createBy$", |
| | | "createTime", |
| | | "extendFields.[baseUnitId]", |
| | | ]; |
| | | |
| | | const resolveLabel = (translate, label, fallback = "") => { |
| | | if (!label) { |
| | | return fallback; |
| | | } |
| | | const translated = translate(label, { _: label }); |
| | | return translated || fallback || label; |
| | | }; |
| | | |
| | | export const buildWarehouseAreasItemReportMeta = () => { |
| | | return { |
| | | ...buildDefaultReportMeta("收货库存报表"), |
| | | }; |
| | | }; |
| | | |
| | | export const buildWarehouseAreasItemBaseFilters = () => ([ |
| | | <SearchInput key="condition" source="condition" alwaysOn />, |
| | | <NumberInput key="areaId" source="areaId" label="table.field.warehouseAreasItem.areaId" />, |
| | | <TextInput key="asnCode" source="asnCode" label="table.field.warehouseAreasItem.asnCode" />, |
| | | <TextInput key="areaName" source="areaName" label="table.field.warehouseAreasItem.areaName" />, |
| | | <NumberInput key="matnrId" source="matnrId" label="table.field.warehouseAreasItem.matnrId" />, |
| | | <TextInput key="matnrName" source="matnrName" label="table.field.warehouseAreasItem.matnrName" />, |
| | | <TextInput key="matnrCode" source="matnrCode" label="table.field.warehouseAreasItem.matnrCode" />, |
| | | <TextInput key="barcode" source="barcode" label="table.field.warehouseAreasItem.barcode" />, |
| | | <NumberInput key="anfme" source="anfme" label="table.field.warehouseAreasItem.anfme" />, |
| | | <TextInput key="batch" source="batch" label="table.field.warehouseAreasItem.batch" />, |
| | | <TextInput key="platOrderCode" source="platOrderCode" label="table.field.asnOrderItem.platOrderCode" />, |
| | | <TextInput key="platWorkCode" source="platWorkCode" label="table.field.asnOrderItem.platWorkCode" />, |
| | | <TextInput key="projectCode" source="projectCode" label="table.field.asnOrderItem.projectCode" />, |
| | | <TextInput key="unit" source="unit" label="table.field.warehouseAreasItem.unit" />, |
| | | <TextInput key="stockUnit" source="stockUnit" label="table.field.warehouseAreasItem.stockUnit" />, |
| | | <TextInput key="brand" source="brand" label="table.field.warehouseAreasItem.brand" />, |
| | | <ReferenceInput |
| | | key="shipperId" |
| | | source="shipperId" |
| | | label="table.field.warehouseAreasItem.shipperId" |
| | | reference="companys" |
| | | > |
| | | <AutocompleteInput |
| | | label="table.field.warehouseAreasItem.shipperId" |
| | | optionText="name" |
| | | filterToQuery={val => ({ name: val })} |
| | | /> |
| | | </ReferenceInput>, |
| | | <TextInput key="splrId" source="splrId" label="table.field.warehouseAreasItem.splrId" />, |
| | | <NumberInput key="weight" source="weight" label="table.field.warehouseAreasItem.weight" />, |
| | | <TextInput key="prodTime" source="prodTime" label="table.field.warehouseAreasItem.prodTime" />, |
| | | <TextInput key="splrBtch" source="splrBtch" label="table.field.warehouseAreasItem.splrBtch" />, |
| | | <TextInput key="memo" label="common.field.memo" source="memo" />, |
| | | <SelectInput |
| | | key="status" |
| | | label="common.field.status" |
| | | source="status" |
| | | choices={[ |
| | | { id: "1", name: "common.enums.statusTrue" }, |
| | | { id: "0", name: "common.enums.statusFalse" }, |
| | | ]} |
| | | resettable |
| | | />, |
| | | ]); |
| | | |
| | | const createColumnDef = ({ key, source, label, element, isExtendField = false }) => ({ |
| | | key, |
| | | source, |
| | | label, |
| | | isExtendField, |
| | | element, |
| | | }); |
| | | |
| | | export const buildWarehouseAreasItemColumnDefs = (translate, dynamicFields = []) => { |
| | | const baseDefs = [ |
| | | createColumnDef({ |
| | | key: "id", |
| | | source: "id", |
| | | label: "ID", |
| | | element: <NumberField key="id" source="id" label="ID" />, |
| | | }), |
| | | createColumnDef({ |
| | | key: "areaName", |
| | | source: "areaName", |
| | | label: "收货区名称", |
| | | element: <TextField key="areaName" source="areaName" label="收货区名称" />, |
| | | }), |
| | | createColumnDef({ |
| | | key: "asnCode", |
| | | source: "asnCode", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.asnCode"), |
| | | element: ( |
| | | <TextField |
| | | key="asnCode" |
| | | source="asnCode" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.asnCode")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "platWorkCode", |
| | | source: "platWorkCode", |
| | | label: resolveLabel(translate, "table.field.asnOrderItem.platWorkCode"), |
| | | element: ( |
| | | <TextField |
| | | key="platWorkCode" |
| | | source="platWorkCode" |
| | | label={resolveLabel(translate, "table.field.asnOrderItem.platWorkCode")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "platItemId", |
| | | source: "platItemId", |
| | | label: resolveLabel(translate, "table.field.deliveryItem.platItemId"), |
| | | element: ( |
| | | <TextField |
| | | key="platItemId" |
| | | source="platItemId" |
| | | label={resolveLabel(translate, "table.field.deliveryItem.platItemId")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "matnrId", |
| | | source: "matnrId", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.matnrId"), |
| | | element: ( |
| | | <NumberField |
| | | key="matnrId" |
| | | source="matnrId" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.matnrId")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "matnrCode", |
| | | source: "matnrCode", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.matnrCode"), |
| | | element: ( |
| | | <TextField |
| | | key="matnrCode" |
| | | source="matnrCode" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.matnrCode")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "maktx", |
| | | source: "maktx", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.matnrName"), |
| | | element: ( |
| | | <TextField |
| | | key="maktx" |
| | | source="maktx" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.matnrName")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "splrBatch", |
| | | source: "splrBatch", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.splrBtch"), |
| | | element: ( |
| | | <TextField |
| | | key="splrBatch" |
| | | source="splrBatch" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.splrBtch")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "batch", |
| | | source: "batch", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.batch"), |
| | | element: ( |
| | | <TextField |
| | | key="batch" |
| | | source="batch" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.batch")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "trackCode", |
| | | source: "trackCode", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.barcode"), |
| | | element: ( |
| | | <TextField |
| | | key="trackCode" |
| | | source="trackCode" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.barcode")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "unit", |
| | | source: "unit", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.unit"), |
| | | element: ( |
| | | <TextField |
| | | key="unit" |
| | | source="unit" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.unit")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "anfme", |
| | | source: "anfme", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.anfme"), |
| | | element: ( |
| | | <NumberField |
| | | key="anfme" |
| | | source="anfme" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.anfme")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "workQty", |
| | | source: "workQty", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.workQty"), |
| | | element: ( |
| | | <NumberField |
| | | key="workQty" |
| | | source="workQty" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.workQty")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "ableQty", |
| | | source: "ableQty", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.qty"), |
| | | element: ( |
| | | <NumberField |
| | | key="ableQty" |
| | | source="ableQty" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.qty")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "platOrderCode", |
| | | source: "platOrderCode", |
| | | label: resolveLabel(translate, "table.field.asnOrderItem.platOrderCode"), |
| | | element: ( |
| | | <TextField |
| | | key="platOrderCode" |
| | | source="platOrderCode" |
| | | label={resolveLabel(translate, "table.field.asnOrderItem.platOrderCode")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "projectCode", |
| | | source: "projectCode", |
| | | label: resolveLabel(translate, "table.field.asnOrderItem.projectCode"), |
| | | element: ( |
| | | <TextField |
| | | key="projectCode" |
| | | source="projectCode" |
| | | label={resolveLabel(translate, "table.field.asnOrderItem.projectCode")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "brand", |
| | | source: "brand", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.brand"), |
| | | element: ( |
| | | <TextField |
| | | key="brand" |
| | | source="brand" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.brand")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "shipperId", |
| | | source: "shipperId", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.shipperId"), |
| | | element: ( |
| | | <TextField |
| | | key="shipperId" |
| | | source="shipperId" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.shipperId")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "splrId", |
| | | source: "splrId", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.splrId"), |
| | | element: ( |
| | | <TextField |
| | | key="splrId" |
| | | source="splrId" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.splrId")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "isptResult$", |
| | | source: "isptResult$", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.isptResult"), |
| | | element: ( |
| | | <TextField |
| | | key="isptResult$" |
| | | source="isptResult$" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.isptResult")} |
| | | sortable={false} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "weight", |
| | | source: "weight", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.weight"), |
| | | element: ( |
| | | <NumberField |
| | | key="weight" |
| | | source="weight" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.weight")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "prodTime", |
| | | source: "prodTime", |
| | | label: resolveLabel(translate, "table.field.warehouseAreasItem.prodTime"), |
| | | element: ( |
| | | <TextField |
| | | key="prodTime" |
| | | source="prodTime" |
| | | label={resolveLabel(translate, "table.field.warehouseAreasItem.prodTime")} |
| | | /> |
| | | ), |
| | | }), |
| | | ]; |
| | | |
| | | const extendDefs = dynamicFields.map(field => { |
| | | const source = `extendFields.[${field.fields}]`; |
| | | return createColumnDef({ |
| | | key: source, |
| | | source, |
| | | label: field.fieldsAlise || field.fields, |
| | | isExtendField: true, |
| | | element: <TextField key={source} source={source} label={field.fieldsAlise || field.fields} />, |
| | | }); |
| | | }); |
| | | |
| | | const tailDefs = [ |
| | | createColumnDef({ |
| | | key: "updateBy$", |
| | | source: "updateBy$", |
| | | label: resolveLabel(translate, "common.field.updateBy"), |
| | | element: ( |
| | | <TextField |
| | | key="updateBy$" |
| | | source="updateBy$" |
| | | label={resolveLabel(translate, "common.field.updateBy")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "updateTime", |
| | | source: "updateTime", |
| | | label: resolveLabel(translate, "common.field.updateTime"), |
| | | element: ( |
| | | <DateField |
| | | key="updateTime" |
| | | source="updateTime" |
| | | label={resolveLabel(translate, "common.field.updateTime")} |
| | | showTime |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "createBy$", |
| | | source: "createBy$", |
| | | label: resolveLabel(translate, "common.field.createBy"), |
| | | element: ( |
| | | <TextField |
| | | key="createBy$" |
| | | source="createBy$" |
| | | label={resolveLabel(translate, "common.field.createBy")} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "createTime", |
| | | source: "createTime", |
| | | label: resolveLabel(translate, "common.field.createTime"), |
| | | element: ( |
| | | <DateField |
| | | key="createTime" |
| | | source="createTime" |
| | | label={resolveLabel(translate, "common.field.createTime")} |
| | | showTime |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "statusBool", |
| | | source: "statusBool", |
| | | label: resolveLabel(translate, "common.field.status"), |
| | | element: ( |
| | | <BooleanField |
| | | key="statusBool" |
| | | source="statusBool" |
| | | label={resolveLabel(translate, "common.field.status")} |
| | | sortable={false} |
| | | /> |
| | | ), |
| | | }), |
| | | createColumnDef({ |
| | | key: "memo", |
| | | source: "memo", |
| | | label: resolveLabel(translate, "common.field.memo"), |
| | | element: ( |
| | | <TextField |
| | | key="memo" |
| | | source="memo" |
| | | label={resolveLabel(translate, "common.field.memo")} |
| | | sortable={false} |
| | | /> |
| | | ), |
| | | }), |
| | | ]; |
| | | |
| | | return [...baseDefs, ...extendDefs, ...tailDefs]; |
| | | }; |
| | | |
| | | export const buildWarehouseAreasItemDynamicFilters = dynamicFields => |
| | | dynamicFields.map(field => ( |
| | | <TextInput |
| | | key={`filter-${field.fields}`} |
| | | source={field.fields} |
| | | label={field.fieldsAlise || field.fields} |
| | | /> |
| | | )); |
| | | |
| | | export const buildWarehouseAreasItemReportConfig = (translate, dynamicFields = []) => ({ |
| | | resource: "warehouseAreasItem", |
| | | preferenceKey: WAREHOUSE_AREAS_ITEM_PREFERENCE_KEY, |
| | | title: "收货库存报表", |
| | | columns: buildWarehouseAreasItemColumnDefs(translate, dynamicFields), |
| | | omit: WAREHOUSE_AREAS_ITEM_OMIT, |
| | | buildReportMeta: buildWarehouseAreasItemReportMeta, |
| | | enablePrint: true, |
| | | defaultOrientation: "landscape", |
| | | exportFileName: "warehouseAreasItem.xlsx", |
| | | }); |
| New file |
| | |
| | | package com.vincent.rsf.server.common.domain.report; |
| | | |
| | | public class ReportColumnMeta { |
| | | private String key; |
| | | private String source; |
| | | private String label; |
| | | private Boolean isExtendField; |
| | | |
| | | public String getKey() { |
| | | return key; |
| | | } |
| | | |
| | | public void setKey(String key) { |
| | | this.key = key; |
| | | } |
| | | |
| | | public String getSource() { |
| | | return source; |
| | | } |
| | | |
| | | public void setSource(String source) { |
| | | this.source = source; |
| | | } |
| | | |
| | | public String getLabel() { |
| | | return label; |
| | | } |
| | | |
| | | public void setLabel(String label) { |
| | | this.label = label; |
| | | } |
| | | |
| | | public Boolean getIsExtendField() { |
| | | return isExtendField; |
| | | } |
| | | |
| | | public void setIsExtendField(Boolean extendField) { |
| | | isExtendField = extendField; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.common.domain.report; |
| | | |
| | | public class ReportMeta { |
| | | private String title; |
| | | private String companyName; |
| | | private String printedBy; |
| | | private String reportDate; |
| | | private String reportDateValue; |
| | | |
| | | public String getTitle() { |
| | | return title; |
| | | } |
| | | |
| | | public void setTitle(String title) { |
| | | this.title = title; |
| | | } |
| | | |
| | | public String getCompanyName() { |
| | | return companyName; |
| | | } |
| | | |
| | | public void setCompanyName(String companyName) { |
| | | this.companyName = companyName; |
| | | } |
| | | |
| | | public String getPrintedBy() { |
| | | return printedBy; |
| | | } |
| | | |
| | | public void setPrintedBy(String printedBy) { |
| | | this.printedBy = printedBy; |
| | | } |
| | | |
| | | public String getReportDate() { |
| | | return reportDate; |
| | | } |
| | | |
| | | public void setReportDate(String reportDate) { |
| | | this.reportDate = reportDate; |
| | | } |
| | | |
| | | public String getReportDateValue() { |
| | | return reportDateValue; |
| | | } |
| | | |
| | | public void setReportDateValue(String reportDateValue) { |
| | | this.reportDateValue = reportDateValue; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.common.domain.report; |
| | | |
| | | import java.util.*; |
| | | |
| | | public class ReportQueryRequest { |
| | | private Long current = 1L; |
| | | private Long pageSize = 12L; |
| | | private String orderBy; |
| | | private List<Long> ids = new ArrayList<>(); |
| | | private List<ReportColumnMeta> columns = new ArrayList<>(); |
| | | private ReportMeta reportMeta; |
| | | private Map<String, Object> rawParams = new HashMap<>(); |
| | | |
| | | public static ReportQueryRequest fromMap(Map<String, Object> map) { |
| | | ReportQueryRequest request = new ReportQueryRequest(); |
| | | Map<String, Object> safeMap = map == null ? new HashMap<>() : new HashMap<>(map); |
| | | request.setRawParams(safeMap); |
| | | request.setCurrent(parseLong(safeMap.get("current"), 1L)); |
| | | request.setPageSize(parseLong(safeMap.get("pageSize"), 12L)); |
| | | request.setOrderBy(Objects.isNull(safeMap.get("orderBy")) ? null : String.valueOf(safeMap.get("orderBy"))); |
| | | request.setIds(parseIds(safeMap.get("ids"))); |
| | | request.setColumns(parseColumns(safeMap.get("columns"))); |
| | | request.setReportMeta(parseReportMeta(safeMap.get("reportMeta"))); |
| | | return request; |
| | | } |
| | | |
| | | public Map<String, Object> toPageParamMap(boolean includeFilters) { |
| | | Map<String, Object> queryMap = new HashMap<>(rawParams); |
| | | queryMap.remove("ids"); |
| | | queryMap.remove("columns"); |
| | | queryMap.remove("reportMeta"); |
| | | |
| | | if (!includeFilters) { |
| | | Object resolvedOrderBy = queryMap.get("orderBy"); |
| | | queryMap.clear(); |
| | | if (!Objects.isNull(resolvedOrderBy)) { |
| | | queryMap.put("orderBy", resolvedOrderBy); |
| | | } |
| | | } |
| | | |
| | | return queryMap; |
| | | } |
| | | |
| | | public Long getCurrent() { |
| | | return current; |
| | | } |
| | | |
| | | public void setCurrent(Long current) { |
| | | this.current = current; |
| | | } |
| | | |
| | | public Long getPageSize() { |
| | | return pageSize; |
| | | } |
| | | |
| | | public void setPageSize(Long pageSize) { |
| | | this.pageSize = pageSize; |
| | | } |
| | | |
| | | public String getOrderBy() { |
| | | return orderBy; |
| | | } |
| | | |
| | | public void setOrderBy(String orderBy) { |
| | | this.orderBy = orderBy; |
| | | } |
| | | |
| | | public List<Long> getIds() { |
| | | return ids; |
| | | } |
| | | |
| | | public void setIds(List<Long> ids) { |
| | | this.ids = ids; |
| | | } |
| | | |
| | | public List<ReportColumnMeta> getColumns() { |
| | | return columns; |
| | | } |
| | | |
| | | public void setColumns(List<ReportColumnMeta> columns) { |
| | | this.columns = columns; |
| | | } |
| | | |
| | | public ReportMeta getReportMeta() { |
| | | return reportMeta; |
| | | } |
| | | |
| | | public void setReportMeta(ReportMeta reportMeta) { |
| | | this.reportMeta = reportMeta; |
| | | } |
| | | |
| | | public Map<String, Object> getRawParams() { |
| | | return rawParams; |
| | | } |
| | | |
| | | public void setRawParams(Map<String, Object> rawParams) { |
| | | this.rawParams = rawParams; |
| | | } |
| | | |
| | | private static long parseLong(Object value, long defaultValue) { |
| | | if (Objects.isNull(value)) { |
| | | return defaultValue; |
| | | } |
| | | try { |
| | | return Long.parseLong(String.valueOf(value)); |
| | | } catch (NumberFormatException ignore) { |
| | | return defaultValue; |
| | | } |
| | | } |
| | | |
| | | private static List<Long> parseIds(Object idsObj) { |
| | | List<Long> ids = new ArrayList<>(); |
| | | if (!(idsObj instanceof Collection<?> collection)) { |
| | | return ids; |
| | | } |
| | | for (Object value : collection) { |
| | | if (Objects.isNull(value)) { |
| | | continue; |
| | | } |
| | | ids.add(Long.parseLong(String.valueOf(value))); |
| | | } |
| | | return ids; |
| | | } |
| | | |
| | | private static List<ReportColumnMeta> parseColumns(Object columnsObj) { |
| | | List<ReportColumnMeta> columns = new ArrayList<>(); |
| | | if (!(columnsObj instanceof Collection<?> collection)) { |
| | | return columns; |
| | | } |
| | | for (Object item : collection) { |
| | | if (!(item instanceof Map<?, ?> columnMap)) { |
| | | continue; |
| | | } |
| | | Object source = columnMap.get("source"); |
| | | if (Objects.isNull(source) || String.valueOf(source).trim().isEmpty()) { |
| | | continue; |
| | | } |
| | | ReportColumnMeta columnMeta = new ReportColumnMeta(); |
| | | columnMeta.setKey(Objects.isNull(columnMap.get("key")) ? null : String.valueOf(columnMap.get("key"))); |
| | | columnMeta.setSource(String.valueOf(source)); |
| | | columnMeta.setLabel(Objects.isNull(columnMap.get("label")) ? String.valueOf(source) : String.valueOf(columnMap.get("label"))); |
| | | columnMeta.setIsExtendField(Boolean.parseBoolean(String.valueOf(columnMap.get("isExtendField")))); |
| | | columns.add(columnMeta); |
| | | } |
| | | return columns; |
| | | } |
| | | |
| | | private static ReportMeta parseReportMeta(Object reportMetaObj) { |
| | | if (!(reportMetaObj instanceof Map<?, ?> reportMetaMap)) { |
| | | return null; |
| | | } |
| | | ReportMeta reportMeta = new ReportMeta(); |
| | | reportMeta.setTitle(getMapString(reportMetaMap, "title")); |
| | | reportMeta.setCompanyName(getMapString(reportMetaMap, "companyName")); |
| | | reportMeta.setPrintedBy(getMapString(reportMetaMap, "printedBy")); |
| | | reportMeta.setReportDate(getMapString(reportMetaMap, "reportDate")); |
| | | reportMeta.setReportDateValue(getMapString(reportMetaMap, "reportDateValue")); |
| | | return reportMeta; |
| | | } |
| | | |
| | | private static String getMapString(Map<?, ?> map, String key) { |
| | | Object value = map.get(key); |
| | | return Objects.isNull(value) ? null : String.valueOf(value); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.common.domain.report; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class ReportQueryResponse<T> { |
| | | private List<T> records = new ArrayList<>(); |
| | | private Long total = 0L; |
| | | private Long current = 1L; |
| | | private Long pageSize = 0L; |
| | | private Long pages = 0L; |
| | | |
| | | public List<T> getRecords() { |
| | | return records; |
| | | } |
| | | |
| | | public void setRecords(List<T> records) { |
| | | this.records = records; |
| | | } |
| | | |
| | | public Long getTotal() { |
| | | return total; |
| | | } |
| | | |
| | | public void setTotal(Long total) { |
| | | this.total = total; |
| | | } |
| | | |
| | | public Long getCurrent() { |
| | | return current; |
| | | } |
| | | |
| | | public void setCurrent(Long current) { |
| | | this.current = current; |
| | | } |
| | | |
| | | public Long getPageSize() { |
| | | return pageSize; |
| | | } |
| | | |
| | | public void setPageSize(Long pageSize) { |
| | | this.pageSize = pageSize; |
| | | } |
| | | |
| | | public Long getPages() { |
| | | return pages; |
| | | } |
| | | |
| | | public void setPages(Long pages) { |
| | | this.pages = pages; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.common.support.report; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.vincent.rsf.framework.common.Cools; |
| | | import com.vincent.rsf.server.common.domain.report.ReportColumnMeta; |
| | | import com.vincent.rsf.server.common.domain.report.ReportMeta; |
| | | import com.vincent.rsf.server.common.domain.report.ReportQueryRequest; |
| | | import com.vincent.rsf.server.common.domain.report.ReportQueryResponse; |
| | | import com.vincent.rsf.server.common.utils.ExcelUtil; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | public class ListReportSupport<T> { |
| | | |
| | | public interface QueryWrapperBuilder<T> { |
| | | QueryWrapper<T> build(ReportQueryRequest request); |
| | | } |
| | | |
| | | public interface RecordLoader<T> { |
| | | List<T> list(QueryWrapper<T> queryWrapper); |
| | | |
| | | IPage<T> page(Page<T> page, QueryWrapper<T> queryWrapper); |
| | | |
| | | default void afterLoad(List<T> records) { |
| | | } |
| | | } |
| | | |
| | | private final QueryWrapperBuilder<T> queryWrapperBuilder; |
| | | private final RecordLoader<T> recordLoader; |
| | | |
| | | public ListReportSupport(QueryWrapperBuilder<T> queryWrapperBuilder, RecordLoader<T> recordLoader) { |
| | | this.queryWrapperBuilder = queryWrapperBuilder; |
| | | this.recordLoader = recordLoader; |
| | | } |
| | | |
| | | public List<T> queryRecords(ReportQueryRequest request) { |
| | | List<T> records = recordLoader.list(queryWrapperBuilder.build(request)); |
| | | recordLoader.afterLoad(records); |
| | | return records; |
| | | } |
| | | |
| | | public ReportQueryResponse<T> queryPage(ReportQueryRequest request) { |
| | | Page<T> page = new Page<>( |
| | | Math.max(request.getCurrent(), 1L), |
| | | Math.max(request.getPageSize(), 1L) |
| | | ); |
| | | IPage<T> result = recordLoader.page(page, queryWrapperBuilder.build(request)); |
| | | recordLoader.afterLoad(result.getRecords()); |
| | | |
| | | ReportQueryResponse<T> response = new ReportQueryResponse<>(); |
| | | response.setRecords(result.getRecords()); |
| | | response.setTotal(result.getTotal()); |
| | | response.setCurrent(result.getCurrent()); |
| | | response.setPageSize(result.getSize()); |
| | | response.setPages(result.getPages()); |
| | | return response; |
| | | } |
| | | |
| | | public static List<ExcelUtil.ColumnMeta> toExcelColumns(List<ReportColumnMeta> columns) { |
| | | if (columns == null || columns.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | List<ExcelUtil.ColumnMeta> excelColumns = new ArrayList<>(); |
| | | for (ReportColumnMeta column : columns) { |
| | | if (column == null || Cools.isEmpty(column.getSource())) { |
| | | continue; |
| | | } |
| | | excelColumns.add(new ExcelUtil.ColumnMeta() |
| | | .setKey(column.getKey()) |
| | | .setSource(column.getSource()) |
| | | .setLabel(column.getLabel()) |
| | | .setExtendField(Boolean.TRUE.equals(column.getIsExtendField()))); |
| | | } |
| | | return excelColumns; |
| | | } |
| | | |
| | | public static ExcelUtil.ReportMeta toExcelReportMeta(ReportMeta reportMeta) { |
| | | if (reportMeta == null) { |
| | | return null; |
| | | } |
| | | return new ExcelUtil.ReportMeta() |
| | | .setTitle(reportMeta.getTitle()) |
| | | .setCompanyName(reportMeta.getCompanyName()) |
| | | .setPrintedBy(reportMeta.getPrintedBy()) |
| | | .setReportDate(reportMeta.getReportDate()) |
| | | .setReportDateValue(reportMeta.getReportDateValue()); |
| | | } |
| | | |
| | | public static void applyOrderBy(QueryWrapper<?> queryWrapper, String orderBy) { |
| | | if (Cools.isEmpty(orderBy)) { |
| | | return; |
| | | } |
| | | for (String item : orderBy.split(",")) { |
| | | String[] temp = item.trim().split(" "); |
| | | if (temp.length == 0 || Cools.isEmpty(temp[0])) { |
| | | continue; |
| | | } |
| | | boolean asc = temp.length == 1 || !"desc".equalsIgnoreCase(temp[temp.length - 1]); |
| | | queryWrapper.orderBy(true, asc, temp[0]); |
| | | } |
| | | } |
| | | } |
| | |
| | | import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.apache.poi.ss.util.CellRangeAddress; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.lang.reflect.Field; |
| | | import java.lang.reflect.Method; |
| | | import java.lang.reflect.Modifier; |
| | | import java.net.URLEncoder; |
| | | import java.text.SimpleDateFormat; |
| | |
| | | return workbook; |
| | | } |
| | | |
| | | public static Workbook create(List<?> list, List<ColumnMeta> columns) { |
| | | return create(list, columns, null); |
| | | } |
| | | |
| | | public static Workbook create(List<?> list, List<ColumnMeta> columns, ReportMeta reportMeta) { |
| | | XSSFWorkbook workbook = new XSSFWorkbook(); |
| | | Sheet sheet = workbook.createSheet("export"); |
| | | List<ColumnMeta> safeColumns = columns == null ? Collections.emptyList() : columns; |
| | | int sheetColumnCount = safeColumns.size() + 1; |
| | | configureA4PrintLayout(sheet); |
| | | |
| | | CellStyle titleStyle = createTitleStyle(workbook); |
| | | CellStyle metaLabelStyle = createMetaLabelStyle(workbook); |
| | | CellStyle metaValueStyle = createMetaValueStyle(workbook); |
| | | CellStyle headerStyle = createHeaderStyle(workbook); |
| | | CellStyle bodyStyle = createBodyStyle(workbook); |
| | | CellStyle serialStyle = createCenteredBodyStyle(workbook); |
| | | |
| | | int rowIndex = 0; |
| | | if (reportMeta != null) { |
| | | Row titleRow = sheet.createRow(rowIndex++); |
| | | titleRow.setHeightInPoints(28); |
| | | Cell titleCell = titleRow.createCell(0); |
| | | titleCell.setCellValue(StringUtils.defaultIfBlank(reportMeta.getTitle(), "报表")); |
| | | titleCell.setCellStyle(titleStyle); |
| | | sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, Math.max(0, sheetColumnCount - 1))); |
| | | |
| | | Row metaRow = sheet.createRow(rowIndex++); |
| | | int metaCol = 0; |
| | | metaCol = writeMetaPair(metaRow, metaCol, "报表日期", reportMeta.getReportDate(), metaLabelStyle, metaValueStyle); |
| | | writeMetaPair(metaRow, metaCol, "打印人", reportMeta.getPrintedBy(), metaLabelStyle, metaValueStyle); |
| | | |
| | | rowIndex++; |
| | | } |
| | | |
| | | int headerRowIndex = rowIndex; |
| | | Row header = sheet.createRow(rowIndex++); |
| | | Cell serialHeaderCell = header.createCell(0); |
| | | serialHeaderCell.setCellValue("序号"); |
| | | serialHeaderCell.setCellStyle(headerStyle); |
| | | |
| | | for (int i = 0; i < safeColumns.size(); i++) { |
| | | ColumnMeta column = safeColumns.get(i); |
| | | Cell headerCell = header.createCell(i + 1); |
| | | headerCell.setCellValue( |
| | | StringUtils.isBlank(column.getLabel()) ? column.getSource() : column.getLabel() |
| | | ); |
| | | headerCell.setCellStyle(headerStyle); |
| | | } |
| | | |
| | | if (list != null) { |
| | | int serialNo = 1; |
| | | for (Object rowObj : list) { |
| | | Row row = sheet.createRow(rowIndex++); |
| | | Cell serialCell = row.createCell(0); |
| | | serialCell.setCellValue(String.format("%03d", serialNo++)); |
| | | serialCell.setCellStyle(serialStyle); |
| | | for (int i = 0; i < safeColumns.size(); i++) { |
| | | Object value = getColumnValue(rowObj, safeColumns.get(i).getSource()); |
| | | Cell cell = row.createCell(i + 1); |
| | | cell.setCellStyle(bodyStyle); |
| | | if (value != null) { |
| | | if (value instanceof Date) { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | cell.setCellValue(sdf.format((Date) value)); |
| | | } else { |
| | | cell.setCellValue(value.toString()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (int i = 0; i <= safeColumns.size(); i++) { |
| | | sheet.autoSizeColumn(i); |
| | | sheet.setColumnWidth(i, Math.min(sheet.getColumnWidth(i) + 1024, 12000)); |
| | | } |
| | | |
| | | sheet.setRepeatingRows(CellRangeAddress.valueOf((headerRowIndex + 1) + ":" + (headerRowIndex + 1))); |
| | | |
| | | return workbook; |
| | | } |
| | | |
| | | private static void configureA4PrintLayout(Sheet sheet) { |
| | | sheet.setAutobreaks(true); |
| | | sheet.setFitToPage(true); |
| | | sheet.setHorizontallyCenter(true); |
| | | sheet.setDisplayGridlines(false); |
| | | |
| | | PrintSetup printSetup = sheet.getPrintSetup(); |
| | | printSetup.setPaperSize(PrintSetup.A4_PAPERSIZE); |
| | | printSetup.setLandscape(true); |
| | | printSetup.setFitWidth((short) 1); |
| | | printSetup.setFitHeight((short) 0); |
| | | |
| | | sheet.setMargin(Sheet.LeftMargin, 0.3); |
| | | sheet.setMargin(Sheet.RightMargin, 0.3); |
| | | sheet.setMargin(Sheet.TopMargin, 0.4); |
| | | sheet.setMargin(Sheet.BottomMargin, 0.4); |
| | | } |
| | | |
| | | private static int writeMetaPair(Row row, int startCol, String label, String value, CellStyle labelStyle, CellStyle valueStyle) { |
| | | Cell labelCell = row.createCell(startCol); |
| | | labelCell.setCellValue(label + ":"); |
| | | labelCell.setCellStyle(labelStyle); |
| | | |
| | | Cell valueCell = row.createCell(startCol + 1); |
| | | valueCell.setCellValue(StringUtils.defaultString(value)); |
| | | valueCell.setCellStyle(valueStyle); |
| | | return startCol + 2; |
| | | } |
| | | |
| | | private static CellStyle createTitleStyle(Workbook workbook) { |
| | | CellStyle style = workbook.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | style.setBorderBottom(BorderStyle.THICK); |
| | | Font font = workbook.createFont(); |
| | | font.setBold(true); |
| | | font.setFontHeightInPoints((short) 16); |
| | | style.setFont(font); |
| | | return style; |
| | | } |
| | | |
| | | private static CellStyle createMetaLabelStyle(Workbook workbook) { |
| | | CellStyle style = workbook.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.LEFT); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | style.setBorderBottom(BorderStyle.THIN); |
| | | Font font = workbook.createFont(); |
| | | font.setBold(true); |
| | | style.setFont(font); |
| | | return style; |
| | | } |
| | | |
| | | private static CellStyle createMetaValueStyle(Workbook workbook) { |
| | | CellStyle style = workbook.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.LEFT); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | style.setBorderBottom(BorderStyle.THIN); |
| | | return style; |
| | | } |
| | | |
| | | private static CellStyle createHeaderStyle(Workbook workbook) { |
| | | CellStyle style = workbook.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); |
| | | style.setFillPattern(FillPatternType.SOLID_FOREGROUND); |
| | | Font font = workbook.createFont(); |
| | | font.setBold(true); |
| | | style.setFont(font); |
| | | return style; |
| | | } |
| | | |
| | | private static CellStyle createBodyStyle(Workbook workbook) { |
| | | CellStyle style = workbook.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.LEFT); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | return style; |
| | | } |
| | | |
| | | private static CellStyle createCenteredBodyStyle(Workbook workbook) { |
| | | CellStyle style = workbook.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | return style; |
| | | } |
| | | |
| | | private static Object getColumnValue(Object rowObj, String source) { |
| | | if (rowObj == null || StringUtils.isBlank(source)) { |
| | | return null; |
| | | } |
| | | |
| | | if (rowObj instanceof Map) { |
| | | return getValueFromMap((Map<?, ?>) rowObj, source); |
| | | } |
| | | |
| | | String extendFieldKey = extractExtendFieldKey(source); |
| | | if (extendFieldKey != null) { |
| | | Object extendFields = getBeanValue(rowObj, "extendFields"); |
| | | if (extendFields instanceof Map) { |
| | | return ((Map<?, ?>) extendFields).get(extendFieldKey); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | return getBeanValue(rowObj, source); |
| | | } |
| | | |
| | | private static Object getValueFromMap(Map<?, ?> rowObj, String source) { |
| | | String extendFieldKey = extractExtendFieldKey(source); |
| | | if (extendFieldKey != null) { |
| | | Object extendFields = rowObj.get("extendFields"); |
| | | if (extendFields instanceof Map) { |
| | | return ((Map<?, ?>) extendFields).get(extendFieldKey); |
| | | } |
| | | return null; |
| | | } |
| | | return rowObj.get(source); |
| | | } |
| | | |
| | | private static String extractExtendFieldKey(String source) { |
| | | if (source == null || !source.startsWith("extendFields.[")) { |
| | | return null; |
| | | } |
| | | int startIndex = source.indexOf('['); |
| | | int endIndex = source.indexOf(']'); |
| | | if (startIndex < 0 || endIndex <= startIndex) { |
| | | return null; |
| | | } |
| | | return source.substring(startIndex + 1, endIndex); |
| | | } |
| | | |
| | | private static Object getBeanValue(Object rowObj, String source) { |
| | | Object value = invokeGetter(rowObj, source); |
| | | if (value != null) { |
| | | return value; |
| | | } |
| | | Field field = findField(rowObj.getClass(), source); |
| | | if (field == null) { |
| | | return null; |
| | | } |
| | | try { |
| | | field.setAccessible(true); |
| | | return field.get(rowObj); |
| | | } catch (IllegalAccessException ignore) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private static Object invokeGetter(Object target, String source) { |
| | | String suffix = Character.toUpperCase(source.charAt(0)) + source.substring(1); |
| | | String[] methodNames = new String[] { "get" + suffix, "is" + suffix }; |
| | | for (String methodName : methodNames) { |
| | | try { |
| | | Method method = target.getClass().getMethod(methodName); |
| | | return method.invoke(target); |
| | | } catch (Exception ignore) { |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private static Field findField(Class<?> clazz, String source) { |
| | | Class<?> current = clazz; |
| | | while (current != null && current != Object.class) { |
| | | try { |
| | | return current.getDeclaredField(source); |
| | | } catch (NoSuchFieldException ignore) { |
| | | current = current.getSuperclass(); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 添加导入excel配置参数 |
| | | * 注:默认配置可满足当前需求 |
| | |
| | | return false; |
| | | } |
| | | |
| | | public static class ColumnMeta { |
| | | private String key; |
| | | private String source; |
| | | private String label; |
| | | private Boolean extendField; |
| | | |
| | | public String getKey() { |
| | | return key; |
| | | } |
| | | |
| | | public ColumnMeta setKey(String key) { |
| | | this.key = key; |
| | | return this; |
| | | } |
| | | |
| | | public String getSource() { |
| | | return source; |
| | | } |
| | | |
| | | public ColumnMeta setSource(String source) { |
| | | this.source = source; |
| | | return this; |
| | | } |
| | | |
| | | public String getLabel() { |
| | | return label; |
| | | } |
| | | |
| | | public ColumnMeta setLabel(String label) { |
| | | this.label = label; |
| | | return this; |
| | | } |
| | | |
| | | public Boolean getExtendField() { |
| | | return extendField; |
| | | } |
| | | |
| | | public ColumnMeta setExtendField(Boolean extendField) { |
| | | this.extendField = extendField; |
| | | return this; |
| | | } |
| | | } |
| | | |
| | | public static class ReportMeta { |
| | | private String title; |
| | | private String companyName; |
| | | private String printedBy; |
| | | private String reportDate; |
| | | private String reportDateValue; |
| | | |
| | | public String getTitle() { |
| | | return title; |
| | | } |
| | | |
| | | public ReportMeta setTitle(String title) { |
| | | this.title = title; |
| | | return this; |
| | | } |
| | | |
| | | public String getCompanyName() { |
| | | return companyName; |
| | | } |
| | | |
| | | public ReportMeta setCompanyName(String companyName) { |
| | | this.companyName = companyName; |
| | | return this; |
| | | } |
| | | |
| | | public String getReportDate() { |
| | | return reportDate; |
| | | } |
| | | |
| | | public ReportMeta setReportDate(String reportDate) { |
| | | this.reportDate = reportDate; |
| | | return this; |
| | | } |
| | | |
| | | public String getReportDateValue() { |
| | | return reportDateValue; |
| | | } |
| | | |
| | | public ReportMeta setReportDateValue(String reportDateValue) { |
| | | this.reportDateValue = reportDateValue; |
| | | return this; |
| | | } |
| | | |
| | | public String getPrintedBy() { |
| | | return printedBy; |
| | | } |
| | | |
| | | public ReportMeta setPrintedBy(String printedBy) { |
| | | this.printedBy = printedBy; |
| | | return this; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | 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.domain.report.ReportQueryRequest; |
| | | import com.vincent.rsf.server.common.domain.report.ReportQueryResponse; |
| | | import com.vincent.rsf.server.common.support.report.ListReportSupport; |
| | | import com.vincent.rsf.server.common.utils.FieldsUtils; |
| | | import com.vincent.rsf.server.manager.entity.WarehouseAreasItem; |
| | | import com.vincent.rsf.server.manager.service.WarehouseAreasItemService; |
| | |
| | | @PreAuthorize("hasAuthority('manager:warehouseAreasItem:list')") |
| | | @PostMapping("/warehouseAreasItem/page") |
| | | public R page(@RequestBody Map<String, Object> map) { |
| | | BaseParam baseParam = buildParam(map, BaseParam.class); |
| | | PageParam<WarehouseAreasItem, BaseParam> pageParam = new PageParam<>(baseParam, WarehouseAreasItem.class); |
| | | QueryWrapper<WarehouseAreasItem> queryWrapper = pageParam.buildWrapper(true); |
| | | /**拼接扩展字段过滤*/ |
| | | FieldsUtils.setFieldsFilters(queryWrapper,pageParam, WarehouseAreasItem.class); |
| | | /**拼接扩展字段*/ |
| | | PageParam<WarehouseAreasItem, BaseParam> pageParam = buildPageParam(map, true); |
| | | QueryWrapper<WarehouseAreasItem> queryWrapper = buildFilterQueryWrapper(pageParam); |
| | | PageParam<WarehouseAreasItem, BaseParam> page = warehouseAreasItemService.page(pageParam, queryWrapper); |
| | | List<WarehouseAreasItem> records = page.getRecords(); |
| | | for (WarehouseAreasItem record : records) { |
| | | if (!Objects.isNull(record.getFieldsIndex())) { |
| | | Map<String, String> fields = FieldsUtils.getFields(record.getFieldsIndex()); |
| | | record.setExtendFields(fields); |
| | | } |
| | | } |
| | | page.setRecords(records); |
| | | warehouseAreasItemService.fillExtendFields(page.getRecords()); |
| | | return R.ok().add(page); |
| | | } |
| | | |
| | |
| | | @PreAuthorize("hasAuthority('manager:warehouseAreasItem:list')") |
| | | @PostMapping("/warehouseAreasItem/ispts/page") |
| | | public R getIsptPage(@RequestBody Map<String, Object> map) { |
| | | BaseParam baseParam = buildParam(map, BaseParam.class); |
| | | PageParam<WarehouseAreasItem, BaseParam> pageParam = new PageParam<>(baseParam, WarehouseAreasItem.class); |
| | | PageParam<WarehouseAreasItem, BaseParam> pageParam = buildPageParam(map, true); |
| | | QueryWrapper<WarehouseAreasItem> queryWrapper = pageParam.buildWrapper(true); |
| | | /**拼接扩展字段*/ |
| | | IPage<WarehouseAreasItem> page = warehouseAreasItemService.pageByItemId(pageParam, queryWrapper); |
| | | List<WarehouseAreasItem> records = page.getRecords(); |
| | | for (WarehouseAreasItem record : records) { |
| | | if (!Objects.isNull(record.getFieldsIndex())) { |
| | | Map<String, String> fields = FieldsUtils.getFields(record.getFieldsIndex()); |
| | | record.setExtendFields(fields); |
| | | } |
| | | } |
| | | page.setRecords(records); |
| | | warehouseAreasItemService.fillExtendFields(page.getRecords()); |
| | | return R.ok().add(page); |
| | | } |
| | | |
| | |
| | | @PreAuthorize("hasAuthority('manager:warehouseAreasItem:list')") |
| | | @PostMapping("/warehouseAreasItem/export") |
| | | public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception { |
| | | ExcelUtil.build(ExcelUtil.create(warehouseAreasItemService.list(), WarehouseAreasItem.class), response); |
| | | ReportQueryRequest request = ReportQueryRequest.fromMap(map); |
| | | List<WarehouseAreasItem> records = createListReportSupport().queryRecords(request); |
| | | List<ExcelUtil.ColumnMeta> columns = ListReportSupport.toExcelColumns(request.getColumns()); |
| | | ExcelUtil.ReportMeta reportMeta = ListReportSupport.toExcelReportMeta(request.getReportMeta()); |
| | | if (columns.isEmpty()) { |
| | | ExcelUtil.build(ExcelUtil.create(records, WarehouseAreasItem.class), response); |
| | | return; |
| | | } |
| | | ExcelUtil.build(ExcelUtil.create(records, columns, reportMeta), response); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('manager:warehouseAreasItem:list')") |
| | | @PostMapping("/warehouseAreasItem/print/query") |
| | | public R printQuery(@RequestBody Map<String, Object> map) { |
| | | ReportQueryResponse<WarehouseAreasItem> result = createListReportSupport() |
| | | .queryPage(ReportQueryRequest.fromMap(map)); |
| | | return R.ok().add(result); |
| | | } |
| | | |
| | | private PageParam<WarehouseAreasItem, BaseParam> buildPageParam(Map<String, Object> map, boolean includeFilters) { |
| | | return buildPageParam(ReportQueryRequest.fromMap(map), includeFilters); |
| | | } |
| | | |
| | | private PageParam<WarehouseAreasItem, BaseParam> buildPageParam(ReportQueryRequest request, boolean includeFilters) { |
| | | BaseParam baseParam = buildParam(request.toPageParamMap(includeFilters), BaseParam.class); |
| | | return new PageParam<>(baseParam, WarehouseAreasItem.class); |
| | | } |
| | | |
| | | private QueryWrapper<WarehouseAreasItem> buildFilterQueryWrapper(PageParam<WarehouseAreasItem, BaseParam> pageParam) { |
| | | QueryWrapper<WarehouseAreasItem> queryWrapper = pageParam.buildWrapper(true); |
| | | FieldsUtils.setFieldsFilters(queryWrapper, pageParam, WarehouseAreasItem.class); |
| | | return queryWrapper; |
| | | } |
| | | |
| | | private QueryWrapper<WarehouseAreasItem> buildOutputQueryWrapper(ReportQueryRequest request) { |
| | | List<Long> ids = request.getIds(); |
| | | PageParam<WarehouseAreasItem, BaseParam> pageParam = buildPageParam(request, ids.isEmpty()); |
| | | QueryWrapper<WarehouseAreasItem> queryWrapper = ids.isEmpty() |
| | | ? buildFilterQueryWrapper(pageParam) |
| | | : new QueryWrapper<>(); |
| | | |
| | | if (!ids.isEmpty()) { |
| | | queryWrapper.in("id", ids); |
| | | } |
| | | ListReportSupport.applyOrderBy(queryWrapper, pageParam.getWhere().getOrderBy()); |
| | | return queryWrapper; |
| | | } |
| | | |
| | | private ListReportSupport<WarehouseAreasItem> createListReportSupport() { |
| | | return new ListReportSupport<>( |
| | | this::buildOutputQueryWrapper, |
| | | new ListReportSupport.RecordLoader<>() { |
| | | @Override |
| | | public List<WarehouseAreasItem> list(QueryWrapper<WarehouseAreasItem> queryWrapper) { |
| | | return warehouseAreasItemService.listForOutput(queryWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public IPage<WarehouseAreasItem> page(Page<WarehouseAreasItem> page, QueryWrapper<WarehouseAreasItem> queryWrapper) { |
| | | return warehouseAreasItemService.pageForOutput(page, queryWrapper); |
| | | } |
| | | } |
| | | ); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Constants; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.vincent.rsf.server.common.domain.BaseParam; |
| | | import com.vincent.rsf.server.common.domain.PageParam; |
| | |
| | | List<WarehouseAreasItem> getList(); |
| | | |
| | | IPage<WarehouseAreasItem> pageByItemId(PageParam<WarehouseAreasItem, BaseParam> pageParam, QueryWrapper<WarehouseAreasItem> queryWrapper); |
| | | |
| | | List<WarehouseAreasItem> listForOutput(QueryWrapper<WarehouseAreasItem> queryWrapper); |
| | | |
| | | IPage<WarehouseAreasItem> pageForOutput(Page<WarehouseAreasItem> page, QueryWrapper<WarehouseAreasItem> queryWrapper); |
| | | |
| | | void fillExtendFields(List<WarehouseAreasItem> records); |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.vincent.rsf.server.common.domain.BaseParam; |
| | | import com.vincent.rsf.server.common.domain.PageParam; |
| | | import com.vincent.rsf.server.common.utils.FieldsUtils; |
| | |
| | | @Override |
| | | public List<WarehouseAreasItem> getList() { |
| | | List<WarehouseAreasItem> areasItems = this.list(); |
| | | for (WarehouseAreasItem areasItem : areasItems) { |
| | | if (Objects.isNull(areasItem.getFieldsIndex())) { |
| | | continue; |
| | | } |
| | | areasItem.setExtendFields(FieldsUtils.getFields(areasItem.getFieldsIndex())); |
| | | } |
| | | fillExtendFields(areasItems); |
| | | return areasItems; |
| | | } |
| | | |
| | |
| | | IPage<WarehouseAreasItem> itemIPage = this.baseMapper.pageByItemId(pageParam, queryWrapper); |
| | | return itemIPage; |
| | | } |
| | | |
| | | @Override |
| | | public List<WarehouseAreasItem> listForOutput(QueryWrapper<WarehouseAreasItem> queryWrapper) { |
| | | List<WarehouseAreasItem> records = this.list(queryWrapper); |
| | | fillExtendFields(records); |
| | | return records; |
| | | } |
| | | |
| | | @Override |
| | | public IPage<WarehouseAreasItem> pageForOutput(Page<WarehouseAreasItem> page, QueryWrapper<WarehouseAreasItem> queryWrapper) { |
| | | IPage<WarehouseAreasItem> outputPage = this.page(page, queryWrapper); |
| | | fillExtendFields(outputPage.getRecords()); |
| | | return outputPage; |
| | | } |
| | | |
| | | @Override |
| | | public void fillExtendFields(List<WarehouseAreasItem> records) { |
| | | if (records == null || records.isEmpty()) { |
| | | return; |
| | | } |
| | | for (WarehouseAreasItem record : records) { |
| | | if (Objects.isNull(record.getFieldsIndex())) { |
| | | continue; |
| | | } |
| | | record.setExtendFields(FieldsUtils.getFields(record.getFieldsIndex())); |
| | | } |
| | | } |
| | | } |