Files
srdb/webui/static/js/components/App.js
bourdon 30c3e74bd2 feat: 完善 WebUI basePath 支持并简化示例代码
主要改动:

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 目录
   - 无需为新示例项目修改配置
2025-10-14 22:23:30 +08:00

147 lines
4.7 KiB
JavaScript

import { html } from 'htm/preact';
import { useState, useEffect } from 'preact/hooks';
import { Sidebar } from '~/components/Sidebar.js';
import { TableView } from '~/components/TableView.js';
import { getTables } from '~/utils/api.js';
export function App() {
const [theme, setTheme] = useState('dark');
const [tables, setTables] = useState([]);
const [selectedTable, setSelectedTable] = useState(null);
const [loading, setLoading] = useState(true);
// 初始化主题
useEffect(() => {
const savedTheme = localStorage.getItem('srdb_theme') || 'dark';
setTheme(savedTheme);
if (savedTheme === 'light') {
document.documentElement.setAttribute('data-theme', 'light');
}
}, []);
// 加载表列表
useEffect(() => {
fetchTables();
}, []);
const fetchTables = async () => {
try {
setLoading(true);
const data = await getTables();
setTables(data.tables || []);
if (data.tables && data.tables.length > 0) {
setSelectedTable(data.tables[0].name);
}
} catch (error) {
console.error('Failed to fetch tables:', error);
} finally {
setLoading(false);
}
};
const toggleTheme = () => {
const newTheme = theme === 'dark' ? 'light' : 'dark';
setTheme(newTheme);
localStorage.setItem('srdb_theme', newTheme);
if (newTheme === 'light') {
document.documentElement.setAttribute('data-theme', 'light');
} else {
document.documentElement.removeAttribute('data-theme');
}
};
const styles = {
container: {
display: 'flex',
height: '100vh',
overflow: 'hidden'
},
sidebar: {
width: '280px',
background: 'var(--bg-surface)',
borderRight: '1px solid var(--border-color)',
overflowY: 'auto',
overflowX: 'hidden',
padding: '16px 12px',
display: 'flex',
flexDirection: 'column',
gap: '8px'
},
sidebarHeader: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: '4px'
},
sidebarTitle: {
fontSize: '18px',
fontWeight: 700,
letterSpacing: '-0.02em',
background: 'linear-gradient(135deg, #667eea, #764ba2)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
margin: 0
},
themeToggle: {
width: '32px',
height: '32px',
background: 'var(--bg-elevated)',
border: '1px solid var(--border-color)',
borderRadius: 'var(--radius-md)',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '16px',
transition: 'var(--transition)'
},
main: {
flex: 1,
overflowY: 'auto',
overflowX: 'hidden',
background: 'var(--bg-main)',
padding: '24px'
}
};
return html`
<div style=${styles.container}>
<!-- 左侧侧边栏 -->
<div style=${styles.sidebar}>
<div style=${styles.sidebarHeader}>
<h1 style=${styles.sidebarTitle}>SRDB Tables</h1>
<button
style=${styles.themeToggle}
onClick=${toggleTheme}
onMouseEnter=${(e) => e.target.style.background = 'var(--bg-hover)'}
onMouseLeave=${(e) => e.target.style.background = 'var(--bg-elevated)'}
title=${theme === 'dark' ? '切换到浅色主题' : '切换到深色主题'}
>
${theme === 'dark' ? '☀️' : '🌙'}
</button>
</div>
<${Sidebar}
tables=${tables}
selectedTable=${selectedTable}
onSelectTable=${setSelectedTable}
loading=${loading}
/>
</div>
<!-- 右侧主内容区 -->
<div style=${styles.main}>
${!selectedTable && html`
<div class="empty">
<p>Select a table from the sidebar</p>
</div>
`}
${selectedTable && html`
<${TableView} tableName=${selectedTable} key=${selectedTable} />
`}
</div>
</div>
`;
}