feat: crud、crud2支持行移入、行移出事件

This commit is contained in:
wanglinfang 2023-03-31 11:47:22 +08:00
parent 2a79bd18f2
commit 230823daa7
11 changed files with 176 additions and 36 deletions

View File

@ -1872,7 +1872,9 @@ popOver 的其它配置请参考 [popover](./popover)
| columnSearch | `searchName: string` 列搜索列名<br/>`searchValue: string` 列搜索数据 | 点击列搜索时触发 |
| orderChange | `movedItems: item[]` 已排序数据 | 手动拖拽行排序时触发 |
| columnToggled | `columns: item[]` 当前显示的列配置数据 | 点击自定义列时触发 |
| rowClick | `rowItem: object` 行点击数据 | 点击整行时触发 |
| rowClick | `item: object` 行点击数据<br/>`index: number` 行索引 | 点击整行时触发 |
| rowMouseEnter | `item: object` 行移入数据<br/>`index: number` 行索引 | 移入整行时触发 |
| rowMouseLeave | `item: object` 行移出数据<br/>`index: number` 行索引 | 移出整行时触发 |
### 列配置事件表

View File

@ -256,7 +256,7 @@ export default {
actionType: 'toast',
args: {
msgType: 'info',
msg: '行单击数据:${rowItem|json}'
msg: '行单击数据:${item|json};行索引:${index}'
}
}
]

View File

