// 消息处理模块
import { renderMarkdown } from './markdown.js';
import { highlightCodeBlocks } from './highlight.js';
import { scrollToBottom } from './dom-utils.js';
export function addMessage(chatArea, role, markdownContent) {
if (!chatArea) return null;
const messageEl = document.createElement('div');
messageEl.className = `message ${role}`;
const contentEl = document.createElement('div');
contentEl.className = 'message-content markdown-body';
contentEl.innerHTML = renderMarkdown(markdownContent || '');
// 添加操作栏 (复制 & 删除)
const actionRow = document.createElement('div');
actionRow.className = 'message-actions';
const copyBtn = document.createElement('button');
copyBtn.className = 'btn-copy-markdown';
copyBtn.title = '复制原始内容';
copyBtn.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>';
const rawContent = document.createElement('div');
rawContent.className = 'raw-markdown';
rawContent.style.display = 'none';
rawContent.textContent = markdownContent || '';
const deleteBtn = document.createElement('button');
deleteBtn.className = 'btn-delete-message';
deleteBtn.title = '删除消息';
deleteBtn.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>';
actionRow.appendChild(copyBtn);
actionRow.appendChild(rawContent);
actionRow.appendChild(deleteBtn);
contentEl.appendChild(actionRow);
const timestamp = document.createElement('div');
timestamp.className = 'timestamp';
timestamp.textContent = new Date().toLocaleString();
contentEl.appendChild(timestamp);
const avatarEl = document.createElement('div');
avatarEl.className = 'avatar';
avatarEl.textContent = role === 'user' ? '👤' : (role === 'assistant' ? '🤖' : '⚠');
messageEl.appendChild(contentEl);
messageEl.appendChild(avatarEl);
chatArea.appendChild(messageEl);
// 异步高亮代码块(不阻塞)
highlightCodeBlocks(contentEl).catch(err => {
console.warn('代码高亮失败:', err);
});
scrollToBottom(chatArea);
return contentEl;
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
这是一个聊天应用中的消息处理模块,主要功能是创建和渲染聊天消息。让我详细解释一下代码的结构和功能:
模块导入
import { renderMarkdown } from './markdown.js';
import { highlightCodeBlocks } from './highlight.js';
import { scrollToBottom } from './dom-utils.js';
导入了三个工具模块:
renderMarkdown: 将Markdown文本转换为HTMLhighlightCodeBlocks: 代码块语法高亮scrollToBottom: 滚动到聊天区域底部
主要函数 addMessage
参数
chatArea: 聊天区域的DOM元素role: 消息角色('user'用户、'assistant'助手等)markdownContent: Markdown格式的消息内容
功能实现
创建消息容器
const messageEl = document.createElement('div'); messageEl.className = `message ${role}`;创建带有角色样式的消息容器
渲染消息内容
const contentEl = document.createElement('div'); contentEl.className = 'message-content markdown-body'; contentEl.innerHTML = renderMarkdown(markdownContent || '');将Markdown内容转换为HTML并渲染
添加操作按钮
- 复制按钮: 带有复制图标的SVG,用于复制原始Markdown内容
- 隐藏的原始内容: 存储原始Markdown文本,供复制功能使用
- 删除按钮: 带有垃圾桶图标的SVG,用于删除消息
添加时间戳
const timestamp = document.createElement('div'); timestamp.className = 'timestamp'; timestamp.textContent = new Date().toLocaleString();显示消息创建的时间
添加头像
const avatarEl = document.createElement('div'); avatarEl.className = 'avatar'; avatarEl.textContent = role === 'user' ? '👤' : (role === 'assistant' ? '🤖' : '⚠');根据角色显示不同的emoji头像
组装和渲染
- 将所有元素组装到消息容器中
- 添加到聊天区域
- 异步执行代码高亮(不阻塞主线程)
- 滚动到底部显示最新消息
特点
- 模块化设计: 功能分离,易于维护
- 异步处理: 代码高亮异步执行,不影响用户体验
- 错误处理: 对代码高亮失败进行捕获和警告
- 用户体验: 自动滚动到底部,显示时间戳和操作按钮
- 灵活性: 支持不同角色的消息,带有相应的样式和头像
这个模块为聊天应用提供了完整的消息展示功能,支持Markdown渲染、代码高亮、消息操作等特性。
评论加载中...