mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:58:07 +08:00
commit
38d26ae414
@ -183,13 +183,14 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
|
||||
})
|
||||
];
|
||||
});
|
||||
items = items.filter((item: any) => arrItems.find(a => a === item));
|
||||
items = items.filter((item: any) =>
|
||||
arrItems.find(a => a === item)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
items = matchSorter(items, value, {
|
||||
keys: [key]
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -349,11 +350,11 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
|
||||
})
|
||||
];
|
||||
});
|
||||
filteredItems = filteredItems.filter(
|
||||
item => arrItems.find(a => a === item));
|
||||
filteredItems = filteredItems.filter(item =>
|
||||
arrItems.find(a => a === item)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
filteredItems = matchSorter(filteredItems, value, {
|
||||
keys: [key]
|
||||
});
|
||||
|
@ -97,28 +97,97 @@ export class DataScope {
|
||||
return false;
|
||||
}
|
||||
|
||||
assignSchema(target: any, schema: any): any {
|
||||
// key相同,type也相同
|
||||
if (target.type && target.type === schema.type) {
|
||||
if (target.type === 'array') {
|
||||
// 先只考虑items,不考虑contains
|
||||
if (target.items) {
|
||||
if (Array.isArray(target.items)) {
|
||||
if (schema.items) {
|
||||
if (Array.isArray(schema.items)) {
|
||||
// 如果都是数组,就后者覆盖前者
|
||||
return schema.items;
|
||||
} else {
|
||||
// 否则,追加
|
||||
return {
|
||||
...target,
|
||||
items: [...target.items, schema.items]
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...target,
|
||||
...schema
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// 非数组,则merge
|
||||
return {
|
||||
...target,
|
||||
items: this.assignSchema(target.items, schema.items)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return schema;
|
||||
}
|
||||
} else if (target.type === 'object' && target.properties) {
|
||||
let properties: any = {};
|
||||
|
||||
// 合并属性
|
||||
for (let key of Array.from(
|
||||
new Set([
|
||||
...Object.keys(target.properties),
|
||||
...Object.keys(schema.properties)
|
||||
])
|
||||
)) {
|
||||
const value = target.properties[key];
|
||||
if (value) {
|
||||
properties[key] = schema.properties[key]
|
||||
? this.assignSchema(value, schema.properties[key])
|
||||
: value;
|
||||
} else {
|
||||
properties[key] = schema.properties[key];
|
||||
}
|
||||
}
|
||||
return {
|
||||
...target,
|
||||
properties
|
||||
};
|
||||
} else {
|
||||
return schema;
|
||||
}
|
||||
} else {
|
||||
// key相同、type不同
|
||||
if (Array.isArray(target.oneOf)) {
|
||||
return {
|
||||
...target, // 先做个显示过度,因formula还没支持oneOf
|
||||
oneOf: [...target.oneOf, schema]
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...target, // 先做个显示过度,因formula还没支持oneOf
|
||||
oneOf: [target, schema]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getMergedSchema() {
|
||||
const mergedSchema: any = {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
};
|
||||
|
||||
// todo 以后再来细化这一块,先粗略的写个大概
|
||||
this.schemas.forEach(schema => {
|
||||
const properties: any = schema.properties || {};
|
||||
Object.keys(properties).forEach(key => {
|
||||
const value = properties[key];
|
||||
if (mergedSchema.properties[key]) {
|
||||
if (Array.isArray(mergedSchema.properties[key].oneOf)) {
|
||||
mergedSchema.properties[key].oneOf.push();
|
||||
} else if (
|
||||
mergedSchema.properties[key].type &&
|
||||
mergedSchema.properties[key].type !== value.type
|
||||
) {
|
||||
mergedSchema.properties[key] = {
|
||||
oneOf: [mergedSchema.properties[key], value]
|
||||
};
|
||||
}
|
||||
mergedSchema.properties[key] = this.assignSchema(
|
||||
mergedSchema.properties[key],
|
||||
value
|
||||
);
|
||||
} else {
|
||||
mergedSchema.properties[key] = value;
|
||||
}
|
||||
@ -132,19 +201,14 @@ export class DataScope {
|
||||
options: Array<any>,
|
||||
schema: JSONSchema,
|
||||
path: string = '',
|
||||
key: string = '',
|
||||
/** 是否数组元素,数组元素的内容将获取每个成员的对应值 */
|
||||
isArrayItem = false,
|
||||
/** 不是所有的都可以选择,但不影响子元素 */
|
||||
disabled?: boolean
|
||||
key: string = ''
|
||||
) {
|
||||
// todo 支持 oneOf, anyOf
|
||||
const option: any = {
|
||||
label: schema.title || key,
|
||||
value: path,
|
||||
type: schema.type,
|
||||
tag: schema.description ?? schema.type,
|
||||
disabled
|
||||
tag: schema.description ?? schema.type
|
||||
};
|
||||
|
||||
options.push(option);
|
||||
@ -155,43 +219,32 @@ export class DataScope {
|
||||
|
||||
keys.forEach(key => {
|
||||
const child: any = schema.properties![key];
|
||||
const newPath = isArrayItem ? `ARRAYMAP(${path}, item => item.${key})` : (path + (path ? '.' : '') + key);
|
||||
|
||||
this.buildOptions(
|
||||
option.children,
|
||||
child,
|
||||
newPath,
|
||||
key,
|
||||
isArrayItem,
|
||||
false
|
||||
path + (path ? '.' : '') + key,
|
||||
key
|
||||
);
|
||||
});
|
||||
} else if (schema.type === 'array' && schema.items) {
|
||||
option.children = [];
|
||||
|
||||
this.buildOptions(
|
||||
option.children,
|
||||
{
|
||||
title: '成员',
|
||||
...(schema.items as any)
|
||||
},
|
||||
path,
|
||||
'items',
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
this.buildOptions(
|
||||
option.children,
|
||||
{
|
||||
title: '总数',
|
||||
type: 'number'
|
||||
title: '成员',
|
||||
...(schema.items as any),
|
||||
disabled: true
|
||||
},
|
||||
path + (path ? '.' : '') + 'length',
|
||||
'length',
|
||||
true,
|
||||
isArrayItem
|
||||
path,
|
||||
'items'
|
||||
);
|
||||
|
||||
option.children = mapTree(option.children, item => ({
|
||||
...item,
|
||||
disabled: true
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,4 +272,8 @@ export class DataScope {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getSchemaById(id: string) {
|
||||
return this.schemas?.find(item => item.$id === id);
|
||||
}
|
||||
}
|
||||
|
@ -931,32 +931,40 @@ export function isObject(curObj: any) {
|
||||
return isObject;
|
||||
}
|
||||
|
||||
export function jsonToJsonSchema(json: any = {}) {
|
||||
export function jsonToJsonSchema(
|
||||
json: any = {},
|
||||
titleBuilder?: (type: string, key: string) => string
|
||||
) {
|
||||
const jsonschema: any = {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
};
|
||||
|
||||
Object.keys(json).forEach(key => {
|
||||
const value = json[key];
|
||||
const type = typeof value;
|
||||
const type = Array.isArray(value) ? 'array' : typeof value;
|
||||
|
||||
if (~['string', 'number'].indexOf(type)) {
|
||||
jsonschema.properties[key] = {
|
||||
type: type,
|
||||
title: key
|
||||
type,
|
||||
title: titleBuilder?.(type, key) || key
|
||||
};
|
||||
} else if (type === 'object' && value) {
|
||||
} else if (~['object', 'array'].indexOf(type) && value) {
|
||||
jsonschema.properties[key] = {
|
||||
type: 'object',
|
||||
title: key
|
||||
type,
|
||||
title: titleBuilder?.(type, key) || key,
|
||||
...(type === 'object'
|
||||
? jsonToJsonSchema(value, titleBuilder)
|
||||
: {items: jsonToJsonSchema(value[0], titleBuilder)})
|
||||
};
|
||||
} else {
|
||||
jsonschema.properties[key] = {
|
||||
type: '',
|
||||
title: key
|
||||
title: titleBuilder?.(type, key) || key
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return jsonschema;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import React from 'react';
|
||||
|
||||
import {
|
||||
getI18nEnabled,
|
||||
jsonToJsonSchema,
|
||||
registerEditorPlugin,
|
||||
tipedLabel
|
||||
} from 'amis-editor-core';
|
||||
@ -23,13 +24,14 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {isObject, JSONPipeIn} from 'amis-editor-core';
|
||||
import {setVariable} from 'amis-core';
|
||||
import {setVariable, someTree} from 'amis-core';
|
||||
import type {ActionSchema} from 'amis';
|
||||
import type {CRUDCommonSchema} from 'amis';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import {EditorNodeType, RendererPluginAction} from 'amis-editor-core';
|
||||
import type {EditorNodeType, RendererPluginAction} from 'amis-editor-core';
|
||||
import {normalizeApi} from 'amis-core';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
interface ColumnItem {
|
||||
label: string;
|
||||
@ -1745,7 +1747,92 @@ export class CRUDPlugin extends BasePlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
return child.info.plugin.buildDataSchemas(child, undefined, trigger);
|
||||
let childSchame = await child.info.plugin.buildDataSchemas(
|
||||
child,
|
||||
undefined,
|
||||
trigger
|
||||
);
|
||||
|
||||
// 兼容table的rows,并自行merged异步数据
|
||||
if (child.type === 'table') {
|
||||
let cellProperties = {};
|
||||
const columns: EditorNodeType = child.children.find(
|
||||
item => item.isRegion && item.region === 'columns'
|
||||
);
|
||||
|
||||
if (trigger) {
|
||||
const isColumnChild = someTree(
|
||||
columns?.children,
|
||||
item => item.id === trigger.id
|
||||
);
|
||||
|
||||
// merge异步数据中的单列成员,因为rendererBeforeDispatchEvent无法区分是否需要单列成员
|
||||
if (isColumnChild) {
|
||||
const scope = this.manager.dataSchema.getScope(
|
||||
`${node.id}-${node.type}`
|
||||
);
|
||||
const menberProps = (
|
||||
scope.getSchemaById('crudFetchInitedData')?.properties?.items as any
|
||||
)?.items?.properties;
|
||||
|
||||
cellProperties = {
|
||||
...menberProps,
|
||||
...omit(
|
||||
childSchame.properties,
|
||||
'rows',
|
||||
'selectedItems',
|
||||
'unSelectedItems'
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
childSchame = {
|
||||
$id: childSchame.$id,
|
||||
type: childSchame.type,
|
||||
properties: {
|
||||
...cellProperties,
|
||||
items: childSchame.properties.rows,
|
||||
selectedItems: childSchame.properties.selectedItems,
|
||||
unSelectedItems: childSchame.properties.unSelectedItems,
|
||||
count: {
|
||||
type: 'number',
|
||||
title: '总行数'
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
title: '当前页码'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return childSchame;
|
||||
}
|
||||
|
||||
rendererBeforeDispatchEvent(node: EditorNodeType, e: any, data: any) {
|
||||
if (e === 'fetchInited') {
|
||||
const scope = this.manager.dataSchema.getScope(`${node.id}-${node.type}`);
|
||||
const jsonschema: any = {
|
||||
$id: 'crudFetchInitedData',
|
||||
type: 'object',
|
||||
...jsonToJsonSchema(
|
||||
omit(data, 'selectedItems', 'unSelectedItems'),
|
||||
(type: string, key: string) => {
|
||||
if (type === 'array' && key === 'items') {
|
||||
return '数据列表';
|
||||
}
|
||||
if (type === 'number' && key === 'count') {
|
||||
return '总行数';
|
||||
}
|
||||
return key;
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
scope?.removeSchema(jsonschema.$id);
|
||||
scope?.addSchema(jsonschema);
|
||||
}
|
||||
}
|
||||
|
||||
/** crud 不同 mode 之间转换时候,主体的转换 */
|
||||
|
@ -68,13 +68,13 @@ export class ServicePlugin extends BasePlugin {
|
||||
},
|
||||
{
|
||||
eventName: 'fetchInited',
|
||||
eventLabel: '初始化数据接口请求成功',
|
||||
description: '远程初始化数据接口请求成功时触发'
|
||||
eventLabel: '初始化数据接口请求完成',
|
||||
description: '远程初始化数据接口请求完成时触发'
|
||||
},
|
||||
{
|
||||
eventName: 'fetchSchemaInited',
|
||||
eventLabel: '初始化Schema接口请求成功',
|
||||
description: '远程初始化Schema接口请求成功时触发'
|
||||
eventLabel: '初始化Schema接口请求完成',
|
||||
description: '远程初始化Schema接口请求完成时触发'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -27,7 +27,11 @@ import {
|
||||
getEventControlConfig,
|
||||
getArgsWrapper
|
||||
} from '../renderer/event-control/helper';
|
||||
import {schemaArrayFormat, schemaToArray, resolveArrayDatasource} from '../util';
|
||||
import {
|
||||
schemaArrayFormat,
|
||||
schemaToArray,
|
||||
resolveArrayDatasource
|
||||
} from '../util';
|
||||
|
||||
export class TablePlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -289,7 +293,51 @@ export class TablePlugin extends BasePlugin {
|
||||
properties: {
|
||||
'event.data.item': {
|
||||
type: 'object',
|
||||
title: '行点击数据'
|
||||
title: '当前行数据'
|
||||
},
|
||||
'event.data.index': {
|
||||
type: 'number',
|
||||
title: '当前行索引'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'rowMouseEnter',
|
||||
eventLabel: '鼠标移入行事件',
|
||||
description: '移入整行时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data.item': {
|
||||
type: 'object',
|
||||
title: '当前行数据'
|
||||
},
|
||||
'event.data.index': {
|
||||
type: 'number',
|
||||
title: '当前行索引'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'rowMouseLeave',
|
||||
eventLabel: '鼠标移出行事件',
|
||||
description: '移出整行时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data.item': {
|
||||
type: 'object',
|
||||
title: '当前行数据'
|
||||
},
|
||||
'event.data.index': {
|
||||
type: 'number',
|
||||
title: '当前行索引'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -680,16 +728,28 @@ export class TablePlugin extends BasePlugin {
|
||||
item => item.isRegion && item.region === 'columns'
|
||||
);
|
||||
|
||||
for (let current of columns?.children) {
|
||||
const schema = current.schema;
|
||||
if (schema.name) {
|
||||
itemsSchema.properties[schema.name] = current.info?.plugin
|
||||
?.buildDataSchemas
|
||||
? await current.info.plugin.buildDataSchemas(current, region)
|
||||
: {
|
||||
type: 'string',
|
||||
title: schema.label || schema.name
|
||||
};
|
||||
// todo:以下的处理无效,需要cell实现才能深层细化
|
||||
// for (let current of columns?.children) {
|
||||
// const schema = current.schema;
|
||||
// if (schema.name) {
|
||||
// itemsSchema.properties[schema.name] = current.info?.plugin
|
||||
// ?.buildDataSchemas
|
||||
// ? await current.info.plugin.buildDataSchemas(current, region)
|
||||
// : {
|
||||
// type: 'string',
|
||||
// title: schema.label || schema.name
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// 一期先简单处理,上面todo实现之后,这里可以废弃
|
||||
// table 无法根据source确定异步数据来源,因此不能在table层做异步数据列的收集
|
||||
for (let current of node.schema?.columns) {
|
||||
if (current.name) {
|
||||
itemsSchema.properties[current.name] = {
|
||||
type: 'string',
|
||||
title: current.label || current.name
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -716,6 +776,16 @@ export class TablePlugin extends BasePlugin {
|
||||
type: 'array',
|
||||
title: '数据列表',
|
||||
items: itemsSchema
|
||||
},
|
||||
selectedItems: {
|
||||
type: 'array',
|
||||
title: '已选中行'
|
||||
// items: itemsSchema
|
||||
},
|
||||
unSelectedItems: {
|
||||
type: 'array',
|
||||
title: '未选中行'
|
||||
// items: itemsSchema
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -775,7 +775,7 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
|
||||
const ctx = createObject(store.mergedData, {
|
||||
...selectedItems[0],
|
||||
currentPageData: store.mergedData.items.concat(),
|
||||
currentPageData: (store.mergedData?.items || []).concat(),
|
||||
rows: selectedItems,
|
||||
items: selectedItems,
|
||||
selectedItems,
|
||||
@ -865,7 +865,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
},
|
||||
false,
|
||||
true,
|
||||
this.props.initFetch !== false
|
||||
this.props.initFetch !== false,
|
||||
true
|
||||
);
|
||||
|
||||
store.setPristineQuery();
|
||||
@ -910,7 +911,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
values: Record<string, any>,
|
||||
jumpToFirstPage: boolean = true,
|
||||
replaceLocation: boolean = false,
|
||||
search: boolean = true
|
||||
search: boolean = true,
|
||||
isInit: boolean = false
|
||||
) {
|
||||
const {
|
||||
store,
|
||||
@ -942,8 +944,15 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
perPageField
|
||||
);
|
||||
this.lastQuery = store.query;
|
||||
|
||||
search &&
|
||||
this.search(undefined, undefined, undefined, loadDataOnceFetchOnFilter);
|
||||
this.search(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
loadDataOnceFetchOnFilter,
|
||||
isInit
|
||||
);
|
||||
}
|
||||
|
||||
handleBulkGo(
|
||||
@ -1110,7 +1119,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
values?: any,
|
||||
silent?: boolean,
|
||||
clearSelection?: boolean,
|
||||
forceReload = false
|
||||
forceReload = false,
|
||||
isInit: boolean = false
|
||||
) {
|
||||
const {
|
||||
store,
|
||||
@ -1130,7 +1140,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
loadDataOnce,
|
||||
loadDataOnceFetchOnFilter,
|
||||
source,
|
||||
columns
|
||||
columns,
|
||||
dispatchEvent
|
||||
} = this.props;
|
||||
|
||||
// reload 需要清空用户选择。
|
||||
@ -1175,7 +1186,26 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
columns: store.columns ?? columns
|
||||
})
|
||||
.then(value => {
|
||||
const {page, lastPage} = store;
|
||||
const {page, lastPage, data, error, msg} = store;
|
||||
|
||||
if (isInit) {
|
||||
// 初始化请求完成
|
||||
const rendererEvent = dispatchEvent?.(
|
||||
'fetchInited',
|
||||
createObject(this.props.data, {
|
||||
...data,
|
||||
__response: {
|
||||
error,
|
||||
msg
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (rendererEvent?.prevented) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 空列表 且 页数已经非法超出,则跳转到最后的合法页数
|
||||
if (
|
||||
!store.data.items.length &&
|
||||
@ -1537,8 +1567,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
newItems.splice(0, newItems.length - 1)
|
||||
);
|
||||
}
|
||||
store.setSelectedItems(newItems);
|
||||
store.setUnSelectedItems(newUnSelectedItems);
|
||||
store.updateSelectData(newItems, newUnSelectedItems);
|
||||
|
||||
onSelect && onSelect(newItems, newUnSelectedItems);
|
||||
}
|
||||
|
||||
@ -1701,7 +1731,6 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
|
||||
let bulkBtns: Array<ActionSchema> = [];
|
||||
let itemBtns: Array<ActionSchema> = [];
|
||||
|
||||
const ctx = createObject(store.mergedData, {
|
||||
currentPageData: (store.mergedData?.items || []).concat(),
|
||||
rows: selectedItems.concat(),
|
||||
@ -2414,4 +2443,13 @@ export class CRUDRenderer extends CRUD {
|
||||
const scoped = this.context as IScopedContext;
|
||||
scoped.close(target);
|
||||
}
|
||||
|
||||
setData(values: object, replace?: boolean) {
|
||||
return this.props.store.updateData(values, undefined, replace);
|
||||
}
|
||||
|
||||
getData() {
|
||||
const {store, data} = this.props;
|
||||
return store.getData(data);
|
||||
}
|
||||
}
|
||||
|
@ -910,6 +910,7 @@ export default class CRUD2 extends React.Component<CRUD2Props, any> {
|
||||
);
|
||||
}
|
||||
store.updateSelectData(newItems, newUnSelectedItems);
|
||||
|
||||
onSelect && onSelect(newItems);
|
||||
}
|
||||
|
||||
|
@ -512,10 +512,13 @@ export default class Service extends React.Component<ServiceProps> {
|
||||
const data = result?.hasOwnProperty('ok') ? result.data ?? {} : result;
|
||||
const {onBulkChange, dispatchEvent, store} = this.props;
|
||||
|
||||
dispatchEvent?.('fetchInited', {
|
||||
...data,
|
||||
__response: {msg: store.msg, error: store.error}
|
||||
});
|
||||
dispatchEvent?.(
|
||||
'fetchInited',
|
||||
createObject(this.props.data, {
|
||||
...data,
|
||||
__response: {msg: store.msg, error: store.error}
|
||||
})
|
||||
);
|
||||
|
||||
if (!isEmpty(data) && onBulkChange) {
|
||||
onBulkChange(data);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import {ClassNamesFn} from 'amis-core';
|
||||
import {ClassNamesFn, RendererEvent} from 'amis-core';
|
||||
|
||||
import {SchemaNode, ActionObject} from 'amis-core';
|
||||
import {TableRow} from './TableRow';
|
||||
@ -26,6 +26,15 @@ export interface TableBodyProps extends LocaleProps {
|
||||
props: any
|
||||
) => React.ReactNode;
|
||||
onCheck: (item: IRow, value: boolean, shift?: boolean) => void;
|
||||
onRowClick: (item: IRow, index: number) => Promise<RendererEvent<any> | void>;
|
||||
onRowMouseEnter: (
|
||||
item: IRow,
|
||||
index: number
|
||||
) => Promise<RendererEvent<any> | void>;
|
||||
onRowMouseLeave: (
|
||||
item: IRow,
|
||||
index: number
|
||||
) => Promise<RendererEvent<any> | void>;
|
||||
onQuickChange?: (
|
||||
item: IRow,
|
||||
values: object,
|
||||
@ -69,12 +78,14 @@ export class TableBody extends React.Component<TableBodyProps> {
|
||||
footable,
|
||||
ignoreFootableContent,
|
||||
footableColumns,
|
||||
itemAction
|
||||
itemAction,
|
||||
onRowClick,
|
||||
onRowMouseEnter,
|
||||
onRowMouseLeave
|
||||
} = this.props;
|
||||
|
||||
return rows.map((item: IRow, rowIndex: number) => {
|
||||
const itemProps = buildItemProps ? buildItemProps(item, rowIndex) : null;
|
||||
|
||||
const doms = [
|
||||
<TableRow
|
||||
{...itemProps}
|
||||
@ -99,6 +110,9 @@ export class TableBody extends React.Component<TableBodyProps> {
|
||||
onCheck={onCheck}
|
||||
// todo 先注释 quickEditEnabled={item.depth === 1}
|
||||
onQuickChange={onQuickChange}
|
||||
onRowClick={onRowClick}
|
||||
onRowMouseEnter={onRowMouseEnter}
|
||||
onRowMouseLeave={onRowMouseLeave}
|
||||
{...rowProps}
|
||||
/>
|
||||
];
|
||||
@ -124,6 +138,9 @@ export class TableBody extends React.Component<TableBodyProps> {
|
||||
render={render}
|
||||
onAction={onAction}
|
||||
onCheck={onCheck}
|
||||
onRowClick={onRowClick}
|
||||
onRowMouseEnter={onRowMouseEnter}
|
||||
onRowMouseLeave={onRowMouseLeave}
|
||||
footableMode
|
||||
footableColSpan={columns.length}
|
||||
onQuickChange={onQuickChange}
|
||||
|
@ -5,7 +5,8 @@ import {
|
||||
SchemaNode,
|
||||
ActionObject,
|
||||
LocaleProps,
|
||||
OnEventProps
|
||||
OnEventProps,
|
||||
RendererEvent
|
||||
} from 'amis-core';
|
||||
import {TableBody} from './TableBody';
|
||||
import {observer} from 'mobx-react';
|
||||
@ -42,6 +43,15 @@ export interface TableContentProps extends LocaleProps {
|
||||
props: any
|
||||
) => React.ReactNode;
|
||||
onCheck: (item: IRow, value: boolean, shift?: boolean) => void;
|
||||
onRowClick: (item: IRow, index: number) => Promise<RendererEvent<any> | void>;
|
||||
onRowMouseEnter: (
|
||||
item: IRow,
|
||||
index: number
|
||||
) => Promise<RendererEvent<any> | void>;
|
||||
onRowMouseLeave: (
|
||||
item: IRow,
|
||||
index: number
|
||||
) => Promise<RendererEvent<any> | void>;
|
||||
onQuickChange?: (
|
||||
item: IRow,
|
||||
values: object,
|
||||
@ -128,6 +138,9 @@ export class TableContent extends React.Component<TableContentProps> {
|
||||
renderHeadCell,
|
||||
renderCell,
|
||||
onCheck,
|
||||
onRowClick,
|
||||
onRowMouseEnter,
|
||||
onRowMouseLeave,
|
||||
rowClassName,
|
||||
onQuickChange,
|
||||
footable,
|
||||
@ -233,6 +246,9 @@ export class TableContent extends React.Component<TableContentProps> {
|
||||
render={render}
|
||||
renderCell={renderCell}
|
||||
onCheck={onCheck}
|
||||
onRowClick={onRowClick}
|
||||
onRowMouseEnter={onRowMouseEnter}
|
||||
onRowMouseLeave={onRowMouseLeave}
|
||||
onQuickChange={onQuickChange}
|
||||
footable={footable}
|
||||
footableColumns={footableColumns}
|
||||
|
@ -1,12 +1,21 @@
|
||||
import {observer} from 'mobx-react';
|
||||
import React from 'react';
|
||||
import type {IColumn, IRow} from 'amis-core';
|
||||
import {RendererProps} from 'amis-core';
|
||||
import type {IColumn, IRow} from 'amis-core/lib/store/table';
|
||||
import {RendererEvent, RendererProps} from 'amis-core';
|
||||
import {Action} from '../Action';
|
||||
import {isClickOnInput, createObject} from 'amis-core';
|
||||
|
||||
interface TableRowProps extends Pick<RendererProps, 'render'> {
|
||||
onCheck: (item: IRow) => Promise<void>;
|
||||
onRowClick: (item: IRow, index: number) => Promise<RendererEvent<any> | void>;
|
||||
onRowMouseEnter: (
|
||||
item: IRow,
|
||||
index: number
|
||||
) => Promise<RendererEvent<any> | void>;
|
||||
onRowMouseLeave: (
|
||||
item: IRow,
|
||||
index: number
|
||||
) => Promise<RendererEvent<any> | void>;
|
||||
classPrefix: string;
|
||||
renderCell: (
|
||||
region: string,
|
||||
@ -39,26 +48,13 @@ export class TableRow extends React.Component<TableRowProps> {
|
||||
}
|
||||
|
||||
handleMouseEnter(e: React.MouseEvent<HTMLTableRowElement>) {
|
||||
const {item, itemIndex, data, dispatchEvent} = this.props;
|
||||
|
||||
dispatchEvent(
|
||||
'rowMouseEnter',
|
||||
createObject(data, {
|
||||
item: item?.data,
|
||||
index: itemIndex
|
||||
})
|
||||
);
|
||||
const {item, itemIndex, onRowMouseEnter} = this.props;
|
||||
onRowMouseEnter?.(item?.data, itemIndex);
|
||||
}
|
||||
|
||||
handleMouseLeave(e: React.MouseEvent<HTMLTableRowElement>) {
|
||||
const {item, itemIndex, data, dispatchEvent} = this.props;
|
||||
dispatchEvent(
|
||||
'rowMouseLeave',
|
||||
createObject(data, {
|
||||
item: item?.data,
|
||||
index: itemIndex
|
||||
})
|
||||
);
|
||||
const {item, itemIndex, onRowMouseLeave} = this.props;
|
||||
onRowMouseLeave?.(item?.data, itemIndex);
|
||||
}
|
||||
|
||||
// 定义点击一行的行为,通过 itemAction配置
|
||||
@ -70,24 +66,10 @@ export class TableRow extends React.Component<TableRowProps> {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const {
|
||||
itemAction,
|
||||
onAction,
|
||||
item,
|
||||
itemIndex,
|
||||
data,
|
||||
dispatchEvent,
|
||||
onCheck
|
||||
} = this.props;
|
||||
const {itemAction, onAction, item, itemIndex, onCheck, onRowClick} =
|
||||
this.props;
|
||||
|
||||
const rendererEvent = await dispatchEvent(
|
||||
'rowClick',
|
||||
createObject(data, {
|
||||
rowItem: item?.data, // 保留rowItem 可能有用户已经在用 兼容之前的版本
|
||||
item: item?.data,
|
||||
index: itemIndex
|
||||
})
|
||||
);
|
||||
const rendererEvent = await onRowClick?.(item?.data, itemIndex);
|
||||
|
||||
if (rendererEvent?.prevented) {
|
||||
return;
|
||||
|
@ -1,7 +1,12 @@
|
||||
import React from 'react';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import {ScopedContext, IScopedContext, SchemaExpression} from 'amis-core';
|
||||
import {
|
||||
ScopedContext,
|
||||
IScopedContext,
|
||||
SchemaExpression,
|
||||
extendObject
|
||||
} from 'amis-core';
|
||||
import {Renderer, RendererProps} from 'amis-core';
|
||||
import {SchemaNode, ActionObject, Schema} from 'amis-core';
|
||||
import forEach from 'lodash/forEach';
|
||||
@ -547,6 +552,9 @@ export default class Table extends React.Component<TableProps, object> {
|
||||
this.handleMouseLeave = this.handleMouseLeave.bind(this);
|
||||
this.subFormRef = this.subFormRef.bind(this);
|
||||
this.handleColumnToggle = this.handleColumnToggle.bind(this);
|
||||
this.handleRowClick = this.handleRowClick.bind(this);
|
||||
this.handleRowMouseEnter = this.handleRowMouseEnter.bind(this);
|
||||
this.handleRowMouseLeave = this.handleRowMouseLeave.bind(this);
|
||||
|
||||
this.updateAutoFillHeight = this.updateAutoFillHeight.bind(this);
|
||||
|
||||
@ -910,16 +918,51 @@ export default class Table extends React.Component<TableProps, object> {
|
||||
this.syncSelected();
|
||||
}
|
||||
|
||||
handleRowClick(item: IRow, index: number) {
|
||||
const {dispatchEvent, store, data} = this.props;
|
||||
return dispatchEvent(
|
||||
'rowClick',
|
||||
createObject(data, {
|
||||
rowItem: item, // 保留rowItem 可能有用户已经在用 兼容之前的版本
|
||||
item,
|
||||
index
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
handleRowMouseEnter(item: IRow, index: number) {
|
||||
const {dispatchEvent, store, data} = this.props;
|
||||
return dispatchEvent(
|
||||
'rowMouseEnter',
|
||||
createObject(data, {
|
||||
item,
|
||||
index
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
handleRowMouseLeave(item: IRow, index: number) {
|
||||
const {dispatchEvent, store, data} = this.props;
|
||||
return dispatchEvent(
|
||||
'rowMouseLeave',
|
||||
createObject(data, {
|
||||
item,
|
||||
index
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async handleCheckAll() {
|
||||
const {store, data, dispatchEvent} = this.props;
|
||||
|
||||
const items = store.getSelectedRows().map(item => item.data);
|
||||
const items = store.rows.map((row: any) => row.data);
|
||||
const selectedItems = store.getSelectedRows().map(item => item.data);
|
||||
|
||||
const rendererEvent = await dispatchEvent(
|
||||
'selectedChange',
|
||||
createObject(data, {
|
||||
selectedItems: store.allChecked ? [] : items,
|
||||
unSelectedItems: store.allChecked ? items : []
|
||||
selectedItems: store.allChecked ? [] : selectedItems,
|
||||
unSelectedItems: store.allChecked ? selectedItems : [],
|
||||
items
|
||||
})
|
||||
);
|
||||
|
||||
@ -2236,7 +2279,13 @@ export default class Table extends React.Component<TableProps, object> {
|
||||
// 操作列不下发loading,否则会导致操作栏里面的所有按钮都出现loading
|
||||
loading: column.type === 'operation' ? false : props.loading,
|
||||
btnDisabled: store.dragging,
|
||||
data: item.locals,
|
||||
data: this.props.selectable
|
||||
? extendObject(item.locals, {
|
||||
// 只有table时,也可以获取选中行
|
||||
selectedItems: store.selectedRows.map(item => item.data),
|
||||
unSelectedItems: store.unSelectedRows.map(item => item.data)
|
||||
})
|
||||
: item.locals,
|
||||
value: column.name
|
||||
? resolveVariable(
|
||||
column.name,
|
||||
@ -2430,6 +2479,9 @@ export default class Table extends React.Component<TableProps, object> {
|
||||
render={render}
|
||||
renderCell={this.renderCell}
|
||||
onCheck={this.handleCheck}
|
||||
onRowClick={this.handleRowClick}
|
||||
onRowMouseEnter={this.handleRowMouseEnter}
|
||||
onRowMouseLeave={this.handleRowMouseLeave}
|
||||
onQuickChange={store.dragging ? undefined : this.handleQuickChange}
|
||||
footable={store.footable}
|
||||
ignoreFootableContent
|
||||
@ -2817,6 +2869,7 @@ export default class Table extends React.Component<TableProps, object> {
|
||||
{
|
||||
...this.props,
|
||||
selectedItems: store.selectedRows.map(item => item.data),
|
||||
unSelectedItems: store.unSelectedRows.map(item => item.data),
|
||||
items: store.rows.map(item => item.data)
|
||||
},
|
||||
this.renderToolbar
|
||||
@ -2916,6 +2969,9 @@ export default class Table extends React.Component<TableProps, object> {
|
||||
renderHeadCell={this.renderHeadCell}
|
||||
renderCell={this.renderCell}
|
||||
onCheck={this.handleCheck}
|
||||
onRowClick={this.handleRowClick}
|
||||
onRowMouseEnter={this.handleRowMouseEnter}
|
||||
onRowMouseLeave={this.handleRowMouseLeave}
|
||||
onQuickChange={store.dragging ? undefined : this.handleQuickChange}
|
||||
footable={store.footable}
|
||||
footableColumns={store.footableColumns}
|
||||
@ -3091,6 +3147,19 @@ export class TableRenderer extends Table {
|
||||
return scoped.reload(subPath, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
setData(values: any, replace?: boolean) {
|
||||
const data = {
|
||||
...values,
|
||||
rows: values.rows ?? values.items // 做个兼容
|
||||
};
|
||||
return this.props.store.updateData(data, undefined, replace);
|
||||
}
|
||||
|
||||
getData() {
|
||||
const {store, data} = this.props;
|
||||
return store.getData(data);
|
||||
}
|
||||
}
|
||||
|
||||
export {TableCell};
|
||||
|
Loading…
Reference in New Issue
Block a user