Commit c95a21b7 authored by chenshouchao's avatar chenshouchao

feat: 完成表格组件的封装

parent 16485b8e
// 分页组件
import Pagination from "@mui/material/Pagination";
import MySelect from "./MySelect";
import { ThemeProvider, createTheme } from "@mui/material/styles";
const theme = createTheme({
components: {
MuiPagination: {
......@@ -31,26 +33,74 @@ type IMyPaginationProps = {
page: number;
pageChange: any;
count: number;
totalElements?: number;
type?: "simple" | "complex";
rowsPerPage?: number; // 每页多少条数据
handleChangeRowsPerPage?: any;
};
const MyPagination = (props: IMyPaginationProps) => {
const { page, pageChange, count } = props;
const {
page,
pageChange,
count,
type = "simple",
rowsPerPage = 10,
handleChangeRowsPerPage,
totalElements = 0,
} = props;
const handlePageChange = (e: any, value: number) => {
pageChange && pageChange(value);
};
const rowsPerPageChange = (e: any) => {
handleChangeRowsPerPage(Number(e));
};
return (
<ThemeProvider theme={theme}>
{type === "complex" && (
<>
<span
style={{
marginRight: "20px",
fontSize: "14px",
color: "rgba(30, 38, 51, 1)",
}}
>
总计:{totalElements}
</span>
<MySelect
style={{ marginRight: "20px" }}
value={String(rowsPerPage)}
onChange={(e) => rowsPerPageChange(e)}
size={"small"}
options={[
{
label: "10/页",
value: "10",
},
{
label: "20/页",
value: "20",
},
{
label: "50/页",
value: "50",
},
{
label: "100/页",
value: "100",
},
]}
></MySelect>
</>
)}
<Pagination
page={page + 1} // 请求接口的页码是从0开始的
count={count + 1}
shape="rounded"
onChange={handlePageChange}
// sx={{
// padding: "20px 0",
// display: "flex",
// justifyContent: "flex-end",
// }}
/>
</ThemeProvider>
);
......
......@@ -11,7 +11,10 @@ import MyPagination from "@/components/mui/MyPagination";
import ascIcon from "@/assets/project/ascIcon.svg";
import descIcon from "@/assets/project/descIcon.svg";
import sortIcon from "@/assets/project/sort.svg";
import NoData from "../BusinessComponents/NoData";
import CircularProgress from "@mui/material/CircularProgress";
import { createTheme, ThemeProvider } from "@mui/material";
import noFile from "@/assets/project/noFile.svg";
type Order = "asc" | "desc"; // 升序为asc,降序为desc。
......@@ -24,6 +27,7 @@ interface IMyTableProps {
rows: Array<any>; // 表格数据
headCells: Array<any>; // 表头配置
key?: string; // 表格数据的key
loading?: boolean;
hasCheckbox?: boolean; // 是否有复选框
selectItems?: Array<any>; // 选中的项
setSelectItems?: any; // 设置选中的项
......@@ -33,17 +37,21 @@ interface IMyTableProps {
page?: number; // 当前页
pageChange?: any; // 页码改变
count?: number; // 总页数
randerTooterContent?: any; // 分页左侧内容渲染
totalElements?: number; // 数据总量 不止是列表渲染的长度
sortState?: sortState; // 排序状态
setSortState?: any; // 设置排序状态
paginationType?: "simple" | "complex"; // 分页组件的类型 simple简介式 complex复杂、带每页数量切换、总数等
rowsPerPage?: number; // 每页多少条数据
handleChangeRowsPerPage?: any; // 每页多少条数据变化
nodataText?: any; // 无数据文案
}
const MyTable = (props: IMyTableProps) => {
// tode loading nodata
const {
rows,
headCells,
key = "id",
loading = false,
hasCheckbox = false,
selectItems = [],
setSelectItems,
......@@ -52,14 +60,25 @@ const MyTable = (props: IMyTableProps) => {
page = 0,
pageChange = () => {},
count = 1,
randerTooterContent = null,
sortState,
setSortState,
paginationType = "simple",
rowsPerPage = 10,
handleChangeRowsPerPage,
totalElements = 0,
nodataText,
} = props;
const theme = useMemo(() => {
return createTheme({
components: {
MuiTable: {
styleOverrides: {
root: {
// minHeight: "100px",
},
},
},
MuiTableHead: {
styleOverrides: {
root: {
......@@ -74,6 +93,7 @@ const MyTable = (props: IMyTableProps) => {
MuiTableRow: {
styleOverrides: {
root: {
opacity: loading ? 0.5 : 1,
":hover": {
background: "rgba(245, 246, 247, 1)",
},
......@@ -100,6 +120,8 @@ const MyTable = (props: IMyTableProps) => {
MuiPaper: {
styleOverrides: {
root: {
minHeight: "200px",
position: "relative",
"&.MuiTableContainer-root": {
boxShadow: "none",
},
......@@ -111,7 +133,7 @@ const MyTable = (props: IMyTableProps) => {
root: {
fontSize: "14px",
lineHeight: "22px",
color: "rgba(86, 92, 102, 1)",
color: "rgba(30, 38, 51, 1)",
padding: "16px",
borderBottom: "1px solid rgba(240, 242, 245, 1)",
},
......@@ -120,8 +142,12 @@ const MyTable = (props: IMyTableProps) => {
MuiTableBody: {
styleOverrides: {
root: {
position: "relative",
"& .MuiTableRow-root:nth-last-of-type(1) .MuiTableCell-root": {
borderBottom: "none",
// 有分页的话 表格最后一行就不要下边框
borderBottom: hasTableFooter
? "none"
: "1px solid rgba(240, 242, 245, 1)",
},
},
},
......@@ -154,9 +180,26 @@ const MyTable = (props: IMyTableProps) => {
},
},
},
MuiCircularProgress: {
styleOverrides: {
root: {
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
margin: "auto",
// top: "50%",
// left: "50%",
// transform: "translate(-50%, -50%)",
zIndex: 1,
},
},
},
},
});
}, [hasCheckbox]);
}, [hasCheckbox, hasTableFooter, loading]);
const onSelectAllClick = useCallback(() => {
return (e: any) => {
......@@ -271,6 +314,42 @@ const MyTable = (props: IMyTableProps) => {
]);
const randerTableBody = useMemo(() => {
if (rows.length === 0) {
if (loading) {
return null;
}
return (
<tbody>
<tr>
<td>
<img
src={noFile}
alt=""
style={{
position: "absolute",
top: "100px",
left: "50%",
transform: "translate(-50%, 0)",
}}
/>
<span
style={{
position: "absolute",
top: "165px",
left: "50%",
transform: "translate(-50%, 0)",
fontSize: "14px",
lineHeight: "22px",
color: "#8a9099",
}}
>
{nodataText || "暂无数据"}
</span>
</td>
</tr>
</tbody>
);
}
return (
<TableBody>
{rows.map((row) => (
......@@ -298,7 +377,16 @@ const MyTable = (props: IMyTableProps) => {
))}
</TableBody>
);
}, [rows, key, hasCheckbox, selectItems, onSelectRowClick, headCells]);
}, [
rows,
key,
hasCheckbox,
selectItems,
onSelectRowClick,
headCells,
nodataText,
loading,
]);
const randerTableFooter = useMemo(() => {
if (hasTableFooter) {
......@@ -307,25 +395,50 @@ const MyTable = (props: IMyTableProps) => {
style={{
padding: "20px 0",
display: "flex",
justifyContent: "space-between",
justifyContent: "flex-end",
alignItems: "center",
borderTop: "1px solid rgba(240, 242, 245, 1)",
}}
>
<div>{randerTooterContent}</div>
<MyPagination page={page} pageChange={pageChange} count={count} />
<MyPagination
page={page}
pageChange={pageChange}
count={count}
totalElements={totalElements}
type={paginationType}
rowsPerPage={rowsPerPage}
handleChangeRowsPerPage={handleChangeRowsPerPage}
/>
</div>
);
} else {
return null;
}
}, [hasTableFooter, page, count, pageChange, randerTooterContent]);
}, [
hasTableFooter,
page,
count,
pageChange,
paginationType,
rowsPerPage,
handleChangeRowsPerPage,
totalElements,
]);
const randerCircularProgress = useMemo(() => {
if (loading) {
return <CircularProgress></CircularProgress>;
} else {
return null;
}
}, [loading]);
return (
<ThemeProvider theme={theme}>
{!fixedHead && (
<>
<TableContainer component={Paper}>
{randerCircularProgress}
<Table>
{randerTableHead}
{randerTableBody}
......@@ -336,7 +449,12 @@ const MyTable = (props: IMyTableProps) => {
)}
{fixedHead && (
<div
style={{ height: "100%", display: "flex", flexDirection: "column" }}
style={{
height: "100%",
display: "flex",
flexDirection: "column",
position: "relative",
}}
>
<TableContainer component={Paper}>
<Table>{randerTableHead}</Table>
......@@ -345,6 +463,7 @@ const MyTable = (props: IMyTableProps) => {
<Table>{randerTableBody}</Table>
</TableContainer>
{randerTableFooter}
{randerCircularProgress}
</div>
)}
</ThemeProvider>
......
......@@ -6,6 +6,7 @@ import MyTable from "@/components/mui/MyTableNew";
const MyTableDemo = () => {
const [page, setPage] = useState(0);
const [count, setCount] = useState(5);
const [rowsPerPage, setRowsPerPage] = useState(10);
const pageChange = (value: number) => {
setPage(value - 1);
};
......@@ -112,6 +113,34 @@ const MyTableDemo = () => {
id: "12",
},
];
const buttonHeadCells = [
{
id: "a",
label: "属性a",
width: "25%",
},
{
id: "b",
label: "属性b",
width: "25%",
},
{
id: "c",
label: "属性c",
width: "25%",
},
{
id: "d",
label: "属性d",
width: "25%",
},
{
id: "caozuo",
label: "操作",
width: "25%",
},
];
const headCells = [
{
id: "a",
......@@ -161,8 +190,8 @@ const MyTableDemo = () => {
];
const [selectItems, setSelectItems] = useState(["1"]);
const randerButton = () => {
return <MyButton text="下载"></MyButton>;
const handleDelete = (e: string) => {
console.log(e);
};
console.log(selectItems);
......@@ -171,8 +200,21 @@ const MyTableDemo = () => {
<h2>常规表格</h2>
<div>
<MyTable
rows={rows}
headCells={headCells}
// rows={rows.map((row) => {
// return {
// ...row,
// caozuo: (
// <MyButton
// text="删除"
// onClick={() => {
// handleDelete(row.id);
// }}
// ></MyButton>
// ),
// };
// })}
rows={[]}
headCells={buttonHeadCells}
selectItems={selectItems}
setSelectItems={setSelectItems}
/>
......@@ -210,6 +252,10 @@ const MyTableDemo = () => {
page={page}
count={count}
pageChange={pageChange}
paginationType={"complex"}
rowsPerPage={rowsPerPage}
handleChangeRowsPerPage={setRowsPerPage}
totalElements={12}
/>
</div>
<h2>带分页且固定表头(需要指定每列宽度 不然对不齐)的表格</h2>
......@@ -227,22 +273,7 @@ const MyTableDemo = () => {
pageChange={pageChange}
/>
</div>
<h2>表格底部带按钮 有分页才能用</h2>
<div style={{ height: "300px" }}>
<MyTable
rows={rows}
headCells={headCells}
hasCheckbox={true}
selectItems={selectItems}
setSelectItems={setSelectItems}
fixedHead={true}
hasTableFooter={true}
page={page}
count={count}
pageChange={pageChange}
randerTooterContent={randerButton()}
/>
</div>
<h2>
带排序表格(headCells中sort为true, 传入sortState、setSortState字段)
</h2>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment