feat: suport table column fixed

This commit is contained in:
katherinehhh
2025-10-11 20:39:07 +08:00
parent f0132b7bf0
commit 330a40dfe3
11 changed files with 120 additions and 49 deletions
@@ -0,0 +1,36 @@
/**
* 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 { defineAction, FlowModel } from '@nocobase/flow-engine';
import { tval } from '@nocobase/utils/client';
export const fixed = defineAction({
title: tval('Fixed'),
name: 'fixed',
uiSchema: (ctx) => {
const t = ctx.t;
return {
fixed: {
'x-component': 'Select',
'x-decorator': 'FormItem',
enum: [
{ label: t('Not fixed'), value: 'none' },
{ label: t('Left fixed'), value: 'left' },
{ label: t('Right fixed'), value: 'right' },
],
},
};
},
defaultParams: {
fixed: 'none',
},
handler(ctx, params) {
ctx.model.setProps('fixed', params.fixed);
},
});
@@ -22,6 +22,7 @@ export * from './fieldComponent';
export * from './aclCheck';
export * from './pattern';
export * from './validation';
export * from './columnFixed';
export {
fieldLinkageRules,
detailsFieldLinkageRules,
@@ -338,7 +338,6 @@ export class CollectionBlockModel<T = DefaultStructure> extends DataBlockModel<T
}
addAppends(fieldPath: string, refresh = false) {
console.log(fieldPath);
if (!fieldPath) {
return;
}
@@ -367,7 +366,6 @@ export class CollectionBlockModel<T = DefaultStructure> extends DataBlockModel<T
return;
}
if (field.isAssociationField()) {
console.log(field.name);
(this.resource as BaseRecordResource).addAppends(field.name);
if (refresh) {
this.resource.refresh();
@@ -32,8 +32,7 @@ import React, { useRef } from 'react';
import { ActionModel, BlockSceneEnum, CollectionBlockModel } from '../../base';
import { QuickEditFormModel } from '../form/QuickEditFormModel';
import { TableColumnModel } from './TableColumnModel';
import { TableCustomColumnModel } from './TableCustomColumnModel';
import { extractIndex } from './utils';
import { extractIndex, adjustColumnOrder } from './utils';
type TableBlockModelStructure = {
subModels: {
@@ -174,8 +173,7 @@ export class TableBlockModel extends CollectionBlockModel<TableBlockModelStructu
title: <AddFieldColumn model={this} />,
} as any);
}
return cols;
return adjustColumnOrder(cols);
}
EditableRow = (props) => {
@@ -396,5 +396,9 @@ TableColumnModel.registerFlow({
});
},
},
fixed: {
title: escapeT('Fixed'),
use: 'fixed',
},
},
});
@@ -70,6 +70,10 @@ TableCustomColumnModel.registerFlow({
ctx.model.setProps('width', params.width);
},
},
fixed: {
title: escapeT('Fixed'),
use: 'fixed',
},
},
});
@@ -16,3 +16,21 @@ export function extractIndex(str) {
});
return numbers.join('.');
}
export function adjustColumnOrder(columns) {
const leftFixedColumns = [];
const normalColumns = [];
const rightFixedColumns = [];
columns.forEach((column) => {
if (column.fixed === 'left') {
leftFixedColumns.push(column);
} else if (column.fixed === 'right') {
rightFixedColumns.push(column);
} else {
normalColumns.push(column);
}
});
return [...leftFixedColumns, ...normalColumns, ...rightFixedColumns];
}
@@ -447,6 +447,10 @@ SubTableColumnModel.registerFlow({
title: escapeT('Display mode'),
use: 'pattern',
},
fixed: {
title: escapeT('Fixed'),
use: 'fixed',
},
},
});
@@ -17,11 +17,12 @@ import {
useFlowEngine,
} from '@nocobase/flow-engine';
import React from 'react';
import { EditFormModel, FormItemModel } from '../../../blocks/form';
import { FormItemModel } from '../../../blocks/form';
import { AssociationFieldModel } from '../AssociationFieldModel';
import { RecordPickerContent } from '../RecordPickerFieldModel';
import { SubTableColumnModel } from './SubTableColumnModel';
import { SubTableField } from './SubTableField';
import { adjustColumnOrder } from '../../../blocks/table/utils';
const AddFieldColumn = ({ model }) => {
return (
@@ -67,26 +68,28 @@ export class SubTableFieldModel extends AssociationFieldModel {
Boolean,
);
return [
enableIndexColumn && {
key: '__index__',
width: 48,
align: 'center',
fixed: 'left',
render: (props) => {
return props.rowIdx + 1;
return adjustColumnOrder(
[
enableIndexColumn && {
key: '__index__',
width: 48,
align: 'center',
fixed: 'left',
render: (props) => {
return props.rowIdx + 1;
},
},
},
...baseColumns.concat({
key: '_empty',
}),
isConfigMode && {
key: 'addColumn',
fixed: 'right',
width: 100,
title: <AddFieldColumn model={this} />,
},
].filter(Boolean) as any;
...baseColumns.concat({
key: '_empty',
}),
isConfigMode && {
key: 'addColumn',
fixed: 'right',
width: 100,
title: <AddFieldColumn model={this} />,
},
].filter(Boolean),
) as any;
}
render() {
@@ -13,6 +13,7 @@ import { Table } from 'antd';
import React from 'react';
import { FieldModel } from '../../base';
import { DetailsItemModel } from '../../blocks/details/DetailsItemModel';
import { adjustColumnOrder } from '../../blocks/table/utils';
const AddFieldColumn = ({ model }) => {
return (
@@ -60,26 +61,28 @@ export class DisplaySubTableFieldModel extends FieldModel {
return !v.hidden;
});
return [
enableIndexColumn && {
key: '__index__',
width: 48,
align: 'center',
fixed: 'left',
render: (props, record, index) => {
return index + 1;
return adjustColumnOrder(
[
enableIndexColumn && {
key: '__index__',
width: 48,
align: 'center',
fixed: 'left',
render: (props, record, index) => {
return index + 1;
},
},
},
...baseColumns.concat({
key: 'empty',
}),
{
key: 'addColumn',
fixed: 'right',
width: 100,
title: <AddFieldColumn model={this} />,
},
].filter(Boolean) as any;
...baseColumns.concat({
key: 'empty',
}),
{
key: 'addColumn',
fixed: 'right',
width: 100,
title: <AddFieldColumn model={this} />,
},
].filter(Boolean),
) as any;
}
public render() {
return (
@@ -230,11 +230,13 @@ const Preview = (props) => {
};
export class DisplayPreviewFieldModel extends FieldModel {
render(): any {
const { value, titleField } = this.props;
if (titleField && this.context.collectionField?.targetCollection?.template !== 'file') {
const { value, titleField, target } = this.props;
if (titleField && target !== 'file') {
return castArray(value).flatMap((v, idx) => {
const content = v?.[titleField] ? (
<Preview key={idx} {...this.props} value={castArray(v?.[titleField])} />
const res = v?.[titleField];
const result = typeof res === 'object' ? res : v;
const content = result ? (
<Preview key={idx} {...this.props} value={castArray(result)} />
) : (
<span key={idx}>N/A</span>
);