Files
srdb/webui/static/js/app.js
bourdon 23843493b8 重构代码结构并添加完整功能
主要改动:
- 重构目录结构:合并子目录到根目录,简化项目结构
- 添加完整的查询 API:支持复杂条件查询、字段选择、游标模式
- 实现 LSM-Tree Compaction:7层结构、Score-based策略、后台异步合并
- 添加 Web UI:基于 Lit 的现代化管理界面,支持数据浏览和 Manifest 查看
- 完善文档:添加 README.md 和 examples/webui/README.md

新增功能:
- Query Builder:链式查询 API,支持 Eq/Lt/Gt/In/Between/Contains 等操作符
- Web UI 组件:srdb-app、srdb-table-list、srdb-data-view、srdb-manifest-view 等
- 列选择持久化:自动保存到 localStorage
- 刷新按钮:一键刷新当前视图
- 主题切换:深色/浅色主题支持

代码优化:
- 使用 Go 1.24 新特性:range 7、min()、maps.Copy()、slices.Sort()
- 统一组件命名:所有 Web Components 使用 srdb-* 前缀
- CSS 优化:提取共享样式,减少重复代码
- 清理遗留代码:删除未使用的方法和样式
2025-10-08 23:04:47 +08:00

111 lines
3.7 KiB
JavaScript

import './components/app.js';
import './components/table-list.js';
import './components/table-view.js';
import './components/modal-dialog.js';
import './components/theme-toggle.js';
import './components/badge.js';
import './components/field-icon.js';
import './components/data-view.js';
import './components/manifest-view.js';
import './components/page-header.js';
class App {
constructor() {
// 等待 srdb-app 组件渲染完成
this.appContainer = document.querySelector('srdb-app');
this.modal = document.querySelector('srdb-modal-dialog');
// 等待组件初始化
if (this.appContainer) {
// 使用 updateComplete 等待组件渲染完成
this.appContainer.updateComplete.then(() => {
this.tableList = this.appContainer.shadowRoot.querySelector('srdb-table-list');
this.tableView = this.appContainer.shadowRoot.querySelector('srdb-table-view');
this.pageHeader = this.appContainer.shadowRoot.querySelector('srdb-page-header');
this.setupEventListeners();
});
} else {
// 如果组件还未定义,等待它被定义
customElements.whenDefined('srdb-app').then(() => {
this.appContainer = document.querySelector('srdb-app');
this.appContainer.updateComplete.then(() => {
this.tableList = this.appContainer.shadowRoot.querySelector('srdb-table-list');
this.tableView = this.appContainer.shadowRoot.querySelector('srdb-table-view');
this.pageHeader = this.appContainer.shadowRoot.querySelector('srdb-page-header');
this.setupEventListeners();
});
});
}
}
setupEventListeners() {
// Listen for table selection
document.addEventListener('table-selected', (e) => {
const tableName = e.detail.tableName;
this.pageHeader.tableName = tableName;
this.pageHeader.view = 'data';
this.tableView.tableName = tableName;
this.tableView.view = 'data';
this.tableView.page = 1;
});
// Listen for view change from page-header
document.addEventListener('view-changed', (e) => {
this.tableView.view = e.detail.view;
});
// Listen for refresh request from page-header
document.addEventListener('refresh-view', (e) => {
this.tableView.loadData();
});
// Listen for row detail request
document.addEventListener('show-row-detail', async (e) => {
const { tableName, seq } = e.detail;
await this.showRowDetail(tableName, seq);
});
// Listen for cell content request
document.addEventListener('show-cell-content', (e) => {
this.showCellContent(e.detail.content);
});
// Close modal on backdrop click
this.modal.addEventListener('click', () => {
this.modal.open = false;
});
}
async showRowDetail(tableName, seq) {
try {
const response = await fetch(`/api/tables/${tableName}/data/${seq}`);
if (!response.ok) throw new Error('Failed to load row detail');
const data = await response.json();
const content = JSON.stringify(data, null, 2);
this.modal.title = `Row Detail - Seq: ${seq}`;
this.modal.content = content;
this.modal.open = true;
} catch (error) {
console.error('Error loading row detail:', error);
this.modal.title = 'Error';
this.modal.content = `Failed to load row detail: ${error.message}`;
this.modal.open = true;
}
}
showCellContent(content) {
this.modal.title = 'Cell Content';
this.modal.content = String(content);
this.modal.open = true;
}
}
// Initialize app when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => new App());
} else {
new App();
}