contant.ts
type List<T> = Array<{
code: T;
label: string;
}>;
const parseListToMap = <T>(list: List<keyof T>): Record<keyof T, string> => {
const result: Record<keyof T, string> = Object.create(null);
list.forEach((item) => (result[item.code] = item.label));
return result;
};
// 公共状态
export enum pubilcStatus {
GONGKAI = 'GONGKAI',
GEREN = 'GEREN',
BAOMI = 'BAOMI',
}
export const pubilcStatusList: List<pubilcStatus> = [
{
code : pubilcStatus.BAOMI,
label: '保密',
},
{
code : pubilcStatus.BAOMI,
label: '个人',
},
{
code : pubilcStatus.GONGKAI,
label: '公开',
}
];
export const pubilcStatusMap = parseListToMap(pubilcStatusList);
index.tsx
import React ,{FC}from 'react'
import {pubilcStatus,pubilcStatusMap} from '@/constants'
import {Badge,BadgeProps} from 'antd'
interface PubilcStatusProps extends Omit<BadgeProps,'status'> {
status: pubilcStatus,
text?: string
}
const publicColorMap = {
[pubilcStatus.GONGKAI]: 'green',
[pubilcStatus.GEREN]: 'red',
[pubilcStatus.BAOMI]: 'block'
};
const PubilcGroupStatus: FC<PubilcStatusProps> = ({status,text,...props}) => {
return <Badge color={publicColorMap[status]} text={text || pubilcStatusMap[status]} {...props}/>
}
export default PubilcGroupStatus;
type.d.ts
export interface PublicGroupRecord {
publicGroupId: string;
publicGroupName: string;
status: publicGroupStatus;
resultStrategy: publicGroupResultMode;
riskType: string;
remark: string;
creator: string;
}
列表组件
const columns: ColumnsType<PublicGroupRecord> = [
{
dataIndex: 'status',
key: 'status',
title: '状态',
width: '10%',
render: (text: publicGroupStatus) => (
<EllipsisPopover text={text ? <PublicGroupStatus status={text} /> : '-'} />
),
ellipsis: true,
filters: publicGroupStatusList.map((i) => ({value: i.code, text: i.label}))
},
]
加载配合组件
/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/prefer-for-of */
import {Popover} from 'antd';
import {FC, useRef, useState} from 'react';
interface PopoverProps {
text: string | React.ReactNode;
}
let currBubbleCallback = (state: boolean) => {};
let showCurrBubble = () => currBubbleCallback(true);
let hideCurrBubble = () => currBubbleCallback(false);
const EllipsisPopover: FC<PopoverProps> = ({text}) => {
const [isVisible, setIsVisible] = useState(false);
const spanRef = useRef<HTMLSpanElement>(null);
const timeRef = useRef<any>(undefined); // timeoutID
const renderBubble = (state: boolean) => {
// 有上一个泡时
if (timeRef.current !== undefined) {
clearTimeout(timeRef.current);
timeRef.current = undefined;
}
setIsVisible(state);
};
// 判断是否文字超出
const hasEllipsis = (ele: HTMLSpanElement | null) => {
return ele && ele.scrollWidth > ele.offsetWidth;
};
const handleMouseEnter = () => {
// 现在的泡可以用上一个泡的renderBubble来隐藏上一个泡
currBubbleCallback(false); // 隐藏上一个泡
currBubbleCallback = renderBubble; // 把现在泡的renderBubble给下一个
if (hasEllipsis(spanRef.current)) {
setIsVisible(true);
}
};
const handleMouseLeave = () => {
const popDom = document.getElementsByClassName('ant-popover-inner-content');
for (let i = 0; i < popDom.length; ++i) {
const dom = popDom[i];
// 给每个泡监听器
if (dom.getAttribute('listener') !== 'true') {
dom.addEventListener('mouseenter', showCurrBubble);
dom.addEventListener('mouseleave', hideCurrBubble);
dom.setAttribute('listener', 'true');
}
}
timeRef.current = setTimeout(() => {
renderBubble(false);
}, 500);
};
return (
<Popover content={text} visible={isVisible}>
<span
ref={spanRef}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
style={{
display: 'block',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}
>
{text}
</span>
</Popover>
);
};
export default EllipsisPopover;