feat: TicketCreatePage tab化 + SchemaSidebar + Redis快速搜索 + Dashboard导航修复

TicketCreatePage 重构:
- SQL编辑器右侧新增数据库浏览器面板(tab化)
- 表结构Tab: 表列表→字段展开(PK/索引标记)→点击插入SQL
- 索引Tab: 选中表的索引详情(索引名/类型/字段/基数)
- Redis Keys Tab: DB选择器+Key模式搜索+Key列表+类型/TTL/值查看

SchemaSidebar 新组件(365行):
- MySQL/PostgreSQL: 左侧数据库表树→字段→点击插入SQL
- Redis: Key树(DB选择→模式搜索→Key值查看, 类似Another Redis Desktop Manager)
- 用于 QueriesPage 查询页面

Dashboard:
- 快捷按钮改用 useNavigate + onClick 替代 <a href>

API增强:
- redis.ts: 新增 getKeys/createKey/deleteKey 方法
- instanceDetail.ts: 导出 TableMeta/TableDetail/ColumnInfo/IndexInfo 类型接口
This commit is contained in:
logan committed 2026-05-24 15:10:31 +08:00
1 parent 8471f368eb
commit 0fb947dcb5
6 files changed
+1020 -476

No files matched your search

+72 -37
View File
@@ -1,48 +1,83 @@
import request from './request';
/** 实例详情 API — 数据库/表/字段/索引/Redis Key */
export const instanceDetailApi = {
// Databases
listDatabases: (id: number) =>
request.get<any, string[]>('/instances/' + id + '/detail/databases'),
/** 获取 MySQL 数据库列表 */
listDatabases: (instanceId: number) =>
request.get<any, string[]>(`/instances/${instanceId}/detail/databases`),
// Tables
listTables: (id: number, database: string) =>
request.get<any, any[]>('/instances/' + id + '/detail/tables', { params: { database: database } }),
/** 获取表列表(含引擎、行数等) */
listTables: (instanceId: number, database: string) =>
request.get<any, TableMeta[]>(`/instances/${instanceId}/detail/tables`, {
params: { database },
}),
// Table Detail
getTableDetail: (id: number, database: string, table: string) =>
request.get<any, any>('/instances/' + id + '/detail/table-detail', { params: { database: database, table: table } }),
/** 获取表详情(DDL + 字段 + 索引) */
getTableDetail: (instanceId: number, database: string, table: string) =>
request.get<any, TableDetail>(`/instances/${instanceId}/detail/table-detail`, {
params: { database, table },
}),
// Users
listUsers: (id: number) =>
request.get<any, any[]>('/instances/' + id + '/detail/users'),
/** SHOW PROCESSLIST */
getProcesslist: (instanceId: number) =>
request.get<any, any[]>(`/instances/${instanceId}/detail/processlist`),
// Grants
getGrants: (id: number, user: string, host: string) =>
request.get<any, any>('/instances/' + id + '/detail/grants', { params: { user: user, host: host } }),
/** SHOW GLOBAL STATUS */
getStatus: (instanceId: number) =>
request.get<any, { key_metrics: Record<string, string>; all_status: any[] }>(
`/instances/${instanceId}/detail/status`
),
// Processlist
getProcesslist: (id: number) =>
request.get<any, any[]>('/instances/' + id + '/detail/processlist'),
/** 终止进程 */
killProcess: (instanceId: number, pid: number) =>
request.post<any, any>(`/instances/${instanceId}/detail/processlist/${pid}/kill`),
// Kill Process
killProcess: (id: number, pid: number) =>
request.post<any, any>('/instances/' + id + '/detail/processlist/' + pid + '/kill'),
// Status
getStatus: (id: number) =>
request.get<any, any>('/instances/' + id + '/detail/status'),
// Variables
getVariables: (id: number) =>
request.get<any, any[]>('/instances/' + id + '/detail/variables'),
/** 获取数据库用户列表 */
listUsers: (instanceId: number) =>
request.get<any, any[]>(`/instances/${instanceId}/detail/users`),
};
export const backupApi = {
list: (instanceId?: number) =>
request.get<any, any[]>('/backups', { params: instanceId ? { instance_id: instanceId } : {} }),
create: (data: any) =>
request.post<any, any>('/backups', data),
get: (id: number) =>
request.get<any, any>('/backups/' + id),
};
/** 表元信息 */
export interface TableMeta {
name: string;
engine: string;
rows: number;
data_length: number;
index_length: number;
comment: string;
collation: string;
create_time: string;
update_time: string;
}
/** 表详情 */
export interface TableDetail {
ddl: string;
columns: ColumnInfo[];
indexes: IndexInfo[];
}
export interface ColumnInfo {
Field: string;
Type: string;
Null: string;
Key: string;
Default: string | null;
Extra: string;
}
export interface IndexInfo {
Table: string;
Non_unique: number;
Key_name: string;
Seq_in_index: number;
Column_name: string;
Collation: string;
Cardinality: number;
Sub_part: string | null;
Packed: string | null;
Null: string;
Index_type: string;
Comment: string;
Index_comment: string;
}
+12
View File
@@ -28,4 +28,16 @@ export const redisApi = {
// 执行命令
executeCommand: (instanceId: number, data: { db: number; command: string }) =>
request.post<any, any>('/redis/' + instanceId + '/command', data),
// 获取键列表(兼容旧接口)
getKeys: (instanceId: number, params?: { db?: number; pattern?: string; count?: number; type?: string; cursor?: number }) =>
request.get<any, any>('/redis/' + instanceId + '/keys', { params }),
// 创建键
createKey: (instanceId: number, data: { db?: number; key: string; type?: string; value: any; ttl?: number }) =>
request.post<any, any>('/redis/' + instanceId + '/keys', data),
// 删除键
deleteKey: (instanceId: number, key: string, db?: number) =>
request.delete<any, any>('/redis/' + instanceId + '/keys/' + encodeURIComponent(key), { params: { db: db ?? 0 } }),
};