RAGFlow构建知识库和联网搜索对话平台:从零到一的完整开发指南

构建知识库和联网搜索对话平台:从零到一的完整开发指南

项目概述

本项目集成了AI思维链展示、文档引用、流式响应等先进功能。 我这里的api是调用了RAGFlow API,有兴趣的可以去搜索一下,网站中可搭建知识库模型,有免费的使用额度。

转义查看预览部分

返回检索的本地知识库文档

项目特色

  • 智能思维链展示:实时展示AI的思考过程
  • 文档引用系统:支持PDF文档预览和引用
  • 流式响应处理:实时显示AI回复内容
  • 响应式设计:完美适配桌面端和移动端
  • 企业级UI:现代化的用户界面设计

系统架构设计

整体架构图

graph TB A[用户界面层] --> B[业务逻辑层] B --> C[API通信层] C --> D[RAGFlow后端] A --> A1[响应式布局] A --> A2[消息展示] A --> A3[文档预览] B --> B1[消息处理] B --> B2[思维链解析] B --> B3[引用处理] C --> C1[流式API] C --> C2[会话管理] C --> C3[错误处理] D --> D1[AI模型] D --> D2[文档库] D --> D3[知识检索]

技术栈选择

层级 技术选择 说明
前端框架 原生JavaScript + TailwindCSS 轻量级,高性能
UI组件 LayUI 企业级组件库
样式预处理 LESS 模块化样式管理
构建工具 UnoCSS 原子化CSS引擎
后端API RAGFlow AI对话和文档检索
文档解析 Marked.js Markdown渲染
代码高亮 Highlight.js 代码语法高亮

开发流程详解

第一阶段:项目初始化

1.1 项目结构设计
bash 复制代码
ai-agent-search/
├── css/
│   ├── common.less      # 公共样式
│   ├── style.less       # 主样式文件
│   ├── layui.css        # UI组件样式
│   └── iconfont.css     # 图标字体
├── js/
│   ├── ragflow-api.js   # API封装
│   ├── config.js        # 配置文件
│   ├── layui.js         # UI组件库
│   └── rem7.5.js        # 移动端适配
├── images/              # 图片资源
└── aiagentsearch.html   # 主页面
1.2 基础HTML结构
html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能代理对话平台</title>
    <!-- 样式文件引入 -->
</head>
<body>
    <!-- 页面加载动画 -->
    <div id="pageLoader" class="page-loader">
        <!-- 加载内容 -->
    </div>

    <!-- 主内容区域 -->
    <div id="mainContent">
        <!-- 左侧边栏 -->
        <div id="leftSidebar">
            <!-- 会话历史 -->
        </div>

        <!-- 主对话区 -->
        <div class="main-chat-area">
            <!-- 消息列表 -->
            <div id="chatMessages"></div>

            <!-- 输入区域 -->
            <div class="input-area">
                <textarea id="messageInput"></textarea>
                <button id="sendButton">发送</button>
            </div>
        </div>
    </div>
</body>
</html>

第二阶段:核心功能开发

2.1 消息系统设计
sequenceDiagram participant U as 用户 participant UI as 用户界面 participant API as API层 participant AI as AI后端 U->>UI: 输入消息 UI->>UI: 添加用户消息 UI->>UI: 显示AI思考状态 UI->>API: 发送请求 API->>AI: 调用Agent API loop 流式响应 AI-->>API: 返回数据块 API-->>UI: 处理数据块 UI-->>UI: 更新思维链 UI-->>UI: 更新AI回复 end AI-->>API: 响应完成 API-->>UI: 处理完成 UI-->>UI: 生成文档列表 UI-->>U: 显示完整回复
2.2 思维链处理机制

思维链是AI思考过程的可视化展示,通过解析AI回复中的<think>标签实现:

javascript 复制代码
function processAnswerContent(answer, aiMessageElement, reasoningElementRef, responseData) {
    // 提取思维链内容
    const thinkMatch = answer.match(/<think>([\s\S]*?)<\/think>/);
    if (thinkMatch && thinkMatch[1]) {
        const thinkContent = thinkMatch[1].trim();

        // 创建思维链区域
        if (!reasoningElementRef.current) {
            const aiMessageContainer = aiMessageElement.closest('.ai-message-container');
            reasoningElementRef.current = addReasoningMessage(true, aiMessageContainer);
        }

        // 更新思维链内容
        updateReasoningMessage(reasoningElementRef.current, thinkContent);
    }

    // 提取AI回复内容(去除think标签)
    const cleanAnswer = answer.replace(/<think>[\s\S]*?<\/think>\s*/g, '');

    // 处理文档引用和回复内容
    processDocAggsAndReferences(responseData, cleanAnswer, aiMessageElement);
}

第三阶段:高级功能实现

3.1 文档引用系统

文档引用系统允许AI回复中包含可点击的引用标记,用户可以预览相关文档:

graph LR A[AI回复] --> B[解析引用标记] B --> C[生成引用角标] C --> D[绑定点击事件] D --> E[显示文档预览] E --> F[支持图片预览]
3.2 流式响应处理

流式响应确保用户能够实时看到AI的回复过程:

javascript 复制代码
function createStreamResponseHandler(aiMessageElement, reasoningElementRef) {
    return (chunk, fullContent, chunkData) => {
        if (chunkData && chunkData.data) {
            // 保存会话ID
            if (chunkData.data.session_id) {
                currentSessionId = chunkData.data.session_id;
            }

            // 处理完整的answer内容
            if (chunkData.data.answer) {
                processAnswerContent(chunkData.data.answer, aiMessageElement, reasoningElementRef, chunkData.data);
            } else {
                // 兼容旧格式
                updateAIMessage(aiMessageElement, fullContent);
            }
        }
    };
}

第四阶段:用户体验优化

4.1 响应式设计

采用移动优先的设计策略,确保在各种设备上都有良好的用户体验:

css 复制代码
/* 桌面端样式 */
.main-content {
    display: flex;
    height: calc(100vh - 180px);
}

.left-sidebar {
    width: 200px;
    background: white;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* 移动端适配 */
@media (max-width: 768px) {
    .main-content {
        flex-direction: column;
        height: 100vh;
    }

    .left-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        width: 250px;
        height: 100vh;
        transform: translateX(-100%);
        transition: transform 0.3s ease;
        z-index: 40;
    }

    .left-sidebar.open {
        transform: translateX(0);
    }
}
4.2 加载动画设计

企业级的加载动画提升用户体验:

css 复制代码
.page-loader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #ffffff 0%, #f8fafc 50%, #f1f5f9 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 99999;
}

.loader-content {
    text-align: center;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
    backdrop-filter: blur(10px);
    padding: 40px;
}

关键技术实现

API封装设计

javascript 复制代码
class RAGFlowAPI {
    constructor() {
        this.baseURL = 'url';
        this.apiKey = 'apiKey';
    }

