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();

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

相关推荐
Nueuis1 小时前
微信小程序前端面经
前端·微信小程序·小程序
_r0bin_3 小时前
前端面试准备-7
开发语言·前端·javascript·fetch·跨域·class
IT瘾君3 小时前
JavaWeb:前端工程化-Vue
前端·javascript·vue.js
zhang98800003 小时前
JavaScript 核心原理深度解析-不停留于表面的VUE等的使用!
开发语言·javascript·vue.js
potender3 小时前
前端框架Vue
前端·vue.js·前端框架
站在风口的猪11084 小时前
《前端面试题:CSS预处理器(Sass、Less等)》
前端·css·html·less·css3·sass·html5
程序员的世界你不懂4 小时前
(9)-Fiddler抓包-Fiddler如何设置捕获Https会话
前端·https·fiddler
MoFe14 小时前
【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
java·前端·.netcore
去旅行、在路上5 小时前
chrome使用手机调试触屏web
前端·chrome
Aphasia3115 小时前
模式验证库——zod
前端·react.js