@@ -13,6 +13,7 @@ import {
1313 normalizeInstrumentRef ,
1414 parseCanonicalInstrumentInput ,
1515 parseInstrumentNamespace ,
16+ parseOpptrixInstrumentId ,
1617 resolveCnInstrumentIdentity ,
1718 tryParseInstrumentInput as sharedTryParse ,
1819} from '@opptrix/shared/instrument-symbol'
@@ -161,13 +162,40 @@ export const UNRESOLVED_INSTRUMENT_COPY = {
161162 ambiguousShort : '点选确认' ,
162163} as const
163164
164- /** 展示用代码:已消歧用 namespace,否则保留原 code */
165+ /** OpptrixQuant 搜索 / 入库用的统一 ID(CN:REIT:508000.SH 等) */
166+ export function isOpptrixInstrumentCode ( code : string ) : boolean {
167+ return parseOpptrixInstrumentId ( code . trim ( ) ) != null
168+ }
169+
170+ /** 入库前:搜索 Opptrix ID 原样保留;旧关注项仍走 normalizeWatchlistItem */
171+ export function prepareWatchlistItemForStore ( item : WatchlistItem ) : WatchlistItem {
172+ const raw = item . code . trim ( )
173+ if ( isOpptrixInstrumentCode ( raw ) ) {
174+ return {
175+ ...item ,
176+ code : raw ,
177+ name : item . name ?. trim ( ) || raw ,
178+ industry : item . industry ?. trim ( ) || undefined ,
179+ note : item . note ?. trim ( ) || undefined ,
180+ addedPrice : item . addedPrice ?? null ,
181+ instrument : item . instrument ? normalizeInstrumentRefLocal ( item . instrument ) : undefined ,
182+ }
183+ }
184+ return normalizeWatchlistItem ( item )
185+ }
186+
187+ /** 展示用代码:Opptrix ID 直接展示;旧关注项用命名空间 */
165188export function watchlistDisplayCode ( item : WatchlistItem ) : string {
189+ const raw = item . code . trim ( )
190+ if ( isOpptrixInstrumentCode ( raw ) ) return raw
166191 const ref = tryResolveWatchlistInstrument ( item )
167- return ref ? displayCodeFromInstrument ( ref ) : ( item . code . trim ( ) || '—' )
192+ return ref ? displayCodeFromInstrument ( ref ) : ( raw || '—' )
168193}
169194
170195export function normalizeWatchlistItem ( item : WatchlistItem ) : WatchlistItem {
196+ if ( isOpptrixInstrumentCode ( item . code ) ) {
197+ return prepareWatchlistItemForStore ( item )
198+ }
171199 const resolved = tryResolveWatchlistInstrument ( item )
172200 if ( resolved ) {
173201 const code = displayCodeFromInstrument ( resolved )
@@ -249,12 +277,11 @@ export function marketDisplayName(market: Market): string {
249277 }
250278}
251279
252- /** 搜索候选副标题 — 市场 · 代码 · 类型,单行 ellipsis 友好 */
280+ /** 搜索候选副标题 — 市场 · 代码 · 类型(搜索 ID 不再 normalize) */
253281export function formatInstrumentSearchHitSubtitle ( item : WatchlistItem ) : string {
254- const row = normalizeWatchlistItem ( item )
255- const ref = row . instrument
256- const code = watchlistDisplayCode ( row )
257- if ( ! ref ) return row . industry ?. trim ( ) || code
282+ const ref = item . instrument ?? tryResolveWatchlistInstrument ( item )
283+ const code = watchlistDisplayCode ( item )
284+ if ( ! ref ) return item . industry ?. trim ( ) || code
258285
259286 const parts : string [ ] = [ marketDisplayName ( ref . market ) , code ]
260287 if ( ref . assetClass === 'ETF' ) {
@@ -301,7 +328,7 @@ export function hitToWatchlistItem(hit: LocalInstrumentHit): WatchlistItem {
301328 : hit . market === 'CN' && hit . exchange
302329 ? `${ marketDisplayName ( hit . market ) } · ${ hit . exchange === 'SH' ? '上交所' : hit . exchange === 'SZ' ? '深交所' : hit . exchange === 'BJ' ? '北交所' : hit . exchange } `
303330 : marketDisplayName ( hit . market )
304- return normalizeWatchlistItem ( {
331+ return prepareWatchlistItemForStore ( {
305332 code : hit . code ,
306333 name : hit . name ?? hit . code ,
307334 industry,
0 commit comments