“历史素材”
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
import React from 'react';
|
||||
import { Button, DatePicker, Input, Space } from 'antd';
|
||||
import {
|
||||
CheckOutlined,
|
||||
ClearOutlined,
|
||||
DeleteOutlined,
|
||||
DownloadOutlined,
|
||||
SearchOutlined,
|
||||
UploadOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import type { Dayjs } from 'dayjs';
|
||||
|
||||
interface UnifiedFilterBarProps {
|
||||
// 搜索
|
||||
searchValue: string;
|
||||
searchPlaceholder?: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
onSearch: () => void;
|
||||
// 日期
|
||||
showDate?: boolean;
|
||||
dateValue?: Dayjs | null;
|
||||
onDateChange?: (date: Dayjs | null) => void;
|
||||
datePlaceholder?: string;
|
||||
// 批量操作
|
||||
batchCount: number;
|
||||
totalCount: number;
|
||||
onSelectAll: () => void;
|
||||
onClearSelection: () => void;
|
||||
onDelete: () => void;
|
||||
onDownload?: () => void;
|
||||
onPush?: () => void;
|
||||
pushLoading?: boolean;
|
||||
pushText?: string;
|
||||
// 右侧额外操作
|
||||
extraActions?: React.ReactNode;
|
||||
}
|
||||
|
||||
const btnBase: React.CSSProperties = {
|
||||
borderRadius: 8,
|
||||
fontWeight: 600,
|
||||
height: 36,
|
||||
};
|
||||
|
||||
const btnSecondary: React.CSSProperties = {
|
||||
...btnBase,
|
||||
background: '#f8f9fc',
|
||||
border: '1px solid #e2e8f0',
|
||||
color: '#334155',
|
||||
};
|
||||
|
||||
const btnDanger: React.CSSProperties = {
|
||||
...btnBase,
|
||||
background: 'linear-gradient(135deg, #ef4444, #dc2626)',
|
||||
border: 'none',
|
||||
color: '#fff',
|
||||
};
|
||||
|
||||
const btnPrimary: React.CSSProperties = {
|
||||
...btnBase,
|
||||
background: 'linear-gradient(135deg, #6366f1, #8b5cf6)',
|
||||
border: 'none',
|
||||
color: '#fff',
|
||||
};
|
||||
|
||||
const UnifiedFilterBar: React.FC<UnifiedFilterBarProps> = ({
|
||||
searchValue,
|
||||
searchPlaceholder = '搜索...',
|
||||
onSearchChange,
|
||||
onSearch,
|
||||
showDate = false,
|
||||
dateValue,
|
||||
onDateChange,
|
||||
datePlaceholder = '选择日期',
|
||||
batchCount,
|
||||
totalCount,
|
||||
onSelectAll,
|
||||
onClearSelection,
|
||||
onDelete,
|
||||
onDownload,
|
||||
onPush,
|
||||
pushLoading = false,
|
||||
pushText = '推送至账户',
|
||||
extraActions,
|
||||
}) => {
|
||||
const allSelected = batchCount === totalCount && totalCount > 0;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
marginBottom: 16,
|
||||
padding: '12px 16px',
|
||||
borderRadius: 12,
|
||||
background: '#fff',
|
||||
border: '1px solid #f0f0f5',
|
||||
}}
|
||||
>
|
||||
{/* 左侧:搜索 + 日期 */}
|
||||
<Space size={8} wrap>
|
||||
<Input.Search
|
||||
placeholder={searchPlaceholder}
|
||||
allowClear
|
||||
value={searchValue}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value;
|
||||
onSearchChange(val);
|
||||
if (!val) onSearch();
|
||||
}}
|
||||
onSearch={onSearch}
|
||||
style={{ width: 240, borderRadius: 8 }}
|
||||
enterButton
|
||||
/>
|
||||
{showDate && (
|
||||
<>
|
||||
<DatePicker
|
||||
value={dateValue || undefined}
|
||||
onChange={(date) => onDateChange?.(date)}
|
||||
format="YYYY-MM-DD"
|
||||
placeholder={datePlaceholder}
|
||||
style={{ width: 160, borderRadius: 8 }}
|
||||
allowClear
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Space>
|
||||
|
||||
{/* 右侧:批量操作 + 额外操作 */}
|
||||
<Space size={8} wrap>
|
||||
{/* 全选 / 取消选择 */}
|
||||
<Button
|
||||
icon={allSelected ? <ClearOutlined /> : <CheckOutlined />}
|
||||
onClick={allSelected ? onClearSelection : onSelectAll}
|
||||
style={btnSecondary}
|
||||
>
|
||||
{allSelected ? '取消全选' : '全选'}
|
||||
</Button>
|
||||
|
||||
{/* 删除 */}
|
||||
<Button
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={onDelete}
|
||||
disabled={batchCount === 0}
|
||||
style={batchCount === 0 ? { ...btnSecondary, opacity: 0.5 } : btnDanger}
|
||||
>
|
||||
删除 {batchCount > 0 && `(${batchCount})`}
|
||||
</Button>
|
||||
|
||||
{/* 下载 */}
|
||||
{onDownload && (
|
||||
<Button
|
||||
icon={<DownloadOutlined />}
|
||||
onClick={onDownload}
|
||||
disabled={batchCount === 0}
|
||||
style={batchCount === 0 ? { ...btnSecondary, opacity: 0.5 } : btnPrimary}
|
||||
>
|
||||
下载 {batchCount > 0 && `(${batchCount})`}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* 推送 */}
|
||||
{onPush && (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<UploadOutlined />}
|
||||
onClick={onPush}
|
||||
loading={pushLoading}
|
||||
disabled={batchCount === 0}
|
||||
style={batchCount === 0 ? { ...btnBase, opacity: 0.5 } : btnPrimary}
|
||||
>
|
||||
{pushLoading ? '推送中...' : `${pushText} ${batchCount > 0 ? `(${batchCount})` : ''}`}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* 额外操作按钮 */}
|
||||
{extraActions}
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UnifiedFilterBar;
|
||||
Reference in New Issue
Block a user