From 28238befb9bb4546ab1a2b4942354e20bb3bdced Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期三, 04 二月 2026 13:37:31 +0800
Subject: [PATCH] #封装foot
---
rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeCreate.jsx | 85 ---------------------
rsf-admin/src/page/orders/asnOrderItem/AsnOrderItemList.jsx | 6 +
rsf-admin/src/page/components/StickyDataTable.jsx | 111 ++++++++++++++++++++++++++-
3 files changed, 113 insertions(+), 89 deletions(-)
diff --git a/rsf-admin/src/page/components/StickyDataTable.jsx b/rsf-admin/src/page/components/StickyDataTable.jsx
index fe4189b..f2cbada 100644
--- a/rsf-admin/src/page/components/StickyDataTable.jsx
+++ b/rsf-admin/src/page/components/StickyDataTable.jsx
@@ -1,17 +1,104 @@
import React from 'react';
-import { DataTable } from 'react-admin';
+import { DataTable, useDataTableDataContext, useTranslate } from 'react-admin';
+import { TableFooter, TableRow, TableCell } from '@mui/material';
+
+/**
+ * 璁$畻鍑芥暟鏄犲皠
+ */
+const calculators = {
+ sum: (data, field) => data.reduce((acc, record) => acc + (Number(record[field]) || 0), 0),
+ count: (data, field) => data.filter(record => record[field] != null && record[field] !== '').length,
+ avg: (data, field) => {
+ const validData = data.filter(record => record[field] != null);
+ if (validData.length === 0) return 0;
+ const sum = validData.reduce((acc, record) => acc + (Number(record[field]) || 0), 0);
+ return (sum / validData.length).toFixed(2);
+ },
+ min: (data, field) => {
+ const values = data.map(record => Number(record[field]) || 0);
+ return values.length > 0 ? Math.min(...values) : 0;
+ },
+ max: (data, field) => {
+ const values = data.map(record => Number(record[field]) || 0);
+ return values.length > 0 ? Math.max(...values) : 0;
+ },
+};
+
+/**
+ * 璁$畻绫诲瀷鐨勪腑鏂囧墠缂�鏄犲皠
+ */
+const typeLabels = {
+ sum: '鍚堣',
+ count: '鏁伴噺',
+ avg: '骞冲潎',
+ min: '鏈�灏�',
+ max: '鏈�澶�',
+};
+
+/**
+ * 鍐呴儴 Footer 缁勪欢
+ * @param {Object} props
+ * @param {Array} props.footerConfig - footer 閰嶇疆鏁扮粍
+ * @param {string} props.footerLabel - 绗竴鍒楁樉绀虹殑鏍囩锛岄粯璁�'鍚堣'
+ */
+const StickyTableFooter = ({ footerConfig, footerLabel = '鍚堣' }) => {
+ const data = useDataTableDataContext();
+ const translate = useTranslate();
+
+ const results = footerConfig.map(config => {
+ const { field, type = 'sum', label, render } = config;
+ const calculator = calculators[type];
+ const value = calculator ? calculator(data, field) : 0;
+ const typePrefix = typeLabels[type] || '鍚堣';
+
+ // 鏀寔鑷畾涔夋覆鏌�
+ if (render) {
+ return { label, value: render(value, data), typePrefix };
+ }
+
+ // 鑾峰彇缈昏瘧鍚庣殑鏍囩
+ const displayLabel = label ? (label.startsWith('table.') || label.startsWith('common.') ? translate(label) : label) : field;
+ return { label: displayLabel, value, typePrefix };
+ });
+
+ return (
+ <TableFooter>
+ <TableRow>
+ {results.map((item, index) => (
+ <TableCell key={index} variant="footer" align="left">
+ {item.label} {item.typePrefix}: {item.value}
+ </TableCell>
+ ))}
+ <TableCell colSpan={99} />
+ </TableRow>
+ </TableFooter>
+ );
+};
/**
* StickyDataTable Component
*
- * 灏佽 react-admin 鐨� DataTable锛屽疄鐜颁紶鍏ュ垪鍚嶅嵆鍙浐瀹氬垪銆�
+ * 灏佽 react-admin 鐨� DataTable锛屽疄鐜颁紶鍏ュ垪鍚嶅嵆鍙浐瀹氬垪锛屾敮鎸侀厤缃寲 footer 姹囨�汇��
*
* @param {Object} props
* @param {string[]} props.stickyLeft - 闇�瑕佸浐瀹氬湪宸︿晶鐨勫瓧娈� source 鍒楄〃
* @param {string[]} props.stickyRight - 闇�瑕佸浐瀹氬湪鍙充晶鐨勫瓧娈� source 鍒楄〃
+ * @param {Array} props.footerConfig - footer 姹囨�婚厤缃紝鏍煎紡锛歔{ field: 'anfme', type: 'sum', label: 'table.field.xxx' }]
+ * - field: 瑕佽绠楃殑瀛楁鍚�
+ * - type: 璁$畻绫诲瀷锛屾敮鎸� 'sum' | 'count' | 'avg' | 'min' | 'max'锛岄粯璁� 'sum'
+ * - label: 鏄剧ず鐨勬爣绛撅紝鏀寔缈昏瘧 key 鎴栫洿鎺ユ樉绀虹殑鏂囨湰
+ * - render: 鍙�夛紝鑷畾涔夋覆鏌撳嚱鏁� (value, data) => ReactNode
+ * @param {string} props.footerLabel - footer 绗竴鍒楁爣绛撅紝榛樿'鍚堣'
*/
-export const StickyDataTable = ({ stickyLeft = [], stickyRight = [], children, ...props }) => {
+export const StickyDataTable = ({
+ stickyLeft = [],
+ stickyRight = [],
+ footerConfig,
+ footerLabel = '鍚堣',
+ children,
+ ...props
+}) => {
// 閫掑綊澶勭悊 Children锛岀‘淇濆嵆渚挎槸 Fragment 鍖呰9鐨勫垪涔熻兘琚鐞�
const processChildren = (children) => {
@@ -63,12 +150,28 @@
});
};
+ // 鏋勫缓 foot 灞炴��
+ const footerComponent = footerConfig && footerConfig.length > 0
+ ? () => <StickyTableFooter footerConfig={footerConfig} footerLabel={footerLabel} />
+ : undefined;
+
return (
- <DataTable {...props} sx={{
+ <DataTable {...props} foot={footerComponent} sx={{
'& .MuiTableCell-head': {
zIndex: 4,
borderBottom: 'none' // 閬靛惊涔嬪墠鐨勪紭鍖栵紝鍘婚櫎琛ㄥご涓嬭竟妗�
},
+ '& .MuiTableFooter-root': {
+ position: 'sticky',
+ bottom: 0,
+ zIndex: 3,
+ backgroundColor: '#FFFFFF',
+ },
+ '& .MuiTableFooter-root .MuiTableCell-root': {
+ backgroundColor: '#f5f5f5',
+ fontWeight: 'bold',
+ borderTop: '2px solid #e0e0e0',
+ },
}}>
{processChildren(children)}
</DataTable>
diff --git a/rsf-admin/src/page/orders/asnOrderItem/AsnOrderItemList.jsx b/rsf-admin/src/page/orders/asnOrderItem/AsnOrderItemList.jsx
index a541c22..060c0e6 100644
--- a/rsf-admin/src/page/orders/asnOrderItem/AsnOrderItemList.jsx
+++ b/rsf-admin/src/page/orders/asnOrderItem/AsnOrderItemList.jsx
@@ -160,6 +160,8 @@
const { boxMaxWidth, boxMaxHeight } = useTableLayout(drawerVal);
+
+
return (
<Box sx={{
position: 'relative',
@@ -184,6 +186,10 @@
)}
{columns.length > 0 &&
<StickyDataTable
+ footerConfig={[
+ { field: 'anfme', type: 'sum', label: 'table.field.asnOrderItem.anfme' },
+ { field: 'qty', type: 'max', label: 'table.field.asnOrderItem.qty' },
+ ]}
stickyRight={['createTime']}
storeKey='asnOrderItem'
bulkActionButtons={false}
diff --git a/rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeCreate.jsx b/rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeCreate.jsx
index e62987d..49c33f9 100644
--- a/rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeCreate.jsx
+++ b/rsf-admin/src/page/taskPathTemplateMerge/TaskPathTemplateMergeCreate.jsx
@@ -86,23 +86,6 @@
</DialogTitle>
<DialogContent sx={{ mt: 2 }}>
<Grid container rowSpacing={2} columnSpacing={2}>
- {/* <Grid item xs={6} display="flex" gap={1}>
- <TextInput
- label="table.field.taskPathTemplateMerge.templateCode"
- source="templateCode"
- parse={v => v}
- autoFocus
- validate={required()}
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <TextInput
- label="table.field.taskPathTemplateMerge.templateName"
- source="templateName"
- parse={v => v}
- validate={required()}
- />
- </Grid> */}
<Grid item xs={6} display="flex" gap={1}>
<TaskPathTemplateMergeSelect
@@ -138,74 +121,6 @@
/>
</ReferenceArrayInput>
</Grid>
- {/* <Grid item xs={6} display="flex" gap={1}>
- <TextInput
- label="table.field.taskPathTemplateMerge.conditionDesc"
- source="conditionDesc"
- parse={v => v}
- />
- </Grid> */}
- {/* <Grid item xs={6} display="flex" gap={1}>
- <NumberInput
- label="table.field.taskPathTemplateMerge.version"
- source="version"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <NumberInput
- label="table.field.taskPathTemplateMerge.isCurrent"
- source="isCurrent"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <DateInput
- label="table.field.taskPathTemplateMerge.effectiveTime"
- source="effectiveTime"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <DateInput
- label="table.field.taskPathTemplateMerge.expireTime"
- source="expireTime"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <NumberInput
- label="table.field.taskPathTemplateMerge.priority"
- source="priority"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <NumberInput
- label="table.field.taskPathTemplateMerge.timeoutMinutes"
- source="timeoutMinutes"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <NumberInput
- label="table.field.taskPathTemplateMerge.maxRetryTimes"
- source="maxRetryTimes"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <NumberInput
- label="table.field.taskPathTemplateMerge.retryIntervalSeconds"
- source="retryIntervalSeconds"
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <TextInput
- label="table.field.taskPathTemplateMerge.remark"
- source="remark"
- parse={v => v}
- />
- </Grid>
- <Grid item xs={6} display="flex" gap={1}>
- <NumberInput
- label="table.field.taskPathTemplateMerge.stepSize"
- source="stepSize"
- />
- </Grid> */}
<Grid item xs={6} display="flex" gap={1}>
<StatusSelectInput />
--
Gitblit v1.9.1