@ -287,7 +287,7 @@ export class TablePlugin extends BasePlugin {
{
type: 'object',
properties: {
'event.data.rowItem': {
'event.data.item': {
type: 'object',
title: '行点击数据'
}

View File

@ -279,7 +279,7 @@ export class Table2Plugin extends BasePlugin {
{
type: 'object',
properties: {
'event.data.rowItem': {
'event.data.item': {
type: 'object',
title: '行点击数据'
}

View File

@ -1166,13 +1166,20 @@ export class Table extends React.PureComponent<TableProps, TableState> {
}
}
onRowMouseEnter(
async onRowMouseEnter(
event: React.ChangeEvent<any>,
record?: any,
rowIndex?: number
) {
const {classnames: cx, onRow} = this.props;
if (onRow && onRow.onRowMouseEnter) {
const prevented = await onRow.onRowMouseEnter(event, record, rowIndex);
if (prevented) {
return;
}
}
let parent = event.target;
while (parent && parent.tagName !== 'TR') {
parent = parent.parentElement;
@ -1191,22 +1198,24 @@ export class Table extends React.PureComponent<TableProps, TableState> {
target = target.closest('tr');
}
this.setState({hoverRow: {target, rowIndex, record}}, () => {
if (onRow) {
onRow.onRowMouseEnter &&
onRow.onRowMouseEnter(event, record, rowIndex);
}
});
this.setState({hoverRow: {target, rowIndex, record}});
}
}
onRowMouseLeave(
async onRowMouseLeave(
event: React.ChangeEvent<any>,
record?: any,
rowIndex?: number
) {
const {classnames: cx, onRow} = this.props;
if (onRow && onRow.onRowMouseLeave) {
const prevented = await onRow.onRowMouseLeave(event, record, rowIndex);
if (prevented) {
return;
}
}
let parent = event.target;
while (parent && parent.tagName !== 'TR') {
parent = parent.parentElement;
@ -1218,12 +1227,6 @@ export class Table extends React.PureComponent<TableProps, TableState> {
td.classList.remove(cx('Table-cell-row-hover'));
}
}
if (record) {
if (onRow) {
onRow.onRowMouseLeave && onRow.onRowMouseLeave(event, record, rowIndex);
}
}
}
onMouseLeave() {

View File

@ -1,6 +1,7 @@
import React from 'react';
import isEqual from 'lodash/isEqual';
import pickBy from 'lodash/pickBy';
import omitBy from 'lodash/omitBy';
import {Renderer, RendererProps} from 'amis-core';
import {SchemaNode, Schema, ActionObject, PlainObject} from 'amis-core';
import {CRUDStore, ICRUDStore} from 'amis-core';
@ -44,6 +45,8 @@ import {ActionSchema} from './Action';
import {CardsSchema} from './Cards';
import {ListSchema} from './List';
import {TableSchema} from './Table';
import type {TableRendererEvent} from './Table';
import type {CardsRendererEvent} from './Cards';
import {isPureVariable, resolveVariableAndFilter, parseQuery} from 'amis-core';
import type {PaginationProps} from './Pagination';
@ -74,6 +77,8 @@ export type CRUDToolbarObject = {
align?: 'left' | 'right';
};
export type CRUDRendererEvent = TableRendererEvent | CardsRendererEvent;
export interface CRUDCommonSchema extends BaseSchema, SpinnerExtraProps {
/**
* CRUD
@ -332,6 +337,19 @@ export interface CRUDProps
pickerMode?: boolean; // 选择模式,用做表单中的选择操作
}
const INNER_EVENTS: Array<CRUDRendererEvent> = [
'selectedChange',
'columnSort',
'columnFilter',
'columnSearch',
'columnToggled',
'orderChange',
'rowClick',
'rowMouseEnter',
'rowMouseLeave',
'selected'
];
export default class CRUD extends React.Component<CRUDProps, any> {
static propsList: Array<keyof CRUDProps> = [
'bulkActions',
@ -2230,6 +2248,12 @@ export default class CRUD extends React.Component<CRUDProps, any> {
'body',
{
...rest,
// 通用事件 例如cus-event 如果直接透传给table 则会被触发2次
// 因此只将下层组件table、cards中自定义事件透传下去 否则通过crud配置了也不会执行
onEvent: omitBy(
onEvent,
(event, key: any) => !INNER_EVENTS.includes(key)
),
columns: store.columns ?? rest.columns,
type: mode || 'table'
},

View File

@ -1,7 +1,6 @@
import React from 'react';
import omitBy from 'lodash/omitBy';
import {Renderer, RendererProps} from 'amis-core';
import {Action} from '../types';
import {CRUDStore, ICRUDStore} from 'amis-core';
import {
createObject,
@ -22,6 +21,7 @@ import {evalExpression, filter} from 'amis-core';
import {isEffectiveApi, isApiOutdated} from 'amis-core';
import findIndex from 'lodash/findIndex';
import {Html, SpinnerExtraProps} from 'amis-ui';
import {Action} from '../types';
import {
BaseSchema,
SchemaApi,
@ -33,11 +33,13 @@ import {
import {CardsSchema} from './Cards';
import {ListSchema} from './List';
import {TableSchema2} from './Table2';
import type {Table2RendererEvent} from './Table2';
import type {CardsRendererEvent} from './Cards';
import {isPureVariable, resolveVariableAndFilter} from 'amis-core';
import {SchemaCollection} from '../Schema';
import upperFirst from 'lodash/upperFirst';
export type CRUDRendererEvent = 'search';
export type CRUDRendererEvent = Table2RendererEvent | CardsRendererEvent;
export interface CRUD2CommonSchema extends BaseSchema, SpinnerExtraProps {
/**
@ -193,6 +195,19 @@ export interface CRUD2Props
pickerMode?: boolean; // 选择模式,用做表单中的选择操作
}
const INNER_EVENTS: Array<CRUDRendererEvent> = [
'selectedChange',
'columnSort',
'columnFilter',
'columnSearch',
'columnToggled',
'orderChange',
'rowClick',
'rowMouseEnter',
'rowMouseLeave',
'selected'
];
export default class CRUD2 extends React.Component<CRUD2Props, any> {
static propsList: Array<keyof CRUD2Props> = [
'mode',
@ -1135,6 +1150,7 @@ export default class CRUD2 extends React.Component<CRUD2Props, any> {
classnames: cx,
keepItemSelectionOnPageChange,
maxKeepItemSelectionLength,
onEvent,
onAction,
popOverContainer,
translate: __,
@ -1171,6 +1187,12 @@ export default class CRUD2 extends React.Component<CRUD2Props, any> {
'body',
{
...rest,
// 通用事件 例如cus-event 如果直接透传给table 则会被触发2次
// 因此只将下层组件table、cards中自定义事件透传下去 否则通过crud配置了也不会执行
onEvent: omitBy(
onEvent,
(event, key: any) => !INNER_EVENTS.includes(key)
),
type: mode,
columns: mode.startsWith('table')
? store.columns || columns

View File

@ -1,4 +1,4 @@
import React, {Fragment} from 'react';
import React from 'react';
import {findDOMNode} from 'react-dom';
import {Renderer, RendererProps} from 'amis-core';
import {SchemaNode, Schema, ActionObject} from 'amis-core';
@ -10,7 +10,6 @@ import {
getScrollParent,
difference,
ucFirst,
noop,
autobind,
createObject
} from 'amis-core';
@ -138,9 +137,9 @@ export interface Column {
type: string;
[propName: string]: any;
}
export type CardsRendererEvent = 'change';
export type CardsRendererAction = 'check-all';
// 如果这里的事件调整对应CRUD里的事件配置也需要同步修改
export type CardsRendererEvent = 'selected';
export type CardsRendererAction = 'toggleSelectAll' | 'selectAll' | 'clearAll';
export interface GridProps
extends RendererProps,

View File

@ -1,6 +1,5 @@
import {observer} from 'mobx-react';
import React from 'react';
import uniq from 'lodash/uniq';
import type {IColumn, IRow} from 'amis-core/lib/store/table';
import {RendererProps} from 'amis-core';
import {Action} from '../Action';
@ -35,6 +34,31 @@ export class TableRow extends React.Component<TableRowProps> {
this.handleQuickChange = this.handleQuickChange.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleItemClick = this.handleItemClick.bind(this);
this.handleMouseEnter = this.handleMouseEnter.bind(this);
this.handleMouseLeave = this.handleMouseLeave.bind(this);
}
handleMouseEnter(e: React.MouseEvent<HTMLTableRowElement>) {
const {item, itemIndex, data, dispatchEvent} = this.props;
dispatchEvent(
'rowMouseEnter',
createObject(data, {
item: item?.data,
index: itemIndex
})
);
}
handleMouseLeave(e: React.MouseEvent<HTMLTableRowElement>) {
const {item, itemIndex, data, dispatchEvent} = this.props;
dispatchEvent(
'rowMouseLeave',
createObject(data, {
item: item?.data,
index: itemIndex
})
);
}
// 定义点击一行的行为,通过 itemAction配置
@ -43,13 +67,22 @@ export class TableRow extends React.Component<TableRowProps> {
return;
}
const {itemAction, onAction, item, data, dispatchEvent, onCheck} =
this.props;
const {
itemAction,
onAction,
item,
itemIndex,
data,
dispatchEvent,
onCheck
} = this.props;
const rendererEvent = await dispatchEvent(
'rowClick',
createObject(data, {
rowItem: item?.data
rowItem: item?.data, // 保留rowItem 可能有用户已经在用 兼容之前的版本
item: item?.data,
index: itemIndex
})
);
@ -144,6 +177,8 @@ export class TableRow extends React.Component<TableRowProps> {
? this.handleItemClick
: undefined
}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
className={cx(itemClassName, {
'is-hovered': item.isHover,
'is-checked': item.checked,
@ -210,6 +245,8 @@ export class TableRow extends React.Component<TableRowProps> {
? this.handleItemClick
: undefined
}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
data-index={item.depth === 1 ? item.newIndex : undefined}
data-id={item.id}
className={cx(

View File

@ -400,6 +400,7 @@ export type ExportExcelToolbar = SchemaNode & {
filename?: string;
};
// 如果这里的事件调整对应CRUD里的事件配置也需要同步修改
export type TableRendererEvent =
| 'selectedChange'
| 'columnSort'
@ -407,7 +408,9 @@ export type TableRendererEvent =
| 'columnSearch'
| 'columnToggled'
| 'orderChange'
| 'rowClick';
| 'rowClick'
| 'rowMouseEnter'
| 'rowMouseLeave';
export type TableRendererAction =
| 'selectAll'

View File

@ -368,13 +368,17 @@ export interface TableSchema2 extends BaseSchema {
keepItemSelectionOnPageChange?: boolean;
}
// 事件调整 对应CRUD2里的事件配置也需要同步修改
export type Table2RendererEvent =
| 'selected'
| 'selectedChange'
| 'columnSort'
| 'columnFilter'
| 'columnSearch'
| 'columnToggled'
| 'dragOver';
| 'orderChange'
| 'rowClick'
| 'rowMouseEnter'
| 'rowMouseLeave';
export type Table2RendererAction =
| 'selectAll'
@ -1137,11 +1141,11 @@ export default class Table2 extends React.Component<Table2Props, object> {
const rendererEvent = await dispatchEvent(
'rowClick',
createObject(data, {rowItem})
createObject(data, {item: rowItem, index: rowIndex})
);
if (rendererEvent?.prevented) {
return rendererEvent?.prevented;
return;
}
if (rowItem && onRow) {
@ -1149,6 +1153,50 @@ export default class Table2 extends React.Component<Table2Props, object> {
}
}
@autobind
async handleRowMouseEnter(
event: React.MouseEvent<HTMLTableRowElement>,
rowItem: any,
rowIndex?: number
) {
const {dispatchEvent, data, onRow} = this.props;
const rendererEvent = await dispatchEvent(
'rowMouseEnter',
createObject(data, {item: rowItem, index: rowIndex})
);
if (rendererEvent?.prevented) {
return;
}
if (rowItem && onRow) {
onRow.onRowMouseEnter && onRow.onRowMouseEnter(event, rowItem, rowIndex);
}
}
@autobind
async handleRowMouseLeave(
event: React.MouseEvent<HTMLTableRowElement>,
rowItem: any,
rowIndex?: number
) {
const {dispatchEvent, data, onRow} = this.props;
const rendererEvent = await dispatchEvent(
'rowMouseLeave',
createObject(data, {item: rowItem, index: rowIndex})
);
if (rendererEvent?.prevented) {
return;
}
if (rowItem && onRow) {
onRow.onRowMouseLeave && onRow.onRowMouseLeave(event, rowItem, rowIndex);
}
}
@autobind
async handleOrderChange(
oldIndex: number,
@ -1457,7 +1505,9 @@ export default class Table2 extends React.Component<Table2Props, object> {
keyField={keyField}
onRow={{
...onRow,
onRowClick: this.handleRowClick
onRowClick: this.handleRowClick,
onRowMouseEnter: this.handleRowMouseEnter,
onRowMouseLeave: this.handleRowMouseLeave
}}
></Table>
);