mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
Merge branch 'master' into feat-formulaeditor
This commit is contained in:
commit
78a81e3d0e
@ -2269,6 +2269,61 @@ crud 组件支持通过配置`headerToolbar`和`footerToolbar`属性,实现在
|
||||
}
|
||||
```
|
||||
|
||||
还可以定制文案和按钮如:
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "crud",
|
||||
"syncLocation": false,
|
||||
"api": "/api/mock2/sample",
|
||||
"filter": {
|
||||
"title": "条件搜索",
|
||||
"body": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "keywords",
|
||||
"placeholder": "通过关键字搜索"
|
||||
}
|
||||
]
|
||||
},
|
||||
"filterTogglable": {
|
||||
"label": "更多搜索",
|
||||
"activeLabel": "收起搜索",
|
||||
"icon": "fa fa-arrow-down mr-1",
|
||||
"activeIcon": "fa fa-arrow-up mr-1"
|
||||
},
|
||||
"headerToolbar": [
|
||||
"filter-toggler"
|
||||
],
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 刷新按钮
|
||||
|
||||
> 1.5.0 及以上版本
|
||||
@ -2862,60 +2917,60 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
|
||||
|
||||
## 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------------------- | ------------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| type | `string` | | `type` 指定为 CRUD 渲染器 |
|
||||
| mode | `string` | `"table"` | `"table" 、 "cards" 或者 "list"` |
|
||||
| title | `string` | `""` | 可设置成空,当设置成空时,没有标题栏 |
|
||||
| className | `string` | | 表格外层 Dom 的类名 |
|
||||
| api | [API](../../docs/types/api) | | CRUD 用来获取列表数据的 api。 |
|
||||
| loadDataOnce | `boolean` | | 是否一次性加载所有数据(前端分页) |
|
||||
| loadDataOnceFetchOnFilter | `boolean` | `true` | 在开启 loadDataOnce 时,filter 时是否去重新请求 api |
|
||||
| source | `string` | | 数据映射接口返回某字段的值,不设置会默认使用接口返回的`${items}`或者`${rows}`,也可以设置成上层数据源的内容 |
|
||||
| filter | [Form](./form/index) | | 设置过滤器,当该表单提交后,会把数据带给当前 `mode` 刷新列表。 |
|
||||
| filterTogglable | `boolean` | `false` | 是否可显隐过滤器 |
|
||||
| filterDefaultVisible | `boolean` | `true` | 设置过滤器默认是否可见。 |
|
||||
| initFetch | `boolean` | `true` | 是否初始化的时候拉取数据, 只针对有 filter 的情况, 没有 filter 初始都会拉取数据 |
|
||||
| interval | `number` | `3000` | 刷新时间(最低 1000) |
|
||||
| silentPolling | `boolean` | `false` | 配置刷新时是否隐藏加载动画 |
|
||||
| stopAutoRefreshWhen | `string` | `""` | 通过[表达式](../../docs/concepts/expression)来配置停止刷新的条件 |
|
||||
| stopAutoRefreshWhenModalIsOpen | `boolean` | `false` | 当有弹框时关闭自动刷新,关闭弹框又恢复 |
|
||||
| syncLocation | `boolean` | `true` | 是否将过滤条件的参数同步到地址栏 |
|
||||
| draggable | `boolean` | `false` | 是否可通过拖拽排序 |
|
||||
| resizable | `boolean` | `true` | 是否可以调整列宽度 |
|
||||
| itemDraggableOn | `boolean` | | 用[表达式](../../docs/concepts/expression)来配置是否可拖拽排序 |
|
||||
| [saveOrderApi](#saveOrderApi) | [API](../../docs/types/api) | | 保存排序的 api。 |
|
||||
| [quickSaveApi](#quickSaveApi) | [API](../../docs/types/api) | | 快速编辑后用来批量保存的 API。 |
|
||||
| [quickSaveItemApi](#quickSaveItemApi) | [API](../../docs/types/api) | | 快速编辑配置成及时保存时使用的 API。 |
|
||||
| bulkActions | Array<[Action](./action)> | | 批量操作列表,配置后,表格可进行选中操作。 |
|
||||
| messages | `Object` | | 覆盖消息提示,如果不指定,将采用 api 返回的 message |
|
||||
| messages.fetchFailed | `string` | | 获取失败时提示 |
|
||||
| messages.saveOrderFailed | `string` | | 保存顺序失败提示 |
|
||||
| messages.saveOrderSuccess | `string` | | 保存顺序成功提示 |
|
||||
| messages.quickSaveFailed | `string` | | 快速保存失败提示 |
|
||||
| messages.quickSaveSuccess | `string` | | 快速保存成功提示 |
|
||||
| primaryField | `string` | `"id"` | 设置 ID 字段名。 |
|
||||
| perPage | `number` | 10 | 设置一页显示多少条数据。 |
|
||||
| orderBy | `string` | | 默认排序字段,这个是传给后端,需要后端接口实现 |
|
||||
| orderDir | `asc` \| `desc` | | 排序方向 |
|
||||
| defaultParams | `Object` | | 设置默认 filter 默认参数,会在查询的时候一起发给后端 |
|
||||
| pageField | `string` | `"page"` | 设置分页页码字段名。 |
|
||||
| perPageField | `string` | `"perPage"` | 设置分页一页显示的多少条数据的字段名。注意:最好与 defaultParams 一起使用,请看下面例子。 |
|
||||
| perPageAvailable | `Array<number>` | `[5, 10, 20, 50, 100]` | 设置一页显示多少条数据下拉框可选条数。 |
|
||||
| orderField | `string` | | 设置用来确定位置的字段名,设置后新的顺序将被赋值到该字段中。 |
|
||||
| hideQuickSaveBtn | `boolean` | `false` | 隐藏顶部快速保存提示 |
|
||||
| autoJumpToTopOnPagerChange | `boolean` | `false` | 当切分页的时候,是否自动跳顶部。 |
|
||||
| syncResponse2Query | `boolean` | `true` | 将返回数据同步到过滤器上。 |
|
||||
| keepItemSelectionOnPageChange | `boolean` | `true` | 保留条目选择,默认分页、搜素后,用户选择条目会被清空,开启此选项后会保留用户选择,可以实现跨页面批量操作。 |
|
||||
| labelTpl | `string` | | 单条描述模板,`keepItemSelectionOnPageChange`设置为`true`后会把所有已选择条目列出来,此选项可以用来定制条目展示文案。 |
|
||||
| headerToolbar | Array | `['bulkActions', 'pagination']` | 顶部工具栏配置 |
|
||||
| footerToolbar | Array | `['statistics', 'pagination']` | 底部工具栏配置 |
|
||||
| alwaysShowPagination | `boolean` | `false` | 是否总是显示分页 |
|
||||
| affixHeader | `boolean` | `true` | 是否固定表头(table 下) |
|
||||
| autoGenerateFilter | `Object \| boolean` | | 是否开启查询区域,开启后会根据列元素的 `searchable` 属性值,自动生成查询条件表单 |
|
||||
| resetPageAfterAjaxItemAction | `boolean` | `false` | 单条数据 ajax 操作后是否重置页码为第一页 |
|
||||
| autoFillHeight | `boolean` 丨 `{height: number}` | | 内容区域自适应高度 |
|
||||
| canAccessSuperData | `boolean` | `true` | 指定是否可以自动获取上层的数据并映射到表格行数据上,如果列也配置了该属性,则列的优先级更高 |
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| type | `string` | | `type` 指定为 CRUD 渲染器 |
|
||||
| mode | `string` | `"table"` | `"table" 、 "cards" 或者 "list"` |
|
||||
| title | `string` | `""` | 可设置成空,当设置成空时,没有标题栏 |
|
||||
| className | `string` | | 表格外层 Dom 的类名 |
|
||||
| api | [API](../../docs/types/api) | | CRUD 用来获取列表数据的 api。 |
|
||||
| loadDataOnce | `boolean` | | 是否一次性加载所有数据(前端分页) |
|
||||
| loadDataOnceFetchOnFilter | `boolean` | `true` | 在开启 loadDataOnce 时,filter 时是否去重新请求 api |
|
||||
| source | `string` | | 数据映射接口返回某字段的值,不设置会默认使用接口返回的`${items}`或者`${rows}`,也可以设置成上层数据源的内容 |
|
||||
| filter | [Form](./form/index) | | 设置过滤器,当该表单提交后,会把数据带给当前 `mode` 刷新列表。 |
|
||||
| filterTogglable | `boolean` \| `{label: string; icon: string; activeLabel: string; activeIcon?: stirng;}` | `false` | 是否可显隐过滤器 |
|
||||
| filterDefaultVisible | `boolean` | `true` | 设置过滤器默认是否可见。 |
|
||||
| initFetch | `boolean` | `true` | 是否初始化的时候拉取数据, 只针对有 filter 的情况, 没有 filter 初始都会拉取数据 |
|
||||
| interval | `number` | `3000` | 刷新时间(最低 1000) |
|
||||
| silentPolling | `boolean` | `false` | 配置刷新时是否隐藏加载动画 |
|
||||
| stopAutoRefreshWhen | `string` | `""` | 通过[表达式](../../docs/concepts/expression)来配置停止刷新的条件 |
|
||||
| stopAutoRefreshWhenModalIsOpen | `boolean` | `false` | 当有弹框时关闭自动刷新,关闭弹框又恢复 |
|
||||
| syncLocation | `boolean` | `true` | 是否将过滤条件的参数同步到地址栏 |
|
||||
| draggable | `boolean` | `false` | 是否可通过拖拽排序 |
|
||||
| resizable | `boolean` | `true` | 是否可以调整列宽度 |
|
||||
| itemDraggableOn | `boolean` | | 用[表达式](../../docs/concepts/expression)来配置是否可拖拽排序 |
|
||||
| [saveOrderApi](#saveOrderApi) | [API](../../docs/types/api) | | 保存排序的 api。 |
|
||||
| [quickSaveApi](#quickSaveApi) | [API](../../docs/types/api) | | 快速编辑后用来批量保存的 API。 |
|
||||
| [quickSaveItemApi](#quickSaveItemApi) | [API](../../docs/types/api) | | 快速编辑配置成及时保存时使用的 API。 |
|
||||
| bulkActions | Array<[Action](./action)> | | 批量操作列表,配置后,表格可进行选中操作。 |
|
||||
| messages | `Object` | | 覆盖消息提示,如果不指定,将采用 api 返回的 message |
|
||||
| messages.fetchFailed | `string` | | 获取失败时提示 |
|
||||
| messages.saveOrderFailed | `string` | | 保存顺序失败提示 |
|
||||
| messages.saveOrderSuccess | `string` | | 保存顺序成功提示 |
|
||||
| messages.quickSaveFailed | `string` | | 快速保存失败提示 |
|
||||
| messages.quickSaveSuccess | `string` | | 快速保存成功提示 |
|
||||
| primaryField | `string` | `"id"` | 设置 ID 字段名。 |
|
||||
| perPage | `number` | 10 | 设置一页显示多少条数据。 |
|
||||
| orderBy | `string` | | 默认排序字段,这个是传给后端,需要后端接口实现 |
|
||||
| orderDir | `asc` \| `desc` | | 排序方向 |
|
||||
| defaultParams | `Object` | | 设置默认 filter 默认参数,会在查询的时候一起发给后端 |
|
||||
| pageField | `string` | `"page"` | 设置分页页码字段名。 |
|
||||
| perPageField | `string` | `"perPage"` | 设置分页一页显示的多少条数据的字段名。注意:最好与 defaultParams 一起使用,请看下面例子。 |
|
||||
| perPageAvailable | `Array<number>` | `[5, 10, 20, 50, 100]` | 设置一页显示多少条数据下拉框可选条数。 |
|
||||
| orderField | `string` | | 设置用来确定位置的字段名,设置后新的顺序将被赋值到该字段中。 |
|
||||
| hideQuickSaveBtn | `boolean` | `false` | 隐藏顶部快速保存提示 |
|
||||
| autoJumpToTopOnPagerChange | `boolean` | `false` | 当切分页的时候,是否自动跳顶部。 |
|
||||
| syncResponse2Query | `boolean` | `true` | 将返回数据同步到过滤器上。 |
|
||||
| keepItemSelectionOnPageChange | `boolean` | `true` | 保留条目选择,默认分页、搜素后,用户选择条目会被清空,开启此选项后会保留用户选择,可以实现跨页面批量操作。 |
|
||||
| labelTpl | `string` | | 单条描述模板,`keepItemSelectionOnPageChange`设置为`true`后会把所有已选择条目列出来,此选项可以用来定制条目展示文案。 |
|
||||
| headerToolbar | Array | `['bulkActions', 'pagination']` | 顶部工具栏配置 |
|
||||
| footerToolbar | Array | `['statistics', 'pagination']` | 底部工具栏配置 |
|
||||
| alwaysShowPagination | `boolean` | `false` | 是否总是显示分页 |
|
||||
| affixHeader | `boolean` | `true` | 是否固定表头(table 下) |
|
||||
| autoGenerateFilter | `Object \| boolean` | | 是否开启查询区域,开启后会根据列元素的 `searchable` 属性值,自动生成查询条件表单 |
|
||||
| resetPageAfterAjaxItemAction | `boolean` | `false` | 单条数据 ajax 操作后是否重置页码为第一页 |
|
||||
| autoFillHeight | `boolean` 丨 `{height: number}` | | 内容区域自适应高度 |
|
||||
| canAccessSuperData | `boolean` | `true` | 指定是否可以自动获取上层的数据并映射到表格行数据上,如果列也配置了该属性,则列的优先级更高 |
|
||||
|
||||
注意除了上面这些属性,CRUD 在不同模式下的属性需要参考各自的文档,比如
|
||||
|
||||
|
@ -490,7 +490,7 @@ type Value = ValueGroup;
|
||||
"label": "条件组件",
|
||||
"name": "conditions",
|
||||
"description": "适合让用户自己拼查询条件,然后后端根据数据生成 query where",
|
||||
"source": "/api/condition-fields?a=${a}&waitSeconds=2"
|
||||
"source": "/api/condition-fields/custom?a=${a}&waitSeconds=2"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -500,7 +500,7 @@ type Value = ValueGroup;
|
||||
|
||||
> 2.3.0 及以上版本
|
||||
|
||||
通过 selectMode 配置组合条件左侧选项类型,可配置项为`list`、`tree`,默认为`list`。两者数据格式相同,只是下拉框展示方式不同,当存在多层 children 嵌套时,建议使用`tree`。
|
||||
通过 selectMode 配置组合条件左侧选项类型,可配置项为`list`、`tree`、`chained`,默认为`list`。这三个数据格式基本类似,只是下拉框展示方式不同,`tree`是树形下拉,`chained`为多个级联的下拉。当存在多层 children 嵌套时,建议使用`tree`。
|
||||
|
||||
selectMode 为`list`时
|
||||
|
||||
@ -640,6 +640,84 @@ selectMode 为`tree`时
|
||||
}
|
||||
```
|
||||
|
||||
> 3.2.0 及以上版本
|
||||
|
||||
selectMode 为`chained`时,使用`fields`字段
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"debug": true,
|
||||
"body": [
|
||||
{
|
||||
"type": "condition-builder",
|
||||
"label": "条件组件",
|
||||
"name": "conditions",
|
||||
"selectMode": "chained",
|
||||
"description": "适合让用户自己拼查询条件,然后后端根据数据生成 query where",
|
||||
"fields": [
|
||||
{
|
||||
"label": "文本",
|
||||
"type": "text",
|
||||
"name": "text"
|
||||
},
|
||||
{
|
||||
"label": "数字",
|
||||
"type": "number",
|
||||
"name": "number"
|
||||
},
|
||||
{
|
||||
"label": "布尔",
|
||||
"type": "boolean",
|
||||
"name": "boolean"
|
||||
},
|
||||
{
|
||||
"label": "链式结构",
|
||||
"name": "chained",
|
||||
"children": [
|
||||
{
|
||||
"label": "Folder A",
|
||||
"name": "Folder_A",
|
||||
"children": [
|
||||
{
|
||||
"label": "file A",
|
||||
"name": "file_A",
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"label": "file B",
|
||||
"name": "file_B",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
selectMode 为`chained`时,使用`source`字段
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"debug": true,
|
||||
"body": [
|
||||
{
|
||||
"type": "condition-builder",
|
||||
"label": "条件组件",
|
||||
"name": "conditions",
|
||||
"selectMode": "chained",
|
||||
"description": "适合让用户自己拼查询条件,然后后端根据数据生成 query where",
|
||||
"source": "/api/condition-fields/chained"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 简易模式
|
||||
|
||||
通过 builderMode 配置为简易模式,在这个模式下将不开启树形分组功能,输出结果只有一层,方便后端实现简单的 SQL 生成。
|
||||
@ -918,7 +996,7 @@ selectMode 为`tree`时
|
||||
|
||||
## 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| -------------- | ------------------ | -------- | ------------------------------ |
|
||||
| className | `string` | | 外层 dom 类名 |
|
||||
| fieldClassName | `string` | | 输入字段的类名 |
|
||||
@ -929,4 +1007,6 @@ selectMode 为`tree`时
|
||||
| showANDOR | `boolean` | | 用于 simple 模式下显示切换按钮 |
|
||||
| showNot | `boolean` | | 是否显示「非」按钮 |
|
||||
| searchable | `boolean` | | 字段是否可搜索 |
|
||||
| selectMode | `'list'`、`'tree'` | `'list'` | 组合条件左侧选项类型 |
|
||||
| selectMode | `'list'` \| `'tree'` \| `'chained'` | `'list'` | 组合条件左侧选项类型。`'chained'`模式需要`3.2.0及以上版本` |
|
||||
| addBtnVisibleOn | `string` | | 表达式:控制按钮“添加条件”的显示。参数为`depth`、`breadth`,分别代表深度、长度。表达式需要返回`boolean`类型`3.2.0及以上版本` |
|
||||
| addGroupBtnVisibleOn | `string` | | 表达式:控制按钮“添加条件组”的显示。参数为`depth`、`breadth`,分别代表深度、长度。表达式需要返回`boolean`类型`3.2.0及以上版本` |
|
||||
|
@ -530,6 +530,46 @@ order: 68
|
||||
}
|
||||
```
|
||||
|
||||
内容来源于 source
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "page",
|
||||
"data": {
|
||||
"arr": [
|
||||
{
|
||||
"a": "收入",
|
||||
"b": 199,
|
||||
"key": "a"
|
||||
},
|
||||
|
||||
{
|
||||
"a": "支出",
|
||||
"b": 299,
|
||||
"key": "b"
|
||||
}
|
||||
]
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "tabs",
|
||||
"activeKey": "b",
|
||||
"source": "${arr}",
|
||||
"tabs": [
|
||||
{
|
||||
"title": "${a}",
|
||||
"hash": "${key}",
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "金额:${b|number}元"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 配置索引值
|
||||
|
||||
单个`tab`上不要配置`hash`属性,配置需要展示的`tab`索引值,`0`代表第一个。支持变量,如`"${id}"`
|
||||
|
@ -192,9 +192,31 @@ page
|
||||
|
||||
> **注意:** 当前例子中,对数据域中数据的获取使用的是 **\${xxx}** 模板语法,但是在不同的组件配置项中,获取数据的语法会有差异,我们会在后续的[模板](./template)和[表达式章节](./expression)中一一介绍。
|
||||
|
||||
### 具备数据域的组件
|
||||
|
||||
- App
|
||||
- Page
|
||||
- Cards
|
||||
- Chart
|
||||
- CRUD
|
||||
- CRUD2
|
||||
- Dialog
|
||||
- Drawer
|
||||
- List
|
||||
- Page
|
||||
- PaginationWrapper
|
||||
- Service
|
||||
- Wizard
|
||||
- Combo
|
||||
- InputArray
|
||||
- Table
|
||||
- Table2
|
||||
|
||||
有个特殊情况是 CRUD 中 filter,实际上是个 form,所以 CRUD 中有两层数据域,第一层是 CRUD 本身,同时查询条件表单中也有一层数据域。
|
||||
|
||||
### 常见误解
|
||||
|
||||
需要注意,只有少数几个容器组件会创建新的数据域,除了最顶层的 Page,还有 CRUD、Dialog、IFrame、Form、Service 等。
|
||||
需要注意,只有少数几个容器组件会创建新的数据域,具体查看[具备数据域的组件](#具备数据域的组件)列表。
|
||||
|
||||
常见的错误写法是给容器组件加 data 属性,比如:
|
||||
|
||||
@ -377,6 +399,53 @@ page
|
||||
|
||||
> 具有类似特征的组件还有`Formula`等
|
||||
|
||||
## 更新数据链
|
||||
|
||||
通常顶层数据域数据更新,孩子中具备数据域的组件都会更新,如果不更新会拿不到最新的值。从功能来看这个更新代价其实是很大的,有性能损耗,比如如果我在顶层更新了个变量 `name`,所有的孩子都会重新刷新一遍。
|
||||
目前 amis 中,具备数据域的组件,默认会检测两层节点的数据是否发生变化(上层数据域和上上层数据域),来决定当前层的数据要不要更新。存在两个问题:
|
||||
|
||||
1. 当前组件也许并不关心上层数据是否变化,没必要进行这些刷新操作
|
||||
2. 当前组件关系上上层的数据变化,但是在此拿不到最新的。(比如:放在 service 中的 crud,crud 中 filter 用了 service 的接口返回数据,但是拿不到最新的)
|
||||
|
||||
amis 从 3.2.0 版本开始针对[具备数据域的组件](#具备数据域的组件)新增了 `trackExpression` 属性,用来主动配置当前组件需要关心的上层数据。
|
||||
|
||||
针对以上问题,则可以通过这样配置来解决
|
||||
|
||||
1. `trackExpression` 配置成 `"none"` 也就是说不追踪任何数据。
|
||||
2. `trackExpression` 配置成 `"${xxxVariable}"` 这样 xxxVariable 变化了更新当前组件的数据链。
|
||||
|
||||
关于 `trackExpression` 的语法,请查看表达式篇章,可以监听多个变量比如: `"${xxx1},${xxx2}"`,还可以写表单时如 `"${ xxx ? xxx : yyy}"`。
|
||||
|
||||
amis 内部是通过运算这个表达式的结果来判断。所以表达式中千万不要用随机函数,或者用当前时间等,否则每次都会更新数据链。另外如果变量是数组,或者对象,会转成统一的字符串 `[object Array]` 或者 `[object Object]` 这个其实会影响检测的,所以建议转成 json 字符串如。 `${xxxObject | json}`。还有就是既然是监控上层数据,表达式中不要写当前层数据变量,是取不到的。
|
||||
|
||||
```schema
|
||||
{
|
||||
"data": {
|
||||
"name": "amis"
|
||||
},
|
||||
"type": "page",
|
||||
"body": [
|
||||
{ "label": "请修改输入框", "type": "input-text", "name": "name"},
|
||||
{
|
||||
"type": "switch",
|
||||
"label": "同步更新",
|
||||
"name": "syncSwitch"
|
||||
},
|
||||
{
|
||||
"type": "crud",
|
||||
"filter": {
|
||||
"trackExpression": "${syncSwitch ? name : ''}",
|
||||
"body": [
|
||||
|
||||
|
||||
"my name is ${name}"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## URL 参数
|
||||
|
||||
url 中的参数会进入顶层数据域,比如下面的例子,可以点击[这里](./datascope-and-datachain?word=myquery#url-参数)看效果。
|
||||
|
@ -236,6 +236,34 @@ amisScoped.updateProps(
|
||||
);
|
||||
```
|
||||
|
||||
### 更新配置
|
||||
|
||||
可以通过 amisScoped 对象的 udpateSchema 方法来更新更新内容配置。
|
||||
|
||||
```js
|
||||
let amisJSON = {
|
||||
type: 'page',
|
||||
body: [
|
||||
'inital string',
|
||||
|
||||
{
|
||||
type: 'button',
|
||||
label: 'Change',
|
||||
onClick: handleChange
|
||||
}
|
||||
]
|
||||
};
|
||||
let amisScoped = amis.embed('#root', amisJSON);
|
||||
|
||||
function handleChange() {
|
||||
const schema = {
|
||||
...amisJSON,
|
||||
body: ['changed']
|
||||
};
|
||||
amisScoped.updateSchema(schema);
|
||||
}
|
||||
```
|
||||
|
||||
### 多页模式
|
||||
|
||||
默认 amis 渲染是单页模式,如果想实现多页应用,请使用 [app 渲染器](../../components/app)。
|
||||
|
@ -295,6 +295,10 @@ export function embed(
|
||||
updateProps: (props: any, callback?: () => void) => {
|
||||
root.render(createElements(props));
|
||||
},
|
||||
updateSchema: (newSchema: any, props = {}) => {
|
||||
schema = newSchema;
|
||||
root.render(createElements(props));
|
||||
},
|
||||
unmount: () => {
|
||||
root.unmount();
|
||||
}
|
||||
|
@ -18,10 +18,3 @@ import 'core-js/es/symbol';
|
||||
import './cloest';
|
||||
// @ts-ignore
|
||||
import './classList';
|
||||
|
||||
// ios 没有这个会报错
|
||||
if (!('DragEvent' in window)) {
|
||||
Object.defineProperty(window, 'DragEvent', {
|
||||
value: class DragEvent {}
|
||||
});
|
||||
}
|
||||
|
44
mock/cfc/mock/condition-fields/chained.json
Normal file
44
mock/cfc/mock/condition-fields/chained.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "",
|
||||
"data": {
|
||||
"fields": [
|
||||
{
|
||||
"label": "文本",
|
||||
"type": "text",
|
||||
"name": "text"
|
||||
},
|
||||
{
|
||||
"label": "数字",
|
||||
"type": "number",
|
||||
"name": "number"
|
||||
},
|
||||
{
|
||||
"label": "布尔",
|
||||
"type": "boolean",
|
||||
"name": "boolean"
|
||||
},
|
||||
{
|
||||
"label": "日期",
|
||||
"name": "date",
|
||||
"children": [
|
||||
{
|
||||
"label": "日期1",
|
||||
"type": "date",
|
||||
"name": "date1"
|
||||
},
|
||||
{
|
||||
"label": "时间2",
|
||||
"type": "time",
|
||||
"name": "time2"
|
||||
},
|
||||
{
|
||||
"label": "日期时间3",
|
||||
"type": "datetime",
|
||||
"name": "datetime"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -60,7 +60,8 @@ export const RENDERER_TRANSMISSION_OMIT_PROPS = [
|
||||
'id',
|
||||
'inputOnly',
|
||||
'label',
|
||||
'renderLabel'
|
||||
'renderLabel',
|
||||
'trackExpression'
|
||||
];
|
||||
|
||||
const componentCache: SimpleMap = new SimpleMap();
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
syncDataFromSuper,
|
||||
isSuperDataModified
|
||||
} from './utils/helper';
|
||||
import {dataMapping} from './utils/tpl-builtin';
|
||||
import {dataMapping, tokenize} from './utils/tpl-builtin';
|
||||
import {RootStoreContext} from './WithRootStore';
|
||||
|
||||
export function HocStoreFactory(renderer: {
|
||||
@ -191,13 +191,16 @@ export function HocStoreFactory(renderer: {
|
||||
if (
|
||||
shouldSync === true ||
|
||||
prevProps.defaultData !== props.defaultData ||
|
||||
isObjectShallowModified(prevProps.data, props.data) ||
|
||||
//
|
||||
// 特殊处理 CRUD。
|
||||
// CRUD 中 toolbar 里面的 data 是空对象,但是 __super 会不一样
|
||||
(props.data &&
|
||||
prevProps.data &&
|
||||
props.data.__super !== prevProps.data.__super)
|
||||
(props.trackExpression
|
||||
? tokenize(props.trackExpression, props.data!) !==
|
||||
tokenize(props.trackExpression, prevProps.data!)
|
||||
: isObjectShallowModified(prevProps.data, props.data) ||
|
||||
//
|
||||
// 特殊处理 CRUD。
|
||||
// CRUD 中 toolbar 里面的 data 是空对象,但是 __super 会不一样
|
||||
(props.data &&
|
||||
prevProps.data &&
|
||||
props.data.__super !== prevProps.data.__super))
|
||||
) {
|
||||
store.initData(
|
||||
extendObject(props.data, {
|
||||
@ -209,9 +212,12 @@ export function HocStoreFactory(renderer: {
|
||||
}
|
||||
} else if (
|
||||
shouldSync === true ||
|
||||
isObjectShallowModified(prevProps.data, props.data) ||
|
||||
(props.syncSuperStore !== false &&
|
||||
isSuperDataModified(props.data, prevProps.data, store))
|
||||
(props.trackExpression
|
||||
? tokenize(props.trackExpression, props.data!) !==
|
||||
tokenize(props.trackExpression, prevProps.data!)
|
||||
: isObjectShallowModified(prevProps.data, props.data) ||
|
||||
(props.syncSuperStore !== false &&
|
||||
isSuperDataModified(props.data, prevProps.data, store)))
|
||||
) {
|
||||
if (props.store && props.store.data === props.data) {
|
||||
store.initData(
|
||||
@ -246,9 +252,8 @@ export function HocStoreFactory(renderer: {
|
||||
store.initData(createObject(props.scope, props.data));
|
||||
}
|
||||
} else if (
|
||||
(shouldSync === true ||
|
||||
!props.store ||
|
||||
props.data !== props.store.data) &&
|
||||
!props.trackExpression &&
|
||||
(!props.store || props.data !== props.store.data) &&
|
||||
props.data &&
|
||||
props.data.__super
|
||||
) {
|
||||
@ -273,9 +278,10 @@ export function HocStoreFactory(renderer: {
|
||||
}
|
||||
// nextProps.data.__super !== props.data.__super) &&
|
||||
} else if (
|
||||
!props.trackExpression &&
|
||||
props.scope &&
|
||||
props.data === props.store!.data &&
|
||||
(shouldSync === true || prevProps.data !== props.data)
|
||||
prevProps.data !== props.data
|
||||
) {
|
||||
// 只有父级数据变动的时候才应该进来,
|
||||
// 目前看来这个 case 很少有情况下能进来
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
extendDefaultEnv
|
||||
} from './factory';
|
||||
import type {RenderOptions, RendererConfig, RendererProps} from './factory';
|
||||
import './polyfills';
|
||||
import './renderers/builtin';
|
||||
import './renderers/register';
|
||||
export * from './utils/index';
|
||||
|
10
packages/amis-core/src/polyfills.ts
Normal file
10
packages/amis-core/src/polyfills.ts
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* 用于放一些关键的 polyfill
|
||||
*/
|
||||
|
||||
// ios 老版本没有这个会报错
|
||||
if (!('DragEvent' in window)) {
|
||||
Object.defineProperty(window, 'DragEvent', {
|
||||
value: class DragEvent {}
|
||||
});
|
||||
}
|
@ -1110,7 +1110,7 @@ export class FormItemWrap extends React.Component<FormItemProps> {
|
||||
static: isStatic,
|
||||
staticClassName
|
||||
} = props;
|
||||
|
||||
const mobileUI = useMobileUI && isMobile();
|
||||
description = description || desc;
|
||||
|
||||
return (
|
||||
@ -1157,50 +1157,101 @@ export class FormItemWrap extends React.Component<FormItemProps> {
|
||||
</label>
|
||||
) : null}
|
||||
|
||||
{renderControl()}
|
||||
{mobileUI ? (
|
||||
<div className={cx('Form-item-controlBox')}>
|
||||
{renderControl()}
|
||||
|
||||
{caption
|
||||
? render('caption', caption, {
|
||||
className: cx(`Form-caption`, captionClassName)
|
||||
})
|
||||
: null}
|
||||
{caption
|
||||
? render('caption', caption, {
|
||||
className: cx(`Form-caption`, captionClassName)
|
||||
})
|
||||
: null}
|
||||
|
||||
{remark
|
||||
? render('remark', {
|
||||
type: 'remark',
|
||||
icon: remark.icon || 'warning-mark',
|
||||
className: cx(`Form-remark`),
|
||||
tooltip: remark,
|
||||
useMobileUI,
|
||||
container:
|
||||
env && env.getModalContainer
|
||||
? env.getModalContainer
|
||||
: undefined
|
||||
})
|
||||
: null}
|
||||
{remark
|
||||
? render('remark', {
|
||||
type: 'remark',
|
||||
icon: remark.icon || 'warning-mark',
|
||||
className: cx(`Form-remark`),
|
||||
tooltip: remark,
|
||||
useMobileUI,
|
||||
container:
|
||||
env && env.getModalContainer
|
||||
? env.getModalContainer
|
||||
: undefined
|
||||
})
|
||||
: null}
|
||||
|
||||
{hint && model && model.isFocused
|
||||
? render('hint', hint, {
|
||||
className: cx(`Form-hint`)
|
||||
})
|
||||
: null}
|
||||
{hint && model && model.isFocused
|
||||
? render('hint', hint, {
|
||||
className: cx(`Form-hint`)
|
||||
})
|
||||
: null}
|
||||
|
||||
{model &&
|
||||
!model.valid &&
|
||||
showErrorMsg !== false &&
|
||||
Array.isArray(model.errors) ? (
|
||||
<ul className={cx(`Form-feedback`)}>
|
||||
{model.errors.map((msg: string, key: number) => (
|
||||
<li key={key}>{msg}</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
{model &&
|
||||
!model.valid &&
|
||||
showErrorMsg !== false &&
|
||||
Array.isArray(model.errors) ? (
|
||||
<ul className={cx(`Form-feedback`)}>
|
||||
{model.errors.map((msg: string, key: number) => (
|
||||
<li key={key}>{msg}</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
|
||||
{renderDescription !== false && description
|
||||
? render('description', description, {
|
||||
className: cx(`Form-description`, descriptionClassName)
|
||||
})
|
||||
: null}
|
||||
{renderDescription !== false && description
|
||||
? render('description', description, {
|
||||
className: cx(`Form-description`, descriptionClassName)
|
||||
})
|
||||
: null}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{renderControl()}
|
||||
|
||||
{caption
|
||||
? render('caption', caption, {
|
||||
className: cx(`Form-caption`, captionClassName)
|
||||
})
|
||||
: null}
|
||||
|
||||
{remark
|
||||
? render('remark', {
|
||||
type: 'remark',
|
||||
icon: remark.icon || 'warning-mark',
|
||||
className: cx(`Form-remark`),
|
||||
tooltip: remark,
|
||||
useMobileUI,
|
||||
container:
|
||||
env && env.getModalContainer
|
||||
? env.getModalContainer
|
||||
: undefined
|
||||
})
|
||||
: null}
|
||||
|
||||
{hint && model && model.isFocused
|
||||
? render('hint', hint, {
|
||||
className: cx(`Form-hint`)
|
||||
})
|
||||
: null}
|
||||
|
||||
{model &&
|
||||
!model.valid &&
|
||||
showErrorMsg !== false &&
|
||||
Array.isArray(model.errors) ? (
|
||||
<ul className={cx(`Form-feedback`)}>
|
||||
{model.errors.map((msg: string, key: number) => (
|
||||
<li key={key}>{msg}</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
|
||||
{renderDescription !== false && description
|
||||
? render('description', description, {
|
||||
className: cx(`Form-description`, descriptionClassName)
|
||||
})
|
||||
: null}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@ -188,8 +188,8 @@ export const FormStore = ServiceStore.named('FormStore')
|
||||
|
||||
// 如果数据域中有数据变化,就都reset一下,去掉之前残留的验证消息
|
||||
self.items.forEach(item => {
|
||||
const value = item.value;
|
||||
if (typeof value !== 'undefined' && value !== item.tmpValue) {
|
||||
const value = getVariable(values, item.name);
|
||||
if (value !== undefined && value !== item.tmpValue) {
|
||||
item.changeTmpValue(value);
|
||||
}
|
||||
item.reset();
|
||||
|
@ -162,7 +162,7 @@ export interface BaseApiObject {
|
||||
|
||||
/**
|
||||
* 当开启自动刷新的时候,默认是 api 的 url 来自动跟踪变量变化的。
|
||||
* 如果你希望监控 url 外的变量,请配置 traceExpression。
|
||||
* 如果你希望监控 url 外的变量,请配置 trackExpression。
|
||||
*/
|
||||
trackExpression?: string;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import {attachmentAdpator} from 'amis-core';
|
||||
import omit from 'lodash/omit';
|
||||
import {Api, ApiObject, EventTrack, fetcherResult, Payload} from '../types';
|
||||
import {fetcherConfig} from '../factory';
|
||||
@ -143,6 +144,30 @@ export function buildApi(
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
/** 追加data到请求的Query中 */
|
||||
const attachDataToQuery = (
|
||||
apiObject: ApiObject,
|
||||
ctx: Record<string, any>
|
||||
) => {
|
||||
const idx = apiObject.url.indexOf('?');
|
||||
if (~idx) {
|
||||
const params = (apiObject.query = {
|
||||
...qsparse(apiObject.url.substring(idx + 1)),
|
||||
...apiObject.query,
|
||||
...ctx
|
||||
});
|
||||
apiObject.url =
|
||||
apiObject.url.substring(0, idx) + '?' + queryStringify(params);
|
||||
} else {
|
||||
apiObject.query = {...apiObject.query, ...ctx};
|
||||
const query = queryStringify(ctx);
|
||||
if (query) {
|
||||
apiObject.url = `${apiObject.url}?${query}`;
|
||||
}
|
||||
}
|
||||
|
||||
return apiObject;
|
||||
};
|
||||
|
||||
if (~idx) {
|
||||
const hashIdx = url.indexOf('#');
|
||||
@ -217,39 +242,11 @@ export function buildApi(
|
||||
api.data &&
|
||||
((!~raw.indexOf('$') && autoAppend) || api.forceAppendDataToQuery)
|
||||
) {
|
||||
const idx = api.url.indexOf('?');
|
||||
if (~idx) {
|
||||
let params = (api.query = {
|
||||
...qsparse(api.url.substring(idx + 1)),
|
||||
...api.query,
|
||||
...data
|
||||
});
|
||||
api.url = api.url.substring(0, idx) + '?' + queryStringify(params);
|
||||
} else {
|
||||
api.query = {...api.query, ...data};
|
||||
const query = queryStringify(data);
|
||||
if (query) {
|
||||
api.url = `${api.url}?${query}`;
|
||||
}
|
||||
}
|
||||
api = attachDataToQuery(api, data);
|
||||
}
|
||||
|
||||
if (api.data && api.attachDataToQuery !== false) {
|
||||
const idx = api.url.indexOf('?');
|
||||
if (~idx) {
|
||||
let params = (api.query = {
|
||||
...qsparse(api.url.substring(idx + 1)),
|
||||
...api.query,
|
||||
...api.data
|
||||
});
|
||||
api.url = api.url.substring(0, idx) + '?' + queryStringify(params);
|
||||
} else {
|
||||
api.query = {...api.query, ...api.data};
|
||||
const query = queryStringify(api.query);
|
||||
if (query) {
|
||||
api.url = `${api.url}?${query}`;
|
||||
}
|
||||
}
|
||||
api = attachDataToQuery(api, data);
|
||||
delete api.data;
|
||||
}
|
||||
}
|
||||
@ -302,6 +299,11 @@ export function buildApi(
|
||||
jsonql: api.jsonql
|
||||
}
|
||||
: api.jsonql;
|
||||
|
||||
/** JSONQL所有method需要追加data中的变量到query中 */
|
||||
if (api.forceAppendDataToQuery) {
|
||||
api = attachDataToQuery(api, data);
|
||||
}
|
||||
}
|
||||
|
||||
return api;
|
||||
|
@ -321,6 +321,8 @@ $tooltip-bottom: '[data-tooltip][data-position=' bottom ']:hover:after';
|
||||
width: 100%;
|
||||
--Tabs--line-active-fontSize: 14px;
|
||||
--Tabs--line-fontSize: 14px;
|
||||
--Tabs--line-hover-fontSize: 14px;
|
||||
--Tabs--line-disabled-fontSize: 14px;
|
||||
letter-spacing: 0;
|
||||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
|
@ -60,4 +60,19 @@
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
&-dragBar {
|
||||
position: absolute;
|
||||
display: none;
|
||||
z-index: 2;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:hover &-dragBar {
|
||||
display: block;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,15 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border: none;
|
||||
|
||||
&.ae-FeatureControlItem-go {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.ae-GoConfig-trigger {
|
||||
display: block;
|
||||
border-radius: $Editor-borderRadius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@
|
||||
}
|
||||
&-fxIcon {
|
||||
> a {
|
||||
font-size: 18px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,7 +130,7 @@
|
||||
}
|
||||
&-fxIcon {
|
||||
> a {
|
||||
font-size: 28px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,12 @@ export interface DSSourceSettingFormConfig {
|
||||
grain?: DSGrain;
|
||||
/** 数据源所被使用的功能场景 */
|
||||
feat: DSFeatureType;
|
||||
/** 是否是在CRUD场景下,有的数据源在CRUD中可以统一设置 */
|
||||
/** 渲染器类型 */
|
||||
renderer?: string;
|
||||
/**
|
||||
* @deprecated 待废弃,使用renderer字段代替
|
||||
* 是否是在CRUD场景下,有的数据源在CRUD中可以统一设置
|
||||
* */
|
||||
inCrud?: boolean;
|
||||
/** 是否在脚手架中 */
|
||||
inScaffold?: boolean;
|
||||
|
@ -33,7 +33,7 @@ import SearchPanel from './component/base/SearchPanel';
|
||||
import {VRenderer} from './component/VRenderer';
|
||||
import {RegionWrapper} from './component/RegionWrapper';
|
||||
import {mapReactElement} from './component/factory';
|
||||
import type {EditorNodeType} from './store/node';
|
||||
import type {EditorNodeType, EditorNodeSnapshot} from './store/node';
|
||||
import {ContainerWrapper} from './component/ContainerWrapper';
|
||||
import type {EditorStoreType} from './store/editor';
|
||||
import {AvailableRenderersPlugin} from './plugin/AvailableRenderers';
|
||||
@ -56,6 +56,7 @@ export {
|
||||
IFramePreview as IFrameEditor,
|
||||
SearchPanel,
|
||||
EditorNodeType,
|
||||
EditorNodeSnapshot,
|
||||
EditorStoreType,
|
||||
ContainerWrapper,
|
||||
AvailableRenderersPlugin,
|
||||
|
@ -2,8 +2,12 @@
|
||||
* @file 把一些功能性的东西放在了这个里面,辅助 compoennt/Editor.tsx 组件的。
|
||||
* 编辑器非 UI 相关的东西应该放在这。
|
||||
*/
|
||||
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import {reaction} from 'mobx';
|
||||
import {parse, stringify} from 'json-ast-comments';
|
||||
import debounce from 'lodash/debounce';
|
||||
import findIndex from 'lodash/findIndex';
|
||||
import omit from 'lodash/omit';
|
||||
import {openContextMenus, toast, alert, DataScope, DataSchema} from 'amis';
|
||||
import {getRenderers, RenderOptions, mapTree} from 'amis-core';
|
||||
import {
|
||||
PluginInterface,
|
||||
@ -31,14 +35,14 @@ import {
|
||||
DeleteEventContext,
|
||||
RendererPluginEvent,
|
||||
PluginEvents,
|
||||
PluginActions
|
||||
PluginActions,
|
||||
BasePlugin
|
||||
} from './plugin';
|
||||
import {
|
||||
EditorStoreType,
|
||||
PopOverFormContext,
|
||||
SubEditorContext
|
||||
} from './store/editor';
|
||||
|
||||
import {
|
||||
autobind,
|
||||
camelize,
|
||||
@ -49,29 +53,18 @@ import {
|
||||
isString,
|
||||
isObject,
|
||||
isLayoutPlugin,
|
||||
JSONPipeOut,
|
||||
generateNodeId,
|
||||
JSONTraverse
|
||||
JSONPipeOut
|
||||
} from './util';
|
||||
import {reaction} from 'mobx';
|
||||
import {hackIn, makeSchemaFormRender, makeWrapper} from './component/factory';
|
||||
import {env} from './env';
|
||||
import debounce from 'lodash/debounce';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import reverse from 'lodash/reverse';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {openContextMenus, toast, alert, DataScope, DataSchema} from 'amis';
|
||||
import {parse, stringify} from 'json-ast-comments';
|
||||
import {EditorNodeType} from './store/node';
|
||||
import {EditorProps} from './component/Editor';
|
||||
import findIndex from 'lodash/findIndex';
|
||||
import {EditorDNDManager} from './dnd';
|
||||
import {VariableManager} from './variable';
|
||||
import {IScopedContext} from 'amis';
|
||||
|
||||
import type {IScopedContext} from 'amis';
|
||||
import type {SchemaObject, SchemaCollection} from 'amis';
|
||||
import type {RendererConfig} from 'amis-core';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import {omit} from 'lodash';
|
||||
|
||||
export interface EditorManagerConfig
|
||||
extends Omit<EditorProps, 'value' | 'onChange'> {}
|
||||
@ -79,6 +72,8 @@ export interface EditorManagerConfig
|
||||
export interface PluginClass {
|
||||
new (manager: EditorManager, options?: any): PluginInterface;
|
||||
id?: string;
|
||||
/** 优先级,值为整数,当存在两个ID相同的Plugin时,数字更大的优先级更高 */
|
||||
priority?: number;
|
||||
scene?: Array<string>;
|
||||
}
|
||||
|
||||
@ -111,22 +106,58 @@ export function registerEditorPlugin(klass: PluginClass) {
|
||||
// 处理插件身上的场景信息
|
||||
const scene = Array.from(new Set(['global'].concat(klass.scene || 'global')));
|
||||
klass.scene = scene;
|
||||
let isExitPlugin: any = null;
|
||||
|
||||
let exsitedPluginIdx: any = null;
|
||||
if (klass.prototype && klass.prototype.isNpmCustomWidget) {
|
||||
isExitPlugin = builtInPlugins.find(item =>
|
||||
exsitedPluginIdx = builtInPlugins.findIndex(item =>
|
||||
Array.isArray(item)
|
||||
? item[0].prototype.name === klass.prototype.name
|
||||
: item.prototype.name === klass.prototype.name
|
||||
);
|
||||
} else {
|
||||
// 待进一步优化
|
||||
isExitPlugin = builtInPlugins.find(item => item === klass);
|
||||
exsitedPluginIdx = builtInPlugins.findIndex(item => item === klass);
|
||||
}
|
||||
if (!isExitPlugin) {
|
||||
|
||||
/** 先给新加入的plugin加一个ID */
|
||||
if (!~exsitedPluginIdx) {
|
||||
klass.id = klass.id || klass.name || guid();
|
||||
builtInPlugins.push(klass);
|
||||
}
|
||||
|
||||
/** 因为class的继承关系,未设置ID的子class会和父class共用ID, 只有设置了priority的时候才会执行同ID去重 */
|
||||
if (klass.priority == null || !Number.isInteger(klass.priority)) {
|
||||
if (!~exsitedPluginIdx) {
|
||||
builtInPlugins.push(klass);
|
||||
} else {
|
||||
console.warn(`注册插件「${klass.id}」异常,已存在同名插件:`, klass);
|
||||
}
|
||||
} else {
|
||||
console.warn(`注册插件异常,已存在同名插件:`, klass);
|
||||
exsitedPluginIdx = ~exsitedPluginIdx
|
||||
? exsitedPluginIdx
|
||||
: builtInPlugins.findIndex(
|
||||
item =>
|
||||
!Array.isArray(item) &&
|
||||
item.id === klass.id &&
|
||||
item?.prototype instanceof BasePlugin
|
||||
);
|
||||
|
||||
if (!~exsitedPluginIdx) {
|
||||
builtInPlugins.push(klass);
|
||||
} else {
|
||||
const current = builtInPlugins[exsitedPluginIdx] as PluginClass;
|
||||
|
||||
/** 同ID的插件根据优先级决定是否update */
|
||||
const currentPriority =
|
||||
current.priority && Number.isInteger(current.priority)
|
||||
? current.priority
|
||||
: 0;
|
||||
|
||||
if (klass.priority > currentPriority) {
|
||||
builtInPlugins.splice(exsitedPluginIdx, 1, klass);
|
||||
} else {
|
||||
console.warn(`注册插件「${klass.id}」异常,已存在同名插件:`, klass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +230,39 @@ export class EditorManager {
|
||||
this.hackIn = parent?.hackIn || hackIn;
|
||||
// 自动加载预先注册的自定义组件
|
||||
autoPreRegisterEditorCustomPlugins();
|
||||
const scene = config.scene || 'global';
|
||||
/** 在顶层对外部注册的Plugin和builtInPlugins合并去重 */
|
||||
if (!parent?.plugins) {
|
||||
(config?.plugins || []).forEach(external => {
|
||||
if (
|
||||
Array.isArray(external) ||
|
||||
!external.priority ||
|
||||
!Number.isInteger(external.priority)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idx = builtInPlugins.findIndex(
|
||||
builtIn =>
|
||||
!Array.isArray(builtIn) &&
|
||||
!Array.isArray(external) &&
|
||||
builtIn.id === external.id &&
|
||||
builtIn?.prototype instanceof BasePlugin
|
||||
);
|
||||
|
||||
if (~idx) {
|
||||
const current = builtInPlugins[idx] as PluginClass;
|
||||
const currentPriority =
|
||||
current.priority && Number.isInteger(current.priority)
|
||||
? current.priority
|
||||
: 0;
|
||||
/** 同ID Plugin根据优先级决定是否替换掉Builtin中的Plugin */
|
||||
if (external.priority > currentPriority) {
|
||||
builtInPlugins.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.plugins =
|
||||
parent?.plugins ||
|
||||
(config.disableBultinPlugin ? [] : builtInPlugins) // 页面设计器注册的插件列表
|
||||
|
@ -291,6 +291,8 @@ export interface RendererInfo extends RendererScaffoldInfo {
|
||||
memberIndex?: number;
|
||||
|
||||
tipName?: string;
|
||||
/** 共享上下文 */
|
||||
sharedContext?: Record<string, any>;
|
||||
}
|
||||
|
||||
export type BasicRendererInfo = Omit<
|
||||
|
@ -77,6 +77,14 @@ export const EditorNode = types
|
||||
info = value;
|
||||
},
|
||||
|
||||
updateSharedContext(value: Record<string, any>) {
|
||||
if (!value || !info?.hasOwnProperty('sharedContext')) {
|
||||
return;
|
||||
}
|
||||
|
||||
info.sharedContext = value;
|
||||
},
|
||||
|
||||
get rendererConfig() {
|
||||
return rendererConfig;
|
||||
},
|
||||
|
@ -5,6 +5,7 @@ import {getSchemaTpl} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis';
|
||||
|
||||
export class AlertPlugin extends BasePlugin {
|
||||
static id = 'AlertPlugin';
|
||||
static scene = ['layout'];
|
||||
|
||||
// 关联渲染器名字
|
||||
|
@ -11,6 +11,7 @@ import {registerFilter} from 'amis-formula';
|
||||
registerFilter('appTranslate', (input: any) => translateSchema(input));
|
||||
|
||||
export class AnchorNavPlugin extends BasePlugin {
|
||||
static id = 'AnchorNavPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'anchor-nav';
|
||||
$schema = '/schemas/AnchorNavSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {BaseEventContext, BasePlugin} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export class AudioPlugin extends BasePlugin {
|
||||
static id = 'AudioPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'audio';
|
||||
|
@ -13,6 +13,7 @@ const widthOrheightPipeIn = (curValue: string, rest: any) =>
|
||||
curValue ? curValue : rest.data?.size ?? DefaultSize;
|
||||
|
||||
export class AvatarPlugin extends BasePlugin {
|
||||
static id = 'AvatarPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'avatar';
|
||||
|
@ -6,6 +6,7 @@ import {BaseEventContext, BasePlugin} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export class BreadcrumbPlugin extends BasePlugin {
|
||||
static id = 'BreadcrumbPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'breadcrumb';
|
||||
$schema = '/schemas/BreadcrumbSchema.json';
|
||||
|
@ -15,6 +15,7 @@ import type {SchemaObject} from 'amis';
|
||||
import {getOldActionSchema} from '../renderer/event-control/helper';
|
||||
|
||||
export class ButtonPlugin extends BasePlugin {
|
||||
static id = 'ButtonPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'button';
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
import {BUTTON_DEFAULT_ACTION} from '../component/BaseControl';
|
||||
|
||||
export class ButtonGroupPlugin extends BasePlugin {
|
||||
static id = 'ButtonGroupPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'button-group';
|
||||
|
@ -56,6 +56,7 @@ const viewTypeToEditType = (type: string) => {
|
||||
};
|
||||
|
||||
export class CRUDPlugin extends BasePlugin {
|
||||
static id = 'CRUDPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'crud';
|
||||
$schema = '/schemas/CRUDSchema.json';
|
||||
|
@ -477,6 +477,7 @@ const DataOperators: Array<FeatOption> = [
|
||||
];
|
||||
|
||||
export class CRUDPlugin extends BasePlugin {
|
||||
static id = 'CRUD2Plugin';
|
||||
constructor(manager: EditorManager) {
|
||||
super(manager);
|
||||
this.dsBuilderMgr = new DSBuilderManager('crud2', 'api');
|
||||
|
@ -18,6 +18,7 @@ import flatten from 'lodash/flatten';
|
||||
import {VRenderer} from 'amis-editor-core';
|
||||
|
||||
export class CardPlugin extends BasePlugin {
|
||||
static id = 'CardPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'card';
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
|
||||
export class Card2Plugin extends BasePlugin {
|
||||
static id = 'Card2Plugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'card2';
|
||||
|
@ -19,6 +19,7 @@ import {diff, JSONPipeOut, repeatArray} from 'amis-editor-core';
|
||||
import {resolveArrayDatasource} from '../util';
|
||||
|
||||
export class CardsPlugin extends BasePlugin {
|
||||
static id = 'CardsPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'cards';
|
||||
|
@ -4,6 +4,7 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {mockValue} from 'amis-editor-core';
|
||||
|
||||
export class CarouselPlugin extends BasePlugin {
|
||||
static id = 'CarouselPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'carousel';
|
||||
$schema = '/schemas/CarouselSchema.json';
|
||||
|
@ -76,6 +76,7 @@ const DEFAULT_EVENT_PARAMS = [
|
||||
];
|
||||
|
||||
export class ChartPlugin extends BasePlugin {
|
||||
static id = 'ChartPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'chart';
|
||||
$schema = '/schemas/ChartSchema.json';
|
||||
|
@ -6,6 +6,7 @@ import {BaseEventContext, BasePlugin} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export class CodeViewPlugin extends BasePlugin {
|
||||
static id = 'CodeViewPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'code';
|
||||
$schema = '/schemas/CodeSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {BasePlugin, RegionConfig, BaseEventContext} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export class CollapsePlugin extends BasePlugin {
|
||||
static id = 'CollapsePlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'collapse';
|
||||
$schema = '/schemas/CollapseSchema.json';
|
||||
|
@ -6,6 +6,7 @@ import {tipedLabel} from 'amis-editor-core';
|
||||
import {isObject} from 'amis-editor-core';
|
||||
|
||||
export class CollapseGroupPlugin extends BasePlugin {
|
||||
static id = 'CollapseGroupPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'collapse-group';
|
||||
$schema = '/schemas/CollapseGroupSchema.json';
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
|
||||
export class ColumnToggler extends BasePlugin {
|
||||
static id = 'ColumnToggler';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'column-toggler';
|
||||
$schema = '/schemas/ColumnToggler.json';
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
|
||||
export class ContainerPlugin extends LayoutBasePlugin {
|
||||
static id = 'ContainerPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'container';
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export class CustomPlugin extends BasePlugin {
|
||||
static id = 'CustomPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'custom';
|
||||
$schema = '/schemas/CustomSchema.json';
|
||||
|
@ -15,6 +15,7 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import isArray from 'lodash/isArray';
|
||||
|
||||
export class CustomPlugin extends BasePlugin {
|
||||
static id = 'CustomRegionPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'custom';
|
||||
$schema = '/schemas/CustomSchema.json';
|
||||
|
@ -31,6 +31,7 @@ const valueDateFormatOptions = [
|
||||
}
|
||||
];
|
||||
export class DatePlugin extends BasePlugin {
|
||||
static id = 'DatePlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'date';
|
||||
|
@ -32,6 +32,7 @@ const valueDateFormatOptions = [
|
||||
}
|
||||
];
|
||||
export class DatetimePlugin extends DatePlugin {
|
||||
static id = 'DatetimePlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'datetime';
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
|
||||
export class DialogPlugin extends BasePlugin {
|
||||
static id = 'DialogPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'dialog';
|
||||
$schema = '/schemas/DialogSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {BasePlugin} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export class DividerPlugin extends BasePlugin {
|
||||
static id = 'DividerPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'divider';
|
||||
|
@ -13,6 +13,7 @@ import {InlineModal} from './Dialog';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
|
||||
export class DrawerPlugin extends BasePlugin {
|
||||
static id = 'DrawerPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'drawer';
|
||||
$schema = '/schemas/DrawerSchema.json';
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {BUTTON_DEFAULT_ACTION} from '../component/BaseControl';
|
||||
export class DropDownButtonPlugin extends BasePlugin {
|
||||
static id = 'DropDownButtonPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'dropdown-button';
|
||||
|
@ -12,6 +12,7 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {diff, JSONPipeOut} from 'amis-editor-core';
|
||||
|
||||
export class EachPlugin extends BasePlugin {
|
||||
static id = 'EachPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'each';
|
||||
|
@ -5,6 +5,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {FlexPluginBase} from './Layout/FlexPluginBase';
|
||||
|
||||
export class FlexPlugin extends FlexPluginBase {
|
||||
static id = 'FlexPlugin';
|
||||
static scene = ['layout'];
|
||||
name = 'Flex 布局';
|
||||
pluginIcon = 'flex-container-plugin';
|
||||
|
@ -10,6 +10,7 @@ import {getSchemaTpl, defaultValue} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
export class ButtonGroupControlPlugin extends BasePlugin {
|
||||
static id = 'ButtonGroupControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'button-group-select';
|
||||
$schema = '/schemas/ButtonGroupControlSchema.json';
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
} from '../../component/BaseControl';
|
||||
|
||||
export class ButtonToolbarControlPlugin extends BasePlugin {
|
||||
static id = 'ButtonToolbarControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'button-toolbar';
|
||||
|
@ -15,6 +15,7 @@ import {ValidatorTag} from '../../validator';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
export class ChainedSelectControlPlugin extends BasePlugin {
|
||||
static id = 'ChainedSelectControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'chained-select';
|
||||
$schema = '/schemas/ChainedSelectControlSchema.json';
|
||||
|
@ -23,6 +23,7 @@ setSchemaTpl('option', {
|
||||
label: tipedLabel('说明', '选项说明')
|
||||
});
|
||||
export class CheckboxControlPlugin extends BasePlugin {
|
||||
static id = 'CheckboxControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'checkbox';
|
||||
@ -159,7 +160,9 @@ export class CheckboxControlPlugin extends BasePlugin {
|
||||
getSchemaTpl('labelRemark'),
|
||||
getSchemaTpl('remark'),
|
||||
getSchemaTpl('description'),
|
||||
getSchemaTpl('autoFillApi')
|
||||
getSchemaTpl('autoFillApi', {
|
||||
trigger: 'change'
|
||||
})
|
||||
]
|
||||
},
|
||||
getSchemaTpl('status', {isFormItem: true}),
|
||||
|
@ -18,6 +18,7 @@ import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
export class CheckboxesControlPlugin extends BasePlugin {
|
||||
static id = 'CheckboxesControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'checkboxes';
|
||||
$schema = '/schemas/CheckboxesControlSchema.json';
|
||||
@ -171,7 +172,9 @@ export class CheckboxesControlPlugin extends BasePlugin {
|
||||
getSchemaTpl('labelRemark'),
|
||||
getSchemaTpl('remark'),
|
||||
getSchemaTpl('description'),
|
||||
getSchemaTpl('autoFillApi')
|
||||
getSchemaTpl('autoFillApi', {
|
||||
trigger: 'change'
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -9,6 +9,7 @@ import {RendererPluginEvent, RendererPluginAction} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
export class CodeEditorControlPlugin extends BasePlugin {
|
||||
static id = 'CodeEditorControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'editor';
|
||||
$schema = '/schemas/EditorControlSchema.json';
|
||||
|
@ -23,6 +23,7 @@ import {
|
||||
} from '../../renderer/event-control/helper';
|
||||
|
||||
export class ComboControlPlugin extends BasePlugin {
|
||||
static id = 'ComboControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'combo';
|
||||
$schema = '/schemas/ComboControlSchema.json';
|
||||
@ -665,24 +666,31 @@ export class ComboControlPlugin extends BasePlugin {
|
||||
target: EditorNodeType,
|
||||
region?: EditorNodeType
|
||||
) {
|
||||
if (target.parent.isRegion && target.parent.region === 'items') {
|
||||
const scope = scopeNode.parent.parent;
|
||||
const builder = this.dsBuilderManager.resolveBuilderBySchema(
|
||||
let scope;
|
||||
let builder;
|
||||
|
||||
if (
|
||||
target.type === scopeNode.type ||
|
||||
(target.parent.isRegion && target.parent.region === 'items')
|
||||
) {
|
||||
scope = scopeNode.parent.parent;
|
||||
builder = this.dsBuilderManager.resolveBuilderBySchema(
|
||||
scope.schema,
|
||||
'api'
|
||||
);
|
||||
}
|
||||
|
||||
if (builder && scope.schema.api) {
|
||||
return builder.getAvailableContextFileds(
|
||||
{
|
||||
schema: scope.schema,
|
||||
sourceKey: 'api',
|
||||
feat: scope.schema?.feat ?? 'List',
|
||||
scopeNode
|
||||
},
|
||||
target
|
||||
);
|
||||
}
|
||||
if (builder && scope.schema.api) {
|
||||
return builder.getAvailableContextFileds(
|
||||
{
|
||||
schema: scope.schema,
|
||||
sourceKey: 'api',
|
||||
feat: scope.schema?.feat ?? 'List',
|
||||
scopeNode
|
||||
},
|
||||
/** ID相同为本体,否则为子项 */
|
||||
target?.id === scopeNode?.id ? scopeNode : target
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import defaultConfig, {
|
||||
} from 'amis-ui/lib/components/condition-builder/config';
|
||||
|
||||
export class ConditionBilderPlugin extends BasePlugin {
|
||||
static id = 'ConditionBilderPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'condition-builder';
|
||||
$schema = '/schemas/ConditionBuilderControlSchema.json';
|
||||
|
@ -6,6 +6,7 @@ import {BasePlugin, RegionConfig, BaseEventContext} from 'amis-editor-core';
|
||||
import {formItemControl} from '../../component/BaseControl';
|
||||
|
||||
export class ControlPlugin extends BasePlugin {
|
||||
static id = 'ControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'control';
|
||||
$schema = '/schemas/FormControlSchema.json';
|
||||
|
@ -14,6 +14,7 @@ import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
import {RendererPluginEvent, RendererPluginAction} from 'amis-editor-core';
|
||||
|
||||
export class DiffEditorControlPlugin extends BasePlugin {
|
||||
static id = 'DiffEditorControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'diff-editor';
|
||||
$schema = '/schemas/DiffEditorControlSchema.json';
|
||||
|
@ -5,6 +5,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BaseEventContext, BasePlugin, RegionConfig} from 'amis-editor-core';
|
||||
|
||||
export class FieldSetControlPlugin extends BasePlugin {
|
||||
static id = 'FieldSetControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'fieldset';
|
||||
$schema = '/schemas/FieldSetControlSchema.json';
|
||||
|
@ -124,6 +124,7 @@ const autoAddOptions = (values: any) => {
|
||||
};
|
||||
|
||||
export class FormPlugin extends BasePlugin {
|
||||
static id = 'FormPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'form';
|
||||
$schema = '/schemas/FormSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BasePlugin} from 'amis-editor-core';
|
||||
|
||||
export class FormulaControlPlugin extends BasePlugin {
|
||||
static id = 'FormulaControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'formula';
|
||||
$schema = '/schemas/FormulaControlSchema.json';
|
||||
|
@ -11,6 +11,7 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {JSONPipeIn, JSONUpdate, makeHorizontalDeeper} from 'amis-editor-core';
|
||||
|
||||
export class GroupControlPlugin extends BasePlugin {
|
||||
static id = 'GroupControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'group';
|
||||
$schema = '/schemas/GroupControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BasePlugin, getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
export class HiddenControlPlugin extends BasePlugin {
|
||||
static id = 'HiddenControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'hidden';
|
||||
$schema = '/schemas/HiddenControlSchema.json';
|
||||
|
@ -15,6 +15,7 @@ import React from 'react';
|
||||
import {diff, JSONPipeOut} from 'amis-editor-core';
|
||||
|
||||
export class ArrayControlPlugin extends BasePlugin {
|
||||
static id = 'ArrayControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-array';
|
||||
$schema = '/schemas/ArrayControlSchema.json';
|
||||
|
@ -15,6 +15,7 @@ import {ValidatorTag} from '../../validator';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
export class CityControlPlugin extends BasePlugin {
|
||||
static id = 'CityControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-city';
|
||||
|
@ -55,6 +55,7 @@ const presetColorsByFormat = colorFormat.reduce<{
|
||||
return res;
|
||||
}, {});
|
||||
export class ColorControlPlugin extends BasePlugin {
|
||||
static id = 'ColorControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-color';
|
||||
|
@ -140,6 +140,7 @@ const dateTooltip =
|
||||
'支持例如: <code>now、+3days、-2weeks、+1hour、+2years</code> 等(minute|min|hour|day|week|month|year|weekday|second|millisecond)这种相对值用法';
|
||||
|
||||
export class DateControlPlugin extends BasePlugin {
|
||||
static id = 'DateControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-date';
|
||||
$schema = '/schemas/DateControlSchema.json';
|
||||
|
@ -181,6 +181,7 @@ const sizeImmutableComponents = Object.values(DateType)
|
||||
.filter(a => a);
|
||||
|
||||
export class DateRangeControlPlugin extends BasePlugin {
|
||||
static id = 'DateRangeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-date-range';
|
||||
$schema = '/schemas/DateRangeControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateControlPlugin} from './InputDate';
|
||||
|
||||
export class DateTimeControlPlugin extends DateControlPlugin {
|
||||
static id = 'DateTimeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-datetime';
|
||||
$schema = '/schemas/DateTimeControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateRangeControlPlugin} from './InputDateRange';
|
||||
|
||||
export class DateTimeRangeControlPlugin extends DateRangeControlPlugin {
|
||||
static id = 'DateTimeRangeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-datetime-range';
|
||||
$schema = '/schemas/DateTimeRangeControlSchema.json';
|
||||
|
@ -2,6 +2,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {TextControlPlugin} from './InputText';
|
||||
|
||||
export class EmailControlPlugin extends TextControlPlugin {
|
||||
static id = 'EmailControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-email';
|
||||
$schema = '/schemas/TextControlSchema.json';
|
||||
|
@ -14,6 +14,7 @@ import {formItemControl} from '../../component/BaseControl';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
|
||||
export class ExcelControlPlugin extends BasePlugin {
|
||||
static id = 'ExcelControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-excel';
|
||||
$schema = '/schemas/ExcelControlSchema.json';
|
||||
|
@ -6,6 +6,7 @@ import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
|
||||
export class FileControlPlugin extends BasePlugin {
|
||||
static id = 'FileControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-file';
|
||||
$schema = '/schemas/FileControlSchema.json';
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
import {ValidatorTag} from '../../validator';
|
||||
|
||||
export class InputGroupControlPlugin extends BasePlugin {
|
||||
static id = 'InputGroupControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-group';
|
||||
|
@ -48,6 +48,7 @@ const inputStateFunc = (visibleOn: string, state: string) => {
|
||||
};
|
||||
|
||||
export class ImageControlPlugin extends BasePlugin {
|
||||
static id = 'ImageControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-image';
|
||||
$schema = '/schemas/ImageControlSchema.json';
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
|
||||
export class KVControlPlugin extends BasePlugin {
|
||||
static id = 'KVControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-kv';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateControlPlugin} from './InputDate';
|
||||
|
||||
export class MonthControlPlugin extends DateControlPlugin {
|
||||
static id = 'MonthControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-month';
|
||||
$schema = '/schemas/MonthControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateRangeControlPlugin} from './InputDateRange';
|
||||
|
||||
export class MonthRangeControlPlugin extends DateRangeControlPlugin {
|
||||
static id = 'MonthRangeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-month-range';
|
||||
$schema = '/schemas/MonthRangeControlSchema.json';
|
||||
|
@ -20,6 +20,7 @@ import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
import {inputStateTpl} from '../../renderer/style-control/helper';
|
||||
|
||||
export class NumberControlPlugin extends BasePlugin {
|
||||
static id = 'NumberControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-number';
|
||||
$schema = '/schemas/NumberControlSchema.json';
|
||||
|
@ -2,6 +2,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {TextControlPlugin} from './InputText';
|
||||
|
||||
export class PasswordControlPlugin extends TextControlPlugin {
|
||||
static id = 'PasswordControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-password';
|
||||
$schema = '/schemas/TextControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateControlPlugin} from './InputDate';
|
||||
|
||||
export class InputQuarterPlugin extends DateControlPlugin {
|
||||
static id = 'InputQuarterPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-quarter';
|
||||
$schema = '/schemas/QuarterControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateRangeControlPlugin} from './InputDateRange';
|
||||
|
||||
export class QuarterRangePlugin extends DateRangeControlPlugin {
|
||||
static id = 'QuarterRangePlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-quarter-range';
|
||||
$schema = '/schemas/MonthRangeControlSchema.json';
|
||||
|
@ -6,6 +6,7 @@ import {ValidatorTag} from '../../validator';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
export class RangeControlPlugin extends BasePlugin {
|
||||
static id = 'RangeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-range';
|
||||
$schema = '/schemas/RangeControlSchema.json';
|
||||
|
@ -12,6 +12,7 @@ import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
|
||||
export class RateControlPlugin extends BasePlugin {
|
||||
static id = 'RateControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-rating';
|
||||
$schema = '/schemas/RatingControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BasePlugin} from 'amis-editor-core';
|
||||
|
||||
export class RepeatControlPlugin extends BasePlugin {
|
||||
static id = 'RepeatControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-repeat';
|
||||
$schema = '/schemas/RepeatControlSchema.json';
|
||||
|
@ -150,6 +150,7 @@ const froalaOptionsPipeOut = (arr: Array<string>) => {
|
||||
};
|
||||
|
||||
export class RichTextControlPlugin extends BasePlugin {
|
||||
static id = 'RichTextControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-rich-text';
|
||||
$schema = '/schemas/RichTextControlSchema.json';
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
|
||||
export class SubFormControlPlugin extends BasePlugin {
|
||||
static id = 'SubFormControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-sub-form';
|
||||
$schema = '/schemas/SubFormControlSchema.json';
|
||||
|
@ -28,6 +28,7 @@ import cloneDeep from 'lodash/cloneDeep';
|
||||
import {resolveArrayDatasource} from '../../util';
|
||||
|
||||
export class TableControlPlugin extends BasePlugin {
|
||||
static id = 'TableControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-table';
|
||||
$schema = '/schemas/TableControlSchema.json';
|
||||
@ -1111,16 +1112,28 @@ export class TableControlPlugin extends BasePlugin {
|
||||
const columns: EditorNodeType = node.children.find(
|
||||
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实现之后,这里可以废弃
|
||||
for (let current of node.schema?.columns) {
|
||||
if (current.name) {
|
||||
itemsSchema.properties[current.name] = {
|
||||
type: 'string',
|
||||
title: current.label || current.name
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1141,24 +1154,31 @@ export class TableControlPlugin extends BasePlugin {
|
||||
target: EditorNodeType,
|
||||
region?: EditorNodeType
|
||||
) {
|
||||
if (target.parent.isRegion && target.parent.region === 'columns') {
|
||||
const scope = scopeNode.parent.parent;
|
||||
const builder = this.dsBuilderManager.resolveBuilderBySchema(
|
||||
let scope;
|
||||
let builder;
|
||||
|
||||
if (
|
||||
target.type === scopeNode.type ||
|
||||
(target.parent.isRegion && target.parent.region === 'columns')
|
||||
) {
|
||||
scope = scopeNode.parent.parent;
|
||||
builder = this.dsBuilderManager.resolveBuilderBySchema(
|
||||
scope.schema,
|
||||
'api'
|
||||
);
|
||||
}
|
||||
|
||||
if (builder && scope.schema.api) {
|
||||
return builder.getAvailableContextFileds(
|
||||
{
|
||||
schema: scope.schema,
|
||||
sourceKey: 'api',
|
||||
feat: scope.schema?.feat ?? 'List',
|
||||
scopeNode
|
||||
},
|
||||
target
|
||||
);
|
||||
}
|
||||
if (builder && scope.schema.api) {
|
||||
return builder.getAvailableContextFileds(
|
||||
{
|
||||
schema: scope.schema,
|
||||
sourceKey: 'api',
|
||||
feat: scope.schema?.feat ?? 'List',
|
||||
scopeNode
|
||||
},
|
||||
/** ID相同为本体,否则为子项 */
|
||||
target?.id === scopeNode?.id ? scopeNode : target
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import {formItemControl} from '../../component/BaseControl';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
|
||||
export class TagControlPlugin extends BasePlugin {
|
||||
static id = 'TagControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-tag';
|
||||
|
@ -20,6 +20,7 @@ function isTextShow(value: string, name: boolean): boolean {
|
||||
}
|
||||
|
||||
export class TextControlPlugin extends BasePlugin {
|
||||
static id = 'TextControlPlugin';
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-text';
|
||||
|
@ -2,6 +2,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateControlPlugin} from './InputDate';
|
||||
|
||||
export class TimeControlPlugin extends DateControlPlugin {
|
||||
static id = 'TimeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-time';
|
||||
$schema = '/schemas/TimeControlSchema.json';
|
||||
|
@ -3,6 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {DateRangeControlPlugin} from './InputDateRange';
|
||||
|
||||
export class TimeRangeControlPlugin extends DateRangeControlPlugin {
|
||||
static id = 'TimeRangeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-time-range';
|
||||
$schema = '/schemas/DateRangeControlSchema.json';
|
||||
|
@ -16,6 +16,7 @@ import {tipedLabel} from 'amis-editor-core';
|
||||
import {ValidatorTag} from '../../validator';
|
||||
|
||||
export class TreeControlPlugin extends BasePlugin {
|
||||
static id = 'TreeControlPlugin';
|
||||
// 关联渲染器名字
|
||||
rendererName = 'input-tree';
|
||||
$schema = '/schemas/TreeControlSchema.json';
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user