@@ -728,34 +728,61 @@ def _build_sector_block(self, overview: MarketOverview) -> str:
728728 return "\n " .join (lines )
729729
730730 def _build_news_block (self , news : List ) -> str :
731- """Build a compact news catalyst table for the rendered report."""
731+ """Build a source-aware news catalyst table for the rendered report."""
732732 if not news :
733733 return ""
734734 if self ._get_review_language () == "en" :
735735 lines = [
736736 "#### News Catalysts" ,
737- "| # | Headline | Signal |" ,
738- "|---|----------|--------|" ,
737+ "| # | Headline | Snippet / Lead | Source |" ,
738+ "|---|----------|----------------|-------- |" ,
739739 ]
740740 else :
741741 lines = [
742742 "#### 近三日催化线索" ,
743- "| 序号 | 事件/标题 | 关注点 |" ,
744- "|------|-----------|--------|" ,
743+ "| 序号 | 事件/标题 | 摘要/线索片段 | 来源 |" ,
744+ "|------|-----------|----------------|------ |" ,
745745 ]
746746
747747 for idx , item in enumerate (news [:5 ], 1 ):
748- if hasattr (item , "title" ):
749- title = getattr (item , "title" , "" ) or "-"
750- snippet = getattr (item , "snippet" , "" ) or ""
751- else :
752- title = item .get ("title" , "-" ) or "-"
753- snippet = item .get ("snippet" , "" ) or ""
754- title = self ._escape_table_cell (str (title ).strip ()[:42 ])
755- signal = self ._escape_table_cell (str (snippet ).strip ().replace ("\n " , " " )[:58 ] or "-" )
756- lines .append (f"| { idx } | { title } | { signal } |" )
748+ title = self ._escape_table_cell (
749+ self ._compact_news_text (self ._get_news_field (item , "title" ), limit = 80 ) or "-"
750+ )
751+ snippet = self ._escape_table_cell (
752+ self ._compact_news_text (self ._get_news_field (item , "snippet" ), limit = 180 ) or "-"
753+ )
754+ source = self ._escape_table_cell (self ._format_news_source_cell (item ) or "-" )
755+ lines .append (f"| { idx } | { title } | { snippet } | { source } |" )
757756 return "\n " .join (lines )
758757
758+ @staticmethod
759+ def _get_news_field (item : Any , field : str ) -> str :
760+ if hasattr (item , field ):
761+ value = getattr (item , field , "" ) or ""
762+ elif isinstance (item , dict ):
763+ value = item .get (field , "" ) or ""
764+ else :
765+ value = ""
766+ return str (value ).strip ()
767+
768+ @classmethod
769+ def _format_news_source_cell (cls , item : Any ) -> str :
770+ source = cls ._compact_news_text (cls ._get_news_field (item , "source" ), limit = 40 )
771+ date_text = cls ._compact_news_text (cls ._get_news_field (item , "published_date" ), limit = 24 )
772+ url = cls ._compact_news_text (cls ._get_news_field (item , "url" ), limit = 0 )
773+ label_parts = [part for part in (source , date_text ) if part ]
774+ label = " / " .join (label_parts )
775+ if url :
776+ return f"[{ label or 'URL' } ]({ url } )"
777+ return label
778+
779+ @staticmethod
780+ def _compact_news_text (value : str , * , limit : int ) -> str :
781+ text = " " .join (str (value or "" ).split ())
782+ if limit <= 0 or len (text ) <= limit :
783+ return text
784+ return text [: max (0 , limit - 3 )].rstrip () + "..."
785+
759786 @staticmethod
760787 def _format_optional_number (value : float ) -> str :
761788 return "N/A" if value in (None , 0 , 0.0 ) else f"{ value :.2f} "
@@ -847,13 +874,15 @@ def _build_review_prompt(self, overview: MarketOverview, news: List) -> str:
847874 news_text = ""
848875 for i , n in enumerate (news [:6 ], 1 ):
849876 # 兼容 SearchResult 对象和字典
850- if hasattr (n , 'title' ):
851- title = n .title [:50 ] if n .title else ''
852- snippet = n .snippet [:100 ] if n .snippet else ''
853- else :
854- title = n .get ('title' , '' )[:50 ]
855- snippet = n .get ('snippet' , '' )[:100 ]
856- news_text += f"{ i } . { title } \n { snippet } \n "
877+ title = self ._compact_news_text (self ._get_news_field (n , "title" ), limit = 90 )
878+ snippet = self ._compact_news_text (self ._get_news_field (n , "snippet" ), limit = 220 )
879+ source = self ._compact_news_text (self ._get_news_field (n , "source" ), limit = 60 )
880+ published_date = self ._compact_news_text (self ._get_news_field (n , "published_date" ), limit = 30 )
881+ url = self ._compact_news_text (self ._get_news_field (n , "url" ), limit = 180 )
882+ meta_parts = [part for part in (source , published_date ) if part ]
883+ meta = f" ({ ' / ' .join (meta_parts )} )" if meta_parts else ""
884+ url_line = f"\n URL: { url } " if url else ""
885+ news_text += f"{ i } . { title } { meta } \n { snippet or '-' } { url_line } \n "
857886
858887 # 按 region 组装市场概况与板块区块(美股无涨跌家数、板块数据)
859888 stats_block = ""
0 commit comments