import tinycolor from 'tinycolor2'; import { ComponentType, Defs, Ellipse, Group, Rect } from '../../jsx'; import { ItemDesc, ItemIcon, ItemLabel, ItemValue } from '../components'; import { FlexLayout } from '../layouts'; import { getItemProps } from '../utils'; import { registerItem } from './registry'; import type { BaseItemProps } from './types'; export interface BadgeCardProps extends BaseItemProps { width?: number; height?: number; iconSize?: number; badgeSize?: number; gap?: number; } export const BadgeCard: ComponentType = (props) => { const [ { datum, indexes, width = 200, height = 80, iconSize = 24, badgeSize = 32, gap = 8, positionH = 'normal', themeColors, valueFormatter, }, restProps, ] = getItemProps(props, ['width', 'height', 'iconSize', 'badgeSize', 'gap']); const value = datum.value; const hasValue = value !== undefined; const hasDesc = !!datum.desc; const hasIcon = !!datum.icon; const gradientId = `${themeColors.colorPrimary}-badge`; const badgeX = positionH === 'flipped' ? width - gap - badgeSize : gap; const contentStartX = hasIcon ? positionH === 'flipped' ? gap : badgeSize + 2 * gap : gap; // 没有图标时从左边距开始 const fullWidth = width - gap * 2; const contentWidth = hasIcon ? width - badgeSize - 3 * gap : fullWidth; // 描述区域的固定位置(label + value 区域的下方) const descY = gap + 14 + 18 + 8; // label(14) + value(18) + gap(8) const contentAreaHeight = descY - gap; // label 和 value 占据的总高度 // 当没有 desc 时,徽章和内容区域垂直居中 const badgeY = !hasDesc ? (height - badgeSize) / 2 : gap; // 没有 value 时,label 在整个内容区域垂直居中;有 value 时从顶部开始 const contentY = !hasValue && !hasDesc ? (height - 14) / 2 : gap; const textAlign = !hasIcon && positionH === 'center' ? 'center' : positionH === 'flipped' ? 'right' : 'left'; return ( {/* 背景卡片 */} {hasIcon && ( <> {/* 徽章背景 */} {/* 徽章图标 */} )} {/* 上方内容区域:label 和 value */} {/* 标签 */} {datum.label} {/* 数值 */} {hasValue && ( )} {/* 描述区域(固定位置,独立于 value) */} {hasDesc && ( {datum.desc} )} ); }; registerItem('badge-card', { component: BadgeCard, composites: ['icon', 'label', 'value', 'desc'], });