Files
srdb/webui/static/js/components/TableItem.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

131 lines
4.3 KiB
JavaScript

import { html } from 'htm/preact';
import { useState } from 'preact/hooks';
import { FieldList } from '~/components/FieldList.js';
const styles = {
tableItem: (isSelected, isExpanded) => ({
background: 'var(--bg-elevated)',
border: isSelected ? '1px solid var(--primary)' : '1px solid var(--border-color)',
borderRadius: 'var(--radius-md)',
overflow: 'hidden',
transition: 'var(--transition)',
boxShadow: isSelected ? '0 0 0 1px var(--primary)' : 'none'
}),
tableHeader: (isSelected) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: '4px',
paddingRight: '12px',
cursor: 'pointer',
transition: 'var(--transition)',
background: isSelected ? 'var(--primary-bg)' : 'transparent'
}),
tableHeaderLeft: {
display: 'flex',
alignItems: 'center',
gap: '8px',
flex: 1,
minWidth: 0
},
expandIcon: (isExpanded) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '32px',
height: '32px',
fontSize: '12px',
transition: 'var(--transition)',
flexShrink: 0,
borderRadius: 'var(--radius-sm)',
cursor: 'pointer',
color: isExpanded ? 'var(--primary)' : 'var(--text-secondary)',
transform: isExpanded ? 'rotate(90deg)' : 'rotate(0deg)',
marginLeft: '-4px'
}),
tableName: {
fontWeight: 500,
color: 'var(--text-primary)',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
},
tableCount: {
fontSize: '12px',
color: 'var(--text-tertiary)',
whiteSpace: 'nowrap',
flexShrink: 0
}
};
export function TableItem({ table, isSelected, onSelect }) {
const [isExpanded, setIsExpanded] = useState(false);
const toggleExpand = (e) => {
e.stopPropagation();
setIsExpanded(!isExpanded);
};
return html`
<div
style=${styles.tableItem(isSelected, isExpanded)}
onMouseEnter=${(e) => {
if (!isSelected) {
e.currentTarget.style.borderColor = 'var(--border-hover)';
}
}}
onMouseLeave=${(e) => {
if (!isSelected) {
e.currentTarget.style.borderColor = 'var(--border-color)';
}
}}
>
<!-- 表头 -->
<div
style=${styles.tableHeader(isSelected)}
onClick=${onSelect}
onMouseEnter=${(e) => {
if (!isSelected) {
e.currentTarget.style.background = 'var(--bg-hover)';
}
}}
onMouseLeave=${(e) => {
if (!isSelected) {
e.currentTarget.style.background = 'transparent';
}
}}
>
<div style=${styles.tableHeaderLeft}>
<span
style=${styles.expandIcon(isExpanded)}
onClick=${toggleExpand}
onMouseEnter=${(e) => {
e.currentTarget.style.background = 'var(--bg-hover)';
if (!isExpanded) {
e.currentTarget.style.color = 'var(--text-primary)';
}
}}
onMouseLeave=${(e) => {
e.currentTarget.style.background = 'transparent';
if (!isExpanded) {
e.currentTarget.style.color = 'var(--text-secondary)';
}
}}
>
</span>
<span style=${styles.tableName}>${table.name}</span>
</div>
<span style=${styles.tableCount}>
${table.fields?.length || 0} fields
</span>
</div>
<!-- 字段列表 -->
${isExpanded && html`
<${FieldList} fields=${table.fields} />
`}
</div>
`;
}