From 7ee693589bfc3d884e55dfcc245c3bda8970886d Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 13 Sep 2023 20:52:19 +0800 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20=E4=BC=98=E5=8C=96=20Table=20?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=8D=95=E5=85=83=E6=A0=BC=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/amis/src/renderers/Table/Cell.tsx | 221 ++++++++++++++++++++ packages/amis/src/renderers/Table/index.tsx | 182 ++-------------- 2 files changed, 244 insertions(+), 159 deletions(-) create mode 100644 packages/amis/src/renderers/Table/Cell.tsx diff --git a/packages/amis/src/renderers/Table/Cell.tsx b/packages/amis/src/renderers/Table/Cell.tsx new file mode 100644 index 000000000..1a4bb7f88 --- /dev/null +++ b/packages/amis/src/renderers/Table/Cell.tsx @@ -0,0 +1,221 @@ +import { + IColumn, + IRow, + ITableStore, + PlainObject, + SchemaNode, + ThemeProps, + resolveVariable +} from 'amis-core'; +import {BadgeObject, Checkbox, Icon} from 'amis-ui'; +import React from 'react'; + +export interface CellProps extends ThemeProps { + region: string; + column: IColumn; + item: IRow; + props: PlainObject; + ignoreDrag?: boolean; + render: ( + region: string, + node: SchemaNode, + props?: PlainObject + ) => JSX.Element; + store: ITableStore; + multiple: boolean; + canAccessSuperData?: boolean; + itemBadge?: BadgeObject; + onCheck?: (item: IRow) => void; + onDragStart?: (e: React.DragEvent) => void; + popOverContainer?: any; + quickEditFormRef: any; + onImageEnlarge?: any; +} + +export default function Cell({ + region, + column, + item, + props, + ignoreDrag, + render, + store, + multiple, + itemBadge, + classnames: cx, + classPrefix: ns, + canAccessSuperData, + onCheck, + onDragStart, + popOverContainer, + quickEditFormRef, + onImageEnlarge +}: CellProps) { + if (column.name && item.rowSpans[column.name] === 0) { + return null; + } + + const [style, stickyClassName]: any = React.useMemo(() => { + const style = {...column.pristine.style}; + const [stickyStyle, stickyClassName] = store.getStickyStyles( + column, + store.filteredColumns + ); + return [Object.assign(style, stickyStyle), stickyClassName]; + }, []); + + const onCheckboxChange = React.useCallback(() => { + onCheck?.(item); + }, []); + + if (column.type === '__checkme') { + return ( + + + + ); + } else if (column.type === '__dragme') { + return ( + + {item.draggable ? : null} + + ); + } else if (column.type === '__expandme') { + return ( + + {item.expandable ? ( + + + + ) : null} + + ); + } + + let [prefix, affix, addtionalClassName] = React.useMemo(() => { + let prefix: React.ReactNode[] = []; + let affix: React.ReactNode[] = []; + let addtionalClassName = ''; + + if (column.isPrimary && store.isNested) { + addtionalClassName = 'Table-primayCell'; + prefix.push( + + ); + prefix.push( + item.expandable ? ( + + + + ) : ( + + ) + ); + } + + if ( + !ignoreDrag && + column.isPrimary && + store.isNested && + store.draggable && + item.draggable + ) { + affix.push( + + + + ); + } + return [prefix, affix, addtionalClassName]; + }, [item.expandable, item.expanded]); + const data = React.useMemo(() => item.locals, [JSON.stringify(item.locals)]); + + const finalCanAccessSuperData = + column.pristine.canAccessSuperData ?? canAccessSuperData; + const subProps: any = { + ...props, + // 操作列不下发loading,否则会导致操作栏里面的所有按钮都出现loading + loading: column.type === 'operation' ? false : props.loading, + btnDisabled: store.dragging, + data: data, + value: column.name + ? resolveVariable( + column.name, + finalCanAccessSuperData ? item.locals : item.data + ) + : column.value, + popOverContainer: popOverContainer, + rowSpan: item.rowSpans[column.name as string], + quickEditFormRef: quickEditFormRef, + cellPrefix: prefix, + cellAffix: affix, + onImageEnlarge: onImageEnlarge, + canAccessSuperData: finalCanAccessSuperData, + row: item, + itemBadge, + showBadge: + !props.isHead && + itemBadge && + store.firstToggledColumnIndex === props.colIndex, + onQuery: undefined, + style, + className: cx( + column.pristine.className, + stickyClassName, + addtionalClassName + ), + /** 给子节点的设置默认值,避免取到env.affixHeader的默认值,导致表头覆盖首行 */ + affixOffsetTop: 0 + }; + delete subProps.label; + + return render( + region, + { + ...column.pristine, + column: column.pristine, + type: 'cell' + }, + subProps + ); +} diff --git a/packages/amis/src/renderers/Table/index.tsx b/packages/amis/src/renderers/Table/index.tsx index 2b4370fbe..68d0e4a69 100644 --- a/packages/amis/src/renderers/Table/index.tsx +++ b/packages/amis/src/renderers/Table/index.tsx @@ -69,6 +69,7 @@ import omit from 'lodash/omit'; import ColGroup from './ColGroup'; import debounce from 'lodash/debounce'; import AutoFilterForm from './AutoFilterForm'; +import Cell from './Cell'; /** * 表格列,不指定类型时默认为文本类型。 @@ -2018,168 +2019,31 @@ export default class Table extends React.Component { classnames: cx, checkOnItemClick, popOverContainer, + canAccessSuperData, itemBadge } = this.props; - if (column.name && item.rowSpans[column.name] === 0) { - return null; - } - - const style: any = {...column.pristine.style}; - const [stickyStyle, stickyClassName] = store.getStickyStyles( - column, - store.filteredColumns - ); - Object.assign(style, stickyStyle); - - if (column.type === '__checkme') { - return ( - - - - ); - } else if (column.type === '__dragme') { - return ( - - {item.draggable ? : null} - - ); - } else if (column.type === '__expandme') { - return ( - - {item.expandable ? ( - - - - ) : null} - - ); - } - - let prefix: React.ReactNode[] = []; - let affix: React.ReactNode[] = []; - let addtionalClassName = ''; - - if (column.isPrimary && store.isNested) { - addtionalClassName = 'Table-primayCell'; - prefix.push( - - ); - prefix.push( - item.expandable ? ( - - - - ) : ( - - ) - ); - } - - if ( - !ignoreDrag && - column.isPrimary && - store.isNested && - store.draggable && - item.draggable - ) { - affix.push( - - - - ); - } - - const canAccessSuperData = - column.pristine.canAccessSuperData ?? this.props.canAccessSuperData; - const subProps: any = { - ...props, - // 操作列不下发loading,否则会导致操作栏里面的所有按钮都出现loading - loading: column.type === 'operation' ? false : props.loading, - btnDisabled: store.dragging, - data: item.locals, - value: column.name - ? resolveVariable( - column.name, - canAccessSuperData ? item.locals : item.data - ) - : column.value, - popOverContainer: this.getPopOverContainer, - rowSpan: item.rowSpans[column.name as string], - quickEditFormRef: this.subFormRef, - cellPrefix: prefix, - cellAffix: affix, - onImageEnlarge: this.handleImageEnlarge, - canAccessSuperData, - row: item, - itemBadge, - showBadge: - !props.isHead && - itemBadge && - store.firstToggledColumnIndex === props.colIndex, - onQuery: undefined, - style, - className: cx( - column.pristine.className, - stickyClassName, - addtionalClassName - ), - /** 给子节点的设置默认值,避免取到env.affixHeader的默认值,导致表头覆盖首行 */ - affixOffsetTop: 0 - }; - delete subProps.label; - - return render( - region, - { - ...column.pristine, - column: column.pristine, - type: 'cell' - }, - subProps + return ( + ); } From 317878c0e0625ccb1c48c2cfe831474d0e5f5147 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 14 Sep 2023 08:56:03 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=89=94=E9=99=A4=E6=97=A0=E5=85=B3?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E4=B8=8B=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/amis/src/renderers/Table/TableRow.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/amis/src/renderers/Table/TableRow.tsx b/packages/amis/src/renderers/Table/TableRow.tsx index 1e0a05dfd..fef111005 100644 --- a/packages/amis/src/renderers/Table/TableRow.tsx +++ b/packages/amis/src/renderers/Table/TableRow.tsx @@ -179,6 +179,7 @@ export class TableRow extends React.PureComponent< onEvent, expanded, + parentExpanded, id, newIndex, isHover, @@ -188,7 +189,9 @@ export class TableRow extends React.PureComponent< depth, expandable, appeard, + checkdisable, trRef, + isNested, ...rest } = this.props; From ab75c4ea8da3e2705e34c670bb2194c1a512eeaf Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 14 Sep 2023 10:24:29 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=20table=20=E5=AE=BD?= =?UTF-8?q?=E5=BA=A6=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/amis-core/src/store/table.ts | 67 +++++++++++-------- .../__snapshots__/crud.test.tsx.snap | 3 - .../__snapshots__/inputTable.test.tsx.snap | 5 -- .../__snapshots__/CRUD.test.tsx.snap | 3 - .../__snapshots__/Pagination.test.tsx.snap | 1 - .../__snapshots__/Table.test.tsx.snap | 13 ---- .../amis/src/renderers/Table/ColGroup.tsx | 5 +- packages/amis/src/renderers/Table/index.tsx | 15 ----- 8 files changed, 42 insertions(+), 70 deletions(-) diff --git a/packages/amis-core/src/store/table.ts b/packages/amis-core/src/store/table.ts index be5fd5e60..b395debd2 100644 --- a/packages/amis-core/src/store/table.ts +++ b/packages/amis-core/src/store/table.ts @@ -785,7 +785,7 @@ export const TableStore = iRendererStore }, get columnWidthReady() { - return getFilteredColumns().every(column => column.width); + return getFilteredColumns().every(column => column.realWidth); }, getStickyStyles(column: IColumn, columns: Array) { @@ -1036,11 +1036,11 @@ export const TableStore = iRendererStore const tableWidth = table.parentElement!.offsetWidth; const thead = table.querySelector(':scope>thead')!; let tbody: HTMLElement | null = null; - const div = document.createElement('div'); - div.className = 'amis-scope'; // jssdk 里面 css 会在这一层 - div.style.cssText += `visibility: hidden!important;`; const htmls: Array = []; const isFixed = self.tableLayout === 'fixed'; + const someSettedWidth = self.columns.some( + column => column.pristine.width + ); const minWidths: { [propName: string]: number; @@ -1054,17 +1054,27 @@ export const TableStore = iRendererStore ); } - htmls.push( - `${thead.outerHTML}${ - tbody ? `${tbody.innerHTML}` : '' - }
` - ); + if (someSettedWidth || isFixed) { + htmls.push( + `${thead.outerHTML}${ + tbody ? `${tbody.innerHTML}` : '' + }
` + ); + } + if (!htmls.length) { + return; + } + + const div = document.createElement('div'); + div.className = 'amis-scope'; // jssdk 里面 css 会在这一层 + div.style.cssText += `visibility: hidden!important;`; div.innerHTML = htmls.join(''); let ths1: Array = []; + let ths2: Array = []; if (isFixed) { ths1 = [].slice.call( @@ -1074,9 +1084,13 @@ export const TableStore = iRendererStore ); } - const ths2: Array = [].slice.call( - div.querySelectorAll(':scope>table:last-child>thead>tr>th[data-index]') - ); + if (someSettedWidth || isFixed) { + ths2 = [].slice.call( + div.querySelectorAll( + ':scope>table:last-child>thead>tr>th[data-index]' + ) + ); + } ths1.forEach(th => { th.style.cssText += 'width: 0'; @@ -1106,14 +1120,16 @@ export const TableStore = iRendererStore ths2.forEach((col: HTMLElement) => { const index = parseInt(col.getAttribute('data-index')!, 10); const column = self.columns[index]; - column.setWidth( - Math.max( - typeof column.pristine.width === 'number' - ? column.pristine.width - : col.clientWidth, - minWidths[index] || 0 - ) - ); + if (column.pristine.width || isFixed) { + column.setWidth( + Math.max( + typeof column.pristine.width === 'number' + ? column.pristine.width + : col.clientWidth, + minWidths[index] || 0 + ) + ); + } }); document.body.removeChild(div); @@ -1134,10 +1150,6 @@ export const TableStore = iRendererStore }); } - function invalidTableColumnWidth() { - self.columns.forEach(column => column.setWidth(0)); - } - function combineCell(arr: Array, keys: Array): Array { if (!keys.length || !arr.length) { return arr; @@ -1740,7 +1752,6 @@ export const TableStore = iRendererStore updateColumns, initTableWidth, syncTableWidth, - invalidTableColumnWidth, initRows, updateSelected, toggleAll, diff --git a/packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap b/packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap index 316d65941..2334848bb 100644 --- a/packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap +++ b/packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap @@ -259,7 +259,6 @@ exports[`doAction:crud reload 1`] = ` class="cxd-Spinner-icon cxd-Spinner-icon--default" /> -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{ if (domRef.current) { + store.initTableWidth(); store.syncTableWidth(); } - }); + }, []); React.useEffect(() => { const table = domRef.current!.parentElement!; @@ -37,7 +38,7 @@ export function ColGroup({ {columns.map(column => { const style: any = {}; - if (store.columnWidthReady) { + if (store.columnWidthReady && column.width) { style.width = column.width; } else if (column.pristine.width) { style.width = column.pristine.width; diff --git a/packages/amis/src/renderers/Table/index.tsx b/packages/amis/src/renderers/Table/index.tsx index 68d0e4a69..bd77b2084 100644 --- a/packages/amis/src/renderers/Table/index.tsx +++ b/packages/amis/src/renderers/Table/index.tsx @@ -548,7 +548,6 @@ export default class Table extends React.Component { this.tableRef = this.tableRef.bind(this); this.affixedTableRef = this.affixedTableRef.bind(this); this.updateTableInfo = this.updateTableInfo.bind(this); - this.updateTableInfoRef = this.updateTableInfoRef.bind(this); this.handleAction = this.handleAction.bind(this); this.handleCheck = this.handleCheck.bind(this); this.handleCheckAll = this.handleCheckAll.bind(this); @@ -1239,13 +1238,6 @@ export default class Table extends React.Component { callback && setTimeout(callback, 20); } - updateTableInfoRef(ref: any) { - if (!ref) { - return; - } - this.updateTableInfo(); - } - // 当表格滚动是,需要让 affixHeader 部分的表格也滚动 handleOutterScroll() { const table = this.table as HTMLElement; @@ -2721,13 +2713,6 @@ export default class Table extends React.Component { onMouseLeave={this.handleMouseLeave} > {this.renderTableContent()} - - { - // 利用这个将 table-layout: auto 转成 table-layout: fixed - store.columnWidthReady ? null : ( - - ) - }
{footer}