fdb2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +21 -0
- package/.editorconfig +11 -0
- package/.eslintrc.cjs +14 -0
- package/.eslintrc.json +7 -0
- package/.prettierrc.js +3 -0
- package/.tpl.env +22 -0
- package/README.md +260 -0
- package/bin/build.sh +28 -0
- package/bin/deploy.sh +8 -0
- package/bin/dev.sh +10 -0
- package/bin/docker/.env +4 -0
- package/bin/docker/dev-docker-compose.yml +43 -0
- package/bin/docker/dev.Dockerfile +24 -0
- package/bin/docker/prod-docker-compose.yml +17 -0
- package/bin/docker/prod.Dockerfile +29 -0
- package/bin/fdb2.js +142 -0
- package/data/connections.demo.json +32 -0
- package/env.d.ts +1 -0
- package/nw-build.js +120 -0
- package/nw-dev.js +65 -0
- package/package.json +114 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +9 -0
- package/public/modules/header.tpl +14 -0
- package/public/modules/initial_state.tpl +55 -0
- package/server/index.ts +677 -0
- package/server/model/connection.entity.ts +66 -0
- package/server/model/database.entity.ts +246 -0
- package/server/service/connection.service.ts +334 -0
- package/server/service/database/base.service.ts +363 -0
- package/server/service/database/database.service.ts +510 -0
- package/server/service/database/index.ts +7 -0
- package/server/service/database/mssql.service.ts +723 -0
- package/server/service/database/mysql.service.ts +761 -0
- package/server/service/database/oracle.service.ts +839 -0
- package/server/service/database/postgres.service.ts +744 -0
- package/server/service/database/sqlite.service.ts +559 -0
- package/server/service/session.service.ts +158 -0
- package/server.js +128 -0
- package/src/adapter/ajax.ts +135 -0
- package/src/assets/base.css +1 -0
- package/src/assets/database.css +950 -0
- package/src/assets/images/collapse.png +0 -0
- package/src/assets/images/no-login.png +0 -0
- package/src/assets/images/svg/illustrations/illustration-1.svg +1 -0
- package/src/assets/images/svg/illustrations/illustration-2.svg +2 -0
- package/src/assets/images/svg/illustrations/illustration-3.svg +50 -0
- package/src/assets/images/svg/illustrations/illustration-4.svg +1 -0
- package/src/assets/images/svg/illustrations/illustration-5.svg +73 -0
- package/src/assets/images/svg/illustrations/illustration-6.svg +89 -0
- package/src/assets/images/svg/illustrations/illustration-7.svg +39 -0
- package/src/assets/images/svg/illustrations/illustration-8.svg +1 -0
- package/src/assets/images/svg/separators/curve-2.svg +3 -0
- package/src/assets/images/svg/separators/curve.svg +3 -0
- package/src/assets/images/svg/separators/line.svg +3 -0
- package/src/assets/images/theme/light/screen-1-1000x800.jpg +0 -0
- package/src/assets/images/theme/light/screen-2-1000x800.jpg +0 -0
- package/src/assets/login/bg.jpg +0 -0
- package/src/assets/login/bg.png +0 -0
- package/src/assets/login/left.jpg +0 -0
- package/src/assets/logo.svg +73 -0
- package/src/assets/logo.webp +0 -0
- package/src/assets/main.css +1 -0
- package/src/base/config.ts +20 -0
- package/src/base/detect.ts +134 -0
- package/src/base/entity.ts +92 -0
- package/src/base/eventBus.ts +37 -0
- package/src/base//345/237/272/347/241/200/345/261/202.md +7 -0
- package/src/components/connection-editor/index.vue +590 -0
- package/src/components/dataGrid/index.vue +105 -0
- package/src/components/dataGrid/pagination.vue +106 -0
- package/src/components/loading/index.vue +43 -0
- package/src/components/modal/index.ts +181 -0
- package/src/components/modal/index.vue +560 -0
- package/src/components/toast/index.ts +44 -0
- package/src/components/toast/toast.vue +58 -0
- package/src/components/user/name.vue +104 -0
- package/src/components/user/selector.vue +416 -0
- package/src/domain/SysConfig.ts +74 -0
- package/src/platform/App.vue +8 -0
- package/src/platform/database/components/connection-detail.vue +1154 -0
- package/src/platform/database/components/data-editor.vue +478 -0
- package/src/platform/database/components/data-import-export.vue +1602 -0
- package/src/platform/database/components/database-detail.vue +1173 -0
- package/src/platform/database/components/database-monitor.vue +1086 -0
- package/src/platform/database/components/db-tools.vue +577 -0
- package/src/platform/database/components/query-history.vue +1349 -0
- package/src/platform/database/components/sql-executor.vue +738 -0
- package/src/platform/database/components/sql-query-editor.vue +1046 -0
- package/src/platform/database/components/table-detail.vue +1376 -0
- package/src/platform/database/components/table-editor.vue +690 -0
- package/src/platform/database/explorer.vue +1840 -0
- package/src/platform/database/index.vue +1193 -0
- package/src/platform/database/layout.vue +367 -0
- package/src/platform/database/router.ts +37 -0
- package/src/platform/database/styles/common.scss +602 -0
- package/src/platform/database/types/common.ts +445 -0
- package/src/platform/database/utils/export.ts +232 -0
- package/src/platform/database/utils/helpers.ts +437 -0
- package/src/platform/index.ts +33 -0
- package/src/platform/router.ts +41 -0
- package/src/service/base.ts +128 -0
- package/src/service/database.ts +500 -0
- package/src/service/login.ts +121 -0
- package/src/shims-vue.d.ts +7 -0
- package/src/stores/connection.ts +266 -0
- package/src/stores/session.ts +87 -0
- package/src/typings/database-types.ts +413 -0
- package/src/typings/database.ts +364 -0
- package/src/typings/global.d.ts +58 -0
- package/src/typings/pinia.d.ts +8 -0
- package/src/utils/clipboard.ts +30 -0
- package/src/utils/database-types.ts +243 -0
- package/src/utils/modal.ts +124 -0
- package/src/utils/request.ts +55 -0
- package/src/utils/sleep.ts +4 -0
- package/src/utils/toast.ts +73 -0
- package/src/utils/util.ts +171 -0
- package/src/utils/xlsx.ts +228 -0
- package/tsconfig.json +33 -0
- package/tsconfig.server.json +19 -0
- package/view/index.html +9 -0
- package/view/modules/header.tpl +14 -0
- package/view/modules/initial_state.tpl +20 -0
- package/vite.config.ts +384 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import { DataSource } from 'typeorm';
|
|
2
|
+
import {
|
|
3
|
+
DatabaseEntity,
|
|
4
|
+
TableEntity,
|
|
5
|
+
ColumnEntity,
|
|
6
|
+
IndexEntity,
|
|
7
|
+
ForeignKeyEntity
|
|
8
|
+
} from '../../model/database.entity';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 数据库服务基础类
|
|
12
|
+
* 提供所有数据库类型的通用操作
|
|
13
|
+
*/
|
|
14
|
+
export abstract class BaseDatabaseService {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 获取数据库类型
|
|
18
|
+
*/
|
|
19
|
+
abstract getDatabaseType(): string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 获取数据库列表 - 子类实现
|
|
23
|
+
*/
|
|
24
|
+
abstract getDatabases(dataSource: DataSource): Promise<string[]>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 获取表列表 - 子类实现
|
|
28
|
+
*/
|
|
29
|
+
abstract getTables(dataSource: DataSource, database: string): Promise<TableEntity[]>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 获取列信息 - 子类实现
|
|
33
|
+
*/
|
|
34
|
+
abstract getColumns(dataSource: DataSource, database: string, table: string): Promise<ColumnEntity[]>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 获取索引信息 - 子类实现
|
|
38
|
+
*/
|
|
39
|
+
abstract getIndexes(dataSource: DataSource, database: string, table: string): Promise<IndexEntity[]>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 获取外键信息 - 子类实现
|
|
43
|
+
*/
|
|
44
|
+
abstract getForeignKeys(dataSource: DataSource, database: string, table: string): Promise<ForeignKeyEntity[]>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 获取数据库大小 - 子类实现
|
|
48
|
+
*/
|
|
49
|
+
abstract getDatabaseSize(dataSource: DataSource, database: string): Promise<number>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 通用方法:获取数据库详细信息
|
|
53
|
+
*/
|
|
54
|
+
async getDatabaseInfo(dataSource: DataSource, databaseName: string): Promise<DatabaseEntity> {
|
|
55
|
+
const tables = await this.getTables(dataSource, databaseName);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
name: databaseName,
|
|
59
|
+
tableCount: tables.length,
|
|
60
|
+
size: await this.getDatabaseSize(dataSource, databaseName),
|
|
61
|
+
tables
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 通用方法:获取表详细信息
|
|
67
|
+
*/
|
|
68
|
+
async getTableInfo(dataSource: DataSource, databaseName: string, tableName: string): Promise<TableEntity> {
|
|
69
|
+
const tables = await this.getTables(dataSource, databaseName);
|
|
70
|
+
const table = tables.find(t => t.name === tableName);
|
|
71
|
+
|
|
72
|
+
if (!table) {
|
|
73
|
+
throw new Error(`表 ${tableName} 不存在`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 获取列信息
|
|
77
|
+
table.columns = await this.getColumns(dataSource, databaseName, tableName);
|
|
78
|
+
|
|
79
|
+
// 获取索引信息
|
|
80
|
+
table.indexes = await this.getIndexes(dataSource, databaseName, tableName);
|
|
81
|
+
|
|
82
|
+
// 获取外键信息
|
|
83
|
+
table.foreignKeys = await this.getForeignKeys(dataSource, databaseName, tableName);
|
|
84
|
+
|
|
85
|
+
return table;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 通用方法:获取表数据
|
|
90
|
+
*/
|
|
91
|
+
async getTableData(
|
|
92
|
+
dataSource: DataSource,
|
|
93
|
+
databaseName: string,
|
|
94
|
+
tableName: string,
|
|
95
|
+
page: number = 1,
|
|
96
|
+
pageSize: number = 100,
|
|
97
|
+
where?: string,
|
|
98
|
+
orderBy?: string
|
|
99
|
+
): Promise<{ data: any[], total: number }> {
|
|
100
|
+
// 构建查询
|
|
101
|
+
let query = `SELECT * FROM ${this.quoteIdentifier(tableName)}`;
|
|
102
|
+
|
|
103
|
+
if (where) {
|
|
104
|
+
query += ` WHERE ${where}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (orderBy) {
|
|
108
|
+
query += ` ORDER BY ${orderBy}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const offset = (page - 1) * pageSize;
|
|
112
|
+
query += ` LIMIT ${pageSize} OFFSET ${offset}`;
|
|
113
|
+
|
|
114
|
+
// 执行数据查询
|
|
115
|
+
const data = await dataSource.query(query);
|
|
116
|
+
|
|
117
|
+
// 获取总数
|
|
118
|
+
let countQuery = `SELECT COUNT(*) as total FROM ${this.quoteIdentifier(tableName)}`;
|
|
119
|
+
if (where) {
|
|
120
|
+
countQuery += ` WHERE ${where}`;
|
|
121
|
+
}
|
|
122
|
+
const countResult = await dataSource.query(countQuery);
|
|
123
|
+
const total = countResult[0]?.total || 0;
|
|
124
|
+
|
|
125
|
+
return { data, total };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 通用方法:执行SQL查询
|
|
130
|
+
*/
|
|
131
|
+
async executeQuery(dataSource: DataSource, sql: string): Promise<any> {
|
|
132
|
+
try {
|
|
133
|
+
const result = await dataSource.query(sql);
|
|
134
|
+
return result;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error('SQL执行失败:', error);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 批量执行SQL查询(支持多条语句)
|
|
143
|
+
*/
|
|
144
|
+
async executeBatchQuery(
|
|
145
|
+
dataSource: DataSource,
|
|
146
|
+
sqlStatements: string[],
|
|
147
|
+
options?: {
|
|
148
|
+
batchSize?: number; // 每批执行的语句数量
|
|
149
|
+
useTransaction?: boolean; // 是否使用事务
|
|
150
|
+
continueOnError?: boolean; // 错误时是否继续执行
|
|
151
|
+
}
|
|
152
|
+
): Promise<{ success: number; failed: number; errors: any[] }> {
|
|
153
|
+
const {
|
|
154
|
+
batchSize = 100,
|
|
155
|
+
useTransaction = true,
|
|
156
|
+
continueOnError = false
|
|
157
|
+
} = options || {};
|
|
158
|
+
|
|
159
|
+
let success = 0;
|
|
160
|
+
let failed = 0;
|
|
161
|
+
const errors: any[] = [];
|
|
162
|
+
|
|
163
|
+
// 分批处理SQL语句
|
|
164
|
+
for (let i = 0; i < sqlStatements.length; i += batchSize) {
|
|
165
|
+
const batch = sqlStatements.slice(i, i + batchSize);
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
if (useTransaction) {
|
|
169
|
+
// 使用事务执行批次
|
|
170
|
+
await dataSource.transaction(async (manager) => {
|
|
171
|
+
for (const statement of batch) {
|
|
172
|
+
try {
|
|
173
|
+
await manager.query(statement);
|
|
174
|
+
success++;
|
|
175
|
+
} catch (error) {
|
|
176
|
+
failed++;
|
|
177
|
+
errors.push({ statement, error: error.message });
|
|
178
|
+
if (!continueOnError) {
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
} else {
|
|
185
|
+
// 非事务执行批次
|
|
186
|
+
for (const statement of batch) {
|
|
187
|
+
try {
|
|
188
|
+
await dataSource.query(statement);
|
|
189
|
+
success++;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
failed++;
|
|
192
|
+
errors.push({ statement, error: error.message });
|
|
193
|
+
if (!continueOnError) {
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
} catch (batchError) {
|
|
200
|
+
console.error(`批次执行失败 (${i}-${i + batchSize}):`, batchError);
|
|
201
|
+
if (!continueOnError) {
|
|
202
|
+
throw new Error(`批次执行失败: ${batchError.message}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return { success, failed, errors };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 执行文件中的SQL(支持大文件)
|
|
212
|
+
*/
|
|
213
|
+
async executeSqlFile(
|
|
214
|
+
dataSource: DataSource,
|
|
215
|
+
filePath: string,
|
|
216
|
+
options?: {
|
|
217
|
+
batchSize?: number;
|
|
218
|
+
useTransaction?: boolean;
|
|
219
|
+
continueOnError?: boolean;
|
|
220
|
+
}
|
|
221
|
+
): Promise<{ success: number; failed: number; errors: any[] }> {
|
|
222
|
+
const fs = require('fs');
|
|
223
|
+
const sqlContent = fs.readFileSync(filePath, 'utf8');
|
|
224
|
+
|
|
225
|
+
// 分割SQL语句
|
|
226
|
+
const sqlStatements = sqlContent
|
|
227
|
+
.split(';')
|
|
228
|
+
.map(statement => statement.trim())
|
|
229
|
+
.filter(statement => statement.length > 0);
|
|
230
|
+
|
|
231
|
+
return this.executeBatchQuery(dataSource, sqlStatements, options);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* 通用方法:测试连接
|
|
236
|
+
*/
|
|
237
|
+
async testConnection(dataSource: DataSource): Promise<boolean> {
|
|
238
|
+
try {
|
|
239
|
+
await dataSource.query('SELECT 1');
|
|
240
|
+
return true;
|
|
241
|
+
} catch (error) {
|
|
242
|
+
//this.ctx.logger.error('数据库连接测试失败:', error);
|
|
243
|
+
console.error(error);
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 通用方法:给标识符加引号
|
|
250
|
+
*/
|
|
251
|
+
public quoteIdentifier(identifier: string): string {
|
|
252
|
+
return `"${identifier}"`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 通用方法:构建分页查询
|
|
257
|
+
*/
|
|
258
|
+
protected buildPaginationQuery(baseQuery: string, page: number, pageSize: number): string {
|
|
259
|
+
const offset = (page - 1) * pageSize;
|
|
260
|
+
return `${baseQuery} LIMIT ${pageSize} OFFSET ${offset}`;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* 通用方法:构建计数查询
|
|
265
|
+
*/
|
|
266
|
+
protected buildCountQuery(baseQuery: string): string {
|
|
267
|
+
return `SELECT COUNT(*) as total FROM (${baseQuery}) as count_query`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* 获取视图列表 - 子类实现(如果支持)
|
|
272
|
+
*/
|
|
273
|
+
async getViews(dataSource: DataSource, database: string): Promise<any[]> {
|
|
274
|
+
// 默认实现,子类可以重写
|
|
275
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持视图`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* 获取视图定义 - 子类实现(如果支持)
|
|
280
|
+
*/
|
|
281
|
+
async getViewDefinition(dataSource: DataSource, database: string, viewName: string): Promise<string> {
|
|
282
|
+
// 默认实现,子类可以重写
|
|
283
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持视图`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* 获取存储过程列表 - 子类实现(如果支持)
|
|
288
|
+
*/
|
|
289
|
+
async getProcedures(dataSource: DataSource, database: string): Promise<any[]> {
|
|
290
|
+
// 默认实现,子类可以重写
|
|
291
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持存储过程`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* 获取存储过程定义 - 子类实现(如果支持)
|
|
296
|
+
*/
|
|
297
|
+
async getProcedureDefinition(dataSource: DataSource, database: string, procedureName: string): Promise<string> {
|
|
298
|
+
// 默认实现,子类可以重写
|
|
299
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持存储过程`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* 导出数据库架构 - 子类实现
|
|
304
|
+
*/
|
|
305
|
+
abstract exportSchema(dataSource: DataSource, database: string): Promise<string>;
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* 查看数据库日志 - 子类实现(如果支持)
|
|
309
|
+
*/
|
|
310
|
+
abstract viewLogs(dataSource: DataSource, database?: string, limit?: number): Promise<any[]>;
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* 创建数据库 - 子类实现(如果支持)
|
|
314
|
+
*/
|
|
315
|
+
async createDatabase(dataSource: DataSource, databaseName: string, options?: any): Promise<void> {
|
|
316
|
+
// 默认实现,子类可以重写
|
|
317
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持创建数据库`);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* 删除数据库 - 子类实现(如果支持)
|
|
322
|
+
*/
|
|
323
|
+
async dropDatabase(dataSource: DataSource, databaseName: string): Promise<void> {
|
|
324
|
+
// 默认实现,子类可以重写
|
|
325
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持删除数据库`);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* 备份数据库 - 子类实现(如果支持)
|
|
330
|
+
*/
|
|
331
|
+
async backupDatabase(dataSource: DataSource, databaseName: string, options?: any): Promise<string> {
|
|
332
|
+
// 默认实现,子类可以重写
|
|
333
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持备份数据库`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 恢复数据库 - 子类实现(如果支持)
|
|
338
|
+
*/
|
|
339
|
+
async restoreDatabase(dataSource: DataSource, databaseName: string, filePath: string, options?: any): Promise<void> {
|
|
340
|
+
// 默认实现,子类可以重写
|
|
341
|
+
throw new Error(`数据库类型 ${this.getDatabaseType()} 不支持恢复数据库`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* 导出表数据到 SQL 文件 - 子类实现
|
|
346
|
+
*/
|
|
347
|
+
abstract exportTableDataToSQL(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* 导出表数据到 CSV 文件 - 子类实现
|
|
351
|
+
*/
|
|
352
|
+
abstract exportTableDataToCSV(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* 导出表数据到 JSON 文件 - 子类实现
|
|
356
|
+
*/
|
|
357
|
+
abstract exportTableDataToJSON(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* 导出表数据到 Excel 文件 - 子类实现
|
|
361
|
+
*/
|
|
362
|
+
abstract exportTableDataToExcel(dataSource: DataSource, databaseName: string, tableName: string, options?: any): Promise<string>;
|
|
363
|
+
}
|