mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-21 08:10:29 +08:00
- 保存逻辑:外部 SQL 文件标签页携带 filePath,保存时写回原始磁盘文件 - 后端接口:新增 WriteSQLFile 能力,支持覆盖已有 SQL 文件并保留原文件权限 - 状态隔离:外部文件保存失败时不创建 savedQuery,避免写入 localStorage 副本 - 兼容行为:非文件标签页继续沿用原有 savedQuery 快速保存逻辑 - 文案优化:将数据库下入口改为“外部 SQL 目录”,减少与单文件打开入口的歧义 - 测试覆盖:补充前端保存分支、后端写文件边界和外部 SQL 目录文案测试 Refs #422
132 lines
4.2 KiB
TypeScript
132 lines
4.2 KiB
TypeScript
import type { ExternalSQLDirectory, ExternalSQLTreeEntry } from '../types';
|
|
|
|
export type ExternalSQLNodeType =
|
|
| 'external-sql-root'
|
|
| 'external-sql-directory'
|
|
| 'external-sql-folder'
|
|
| 'external-sql-file';
|
|
|
|
export interface ExternalSQLTreeNode {
|
|
title: string;
|
|
key: string;
|
|
isLeaf?: boolean;
|
|
children?: ExternalSQLTreeNode[];
|
|
type: ExternalSQLNodeType;
|
|
dataRef: Record<string, unknown>;
|
|
}
|
|
|
|
type BuildExternalSQLRootNodeParams = {
|
|
dbNodeKey: string;
|
|
connectionId: string;
|
|
dbName: string;
|
|
directories: ExternalSQLDirectory[];
|
|
directoryTrees: Record<string, ExternalSQLTreeEntry[]>;
|
|
};
|
|
|
|
const normalizeExternalSQLPath = (value: string): string =>
|
|
String(value || '').trim().replace(/\\/g, '/');
|
|
|
|
const resolveDirectoryDisplayName = (directory: ExternalSQLDirectory): string => {
|
|
const explicitName = String(directory.name || '').trim();
|
|
if (explicitName) return explicitName;
|
|
const normalizedPath = normalizeExternalSQLPath(directory.path);
|
|
const segments = normalizedPath.split('/').filter(Boolean);
|
|
return segments[segments.length - 1] || 'SQL目录';
|
|
};
|
|
|
|
export const buildExternalSQLDirectoryId = (connectionId: string, dbName: string, directoryPath: string): string =>
|
|
`external-sql-dir:${String(connectionId || '').trim()}:${String(dbName || '').trim()}:${normalizeExternalSQLPath(directoryPath)}`;
|
|
|
|
export const buildExternalSQLTabId = (connectionId: string, dbName: string, filePath: string): string =>
|
|
`external-sql-tab:${String(connectionId || '').trim()}:${String(dbName || '').trim()}:${normalizeExternalSQLPath(filePath)}`;
|
|
|
|
const buildExternalSQLNodeKey = (type: ExternalSQLNodeType, base: string): string =>
|
|
`${type}:${normalizeExternalSQLPath(base)}`;
|
|
|
|
const mapExternalSQLTreeEntries = (
|
|
entries: ExternalSQLTreeEntry[],
|
|
context: { connectionId: string; dbName: string; dbNodeKey: string; directoryId: string },
|
|
): ExternalSQLTreeNode[] => entries.map((entry) => {
|
|
const entryPath = normalizeExternalSQLPath(entry.path);
|
|
if (entry.isDir) {
|
|
const children = mapExternalSQLTreeEntries(entry.children || [], context);
|
|
return {
|
|
title: entry.name,
|
|
key: buildExternalSQLNodeKey('external-sql-folder', entryPath),
|
|
type: 'external-sql-folder',
|
|
isLeaf: children.length === 0,
|
|
children: children.length > 0 ? children : undefined,
|
|
dataRef: {
|
|
connectionId: context.connectionId,
|
|
dbName: context.dbName,
|
|
dbNodeKey: context.dbNodeKey,
|
|
directoryId: context.directoryId,
|
|
path: entry.path,
|
|
name: entry.name,
|
|
},
|
|
};
|
|
}
|
|
|
|
return {
|
|
title: entry.name,
|
|
key: buildExternalSQLNodeKey('external-sql-file', entryPath),
|
|
type: 'external-sql-file',
|
|
isLeaf: true,
|
|
dataRef: {
|
|
connectionId: context.connectionId,
|
|
dbName: context.dbName,
|
|
dbNodeKey: context.dbNodeKey,
|
|
directoryId: context.directoryId,
|
|
path: entry.path,
|
|
name: entry.name,
|
|
},
|
|
};
|
|
});
|
|
|
|
export const buildExternalSQLRootNode = ({
|
|
dbNodeKey,
|
|
connectionId,
|
|
dbName,
|
|
directories,
|
|
directoryTrees,
|
|
}: BuildExternalSQLRootNodeParams): ExternalSQLTreeNode => {
|
|
const sortedDirectories = [...directories].sort((left, right) =>
|
|
resolveDirectoryDisplayName(left).toLowerCase().localeCompare(resolveDirectoryDisplayName(right).toLowerCase()),
|
|
);
|
|
|
|
const children = sortedDirectories.map((directory) => {
|
|
const directoryChildren = mapExternalSQLTreeEntries(directoryTrees[directory.id] || [], {
|
|
connectionId,
|
|
dbName,
|
|
dbNodeKey,
|
|
directoryId: directory.id,
|
|
});
|
|
return {
|
|
title: resolveDirectoryDisplayName(directory),
|
|
key: buildExternalSQLNodeKey('external-sql-directory', directory.id),
|
|
type: 'external-sql-directory' as const,
|
|
isLeaf: directoryChildren.length === 0,
|
|
children: directoryChildren.length > 0 ? directoryChildren : undefined,
|
|
dataRef: {
|
|
...directory,
|
|
connectionId,
|
|
dbName,
|
|
dbNodeKey,
|
|
},
|
|
};
|
|
});
|
|
|
|
return {
|
|
title: children.length > 0 ? `外部 SQL 目录 (${children.length})` : '外部 SQL 目录',
|
|
key: `${dbNodeKey}-external-sql`,
|
|
type: 'external-sql-root',
|
|
isLeaf: children.length === 0,
|
|
children: children.length > 0 ? children : undefined,
|
|
dataRef: {
|
|
connectionId,
|
|
dbName,
|
|
dbNodeKey,
|
|
},
|
|
};
|
|
};
|