mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-04 21:08:55 +08:00
公用代码,解决因为不一致导致的嵌套+固定列用法的样式错乱问题
This commit is contained in:
parent
164b2d7840
commit
a7d2bbc920
196
src/renderers/Table/TableBody.tsx
Normal file
196
src/renderers/Table/TableBody.tsx
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {ClassNamesFn} from '../../theme';
|
||||||
|
import {IColumn, IRow} from '../../store/table';
|
||||||
|
import {SchemaNode, Action} from '../../types';
|
||||||
|
import {TableRow} from './TableRow';
|
||||||
|
import {filter} from '../../utils/tpl';
|
||||||
|
import {observer} from 'mobx-react';
|
||||||
|
import {trace, reaction} from 'mobx';
|
||||||
|
import {flattenTree} from '../../utils/helper';
|
||||||
|
|
||||||
|
export interface TableBodyProps {
|
||||||
|
className?: string;
|
||||||
|
rowsProps?: any;
|
||||||
|
tableClassName?: string;
|
||||||
|
classnames: ClassNamesFn;
|
||||||
|
columns: Array<IColumn>;
|
||||||
|
rows: Array<IRow>;
|
||||||
|
placeholder?: string;
|
||||||
|
render: (region: string, node: SchemaNode, props?: any) => JSX.Element;
|
||||||
|
renderCell: (
|
||||||
|
region: string,
|
||||||
|
column: IColumn,
|
||||||
|
item: IRow,
|
||||||
|
props: any
|
||||||
|
) => React.ReactNode;
|
||||||
|
onCheck: (item: IRow) => void;
|
||||||
|
onQuickChange?: (
|
||||||
|
item: IRow,
|
||||||
|
values: object,
|
||||||
|
saveImmediately?: boolean | any,
|
||||||
|
savePristine?: boolean
|
||||||
|
) => void;
|
||||||
|
footable?: boolean;
|
||||||
|
footableColumns: Array<IColumn>;
|
||||||
|
checkOnItemClick?: boolean;
|
||||||
|
buildItemProps?: (item: IRow, index: number) => any;
|
||||||
|
onAction?: (e: React.UIEvent<any>, action: Action, ctx: object) => void;
|
||||||
|
rowClassNameExpr?: string;
|
||||||
|
rowClassName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TableBody extends React.Component<TableBodyProps> {
|
||||||
|
reaction?: () => void;
|
||||||
|
constructor(props: TableBodyProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
const rows = props.rows;
|
||||||
|
|
||||||
|
this.reaction = reaction(
|
||||||
|
() =>
|
||||||
|
`${flattenTree(rows)
|
||||||
|
.map(item => `${item.id}`)
|
||||||
|
.join(',')}${rows
|
||||||
|
.filter(item => item.checked)
|
||||||
|
.map(item => item.id)
|
||||||
|
.join(',')}`,
|
||||||
|
() => this.forceUpdate(),
|
||||||
|
{
|
||||||
|
onError: () => this.reaction!()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps: TableBodyProps) {
|
||||||
|
const props = this.props;
|
||||||
|
|
||||||
|
if (
|
||||||
|
props.columns !== nextProps.columns ||
|
||||||
|
props.buildItemProps !== nextProps.buildItemProps
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentwillUnmount() {
|
||||||
|
this.reaction?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRows(
|
||||||
|
rows: Array<any>,
|
||||||
|
columns = this.props.columns,
|
||||||
|
rowProps: any = {}
|
||||||
|
): any {
|
||||||
|
const {
|
||||||
|
rowClassName,
|
||||||
|
rowClassNameExpr,
|
||||||
|
onAction,
|
||||||
|
buildItemProps,
|
||||||
|
checkOnItemClick,
|
||||||
|
classnames: cx,
|
||||||
|
render,
|
||||||
|
renderCell,
|
||||||
|
onCheck,
|
||||||
|
onQuickChange,
|
||||||
|
footable,
|
||||||
|
footableColumns
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return rows.map((item: IRow, rowIndex: number) => {
|
||||||
|
const itemProps = buildItemProps ? buildItemProps(item, rowIndex) : null;
|
||||||
|
|
||||||
|
const doms = [
|
||||||
|
<TableRow
|
||||||
|
{...itemProps}
|
||||||
|
classnames={cx}
|
||||||
|
checkOnItemClick={checkOnItemClick}
|
||||||
|
key={item.id}
|
||||||
|
itemIndex={rowIndex}
|
||||||
|
item={item}
|
||||||
|
itemClassName={cx(
|
||||||
|
rowClassNameExpr
|
||||||
|
? filter(rowClassNameExpr, item.data)
|
||||||
|
: rowClassName,
|
||||||
|
{
|
||||||
|
'is-last': item.depth > 1 && rowIndex === rows.length - 1
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
columns={columns}
|
||||||
|
renderCell={renderCell}
|
||||||
|
render={render}
|
||||||
|
onAction={onAction}
|
||||||
|
onCheck={onCheck}
|
||||||
|
// todo 先注释 quickEditEnabled={item.depth === 1}
|
||||||
|
onQuickChange={onQuickChange}
|
||||||
|
{...rowProps}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
|
||||||
|
if (footable && footableColumns.length) {
|
||||||
|
if (item.depth === 1) {
|
||||||
|
doms.push(
|
||||||
|
<TableRow
|
||||||
|
{...itemProps}
|
||||||
|
classnames={cx}
|
||||||
|
checkOnItemClick={checkOnItemClick}
|
||||||
|
key={`foot-${item.id}`}
|
||||||
|
itemIndex={rowIndex}
|
||||||
|
item={item}
|
||||||
|
itemClassName={cx(
|
||||||
|
rowClassNameExpr
|
||||||
|
? filter(rowClassNameExpr, item.data)
|
||||||
|
: rowClassName
|
||||||
|
)}
|
||||||
|
columns={footableColumns}
|
||||||
|
renderCell={renderCell}
|
||||||
|
render={render}
|
||||||
|
onAction={onAction}
|
||||||
|
onCheck={onCheck}
|
||||||
|
footableMode
|
||||||
|
footableColSpan={columns.length}
|
||||||
|
onQuickChange={onQuickChange}
|
||||||
|
{...rowProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (item.children.length) {
|
||||||
|
// 嵌套表格
|
||||||
|
doms.push(
|
||||||
|
...this.renderRows(item.children, columns, {
|
||||||
|
...rowProps,
|
||||||
|
parent: item
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return doms;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
placeholder,
|
||||||
|
classnames: cx,
|
||||||
|
className,
|
||||||
|
render,
|
||||||
|
rows,
|
||||||
|
columns,
|
||||||
|
rowsProps
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tbody className={className}>
|
||||||
|
{rows.length ? (
|
||||||
|
this.renderRows(rows, columns, rowsProps)
|
||||||
|
) : (
|
||||||
|
<tr className={cx('Table-placeholder')}>
|
||||||
|
<td colSpan={columns.length}>
|
||||||
|
{render('placeholder', placeholder || '暂无数据')}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import {filter} from '../../utils/tpl';
|
|||||||
import {observer} from 'mobx-react';
|
import {observer} from 'mobx-react';
|
||||||
import {trace, reaction} from 'mobx';
|
import {trace, reaction} from 'mobx';
|
||||||
import {flattenTree} from '../../utils/helper';
|
import {flattenTree} from '../../utils/helper';
|
||||||
|
import {TableBody} from './TableBody';
|
||||||
|
|
||||||
export interface TableContentProps {
|
export interface TableContentProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -52,22 +53,6 @@ export class TableContent extends React.Component<TableContentProps> {
|
|||||||
reaction?: () => void;
|
reaction?: () => void;
|
||||||
constructor(props: TableContentProps) {
|
constructor(props: TableContentProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const rows = props.rows;
|
|
||||||
|
|
||||||
this.reaction = reaction(
|
|
||||||
() =>
|
|
||||||
`${flattenTree(rows)
|
|
||||||
.map(item => `${item.id}`)
|
|
||||||
.join(',')}${rows
|
|
||||||
.filter(item => item.checked)
|
|
||||||
.map(item => item.id)
|
|
||||||
.join(',')}`,
|
|
||||||
() => this.forceUpdate(),
|
|
||||||
{
|
|
||||||
onError: () => this.reaction!()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: TableContentProps) {
|
shouldComponentUpdate(nextProps: TableContentProps) {
|
||||||
@ -83,100 +68,6 @@ export class TableContent extends React.Component<TableContentProps> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentwillUnmount() {
|
|
||||||
this.reaction?.();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderRows(
|
|
||||||
rows: Array<any>,
|
|
||||||
columns = this.props.columns,
|
|
||||||
rowProps: any = {}
|
|
||||||
): any {
|
|
||||||
const {
|
|
||||||
rowClassName,
|
|
||||||
rowClassNameExpr,
|
|
||||||
onAction,
|
|
||||||
buildItemProps,
|
|
||||||
checkOnItemClick,
|
|
||||||
classnames: cx,
|
|
||||||
render,
|
|
||||||
renderCell,
|
|
||||||
onCheck,
|
|
||||||
onQuickChange,
|
|
||||||
footable,
|
|
||||||
footableColumns
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return rows.map((item: IRow, rowIndex: number) => {
|
|
||||||
const itemProps = buildItemProps ? buildItemProps(item, rowIndex) : null;
|
|
||||||
|
|
||||||
const doms = [
|
|
||||||
<TableRow
|
|
||||||
{...itemProps}
|
|
||||||
classnames={cx}
|
|
||||||
checkOnItemClick={checkOnItemClick}
|
|
||||||
key={item.id}
|
|
||||||
itemIndex={rowIndex}
|
|
||||||
item={item}
|
|
||||||
itemClassName={cx(
|
|
||||||
rowClassNameExpr
|
|
||||||
? filter(rowClassNameExpr, item.data)
|
|
||||||
: rowClassName,
|
|
||||||
{
|
|
||||||
'is-last': item.depth > 1 && rowIndex === rows.length - 1
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
columns={columns}
|
|
||||||
renderCell={renderCell}
|
|
||||||
render={render}
|
|
||||||
onAction={onAction}
|
|
||||||
onCheck={onCheck}
|
|
||||||
// todo 先注释 quickEditEnabled={item.depth === 1}
|
|
||||||
onQuickChange={onQuickChange}
|
|
||||||
{...rowProps}
|
|
||||||
/>
|
|
||||||
];
|
|
||||||
|
|
||||||
if (footable && footableColumns.length) {
|
|
||||||
if (item.depth === 1) {
|
|
||||||
doms.push(
|
|
||||||
<TableRow
|
|
||||||
{...itemProps}
|
|
||||||
classnames={cx}
|
|
||||||
checkOnItemClick={checkOnItemClick}
|
|
||||||
key={`foot-${item.id}`}
|
|
||||||
itemIndex={rowIndex}
|
|
||||||
item={item}
|
|
||||||
itemClassName={cx(
|
|
||||||
rowClassNameExpr
|
|
||||||
? filter(rowClassNameExpr, item.data)
|
|
||||||
: rowClassName
|
|
||||||
)}
|
|
||||||
columns={footableColumns}
|
|
||||||
renderCell={renderCell}
|
|
||||||
render={render}
|
|
||||||
onAction={onAction}
|
|
||||||
onCheck={onCheck}
|
|
||||||
footableMode
|
|
||||||
footableColSpan={columns.length}
|
|
||||||
onQuickChange={onQuickChange}
|
|
||||||
{...rowProps}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (item.children.length) {
|
|
||||||
// 嵌套表格
|
|
||||||
doms.push(
|
|
||||||
...this.renderRows(item.children, columns, {
|
|
||||||
...rowProps,
|
|
||||||
parent: item
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return doms;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
placeholder,
|
placeholder,
|
||||||
@ -189,7 +80,17 @@ export class TableContent extends React.Component<TableContentProps> {
|
|||||||
onScroll,
|
onScroll,
|
||||||
tableRef,
|
tableRef,
|
||||||
rows,
|
rows,
|
||||||
renderHeadCell
|
renderHeadCell,
|
||||||
|
renderCell,
|
||||||
|
onCheck,
|
||||||
|
rowClassName,
|
||||||
|
onQuickChange,
|
||||||
|
footable,
|
||||||
|
footableColumns,
|
||||||
|
checkOnItemClick,
|
||||||
|
buildItemProps,
|
||||||
|
onAction,
|
||||||
|
rowClassNameExpr
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const tableClassName = cx('Table-table', this.props.tableClassName);
|
const tableClassName = cx('Table-table', this.props.tableClassName);
|
||||||
@ -225,17 +126,23 @@ export class TableContent extends React.Component<TableContentProps> {
|
|||||||
)}
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<TableBody
|
||||||
{rows.length ? (
|
classnames={cx}
|
||||||
this.renderRows(rows, columns)
|
placeholder={placeholder}
|
||||||
) : (
|
render={render}
|
||||||
<tr className={cx('Table-placeholder')}>
|
renderCell={renderCell}
|
||||||
<td colSpan={columns.length}>
|
onCheck={onCheck}
|
||||||
{render('placeholder', placeholder || '暂无数据')}
|
onQuickChange={onQuickChange}
|
||||||
</td>
|
footable={footable}
|
||||||
</tr>
|
footableColumns={footableColumns}
|
||||||
)}
|
checkOnItemClick={checkOnItemClick}
|
||||||
</tbody>
|
buildItemProps={buildItemProps}
|
||||||
|
onAction={onAction}
|
||||||
|
rowClassNameExpr={rowClassNameExpr}
|
||||||
|
rowClassName={rowClassName}
|
||||||
|
rows={rows}
|
||||||
|
columns={columns}
|
||||||
|
></TableBody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -40,6 +40,7 @@ import {SchemaQuickEdit} from '../QuickEdit';
|
|||||||
import {SchemaCopyable} from '../Copyable';
|
import {SchemaCopyable} from '../Copyable';
|
||||||
import {SchemaRemark} from '../Remark';
|
import {SchemaRemark} from '../Remark';
|
||||||
import {toDataURL, getImageDimensions} from '../../utils/image';
|
import {toDataURL, getImageDimensions} from '../../utils/image';
|
||||||
|
import {TableBody} from './TableBody';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表格列,不指定类型时默认为文本类型。
|
* 表格列,不指定类型时默认为文本类型。
|
||||||
@ -1572,7 +1573,17 @@ export default class Table extends React.Component<TableProps, object> {
|
|||||||
headerOnly: boolean = false,
|
headerOnly: boolean = false,
|
||||||
tableClassName: string = ''
|
tableClassName: string = ''
|
||||||
) {
|
) {
|
||||||
const {placeholder, store, classnames: cx, render, data} = this.props;
|
const {
|
||||||
|
placeholder,
|
||||||
|
store,
|
||||||
|
classnames: cx,
|
||||||
|
render,
|
||||||
|
data,
|
||||||
|
checkOnItemClick,
|
||||||
|
buildItemProps,
|
||||||
|
rowClassNameExpr,
|
||||||
|
rowClassName
|
||||||
|
} = this.props;
|
||||||
const hideHeader = store.filteredColumns.every(column => !column.label);
|
const hideHeader = store.filteredColumns.every(column => !column.label);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -1612,9 +1623,27 @@ export default class Table extends React.Component<TableProps, object> {
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
{headerOnly ? null : (
|
{headerOnly ? null : (
|
||||||
<tbody>
|
<TableBody
|
||||||
{rows.length ? (
|
tableClassName={cx(
|
||||||
this.renderRows(rows, columns, {
|
store.combineNum > 0 ? 'Table-table--withCombine' : '',
|
||||||
|
tableClassName
|
||||||
|
)}
|
||||||
|
classnames={cx}
|
||||||
|
placeholder={placeholder}
|
||||||
|
render={render}
|
||||||
|
renderCell={this.renderCell}
|
||||||
|
onCheck={this.handleCheck}
|
||||||
|
onQuickChange={store.dragging ? undefined : this.handleQuickChange}
|
||||||
|
footable={store.footable}
|
||||||
|
footableColumns={store.footableColumns}
|
||||||
|
checkOnItemClick={checkOnItemClick}
|
||||||
|
buildItemProps={buildItemProps}
|
||||||
|
onAction={this.handleAction}
|
||||||
|
rowClassNameExpr={rowClassNameExpr}
|
||||||
|
rowClassName={rowClassName}
|
||||||
|
columns={columns}
|
||||||
|
rows={rows}
|
||||||
|
rowsProps={{
|
||||||
regionPrefix: 'fixed/',
|
regionPrefix: 'fixed/',
|
||||||
renderCell: (
|
renderCell: (
|
||||||
region: string,
|
region: string,
|
||||||
@ -1622,15 +1651,8 @@ export default class Table extends React.Component<TableProps, object> {
|
|||||||
item: IRow,
|
item: IRow,
|
||||||
props: any
|
props: any
|
||||||
) => this.renderCell(region, column, item, props, true)
|
) => this.renderCell(region, column, item, props, true)
|
||||||
})
|
}}
|
||||||
) : (
|
/>
|
||||||
<tr className={cx('Table-placeholder')}>
|
|
||||||
<td colSpan={columns.length}>
|
|
||||||
{render('placeholder', placeholder, {data})}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
)}
|
)}
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
@ -2085,93 +2107,6 @@ export default class Table extends React.Component<TableProps, object> {
|
|||||||
: footerNode || toolbarNode || null;
|
: footerNode || toolbarNode || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRows(
|
|
||||||
rows: Array<any>,
|
|
||||||
columns = this.props.store.filteredColumns,
|
|
||||||
rowProps: any = {}
|
|
||||||
): any {
|
|
||||||
const {
|
|
||||||
store,
|
|
||||||
rowClassName,
|
|
||||||
rowClassNameExpr,
|
|
||||||
onAction,
|
|
||||||
buildItemProps,
|
|
||||||
checkOnItemClick,
|
|
||||||
classPrefix: ns,
|
|
||||||
classnames: cx,
|
|
||||||
render
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return rows.map((item: IRow, rowIndex: number) => {
|
|
||||||
const itemProps = buildItemProps ? buildItemProps(item, rowIndex) : null;
|
|
||||||
|
|
||||||
const doms = [
|
|
||||||
<TableRow
|
|
||||||
{...itemProps}
|
|
||||||
classPrefix={ns}
|
|
||||||
classnames={cx}
|
|
||||||
checkOnItemClick={checkOnItemClick}
|
|
||||||
key={item.id}
|
|
||||||
itemIndex={rowIndex}
|
|
||||||
item={item}
|
|
||||||
itemClassName={cx(
|
|
||||||
rowClassNameExpr
|
|
||||||
? filter(rowClassNameExpr, item.data)
|
|
||||||
: rowClassName,
|
|
||||||
{
|
|
||||||
'is-last': item.depth > 1 && rowIndex === rows.length - 1,
|
|
||||||
'is-expanded': item.expanded,
|
|
||||||
'is-expandable': item.expandable
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
columns={columns}
|
|
||||||
renderCell={this.renderCell}
|
|
||||||
render={render}
|
|
||||||
onAction={onAction}
|
|
||||||
onCheck={this.handleCheck}
|
|
||||||
// todo 先注释 quickEditEnabled={item.depth === 1}
|
|
||||||
onQuickChange={store.dragging ? null : this.handleQuickChange}
|
|
||||||
{...rowProps}
|
|
||||||
/>
|
|
||||||
];
|
|
||||||
|
|
||||||
if (store.footable && store.footableColumns.length) {
|
|
||||||
if (item.depth === 1) {
|
|
||||||
doms.push(
|
|
||||||
<TableRow
|
|
||||||
{...itemProps}
|
|
||||||
classPrefix={ns}
|
|
||||||
classnames={cx}
|
|
||||||
checkOnItemClick={checkOnItemClick}
|
|
||||||
key={`foot-${item.id}`}
|
|
||||||
itemIndex={rowIndex}
|
|
||||||
item={item}
|
|
||||||
itemClassName={cx(
|
|
||||||
rowClassNameExpr
|
|
||||||
? filter(rowClassNameExpr, item.data)
|
|
||||||
: rowClassName
|
|
||||||
)}
|
|
||||||
columns={store.footableColumns}
|
|
||||||
renderCell={this.renderCell}
|
|
||||||
render={render}
|
|
||||||
onAction={onAction}
|
|
||||||
onCheck={this.handleCheck}
|
|
||||||
footableMode
|
|
||||||
footableColSpan={store.filteredColumns.length}
|
|
||||||
onQuickChange={store.dragging ? null : this.handleQuickChange}
|
|
||||||
{...rowProps}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (Array.isArray(item.data.children)) {
|
|
||||||
// 嵌套表格
|
|
||||||
doms.push(...this.renderRows(item.children, columns, rowProps));
|
|
||||||
}
|
|
||||||
|
|
||||||
return doms;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
renderItemActions() {
|
renderItemActions() {
|
||||||
const {itemActions, render, store, classnames: cx} = this.props;
|
const {itemActions, render, store, classnames: cx} = this.props;
|
||||||
const finalActions = Array.isArray(itemActions)
|
const finalActions = Array.isArray(itemActions)
|
||||||
|
Loading…
Reference in New Issue
Block a user