From a9b6724d5ad959803053a0bca9d08913c5ef9228 Mon Sep 17 00:00:00 2001 From: shy3130 <415333856@qq.com> Date: Thu, 20 Aug 2026 16:21:52 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E9=80=89=E6=90=9C=E7=B4=A2=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E6=94=AF=E6=8C=81=E5=B7=B2=E5=8A=A0=E6=A0=87=E7=9A=84?= =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E5=8A=A0=E5=85=A5=E5=85=B6=E4=BB=96=E5=88=86?= =?UTF-8?q?=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 搜索结果中已加自选的标的: 禁用对勾改为「已加自选 ✓ + 分组勾选面板」, 可直接勾选加入/移出分组 (走 members 端点, 不重排列表、不覆盖备注) - 分组勾选弹层标记 data-watchlist-group-menu, 搜索下拉的 点击外部关闭逻辑对其豁免, 两组浮层可并存操作 --- frontend/src/components/WatchlistGroups.tsx | 1 + frontend/src/pages/Watchlist.tsx | 46 +++++++++++++++------ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/WatchlistGroups.tsx b/frontend/src/components/WatchlistGroups.tsx index 79dc62d..53d6f7a 100644 --- a/frontend/src/components/WatchlistGroups.tsx +++ b/frontend/src/components/WatchlistGroups.tsx @@ -623,6 +623,7 @@ export function WatchlistGroupPicker({ groups, groupIds, symbol, disabled, onTog ref={popRef} role="menu" aria-label={`${symbol} 的分组`} + data-watchlist-group-menu style={{ position: 'fixed', top: pos.flipUp ? undefined : pos.top, diff --git a/frontend/src/pages/Watchlist.tsx b/frontend/src/pages/Watchlist.tsx index 906c29a..29cd648 100644 --- a/frontend/src/pages/Watchlist.tsx +++ b/frontend/src/pages/Watchlist.tsx @@ -224,16 +224,23 @@ function renderExtCell( function StockSearchBox({ onPreview, - existingSymbols, + existingBySymbol, + groups, onAdd, + onToggleMember, preferredGroupId, addPending, + memberPending, }: { onPreview: (symbol: string, name: string) => void - existingSymbols: string[] + /** symbol -> 该标的当前所属分组 id 列表; 不在 Map 中 = 未加自选 */ + existingBySymbol: Map + groups: WatchlistGroup[] onAdd: (symbol: string, groupId: string | null) => void + onToggleMember: (symbol: string, groupId: string, member: boolean) => void preferredGroupId: string | null addPending: boolean + memberPending: boolean }) { const [query, setQuery] = useState('') const [open, setOpen] = useState(false) @@ -310,7 +317,8 @@ function StockSearchBox({ className="absolute right-0 top-full mt-1 z-50 w-64 max-h-[320px] overflow-y-auto rounded-card border border-border bg-base shadow-xl" > {results.map((r, i) => { - const inWatchlist = existingSymbols.includes(r.symbol) + const entryGids = existingBySymbol.get(r.symbol) + const inWatchlist = entryGids !== undefined return (
{inWatchlist ? ( - + // 已加自选: 对勾标识 + 分组勾选面板, 可继续加入/移出其他分组 + // (走 members 端点, 不重排列表、不覆盖备注) + + + + + + ) : ( onAdd(r.symbol, groupId)} @@ -1259,10 +1276,13 @@ export function Watchlist() { )} { setPreviewSymbol(sym); setPreviewName(name) }} - existingSymbols={allSymbols as string[]} + existingBySymbol={groupBySymbol} + groups={groups} onAdd={(symbol, groupId) => addMutation.mutate({ symbol, groupId })} + onToggleMember={handleToggleMember} preferredGroupId={activeGroupId} addPending={addMutation.isPending} + memberPending={addGroupMember.isPending || removeGroupMember.isPending} />