135 lines
4.4 KiB
JavaScript
135 lines
4.4 KiB
JavaScript
import { Button, Input, Space, Popover } from 'antd'
|
||
import { ReloadOutlined, FilterOutlined } from '@ant-design/icons'
|
||
import './ListActionBar.css'
|
||
|
||
const { Search } = Input
|
||
|
||
/**
|
||
* 列表操作栏组件
|
||
* @param {Object} props
|
||
* @param {Array} props.actions - 左侧操作按钮配置数组
|
||
* @param {Array} props.batchActions - 批量操作按钮配置数组(仅在有选中项时显示)
|
||
* @param {Object} props.selectionInfo - 选中信息 { count: 选中数量, total: 总数量, isAllPagesSelected: 是否跨页全选 }
|
||
* @param {Function} props.onSelectAllPages - 选择所有页回调
|
||
* @param {Function} props.onClearSelection - 清除选择回调
|
||
* @param {Object} props.search - 搜索配置
|
||
* @param {Object} props.filter - 高级筛选配置(可选)
|
||
* @param {boolean} props.showRefresh - 是否显示刷新按钮
|
||
* @param {Function} props.onRefresh - 刷新回调
|
||
*/
|
||
function ListActionBar({
|
||
actions = [],
|
||
batchActions = [],
|
||
selectionInfo,
|
||
onSelectAllPages,
|
||
onClearSelection,
|
||
search,
|
||
filter,
|
||
showRefresh = false,
|
||
onRefresh,
|
||
}) {
|
||
// 是否有选中项
|
||
const hasSelection = selectionInfo && selectionInfo.count > 0
|
||
return (
|
||
<div className="list-action-bar">
|
||
{/* 左侧操作按钮区 */}
|
||
<div className="list-action-bar-left">
|
||
{/* 常规操作按钮(无选中时显示) */}
|
||
{!hasSelection && actions.map((action) => (
|
||
<Button
|
||
key={action.key}
|
||
type={action.type || 'default'}
|
||
icon={action.icon}
|
||
disabled={action.disabled}
|
||
danger={action.danger}
|
||
onClick={action.onClick}
|
||
>
|
||
{action.label}
|
||
</Button>
|
||
))}
|
||
|
||
{/* 批量操作区域(有选中时显示) */}
|
||
{hasSelection && (
|
||
<Space>
|
||
{/* 选中信息 */}
|
||
<div className="selection-info">
|
||
<span className="selection-count">
|
||
已选择 <strong>{selectionInfo.count}</strong> 项
|
||
{selectionInfo.isAllPagesSelected && (
|
||
<span className="all-pages-tag">(全部页)</span>
|
||
)}
|
||
</span>
|
||
{!selectionInfo.isAllPagesSelected && selectionInfo.total > selectionInfo.count && (
|
||
<a onClick={onSelectAllPages} className="select-all-link">
|
||
选择全部 {selectionInfo.total} 项
|
||
</a>
|
||
)}
|
||
<a onClick={onClearSelection} className="clear-selection-link">
|
||
清除
|
||
</a>
|
||
</div>
|
||
|
||
{/* 批量操作按钮 */}
|
||
{batchActions.map((action) => (
|
||
<Button
|
||
key={action.key}
|
||
type={action.type || 'default'}
|
||
icon={action.icon}
|
||
disabled={action.disabled}
|
||
danger={action.danger}
|
||
onClick={action.onClick}
|
||
>
|
||
{action.label}
|
||
</Button>
|
||
))}
|
||
</Space>
|
||
)}
|
||
</div>
|
||
|
||
{/* 右侧搜索筛选区 */}
|
||
<div className="list-action-bar-right">
|
||
<Space.Compact>
|
||
<Search
|
||
placeholder={search?.placeholder || '请输入搜索关键词'}
|
||
allowClear
|
||
style={{ width: search?.width || 280 }}
|
||
onSearch={search?.onSearch}
|
||
onChange={(e) => search?.onChange?.(e.target.value)}
|
||
value={search?.value}
|
||
/>
|
||
{filter && (
|
||
<Popover
|
||
content={filter.content}
|
||
title={
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||
<FilterOutlined />
|
||
<span>{filter.title || '高级筛选'}</span>
|
||
</div>
|
||
}
|
||
trigger="click"
|
||
open={filter.visible}
|
||
onOpenChange={filter.onVisibleChange}
|
||
placement="bottomRight"
|
||
overlayClassName="filter-popover"
|
||
>
|
||
<Button
|
||
icon={<FilterOutlined />}
|
||
type={filter.isActive ? 'primary' : 'default'}
|
||
>
|
||
{filter.selectedLabel || '筛选'}
|
||
</Button>
|
||
</Popover>
|
||
)}
|
||
</Space.Compact>
|
||
{showRefresh && (
|
||
<Button icon={<ReloadOutlined />} onClick={onRefresh}>
|
||
刷新
|
||
</Button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default ListActionBar
|