From e864ecde4b02f38635a3a2b0b39d2dfbaaaa1053 Mon Sep 17 00:00:00 2001 From: intfoo Date: Sun, 2 Aug 2026 22:34:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(monitor):=20=E7=9B=91=E6=8E=A7=E8=A7=84?= =?UTF-8?q?=E5=88=99=E4=BF=A1=E5=8F=B7=E9=80=89=E6=8B=A9=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E8=87=AA=E5=AE=9A=E4=B9=89=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?,=20=E4=B8=8D=E5=86=8D=E6=8C=89=20kind=20=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SignalPicker 新增 filterCustomByKind 选项 (默认 true 保持原行为); 监控规则页传 false — 报警语义是"命中即报", 不分入场/出场, 与后端监控引擎按 csg_ 布尔列直接求值对齐; 可选 props 收拢为 options 对象; 自定义信号按钮配色与内置一致, 右上角 PenLine 角标区分 --- .../src/components/monitor/RuleEditor.tsx | 18 +++++--- .../src/components/screener/SignalPicker.tsx | 42 ++++++++++++------- .../screener/StrategySettingsDialog.tsx | 4 +- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/monitor/RuleEditor.tsx b/frontend/src/components/monitor/RuleEditor.tsx index 58d7639..62d52a9 100644 --- a/frontend/src/components/monitor/RuleEditor.tsx +++ b/frontend/src/components/monitor/RuleEditor.tsx @@ -253,9 +253,12 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { signals={selectedSignals} onChange={onSignalPickerChange} kind="entry" - builtinSignals={pickerSignals} - disabledSignals={intradaySupport?.available === false ? MONITOR_INTRADAY_SIGNAL_OPTIONS : []} - disabledSignalHint={intradaySupport?.reason} + options={{ + builtinSignals: pickerSignals, + disabledSignals: intradaySupport?.available === false ? MONITOR_INTRADAY_SIGNAL_OPTIONS : [], + disabledSignalHint: intradaySupport?.reason, + filterCustomByKind: false, + }} /> {hasIntradaySignal && (
@@ -472,9 +475,12 @@ export function RuleEditor({ rule, preset, simple, onClose, onSaved }: Props) { signals={selectedSignals} onChange={onSignalPickerChange} kind="entry" - builtinSignals={pickerSignals} - disabledSignals={intradaySupport?.available === false ? MONITOR_INTRADAY_SIGNAL_OPTIONS : []} - disabledSignalHint={intradaySupport?.reason} + options={{ + builtinSignals: pickerSignals, + disabledSignals: intradaySupport?.available === false ? MONITOR_INTRADAY_SIGNAL_OPTIONS : [], + disabledSignalHint: intradaySupport?.reason, + filterCustomByKind: false, + }} /> {hasIntradaySignal && (
diff --git a/frontend/src/components/screener/SignalPicker.tsx b/frontend/src/components/screener/SignalPicker.tsx index 79e098d..8ce3f60 100644 --- a/frontend/src/components/screener/SignalPicker.tsx +++ b/frontend/src/components/screener/SignalPicker.tsx @@ -1,9 +1,25 @@ import { useMemo } from 'react' import { useQuery } from '@tanstack/react-query' +import { PenLine } from 'lucide-react' import { api } from '@/lib/api' import { QK } from '@/lib/queryKeys' import { SIGNAL_OPTIONS, cnSignal } from '@/lib/signals' +/** 展示与过滤可选项 (全部可选, 有默认值) */ +interface SignalPickerOptions { + /** 渲染尺寸: dialog = 选股弹窗紧凑样式; panel = 回测页设置抽屉样式 */ + variant?: 'dialog' | 'panel' + builtinSignals?: { key: string; label: string }[] + disabledSignals?: string[] + disabledSignalHint?: string + /** + * 是否按 kind 过滤自定义信号 (csg_*)。默认 true (选股/回测: 入场区只显示 entry)。 + * 监控规则页设 false: 报警语义是"命中即报", 不分入场出场, 自定义信号全部显示 + * (与内置信号一致: builtinSignals 透传时本就不按 kind 过滤)。 + */ + filterCustomByKind?: boolean +} + interface Props { /** 当前选中的信号 ID 列表 */ signals: string[] @@ -11,30 +27,27 @@ interface Props { onChange: (next: string[]) => void /** 买点 / 卖点 — 决定自定义信号的过滤与配色主题 */ kind: 'entry' | 'exit' - /** 渲染尺寸: dialog = 选股弹窗紧凑样式; panel = 回测页设置抽屉样式 */ - variant?: 'dialog' | 'panel' - builtinSignals?: { key: string; label: string }[] - disabledSignals?: string[] - disabledSignalHint?: string + options?: SignalPickerOptions } /** * 买卖触发器信号选择 — 选股页弹窗 / 回测页共用。 * * - 内置信号 (signal_*): 全部展示 - * - 自定义信号 (csg_*): 按 kind 过滤 (entry / exit / both) - * - entry 蓝色主题, exit 橙色主题 + * - 自定义信号 (csg_*): 按 kind 过滤 (entry / exit / both), 除非 filterCustomByKind=false + * - entry 蓝色主题, exit 橙色主题; 自定义信号边框配色与内置一致, 右上角 PenLine 角标区分 */ -export function SignalPicker({ signals, onChange, kind, variant = 'panel', builtinSignals, disabledSignals = [], disabledSignalHint }: Props) { +export function SignalPicker({ signals, onChange, kind, options }: Props) { + const { variant = 'panel', builtinSignals, disabledSignals = [], disabledSignalHint, filterCustomByKind = true } = options ?? {} const customSignalsQuery = useQuery({ queryKey: QK.customSignals, queryFn: api.customSignalsList }) const customOptions = useMemo(() => { const list = (customSignalsQuery.data?.signals ?? []) - .filter(s => s.enabled && (s.kind === kind || s.kind === 'both')) + .filter(s => s.enabled && (!filterCustomByKind || s.kind === kind || s.kind === 'both')) const names: Record = {} for (const cs of list) names[`csg_${cs.id}`] = cs.name return { list, names } - }, [customSignalsQuery.data, kind]) + }, [customSignalsQuery.data, kind, filterCustomByKind]) const toggle = (sig: string) => { const next = signals.includes(sig) ? signals.filter(x => x !== sig) : [...signals, sig] @@ -49,10 +62,6 @@ export function SignalPicker({ signals, onChange, kind, variant = 'panel', built const idle = variant === 'dialog' ? 'border-border bg-base text-muted hover:border-accent/40' : 'border-border bg-base text-muted hover:border-accent/40' - const customActive = isEntry - ? 'border-accent/50 bg-accent/10 text-accent' - : 'border-warning/50 bg-warning/10 text-warning' - const customIdle = 'border-amber-400/30 bg-amber-400/5 text-secondary hover:border-amber-400/50 hover:text-amber-400' const btnCls = variant === 'dialog' ? 'rounded px-1.5 py-0.5 text-[10px] font-medium border transition-colors cursor-pointer' @@ -84,9 +93,12 @@ export function SignalPicker({ signals, onChange, kind, variant = 'panel', built type="button" onClick={() => toggle(id)} title="自定义信号" - className={`${btnCls} ${signals.includes(id) ? customActive : customIdle}`} + className={`${btnCls} relative ${signals.includes(id) ? active : idle}`} > {customOptions.names[id]} + + + ) })} diff --git a/frontend/src/components/screener/StrategySettingsDialog.tsx b/frontend/src/components/screener/StrategySettingsDialog.tsx index 0a01321..4f29999 100644 --- a/frontend/src/components/screener/StrategySettingsDialog.tsx +++ b/frontend/src/components/screener/StrategySettingsDialog.tsx @@ -638,7 +638,7 @@ export function StrategySettingsDialog({ strategyId, onClose, onSaved, onAiModif defaultOpen={false} extra={} > - +
任一入场点满足即进入候选。
@@ -649,7 +649,7 @@ export function StrategySettingsDialog({ strategyId, onClose, onSaved, onAiModif defaultOpen={false} extra={} > - +
任一出场点满足即触发出场。