mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-08 06:59:26 +08:00
fix: export with relation repository (#5170)
This commit is contained in:
parent
4fd8122c61
commit
841db6ce9f
@ -55,6 +55,44 @@ export abstract class RelationRepository {
|
|||||||
return this.db.getCollection(this.targetModel.name);
|
return this.db.getCollection(this.targetModel.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract find(options?: FindOptions): Promise<any>;
|
||||||
|
|
||||||
|
async chunk(
|
||||||
|
options: FindOptions & { chunkSize: number; callback: (rows: Model[], options: FindOptions) => Promise<void> },
|
||||||
|
) {
|
||||||
|
const { chunkSize, callback, limit: overallLimit } = options;
|
||||||
|
const transaction = await this.getTransaction(options);
|
||||||
|
|
||||||
|
let offset = 0;
|
||||||
|
let totalProcessed = 0;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
|
// Calculate the limit for the current chunk
|
||||||
|
const currentLimit = overallLimit !== undefined ? Math.min(chunkSize, overallLimit - totalProcessed) : chunkSize;
|
||||||
|
|
||||||
|
const rows = await this.find({
|
||||||
|
...options,
|
||||||
|
limit: currentLimit,
|
||||||
|
offset,
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (rows.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
await callback(rows, options);
|
||||||
|
|
||||||
|
offset += currentLimit;
|
||||||
|
totalProcessed += rows.length;
|
||||||
|
|
||||||
|
if (overallLimit !== undefined && totalProcessed >= overallLimit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
convertTk(options: any) {
|
convertTk(options: any) {
|
||||||
let tk = options;
|
let tk = options;
|
||||||
if (typeof options === 'object' && options['tk']) {
|
if (typeof options === 'object' && options['tk']) {
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
import { createMockServer, MockServer } from '@nocobase/test';
|
||||||
|
import fs from 'fs';
|
||||||
|
import os from 'os';
|
||||||
|
import path from 'path';
|
||||||
|
import XLSX from 'xlsx';
|
||||||
|
|
||||||
|
describe('export action', () => {
|
||||||
|
let app: MockServer;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
app = await createMockServer({
|
||||||
|
plugins: ['nocobase'],
|
||||||
|
acl: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should export with association repository', async () => {
|
||||||
|
await app.db.getRepository('collections').create({
|
||||||
|
values: {
|
||||||
|
name: 'posts',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'comments',
|
||||||
|
type: 'hasMany',
|
||||||
|
target: 'comments',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
context: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.db.getRepository('collections').create({
|
||||||
|
values: {
|
||||||
|
name: 'comments',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'content',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
context: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.db.getRepository('posts').create({
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
title: 'post1',
|
||||||
|
comments: [
|
||||||
|
{
|
||||||
|
content: 'comment1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'post2',
|
||||||
|
comments: [
|
||||||
|
{
|
||||||
|
content: 'comment2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await app
|
||||||
|
.agent()
|
||||||
|
.resource('posts.comments', 1)
|
||||||
|
.export({
|
||||||
|
values: {
|
||||||
|
columns: [{ dataIndex: ['content'], defaultTitle: 'content' }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
|
||||||
|
const buffer = res.body;
|
||||||
|
|
||||||
|
const workbook = XLSX.read(buffer, { type: 'buffer' });
|
||||||
|
const sheetName = workbook.SheetNames[0];
|
||||||
|
const sheet = workbook.Sheets[sheetName];
|
||||||
|
const rows = XLSX.utils.sheet_to_json(sheet);
|
||||||
|
expect(rows.length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
@ -33,6 +33,7 @@ async function exportXlsxAction(ctx: Context, next: Next) {
|
|||||||
const xlsxExporter = new XlsxExporter({
|
const xlsxExporter = new XlsxExporter({
|
||||||
collectionManager: dataSource.collectionManager,
|
collectionManager: dataSource.collectionManager,
|
||||||
collection,
|
collection,
|
||||||
|
repository,
|
||||||
columns,
|
columns,
|
||||||
findOptions: {
|
findOptions: {
|
||||||
filter,
|
filter,
|
||||||
|
@ -29,6 +29,7 @@ type ExportColumn = {
|
|||||||
type ExportOptions = {
|
type ExportOptions = {
|
||||||
collectionManager: ICollectionManager;
|
collectionManager: ICollectionManager;
|
||||||
collection: ICollection;
|
collection: ICollection;
|
||||||
|
repository?: any;
|
||||||
columns: Array<ExportColumn>;
|
columns: Array<ExportColumn>;
|
||||||
findOptions?: FindOptions;
|
findOptions?: FindOptions;
|
||||||
chunkSize?: number;
|
chunkSize?: number;
|
||||||
@ -51,7 +52,7 @@ class XlsxExporter {
|
|||||||
constructor(private options: ExportOptions) {}
|
constructor(private options: ExportOptions) {}
|
||||||
|
|
||||||
async run(ctx?): Promise<XLSX.WorkBook> {
|
async run(ctx?): Promise<XLSX.WorkBook> {
|
||||||
const { collection, columns, chunkSize } = this.options;
|
const { collection, columns, chunkSize, repository } = this.options;
|
||||||
|
|
||||||
const workbook = XLSX.utils.book_new();
|
const workbook = XLSX.utils.book_new();
|
||||||
const worksheet = XLSX.utils.sheet_new();
|
const worksheet = XLSX.utils.sheet_new();
|
||||||
@ -63,7 +64,7 @@ class XlsxExporter {
|
|||||||
|
|
||||||
let startRowNumber = 2;
|
let startRowNumber = 2;
|
||||||
|
|
||||||
await collection.repository.chunk({
|
await (repository || collection.repository).chunk({
|
||||||
...this.getFindOptions(),
|
...this.getFindOptions(),
|
||||||
chunkSize: chunkSize || 200,
|
chunkSize: chunkSize || 200,
|
||||||
callback: async (rows, options) => {
|
callback: async (rows, options) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user