feat: 调整搜索框UI
This commit is contained in:
80
src/views/Community/components/CompactSearchBox.css
Normal file
80
src/views/Community/components/CompactSearchBox.css
Normal file
@@ -0,0 +1,80 @@
|
||||
/* CompactSearchBox.css */
|
||||
/* 紧凑版搜索和筛选组件样式 */
|
||||
|
||||
/* 搜索框 placeholder 白色 - 全覆盖选择器 */
|
||||
.gold-placeholder input::placeholder,
|
||||
.gold-placeholder input[type="text"]::placeholder,
|
||||
.gold-placeholder .ant-input::placeholder,
|
||||
.gold-placeholder .ant-input-affix-wrapper input::placeholder,
|
||||
.gold-placeholder .ant-select-selection-search-input::placeholder,
|
||||
.gold-placeholder .ant-input-affix-wrapper .ant-input::placeholder {
|
||||
color: #FFFFFF !important;
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
|
||||
/* AutoComplete placeholder - 关键选择器 */
|
||||
.gold-placeholder .ant-select-selection-placeholder {
|
||||
color: #FFFFFF !important;
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
|
||||
.gold-placeholder .ant-input-affix-wrapper .ant-input,
|
||||
.gold-placeholder .ant-input {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.gold-placeholder .ant-input-affix-wrapper {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
/* 透明下拉框样式 */
|
||||
.transparent-select .ant-select-selector,
|
||||
.transparent-cascader .ant-select-selector {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* 行业筛选宽度自适应,减少间距 */
|
||||
.transparent-cascader {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.transparent-cascader .ant-select-selector {
|
||||
padding-right: 8px !important;
|
||||
min-width: unset !important;
|
||||
}
|
||||
|
||||
/* 行业筛选 Cascader placeholder 白色 */
|
||||
.transparent-select .ant-select-selection-placeholder,
|
||||
.transparent-cascader .ant-select-selection-placeholder,
|
||||
.transparent-cascader input::placeholder,
|
||||
.transparent-cascader .ant-cascader-input::placeholder {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.transparent-cascader .ant-cascader-input {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
/* 行业筛选 Cascader 选中值白色 */
|
||||
.transparent-cascader .ant-select-selection-item,
|
||||
.transparent-cascader .ant-cascader-picker-label {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
/* 方括号样式下拉框 - 无边框 */
|
||||
.bracket-select .ant-select-selector {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.bracket-select .ant-select-selection-item,
|
||||
.bracket-select .ant-select-selection-placeholder {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.bracket-select .ant-select-arrow {
|
||||
color: rgba(255, 255, 255, 0.65) !important;
|
||||
}
|
||||
@@ -4,30 +4,49 @@
|
||||
import React, { useState, useMemo, useEffect, useCallback, useRef } from 'react';
|
||||
import {
|
||||
Input, Cascader, Button, Space, Tag, AutoComplete, Select as AntSelect,
|
||||
Tooltip
|
||||
Tooltip, Divider, Flex
|
||||
} from 'antd';
|
||||
import {
|
||||
SearchOutlined, CloseCircleOutlined, StockOutlined, FilterOutlined,
|
||||
CalendarOutlined, SortAscendingOutlined
|
||||
CalendarOutlined, SortAscendingOutlined, ReloadOutlined, ThunderboltOutlined
|
||||
} from '@ant-design/icons';
|
||||
import dayjs from 'dayjs';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { fetchIndustryData, selectIndustryData, selectIndustryLoading } from '../../../store/slices/industrySlice';
|
||||
import { stockService } from '../../../services/stockService';
|
||||
import { logger } from '../../../utils/logger';
|
||||
import { fetchIndustryData, selectIndustryData, selectIndustryLoading } from '@store/slices/industrySlice';
|
||||
import { stockService } from '@services/stockService';
|
||||
import { logger } from '@utils/logger';
|
||||
import TradingTimeFilter from './TradingTimeFilter';
|
||||
import { PROFESSIONAL_COLORS } from '../../../constants/professionalTheme';
|
||||
import { PROFESSIONAL_COLORS } from '@constants/professionalTheme';
|
||||
import './CompactSearchBox.css';
|
||||
|
||||
const { Option } = AntSelect;
|
||||
|
||||
// 排序选项常量
|
||||
const SORT_OPTIONS = [
|
||||
{ value: 'new', label: '最新排序', mobileLabel: '最新' },
|
||||
{ value: 'hot', label: '最热排序', mobileLabel: '热门' },
|
||||
{ value: 'importance', label: '重要性排序', mobileLabel: '重要' },
|
||||
{ value: 'returns_avg', label: '平均收益', mobileLabel: '均收' },
|
||||
{ value: 'returns_week', label: '周收益', mobileLabel: '周收' },
|
||||
];
|
||||
|
||||
// 重要性等级常量
|
||||
const IMPORTANCE_OPTIONS = [
|
||||
{ value: 'S', label: 'S级' },
|
||||
{ value: 'A', label: 'A级' },
|
||||
{ value: 'B', label: 'B级' },
|
||||
{ value: 'C', label: 'C级' },
|
||||
];
|
||||
|
||||
const CompactSearchBox = ({
|
||||
onSearch,
|
||||
onSearchFocus,
|
||||
filters = {},
|
||||
mode,
|
||||
pageSize,
|
||||
trackingFunctions = {}
|
||||
trackingFunctions = {},
|
||||
isMobile = false
|
||||
}) => {
|
||||
// 状态
|
||||
const [stockOptions, setStockOptions] = useState([]);
|
||||
@@ -420,19 +439,21 @@ const CompactSearchBox = ({
|
||||
dispatch(fetchIndustryData());
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
padding: window.innerWidth < 768 ? '12px 16px' : '16px 20px',
|
||||
background: PROFESSIONAL_COLORS.background.card,
|
||||
borderRadius: '12px',
|
||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3), 0 0 20px rgba(255, 195, 0, 0.1)',
|
||||
border: `1px solid ${PROFESSIONAL_COLORS.border.default}`,
|
||||
backdropFilter: 'blur(10px)'
|
||||
}}>
|
||||
{/* 单行紧凑布局 - 移动端自动换行 */}
|
||||
<Space wrap style={{ width: '100%' }} size={window.innerWidth < 768 ? 'small' : 'medium'}>
|
||||
{/* 搜索框 */}
|
||||
<div style={{ padding: 0, background: 'transparent' }}>
|
||||
{/* 第一行:搜索框 + 日期筛选 */}
|
||||
<Flex
|
||||
align="center"
|
||||
gap={isMobile ? 8 : 12}
|
||||
style={{
|
||||
background: 'rgba(255, 255, 255, 0.03)',
|
||||
border: `1px solid ${PROFESSIONAL_COLORS.border.light}`,
|
||||
borderRadius: '24px',
|
||||
padding: isMobile ? '2px 4px' : '8px 16px',
|
||||
marginBottom: isMobile ? 8 : 12
|
||||
}}
|
||||
>
|
||||
{/* 搜索框 - flex: 1 占满剩余空间 */}
|
||||
<AutoComplete
|
||||
value={inputValue}
|
||||
onChange={handleInputChange}
|
||||
@@ -440,46 +461,57 @@ const CompactSearchBox = ({
|
||||
onSelect={handleStockSelect}
|
||||
onFocus={onSearchFocus}
|
||||
options={stockOptions}
|
||||
placeholder="搜索股票/话题..."
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
handleMainSearch();
|
||||
}
|
||||
}}
|
||||
style={{ width: window.innerWidth < 768 ? '100%' : 240, minWidth: window.innerWidth < 768 ? 0 : 240 }}
|
||||
style={{ flex: 1, minWidth: isMobile ? 100 : 200 }}
|
||||
className="gold-placeholder"
|
||||
>
|
||||
<Input
|
||||
prefix={<SearchOutlined style={{ color: PROFESSIONAL_COLORS.gold[500] }} />}
|
||||
placeholder="搜索股票/话题..."
|
||||
style={{
|
||||
borderRadius: '8px',
|
||||
border: `1px solid ${PROFESSIONAL_COLORS.border.default}`,
|
||||
boxShadow: `0 2px 8px rgba(255, 195, 0, 0.1)`,
|
||||
background: PROFESSIONAL_COLORS.background.secondary,
|
||||
color: PROFESSIONAL_COLORS.text.primary
|
||||
border: 'none',
|
||||
background: 'transparent',
|
||||
color: PROFESSIONAL_COLORS.text.primary,
|
||||
boxShadow: 'none'
|
||||
}}
|
||||
/>
|
||||
</AutoComplete>
|
||||
|
||||
{/* 时间筛选 */}
|
||||
<Tooltip title="时间筛选">
|
||||
<div style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
|
||||
<CalendarOutlined style={{ color: PROFESSIONAL_COLORS.gold[500], fontSize: 12 }} />
|
||||
<TradingTimeFilter
|
||||
value={tradingTimeRange?.key || null}
|
||||
onChange={handleTradingTimeChange}
|
||||
compact
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
{/* 分隔线 - H5 时隐藏 */}
|
||||
{!isMobile && <Divider type="vertical" style={{ height: 24, margin: '0 8px', borderColor: 'rgba(255,255,255,0.15)' }} />}
|
||||
|
||||
{/* 行业筛选 */}
|
||||
<Tooltip title="行业分类">
|
||||
{/* 日期筛选按钮组 */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 0 }}>
|
||||
<CalendarOutlined style={{ color: PROFESSIONAL_COLORS.gold[500], fontSize: 14, marginRight: 8 }} />
|
||||
<TradingTimeFilter
|
||||
value={tradingTimeRange?.key || null}
|
||||
onChange={handleTradingTimeChange}
|
||||
compact={!isMobile}
|
||||
mobile={isMobile}
|
||||
/>
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
{/* 第二行:筛选条件 */}
|
||||
<Flex justify="space-between" align="center">
|
||||
{/* 左侧筛选 */}
|
||||
<Space size={isMobile ? 4 : 8}>
|
||||
{/* 行业筛选 */}
|
||||
<Cascader
|
||||
value={industryValue}
|
||||
onChange={handleIndustryChange}
|
||||
onFocus={handleCascaderFocus}
|
||||
options={industryData || []}
|
||||
placeholder="行业"
|
||||
placeholder={
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<FilterOutlined style={{ fontSize: 12 }} />
|
||||
{isMobile ? '行业' : '行业筛选'}
|
||||
</span>
|
||||
}
|
||||
changeOnSelect
|
||||
showSearch={{
|
||||
filter: (inputValue, path) =>
|
||||
@@ -489,145 +521,65 @@ const CompactSearchBox = ({
|
||||
}}
|
||||
allowClear
|
||||
expandTrigger="hover"
|
||||
displayRender={(labels) => labels[labels.length - 1] || '行业'}
|
||||
displayRender={(labels) => labels[labels.length - 1] || (isMobile ? '行业' : '行业筛选')}
|
||||
disabled={industryLoading}
|
||||
style={{
|
||||
width: window.innerWidth < 768 ? '100%' : 120,
|
||||
minWidth: window.innerWidth < 768 ? 0 : 120,
|
||||
borderRadius: '8px'
|
||||
}}
|
||||
suffixIcon={<FilterOutlined style={{ fontSize: 14, color: PROFESSIONAL_COLORS.gold[500] }} />}
|
||||
style={{ minWidth: isMobile ? 70 : 80 }}
|
||||
suffixIcon={null}
|
||||
className="transparent-cascader"
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
{/* 重要性筛选 */}
|
||||
<Tooltip title="事件等级筛选">
|
||||
{/* 事件等级 */}
|
||||
<AntSelect
|
||||
mode="multiple"
|
||||
value={importance}
|
||||
onChange={handleImportanceChange}
|
||||
style={{
|
||||
width: window.innerWidth < 768 ? '100%' : 120,
|
||||
minWidth: window.innerWidth < 768 ? 0 : 120,
|
||||
borderRadius: '8px'
|
||||
}}
|
||||
placeholder="事件等级"
|
||||
style={{ minWidth: isMobile ? 100 : 120 }}
|
||||
placeholder={
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<ThunderboltOutlined style={{ fontSize: 12 }} />
|
||||
{isMobile ? '等级' : '事件等级'}
|
||||
</span>
|
||||
}
|
||||
maxTagCount={0}
|
||||
maxTagPlaceholder={(omittedValues) => `已选 ${omittedValues.length} 项`}
|
||||
maxTagPlaceholder={(omittedValues) => isMobile ? `${omittedValues.length}项` : `已选 ${omittedValues.length} 项`}
|
||||
className="bracket-select"
|
||||
>
|
||||
<Option value="S">S级</Option>
|
||||
<Option value="A">A级</Option>
|
||||
<Option value="B">B级</Option>
|
||||
<Option value="C">C级</Option>
|
||||
{IMPORTANCE_OPTIONS.map(opt => (
|
||||
<Option key={opt.value} value={opt.value}>{opt.label}</Option>
|
||||
))}
|
||||
</AntSelect>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
|
||||
{/* 排序 */}
|
||||
<Tooltip title="排序方式">
|
||||
{/* 右侧排序和重置 */}
|
||||
<Space size={isMobile ? 4 : 8}>
|
||||
{/* 排序 */}
|
||||
<AntSelect
|
||||
value={sort}
|
||||
onChange={handleSortChange}
|
||||
style={{
|
||||
width: window.innerWidth < 768 ? '100%' : 130,
|
||||
minWidth: window.innerWidth < 768 ? 0 : 130,
|
||||
borderRadius: '8px'
|
||||
}}
|
||||
suffixIcon={<SortAscendingOutlined style={{ fontSize: 14, color: PROFESSIONAL_COLORS.gold[500] }} />}
|
||||
style={{ minWidth: isMobile ? 55 : 120 }}
|
||||
className="bracket-select"
|
||||
>
|
||||
<Option value="new">⏰ 最新</Option>
|
||||
<Option value="hot">🔥 最热</Option>
|
||||
<Option value="importance">⭐ 重要性</Option>
|
||||
<Option value="returns_avg">📊 平均收益</Option>
|
||||
<Option value="returns_week">📈 周收益</Option>
|
||||
{SORT_OPTIONS.map(opt => (
|
||||
<Option key={opt.value} value={opt.value}>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<SortAscendingOutlined style={{ fontSize: 12 }} />
|
||||
{isMobile ? opt.mobileLabel : opt.label}
|
||||
</span>
|
||||
</Option>
|
||||
))}
|
||||
</AntSelect>
|
||||
</Tooltip>
|
||||
|
||||
{/* 重置按钮 */}
|
||||
<Tooltip title="重置所有筛选">
|
||||
{/* 重置按钮 */}
|
||||
<Button
|
||||
icon={<CloseCircleOutlined />}
|
||||
icon={<ReloadOutlined />}
|
||||
onClick={handleReset}
|
||||
danger
|
||||
type="primary"
|
||||
style={{
|
||||
borderRadius: '8px',
|
||||
boxShadow: '0 2px 8px rgba(255, 77, 79, 0.2)'
|
||||
}}
|
||||
type="text"
|
||||
style={{ color: PROFESSIONAL_COLORS.text.secondary }}
|
||||
>
|
||||
重置
|
||||
{!isMobile && '重置筛选'}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
|
||||
{/* 激活的筛选标签(如果有的话) */}
|
||||
{(inputValue || industryValue.length > 0 || importance.length > 0 || tradingTimeRange || sort !== 'new') && (
|
||||
<div style={{ marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 4 }}>
|
||||
{inputValue && (
|
||||
<Tag closable onClose={() => {
|
||||
setInputValue('');
|
||||
const params = buildFilterParams({ q: '' });
|
||||
triggerSearch(params);
|
||||
}} color="blue">
|
||||
搜索: {inputValue}
|
||||
</Tag>
|
||||
)}
|
||||
{tradingTimeRange && (
|
||||
<Tag closable onClose={() => {
|
||||
setTradingTimeRange(null);
|
||||
const params = buildFilterParams({
|
||||
start_date: '',
|
||||
end_date: '',
|
||||
recent_days: ''
|
||||
});
|
||||
triggerSearch(params);
|
||||
}} color="green">
|
||||
{tradingTimeRange.label}
|
||||
</Tag>
|
||||
)}
|
||||
{industryValue.length > 0 && industryData && (
|
||||
<Tag closable onClose={() => {
|
||||
setIndustryValue([]);
|
||||
const params = buildFilterParams({ industry_code: '' });
|
||||
triggerSearch(params);
|
||||
}} color="orange">
|
||||
行业: {(() => {
|
||||
const findLabel = (code, data) => {
|
||||
for (const item of data) {
|
||||
if (code.startsWith(item.value)) {
|
||||
if (item.value === code) {
|
||||
return item.label;
|
||||
} else {
|
||||
return findLabel(code, item.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const lastLevelCode = industryValue[industryValue.length - 1];
|
||||
return findLabel(lastLevelCode, industryData);
|
||||
})()}
|
||||
</Tag>
|
||||
)}
|
||||
{importance.length > 0 && (
|
||||
<Tag closable onClose={() => {
|
||||
setImportance([]);
|
||||
const params = buildFilterParams({ importance: 'all' });
|
||||
triggerSearch(params);
|
||||
}} color="purple">
|
||||
重要性: {importance.map(imp => ({ 'S': '极高', 'A': '高', 'B': '中', 'C': '低' }[imp] || imp)).join(', ')}
|
||||
</Tag>
|
||||
)}
|
||||
{sort && sort !== 'new' && (
|
||||
<Tag closable onClose={() => {
|
||||
setSort('new');
|
||||
const params = buildFilterParams({ sort: 'new' });
|
||||
triggerSearch(params);
|
||||
}} color="cyan">
|
||||
排序: {({ 'hot': '最热', 'importance': '重要性', 'returns_avg': '平均收益', 'returns_week': '周收益' }[sort] || sort)}
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Space>
|
||||
</Flex>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
// src/views/Community/components/TradingTimeFilter.js
|
||||
// 交易时段智能筛选组件
|
||||
import React, { useState, useMemo, useEffect } from 'react';
|
||||
import { Space, Button, Tag, Tooltip, DatePicker, Popover } from 'antd';
|
||||
import { ClockCircleOutlined, CalendarOutlined } from '@ant-design/icons';
|
||||
import { Space, Button, Tag, Tooltip, DatePicker, Popover, Select } from 'antd';
|
||||
import { ClockCircleOutlined, CalendarOutlined, FilterOutlined } from '@ant-design/icons';
|
||||
import dayjs from 'dayjs';
|
||||
import locale from 'antd/es/date-picker/locale/zh_CN';
|
||||
import { logger } from '../../../utils/logger';
|
||||
import { logger } from '@utils/logger';
|
||||
import { PROFESSIONAL_COLORS } from '@constants/professionalTheme';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
/**
|
||||
* 交易时段筛选组件
|
||||
* @param {string} value - 当前选中的 key(受控)
|
||||
* @param {Function} onChange - 时间范围变化回调 (timeConfig) => void
|
||||
* @param {boolean} compact - 是否使用紧凑模式(PC 端搜索栏内使用)
|
||||
* @param {boolean} mobile - 是否使用移动端模式(下拉选择)
|
||||
*/
|
||||
const TradingTimeFilter = ({ value, onChange }) => {
|
||||
const TradingTimeFilter = ({ value, onChange, compact = false, mobile = false }) => {
|
||||
const [selectedKey, setSelectedKey] = useState(null);
|
||||
const [customRangeVisible, setCustomRangeVisible] = useState(false);
|
||||
const [customRange, setCustomRange] = useState(null);
|
||||
@@ -266,7 +271,39 @@ const TradingTimeFilter = ({ value, onChange }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 渲染按钮
|
||||
// 渲染紧凑模式按钮(PC 端搜索栏内使用,文字按钮 + | 分隔符)
|
||||
const renderCompactButton = (config, showDivider = true) => {
|
||||
const isSelected = selectedKey === config.key;
|
||||
const fullTooltip = config.timeHint ? `${config.tooltip} · ${config.timeHint}` : config.tooltip;
|
||||
|
||||
return (
|
||||
<React.Fragment key={config.key}>
|
||||
<Tooltip title={fullTooltip}>
|
||||
<span
|
||||
onClick={() => handleButtonClick(config)}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
padding: '4px 8px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '13px',
|
||||
fontWeight: isSelected ? 600 : 400,
|
||||
color: isSelected ? PROFESSIONAL_COLORS.gold[500] : PROFESSIONAL_COLORS.text.secondary,
|
||||
background: isSelected ? 'rgba(255, 195, 0, 0.15)' : 'transparent',
|
||||
transition: 'all 0.2s ease',
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
>
|
||||
{config.label}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{showDivider && (
|
||||
<span style={{ color: 'rgba(255, 255, 255, 0.2)', margin: '0 2px' }}>|</span>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
// 渲染按钮(默认模式)
|
||||
const renderButton = (config) => {
|
||||
const isSelected = selectedKey === config.key;
|
||||
|
||||
@@ -321,6 +358,98 @@ const TradingTimeFilter = ({ value, onChange }) => {
|
||||
</div>
|
||||
);
|
||||
|
||||
// 移动端模式:下拉选择器
|
||||
if (mobile) {
|
||||
const allButtons = [...timeRangeConfig.dynamic, ...timeRangeConfig.fixed];
|
||||
|
||||
const handleMobileSelect = (key) => {
|
||||
if (key === selectedKey) {
|
||||
// 取消选中
|
||||
setSelectedKey(null);
|
||||
onChange(null);
|
||||
} else {
|
||||
const config = allButtons.find(b => b.key === key);
|
||||
if (config) {
|
||||
handleButtonClick(config);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Select
|
||||
value={selectedKey}
|
||||
onChange={handleMobileSelect}
|
||||
placeholder={
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<FilterOutlined style={{ fontSize: 12 }} />
|
||||
筛选
|
||||
</span>
|
||||
}
|
||||
allowClear
|
||||
onClear={() => {
|
||||
setSelectedKey(null);
|
||||
onChange(null);
|
||||
}}
|
||||
style={{ minWidth: 80 }}
|
||||
className="transparent-select"
|
||||
popupMatchSelectWidth={false}
|
||||
>
|
||||
{allButtons.map(config => (
|
||||
<Option key={config.key} value={config.key}>
|
||||
{config.label}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
// 紧凑模式:PC 端搜索栏内的样式
|
||||
if (compact) {
|
||||
// 合并所有按钮配置
|
||||
const allButtons = [...timeRangeConfig.dynamic, ...timeRangeConfig.fixed];
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'nowrap' }}>
|
||||
{allButtons.map((config, index) =>
|
||||
renderCompactButton(config, index < allButtons.length - 1)
|
||||
)}
|
||||
{/* 更多时间 */}
|
||||
<span style={{ color: 'rgba(255, 255, 255, 0.2)', margin: '0 2px' }}>|</span>
|
||||
<Popover
|
||||
content={customRangeContent}
|
||||
title="选择自定义时间范围"
|
||||
trigger="click"
|
||||
open={customRangeVisible}
|
||||
onOpenChange={setCustomRangeVisible}
|
||||
placement="bottomLeft"
|
||||
>
|
||||
<Tooltip title="自定义时间范围">
|
||||
<span
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
padding: '4px 8px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '13px',
|
||||
fontWeight: selectedKey === 'custom' ? 600 : 400,
|
||||
color: selectedKey === 'custom' ? PROFESSIONAL_COLORS.gold[500] : PROFESSIONAL_COLORS.text.secondary,
|
||||
background: selectedKey === 'custom' ? 'rgba(255, 195, 0, 0.15)' : 'transparent',
|
||||
transition: 'all 0.2s ease',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '4px',
|
||||
}}
|
||||
>
|
||||
<CalendarOutlined style={{ fontSize: 12 }} />
|
||||
更多
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 默认模式:移动端/独立使用
|
||||
return (
|
||||
<Space wrap size={[8, 8]} style={{ display: 'flex', alignItems: 'flex-start' }}>
|
||||
{/* 动态按钮(根据时段显示多个) */}
|
||||
|
||||
Reference in New Issue
Block a user