Files
MyGoNavi/frontend/src/components/tableCopyAction.ts
Syngnat 446707698f feat(table-copy): 新增整表复制与自动副本命名
- 在表概览及新旧侧栏右键菜单接入复制整表入口与确认、进度和刷新反馈
- 按 source_copyN 原子创建目标表并复制列、索引、默认值及全部数据
- 处理 PostgreSQL 生成列、identity/serial 序列校准与失败清理
- 限定安全数据源与连接保护策略,阻止分区表、RLS 及引用型存储引擎
- 加固 MySQL/PostgreSQL 元数据标识符处理并补齐六语种文案
- 增加后端、能力矩阵、菜单接线和国际化回归测试
2026-07-21 13:27:24 +08:00

93 lines
2.5 KiB
TypeScript

import { message } from 'antd';
import { t } from '../i18n';
import Modal from './common/ResizableDraggableModal';
type CopyTableResult = {
success?: boolean;
data?: unknown;
message?: string;
};
type CopyTableBackend = (
config: unknown,
dbName: string,
sourceSchemaName: string,
sourceTableName: string,
) => Promise<CopyTableResult>;
type ConfirmCopyTableOptions = {
config: unknown;
dbName: string;
sourceSchemaName?: string;
sourceTableName: string;
onSuccess?: (targetTableName: string) => void | Promise<void>;
};
const resolveCopyTableBackend = (): CopyTableBackend | null => {
const runtime = globalThis as typeof globalThis & {
go?: { app?: { App?: { CopyTable?: CopyTableBackend } } };
};
return typeof runtime.go?.app?.App?.CopyTable === 'function'
? runtime.go.app.App.CopyTable
: null;
};
export const confirmCopyTable = ({
config,
dbName,
sourceSchemaName = '',
sourceTableName,
onSuccess,
}: ConfirmCopyTableOptions): void => {
const source = String(sourceTableName || '').trim();
if (!source) return;
Modal.confirm({
title: t('table_copy.modal.title'),
content: t('table_copy.modal.content', { source, target: `${source}_copy1` }),
okText: t('common.confirm'),
cancelText: t('common.cancel'),
onOk: async () => {
const copyTable = resolveCopyTableBackend();
if (!copyTable) {
const error = t('table_copy.message.backend_unavailable');
message.error(error);
return Promise.reject(new Error(error));
}
const hide = message.loading(t('table_copy.message.loading', { source }), 0);
try {
const result = await copyTable(config, dbName, sourceSchemaName, source);
if (!result?.success) {
throw new Error(result?.message || t('common.unknown'));
}
const target = String(result.data || '').trim();
if (!target) {
throw new Error(t('table_copy.message.target_missing'));
}
message.success(t('table_copy.message.success', { target }));
if (onSuccess) {
try {
await onSuccess(target);
} catch (error: any) {
message.warning(t('table_copy.message.refresh_failed', {
target,
error: error?.message || String(error),
}));
}
}
} catch (error: any) {
message.error(t('table_copy.message.failed', {
error: error?.message || String(error),
}));
return Promise.reject(error);
} finally {
hide();
}
},
});
};