223 lines
6.4 KiB
JavaScript
223 lines
6.4 KiB
JavaScript
import { useState } from 'react'
|
||
import { Button, Badge, Modal, Steps, Tag, Divider } from 'antd'
|
||
import {
|
||
QuestionCircleOutlined,
|
||
BulbOutlined,
|
||
WarningOutlined,
|
||
CheckCircleOutlined,
|
||
InfoCircleOutlined,
|
||
} from '@ant-design/icons'
|
||
import './ButtonWithGuideBadge.css'
|
||
|
||
/**
|
||
* 智能引导徽章按钮组件
|
||
* 为新功能或复杂按钮添加脉冲动画的徽章,点击后显示详细引导
|
||
* @param {Object} props
|
||
* @param {string} props.label - 按钮文本
|
||
* @param {ReactNode} props.icon - 按钮图标
|
||
* @param {string} props.type - 按钮类型
|
||
* @param {boolean} props.danger - 危险按钮
|
||
* @param {boolean} props.disabled - 禁用状态
|
||
* @param {Function} props.onClick - 点击回调
|
||
* @param {Object} props.guide - 引导配置
|
||
* @param {boolean} props.showBadge - 是否显示徽章
|
||
* @param {string} props.badgeType - 徽章类型:new, help, warn
|
||
* @param {string} props.size - 按钮大小
|
||
*/
|
||
function ButtonWithGuideBadge({
|
||
label,
|
||
icon,
|
||
type = 'default',
|
||
danger = false,
|
||
disabled = false,
|
||
onClick,
|
||
guide,
|
||
showBadge = true,
|
||
badgeType = 'help',
|
||
size = 'middle',
|
||
...restProps
|
||
}) {
|
||
const [showGuideModal, setShowGuideModal] = useState(false)
|
||
|
||
const handleBadgeClick = (e) => {
|
||
e.stopPropagation()
|
||
if (guide) {
|
||
setShowGuideModal(true)
|
||
}
|
||
}
|
||
|
||
const getBadgeConfig = () => {
|
||
const configs = {
|
||
new: {
|
||
text: 'NEW',
|
||
color: '#52c41a',
|
||
icon: <InfoCircleOutlined />,
|
||
},
|
||
help: {
|
||
text: '?',
|
||
color: '#1677ff',
|
||
icon: <QuestionCircleOutlined />,
|
||
},
|
||
warn: {
|
||
text: '!',
|
||
color: '#faad14',
|
||
icon: <WarningOutlined />,
|
||
},
|
||
}
|
||
return configs[badgeType] || configs.help
|
||
}
|
||
|
||
const badgeConfig = getBadgeConfig()
|
||
|
||
return (
|
||
<>
|
||
<div className="button-guide-badge-wrapper">
|
||
{showBadge && guide && !disabled ? (
|
||
<Badge
|
||
count={
|
||
<div
|
||
className={`guide-badge guide-badge-${badgeType}`}
|
||
onClick={handleBadgeClick}
|
||
>
|
||
{badgeConfig.icon}
|
||
</div>
|
||
}
|
||
offset={[-5, 5]}
|
||
>
|
||
<Button
|
||
type={type}
|
||
icon={icon}
|
||
danger={danger}
|
||
disabled={disabled}
|
||
onClick={onClick}
|
||
size={size}
|
||
{...restProps}
|
||
>
|
||
{label}
|
||
</Button>
|
||
</Badge>
|
||
) : (
|
||
<Button
|
||
type={type}
|
||
icon={icon}
|
||
danger={danger}
|
||
disabled={disabled}
|
||
onClick={onClick}
|
||
size={size}
|
||
{...restProps}
|
||
>
|
||
{label}
|
||
</Button>
|
||
)}
|
||
</div>
|
||
|
||
{/* 引导弹窗 */}
|
||
{guide && (
|
||
<Modal
|
||
title={
|
||
<div className="guide-modal-header">
|
||
<span className="guide-modal-icon">{guide.icon || icon}</span>
|
||
<span className="guide-modal-title">{guide.title}</span>
|
||
{guide.badge && (
|
||
<Tag color={guide.badge.color} className="guide-modal-badge">
|
||
{guide.badge.text}
|
||
</Tag>
|
||
)}
|
||
</div>
|
||
}
|
||
open={showGuideModal}
|
||
onCancel={() => setShowGuideModal(false)}
|
||
footer={[
|
||
<Button key="close" type="primary" onClick={() => setShowGuideModal(false)}>
|
||
知道了
|
||
</Button>,
|
||
]}
|
||
width={600}
|
||
className="button-guide-modal"
|
||
>
|
||
{/* 功能描述 */}
|
||
{guide.description && (
|
||
<div className="guide-section">
|
||
<div className="guide-section-title">
|
||
<InfoCircleOutlined className="guide-section-icon" />
|
||
功能说明
|
||
</div>
|
||
<p className="guide-section-content">{guide.description}</p>
|
||
</div>
|
||
)}
|
||
|
||
{/* 使用步骤 */}
|
||
{guide.steps && guide.steps.length > 0 && (
|
||
<div className="guide-section">
|
||
<div className="guide-section-title">
|
||
<CheckCircleOutlined className="guide-section-icon" />
|
||
操作步骤
|
||
</div>
|
||
<Steps
|
||
direction="vertical"
|
||
current={-1}
|
||
items={guide.steps.map((step, index) => ({
|
||
title: `步骤 ${index + 1}`,
|
||
description: step,
|
||
status: 'wait',
|
||
}))}
|
||
className="guide-steps"
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* 使用场景 */}
|
||
{guide.scenarios && guide.scenarios.length > 0 && (
|
||
<div className="guide-section">
|
||
<div className="guide-section-title">
|
||
<BulbOutlined className="guide-section-icon" />
|
||
适用场景
|
||
</div>
|
||
<ul className="guide-list">
|
||
{guide.scenarios.map((scenario, index) => (
|
||
<li key={index}>{scenario}</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
)}
|
||
|
||
{/* 注意事项 */}
|
||
{guide.warnings && guide.warnings.length > 0 && (
|
||
<div className="guide-section guide-section-warning">
|
||
<div className="guide-section-title">
|
||
<WarningOutlined className="guide-section-icon" />
|
||
注意事项
|
||
</div>
|
||
<ul className="guide-list">
|
||
{guide.warnings.map((warning, index) => (
|
||
<li key={index}>{warning}</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
)}
|
||
|
||
{/* 快捷键和权限 */}
|
||
{(guide.shortcut || guide.permission) && (
|
||
<div className="guide-footer">
|
||
{guide.shortcut && (
|
||
<div className="guide-footer-item">
|
||
<span className="guide-footer-label">快捷键:</span>
|
||
<kbd className="guide-footer-kbd">{guide.shortcut}</kbd>
|
||
</div>
|
||
)}
|
||
{guide.permission && (
|
||
<div className="guide-footer-item">
|
||
<span className="guide-footer-label">权限要求:</span>
|
||
<Tag color="blue">{guide.permission}</Tag>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
</Modal>
|
||
)}
|
||
</>
|
||
)
|
||
}
|
||
|
||
export default ButtonWithGuideBadge
|