223 lines
6.4 KiB
React
223 lines
6.4 KiB
React
|
|
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
|