diff --git a/frontend/src/components/financials/StockFinancialSearch.tsx b/frontend/src/components/financials/StockFinancialSearch.tsx index b5f408a..2b739b8 100644 --- a/frontend/src/components/financials/StockFinancialSearch.tsx +++ b/frontend/src/components/financials/StockFinancialSearch.tsx @@ -7,6 +7,8 @@ import { QK } from '@/lib/queryKeys' interface Props { onSelect: (symbol: string, name: string) => void + /** 搜索资产类型, 逗号分隔 (默认 'stock')。如 'stock,index' */ + assetTypes?: string } /** @@ -14,7 +16,7 @@ interface Props { * 复用 instrumentSearch 后端(代码 / 名称模糊匹配),单选即跳转该股财务详情。 * 模式对齐 Watchlist.StockSearchBox:useQuery + 外部点击关闭 + 键盘导航。 */ -export function StockFinancialSearch({ onSelect }: Props) { +export function StockFinancialSearch({ onSelect, assetTypes }: Props) { const [query, setQuery] = useState('') const [open, setOpen] = useState(false) const [activeIdx, setActiveIdx] = useState(-1) @@ -22,8 +24,8 @@ export function StockFinancialSearch({ onSelect }: Props) { const inputRef = useRef(null) const search = useQuery({ - queryKey: QK.instrumentSearch(query), - queryFn: () => api.instrumentSearch(query), + queryKey: QK.instrumentSearch(query, assetTypes ?? 'stock'), + queryFn: () => api.instrumentSearch(query, 20, assetTypes), enabled: query.trim().length > 0, staleTime: 30_000, }) @@ -116,6 +118,9 @@ export function StockFinancialSearch({ onSelect }: Props) { > {r.symbol} {r.name} + {r.asset_type === 'index' && ( + 指数 + )} {r.code && {r.code}} )) diff --git a/frontend/src/components/monitor/RuleEditor.tsx b/frontend/src/components/monitor/RuleEditor.tsx index 045af41..90b3a85 100644 --- a/frontend/src/components/monitor/RuleEditor.tsx +++ b/frontend/src/components/monitor/RuleEditor.tsx @@ -82,8 +82,8 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { const [symbolQuery, setSymbolQuery] = useState('') const [strategyQuery, setStrategyQuery] = useState('') const [strategyCategory, setStrategyCategory] = useState<'all' | 'builtin' | 'custom' | 'ai'>('all') - // ETF 规则时标的搜索一并搜出 ETF。 - const symbolAssetTypes = assetType === 'etf' ? 'stock,etf' : 'stock' + // 标的搜索资产类型: ETF 一并搜股票; 指数只搜指数; 否则只搜股票。 + const symbolAssetTypes = assetType === 'etf' ? 'stock,etf' : assetType === 'index' ? 'index' : 'stock' const symbolSearch = useQuery({ queryKey: QK.instrumentSearch(symbolQuery, symbolAssetTypes), queryFn: () => api.instrumentSearch(symbolQuery, 20, symbolAssetTypes), @@ -158,6 +158,20 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { ...SIGNAL_OPTIONS.map(key => ({ key, label: cnSignal(key) })), ...(options.data?.builtin_signals ?? []).filter(option => MONITOR_INTRADAY_SIGNAL_OPTIONS.includes(option.key)), ] + // 指数: 隐藏涨跌停/连板类 (指数无这些列) 与分时信号 (无本地分钟K, 会静默不触发) + const INDEX_HIDDEN_SIGNALS = (key: string) => + key.includes('limit') || MONITOR_INTRADAY_SIGNAL_OPTIONS.includes(key) + const pickerSignals = assetType === 'index' + ? monitorBuiltinSignals.filter(o => !INDEX_HIDDEN_SIGNALS(o.key)) + : monitorBuiltinSignals + // 指数: 监控类型仅 signal/price (无涨跌停/策略/封单语义) + const visibleTypes = (options.data?.types ?? []).filter( + t => assetType !== 'index' || t.key === 'signal' || t.key === 'price', + ) + // 指数: 作用范围仅 symbols (无全市场/板块语义) + const visibleScopes = (options.data?.scopes ?? []).filter( + s => assetType !== 'index' || s.key === 'symbols', + ) const thresholdConds = draft.conditions.filter(c => c.op !== 'truth') const strategyPresets = strategies.data?.presets ?? [] const selectedStrategy = strategyPresets.find(strategy => strategy.id === draft.strategy_id) @@ -212,7 +226,7 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { signals={selectedSignals} onChange={onSignalPickerChange} kind="entry" - builtinSignals={monitorBuiltinSignals} + builtinSignals={pickerSignals} disabledSignals={intradaySupport?.available === false ? MONITOR_INTRADAY_SIGNAL_OPTIONS : []} disabledSignalHint={intradaySupport?.reason} /> @@ -287,26 +301,33 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { - {/* 资产类型: 股票 / ETF (个股极简模式不显示) */} + {/* 资产类型: 股票 / ETF / 指数 (个股极简模式不显示) */} {!simple && (
资产类型
- {(['stock', 'etf'] as const).map(t => ( + {(['stock', 'etf', 'index'] as const).map(t => ( ))}
@@ -317,7 +338,7 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) {
监控类型
- {(options.data?.types ?? []).map(t => { + {visibleTypes.map(t => { const Icon = TYPE_ICONS[t.key as keyof typeof TYPE_ICONS] ?? Activity const active = draft.type === t.key return ( @@ -354,7 +375,7 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { 作用范围
{draft.scope === 'symbols' && (
@@ -417,7 +438,7 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { signals={selectedSignals} onChange={onSignalPickerChange} kind="entry" - builtinSignals={monitorBuiltinSignals} + builtinSignals={pickerSignals} disabledSignals={intradaySupport?.available === false ? MONITOR_INTRADAY_SIGNAL_OPTIONS : []} disabledSignalHint={intradaySupport?.reason} /> diff --git a/frontend/src/pages/Monitor.tsx b/frontend/src/pages/Monitor.tsx index 952f7fe..3ddfaad 100644 --- a/frontend/src/pages/Monitor.tsx +++ b/frontend/src/pages/Monitor.tsx @@ -662,6 +662,9 @@ function RulesList({ rulesQuery, onEdit }: { {TYPE_LABEL[r.type]} + {r.asset_type === 'index' && ( + 指数 + )} {/* 个股类型: 直接显示可点击的代码+名称; 其他类型显示规则名 */} {r.scope === 'symbols' && r.symbols.length > 0 ? (