feat: 搜索框接入交易时间段筛选能力
This commit is contained in:
@@ -16,6 +16,7 @@ import { fetchIndustryData, selectIndustryData, selectIndustryLoading } from '..
|
|||||||
import { stockService } from '../../../services/stockService';
|
import { stockService } from '../../../services/stockService';
|
||||||
import { logger } from '../../../utils/logger';
|
import { logger } from '../../../utils/logger';
|
||||||
import PopularKeywords from './PopularKeywords';
|
import PopularKeywords from './PopularKeywords';
|
||||||
|
import TradingTimeFilter from './TradingTimeFilter';
|
||||||
|
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
const { Option } = AntSelect;
|
const { Option } = AntSelect;
|
||||||
@@ -36,6 +37,7 @@ const UnifiedSearchBox = ({
|
|||||||
const [sort, setSort] = useState('new'); // 排序方式
|
const [sort, setSort] = useState('new'); // 排序方式
|
||||||
const [importance, setImportance] = useState([]); // 重要性(数组,支持多选)
|
const [importance, setImportance] = useState([]); // 重要性(数组,支持多选)
|
||||||
const [dateRange, setDateRange] = useState(null); // 日期范围
|
const [dateRange, setDateRange] = useState(null); // 日期范围
|
||||||
|
const [tradingTimeRange, setTradingTimeRange] = useState(null); // 交易时段筛选
|
||||||
|
|
||||||
// ✅ 本地输入状态 - 管理用户的实时输入
|
// ✅ 本地输入状态 - 管理用户的实时输入
|
||||||
const [inputValue, setInputValue] = useState('');
|
const [inputValue, setInputValue] = useState('');
|
||||||
@@ -360,6 +362,46 @@ const UnifiedSearchBox = ({
|
|||||||
triggerSearch(params);
|
triggerSearch(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ✅ 交易时段筛选变化(立即触发搜索)
|
||||||
|
const handleTradingTimeChange = (timeConfig) => {
|
||||||
|
if (!timeConfig) {
|
||||||
|
// 清空筛选
|
||||||
|
setTradingTimeRange(null);
|
||||||
|
const params = buildFilterParams({
|
||||||
|
start_date: '',
|
||||||
|
end_date: '',
|
||||||
|
recent_days: ''
|
||||||
|
});
|
||||||
|
triggerSearch(params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { range, type, label } = timeConfig;
|
||||||
|
let params = {};
|
||||||
|
|
||||||
|
if (type === 'recent_days') {
|
||||||
|
// 近一周/近一月使用 recent_days
|
||||||
|
params.recent_days = range;
|
||||||
|
params.start_date = '';
|
||||||
|
params.end_date = '';
|
||||||
|
} else {
|
||||||
|
// 其他使用 start_date + end_date
|
||||||
|
params.start_date = range[0].format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
params.end_date = range[1].format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
params.recent_days = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
setTradingTimeRange({ ...params, label });
|
||||||
|
|
||||||
|
// 立即触发搜索
|
||||||
|
const searchParams = buildFilterParams(params);
|
||||||
|
logger.debug('UnifiedSearchBox', '交易时段筛选变化,立即触发搜索', {
|
||||||
|
timeConfig,
|
||||||
|
params: searchParams
|
||||||
|
});
|
||||||
|
triggerSearch(searchParams);
|
||||||
|
};
|
||||||
|
|
||||||
// 主搜索(点击搜索按钮或回车)
|
// 主搜索(点击搜索按钮或回车)
|
||||||
const handleMainSearch = () => {
|
const handleMainSearch = () => {
|
||||||
// 取消之前的防抖
|
// 取消之前的防抖
|
||||||
@@ -432,6 +474,11 @@ const UnifiedSearchBox = ({
|
|||||||
// 行业代码: 取选中路径的最后一级(最具体的行业代码)
|
// 行业代码: 取选中路径的最后一级(最具体的行业代码)
|
||||||
industry_code: overrides.industry_code ?? (industryValue?.[industryValue.length - 1] || ''),
|
industry_code: overrides.industry_code ?? (industryValue?.[industryValue.length - 1] || ''),
|
||||||
|
|
||||||
|
// 交易时段筛选参数
|
||||||
|
start_date: overrides.start_date ?? (tradingTimeRange?.start_date || ''),
|
||||||
|
end_date: overrides.end_date ?? (tradingTimeRange?.end_date || ''),
|
||||||
|
recent_days: overrides.recent_days ?? (tradingTimeRange?.recent_days || ''),
|
||||||
|
|
||||||
// 最终 overrides 具有最高优先级
|
// 最终 overrides 具有最高优先级
|
||||||
...overrides
|
...overrides
|
||||||
};
|
};
|
||||||
@@ -443,7 +490,7 @@ const UnifiedSearchBox = ({
|
|||||||
|
|
||||||
logger.debug('UnifiedSearchBox', '🔧 buildFilterParams - 输出结果', result);
|
logger.debug('UnifiedSearchBox', '🔧 buildFilterParams - 输出结果', result);
|
||||||
return result;
|
return result;
|
||||||
}, [sort, importance, dateRange, filters.q, industryValue]);
|
}, [sort, importance, dateRange, filters.q, industryValue, tradingTimeRange]);
|
||||||
|
|
||||||
// ✅ 应用筛选(立即搜索,取消防抖)
|
// ✅ 应用筛选(立即搜索,取消防抖)
|
||||||
const handleApplyFilters = () => {
|
const handleApplyFilters = () => {
|
||||||
@@ -466,6 +513,7 @@ const UnifiedSearchBox = ({
|
|||||||
setSort('new');
|
setSort('new');
|
||||||
setImportance([]); // 改为空数组
|
setImportance([]); // 改为空数组
|
||||||
setDateRange(null);
|
setDateRange(null);
|
||||||
|
setTradingTimeRange(null); // 清空交易时段筛选
|
||||||
|
|
||||||
// 输出重置后的完整参数
|
// 输出重置后的完整参数
|
||||||
const resetParams = {
|
const resetParams = {
|
||||||
@@ -474,6 +522,9 @@ const UnifiedSearchBox = ({
|
|||||||
sort: 'new',
|
sort: 'new',
|
||||||
importance: 'all', // 传给后端时转为'all'
|
importance: 'all', // 传给后端时转为'all'
|
||||||
date_range: '',
|
date_range: '',
|
||||||
|
start_date: '',
|
||||||
|
end_date: '',
|
||||||
|
recent_days: '',
|
||||||
page: 1
|
page: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -522,6 +573,14 @@ const UnifiedSearchBox = ({
|
|||||||
tags.push({ key: 'date_range', label: `日期: ${dateLabel}` });
|
tags.push({ key: 'date_range', label: `日期: ${dateLabel}` });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 交易时段筛选标签
|
||||||
|
if (tradingTimeRange?.label) {
|
||||||
|
tags.push({
|
||||||
|
key: 'trading_time',
|
||||||
|
label: `时间: ${tradingTimeRange.label}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 重要性标签(多选合并显示为单个标签)
|
// 重要性标签(多选合并显示为单个标签)
|
||||||
if (importance && importance.length > 0) {
|
if (importance && importance.length > 0) {
|
||||||
const importanceLabel = importance.map(imp => `${imp}级`).join(', ');
|
const importanceLabel = importance.map(imp => `${imp}级`).join(', ');
|
||||||
@@ -540,7 +599,7 @@ const UnifiedSearchBox = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return tags;
|
return tags;
|
||||||
}, [filters.q, industryValue, dateRange, importance, sort]);
|
}, [filters.q, industryValue, dateRange, importance, sort, tradingTimeRange]);
|
||||||
|
|
||||||
// ✅ 移除单个标签 - 构建新参数并触发搜索
|
// ✅ 移除单个标签 - 构建新参数并触发搜索
|
||||||
const handleRemoveTag = (key) => {
|
const handleRemoveTag = (key) => {
|
||||||
@@ -567,6 +626,15 @@ const UnifiedSearchBox = ({
|
|||||||
setDateRange(null);
|
setDateRange(null);
|
||||||
const params = buildFilterParams({ date_range: '' });
|
const params = buildFilterParams({ date_range: '' });
|
||||||
triggerSearch(params);
|
triggerSearch(params);
|
||||||
|
} else if (key === 'trading_time') {
|
||||||
|
// 清除交易时段筛选
|
||||||
|
setTradingTimeRange(null);
|
||||||
|
const params = buildFilterParams({
|
||||||
|
start_date: '',
|
||||||
|
end_date: '',
|
||||||
|
recent_days: ''
|
||||||
|
});
|
||||||
|
triggerSearch(params);
|
||||||
} else if (key === 'importance') {
|
} else if (key === 'importance') {
|
||||||
// 重置重要性为空数组(传给后端为'all')
|
// 重置重要性为空数组(传给后端为'all')
|
||||||
setImportance([]);
|
setImportance([]);
|
||||||
@@ -633,6 +701,10 @@ const UnifiedSearchBox = ({
|
|||||||
{/* 左侧:筛选器组 */}
|
{/* 左侧:筛选器组 */}
|
||||||
<Space size="middle" wrap>
|
<Space size="middle" wrap>
|
||||||
<span style={{ fontSize: 14, color: '#666', fontWeight: 'bold' }}>筛选:</span>
|
<span style={{ fontSize: 14, color: '#666', fontWeight: 'bold' }}>筛选:</span>
|
||||||
|
|
||||||
|
{/* 交易时段筛选 */}
|
||||||
|
<TradingTimeFilter onChange={handleTradingTimeChange} />
|
||||||
|
|
||||||
{/* 行业分类 */}
|
{/* 行业分类 */}
|
||||||
<Cascader
|
<Cascader
|
||||||
value={industryValue}
|
value={industryValue}
|
||||||
|
|||||||
Reference in New Issue
Block a user