主要改动: 1. WebUI basePath 逻辑完善 - NewWebUI 支持可变参数 basePath - 新增 path() 辅助方法统一路径处理 - handleTableAPI 正确处理 basePath 前缀 - handleIndex 根据 basePath 替换占位符 2. 简化示例代码 - 删除反向代理实现(111行) - 直接使用带 basePath 的 WebUI - 代码量减少 33%,架构更清晰 3. 前端优化 - 新增 api.js 统一 API 服务层 - 所有组件使用统一的 API 调用 - 支持通过 window.API_BASE 配置 basePath 4. 修复 .gitignore - 使用通用模式支持 commands 目录 - 无需为新示例项目修改配置
101 lines
3.3 KiB
JavaScript
101 lines
3.3 KiB
JavaScript
import { html } from 'htm/preact';
|
|
import { useState, useEffect } from 'preact/hooks';
|
|
import { LevelCard } from '~/components/LevelCard.js';
|
|
import { StatCard } from '~/components/StatCard.js';
|
|
import { CompactionStats } from '~/components/CompactionStats.js';
|
|
import { getTableManifest } from '~/utils/api.js';
|
|
|
|
const styles = {
|
|
container: {
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: '12px'
|
|
},
|
|
statsGrid: {
|
|
display: 'grid',
|
|
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
|
|
gap: '8px'
|
|
}
|
|
};
|
|
|
|
function formatBytes(bytes) {
|
|
if (bytes === 0) return '0 B';
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
|
|
}
|
|
|
|
function formatNumber(num) {
|
|
return num.toLocaleString('zh-CN');
|
|
}
|
|
|
|
export function ManifestView({ tableName }) {
|
|
const [manifest, setManifest] = useState(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [expandedLevels, setExpandedLevels] = useState(new Set());
|
|
|
|
useEffect(() => {
|
|
fetchManifest();
|
|
const interval = setInterval(fetchManifest, 5000); // 每5秒刷新
|
|
return () => clearInterval(interval);
|
|
}, [tableName]);
|
|
|
|
const fetchManifest = async () => {
|
|
try {
|
|
const data = await getTableManifest(tableName);
|
|
setManifest(data);
|
|
} catch (error) {
|
|
console.error('Failed to fetch manifest:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const toggleLevel = (levelNum) => {
|
|
const newExpanded = new Set(expandedLevels);
|
|
if (newExpanded.has(levelNum)) {
|
|
newExpanded.delete(levelNum);
|
|
} else {
|
|
newExpanded.add(levelNum);
|
|
}
|
|
setExpandedLevels(newExpanded);
|
|
};
|
|
|
|
if (loading) {
|
|
return html`<div class="loading"><p>加载中...</p></div>`;
|
|
}
|
|
|
|
if (!manifest) {
|
|
return html`<div class="empty"><p>无法加载 Manifest 数据</p></div>`;
|
|
}
|
|
|
|
const totalFiles = manifest.levels?.reduce((sum, level) => sum + level.file_count, 0) || 0;
|
|
const totalSize = manifest.levels?.reduce((sum, level) => sum + level.total_size, 0) || 0;
|
|
|
|
return html`
|
|
<div style=${styles.container}>
|
|
<!-- 统计信息 -->
|
|
<div style=${styles.statsGrid}>
|
|
<${StatCard} label="总文件数" value=${formatNumber(totalFiles)} />
|
|
<${StatCard} label="总大小" value=${formatBytes(totalSize)} />
|
|
<${StatCard} label="下一个文件号" value=${formatNumber(manifest.next_file_number || 0)} />
|
|
<${StatCard} label="最后序列号" value=${formatNumber(manifest.last_sequence || 0)} />
|
|
</div>
|
|
|
|
<!-- Compaction 统计 -->
|
|
<${CompactionStats} stats=${manifest.compaction_stats} />
|
|
|
|
<!-- 各层级详情 -->
|
|
${manifest.levels?.filter(level => level.file_count > 0).map(level => html`
|
|
<${LevelCard}
|
|
key=${level.level}
|
|
level=${level}
|
|
isExpanded=${expandedLevels.has(level.level)}
|
|
onToggle=${() => toggleLevel(level.level)}
|
|
/>
|
|
`)}
|
|
</div>
|
|
`;
|
|
}
|