前端:重构 Web UI 代码结构
- 添加 Import Map 支持 Lit 和本地模块的简洁导入 - 创建统一的 API 管理模块 (common/api.js) - 重命名 styles/ 为 common/ 目录 - 修复分页时列选择被重置的问题 - 将 app.js 重命名为 main.js - 所有导入路径使用 ~ 别名映射
This commit is contained in:
174
webui/static/js/common/api.js
Normal file
174
webui/static/js/common/api.js
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* API 请求管理模块
|
||||
* 统一管理所有后端接口请求
|
||||
*/
|
||||
|
||||
const API_BASE = '/api';
|
||||
|
||||
/**
|
||||
* 通用请求处理函数
|
||||
* @param {string} url - 请求 URL
|
||||
* @param {RequestInit} options - fetch 选项
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
async function request(url, options = {}) {
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
error.status = response.status;
|
||||
error.response = response;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('API request failed:', url, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表相关 API
|
||||
*/
|
||||
export const tableAPI = {
|
||||
/**
|
||||
* 获取所有表列表
|
||||
* @returns {Promise<Array>}
|
||||
*/
|
||||
async list() {
|
||||
return request(`${API_BASE}/tables`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取表的 Schema
|
||||
* @param {string} tableName - 表名
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getSchema(tableName) {
|
||||
return request(`${API_BASE}/tables/${tableName}/schema`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取表数据(分页)
|
||||
* @param {string} tableName - 表名
|
||||
* @param {Object} params - 查询参数
|
||||
* @param {number} params.page - 页码
|
||||
* @param {number} params.pageSize - 每页大小
|
||||
* @param {string} params.select - 选择的列(逗号分隔)
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getData(tableName, { page = 1, pageSize = 20, select = '' } = {}) {
|
||||
const params = new URLSearchParams({
|
||||
page: page.toString(),
|
||||
pageSize: pageSize.toString(),
|
||||
});
|
||||
|
||||
if (select) {
|
||||
params.append('select', select);
|
||||
}
|
||||
|
||||
return request(`${API_BASE}/tables/${tableName}/data?${params}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单行数据详情
|
||||
* @param {string} tableName - 表名
|
||||
* @param {number} seq - 序列号
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getRow(tableName, seq) {
|
||||
return request(`${API_BASE}/tables/${tableName}/data/${seq}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取表的 Manifest 信息
|
||||
* @param {string} tableName - 表名
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getManifest(tableName) {
|
||||
return request(`${API_BASE}/tables/${tableName}/manifest`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 插入数据
|
||||
* @param {string} tableName - 表名
|
||||
* @param {Object} data - 数据对象
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async insert(tableName, data) {
|
||||
return request(`${API_BASE}/tables/${tableName}/data`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量插入数据
|
||||
* @param {string} tableName - 表名
|
||||
* @param {Array<Object>} data - 数据数组
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async batchInsert(tableName, data) {
|
||||
return request(`${API_BASE}/tables/${tableName}/data/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除表
|
||||
* @param {string} tableName - 表名
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async delete(tableName) {
|
||||
return request(`${API_BASE}/tables/${tableName}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取表统计信息
|
||||
* @param {string} tableName - 表名
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getStats(tableName) {
|
||||
return request(`${API_BASE}/tables/${tableName}/stats`);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 数据库相关 API
|
||||
*/
|
||||
export const databaseAPI = {
|
||||
/**
|
||||
* 获取数据库信息
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getInfo() {
|
||||
return request(`${API_BASE}/database/info`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取数据库统计信息
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async getStats() {
|
||||
return request(`${API_BASE}/database/stats`);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出默认 API 对象
|
||||
*/
|
||||
export default {
|
||||
table: tableAPI,
|
||||
database: databaseAPI,
|
||||
};
|
||||
89
webui/static/js/common/shared-styles.js
Normal file
89
webui/static/js/common/shared-styles.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import { css } from 'lit';
|
||||
|
||||
// 共享的基础样式
|
||||
export const sharedStyles = css`
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
*::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
/* 通用状态样式 */
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
`;
|
||||
|
||||
// CSS 变量(可以在组件中使用,优先使用外部定义的变量)
|
||||
export const cssVariables = css`
|
||||
:host {
|
||||
/* 主色调 - 优雅的紫蓝色 */
|
||||
--primary: var(--srdb-primary, #6366f1);
|
||||
--primary-dark: var(--srdb-primary-dark, #4f46e5);
|
||||
--primary-light: var(--srdb-primary-light, #818cf8);
|
||||
--primary-bg: var(--srdb-primary-bg, rgba(99, 102, 241, 0.1));
|
||||
|
||||
/* 背景色 */
|
||||
--bg-main: var(--srdb-bg-main, #0f0f1a);
|
||||
--bg-surface: var(--srdb-bg-surface, #1a1a2e);
|
||||
--bg-elevated: var(--srdb-bg-elevated, #222236);
|
||||
--bg-hover: var(--srdb-bg-hover, #2a2a3e);
|
||||
|
||||
/* 文字颜色 */
|
||||
--text-primary: var(--srdb-text-primary, #ffffff);
|
||||
--text-secondary: var(--srdb-text-secondary, #a0a0b0);
|
||||
--text-tertiary: var(--srdb-text-tertiary, #6b6b7b);
|
||||
|
||||
/* 边框和分隔线 */
|
||||
--border-color: var(--srdb-border-color, rgba(255, 255, 255, 0.1));
|
||||
--border-hover: var(--srdb-border-hover, rgba(255, 255, 255, 0.2));
|
||||
|
||||
/* 状态颜色 */
|
||||
--success: var(--srdb-success, #10b981);
|
||||
--warning: var(--srdb-warning, #f59e0b);
|
||||
--danger: var(--srdb-danger, #ef4444);
|
||||
--info: var(--srdb-info, #3b82f6);
|
||||
|
||||
/* 阴影 */
|
||||
--shadow-sm: var(--srdb-shadow-sm, 0 1px 2px 0 rgba(0, 0, 0, 0.3));
|
||||
--shadow-md: var(--srdb-shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3));
|
||||
--shadow-lg: var(--srdb-shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.3));
|
||||
--shadow-xl: var(--srdb-shadow-xl, 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.3));
|
||||
|
||||
/* 圆角 */
|
||||
--radius-sm: var(--srdb-radius-sm, 6px);
|
||||
--radius-md: var(--srdb-radius-md, 8px);
|
||||
--radius-lg: var(--srdb-radius-lg, 12px);
|
||||
--radius-xl: var(--srdb-radius-xl, 16px);
|
||||
|
||||
/* 过渡 */
|
||||
--transition: var(--srdb-transition, all 0.2s cubic-bezier(0.4, 0, 0.2, 1));
|
||||
}
|
||||
`;
|
||||
Reference in New Issue
Block a user