Commit c53470a3 authored by chenshouchao's avatar chenshouchao

Merge branch 'feat-20220908-dataset' into 'release'

cn-Feat 20220908 dataset

See merge request !102
parents 8ebf7808 6d9f6e40
......@@ -30,6 +30,27 @@ type IGetDatasetItemsListParams = {
sort?: string; // 排序
}
export type IQuery = {
index: string;
compare: ">" | "<" | ">=" | "<=" | "=" | "≈";
query: string;
};
type IQuerylist = Array<IQuery>
type IGetDatasetItemsListNewParamstype = {
type?: string;
projectId: string;
token: string;
filetoken: string;
path: string; // 数据集路径
name: string; // 数据集名称
page: number; //
size: number; //
index?: string; // 选择的属性
sort?: string; // 排序
}
type IGetDatasetSizeParams = {
type?: string; // 产品id
projectId: string;
......@@ -281,6 +302,22 @@ class CloudEController {
}
}
// 获取数据集里的数据列表(新 可支持高级搜索)
static GetDatasetItemsListNew(params: IGetDatasetItemsListNewParamstype, querylist: IQuerylist) {
if (ApiUtils.getAuthorizationHeaders(headers)) {
headers["Cache-Control"] = "no-cache";
let url = getUrlThroughParams(params, ['filetoken','path','token'], '?')
return axios.post(
`${APIOPTION()}:5003/find/dataset/new${url}`,{
querylist
},
{
headers: headers,
}
);
}
}
// 分子另存为
static SaveDataset(params: ISaveDatasetParams) {
if (ApiUtils.getAuthorizationHeaders(headers)) {
......
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 64</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-64">
<rect id="底框备份" x="0" y="0" width="16" height="16"></rect>
<polygon id="路径-15备份-5" fill="#8A9099" fill-rule="nonzero" points="7 3 7 13 3 13 3 11.2857143 5.39968807 11.2855021 5.4 3"></polygon>
<polygon id="路径-15备份-6" fill="#1370FF" fill-rule="nonzero" transform="translate(11.000000, 8.000000) scale(-1, -1) translate(-11.000000, -8.000000) " points="13 3 13 13 9 13 9 11.2857143 11.3996881 11.2855021 11.4 3"></polygon>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 8备份 5</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.Base基础/Icon图标/图表排序">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-4" transform="translate(1.000000, 1.000000)">
<rect id="矩形" stroke="#8A9099" stroke-width="1.5" x="0.75" y="0.75" width="12.5" height="12.5" rx="1"></rect>
<rect id="矩形备份-3" fill="#8A9099" x="3" y="3" width="3.25" height="3.25"></rect>
<rect id="矩形备份-7" fill="#8A9099" x="3" y="7.75" width="3.25" height="3.25"></rect>
<rect id="矩形备份-4" fill="#8A9099" x="7.75" y="3" width="3.25" height="3.25"></rect>
<rect id="矩形备份-9" fill="#8A9099" x="7.75" y="7.75" width="3.25" height="3.25"></rect>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/图表排序备份</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.Base基础/Icon图标/图表排序备份">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-4" transform="translate(1.000000, 1.000000)">
<rect id="矩形" stroke="#1370FF" stroke-width="1.5" x="0.75" y="0.75" width="12.5" height="12.5" rx="1"></rect>
<rect id="矩形备份-3" fill="#1370FF" x="3" y="3" width="3.25" height="3.25"></rect>
<rect id="矩形备份-7" fill="#1370FF" x="3" y="7.75" width="3.25" height="3.25"></rect>
<rect id="矩形备份-4" fill="#1370FF" x="7.75" y="3" width="3.25" height="3.25"></rect>
<rect id="矩形备份-9" fill="#1370FF" x="7.75" y="7.75" width="3.25" height="3.25"></rect>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 65</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-65">
<rect id="底框" x="0" y="0" width="16" height="16"></rect>
<polygon id="路径-15" fill="#1370FF" fill-rule="nonzero" points="7 3 7 13 3 13 3 11.2857143 5.39968807 11.2855021 5.4 3"></polygon>
<polygon id="路径-15备份" fill="#8A9099" fill-rule="nonzero" transform="translate(11.000000, 8.000000) scale(-1, -1) translate(-11.000000, -8.000000) " points="13 3 13 13 9 13 9 11.2857143 11.3996881 11.2855021 11.4 3"></polygon>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/筛选备份</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.Base基础/Icon图标/筛选备份">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组" transform="translate(1.780000, 2.250000)" stroke="#565C66" stroke-linejoin="round" stroke-width="1.5">
<polygon id="路径-37" points="0 0 12.4359884 0 7.73913801 5.73968697 7.73913801 12 4.97439538 10.7631496 4.97439538 5.85023682"></polygon>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/排序备份 5</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.Base基础/Icon图标/排序备份-5">
<rect id="底框" x="0" y="0" width="16" height="16"></rect>
<g id="排序" transform="translate(3.000000, 3.000000)" fill="#8A9099" fill-rule="nonzero">
<polygon id="路径-15" points="4 0 4 10 0 10 0 8.28571429 2.39968807 8.28550207 2.4 0"></polygon>
<polygon id="路径-15备份" transform="translate(8.000000, 5.000000) scale(-1, -1) translate(-8.000000, -5.000000) " points="10 0 10 10 6 10 6 8.28571429 8.39968807 8.28550207 8.4 0"></polygon>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/列表排序备份</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.Base基础/Icon图标/列表排序备份">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-4" transform="translate(1.000000, 1.000000)">
<rect id="矩形" stroke="#8A9099" stroke-width="1.5" x="0.75" y="0.75" width="12.5" height="12.5" rx="1"></rect>
<rect id="矩形" fill="#8A9099" x="3" y="3" width="8" height="1.5"></rect>
<rect id="矩形备份-10" fill="#8A9099" x="3" y="6.25" width="8" height="1.5"></rect>
<rect id="矩形备份-11" fill="#8A9099" x="3" y="9.5" width="8" height="1.5"></rect>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/列表排序备份 2</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.Base基础/Icon图标/列表排序备份">
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
<g id="编组-4" transform="translate(1.000000, 1.000000)">
<rect id="矩形" stroke="#1370FF" stroke-width="1.5" x="0.75" y="0.75" width="12.5" height="12.5" rx="1"></rect>
<rect id="矩形" fill="#1370FF" x="3" y="3" width="8" height="1.5"></rect>
<rect id="矩形备份-10" fill="#1370FF" x="3" y="6.25" width="8" height="1.5"></rect>
<rect id="矩形备份-11" fill="#1370FF" x="3" y="9.5" width="8" height="1.5"></rect>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -3,7 +3,7 @@
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #e6e8eb;
/* border: 1px solid #e6e8eb; */
border-radius: 4px;
background-color: #f0f2f5;
cursor: pointer;
......@@ -11,21 +11,28 @@
box-sizing: border-box;
padding: 2px;
}
.radio {
.radioBox {
position: relative;
min-width: 63px;
height: 28px;
box-sizing: border-box;
font-size: 14px;
color: #565c66;
border-radius: 2px;
line-height: 20px;
padding: 6px 16px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.radio {
position: relative;
box-sizing: border-box;
font-size: 14px;
color: #565c66;
padding: 6px 16px;
white-space: nowrap;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.radioActive {
......@@ -33,6 +40,8 @@
position: relative;
}
.border {
position: absolute;
right: 0px;
width: 1px;
height: 16px;
background-color: rgba(209, 214, 222, 1);
......@@ -41,10 +50,10 @@
visibility: hidden;
}
.radioActiveBgBox {
width: calc(100% - 2px);
width: calc(100% - 4px);
position: absolute;
left: 1px;
top: 1px;
left: 2px;
top: 2px;
height: 28px;
}
.radioActiveBg {
......
......@@ -8,12 +8,12 @@
*/
// 按钮样式的单选组
import classnames from "classnames";
import { useMemo } from "react";
import { ReactElement, useMemo } from "react";
import style from "./index.module.css";
type radioOption = {
value: string;
label: string;
label: string | ReactElement;
};
type IRadioGroupOfButtonStyleProps = {
......@@ -21,6 +21,7 @@ type IRadioGroupOfButtonStyleProps = {
value: string;
handleRadio: any;
RadiosBoxStyle?: object;
radioBoxStyle?: object;
radioStyle?: object;
radioActiveBgBoxStyle?: object;
};
......@@ -31,6 +32,7 @@ const RadioGroupOfButtonStyle = (props: IRadioGroupOfButtonStyleProps) => {
value,
handleRadio,
RadiosBoxStyle,
radioBoxStyle,
radioStyle,
radioActiveBgBoxStyle,
} = props;
......@@ -58,6 +60,7 @@ const RadioGroupOfButtonStyle = (props: IRadioGroupOfButtonStyleProps) => {
<div className={style.radioActiveBgBox} style={radioActiveBgBoxStyle}>
<div
className={style.radioActiveBg}
// 动画样式绑定
style={{
width: `${radioWidth}%`,
transform: `translateX(${activeIndex * 100}%)`,
......@@ -67,14 +70,17 @@ const RadioGroupOfButtonStyle = (props: IRadioGroupOfButtonStyleProps) => {
{radioOptions.map((options, index) => {
return (
<>
<div
key={options.value}
className={style.radioBox}
onClick={() => handleRadio(options.value)}
style={radioBoxStyle}
>
<div
className={classnames({
[style.radio]: true,
[style.radioActive]: value === options.value,
})}
onClick={() => handleRadio(options.value)}
style={radioStyle}
>
{options.label}
......@@ -82,6 +88,7 @@ const RadioGroupOfButtonStyle = (props: IRadioGroupOfButtonStyleProps) => {
<div
className={classnames({
[style.border]: true,
// 当相邻的两个tab都是未激活时中间有一条分隔线判断逻辑
[style.borderHidden]: !(
index !== radioOptions.length - 1 &&
index !== activeIndex &&
......@@ -89,7 +96,7 @@ const RadioGroupOfButtonStyle = (props: IRadioGroupOfButtonStyleProps) => {
),
})}
></div>
</>
</div>
);
})}
</div>
......
......@@ -27,6 +27,22 @@ const useMyRouter = () => {
);
permissionStore.restAddRoutes();
if (window.location.host === "localhost:8088") {
menuInfo.res.data.forEach((item: any) => {
if (item.id === 'cadd') {
item.routes.push({
element: 'Demo',
id: "demo",
name: "demo",
order: 1000,
path: "/demo",
show: true,
type: "page",
})
}
});
}
for (let item of menuInfo.res.data) {
for (let route of item.routes) {
route.element = elements[route.element] || NotFound;
......
......@@ -57,6 +57,7 @@ const theme = createTheme({
MuiSvgIcon: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
fontSize: "19px",
},
},
......
......@@ -82,6 +82,7 @@ type IMyMultipleMenuProps = {
showSelectAll?: boolean; // 是否显示全选
selectAllText?: string; // 全选的文字
showHiddenIcon?: boolean; // 是否显示 展开收起箭头
iconColor?: string; // 展开收起箭头的颜色
};
const MyMultipleMenu = (props: IMyMultipleMenuProps) => {
......@@ -93,6 +94,7 @@ const MyMultipleMenu = (props: IMyMultipleMenuProps) => {
showSelectAll = false,
selectAllText = "全部",
showHiddenIcon = true,
iconColor,
} = props;
// 下拉框展示的相对位置参考元素
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
......@@ -138,9 +140,15 @@ const MyMultipleMenu = (props: IMyMultipleMenuProps) => {
const randerShowHiddenIcon = () => {
if (Boolean(anchorEl)) {
return <ArrowDropUpIcon sx={{ color: "rgba(19, 112, 255, 1)" }} />;
return (
<ArrowDropUpIcon sx={{ color: iconColor || "rgba(19, 112, 255, 1)" }} />
);
} else {
return <ArrowDropDownIcon sx={{ color: "rgba(19, 112, 255, 1)" }} />;
return (
<ArrowDropDownIcon
sx={{ color: iconColor || "rgba(19, 112, 255, 1)" }}
/>
);
}
};
......
// 分页组件
import Pagination from "@mui/material/Pagination";
import MySelect from "./MySelect";
import { ThemeProvider, createTheme } from "@mui/material/styles";
const theme = createTheme({
components: {
MuiPagination: {
styleOverrides: {
ul: {
flexWrap: "nowrap",
},
},
},
MuiPaginationItem: {
styleOverrides: {
root: {
......@@ -24,16 +33,69 @@ 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}
......
......@@ -8,7 +8,7 @@
*/
import { useRef, useEffect, useState } from "react";
import Popover, { PopoverProps } from "@mui/material/Popover";
import Typography from "@mui/material/Typography";
import { ThemeProvider, createTheme } from "@mui/material/styles";
interface IProps extends Omit<PopoverProps, "open"> {
/** 触发行为 */
......@@ -22,7 +22,18 @@ interface IProps extends Omit<PopoverProps, "open"> {
/** open 修改 */
changeOpen: (val: boolean) => void;
}
const theme = createTheme({
components: {
MuiPaper: {
styleOverrides: {
root: {
boxShadow: "0px 3px 10px 0px rgba(0,24,57,0.14)",
},
},
},
},
});
// .css-3bmhjh-MuiPaper-root-MuiPopover-paper
const MyPopover = (props: IProps) => {
const [anchorEl, setAnchorEl] = useState<any | null>(null);
const ref = useRef(null);
......@@ -61,8 +72,9 @@ const MyPopover = (props: IProps) => {
const id = open ? "simple-popover" : undefined;
return (
<ThemeProvider theme={theme}>
<div>
<Typography
<div
ref={ref}
aria-owns={id}
onClick={trigger === "click" ? handelClick : undefined}
......@@ -70,7 +82,7 @@ const MyPopover = (props: IProps) => {
onMouseLeave={trigger === "hover" ? handlePopoverClose : undefined}
>
{children}
</Typography>
</div>
<Popover
id={id}
open={open}
......@@ -92,9 +104,10 @@ const MyPopover = (props: IProps) => {
}
}
>
<Typography sx={{ p: 1 }}>{content}</Typography>
{content}
</Popover>
</div>
</ThemeProvider>
);
};
......
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; // 无数据文案
}
const MyTable = (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,
} = 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: {
"&.Mui-checked .MuiSvgIcon-root": {
color: "rgba(19, 110, 250, 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 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: "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) => (
<TableRow key={row[tableKey]}>
{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}>
{/* {row[headCell.id]} */}
{headCell.showOverflowTooltip && (
<MyTooltip title={row[headCell.id]}>
<div
style={{
// width: headCell.width,
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,
]);
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 MyTable;
......@@ -32,6 +32,9 @@ const MenuLayout = observer(() => {
const routerIcon = (id: string, isSelect: boolean) => {
try {
if (id === "demo") {
return require("../../assets/project/PROJECT_SETTING.svg");
}
const result = require(`../../assets/project/${id}${
isSelect ? "_BLUE" : ""
}.svg`);
......
......@@ -49,8 +49,8 @@ const DeleteDialog = (props: IDeleteFileProps) => {
if (currentOperateFile) {
return [currentOperateFile];
} else {
return showList.filter((item: any) => {
return selectIds.indexOf(item.name) !== -1;
return selectIds.map((item) => {
return showList[item];
});
}
}, [currentOperateFile, selectIds, showList]);
......
......@@ -102,9 +102,11 @@ const MoveFile = (props: IMoveFileProps) => {
moveFolderArr = [];
}
} else {
moveFolderArr = showList.filter((item: any) => {
return selectIds.indexOf(item.name) !== -1 && item.type === "directory";
});
moveFolderArr = selectIds
.map((item) => {
return showList[item];
})
.filter((item) => item.type === "directory");
}
pathArr = moveFolderArr.map((item: any) => {
return path === "/" ? `/${item.name}` : `${path}/${item.name}`;
......@@ -147,8 +149,8 @@ const MoveFile = (props: IMoveFileProps) => {
if (currentOperateFile) {
return [currentOperateFile];
} else {
return showList.filter((item: any) => {
return selectIds.indexOf(item.name) !== -1;
return selectIds.map((item) => {
return showList[item];
});
}
}, [currentOperateFile, selectIds, showList]);
......
.list {
flex: 1;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
position: relative;
}
.datasetLi {
flex: 1;
min-width: 20%;
margin: 0 16px 16px 0;
border: 1px solid rgba(235, 237, 240, 1);
border-radius: 4px;
min-height: 275px;
box-sizing: border-box;
position: relative;
cursor: pointer;
}
.datasetLi:nth-child(4n) {
margin-right: 0;
}
.datasetLi:nth-last-child(1) {
margin-bottom: 0;
}
.datasetLi:nth-last-child(2) {
margin-bottom: 0;
}
.datasetLi:nth-last-child(3) {
margin-bottom: 0;
}
.datasetLi:nth-last-child(4) {
margin-bottom: 0;
}
.datasetLiTop {
height: 55%;
box-sizing: border-box;
}
.datasetLiBottom {
height: 45%;
box-sizing: border-box;
background-color: RGBA(247, 248, 250, 1);
display: flex;
flex-direction: column;
}
.datasetLiTitle {
height: 38px;
line-height: 38px;
color: rgba(19, 112, 255, 1);
font-size: 14px;
text-align: center;
font-weight: 600;
width: 100%;
overflow: hidden;
}
.datasetLiDataList {
flex: 1;
overflow: overlay;
}
.noDataList {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
color: rgba(138, 144, 153, 1);
font-size: 14px;
line-height: 22px;
}
.datasetLiDataLi {
height: 20px;
line-height: 20px;
color: rgba(30, 38, 51, 1);
font-size: 12px;
padding: 0 16px;
display: flex;
justify-content: space-between;
}
.datasetLiDataLi:nth-child(2n) {
background-color: rgba(235, 237, 240, 1);
}
.datasetLiDataLiKey {
max-width: 50%;
white-space: nowrap;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
.datasetLiDataLiValue {
max-width: 50%;
white-space: nowrap;
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
.nullBox {
visibility: hidden;
}
import { useMemo } from "react";
import NglView from "@/components/BusinessComponents/NglView";
import KekuleView from "@/components/BusinessComponents/KekuleView";
import MyTooltip from "@/components/mui/MyTooltip";
import Checkbox from "@mui/material/Checkbox";
import style from "./index.module.css";
import classNames from "classnames";
import MyCircularProgress from "@/components/mui/MyCircularProgress";
import NoData from "@/components/BusinessComponents/NoData";
type IDatasetCardTableProps = {
list: Array<any>;
graphicDimension: string;
showData: Array<string>;
selectItems: Array<string>;
setSelectItems: any;
loading: boolean;
};
const DatasetCardTable = (props: IDatasetCardTableProps) => {
const {
list,
graphicDimension,
showData,
selectItems,
setSelectItems,
loading,
} = props;
// 选择/取消分子
const handleSelectItem = (id: string) => {
let list: string[] = [...selectItems];
if (selectItems.filter((e) => e === id).length > 0) {
list = list.filter((e) => e !== id);
setSelectItems(list);
} else {
list.push(id);
setSelectItems(list);
}
};
// 空盒子用于布局
const nullBox = useMemo(() => {
if (list.length > 4) {
let nullBoxLength = Math.abs(8 - list.length);
return new Array(nullBoxLength).fill("");
} else {
return [];
}
}, [list]);
return (
<>
{list.length !== 0 && (
<>
<div className={style.list}>
<MyCircularProgress loading={loading} />
{list.map((item, index) => {
return (
<div
className={style.datasetLi}
key={item.id}
onClick={() => {
handleSelectItem(item.id);
}}
>
<div className={style.datasetLiTop}>
{graphicDimension === "2D" && (
<KekuleView id={`${index}2d`} smi={item.smiles} />
)}
{graphicDimension === "3D" && (
<NglView id={`${index}3d`} content={item.pdb} />
)}
</div>
<div className={style.datasetLiBottom}>
<div className={style.datasetLiTitle} title={item.smiles}>
{item.smiles}
</div>
{showData.length !== 0 && (
<div className={style.datasetLiDataList}>
{Object.keys(item)
.filter((key) => showData.indexOf(key) !== -1)
.map((key, index) => {
return (
<div
className={style.datasetLiDataLi}
key={index}
>
<span className={style.datasetLiDataLiKey}>
{key}
</span>
<MyTooltip title={item[key]}>
<span className={style.datasetLiDataLiValue}>
{item[key]}
</span>
</MyTooltip>
</div>
);
})}
</div>
)}
{showData.length === 0 && (
<div className={style.noDataList}>请选择显示数据</div>
)}
</div>
{graphicDimension === "2D" && (
<Checkbox
size="small"
sx={{
padding: "0px",
position: "absolute",
top: "16px",
right: "20px",
zIndex: 1,
}}
checked={selectItems.includes(item.id)}
/>
)}
{graphicDimension === "3D" && (
<Checkbox
size="small"
sx={{
padding: "0px",
position: "absolute",
top: "16px",
right: "20px",
zIndex: 1,
background: "RGBA(30, 38, 51, 1)",
border: "1px solid #565C66",
borderRadius: "2px",
}}
checked={selectItems.includes(item.id)}
/>
)}
</div>
);
})}
{nullBox.map((item, index) => {
return (
<div
className={classNames({
[style.datasetLi]: true,
[style.nullBox]: true,
})}
key={index + "null"}
></div>
);
})}
</div>
</>
)}
{list.length === 0 && <NoData text="未搜索到相关数据"></NoData>}
</>
);
};
export default DatasetCardTable;
import { useMemo } from "react";
import MyTable from "@/components/mui/MyTableNew";
import { sortState } from "@/components/mui/MyTableNew";
type IDatasetTableProps = {
list: Array<any>;
showData: Array<string>;
selectItems: Array<any>;
setSelectItems: any;
sortState: sortState;
setSortState: any;
loading: boolean;
};
const DatasetTable = (props: IDatasetTableProps) => {
const {
list,
showData,
selectItems,
setSelectItems,
sortState,
setSortState,
loading,
} = props;
const headCells = useMemo(() => {
let width =
showData.length === 0
? window.innerWidth - 112
: `${(window.innerWidth - 112) / showData.length}`;
return showData.map((item, index) => {
return {
id: item,
label: item,
width,
showOverflowTooltip: true,
sort: true,
};
});
}, [showData]);
return (
<MyTable
rows={list}
headCells={headCells}
hasCheckbox={true}
fixedHead={true}
selectItems={selectItems}
setSelectItems={setSelectItems}
sortState={sortState}
setSortState={setSortState}
loading={loading}
></MyTable>
);
};
export default DatasetTable;
......@@ -102,7 +102,6 @@ const Download = (props: IDownloadProps) => {
value={downloadType}
options={options}
onChange={(e) => handleChange(e)}
// fullWidth={true}
title="下载格式"
isTitle={true}
sx={{
......
......@@ -11,14 +11,14 @@
padding-bottom: 64px;
}
.top {
margin-bottom: 20px;
margin-bottom: 16px;
}
.title {
line-height: 22px;
color: rgba(30, 38, 51, 1);
font-size: 18px;
font-weight: 600;
margin-bottom: 20px;
margin-bottom: 16px;
}
.screens {
display: flex;
......@@ -30,134 +30,112 @@
justify-content: flex-start;
align-items: center;
}
.screensRight {
display: flex;
justify-content: flex-end;
align-items: center;
.separator {
width: 1px;
height: 20px;
background-color: rgba(230, 232, 235, 1);
margin: 0 15px;
}
.selectShowData {
margin-left: 24px;
font-size: 14px;
.graphicDimension {
line-height: 22px;
padding: 5px 16px;
color: rgba(138, 144, 153, 1);
background-color: #fff;
border-radius: 4px;
cursor: pointer;
}
.graphicDimensionActive {
color: rgba(19, 112, 255, 1);
background-color: rgba(240, 242, 245, 1);
}
.table {
flex: 1;
overflow-y: overlay;
display: flex;
flex-direction: column;
.marginRight20 {
margin-right: 20px;
}
.list {
flex: 1;
.screensRight {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.datasetLi {
flex: 1;
min-width: 20%;
margin: 0 16px 16px 0;
border: 1px solid rgba(235, 237, 240, 1);
border-radius: 4px;
min-height: 275px;
box-sizing: border-box;
justify-content: flex-end;
align-items: center;
position: relative;
cursor: pointer;
}
.datasetLi:nth-child(4n) {
margin-right: 0;
.searchBox {
width: 662px;
background-color: #fff;
padding: 20px 24px 24px;
box-sizing: border-box;
}
.datasetLi:nth-last-child(1) {
margin-bottom: 0;
.deleteIcon {
cursor: pointer;
}
.datasetLi:nth-last-child(2) {
margin-bottom: 0;
.deleteIconDisabled {
cursor: not-allowed;
}
.datasetLi:nth-last-child(3) {
margin-bottom: 0;
.searchTop {
margin-bottom: 12px;
}
.datasetLi:nth-last-child(4) {
margin-bottom: 0;
.searchTopText {
display: inline-block;
line-height: 22px;
font-size: 14px;
color: rgba(30, 38, 51, 1);
margin-right: 16px;
font-weight: 600;
}
.datasetLiTop {
height: 55%;
box-sizing: border-box;
.width250 {
width: 250px;
}
.datasetLiBottom {
height: 45%;
box-sizing: border-box;
background-color: RGBA(247, 248, 250, 1);
display: flex;
flex-direction: column;
.width120 {
width: 120px;
}
.datasetLiTitle {
height: 38px;
line-height: 38px;
color: rgba(19, 112, 255, 1);
font-size: 14px;
text-align: center;
font-weight: 600;
width: 100%;
overflow: hidden;
.width180 {
width: 180px;
}
.datasetLiDataList {
flex: 1;
overflow: overlay;
.searchList {
margin-bottom: 24px;
}
.noDataList {
flex: 1;
.searchLi {
display: flex;
justify-content: flex-start;
align-items: center;
justify-content: center;
color: rgba(138, 144, 153, 1);
font-size: 14px;
line-height: 22px;
margin-bottom: 16px;
}
.datasetLiDataLi {
height: 20px;
line-height: 20px;
color: rgba(30, 38, 51, 1);
font-size: 12px;
padding: 0 16px;
.searchFooter {
display: flex;
justify-content: space-between;
align-items: center;
}
.datasetLiDataLi:nth-child(2n) {
background-color: rgba(235, 237, 240, 1);
}
.datasetLiDataLiKey {
max-width: 50%;
white-space: nowrap;
display: block;
overflow: hidden;
text-overflow: ellipsis;
.searchFooterLeft {
color: rgba(19, 112, 255, 1);
font-size: 14px;
line-height: 22px;
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
}
.datasetLiDataLiValue {
max-width: 50%;
white-space: nowrap;
display: block;
overflow: hidden;
text-overflow: ellipsis;
.selectShowData {
font-size: 14px;
color: rgba(30, 38, 51, 1);
cursor: pointer;
}
.pagination {
height: 76px;
min-height: 76px;
.table {
flex: 1;
overflow-y: overlay;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.foot {
position: absolute;
bottom: 0;
background-color: #fff;
width: 100%;
width: calc(100vw - 64px);
box-sizing: border-box;
height: 64px;
height: 76px;
padding: 0 32px;
margin: 0 32px;
display: flex;
justify-content: flex-end;
align-items: center;
box-shadow: 0px -3px 10px 0px rgba(0, 24, 57, 0.04);
}
.nullBox {
visibility: hidden;
.borderTop {
border-top: 1px solid rgba(240, 242, 245, 1);
}
import FullScreenDrawer from "@/components/CommonComponents/FullScreenDrawer";
import { useState, useMemo, useCallback, useEffect } from "react";
import { useState, useCallback, useEffect } from "react";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import MyMultipleMenu, { IOption } from "@/components/mui/MyMultipleMenu";
import MySelect from "@/components/mui/MySelect";
import MyInput from "@/components/mui/MyInput";
import MyButton from "@/components/mui/MyButton";
import SearchIcon from "@mui/icons-material/Search";
import MyPagination from "@/components/mui/MyPagination";
import NglView from "@/components/BusinessComponents/NglView";
import KekuleView from "@/components/BusinessComponents/KekuleView";
import Checkbox from "@mui/material/Checkbox";
import CloudEController from "@/api/fileserver/CloudEController";
import { getToken } from "@/utils/util";
import { observer } from "mobx-react-lite";
import { useStores } from "@/store";
import { toJS } from "mobx";
import classNames from "classnames";
import Save from "./save";
import NoData from "@/components/BusinessComponents/NoData";
import Download from "./download";
import MyTooltip from "@/components/mui/MyTooltip";
import Save from "./components/Save";
import Download from "./components/Download";
import DatasetCardTable from "./components/DatasetCardTable";
import DatasetTable from "./components/DatasetTable";
import table from "@/assets/project/table.svg";
import tableActive from "@/assets/project/tableActive.svg";
import card from "@/assets/project/card.svg";
import cardActive from "@/assets/project/cardActive.svg";
import filter from "@/assets/project/filter.svg";
import jobDel from "@/assets/project/jobDel.svg";
import style from "./index.module.css";
import _ from "lodash";
import AddIcon from "@mui/icons-material/Add";
import MySelect from "@/components/mui/MySelect";
import { sortState } from "@/components/mui/MyTableNew";
import { IQuery } from "@/api/fileserver/CloudEController";
import MyInput from "@/components/mui/MyInput";
import MyPopover from "@/components/mui/MyPopover";
type ISeeDatasetProps = {
handleClose: any;
......@@ -35,68 +42,49 @@ const SeeDataset = observer((props: ISeeDatasetProps) => {
const { currentProjectStore } = useStores();
const productId = toJS(currentProjectStore.currentProductInfo.id); // 产品id 如:cadd
const token = getToken();
const [loading, setLoading] = useState(false);
const [tableType, setTableType] = useState<"table" | "card">("table"); // 展示普通表格还是卡片式表格
const [graphicDimension, setGraphicDimension] = useState("2D"); // 分子结构图是2D还是3D
const [showData, setShowData] = useState<Array<string>>([]); //显示的数据类型
const [showSearchBox, setShowSearchBox] = useState<boolean>(false); // 高级筛选显示隐藏控制
const [hasSmiles, setHasSmiles] = useState(false); // 是否是分子结构型数据集
const [dataTypes, setdataTypes] = useState<Array<IOption>>([]); // 可选的数据类型
const [sort, setSort] = useState("null"); // 排序方式
const [keyword, setKeyword] = useState(""); // 关键字
const [searchDataType, setSearchDataType] = useState<any>(null); // 搜索的数据属性
const [sortState, setSortState] = useState<sortState>({
// 排序状态
field: null,
order: null,
});
const [querylist, setQuerylist] = useState<Array<IQuery>>([]); // 高级筛选
const [queryInit, setQueryInit] = useState<IQuery>({
// 高级筛选初始化数据
index: "",
compare: ">",
query: "",
});
const [page, setPage] = useState(0); // 当前页码 // 请求接口的页码是从0开始的
const size = 8; // 每页数量
const [count, setCount] = useState(0); // 总页数
const [list, setList] = useState<Array<any>>([]); // 分子列表
const [selectItems, setSelectItems] = useState<Array<any>>([]);
const [selectItems, setSelectItems] = useState<Array<any>>([]); // 选中的数据
const [saveOpen, setSaveOpen] = useState(false); // 另存为弹窗显示控制
const [downloadOpen, setDownloadOpen] = useState(false); // 下载弹窗显示控制
const [showAnimation, setShowAnimation] = useState(true); // 弹窗动画变化中
const [firstGetList, setFirstGetList] = useState(true); // 第一次请求列表
// 解决图像渲染造成弹窗卡顿的问题
useEffect(() => {
setTimeout(() => {
setShowAnimation(false);
}, 300);
}, []);
const isCadd = useMemo(() => {
if (productId === "cadd") {
return true;
} else {
return false;
}
}, [productId]);
const handleSearchDataTypeChange = (e: any) => {
setSearchDataType(e);
};
const handleSortChange = (e: any) => {
setSort(e);
};
const handleKeywordChange = (e: any) => {
if (e.target.value.length <= 30) {
setKeyword(e.target.value);
}
};
// 页码改变
const pageChange = (value: number) => {
setPage(value - 1);
getList(value - 1);
};
// 空盒子用于布局
const nullBox = useMemo(() => {
if (list.length > 4) {
let nullBoxLength = 8 - list.length;
return new Array(nullBoxLength).fill("");
} else {
return [];
}
}, [list]);
// 获取分子列表
const getList = useCallback(
(paramsPage = 0) => {
setPage(paramsPage);
CloudEController.GetDatasetItemsList({
setSelectItems([]);
let requestQuerylist = querylist.filter((query) => {
return query.index !== "" && query.query !== "";
});
setLoading(true);
CloudEController.GetDatasetItemsListNew(
{
type: productId as string,
projectId: projectId as string,
token: token,
......@@ -104,48 +92,54 @@ const SeeDataset = observer((props: ISeeDatasetProps) => {
path: path,
name: name,
page: paramsPage,
size,
index: searchDataType ? `${searchDataType}` : "",
sort: sort === "null" ? "" : sort,
query: keyword,
})
size: tableType === "table" ? 15 : 8,
index: sortState.field ? sortState.field : "",
sort: sortState.order ? sortState.order : "",
},
requestQuerylist
)
?.then((res) => {
setLoading(false);
setList(res.data.list);
setCount(res.data.totalPage - 1);
if (res.data.list && res.data.list.length > 0) {
if (res.data.list[0]) {
let arr: any = [];
let _hasSmiles = false;
Object.keys(res.data.list[0]).forEach((item) => {
if (
![
"meta",
"id",
// "canonical_smiles",
// "mol",
// "mol2",
// "pdb",
// "sdf",
// "sdf2d",
// "sdf3d",
// "smiles",
].includes(item)
) {
if (!["meta", "id"].includes(item)) {
arr.push({ label: item, value: item });
}
if (item === "smiles") {
_hasSmiles = true;
}
});
if (firstGetList) {
setdataTypes(arr);
setSearchDataType(arr[0].value);
setShowData(arr.slice(0, 5).map((item: any) => item.value));
setHasSmiles(_hasSmiles);
setQuerylist([
{
index: arr[0]?.value || "",
compare: ">",
query: "",
},
]);
setQueryInit({
index: arr[0]?.value || "",
compare: ">",
query: "",
});
}
setFirstGetList(false);
setShowSearchBox(false);
}
}
})
?.catch((error) => {
setLoading(false);
console.log(error);
setList([]);
// Message.error(error?.response?.data?.message || "获取数据集信息失败");
// Message.error("未搜索到相关数据");
});
},
[
......@@ -155,272 +149,336 @@ const SeeDataset = observer((props: ISeeDatasetProps) => {
fileToken,
path,
name,
searchDataType,
sort,
keyword,
sortState,
firstGetList,
// Message,
querylist,
tableType,
]
);
// 当排序状态、展示方式改变的时候获取第一页数据
useEffect(() => {
getList(page);
}, [page]);
getList(0);
}, [sortState, tableType]);
// 高级筛选值变化
const handleIndexChange = (e: any, subscriptIndex: number) => {
let arr = _.cloneDeep(querylist);
arr[subscriptIndex].index = e;
setQuerylist(arr);
};
// 高级筛选值变化
const handleCompareChange = (e: any, subscriptIndex: number) => {
let arr = _.cloneDeep(querylist);
arr[subscriptIndex].compare = e;
setQuerylist(arr);
};
// 高级筛选值变化
const handleQueryChange = (e: any, subscriptIndex: number) => {
let arr = _.cloneDeep(querylist);
arr[subscriptIndex].query = e.target.value;
setQuerylist(arr);
};
// 高级筛选值变化
const handleDeleteQuery = (index: number) => {
if (querylist.length === 1) {
return;
}
let arr = _.cloneDeep(querylist);
arr.splice(index, 1);
setQuerylist(arr);
};
// 高级筛选值初始化
const handleInitQuerylist = () => {
setQuerylist([{ ...queryInit }]);
};
// 选择/取消分子
const handleSelectItem = (id: string) => {
let list: string[] = [...selectItems];
if (selectItems.filter((e) => e === id).length > 0) {
list = list.filter((e) => e !== id);
setSelectItems(list);
} else {
list.push(id);
setSelectItems(list);
// 显示数据变化
const handleSetShowData = (e: any) => {
if (e.length === 0) {
return;
}
setShowData(e);
};
// 高级筛选渲染
const searchBox = () => {
return (
<FullScreenDrawer handleClose={props.handleClose} zIndex={1100}>
<div
<div className={style.searchBox}>
<div className={style.searchTop}>
<span
className={classNames({
[style.datasetBox]: true,
[style.datasetBoxShowFoot]: true,
[style.searchTopText]: true,
[style.width250]: true,
})}
>
<div className={style.top}>
<div className={style.title}>{name}</div>
<div className={style.screens}>
<div className={style.screensLeft}>
{isCadd && (
<RadioGroupOfButtonStyle
handleRadio={setGraphicDimension}
value={graphicDimension}
radioOptions={[
{
value: "2D",
label: "2D",
},
{
value: "3D",
label: "3D",
},
]}
RadiosBoxStyle={{ width: "132px" }}
/>
)}
<MyMultipleMenu
value={showData}
options={dataTypes}
setValue={setShowData}
showSelectAll={true}
选择属性
</span>
<span
className={classNames({
[style.searchTopText]: true,
[style.width120]: true,
})}
>
<span className={style.selectShowData}>
选择显示数据({showData.length})
比较符
</span>
<span
className={classNames({
[style.searchTopText]: true,
[style.width180]: true,
})}
>
比较值
</span>
</MyMultipleMenu>
</div>
<div className={style.screensRight}>
<div className={style.searchList}>
{querylist.map((item, index) => {
return (
<div className={style.searchLi} key={index}>
<MySelect
options={dataTypes}
title={dataTypes.length === 0 ? "暂无属性" : "选择属性"}
isTitle={true}
value={searchDataType}
onChange={handleSearchDataTypeChange}
fullWidth={false}
disabled={dataTypes.length === 0}
sx={{
width: "160px",
marginRight: "16px",
height: "32px",
}}
placeholder="请选择属性"
value={item.index}
sx={{ marginRight: "16px", width: "250px" }}
onChange={(e) => handleIndexChange(e, index)}
></MySelect>
<MySelect
value={item.compare}
onChange={(e) => handleCompareChange(e, index)}
options={[
{
label: "无",
value: "null",
label: ">",
value: ">",
},
{
label: "<",
value: "<",
},
{
label: ">=",
value: ">=",
},
{
label: "<=",
value: "<=",
},
{
label: "正序",
value: "ASC",
label: "=",
value: "=",
},
{
label: "倒序",
value: "DESC",
label: "≈",
value: "≈",
},
]}
title="排序方式"
value={sort}
onChange={handleSortChange}
isTitle={true}
fullWidth={false}
sx={{
width: "160px",
marginRight: "16px",
height: "32px",
}}
sx={{ marginRight: "16px", width: "120px" }}
></MySelect>
<MyInput
value={keyword}
onChange={handleKeywordChange}
placeholder="请输入关键词搜索"
fullWidth={false}
InputProps={{
endAdornment: <SearchIcon style={{ color: "#8A9099" }} />,
}}
sx={{
width: "340px",
marginRight: "16px",
}}
size="small"
value={item.query}
onChange={(e) => handleQueryChange(e, index)}
sx={{ marginRight: "16px", width: "180px" }}
></MyInput>
<img
onClick={() => handleDeleteQuery(index)}
src={jobDel}
alt=""
className={classNames({
[style.deleteIcon]: true,
[style.deleteIconDisabled]: querylist.length === 1,
})}
/>
</div>
);
})}
</div>
<div className={style.searchFooter}>
<div
className={style.searchFooterLeft}
onClick={() => setQuerylist([...querylist, { ...queryInit }])}
>
<AddIcon sx={{ fontSize: "20px", marginRight: "6px" }} />
<span>添加条件</span>
</div>
<div className={style.searchFooterRight}>
<MyButton
text="确认"
style={{ width: "68px" }}
variant="outlined"
text="重置"
style={{ marginRight: "12px" }}
onClick={() => handleInitQuerylist()}
color="secondary"
></MyButton>
<MyButton
text="筛选"
onClick={() => {
getList();
getList(0);
}}
></MyButton>
</div>
</div>
</div>
{!showAnimation && (
<div className={style.table}>
{list.length !== 0 && (
<>
<div className={style.list}>
{list.map((item, index) => {
);
};
return (
<FullScreenDrawer handleClose={props.handleClose} zIndex={1100}>
<div
className={style.datasetLi}
key={item.id}
onClick={() => {
handleSelectItem(item.id);
}}
className={classNames({
[style.datasetBox]: true,
[style.datasetBoxShowFoot]: true,
})}
>
{isCadd && (
<div className={style.datasetLiTop}>
{graphicDimension === "2D" && (
<KekuleView id={`${index}2d`} smi={item.smiles} />
)}
{graphicDimension === "3D" && (
<NglView id={`${index}3d`} content={item.pdb} />
)}
</div>
<div className={style.top}>
<div className={style.title}>{name}</div>
<div className={style.screens}>
<div className={style.screensLeft}>
{hasSmiles && (
<>
<RadioGroupOfButtonStyle
handleRadio={setTableType}
value={tableType}
radioBoxStyle={{ minWidth: "40px" }}
radioStyle={{ padding: "0" }}
radioOptions={[
{
value: "table",
label: (
<img
src={tableType === "table" ? tableActive : table}
alt=""
></img>
),
},
{
value: "card",
label: (
<img
src={tableType === "card" ? cardActive : card}
alt=""
></img>
),
},
]}
/>
<div className={style.separator}></div>
</>
)}
<div className={style.datasetLiBottom}>
{tableType === "card" && hasSmiles && (
<>
<div
className={style.datasetLiTitle}
title={item.smiles}
className={classNames({
[style.graphicDimension]: true,
[style.graphicDimensionActive]: graphicDimension === "2D",
})}
onClick={() => setGraphicDimension("2D")}
>
{item.smiles}
2D
</div>
{showData.length !== 0 && (
<div className={style.datasetLiDataList}>
{Object.keys(item)
.filter((key) => showData.indexOf(key) !== -1)
.map((key, index) => {
return (
<div
className={style.datasetLiDataLi}
key={index}
>
<span
className={style.datasetLiDataLiKey}
className={classNames({
[style.graphicDimension]: true,
[style.graphicDimensionActive]: graphicDimension === "3D",
[style.marginRight20]: true,
})}
onClick={() => setGraphicDimension("3D")}
>
{key}
</span>
<MyTooltip title={item[key]}>
<span
className={style.datasetLiDataLiValue}
3D
</div>
</>
)}
<MyMultipleMenu
value={showData}
options={dataTypes}
setValue={(e: any) => handleSetShowData(e)}
showSelectAll={true}
iconColor="rgba(138, 144, 153, 1)"
>
{item[key]}
<span className={style.selectShowData}>
选择显示数据({showData.length})
</span>
</MyTooltip>
</MyMultipleMenu>
</div>
);
})}
<div className={style.screensRight}>
<MyPopover
open={showSearchBox}
changeOpen={(e) => setShowSearchBox(e)}
content={searchBox()}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
>
<MyButton
text="高级筛选"
variant="outlined"
color="secondary"
img={
<img
src={filter}
alt=""
style={{ marginRight: "10px" }}
></img>
}
style={{ margin: "4px 0" }}
></MyButton>
</MyPopover>
</div>
)}
{showData.length === 0 && (
<div className={style.noDataList}>
请选择显示数据
</div>
)}
</div>
{graphicDimension === "2D" && (
<Checkbox
size="small"
sx={{
padding: "0px",
position: "absolute",
top: "16px",
right: "20px",
zIndex: 1,
}}
checked={selectItems.includes(item.id)}
/>
<div className={style.table}>
{tableType === "table" && (
<DatasetTable
list={list}
showData={showData}
selectItems={selectItems}
setSelectItems={setSelectItems}
sortState={sortState}
setSortState={setSortState}
loading={loading}
></DatasetTable>
)}
{graphicDimension === "3D" && (
<Checkbox
size="small"
sx={{
padding: "0px",
position: "absolute",
top: "16px",
right: "20px",
zIndex: 1,
background: "RGBA(30, 38, 51, 1)",
border: "1px solid #565C66",
borderRadius: "2px",
}}
checked={selectItems.includes(item.id)}
/>
{tableType === "card" && (
<DatasetCardTable
list={list}
graphicDimension={graphicDimension}
showData={showData}
selectItems={selectItems}
setSelectItems={setSelectItems}
loading={loading}
></DatasetCardTable>
)}
</div>
);
})}
{nullBox.map((item, index) => {
return (
</div>
<div
className={classNames({
[style.datasetLi]: true,
[style.nullBox]: true,
[style.foot]: true,
[style.borderTop]: tableType === "table",
})}
key={index + "null"}
></div>
);
})}
</div>
<div className={style.pagination}>
<MyPagination
page={page}
pageChange={pageChange}
count={count}
/>
</div>
</>
)}
{list.length === 0 && <NoData text="未搜索到相关数据"></NoData>}
</div>
>
{selectItems.length === 0 && (
<MyPagination page={page} pageChange={pageChange} count={count} />
)}
</div>
<div className={style.foot}>
{isCadd && (
{selectItems.length !== 0 && (
<>
<MyButton
text={`另存为(${selectItems.length})`}
style={{ marginRight: "12px" }}
onClick={() => setSaveOpen(true)}
></MyButton>
<MyButton
variant="outlined"
text={`下载(${selectItems.length})`}
style={{ marginRight: "12px" }}
disabled={selectItems.length === 0}
onClick={() => setDownloadOpen(true)}
></MyButton>
</>
)}
<MyButton
disabled={selectItems.length === 0}
text={`另存为(${selectItems.length})`}
onClick={() => setSaveOpen(true)}
></MyButton>
</div>
{saveOpen && (
<Save
......
......@@ -14,6 +14,9 @@
margin-bottom: 14px;
font-weight: 600;
}
.tableBox {
height: 350px;
}
.dropBox {
cursor: pointer;
height: 300px;
......
......@@ -8,7 +8,7 @@ import style from "./index.module.css";
import MyDialog from "@/components/mui/MyDialog";
import { uuid } from "@/utils/util";
import { useMessage } from "@/components/MySnackbar";
import MyTable from "@/components/mui/MyTable";
import MyTable from "@/components/mui/MyTableNew";
import fileIcon from "@/assets/project/fileIcon.svg";
import noFile from "@/assets/project/noFile.svg";
import uploaderIcon from "@/assets/project/uploaderIcon.svg";
......@@ -149,9 +149,9 @@ const UpLoaderFile = observer((props: IMoveFileProps) => {
}, [uploaderDialogOpen]);
const fileListHeadCells = [
{ id: "name", numeric: false, label: "名称", width: "60%" },
{ id: "size", numeric: false, label: "大小", width: "25%" },
{ id: "caozuo", numeric: false, label: "操作", width: "15%" },
{ id: "name", label: "名称", width: 300 },
{ id: "size", label: "大小", width: 120 },
{ id: "caozuo", label: "操作", width: 100 },
];
const renderName = (item: any) => {
......@@ -163,7 +163,7 @@ const UpLoaderFile = observer((props: IMoveFileProps) => {
);
};
const renderSize = (item: any) => {
return <span>{item.size ? storageUnitFromB(Number(item.size)) : "-"}</span>;
return `${item.size ? storageUnitFromB(Number(item.size)) : "-"}`;
};
const handleRowDelete = (index: number) => {
......@@ -224,25 +224,14 @@ const UpLoaderFile = observer((props: IMoveFileProps) => {
</div>
<div className={style.tableBox}>
<MyTable
rowHover={true}
stickyHeader={true}
fixedHead={true}
rows={fileList.map((item: any, index: number) => ({
...item,
name: renderName(item),
size: renderSize(item),
caozuo: renderButtons(item, index),
}))}
rowsPerPage={"99"}
headCells={fileListHeadCells}
footer={false}
// headTableCellStyle={{
// fontSize: "12px",
// lineHeight: "20px",
// color: "#8A9099",
// }}
tableContainerStyle={{
maxHeight: "300px",
}}
/>
</div>
{fileList.length === 0 && (
......
......@@ -116,3 +116,6 @@
line-height: 22px;
color: #8a9099;
}
.tableBox {
height: calc(100vh - 300px);
}
......@@ -2,12 +2,11 @@ import React, { useState, useCallback, useEffect, useMemo } from "react";
import style from "./index.module.css";
import classnames from "classnames";
import { IconButton } from "@mui/material";
import MyTable from "@/components/mui/MyTable";
import MyTable from "@/components/mui/MyTableNew";
import dataSetIcon from "@/assets/project/dataSetIcon.svg";
import refresh from "@/assets/project/refresh.svg";
import fileIcon from "@/assets/project/fileIcon.svg";
import folderIcon from "@/assets/project/folderIcon.svg";
import noFile from "@/assets/project/noFile.svg";
import AddFolder from "./AddFolder";
import MoveFile from "./MoveFile";
import DeleteDialog from "./DeleteDialog";
......@@ -73,6 +72,11 @@ const ProjectData = observer(() => {
setPath(locationInfo?.pathName || "/");
}, [location]);
// 切换文件数据集时情况勾选项
useEffect(() => {
setSelectIds([]);
}, [activeTab]);
// 列表展示的数据
const showList = useMemo(() => {
if (activeTab === "file") {
......@@ -86,12 +90,24 @@ const ProjectData = observer(() => {
fileList.push(item);
}
});
return [...folderList, ...fileList];
let arr = [...folderList, ...fileList];
return arr.map((item, index) => {
return {
...item,
id: index,
};
});
} else {
const folderList = list.filter((item: any) => {
return item.type === "directory";
});
return [...folderList, ...dataSetList];
let arr = [...folderList, ...dataSetList];
return arr.map((item, index) => {
return {
...item,
id: index,
};
});
}
}, [list, dataSetList, activeTab]);
......@@ -256,45 +272,16 @@ const ProjectData = observer(() => {
};
// table配置
const versionsHeadCells = useMemo(() => {
if (showCheckBox) {
return [
{ id: "checkbox" },
{ id: "name", numeric: false, label: "名称", width: "25%" },
{ id: "size", numeric: false, label: "大小", width: "25%", sort: true },
const versionsHeadCells = [
{ id: "name", label: "名称" },
{ id: "size", label: "大小", width: 200 },
{
id: "mtime",
numeric: false,
label: "创建时间",
width: "25%",
sort: true,
width: 200,
},
{ id: "caozuo", numeric: false, label: "操作", width: "25%" },
{ id: "caozuo", label: "操作", width: 200 },
];
} else {
return [
{ id: "name", numeric: false, label: "名称", width: "25%" },
{ id: "size", numeric: false, label: "大小", width: "25%", sort: true },
{
id: "mtime",
numeric: false,
label: "创建时间",
width: "25%",
sort: true,
},
{ id: "caozuo", numeric: false, label: "操作", width: "25%" },
];
}
}, [showCheckBox]);
// 点击复选框
const hanldeCheckbox = (e: any) => {
const selectarr = e.map((item: any) => {
let andIndex = item.indexOf("&index=");
return item.slice(5, andIndex);
});
setSelectIds(selectarr);
};
// 文件夹下钻
const handleViewFolders = (item: any) => {
......@@ -312,7 +299,6 @@ const ProjectData = observer(() => {
// 查看数据集
const handleSeeDataset = (item: any) => {
console.log(item);
setSeeDatasetName(item.name);
setShowSeeDataset(true);
};
......@@ -593,32 +579,22 @@ const ProjectData = observer(() => {
</div>
</div>
</div>
<div className={style.tableBox}>
<MyTable
footer={false}
rowHover={true}
onRef={tableRef}
stickyHeader={true}
initSelected={selectIds}
fixedHead={true}
hasCheckbox={showCheckBox}
headCells={versionsHeadCells}
rowsPerPage={"99"}
checkboxData={(e: any) => {
hanldeCheckbox(e);
}}
selectItems={selectIds}
setSelectItems={setSelectIds}
rows={showList.map((item: any, index: number) => ({
...item,
id: `name=${item.name}&index=${index}`,
name: renderName(item),
size: renderSize(item),
mtime: renderMtime(item),
caozuo: renderButtons(item),
}))}
/>
{showList.length === 0 && (
<div className={style.noDataBox}>
<img className={style.noDataImg} src={noFile} alt="" />
<span className={style.noDataText}>暂无数据</span>
</div>
)}
</div>
{selectIds.length > 0 && (
<div className={style.projectDataStickyBox}>
......@@ -635,7 +611,6 @@ const ProjectData = observer(() => {
/>
<MyButton
text={`批量移动 (${selectIds.length})`}
// color="neutral"
variant="contained"
style={{ marginRight: "24px" }}
onClick={() => {
......
......@@ -9,15 +9,17 @@
import { toJS } from "mobx";
import { observer } from "mobx-react-lite";
import _ from "lodash";
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import { Box, OutlinedInput } from "@mui/material";
import { memo, useCallback, useEffect, useState } from "react";
import { Box } from "@mui/material";
import Dialog from "@/components/mui/MyDialog";
import useMyRequest from "@/hooks/useMyRequest";
import { useStores } from "@/store";
import { useMessage } from "@/components/MySnackbar";
import MyBorderlessSelect, { IOption } from "@/components/mui/MyBorderlessSelect";
import MyTable from "@/components/mui/MyTable";
import MyBorderlessSelect, {
IOption,
} from "@/components/mui/MyBorderlessSelect";
import MyTable from "@/components/mui/MyTableNew";
import SearchInput from "@/components/BusinessComponents/SearchInput";
import {
addProjectUser,
......@@ -35,7 +37,6 @@ const AddMember = observer((props: IProps) => {
const { addMemberDialog, setAddMemberDialog, getTableList } = props;
const { currentProjectStore } = useStores();
const [tableData, setTableData] = useState([]);
const [projectMember, setProjectMember] = useState("");
const [filterTableData, setFilterTableData] = useState([]);
......@@ -54,17 +55,18 @@ const AddMember = observer((props: IProps) => {
[tableData]
);
const columns = useMemo(() => {
return [
{ id: "checkbox", width: 50 },
{ id: "username", label: "项目成员", width: 160 },
const columns = [
{ id: "username", label: "项目成员", width: 200 },
{
id: "projectRole",
label: "项目权限",
width: 160,
render: (item: string, row: any, index: number) => {
width: 100,
},
];
const randerRole = (item: any, index: number) => {
const defaultValue = selectOptions.filter(
(every) => every.value === item
(every) => every.value === item.projectRole
);
return (
<MyBorderlessSelect
......@@ -72,12 +74,10 @@ const AddMember = observer((props: IProps) => {
onChange={(val) => changePermission(val, index)}
options={selectOptions}
size="small"
sx={{ position: "relative", left: "-13px" }}
/>
);
},
},
];
}, [changePermission, selectOptions]);
};
/** 过滤表格数据 */
useEffect(() => {
......@@ -93,11 +93,14 @@ const AddMember = observer((props: IProps) => {
}, [projectMember, tableData]);
// 获取表格数据接口
const { run: getProjectUsersList } = useMyRequest(fetchProjectUsersList, {
const { run: getProjectUsersList, loading } = useMyRequest(
fetchProjectUsersList,
{
onSuccess: (res: any) => {
setTableData(res?.data);
},
});
}
);
// 获取项目权限
const { run: getProjectPower } = useMyRequest(fetchProjectPower, {
......@@ -173,23 +176,22 @@ const AddMember = observer((props: IProps) => {
placeholder="搜索项目成员"
sx={{ mb: 2 }}
/>
<div style={{ overflow: "overlay", maxHeight: 400 }}>
<div style={{ height: "320px" }}>
<MyTable
noDataText={
projectMember ? `暂无 "${projectMember}" 搜索结果` : undefined
}
tableContainerStyle={{ height: 346 }}
checkboxData={(val: string[]) => setCheckData(val)}
param="username"
disabledParam={"enabled"}
rowHover={true}
stickyHeader={true}
rows={filterTableData}
rowsPerPage="99"
tableKey="username"
hasCheckbox={true}
selectItems={checkData}
setSelectItems={setCheckData}
fixedHead={true}
rows={filterTableData.map((item: any, idnex) => ({
...item,
projectRole: randerRole(item, idnex),
}))}
headCells={columns}
footer={false}
tableStyle={{ minWidth: "auto" }}
borderBottom="none"
loading={loading}
/>
</div>
</Box>
......
......@@ -10,3 +10,6 @@
margin-left: 32px;
cursor: pointer;
}
.tableBox {
height: calc(100vh - 300px);
}
......@@ -7,15 +7,12 @@
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import _ from "lodash";
import OutlinedInput from "@mui/material/OutlinedInput";
import { Box } from "@mui/material";
import SearchIcon from "@mui/icons-material/Search";
import Add from "@mui/icons-material/Add";
import { toJS } from "mobx";
import { observer } from "mobx-react";
import MyTable from "@/components/mui/MyTable";
import MyTable from "@/components/mui/MyTableNew";
import { IResponse, useHttp } from "@/api/http";
import RemoveItem from "./components/RemoveItem";
import ChangePermission from "./components/ChangePermission";
......@@ -52,26 +49,15 @@ const ProjectMembers = observer(() => {
const [projectName, setProjectMember] = useState("");
/** 过滤后数据 */
const [filterTableData, setFilterTableData] = useState([]);
const [loading, setLoading] = useState(false);
const columns = useMemo(() => {
const val: any = [
{ id: "username", label: "成员名称" },
{ id: "projectRoleDesc", label: "项目权限" },
{ id: "phone", label: "联系方式" },
...(projectRole !== "OWNER"
? []
: [
{
id: "operation",
label: "操作",
width: 160,
render: (item: any, row: any) => {
return row?.projectRole === "OWNER" ? null : (
const randerOperation = (item: any) => {
return item?.projectRole === "OWNER" ? null : (
<>
<span
style={{ color: "#1370FF", cursor: "pointer" }}
onClick={() => {
onPermissionBtn(row);
onPermissionBtn(item);
}}
>
更改权限
......@@ -79,17 +65,28 @@ const ProjectMembers = observer(() => {
<span
className={styles.removeItemBox}
onClick={() => {
onRemoveItemBtn(row.username);
onRemoveItemBtn(item.username);
}}
>
移出项目
</span>
</>
);
},
},
]),
};
const columns = useMemo(() => {
let val: any = [
{ id: "username", label: "成员名称", width: 200 },
{ id: "projectRoleDesc", label: "项目权限", width: 200 },
{ id: "phone", label: "联系方式" },
];
if (projectRole === "OWNER") {
val.push({
id: "operation",
label: "操作",
width: 180,
});
}
return val;
}, [projectRole]);
......@@ -97,14 +94,19 @@ const ProjectMembers = observer(() => {
const getTableList = useCallback(() => {
const projectInfo = toJS(currentProjectStore?.currentProjectInfo);
if (!projectInfo?.id) return;
setLoading(true);
http
.get<IResponse<any>>("/cpp/project/get", {
params: { id: projectInfo?.id || "" },
})
.then((res) => {
setLoading(false);
const { data = {} } = res;
setTableData(data?.members || []);
setProjectRole(data?.projectRole || "");
})
.catch(() => {
setLoading(false);
});
}, [currentProjectStore?.currentProjectInfo, http]);
......@@ -147,7 +149,7 @@ const ProjectMembers = observer(() => {
if (e.keyCode === 13) {
setProjectMember(e.target.value);
}
}
};
return (
<>
......@@ -159,7 +161,7 @@ const ProjectMembers = observer(() => {
/>
{currentProjectStore?.currentProjectInfo?.projectRole === "OWNER" ? (
<MyButton
text='添加成员'
text="添加成员"
style={{ backgroundColor: "#1370FF " }}
variant="contained"
onClick={onAddMember}
......@@ -168,16 +170,18 @@ const ProjectMembers = observer(() => {
/>
) : null}
</Box>
<div className={styles.tableBox}>
<MyTable
rowHover={true}
stickyHeader={true}
rows={filterTableData}
rowsPerPage={"99"}
fixedHead={true}
rows={filterTableData.map((item: any, index) => ({
...item,
operation: randerOperation(item),
}))}
tableKey="username"
headCells={columns}
footer={false}
tableStyle={{ minWidth: "auto" }}
borderBottom={"none"}
loading={loading}
/>
</div>
<RemoveItem
removeDialog={removeDialog}
setRemoveDialog={setRemoveDialog}
......
import { useState } from "react";
import MyButton from "@/components/mui/MyButton";
import { sortState } from "@/components/mui/MyTableNew";
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);
};
const [sortState, setSortState] = useState<sortState>({
field: "",
order: "",
});
const rows = [
{
a: "啊手动阀建行卡实际付款啦即使对方卢卡库上的飞机啊离开解放了;拉萨的飞机拉萨酱豆腐啊肌肤抵抗力就",
b: "werewrw",
c: "asdfasf",
d: "asdfasdf",
e: "asd4534",
id: "1",
},
{
a: "asdf",
b: "asdg",
c: "asdasdffasf",
d: "sfgh",
e: "asdgshdsdfh534",
id: "2",
},
{
a: "dfgj",
b: "xcvb",
c: "xcvb",
d: "xcvb",
e: "ert",
id: "3",
},
{
a: "xcgh",
b: "sdf",
c: "sdfg",
d: "sdfg",
e: "wertwe",
id: "4",
},
{
a: "as123",
b: "werewrw",
c: "asdfasf",
d: "asdfasdf",
e: "asd4534",
id: "5",
},
{
a: "asdf",
b: "asdg",
c: "asdasdffasf",
d: "sfgh",
e: "asdgshdsdfh534",
id: "6",
},
{
a: "dfgj",
b: "xcvb",
c: "xcvb",
d: "xcvb",
e: "ert",
id: "7",
},
{
a: "xcgh",
b: "sdf",
c: "sdfg",
d: "sdfg",
e: "wertwe",
id: "8",
},
{
a: "as123",
b: "werewrw",
c: "asdfasf",
d: "asdfasdf",
e: "asd4534",
id: "9",
},
{
a: "asdf",
b: "asdg",
c: "asdasdffasf",
d: "sfgh",
e: "asdgshdsdfh534",
id: "10",
},
{
a: "dfgj",
b: "xcvb",
c: "xcvb",
d: "xcvb",
e: "ert",
id: "11",
},
{
a: "xcgh",
b: "sdf",
c: "sdfg",
d: "sdfg",
e: "wertwe",
id: "12",
},
];
const buttonHeadCells = [
{
id: "a",
label: "属性a",
width: "150",
},
{
id: "b",
label: "属性b",
width: "250",
},
{
id: "c",
label: "属性c",
width: "350",
},
{
id: "d",
label: "属性d",
width: "250",
},
{
id: "caozuo",
label: "操作",
width: "250",
},
];
const headCells = [
{
id: "a",
label: "属性a",
width: "200",
showOverflowTooltip: true,
},
{
id: "b",
label: "属性b",
width: "200",
},
{
id: "c",
label: "属性c",
// width: "200",
},
{
id: "d",
label: "属性d",
width: "200",
},
];
const sortHeadCells = [
{
id: "a",
label: "属性a",
width: "25%",
sort: true,
},
{
id: "b",
label: "属性b",
width: "25%",
sort: true,
},
{
id: "c",
label: "属性c",
width: "25%",
},
{
id: "d",
label: "属性d",
width: "25%",
},
];
const [selectItems, setSelectItems] = useState(["1"]);
const handleDelete = (e: string) => {
console.log(e);
};
console.log(selectItems);
return (
<div>
<h2>常规表格</h2>
<div>
<MyTable
rows={rows.map((row) => {
return {
...row,
caozuo: (
<MyButton
text="删除"
onClick={() => {
handleDelete(row.id);
}}
></MyButton>
),
};
})}
// rows={[]}
headCells={buttonHeadCells}
selectItems={selectItems}
setSelectItems={setSelectItems}
/>
</div>
<h2>有复选框表格</h2>
<div>
<MyTable
rows={rows}
headCells={headCells}
hasCheckbox={true}
selectItems={selectItems}
setSelectItems={setSelectItems}
/>
</div>
<h2>固定表头(需要指定每列宽度 不然对不齐)表格,内容滚动, </h2>
<div style={{ height: "300" }}>
<MyTable
rows={rows}
headCells={headCells}
hasCheckbox={true}
selectItems={selectItems}
setSelectItems={setSelectItems}
fixedHead={true}
/>
</div>
<h2>带分页的表格</h2>
<div>
<MyTable
rows={rows}
headCells={headCells}
hasCheckbox={true}
selectItems={selectItems}
setSelectItems={setSelectItems}
hasTableFooter={true}
page={page}
count={count}
pageChange={pageChange}
paginationType={"complex"}
rowsPerPage={rowsPerPage}
handleChangeRowsPerPage={setRowsPerPage}
totalElements={12}
/>
</div>
<h2>带分页且固定表头(需要指定每列宽度 不然对不齐)的表格</h2>
<div style={{ height: "300" }}>
<MyTable
rows={rows}
headCells={headCells}
hasCheckbox={true}
selectItems={selectItems}
setSelectItems={setSelectItems}
fixedHead={true}
hasTableFooter={true}
page={page}
count={count}
pageChange={pageChange}
/>
</div>
<h2>
带排序表格(headCells中sort为true, 传入sortState、setSortState字段)
</h2>
<div>
<MyTable
rows={rows}
headCells={sortHeadCells}
selectItems={selectItems}
setSelectItems={setSelectItems}
sortState={sortState}
setSortState={setSortState}
/>
</div>
</div>
);
};
export default MyTableDemo;
.demoBox {
padding: 16px 16px 0;
box-sizing: border-box;
height: 100%;
overflow: auto;
display: flex;
flex-direction: column;
}
.demoContentBox {
padding-top: 16px;
flex: 1;
}
import { useMessage } from "@/components/MySnackbar";
// import usePass from "@/hooks/usePass";
import { operation, route } from "@/router";
import { Button } from "@mui/material";
import { Box } from "@mui/system";
import { useEffect } from "react";
import MyTableDemo from "./MyTableDemo";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import { useCallback, useMemo, useState } from "react";
import styles from "./index.module.css";
const Demo = ({
childrenRoutes,
}: {
childrenRoutes?: Array<route | operation>;
}) => {
const message = useMessage();
// const isPass = usePass();
useEffect(() => {
// console.log(isPass("PROJECT_OVERIVEW_CREATE"), "11111111111");
// console.log(isPass("PROJECT_SUMMARY_MEMBER"), "2222222");
// console.log(isPass("test"), "33333");
// eslint-disable-next-line react-hooks/exhaustive-deps
const Demo = () => {
const demoList = useCallback(() => {
return [
{
name: "表格",
element: MyTableDemo,
},
{
name: "box",
element: () => {
return <div>box</div>;
},
},
];
}, []);
const radioOptionsArr = [
{
value: "表格",
label: "表格",
},
{
value: "box",
label: "box",
},
];
const handleRadio = (e: string) => {
setSelectDemo(e);
};
const [selectDemo, setSelectDemo] = useState("表格");
const randerDemo = useMemo(() => {
return demoList().filter((item) => item.name === selectDemo)[0].element;
}, [selectDemo, demoList]);
return (
<Box>
<Box>{JSON.stringify(childrenRoutes)}</Box>
<Box>{JSON.stringify(process.env.NODE_ENV)}</Box>
<Button onClick={() => message.success("测试测试")}>message测试</Button>
</Box>
<div className={styles.demoBox}>
<RadioGroupOfButtonStyle
value={selectDemo}
radioOptions={radioOptionsArr}
handleRadio={handleRadio}
/>
<div className={styles.demoContentBox}>{randerDemo()}</div>
</div>
);
};
......
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