Commit 777d07f5 authored by wuyongsheng's avatar wuyongsheng

Merge branch 'master' into 'staging'

Master

See merge request !200
parents e7f7e081 2c78102d
...@@ -2,7 +2,5 @@ ...@@ -2,7 +2,5 @@
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
} position: relative;
.itemBox {
/* flex: 1; */
} }
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import MyCircularProgress from "@/components/mui/MyCircularProgress";
import style from "./index.module.css"; import style from "./index.module.css";
interface ICardTableProps { interface ICardTableProps {
...@@ -10,6 +11,7 @@ interface ICardTableProps { ...@@ -10,6 +11,7 @@ interface ICardTableProps {
horizontalSpacing?: number; // 水平方向的间隔 horizontalSpacing?: number; // 水平方向的间隔
verticalSpacing?: number; // 垂直方向的间隔 verticalSpacing?: number; // 垂直方向的间隔
renderBefore?: any; renderBefore?: any;
loading?: boolean;
} }
const CardTable = (props: ICardTableProps) => { const CardTable = (props: ICardTableProps) => {
...@@ -22,6 +24,7 @@ const CardTable = (props: ICardTableProps) => { ...@@ -22,6 +24,7 @@ const CardTable = (props: ICardTableProps) => {
verticalSpacing = 20, verticalSpacing = 20,
itemMinWidth, itemMinWidth,
renderBefore, renderBefore,
loading = false,
} = props; } = props;
const [numberOfColumns, setNumberOfColumns] = useState(3); const [numberOfColumns, setNumberOfColumns] = useState(3);
...@@ -61,6 +64,7 @@ const CardTable = (props: ICardTableProps) => { ...@@ -61,6 +64,7 @@ const CardTable = (props: ICardTableProps) => {
}} }}
ref={tableBoxRef} ref={tableBoxRef}
> >
<MyCircularProgress loading={loading} />
{renderBefore && renderBefore() && ( {renderBefore && renderBefore() && (
<div <div
className={style.itemBox} className={style.itemBox}
......
import { useEffect, useState, useRef } from "react";
import MyCircularProgress from "@/components/mui/MyCircularProgress";
import { List } from "react-virtualized"; import { List } from "react-virtualized";
interface IVirtuallyListProps { interface IVirtuallyListProps {
list: Array<any>; list: Array<any>;
renderRow: any; renderRow: any;
rowHeight: Number | Function;
listStyle?: Object;
loading?: boolean;
onScroll?: Function;
} }
const VirtuallyList = (props: IVirtuallyListProps) => { const VirtuallyList = (props: IVirtuallyListProps) => {
const { list, renderRow } = props; const {
list,
renderRow,
rowHeight,
listStyle,
loading = false,
onScroll,
} = props;
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
const virtuallyListBoxRef: any = useRef(null);
const getTableWidthHeight = () => {
setWidth(virtuallyListBoxRef?.current?.offsetWidth || 1000);
setHeight(virtuallyListBoxRef?.current?.offsetHeight || 300);
};
useEffect(() => {
getTableWidthHeight();
}, []);
window.onresize = () => {
getTableWidthHeight();
};
return ( return (
<div
ref={virtuallyListBoxRef}
style={{ width: "100%", height: "100%", position: "relative" }}
>
<MyCircularProgress loading={loading} />
<List <List
width={300} width={width}
height={300} height={height}
rowCount={list.length} rowCount={list.length}
rowHeight={20} rowHeight={rowHeight}
rowRenderer={renderRow} rowRenderer={renderRow}
overscanRowCount={20} overscanRowCount={20}
style={listStyle}
onScroll={onScroll}
/> />
</div>
); );
}; };
export default VirtuallyList; export default VirtuallyList;
.VTHeader { .VTHeader {
font-size: 12px; font-size: 12px;
line-height: 20px;
color: rgba(138, 144, 153, 1); color: rgba(138, 144, 153, 1);
padding: 12px 16px; padding: 12px 16px;
white-space: nowrap; white-space: nowrap;
font-weight: 400; font-weight: 400;
box-sizing: border-box; box-sizing: border-box;
display: flex;
align-items: center;
} }
.VTHeaderRow { .VTHeaderRow {
background-color: rgba(247, 248, 250, 1); background-color: rgba(247, 248, 250, 1);
box-sizing: border-box; box-sizing: border-box;
border-radius: 4px 4px 0 0;
border-bottom: 1px solid rgba(240, 242, 245, 1);
} }
.VTRow { .VTRow {
background-color: #fff; background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
border-bottom: 1px solid rgba(240, 242, 245, 1);
&:hover { &:hover {
background-color: rgba(245, 246, 247, 1); background-color: rgba(245, 246, 247, 1);
} }
} }
.VTActiveRow {
@extend .VTRow;
background-color: rgba(237, 244, 255, 1);
}
.VTRowColumn { .VTRowColumn {
text-align: left; text-align: left;
box-sizing: border-box; box-sizing: border-box;
...@@ -25,5 +33,4 @@ ...@@ -25,5 +33,4 @@
line-height: 22px; line-height: 22px;
color: rgba(30, 38, 51, 1); color: rgba(30, 38, 51, 1);
padding: 16px; padding: 16px;
border-bottom: 1px solid rgba(240, 242, 245, 1);
} }
import React from "react"; import { useCallback, useEffect, useState, useRef } from "react";
import { useCallback, useEffect, useState, useRef, useMemo } from "react"; import { Column, Table } from "react-virtualized";
import { Column, Table, AutoSizer } from "react-virtualized";
import style from "./index.module.scss"; import style from "./index.module.scss";
import "react-virtualized/styles.css"; // only needs to be imported once import "react-virtualized/styles.css"; // only needs to be imported once
import Checkbox from "@mui/material/Checkbox";
import MyCircularProgress from "@/components/mui/MyCircularProgress"; import MyCircularProgress from "@/components/mui/MyCircularProgress";
import { createTheme, ThemeProvider } from "@mui/material";
import NoData from "@/components/BusinessComponents/NoData";
import ascIcon from "@/assets/project/ascIcon.svg";
import descIcon from "@/assets/project/descIcon.svg";
import sortIcon from "@/assets/project/sort.svg";
type Order = "ASC" | "DESC"; // 升序为asc,降序为desc。 type Order = "ASC" | "DESC"; // 升序为asc,降序为desc。
...@@ -20,24 +25,52 @@ interface IVirtuallyTableProps { ...@@ -20,24 +25,52 @@ interface IVirtuallyTableProps {
hasCheckbox?: boolean; // 是否有复选框 hasCheckbox?: boolean; // 是否有复选框
selectItems?: Array<any>; // 选中的项 selectItems?: Array<any>; // 选中的项
setSelectItems?: any; // 设置选中的项 setSelectItems?: any; // 设置选中的项
// fixedHead?: boolean; // 是否是固定表头
noDataText?: string; // 无数据提示文案 noDataText?: string; // 无数据提示文案
// hasTableFooter?: boolean; // 是否有分页组件
// page?: number; // 当前页
// pageChange?: any; // 页码改变
// count?: number; // 总页数
// totalElements?: number; // 数据总量 不止是列表渲染的长度
sortState?: sortState; // 排序状态 sortState?: sortState; // 排序状态
setSortState?: any; // 设置排序状态 setSortState?: any; // 设置排序状态
// paginationType?: "simple" | "complex"; // 分页组件的类型 simple简洁式 complex复杂、带每页数量切换、总数等
// rowsPerPage?: number; // 每页多少条数据
// handleChangeRowsPerPage?: any; // 每页多少条数据变化
nodataText?: any; // 无数据文案 nodataText?: any; // 无数据文案
handleRow?: any; // 点击一行 handleRow?: any; // 点击一行
activeId?: string; // 选中的一行的id activeId?: string; // 选中的一行的id
disableFn?: any; // 禁用时根据disableFn来判断是否禁用 disableFn?: any; // 禁用时根据disableFn来判断是否禁用
headerHeight?: number; // 表头高度
} }
const theme = createTheme({
components: {
// 复选框样式
MuiSvgIcon: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
fontSize: "18px",
},
},
},
MuiCheckbox: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
"&.MuiCheckbox-indeterminate .MuiSvgIcon-root": {
color: "rgba(19, 112, 255, 1)",
},
"&.Mui-checked .MuiSvgIcon-root": {
color: "rgba(19, 112, 255, 1)",
},
},
},
},
MuiButtonBase: {
styleOverrides: {
root: {
"&.MuiCheckbox-root": {
padding: 0,
},
},
},
},
},
});
const VirtuallyTable = (props: IVirtuallyTableProps) => { const VirtuallyTable = (props: IVirtuallyTableProps) => {
const { const {
rows, rows,
...@@ -53,10 +86,10 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => { ...@@ -53,10 +86,10 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => {
handleRow, handleRow,
activeId, activeId,
disableFn, disableFn,
headerHeight = 59,
} = props; } = props;
const virtuallyTableBoxRef: any = useRef(null); const virtuallyTableBoxRef: any = useRef(null);
const virtuallyTableRef: any = useRef(null);
const [width, setWidth] = useState(0); const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0); const [height, setHeight] = useState(0);
...@@ -74,7 +107,75 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => { ...@@ -74,7 +107,75 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => {
getTableWidthHeight(); getTableWidthHeight();
}; };
const onSelectAllClick = useCallback(
(e: any) => {
if (e.target.checked) {
setSelectItems && setSelectItems(rows.map((row) => row[tableKey]));
} else {
setSelectItems && setSelectItems([]);
}
},
[setSelectItems, tableKey, rows]
);
const onSelectRowClick = useCallback(
(e: any, itemValue: string) => {
if (e.target.checked) {
setSelectItems && setSelectItems([...selectItems, itemValue]);
} else {
const selectItemIndex = selectItems.indexOf(itemValue);
const newSelectItems = [
...selectItems.slice(0, selectItemIndex),
...selectItems.slice(selectItemIndex + 1, selectItems.length),
];
setSelectItems && setSelectItems(newSelectItems);
}
},
[selectItems, setSelectItems]
);
const handleSort = useCallback(
(field: string) => {
if (sortState?.field === field) {
if (sortState?.order === "ASC") {
setSortState({
field,
order: "DESC",
});
} else if (sortState?.order === "DESC") {
setSortState({
field,
order: "ASC",
});
} else {
setSortState({
field,
order: "DESC",
});
}
} else {
setSortState({
field,
order: "DESC",
});
}
},
[sortState, setSortState]
);
const handleRowFn = useCallback(
(row: any) => {
if (!disableFn) {
handleRow && handleRow(row);
} else {
!disableFn(row) && handleRow && handleRow(row);
}
},
[disableFn, handleRow]
);
return ( return (
<ThemeProvider theme={theme}>
<div <div
ref={virtuallyTableBoxRef} ref={virtuallyTableBoxRef}
style={{ width: "100%", height: "100%", position: "relative" }} style={{ width: "100%", height: "100%", position: "relative" }}
...@@ -82,28 +183,112 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => { ...@@ -82,28 +183,112 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => {
<MyCircularProgress loading={loading} /> <MyCircularProgress loading={loading} />
{width && height && ( {width && height && (
<Table <Table
ref={virtuallyTableRef}
width={width} width={width}
height={height} height={height}
headerHeight={59} headerHeight={headerHeight}
rowHeight={54} rowHeight={54}
rowCount={rows.length} rowCount={rows.length}
rowGetter={({ index }: any) => rows[index]} rowGetter={({ index }: any) => rows[index]}
headerClassName={style.VTHeader} headerClassName={style.VTHeader}
onRowClick={(data: any) => {
handleRowFn(data.rowData);
}}
rowClassName={({ index }: any) => { rowClassName={({ index }: any) => {
if (index < 0) { if (index < 0) {
return style.VTHeaderRow; return style.VTHeaderRow;
} else {
if (rows[index][tableKey] === activeId) {
return style.VTActiveRow;
} else { } else {
return style.VTRow; return style.VTRow;
} }
}
}}
rowStyle={({ index }: any) => {
if (index !== -1) {
return {
background:
activeId === rows[index][tableKey]
? "rgba(237, 244, 255, 1)"
: "",
cursor: disableFn && disableFn(rows[index]) ? "no-drop" : "",
opacity: disableFn && disableFn(rows[index]) ? "0.3" : "",
};
}
}} }}
> >
{hasCheckbox && (
<Column
dataKey="checkbox"
headerRenderer={() => {
return (
<Checkbox
indeterminate={
selectItems.length > 0 &&
selectItems.length < rows.length
}
checked={
rows.length > 0 && selectItems.length === rows.length
}
onChange={(e) => onSelectAllClick(e)}
/>
);
}}
headerStyle={{ margin: 0 }}
style={{ margin: 0 }}
width={50}
cellRenderer={(data: any) => {
return (
<Checkbox
checked={
selectItems.filter(
(selectItem) => selectItem === data.rowData[tableKey]
).length > 0
}
onChange={(e) =>
onSelectRowClick(e, data.rowData[tableKey])
}
/>
);
}}
className={style.VTRowColumn}
/>
)}
{headCells.map((headCell) => { {headCells.map((headCell) => {
console.log(headCell.cellRenderer);
return ( return (
<Column <Column
key={headCell.id} key={headCell.id}
label={headCell.label} // label={headCell.label}
headerRenderer={(data: any) => {
if (headCell.sort) {
return (
<div>
<span>{headCell.label}</span>
<img
src={
sortState?.field === headCell.id
? sortState?.order === "ASC"
? ascIcon
: sortState?.order === "DESC"
? descIcon
: sortIcon
: sortIcon
}
alt=""
onClick={() => handleSort(headCell.id)}
style={{
marginLeft: "8px",
cursor: "pointer",
position: "relative",
top: "3px",
}}
/>
</div>
);
} else {
return headCell.label;
}
}}
dataKey={headCell.id} dataKey={headCell.id}
width={headCell.width} width={headCell.width}
flexGrow={headCell.flexGrow || 0} flexGrow={headCell.flexGrow || 0}
...@@ -120,7 +305,19 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => { ...@@ -120,7 +305,19 @@ const VirtuallyTable = (props: IVirtuallyTableProps) => {
})} })}
</Table> </Table>
)} )}
{rows.length === 0 && (
<NoData
text={nodataText}
noDataBoxStyle={{
position: "absolute",
bottom: 0,
width: `${width}px`,
height: `${height - headerHeight}px`,
}}
/>
)}
</div> </div>
</ThemeProvider>
); );
}; };
......
.tableBox {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
height: 100%;
position: relative;
}
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import VirtuallyList from "../VirtuallyList";
import style from "./index.module.scss";
interface IVrituallyCardTableProps {
data: Array<any>; // 列表数据
renderItem: any; // 单个卡片的渲染函数 这里面的元素的boxSizing属性最好是"border-box",
rowHeight: number; // 行高 这个属性的高度最好是itemHeight + verticalSpacing
itemMinWidth?: number; // 单个卡片的最小宽度,有这个参数时numberOfColumns参数失效,效果为根据屏幕大小和单个卡片的最小宽度来适配每行渲染个数
tableKey?: string; // 表格数据的key
numberOfColumns?: number; // 列数 每行渲染几个
horizontalSpacing?: number; // 水平方向的间隔
verticalSpacing?: number; // 垂直方向的间隔
loading?: boolean;
}
const VrituallyCardTable = (props: IVrituallyCardTableProps) => {
const {
data,
renderItem,
tableKey = "id",
rowHeight,
numberOfColumns: propsNumberOfColumns = 3,
horizontalSpacing = 20,
verticalSpacing = 20,
itemMinWidth,
loading = false,
} = props;
const [numberOfColumns, setNumberOfColumns] = useState(3);
const tableBoxRef: any = useRef(null);
const getNumberOfColumns = useCallback(() => {
if (itemMinWidth) {
const boxWidth = tableBoxRef?.current?.offsetWidth;
if (boxWidth) {
setNumberOfColumns(Math.floor(boxWidth / itemMinWidth));
} else {
setNumberOfColumns(propsNumberOfColumns);
}
} else {
setNumberOfColumns(propsNumberOfColumns);
}
}, [itemMinWidth, propsNumberOfColumns]);
useEffect(() => {
getNumberOfColumns();
}, [getNumberOfColumns]);
const boxWidth = useMemo(() => {
return `${100 / numberOfColumns}%`;
}, [numberOfColumns]);
window.onresize = () => {
getNumberOfColumns();
};
const listData = useMemo(() => {
let resData: any = [[]];
data.forEach((item) => {
if (resData[resData.length - 1].length >= numberOfColumns) {
resData.push([item]);
} else {
resData[resData.length - 1].push(item);
}
});
return resData;
}, [numberOfColumns, data]);
const renderRow = ({
index,
isScrolling,
isVisible,
key,
parent,
style,
}: any) => {
return (
<div key={key} style={style}>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
boxSizing: "border-box",
height: "100%",
}}
>
{listData[index].map((item: any, index: number) => {
return (
<div
className={style.itemBox}
key={item[tableKey] ? item[tableKey] : index}
style={{
width: boxWidth,
paddingLeft: `${horizontalSpacing / 2}px`,
paddingRight: `${horizontalSpacing / 2}px`,
paddingBottom: `${verticalSpacing}px`,
boxSizing: "border-box",
}}
>
{renderItem(item, index)}
</div>
);
})}
</div>
</div>
);
};
return (
<div
className={style.tableBox}
style={{
marginLeft: `-${horizontalSpacing / 2}px`,
marginRight: `-${horizontalSpacing / 2}px`,
width: `calc(100% + ${horizontalSpacing}px)`,
}}
ref={tableBoxRef}
>
<VirtuallyList
list={listData}
renderRow={renderRow}
rowHeight={rowHeight}
loading={loading}
></VirtuallyList>
</div>
);
};
export default VrituallyCardTable;
import { useCallback, useMemo } from "react";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import Checkbox from "@mui/material/Checkbox";
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 CircularProgress from "@mui/material/CircularProgress";
import { createTheme, ThemeProvider } from "@mui/material";
import MyTooltip from "./MyTooltip";
import noFile from "@/assets/project/noFile.svg";
type Order = "ASC" | "DESC"; // 升序为asc,降序为desc。
export type sortState = {
field: string | null | undefined | ""; // 根据哪个属性来排序
order: Order | null | undefined | "";
};
interface IMyTableProps {
rows: Array<any>; // 表格数据
headCells: Array<any>; // 表头配置
tableKey?: string; // 表格数据的key
loading?: boolean; // 是否正在加载数据
hasCheckbox?: boolean; // 是否有复选框
selectItems?: Array<any>; // 选中的项
setSelectItems?: any; // 设置选中的项
fixedHead?: boolean; // 是否是固定表头
noDataText?: string; // 无数据提示文案
hasTableFooter?: boolean; // 是否有分页组件
page?: number; // 当前页
pageChange?: any; // 页码改变
count?: number; // 总页数
totalElements?: number; // 数据总量 不止是列表渲染的长度
sortState?: sortState; // 排序状态
setSortState?: any; // 设置排序状态
paginationType?: "simple" | "complex"; // 分页组件的类型 simple简洁式 complex复杂、带每页数量切换、总数等
rowsPerPage?: number; // 每页多少条数据
handleChangeRowsPerPage?: any; // 每页多少条数据变化
nodataText?: any; // 无数据文案
handleRow?: any; // 点击一行
activeId?: string; // 选中的一行的id
disableFn?: any; // 禁用时根据disableFn来判断是否禁用
}
const MyMuiTable = (props: IMyTableProps) => {
const {
rows,
headCells,
tableKey = "id",
loading = false,
hasCheckbox = false,
selectItems = [],
setSelectItems,
fixedHead,
hasTableFooter = false,
page = 0,
pageChange = () => {},
count = 1,
sortState,
setSortState,
paginationType = "simple",
rowsPerPage = 10,
handleChangeRowsPerPage,
totalElements = 0,
nodataText,
handleRow,
activeId,
disableFn,
} = props;
const theme = useMemo(() => {
return createTheme({
components: {
MuiTable: {
styleOverrides: {
root: {
// minHeight: "100px",
},
},
},
MuiTableHead: {
styleOverrides: {
root: {
background: "rgba(247, 248, 250, 1)",
"& .MuiTableRow-head": {
borderRadius: "4px 4px 0 0",
borderBottom: "1px solid rgba(240, 242, 245, 1)",
},
},
},
},
MuiTableRow: {
styleOverrides: {
root: {
opacity: loading ? 0.5 : 1,
":hover": {
background: "rgba(245, 246, 247, 1)",
},
"& .MuiTableCell-root": {
"&.MuiTableCell-head": {
fontSize: "12px",
lineHeight: "20px",
color: "rgba(138, 144, 153, 1)",
padding: "12px 16px",
whiteSpace: "nowrap",
},
"&.MuiTableCell-head:nth-of-type(1)": {
paddingRight: hasCheckbox ? "8px" : "16px",
},
},
"&.MuiTableRow-footer": {
// 分页的那一行不要hover效果
":hover": {
background: "#fff",
},
},
},
},
},
MuiPaper: {
styleOverrides: {
root: {
// minHeight: "200px",
position: "relative",
"&.MuiTableContainer-root": {
boxShadow: "none",
},
},
},
},
MuiTableCell: {
styleOverrides: {
root: {
boxSizing: "border-box",
fontSize: "14px",
lineHeight: "22px",
color: "rgba(30, 38, 51, 1)",
padding: "16px",
borderBottom: "1px solid rgba(240, 242, 245, 1)",
},
},
},
MuiTableBody: {
styleOverrides: {
root: {
minHeight: "200px",
position: "relative",
"& .MuiTableRow-root:nth-last-of-type(1) .MuiTableCell-root": {
// 有分页的话 表格最后一行就不要下边框
borderBottom: hasTableFooter
? "none"
: "1px solid rgba(240, 242, 245, 1)",
},
},
},
},
// 复选框样式
MuiSvgIcon: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
fontSize: "18px",
},
},
},
MuiCheckbox: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
"&.MuiCheckbox-indeterminate .MuiSvgIcon-root": {
color: "rgba(19, 112, 255, 1)",
},
"&.Mui-checked .MuiSvgIcon-root": {
color: "rgba(19, 112, 255, 1)",
},
},
},
},
MuiButtonBase: {
styleOverrides: {
root: {
"&.MuiCheckbox-root": {
padding: 0,
},
},
},
},
MuiCircularProgress: {
styleOverrides: {
root: {
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
margin: "auto",
zIndex: 1,
},
},
},
},
});
}, [hasCheckbox, hasTableFooter, loading]);
const onSelectAllClick = useCallback(
(e: any) => {
if (e.target.checked) {
setSelectItems && setSelectItems(rows.map((row) => row[tableKey]));
} else {
setSelectItems && setSelectItems([]);
}
},
[setSelectItems, tableKey, rows]
);
const onSelectRowClick = useCallback(
(e: any, itemValue: string) => {
if (e.target.checked) {
setSelectItems && setSelectItems([...selectItems, itemValue]);
} else {
const selectItemIndex = selectItems.indexOf(itemValue);
const newSelectItems = [
...selectItems.slice(0, selectItemIndex),
...selectItems.slice(selectItemIndex + 1, selectItems.length),
];
setSelectItems && setSelectItems(newSelectItems);
}
},
[selectItems, setSelectItems]
);
const handleRowFn = useCallback(
(row: any) => {
if (!disableFn) {
handleRow && handleRow(row);
} else {
!disableFn(row) && handleRow && handleRow(row);
}
},
[disableFn, handleRow]
);
const handleSort = useCallback(
(field: string) => {
if (sortState?.field === field) {
if (sortState?.order === "ASC") {
setSortState({
field,
order: "DESC",
});
} else if (sortState?.order === "DESC") {
setSortState({
field,
order: "ASC",
});
} else {
setSortState({
field,
order: "DESC",
});
}
} else {
setSortState({
field,
order: "DESC",
});
}
},
[sortState, setSortState]
);
const randerTableHead = useMemo(() => {
return (
<TableHead>
<TableRow>
{hasCheckbox && (
<TableCell align="left" sx={{ width: "18px", paddingRight: "8px" }}>
<Checkbox
indeterminate={
selectItems.length > 0 && selectItems.length < rows.length
}
checked={rows.length > 0 && selectItems.length === rows.length}
onChange={(e) => onSelectAllClick(e)}
/>
</TableCell>
)}
{headCells.map((headCell, index) => (
<TableCell key={index} align="left" width={headCell.width}>
{headCell.sort && (
<>
<span>{headCell.label}</span>
<img
src={
sortState?.field === headCell.id
? sortState?.order === "ASC"
? ascIcon
: sortState?.order === "DESC"
? descIcon
: sortIcon
: sortIcon
}
alt=""
onClick={() => handleSort(headCell.id)}
style={{
marginLeft: "8px",
cursor: "pointer",
position: "relative",
top: "3px",
}}
/>
</>
)}
{!headCell.sort && headCell.label}
</TableCell>
))}
</TableRow>
</TableHead>
);
}, [
hasCheckbox,
headCells,
selectItems,
onSelectAllClick,
rows.length,
handleSort,
sortState,
]);
const randerTableBody = useMemo(() => {
if (rows.length === 0) {
if (loading) {
return (
<tbody>
<tr>
<td></td>
</tr>
</tbody>
);
}
return (
<tbody>
<tr>
<td>
<img
src={noFile}
alt=""
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -100%)",
}}
/>
<span
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, 8px)",
fontSize: "14px",
lineHeight: "22px",
color: "#8a9099",
}}
>
{nodataText || "暂无数据"}
</span>
</td>
</tr>
</tbody>
);
}
return (
<TableBody>
{rows.map((row, rowIndex) => (
<TableRow
key={row[tableKey] || rowIndex}
onClick={() => handleRowFn(row)}
sx={{
background:
activeId === row[tableKey] ? "rgba(237, 244, 255, 1)" : "",
cursor: disableFn && disableFn(row) ? "no-drop" : "",
opacity: disableFn && disableFn(row) ? "0.3" : "",
}}
>
{hasCheckbox && (
<TableCell
align="left"
sx={{ width: "18px", paddingRight: "8px" }}
>
<Checkbox
checked={
selectItems.filter(
(selectItem) => selectItem === row[tableKey]
).length > 0
}
onChange={(e) => onSelectRowClick(e, row[tableKey])}
/>
</TableCell>
)}
{headCells.map((headCell, index) => (
<TableCell key={index} align="left" width={headCell.width}>
{headCell.showOverflowTooltip && (
<MyTooltip title={row[headCell.id]}>
<div
style={{
width: Number(headCell.width) - 32 || "",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{row[headCell.id]}
</div>
</MyTooltip>
)}
{!headCell.showOverflowTooltip && (
<div
style={{
width: headCell.width ? Number(headCell.width) - 32 : "",
}}
>
{row[headCell.id]}
</div>
)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
);
}, [
rows,
tableKey,
hasCheckbox,
selectItems,
onSelectRowClick,
headCells,
nodataText,
loading,
handleRowFn,
activeId,
disableFn,
]);
const randerTableFooter = useMemo(() => {
if (hasTableFooter) {
return (
<div
style={{
padding: "20px 0",
display: "flex",
justifyContent: "flex-end",
alignItems: "center",
borderTop: "1px solid rgba(240, 242, 245, 1)",
}}
>
<MyPagination
page={page}
pageChange={pageChange}
count={count}
totalElements={totalElements}
type={paginationType}
rowsPerPage={rowsPerPage}
handleChangeRowsPerPage={handleChangeRowsPerPage}
/>
</div>
);
} else {
return null;
}
}, [
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} sx={{ minHeight: "200px" }}>
{randerCircularProgress}
<Table>
{randerTableHead}
{randerTableBody}
</Table>
</TableContainer>
{randerTableFooter}
</>
)}
{fixedHead && (
<div
style={{
height: "100%",
display: "flex",
flexDirection: "column",
position: "relative",
}}
>
<TableContainer
component={Paper}
sx={{
minHeight: "45px",
overflowY: "scroll",
background: "rgba(247, 248, 250, 1)",
}}
>
<Table sx={{}}>{randerTableHead}</Table>
</TableContainer>
<TableContainer
component={Paper}
sx={{ flex: 1, minHeight: "200px", overflowY: "scroll" }}
>
<Table>{randerTableBody}</Table>
</TableContainer>
{randerTableFooter}
{randerCircularProgress}
</div>
)}
</ThemeProvider>
);
};
export default MyMuiTable;
import { useCallback, useMemo } from "react"; import MyMuiTable from "./MyMuiTable";
import Table from "@mui/material/Table"; import VirtuallyTable from "../CommonComponents/VirtuallyTable";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import Checkbox from "@mui/material/Checkbox";
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 CircularProgress from "@mui/material/CircularProgress";
import { createTheme, ThemeProvider } from "@mui/material";
import MyTooltip from "./MyTooltip";
import noFile from "@/assets/project/noFile.svg";
type Order = "ASC" | "DESC"; // 升序为asc,降序为desc。 type Order = "ASC" | "DESC"; // 升序为asc,降序为desc。
...@@ -24,6 +9,7 @@ export type sortState = { ...@@ -24,6 +9,7 @@ export type sortState = {
}; };
interface IMyTableProps { interface IMyTableProps {
isVirtuallyTable?: boolean; // 是不是虚拟表格
rows: Array<any>; // 表格数据 rows: Array<any>; // 表格数据
headCells: Array<any>; // 表头配置 headCells: Array<any>; // 表头配置
tableKey?: string; // 表格数据的key tableKey?: string; // 表格数据的key
...@@ -51,6 +37,7 @@ interface IMyTableProps { ...@@ -51,6 +37,7 @@ interface IMyTableProps {
const MyTable = (props: IMyTableProps) => { const MyTable = (props: IMyTableProps) => {
const { const {
isVirtuallyTable = false,
rows, rows,
headCells, headCells,
tableKey = "id", tableKey = "id",
...@@ -75,473 +62,52 @@ const MyTable = (props: IMyTableProps) => { ...@@ -75,473 +62,52 @@ const MyTable = (props: IMyTableProps) => {
disableFn, disableFn,
} = props; } = props;
const theme = useMemo(() => { if (!isVirtuallyTable) {
return createTheme({
components: {
MuiTable: {
styleOverrides: {
root: {
// minHeight: "100px",
},
},
},
MuiTableHead: {
styleOverrides: {
root: {
background: "rgba(247, 248, 250, 1)",
"& .MuiTableRow-head": {
borderRadius: "4px 4px 0 0",
borderBottom: "1px solid rgba(240, 242, 245, 1)",
},
},
},
},
MuiTableRow: {
styleOverrides: {
root: {
opacity: loading ? 0.5 : 1,
":hover": {
background: "rgba(245, 246, 247, 1)",
},
"& .MuiTableCell-root": {
"&.MuiTableCell-head": {
fontSize: "12px",
lineHeight: "20px",
color: "rgba(138, 144, 153, 1)",
padding: "12px 16px",
whiteSpace: "nowrap",
},
"&.MuiTableCell-head:nth-of-type(1)": {
paddingRight: hasCheckbox ? "8px" : "16px",
},
},
"&.MuiTableRow-footer": {
// 分页的那一行不要hover效果
":hover": {
background: "#fff",
},
},
},
},
},
MuiPaper: {
styleOverrides: {
root: {
// minHeight: "200px",
position: "relative",
"&.MuiTableContainer-root": {
boxShadow: "none",
},
},
},
},
MuiTableCell: {
styleOverrides: {
root: {
boxSizing: "border-box",
fontSize: "14px",
lineHeight: "22px",
color: "rgba(30, 38, 51, 1)",
padding: "16px",
borderBottom: "1px solid rgba(240, 242, 245, 1)",
},
},
},
MuiTableBody: {
styleOverrides: {
root: {
minHeight: "200px",
position: "relative",
"& .MuiTableRow-root:nth-last-of-type(1) .MuiTableCell-root": {
// 有分页的话 表格最后一行就不要下边框
borderBottom: hasTableFooter
? "none"
: "1px solid rgba(240, 242, 245, 1)",
},
},
},
},
// 复选框样式
MuiSvgIcon: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
fontSize: "18px",
},
},
},
MuiCheckbox: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
"&.MuiCheckbox-indeterminate .MuiSvgIcon-root": {
color: "rgba(19, 112, 255, 1)",
},
"&.Mui-checked .MuiSvgIcon-root": {
color: "rgba(19, 112, 255, 1)",
},
},
},
},
MuiButtonBase: {
styleOverrides: {
root: {
"&.MuiCheckbox-root": {
padding: 0,
},
},
},
},
MuiCircularProgress: {
styleOverrides: {
root: {
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
margin: "auto",
zIndex: 1,
},
},
},
},
});
}, [hasCheckbox, hasTableFooter, loading]);
const onSelectAllClick = useCallback(
(e: any) => {
if (e.target.checked) {
setSelectItems && setSelectItems(rows.map((row) => row[tableKey]));
} else {
setSelectItems && setSelectItems([]);
}
},
[setSelectItems, tableKey, rows]
);
const onSelectRowClick = useCallback(
(e: any, itemValue: string) => {
if (e.target.checked) {
setSelectItems && setSelectItems([...selectItems, itemValue]);
} else {
const selectItemIndex = selectItems.indexOf(itemValue);
const newSelectItems = [
...selectItems.slice(0, selectItemIndex),
...selectItems.slice(selectItemIndex + 1, selectItems.length),
];
setSelectItems && setSelectItems(newSelectItems);
}
},
[selectItems, setSelectItems]
);
const handleRowFn = useCallback(
(row: any) => {
if (!disableFn) {
handleRow && handleRow(row);
} else {
!disableFn(row) && handleRow && handleRow(row);
}
},
[disableFn, handleRow]
);
const handleSort = useCallback(
(field: string) => {
if (sortState?.field === field) {
if (sortState?.order === "ASC") {
setSortState({
field,
order: "DESC",
});
} else if (sortState?.order === "DESC") {
setSortState({
field,
order: "ASC",
});
} else {
setSortState({
field,
order: "DESC",
});
}
} else {
setSortState({
field,
order: "DESC",
});
}
},
[sortState, setSortState]
);
const randerTableHead = useMemo(() => {
return (
<TableHead>
<TableRow>
{hasCheckbox && (
<TableCell align="left" sx={{ width: "18px", paddingRight: "8px" }}>
<Checkbox
indeterminate={
selectItems.length > 0 && selectItems.length < rows.length
}
checked={rows.length > 0 && selectItems.length === rows.length}
onChange={(e) => onSelectAllClick(e)}
/>
</TableCell>
)}
{headCells.map((headCell, index) => (
<TableCell key={index} align="left" width={headCell.width}>
{headCell.sort && (
<>
<span>{headCell.label}</span>
<img
src={
sortState?.field === headCell.id
? sortState?.order === "ASC"
? ascIcon
: sortState?.order === "DESC"
? descIcon
: sortIcon
: sortIcon
}
alt=""
onClick={() => handleSort(headCell.id)}
style={{
marginLeft: "8px",
cursor: "pointer",
position: "relative",
top: "3px",
}}
/>
</>
)}
{!headCell.sort && headCell.label}
</TableCell>
))}
</TableRow>
</TableHead>
);
}, [
hasCheckbox,
headCells,
selectItems,
onSelectAllClick,
rows.length,
handleSort,
sortState,
]);
const randerTableBody = useMemo(() => {
if (rows.length === 0) {
if (loading) {
return (
<tbody>
<tr>
<td></td>
</tr>
</tbody>
);
}
return (
<tbody>
<tr>
<td>
<img
src={noFile}
alt=""
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -100%)",
}}
/>
<span
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, 8px)",
fontSize: "14px",
lineHeight: "22px",
color: "#8a9099",
}}
>
{nodataText || "暂无数据"}
</span>
</td>
</tr>
</tbody>
);
}
return (
<TableBody>
{rows.map((row, rowIndex) => (
<TableRow
key={row[tableKey] || rowIndex}
// onClick={() => handleRow && handleRow(row)}
onClick={() => handleRowFn(row)}
sx={{
background:
activeId === row[tableKey] ? "rgba(237, 244, 255, 1)" : "",
cursor: disableFn && disableFn(row) ? "no-drop" : "",
opacity: disableFn && disableFn(row) ? "0.3" : "",
}}
>
{hasCheckbox && (
<TableCell
align="left"
sx={{ width: "18px", paddingRight: "8px" }}
>
<Checkbox
checked={
selectItems.filter(
(selectItem) => selectItem === row[tableKey]
).length > 0
}
onChange={(e) => onSelectRowClick(e, row[tableKey])}
/>
</TableCell>
)}
{headCells.map((headCell, index) => (
<TableCell key={index} align="left" width={headCell.width}>
{headCell.showOverflowTooltip && (
<MyTooltip title={row[headCell.id]}>
<div
style={{
width: Number(headCell.width) - 32 || "",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{row[headCell.id]}
</div>
</MyTooltip>
)}
{!headCell.showOverflowTooltip && (
<div
style={{
width: headCell.width ? Number(headCell.width) - 32 : "",
}}
>
{row[headCell.id]}
</div>
)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
);
}, [
rows,
tableKey,
hasCheckbox,
selectItems,
onSelectRowClick,
headCells,
nodataText,
loading,
handleRowFn,
activeId,
disableFn,
]);
const randerTableFooter = useMemo(() => {
if (hasTableFooter) {
return ( return (
<div <MyMuiTable
style={{ rows={rows}
padding: "20px 0", headCells={headCells}
display: "flex", tableKey={tableKey}
justifyContent: "flex-end", loading={loading}
alignItems: "center", hasCheckbox={hasCheckbox}
borderTop: "1px solid rgba(240, 242, 245, 1)", selectItems={selectItems}
}} setSelectItems={setSelectItems}
> fixedHead={fixedHead}
<MyPagination hasTableFooter={hasTableFooter}
page={page} page={page}
pageChange={pageChange} pageChange={pageChange}
count={count} count={count}
totalElements={totalElements} sortState={sortState}
type={paginationType} setSortState={setSortState}
paginationType={paginationType}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}
handleChangeRowsPerPage={handleChangeRowsPerPage} handleChangeRowsPerPage={handleChangeRowsPerPage}
/> totalElements={totalElements}
</div> nodataText={nodataText}
handleRow={handleRow}
activeId={activeId}
disableFn={disableFn}
></MyMuiTable>
); );
} else { } else {
return null;
}
}, [
hasTableFooter,
page,
count,
pageChange,
paginationType,
rowsPerPage,
handleChangeRowsPerPage,
totalElements,
]);
const randerCircularProgress = useMemo(() => {
if (loading) {
return <CircularProgress></CircularProgress>;
} else {
return null;
}
}, [loading]);
return ( return (
<ThemeProvider theme={theme}> <VirtuallyTable
{!fixedHead && ( rows={rows}
<> headCells={headCells}
<TableContainer component={Paper} sx={{ minHeight: "200px" }}> tableKey={tableKey}
{randerCircularProgress} loading={loading}
<Table> hasCheckbox={hasCheckbox}
{randerTableHead} selectItems={selectItems}
{randerTableBody} setSelectItems={setSelectItems}
</Table> sortState={sortState}
</TableContainer> setSortState={setSortState}
{randerTableFooter} nodataText={nodataText}
</> handleRow={handleRow}
)} activeId={activeId}
{fixedHead && ( disableFn={disableFn}
<div ></VirtuallyTable>
style={{
height: "100%",
display: "flex",
flexDirection: "column",
position: "relative",
}}
>
<TableContainer
component={Paper}
sx={{
minHeight: "45px",
overflowY: "scroll",
background: "rgba(247, 248, 250, 1)",
}}
>
<Table sx={{}}>{randerTableHead}</Table>
</TableContainer>
<TableContainer
component={Paper}
sx={{ flex: 1, minHeight: "200px", overflowY: "scroll" }}
>
<Table>{randerTableBody}</Table>
</TableContainer>
{randerTableFooter}
{randerCircularProgress}
</div>
)}
</ThemeProvider>
); );
}
}; };
export default MyTable; export default MyTable;
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
box-sizing: border-box; box-sizing: border-box;
} }
.projectDataStickyTopPadding { .projectDataStickyTopPadding {
padding: 22px 24px 24px; padding: 22px 24px 64px;
} }
.projectDataTitle { .projectDataTitle {
font-size: 18px; font-size: 18px;
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
.tableBox { .tableBox {
/* flex: 1; */ /* flex: 1; */
height: calc(100% - 146px); height: calc(100% - 140px);
} }
.projectDataButtonAndSearch { .projectDataButtonAndSearch {
display: flex; display: flex;
......
...@@ -271,18 +271,6 @@ const ProjectData = observer(() => { ...@@ -271,18 +271,6 @@ const ProjectData = observer(() => {
} }
}; };
// table配置
const versionsHeadCells = [
{ id: "name", label: "名称" },
{ id: "size", label: "大小", width: 200 },
{
id: "mtime",
label: "创建时间",
width: 200,
},
{ id: "caozuo", label: "操作", width: 200 },
];
// 文件夹下钻 // 文件夹下钻
const handleViewFolders = (item: any) => { const handleViewFolders = (item: any) => {
if (debounce) { if (debounce) {
...@@ -304,52 +292,54 @@ const ProjectData = observer(() => { ...@@ -304,52 +292,54 @@ const ProjectData = observer(() => {
}; };
// table配置 // table配置
const renderName = (item: any) => { const renderName = (data: any) => {
if (item.type === "directory") { if (data.rowData.type === "directory") {
return ( return (
<span <span
className={classnames({ className={classnames({
[style.folderIconBox]: true, [style.folderIconBox]: true,
[style.pointer]: true, [style.pointer]: true,
})} })}
onClick={() => handleViewFolders(item)} onClick={() => handleViewFolders(data.rowData)}
> >
<img className={style.folderIcon} src={folderIcon} alt="" /> <img className={style.folderIcon} src={folderIcon} alt="" />
{item.name} {data.rowData.name}
</span> </span>
); );
} else if (item.type === "dataSet") { } else if (data.rowData.type === "dataSet") {
return ( return (
<span <span
className={classnames({ className={classnames({
[style.folderIconBox]: true, [style.folderIconBox]: true,
[style.pointer]: true, [style.pointer]: true,
})} })}
onClick={() => handleSeeDataset(item)} onClick={() => handleSeeDataset(data.rowData)}
> >
<img className={style.folderIcon} src={dataSetIcon} alt="" /> <img className={style.folderIcon} src={dataSetIcon} alt="" />
{item.name} {data.rowData.name}
</span> </span>
); );
} else { } else {
return ( return (
<span className={style.folderIconBox}> <span className={style.folderIconBox}>
<img className={style.folderIcon} src={fileIcon} alt="" /> <img className={style.folderIcon} src={fileIcon} alt="" />
{item.name} {data.rowData.name}
</span> </span>
); );
} }
}; };
const renderSize = (item: any) => { const renderSize = (data: any) => {
if (item.type === "dataSet") { if (data.rowData.type === "dataSet") {
return `${item.size}条`; return `${data.rowData.size}条`;
} }
return `${item.size ? storageUnitFromB(Number(item.size)) : "-"}`; return `${
data.rowData.size ? storageUnitFromB(Number(data.rowData.size)) : "-"
}`;
}; };
const renderMtime = (item: any) => { const renderMtime = (data: any) => {
return String(moment(item.mtime).format("YYYY-MM-DD HH:mm:ss")); return String(moment(data.rowData.mtime).format("YYYY-MM-DD HH:mm:ss"));
}; };
const renderButtons = (item: any) => { const renderButtons = (data: any) => {
return ( return (
<span style={{ whiteSpace: "nowrap" }}> <span style={{ whiteSpace: "nowrap" }}>
{!isAllDirectory && ( {!isAllDirectory && (
...@@ -362,14 +352,15 @@ const ProjectData = observer(() => { ...@@ -362,14 +352,15 @@ const ProjectData = observer(() => {
height: "22px", height: "22px",
padding: "0 10px", padding: "0 10px",
visibility: visibility:
item.type !== "dataSet" && item.type !== "directory" data.rowData.type !== "dataSet" &&
data.rowData.type !== "directory"
? "visible" ? "visible"
: "hidden", : "hidden",
}} }}
variant="text" variant="text"
size="medium" size="medium"
disabled={selectIds.length > 0 || !isPass("PROJECT_DATA_DOWNLOAD")} disabled={selectIds.length > 0 || !isPass("PROJECT_DATA_DOWNLOAD")}
onClick={() => hanleDownloadFile(item)} onClick={() => hanleDownloadFile(data.rowData)}
/> />
)} )}
<MyButton <MyButton
...@@ -384,7 +375,7 @@ const ProjectData = observer(() => { ...@@ -384,7 +375,7 @@ const ProjectData = observer(() => {
variant="text" variant="text"
size="medium" size="medium"
onClick={() => { onClick={() => {
setCurrentOperateFile(item); setCurrentOperateFile(data.rowData);
setMoveDialogOpen(true); setMoveDialogOpen(true);
}} }}
disabled={ disabled={
...@@ -405,7 +396,7 @@ const ProjectData = observer(() => { ...@@ -405,7 +396,7 @@ const ProjectData = observer(() => {
size="medium" size="medium"
color="error" color="error"
onClick={() => { onClick={() => {
setCurrentOperateFile(item); setCurrentOperateFile(data.rowData);
setDeleteDialogOpen(true); setDeleteDialogOpen(true);
}} }}
disabled={ disabled={
...@@ -416,6 +407,25 @@ const ProjectData = observer(() => { ...@@ -416,6 +407,25 @@ const ProjectData = observer(() => {
); );
}; };
// table配置
const versionsHeadCells = [
{
id: "name",
label: "名称",
width: 200,
flexGrow: 2,
cellRenderer: renderName,
},
{ id: "size", label: "大小", width: 200, cellRenderer: renderSize },
{
id: "mtime",
label: "创建时间",
width: 200,
cellRenderer: renderMtime,
},
{ id: "caozuo", label: "操作", width: 200, cellRenderer: renderButtons },
];
// 下载文件 // 下载文件
const hanleDownloadFile = (item: any) => { const hanleDownloadFile = (item: any) => {
const downloadPath = const downloadPath =
...@@ -590,18 +600,13 @@ const ProjectData = observer(() => { ...@@ -590,18 +600,13 @@ const ProjectData = observer(() => {
</div> </div>
<div className={style.tableBox}> <div className={style.tableBox}>
<MyTable <MyTable
isVirtuallyTable={true}
fixedHead={true} fixedHead={true}
hasCheckbox={showCheckBox} hasCheckbox={showCheckBox}
headCells={versionsHeadCells} headCells={versionsHeadCells}
selectItems={selectIds} selectItems={selectIds}
setSelectItems={setSelectIds} setSelectItems={setSelectIds}
rows={showList.map((item: any, index: number) => ({ rows={showList}
...item,
name: renderName(item),
size: renderSize(item),
mtime: renderMtime(item),
caozuo: renderButtons(item),
}))}
/> />
</div> </div>
</div> </div>
......
...@@ -174,7 +174,7 @@ const AddMember = observer((props: IProps) => { ...@@ -174,7 +174,7 @@ const AddMember = observer((props: IProps) => {
setProjectMember(e.target.value); setProjectMember(e.target.value);
} }
}} }}
placeholder="搜索项目成员" placeholder="按回车搜索项目成员"
sx={{ mb: 2 }} sx={{ mb: 2 }}
/> />
<div style={{ height: "320px" }}> <div style={{ height: "320px" }}>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-12 11:20:29 * @Date: 2022-07-12 11:20:29
* @LastEditors: 吴永生 15770852798@163.com * @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-07 10:06:13 * @LastEditTime: 2022-11-10 17:40:11
* @FilePath: /bkunyun/src/views/Project/components/Flow/components/BatchNode.tsx * @FilePath: /bkunyun/src/views/Project/components/Flow/components/BatchNode.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -73,7 +73,7 @@ const BatchNode = (props: IBatchNode) => { ...@@ -73,7 +73,7 @@ const BatchNode = (props: IBatchNode) => {
? "1px solid #FF4E4E" ? "1px solid #FF4E4E"
: "1px solid #fff", : "1px solid #fff",
left: index * 24 + 20, left: index * 24 + 20,
top: '-47px', top: isFlowNode ? '-47px' : '-3px',
}} }}
type="target" type="target"
position={Position.Top} position={Position.Top}
......
...@@ -269,22 +269,23 @@ const Flow = (props: IProps) => { ...@@ -269,22 +269,23 @@ const Flow = (props: IProps) => {
positionYArr.sort((a, b) => { positionYArr.sort((a, b) => {
return a - b; return a - b;
}); });
const initialHeight = isFlowNode(value.id) ? 66 : 12;
let width = 176, let width = 176,
height = 12; height = initialHeight
if (positionXArr?.length) { if (positionXArr?.length) {
const val = positionXArr[positionXArr.length - 1] + 144; const val = positionXArr[positionXArr.length - 1] + 144;
width = val > 176 ? val : width; width = val > 176 ? val : width;
} }
if (positionYArr?.length) { if (positionYArr?.length) {
const val = positionYArr[positionYArr.length - 1] + 74; const val = positionYArr[positionYArr.length - 1] + 74;
height = val > 12 ? val : height; height = val > initialHeight ? val : height;
} }
return { return {
width, width,
height, height,
}; };
}, },
[tasks] [isFlowNode, tasks]
); );
/** 生成初始化node节点 */ /** 生成初始化node节点 */
...@@ -322,8 +323,9 @@ const Flow = (props: IProps) => { ...@@ -322,8 +323,9 @@ const Flow = (props: IProps) => {
/** 样式 */ /** 样式 */
style: { style: {
...getBatchStyle(item), ...getBatchStyle(item),
marginTop: "-44px", marginTop: isFlowNode(item.id) ? "-44px": '0px',
padding: "12px 20px 20px 20px", padding: "12px 20px 20px 20px",
visibility: 'visible',
}, },
}, },
/** 坐标 */ /** 坐标 */
...@@ -494,7 +496,7 @@ const Flow = (props: IProps) => { ...@@ -494,7 +496,7 @@ const Flow = (props: IProps) => {
const getClassType = useCallback( const getClassType = useCallback(
(connection: Connection) => { (connection: Connection) => {
let inputClassType = "", let inputClassType = "",
outClassType: string | undefined = undefined; outClassType: string | undefined = '';
tasks?.length && tasks?.length &&
tasks.forEach((item) => { tasks.forEach((item) => {
if ([connection.source, connection.target].includes(item.id)) { if ([connection.source, connection.target].includes(item.id)) {
...@@ -612,7 +614,7 @@ const Flow = (props: IProps) => { ...@@ -612,7 +614,7 @@ const Flow = (props: IProps) => {
getTaskType(connection.target as string) === "FLOW" getTaskType(connection.target as string) === "FLOW"
) { ) {
return; return;
} else if (inputClassType === outClassType) { } else if (outClassType && (inputClassType.includes(outClassType) || outClassType.includes(inputClassType))) {
result = connectCheck(connection) as ITask[]; result = connectCheck(connection) as ITask[];
} else { } else {
Message.error("端口数据类型不一致,无法连接!"); Message.error("端口数据类型不一致,无法连接!");
......
...@@ -57,6 +57,6 @@ ...@@ -57,6 +57,6 @@
margin-left: 4px; margin-left: 4px;
} }
.LogViewBox { .LogViewBox {
margin: 0 24px; margin: 0 24px 20px;
position: relative; position: relative;
} }
...@@ -203,7 +203,7 @@ const OperatorList = observer((props: IOperatorListProps) => { ...@@ -203,7 +203,7 @@ const OperatorList = observer((props: IOperatorListProps) => {
setKeyword(e.target.value); setKeyword(e.target.value);
}} }}
value={keyword} value={keyword}
placeholder="输入关键词搜索" placeholder="输入关键词按回车搜索"
onKeyUp={handleEnterCode} onKeyUp={handleEnterCode}
size="medium" size="medium"
sx={{ height: 32, width: "100%" }} sx={{ height: 32, width: "100%" }}
......
...@@ -390,7 +390,7 @@ const ParameterSetting = (props: IParameterSettingProps) => { ...@@ -390,7 +390,7 @@ const ParameterSetting = (props: IParameterSettingProps) => {
</MyTooltip> </MyTooltip>
); );
}, },
[handleParameterChange, cpuList, gpuList] [handleParameterChange, cpuList, gpuList, cpuLoading, gpuLoading]
); );
// 输入参数 // 输入参数
......
import CardTable from "@/components/CommonComponents/CardTable"; import CardTable from "@/components/CommonComponents/CardTable";
import VrituallyCardTable from "@/components/CommonComponents/VrituallyCardTable";
const CardTableDemo = () => { const CardTableDemo = () => {
const list = [ const list = [
...@@ -44,12 +45,28 @@ const CardTableDemo = () => { ...@@ -44,12 +45,28 @@ const CardTableDemo = () => {
]; ];
const renderItem = (item: any) => { const renderItem = (item: any) => {
return ( return (
<div style={{ border: "1px solid red", height: "200px" }}>{item.id}</div> <div
style={{
border: "1px solid red",
height: "200px",
boxSizing: "border-box",
}}
>
{item.id}
</div>
); );
}; };
return ( return (
<div> <div>
CardTableDemo CardTableDemo
<div style={{ height: "600px" }}>
<VrituallyCardTable
data={list}
renderItem={renderItem}
numberOfColumns={4}
rowHeight={220}
></VrituallyCardTable>
</div>
<CardTable <CardTable
data={list} data={list}
renderItem={renderItem} renderItem={renderItem}
......
import VirtuallyList from "@/components/CommonComponents/VirtuallyList"; import VirtuallyList from "@/components/CommonComponents/VirtuallyList";
import VirtuallyTable from "@/components/CommonComponents/VirtuallyTable";
import MyButton from "@/components/mui/MyButton";
const VirtuallyListDemo = () => { const VirtuallyListDemo = () => {
let listData: Array<any> = []; let listData: Array<any> = [];
...@@ -25,6 +23,9 @@ const VirtuallyListDemo = () => { ...@@ -25,6 +23,9 @@ const VirtuallyListDemo = () => {
display: "flex", display: "flex",
justifyContent: "space-between", justifyContent: "space-between",
alignItems: "center", alignItems: "center",
boxSizing: "border-box",
height: "100%",
border: "1px solid red",
}} }}
> >
<div>{listData[index].name}</div> <div>{listData[index].name}</div>
...@@ -39,89 +40,14 @@ const VirtuallyListDemo = () => { ...@@ -39,89 +40,14 @@ const VirtuallyListDemo = () => {
); );
}; };
const rows = [
{
a: "啊手动阀建行卡实际付款啦即使对方卢卡库上的飞机啊离开解放了;拉萨的飞机拉萨酱豆腐啊肌肤抵抗力就",
b: "werewrw",
c: "asdfasf",
d: "asdfasdf",
e: "asd4534",
id: "1",
},
];
for (let i = 0; i < 10000; i++) {
rows.push({
a: "xcgh",
b: "sdf",
c: "sdfg",
d: "sdfg",
e: "wertwe",
id: "12" + i,
});
}
const buttonHeadCells = [
{
id: "a",
label: "属性a",
width: 150,
},
{
id: "b",
label: "属性b",
width: 150,
},
{
id: "c",
label: "属性c",
width: 150,
// flexGrow: 2,
},
{
id: "d",
label: "属性d",
width: 200,
flexGrow: 2,
},
{
id: "caozuo",
label: "操作",
width: 150,
cellRenderer: (data: any) => {
return (
<MyButton
text="删除"
onClick={() => {
// handleDelete(row.id);
}}
></MyButton>
);
},
},
];
return ( return (
<div> <div>
<div> <div>
{/* <VirtuallyList list={listData} renderRow={renderRow}></VirtuallyList>; */} <VirtuallyList
</div> list={listData}
<div style={{ height: "600px" }}> renderRow={renderRow}
<VirtuallyTable rowHeight={40}
// rows={rows} ></VirtuallyList>
rows={rows.map((row) => {
return {
...row,
// caozuo: (
// <MyButton
// text="删除"
// onClick={() => {
// // handleDelete(row.id);
// }}
// ></MyButton>
// ),
};
})}
headCells={buttonHeadCells}
/>
</div> </div>
</div> </div>
); );
......
import { useState } from "react";
import VirtuallyTable from "@/components/CommonComponents/VirtuallyTable";
import MyButton from "@/components/mui/MyButton";
const VirtuallyTableDemo = () => {
const rows = [
{
a: "啊手动阀建行卡实际付款啦即使对方卢卡库上的飞机啊离开解放了;拉萨的飞机拉萨酱豆腐啊肌肤抵抗力就",
b: "werewrw",
c: "asdfasf",
d: "asdfasdf",
e: "asd4534",
id: "a1",
},
];
for (let i = 0; i < 10000; i++) {
rows.push({
a: "xcgh",
b: "sdf",
c: "sdfg",
d: "sdfg",
e: "wertwe",
id: String(i),
});
}
const buttonHeadCells = [
{
id: "a",
label: "属性a",
width: 150,
},
{
id: "b",
label: "属性b",
width: 150,
},
{
id: "c",
label: "属性c",
width: 150,
// flexGrow: 2,
},
{
id: "d",
label: "属性d",
width: 200,
flexGrow: 2,
},
{
id: "caozuo",
label: "操作",
width: 150,
cellRenderer: (data: any) => {
return (
<MyButton
text="删除"
onClick={() => {
// handleDelete(row.id);
}}
></MyButton>
);
},
},
];
const [selectItems, setSelectItems] = useState([]);
return (
<div style={{ height: "600px" }}>
<VirtuallyTable
selectItems={selectItems}
setSelectItems={setSelectItems}
rows={rows}
headCells={buttonHeadCells}
activeId="8"
/>
</div>
);
};
export default VirtuallyTableDemo;
.box {
background-color: red;
}
...@@ -3,20 +3,24 @@ import QueueSelectDemo from "./QueueSelectDemo"; ...@@ -3,20 +3,24 @@ import QueueSelectDemo from "./QueueSelectDemo";
import IconfontDemo from "./IconfontDemo"; import IconfontDemo from "./IconfontDemo";
import CardTableDemo from "./CardTableDemo"; import CardTableDemo from "./CardTableDemo";
import VirtuallyListDemo from "./VirtuallyListDemo"; import VirtuallyListDemo from "./VirtuallyListDemo";
import VirtuallyTableDemo from "./VirtuallyTableDemo";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle"; import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import { useState } from "react"; import { useState } from "react";
import styles from "./index.module.css"; import styles from "./index.module.css";
import style from "./index.module.scss";
const Demo = () => { const Demo = () => {
const radioOptionsArr = [ const radioOptionsArr = [
{
value: "virtuallyTableDemo",
label: "virtuallyTableDemo",
},
{ {
value: "virtuallyListDemo", value: "virtuallyListDemo",
label: "virtuallyListDemo", label: "virtuallyListDemo",
}, },
{ {
value: "cardTable", value: "cardTable",
label: "cardTable", label: "cardTable/virtuallyCardTable",
}, },
{ {
value: "iconfont", value: "iconfont",
...@@ -51,6 +55,9 @@ const Demo = () => { ...@@ -51,6 +55,9 @@ const Demo = () => {
{selectDemo === "virtuallyListDemo" && ( {selectDemo === "virtuallyListDemo" && (
<VirtuallyListDemo></VirtuallyListDemo> <VirtuallyListDemo></VirtuallyListDemo>
)} )}
{selectDemo === "virtuallyTableDemo" && (
<VirtuallyTableDemo></VirtuallyTableDemo>
)}
{selectDemo === "cardTable" && <CardTableDemo></CardTableDemo>} {selectDemo === "cardTable" && <CardTableDemo></CardTableDemo>}
{selectDemo === "iconfont" && <IconfontDemo></IconfontDemo>} {selectDemo === "iconfont" && <IconfontDemo></IconfontDemo>}
{selectDemo === "队列选择器" && <QueueSelectDemo></QueueSelectDemo>} {selectDemo === "队列选择器" && <QueueSelectDemo></QueueSelectDemo>}
......
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