    async agentCompletionStream(agentId, message, sessionId, onChunk, onComplete, onError) {
        try {
            const response = await fetch(`${this.baseURL}/api/v1/agents/${agentId}/completions`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${this.apiKey}`
                },
                body: JSON.stringify({
                    message: message,
                    session_id: sessionId,
                    stream: true
                })
            });

            // 处理流式响应
            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            let buffer = '';

            while (true) {
                const { done, value } = await reader.read();
                if (done) break;

                buffer += decoder.decode(value, { stream: true });
                const lines = buffer.split('\n');
                buffer = lines.pop();

                for (const line of lines) {
                    if (line.startsWith('data: ')) {
                        const data = line.slice(6);
                        if (data === '[DONE]') {
                            onComplete();
                            return;
                        }

                        try {
                            const parsed = JSON.parse(data);
                            onChunk(data, parsed.choices?.[0]?.delta?.content || '', parsed);
                        } catch (e) {
                            console.warn('解析数据失败:', e);
                        }
                    }
                }
            }
        } catch (error) {
            onError(error);
        }
    }
}

错误处理机制

javascript 复制代码
// 全局错误处理
window.addEventListener('error', function(e) {
    console.error('❌ 全局JavaScript错误:', e.error);
    showToast('系统出现异常,请刷新页面重试');
});

window.addEventListener('unhandledrejection', function(e) {
    console.error('❌ 未处理的Promise拒绝:', e.reason);
    showToast('网络请求失败,请检查网络连接');
});

// 统一的错误处理器
function createErrorHandler(reasoningElementRef, aiMessageElement, isInitialization = false) {
    return (error) => {
        console.error('API错误:', error);

        if (reasoningElementRef.current) {
            hideReasoningMessage(reasoningElementRef.current);
        }

        const errorMessage = "抱歉,我遇到了一些问题,请稍后再试。";
        updateAIMessage(aiMessageElement, errorMessage);

        showToast(isInitialization ? "智能代理连接失败,请刷新页面重试" : "回复失败,请重试");
    };
}

性能优化策略

1. 资源加载优化

  • 异步加载:非关键资源采用异步加载
  • CDN加速:第三方库使用CDN加载
  • 资源压缩:CSS和JS文件进行压缩

2. 渲染性能优化

  • 虚拟滚动:长消息列表采用虚拟滚动
  • 防抖处理:输入框变化采用防抖处理
  • 懒加载:图片和文档采用懒加载

3. 内存管理

  • 及时清理:定期清理不需要的DOM元素
  • 事件解绑:组件销毁时解绑事件监听器
  • 缓存控制:合理控制缓存大小

测试与调试

单元测试

javascript 复制代码
// 测试消息处理功能
function testMessageProcessing() {
    const testMessage = "测试消息";
    const result = processMessage(testMessage);
    console.assert(result.length > 0, "消息处理失败");
}

// 测试API连接
async function testAPIConnection() {
    try {
        const api = new RAGFlowAPI();
        const result = await api.testConnection();
        console.log("API连接测试:", result ? "成功" : "失败");
    } catch (error) {
        console.error("API连接测试失败:", error);
    }
}

调试工具

javascript 复制代码
// 调试模式开关
const DEBUG_MODE = true;

function debugLog(message, data) {
    if (DEBUG_MODE) {
        console.log(`🔍 [DEBUG] ${message}:`, data);
    }
}

// 性能监控
function performanceMonitor() {
    const observer = new PerformanceObserver((list) => {
        for (const entry of list.getEntries()) {
            if (entry.duration > 100) {
                console.warn(`⚠️ 性能警告: ${entry.name} 耗时 ${entry.duration}ms`);
            }
        }
    });

    observer.observe({ entryTypes: ['measure', 'navigation'] });
}

部署与运维

部署流程

graph LR A[代码提交] --> B[构建打包] B --> C[测试验证] C --> D[部署到服务器] D --> E[健康检查] E --> F[监控告警]

监控指标

  • 响应时间:API响应时间监控
  • 错误率:系统错误率统计
  • 用户活跃度:用户使用情况分析
  • 资源使用:服务器资源使用监控

📈 未来扩展计划

功能扩展

  1. 多模态支持:支持图片、音频输入
  2. 插件系统:支持第三方插件扩展
  3. 协作功能:支持多人协作对话
  4. 个性化设置:用户个性化配置

技术升级

  1. 框架升级:考虑迁移到现代前端框架
  2. PWA支持:添加离线功能支持
  3. WebRTC:支持实时音视频通话
  4. AI增强:集成更多AI能力

💡 总结

通过本文的详细介绍,我们完成了一个功能完整的智能代理对话平台的构建。该平台具备以下特点:

  • 现代化架构:采用模块化设计,易于维护和扩展
  • 用户体验优秀:响应式设计,流畅的交互体验
  • 功能丰富:思维链展示、文档引用、流式响应等高级功能
  • 性能优化:多项性能优化措施,确保系统稳定运行
  • 可扩展性强:预留扩展接口,支持未来功能升级

这个项目展示了如何将现代Web技术与AI能力相结合,创造出具有实用价值的智能对话系统。希望本文能为你的AI项目开发提供有价值的参考。

详细实现解析

消息流处理详解

消息发送流程图
flowchart TD A[用户输入消息] --> B{验证输入} B -->|无效| C[显示错误提示] B -->|有效| D[禁用发送按钮] D --> E[添加用户消息到界面] E --> F[清空输入框] F --> G[创建AI消息容器] G --> H[显示AI思考状态] H --> I[调用RAGFlow API] I --> J[处理流式响应] J --> K{是否包含思维链} K -->|是| L[创建思维链区域] K -->|否| M[直接更新AI回复] L --> N[更新思维链内容] N --> O[提取AI回复内容] O --> P[处理文档引用] M --> P P --> Q[生成文档列表] Q --> R[启用发送按钮] R --> S[滚动到底部]
核心消息处理代码
javascript 复制代码
// 消息发送核心逻辑
async function sendMessage() {
    const message = messageInput.value.trim();
    if (message === "") {
        showToast("请输入消息内容!");
        return;
    }

    // 1. UI状态管理
    sendButton.disabled = true;
    sendButton.textContent = "发送中...";

    // 2. 添加用户消息
    addUserMessage(message);
    messageInput.value = "";

    // 3. 创建AI回复区域
    const aiMessageElement = addAIMessage("", false);
    showAIThinking(aiMessageElement);

    // 4. 初始化思维链引用
    const reasoningElementRef = { current: null };

    // 5. 清空缓存,开始新对话
    window.lastDocAggs = null;

    try {
        // 6. 调用Agent API
        const agentId = "agentId";
        await window.ragflowAPI.agentCompletionStream(
            agentId,
            message,
            currentSessionId,
            createStreamResponseHandler(aiMessageElement, reasoningElementRef),
            createCompletionHandler(false),
            createErrorHandler(reasoningElementRef, aiMessageElement, false)
        );
    } catch (error) {
        console.error("发送消息失败:", error);
        createErrorHandler(reasoningElementRef, aiMessageElement, false)(error);
    } finally {
        // 7. 恢复UI状态
        sendButton.disabled = false;
        sendButton.textContent = "发送";
        scrollToBottom();
    }
}

思维链系统深度解析

思维链处理流程
sequenceDiagram participant API as RAGFlow API participant Parser as 内容解析器 participant UI as 思维链UI participant User as 用户界面 API->>Parser: 返回包含标签的内容 Parser->>Parser: 正则匹配提取思维链 Parser->>UI: 创建思维链容器 UI->>User: 显示"AI正在思考..." loop 思维链内容更新 Parser->>UI: 更新思维链文本 UI->>User: 实时显示思考过程 end Parser->>Parser: 提取最终回复内容 Parser->>User: 显示AI最终回复 UI->>User: 思维链可折叠查看
思维链UI组件实现
javascript 复制代码
// 创建思维链消息区域
function addReasoningMessage(isVisible = true, insertBefore = null) {
    const chatMessages = document.getElementById("chatMessages");
    const reasoningContainer = document.createElement("div");
    reasoningContainer.className = `reasoning-container mb-4 ${isVisible ? 'flex' : 'hidden'} flex-col`;

    reasoningContainer.innerHTML = `
        <div class="flex items-center gap-2 mb-2">
            <div class="w-8 h-8 rounded-full bg-gradient-to-r from-blue-500 to-purple-600 flex items-center justify-center">
                <svg class="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 20 20">
                    <path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
                </svg>
            </div>
            <span class="font-medium text-gray-700 agent-thinking">AI正在深度思考</span>
            <button class="reasoning-toggle ml-auto px-3 py-1 bg-blue-500 text-white text-xs rounded-full hover:bg-blue-600 transition-colors">
                展开思维链
            </button>
        </div>
        <div class="reasoning-content bg-gray-50 rounded-lg p-4 border-l-4 border-blue-500 hidden">
            <div class="reasoning-text text-sm text-gray-700 font-mono leading-relaxed max-h-60 overflow-y-auto whitespace-pre-wrap"></div>
        </div>
    `;

    // 插入到指定位置或末尾
    if (insertBefore) {
        chatMessages.insertBefore(reasoningContainer, insertBefore);
    } else {
        chatMessages.appendChild(reasoningContainer);
    }

    // 绑定折叠/展开事件
    const toggleButton = reasoningContainer.querySelector('.reasoning-toggle');
    const reasoningContent = reasoningContainer.querySelector('.reasoning-content');

    toggleButton.addEventListener('click', () => {
        const isHidden = reasoningContent.classList.contains('hidden');
        if (isHidden) {
            reasoningContent.classList.remove('hidden');
            toggleButton.textContent = '收起思维链';
        } else {
            reasoningContent.classList.add('hidden');
            toggleButton.textContent = '展开思维链';
        }
    });

    return reasoningContainer;
}

// 更新思维链内容
function updateReasoningMessage(reasoningElement, content) {
    if (!reasoningElement) return;

    const reasoningText = reasoningElement.querySelector('.reasoning-text');
    if (reasoningText) {
        // 添加打字机效果
        reasoningText.classList.add('reasoning-typing');
        reasoningText.textContent = content;

        // 移除打字机效果
        setTimeout(() => {
            reasoningText.classList.remove('reasoning-typing');
        }, 100);
    }

    // 自动滚动到底部
    const reasoningContent = reasoningElement.querySelector('.reasoning-content');
    if (reasoningContent && !reasoningContent.classList.contains('hidden')) {
        reasoningText.scrollTop = reasoningText.scrollHeight;
    }
}

文档引用系统实现

引用处理流程图
graph TD A[AI回复包含引用] --> B[解析引用数据] B --> C[生成引用角标] C --> D[绑定悬停事件] D --> E[创建预览弹窗] E --> F[加载文档缩略图] F --> G[支持全屏预览] B --> H[提取文档信息] H --> I[生成文档列表] I --> J[支持文档下载]
引用角标生成代码
javascript 复制代码
// 处理引用并生成角标
function processReferences(content, chunks) {
    if (!chunks || chunks.length === 0) {
        return content;
    }

    console.log('📖 开始处理引用,chunks数量:', chunks.length);

    // 为每个chunk创建引用角标
    chunks.forEach((chunk, index) => {
        const referenceId = index + 1;
        const marker = `<span class="reference-marker" data-chunk-index="${index}" data-reference-id="${referenceId}">
            <svg viewBox="0 0 1024 1024" width="1em" height="1em">
                <path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"/>
                <path d="M464 336a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z"/>
            </svg>
        </span>`;

        // 在内容中插入引用角标(简化版本,实际可能需要更复杂的逻辑)
        if (index === 0) {
            content = content + ' ' + marker;
        }
    });

    return content;
}

// 初始化引用角标事件监听
function initReferenceTooltips() {
    let currentTooltip = null;

    // 使用事件委托处理引用角标点击
    document.addEventListener('click', function(e) {
        const marker = e.target.closest('.reference-marker');
        if (marker) {
            e.preventDefault();
            e.stopPropagation();

            const chunkIndex = parseInt(marker.dataset.chunkIndex);
            const referenceId = marker.dataset.referenceId;

            console.log('📖 点击引用角标:', { chunkIndex, referenceId });

            // 关闭现有的tooltip
            if (currentTooltip) {
                currentTooltip.remove();
                currentTooltip = null;
            }

            // 创建新的tooltip
            if (window.lastResponseChunks && window.lastResponseChunks[chunkIndex]) {
                currentTooltip = createReferenceTooltip(window.lastResponseChunks[chunkIndex], marker);
            }
        } else {
            // 点击其他地方关闭tooltip
            if (currentTooltip) {
                currentTooltip.remove();
                currentTooltip = null;
            }
        }
    });
}

响应式设计实现

移动端适配策略
graph LR A[设备检测] --> B{屏幕宽度} B -->|>768px| C[桌面端布局] B -->|≤768px| D[移动端布局] C --> C1[侧边栏固定显示] C --> C2[三栏布局] C --> C3[鼠标交互] D --> D1[侧边栏抽屉式] D --> D2[单栏布局] D --> D3[触摸交互]
CSS媒体查询实现
css 复制代码
/* 基础布局 - 桌面端优先 */
.main-content {
    display: flex;
    height: calc(100vh - 180px);
}

.left-sidebar {
    width: 200px;
    background: white;
    box-shadow: 2px 0 8px rgba(0,0,0,0.1);
    transition: transform 0.3s ease;
}

.chat-area {
    flex: 1;
    display: flex;
    flex-direction: column;
}

/* 移动端适配 */
@media (max-width: 768px) {
    .main-content {
        height: 100vh;
        position: relative;
    }

    .left-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        width: 250px;
        height: 100vh;
        z-index: 40;
        transform: translateX(-100%);
    }

    .left-sidebar.open {
        transform: translateX(0);
    }

    .chat-area {
        width: 100%;
        height: 100vh;
    }

    /* 移动端消息样式调整 */
    .message-container {
        padding: 12px 16px;
        margin: 8px 12px;
    }

    .user-message {
        max-width: 85%;
        font-size: 14px;
    }

    .ai-message {
        max-width: 90%;
        font-size: 14px;
        line-height: 1.5;
    }

    /* 输入区域移动端优化 */
    .input-area {
        padding: 12px;
    }

    .message-input {
        font-size: 16px; /* 防止iOS缩放 */
        min-height: 44px; /* 符合触摸目标大小 */
    }

    .send-button {
        min-width: 44px;
        min-height: 44px;
    }
}

/* 超小屏幕适配 */
@media (max-width: 480px) {
    .left-sidebar {
        width: 280px; /* 更宽的侧边栏 */
    }

    .message-container {
        padding: 10px 12px;
        margin: 6px 8px;
    }

    .reasoning-container {
        margin: 8px 12px;
        padding: 12px;
    }

    .reference-tooltip {
        max-width: calc(100vw - 32px);
        left: 16px !important;
        right: 16px !important;
        width: auto !important;
    }
}

性能监控与优化

性能监控实现
javascript 复制代码
// 性能监控类
class PerformanceMonitor {
    constructor() {
        this.metrics = {
            apiResponseTime: [],
            renderTime: [],
            memoryUsage: [],
            errorCount: 0
        };

        this.initMonitoring();
    }

    initMonitoring() {
        // 监控API响应时间
        this.monitorAPIPerformance();

        // 监控渲染性能
        this.monitorRenderPerformance();

        // 监控内存使用
        this.monitorMemoryUsage();

        // 定期报告
        setInterval(() => this.reportMetrics(), 30000);
    }

    monitorAPIPerformance() {
        const originalFetch = window.fetch;
        window.fetch = async (...args) => {
            const startTime = performance.now();
            try {
                const response = await originalFetch(...args);
                const endTime = performance.now();
                const duration = endTime - startTime;

                this.metrics.apiResponseTime.push(duration);

                if (duration > 5000) {
                    console.warn(`⚠️ API响应缓慢: ${duration}ms`);
                }

                return response;
            } catch (error) {
                this.metrics.errorCount++;
                throw error;
            }
        };
    }

    monitorRenderPerformance() {
        const observer = new PerformanceObserver((list) => {
            for (const entry of list.getEntries()) {
                if (entry.entryType === 'measure') {
                    this.metrics.renderTime.push(entry.duration);

                    if (entry.duration > 100) {
                        console.warn(`⚠️ 渲染性能警告: ${entry.name} 耗时 ${entry.duration}ms`);
                    }
                }
            }
        });

        observer.observe({ entryTypes: ['measure'] });
    }

    monitorMemoryUsage() {
        if ('memory' in performance) {
            setInterval(() => {
                const memory = performance.memory;
                this.metrics.memoryUsage.push({
                    used: memory.usedJSHeapSize,
                    total: memory.totalJSHeapSize,
                    limit: memory.jsHeapSizeLimit,
                    timestamp: Date.now()
                });

                // 内存使用率超过80%时警告
                const usageRatio = memory.usedJSHeapSize / memory.jsHeapSizeLimit;
                if (usageRatio > 0.8) {
                    console.warn(`⚠️ 内存使用率过高: ${(usageRatio * 100).toFixed(1)}%`);
                }
            }, 10000);
        }
    }

    reportMetrics() {
        const report = {
            avgApiResponseTime: this.calculateAverage(this.metrics.apiResponseTime),
            avgRenderTime: this.calculateAverage(this.metrics.renderTime),
            errorCount: this.metrics.errorCount,
            memoryTrend: this.analyzeMemoryTrend()
        };

        console.log('📊 性能报告:', report);

        // 清理旧数据,保持数组大小
        this.cleanupMetrics();
    }

    calculateAverage(arr) {
        if (arr.length === 0) return 0;
        return arr.reduce((sum, val) => sum + val, 0) / arr.length;
    }

    analyzeMemoryTrend() {
        const recent = this.metrics.memoryUsage.slice(-10);
        if (recent.length < 2) return 'insufficient_data';

        const first = recent[0].used;
        const last = recent[recent.length - 1].used;
        const change = ((last - first) / first) * 100;

        if (change > 10) return 'increasing';
        if (change < -10) return 'decreasing';
        return 'stable';
    }

    cleanupMetrics() {
        // 保持最近1000条记录
        if (this.metrics.apiResponseTime.length > 1000) {
            this.metrics.apiResponseTime = this.metrics.apiResponseTime.slice(-500);
        }
        if (this.metrics.renderTime.length > 1000) {
            this.metrics.renderTime = this.metrics.renderTime.slice(-500);
        }
        if (this.metrics.memoryUsage.length > 100) {
            this.metrics.memoryUsage = this.metrics.memoryUsage.slice(-50);
        }
    }
}

// 初始化性能监控
const performanceMonitor = new PerformanceMonitor();

本文基于实际项目开发经验编写,所有代码示例均经过测试验证。如有疑问,欢迎交流讨论。

相关推荐
徐子颐5 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭17 分钟前
如何理解HTML语义化
前端·html
jump68040 分钟前
url输入到网页展示会发生什么?
前端
诸葛韩信44 分钟前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu1 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花1 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋1 小时前
场景模拟:基础路由配置
前端
六月的可乐1 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程
一 乐2 小时前
智慧党建|党务学习|基于SprinBoot+vue的智慧党建学习平台(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·学习