2025-02-23 09:08:06 +08:00

211 lines
6.6 KiB
TypeScript

/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Schema, useFieldSchema, useForm } from '@formily/react';
import {
useActionContext,
useAPIClient,
useBlockRequestContext,
useCollection_deprecated,
useCollectionManager_deprecated,
useCompile,
useDataBlockProps,
useDataBlockResource,
useDataSourceHeaders,
} from '@nocobase/client';
import lodash from 'lodash';
import { saveAs } from 'file-saver';
import { useTranslation } from 'react-i18next';
import { NAMESPACE } from './constants';
import { useImportContext } from './context';
import { ImportStatus } from './ImportModal';
import { useEffect } from 'react';
import { useFields } from './useFields';
import { initImportSettings } from './ImportActionInitializer';
import { useImportActionContext } from './ImportActionContext';
const useImportSchema = () => {
const { fieldSchema: actionSchema } = useActionContext();
const fieldSchema = useFieldSchema();
let schema = actionSchema || fieldSchema;
while (schema && schema['x-action'] !== 'importXlsx') {
schema = schema.parent;
console.log('schema', schema);
}
return { schema };
};
const toArr = (v: any) => {
if (!v || !Array.isArray(v)) {
return [];
}
return v;
};
export const useDownloadXlsxTemplateAction = () => {
const { service, resource } = useBlockRequestContext();
const apiClient = useAPIClient();
const actionSchema = useFieldSchema();
const compile = useCompile();
const { getCollectionJoinField, getCollectionField } = useCollectionManager_deprecated();
const { name, title, getField } = useCollection_deprecated();
const { t } = useTranslation(NAMESPACE);
const { schema: importSchema } = useImportSchema();
return {
async run() {
const { importColumns, explain } = lodash.cloneDeep(
importSchema?.['x-action-settings']?.['importSettings'] ?? {},
);
const columns = toArr(importColumns)
.map((column) => {
const field = getCollectionField(`${name}.${column.dataIndex[0]}`);
if (!field) {
return;
}
column.defaultTitle = compile(field?.uiSchema?.title) || field.name;
if (column.dataIndex.length > 1) {
const subField = getCollectionJoinField(`${name}.${column.dataIndex.join('.')}`);
if (!subField) {
return;
}
column.defaultTitle = column.defaultTitle + '/' + compile(subField?.uiSchema?.title) || subField.name;
}
if (field.interface === 'chinaRegion') {
column.dataIndex.push('name');
}
return column;
})
.filter(Boolean);
const { data } = await resource.downloadXlsxTemplate(
{
values: {
title: compile(title),
explain,
columns: compile(columns),
},
},
{
method: 'post',
responseType: 'blob',
},
);
const blob = new Blob([data], { type: 'application/x-xls' });
saveAs(blob, `${compile(title)}.xlsx`);
},
};
};
export const useImportStartAction = () => {
const { service, resource } = useBlockRequestContext();
const apiClient = useAPIClient();
const actionSchema = useFieldSchema();
const compile = useCompile();
const { getCollectionJoinField, getCollectionField } = useCollectionManager_deprecated();
const { name, title, getField } = useCollection_deprecated();
const { t } = useTranslation(NAMESPACE);
const { schema: importSchema } = useImportSchema();
const form = useForm();
const { setVisible, fieldSchema } = useActionContext();
const { setImportModalVisible, setImportStatus, setImportResult } = useImportContext();
const { upload } = form.values;
const dataBlockProps = useDataBlockProps();
const headers = useDataSourceHeaders(dataBlockProps.dataSource);
const newResource = useDataBlockResource();
useEffect(() => {
form.reset();
}, []);
return {
async run() {
const { importColumns, explain } = lodash.cloneDeep(
importSchema?.['x-action-settings']?.['importSettings'] ?? {},
);
const columns = toArr(importColumns)
.map((column) => {
const field = getCollectionField(`${name}.${column.dataIndex[0]}`);
if (!field) {
return;
}
column.defaultTitle = compile(field?.uiSchema?.title) || field.name;
if (column.dataIndex.length > 1) {
const subField = getCollectionJoinField(`${name}.${column.dataIndex.join('.')}`);
if (!subField) {
return;
}
column.defaultTitle = column.defaultTitle + '/' + compile(subField?.uiSchema?.title) || subField.name;
}
if (field.interface === 'chinaRegion') {
column.dataIndex.push('name');
}
return column;
})
.filter(Boolean);
const formData = new FormData();
const uploadFiles = form.values.upload.map((f) => f.originFileObj);
formData.append('file', uploadFiles[0]);
formData.append('columns', JSON.stringify(columns));
formData.append('explain', explain);
const { triggerWorkflow, identifyDuplicates, uniqueField, duplicateStrategy } = form.values;
if (triggerWorkflow !== undefined) {
formData.append('triggerWorkflow', JSON.stringify(triggerWorkflow));
}
if (identifyDuplicates) {
formData.append(
'duplicateOption',
JSON.stringify({
uniqueField,
mode: duplicateStrategy,
}),
);
}
const importMode = importSchema?.['x-action-settings']?.importMode || 'auto';
setVisible(false);
setImportModalVisible(true);
setImportStatus(ImportStatus.IMPORTING);
try {
const { data } = await (newResource as any).importXlsx(
{
values: formData,
mode: importMode,
},
{
timeout: 10 * 60 * 1000,
},
);
form.reset();
if (!data.data.taskId) {
setImportResult(data);
await service?.refresh?.();
setImportStatus(ImportStatus.IMPORTED);
} else {
setImportModalVisible(false);
setVisible(false);
}
} catch (error) {
setImportModalVisible(false);
setVisible(true);
}
},
disabled: upload?.length === 0 || form.errors?.length > 0,
};
};