From a97bf77ee634900b03491d15020fe6a9b3801ffe Mon Sep 17 00:00:00 2001
From: 2betop <2698393+2betop@users.noreply.github.com>
Date: Thu, 19 Sep 2024 20:11:03 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E9=9A=90=E8=97=8F=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E4=B8=AD=E6=B7=BB=E5=8A=A0=20=5F=5FchangeReason=20=E5=AD=97?=
=?UTF-8?q?=E6=AE=B5=E5=B9=B6=E8=A1=A5=E5=85=85=E6=96=87=E6=A1=A3=E8=AF=B4?=
=?UTF-8?q?=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../zh-CN/concepts/datascope-and-datachain.md | 75 +++++++++++++++++++
packages/amis-core/src/WithStore.tsx | 21 ++++--
packages/amis-core/src/renderers/Form.tsx | 41 ++++++++--
packages/amis-core/src/renderers/Item.tsx | 4 +-
.../amis-core/src/renderers/wrapControl.tsx | 58 ++++++++++++--
packages/amis-core/src/store/form.ts | 41 ++++++++--
packages/amis-core/src/store/iRenderer.ts | 40 +++++++++-
packages/amis-core/src/store/service.ts | 15 +++-
packages/amis-core/src/types.ts | 29 +++++++
packages/amis-editor-core/src/plugin.ts | 2 +-
packages/amis-editor-core/src/store/editor.ts | 6 +-
packages/amis-editor-core/src/util.ts | 4 +-
packages/amis-editor/src/plugin/Dialog.tsx | 2 +-
.../src/renderer/FormulaControl.tsx | 2 +-
.../src/renderer/StatusControl.tsx | 2 +-
.../event-control/DialogActionPanel.tsx | 2 +-
.../src/renderer/event-control/index.tsx | 2 +-
packages/amis-editor/src/tpl/common.tsx | 2 +-
.../__tests__/renderers/CRUDfilter.test.tsx | 2 +-
packages/amis/src/renderers/Service.tsx | 4 +-
packages/amis/src/types.ts | 14 ++++
21 files changed, 320 insertions(+), 48 deletions(-)
diff --git a/docs/zh-CN/concepts/datascope-and-datachain.md b/docs/zh-CN/concepts/datascope-and-datachain.md
index a4042e859..9c3be10d2 100755
--- a/docs/zh-CN/concepts/datascope-and-datachain.md
+++ b/docs/zh-CN/concepts/datascope-and-datachain.md
@@ -456,3 +456,78 @@ url 中的参数会进入顶层数据域,比如下面的例子,可以点击[
"body": "${word}"
}
```
+
+## 隐藏数据
+
+数据中还有以下字段不会被枚举到,但是可以读取:
+
+- `__prev` 修改前的值
+- `__changeReason` 修改原因
+- `__changeReason.type` 修改原因类型
+ - `input` 用户输入
+ - `api` api 接口返回触发
+ - `formula` 公式计算触发
+ - `hide` 隐藏属性变化触发
+ - `init` 表单项初始化触发
+ - `action` 事件动作触发
+- `__super` 数据链的上一级
+
+> `__changeReason` 字段在 amis 6.9.0 版本开始支持
+
+```schema
+{
+ "data": {
+ "name": "amis"
+ },
+ "type": "form",
+ id: "form_data",
+ "actions": [
+ {
+ type: "button",
+ label: "接口获取",
+ actionType: "ajax",
+ api: {
+ "method": "get",
+ url: "/api/mock2/form/saveForm",
+ mockResponse: {
+ status: 200,
+ data: {
+ name: "amis-demo"
+ }
+ }
+ }
+ },
+
+ {
+ type: "button",
+ label: "设置值",
+ onEvent: {
+ click: {
+ actions: [
+ {
+ "actionType": "setValue",
+ "componentId": "form_data",
+ "args": {
+ "value": {
+ "name": "amis-demo2"
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ ],
+ "body": [
+ {
+ type: "input-text",
+ name: "name",
+ label: "姓名"
+ },
+ {
+ type: "tpl",
+ tpl: "当前值:${name}
修改前的值:${__prev.name}
变化原因:${__changeReason|json}"
+ }
+ ]
+}
+```
diff --git a/packages/amis-core/src/WithStore.tsx b/packages/amis-core/src/WithStore.tsx
index 057e5643a..8b520770c 100644
--- a/packages/amis-core/src/WithStore.tsx
+++ b/packages/amis-core/src/WithStore.tsx
@@ -258,7 +258,8 @@ export function HocStoreFactory(renderer: {
...this.formatData(props.data)
}),
(props.updatePristineAfterStoreDataReInit ??
- props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false
+ props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false,
+ props.data?.__changeReason
);
}
} else if (
@@ -293,7 +294,9 @@ export function HocStoreFactory(renderer: {
))
}),
(props.updatePristineAfterStoreDataReInit ??
- props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false
+ props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false,
+
+ props.data?.__changeReason
);
} else if (props.data && (props.data as any).__super) {
store.initData(
@@ -325,13 +328,15 @@ export function HocStoreFactory(renderer: {
))
}),
(props.updatePristineAfterStoreDataReInit ??
- props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false
+ props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false,
+ props.data?.__changeReason
);
} else {
store.initData(
createObject(props.scope, props.data),
(props.updatePristineAfterStoreDataReInit ??
- props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false
+ props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false,
+ props.data?.__changeReason
);
}
} else if (
@@ -358,7 +363,9 @@ export function HocStoreFactory(renderer: {
(props.updatePristineAfterStoreDataReInit ??
props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false ||
(store.storeType === 'FormStore' &&
- prevProps.store?.storeType === 'CRUDStore')
+ prevProps.store?.storeType === 'CRUDStore'),
+
+ props.data?.__changeReason
);
}
// nextProps.data.__super !== props.data.__super) &&
@@ -376,7 +383,9 @@ export function HocStoreFactory(renderer: {
...store.data
}),
(props.updatePristineAfterStoreDataReInit ??
- props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false
+ props.dataUpdatedAt !== prevProps.dataUpdatedAt) === false,
+
+ props.data?.__changeReason
);
}
}
diff --git a/packages/amis-core/src/renderers/Form.tsx b/packages/amis-core/src/renderers/Form.tsx
index 5a24a34aa..1eb78a1e3 100644
--- a/packages/amis-core/src/renderers/Form.tsx
+++ b/packages/amis-core/src/renderers/Form.tsx
@@ -11,7 +11,8 @@ import {
ClassName,
BaseApiObject,
SchemaExpression,
- SchemaClassName
+ SchemaClassName,
+ DataChangeReason
} from '../types';
import {filter, evalExpression} from '../utils/tpl';
import getExprProperties from '../utils/filter-schema';
@@ -633,7 +634,9 @@ export default class Form extends React.Component {
successMessage: fetchSuccess,
errorMessage: fetchFailed,
onSuccess: (json: Payload, data: any) => {
- store.setValues(data);
+ store.setValues(data, undefined, undefined, undefined, {
+ type: 'api'
+ });
if (
!isEffectiveApi(initAsyncApi, store.data) ||
@@ -968,7 +971,9 @@ export default class Form extends React.Component {
setValues(value: any, replace?: boolean) {
const {store} = this.props;
this.flush();
- store.setValues(value, undefined, replace);
+ store.setValues(value, undefined, replace, undefined, {
+ type: 'action'
+ });
}
async submit(
@@ -1056,13 +1061,23 @@ export default class Form extends React.Component {
value: any,
name: string,
submit: boolean,
- changePristine = false
+ changePristine = false,
+ changeReason?: DataChangeReason
) {
const {store, formLazyChange, persistDataKeys} = this.props;
if (typeof name !== 'string') {
return;
}
- store.changeValue(name, value, changePristine);
+ store.changeValue(
+ name,
+ value,
+ changePristine,
+ undefined,
+ undefined,
+ changeReason || {
+ type: 'input'
+ }
+ );
if (!changePristine || typeof value !== 'undefined') {
(formLazyChange === false ? this.emitChange : this.lazyEmitChange)(
submit
@@ -1131,9 +1146,21 @@ export default class Form extends React.Component {
}
}
- handleBulkChange(values: Object, submit: boolean) {
+ handleBulkChange(
+ values: Object,
+ submit: boolean,
+ changeReason?: DataChangeReason
+ ) {
const {onChange, store, formLazyChange} = this.props;
- store.setValues(values);
+ store.setValues(
+ values,
+ undefined,
+ undefined,
+ undefined,
+ changeReason || {
+ type: 'input'
+ }
+ );
// store.updateData(values);
// store.items.forEach(formItem => {
diff --git a/packages/amis-core/src/renderers/Item.tsx b/packages/amis-core/src/renderers/Item.tsx
index c6e51e6c4..9fa8f0b69 100644
--- a/packages/amis-core/src/renderers/Item.tsx
+++ b/packages/amis-core/src/renderers/Item.tsx
@@ -27,6 +27,7 @@ import {
BaseApiObject,
BaseSchemaWithoutType,
ClassName,
+ DataChangeReason,
Schema
} from '../types';
import {HocStoreFactory} from '../WithStore';
@@ -530,7 +531,8 @@ export interface FormItemProps extends RendererProps {
) => void;
onBulkChange?: (
values: {[propName: string]: any},
- submitOnChange?: boolean
+ submitOnChange?: boolean,
+ changeReason?: DataChangeReason
) => void;
addHook: (
fn: Function,
diff --git a/packages/amis-core/src/renderers/wrapControl.tsx b/packages/amis-core/src/renderers/wrapControl.tsx
index 090349f0e..ef5ccdd1f 100644
--- a/packages/amis-core/src/renderers/wrapControl.tsx
+++ b/packages/amis-core/src/renderers/wrapControl.tsx
@@ -28,7 +28,7 @@ import {observer} from 'mobx-react';
import hoistNonReactStatic from 'hoist-non-react-statics';
import {withRootStore} from '../WithRootStore';
import {FormBaseControl, FormItemWrap} from './Item';
-import {Api} from '../types';
+import {Api, DataChangeReason} from '../types';
import {TableStore} from '../store/table';
import pick from 'lodash/pick';
import {
@@ -75,14 +75,19 @@ export interface ControlOutterProps extends RendererProps {
value: any,
name: string,
submit?: boolean,
- changePristine?: boolean
+ changePristine?: boolean,
+ changeReason?: DataChangeReason
) => void;
formItemDispatchEvent: (type: string, data: any) => void;
formItemRef?: (control: any) => void;
}
export interface ControlProps {
- onBulkChange?: (values: Object) => void;
+ onBulkChange?: (
+ values: Object,
+ submitOnChange?: boolean,
+ changeReason?: DataChangeReason
+ ) => void;
onChange?: (value: any, name: string, submit: boolean) => void;
store: IIRendererStore;
}
@@ -535,7 +540,9 @@ export function wrapControl<
formItem.removeSubFormItem(this.model);
this.model.clearValueOnHidden &&
- this.model.form?.deleteValueByName(this.model.name);
+ this.model.form?.deleteValueByName(this.model.name, {
+ type: 'hide'
+ });
isAlive(rootStore) && rootStore.removeStore(this.model);
}
@@ -691,7 +698,10 @@ export function wrapControl<
);
}
- this.model.changeTmpValue(value, 'input');
+ this.model.changeTmpValue(
+ value,
+ type === 'formula' ? 'formulaChanged' : 'input'
+ );
if (changeImmediately || conrolChangeImmediately || !formInited) {
this.emitChange(submitOnChange);
@@ -772,12 +782,44 @@ export function wrapControl<
return;
}
+ const changeReason: DataChangeReason = {
+ type: 'input'
+ };
+
+ if (model.changeMotivation === 'formulaChanged') {
+ changeReason.type = 'formula';
+ } else if (
+ model.changeMotivation === 'initialValue' ||
+ model.changeMotivation === 'formInited' ||
+ model.changeMotivation === 'defaultValue'
+ ) {
+ changeReason.type = 'init';
+ }
+
if (model.extraName) {
const values = model.splitExtraValue(value);
- onChange?.(values[0], model.name);
- onChange?.(values[1], model.extraName, submitOnChange === true);
+ onChange?.(
+ values[0],
+ model.name,
+ undefined,
+ undefined,
+ changeReason
+ );
+ onChange?.(
+ values[1],
+ model.extraName,
+ submitOnChange === true,
+ undefined,
+ changeReason
+ );
} else {
- onChange?.(value, model.name, submitOnChange === true);
+ onChange?.(
+ value,
+ model.name,
+ submitOnChange === true,
+ undefined,
+ changeReason
+ );
}
this.checkValidate();
}
diff --git a/packages/amis-core/src/store/form.ts b/packages/amis-core/src/store/form.ts
index 617248073..c675ebea7 100644
--- a/packages/amis-core/src/store/form.ts
+++ b/packages/amis-core/src/store/form.ts
@@ -5,7 +5,13 @@ import toPairs from 'lodash/toPairs';
import pick from 'lodash/pick';
import {ServiceStore} from './service';
import type {IFormItemStore} from './formItem';
-import {Api, ApiObject, fetchOptions, Payload} from '../types';
+import {
+ Api,
+ ApiObject,
+ DataChangeReason,
+ fetchOptions,
+ Payload
+} from '../types';
import {ServerError} from '../utils/errors';
import {
getVariable,
@@ -168,9 +174,10 @@ export const FormStore = ServiceStore.named('FormStore')
values: object,
tag?: object,
replace?: boolean,
- concatFields?: string | string[]
+ concatFields?: string | string[],
+ changeReason?: DataChangeReason
) {
- self.updateData(values, tag, replace, concatFields);
+ self.updateData(values, tag, replace, concatFields, changeReason);
// 如果数据域中有数据变化,就都reset一下,去掉之前残留的验证消息
self.items.forEach(item => {
@@ -209,7 +216,8 @@ export const FormStore = ServiceStore.named('FormStore')
name: string,
value: any,
isPristine: boolean = false,
- force: boolean = false
+ force: boolean = false,
+ changeReason?: DataChangeReason
) {
// 没有变化就不跑了。
const origin = getVariable(self.data, name, false);
@@ -257,13 +265,22 @@ export const FormStore = ServiceStore.named('FormStore')
});
}
+ changeReason &&
+ Object.isExtensible(data) &&
+ Object.defineProperty(data, '__changeReason', {
+ value: changeReason,
+ enumerable: false,
+ configurable: false,
+ writable: false
+ });
+
self.data = data;
// 同步 options
syncOptions();
}
- function deleteValueByName(name: string) {
+ function deleteValueByName(name: string, changeReason?: DataChangeReason) {
const prev = self.data;
const data = cloneObject(self.data);
@@ -287,6 +304,15 @@ export const FormStore = ServiceStore.named('FormStore')
}
deleteVariable(data, name);
+
+ changeReason &&
+ Object.isExtensible(data) &&
+ Object.defineProperty(data, '__changeReason', {
+ value: changeReason,
+ enumerable: false,
+ configurable: false,
+ writable: false
+ });
self.data = data;
}
@@ -374,7 +400,10 @@ export const FormStore = ServiceStore.named('FormStore')
}
: undefined,
!!(api as ApiObject).replaceData,
- (api as ApiObject).concatDataFields
+ (api as ApiObject).concatDataFields,
+ {
+ type: 'api'
+ }
);
}
diff --git a/packages/amis-core/src/store/iRenderer.ts b/packages/amis-core/src/store/iRenderer.ts
index dad28c5a1..741660fd7 100644
--- a/packages/amis-core/src/store/iRenderer.ts
+++ b/packages/amis-core/src/store/iRenderer.ts
@@ -18,6 +18,7 @@ import {
extractObjectChain,
injectObjectChain
} from '../utils';
+import {DataChangeReason} from '../types';
export const iRendererStore = StoreNode.named('iRendererStore')
.props({
@@ -66,7 +67,11 @@ export const iRendererStore = StoreNode.named('iRendererStore')
top = value;
},
- initData(data: object = {}, skipSetPristine = false) {
+ initData(
+ data: object = {},
+ skipSetPristine = false,
+ changeReason?: DataChangeReason
+ ) {
self.initedAt = Date.now();
if (self.data.__tag) {
@@ -78,6 +83,15 @@ export const iRendererStore = StoreNode.named('iRendererStore')
self.pristineRaw = data;
}
+ changeReason &&
+ Object.isExtensible(data) &&
+ Object.defineProperty(data, '__changeReason', {
+ value: changeReason,
+ enumerable: false,
+ configurable: false,
+ writable: false
+ });
+
self.data = data;
self.upStreamData = data;
},
@@ -90,7 +104,8 @@ export const iRendererStore = StoreNode.named('iRendererStore')
data: object = {},
tag?: object,
replace?: boolean,
- concatFields?: string | string[]
+ concatFields?: string | string[],
+ changeReason?: DataChangeReason
) {
if (concatFields) {
data = concatData(data, self.data, concatFields);
@@ -118,6 +133,15 @@ export const iRendererStore = StoreNode.named('iRendererStore')
writable: false
});
+ changeReason &&
+ Object.isExtensible(newData) &&
+ Object.defineProperty(newData, '__changeReason', {
+ value: changeReason,
+ enumerable: false,
+ configurable: false,
+ writable: false
+ });
+
self.data = newData;
},
@@ -126,7 +150,8 @@ export const iRendererStore = StoreNode.named('iRendererStore')
value: any,
changePristine?: boolean,
force?: boolean,
- otherModifier?: (data: Object) => void
+ otherModifier?: (data: Object) => void,
+ changeReason?: DataChangeReason
) {
if (!name) {
return;
@@ -183,6 +208,15 @@ export const iRendererStore = StoreNode.named('iRendererStore')
});
}
+ changeReason &&
+ Object.isExtensible(data) &&
+ Object.defineProperty(data, '__changeReason', {
+ value: changeReason,
+ enumerable: false,
+ configurable: false,
+ writable: false
+ });
+
self.data = data;
},
diff --git a/packages/amis-core/src/store/service.ts b/packages/amis-core/src/store/service.ts
index 70b46d0a9..9f8c82702 100644
--- a/packages/amis-core/src/store/service.ts
+++ b/packages/amis-core/src/store/service.ts
@@ -202,7 +202,10 @@ export const ServiceStore = iRendererStore
normalizeApiResponseData(json.data),
undefined,
!!(api as ApiObject).replaceData,
- (api as ApiObject).concatDataFields
+ (api as ApiObject).concatDataFields,
+ {
+ type: 'api'
+ }
);
self.hasRemoteData = true;
@@ -301,7 +304,10 @@ export const ServiceStore = iRendererStore
normalizeApiResponseData(json.data),
undefined,
!!(api as ApiObject).replaceData,
- (api as ApiObject).concatDataFields
+ (api as ApiObject).concatDataFields,
+ {
+ type: 'api'
+ }
);
}
@@ -471,7 +477,10 @@ export const ServiceStore = iRendererStore
json.data.data,
undefined,
!!(api as ApiObject).replaceData,
- (api as ApiObject).concatDataFields
+ (api as ApiObject).concatDataFields,
+ {
+ type: 'api'
+ }
);
}
diff --git a/packages/amis-core/src/types.ts b/packages/amis-core/src/types.ts
index e95954a9a..5f4458bec 100644
--- a/packages/amis-core/src/types.ts
+++ b/packages/amis-core/src/types.ts
@@ -405,9 +405,38 @@ export interface PlainObject {
[propsName: string]: any;
}
+export interface DataChangeReason {
+ type:
+ | 'input' // 用户输入
+ | 'api' // api 接口返回触发
+ | 'formula' // 公式计算触发
+ | 'hide' // 隐藏属性变化触发
+ | 'init' // 表单项初始化触发
+ | 'action'; // 事件动作触发
+
+ // 变化的字段名
+ // 如果是整体变化,那么是 undefined
+ name?: string;
+
+ // 变化的值
+ value?: any;
+}
+
export interface RendererData {
[propsName: string]: any;
+ /**
+ * 记录变化前的数据
+ */
__prev?: RendererDataAlias;
+
+ /**
+ * 记录变化的信息
+ */
+ __changeReason?: DataChangeReason;
+
+ /**
+ * 记录上层数据
+ */
__super?: RendererData;
}
type RendererDataAlias = RendererData;
diff --git a/packages/amis-editor-core/src/plugin.ts b/packages/amis-editor-core/src/plugin.ts
index 4bea29a08..af335b75a 100644
--- a/packages/amis-editor-core/src/plugin.ts
+++ b/packages/amis-editor-core/src/plugin.ts
@@ -18,7 +18,7 @@ import type {RendererConfig, Schema} from 'amis-core';
import type {MenuDivider, MenuItem} from 'amis-ui/lib/components/ContextMenu';
import type {BaseSchema, SchemaCollection} from 'amis';
import type {AsyncLayerOptions} from './component/AsyncLayer';
-import type {SchemaType} from 'packages/amis/src/Schema';
+import type {SchemaType} from 'amis/lib/Schema';
/**
* 区域的定义,容器渲染器都需要定义区域信息。
diff --git a/packages/amis-editor-core/src/store/editor.ts b/packages/amis-editor-core/src/store/editor.ts
index a044ae575..7b70ec6b4 100644
--- a/packages/amis-editor-core/src/store/editor.ts
+++ b/packages/amis-editor-core/src/store/editor.ts
@@ -25,7 +25,7 @@ import {
addModal,
mergeDefinitions,
getModals
-} from '../../src/util';
+} from '../util';
import {
InsertEventContext,
PluginEvent,
@@ -60,8 +60,8 @@ import {EditorNode, EditorNodeType} from './node';
import findIndex from 'lodash/findIndex';
import {matchSorter} from 'match-sorter';
import debounce from 'lodash/debounce';
-import type {DialogSchema} from '../../../amis/src/renderers/Dialog';
-import type {DrawerSchema} from '../../../amis/src/renderers/Drawer';
+import type {DialogSchema} from 'amis/lib/renderers/Dialog';
+import type {DrawerSchema} from 'amis/lib/renderers/Drawer';
import getLayoutInstance from '../layout';
export interface SchemaHistory {
diff --git a/packages/amis-editor-core/src/util.ts b/packages/amis-editor-core/src/util.ts
index 22e4af8ff..f8c8f3f44 100644
--- a/packages/amis-editor-core/src/util.ts
+++ b/packages/amis-editor-core/src/util.ts
@@ -23,8 +23,8 @@ import merge from 'lodash/merge';
import {EditorModalBody} from './store/editor';
import {filter} from 'lodash';
import type {SchemaType} from 'amis/lib/Schema';
-import type {DialogSchema} from '../../amis/src/renderers/Dialog';
-import type {DrawerSchema} from '../../amis/src/renderers/Drawer';
+import type {DialogSchema} from 'amis/lib/renderers/Dialog';
+import type {DrawerSchema} from 'amis/lib/renderers/Drawer';
const {
guid,
diff --git a/packages/amis-editor/src/plugin/Dialog.tsx b/packages/amis-editor/src/plugin/Dialog.tsx
index 213db6ce0..6ea63e26f 100644
--- a/packages/amis-editor/src/plugin/Dialog.tsx
+++ b/packages/amis-editor/src/plugin/Dialog.tsx
@@ -21,7 +21,7 @@ import {
import {getEventControlConfig} from '../renderer/event-control/helper';
import omit from 'lodash/omit';
import type {RendererConfig, Schema} from 'amis-core';
-import {ModalProps} from 'amis-ui/src/components/Modal';
+import {ModalProps} from 'amis-ui/lib/components/Modal';
import ModalSettingPanel from '../component/ModalSettingPanel';
import find from 'lodash/find';
diff --git a/packages/amis-editor/src/renderer/FormulaControl.tsx b/packages/amis-editor/src/renderer/FormulaControl.tsx
index 302da9e62..27914cba9 100644
--- a/packages/amis-editor/src/renderer/FormulaControl.tsx
+++ b/packages/amis-editor/src/renderer/FormulaControl.tsx
@@ -27,7 +27,7 @@ import {getVariables, getQuickVariables, utils} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core';
import type {VariableItem, FuncGroup} from 'amis-ui';
-import {SchemaType} from 'packages/amis/src/Schema';
+import {SchemaType} from 'amis/lib/Schema';
export enum FormulaDateType {
NotDate, // 不是时间类
diff --git a/packages/amis-editor/src/renderer/StatusControl.tsx b/packages/amis-editor/src/renderer/StatusControl.tsx
index e5e765543..edfe8eea0 100644
--- a/packages/amis-editor/src/renderer/StatusControl.tsx
+++ b/packages/amis-editor/src/renderer/StatusControl.tsx
@@ -10,7 +10,7 @@ import {autobind, getSchemaTpl} from 'amis-editor-core';
import type {FormControlProps} from 'amis-core';
import type {SchemaCollection} from 'amis';
-import type {FormSchema} from '../../../amis/src/Schema';
+import type {FormSchema} from 'amis/lib/Schema';
export interface StatusControlProps extends FormControlProps {
name: string;
diff --git a/packages/amis-editor/src/renderer/event-control/DialogActionPanel.tsx b/packages/amis-editor/src/renderer/event-control/DialogActionPanel.tsx
index 19d300e0f..b857f3cc7 100644
--- a/packages/amis-editor/src/renderer/event-control/DialogActionPanel.tsx
+++ b/packages/amis-editor/src/renderer/event-control/DialogActionPanel.tsx
@@ -23,7 +23,7 @@ import {
Select,
Switch
} from 'amis-ui';
-import type {EditorModalBody} from '../../../../amis-editor-core/src/store/editor';
+import type {EditorModalBody} from 'amis-editor-core/lib/store/editor';
export interface DialogActionPanelProps extends RendererProps {
manager: EditorManager;
diff --git a/packages/amis-editor/src/renderer/event-control/index.tsx b/packages/amis-editor/src/renderer/event-control/index.tsx
index bda247607..95002b2f7 100644
--- a/packages/amis-editor/src/renderer/event-control/index.tsx
+++ b/packages/amis-editor/src/renderer/event-control/index.tsx
@@ -47,7 +47,7 @@ import {
} from 'amis-editor-core';
export * from './helper';
import {i18n as _i18n} from 'i18n-runtime';
-import type {VariableItem} from 'amis-ui/src/components/formula/CodeEditor';
+import type {VariableItem} from 'amis-ui/lib/components/formula/CodeEditor';
import {reaction} from 'mobx';
import {updateComponentContext} from 'amis-editor-core';
diff --git a/packages/amis-editor/src/tpl/common.tsx b/packages/amis-editor/src/tpl/common.tsx
index b5b257db9..3af88f4cd 100644
--- a/packages/amis-editor/src/tpl/common.tsx
+++ b/packages/amis-editor/src/tpl/common.tsx
@@ -10,7 +10,7 @@ import type {SchemaObject} from 'amis';
import flatten from 'lodash/flatten';
import {InputComponentName} from '../component/InputComponentName';
import {FormulaDateType} from '../renderer/FormulaControl';
-import type {VariableItem} from 'amis-ui/src/components/formula/CodeEditor';
+import type {VariableItem} from 'amis-ui/lib/components/formula/CodeEditor';
import reduce from 'lodash/reduce';
import map from 'lodash/map';
import omit from 'lodash/omit';
diff --git a/packages/amis/__tests__/renderers/CRUDfilter.test.tsx b/packages/amis/__tests__/renderers/CRUDfilter.test.tsx
index 5c33b513f..63bb2a714 100644
--- a/packages/amis/__tests__/renderers/CRUDfilter.test.tsx
+++ b/packages/amis/__tests__/renderers/CRUDfilter.test.tsx
@@ -307,7 +307,7 @@ test('Picker filter2', async () => {
fireEvent.click(pickerBtn);
- await wait(500);
+ await wait(1000);
const a = container.querySelector('input[name="a"]')!;
const b = container.querySelector('input[name="b"]')!;
diff --git a/packages/amis/src/renderers/Service.tsx b/packages/amis/src/renderers/Service.tsx
index c181eee29..5f000d983 100644
--- a/packages/amis/src/renderers/Service.tsx
+++ b/packages/amis/src/renderers/Service.tsx
@@ -543,7 +543,9 @@ export default class Service extends React.Component {
);
if (!isEmpty(data) && onBulkChange && formStore) {
- onBulkChange(data);
+ onBulkChange(data, false, {
+ type: 'api'
+ });
}
result?.ok && this.initInterval(data);
diff --git a/packages/amis/src/types.ts b/packages/amis/src/types.ts
index 3b8b0718f..1e4e62afe 100644
--- a/packages/amis/src/types.ts
+++ b/packages/amis/src/types.ts
@@ -1,3 +1,4 @@
+import {DataChangeReason} from 'amis-core';
import type {ActionSchema} from './renderers/Action';
import {SchemaApi, SchemaApiObject} from './Schema';
@@ -156,7 +157,20 @@ export interface PlainObject {
export interface RendererData {
[propsName: string]: any;
+
+ /**
+ * 记录变化前的数据
+ */
__prev?: RendererDataAlias;
+
+ /**
+ * 记录变化的信息
+ */
+ __changeReason?: DataChangeReason;
+
+ /**
+ * 记录上层数据
+ */
__super?: RendererData;
}
type RendererDataAlias = RendererData;