Commit a04fa626 authored by chenshouchao's avatar chenshouchao

feat: 新增多选下拉框组件

parent 577fbd69
...@@ -12,6 +12,14 @@ type IFullScreenDrawerProps = { ...@@ -12,6 +12,14 @@ type IFullScreenDrawerProps = {
const FullScreenDrawer = (props: IFullScreenDrawerProps) => { const FullScreenDrawer = (props: IFullScreenDrawerProps) => {
const { children, handleClose } = props; const { children, handleClose } = props;
const [closeing, setCloseing] = useState(false); const [closeing, setCloseing] = useState(false);
const handleReadyToClose = () => {
setCloseing(true);
setTimeout(() => {
setCloseing(false);
handleClose();
}, 1000);
};
return ( return (
<div <div
className={classNames({ className={classNames({
...@@ -27,13 +35,7 @@ const FullScreenDrawer = (props: IFullScreenDrawerProps) => { ...@@ -27,13 +35,7 @@ const FullScreenDrawer = (props: IFullScreenDrawerProps) => {
> >
<CloseOutlinedIcon <CloseOutlinedIcon
className={style.closeiIcon} className={style.closeiIcon}
onClick={() => { onClick={() => handleReadyToClose()}
setCloseing(true);
setTimeout(() => {
setCloseing(false);
handleClose();
}, 1000);
}}
/> />
</div> </div>
<div <div
......
...@@ -11,85 +11,92 @@ import FormGroup, { FormGroupProps } from "@mui/material/FormGroup"; ...@@ -11,85 +11,92 @@ import FormGroup, { FormGroupProps } from "@mui/material/FormGroup";
import FormControlLabel from "@mui/material/FormControlLabel"; import FormControlLabel from "@mui/material/FormControlLabel";
import Checkbox from "@mui/material/Checkbox"; import Checkbox from "@mui/material/Checkbox";
import FormControl from "@mui/material/FormControl"; import FormControl from "@mui/material/FormControl";
import FormHelperText from '@mui/material/FormHelperText'; import FormHelperText from "@mui/material/FormHelperText";
import _ from "lodash"; import _ from "lodash";
interface IMyCheckBoxProps extends FormGroupProps{ interface IMyCheckBoxProps extends FormGroupProps {
value: Array<any>; value: Array<any>;
options: Array<ICheckBoxOption>; options: Array<ICheckBoxOption>;
onChange: any; // 直接返回选中项的数组 onChange: any; // 直接返回选中项的数组
variant?: "standard" | "outlined" | "filled"; variant?: "standard" | "outlined" | "filled";
error?: boolean; error?: boolean;
helperText?: string; helperText?: string;
}; }
type ICheckBoxOption = { type ICheckBoxOption = {
value: any; value: any;
label?: string; label?: string;
disabled?: boolean; disabled?: boolean;
}; };
export const optionsTransform = ( export const optionsTransform = (
arr: Array<any>, arr: Array<any>,
labelKey: string = "label", labelKey: string = "label",
valueKey: string = "value", valueKey: string = "value",
disabledKey: string = "disabled" disabledKey: string = "disabled"
): Array<ICheckBoxOption> => { ): Array<ICheckBoxOption> => {
return arr.map((item: any) => { return arr.map((item: any) => {
return { return {
value: item[valueKey], value: item[valueKey],
label: item[labelKey], label: item[labelKey],
disabled: item[disabledKey] || false, disabled: item[disabledKey] || false,
}; };
}); });
}; };
export default function MyCheckBox(props: IMyCheckBoxProps) { export default function MyCheckBox(props: IMyCheckBoxProps) {
const { value, options, onChange, error = false, helperText, variant } = props; const {
value,
options,
onChange,
error = false,
helperText,
variant,
} = props;
const getCheckedStatus = ( const getCheckedStatus = (
checkBoxItemValue: any, checkBoxItemValue: any,
valueArr: Array<any> valueArr: Array<any>
): boolean => { ): boolean => {
const result = valueArr.indexOf(checkBoxItemValue); const result = valueArr.indexOf(checkBoxItemValue);
return result === -1 ? false : true; return result === -1 ? false : true;
}; };
const handleMyCheckBoxOnChange = (e: any) => { const handleMyCheckBoxOnChange = (e: any) => {
const resultArr = _.cloneDeep(value); const resultArr = _.cloneDeep(value);
const clickValue = e.target.name; const clickValue = e.target.name;
const clickValueIndex = value.indexOf(clickValue); const clickValueIndex = value.indexOf(clickValue);
if (clickValueIndex === -1) { if (clickValueIndex === -1) {
resultArr.push(clickValue); resultArr.push(clickValue);
onChange && onChange(resultArr); onChange && onChange(resultArr);
} else { } else {
resultArr.splice(clickValueIndex, 1); resultArr.splice(clickValueIndex, 1);
onChange && onChange(resultArr); onChange && onChange(resultArr);
} }
}; };
return ( return (
<FormControl fullWidth variant={variant} error={error}> <FormControl fullWidth variant={variant} error={error}>
<FormGroup {...props} row> <FormGroup {...props} row>
{options.map((option) => { {options.map((option) => {
return ( return (
<FormControlLabel <FormControlLabel
key={option.value} key={option.value}
control={ control={
<Checkbox <Checkbox
checked={getCheckedStatus(option.value, value)} checked={getCheckedStatus(option.value, value)}
value={option.value} value={option.value}
/> />
} }
label={option.label} label={option.label}
name={option.value} name={option.value}
onChange={handleMyCheckBoxOnChange} onChange={handleMyCheckBoxOnChange}
disabled={option.disabled} disabled={option.disabled}
/> />
); );
})} })}
</FormGroup> </FormGroup>
{helperText && error && <FormHelperText>{helperText}</FormHelperText>} {helperText && error && <FormHelperText>{helperText}</FormHelperText>}
</FormControl> </FormControl>
); );
} }
// 单选下拉框, 是input还是text还是其他由children决定
import * as React from "react"; import * as React from "react";
import Menu from "@mui/material/Menu"; import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem"; import MenuItem from "@mui/material/MenuItem";
...@@ -42,6 +44,13 @@ const theme = createTheme({ ...@@ -42,6 +44,13 @@ const theme = createTheme({
}, },
}, },
}, },
MuiList: {
styleOverrides: {
root: {
maxHeight: "268px",
},
},
},
MuiSvgIcon: { MuiSvgIcon: {
styleOverrides: { styleOverrides: {
root: { root: {
......
// 多选下拉框, 是input还是text还是其他由children决定
import * as React from "react";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import Checkbox from "@mui/material/Checkbox";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import _ from "lodash";
const theme = createTheme({
components: {
MuiMenu: {
styleOverrides: {
root: {
overflowY: "scroll",
},
},
},
MuiMenuItem: {
styleOverrides: {
root: {
fontSize: "14px",
lineHeight: "36px",
display: "flex",
justifyContent: "flex-start",
paddingTop: 0,
paddingBottom: 0,
paddingRight: "32px",
paddingLeft: "4px",
":hover": {
color: "rgba(30, 38, 51, 1)",
background: "rgba(240, 242, 245, 1)",
},
},
},
},
MuiList: {
styleOverrides: {
root: {
maxHeight: "268px",
},
},
},
MuiSvgIcon: {
styleOverrides: {
root: {
width: "22px",
height: "22px",
},
},
},
MuiButtonBase: {
styleOverrides: {
root: {},
},
},
MuiCheckbox: {
styleOverrides: {
root: {
color: "rgba(209, 214, 222, 1)",
"&.Mui-checked": {
color: "rgba(19, 112, 255, 1)",
},
},
},
},
},
});
export type IOption = {
label: string;
value: string;
};
type IMyMultipleMenuProps = {
children: React.ReactNode;
options: Array<IOption>; // 选项
value: Array<string>; // 选中的项values
setValue?: any; // 设置选中的项values
showSelectAll?: boolean; // 是否显示全选
selectAllText?: string; // 全选的文字
};
const MyMultipleMenu = (props: IMyMultipleMenuProps) => {
const {
children,
options,
value,
setValue,
showSelectAll = false,
selectAllText = "全部",
} = props;
// 下拉框展示的相对位置参考元素
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
// 展示/隐藏下拉框切换
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
setAnchorEl(event.currentTarget);
};
// 隐藏下拉框
const handleClose = (value: string) => {
setAnchorEl(null);
};
// 选择/取消选择
const handleMenuClick = (clickValue: string) => {
const resultArr = _.cloneDeep(value);
const valueIndex = value.indexOf(clickValue);
if (valueIndex === -1) {
resultArr.push(clickValue);
setValue && setValue(resultArr);
} else {
resultArr.splice(valueIndex, 1);
setValue && setValue(resultArr);
}
};
// 全选
const handleMenuAllClick = () => {
if (value.length === options.length) {
setValue([]);
} else {
setValue(options.map((option) => option.value));
}
};
// 是否选中
const getCheckedStatus = (
checkBoxItemValue: any,
valueArr: Array<any>
): boolean => {
const result = valueArr.indexOf(checkBoxItemValue);
return result === -1 ? false : true;
};
return (
<ThemeProvider theme={theme}>
<div>
<div onClick={handleClick}>{children}</div>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "basic-button",
}}
>
{showSelectAll && (
<MenuItem onClick={() => handleMenuAllClick()} key="indeterminate">
<Checkbox
checked={value.length === options.length}
indeterminate={value.length !== options.length}
/>
<span>{selectAllText}</span>
</MenuItem>
)}
{options.map((option, index) => {
return (
<MenuItem
onClick={() => handleMenuClick(option.value)}
key={index}
>
<Checkbox
checked={getCheckedStatus(option.value, value)}
value={option.value}
/>
<span>{option.label}</span>
</MenuItem>
);
})}
</Menu>
</div>
</ThemeProvider>
);
};
export default MyMultipleMenu;
import FullScreenDrawer from "@/components/CommonComponents/FullScreenDrawer"; import FullScreenDrawer from "@/components/CommonComponents/FullScreenDrawer";
import { useState } from "react";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import MyMultipleMenu, { IOption } from "@/components/mui/MyMultipleMenu";
import style from "./index.module.css";
type ISeeDatasetProps = { type ISeeDatasetProps = {
handleClose: any; handleClose: any;
}; };
const dataTypesMock = [
{
label: "123",
value: "1234",
},
{
label: "1232",
value: "12342",
},
{
label: "1233",
value: "12344",
},
];
const SeeDataset = (props: ISeeDatasetProps) => { const SeeDataset = (props: ISeeDatasetProps) => {
const [graphicDimension, setGraphicDimension] = useState("2D"); // 分子结构图是2D还是3D
const [showDataTypes, setShowDataTypes] = useState<Array<string>>([]); //显示的数据类型
const [dataTypes, setdataTypes] = useState<Array<IOption>>(dataTypesMock); // 可选的数据类型
return ( return (
<FullScreenDrawer handleClose={props.handleClose}> <FullScreenDrawer handleClose={props.handleClose}>
<h2>数据集title</h2>
<div className={style.screens}>
<div className={style.screensLeft}>
<RadioGroupOfButtonStyle
handleRadio={setGraphicDimension}
value={graphicDimension}
radioOptions={[
{
value: "2D",
label: "2D",
},
{
value: "3D",
label: "3D",
},
]}
RadiosBoxStyle={{ width: "132px" }}
></RadioGroupOfButtonStyle>
<MyMultipleMenu
value={showDataTypes}
options={dataTypes}
setValue={setShowDataTypes}
showSelectAll={true}
>
选择显示数据({showDataTypes.length})
</MyMultipleMenu>
</div>
<div className={style.screensRight}></div>
</div>
SeeDataset SeeDataset
</FullScreenDrawer> </FullScreenDrawer>
); );
......
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