feat: 调整请求参数

This commit is contained in:
zdl
2025-10-26 23:46:54 +08:00
parent 97c5ce0d4d
commit 5b25136c28
2 changed files with 97 additions and 148 deletions

View File

@@ -57,7 +57,6 @@ const EventTimelineCard = forwardRef(({
onSearch={onSearch}
popularKeywords={popularKeywords}
filters={filters}
loading={loading}
/>
</Box>

View File

@@ -8,6 +8,7 @@ import {
SearchOutlined, CloseCircleOutlined, StockOutlined
} from '@ant-design/icons';
import moment from 'moment';
import dayjs from 'dayjs';
import locale from 'antd/es/date-picker/locale/zh_CN';
import debounce from 'lodash/debounce';
import { useIndustry } from '../../../contexts/IndustryContext';
@@ -21,17 +22,15 @@ const { Option } = AntSelect;
const UnifiedSearchBox = ({
onSearch,
popularKeywords = [],
filters = {},
loading = false
filters = {}
}) => {
const [searchValue, setSearchValue] = useState(''); // 统一搜索值
const [isStockSearch, setIsStockSearch] = useState(false); // 是否股票搜索
// 其他状态
const [stockOptions, setStockOptions] = useState([]); // 股票下拉选项列表
const [allStocks, setAllStocks] = useState([]); // 所有股票数据
const [industryValue, setIndustryValue] = useState([]);
const [selectedStockInfo, setSelectedStockInfo] = useState(null); // 保存选中的股票完整信息
// 新增:管理所有筛选条件
// 筛选条件状态
const [sort, setSort] = useState('new'); // 排序方式
const [importance, setImportance] = useState('all'); // 重要性
const [dateRange, setDateRange] = useState(null); // 日期范围
@@ -39,14 +38,31 @@ const UnifiedSearchBox = ({
// 使用全局行业数据
const { industryData, loadIndustryData, loading: industryLoading } = useIndustry();
// ✅ 从 filters 推导搜索框显示值(受控状态)
const searchValue = useMemo(() => {
if (filters.stock_code && allStocks.length > 0) {
// 股票搜索模式:显示 "代码 名称"
const stock = allStocks.find(s => s.code === filters.stock_code);
return stock ? `${stock.code} ${stock.name}` : filters.stock_code;
}
// 话题搜索模式:显示关键词
return filters.q || '';
}, [filters.stock_code, filters.q, allStocks]);
// 搜索触发函数
const triggerSearch = useCallback((params) => {
logger.debug('UnifiedSearchBox', '触发搜索', params);
onSearch(params);
}, [onSearch]);
// ✅ 创建防抖的搜索函数300ms 延迟)
const debouncedSearchRef = useRef(null);
useEffect(() => {
// 创建防抖函数
// 创建防抖函数,使用 triggerSearch 而不是直接调用 onSearch
debouncedSearchRef.current = debounce((params) => {
logger.debug('UnifiedSearchBox', '防抖搜索触发', params);
onSearch(params);
triggerSearch(params);
}, 300);
// 清理函数
@@ -55,7 +71,7 @@ const UnifiedSearchBox = ({
debouncedSearchRef.current.cancel();
}
};
}, [onSearch]);
}, [triggerSearch]);
// 加载所有股票数据
useEffect(() => {
@@ -100,8 +116,8 @@ const UnifiedSearchBox = ({
return null;
}, []);
// ✅ 修复:从 props.filters 初始化所有筛选条件
React.useEffect(() => {
// ✅ 从 props.filters 初始化筛选条件(不包括搜索值,搜索值由 searchValue useMemo 推导)
useEffect(() => {
if (!filters) return;
// 初始化排序和重要性
@@ -112,41 +128,13 @@ const UnifiedSearchBox = ({
if (filters.date_range) {
const parts = filters.date_range.split(' 至 ');
if (parts.length === 2) {
try {
setDateRange([dayjs(parts[0]), dayjs(parts[1])]);
logger.debug('UnifiedSearchBox', '初始化日期范围', {
date_range: filters.date_range
});
} catch (error) {
logger.error('UnifiedSearchBox', '日期范围解析失败', error);
}
setDateRange([dayjs(parts[0]), dayjs(parts[1])]);
logger.debug('UnifiedSearchBox', '初始化日期范围', {
date_range: filters.date_range
});
}
}
// 初始化搜索值(只在 allStocks 加载完成后处理股票搜索)
if (filters.stock_code) {
// 股票搜索模式
if (allStocks && allStocks.length > 0) {
const stock = allStocks.find(s => s.code === filters.stock_code);
if (stock) {
const displayValue = `${stock.code} ${stock.name}`;
setSearchValue(displayValue);
setSelectedStockInfo(stock);
} else {
setSearchValue(filters.stock_code);
}
setIsStockSearch(true);
} else {
// allStocks 还未加载,先设置 stock_code
setSearchValue(filters.stock_code);
setIsStockSearch(true);
}
} else if (filters.q) {
// 话题搜索模式
setSearchValue(filters.q);
setIsStockSearch(false);
}
// ✅ 初始化行业分类(需要 industryData 加载完成)
if (filters.industry_code && industryData && industryData.length > 0) {
const path = findIndustryPath(filters.industry_code, industryData);
@@ -158,7 +146,7 @@ const UnifiedSearchBox = ({
});
}
}
}, [filters, allStocks, industryData, findIndustryPath]); // ✅ 添加完整依赖
}, [filters.sort, filters.importance, filters.date_range, filters.industry_code, industryData, findIndustryPath]);
// AutoComplete 搜索股票(模糊匹配 code 或 name
const handleSearch = (value) => {
@@ -191,32 +179,24 @@ const UnifiedSearchBox = ({
});
};
// 选中股票(从下拉选择)
const handleStockSelect = (value, option) => {
// 选中股票(从下拉选择) - 直接构建参数并触发搜索
const handleStockSelect = (_value, option) => {
const stockInfo = option.stockInfo;
if (stockInfo) {
// 显示格式:股票代码 + 股票名称
const displayValue = `${stockInfo.code} ${stockInfo.name}`;
setSearchValue(displayValue);
setIsStockSearch(true);
setSelectedStockInfo(stockInfo); // 保存完整股票信息
logger.debug('UnifiedSearchBox', '选中股票', {
code: stockInfo.code,
name: stockInfo.name
});
// 自动触发搜索(股票搜索模式)
// 注意:此时 isStockSearch 状态还没更新,需要手动构建参数
setTimeout(() => {
const params = buildFilterParams();
// 手动覆盖股票相关参数(因为状态还没更新)
params.stock_code = stockInfo.code;
params.q = '';
params.industry_code = '';
params.industry_classification = '';
logger.debug('UnifiedSearchBox', '自动触发股票搜索', params);
onSearch(params);
}, 100);
// 直接构建参数并触发搜索(股票搜索模式)
const params = buildFilterParams({
stock_code: stockInfo.code,
q: '',
industry_code: '',
industry_classification: ''
});
logger.debug('UnifiedSearchBox', '自动触发股票搜索', params);
triggerSearch(params);
}
};
@@ -267,84 +247,59 @@ const UnifiedSearchBox = ({
}
};
// ✅ 热门概念点击处理(立即搜索,不使用防抖)
// ✅ 热门概念点击处理(立即搜索,不使用防抖) - 直接构建参数并触发搜索
const handleKeywordClick = (keyword) => {
// 设置搜索框的值为热门概念文本
setSearchValue(keyword);
setIsStockSearch(false); // 作为话题搜索
setSelectedStockInfo(null);
// 立即触发搜索(取消之前的防抖)
if (debouncedSearchRef.current) {
debouncedSearchRef.current.cancel();
}
const params = buildFilterParams({ q: keyword });
const params = buildFilterParams({
q: keyword,
stock_code: '',
industry_code: '',
industry_classification: ''
});
logger.debug('UnifiedSearchBox', '热门概念点击,立即触发搜索', {
keyword,
params
});
onSearch(params);
triggerSearch(params);
};
// 主搜索(点击搜索按钮或回车)
const handleMainSearch = () => {
// 直接输入文本(未选择下拉股票)时,作为话题搜索
if (!isStockSearch && searchValue) {
logger.debug('UnifiedSearchBox', '话题搜索', { topic: searchValue });
}
// 直接输入文本时,构建参数并触发搜索
logger.debug('UnifiedSearchBox', '主搜索触发', { searchValue });
handleApplyFilters();
};
// 处理输入变化
// 处理输入变化 - AutoComplete 内部处理显示,不需要更新状态
const handleInputChange = (value) => {
setSearchValue(value);
// 输入变化时重置股票搜索标记(只有从下拉选择才是股票搜索
if (isStockSearch) {
setIsStockSearch(false);
setSelectedStockInfo(null); // 清除保存的股票信息
logger.debug('UnifiedSearchBox', '切换为话题搜索模式');
}
// AutoComplete 组件会自动处理显示值
// 这里可以添加其他逻辑(如实时搜索建议
logger.debug('UnifiedSearchBox', '输入变化', { value });
};
// ✅ 生成完整的筛选参数对象
const buildFilterParams = (overrides = {}) => {
// 构建基础参数overrides 优先级高于本地状态)
const baseParams = {
// ✅ 生成完整的筛选参数对象 - 直接从 filters 和本地筛选器状态构建
const buildFilterParams = useCallback((overrides = {}) => {
return {
// 基础参数overrides 优先级高于本地状态)
sort: overrides.sort ?? sort,
importance: overrides.importance ?? importance,
date_range: dateRange ? `${dateRange[0].format('YYYY-MM-DD')}${dateRange[1].format('YYYY-MM-DD')}` : '',
page: 1
};
page: 1,
// 构建搜索相关参数
let searchParams;
if (isStockSearch && searchValue) {
// 股票搜索模式
const stockCode = searchValue.split(' ')[0];
searchParams = {
stock_code: stockCode,
q: '',
industry_code: '',
industry_classification: ''
};
} else {
// 话题搜索模式
searchParams = {
q: overrides.q ?? searchValue || '',
stock_code: '',
industry_code: industryValue?.[industryValue.length - 1] || '',
industry_classification: industryValue?.[0] || ''
};
}
// 搜索参数(从 filters 继承overrides 可覆盖)
q: overrides.q ?? filters.q ?? '',
stock_code: overrides.stock_code ?? filters.stock_code ?? '',
industry_code: overrides.industry_code ?? (industryValue?.[industryValue.length - 1] || ''),
industry_classification: overrides.industry_classification ?? (industryValue?.[0] || ''),
// 合并所有参数,overrides 具有最高优先级
return {
...baseParams,
...searchParams,
// 最终 overrides 具有最高优先级
...overrides
};
};
}, [sort, importance, dateRange, filters.q, filters.stock_code, industryValue]);
// ✅ 应用筛选(立即搜索,取消防抖)
const handleApplyFilters = () => {
@@ -355,17 +310,14 @@ const UnifiedSearchBox = ({
const params = buildFilterParams();
logger.debug('UnifiedSearchBox', '应用筛选,立即触发搜索', params);
onSearch(params);
triggerSearch(params);
};
// 重置筛选
// 重置筛选 - 清空所有筛选器并触发搜索
const handleReset = () => {
// 重置所有状态
setSearchValue('');
setIsStockSearch(false);
// 重置所有筛选器状态
setStockOptions([]);
setIndustryValue([]);
setSelectedStockInfo(null);
setSort('new');
setImportance('all');
setDateRange(null);
@@ -386,15 +338,17 @@ const UnifiedSearchBox = ({
onSearch(resetParams);
};
// 生成已选条件标签(包含所有筛选条件)
// 生成已选条件标签(包含所有筛选条件) - 从 filters 和本地状态读取
const filterTags = useMemo(() => {
const tags = [];
// 搜索关键词/股票标签
if (isStockSearch && searchValue) {
tags.push({ key: 'stock', label: `股票: ${searchValue}` });
} else if (!isStockSearch && searchValue) {
tags.push({ key: 'topic', label: `话题: ${searchValue}` });
// 股票/话题标签 - 从 filters 读取
if (filters.stock_code) {
const stock = allStocks.find(s => s.code === filters.stock_code);
const label = stock ? `${stock.code} ${stock.name}` : filters.stock_code;
tags.push({ key: 'stock', label: `股票: ${label}` });
} else if (filters.q) {
tags.push({ key: 'topic', label: `话题: ${filters.q}` });
}
// 行业标签
@@ -421,37 +375,40 @@ const UnifiedSearchBox = ({
}
return tags;
}, [searchValue, isStockSearch, industryValue, dateRange, importance, sort]);
}, [filters.stock_code, filters.q, allStocks, industryValue, dateRange, importance, sort]);
// 移除单个标签
// 移除单个标签 - 构建新参数并触发搜索
const handleRemoveTag = (key) => {
logger.debug('UnifiedSearchBox', '移除标签', { key });
if (key === 'topic' || key === 'stock') {
// 清除搜索框内容和股票选择状态
setSearchValue('');
setIsStockSearch(false);
setSelectedStockInfo(null);
// 清除搜索关键词/股票,立即触发搜索
const params = buildFilterParams({ q: '', stock_code: '' });
logger.debug('UnifiedSearchBox', '移除搜索标签后触发搜索', { key, params });
triggerSearch(params);
} else if (key === 'industry') {
// 清除行业选择
setIndustryValue([]);
const params = buildFilterParams({ industry_code: '', industry_classification: '' });
triggerSearch(params);
} else if (key === 'date_range') {
// 清除日期范围
setDateRange(null);
setTimeout(() => {
const params = buildFilterParams();
triggerSearch(params);
}, 50);
} else if (key === 'importance') {
// 重置重要性为默认值
setImportance('all');
const params = buildFilterParams({ importance: 'all' });
triggerSearch(params);
} else if (key === 'sort') {
// 重置排序为默认值
setSort('new');
const params = buildFilterParams({ sort: 'new' });
triggerSearch(params);
}
// 延迟触发搜索,确保状态已更新
setTimeout(() => {
const params = buildFilterParams();
logger.debug('UnifiedSearchBox', '移除标签后触发搜索', { key, params });
onSearch(params);
}, 50);
};
return (
@@ -475,7 +432,6 @@ const UnifiedSearchBox = ({
options={stockOptions}
placeholder="请输入股票代码/股票名称/相关话题"
onPressEnter={handleMainSearch}
disabled={loading}
style={{ flex: 1 }}
size="large"
notFoundContent={searchValue && stockOptions.length === 0 ? "未找到匹配的股票" : null}
@@ -483,7 +439,6 @@ const UnifiedSearchBox = ({
<Button
type="primary"
onClick={handleMainSearch}
loading={loading}
size="large"
style={{ minWidth: 80 }}
>
@@ -521,8 +476,7 @@ const UnifiedSearchBox = ({
allowClear
expandTrigger="hover"
displayRender={(labels) => labels.join(' > ')}
disabled={industryLoading || loading}
loading={industryLoading}
disabled={industryLoading}
style={{ width: 200 }}
size="middle"
/>
@@ -533,7 +487,6 @@ const UnifiedSearchBox = ({
onChange={handleDateRangeChange}
locale={locale}
placeholder={['开始日期', '结束日期']}
disabled={loading}
style={{ width: 240 }}
size="middle"
/>
@@ -544,7 +497,6 @@ const UnifiedSearchBox = ({
<AntSelect
value={importance}
onChange={handleImportanceChange}
disabled={loading}
style={{ width: 100 }}
size="middle"
>
@@ -560,7 +512,6 @@ const UnifiedSearchBox = ({
<Button
icon={<CloseCircleOutlined />}
onClick={handleReset}
disabled={loading}
size="middle"
style={{
borderRadius: 6,
@@ -600,7 +551,6 @@ const UnifiedSearchBox = ({
<AntSelect
value={sort}
onChange={handleSortChange}
disabled={loading}
style={{ width: 120 }}
size="middle"
>