用 ai 跑了一个性能优化 js,不知道有没有用,大家可以试试。
【AI 生成代码 风险自担】
- 使用者须自行测试验证
- 因使用造成的损失自行承担
// ================================================================
// 思源笔记性能优化套件 v1.1
// 版本:1.1 (悬浮球监控版)
// 功能:搜索优化、内存管理、渲染优化、批量保存、悬浮监控球
// 安装:设置 → 外观 → 代码片段 → 粘贴此代码 → 重启思源
// ================================================================
(function() {
'use strict';
console.log('[思源性能优化] 正在加载...');
// ==================== 配置参数 ====================
const CONFIG = {
// 防抖延迟(毫秒)
SEARCH_DEBOUNCE: 300,
INPUT_DEBOUNCE: 150,
// 内存清理间隔(分钟)
MEMORY_CLEANUP_MINUTES: 30,
// 批量保存设置
SAVE_BATCH_SIZE: 10,
SAVE_BATCH_DELAY: 300,
// 缓存设置
MAX_CACHE_SIZE: 100,
CACHE_EXPIRE_MINUTES: 10,
// 监控球设置
MONITOR_BALL_SIZE: 32, // 悬浮球大小(像素)
MONITOR_BALL_OPACITY: 0.6, // 悬浮球默认透明度
MONITOR_BALL_HOVER_OPACITY: 0.9, // 悬停时透明度
MONITOR_BALL_POSITION: 'right', // 默认位置: left/right
MONITOR_UPDATE_INTERVAL: 2000, // 监控更新频率(毫秒)
// 面板设置
PANEL_OPACITY: 0.95, // 面板透明度
PANEL_HOVER_OPACITY: 1.0 // 面板悬停透明度
};
// ==================== 性能统计 ====================
class PerformanceStats {
constructor() {
this.metrics = {
fps: 0,
memory: { used: 0, total: 0 },
domCount: 0,
saveCount: 0,
searchCount: 0,
cacheHits: 0,
cacheMisses: 0
};
this.startTime = Date.now();
this.frameCount = 0;
this.lastFpsTime = performance.now();
this.initFPSMonitor();
this.initMemoryMonitor();
}
initFPSMonitor() {
const updateFPS = () => {
this.frameCount++;
const now = performance.now();
if (now - this.lastFpsTime >= 1000) {
this.metrics.fps = Math.min(this.frameCount, 60);
this.frameCount = 0;
this.lastFpsTime = now;
}
requestAnimationFrame(updateFPS);
};
requestAnimationFrame(updateFPS);
}
initMemoryMonitor() {
setInterval(() => {
if (performance.memory) {
this.metrics.memory.used = Math.round(performance.memory.usedJSHeapSize / 1048576);
this.metrics.memory.total = Math.round(performance.memory.totalJSHeapSize / 1048576);
}
this.metrics.domCount = document.getElementsByTagName('*').length;
}, 3000);
}
recordSave(duration) {
this.metrics.saveCount++;
}
recordSearch(duration, cacheHit = false) {
this.metrics.searchCount++;
cacheHit ? this.metrics.cacheHits++ : this.metrics.cacheMisses++;
}
getCacheRate() {
const total = this.metrics.cacheHits + this.metrics.cacheMisses;
return total > 0 ? Math.round(this.metrics.cacheHits / total * 100) : 0;
}
getUptime() {
const seconds = Math.floor((Date.now() - this.startTime) / 1000);
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
return h > 0 ? `${h}h ${m}m` : `${m}m`;
}
getFPSColor(fps) {
if (fps >= 55) return '#4CAF50';
if (fps >= 30) return '#FFA726';
return '#F44336';
}
getMemoryColor(mem) {
const usedMB = parseInt(mem);
if (usedMB < 1000) return '#4CAF50';
if (usedMB < 2000) return '#FFA726';
return '#F44336';
}
getCacheColor(rate) {
if (rate >= 60) return '#4CAF50';
if (rate >= 30) return '#FFA726';
return '#F44336';
}
getSummary() {
return {
fps: this.metrics.fps,
fpsColor: this.getFPSColor(this.metrics.fps),
memory: `${this.metrics.memory.used}MB`,
memoryColor: this.getMemoryColor(this.metrics.memory.used),
dom: this.metrics.domCount,
cacheRate: this.getCacheRate(),
cacheColor: this.getCacheColor(this.getCacheRate()),
uptime: this.getUptime(),
saves: this.metrics.saveCount,
searches: this.metrics.searchCount
};
}
}
// ==================== 悬浮监控球 ====================
class MonitorBall {
constructor(stats) {
this.stats = stats;
this.ball = null;
this.panel = null;
this.isPanelVisible = false;
this.isDragging = false;
this.dragOffset = { x: 0, y: 0 };
this.init();
}
init() {
this.createBall();
this.createPanel();
this.setupEventListeners();
this.updateLoop();
console.log('[监控球] 悬浮监控球已启用');
}
createBall() {
this.ball = document.createElement('div');
this.ball.id = 'siyuan-monitor-ball';
this.ball.style.cssText = `
position: fixed;
${CONFIG.MONITOR_BALL_POSITION === 'right' ? 'right: 20px' : 'left: 20px'};
top: 50%;
transform: translateY(-50%);
width: ${CONFIG.MONITOR_BALL_SIZE}px;
height: ${CONFIG.MONITOR_BALL_SIZE}px;
border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: bold;
cursor: pointer;
z-index: 99998;
opacity: ${CONFIG.MONITOR_BALL_OPACITY};
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
user-select: none;
`;
document.body.appendChild(this.ball);
}
createPanel() {
this.panel = document.createElement('div');
this.panel.id = 'siyuan-monitor-panel';
this.panel.style.cssText = `
position: fixed;
${CONFIG.MONITOR_BALL_POSITION === 'right' ? 'right: 60px' : 'left: 60px'};
top: 50%;
transform: translateY(-50%);
background: rgba(20, 20, 20, ${CONFIG.PANEL_OPACITY});
color: #e0e0e0;
padding: 15px;
border-radius: 10px;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 12px;
z-index: 99997;
border: 1px solid #333;
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
backdrop-filter: blur(10px);
min-width: 220px;
user-select: none;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease, transform 0.3s ease;
`;
document.body.appendChild(this.panel);
}
setupEventListeners() {
// 悬浮球点击切换面板
this.ball.addEventListener('click', (e) => {
e.stopPropagation();
this.togglePanel();
});
// 悬浮球悬停效果
this.ball.addEventListener('mouseenter', () => {
this.ball.style.opacity = CONFIG.MONITOR_BALL_HOVER_OPACITY;
this.ball.style.transform = 'translateY(-50%) scale(1.1)';
});
this.ball.addEventListener('mouseleave', () => {
this.ball.style.opacity = CONFIG.MONITOR_BALL_OPACITY;
this.ball.style.transform = 'translateY(-50%) scale(1)';
});
// 面板悬停效果
this.panel.addEventListener('mouseenter', () => {
this.panel.style.opacity = CONFIG.PANEL_HOVER_OPACITY;
});
this.panel.addEventListener('mouseleave', () => {
if (this.isPanelVisible) {
this.panel.style.opacity = CONFIG.PANEL_OPACITY;
}
});
// 悬浮球拖动功能
this.ball.addEventListener('mousedown', (e) => {
this.startDrag(e);
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
this.drag(e);
});
document.addEventListener('mouseup', () => {
this.stopDrag();
});
// 点击页面其他地方关闭面板
document.addEventListener('click', (e) => {
if (this.isPanelVisible &&
!this.ball.contains(e.target) &&
!this.panel.contains(e.target)) {
this.hidePanel();
}
});
}
startDrag(e) {
this.isDragging = true;
const rect = this.ball.getBoundingClientRect();
this.dragOffset.x = e.clientX - rect.left;
this.dragOffset.y = e.clientY - rect.top;
this.ball.style.cursor = 'grabbing';
this.ball.style.transition = 'none';
}
drag(e) {
if (!this.isDragging) return;
const x = e.clientX - this.dragOffset.x;
const y = e.clientY - this.dragOffset.y;
// 限制在窗口范围内
const maxX = window.innerWidth - this.ball.offsetWidth;
const maxY = window.innerHeight - this.ball.offsetHeight;
const clampedX = Math.max(0, Math.min(x, maxX));
const clampedY = Math.max(0, Math.min(y, maxY));
this.ball.style.left = clampedX + 'px';
this.ball.style.top = clampedY + 'px';
this.ball.style.right = 'auto';
this.ball.style.transform = 'none';
// 更新面板位置
this.updatePanelPosition();
}
stopDrag() {
if (!this.isDragging) return;
this.isDragging = false;
this.ball.style.cursor = 'pointer';
this.ball.style.transition = 'all 0.3s ease';
// 保存位置到本地存储
this.savePosition();
}
updatePanelPosition() {
if (!this.panel || !this.isPanelVisible) return;
const ballRect = this.ball.getBoundingClientRect();
const panelWidth = this.panel.offsetWidth;
const windowWidth = window.innerWidth;
// 判断面板显示在左边还是右边
if (ballRect.left > windowWidth / 2) {
// 球在右边,面板显示在左边
this.panel.style.left = (ballRect.left - panelWidth - 10) + 'px';
this.panel.style.right = 'auto';
} else {
// 球在左边,面板显示在右边
this.panel.style.left = (ballRect.right + 10) + 'px';
this.panel.style.right = 'auto';
}
this.panel.style.top = (ballRect.top + ballRect.height / 2 - this.panel.offsetHeight / 2) + 'px';
}
savePosition() {
const ballRect = this.ball.getBoundingClientRect();
localStorage.setItem('siyuan-monitor-ball-pos', JSON.stringify({
x: ballRect.left,
y: ballRect.top,
timestamp: Date.now()
}));
}
loadPosition() {
try {
const saved = localStorage.getItem('siyuan-monitor-ball-pos');
if (saved) {
const pos = JSON.parse(saved);
if (Date.now() - pos.timestamp < 7 * 24 * 60 * 60 * 1000) { // 一周内
this.ball.style.left = pos.x + 'px';
this.ball.style.top = pos.y + 'px';
this.ball.style.right = 'auto';
this.ball.style.transform = 'none';
return true;
}
}
} catch (e) {
// 忽略错误
}
return false;
}
togglePanel() {
if (this.isPanelVisible) {
this.hidePanel();
} else {
this.showPanel();
}
}
showPanel() {
this.isPanelVisible = true;
this.updatePanel();
this.updatePanelPosition();
setTimeout(() => {
this.panel.style.opacity = CONFIG.PANEL_OPACITY;
this.panel.style.pointerEvents = 'auto';
this.panel.style.transform = 'translateY(-50%) scale(1)';
}, 10);
}
hidePanel() {
this.isPanelVisible = false;
this.panel.style.opacity = '0';
this.panel.style.pointerEvents = 'none';
this.panel.style.transform = 'translateY(-50%) scale(0.95)';
}
updateBall() {
const summary = this.stats.getSummary();
const fps = summary.fps;
// 悬浮球显示FPS
this.ball.textContent = fps;
this.ball.style.background = summary.fpsColor;
// 添加FPS状态提示
let status = '优秀';
if (fps < 30) status = '较差';
else if (fps < 55) status = '良好';
this.ball.title = `FPS: ${fps} (${status})\n点击查看详细性能信息`;
}
updatePanel() {
if (!this.panel || !this.isPanelVisible) return;
const summary = this.stats.getSummary();
this.panel.innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; border-bottom: 1px solid #444; padding-bottom: 8px;">
<strong style="color: #64B5F6; font-size: 13px;">⚡ 性能监控</strong>
<div style="display: flex; gap: 6px; align-items: center;">
<span style="font-size: 10px; color: #888; cursor: help;" title="可拖动悬浮球调整位置">📍</span>
<button onclick="window.SIYUAN_OPTIMIZER?.toggleMonitor()" style="background: none; border: none; color: #888; cursor: pointer; font-size: 14px; padding: 0; line-height: 1;" title="隐藏">−</button>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 12px;">
<div style="background: rgba(255,255,255,0.05); padding: 6px; border-radius: 4px; border-left: 3px solid ${summary.fpsColor};">
<div style="font-size: 10px; color: #aaa;">FPS</div>
<div style="color: ${summary.fpsColor}; font-weight: bold; font-size: 14px;">${summary.fps}</div>
</div>
<div style="background: rgba(255,255,255,0.05); padding: 6px; border-radius: 4px; border-left: 3px solid ${summary.memoryColor};">
<div style="font-size: 10px; color: #aaa;">内存</div>
<div style="color: ${summary.memoryColor}; font-weight: bold; font-size: 14px;">${summary.memory}</div>
</div>
<div style="background: rgba(255,255,255,0.05); padding: 6px; border-radius: 4px; border-left: 3px solid #64B5F6;">
<div style="font-size: 10px; color: #aaa;">DOM节点</div>
<div style="color: #64B5F6; font-weight: bold; font-size: 14px;">${summary.dom}</div>
</div>
<div style="background: rgba(255,255,255,0.05); padding: 6px; border-radius: 4px; border-left: 3px solid ${summary.cacheColor};">
<div style="font-size: 10px; color: #aaa;">缓存命中</div>
<div style="color: ${summary.cacheColor}; font-weight: bold; font-size: 14px;">${summary.cacheRate}%</div>
</div>
</div>
<div style="font-size: 10px; color: #888; margin-bottom: 10px;">
<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
<span>运行时间:</span>
<span>${summary.uptime}</span>
</div>
<div style="display: flex; justify-content: space-between;">
<span>操作统计:</span>
<span>保存${summary.saves}次 | 搜索${summary.searches}次</span>
</div>
</div>
<div style="display: flex; gap: 8px; border-top: 1px solid #333; padding-top: 10px;">
<button onclick="window.SIYUAN_OPTIMIZER?.cleanup()" style="flex: 1; background: #2196F3; color: white; border: none; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 10px; transition: all 0.2s ease;">清理内存</button>
<button onclick="window.SIYUAN_OPTIMIZER?.clearCache()" style="flex: 1; background: #FF9800; color: white; border: none; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 10px; transition: all 0.2s ease;">清空缓存</button>
</div>
<div style="margin-top: 8px; display: flex; gap: 8px;">
<button onclick="window.SIYUAN_OPTIMIZER?.flushSaves()" style="flex: 1; background: #4CAF50; color: white; border: none; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 10px; transition: all 0.2s ease;">立即保存</button>
<button onclick="location.reload()" style="flex: 1; background: #9C27B0; color: white; border: none; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 10px; transition: all 0.2s ease;">刷新应用</button>
</div>
<div style="margin-top: 8px; font-size: 9px; color: #666; text-align: center; padding-top: 8px; border-top: 1px solid #333;">
思源笔记性能优化套件 v1.1
</div>
`;
// 添加按钮悬停效果
this.panel.querySelectorAll('button').forEach(btn => {
btn.addEventListener('mouseenter', () => {
btn.style.transform = 'translateY(-1px)';
btn.style.boxShadow = '0 2px 8px rgba(0,0,0,0.2)';
});
btn.addEventListener('mouseleave', () => {
btn.style.transform = 'translateY(0)';
btn.style.boxShadow = 'none';
});
});
}
updateLoop() {
this.updateBall();
if (this.isPanelVisible) {
this.updatePanel();
}
setTimeout(() => this.updateLoop(), CONFIG.MONITOR_UPDATE_INTERVAL);
}
hide() {
this.ball.style.display = 'none';
this.hidePanel();
}
show() {
this.ball.style.display = 'flex';
}
toggle() {
if (this.ball.style.display === 'none') {
this.show();
} else {
this.hide();
}
}
}
// ==================== 搜索优化器 ====================
class SearchOptimizer {
constructor(stats) {
this.stats = stats;
this.cache = new Map();
this.pendingSearches = new Map();
this.init();
}
init() {
this.wrapSearchFunction();
this.setupCacheCleaner();
}
wrapSearchFunction() {
const originalSearch = window.siyuan?.search;
if (!originalSearch) {
setTimeout(() => this.wrapSearchFunction(), 1000);
return;
}
window.siyuan.search = async (query, options = {}) => {
if (!query || query.trim().length === 0) {
return [];
}
const cacheKey = this.getCacheKey(query, options);
// 检查缓存
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CONFIG.CACHE_EXPIRE_MINUTES * 60000) {
this.stats.recordSearch(0, true);
return cached.results;
}
// 检查是否已有相同搜索在进行
if (this.pendingSearches.has(cacheKey)) {
return this.pendingSearches.get(cacheKey);
}
// 创建防抖搜索
const searchPromise = new Promise(resolve => {
setTimeout(async () => {
try {
const startTime = performance.now();
const results = await originalSearch(query, options);
const duration = performance.now() - startTime;
// 缓存结果
if (query.length > 2) {
this.cache.set(cacheKey, {
results,
timestamp: Date.now(),
query,
duration
});
this.manageCacheSize();
}
this.stats.recordSearch(duration, false);
resolve(results);
} catch (error) {
console.error('[搜索优化] 搜索失败:', error);
resolve([]);
} finally {
this.pendingSearches.delete(cacheKey);
}
}, CONFIG.SEARCH_DEBOUNCE);
});
this.pendingSearches.set(cacheKey, searchPromise);
return searchPromise;
};
console.log('[搜索优化] 搜索函数已优化');
}
getCacheKey(query, options) {
return JSON.stringify({
q: query.trim().toLowerCase(),
t: options.type || 'all'
});
}
manageCacheSize() {
if (this.cache.size > CONFIG.MAX_CACHE_SIZE) {
let oldestKey = null;
let oldestTime = Date.now();
for (const [key, value] of this.cache.entries()) {
if (value.timestamp < oldestTime) {
oldestTime = value.timestamp;
oldestKey = key;
}
}
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
}
setupCacheCleaner() {
setInterval(() => {
const now = Date.now();
for (const [key, value] of this.cache.entries()) {
if (now - value.timestamp > CONFIG.CACHE_EXPIRE_MINUTES * 60000) {
this.cache.delete(key);
}
}
}, 60000);
}
clearCache() {
this.cache.clear();
console.log('[搜索优化] 缓存已清空');
}
}
// ==================== 内存优化器 ====================
class MemoryOptimizer {
constructor() {
this.init();
}
init() {
this.setupLazyLoading();
this.setupMemoryCleanup();
console.log('[内存优化] 已启用');
}
setupLazyLoading() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
if (img.dataset.src) {
img.src = img.dataset.src;
img.removeAttribute('data-src');
}
observer.unobserve(img);
}
});
}, {
rootMargin: '300px',
threshold: 0.01
});
setTimeout(() => {
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
}, 1000);
new MutationObserver(() => {
document.querySelectorAll('img[data-src]').forEach(img => {
if (!img.hasAttribute('data-lazy-loaded')) {
observer.observe(img);
img.setAttribute('data-lazy-loaded', 'true');
}
});
}).observe(document.body, {
childList: true,
subtree: true
});
}
setupMemoryCleanup() {
setInterval(() => {
this.cleanupHiddenElements();
this.triggerGarbageCollection();
}, CONFIG.MEMORY_CLEANUP_MINUTES * 60000);
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
this.triggerGarbageCollection();
}
});
}
cleanupHiddenElements() {
const hiddenElements = document.querySelectorAll('.fn__none, [style*="display: none"]');
const now = Date.now();
hiddenElements.forEach(el => {
if (!el.hasAttribute('data-keep-in-memory')) {
const lastActive = parseInt(el.dataset.lastActive || '0');
if (now - lastActive > 300000) {
el.innerHTML = '';
el.dataset.cleaned = now;
}
}
});
}
triggerGarbageCollection() {
if (window.gc) {
try {
window.gc();
console.log('[内存优化] 垃圾回收已执行');
} catch (e) {}
}
}
}
// ==================== 保存优化器 ====================
class SaveOptimizer {
constructor(stats) {
this.stats = stats;
this.saveQueue = [];
this.saveTimer = null;
this.init();
}
init() {
this.wrapSaveFunction();
this.setupAutoFlush();
console.log('[保存优化] 批量保存已启用');
}
wrapSaveFunction() {
const originalSave = window.siyuan?.saveTransaction;
if (!originalSave) {
setTimeout(() => this.wrapSaveFunction(), 1000);
return;
}
window.siyuan.saveTransaction = (data) => {
return new Promise((resolve) => {
this.saveQueue.push({ data, resolve });
if (this.saveQueue.length >= CONFIG.SAVE_BATCH_SIZE) {
this.flushSaves(originalSave);
}
else if (!this.saveTimer) {
this.saveTimer = setTimeout(() => {
this.flushSaves(originalSave);
}, CONFIG.SAVE_BATCH_DELAY);
}
});
};
}
async flushSaves(originalSave) {
if (this.saveTimer) {
clearTimeout(this.saveTimer);
this.saveTimer = null;
}
if (this.saveQueue.length === 0) return;
const batch = [...this.saveQueue];
this.saveQueue = [];
const mergedData = this.mergeSaveData(batch);
try {
const startTime = performance.now();
const result = await originalSave(mergedData);
const duration = performance.now() - startTime;
batch.forEach(item => item.resolve(result));
this.stats.recordSave(duration);
console.log(`[保存优化] 批量保存 ${batch.length} 个操作`);
} catch (error) {
console.error('[保存优化] 批量保存失败:', error);
batch.forEach(item => item.resolve(null));
}
}
mergeSaveData(batch) {
return {
operations: batch.flatMap(item => item.data.operations || []),
blocks: batch.flatMap(item => item.data.blocks || []),
batchSize: batch.length,
timestamp: Date.now()
};
}
setupAutoFlush() {
setInterval(() => {
if (this.saveQueue.length > 0) {
const originalSave = window.siyuan?.saveTransaction;
if (originalSave) {
this.flushSaves(originalSave);
}
}
}, 5 * 60000);
}
forceFlush() {
const originalSave = window.siyuan?.saveTransaction;
if (originalSave) {
this.flushSaves(originalSave);
}
}
}
// ==================== 渲染优化器 ====================
class RenderOptimizer {
constructor() {
this.init();
}
init() {
this.injectOptimizedStyles();
this.optimizeScrollPerformance();
console.log('[渲染优化] CSS优化已应用');
}
injectOptimizedStyles() {
const style = document.createElement('style');
style.textContent = `
.protyle-wysiwyg [data-node-id] {
contain: layout;
}
.protyle-content {
transform: translateZ(0);
}
img[data-src] {
opacity: 0;
transition: opacity 0.3s ease;
}
img[src]:not([data-src]) {
opacity: 1;
}
.fn__none {
display: none !important;
}
`;
document.head.appendChild(style);
}
optimizeScrollPerformance() {
let isScrolling = false;
let scrollTimer = null;
const handleScroll = () => {
isScrolling = true;
document.querySelectorAll('.protyle-attr, .protyle-toolbar').forEach(el => {
el.style.opacity = '0.7';
});
if (scrollTimer) clearTimeout(scrollTimer);
scrollTimer = setTimeout(() => {
isScrolling = false;
document.querySelectorAll('.protyle-attr, .protyle-toolbar').forEach(el => {
el.style.opacity = '';
});
}, 100);
};
window.addEventListener('scroll', handleScroll, { passive: true });
window.addEventListener('wheel', handleScroll, { passive: true });
}
}
// ==================== 主控制器 ====================
class SiyuanOptimizer {
constructor() {
this.version = '1.1';
this.modules = {};
this.init();
}
init() {
console.log(`%c思源笔记性能优化套件 v${this.version}`,
'background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 6px 10px; border-radius: 4px;');
const checkSiyuanLoaded = () => {
if (window.siyuan) {
this.startOptimization();
} else {
setTimeout(checkSiyuanLoaded, 500);
}
};
checkSiyuanLoaded();
}
startOptimization() {
try {
this.modules.stats = new PerformanceStats();
this.modules.memory = new MemoryOptimizer();
this.modules.render = new RenderOptimizer();
this.modules.search = new SearchOptimizer(this.modules.stats);
this.modules.save = new SaveOptimizer(this.modules.stats);
this.modules.monitor = new MonitorBall(this.modules.stats);
this.setupGlobalAPI();
setTimeout(() => {
console.log('✅ 思源笔记性能优化已启用!');
console.log('🎯 功能: 悬浮监控球、搜索加速、内存优化、批量保存');
console.log('⚡ 使用: SIYUAN_OPTIMIZER.help() 查看可用命令');
}, 1000);
} catch (error) {
console.error('[思源优化] 初始化失败:', error);
}
}
setupGlobalAPI() {
window.SIYUAN_OPTIMIZER = {
version: this.version,
cleanup: () => {
if (window.gc) {
try {
window.gc();
console.log('[优化器] 内存清理完成');
} catch (e) {}
}
},
flushSaves: () => {
if (this.modules.save) {
this.modules.save.forceFlush();
}
},
clearCache: () => {
if (this.modules.search) {
this.modules.search.clearCache();
}
},
toggleMonitor: () => {
if (this.modules.monitor) {
this.modules.monitor.toggle();
}
},
showMonitor: () => {
if (this.modules.monitor) {
this.modules.monitor.show();
}
},
hideMonitor: () => {
if (this.modules.monitor) {
this.modules.monitor.hide();
}
},
getStats: () => {
return this.modules.stats ? this.modules.stats.getSummary() : null;
},
getConfig: () => {
return CONFIG;
},
help: () => {
console.log(`
思源笔记性能优化套件 v${this.version} - 可用命令:
SIYUAN_OPTIMIZER.help() 显示帮助信息
SIYUAN_OPTIMIZER.getStats() 获取性能统计数据
SIYUAN_OPTIMIZER.cleanup() 手动清理内存
SIYUAN_OPTIMIZER.flushSaves() 立即执行所有保存
SIYUAN_OPTIMIZER.clearCache() 清空搜索缓存
SIYUAN_OPTIMIZER.toggleMonitor()显示/隐藏悬浮监控球
SIYUAN_OPTIMIZER.showMonitor() 显示悬浮监控球
SIYUAN_OPTIMIZER.hideMonitor() 隐藏悬浮监控球
`);
}
};
}
}
// ==================== 启动优化器 ====================
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
new SiyuanOptimizer();
}, 2000);
});
} else {
setTimeout(() => {
new SiyuanOptimizer();
}, 2000);
}
window.addEventListener('beforeunload', () => {
const optimizer = window.SIYUAN_OPTIMIZER;
if (optimizer && optimizer.flushSaves) {
optimizer.flushSaves();
}
localStorage.setItem('siyuan-optimizer-last-run', Date.now());
});
})();
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于