From ad06c98315ab70ebfda4c3ab648d147886ddca14 Mon Sep 17 00:00:00 2001
From: 2betop <2betop.cn@gmail.com>
Date: Sun, 18 Feb 2024 17:03:13 +0800
Subject: [PATCH 1/9] =?UTF-8?q?style:=20=E4=BF=AE=E5=A4=8D=20table=20?=
=?UTF-8?q?=E5=9C=A8=20safari=20=E9=87=8C=E9=9D=A2=E8=AE=BE=E7=BD=AE=20wid?=
=?UTF-8?q?th=20=E6=97=A0=E6=95=88=E9=97=AE=E9=A2=98=20Close:=20#9486?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/amis-core/src/store/table.ts | 2 +-
packages/amis-core/src/utils/browser.ts | 7 +++++++
.../Form/__snapshots__/inputTable.test.tsx.snap | 2 +-
packages/amis/src/renderers/Table/ColGroup.tsx | 11 +++++++++--
packages/amis/src/renderers/Table/index.tsx | 2 +-
5 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/packages/amis-core/src/store/table.ts b/packages/amis-core/src/store/table.ts
index 8b0276ca0..9a2c4d628 100644
--- a/packages/amis-core/src/store/table.ts
+++ b/packages/amis-core/src/store/table.ts
@@ -1286,7 +1286,7 @@ export const TableStore = iRendererStore
typeof column.pristine.width === 'number'
? `width: ${column.pristine.width}px;`
: column.pristine.width
- ? `width: ${column.pristine.width};`
+ ? `width: ${column.pristine.width};min-width: ${column.pristine.width};`
: '' // todo 可能需要让修改过列宽的保持相应宽度,目前这样相当于重置了
}`;
});
diff --git a/packages/amis-core/src/utils/browser.ts b/packages/amis-core/src/utils/browser.ts
index 5cf930432..f222230b4 100644
--- a/packages/amis-core/src/utils/browser.ts
+++ b/packages/amis-core/src/utils/browser.ts
@@ -2,3 +2,10 @@ export const chromeVersion = (function getChromeVersion() {
const raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
return raw ? parseInt(raw[2], 10) : false;
})();
+
+export const isSafari =
+ navigator.vendor &&
+ navigator.vendor.indexOf('Apple') > -1 &&
+ navigator.userAgent &&
+ navigator.userAgent.indexOf('CriOS') == -1 &&
+ navigator.userAgent.indexOf('FxiOS') == -1;
diff --git a/packages/amis/__tests__/renderers/Form/__snapshots__/inputTable.test.tsx.snap b/packages/amis/__tests__/renderers/Form/__snapshots__/inputTable.test.tsx.snap
index ff84c0198..ca2d931ea 100644
--- a/packages/amis/__tests__/renderers/Form/__snapshots__/inputTable.test.tsx.snap
+++ b/packages/amis/__tests__/renderers/Form/__snapshots__/inputTable.test.tsx.snap
@@ -448,7 +448,7 @@ exports[`Renderer:input table add 1`] = `
th
// The problem is min-width CSS property.
// Before Chrome 91, min-width was ignored on COL elements. 91 no longer ignores it.
- if (typeof chromeVersion === 'number' && chromeVersion < 91) {
+ //
+ // 同时 safari 也存在类似问题,设置 colgroup>col 的 width 属性无效
+ if (isSafari || (typeof chromeVersion === 'number' && chromeVersion < 91)) {
React.useEffect(() => {
if (domRef.current) {
const ths = [].slice.call(
diff --git a/packages/amis/src/renderers/Table/index.tsx b/packages/amis/src/renderers/Table/index.tsx
index c114fadfd..58de23f3a 100644
--- a/packages/amis/src/renderers/Table/index.tsx
+++ b/packages/amis/src/renderers/Table/index.tsx
@@ -1301,8 +1301,8 @@ export default class Table extends React.Component {
if (this.resizeLine) {
return;
}
- this.props.store.syncTableWidth();
this.props.store.initTableWidth();
+ this.props.store.syncTableWidth();
this.handleOutterScroll();
callback && setTimeout(callback, 20);
}
From 9cf44211892b63c6113da8c7663122007d847cf2 Mon Sep 17 00:00:00 2001
From: 2betop <2betop.cn@gmail.com>
Date: Mon, 19 Feb 2024 11:29:19 +0800
Subject: [PATCH 2/9] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20select=20?=
=?UTF-8?q?=E7=9A=84=20autoFill=20=E5=9C=A8=20inputTable=20=E4=B8=AD?=
=?UTF-8?q?=E8=B5=8B=E5=80=BC=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE?=
=?UTF-8?q?=E9=A2=98=20Close:=20#9494?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../renderers/Form/inputTable.test.tsx | 138 ++++++++++++++++++
packages/amis/src/renderers/QuickEdit.tsx | 15 ++
2 files changed, 153 insertions(+)
diff --git a/packages/amis/__tests__/renderers/Form/inputTable.test.tsx b/packages/amis/__tests__/renderers/Form/inputTable.test.tsx
index 3238df7a5..374df81e1 100644
--- a/packages/amis/__tests__/renderers/Form/inputTable.test.tsx
+++ b/packages/amis/__tests__/renderers/Form/inputTable.test.tsx
@@ -809,3 +809,141 @@ test('Renderer:input-table formula', async () => {
]
});
});
+
+// 对应 github issue: https://github.com/baidu/amis/issues/9494
+test('Renderer:input-table autoFill', async () => {
+ const onSubmit = jest.fn();
+ const {container} = render(
+ amisRender(
+ {
+ type: 'page',
+ title: 'Hello low code',
+ body: [
+ {
+ type: 'form',
+ api: '/api/mock2/form/saveForm',
+ body: [
+ {
+ type: 'input-table',
+ name: 'table',
+ label: '表格表单',
+ columns: [
+ {
+ label: '名称',
+ name: 'name',
+ quickEdit: {
+ type: 'input-text',
+ name: 'name',
+ id: 'u:514910e73695'
+ },
+ id: 'u:97d119520d7c'
+ },
+ {
+ label: '分数',
+ name: 'score',
+ quickEdit: {
+ type: 'input-number',
+ name: 'score',
+ id: 'u:644f5984ff07'
+ },
+ id: 'u:60636ff9ed10'
+ },
+ {
+ label: '等级',
+ name: 'level',
+ quickEdit: {
+ type: 'select',
+ name: 'level',
+ autoFill: {
+ id: '$id'
+ },
+ id: 'u:38014752298b',
+ options: [
+ {
+ label: 'a',
+ value: '111',
+ id: 111
+ },
+ {
+ label: 'a1',
+ value: '1121',
+ id: 222
+ }
+ ]
+ },
+ id: 'u:bc682229ad4f'
+ }
+ ],
+ addable: true,
+ footerAddBtn: {
+ label: '新增',
+ icon: 'fa fa-plus',
+ id: 'u:a0d2d9eab4f7'
+ },
+ strictMode: true,
+ id: 'u:c296ba75753c',
+ minLength: 0,
+ editable: true,
+ removable: true
+ }
+ ],
+ id: 'u:a2f24ee3ab2d',
+ debug: true
+ }
+ ],
+ id: 'u:09eedced8bb6',
+ asideResizor: false,
+ style: {
+ boxShadow: ' 0px 0px 0px 0px transparent'
+ },
+ pullRefresh: {
+ disabled: true
+ }
+ },
+ {
+ onSubmit: onSubmit
+ },
+ makeEnv({})
+ )
+ );
+
+ await wait(200);
+
+ const add = container.querySelector('.cxd-InputTable-toolbar button');
+ fireEvent.click(add!);
+ await wait(200);
+
+ fireEvent.change(container.querySelector('input[name="name"]')!, {
+ target: {value: 'a1'}
+ });
+ await wait(200);
+
+ fireEvent.change(container.querySelector('input[name="score"]')!, {
+ target: {value: '123'}
+ });
+ await wait(200);
+
+ fireEvent.click(container.querySelector('.cxd-Select')!);
+ await wait(200);
+ fireEvent.click(container.querySelector('.cxd-Select-menu [role="option"]')!);
+ await wait(200);
+
+ fireEvent.click(container.querySelector('.cxd-OperationField button')!);
+ await wait(200);
+
+ const submitBtn = container.querySelector('button[type=submit]');
+ fireEvent.click(submitBtn!);
+ await wait(200);
+
+ expect(onSubmit).toBeCalled();
+ expect(onSubmit.mock.calls[0][0]).toEqual({
+ table: [
+ {
+ id: 111,
+ name: 'a1',
+ score: 123,
+ level: '111'
+ }
+ ]
+ });
+});
diff --git a/packages/amis/src/renderers/QuickEdit.tsx b/packages/amis/src/renderers/QuickEdit.tsx
index fc444b8c2..0b2cd5206 100644
--- a/packages/amis/src/renderers/QuickEdit.tsx
+++ b/packages/amis/src/renderers/QuickEdit.tsx
@@ -140,6 +140,7 @@ export const HocQuickEdit =
this.handleInit = this.handleInit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleFormItemChange = this.handleFormItemChange.bind(this);
+ this.handleBulkChange = this.handleBulkChange.bind(this);
this.state = {
isOpened: false
@@ -379,6 +380,18 @@ export const HocQuickEdit =
);
}
+ // autoFill 是通过 onBulkChange 触发的
+ // quickEdit 需要拦截这个,否则修改的数据就是错的
+ handleBulkChange(values: any) {
+ const {onQuickChange, quickEdit} = this.props;
+ onQuickChange(
+ values,
+ (quickEdit as QuickEditConfig).saveImmediately,
+ false,
+ quickEdit as QuickEditConfig
+ );
+ }
+
openQuickEdit() {
currentOpened = this;
this.setState({
@@ -595,6 +608,7 @@ export const HocQuickEdit =
mode: 'normal',
value: getPropValue(this.props) ?? '',
onChange: this.handleFormItemChange,
+ onBulkChange: this.handleBulkChange,
ref: this.formItemRef,
defaultStatic: false
});
@@ -608,6 +622,7 @@ export const HocQuickEdit =
simpleMode: true,
onInit: this.handleInit,
onChange: this.handleChange,
+ onBulkChange: this.handleBulkChange,
formLazyChange: false,
canAccessSuperData,
disabled,
From 2f92d68d79e518fd55bff01dc1a3cfca795e8f9e Mon Sep 17 00:00:00 2001
From: 2betop <2betop.cn@gmail.com>
Date: Mon, 19 Feb 2024 14:36:31 +0800
Subject: [PATCH 3/9] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20mapping=20?=
=?UTF-8?q?=E7=BB=93=E5=90=88=E5=85=B6=E4=BB=96=E7=BB=84=E4=BB=B6=E5=85=9C?=
=?UTF-8?q?=E5=BA=95=E6=98=BE=E7=A4=BA=E6=97=B6=E5=8F=96=E5=80=BC=E9=94=99?=
=?UTF-8?q?=E8=AF=AF=20Close:=20#9613?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../amis/__tests__/renderers/Mapping.test.tsx | 413 +++++++++++-------
packages/amis/src/renderers/Mapping.tsx | 8 +-
2 files changed, 259 insertions(+), 162 deletions(-)
diff --git a/packages/amis/__tests__/renderers/Mapping.test.tsx b/packages/amis/__tests__/renderers/Mapping.test.tsx
index 1df1ca15e..fa5e09984 100644
--- a/packages/amis/__tests__/renderers/Mapping.test.tsx
+++ b/packages/amis/__tests__/renderers/Mapping.test.tsx
@@ -1,137 +1,156 @@
import {render} from '@testing-library/react';
import '../../src';
import {render as amisRender} from '../../src';
-import {makeEnv} from '../helper';
+import {makeEnv, wait} from '../helper';
-const tag = (label: string) => render(
- amisRender(
- {type: 'tag', label},
- {},
- makeEnv({})
- )
-).container;
+const tag = (label: string) =>
+ render(amisRender({type: 'tag', label}, {}, makeEnv({}))).container;
test('Renderer:mapping width object map', async () => {
- const setup = (value?: any) => render(
- amisRender(
- {
- type: 'mapping',
- map: {
- 1: "漂亮",
- 2: "开心",
- 3: "惊吓",
- 4: "紧张",
- '*': '其他',
+ const setup = (value?: any) =>
+ render(
+ amisRender(
+ {
+ type: 'mapping',
+ map: {
+ 1: '漂亮',
+ 2: '开心',
+ 3: '惊吓',
+ 4: '紧张',
+ '*': '其他'
+ },
+ ...(value !== undefined ? {value} : {})
},
- ...(value !== undefined ? {value} : {})
- },
- {},
- makeEnv({})
- )
- ).container;
+ {},
+ makeEnv({})
+ )
+ ).container;
- const noValue = setup().querySelector('.cxd-MappingField .text-muted')! as HTMLElement;
+ const noValue = setup().querySelector(
+ '.cxd-MappingField .text-muted'
+ )! as HTMLElement;
expect(noValue.innerHTML).toBe('-');
- const value1 = setup(1).querySelector('.cxd-MappingField .cxd-TplField span')! as HTMLElement;
+ const value1 = setup(1).querySelector(
+ '.cxd-MappingField .cxd-TplField span'
+ )! as HTMLElement;
expect(value1.innerHTML).toBe('漂亮');
- const value5 = setup(5).querySelector('.cxd-MappingField .cxd-TplField span')! as HTMLElement;
+ const value5 = setup(5).querySelector(
+ '.cxd-MappingField .cxd-TplField span'
+ )! as HTMLElement;
expect(value5.innerHTML).toBe('其他');
});
test('Renderer:mapping width array map', async () => {
- const setup = (value?: any) => render(
- amisRender(
- {
- type: 'mapping',
- map: [
- {1: "漂亮"},
- {2: "开心"},
- {3: "惊吓"},
- {4: "紧张"},
- {'*': '其他'}
- ],
- ...(value !== undefined ? {value} : {})
- },
- {},
- makeEnv({})
- )
- ).container;
+ const setup = (value?: any) =>
+ render(
+ amisRender(
+ {
+ type: 'mapping',
+ map: [
+ {1: '漂亮'},
+ {2: '开心'},
+ {3: '惊吓'},
+ {4: '紧张'},
+ {'*': '其他'}
+ ],
+ ...(value !== undefined ? {value} : {})
+ },
+ {},
+ makeEnv({})
+ )
+ ).container;
- const noValue = setup().querySelector('.cxd-MappingField .text-muted')! as HTMLElement;
+ const noValue = setup().querySelector(
+ '.cxd-MappingField .text-muted'
+ )! as HTMLElement;
expect(noValue.innerHTML).toBe('-');
- const value1 = setup(1).querySelector('.cxd-MappingField .cxd-TplField span')! as HTMLElement;
+ const value1 = setup(1).querySelector(
+ '.cxd-MappingField .cxd-TplField span'
+ )! as HTMLElement;
expect(value1.innerHTML).toBe('漂亮');
- const value5 = setup(5).querySelector('.cxd-MappingField .cxd-TplField span')! as HTMLElement;
+ const value5 = setup(5).querySelector(
+ '.cxd-MappingField .cxd-TplField span'
+ )! as HTMLElement;
expect(value5.innerHTML).toBe('其他');
});
test('Renderer:mapping attr: valueField and labelField', async () => {
- const setup = (value?: any) => render(
- amisRender(
- {
- type: 'mapping',
- map: [
- {
- name: 1,
- text: '漂亮'
- },
- {
- name: 2,
- text: '开心'
- },
- {
- name: '*',
- text: '其他'
- }
- ],
- labelField: 'text',
- valueField: 'name',
- ...(value !== undefined ? {value} : {})
- },
- {},
- makeEnv({})
- )
- ).container;
+ const setup = (value?: any) =>
+ render(
+ amisRender(
+ {
+ type: 'mapping',
+ map: [
+ {
+ name: 1,
+ text: '漂亮'
+ },
+ {
+ name: 2,
+ text: '开心'
+ },
+ {
+ name: '*',
+ text: '其他'
+ }
+ ],
+ labelField: 'text',
+ valueField: 'name',
+ ...(value !== undefined ? {value} : {})
+ },
+ {},
+ makeEnv({})
+ )
+ ).container;
- const noValue = setup().querySelector('.cxd-MappingField .text-muted')! as HTMLElement;
+ const noValue = setup().querySelector(
+ '.cxd-MappingField .text-muted'
+ )! as HTMLElement;
expect(noValue.innerHTML).toBe('-');
- const value1 = setup(1).querySelector('.cxd-MappingField .cxd-TplField span')! as HTMLElement;
+ const value1 = setup(1).querySelector(
+ '.cxd-MappingField .cxd-TplField span'
+ )! as HTMLElement;
expect(value1.innerHTML).toBe('漂亮');
- const value5 = setup(5).querySelector('.cxd-MappingField .cxd-TplField span')! as HTMLElement;
+ const value5 = setup(5).querySelector(
+ '.cxd-MappingField .cxd-TplField span'
+ )! as HTMLElement;
expect(value5.innerHTML).toBe('其他');
});
test('Renderer:mapping attr: itemSchema when simple map', async () => {
- const setup = (value?: any) => render(
- amisRender(
- {
- type: 'mapping',
- map: [
- {1: "漂亮"},
- {2: "开心"},
- {3: "惊吓"},
- {4: "紧张"},
- {'*': '其他'}
- ],
- valueField: 'name',
- ...(value !== undefined ? {value} : {}),
- itemSchema: {
- type: 'tag',
- label: '${item}'
- }
- },
- {},
- makeEnv({})
- )
- ).container;
+ const setup = (value?: any) =>
+ render(
+ amisRender(
+ {
+ type: 'mapping',
+ map: [
+ {1: '漂亮'},
+ {2: '开心'},
+ {3: '惊吓'},
+ {4: '紧张'},
+ {'*': '其他'}
+ ],
+ valueField: 'name',
+ ...(value !== undefined ? {value} : {}),
+ itemSchema: {
+ type: 'tag',
+ label: '${item}'
+ }
+ },
+ {},
+ makeEnv({})
+ )
+ ).container;
- const noValue = setup().querySelector('.cxd-MappingField .text-muted')! as HTMLElement;
+ const noValue = setup().querySelector(
+ '.cxd-MappingField .text-muted'
+ )! as HTMLElement;
expect(noValue.innerHTML).toBe('-');
const value1 = setup(1).querySelector('.cxd-MappingField')! as HTMLElement;
@@ -142,37 +161,40 @@ test('Renderer:mapping attr: itemSchema when simple map', async () => {
});
test('Renderer:mapping attr: itemSchema when normal map', async () => {
- const setup = (value?: any) => render(
- amisRender(
- {
- type: 'mapping',
- map: [
- {
- name: 1,
- text: '漂亮'
- },
- {
- name: 2,
- text: '开心'
- },
- {
- name: '*',
- text: '其他'
+ const setup = (value?: any) =>
+ render(
+ amisRender(
+ {
+ type: 'mapping',
+ map: [
+ {
+ name: 1,
+ text: '漂亮'
+ },
+ {
+ name: 2,
+ text: '开心'
+ },
+ {
+ name: '*',
+ text: '其他'
+ }
+ ],
+ valueField: 'name',
+ ...(value !== undefined ? {value} : {}),
+ itemSchema: {
+ type: 'tag',
+ label: '${name} ${text}'
}
- ],
- valueField: 'name',
- ...(value !== undefined ? {value} : {}),
- itemSchema: {
- type: 'tag',
- label: '${name} ${text}'
- }
- },
- {},
- makeEnv({})
- )
- ).container;
+ },
+ {},
+ makeEnv({})
+ )
+ ).container;
- const noValue = setup().querySelector('.cxd-MappingField .text-muted')! as HTMLElement;
+ const noValue = setup().querySelector(
+ '.cxd-MappingField .text-muted'
+ )! as HTMLElement;
expect(noValue.innerHTML).toBe('-');
const value1 = setup(1).querySelector('.cxd-MappingField')! as HTMLElement;
@@ -204,23 +226,24 @@ test('Renderer:mapping', async () => {
});
test('Renderer:mapping html', async () => {
- const setup = (value?: any) => render(
- amisRender(
- {
- type: 'mapping',
- map: {
- 1: "漂亮",
- 2: "开心",
- 3: "惊吓",
- 4: "紧张",
- '*': '其他'
+ const setup = (value?: any) =>
+ render(
+ amisRender(
+ {
+ type: 'mapping',
+ map: {
+ 1: "漂亮",
+ 2: "开心",
+ 3: "惊吓",
+ 4: "紧张",
+ '*': '其他'
+ },
+ ...(value !== undefined ? {value} : {})
},
- ...(value !== undefined ? {value} : {})
- },
- {},
- makeEnv({})
- )
- ).container;
+ {},
+ makeEnv({})
+ )
+ ).container;
expect(setup()).toMatchSnapshot();
expect(setup(1)).toMatchSnapshot();
@@ -228,25 +251,28 @@ test('Renderer:mapping html', async () => {
});
test('Renderer:mapping schema', async () => {
- const setup = (value?: any) => render(
- amisRender(
- {
- type: 'mapping',
- map: {
- 1: {type: 'tag', label: '漂亮'},
- 2: {type: 'tag', label: '开心'},
- 3: {type: 'tag', label: '惊吓'},
- 4: {type: 'tag', label: '紧张'},
- '*': {type: 'tag', label: '其他'}
+ const setup = (value?: any) =>
+ render(
+ amisRender(
+ {
+ type: 'mapping',
+ map: {
+ 1: {type: 'tag', label: '漂亮'},
+ 2: {type: 'tag', label: '开心'},
+ 3: {type: 'tag', label: '惊吓'},
+ 4: {type: 'tag', label: '紧张'},
+ '*': {type: 'tag', label: '其他'}
+ },
+ ...(value !== undefined ? {value} : {})
},
- ...(value !== undefined ? {value} : {})
- },
- {},
- makeEnv({})
- )
- ).container;
+ {},
+ makeEnv({})
+ )
+ ).container;
- const noValue = setup().querySelector('.cxd-MappingField .text-muted')! as HTMLElement;
+ const noValue = setup().querySelector(
+ '.cxd-MappingField .text-muted'
+ )! as HTMLElement;
expect(noValue.innerHTML).toBe('-');
const value1 = setup(1).querySelector('.cxd-MappingField')! as HTMLElement;
@@ -255,3 +281,68 @@ test('Renderer:mapping schema', async () => {
const value5 = setup(5).querySelector('.cxd-MappingField')! as HTMLElement;
expect(value5.innerHTML).toBe(tag('其他').innerHTML);
});
+
+// 对应 issue https://github.com/baidu/amis/issues/9613
+test('Renderer:mapping schema status', async () => {
+ const {container, getByText} = render(
+ amisRender(
+ {
+ type: 'page',
+ data: {
+ items: [
+ {
+ status: 1,
+ id: 1
+ }
+ ]
+ },
+ body: [
+ {
+ type: 'table',
+ title: '表格',
+ columns: [
+ {
+ name: 'id',
+ label: 'ID'
+ },
+ {
+ name: 'status',
+ label: '状态2',
+ type: 'mapping',
+ map: {
+ '*': {
+ type: 'status',
+ map: {
+ '0': 'schedule',
+ '1': 'rolling',
+ '2': 'success',
+ '3': 'fail',
+ '4': 'warning'
+ },
+ labelMap: {
+ '2': '任务成功',
+ '1': '处理中',
+ '3': '异常终止',
+ '0': '等待中',
+ '4': '已过期'
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {},
+ makeEnv({})
+ )
+ );
+
+ await wait(200);
+
+ expect(
+ [].slice
+ .call(container.querySelectorAll('tbody td'))
+ .map((td: any) => td.textContent)
+ ).toEqual(['1', '处理中']);
+});
diff --git a/packages/amis/src/renderers/Mapping.tsx b/packages/amis/src/renderers/Mapping.tsx
index 027739d12..aacc70ba2 100644
--- a/packages/amis/src/renderers/Mapping.tsx
+++ b/packages/amis/src/renderers/Mapping.tsx
@@ -253,7 +253,7 @@ export const MappingField = withStore(props =>
}
renderViewValue(value: any) {
- const {render, itemSchema, data, labelField} = this.props;
+ const {render, itemSchema, data, labelField, name} = this.props;
if (!itemSchema) {
let label = value;
@@ -265,6 +265,12 @@ export const MappingField = withStore(props =>
// object 也没有 type,不能作为schema渲染
// 默认取 label 字段
label = value['label'];
+ } else {
+ // 不会下发 value 了,所以要把 name 下发一下
+ label = {
+ name,
+ ...label
+ };
}
} else {
label = value[labelField || 'label'];
From 5072f74c345e6f95586da9ec752f1bba5380e8d9 Mon Sep 17 00:00:00 2001
From: wuduoyi
Date: Sun, 25 Feb 2024 10:46:50 +0800
Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=89=93?=
=?UTF-8?q?=E5=8D=B0=E4=BA=8B=E4=BB=B6,=20=E6=94=AF=E6=8C=81=E6=89=93?=
=?UTF-8?q?=E5=8D=B0=E5=AE=B9=E5=99=A8=E7=BB=84=E4=BB=B6=20Closes=20#9475?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/zh-CN/concepts/event-action.md | 69 +++++++++++++++++
packages/amis-core/src/actions/PrintAction.ts | 51 +++++++++++++
packages/amis-core/src/actions/index.ts | 1 +
packages/amis-core/src/renderers/Form.tsx | 6 +-
packages/amis-core/src/utils/printElement.ts | 76 +++++++++++++++++++
packages/amis-ui/scss/components/_print.scss | 13 ++++
packages/amis-ui/scss/themes/_common.scss | 2 +
packages/amis/src/renderers/CRUD.tsx | 5 +-
packages/amis/src/renderers/CRUD2.tsx | 5 +-
packages/amis/src/renderers/Container.tsx | 4 +-
packages/amis/src/renderers/Flex.tsx | 7 +-
packages/amis/src/renderers/Grid.tsx | 7 +-
packages/amis/src/renderers/Grid2D.tsx | 11 ++-
packages/amis/src/renderers/Table/index.tsx | 7 +-
packages/amis/src/renderers/TableView.tsx | 5 +-
packages/amis/src/renderers/Wrapper.tsx | 13 +++-
16 files changed, 265 insertions(+), 17 deletions(-)
create mode 100644 packages/amis-core/src/actions/PrintAction.ts
create mode 100644 packages/amis-core/src/utils/printElement.ts
create mode 100644 packages/amis-ui/scss/components/_print.scss
diff --git a/docs/zh-CN/concepts/event-action.md b/docs/zh-CN/concepts/event-action.md
index 9141b9111..693f426c0 100644
--- a/docs/zh-CN/concepts/event-action.md
+++ b/docs/zh-CN/concepts/event-action.md
@@ -1444,6 +1444,75 @@ run action ajax
| copyFormat | `string` | `text/html` | 复制格式 |
| content | [模板](../../docs/concepts/template) | - | 指定复制的内容。可用 `${xxx}` 取值 |
+### 打印
+
+> 6.2.0 及以后版本
+
+打印页面中的某个组件,对应的组件需要配置 `testid`,如果要打印多个,可以使用 `"testids": ["x", "y"]` 来打印多个组件
+
+```schema
+{
+ type: 'page',
+ body: [
+ {
+ type: 'button',
+ label: '打印',
+ level: 'primary',
+ className: 'mr-2',
+ onEvent: {
+ click: {
+ actions: [
+ {
+ actionType: 'print',
+ args: {
+ testid: 'mycrud'
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type": "crud",
+ "api": "/api/mock2/sample",
+ "testid": "mycrud",
+ "syncLocation": false,
+ "columns": [
+ {
+ "name": "id",
+ "label": "ID"
+ },
+ {
+ "name": "engine",
+ "label": "Rendering engine"
+ },
+ {
+ "name": "browser",
+ "label": "Browser"
+ },
+ {
+ "name": "platform",
+ "label": "Platform(s)"
+ },
+ {
+ "name": "version",
+ "label": "Engine version"
+ },
+ {
+ "name": "grade",
+ "label": "CSS grade"
+ }
+ ]
+ }
+ ]
+}
+```
+
+| 属性名 | 类型 | 默认值 | 说明 |
+| ------- | ---------- | ------ | ----------------- |
+| testid | `string` | | 组件的 testid |
+| testids | `string[]` | - | 多个组件的 testid |
+
### 发送邮件
通过配置`actionType: 'email'`和邮件属性实现发送邮件操作。
diff --git a/packages/amis-core/src/actions/PrintAction.ts b/packages/amis-core/src/actions/PrintAction.ts
new file mode 100644
index 000000000..852776888
--- /dev/null
+++ b/packages/amis-core/src/actions/PrintAction.ts
@@ -0,0 +1,51 @@
+import {printElements} from '../utils/printElement';
+import {RendererEvent} from '../utils/renderer-event';
+import {
+ RendererAction,
+ ListenerAction,
+ ListenerContext,
+ registerAction
+} from './Action';
+
+export interface IPrintAction extends ListenerAction {
+ actionType: 'copy';
+ args: {
+ testid?: string;
+ testids?: string[];
+ };
+}
+
+/**
+ * 打印动作
+ *
+ * @export
+ * @class PrintAction
+ * @implements {Action}
+ */
+export class PrintAction implements RendererAction {
+ async run(
+ action: IPrintAction,
+ renderer: ListenerContext,
+ event: RendererEvent
+ ) {
+ if (action.args?.testid) {
+ const element = document.querySelector(
+ `[data-testid='${action.args.testid}']`
+ );
+ if (element) {
+ printElements([element]);
+ }
+ } else if (action.args?.testids) {
+ const elements: Element[] = [];
+ action.args.testids.forEach(testid => {
+ const element = document.querySelector(`[data-testid='${testid}']`);
+ if (element) {
+ elements.push(element);
+ }
+ });
+ printElements(elements);
+ }
+ }
+}
+
+registerAction('print', new PrintAction());
diff --git a/packages/amis-core/src/actions/index.ts b/packages/amis-core/src/actions/index.ts
index 1276c0ddf..f4e99458a 100644
--- a/packages/amis-core/src/actions/index.ts
+++ b/packages/amis-core/src/actions/index.ts
@@ -19,5 +19,6 @@ import './EmailAction';
import './LinkAction';
import './ToastAction';
import './PageAction';
+import './PrintAction';
export * from './Action';
diff --git a/packages/amis-core/src/renderers/Form.tsx b/packages/amis-core/src/renderers/Form.tsx
index 494dd9cd4..22b97c9e2 100644
--- a/packages/amis-core/src/renderers/Form.tsx
+++ b/packages/amis-core/src/renderers/Form.tsx
@@ -49,7 +49,7 @@ import LazyComponent from '../components/LazyComponent';
import {isAlive} from 'mobx-state-tree';
import type {LabelAlign} from './Item';
-import {injectObjectChain} from '../utils';
+import {buildTestId, injectObjectChain} from '../utils';
import {reaction} from 'mobx';
export interface FormHorizontal {
@@ -1808,7 +1808,8 @@ export default class Form extends React.Component {
render,
staticClassName,
static: isStatic = false,
- loadingConfig
+ loadingConfig,
+ testid
} = this.props;
const {restError} = store;
@@ -1840,6 +1841,7 @@ export default class Form extends React.Component {
)}
onSubmit={this.handleFormSubmit}
noValidate
+ {...buildTestId(testid)}
>
{/* 实现回车自动提交 */}
diff --git a/packages/amis-core/src/utils/printElement.ts b/packages/amis-core/src/utils/printElement.ts
new file mode 100644
index 000000000..1045b9889
--- /dev/null
+++ b/packages/amis-core/src/utils/printElement.ts
@@ -0,0 +1,76 @@
+/**
+ * 打印元素,参考 https://github.com/szepeshazi/print-elements 里的实现
+ * 原理就是遍历节点加上打印样式,然后打印完了再清理掉
+ * 对代码做了改造和优化
+ */
+
+const hideFromPrintClass = 'pe-no-print';
+const preservePrintClass = 'pe-preserve-print';
+const preserveAncestorClass = 'pe-preserve-ancestor';
+const bodyElementName = 'BODY';
+
+function hide(element: Element) {
+ if (!element.classList.contains(preservePrintClass)) {
+ element.classList.add(hideFromPrintClass);
+ }
+}
+
+function preserve(element: Element, isStartingElement: boolean) {
+ element.classList.remove(hideFromPrintClass);
+ element.classList.add(preservePrintClass);
+ if (!isStartingElement) {
+ element.classList.add(preserveAncestorClass);
+ }
+}
+
+function clean(element: Element) {
+ element.classList.remove(hideFromPrintClass);
+ element.classList.remove(preservePrintClass);
+ element.classList.remove(preserveAncestorClass);
+}
+
+function walkSiblings(element: Element, callback: (element: Element) => void) {
+ let sibling = element.previousElementSibling;
+ while (sibling) {
+ callback(sibling);
+ sibling = sibling.previousElementSibling;
+ }
+ sibling = element.nextElementSibling;
+ while (sibling) {
+ callback(sibling);
+ sibling = sibling.nextElementSibling;
+ }
+}
+
+function attachPrintClasses(element: Element, isStartingElement: boolean) {
+ preserve(element, isStartingElement);
+ walkSiblings(element, hide);
+}
+
+function cleanup(element: Element, isStartingElement: boolean) {
+ clean(element);
+ walkSiblings(element, clean);
+}
+
+function walkTree(
+ element: Element,
+ callback: (element: Element, isStartingElement: boolean) => void
+) {
+ let currentElement: Element | null = element;
+ callback(currentElement, true);
+ currentElement = currentElement.parentElement;
+ while (currentElement && currentElement.nodeName !== bodyElementName) {
+ callback(currentElement, false);
+ currentElement = currentElement.parentElement;
+ }
+}
+
+export function printElements(elements: Element[]) {
+ for (let i = 0; i < elements.length; i++) {
+ walkTree(elements[i], attachPrintClasses);
+ }
+ window.print();
+ for (let i = 0; i < elements.length; i++) {
+ walkTree(elements[i], cleanup);
+ }
+}
diff --git a/packages/amis-ui/scss/components/_print.scss b/packages/amis-ui/scss/components/_print.scss
new file mode 100644
index 000000000..092cdc90d
--- /dev/null
+++ b/packages/amis-ui/scss/components/_print.scss
@@ -0,0 +1,13 @@
+@media print {
+ .pe-no-print {
+ display: none !important;
+ }
+
+ .pe-preserve-ancestor {
+ display: block !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ border: none !important;
+ box-shadow: none !important;
+ }
+}
diff --git a/packages/amis-ui/scss/themes/_common.scss b/packages/amis-ui/scss/themes/_common.scss
index 1d09879b2..df33798ec 100644
--- a/packages/amis-ui/scss/themes/_common.scss
+++ b/packages/amis-ui/scss/themes/_common.scss
@@ -142,3 +142,5 @@
@import '../components/debug';
@import '../components/menu';
@import '../components/overflow-tpl';
+
+@import '../components/print';
diff --git a/packages/amis/src/renderers/CRUD.tsx b/packages/amis/src/renderers/CRUD.tsx
index 3b2f4feba..66daea731 100644
--- a/packages/amis/src/renderers/CRUD.tsx
+++ b/packages/amis/src/renderers/CRUD.tsx
@@ -7,7 +7,8 @@ import {
RendererProps,
evalExpressionWithConditionBuilder,
filterTarget,
- mapTree
+ mapTree,
+ buildTestId
} from 'amis-core';
import {SchemaNode, Schema, ActionObject, PlainObject} from 'amis-core';
import {CRUDStore, ICRUDStore} from 'amis-core';
@@ -2516,6 +2517,7 @@ export default class CRUD extends React.Component {
onSearchableFromInit,
headerToolbarRender,
footerToolbarRender,
+ testid,
...rest
} = this.props;
@@ -2526,6 +2528,7 @@ export default class CRUD extends React.Component {
'is-mobile': isMobile()
})}
style={style}
+ {...buildTestId(testid)}
>
{filter && (!store.filterTogggable || store.filterVisible)
? render(
diff --git a/packages/amis/src/renderers/CRUD2.tsx b/packages/amis/src/renderers/CRUD2.tsx
index 22a990520..118c526e2 100644
--- a/packages/amis/src/renderers/CRUD2.tsx
+++ b/packages/amis/src/renderers/CRUD2.tsx
@@ -30,7 +30,8 @@ import {
isApiOutdated,
isPureVariable,
resolveVariableAndFilter,
- parsePrimitiveQueryString
+ parsePrimitiveQueryString,
+ buildTestId
} from 'amis-core';
import {Html, SpinnerExtraProps} from 'amis-ui';
import {
@@ -1308,6 +1309,7 @@ export default class CRUD2 extends React.Component {
columnsTogglable,
headerToolbarClassName,
footerToolbarClassName,
+ testid,
...rest
} = this.props;
@@ -1317,6 +1319,7 @@ export default class CRUD2 extends React.Component {
'is-loading': store.loading
})}
style={style}
+ {...buildTestId(testid)}
>
{this.renderFilter(filterSchema)}
diff --git a/packages/amis/src/renderers/Container.tsx b/packages/amis/src/renderers/Container.tsx
index 933e71bd9..f26eee69c 100644
--- a/packages/amis/src/renderers/Container.tsx
+++ b/packages/amis/src/renderers/Container.tsx
@@ -195,7 +195,8 @@ export default class Container extends React.Component<
wrapperCustomStyle,
env,
themeCss,
- baseControlClassName
+ baseControlClassName,
+ testid
} = this.props;
const finalDraggable: boolean = isPureVariable(draggable)
? resolveVariableAndFilter(draggable, data, '| raw')
@@ -231,6 +232,7 @@ export default class Container extends React.Component<
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={buildStyle(style, data)}
+ {...buildTestId(testid)}
>
{this.renderBody()}
{
wrapperCustomStyle,
env,
themeCss,
- classnames: cx
+ classnames: cx,
+ testid
} = this.props;
const styleVar = buildStyle(style, data);
const flexStyle = {
@@ -150,6 +152,7 @@ export default class Flex extends React.Component {
themeCss: wrapperCustomStyle
})
)}
+ {...buildTestId(testid)}
>
{(Array.isArray(items) ? items : items ? [items] : []).map(
(item, key) =>
diff --git a/packages/amis/src/renderers/Grid.tsx b/packages/amis/src/renderers/Grid.tsx
index 28b754bb8..5c8875a48 100644
--- a/packages/amis/src/renderers/Grid.tsx
+++ b/packages/amis/src/renderers/Grid.tsx
@@ -5,7 +5,8 @@ import {
RendererProps,
buildStyle,
CustomStyle,
- setThemeClassName
+ setThemeClassName,
+ buildTestId
} from 'amis-core';
import pick from 'lodash/pick';
import {BaseSchema, SchemaClassName, SchemaCollection} from '../Schema';
@@ -212,7 +213,8 @@ export default class Grid extends React.Component {
id,
wrapperCustomStyle,
env,
- themeCss
+ themeCss,
+ testid
} = this.props;
const styleVar = buildStyle(style, data);
return (
@@ -239,6 +241,7 @@ export default class Grid extends React.Component {
})
)}
style={styleVar}
+ {...buildTestId(testid)}
>
{this.renderColumns(this.props.columns)}
diff --git a/packages/amis/src/renderers/Grid2D.tsx b/packages/amis/src/renderers/Grid2D.tsx
index f4f989b14..3dbe1845b 100644
--- a/packages/amis/src/renderers/Grid2D.tsx
+++ b/packages/amis/src/renderers/Grid2D.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import {Renderer, RendererProps} from 'amis-core';
+import {buildTestId, Renderer, RendererProps} from 'amis-core';
import {Api, SchemaNode, Schema, ActionObject} from 'amis-core';
import {isVisible} from 'amis-core';
import {BaseSchema, SchemaObject} from '../Schema';
@@ -172,7 +172,8 @@ export default class Grid2D extends React.Component {
}
render() {
- const {grids, cols, gap, gapRow, width, rowHeight, style} = this.props;
+ const {grids, cols, gap, gapRow, width, rowHeight, style, testid} =
+ this.props;
const templateColumns = new Array(cols);
templateColumns.fill('1fr');
@@ -214,7 +215,11 @@ export default class Grid2D extends React.Component {
gridTemplateRows: templateRows.join(' ')
};
- return {this.renderGrids()} ;
+ return (
+
+ {this.renderGrids()}
+
+ );
}
}
diff --git a/packages/amis/src/renderers/Table/index.tsx b/packages/amis/src/renderers/Table/index.tsx
index c114fadfd..5ef1977c6 100644
--- a/packages/amis/src/renderers/Table/index.tsx
+++ b/packages/amis/src/renderers/Table/index.tsx
@@ -41,7 +41,8 @@ import {
resizeSensor,
offset,
getStyleNumber,
- getPropValue
+ getPropValue,
+ buildTestId
} from 'amis-core';
import {
Button,
@@ -2802,7 +2803,8 @@ export default class Table extends React.Component {
affixHeader,
autoFillHeight,
autoGenerateFilter,
- mobileUI
+ mobileUI,
+ testid
} = this.props;
this.renderedToolbars = []; // 用来记录哪些 toolbar 已经渲染了,已经渲染了就不重复渲染了。
@@ -2821,6 +2823,7 @@ export default class Table extends React.Component {
'Table--autoFillHeight': autoFillHeight
})}
style={store.buildStyles(style)}
+ {...buildTestId(testid)}
>
{autoGenerateFilter ? this.renderAutoFilterForm() : null}
{this.renderAffixHeader(tableClassName)}
diff --git a/packages/amis/src/renderers/TableView.tsx b/packages/amis/src/renderers/TableView.tsx
index 38bbf5bb7..bc1214b69 100644
--- a/packages/amis/src/renderers/TableView.tsx
+++ b/packages/amis/src/renderers/TableView.tsx
@@ -8,7 +8,8 @@ import {
RendererProps,
resolveMappingObject,
CustomStyle,
- setThemeClassName
+ setThemeClassName,
+ buildTestId
} from 'amis-core';
import {BaseSchema, SchemaObject} from '../Schema';
@@ -276,6 +277,7 @@ export default class TableView extends React.Component {
wrapperCustomStyle,
env,
themeCss,
+ testid,
baseControlClassName
} = this.props;
@@ -298,6 +300,7 @@ export default class TableView extends React.Component {
})
)}
style={{width: width, borderCollapse: 'collapse'}}
+ {...buildTestId(testid)}
>
{this.renderCaption()}
{this.renderCols()}
diff --git a/packages/amis/src/renderers/Wrapper.tsx b/packages/amis/src/renderers/Wrapper.tsx
index cb4c7ac88..b4fa79288 100644
--- a/packages/amis/src/renderers/Wrapper.tsx
+++ b/packages/amis/src/renderers/Wrapper.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import {Renderer, RendererProps} from 'amis-core';
+import {buildTestId, Renderer, RendererProps} from 'amis-core';
import {BaseSchema, SchemaCollection} from '../Schema';
import {resolveVariable} from 'amis-core';
import {SchemaNode} from 'amis-core';
@@ -59,7 +59,15 @@ export default class Wrapper extends React.Component {
}
render() {
- const {className, size, classnames: cx, style, data, wrap} = this.props;
+ const {
+ className,
+ size,
+ classnames: cx,
+ style,
+ data,
+ wrap,
+ testid
+ } = this.props;
// 期望不要使用,给 form controls 用法自动转换时使用的。
if (wrap === false) {
@@ -74,6 +82,7 @@ export default class Wrapper extends React.Component {
className
)}
style={buildStyle(style, data)}
+ {...buildTestId(testid)}
>
{this.renderBody()}
From f67d3440994a6c431953729d50e43020645a579c Mon Sep 17 00:00:00 2001
From: wuduoyi
Date: Tue, 27 Feb 2024 15:05:45 +0800
Subject: [PATCH 5/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BC=96=E8=AF=91?=
=?UTF-8?q?=E6=8A=A5=E9=94=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/amis/src/renderers/Container.tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/amis/src/renderers/Container.tsx b/packages/amis/src/renderers/Container.tsx
index f26eee69c..2a8f70d1e 100644
--- a/packages/amis/src/renderers/Container.tsx
+++ b/packages/amis/src/renderers/Container.tsx
@@ -8,7 +8,8 @@ import {
isPureVariable,
resolveVariableAndFilter,
CustomStyle,
- setThemeClassName
+ setThemeClassName,
+ buildTestId
} from 'amis-core';
import {DndContainer as DndWrapper} from 'amis-ui';
import {BaseSchema, SchemaClassName, SchemaCollection} from '../Schema';
From a5f32984a0d90244c9e79d262e5dced065f28a25 Mon Sep 17 00:00:00 2001
From: jinye
Date: Tue, 27 Feb 2024 20:39:31 +0800
Subject: [PATCH 6/9] =?UTF-8?q?fix:=20editor-=E4=BF=AE=E5=A4=8D=E7=A9=BF?=
=?UTF-8?q?=E6=A2=AD=E5=99=A8=E8=A1=A8=E6=A0=BC=E5=BD=A2=E5=BC=8F=E8=AE=BE?=
=?UTF-8?q?=E7=BD=AE=E8=A1=A8=E6=A0=BC=E5=88=97=E4=B8=8D=E5=A1=AB=E5=86=99?=
=?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=90=8D=E6=97=B6valueTpl=E4=B8=BAundefined?=
=?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../amis-editor/src/renderer/TransferTableControl.tsx | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/packages/amis-editor/src/renderer/TransferTableControl.tsx b/packages/amis-editor/src/renderer/TransferTableControl.tsx
index 638445f43..c5b87ceeb 100644
--- a/packages/amis-editor/src/renderer/TransferTableControl.tsx
+++ b/packages/amis-editor/src/renderer/TransferTableControl.tsx
@@ -324,7 +324,7 @@ export default class TransferTableOption extends React.Component<
return {
type: 'action',
actionType: 'dialog',
- label: '添加表格列',
+ label: '设置表格列',
level: 'enhance',
dialog: {
title: '设置表格列选项',
@@ -348,12 +348,14 @@ export default class TransferTableOption extends React.Component<
{
type: 'input-text',
name: 'label',
- placeholder: '标题'
+ placeholder: '标题',
+ required: true
},
{
type: 'input-text',
name: 'name',
- placeholder: '绑定字段名'
+ placeholder: '绑定字段名',
+ required: true
},
{
type: 'select',
@@ -417,7 +419,7 @@ export default class TransferTableOption extends React.Component<
{
type: 'action',
actionType: 'dialog',
- label: '添加表格行',
+ label: '设置表格行',
level: 'enhance',
disabled: columns && columns.length === 0,
block: true,
From da910d58efeae5dc4a4d54e302df050ecac56efc Mon Sep 17 00:00:00 2001
From: shenmenga
Date: Wed, 28 Feb 2024 11:44:03 +0800
Subject: [PATCH 7/9] =?UTF-8?q?fix:=20diff-editor=20=E4=B8=BB=E9=A2=98?=
=?UTF-8?q?=E8=89=B2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/amis/src/renderers/Form/DiffEditor.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/amis/src/renderers/Form/DiffEditor.tsx b/packages/amis/src/renderers/Form/DiffEditor.tsx
index 7eeb321ca..a17aa8998 100644
--- a/packages/amis/src/renderers/Form/DiffEditor.tsx
+++ b/packages/amis/src/renderers/Form/DiffEditor.tsx
@@ -73,7 +73,7 @@ function normalizeValue(value: any, language?: string) {
export class DiffEditor extends React.Component {
static defaultProps: Partial = {
language: 'javascript',
- theme: 'vs',
+ editorTheme: 'vs',
options: {
automaticLayout: false,
selectOnLineNumbers: true,
@@ -304,7 +304,7 @@ export class DiffEditor extends React.Component {
size,
options,
language,
- theme,
+ editorTheme,
classnames: cx
} = this.props;
@@ -326,7 +326,7 @@ export class DiffEditor extends React.Component {
onChange={onChange}
disabled={disabled}
language={language}
- theme={theme}
+ editorTheme={editorTheme}
editorDidMount={this.handleEditorMounted}
editorFactory={this.editorFactory}
options={{
From d1cfd3719f664efccbf97bd667ff6d4b2f033474 Mon Sep 17 00:00:00 2001
From: shenmenga
Date: Wed, 28 Feb 2024 17:14:36 +0800
Subject: [PATCH 8/9] =?UTF-8?q?feat:=20messages=20=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=B8=B2=E6=9F=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
examples/components/CRUD/Table.jsx | 11 ++++++++++-
packages/amis-core/src/store/service.ts | 4 ++--
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/examples/components/CRUD/Table.jsx b/examples/components/CRUD/Table.jsx
index 6b6178d60..6fc8585c5 100644
--- a/examples/components/CRUD/Table.jsx
+++ b/examples/components/CRUD/Table.jsx
@@ -303,7 +303,16 @@ export default {
body: {
type: 'form',
name: 'sample-edit-form',
- api: '/api/sample/$id',
+ data:{
+ env: 'test'
+ },
+ api: {
+ method:'post',
+ url:'/api/sample/$id',
+ messages:{
+ success: '成功了-${env}'
+ }
+ },
body: [
{
type: 'input-text',
diff --git a/packages/amis-core/src/store/service.ts b/packages/amis-core/src/store/service.ts
index a5357be89..90c12009c 100644
--- a/packages/amis-core/src/store/service.ts
+++ b/packages/amis-core/src/store/service.ts
@@ -6,7 +6,7 @@ import {ServerError} from '../utils/errors';
import {normalizeApiResponseData} from '../utils/api';
import {replaceText} from '../utils/replaceText';
import {concatData} from '../utils/concatData';
-
+import {filter} from 'amis-core';
export const ServiceStore = iRendererStore
.named('ServiceStore')
.props({
@@ -54,7 +54,7 @@ export const ServiceStore = iRendererStore
}
function updateMessage(msg?: string, error: boolean = false) {
- self.msg = (msg && String(msg)) || '';
+ self.msg = (msg && filter(msg, self.data)) || '';
self.error = error;
}
From f155bee8709b4a1ac71809cbfd40daf4ff98b11e Mon Sep 17 00:00:00 2001
From: liaoxuezhi <2betop.cn@gmail.com>
Date: Thu, 29 Feb 2024 15:17:29 +0800
Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=E7=BB=84=E4=BB=B6=E4=B8=AD?=
=?UTF-8?q?=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD=E7=9A=84=E7=BB=84=E4=BB=B6?=
=?UTF-8?q?=20schema=20=E4=B9=9F=E6=94=AF=E6=8C=81=E5=A4=9A=E8=AF=AD?=
=?UTF-8?q?=E8=A8=80=E8=A7=84=E5=88=99=20Close:=20#9564=20(#9610)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/amis-core/src/index.tsx | 3 +-
packages/amis-core/src/store/service.ts | 2 +
packages/amis-ui/scss/components/_app.scss | 5 +
.../amis/__tests__/renderers/App.test.tsx | 104 ++++++++++++++++++
packages/amis/src/renderers/App.tsx | 14 ++-
5 files changed, 125 insertions(+), 3 deletions(-)
create mode 100644 packages/amis/__tests__/renderers/App.test.tsx
diff --git a/packages/amis-core/src/index.tsx b/packages/amis-core/src/index.tsx
index 723e83af6..ed12e589a 100644
--- a/packages/amis-core/src/index.tsx
+++ b/packages/amis-core/src/index.tsx
@@ -206,7 +206,8 @@ export {
splitTarget,
CustomStyle,
enableDebug,
- disableDebug
+ disableDebug,
+ envOverwrite
};
export function render(
diff --git a/packages/amis-core/src/store/service.ts b/packages/amis-core/src/store/service.ts
index 90c12009c..1b5a6a8b5 100644
--- a/packages/amis-core/src/store/service.ts
+++ b/packages/amis-core/src/store/service.ts
@@ -6,6 +6,7 @@ import {ServerError} from '../utils/errors';
import {normalizeApiResponseData} from '../utils/api';
import {replaceText} from '../utils/replaceText';
import {concatData} from '../utils/concatData';
+import {envOverwrite} from '../envOverwrite';
import {filter} from 'amis-core';
export const ServiceStore = iRendererStore
.named('ServiceStore')
@@ -445,6 +446,7 @@ export const ServiceStore = iRendererStore
} else {
if (json.data) {
const env = getEnv(self);
+ json.data = envOverwrite(json.data, env.locale);
json.data = replaceText(
json.data,
env.replaceText,
diff --git a/packages/amis-ui/scss/components/_app.scss b/packages/amis-ui/scss/components/_app.scss
index eda5380f6..83e90d32d 100644
--- a/packages/amis-ui/scss/components/_app.scss
+++ b/packages/amis-ui/scss/components/_app.scss
@@ -2,11 +2,16 @@
height: px2rem(30px);
line-height: px2rem(30px);
font-size: px2rem(12px);
+
list-style: none;
margin: 0;
padding: 0 0 0 var(--gap-md);
border-bottom: var(--borderWidth) solid var(--borderColor);
+ a {
+ font-size: inherit;
+ }
+
&-item {
display: inline-block;
}
diff --git a/packages/amis/__tests__/renderers/App.test.tsx b/packages/amis/__tests__/renderers/App.test.tsx
new file mode 100644
index 000000000..ea6f73152
--- /dev/null
+++ b/packages/amis/__tests__/renderers/App.test.tsx
@@ -0,0 +1,104 @@
+import React from 'react';
+import Action from '../../src/renderers/Action';
+import * as renderer from 'react-test-renderer';
+import {
+ render,
+ fireEvent,
+ cleanup,
+ screen,
+ waitFor,
+ within
+} from '@testing-library/react';
+import {render as amisRender} from '../../src';
+import {makeEnv, wait} from '../helper';
+import '../../src';
+
+afterEach(cleanup);
+
+// 关联 issue https://github.com/baidu/amis/issues/9564
+test('Renderers:App locale', async () => {
+ const fetcher = jest.fn().mockImplementation((api, options) => {
+ if (api.url.startsWith('/pageList')) {
+ return Promise.resolve({
+ status: 200,
+ data: {
+ status: 0,
+ msg: '',
+ data: {
+ pages: [
+ {
+ children: [
+ {
+ 'label': 'Home',
+ 'icon': 'fa fa-home',
+ 'url': '/admin/page/home',
+ 'schemaApi': '/pageDetail',
+ 'isDefaultPage': true,
+ 'sort': 100,
+ 'zh-CN': {
+ label: '首页'
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ });
+ } else if (api.url.startsWith('/pageDetail')) {
+ return Promise.resolve({
+ status: 200,
+ data: {
+ type: 'page',
+ body: [
+ {
+ 'type': 'input-text',
+ 'name': 'a',
+ 'label': 'dev',
+ 'content': 'False',
+ 'zh-CN': {
+ label: '开发环境'
+ }
+ }
+ ]
+ }
+ });
+ }
+
+ return Promise.resolve({
+ status: 200,
+ data: {
+ status: 404,
+ msg: 'notFound'
+ }
+ });
+ });
+
+ const {container, getByText} = render(
+ amisRender(
+ {
+ type: 'app',
+ api: {
+ method: 'get',
+ url: '/pageList'
+ }
+ },
+ {
+ locale: 'zh-CN'
+ },
+ makeEnv({
+ fetcher
+ })
+ )
+ );
+
+ await wait(500);
+
+ const link = container.querySelector('nav li span');
+ expect(link).toBeInTheDocument();
+ expect(link!.textContent).toBe('首页');
+
+ const inputLabel = container.querySelector('.cxd-Form-label');
+ expect(inputLabel).toBeInTheDocument();
+ expect(inputLabel!.textContent).toBe('开发环境');
+});
diff --git a/packages/amis/src/renderers/App.tsx b/packages/amis/src/renderers/App.tsx
index 5acbed370..0c62c54b2 100644
--- a/packages/amis/src/renderers/App.tsx
+++ b/packages/amis/src/renderers/App.tsx
@@ -8,7 +8,13 @@ import {
SpinnerExtraProps
} from 'amis-ui';
import {Layout} from 'amis-ui';
-import {Renderer, RendererProps, filter, replaceText} from 'amis-core';
+import {
+ Renderer,
+ RendererProps,
+ envOverwrite,
+ filter,
+ replaceText
+} from 'amis-core';
import {
BaseSchema,
SchemaApi,
@@ -244,11 +250,13 @@ export default class App extends React.Component {
store,
env,
showFullBreadcrumbPath = false,
- showBreadcrumbHomePath = true
+ showBreadcrumbHomePath = true,
+ locale
} = this.props;
if (isEffectiveApi(api, store.data)) {
const json = await store.fetchInitData(api, store.data, {});
+
if (env.replaceText) {
json.data = replaceText(
json.data,
@@ -258,6 +266,8 @@ export default class App extends React.Component {
}
if (json?.data.pages) {
+ json.data = envOverwrite(json.data, locale);
+
store.setPages(json.data.pages);
store.updateActivePage(
Object.assign({}, env ?? {}, {
|