构建知识库和联网搜索对话平台:从零到一的完整开发指南
项目概述
本项目集成了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响应时间监控
- 错误率:系统错误率统计
- 用户活跃度:用户使用情况分析
- 资源使用:服务器资源使用监控
📈 未来扩展计划
功能扩展
- 多模态支持:支持图片、音频输入
- 插件系统:支持第三方插件扩展
- 协作功能:支持多人协作对话
- 个性化设置:用户个性化配置
技术升级
- 框架升级:考虑迁移到现代前端框架
- PWA支持:添加离线功能支持
- WebRTC:支持实时音视频通话
- 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();
本文基于实际项目开发经验编写,所有代码示例均经过测试验证。如有疑问,欢迎交流讨论。