import { LitElement, html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js'; import { sharedStyles, cssVariables } from '../styles/shared-styles.js'; export class ManifestView extends LitElement { static properties = { manifestData: { type: Object }, loading: { type: Boolean }, expandedLevels: { type: Set } }; static styles = [ sharedStyles, cssVariables, css` :host { display: block; } h3 { font-size: 16px; font-weight: 600; margin: 20px 0 12px 0; color: var(--text-primary); } .manifest-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; } .stat-card { padding: 16px; background: var(--bg-elevated); border: 1px solid var(--border-color); border-radius: var(--radius-md); } .stat-label { font-size: 12px; color: var(--text-tertiary); margin-bottom: 8px; } .stat-value { font-size: 20px; font-weight: 600; color: var(--text-primary); } .level-card { margin-bottom: 12px; background: var(--bg-elevated); border: 1px solid var(--border-color); border-radius: var(--radius-md); overflow: hidden; } .level-header { display: flex; align-items: center; justify-content: space-between; padding: 16px; cursor: pointer; transition: var(--transition); } .level-header:hover { background: var(--bg-hover); } .level-header-left { display: flex; align-items: center; gap: 12px; flex: 1; } .expand-icon { font-size: 12px; color: var(--text-secondary); transition: transform 0.2s ease; user-select: none; } .expand-icon.expanded { transform: rotate(90deg); } .level-title { font-size: 16px; font-weight: 600; color: var(--text-primary); } .level-stats { display: flex; gap: 16px; font-size: 13px; color: var(--text-secondary); } .level-files { padding: 16px; background: var(--bg-surface); border-top: 1px solid var(--border-color); display: none; } .level-files.expanded { display: block; } .file-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; } .file-item { padding: 12px; background: var(--bg-elevated); border: 1px solid var(--border-color); border-radius: var(--radius-sm); transition: var(--transition); } .file-item:hover { border-color: var(--primary); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .file-name { font-family: 'Courier New', monospace; font-size: 13px; color: var(--text-primary); font-weight: 500; margin-bottom: 8px; } .file-detail { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-secondary); } .file-detail-row { display: flex; justify-content: space-between; } @media (max-width: 768px) { .file-list { grid-template-columns: 1fr; } } .empty { background: var(--bg-elevated); border-radius: var(--radius-md); border: 1px dashed var(--border-color); margin-top: 24px; } .empty p { margin: 0; } ` ]; constructor() { super(); this.manifestData = null; this.loading = false; this.expandedLevels = new Set(); } toggleLevel(levelNum) { if (this.expandedLevels.has(levelNum)) { this.expandedLevels.delete(levelNum); } else { this.expandedLevels.add(levelNum); } this.requestUpdate(); } formatSize(bytes) { if (bytes >= 1024 * 1024 * 1024) return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB'; if (bytes >= 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(2) + ' MB'; if (bytes >= 1024) return (bytes / 1024).toFixed(2) + ' KB'; return bytes + ' B'; } getScoreVariant(score) { if (score >= 0.8) return 'danger'; // 高分 = 需要紧急 compaction if (score >= 0.5) return 'warning'; // 中分 = 需要关注 return 'success'; // 低分 = 健康状态 } render() { if (this.loading || !this.manifestData) { return html`
No SSTable files in this table yet.
Insert some data to see the LSM-Tree structure.