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} />