import React, { useRef, useContext, ReactNode, CSSProperties } from 'react'; import { DownOutlined, LoadingOutlined, CheckCircleOutlined, MinusCircleOutlined } from '@ant-design/icons'; import { Popconfirm, Dropdown, DropDownProps, Menu, Tooltip, PopconfirmProps } from 'antd'; import classNames from 'classnames'; import ComponentContext from '../component-context'; import './style.less'; export interface OperatorItem { label?: ReactNode, icon?: string, visible?: boolean, disabled?: boolean, color?: string, loading?: boolean, isMore?: boolean, onClick?: () => void, confirm?: PopconfirmProps, statusSwitch?: Record, [key: string]: any, } export interface OperatorProps { // 操作项 items: OperatorItem[] | any, // 更多标签文案 moreText?: ReactNode, // 更多标签宽度 moreContentWidth?: string | number, // 显示更多下拉菜单触发方式 moreTrigger?: DropDownProps['trigger'], className?: string, prefixCls?: string, } function Operator(props: OperatorProps) { const context = useContext(ComponentContext); let { className, prefixCls = context.prefixCls, items, moreText, moreContentWidth, moreTrigger, } = props; prefixCls = `${prefixCls}-operator`; const rootClass = classNames(prefixCls, className); const dividerClass = `${prefixCls}-divider`; const labelClass = `${prefixCls}-label`; const labelRef = useRef([]); // 获取label function getLabel(options, i) { let { label, icon, loading, color, disabled } = options; if (loading) { const labelWidth = labelRef.current[i] ? labelRef.current[i].offsetWidth : 'auto'; return ; } const labelStyle: CSSProperties = { transition: 'all 1ms', // 解决拖拽表格,点击无效问题 }; if (color) labelStyle.color = color; if (icon) { label = {icon}; } const cls = classNames(labelClass, { disabled, }); // eslint-disable-next-line no-return-assign return labelRef.current[i] = v}>{label}; } /* * 如果含有confirm属性,即表明是Popconfirm, * confirm作为Popconfirm的props * * 其他元素同理 * */ function getConfirm(options, i) { let label = getLabel(options, i); const { confirm, withKey = true } = options; // 配合 alt command ctrl 键使用,不弹出提示 if (withKey) { label = ( { if (e) e.stopPropagation(); if (e.altKey || e.metaKey || e.ctrlKey) { e.stopPropagation(); e.preventDefault(); if (confirm && confirm.onConfirm) { confirm.onConfirm(e); } } }}> {label} ); } return ( {label} ); } function getStatusSwitch(opt, i) { const { statusSwitch, disabled = false } = opt; const { status } = statusSwitch; const popConfirmProps = { ...statusSwitch }; const icon = status ? : ; const color = status ? 'green' : 'red'; let label = getLabel({ ...opt, label: icon, color }, i); // 如果没有权限,不允许进行操作,只做展示 if (disabled) return label; Reflect.deleteProperty(popConfirmProps, 'status'); return ( {label} ); } function getText(options, i) { let label = getLabel(options, i); const { onClick } = options; return {label}; } function renderItem(opt, i) { const { confirm, statusSwitch, visible = true, disabled = false, } = opt; if (visible) { // 因为label特殊,getStatusSwitch 内部自己判断了是否可用 if (disabled && statusSwitch) return getStatusSwitch(opt, i); if (disabled) { // eslint-disable-next-line no-param-reassign opt.color = '#ccc'; return getLabel(opt, i); } if (confirm) return getConfirm(opt, i); if (statusSwitch) return getStatusSwitch(opt, i); return getText(opt, i); } return null; } let operators = []; let more = []; if (typeof moreTrigger === 'string') { moreTrigger = [ moreTrigger ]; } items.forEach((opt, i) => { const { isMore } = opt; const item = renderItem(opt, i); if (item) { if (isMore) { more.push(item); } else { operators.push(item); } } }); if (more && more.length) { // 更多 const menu = ( { more.map((item, index) => {item}) } ); operators.push( {moreText} , ); } const operatorsLength = operators.length; if (!operatorsLength) { return null; } return (
{operators.map((v, i) => ( {v} {operatorsLength === i + 1 ? '' : } ))}
); } Operator.defaultProps = { items: [], moreText: 更多, moreContentWidth: 'auto', moreTrigger: 'click', }; export default Operator;