fix: table

This commit is contained in:
chenos 2025-06-29 19:22:54 +08:00
parent 97186d72ce
commit a10b2868f4
2 changed files with 58 additions and 24 deletions

View File

@ -18,10 +18,10 @@ import {
FlowsFloatContextMenu, FlowsFloatContextMenu,
MultiRecordResource, MultiRecordResource,
} from '@nocobase/flow-engine'; } from '@nocobase/flow-engine';
import { tval } from '@nocobase/utils/client';
import { Button, Card, Pagination, Skeleton, Space } from 'antd'; import { Button, Card, Pagination, Skeleton, Space } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React from 'react'; import React from 'react';
import { tval } from '@nocobase/utils/client';
import { ColumnDefinition, TabulatorFull as Tabulator } from 'tabulator-tables'; import { ColumnDefinition, TabulatorFull as Tabulator } from 'tabulator-tables';
import { ActionModel } from '../../base/ActionModel'; import { ActionModel } from '../../base/ActionModel';
import { DataBlockModel } from '../../base/BlockModel'; import { DataBlockModel } from '../../base/BlockModel';
@ -77,13 +77,22 @@ TabulatorColumnModel.registerFlow({
steps: { steps: {
step1: { step1: {
async handler(ctx, params) { async handler(ctx, params) {
if (!params.fieldPath) { if (!params.dataSourceKey || !params.collectionName || !params.fieldPath) {
return; throw new Error('dataSourceKey, collectionName and fieldPath are required parameters');
}
if (!ctx.shared.currentBlockModel) {
throw new Error('Current block model is not set in shared context');
} }
if (ctx.model.collectionField) { if (ctx.model.collectionField) {
return; return;
} }
const field = ctx.globals.dataSourceManager.getCollectionField(params.fieldPath); const { dataSourceKey, collectionName, fieldPath } = params;
const field = ctx.globals.dataSourceManager.getCollectionField(
`${dataSourceKey}.${collectionName}.${fieldPath}`,
);
if (!field) {
throw new Error(`Collection field not found: ${dataSourceKey}.${collectionName}.${fieldPath}`);
}
ctx.model.collectionField = field; ctx.model.collectionField = field;
ctx.model.fieldPath = params.fieldPath; ctx.model.fieldPath = params.fieldPath;
ctx.model.setProps('title', field.title); ctx.model.setProps('title', field.title);
@ -100,13 +109,7 @@ const Columns = observer<any>(({ record, model, index }) => {
{model.mapSubModels('actions', (action: ActionModel) => { {model.mapSubModels('actions', (action: ActionModel) => {
const fork = action.createFork({}, `${index}`); const fork = action.createFork({}, `${index}`);
return ( return (
<FlowModelRenderer <FlowModelRenderer fallback={<Skeleton.Button size="small" />} showFlowSettings key={fork.uid} model={fork} />
fallback={<Skeleton.Button size="small" />}
showFlowSettings
key={fork.uid}
model={fork}
extraContext={{ currentRecord: record }}
/>
); );
})} })}
</Space> </Space>
@ -170,8 +173,8 @@ export class TabulatorModel extends DataBlockModel<S> {
stepParams: { stepParams: {
default: { default: {
step1: { step1: {
collectionName: this.collection.name,
dataSourceKey: this.collection.dataSourceKey, dataSourceKey: this.collection.dataSourceKey,
collectionName: this.collection.name,
fieldPath, fieldPath,
}, },
}, },
@ -179,12 +182,12 @@ export class TabulatorModel extends DataBlockModel<S> {
subModels: { subModels: {
field: { field: {
// @ts-ignore // @ts-ignore
use: defaultOptions.use, use: defaultOptions.use as any,
stepParams: { stepParams: {
default: { default: {
step1: { step1: {
collectionName: this.collection.name,
dataSourceKey: this.collection.dataSourceKey, dataSourceKey: this.collection.dataSourceKey,
collectionName: this.collection.name,
fieldPath, fieldPath,
}, },
}, },
@ -202,8 +205,10 @@ export class TabulatorModel extends DataBlockModel<S> {
}, },
]} ]}
onModelCreated={async (model: TabulatorColumnModel) => { onModelCreated={async (model: TabulatorColumnModel) => {
model.setSharedContext({ currentBlockModel: this });
await model.applyAutoFlows(); await model.applyAutoFlows();
}}
onSubModelAdded={async (model: TabulatorColumnModel) => {
this.addAppends(model.fieldPath, true);
this.initTabulator(); this.initTabulator();
}} }}
/>, />,
@ -224,7 +229,7 @@ export class TabulatorModel extends DataBlockModel<S> {
}); });
this.tabulator = new Tabulator(this.tabulatorRef.current, { this.tabulator = new Tabulator(this.tabulatorRef.current, {
layout: 'fitColumns', // fit columns to width of table (optional) layout: 'fitColumns', // fit columns to width of table (optional)
// height: '75vh', height: '75vh',
renderHorizontal: 'virtual', renderHorizontal: 'virtual',
movableColumns: true, movableColumns: true,
movableRows: true, movableRows: true,
@ -256,14 +261,14 @@ export class TabulatorModel extends DataBlockModel<S> {
render() { render() {
return ( return (
<Card> <Card>
<Space style={{ marginBottom: 16 }}> {/* <Space style={{ marginBottom: 16 }}>
{this.mapSubModels('actions', (action) => ( {this.mapSubModels('actions', (action) => (
<FlowModelRenderer model={action} showFlowSettings sharedContext={{ currentBlockModel: this }} /> <FlowModelRenderer model={action} showFlowSettings sharedContext={{ currentBlockModel: this }} />
))} ))}
<AddActionButton model={this} subModelBaseClass="GlobalActionModel" subModelKey="actions"> <AddActionButton model={this} subModelBaseClass="GlobalActionModel" subModelKey="actions">
<Button icon={<SettingOutlined />}>{this.translate('Configure actions')}</Button> <Button icon={<SettingOutlined />}>{this.translate('Configure actions')}</Button>
</AddActionButton> </AddActionButton>
</Space> </Space> */}
<div ref={this.tabulatorRef} /> <div ref={this.tabulatorRef} />
<Pagination <Pagination
style={{ marginTop: 16 }} style={{ marginTop: 16 }}
@ -323,7 +328,7 @@ TabulatorModel.registerFlow({
resource.setPageSize(20); resource.setPageSize(20);
ctx.model.resource = resource; ctx.model.resource = resource;
await ctx.model.applySubModelsAutoFlows('columns', null, { currentBlockModel: ctx.model }); await ctx.model.applySubModelsAutoFlows('columns', null, { currentBlockModel: ctx.model });
await resource.refresh(); // await resource.refresh();
resource.on('refresh', async () => { resource.on('refresh', async () => {
if (ctx.model.tabulator) { if (ctx.model.tabulator) {
ctx.model.initTabulator(); ctx.model.initTabulator();
@ -332,6 +337,29 @@ TabulatorModel.registerFlow({
}); });
}, },
}, },
editPageSize: {
title: tval('Edit page size'),
uiSchema: {
pageSize: {
'x-component': 'Select',
'x-decorator': 'FormItem',
enum: [
{ label: '10', value: 10 },
{ label: '20', value: 20 },
{ label: '50', value: 50 },
{ label: '100', value: 100 },
{ label: '200', value: 200 },
],
},
},
defaultParams: {
pageSize: 20,
},
handler(ctx, params) {
ctx.model.resource.loading = true;
ctx.model.resource.setPageSize(params.pageSize);
},
},
step2: { step2: {
handler(ctx, params) { handler(ctx, params) {
ctx.reactView.onRefReady(ctx.model.tabulatorRef, (el) => { ctx.reactView.onRefReady(ctx.model.tabulatorRef, (el) => {
@ -339,6 +367,11 @@ TabulatorModel.registerFlow({
}); });
}, },
}, },
refresh: {
async handler(ctx, params) {
await ctx.model.resource.refresh();
},
},
}, },
}); });
@ -346,7 +379,7 @@ TabulatorModel.define({
title: tval('Tabulator'), title: tval('Tabulator'),
group: tval('Content'), group: tval('Content'),
requiresDataSource: true, requiresDataSource: true,
hide: true, // hide: true,
defaultOptions: { defaultOptions: {
use: 'TabulatorModel', use: 'TabulatorModel',
}, },

View File

@ -7,10 +7,11 @@
* For more information, please refer to: https://www.nocobase.com/agreement. * For more information, please refer to: https://www.nocobase.com/agreement.
*/ */
import { Dropdown, DropdownProps, Input, Spin, Empty, InputProps } from 'antd';
import React, { useEffect, useState, useMemo, useRef, FC } from 'react';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { Dropdown, DropdownProps, Empty, Input, InputProps, Spin } from 'antd';
import React, { FC, useEffect, useMemo, useRef, useState } from 'react';
import { useFlowModel } from '../../hooks'; import { useFlowModel } from '../../hooks';
import { useFlowEngine } from '../../provider';
// ==================== Types ==================== // ==================== Types ====================
@ -257,13 +258,13 @@ const createEmptyItem = (itemKey: string, t: (key: string) => string) => ({
// ==================== Main Component ==================== // ==================== Main Component ====================
const LazyDropdown: React.FC<Omit<DropdownProps, 'menu'> & { menu: LazyDropdownMenuProps }> = ({ menu, ...props }) => { const LazyDropdown: React.FC<Omit<DropdownProps, 'menu'> & { menu: LazyDropdownMenuProps }> = ({ menu, ...props }) => {
const model = useFlowModel(); const engine = useFlowEngine();
const [menuVisible, setMenuVisible] = useState(false); const [menuVisible, setMenuVisible] = useState(false);
const [openKeys, setOpenKeys] = useState<Set<string>>(new Set()); const [openKeys, setOpenKeys] = useState<Set<string>>(new Set());
const [rootItems, setRootItems] = useState<Item[]>([]); const [rootItems, setRootItems] = useState<Item[]>([]);
const [rootLoading, setRootLoading] = useState(false); const [rootLoading, setRootLoading] = useState(false);
const dropdownMaxHeight = useNiceDropdownMaxHeight(); const dropdownMaxHeight = useNiceDropdownMaxHeight();
const t = model.translate; const t = engine.translate.bind(engine);
// 使用自定义 hooks // 使用自定义 hooks
const { loadedChildren, loadingKeys, handleLoadChildren } = useAsyncMenuItems(menuVisible, rootItems); const { loadedChildren, loadingKeys, handleLoadChildren } = useAsyncMenuItems(menuVisible, rootItems);