@@ -43,7 +43,8 @@ const ResponseTags = ({
4343 const {
4444 totalQuoteList : quoteList = [ ] ,
4545 llmModuleAccount = 0 ,
46- historyPreviewLength = 0
46+ historyPreviewLength = 0 ,
47+ externalLinkList = [ ]
4748 } = useMemo ( ( ) => addStatisticalDataToHistoryItem ( historyItem ) , [ historyItem ] ) ;
4849
4950 const [ quoteFolded , setQuoteFolded ] = useState < boolean > ( true ) ;
@@ -68,38 +69,53 @@ const ResponseTags = ({
6869 ? quoteListRef . current . scrollHeight > ( isPc ? 50 : 55 )
6970 : true ;
7071
71- const sourceList = useMemo ( ( ) => {
72- return Object . values (
73- quoteList . reduce ( ( acc : Record < string , SearchDataResponseItemType [ ] > , cur ) => {
74- if ( ! acc [ cur . collectionId ] ) {
75- acc [ cur . collectionId ] = [ cur ] ;
76- }
77- return acc ;
78- } , { } )
79- )
80- . flat ( )
81- . map ( ( item ) => ( {
82- sourceName : item . sourceName ,
83- sourceId : item . sourceId ,
84- icon : item . imageId
85- ? 'core/dataset/imageFill'
86- : getSourceNameIcon ( { sourceId : item . sourceId , sourceName : item . sourceName } ) ,
87- collectionId : item . collectionId ,
88- datasetId : item . datasetId
89- } ) ) ;
72+ // Dataset citation render items
73+ const datasetCitationList = useMemo ( ( ) => {
74+ // Keep first item per collectionId and preserve first-seen order
75+ const firstByCollection = new Map < string , SearchDataResponseItemType > ( ) ;
76+ quoteList . forEach ( ( cur ) => {
77+ if ( ! firstByCollection . has ( cur . collectionId ) ) {
78+ firstByCollection . set ( cur . collectionId , cur ) ;
79+ }
80+ } ) ;
81+ return Array . from ( firstByCollection . values ( ) ) . map ( ( item ) => ( {
82+ itemType : 'dataset' as const ,
83+ sourceName : item . sourceName ,
84+ sourceId : item . sourceId ,
85+ icon : item . imageId
86+ ? 'core/dataset/imageFill'
87+ : getSourceNameIcon ( { sourceId : item . sourceId , sourceName : item . sourceName } ) ,
88+ collectionId : item . collectionId ,
89+ datasetId : item . datasetId
90+ } ) ) ;
9091 } , [ quoteList ] ) ;
9192
92- const notEmptyTags =
93- quoteList . length > 0 ||
94- ( llmModuleAccount === 1 && notSharePage ) ||
95- ( llmModuleAccount > 1 && notSharePage ) ||
96- ( isPc && durationSeconds > 0 ) ||
97- notSharePage ;
93+ // Merge dataset citations and external link references for unified rendering
94+ type RenderCitationItem =
95+ | {
96+ itemType : 'dataset' ;
97+ sourceName : string ;
98+ sourceId ?: string ;
99+ icon : string ;
100+ collectionId : string ;
101+ datasetId : string ;
102+ }
103+ | { itemType : 'link' ; name : string ; url : string } ;
104+
105+ const citationRenderList : RenderCitationItem [ ] = useMemo ( ( ) => {
106+ const linkItems : RenderCitationItem [ ] = externalLinkList . map ( ( r ) => ( {
107+ ...r ,
108+ itemType : 'link'
109+ } ) ) ;
110+ return [ ...datasetCitationList , ...linkItems ] ;
111+ } , [ datasetCitationList , externalLinkList ] ) ;
112+
113+ const notEmptyTags = notSharePage || quoteList . length > 0 || ( isPc && durationSeconds > 0 ) ;
98114
99115 return ! showTags ? null : (
100116 < >
101117 { /* quote */ }
102- { sourceList . length > 0 && (
118+ { citationRenderList . length > 0 && (
103119 < >
104120 < Flex justifyContent = { 'space-between' } alignItems = { 'center' } >
105121 < Box width = { '100%' } >
@@ -143,9 +159,16 @@ const ResponseTags = ({
143159 : { }
144160 }
145161 >
146- { sourceList . map ( ( item , index ) => {
162+ { citationRenderList . map ( ( item , index ) => {
163+ const key = item . itemType === 'dataset' ? item . collectionId : `${ item . url } -${ index } ` ;
164+ const label = item . itemType === 'dataset' ? item . sourceName : item . name ;
147165 return (
148- < MyTooltip key = { item . collectionId } label = { t ( 'common:core.chat.quote.Read Quote' ) } >
166+ < MyTooltip
167+ key = { key }
168+ label = {
169+ item . itemType === 'dataset' ? t ( 'common:core.chat.quote.Read Quote' ) : item . url
170+ }
171+ >
149172 < Flex
150173 alignItems = { 'center' }
151174 fontSize = { 'xs' }
@@ -161,7 +184,16 @@ const ResponseTags = ({
161184 cursor = { 'pointer' }
162185 onClick = { ( e ) => {
163186 e . stopPropagation ( ) ;
164- onOpenCiteModal ( item ) ;
187+ if ( item . itemType === 'dataset' ) {
188+ onOpenCiteModal ( {
189+ collectionId : item . collectionId ,
190+ sourceId : item . sourceId ,
191+ sourceName : item . sourceName ,
192+ datasetId : item . datasetId
193+ } ) ;
194+ } else {
195+ window . open ( item . url , '_blank' ) ;
196+ }
165197 } }
166198 height = { 6 }
167199 >
@@ -177,14 +209,16 @@ const ResponseTags = ({
177209 { index + 1 }
178210 </ Flex >
179211 < Flex px = { 1.5 } >
180- < MyIcon name = { item . icon as any } mr = { 1 } flexShrink = { 0 } w = { '12px' } />
212+ { item . itemType === 'dataset' && (
213+ < MyIcon name = { item . icon as any } mr = { 1 } flexShrink = { 0 } w = { '12px' } />
214+ ) }
181215 < Box
182216 className = "textEllipsis3"
183217 wordBreak = { 'break-all' }
184218 flex = { '1 0 0' }
185219 fontSize = { 'mini' }
186220 >
187- { item . sourceName }
221+ { label }
188222 </ Box >
189223 </ Flex >
190224 </ Flex >
0 commit comments