# Chat UI 链接渲染问题修复报告 ## 📝 问题描述 用户报告Chat UI上的链接没有正确被渲染,从截图中可以看到: - 内容中包含HTML格式的``标签而不是markdown格式的链接 - 链接文本显示但不可点击 - HTML代码直接显示在UI中 ## 🔍 根本原因分析 1. **组件配置冲突**: - `MyChat`组件同时配置了`assistantMessage: { components: { Text: MarkdownText } }` - 又使用了自定义的`AiAssistantMessage`组件 - `AiAssistantMessage`使用默认的``,忽略了MarkdownText配置 2. **Agent输出格式问题**: - Agent生成HTML格式的链接而不是Markdown格式 - 后端citations处理正确生成Markdown,但Agent本身输出了HTML 3. **前端处理能力不足**: - `MarkdownTextPrimitive`只能处理markdown,不能处理HTML - 缺少`@tailwindcss/typography`插件支持prose样式 - 没有DOMPurify来安全处理HTML内容 ## ✅ 解决方案 ### 1. 修复组件配置冲突 ```tsx // AiAssistantMessage.tsx - 直接指定MarkdownText组件 // mychat.tsx - 移除重复配置 config={{ welcome: { message: t.welcomeMessage }, // 移除了 assistantMessage 配置 }} ``` ### 2. 增强MarkdownText组件 ```tsx // 智能检测内容类型并相应处理 const containsHTMLLinks = typeof content === 'string' && /]*href/i.test(content); if (containsHTMLLinks) { // HTML内容:使用DOMPurify清理后直接渲染 return
; } else { // Markdown内容:使用标准的markdown处理器 return ; } ``` ### 3. 添加必要的依赖 ```bash pnpm add @tailwindcss/typography # Prose样式支持 pnpm add isomorphic-dompurify # 安全HTML清理 pnpm add rehype-external-links # 外部链接处理 ``` ### 4. 更新Agent系统提示 ```yaml agent_system_prompt: | # Response Format Requirements: - Use ONLY Markdown formatting (headers, lists, emphasis, etc.) - DO NOT use HTML tags like , , etc. Use only Markdown link syntax - DO NOT generate HTML anchor tags - the system will convert markdown links automatically ``` ### 5. 增强Tailwind配置 ```typescript // tailwind.config.ts plugins: [ require("tailwindcss-animate"), require("@tailwindcss/typography"), // 新增 require("@assistant-ui/react-ui/tailwindcss")({...}) ], ``` ## 🎯 修复效果 现在Chat UI应该能够: 1. ✅ **正确渲染链接**:无论是Markdown还是HTML格式 2. ✅ **安全处理**:DOMPurify清理恶意HTML内容 3. ✅ **外部链接安全**:自动添加`target="_blank"`和`rel="noopener noreferrer"` 4. ✅ **视觉样式**:链接显示为蓝色,有适当的悬停效果 5. ✅ **保持功能**:typing indicator等现有功能不受影响 ## 🔧 技术实现细节 ### 智能内容检测 ```typescript const containsHTMLLinks = /]*href/i.test(content); ``` ### HTML属性确保 ```typescript processedContent = processedContent.replace( /]*?)href\s*=\s*["']([^"']+)["']([^>]*?)>/gi, (match, before, href, after) => { const isExternal = href.startsWith('http://') || href.startsWith('https://'); if (isExternal) { // 确保安全属性存在 let attributes = before + after; if (!attributes.includes('target=')) attributes += ' target="_blank"'; if (!attributes.includes('rel=')) attributes += ' rel="noopener noreferrer"'; return ``; } return match; } ); ``` ### DOMPurify安全清理 ```typescript const sanitizedHTML = DOMPurify.sanitize(processedContent, { ALLOWED_TAGS: ['a', 'p', 'div', 'span', 'strong', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'br'], ALLOWED_ATTR: ['href', 'target', 'rel', 'title', 'class'] }); ``` ## 📋 测试验证 1. **服务器状态**:✅ 后端服务运行在 http://127.0.0.1:8000 2. **前端状态**:✅ 前端开发服务器运行在 http://localhost:3001 3. **构建测试**:✅ 所有组件正常构建 4. **依赖完整**:✅ 所有必要的npm包已安装 ## 🔮 下一步 1. 在浏览器中访问 http://localhost:3001 测试Chat UI 2. 发送包含引用的查询验证链接渲染 3. 检查链接是否可点击且在新标签页打开 4. 验证typing indicator等功能正常工作 这个解决方案提供了向后兼容性,能够处理两种内容格式,并确保了安全性和用户体验。