mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-15 09:21:13 +08:00
Merge branch 'baidu:master' into master
This commit is contained in:
commit
4b1e0bc3ce
21
.github/workflows/pr-test.yml
vendored
21
.github/workflows/pr-test.yml
vendored
@ -22,12 +22,29 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: test
|
||||
- name: npm install
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=8192'
|
||||
run: |
|
||||
npm i --legacy-peer-deps
|
||||
cd packages/ooxml-viewer
|
||||
npm i --legacy-peer-deps
|
||||
cd ../../
|
||||
npm run build --workspaces
|
||||
npm run build --workspace amis-formula
|
||||
npm run build --workspace amis-core
|
||||
npm run build --workspace amis-ui
|
||||
npm run build --workspace amis
|
||||
npm run build --workspace amis-editor-core
|
||||
npm run build --workspace amis-editor
|
||||
- name: typescript check
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=8192'
|
||||
run: |
|
||||
npm run typecheck
|
||||
- name: test
|
||||
run: |
|
||||
npm test --workspaces
|
||||
cd packages/ooxml-viewer
|
||||
npm test
|
||||
cd ../../
|
||||
sh deploy-gh-pages.sh
|
||||
|
@ -675,12 +675,22 @@ Cards 模式支持 [Cards](./cards) 中的所有功能。
|
||||
|
||||
通过设置`"autoGenerateFilter": true`开启查询区域,会根据列元素的 `searchable` 属性值,自动生成查询条件表单,只有 `searchable` 属性值为合法的组件 Schema 时才会生成查询条件。注意这个属性和 `filter` 冲突,开启 `filter` 后 `autoGenerateFilter` 将会失效。
|
||||
|
||||
### autoGenerateFilter 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| -------------- | --------- | ------ | -------------------- |
|
||||
| columnsNum | `number` | `3` | 过滤条件单行列数 |
|
||||
| showBtnToolbar | `boolean` | `true` | 是否显示设置查询字段 |
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "crud",
|
||||
"api": "/api/mock2/sample",
|
||||
"syncLocation": false,
|
||||
"autoGenerateFilter": true,
|
||||
"autoGenerateFilter": {
|
||||
"columnsNum": 2,
|
||||
"showBtnToolbar": false
|
||||
},
|
||||
"headerToolbar": [
|
||||
{
|
||||
"type": "columns-toggler",
|
||||
@ -704,7 +714,7 @@ Cards 模式支持 [Cards](./cards) 中的所有功能。
|
||||
},
|
||||
{
|
||||
"name": "engine",
|
||||
"label": "Rendering engine"
|
||||
"label": "Rendering engine",
|
||||
},
|
||||
{
|
||||
"name": "browser",
|
||||
@ -2886,7 +2896,7 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
|
||||
| footerToolbar | Array | `['statistics', 'pagination']` | 底部工具栏配置 |
|
||||
| alwaysShowPagination | `boolean` | `false` | 是否总是显示分页 |
|
||||
| affixHeader | `boolean` | `true` | 是否固定表头(table 下) |
|
||||
| autoGenerateFilter | `boolean` | `false` | 是否开启查询区域,开启后会根据列元素的 `searchable` 属性值,自动生成查询条件表单 |
|
||||
| autoGenerateFilter | `Object \| boolean` | | 是否开启查询区域,开启后会根据列元素的 `searchable` 属性值,自动生成查询条件表单 |
|
||||
| resetPageAfterAjaxItemAction | `boolean` | `false` | 单条数据 ajax 操作后是否重置页码为第一页 |
|
||||
| autoFillHeight | `boolean` 丨 `{height: number}` | | 内容区域自适应高度 |
|
||||
|
||||
|
@ -327,7 +327,7 @@ Dialog 弹框 主要由 [Action](./action) 触发,主要展示一个对话框
|
||||
}
|
||||
```
|
||||
|
||||
## 行为后关闭弹框
|
||||
## 动作后关闭弹框
|
||||
|
||||
在弹框中配置行为按钮,可以在按钮上配置`"close": true`,在行为完成后,关闭当前弹框。
|
||||
|
||||
@ -357,9 +357,49 @@ Dialog 弹框 主要由 [Action](./action) 触发,主要展示一个对话框
|
||||
}
|
||||
```
|
||||
|
||||
以上例子是关闭当前弹窗,如果希望关闭上层弹窗,则需要给目标弹窗设置 `name` 属性,然后配置按钮 `close` 属性为目标 `name` 属性如:
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "button",
|
||||
"label": "多级弹框",
|
||||
"actionType": "dialog",
|
||||
"dialog": {
|
||||
"title": "提示",
|
||||
"body": "这是个简单的弹框",
|
||||
"name": "dialog_1",
|
||||
"actions": [
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "confirm",
|
||||
"label": "确认",
|
||||
"primary": true
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "dialog",
|
||||
"label": "再弹一个",
|
||||
"dialog": {
|
||||
"title": "弹框中的弹框",
|
||||
"body": "关闭当前弹窗的时候把外层的弹窗一起关了",
|
||||
"actions": [
|
||||
{
|
||||
"type": "button",
|
||||
"label": "关闭所有",
|
||||
"level": "info",
|
||||
"close": "dialog_1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 配置弹窗的按钮
|
||||
|
||||
可以通过设置 `actions` 来控制弹窗中的按钮。
|
||||
默认弹窗会自动生成两个按钮,一个取消,一个确认。如果通过 `actions` 来自定义配置,则以配置的为准。
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
|
@ -279,6 +279,164 @@ order: 43
|
||||
}
|
||||
```
|
||||
|
||||
## 多级弹框
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "button",
|
||||
"label": "多级弹框",
|
||||
"actionType": "drawer",
|
||||
"drawer": {
|
||||
"title": "提示",
|
||||
"body": "这是个简单的弹框",
|
||||
"actions": [
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "confirm",
|
||||
"label": "确认",
|
||||
"primary": true
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "drawer",
|
||||
"label": "再弹一个",
|
||||
"drawer": {
|
||||
"title": "弹框中的弹框",
|
||||
"body": "如果你想,可以无限弹下去",
|
||||
"actions": [
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "drawer",
|
||||
"label": "来吧",
|
||||
"level": "info",
|
||||
"drawer": {
|
||||
"title": "弹框中的弹框",
|
||||
"body": "如果你想,可以无限弹下去",
|
||||
"actions": [
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "confirm",
|
||||
"label": "不弹了",
|
||||
"primary": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 动作后关闭弹框
|
||||
|
||||
在弹框中配置行为按钮,可以在按钮上配置`"close": true`,在行为完成后,关闭当前弹框。
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "button",
|
||||
"label": "弹个框",
|
||||
"actionType": "drawer",
|
||||
"drawer": {
|
||||
"title": "弹框",
|
||||
"body": [
|
||||
{
|
||||
"type": "button",
|
||||
"label": "默认的 ajax 请求",
|
||||
"actionType": "ajax",
|
||||
"api": "/api/mock2/form/saveForm?waitSeconds=1"
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"label": "ajax 请求成功后关闭弹框",
|
||||
"actionType": "ajax",
|
||||
"api": "/api/mock2/form/saveForm?waitSeconds=1",
|
||||
"close": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
以上例子是关闭当前弹窗,如果希望关闭上层弹窗,则需要给目标弹窗设置 `name` 属性,然后配置按钮 `close` 属性为目标 `name` 属性如:
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "button",
|
||||
"label": "多级弹框",
|
||||
"actionType": "drawer",
|
||||
"drawer": {
|
||||
"title": "提示",
|
||||
"body": "这是个简单的弹框",
|
||||
"name": "drawer_1",
|
||||
"actions": [
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "confirm",
|
||||
"label": "确认",
|
||||
"primary": true
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"actionType": "drawer",
|
||||
"label": "再弹一个",
|
||||
"drawer": {
|
||||
"title": "弹框中的弹框",
|
||||
"body": "关闭当前弹窗的时候把外层的弹窗一起关了",
|
||||
"actions": [
|
||||
{
|
||||
"type": "button",
|
||||
"label": "关闭所有",
|
||||
"level": "info",
|
||||
"close": "drawer_1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 配置弹窗的按钮
|
||||
|
||||
默认弹窗会自动生成两个按钮,一个取消,一个确认。如果通过 `actions` 来自定义配置,则以配置的为准。
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "button-toolbar",
|
||||
"buttons": [
|
||||
{
|
||||
"type": "button",
|
||||
"label": "无按钮",
|
||||
"actionType": "dialog",
|
||||
"dialog": {
|
||||
"title": "提示",
|
||||
"actions": [],
|
||||
"body": "无按钮的弹框"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"label": "只有一个确认按钮",
|
||||
"actionType": "dialog",
|
||||
"dialog": {
|
||||
"title": "提示",
|
||||
"actions": [{
|
||||
"type": "button",
|
||||
"actionType": "confirm",
|
||||
"label": "OK",
|
||||
"primary": true
|
||||
}],
|
||||
"body": "只有一个 OK 的弹框"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
|
@ -1451,17 +1451,17 @@ Form 支持轮询初始化接口,步骤如下:
|
||||
|
||||
当前组件会对外派发以下事件,可以通过`onEvent`来监听这些事件,并通过`actions`来配置执行的动作,在`actions`中可以通过`${事件参数名}`来获取事件产生的数据(`< 2.3.2 及以下版本 为 ${event.data.[事件参数名]}`),详细请查看[事件动作](../../docs/concepts/event-action)。
|
||||
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| --------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| inited | `event.data: object` initApi 远程请求返回的初始化数据 | 远程初始化接口请求成功时触发 |
|
||||
| change | `event.data: object` 当前表单数据 | 表单值变化时触发 |
|
||||
| formItemValidateSucc | `event.data: object` 当前表单数据 | 表单项校验成功时触发 |
|
||||
| formItemValidateError | `event.data: object` 当前表单数据 | 表单项校验失败时触发 |
|
||||
| validateSucc | `event.data: object` 当前表单数据 | 表单校验成功时触发 |
|
||||
| validateError | `event.data: object` 当前表单数据 | 表单校验失败时触发 |
|
||||
| submit | `event.data: object` 当前表单数据 | 点击提交按钮或者触发表单提交动作的时候触发,配置了该事件后将不会触发表单提交时的校验、提交到 api 或者 target 等行为,所有行为需要自己配置 |
|
||||
| submitSucc | `event.data.result: object` api 远程请求成功后返回的结果数据 | 提交成功时触发 |
|
||||
| submitFail | `event.data.error: object` api 远程请求失败后返回的错误信息 | 提交失败时触发 |
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| inited | `responseData: any` 请求的响应数据</br>`responseStatus: number` 响应状态,0 表示成功</br>`responseMsg: string`响应消息, `error`表示接口是否成功<br/>`[name]: any` 当前数据域中指定字段的值 | initApi 接口请求完成时触发 |
|
||||
| change | `event.data: object` 当前表单数据 | 表单值变化时触发 |
|
||||
| formItemValidateSucc | `event.data: object` 当前表单数据 | 表单项校验成功时触发 |
|
||||
| formItemValidateError | `event.data: object` 当前表单数据 | 表单项校验失败时触发 |
|
||||
| validateSucc | `event.data: object` 当前表单数据 | 表单校验成功时触发 |
|
||||
| validateError | `event.data: object` 当前表单数据 | 表单校验失败时触发 |
|
||||
| submit | `event.data: object` 当前表单数据 | 点击提交按钮或者触发表单提交动作的时候触发,配置了该事件后将不会触发表单提交时的校验、提交到 api 或者 target 等行为,所有行为需要自己配置 |
|
||||
| submitSucc | `event.data.result: object` api 远程请求成功后返回的结果数据 | 提交成功时触发 |
|
||||
| submitFail | `event.data.error: object` api 远程请求失败后返回的错误信息 | 提交失败时触发 |
|
||||
|
||||
## 动作表
|
||||
|
||||
|
@ -77,6 +77,90 @@ key 只能是字符串,因此输入格式是 `input-text`,但 value 格式
|
||||
}
|
||||
```
|
||||
|
||||
## 自定义 value 的 schema
|
||||
|
||||
> 3.1.0 及以上版本
|
||||
|
||||
默认创建的 value schema 是
|
||||
|
||||
```json
|
||||
{
|
||||
"placeholder": "Value",
|
||||
"type": "input-text",
|
||||
"name": "value"
|
||||
}
|
||||
```
|
||||
|
||||
前面的配置可以改其中的 type 或 placeholder,而这个新的 `valueSchema` 配置就能做到替换所有配置,比如
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"api": "/api/mock2/form/saveForm",
|
||||
"debug": true,
|
||||
"body": [
|
||||
{
|
||||
"type": "input-kv",
|
||||
"name": "css",
|
||||
"valueSchema": {
|
||||
"type": "select",
|
||||
"options": [
|
||||
{
|
||||
"label": "A",
|
||||
"value": "a"
|
||||
},
|
||||
{
|
||||
"label": "B",
|
||||
"value": "b"
|
||||
},
|
||||
{
|
||||
"label": "C",
|
||||
"value": "c"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 自定义 key schema
|
||||
|
||||
> 3.1.0 及以上版本
|
||||
|
||||
和前面的 value schema 类似,还可以自定义 key 的 schema
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"api": "/api/mock2/form/saveForm",
|
||||
"debug": true,
|
||||
"body": [
|
||||
{
|
||||
"type": "input-kv",
|
||||
"name": "css",
|
||||
"keySchema": {
|
||||
"type": "select",
|
||||
"options": [
|
||||
{
|
||||
"label": "A",
|
||||
"value": "a"
|
||||
},
|
||||
{
|
||||
"label": "B",
|
||||
"value": "b"
|
||||
},
|
||||
{
|
||||
"label": "C",
|
||||
"value": "c"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 关闭可拖拽排序
|
||||
|
||||
```schema: scope="body"
|
||||
|
@ -71,7 +71,7 @@ Word 渲染支持以下功能:
|
||||
|
||||
> 2.10.0 及以上版本
|
||||
|
||||
默认情况下 word 文档渲染使用流式布局,这样能更好融入到已有页面中,但展现上会和原先的文档有较大差异,且不支持页眉页脚,如果希望能看起来更像桌面端的效果,可以通过 `page` 配置开启分页渲染,只有在分页渲染
|
||||
默认情况下 word 文档渲染使用流式布局,这样能更好融入到已有页面中,但展现上会和原先的文档有较大差异,且不支持页眉页脚,如果希望能看起来更像桌面端的效果,可以通过 `page` 配置开启分页渲染
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
@ -205,7 +205,7 @@ Word 渲染支持以下功能:
|
||||
},
|
||||
{
|
||||
"type": "service",
|
||||
"api": "/api/mock2/sample/mirror?json=%7B%22users%22%3A%5B%7B%22name%22%3A%22u1%22%2C%22age%22%3A10%7D%2C%7B%22name%22%3A%22u2%22%2C%22age%22%3A11%7D%5D%7D",
|
||||
"api": "/api/mock2/sample/mirror?json=%7B%22users%22%3A%5B%7B%22name%22%3A%22u1%22%2C%22age%22%3A10%2C%22img%22%3A%22https%3A%2F%2Fsuda.cdn.bcebos.com%2Fimages%2Famis%2Fai-fake-face.jpg%22%7D%2C%7B%22name%22%3A%22u2%22%2C%22age%22%3A11%7D%5D%7D",
|
||||
"body": [{
|
||||
"type": "office-viewer",
|
||||
"src": "/examples/static/table-list.docx",
|
||||
@ -240,6 +240,41 @@ Word 渲染支持以下功能:
|
||||
|
||||
注意上面的例子用到了 `trackExpression`,默认情况下如果设置了 `enableVar`,每次上层数据变化都会重新渲染文档,如果文档较大可能会有性能问题,这时可以通过配置 `trackExpression` 来限制只有某个数据变化时才重新渲染。
|
||||
|
||||
### 图片中的变量
|
||||
|
||||
> 2.10 及以上版本
|
||||
|
||||
如果要将文档中的图片设置为变量,需要右键对应的图片,选择「查看可选文字」,然后填入类似 `{{img}}` 变量标识,在渲染时图片将替换为这个 `img` 变量的 url 地址
|
||||
|
||||
![word](../../../examples/static/word-alt.png)
|
||||
|
||||
下面是示例
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"title": "",
|
||||
"wrapWithPanel": false,
|
||||
"body": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "img",
|
||||
"value": "https://suda.cdn.bcebos.com/images/amis/ai-fake-face.jpg",
|
||||
"label": "图片地址"
|
||||
},
|
||||
{
|
||||
"type": "office-viewer",
|
||||
"id": "office-viewer",
|
||||
"src": "/examples/static/image-alt-var.docx",
|
||||
"wordOptions": {
|
||||
"enableVar": true,
|
||||
"padding": "8px"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 不渲染模式
|
||||
|
||||
通过配置 `display: false` 可以让文档不渲染,虽然不渲染,但还是可以使用后面的下载及打印功能
|
||||
|
@ -286,11 +286,11 @@ Page 默认将页面分为几个区域,分别是**内容区(`body`)**、**
|
||||
|
||||
> `[name]`为当前数据域中的字段名,例如:当前数据域为 {username: 'amis'},则可以通过${username}获取对应的值。
|
||||
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| ----------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------- |
|
||||
| init | - | 组件实例被创建并插入 DOM 中时触发。2.4.1 及以上版本 |
|
||||
| inited | `event.data` initApi 远程请求返回的初始化数据<br/>`[name]: any` 当前数据域中指定字段的值 | 远程初始化接口请求成功时触发 |
|
||||
| pullRefresh | - | 开启下拉刷新后,下拉释放后触发(仅用于移动端) |
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- |
|
||||
| init | - | 组件实例被创建并插入 DOM 中时触发。2.4.1 及以上版本 |
|
||||
| inited | `responseData: any` 请求的响应数据</br>`responseStatus: number` 响应状态,0 表示成功</br>`responseMsg: string`响应消息, `error`表示接口是否成功<br/>`[name]: any` 当前数据域中指定字段的值 | initApi 接口请求完成时触发 |
|
||||
| pullRefresh | - | 开启下拉刷新后,下拉释放后触发(仅用于移动端) |
|
||||
|
||||
## 动作表
|
||||
|
||||
|
@ -735,7 +735,7 @@ ws.on('connection', function connection(ws) {
|
||||
| interval | `number` | | 轮询时间间隔,单位 ms(最低 1000) |
|
||||
| silentPolling | `boolean` | `false` | 配置轮询时是否显示加载动画 |
|
||||
| stopAutoRefreshWhen | [表达式](../../docs/concepts/expression) | | 配置停止轮询的条件 |
|
||||
| showErrorMsg | `boolean` | `true` | 是否以Alert的形式显示api接口响应的错误信息,默认展示 | `2.8.1` |
|
||||
| showErrorMsg | `boolean` | `true` | 是否以 Alert 的形式显示 api 接口响应的错误信息,默认展示 | `2.8.1` |
|
||||
|
||||
## 事件表
|
||||
|
||||
@ -743,11 +743,11 @@ ws.on('connection', function connection(ws) {
|
||||
|
||||
> `[name]`为当前数据域中的字段名,例如:当前数据域为 {username: 'amis'},则可以通过${username}获取对应的值。
|
||||
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
|
||||
| init | - | 组件实例被创建并插入 DOM 中时触发。2.4.1 及以上版本 |
|
||||
| fetchInited | `event.data` api 远程请求返回的初始化数据<br/>`[name]: any` 当前数据域中指定字段的值</br>`__response: {msg: string; error: boolean}`接口元数据, `msg`为消息体, `error`表示接口是否成功 | 远程初始化接口请求成功时触发 |
|
||||
| fetchSchemaInited | `event.data` schemaApi 远程请求返回的 UI 内容<br/>`[name]: any` 当前数据域中指定字段的值`__response: {msg: string; error: boolean}`接口元数据, `msg`为消息体, `error`表示接口是否成功 | 远程 schemaApi UI 内容接口请求成功 |
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- |
|
||||
| init | - | 组件实例被创建并插入 DOM 中时触发。2.4.1 及以上版本 |
|
||||
| fetchInited | `responseData: any` 请求的响应数据</br>`responseStatus: number` 响应状态,0 表示成功</br>`responseMsg: string`响应消息, `error`表示接口是否成功<br/>`[name]: any` 当前数据域中指定字段的值 | api 接口请求完成时触发 |
|
||||
| fetchSchemaInited | `responseData: any` 请求的响应数据</br>`responseStatus: number` 响应状态,0 表示成功</br>`responseMsg: string`响应消息, `error`表示接口是否成功<br/>`[name]: any` 当前数据域中指定字段的值 | schemaApi 接口请求完成时触发 |
|
||||
|
||||
## 动作表
|
||||
|
||||
|
@ -73,6 +73,7 @@ order: 71
|
||||
| videoType | `string` | | 指定直播视频格式 |
|
||||
| poster | `string` | | 视频封面地址 |
|
||||
| muted | `boolean` | | 是否静音 |
|
||||
| loop | `boolean` | | 是否循环播放 |
|
||||
| autoPlay | `boolean` | | 是否自动播放 |
|
||||
| rates | `array` | | 倍数,格式为`[1.0, 1.5, 2.0]` |
|
||||
| frames | `object` | | key 是时刻信息,value 可以可以为空,可有设置为图片地址,请看上方示例 |
|
||||
|
@ -16,7 +16,6 @@ order: 73
|
||||
{
|
||||
"type": "wizard",
|
||||
"initApi": "/api/mock2/form/saveForm?waitSeconds=2",
|
||||
"mode": "vertical",
|
||||
"steps": [
|
||||
{
|
||||
"title": "第一步",
|
||||
@ -101,16 +100,16 @@ order: 73
|
||||
|
||||
> `[name]`为当前数据域中的字段名,例如:当前数据域为 {username: 'amis'},则可以通过${username}获取对应的值。
|
||||
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| -------------- | ------------------------------------------------------------------------------------------------ | ---------------------------- |
|
||||
| inited | `event.data: object` initApi 远程请求返回的初始化数据<br/>`[name]: any` 当前数据域中指定字段的值 | 远程初始化接口请求成功时触发 |
|
||||
| stepChange | `step: number` 步骤索引 | 切换步骤时触发 |
|
||||
| change | `event.data: object` 当前表单数据<br/>`[name]: any` 当前数据域中指定字段的值 | 表单值变化时触发 |
|
||||
| stepSubmitSucc | - | 单个步骤提交成功 |
|
||||
| stepSubmitFail | `error: object` 单个步骤 api 远程请求失败后返回的错误信息 | 单个步骤提交失败 |
|
||||
| finished | `event.data: object` 即将提交的表单数据<br/>`[name]: any` 当前数据域中指定字段的值 | 最终提交时触发 |
|
||||
| submitSucc | `result: object` api 远程请求成功后返回的结果数据 | 最终提交成功时触发 |
|
||||
| submitFail | `error: object` api 远程请求失败后返回的错误信息 | 最终提交失败时触发 |
|
||||
| 事件名称 | 事件参数 | 说明 |
|
||||
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------- |
|
||||
| inited | `responseData: any` 请求的响应数据</br>`responseStatus: number` 响应状态,0 表示成功</br>`responseMsg: string`响应消息, `error`表示接口是否成功<br/>`[name]: any` 当前数据域中指定字段的值 | initApi 接口请求完成时触发 |
|
||||
| stepChange | `step: number` 步骤索引 | 切换步骤时触发 |
|
||||
| change | `event.data: object` 当前表单数据<br/>`[name]: any` 当前数据域中指定字段的值 | 表单值变化时触发 |
|
||||
| stepSubmitSucc | - | 单个步骤提交成功 |
|
||||
| stepSubmitFail | `error: object` 单个步骤 api 远程请求失败后返回的错误信息 | 单个步骤提交失败 |
|
||||
| finished | `event.data: object` 即将提交的表单数据<br/>`[name]: any` 当前数据域中指定字段的值 | 最终提交时触发 |
|
||||
| submitSucc | `result: object` api 远程请求成功后返回的结果数据 | 最终提交成功时触发 |
|
||||
| submitFail | `error: object` api 远程请求失败后返回的错误信息 | 最终提交失败时触发 |
|
||||
|
||||
## 动作表
|
||||
|
||||
|
@ -42,11 +42,11 @@ amis 主要代码在 `src` 和 `scss` 目录下,这里主要介绍 `src` 下
|
||||
|
||||
虽然文件很多,但对于组件开发而言,大部分情况下只需要关注 `components` 及 `renderers` 目录下的内容就行,如果发现某个组件不满足需求,可以先在 `renderers` 中找到这个组件,对齐进行修改就行。
|
||||
|
||||
下面我们将以一个实际例子来介绍如果新增一个组件。
|
||||
下面我们将以一个实际例子来介绍如何新增一个组件。
|
||||
|
||||
## 实战:avatar 组件
|
||||
|
||||
本文的目标是新增 avatar 头像组件,完整演示如何在 amis 中添加一个新组建,完整实现可以参考这个 [pr](https://github.com/baidu/amis/pull/1684/files),本文基于这个例子进行了简化。
|
||||
本文的目标是新增 avatar 头像组件,完整演示如何在 amis 中添加一个新组件,完整实现可以参考这个 [pr](https://github.com/baidu/amis/pull/1684/files),本文基于这个例子进行了简化。
|
||||
|
||||
### 编写 React 组件代码代码
|
||||
|
||||
|
@ -141,7 +141,7 @@ export default {
|
||||
columns: [
|
||||
{
|
||||
name: 'icon',
|
||||
label: '图标',
|
||||
label: '<%= "图标" %>',
|
||||
type: 'image'
|
||||
},
|
||||
{
|
||||
@ -158,7 +158,8 @@ export default {
|
||||
},
|
||||
{
|
||||
name: 'engine.name',
|
||||
label: '引擎'
|
||||
label: '引擎',
|
||||
className: 'text-primary'
|
||||
},
|
||||
{
|
||||
name: 'browser',
|
||||
@ -170,9 +171,11 @@ export default {
|
||||
},
|
||||
{
|
||||
name: 'engine.version',
|
||||
label: 'CSS版本',
|
||||
label: '引擎版本',
|
||||
type: 'tpl',
|
||||
tpl: '<b>${engine.version}</b>'
|
||||
tpl: '<b>${engine.version}</b>',
|
||||
classNameExpr:
|
||||
"<%= data.engine.version > 4 ? 'bg-green-100' : 'bg-red-50' %>"
|
||||
},
|
||||
{
|
||||
name: 'grade',
|
||||
|
@ -164,7 +164,7 @@ export default class DocSearch extends React.Component {
|
||||
show={this.state.show}
|
||||
position={'right'}
|
||||
>
|
||||
<div className={`${this.props.theme.ns}TextControl-input search-bar`}>
|
||||
<div className={`search-bar`}>
|
||||
<Icon icon="search" className="icon" />
|
||||
<input
|
||||
ref={this.ref}
|
||||
|
@ -49,11 +49,11 @@ const LazyComponent = lazyData(
|
||||
},
|
||||
{
|
||||
title: 'X 轴',
|
||||
body: Axis('x')
|
||||
body: (Axis as any)('x')
|
||||
},
|
||||
{
|
||||
title: 'Y 轴',
|
||||
body: Axis('y')
|
||||
body: (Axis as any)('y')
|
||||
},
|
||||
{
|
||||
title: '极标',
|
||||
|
@ -128,6 +128,7 @@ import Loading from './Loading';
|
||||
import CodeSchema from './Code';
|
||||
import OfficeViewer from './OfficeViewer';
|
||||
import InputTableEvent from './EventAction/cmpt-event-action/InputTableEvent';
|
||||
import WizardPage from './WizardPage';
|
||||
|
||||
import {Switch} from 'react-router-dom';
|
||||
import {navigations2route} from './App';
|
||||
@ -908,6 +909,13 @@ export const examples = [
|
||||
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
label: 'wizard页面',
|
||||
icon: 'fa fa-desktop',
|
||||
path: '/examples/wizard-page',
|
||||
component: makeSchemaRenderer(WizardPage)
|
||||
}
|
||||
|
||||
// {
|
||||
|
117
examples/components/WizardPage.jsx
Normal file
117
examples/components/WizardPage.jsx
Normal file
@ -0,0 +1,117 @@
|
||||
export default {
|
||||
"type": "page",
|
||||
"title": "Simple Form Page",
|
||||
"regions": [
|
||||
"body"
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"type": "wizard",
|
||||
"steps": [
|
||||
{
|
||||
"title": "基本信息",
|
||||
"hiddenOn": "${!validateCode}",
|
||||
"body": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"label": "用户名",
|
||||
"name": "username",
|
||||
"value": "12121123123",
|
||||
"mode": "horizontal"
|
||||
},
|
||||
{
|
||||
"type": "input-password",
|
||||
"label": "密码",
|
||||
"name": "password",
|
||||
"value": "qwerasdfzxcv",
|
||||
"mode": "horizontal"
|
||||
},
|
||||
{
|
||||
"type": "input-password",
|
||||
"label": "确认密码",
|
||||
"name": "confirmPassword",
|
||||
"mode": "horizontal"
|
||||
},
|
||||
{
|
||||
"type": "button-group-select",
|
||||
"name": "hiddenTest",
|
||||
"label": "测试下隐藏",
|
||||
"inline": false,
|
||||
"value": 1,
|
||||
"options": [
|
||||
{
|
||||
"label": "选项1",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"label": "选项2",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"id": "u:20069f4652a4",
|
||||
"multiple": false,
|
||||
"mode": "horizontal"
|
||||
}
|
||||
],
|
||||
"id": "u:4a7fd475044b",
|
||||
"mode": "normal"
|
||||
},
|
||||
{
|
||||
"title": "验证码",
|
||||
"body": [
|
||||
{
|
||||
"type": "input-group",
|
||||
"label": "验证码",
|
||||
"body": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"label": "验证码",
|
||||
"name": "validateCode",
|
||||
"mode": "horizontal"
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"label": "发送验证码"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": "normal"
|
||||
},
|
||||
{
|
||||
"title": "确认信息",
|
||||
"body": [
|
||||
{
|
||||
"type": "tpl",
|
||||
"tpl": "用户名: ${username}"
|
||||
},
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "hahahha"
|
||||
}
|
||||
],
|
||||
"mode": "normal"
|
||||
}
|
||||
],
|
||||
"id": "u:4bd3ac2a9a78",
|
||||
"mode": "horizontal",
|
||||
"stepsClassName": "w-1/2 mx-auto",
|
||||
"wrapWithPanel": false,
|
||||
"footerClassName": "bg-white fixed -bottom-0 w-full",
|
||||
"className": "bg-gray-50 overflow-hidden h-full -mx-3 -my-4",
|
||||
"stepClassName": "overflow-hidden mb-14",
|
||||
"bodyClassName": "bg-white wizard-body"
|
||||
}
|
||||
],
|
||||
"id": "u:ee4880c00289",
|
||||
"pullRefresh": {
|
||||
"disabled": true
|
||||
},
|
||||
"css": {
|
||||
".wizard-body": {
|
||||
"margin": "16px",
|
||||
"padding": "24px"
|
||||
}
|
||||
},
|
||||
"className": "h-full"
|
||||
}
|
@ -33,8 +33,8 @@
|
||||
};
|
||||
|
||||
Object.keys(mapping).forEach(key => {
|
||||
amis.require.aliasMapping[key] = mapping[key];
|
||||
(window as any).amis.require.aliasMapping[key] = mapping[key];
|
||||
});
|
||||
|
||||
(window as any).amisRequire = amis.require;
|
||||
(window as any).amisRequire = (window as any).amis.require;
|
||||
})();
|
||||
|
@ -14,7 +14,9 @@ import 'core-js/es/map';
|
||||
import 'core-js/es/set';
|
||||
import 'core-js/es/symbol';
|
||||
|
||||
// @ts-ignore
|
||||
import './cloest';
|
||||
// @ts-ignore
|
||||
import './classList';
|
||||
|
||||
// ios 没有这个会报错
|
||||
|
@ -1,18 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="@fortawesome/fontawesome-free/css/all.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="@fortawesome/fontawesome-free/css/v4-shims.css"
|
||||
/>
|
||||
<link rel="stylesheet" title="ang" href="amis-ui/scss/helper.scss" />
|
||||
<link rel="stylesheet" href="@fortawesome/fontawesome-free/css/v4-shims.css" />
|
||||
<!--DEPENDENCIES_INJECT_PLACEHOLDER-->
|
||||
<!--STYLE_PLACEHOLDER-->
|
||||
<link rel="stylesheet" title="ang" href="amis-ui/scss/themes/ang.scss" />
|
||||
<link rel="stylesheet" title="cxd" href="amis-ui/scss/themes/cxd.scss" />
|
||||
<link rel="stylesheet" title="dark" href="amis-ui/scss/themes/dark.scss" />
|
||||
<link rel="stylesheet" title="antd" href="amis-ui/scss/themes/antd.scss" />
|
||||
<link rel="stylesheet" title="helper" href="amis-ui/scss/helper.scss" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -31,4 +29,4 @@
|
||||
})(window);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
BIN
examples/static/image-alt-var.docx
Normal file
BIN
examples/static/image-alt-var.docx
Normal file
Binary file not shown.
Binary file not shown.
BIN
examples/static/word-alt.png
Normal file
BIN
examples/static/word-alt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 215 KiB |
@ -949,16 +949,23 @@ body {
|
||||
|
||||
.search-bar {
|
||||
padding: 22px 20px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #e8ebee;
|
||||
border-radius: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
|
||||
> .icon-search {
|
||||
margin-right: 10px;
|
||||
top: 1px;
|
||||
}
|
||||
> input {
|
||||
flex-basis: 1.875rem;
|
||||
flex-grow: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result {
|
||||
|
@ -5,5 +5,5 @@
|
||||
"packages/amis-ui",
|
||||
"packages/amis"
|
||||
],
|
||||
"version": "2.9.0"
|
||||
"version": "3.0.0"
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// cfc 入口。
|
||||
exports.handler = (event, context, callback) => {
|
||||
try {
|
||||
// @ts-ignore
|
||||
const entry = require('./mock/index');
|
||||
entry(mockRequest(event, context), mockResponse(event, context, callback));
|
||||
} catch (e) {
|
||||
@ -55,7 +56,7 @@ function mockResponse(event, context, callback) {
|
||||
function createHeaders(headers) {
|
||||
let referer = '';
|
||||
|
||||
if (/^(https?\:\/\/[^:\/]+(?:\:\d+)?\/)/i.test(headers['referer'])) {
|
||||
if (/^(https?\:\/\/[^:\/]+(?:\:\d+)?\/)/i.test(headers['Referer'])) {
|
||||
referer = RegExp.$1.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
@ -63,6 +64,7 @@ function createHeaders(headers) {
|
||||
'Content-Type': 'Application/json',
|
||||
'Access-Control-Allow-Headers': 'x-requested-with,content-type',
|
||||
'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS,HEAD',
|
||||
'Access-Control-Allow-Origin': referer ? `${referer}` : '*'
|
||||
'Access-Control-Allow-Origin': referer ? `${referer}` : '*',
|
||||
'Access-Control-Allow-Credentials': 'true'
|
||||
};
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
* @file 用于模拟 cfc 接口
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
const cfcHandler = require('./cfc/index').handler;
|
||||
|
||||
module.exports = function (req, res) {
|
||||
|
@ -24,7 +24,8 @@
|
||||
"release": "npm run build --workspaces && lerna publish from-package --registry=https://registry.npmjs.org --ignore-scripts",
|
||||
"revision": "ts-node ./scripts/generate-revision.ts",
|
||||
"publish-to-internal": "sh ./publish-to-internal.sh",
|
||||
"stylelint": "npx stylelint 'packages/**/*.scss'"
|
||||
"stylelint": "npx stylelint 'packages/**/*.scss'",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "amis-core",
|
||||
"version": "2.9.0",
|
||||
"version": "3.0.0",
|
||||
"description": "amis-core",
|
||||
"main": "lib/index.js",
|
||||
"module": "esm/index.js",
|
||||
@ -45,7 +45,7 @@
|
||||
"esm"
|
||||
],
|
||||
"dependencies": {
|
||||
"amis-formula": "^2.9.0",
|
||||
"amis-formula": "^3.0.0",
|
||||
"classnames": "2.3.1",
|
||||
"file-saver": "^2.0.2",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
|
@ -65,6 +65,7 @@ export class RootRenderer extends React.Component<RootRendererProps> {
|
||||
}
|
||||
|
||||
componentDidCatch(error: any, errorInfo: any) {
|
||||
this.props.env?.errorCatcher?.(error, errorInfo);
|
||||
this.store.setRuntimeError(error, errorInfo);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,9 @@ export interface IScopedContext {
|
||||
closeById: (target: string) => void;
|
||||
}
|
||||
type AliasIScopedContext = IScopedContext;
|
||||
export const ScopedContext = React.createContext(createScopedTools(''));
|
||||
|
||||
const rootScopedContext = createScopedTools('');
|
||||
export const ScopedContext = React.createContext(rootScopedContext);
|
||||
|
||||
function createScopedTools(
|
||||
path?: string,
|
||||
@ -115,7 +117,7 @@ function createScopedTools(
|
||||
getComponentById(id: string) {
|
||||
let root: AliasIScopedContext = this;
|
||||
// 找到顶端scoped
|
||||
while (root.parent) {
|
||||
while (root.parent && root.parent !== rootScopedContext) {
|
||||
root = root.parent;
|
||||
}
|
||||
|
||||
@ -130,6 +132,7 @@ function createScopedTools(
|
||||
return false;
|
||||
})
|
||||
) as ScopedComponentType | undefined;
|
||||
|
||||
return component;
|
||||
},
|
||||
|
||||
|
@ -181,9 +181,12 @@ interface OverlayProps {
|
||||
shouldUpdatePosition?: boolean;
|
||||
rootClose?: boolean;
|
||||
onHide?(props: any, ...args: any[]): any;
|
||||
container?: HTMLElement | (() => HTMLElement | null | undefined);
|
||||
container?:
|
||||
| HTMLElement
|
||||
| React.ReactNode
|
||||
| (() => HTMLElement | React.ReactNode | null | undefined);
|
||||
containerSelector?: string;
|
||||
target?: React.ReactNode | Function;
|
||||
target?: React.ReactNode | HTMLElement | Function;
|
||||
watchTargetSizeChange?: boolean;
|
||||
offset?: [number, number];
|
||||
onEnter?(node: HTMLElement): any;
|
||||
|
@ -57,6 +57,10 @@ export interface RendererEnv {
|
||||
watchRouteChange?: (fn: () => void) => () => void;
|
||||
// 用于跟踪用户在界面中的各种操作
|
||||
tracker: (eventTrack: EventTrack, props?: PlainObject) => void;
|
||||
/**
|
||||
* 捕获amis执行中的错误信息
|
||||
*/
|
||||
errorCatcher: (error: any, errorInfo: any) => void;
|
||||
rendererResolver?: (
|
||||
path: string,
|
||||
schema: Schema,
|
||||
|
@ -270,13 +270,13 @@ export const defaultOptions: RenderOptions = {
|
||||
},
|
||||
isCancel() {
|
||||
console.error(
|
||||
'Please implement isCancel. see https://baidu.gitee.io/amis/docs/start/getting-started#%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97'
|
||||
'Please implement isCancel. see https://aisuda.bce.baidu.com/amis/zh-CN/start/getting-started#%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97'
|
||||
);
|
||||
return false;
|
||||
},
|
||||
updateLocation() {
|
||||
console.error(
|
||||
'Please implement updateLocation. see https://baidu.gitee.io/amis/docs/start/getting-started#%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97'
|
||||
'Please implement updateLocation. see https://aisuda.bce.baidu.com/amis/zh-CN/start/getting-started#%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97'
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -186,7 +186,7 @@ export interface FormSchemaBase {
|
||||
/**
|
||||
* Form 用来保存数据的 api。
|
||||
*
|
||||
* 详情:https://baidu.gitee.io/amis/docs/components/form/index#%E8%A1%A8%E5%8D%95%E6%8F%90%E4%BA%A4
|
||||
* 详情:https://aisuda.bce.baidu.com/amis/zh-CN/components/form/index#%E8%A1%A8%E5%8D%95%E6%8F%90%E4%BA%A4
|
||||
*/
|
||||
api?: string | BaseApiObject;
|
||||
|
||||
@ -706,7 +706,12 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
// 派发init事件,参数为初始化数据
|
||||
const dispatcher = await dispatchEvent(
|
||||
'inited',
|
||||
createObject(this.props.data, data)
|
||||
createObject(this.props.data, {
|
||||
...data, // 保留,兼容历史
|
||||
responseData: data ?? {},
|
||||
responseStatus: store.error ? 1 : 0,
|
||||
responseMsg: store.msg
|
||||
})
|
||||
);
|
||||
if (!dispatcher?.prevented) {
|
||||
onInit && onInit(data, this.props);
|
||||
|
@ -890,6 +890,7 @@ export class FormItemWrap extends React.Component<FormItemProps> {
|
||||
{
|
||||
'is-inline': !!rest.inline && !mobileUI,
|
||||
'is-error': model && !model.valid,
|
||||
'is-full': size === 'full',
|
||||
[`Form-control--withSize Form-control--size${ucFirst(
|
||||
controlSize
|
||||
)}`]:
|
||||
@ -1729,6 +1730,7 @@ export function asFormItem(config: Omit<FormItemConfig, 'component'>) {
|
||||
{
|
||||
'is-inline': !!rest.inline && !mobileUI,
|
||||
'is-error': model && !model.valid,
|
||||
'is-full': size === 'full',
|
||||
[`Form-control--withSize Form-control--size${ucFirst(
|
||||
controlSize
|
||||
)}`]:
|
||||
|
@ -183,13 +183,14 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
|
||||
})
|
||||
];
|
||||
});
|
||||
items = items.filter((item: any) => arrItems.find(a => a === item));
|
||||
items = items.filter((item: any) =>
|
||||
arrItems.find(a => a === item)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
items = matchSorter(items, value, {
|
||||
keys: [key]
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -349,11 +350,11 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
|
||||
})
|
||||
];
|
||||
});
|
||||
filteredItems = filteredItems.filter(
|
||||
item => arrItems.find(a => a === item));
|
||||
filteredItems = filteredItems.filter(item =>
|
||||
arrItems.find(a => a === item)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
filteredItems = matchSorter(filteredItems, value, {
|
||||
keys: [key]
|
||||
});
|
||||
|
@ -63,11 +63,11 @@ export const Column = types
|
||||
className: types.union(types.string, types.frozen())
|
||||
})
|
||||
.actions(self => ({
|
||||
toggleToggle() {
|
||||
toggleToggle(min = 1) {
|
||||
self.toggled = !self.toggled;
|
||||
const table = getParent(self, 2) as ITableStore;
|
||||
|
||||
if (!table.activeToggaleColumns.length) {
|
||||
if (table.activeToggaleColumns.length < min) {
|
||||
self.toggled = true;
|
||||
}
|
||||
|
||||
@ -344,6 +344,8 @@ export const TableStore = iRendererStore
|
||||
formsRef: types.optional(types.array(types.frozen()), []),
|
||||
maxKeepItemSelectionLength: Infinity,
|
||||
keepItemSelectionOnPageChange: false,
|
||||
// 导出 Excel 按钮的 loading 状态
|
||||
exportExcelLoading: false,
|
||||
searchFormExpanded: false // 用来控制搜索框是否展开了,那个自动根据 searchable 生成的表单 autoGenerateFilter
|
||||
})
|
||||
.views(self => {
|
||||
@ -805,6 +807,9 @@ export const TableStore = iRendererStore
|
||||
(self.keepItemSelectionOnPageChange =
|
||||
config.keepItemSelectionOnPageChange);
|
||||
|
||||
config.exportExcelLoading !== undefined &&
|
||||
(self.exportExcelLoading = config.exportExcelLoading);
|
||||
|
||||
if (config.columns && Array.isArray(config.columns)) {
|
||||
let columns: Array<SColumn> = config.columns
|
||||
.filter(column => column)
|
||||
@ -1424,10 +1429,11 @@ export const TableStore = iRendererStore
|
||||
});
|
||||
}
|
||||
|
||||
function toggleAllColumns() {
|
||||
function toggleAllColumns(min: number = 1) {
|
||||
if (self.activeToggaleColumns.length) {
|
||||
if (self.activeToggaleColumns.length === self.toggableColumns.length) {
|
||||
self.toggableColumns.map(column => column.setToggled(false));
|
||||
toggleColumnsAtLeast(min);
|
||||
} else {
|
||||
self.toggableColumns.map(column => column.setToggled(true));
|
||||
}
|
||||
@ -1438,6 +1444,14 @@ export const TableStore = iRendererStore
|
||||
persistSaveToggledColumns();
|
||||
}
|
||||
|
||||
function toggleColumnsAtLeast(min: number = 1) {
|
||||
if (self.activeToggaleColumns.length < min) {
|
||||
for (let i = 0; i < min; i++) {
|
||||
self.toggableColumns[i]?.setToggled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getPersistDataKey(columns: any[]) {
|
||||
// 这里的columns使用除了__开头的所有列
|
||||
// sort保证存储和读取的key值保持一致
|
||||
@ -1477,6 +1491,7 @@ export const TableStore = iRendererStore
|
||||
exchange,
|
||||
addForm,
|
||||
toggleAllColumns,
|
||||
toggleColumnsAtLeast,
|
||||
persistSaveToggledColumns,
|
||||
setSearchFormExpanded,
|
||||
toggleSearchFormExpanded,
|
||||
|
@ -211,8 +211,7 @@ export const TableStore2 = ServiceStore.named('TableStore2')
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
dragging: false,
|
||||
keepItemSelectionOnPageChange: false,
|
||||
maxKeepItemSelectionLength: 0
|
||||
rowSelectionKeyField: 'key'
|
||||
})
|
||||
.views(self => {
|
||||
function getToggable() {
|
||||
@ -324,6 +323,13 @@ export const TableStore2 = ServiceStore.named('TableStore2')
|
||||
},
|
||||
|
||||
get currentSelectedRowKeys() {
|
||||
if (self.data && self.data.selectedItems) {
|
||||
return (
|
||||
self.data.selectedItems.map(
|
||||
(item: any) => item[self.rowSelectionKeyField]
|
||||
) || []
|
||||
);
|
||||
}
|
||||
return self.selectedRowKeys.map(item => item);
|
||||
},
|
||||
|
||||
@ -356,6 +362,10 @@ export const TableStore2 = ServiceStore.named('TableStore2')
|
||||
|
||||
get movedRows() {
|
||||
return getMovedRows();
|
||||
},
|
||||
|
||||
get keyField() {
|
||||
return self.rowSelectionKeyField;
|
||||
}
|
||||
};
|
||||
})
|
||||
@ -390,11 +400,9 @@ export const TableStore2 = ServiceStore.named('TableStore2')
|
||||
);
|
||||
}
|
||||
|
||||
config.maxKeepItemSelectionLength !== void 0 &&
|
||||
(self.maxKeepItemSelectionLength = config.maxKeepItemSelectionLength);
|
||||
config.keepItemSelectionOnPageChange !== void 0 &&
|
||||
(self.keepItemSelectionOnPageChange =
|
||||
config.keepItemSelectionOnPageChange);
|
||||
if (config.rowSelectionKeyField) {
|
||||
self.rowSelectionKeyField = config.rowSelectionKeyField;
|
||||
}
|
||||
|
||||
if (config.columns && Array.isArray(config.columns)) {
|
||||
self.columns.replace(updateColumns(config.columns) as any);
|
||||
@ -486,39 +494,36 @@ export const TableStore2 = ServiceStore.named('TableStore2')
|
||||
setTimeout(updater.bind(null, `?${qsstringify(self.query)}`), 4);
|
||||
}
|
||||
|
||||
function updateSelectedRows(
|
||||
rows: Array<any>,
|
||||
selectedKeys: Array<any>,
|
||||
keyField?: string
|
||||
) {
|
||||
function updateSelectedRows(rows: Array<any>, selectedKeys: Array<any>) {
|
||||
const rowSelectionKeyField = self.rowSelectionKeyField;
|
||||
eachTree(rows, item => {
|
||||
if (~selectedKeys.indexOf(item.pristine[keyField || 'key'])) {
|
||||
if (~selectedKeys.indexOf(item.pristine[rowSelectionKeyField])) {
|
||||
self.selectedRows.push(item.id);
|
||||
self.selectedRowKeys.push(item.pristine[keyField || 'key']);
|
||||
self.selectedRowKeys.push(item.pristine[rowSelectionKeyField]);
|
||||
} else if (
|
||||
find(selectedKeys, a => a && a == item.pristine[keyField || 'key'])
|
||||
find(selectedKeys, a => a && a == item.pristine[rowSelectionKeyField])
|
||||
) {
|
||||
self.selectedRows.push(item.id);
|
||||
self.selectedRowKeys.push(item.pristine[keyField || 'key']);
|
||||
self.selectedRowKeys.push(item.pristine[rowSelectionKeyField]);
|
||||
} else if (item.children) {
|
||||
updateSelectedRows(item.children, selectedKeys, keyField);
|
||||
updateSelectedRows(item.children, selectedKeys);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateSelected(selectedKeys: Array<any>, keyField?: string) {
|
||||
function updateSelected(selectedKeys: Array<any>) {
|
||||
self.selectedRows.clear();
|
||||
self.selectedRowKeys.clear();
|
||||
|
||||
updateSelectedRows(self.rows, selectedKeys, keyField);
|
||||
updateSelectedRows(self.rows, selectedKeys);
|
||||
}
|
||||
|
||||
function updateSelectedAll(keyField?: string) {
|
||||
function updateSelectedAll() {
|
||||
const selectedKeys: Array<any> = [];
|
||||
eachTree(self.rows, item =>
|
||||
selectedKeys.push(item.pristine[keyField || 'key'])
|
||||
selectedKeys.push(item.pristine[self.rowSelectionKeyField])
|
||||
);
|
||||
updateSelectedRows(self.rows, selectedKeys, keyField);
|
||||
updateSelectedRows(self.rows, selectedKeys);
|
||||
}
|
||||
|
||||
function updateExpanded(expandedRowKeys: Array<any>, keyField?: string) {
|
||||
@ -630,7 +635,6 @@ export const TableStore2 = ServiceStore.named('TableStore2')
|
||||
: []
|
||||
};
|
||||
});
|
||||
|
||||
replaceRow(arr, reUseRow);
|
||||
}
|
||||
|
||||
|
@ -625,6 +625,13 @@ export interface BaseSchemaWithoutType {
|
||||
*/
|
||||
staticInputClassName?: SchemaClassName;
|
||||
staticSchema?: any;
|
||||
|
||||
/**
|
||||
* 组件样式
|
||||
*/
|
||||
style?: {
|
||||
[propName: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
export type OperatorType =
|
||||
|
@ -97,28 +97,97 @@ export class DataScope {
|
||||
return false;
|
||||
}
|
||||
|
||||
assignSchema(target: any, schema: any): any {
|
||||
// key相同,type也相同
|
||||
if (target.type && target.type === schema.type) {
|
||||
if (target.type === 'array') {
|
||||
// 先只考虑items,不考虑contains
|
||||
if (target.items) {
|
||||
if (Array.isArray(target.items)) {
|
||||
if (schema.items) {
|
||||
if (Array.isArray(schema.items)) {
|
||||
// 如果都是数组,就后者覆盖前者
|
||||
return schema.items;
|
||||
} else {
|
||||
// 否则,追加
|
||||
return {
|
||||
...target,
|
||||
items: [...target.items, schema.items]
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...target,
|
||||
...schema
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// 非数组,则merge
|
||||
return {
|
||||
...target,
|
||||
items: this.assignSchema(target.items, schema.items)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return schema;
|
||||
}
|
||||
} else if (target.type === 'object' && target.properties) {
|
||||
let properties: any = {};
|
||||
|
||||
// 合并属性
|
||||
for (let key of Array.from(
|
||||
new Set([
|
||||
...Object.keys(target.properties),
|
||||
...Object.keys(schema.properties)
|
||||
])
|
||||
)) {
|
||||
const value = target.properties[key];
|
||||
if (value) {
|
||||
properties[key] = schema.properties[key]
|
||||
? this.assignSchema(value, schema.properties[key])
|
||||
: value;
|
||||
} else {
|
||||
properties[key] = schema.properties[key];
|
||||
}
|
||||
}
|
||||
return {
|
||||
...target,
|
||||
properties
|
||||
};
|
||||
} else {
|
||||
return schema;
|
||||
}
|
||||
} else {
|
||||
// key相同、type不同
|
||||
if (Array.isArray(target.oneOf)) {
|
||||
return {
|
||||
...target, // 先做个显示过度,因formula还没支持oneOf
|
||||
oneOf: [...target.oneOf, schema]
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...target, // 先做个显示过度,因formula还没支持oneOf
|
||||
oneOf: [target, schema]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getMergedSchema() {
|
||||
const mergedSchema: any = {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
};
|
||||
|
||||
// todo 以后再来细化这一块,先粗略的写个大概
|
||||
this.schemas.forEach(schema => {
|
||||
const properties: any = schema.properties || {};
|
||||
Object.keys(properties).forEach(key => {
|
||||
const value = properties[key];
|
||||
if (mergedSchema.properties[key]) {
|
||||
if (Array.isArray(mergedSchema.properties[key].oneOf)) {
|
||||
mergedSchema.properties[key].oneOf.push();
|
||||
} else if (
|
||||
mergedSchema.properties[key].type &&
|
||||
mergedSchema.properties[key].type !== value.type
|
||||
) {
|
||||
mergedSchema.properties[key] = {
|
||||
oneOf: [mergedSchema.properties[key], value]
|
||||
};
|
||||
}
|
||||
mergedSchema.properties[key] = this.assignSchema(
|
||||
mergedSchema.properties[key],
|
||||
value
|
||||
);
|
||||
} else {
|
||||
mergedSchema.properties[key] = value;
|
||||
}
|
||||
@ -132,19 +201,14 @@ export class DataScope {
|
||||
options: Array<any>,
|
||||
schema: JSONSchema,
|
||||
path: string = '',
|
||||
key: string = '',
|
||||
/** 是否数组元素,数组元素的内容将获取每个成员的对应值 */
|
||||
isArrayItem = false,
|
||||
/** 不是所有的都可以选择,但不影响子元素 */
|
||||
disabled?: boolean
|
||||
key: string = ''
|
||||
) {
|
||||
// todo 支持 oneOf, anyOf
|
||||
const option: any = {
|
||||
label: schema.title || key,
|
||||
value: path,
|
||||
type: schema.type,
|
||||
tag: schema.description ?? schema.type,
|
||||
disabled
|
||||
tag: schema.description ?? schema.type
|
||||
};
|
||||
|
||||
options.push(option);
|
||||
@ -155,43 +219,32 @@ export class DataScope {
|
||||
|
||||
keys.forEach(key => {
|
||||
const child: any = schema.properties![key];
|
||||
const newPath = isArrayItem ? `ARRAYMAP(${path}, item => item.${key})` : (path + (path ? '.' : '') + key);
|
||||
|
||||
this.buildOptions(
|
||||
option.children,
|
||||
child,
|
||||
newPath,
|
||||
key,
|
||||
isArrayItem,
|
||||
false
|
||||
path + (path ? '.' : '') + key,
|
||||
key
|
||||
);
|
||||
});
|
||||
} else if (schema.type === 'array' && schema.items) {
|
||||
option.children = [];
|
||||
|
||||
this.buildOptions(
|
||||
option.children,
|
||||
{
|
||||
title: '成员',
|
||||
...(schema.items as any)
|
||||
},
|
||||
path,
|
||||
'items',
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
this.buildOptions(
|
||||
option.children,
|
||||
{
|
||||
title: '总数',
|
||||
type: 'number'
|
||||
title: '成员',
|
||||
...(schema.items as any),
|
||||
disabled: true
|
||||
},
|
||||
path + (path ? '.' : '') + 'length',
|
||||
'length',
|
||||
true,
|
||||
isArrayItem
|
||||
path,
|
||||
'items'
|
||||
);
|
||||
|
||||
option.children = mapTree(option.children, item => ({
|
||||
...item,
|
||||
disabled: true
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,4 +272,8 @@ export class DataScope {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getSchemaById(id: string) {
|
||||
return this.schemas?.find(item => item.$id === id);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export function attachmentAdpator(response: any, __: Function) {
|
||||
if (disposition && disposition.indexOf('attachment') !== -1) {
|
||||
// disposition 有可能是 attachment; filename="??.xlsx"; filename*=UTF-8''%E4%B8%AD%E6%96%87.xlsx
|
||||
// 这种情况下最后一个才是正确的文件名
|
||||
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)$/;
|
||||
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
|
||||
|
||||
let matches = disposition.match(filenameRegex);
|
||||
if (matches && matches.length) {
|
||||
|
@ -431,13 +431,14 @@ type Category = 'api' | 'event';
|
||||
* @param ext 扩展信息
|
||||
*/
|
||||
export function debug(cat: Category, msg: string, ext?: object) {
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.groupCollapsed('[amis debug]', msg);
|
||||
console.debug(ext);
|
||||
console.groupEnd();
|
||||
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
const log = {
|
||||
cat,
|
||||
level: 'debug',
|
||||
|
@ -844,6 +844,27 @@ export function findTree<T extends TreeItem>(
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在树中查找节点。
|
||||
* @param tree
|
||||
* @param iterator
|
||||
*/
|
||||
export function findTreeAll<T extends TreeItem>(
|
||||
tree: Array<T>,
|
||||
iterator: (item: T, key: number, level: number, paths: Array<T>) => any
|
||||
): Array<T> {
|
||||
let result: Array<T> = [];
|
||||
|
||||
everyTree(tree, (item, key, level, paths) => {
|
||||
if (iterator(item, key, level, paths)) {
|
||||
result.push(item);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在树中查找节点, 返回下标数组。
|
||||
* @param tree
|
||||
@ -1658,7 +1679,9 @@ export function isClickOnInput(e: React.MouseEvent<HTMLElement>) {
|
||||
if (
|
||||
!e.currentTarget.contains(target) ||
|
||||
~['INPUT', 'TEXTAREA'].indexOf(target.tagName) ||
|
||||
((formItem = target.closest(`button, a, [data-role="form-item"]`)) &&
|
||||
((formItem = target.closest(
|
||||
`button, a, [data-role="form-item"], label[data-role="checkbox"]`
|
||||
)) &&
|
||||
e.currentTarget.contains(formItem))
|
||||
) {
|
||||
return true;
|
||||
|
@ -118,7 +118,7 @@ export const bindEvent = (renderer: any) => {
|
||||
actions: listener.actions
|
||||
});
|
||||
}
|
||||
if (!listener && listeners[key].actions.length) {
|
||||
if (!listener && listeners[key].actions?.length) {
|
||||
rendererEventListeners.push({
|
||||
renderer,
|
||||
type: key,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Evaluator, parse} from 'amis-formula';
|
||||
import {Evaluator, parse, evaluateForAsync} from 'amis-formula';
|
||||
|
||||
export const tokenize = (
|
||||
str: string,
|
||||
|
@ -83,6 +83,17 @@ export function register(): Enginer & {name: string} {
|
||||
} catch (e) {
|
||||
return `error: ${e.message}`;
|
||||
}
|
||||
},
|
||||
asyncCompile: async (
|
||||
str: string,
|
||||
data: object,
|
||||
defaultFilter = '| html'
|
||||
) => {
|
||||
try {
|
||||
return resolveVariableAndFilterForAsync(str, data, defaultFilter);
|
||||
} catch (e) {
|
||||
return `error: ${e.message}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ export function register(): Enginer & {name: string} {
|
||||
return {
|
||||
name: 'lodash',
|
||||
test: (str: string) => !!~str.indexOf('<%'),
|
||||
compile: (str: string, data: object) => lodashCompile(str, data)
|
||||
compile: (str: string, data: object) => lodashCompile(str, data),
|
||||
asyncCompile: (str: string, data: object) => lodashCompile(str, data)
|
||||
};
|
||||
}
|
||||
|
@ -7,6 +7,11 @@ export interface Enginer {
|
||||
test: (tpl: string) => boolean;
|
||||
removeEscapeToken?: (tpl: string) => string;
|
||||
compile: (tpl: string, data: object, ...rest: Array<any>) => string;
|
||||
asyncCompile: (
|
||||
tpl: string,
|
||||
data: object,
|
||||
...rest: Array<any>
|
||||
) => Promise<string>;
|
||||
}
|
||||
|
||||
const enginers: {
|
||||
@ -39,6 +44,28 @@ export function filter(
|
||||
return tpl;
|
||||
}
|
||||
|
||||
export function asyncFilter(
|
||||
tpl?: any,
|
||||
data: object = {},
|
||||
...rest: Array<any>
|
||||
): Promise<string> {
|
||||
if (!tpl || typeof tpl !== 'string') {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
||||
let keys = Object.keys(enginers);
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
let enginer = enginers[keys[i]];
|
||||
if (enginer.test(tpl)) {
|
||||
return enginer.asyncCompile(tpl, data, ...rest);
|
||||
} else if (enginer.removeEscapeToken) {
|
||||
tpl = enginer.removeEscapeToken(tpl);
|
||||
}
|
||||
}
|
||||
|
||||
return tpl;
|
||||
}
|
||||
|
||||
// 缓存一下提升性能
|
||||
const EVAL_CACHE: {[key: string]: Function} = {};
|
||||
|
||||
@ -175,6 +202,7 @@ export function evalJS(js: string, data: object): any {
|
||||
registerTplEnginer(info.name, {
|
||||
test: info.test,
|
||||
compile: info.compile,
|
||||
asyncCompile: info.asyncCompile,
|
||||
removeEscapeToken: info.removeEscapeToken
|
||||
});
|
||||
});
|
||||
|
@ -30,8 +30,8 @@ module.exports = {
|
||||
path: './'
|
||||
},
|
||||
translate: {
|
||||
appId: '20220902001329332',
|
||||
key: 'pVS96QbIzVROBSOarU4R',
|
||||
appId: '20230324001613652', // 私人翻译账户,如有国际化需求,请申请自己的百度翻译服务
|
||||
key: 'Sprp7Mz8_yydeyhYrgE0',
|
||||
host: 'http://api.fanyi.baidu.com'
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "amis-editor-core",
|
||||
"version": "5.2.5-alpha.16",
|
||||
"version": "5.3.0",
|
||||
"description": "amis 可视化编辑器",
|
||||
"main": "lib/index.js",
|
||||
"module": "esm/index.js",
|
||||
@ -83,6 +83,7 @@
|
||||
"concurrently": "^6.2.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"faker": "^5.5.3",
|
||||
"i18n-command": "^0.0.23-beta.15",
|
||||
"mini-css-extract-plugin": "^2.3.0",
|
||||
"postcss-import": "^14.1.0",
|
||||
"postcss-minify": "^1.1.0",
|
||||
@ -111,8 +112,8 @@
|
||||
"amis": "*",
|
||||
"amis-core": "*",
|
||||
"amis-formula": "*",
|
||||
"amis-ui": "*",
|
||||
"amis-theme-editor-helper": "*",
|
||||
"amis-ui": "*",
|
||||
"i18n-runtime": "*",
|
||||
"react": ">=16.8.6",
|
||||
"react-dom": ">=16.8.6"
|
||||
|
@ -109,7 +109,4 @@
|
||||
--link-onClick-fontSize: #{$Editor-right-panel-font-size};
|
||||
--radio-default-default-fontSize: #{$Editor-right-panel-font-size};
|
||||
--select-base-default-option-fontSize: #{$Editor-right-panel-font-size};
|
||||
--Tabs--line-fontSize: #{$Editor-right-panel-font-size};
|
||||
--Tabs--line-active-fontSize: #{$Editor-right-panel-font-size};
|
||||
--Tabs--line-hover-fontSize: #{$Editor-right-panel-font-size};
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ $category-2-height: px2rem(32px);
|
||||
$tooltip-bottom: '[data-tooltip][data-position=' bottom ']:hover:after';
|
||||
|
||||
.editor-right-panel {
|
||||
@include panel-sm-content();
|
||||
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
width: $right-panel-width;
|
||||
|
@ -83,6 +83,9 @@
|
||||
|
||||
.ae-ApiControl-form {
|
||||
@include panel-sm-content();
|
||||
--Tabs--line-fontSize: #{$Editor-right-panel-font-size};
|
||||
--Tabs--line-active-fontSize: #{$Editor-right-panel-font-size};
|
||||
--Tabs--line-hover-fontSize: #{$Editor-right-panel-font-size};
|
||||
.ae-ApiControl-tabContent {
|
||||
max-height: 560px;
|
||||
overflow-x: hidden;
|
||||
|
@ -25,6 +25,7 @@ div.ae-editor-FormulaControl {
|
||||
|
||||
& &-input {
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
border-radius: var(--input-default-default-top-left-border-radius) 0 0
|
||||
var(--input-default-default-bottom-left-border-radius);
|
||||
max-width: calc(100% - 29px); // 避免表达式内容太长撑开面板
|
||||
@ -32,6 +33,11 @@ div.ae-editor-FormulaControl {
|
||||
&.is-clearable {
|
||||
padding-right: 30px; // 避免间隙过大
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&-select-style {
|
||||
|
@ -12,8 +12,8 @@ import {
|
||||
} from './DSBuilder';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import type {ButtonSchema} from 'amis/lib/renderers/Action';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis/lib/Schema';
|
||||
import type {ButtonSchema} from 'amis';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis';
|
||||
|
||||
import type {DSSourceSettingFormConfig} from './DSBuilder';
|
||||
import {getSchemaTpl, tipedLabel} from '../tpl';
|
||||
@ -578,15 +578,19 @@ class APIBuilder extends DSBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
public resolveSimpleFilterSchema(config: {setting: any}) {
|
||||
const {setting} = config;
|
||||
public resolveSimpleFilterSchema(config: {
|
||||
setting: any;
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'full';
|
||||
}) {
|
||||
const {setting, size} = config;
|
||||
const fields = setting.simpleQueryFields || [];
|
||||
return fields
|
||||
.filter((i: any) => i.checked)
|
||||
.map((field: any) => ({
|
||||
type: field.inputType,
|
||||
name: field.name,
|
||||
label: field.label
|
||||
label: field.label,
|
||||
size
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
* 数据源构造器,可用于对接当前amis中的扩展数据源
|
||||
*/
|
||||
|
||||
import type {ButtonSchema} from 'amis/lib/renderers/Action';
|
||||
import type {CRUD2Schema} from 'amis/lib/renderers/CRUD2';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis/lib/Schema';
|
||||
import type {ButtonSchema} from 'amis';
|
||||
import type {CRUD2Schema} from 'amis';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis';
|
||||
import {EditorNodeType} from '../store/node';
|
||||
|
||||
/**
|
||||
@ -230,7 +230,10 @@ export abstract class DSBuilder {
|
||||
feat?: DSFeatureType;
|
||||
}): SchemaObject[];
|
||||
|
||||
abstract resolveSimpleFilterSchema(config: {setting: any}): SchemaObject[];
|
||||
abstract resolveSimpleFilterSchema(config: {
|
||||
setting: any;
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'full';
|
||||
}): SchemaObject[];
|
||||
|
||||
abstract resolveAdvancedFilterSchema(config: {
|
||||
setting: any;
|
||||
|
@ -3,7 +3,7 @@ import cx from 'classnames';
|
||||
import Preview from './Preview';
|
||||
import {autobind} from '../util';
|
||||
import {MainStore, EditorStoreType} from '../store/editor';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {EditorManager, EditorManagerConfig, PluginClass} from '../manager';
|
||||
import {reaction} from 'mobx';
|
||||
import {RenderOptions, toast} from 'amis';
|
||||
@ -475,7 +475,7 @@ export default class Editor extends Component<EditorProps> {
|
||||
|
||||
preview() {
|
||||
if (this.props.onPreview) {
|
||||
this.props.onPreview(true);
|
||||
this.props.onPreview(!this.props.preview);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,9 @@ const ShortcutKeyList = [
|
||||
tooltip: '保存当前所有操作'
|
||||
},
|
||||
{
|
||||
title: '预览',
|
||||
title: '预览/编辑',
|
||||
letters: ['⌘', 'p'],
|
||||
tooltip: '开启预览模式'
|
||||
tooltip: '开启/关闭预览模式'
|
||||
},
|
||||
{
|
||||
title: '删除',
|
||||
|
@ -264,5 +264,8 @@ extendLocale('en-US', {
|
||||
'5b804b05e14aaacc75033a4f77fc2844': 'Source code',
|
||||
'69a53230577258b6d97ee932befcc168': '<Column>:',
|
||||
'cc6aeb073ebc3cb29734a49164f8964c': 'Page variables',
|
||||
'b71e8739cb9bcba8057a8fa8b59512da': '<Column>'
|
||||
'b71e8739cb9bcba8057a8fa8b59512da': '<Column>',
|
||||
'34d240d1ded259c32f7fee21e99c5671': 'Preview/Edit',
|
||||
'6722089d251c1e4aabe9d58c26a2208a': 'Turn preview mode on/off',
|
||||
'107542a61cdccbb2981ad0c8bafc3440': 'Replace component'
|
||||
});
|
||||
|
@ -236,5 +236,8 @@ extendLocale('zh-CN', {
|
||||
'5b804b05e14aaacc75033a4f77fc2844': '源码',
|
||||
'69a53230577258b6d97ee932befcc168': '<列>:',
|
||||
'cc6aeb073ebc3cb29734a49164f8964c': '页面变量',
|
||||
'b71e8739cb9bcba8057a8fa8b59512da': '<列>'
|
||||
'b71e8739cb9bcba8057a8fa8b59512da': '<列>',
|
||||
'34d240d1ded259c32f7fee21e99c5671': '预览/编辑',
|
||||
'6722089d251c1e4aabe9d58c26a2208a': '开启/关闭预览模式',
|
||||
'107542a61cdccbb2981ad0c8bafc3440': '替换组件'
|
||||
});
|
||||
|
@ -66,7 +66,7 @@ import findIndex from 'lodash/findIndex';
|
||||
import {EditorDNDManager} from './dnd';
|
||||
import {VariableManager} from './variable';
|
||||
import {IScopedContext} from 'amis';
|
||||
import type {SchemaObject, SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaObject, SchemaCollection} from 'amis';
|
||||
import type {RendererConfig} from 'amis-core';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import {omit} from 'lodash';
|
||||
@ -121,6 +121,7 @@ export function registerEditorPlugin(klass: PluginClass) {
|
||||
isExitPlugin = builtInPlugins.find(item => item === klass);
|
||||
}
|
||||
if (!isExitPlugin) {
|
||||
klass.id = klass.id || klass.name || guid();
|
||||
builtInPlugins.push(klass);
|
||||
} else {
|
||||
console.warn(`注册插件异常,已存在同名插件:`, klass);
|
||||
@ -132,7 +133,9 @@ export function registerEditorPlugin(klass: PluginClass) {
|
||||
*/
|
||||
export function getEditorPlugins(options: any = {}) {
|
||||
const {scene = 'global'} = options;
|
||||
return builtInPlugins.filter(item => item.scene?.includes(scene));
|
||||
return builtInPlugins.filter(item =>
|
||||
(Array.isArray(item) ? item[0] : item).scene?.includes(scene)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,15 +330,29 @@ export class EditorManager {
|
||||
);
|
||||
}
|
||||
|
||||
normalizeScene(plugins?: Array<PluginClass>) {
|
||||
normalizeScene(
|
||||
plugins?: Array<
|
||||
| PluginClass
|
||||
| [PluginClass, Record<string, any> | (() => Record<string, any>)]
|
||||
>
|
||||
): (
|
||||
| PluginClass
|
||||
| [PluginClass, Record<string, any> | (() => Record<string, any>)]
|
||||
)[] {
|
||||
return (
|
||||
plugins?.map((klass: PluginClass) => {
|
||||
plugins?.map(klass => {
|
||||
let options;
|
||||
if (Array.isArray(klass)) {
|
||||
options = klass[1];
|
||||
klass = klass[0];
|
||||
}
|
||||
|
||||
// 处理插件身上的场景信息
|
||||
const scene = Array.from(
|
||||
new Set(['global'].concat(klass.scene || 'global'))
|
||||
);
|
||||
klass.scene = scene;
|
||||
return klass;
|
||||
return options ? [klass, options] : klass;
|
||||
}) || []
|
||||
);
|
||||
}
|
||||
@ -618,7 +635,7 @@ export class EditorManager {
|
||||
* 备注3: 建议优先使用当前选中组件ID(this.store.activeId)来更新属性配置面板;
|
||||
* @param pluginType 组件类型
|
||||
*/
|
||||
updateConfigPanel(pluginType: string) {
|
||||
updateConfigPanel(pluginType?: string) {
|
||||
const {activeId, getSchema, getNodeById} = this.store;
|
||||
let curPluginType = pluginType;
|
||||
|
||||
@ -850,6 +867,9 @@ export class EditorManager {
|
||||
) {
|
||||
// 布局能力提升: 点击插入新元素,当wrapper为空插入布局容器时,自动改为置换,避免过多层级
|
||||
this.replaceChild(curActiveId, curElemSchema);
|
||||
setTimeout(() => {
|
||||
this.updateConfigPanel();
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
|
||||
/**
|
||||
* @file amis schema 配置模板,主要很多地方都要全部配置的化,
|
||||
|
@ -8,7 +8,7 @@ import DeepDiff, {Diff} from 'deep-diff';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
import type {Schema} from 'amis';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {assign, cloneDeep} from 'lodash';
|
||||
import {getGlobalData} from 'amis-theme-editor-helper';
|
||||
|
||||
@ -931,32 +931,43 @@ export function isObject(curObj: any) {
|
||||
return isObject;
|
||||
}
|
||||
|
||||
export function jsonToJsonSchema(json: any = {}) {
|
||||
export function jsonToJsonSchema(
|
||||
json: any = {},
|
||||
titleBuilder?: (type: string, key: string) => string,
|
||||
maxDepth: number = 3
|
||||
) {
|
||||
const jsonschema: any = {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
};
|
||||
Object.keys(json).forEach(key => {
|
||||
const value = json[key];
|
||||
const type = typeof value;
|
||||
|
||||
if (~['string', 'number'].indexOf(type)) {
|
||||
jsonschema.properties[key] = {
|
||||
type: type,
|
||||
title: key
|
||||
};
|
||||
} else if (type === 'object' && value) {
|
||||
jsonschema.properties[key] = {
|
||||
type: 'object',
|
||||
title: key
|
||||
};
|
||||
} else {
|
||||
jsonschema.properties[key] = {
|
||||
type: '',
|
||||
title: key
|
||||
};
|
||||
}
|
||||
});
|
||||
isObservable(json) ||
|
||||
maxDepth <= 0 ||
|
||||
Object.keys(json).forEach(key => {
|
||||
const value = json[key];
|
||||
const type = Array.isArray(value) ? 'array' : typeof value;
|
||||
|
||||
if (~['string', 'number'].indexOf(type)) {
|
||||
jsonschema.properties[key] = {
|
||||
type,
|
||||
title: titleBuilder?.(type, key) || key
|
||||
};
|
||||
} else if (~['object', 'array'].indexOf(type) && value) {
|
||||
jsonschema.properties[key] = {
|
||||
type,
|
||||
title: titleBuilder?.(type, key) || key,
|
||||
...(type === 'object'
|
||||
? jsonToJsonSchema(value, titleBuilder, maxDepth - 1)
|
||||
: {items: jsonToJsonSchema(value[0], titleBuilder, maxDepth - 1)})
|
||||
};
|
||||
} else {
|
||||
jsonschema.properties[key] = {
|
||||
type: '',
|
||||
title: titleBuilder?.(type, key) || key
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return jsonschema;
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,8 @@ module.exports = {
|
||||
path: './'
|
||||
},
|
||||
translate: {
|
||||
appId: '20220902001329332',
|
||||
key: 'pVS96QbIzVROBSOarU4R',
|
||||
appId: '20230324001613652', // 私人翻译账户,如有国际化需求,请申请自己的百度翻译服务
|
||||
key: 'Sprp7Mz8_yydeyhYrgE0',
|
||||
host: 'http://api.fanyi.baidu.com'
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "amis-editor",
|
||||
"version": "5.2.5-alpha.16",
|
||||
"version": "5.3.0",
|
||||
"description": "amis 可视化编辑器",
|
||||
"main": "lib/index.js",
|
||||
"module": "esm/index.js",
|
||||
@ -74,6 +74,7 @@
|
||||
"concurrently": "^6.2.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"faker": "^5.5.3",
|
||||
"i18n-command": "^0.0.23-beta.15",
|
||||
"mini-css-extract-plugin": "^2.3.0",
|
||||
"prettier": "^2.2.1",
|
||||
"react": "^18.2.0",
|
||||
|
@ -5,11 +5,7 @@
|
||||
import React from 'react';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import {toast} from 'amis';
|
||||
import {
|
||||
TableViewSchema,
|
||||
TdObject,
|
||||
TrObject
|
||||
} from 'amis/lib/renderers/TableView';
|
||||
import {TableViewSchema, TrObject} from 'amis';
|
||||
import {EditorManager} from 'amis-editor-core';
|
||||
import {autobind, JSONGetById, EditorStoreType} from 'amis-editor-core';
|
||||
|
||||
|
@ -3850,5 +3850,123 @@ extendLocale('en-US', {
|
||||
'6922790f45faf064e063069816e4d2ec':
|
||||
'After opening, all the original data will be flattened and set in the data, and customized on this basis',
|
||||
'9791b05a4df9d72f1a01b81fa695fbc6':
|
||||
'When the grouping names of multiple columns are consistent, the table will display the super header on the upper layer of the display header.<a href=“ https://baidu.github.io/amis/zh-CN/components/table#%E8%B6%85%E7%BA%A7%E8%A1%A8%E5%A4%B4 " target="_ Blank ">Example</a>'
|
||||
'When the grouping names of multiple columns are consistent, the table will display the super header on the upper layer of the display header.<a href=“ https://baidu.github.io/amis/zh-CN/components/table#%E8%B6%85%E7%BA%A7%E8%A1%A8%E5%A4%B4 " target="_ Blank ">Example</a>',
|
||||
'7441768e25f67a80f0f2173c2a618c35': 'Date value',
|
||||
'8036cf5e8dbf62ee4f4e896f7354ce5c': 'Date Time Value',
|
||||
'598f69a9b640508d8e124fd7d33131f0': 'Select icon',
|
||||
'ef79da787ad206e5d5f8cf62e195c836': 'Icon size',
|
||||
'ff58428ef8221c4c1bbf532dd3c77113': 'Icon Bottom Margin',
|
||||
'88f109195ad926bcd436f0c56198240d': 'Image upload button',
|
||||
'd825ba2b8ea0c1b0737b0dd5ca9bc128': 'Upload icon',
|
||||
'bade9c4e0b8a75a251c1a2760571d3c3': 'Number Input Box Style',
|
||||
'53069052573de671c6e5108de745b036': 'Number input box',
|
||||
'5c48fa6f337d2b5dd168a0887c6baa2b': 'Table Form Data',
|
||||
'fb7b49ff7f85f6e3f995b5eaae42d084': 'Label selection',
|
||||
'0aefac04b467ce313ca6b05e33c6145a': 'Maximum Word Count',
|
||||
'188676cb26835b8e4d8ea568467c55cd': 'Limit the maximum number of text input',
|
||||
'f1ee660e12ef0b76c10cccc3d923e605':
|
||||
'AK cannot be empty, please visit http://lbsyun.baidu.com/ Obtain Key (AK)',
|
||||
'4d01bb9f50eb1480e0e9995a2a003181':
|
||||
'Please select<a href=“ http://lbsyun.baidu.com/ " target="_ Blank "class=" text sm ">Baidu Maps open platform</a>Get',
|
||||
'f1f7a5f821ca0ee4caaa9324eda48d91': 'Static Form Item',
|
||||
'4602761ee85e2e6e5360cd13fe642a08':
|
||||
'<p>The current component has stopped maintenance. It is recommended that you use the new feature of<a="/amis/zh CN/components/form/formitem #% E9% 85% 8D% E7% BD% AE% E9% 9D% 99% E6% 80% 81% E5% B1% 95% E7% A4% BA" target="_blank">static display</a>to achieve static display of form items</ p>',
|
||||
'6ca92e3386f9e392584367df5054c27c':
|
||||
'Used to display an icon, you can configure different icon styles.',
|
||||
'47fd366b711a0567646854f541449f8b':
|
||||
'For example: ${listVar}, used to associate existing data in the scope',
|
||||
'98204720c30a843a9234bdf22dc05d51': 'Elastic Layout Settings',
|
||||
'3212f1de74130815d12d982437fc6919': 'Document Preview',
|
||||
'a7199769ae58f8a5c35ac0e5f8804abf': 'Office Document Preview',
|
||||
'e414473c886072e393710563f201d7f3': 'Printing',
|
||||
'6a62d33c838524f0609a624aa59ee9e7': 'print a document',
|
||||
'f26ef914245883c80f181c4aade2ed04': 'download',
|
||||
'fc856cd721f5b5955f8c4be2767a1cee': 'Download Documents',
|
||||
'270c7dfc38ec1f8eb7b211481d26659a': 'Document Address',
|
||||
'2bd4fa4fe6637a09add46354f52ea9dc': 'Whether to render',
|
||||
'010787d733c97c5f7a8f9bda438af9e2': 'Word rendering configuration',
|
||||
'9a50cbc2f0c7115043a19c3b1db5776b': 'Ignore width',
|
||||
'927ed823f52a6d3bbceed4436636a7dd': 'Page Inner Margin',
|
||||
'755ea661684e7bffe9f97fb07b8d4921': 'List using font',
|
||||
'9b87dc5a019f749722a1d3a9c854a2b9': 'Variable Replacement',
|
||||
'c6adeba660df8e19ac6cd3b8c57416ad': 'Forced row height',
|
||||
'b93ea0046d63e2df7cf24a7a63bf5c99': 'Font Mapping',
|
||||
'f6e9b56f97af64235bf81f4ddc2288ab': 'Whether to enable pagination rendering',
|
||||
'4c71a09da7ce050d45514b68bb15b4ab': 'Page Top and Bottom Margins',
|
||||
'3651c159e19c05a3bdaa7036dac91e4e': 'Page background color',
|
||||
'91bc444339545a7785f3aa3055d9ba05': 'Show page shadows',
|
||||
'c856051e8c80913ff6607dc880341a20': 'Whether to display page packages',
|
||||
'6a6772a0eae27591ed8763b6e616e988': 'Page Wrap Width',
|
||||
'22bca073daae505d7fc9e7d7c8ee047c': 'Page Wrap Background Color',
|
||||
'2839785a190e062058635add192f961d': 'Zoom ratio',
|
||||
'9723e66141840db4dc6bd1db9b165302': 'Adaptive width',
|
||||
'b7dd79307fb7bcc921aa1b94ef904fe9': 'Behavior button',
|
||||
'c3e817974de836e80c95cc6ce5718eff': 'Search box',
|
||||
'83fe6a5db780fcfa68f3336c7d86f25b':
|
||||
'Used to display a simple search box, usually used in conjunction with other components. For example, after configuring initApi on the page, it can be used to achieve simple data filtering and lookup, and name keywords will be passed as parameters to initApi on the page.',
|
||||
'bb50b53491c2c43845c58b16e48c27f3': 'Search box content',
|
||||
'68a896ef9627fea8cd84f3fa4f7269aa': 'Click Search',
|
||||
'a7be3c702997f49cf9429240fbbc5e36':
|
||||
'Triggered when clicking on the search icon',
|
||||
'1c113a8c88ba15fc1ff04ea410e63f33': 'Search Content',
|
||||
'0796ba76b4b553687e5ffaeb78512ccb': 'Basics',
|
||||
'218bcea849478df7335ac31072860e8e': 'Search immediately after clearing',
|
||||
'a48b511d5da79faf6f7f58c5470738f0': 'Search Now',
|
||||
'71c198baa12405e56705a3c68f66e3ef': 'Mini version',
|
||||
'b814fb5782f733a22ee561397ad376fc': 'Strengthen Style',
|
||||
'87d88a457161f2a09f95f6aa29b38051': 'Step Bar',
|
||||
'2a9a1329b191c2787b1a70c289e3bbe0': 'vertical',
|
||||
'd517acb68fbed2331b57d1a11ca21dcc': 'simple',
|
||||
'341fe804cc8b65dc17a31c7a25a90444': 'Label Name',
|
||||
'd04f139ee0fb6fac19ccaec0f7b323df': 'Click to close',
|
||||
'fe7967a547915be9ae4083ed50c3b94a': 'Triggered when clicked to close',
|
||||
'b624985146c759cfeb1be80325eccd65': 'Text prompt',
|
||||
'6d8e3115be41a8a5690d6fefa637dac7':
|
||||
'The data returned by the interface needs to conform to the following format, with status, msg, and data as necessary fields',
|
||||
'09212e946a4d9b0f775700c46ef0dcd5':
|
||||
'Returning 0 indicates that the current interface is returning correctly, otherwise it will be processed as an error request',
|
||||
'7391774e57425e5d8e83de64100b5f2e':
|
||||
'Returns interface processing information, mainly used for displaying the toast when a form submission or request fails',
|
||||
'fa385c23820ee9999c82035086baa772':
|
||||
'Must return an object with a key value structure',
|
||||
'6494bc042d99f2f5de34a858b8a699c6':
|
||||
'Verification interface return format field description:',
|
||||
'e6246c03148f553e5d6a66adbdabb9f8':
|
||||
'Returning 0 indicates successful verification, 422 indicates failed verification',
|
||||
'b8079b9d1e6d3e8a457787910a75cce4':
|
||||
'When the return status is 422, the displayed verification failure message',
|
||||
'a59c65bea7d5065f19eb9c918a716c33':
|
||||
'The modified API object must be returned.',
|
||||
'05fb5edb84e41c19b0f5429fff20b834': 'Return adapter',
|
||||
'98498eb59e87ec9a0eaf98ac55628da9':
|
||||
"The current request's response payload, which is response.data",
|
||||
'ed33c46d1d69336bb011813e8352fa01': 'horizontal direction',
|
||||
'963e9ff4252cdef288063c41eb6d4998': 'vertical direction',
|
||||
'4117e80d2c2e52f795ec64160f399364': 'Vertically centered',
|
||||
'd365d58d281508b9982f6a0370649ae2': 'horizontally',
|
||||
'21af94c1abc5891b2703c9321417a1a9': 'Interval distribution',
|
||||
'849b9b944a65eb0685f3e6af60a0c523': 'Horizontal spreading',
|
||||
'50334fc77fc5a2c2636f14f158d3c417': 'Context variables',
|
||||
'7f05bea37729325a6cc84eb26bb9f8c8': 'Please enter the subscript text',
|
||||
'bc3f5a690d8c3a47d27ef8a1b127bafc':
|
||||
'Hidden options cannot be set as default values',
|
||||
'240a19929878c26f5e4c41c08f63cd1c': 'Interface verification',
|
||||
'c6f30c2f084ddeacb7944235348bdaa4': 'Memory variables',
|
||||
'fa6b01f51cc2b8e16bfbb914b6c08ace': 'Confirmation dialog box',
|
||||
'4cb9c4bc5cb960fcd03fceb2d2e62f3a': 'Drawer Title',
|
||||
'fd2bed5e9a84273b22f79950a0a1807f': 'Suspended Style',
|
||||
'1daee167a43c72dbe9e31e955b670b4f': 'Click on Style',
|
||||
'd117954f3769008ef22b864060913c65': 'Disabled Style',
|
||||
'd37c4140bd531fc117e91e727d7e576c': 'Normal state style',
|
||||
'0371c0e05806c01e5ce2f26e9e2e39c8': 'Edit Style Source Code',
|
||||
'bb7654f7c2768614e95a0da7e94f4045': 'Expected colon',
|
||||
'af26fdb215bad5b2296529802b129c12': 'Expected attribute',
|
||||
'3955b2e2e06144010a1142d3624b17b1': 'Missing semicolon',
|
||||
'052f7eec7ca35a6b4d72d169ee1de494': 'Please enter an expression',
|
||||
'10710f1c01d960a3ffde384115296026': 'Block level',
|
||||
'26b10072a4e0c8c9a3a1142db3d7b3b4': 'Inline block',
|
||||
'2c7fe494c99c94ba5965f963fd7d3a4c': 'Inline element',
|
||||
'39353c2b258e4bc73d8dd6a46f0a7955': 'Flexible layout (flex)',
|
||||
'553333a72dec41b54e8ed18d49453a76': 'Select the first item by default',
|
||||
'86bf16f0cb7fd8b1fef2e1439e06b632': 'Style source code'
|
||||
});
|
||||
|
@ -3431,5 +3431,135 @@ extendLocale('zh-CN', {
|
||||
'6922790f45faf064e063069816e4d2ec':
|
||||
'开启后,会将所有原始数据打平设置到 data 中,并在此基础上定制',
|
||||
'9791b05a4df9d72f1a01b81fa695fbc6':
|
||||
'当多列的分组名称设置一致时,表格会在显示表头的上层显示超级表头,<a href="https://baidu.github.io/amis/zh-CN/components/table#%E8%B6%85%E7%BA%A7%E8%A1%A8%E5%A4%B4" target="_blank">示例</a>'
|
||||
'当多列的分组名称设置一致时,表格会在显示表头的上层显示超级表头,<a href="https://baidu.github.io/amis/zh-CN/components/table#%E8%B6%85%E7%BA%A7%E8%A1%A8%E5%A4%B4" target="_blank">示例</a>',
|
||||
'7441768e25f67a80f0f2173c2a618c35': '日期值',
|
||||
'8036cf5e8dbf62ee4f4e896f7354ce5c': '日期时间值',
|
||||
'598f69a9b640508d8e124fd7d33131f0': '选择图标',
|
||||
'ef79da787ad206e5d5f8cf62e195c836': '图标大小',
|
||||
'ff58428ef8221c4c1bbf532dd3c77113': '图标底边距',
|
||||
'88f109195ad926bcd436f0c56198240d': '图片上传按钮',
|
||||
'd825ba2b8ea0c1b0737b0dd5ca9bc128': '上传图标',
|
||||
'bade9c4e0b8a75a251c1a2760571d3c3': '数字输入框样式',
|
||||
'53069052573de671c6e5108de745b036': '数字输入框',
|
||||
'5c48fa6f337d2b5dd168a0887c6baa2b': '表格表单数据',
|
||||
'fb7b49ff7f85f6e3f995b5eaae42d084': '标签选择',
|
||||
'0aefac04b467ce313ca6b05e33c6145a': '最大字数',
|
||||
'188676cb26835b8e4d8ea568467c55cd': '限制输入最多文字数量',
|
||||
'f1ee660e12ef0b76c10cccc3d923e605':
|
||||
'AK不能为空,请访问http://lbsyun.baidu.com/获取密钥(AK)',
|
||||
'4d01bb9f50eb1480e0e9995a2a003181':
|
||||
'请从<a href="http://lbsyun.baidu.com/" target="_blank" class="text-sm">百度地图开放平台</a>获取',
|
||||
'f1f7a5f821ca0ee4caaa9324eda48d91': '静态表单项',
|
||||
'4602761ee85e2e6e5360cd13fe642a08':
|
||||
'<p>当前组件已停止维护,建议您使用<a href="/amis/zh-CN/components/form/formitem#%E9%85%8D%E7%BD%AE%E9%9D%99%E6%80%81%E5%B1%95%E7%A4%BA" target="_blank">静态展示</a>新特性实现表单项的静态展示。</p>',
|
||||
'6ca92e3386f9e392584367df5054c27c':
|
||||
'用来展示一个图标,你可以配置不同的图标样式。',
|
||||
'47fd366b711a0567646854f541449f8b':
|
||||
'比如:\\${listVar},用来关联作用域中的已有数据',
|
||||
'98204720c30a843a9234bdf22dc05d51': '弹性布局设置',
|
||||
'3212f1de74130815d12d982437fc6919': '文档预览',
|
||||
'a7199769ae58f8a5c35ac0e5f8804abf': 'Office 文档预览',
|
||||
'e414473c886072e393710563f201d7f3': '打印',
|
||||
'6a62d33c838524f0609a624aa59ee9e7': '打印文档',
|
||||
'f26ef914245883c80f181c4aade2ed04': '下载',
|
||||
'fc856cd721f5b5955f8c4be2767a1cee': '下载文档',
|
||||
'270c7dfc38ec1f8eb7b211481d26659a': '文档地址',
|
||||
'2bd4fa4fe6637a09add46354f52ea9dc': '是否渲染',
|
||||
'010787d733c97c5f7a8f9bda438af9e2': 'Word 渲染配置',
|
||||
'9a50cbc2f0c7115043a19c3b1db5776b': '忽略宽度',
|
||||
'927ed823f52a6d3bbceed4436636a7dd': '页面内边距',
|
||||
'755ea661684e7bffe9f97fb07b8d4921': '列表使用字体',
|
||||
'9b87dc5a019f749722a1d3a9c854a2b9': '变量替换',
|
||||
'c6adeba660df8e19ac6cd3b8c57416ad': '强制行高',
|
||||
'b93ea0046d63e2df7cf24a7a63bf5c99': '字体映射',
|
||||
'f6e9b56f97af64235bf81f4ddc2288ab': '是否开启分页渲染',
|
||||
'4c71a09da7ce050d45514b68bb15b4ab': '页上下边距',
|
||||
'3651c159e19c05a3bdaa7036dac91e4e': '页背景色',
|
||||
'91bc444339545a7785f3aa3055d9ba05': '是否显示页面阴影',
|
||||
'c856051e8c80913ff6607dc880341a20': '是否显示页面包裹',
|
||||
'6a6772a0eae27591ed8763b6e616e988': '页面包裹宽度',
|
||||
'22bca073daae505d7fc9e7d7c8ee047c': '页面包裹背景色',
|
||||
'2839785a190e062058635add192f961d': '缩放比例',
|
||||
'9723e66141840db4dc6bd1db9b165302': '自适应宽度',
|
||||
'b7dd79307fb7bcc921aa1b94ef904fe9': '行为按钮',
|
||||
'c3e817974de836e80c95cc6ce5718eff': '搜索框',
|
||||
'83fe6a5db780fcfa68f3336c7d86f25b':
|
||||
'用于展示一个简单搜索框,通常需要搭配其他组件使用。比如 page 配置 initApi 后,可以用来实现简单数据过滤查找,name keywords 会作为参数传递给 page 的 initApi。',
|
||||
'bb50b53491c2c43845c58b16e48c27f3': '搜索框内容',
|
||||
'68a896ef9627fea8cd84f3fa4f7269aa': '点击搜索',
|
||||
'a7be3c702997f49cf9429240fbbc5e36': '点击搜索图标时触发',
|
||||
'1c113a8c88ba15fc1ff04ea410e63f33': '搜索内容',
|
||||
'0796ba76b4b553687e5ffaeb78512ccb': '基础',
|
||||
'218bcea849478df7335ac31072860e8e': '清除后立即搜索',
|
||||
'a48b511d5da79faf6f7f58c5470738f0': '立即搜索',
|
||||
'71c198baa12405e56705a3c68f66e3ef': 'mini版本',
|
||||
'b814fb5782f733a22ee561397ad376fc': '加强样式',
|
||||
'87d88a457161f2a09f95f6aa29b38051': '步骤条',
|
||||
'2a9a1329b191c2787b1a70c289e3bbe0': '竖直',
|
||||
'd517acb68fbed2331b57d1a11ca21dcc': '简单',
|
||||
'341fe804cc8b65dc17a31c7a25a90444': '标签名称',
|
||||
'd04f139ee0fb6fac19ccaec0f7b323df': '点击关闭',
|
||||
'fe7967a547915be9ae4083ed50c3b94a': '点击关闭时触发',
|
||||
'b624985146c759cfeb1be80325eccd65': '文字提示',
|
||||
'717b9f738e2da460071b1b5ae7cc0e06':
|
||||
"{\n url: string; // 当前接口地址\n method: 'get' | 'post' | 'put' | 'delete';\n data?: Object; // 请求体\n headers?: Object; // 请求头\n ...\n}",
|
||||
'd1bfe86cb1776358c5ed50bc137a2b7a':
|
||||
'{\n data: Object; // 接口返回数据,\n request: XMLHttpRequest;\n headers?: Object; // 请求头\n status: number; // 状态码 200, 404, 500..\n statusText: string; // 状态信息\n ...\n}',
|
||||
'd3b13672e0e24d1490b2564ae7f6da4e':
|
||||
"// API响应或自定义处理后需要符合以下格式\nreturn {\n status: 0, // 0 表示请求成功,否则按错误处理\n msg: '请求成功',\n data: {\n text: 'world',\n items: [\n {label: '张三', value: 1}\n ]\n }\n}",
|
||||
'36d7adab7769ff6741b2860f041e56d2':
|
||||
"// 校验成功\nreturn {\n status: 0\n};\n\n// 校验失败\nreturn {\n status: 422,\n errors: '当前用户已存在'\n}",
|
||||
'0228c8f19830732b523a58a2ee0bbcfd':
|
||||
'{\n "status": 0,\n "msg": "",\n "data": {\n // ...其他字段\n }\n}',
|
||||
'6d8e3115be41a8a5690d6fefa637dac7':
|
||||
'接口返回数据需要符合以下格式, status、msg、data 为必要字段',
|
||||
'09212e946a4d9b0f775700c46ef0dcd5':
|
||||
'返回 0 表示当前接口正确返回,否则按错误请求处理',
|
||||
'7391774e57425e5d8e83de64100b5f2e':
|
||||
'返回接口处理信息,主要用于表单提交或请求失败时的 toast 显示',
|
||||
'fa385c23820ee9999c82035086baa772': '必须返回一个具有 key-value 结构的对象',
|
||||
'6494bc042d99f2f5de34a858b8a699c6': '校验接口返回格式字段说明:',
|
||||
'e6246c03148f553e5d6a66adbdabb9f8': '返回 0 表示校验成功,422 表示校验失败',
|
||||
'b8079b9d1e6d3e8a457787910a75cce4':
|
||||
'返回 status 为 422 时,显示的校验失败信息',
|
||||
'9d49f04a3affb34a31bb157e4887cbe7':
|
||||
'可基于 JavaScript 语言直接录入发送适配器的函数体,在该函数体内,您可以对 <span style="color: #108CEE">api</span> 进行处理或者返回新的内容,最后需要 <span style="color: #108CEE">return</span> <span style="color: #108CEE">api</span>。<br><br/>\n 函数体内可访问的变量如下:<br/>\n 1. <span style="color: #108CEE">api</span>:接口的schema配置对象<br/>\n 2. <span style="color: #108CEE">api.data</span>:请求数据<br/>\n 3. <span style="color: #108CEE">api.query</span>:请求查询参数<br/>\n 4. <span style="color: #108CEE">api.body</span>:请求体(针对POST/PUT/PATCH)<br/>\n 5. <span style="color: #108CEE">api.headers</span>:请求头<br/>\n 6. <span style="color: #108CEE">api.url</span>:请求地址<br/>',
|
||||
'a59c65bea7d5065f19eb9c918a716c33': '必须将修改好的 api 对象 return 出去。',
|
||||
'05fb5edb84e41c19b0f5429fff20b834': '返回适配器',
|
||||
'44af993b124817085dc2579a9f842d55':
|
||||
'可基于 JavaScript 语言直接录入返回适配器的函数体,在函数体内,您可以对 <span style="color: #108CEE">payload</span> 进行处理或者返回新的内容,最后需要 <span style="color: #108CEE">return</span> 接口最终的返回结果。<br><br/>\n 函数体内可访问的变量如下:<br/>\n 1. <span style="color: #108CEE">payload</span>:接口的返回结果<br/>\n 2. <span style="color: #108CEE">response</span>:接口的response对象<br/>\n 3. <span style="color: #108CEE">api</span>:接口的schema配置对象<br/>',
|
||||
'98498eb59e87ec9a0eaf98ac55628da9':
|
||||
'当前请求的响应 payload,即 response.data',
|
||||
'ed33c46d1d69336bb011813e8352fa01': '水平方向',
|
||||
'963e9ff4252cdef288063c41eb6d4998': '垂直方向',
|
||||
'4117e80d2c2e52f795ec64160f399364': '垂直居中',
|
||||
'd365d58d281508b9982f6a0370649ae2': '水平居中',
|
||||
'21af94c1abc5891b2703c9321417a1a9': '间隔分布',
|
||||
'849b9b944a65eb0685f3e6af60a0c523': '水平铺开',
|
||||
'50334fc77fc5a2c2636f14f158d3c417': '上下文变量',
|
||||
'7f05bea37729325a6cc84eb26bb9f8c8': '请输入角标文本',
|
||||
'bc3f5a690d8c3a47d27ef8a1b127bafc': '隐藏选项不能设为默认值',
|
||||
'240a19929878c26f5e4c41c08f63cd1c': '接口校验',
|
||||
'ae7ca6f3dec57a73ddc145a7094adc97':
|
||||
'配置校验接口,对表单项进行远程校验,配置方式与普通接口一致<br />\n 1. 接口返回 <span class="ae-ValidationControl-label-code">{status: 0}</span> 表示校验通过<br />\n 2. 接口返回 <span class="ae-ValidationControl-label-code">{status: 422}</span> 表示校验不通过<br />\n 3. 若校验失败时需要显示错误提示信息,还需返回 errors 字段,示例<br />\n <span class="ae-ValidationControl-label-code">{status: 422, errors: \'错误提示消息\'}</span>\n ',
|
||||
'c6f30c2f084ddeacb7944235348bdaa4': '内存变量',
|
||||
'fa6b01f51cc2b8e16bfbb914b6c08ace': '确认对话框',
|
||||
'4cb9c4bc5cb960fcd03fceb2d2e62f3a': '抽屉标题',
|
||||
'fbaa94ca6b6e6e76a07124e80733f109':
|
||||
"/* 自定义JS使用说明:\n * 1.动作执行函数doAction,可以执行所有类型的动作\n * 2.通过上下文对象context可以获取当前组件实例,例如context.props可以获取该组件相关属性\n * 3.事件对象event,在doAction之后执行event.stopPropagation();可以阻止后续动作执行\n*/\nconst myMsg = '我是自定义JS';\ndoAction({\n actionType: 'toast',\n args: {\n msg: myMsg\n }\n});\n",
|
||||
'fd2bed5e9a84273b22f79950a0a1807f': '悬浮态样式',
|
||||
'1daee167a43c72dbe9e31e955b670b4f': '点击态样式',
|
||||
'd117954f3769008ef22b864060913c65': '禁用态样式',
|
||||
'd37c4140bd531fc117e91e727d7e576c': '常规态样式',
|
||||
'0371c0e05806c01e5ce2f26e9e2e39c8': '编辑样式源码',
|
||||
'bb7654f7c2768614e95a0da7e94f4045': '应为冒号',
|
||||
'af26fdb215bad5b2296529802b129c12': '应为属性',
|
||||
'3955b2e2e06144010a1142d3624b17b1': '缺少分号',
|
||||
'052f7eec7ca35a6b4d72d169ee1de494': '请输入表达式',
|
||||
'10710f1c01d960a3ffde384115296026': '块级(block)',
|
||||
'26b10072a4e0c8c9a3a1142db3d7b3b4': '行内区块(inline-block)',
|
||||
'2c7fe494c99c94ba5965f963fd7d3a4c': '行内元素(inline)',
|
||||
'39353c2b258e4bc73d8dd6a46f0a7955': '弹性布局(flex)',
|
||||
'553333a72dec41b54e8ed18d49453a76': '默认选择第一项',
|
||||
'86bf16f0cb7fd8b1fef2e1439e06b632': '样式源码'
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
|
||||
export class AlertPlugin extends BasePlugin {
|
||||
static scene = ['layout'];
|
||||
|
@ -11,7 +11,7 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {BUTTON_DEFAULT_ACTION} from '../component/BaseControl';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {getOldActionSchema} from '../renderer/event-control/helper';
|
||||
|
||||
export class ButtonPlugin extends BasePlugin {
|
||||
|
@ -5,6 +5,7 @@ import React from 'react';
|
||||
|
||||
import {
|
||||
getI18nEnabled,
|
||||
jsonToJsonSchema,
|
||||
registerEditorPlugin,
|
||||
tipedLabel
|
||||
} from 'amis-editor-core';
|
||||
@ -23,13 +24,18 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {isObject, JSONPipeIn} from 'amis-editor-core';
|
||||
import {setVariable} from 'amis-core';
|
||||
import {ActionSchema} from 'amis/lib/renderers/Action';
|
||||
import {CRUDCommonSchema} from 'amis/lib/renderers/CRUD';
|
||||
import {setVariable, someTree} from 'amis-core';
|
||||
import type {ActionSchema} from 'amis';
|
||||
import type {CRUDCommonSchema} from 'amis';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import {EditorNodeType, RendererPluginAction} from 'amis-editor-core';
|
||||
import type {
|
||||
EditorNodeType,
|
||||
RendererPluginAction,
|
||||
RendererPluginEvent
|
||||
} from 'amis-editor-core';
|
||||
import {normalizeApi} from 'amis-core';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
interface ColumnItem {
|
||||
label: string;
|
||||
@ -85,6 +91,33 @@ export class CRUDPlugin extends BasePlugin {
|
||||
itemActions: []
|
||||
};
|
||||
|
||||
events: RendererPluginEvent[] = [
|
||||
{
|
||||
eventName: 'fetchInited',
|
||||
eventLabel: '初始化数据接口请求完成',
|
||||
description: '远程初始化数据接口请求完成时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data.responseData': {
|
||||
type: 'object',
|
||||
title: '响应数据'
|
||||
},
|
||||
'event.data.responseStatus': {
|
||||
type: 'number',
|
||||
title: '响应状态(0表示成功)'
|
||||
},
|
||||
'event.data.responseMsg': {
|
||||
type: 'string',
|
||||
title: '响应消息'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
actions: RendererPluginAction[] = [
|
||||
{
|
||||
actionType: 'reload',
|
||||
@ -1745,7 +1778,92 @@ export class CRUDPlugin extends BasePlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
return child.info.plugin.buildDataSchemas(child, undefined, trigger);
|
||||
let childSchame = await child.info.plugin.buildDataSchemas(
|
||||
child,
|
||||
undefined,
|
||||
trigger
|
||||
);
|
||||
|
||||
// 兼容table的rows,并自行merged异步数据
|
||||
if (child.type === 'table') {
|
||||
let cellProperties = {};
|
||||
const columns: EditorNodeType = child.children.find(
|
||||
item => item.isRegion && item.region === 'columns'
|
||||
);
|
||||
|
||||
if (trigger) {
|
||||
const isColumnChild = someTree(
|
||||
columns?.children,
|
||||
item => item.id === trigger.id
|
||||
);
|
||||
|
||||
// merge异步数据中的单列成员,因为rendererBeforeDispatchEvent无法区分是否需要单列成员
|
||||
if (isColumnChild) {
|
||||
const scope = this.manager.dataSchema.getScope(
|
||||
`${node.id}-${node.type}`
|
||||
);
|
||||
const menberProps = (
|
||||
scope.getSchemaById('crudFetchInitedData')?.properties?.items as any
|
||||
)?.items?.properties;
|
||||
|
||||
cellProperties = {
|
||||
...menberProps,
|
||||
...omit(
|
||||
childSchame.properties,
|
||||
'rows',
|
||||
'selectedItems',
|
||||
'unSelectedItems'
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
childSchame = {
|
||||
$id: childSchame.$id,
|
||||
type: childSchame.type,
|
||||
properties: {
|
||||
...cellProperties,
|
||||
items: childSchame.properties.rows,
|
||||
selectedItems: childSchame.properties.selectedItems,
|
||||
unSelectedItems: childSchame.properties.unSelectedItems,
|
||||
count: {
|
||||
type: 'number',
|
||||
title: '总行数'
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
title: '当前页码'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return childSchame;
|
||||
}
|
||||
|
||||
rendererBeforeDispatchEvent(node: EditorNodeType, e: any, data: any) {
|
||||
if (e === 'fetchInited') {
|
||||
const scope = this.manager.dataSchema.getScope(`${node.id}-${node.type}`);
|
||||
const jsonschema: any = {
|
||||
$id: 'crudFetchInitedData',
|
||||
type: 'object',
|
||||
...jsonToJsonSchema(
|
||||
omit(data, 'selectedItems', 'unSelectedItems'),
|
||||
(type: string, key: string) => {
|
||||
if (type === 'array' && key === 'items') {
|
||||
return '数据列表';
|
||||
}
|
||||
if (type === 'number' && key === 'count') {
|
||||
return '总行数';
|
||||
}
|
||||
return key;
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
scope?.removeSchema(jsonschema.$id);
|
||||
scope?.addSchema(jsonschema);
|
||||
}
|
||||
}
|
||||
|
||||
/** crud 不同 mode 之间转换时候,主体的转换 */
|
||||
|
@ -24,10 +24,10 @@ import {
|
||||
RendererPluginEvent
|
||||
} from 'amis-editor-core';
|
||||
import {flattenDeep, fromPairs, isObject, remove} from 'lodash';
|
||||
import type {ButtonSchema} from 'amis/lib/renderers/Action';
|
||||
import type {FormSchema, SchemaObject} from 'amis/lib/Schema';
|
||||
import type {ButtonSchema} from 'amis';
|
||||
import type {FormSchema, SchemaObject} from 'amis';
|
||||
import {findTree} from 'amis';
|
||||
import type {CRUD2Schema} from 'amis/lib/renderers/CRUD2';
|
||||
import type {CRUD2Schema} from 'amis';
|
||||
import {FeatureOption} from '../renderer/FeatureControl';
|
||||
import {getArgsWrapper} from '../renderer/event-control/helper';
|
||||
|
||||
@ -305,7 +305,7 @@ const FilterTypes: Array<FeatOption> = [
|
||||
type: 'form',
|
||||
mode: 'inline',
|
||||
behavior: 'SimpleQuery',
|
||||
body: builder.resolveSimpleFilterSchema({setting}) || [],
|
||||
body: builder.resolveSimpleFilterSchema({setting, size: 'full'}) || [],
|
||||
actions: [
|
||||
{
|
||||
type: 'submit',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Button, resolveVariable} from 'amis';
|
||||
import {Button} from 'amis';
|
||||
import React from 'react';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {
|
||||
@ -16,6 +16,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {diff, JSONPipeOut, repeatArray} from 'amis-editor-core';
|
||||
import {resolveArrayDatasource} from '../util';
|
||||
|
||||
export class CardsPlugin extends BasePlugin {
|
||||
static scene = ['layout'];
|
||||
@ -252,11 +253,11 @@ export class CardsPlugin extends BasePlugin {
|
||||
...props.defaultData,
|
||||
...props.data
|
||||
};
|
||||
const arr = Array.isArray(props.value)
|
||||
? props.value
|
||||
: typeof props.source === 'string'
|
||||
? resolveVariable(props.source, data)
|
||||
: resolveVariable('items', data);
|
||||
const arr = resolveArrayDatasource({
|
||||
value: props.value,
|
||||
data,
|
||||
source: props.source
|
||||
});
|
||||
|
||||
if (!Array.isArray(arr) || !arr.length) {
|
||||
const mockedData: any = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {availableLanguages} from 'amis/lib/renderers/Form/Editor';
|
||||
import {EditorAvailableLanguages as availableLanguages} from 'amis';
|
||||
import {defaultValue, getSchemaTpl, undefinedPipeOut} from 'amis-editor-core';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BasePlugin} from 'amis-editor-core';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {availableLanguages} from 'amis/lib/renderers/Form/Editor';
|
||||
import {EditorAvailableLanguages as availableLanguages} from 'amis';
|
||||
import {
|
||||
defaultValue,
|
||||
getSchemaTpl,
|
||||
|
@ -247,16 +247,24 @@ export class FormPlugin extends BasePlugin {
|
||||
events: RendererPluginEvent[] = [
|
||||
{
|
||||
eventName: 'inited',
|
||||
eventLabel: '初始化数据接口请求成功',
|
||||
description: '远程初始化数据接口请求成功时触发',
|
||||
eventLabel: '初始化数据接口请求完成',
|
||||
description: '远程初始化数据接口请求完成时触发',
|
||||
// 表单数据为表单变量
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data': {
|
||||
'event.data.responseData': {
|
||||
type: 'object',
|
||||
title: '初始化数据接口请求成功返回的数据'
|
||||
title: '响应数据'
|
||||
},
|
||||
'event.data.responseStatus': {
|
||||
type: 'number',
|
||||
title: '响应状态(0表示成功)'
|
||||
},
|
||||
'event.data.responseMsg': {
|
||||
type: 'string',
|
||||
title: '响应消息'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {Button} from 'amis';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import React from 'react';
|
||||
import {
|
||||
BaseEventContext,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import {resolveVariable, Button} from 'amis';
|
||||
import {Button} from 'amis';
|
||||
import {
|
||||
registerEditorPlugin,
|
||||
BaseEventContext,
|
||||
@ -25,6 +25,7 @@ import {
|
||||
getArgsWrapper
|
||||
} from '../../renderer/event-control/helper';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {resolveArrayDatasource} from '../../util';
|
||||
|
||||
export class TableControlPlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -791,11 +792,7 @@ export class TableControlPlugin extends BasePlugin {
|
||||
};
|
||||
|
||||
filterProps(props: any) {
|
||||
const arr = Array.isArray(props.value)
|
||||
? props.value
|
||||
: typeof props.source === 'string'
|
||||
? resolveVariable(props.source, props.data)
|
||||
: resolveVariable('items', props.data);
|
||||
const arr = resolveArrayDatasource(props);
|
||||
|
||||
if (!Array.isArray(arr) || !arr.length) {
|
||||
const mockedData: any = {};
|
||||
|
@ -118,11 +118,7 @@ export class ListControlPlugin extends BasePlugin {
|
||||
]
|
||||
},
|
||||
option: {
|
||||
body: [
|
||||
getSchemaTpl('optionControlV2', {
|
||||
description: '设置选项后,输入时会下拉这些选项供用户参考。'
|
||||
})
|
||||
]
|
||||
body: [getSchemaTpl('optionControlV2')]
|
||||
},
|
||||
status: {}
|
||||
},
|
||||
|
@ -1,16 +1,7 @@
|
||||
import {relativeValueRe} from 'amis';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {availableLanguages} from 'amis/lib/renderers/Form/Editor';
|
||||
import {defaultValue, getSchemaTpl, valuePipeOut} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {
|
||||
BasePlugin,
|
||||
BasicSubRenderInfo,
|
||||
RendererEventContext,
|
||||
SubRendererInfo,
|
||||
BaseEventContext,
|
||||
tipedLabel
|
||||
} from 'amis-editor-core';
|
||||
import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core';
|
||||
import {ValidatorTag} from '../../validator';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
|
@ -85,14 +85,13 @@ export class ImagesPlugin extends BasePlugin {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'source',
|
||||
type: 'input-text',
|
||||
label: '关联数据',
|
||||
description:
|
||||
'比如:\\${listVar},用来关联作用域中的已有数据。',
|
||||
getSchemaTpl('sourceBindControl', {
|
||||
label: tipedLabel(
|
||||
'关联数据',
|
||||
'比如:\\${listVar},用来关联作用域中的已有数据'
|
||||
),
|
||||
visibleOn: 'this.__mode == 1'
|
||||
},
|
||||
}),
|
||||
{
|
||||
type: 'combo',
|
||||
name: 'options',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Button, resolveVariable} from 'amis';
|
||||
import {Button} from 'amis';
|
||||
import React from 'react';
|
||||
import {getI18nEnabled, registerEditorPlugin} from 'amis-editor-core';
|
||||
import {
|
||||
@ -13,7 +13,11 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {diff, JSONPipeOut, repeatArray} from 'amis-editor-core';
|
||||
import {schemaArrayFormat, schemaToArray} from '../util';
|
||||
import {
|
||||
schemaArrayFormat,
|
||||
resolveArrayDatasource,
|
||||
schemaToArray
|
||||
} from '../util';
|
||||
|
||||
export class ListPlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -90,13 +94,9 @@ export class ListPlugin extends BasePlugin {
|
||||
},
|
||||
isCRUDBody
|
||||
? null
|
||||
: {
|
||||
name: 'source',
|
||||
type: 'input-text',
|
||||
label: '数据源',
|
||||
pipeIn: defaultValue('${items}'),
|
||||
description: '绑定当前环境变量'
|
||||
},
|
||||
: getSchemaTpl('sourceBindControl', {
|
||||
label: '数据源'
|
||||
}),
|
||||
{
|
||||
name: 'placeholder',
|
||||
pipeIn: defaultValue('没有数据'),
|
||||
@ -192,11 +192,11 @@ export class ListPlugin extends BasePlugin {
|
||||
...props.defaultData,
|
||||
...props.data
|
||||
};
|
||||
let arr = Array.isArray(props.value)
|
||||
? props.value
|
||||
: typeof props.source === 'string'
|
||||
? resolveVariable(props.source, data)
|
||||
: resolveVariable('items', data);
|
||||
const arr = resolveArrayDatasource({
|
||||
value: props.value,
|
||||
data,
|
||||
source: props.source
|
||||
});
|
||||
|
||||
if (!Array.isArray(arr) || !arr.length) {
|
||||
const mockedData: any = this.buildMockData();
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {diff} from 'amis-editor-core';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
|
||||
export class ActionPlugin extends BasePlugin {
|
||||
panelTitle = '按钮';
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
import {jsonToJsonSchema, EditorNodeType} from 'amis-editor-core';
|
||||
|
||||
@ -67,15 +67,23 @@ export class PagePlugin extends BasePlugin {
|
||||
},
|
||||
{
|
||||
eventName: 'inited',
|
||||
eventLabel: '初始化数据接口请求成功',
|
||||
description: '远程初始化数据接口请求成功时触发',
|
||||
eventLabel: '初始化数据接口请求完成',
|
||||
description: '远程初始化数据接口请求完成时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data': {
|
||||
'event.data.responseData': {
|
||||
type: 'object',
|
||||
title: '初始化数据接口请求成功返回的数据'
|
||||
title: '响应数据'
|
||||
},
|
||||
'event.data.responseStatus': {
|
||||
type: 'number',
|
||||
title: '响应状态(0表示成功)'
|
||||
},
|
||||
'event.data.responseMsg': {
|
||||
type: 'string',
|
||||
title: '响应消息'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {Schema} from 'amis-core';
|
||||
|
||||
export class SearchBoxPlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -25,7 +25,7 @@ export class SearchBoxPlugin extends BasePlugin {
|
||||
pluginIcon = 'search-box-plugin';
|
||||
tags = ['表单项'];
|
||||
|
||||
scaffold: SchemaObject = {
|
||||
scaffold: Schema = {
|
||||
type: 'search-box',
|
||||
body: {
|
||||
type: 'tpl',
|
||||
|
@ -68,13 +68,51 @@ export class ServicePlugin extends BasePlugin {
|
||||
},
|
||||
{
|
||||
eventName: 'fetchInited',
|
||||
eventLabel: '初始化数据接口请求成功',
|
||||
description: '远程初始化数据接口请求成功时触发'
|
||||
eventLabel: '初始化数据接口请求完成',
|
||||
description: '远程初始化数据接口请求完成时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data.responseData': {
|
||||
type: 'object',
|
||||
title: '响应数据'
|
||||
},
|
||||
'event.data.responseStatus': {
|
||||
type: 'object',
|
||||
title: '响应状态'
|
||||
},
|
||||
'event.data.responseMsg': {
|
||||
type: 'object',
|
||||
title: '响应消息'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'fetchSchemaInited',
|
||||
eventLabel: '初始化Schema接口请求成功',
|
||||
description: '远程初始化Schema接口请求成功时触发'
|
||||
eventLabel: '初始化Schema接口请求完成',
|
||||
description: '远程初始化Schema接口请求完成时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data.responseData': {
|
||||
type: 'object',
|
||||
title: '响应数据'
|
||||
},
|
||||
'event.data.responseStatus': {
|
||||
type: 'number',
|
||||
title: '响应状态(0表示成功)'
|
||||
},
|
||||
'event.data.responseMsg': {
|
||||
type: 'string',
|
||||
title: '响应消息'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -22,12 +22,16 @@ import {
|
||||
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
|
||||
import {mockValue} from 'amis-editor-core';
|
||||
import {EditorNodeType} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {
|
||||
getEventControlConfig,
|
||||
getArgsWrapper
|
||||
} from '../renderer/event-control/helper';
|
||||
import {schemaArrayFormat, schemaToArray} from '../util';
|
||||
import {
|
||||
schemaArrayFormat,
|
||||
schemaToArray,
|
||||
resolveArrayDatasource
|
||||
} from '../util';
|
||||
|
||||
export class TablePlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -289,7 +293,51 @@ export class TablePlugin extends BasePlugin {
|
||||
properties: {
|
||||
'event.data.item': {
|
||||
type: 'object',
|
||||
title: '行点击数据'
|
||||
title: '当前行数据'
|
||||
},
|
||||
'event.data.index': {
|
||||
type: 'number',
|
||||
title: '当前行索引'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'rowMouseEnter',
|
||||
eventLabel: '鼠标移入行事件',
|
||||
description: '移入整行时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data.item': {
|
||||
type: 'object',
|
||||
title: '当前行数据'
|
||||
},
|
||||
'event.data.index': {
|
||||
type: 'number',
|
||||
title: '当前行索引'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'rowMouseLeave',
|
||||
eventLabel: '鼠标移出行事件',
|
||||
description: '移出整行时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data.item': {
|
||||
type: 'object',
|
||||
title: '当前行数据'
|
||||
},
|
||||
'event.data.index': {
|
||||
type: 'number',
|
||||
title: '当前行索引'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -360,13 +408,9 @@ export class TablePlugin extends BasePlugin {
|
||||
|
||||
isCRUDBody
|
||||
? null
|
||||
: {
|
||||
name: 'source',
|
||||
type: 'input-text',
|
||||
label: '数据源',
|
||||
pipeIn: defaultValue('${items}'),
|
||||
description: '绑定当前环境变量'
|
||||
},
|
||||
: getSchemaTpl('sourceBindControl', {
|
||||
label: '数据源'
|
||||
}),
|
||||
|
||||
{
|
||||
name: 'combineNum',
|
||||
@ -600,11 +644,7 @@ export class TablePlugin extends BasePlugin {
|
||||
};
|
||||
|
||||
filterProps(props: any) {
|
||||
const arr = Array.isArray(props.value)
|
||||
? props.value
|
||||
: typeof props.source === 'string'
|
||||
? resolveVariable(props.source, props.data)
|
||||
: resolveVariable('items', props.data);
|
||||
const arr = resolveArrayDatasource(props);
|
||||
|
||||
if (!Array.isArray(arr) || !arr.length) {
|
||||
const mockedData: any = {};
|
||||
@ -688,16 +728,28 @@ export class TablePlugin extends BasePlugin {
|
||||
item => item.isRegion && item.region === 'columns'
|
||||
);
|
||||
|
||||
for (let current of columns?.children) {
|
||||
const schema = current.schema;
|
||||
if (schema.name) {
|
||||
itemsSchema.properties[schema.name] = current.info?.plugin
|
||||
?.buildDataSchemas
|
||||
? await current.info.plugin.buildDataSchemas(current, region)
|
||||
: {
|
||||
type: 'string',
|
||||
title: schema.label || schema.name
|
||||
};
|
||||
// todo:以下的处理无效,需要cell实现才能深层细化
|
||||
// for (let current of columns?.children) {
|
||||
// const schema = current.schema;
|
||||
// if (schema.name) {
|
||||
// itemsSchema.properties[schema.name] = current.info?.plugin
|
||||
// ?.buildDataSchemas
|
||||
// ? await current.info.plugin.buildDataSchemas(current, region)
|
||||
// : {
|
||||
// type: 'string',
|
||||
// title: schema.label || schema.name
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// 一期先简单处理,上面todo实现之后,这里可以废弃
|
||||
// table 无法根据source确定异步数据来源,因此不能在table层做异步数据列的收集
|
||||
for (let current of node.schema?.columns) {
|
||||
if (current.name) {
|
||||
itemsSchema.properties[current.name] = {
|
||||
type: 'string',
|
||||
title: current.label || current.name
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -724,6 +776,16 @@ export class TablePlugin extends BasePlugin {
|
||||
type: 'array',
|
||||
title: '数据列表',
|
||||
items: itemsSchema
|
||||
},
|
||||
selectedItems: {
|
||||
type: 'array',
|
||||
title: '已选中行'
|
||||
// items: itemsSchema
|
||||
},
|
||||
unSelectedItems: {
|
||||
type: 'array',
|
||||
title: '未选中行'
|
||||
// items: itemsSchema
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,5 +1,3 @@
|
||||
import {resolveVariable} from 'amis';
|
||||
|
||||
import {setVariable, someTree} from 'amis-core';
|
||||
import {
|
||||
BasePlugin,
|
||||
@ -25,7 +23,8 @@ import {
|
||||
getEventControlConfig,
|
||||
getArgsWrapper
|
||||
} from '../renderer/event-control/helper';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {resolveArrayDatasource} from '../util';
|
||||
|
||||
export class Table2Plugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -838,11 +837,7 @@ export class Table2Plugin extends BasePlugin {
|
||||
};
|
||||
|
||||
filterProps(props: any) {
|
||||
const arr = Array.isArray(props.value)
|
||||
? props.value
|
||||
: typeof props.source === 'string'
|
||||
? resolveVariable(props.source, props.data)
|
||||
: resolveVariable('items', props.data);
|
||||
const arr = resolveArrayDatasource(props);
|
||||
|
||||
if (!Array.isArray(arr) || !arr.length) {
|
||||
const mockedData: any = {};
|
||||
|
@ -16,8 +16,8 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import type {DSField} from 'amis-editor-core';
|
||||
import {fromPairs} from 'lodash';
|
||||
import type {TabsSchema} from 'amis/lib/renderers/Tabs';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {TabsSchema} from 'amis';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {remarkTpl} from '../component/BaseControl';
|
||||
|
||||
export class TableCell2Plugin extends BasePlugin {
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {VRenderer} from 'amis-editor-core';
|
||||
import type {TableViewSchema} from 'amis/lib/renderers/TableView';
|
||||
import type {TableViewSchema} from 'amis';
|
||||
import {JSONGetById} from 'amis-editor-core';
|
||||
import {TableViewEditor} from '../component/TableViewEditor';
|
||||
|
||||
|
@ -189,13 +189,11 @@ export class TabsPlugin extends BasePlugin {
|
||||
{
|
||||
title: '高级',
|
||||
body: [
|
||||
getSchemaTpl('expressionFormulaControl', {
|
||||
evalMode: true,
|
||||
getSchemaTpl('sourceBindControl', {
|
||||
label: tipedLabel(
|
||||
'关联数据',
|
||||
'根据该数据来动态重复渲染所配置的选项卡'
|
||||
),
|
||||
name: 'source'
|
||||
)
|
||||
}),
|
||||
getSchemaTpl('switch', {
|
||||
name: 'mountOnEnter',
|
||||
|
@ -90,15 +90,23 @@ export class WizardPlugin extends BasePlugin {
|
||||
events: RendererPluginEvent[] = [
|
||||
{
|
||||
eventName: 'inited',
|
||||
eventLabel: '初始化数据接口请求成功',
|
||||
description: '远程初始化数据接口请求成功时触发',
|
||||
eventLabel: '初始化数据接口请求完成',
|
||||
description: '远程初始化数据接口请求完成时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
'event.data': {
|
||||
'event.data.responseData': {
|
||||
type: 'object',
|
||||
title: '初始化数据接口请求成功返回的数据'
|
||||
title: '响应数据'
|
||||
},
|
||||
'event.data.responseStatus': {
|
||||
type: 'number',
|
||||
title: '响应状态(0表示成功)'
|
||||
},
|
||||
'event.data.responseMsg': {
|
||||
type: 'string',
|
||||
title: '响应消息'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ export default class APIAdaptorControl extends React.Component<
|
||||
APIAdaptorControlProps,
|
||||
APIAdaptorControlState
|
||||
> {
|
||||
|
||||
static defaultProps: Pick<APIAdaptorControlProps, 'params'> = {
|
||||
params: []
|
||||
};
|
||||
@ -89,13 +88,12 @@ export default class APIAdaptorControl extends React.Component<
|
||||
...(typeof content === 'string'
|
||||
? {content}
|
||||
: {
|
||||
content: ' ', // amis缺陷,必须有这个字段,否则显示不出来
|
||||
children: () => content
|
||||
}
|
||||
),
|
||||
...this.props.tooltipProps || {},
|
||||
...othersProps || {}
|
||||
}
|
||||
content: ' ', // amis缺陷,必须有这个字段,否则显示不出来
|
||||
children: () => content
|
||||
}),
|
||||
...(this.props.tooltipProps || {}),
|
||||
...(othersProps || {})
|
||||
};
|
||||
}
|
||||
|
||||
renderEditor() {
|
||||
@ -114,8 +112,8 @@ export default class APIAdaptorControl extends React.Component<
|
||||
mergeParams
|
||||
} = this.props;
|
||||
|
||||
const lastParams = typeof mergeParams === 'function'
|
||||
? mergeParams(params) : params;
|
||||
const lastParams =
|
||||
typeof mergeParams === 'function' ? mergeParams(params) : params;
|
||||
|
||||
return render('api-adaptor-control-editor', [
|
||||
{
|
||||
@ -124,20 +122,22 @@ export default class APIAdaptorControl extends React.Component<
|
||||
body: [
|
||||
'<span class="mtk6">function </span>',
|
||||
'<span class="mtk1 bracket-highlighting-0">(</span>',
|
||||
...lastParams.map(({label, tip}, index) => {
|
||||
return [
|
||||
{
|
||||
type: 'button',
|
||||
level: 'link',
|
||||
label,
|
||||
className: 'ae-AdaptorControl-func-arg',
|
||||
...tip ? {tooltip: this.genTooltipProps(tip)} : {}
|
||||
},
|
||||
...(index === lastParams.length - 1
|
||||
? [] : ['<span class="mtk1">, </span>']
|
||||
)
|
||||
]
|
||||
}).flat(),
|
||||
...lastParams
|
||||
.map(({label, tip}, index) => {
|
||||
return [
|
||||
{
|
||||
type: 'button',
|
||||
level: 'link',
|
||||
label,
|
||||
className: 'ae-AdaptorControl-func-arg',
|
||||
...(tip ? {tooltip: this.genTooltipProps(tip)} : {})
|
||||
},
|
||||
...(index === lastParams.length - 1
|
||||
? []
|
||||
: ['<span class="mtk1">, </span>'])
|
||||
];
|
||||
})
|
||||
.flat(),
|
||||
'<span class="mtk1 bracket-highlighting-0">) {</span>'
|
||||
]
|
||||
},
|
||||
@ -190,20 +190,20 @@ export default class APIAdaptorControl extends React.Component<
|
||||
});
|
||||
}
|
||||
},
|
||||
...switchTip ? [
|
||||
<TooltipWrapper
|
||||
key="TooltipWrapper"
|
||||
tooltip={this.genTooltipProps(switchTip, {
|
||||
placement: 'right'
|
||||
})}
|
||||
>
|
||||
<Icon
|
||||
icon="editor-help"
|
||||
className="icon"
|
||||
color="#84868c"
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
] : []
|
||||
...(switchTip
|
||||
? [
|
||||
<TooltipWrapper
|
||||
key="TooltipWrapper"
|
||||
tooltip={
|
||||
this.genTooltipProps(switchTip, {
|
||||
placement: 'right'
|
||||
}) as any
|
||||
}
|
||||
>
|
||||
<Icon icon="editor-help" className="icon" color="#84868c" />
|
||||
</TooltipWrapper>
|
||||
]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
@ -216,7 +216,7 @@ export default class APIAdaptorControl extends React.Component<
|
||||
{this.renderSwitch()}
|
||||
{this.renderEditor()}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@FormItem({
|
||||
@ -232,11 +232,14 @@ export class APIAdaptorControlRenderer extends APIAdaptorControl {}
|
||||
*/
|
||||
const genCodeSchema = (code: string, size?: string[]) => ({
|
||||
type: 'container',
|
||||
...!size ? {}
|
||||
: {style: {
|
||||
width: size[0],
|
||||
height: size[1]
|
||||
}},
|
||||
...(!size
|
||||
? {}
|
||||
: {
|
||||
style: {
|
||||
width: size[0],
|
||||
height: size[1]
|
||||
}
|
||||
}),
|
||||
body: {
|
||||
type: 'code',
|
||||
language: 'typescript',
|
||||
@ -246,8 +249,7 @@ const genCodeSchema = (code: string, size?: string[]) => ({
|
||||
});
|
||||
|
||||
// 请求适配器 示例代码
|
||||
export const requestAdaptorDefaultCode =
|
||||
`api.data.count = api.data.count + 1;
|
||||
export const requestAdaptorDefaultCode = `api.data.count = api.data.count + 1;
|
||||
return api;`;
|
||||
|
||||
// 适配器 适配器 api 参数说明
|
||||
@ -259,9 +261,9 @@ export const adaptorApiStruct = `{
|
||||
...
|
||||
}`;
|
||||
|
||||
export const adaptorApiStructTooltip =
|
||||
render(genCodeSchema(adaptorApiStruct, ['350px', '128px']))
|
||||
;
|
||||
export const adaptorApiStructTooltip = render(
|
||||
genCodeSchema(adaptorApiStruct, ['350px', '128px'])
|
||||
);
|
||||
|
||||
// 适配器 response 参数说明
|
||||
export const adaptorResponseStruct = `{
|
||||
@ -273,13 +275,12 @@ export const adaptorResponseStruct = `{
|
||||
...
|
||||
}`;
|
||||
|
||||
export const adaptorResponseStructTooltip =
|
||||
render(genCodeSchema(adaptorResponseStruct, ['345px', '144px']))
|
||||
;
|
||||
export const adaptorResponseStructTooltip = render(
|
||||
genCodeSchema(adaptorResponseStruct, ['345px', '144px'])
|
||||
);
|
||||
|
||||
// 接收适配器 示例代码
|
||||
export const adaptorDefaultCode =
|
||||
`// API响应或自定义处理后需要符合以下格式
|
||||
export const adaptorDefaultCode = `// API响应或自定义处理后需要符合以下格式
|
||||
return {
|
||||
status: 0, // 0 表示请求成功,否则按错误处理
|
||||
msg: '请求成功',
|
||||
@ -291,8 +292,7 @@ return {
|
||||
}
|
||||
}`;
|
||||
|
||||
export const validateApiAdaptorDefaultCode =
|
||||
`// 校验成功
|
||||
export const validateApiAdaptorDefaultCode = `// 校验成功
|
||||
return {
|
||||
status: 0
|
||||
};
|
||||
|
@ -17,10 +17,10 @@ import {
|
||||
getSchemaTpl
|
||||
} from 'amis-editor-core';
|
||||
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis';
|
||||
import type {Api} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {ActionSchema} from 'amis/lib/renderers/Action';
|
||||
import type {ActionSchema} from 'amis';
|
||||
|
||||
export type ApiObject = Api & {
|
||||
messages?: Record<
|
||||
@ -913,9 +913,7 @@ export default class APIControl extends React.Component<
|
||||
]
|
||||
},
|
||||
getSchemaTpl(
|
||||
name === 'validateApi'
|
||||
? 'validateApiAdaptor'
|
||||
: 'apiAdaptor'
|
||||
name === 'validateApi' ? 'validateApiAdaptor' : 'apiAdaptor'
|
||||
)
|
||||
]
|
||||
},
|
||||
|
@ -8,13 +8,19 @@ import {PickerContainer} from 'amis-ui';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import {normalizeApi, isEffectiveApi, isApiOutdated} from 'amis-core';
|
||||
|
||||
import {autobind, isObject, anyChanged, createObject, getSchemaTpl} from 'amis-editor-core';
|
||||
import {
|
||||
autobind,
|
||||
isObject,
|
||||
anyChanged,
|
||||
createObject,
|
||||
getSchemaTpl
|
||||
} from 'amis-editor-core';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis';
|
||||
import type {Api} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {ActionSchema} from 'amis/lib/renderers/Action';
|
||||
import type {ActionSchema} from 'amis';
|
||||
|
||||
export interface APIControlProps extends FormControlProps {
|
||||
name?: string;
|
||||
@ -754,7 +760,7 @@ export default class APIControl extends React.Component<
|
||||
]
|
||||
},
|
||||
getSchemaTpl('apiRequestAdaptor'),
|
||||
getSchemaTpl('apiAdaptor'),
|
||||
getSchemaTpl('apiAdaptor')
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
import {defaultValue, tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {SchemaExpression} from 'amis/lib/Schema';
|
||||
import type {SchemaExpression} from 'amis';
|
||||
|
||||
export interface BadgeControlProps extends FormControlProps {
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ import React from 'react';
|
||||
import {EditorManager, EditorNodeType, autobind} from 'amis-editor-core';
|
||||
import type {DSField, DSFieldGroup} from 'amis-editor-core';
|
||||
import {matchSorter} from 'match-sorter';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import {default as cx} from 'classnames';
|
||||
|
||||
export interface DataBindingProps extends FormControlProps {
|
||||
|
@ -402,9 +402,11 @@ export default class FormulaControl extends React.Component<
|
||||
|
||||
let curRendererSchema: any = null;
|
||||
if (rendererSchema) {
|
||||
curRendererSchema = Object.assign({}, rendererSchema, data, {
|
||||
curRendererSchema = Object.assign({}, rendererSchema, {
|
||||
type: rendererSchema.type ?? data.type,
|
||||
name: rendererSchema.name ?? data.name ?? 'value'
|
||||
// 目前表单项 wrapControl 还必须依赖一个 name
|
||||
// 所以这里先随便取个名字,这里渲染的时候应该是 value 控制,而不是关联 name
|
||||
name: 'FORMULA_CONTROL_PLACEHOLDER'
|
||||
});
|
||||
|
||||
// 默认要剔除的字段
|
||||
@ -521,9 +523,6 @@ export default class FormulaControl extends React.Component<
|
||||
|
||||
const {formulaPickerOpen, variables, variableMode} = this.state;
|
||||
|
||||
// 自身字段
|
||||
const selfName = this.props?.data?.name;
|
||||
|
||||
// 判断是否含有公式表达式
|
||||
const isExpr = isExpression(value);
|
||||
|
||||
|
@ -7,12 +7,13 @@ import cx from 'classnames';
|
||||
import {FormItem} from 'amis';
|
||||
import {autobind, getSchemaTpl, tipedLabel} from 'amis-editor-core';
|
||||
import {FormControlProps, isObject} from 'amis-core';
|
||||
import type {SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaApi} from 'amis';
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
enum MapType {
|
||||
CUSTOM = 'custom',
|
||||
API = 'api'
|
||||
API = 'api',
|
||||
VARIABLE = 'variable'
|
||||
}
|
||||
|
||||
export interface MapSourceControlProps extends FormControlProps {
|
||||
@ -38,7 +39,9 @@ export default class MapSourceControl extends React.Component<
|
||||
|
||||
let mapType: MapType = MapType.CUSTOM;
|
||||
if (props.data.hasOwnProperty('source') && props.data.source) {
|
||||
mapType = MapType.API;
|
||||
mapType = /\$\{(.*?)\}/g.test(props.data.source)
|
||||
? MapType.VARIABLE
|
||||
: MapType.API;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
@ -86,7 +89,7 @@ export default class MapSourceControl extends React.Component<
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapType === MapType.API) {
|
||||
if ([MapType.API, MapType.VARIABLE].includes(mapType)) {
|
||||
onBulkChange &&
|
||||
onBulkChange({
|
||||
source,
|
||||
@ -127,6 +130,10 @@ export default class MapSourceControl extends React.Component<
|
||||
{
|
||||
label: '外部接口',
|
||||
value: MapType.API
|
||||
},
|
||||
{
|
||||
label: '上下文变量',
|
||||
value: MapType.VARIABLE
|
||||
}
|
||||
] as Array<{
|
||||
label: string;
|
||||
@ -387,12 +394,25 @@ export default class MapSourceControl extends React.Component<
|
||||
|
||||
render() {
|
||||
const {mapType} = this.state;
|
||||
const {className} = this.props;
|
||||
const {className, render} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('ae-OptionControl', className)}>
|
||||
{this.renderHeader()}
|
||||
{mapType === MapType.CUSTOM ? this.renderMap() : this.renderApiPanel()}
|
||||
{mapType === MapType.CUSTOM ? this.renderMap() : null}
|
||||
{mapType === MapType.API ? this.renderApiPanel() : null}
|
||||
{mapType === MapType.VARIABLE
|
||||
? render(
|
||||
'variable',
|
||||
getSchemaTpl('sourceBindControl', {
|
||||
label: false,
|
||||
className: 'ae-ExtendMore'
|
||||
}),
|
||||
{
|
||||
onChange: this.handleAPIChange
|
||||
}
|
||||
)
|
||||
: null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user