Mege Feat-X Into Master (#11252)

* feat: Editor 支持插件弹出面板 (#11055)

* feat: Editor 支持插件弹出面板 (#11059)

* chore: 暴露 RendererThumb

* feat: resultBox item项支持点击事件 (#11060)

* feat: resultBox item项支持点击事件

* feat: resultBox item项支持点击事件

* feat: resultBox item项点击事件增加testid

* feat: resultBox item项点击事件更新jest快照

---------

Co-authored-by: hezhihang <hezhihang@baidu.com>

* chore: 调整 Page 渲染器导出方便外部覆盖

* chore: ConfirmBox 支持配置 onEntered 和 onExit 事件

* chore: checkboxes radios 选项 children 必须是数组且有长度才切到分组展示

* feat: 折叠面板,无标题时显示折叠箭头。组件存在于表单中,面板新增切换展示方式按钮 (#11067)

* feat: 折叠面板,无标题时显示折叠箭头。组件存在于表单中,面板新增切换展示方式按钮

* feat: 调整面板组件默认值

* feat: 调整无标题时,折叠箭头样式。调整面板配置

* 更新jest快照

* feat: page侧栏支持左右位置 (#11090)

Co-authored-by: hezhihang <hezhihang@baidu.com>

* chore: checkboxes radios 选项 children 必须是数组且有长度才切到分组展示

* feat: AvailableRenderersPanel 支持外围扩展

* feat: AvailableRenderersPanel 支持外围扩展

* feat: editor 插件 scaffoldForm 支持异步获取

* chore: add cross-env

* chore: 避免 Table 数据更新死循环

* chore: 调整 ts 定义

* feat: 给配置面板加些标记方便外围扩充

* chore: checkboxes radios 选项 children 必须是数组且有长度才切到分组展示

* chore: Options 相关逻辑支持外部扩展

* feat: mapping支持接口变量是records,提供外围扩充函数 (#11105)

* feat: mapping支持接口变量是records 的情况

* feat: 提供外围扩充函数

* feat: 修改函数名

* feat: 补充props 类型定义

* chore: 调整用例

* feat: 自定义样式扩展 (#11140)

Co-authored-by: hezhihang <hezhihang@baidu.com>

* feat: tabs支持删除动作,外观样式支持主题

* typo error

* chore: 支持更多的场景

* feat: 穿梭选择器增加点击选项事件

* feat: 锚点导航调整为sticky布局 (#11143)

* feat: 锚点导航调整为sticky布局

* bugfix

* 更新快照

* 更新单测

* 更新单测

* bugfix

* 优化样式

---------

Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>

* 动作面板支持外部注册 (#11149)

* 动作面板支持外部注册

* 修复someTree报错

* chore: debug 面板调整 (#11152)

* feat:事件动作面板支持查看调用链

* feat: 新增autoCheckChildren和onlyChildren属性配置面板,更改穿梭框事件点击位置

* feat: 预留外围扩充函数

* fix: 调整文案和属性名

* 修复初始化弹窗问题

* fix:自定义样式根节点不生效、样式修改时schema更新不正确,tabs动作仅支持hash删除 (#11145)

Co-authored-by: hezhihang <hezhihang@baidu.com>

* feat: 日期\日期范围组件可配禁止输入 (#11197)

* feat:验证器手机和电话号支持国家代号,数字框新增显示上下按钮,修改自定义样式实现。 (#11198)

* fix: 穿梭器面板中onlyChildren属性默认开启

* feat: 验证器中手机号和电话号支持国家代号

* feat: 数字框编辑器新增显示上下按钮开关,修改自定义样式实现

* 修复插件重复注册&输入序号支持表达式

* 移除无用代码

* feat: tree支持节点行为配置、点击事件、虚拟列表高度、工具栏、操作栏等功能

* feat: 虚拟列表支持高度自适应

* feat: 虚拟列表支持高度自适应

* feat: 虚拟列表支持高度自适应

* feat: 虚拟列表支持高度自适应

* feat: 表格列新增textOverflow属性

* feat: 新增文本未超出,不呼出功能

* feat: 修改dom计算的位置

* feat: 增加限制条件

* feat: 删除sonTarget属性

* feat: 合并renderTextOver

* feat: 留出外围扩充位置

* feat: 步骤条新增iconPositon属性,修复简单模式下箭头布局错乱 (#11250)

* feat: 替换按钮配置面板自定义样式

* feat: 步骤条新增iconPositon属性,修复简单模式下箭头布局错乱

---------

Co-authored-by: hzh11012 <43038692+hzh11012@users.noreply.github.com>
Co-authored-by: hezhihang <hezhihang@baidu.com>
Co-authored-by: F-jianchao <161407305+F-jianchao@users.noreply.github.com>
Co-authored-by: hsm-lv <80095014+hsm-lv@users.noreply.github.com>
Co-authored-by: fujianchao <fujianchao@baidu.com>
Co-authored-by: qkiroc <30946345+qkiroc@users.noreply.github.com>
Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>
Co-authored-by: z418577198 <418577198@qq.com>
Co-authored-by: lvxiaojiao <lvxiaojiao@baidu.com>
Co-authored-by: zhangzhijun03 <zhangzhijun03@baidu.com>
Co-authored-by: Allen <yupeng.fe@qq.com>
This commit is contained in:
liaoxuezhi 2024-11-25 12:55:00 +08:00 committed by GitHub
parent 8eb9a667ee
commit ad9c8d73b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
180 changed files with 12027 additions and 4951 deletions

View File

@ -3999,6 +3999,7 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
| filterable | `boolean` \| [`QuickFilterConfig`](./crud#quickfilterconfig) | `false` | 是否可快速搜索,`options`属性为静态选项,支持设置`source`属性从接口获取选项 | | filterable | `boolean` \| [`QuickFilterConfig`](./crud#quickfilterconfig) | `false` | 是否可快速搜索,`options`属性为静态选项,支持设置`source`属性从接口获取选项 |
| quickEdit | `boolean` \| [`QuickEditConfig`](./crud#quickeditconfig) | - | 快速编辑,一般需要配合`quickSaveApi`接口使用 | | quickEdit | `boolean` \| [`QuickEditConfig`](./crud#quickeditconfig) | - | 快速编辑,一般需要配合`quickSaveApi`接口使用 |
| quickEditEnabledOn | `SchemaExpression` | - | 开启快速编辑条件[表达式](../../docs/concepts/expression) | | | quickEditEnabledOn | `SchemaExpression` | - | 开启快速编辑条件[表达式](../../docs/concepts/expression) | |
| textOverflow | `string` | `default` | 文本溢出后展示形式,默认换行处理。可选值 `ellipsis` 溢出隐藏展示, `noWrap` 不换行展示(仅在列为静态文本时生效) | `6.9.0` |
#### QuickFilterConfig #### QuickFilterConfig

View File

@ -249,6 +249,8 @@ order: 59
`cascade`默认为 false子节点禁止反选值不包含子节点值配置`"cascade": true`子节点可以反选值包含父子节点值1.9.0 之前的版本 cascade 配置为 true 的效果为:选中父节点不默认选中子节点) `cascade`默认为 false子节点禁止反选值不包含子节点值配置`"cascade": true`子节点可以反选值包含父子节点值1.9.0 之前的版本 cascade 配置为 true 的效果为:选中父节点不默认选中子节点)
> 6.9.0 以上版本 autoCancelParent 配置为 true 的效果为:取消子节点,自动去除父节点的值(仅在多选和 cascade 为 true 时生效)
```schema: scope="body" ```schema: scope="body"
{ {
"type": "form", "type": "form",
@ -292,7 +294,7 @@ order: 59
{ {
"type": "divider" "type": "divider"
}, },
{ {
"type": "input-tree", "type": "input-tree",
"name": "tree2", "name": "tree2",
"label": "子节点可以反选,值包含父子节点值", "label": "子节点可以反选,值包含父子节点值",
@ -326,6 +328,45 @@ order: 59
"value": "c" "value": "c"
} }
] ]
},
{
"type": "divider"
},
{
"type": "input-tree",
"name": "tree3",
"label": "子节点可以反选,值包含父子节点值,取消子节点,自动去除父节点的值",
"multiple": true,
"cascade": true,
"autoCancelParent": true,
"options": [
{
"label": "A",
"value": "a"
},
{
"label": "B",
"value": "b",
"children": [
{
"label": "B-1",
"value": "b-1"
},
{
"label": "B-2",
"value": "b-2"
},
{
"label": "B-3",
"value": "b-3"
}
]
},
{
"label": "C",
"value": "c"
}
]
} }
] ]
} }
@ -1086,6 +1127,338 @@ true false false [{label: 'A/B/C', value: 'a/b/c'},{label: 'A
适用于需选择的数据/信息源较多时,用户可直观的知道自己所选择的数据/信息的场景。未配置 searchApi 是前端检索,配置之后就只能通过后端检索。 适用于需选择的数据/信息源较多时,用户可直观的知道自己所选择的数据/信息的场景。未配置 searchApi 是前端检索,配置之后就只能通过后端检索。
## 节点行为配置
> 6.9.0 以上版本
设置`nodeBehavior`属性,可以更改节点的行为,默认为选中行为,支持配置多个行为。
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"type": "input-tree",
"name": "tree1",
"label": "选中",
"options": [
{
"label": "Folder A",
"value": 1,
"children": [
{
"label": "file A",
"value": 2,
}
]
},
{
"label": "file C",
"value": 3
}
]
},
{
"type": "input-tree",
"name": "tree2",
"label": "展开",
"nodeBehavior": ["unfold"],
"options": [
{
"label": "Folder A",
"value": 4,
"children": [
{
"label": "file A",
"value": 5,
}
]
},
{
"label": "file C",
"value": 6
}
]
},
{
"type": "input-tree",
"name": "tree3",
"label": "选中+展开",
"nodeBehavior": ["check", "unfold"],
"options": [
{
"label": "Folder A",
"value": 7,
"children": [
{
"label": "file A",
"value": 8,
}
]
},
{
"label": "file C",
"value": 9
}
]
}
]
}
```
## 自定义选项操作
> 6.9.0 以上版本
> 使用`itemActions`属性,自定义下拉选项的操作。
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"type": "input-tree",
"name": "tree",
"label": "Tree",
"iconField": "icon",
"options": [
{
"label": "采购单",
"value": "order",
"tag": "数据模型",
"icon": "fa fa-database",
"children": [
{
"label": "ID",
"value": "id",
"tag": "数字",
"icon": "fa fa-check"
},
{
"label": "采购人",
"value": "name",
"tag": "字符串",
"icon": "fa fa-check"
},
{
"label": "采购时间",
"value": "time",
"tag": "日期时间",
"icon": "fa fa-check"
}
]
}
],
"itemActions": [
{
"type": "button",
"icon": "fa fa-plus",
"level": "link",
"size": "xs",
"onEvent": {
"click": {
"weight": 0,
"actions": [
{
"ignoreError": false,
"actionType": "toast",
"args": {
"msgType": "info",
"position": "top-right",
"closeButton": true,
"showIcon": true,
"msg": "自定义操作",
"className": "theme-toast-action-scope"
}
}
]
}
}
}
]
}
]
}
```
## 工具栏区域
> 6.9.0 以上版本
> 使用`toolbar`属性,自定义工具栏区域。(仅开启检索时生效)
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"type": "input-tree",
"name": "tree",
"label": "Tree",
"searchable": true,
"toolbar": [
{
"type": "button",
"label": "弹窗",
"onEvent": {
"click": {
"actions": [
{
"actionType": "dialog",
"dialog": {
"type": "dialog",
"title": "未命名弹窗",
"body": [
{
"type": "tpl",
"tpl": "弹窗内容"
}
],
"actions": [
{
"type": "button",
"actionType": "cancel",
"label": "取消"
},
{
"type": "button",
"actionType": "confirm",
"label": "确定",
"primary": true
}
]
}
}
]
}
}
}
],
"options": [
{
"label": "Folder A",
"value": 1,
"collapsed": true,
"children": [
{
"label": "file A",
"value": 2
},
{
"label": "file B",
"value": 3
}
]
},
{
"label": "file D",
"value": 4
}
]
}
]
}
```
## 虚拟列表
> 6.9.0 以上版本, 开启 heightAuto 后,虚拟列表将自适应高度
```schema: scope="body"
{
"type": "page",
"aside": [
{
"type": "flex",
"direction": "column",
"isFixedHeight": true,
"style": {
"height": "300px"
},
"items": [
{
"type": "input-tree",
"id": "tree",
"name": "tree",
"label": false,
"heightAuto": true,
"virtualThreshold": 5,
"options": [
{
"label": "Folder A",
"value": 1,
"children": [
{
"label": "file A",
"value": 2
},
{
"label": "file B",
"value": 3
}
]
},
{
"label": "file C",
"value": 4
},
{
"label": "file D",
"value": 5
},
{
"label": "file E",
"value": 6
},
{
"label": "file F",
"value": 7
},
{
"label": "file G",
"value": 8
},
{
"label": "file H",
"value": 9
},
{
"label": "file I",
"value": 10
},
{
"label": "file J",
"value": 11
},
{
"label": "file K",
"value": 12
},
{
"label": "file L",
"value": 13
}
],
"wrapperCustomStyle": {
"root": {
"height": "100%"
}
}
}
]
}
],
"body": [
{
"type": "tpl",
"tpl": "开启heightAuto后设置tree的高度虚拟列表将自适应"
}
]
}
```
## 属性表 ## 属性表
当做选择器表单项使用时,除了支持 [普通表单项属性表](./formitem#%E5%B1%9E%E6%80%A7%E8%A1%A8) 中的配置以外,还支持下面一些配置 当做选择器表单项使用时,除了支持 [普通表单项属性表](./formitem#%E5%B1%9E%E6%80%A7%E8%A1%A8) 中的配置以外,还支持下面一些配置
@ -1137,6 +1510,11 @@ true false false [{label: 'A/B/C', value: 'a/b/c'},{label: 'A
| menuTpl | `string` | | 选项自定义渲染 HTML 片段 | `2.8.0` | | menuTpl | `string` | | 选项自定义渲染 HTML 片段 | `2.8.0` |
| enableDefaultIcon | `boolean` | `true` | 是否为选项添加默认的前缀 Icon父节点默认为`folder`,叶节点默认为`file` | `2.8.0` | | enableDefaultIcon | `boolean` | `true` | 是否为选项添加默认的前缀 Icon父节点默认为`folder`,叶节点默认为`file` | `2.8.0` |
| heightAuto | `boolean` | `false` | 默认高度会有个 maxHeight即超过一定高度就会内部滚动如果希望自动增长请设置此属性 | `3.0.0` | | heightAuto | `boolean` | `false` | 默认高度会有个 maxHeight即超过一定高度就会内部滚动如果希望自动增长请设置此属性 | `3.0.0` |
| nodeBehavior | `Array<'unfold' \| 'check' \| ''>` | `['check']` | 节点行为配置,支持配置多个行为 | `6.9.0` |
| autoCancelParent | `boolean` | `false` | 子节点取消时自动取消父节点的值,仅在多选且 cascade 为 true 时生效 | `6.9.0` |
| toolbar | `SchemaNode` | | 工具栏区域,仅开启检索时生效 | `6.9.0` |
| toolbarClassName | `string` | | 工具栏区域类名 | `6.9.0` |
| itemActions | `SchemaNode` | | 节点操作栏区域 | `6.9.0` |
## 事件表 ## 事件表
@ -1151,6 +1529,7 @@ true false false [{label: 'A/B/C', value: 'a/b/c'},{label: 'A
| editConfirm (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`item: object` 编辑的节点信息<br/>`items: object[]`选项集合 | 编辑节点提交时触发 | | editConfirm (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`item: object` 编辑的节点信息<br/>`items: object[]`选项集合 | 编辑节点提交时触发 |
| deleteConfirm (3.6.4 及以上版本) | `[name]: string` 组件的值<br/>`item: object` 删除的节点信息<br/>`items: object[]`选项集合 | 删除节点提交时触发 | | deleteConfirm (3.6.4 及以上版本) | `[name]: string` 组件的值<br/>`item: object` 删除的节点信息<br/>`items: object[]`选项集合 | 删除节点提交时触发 |
| deferLoadFinished (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`result: object` deferApi 懒加载远程请求成功后返回的数据 <br/>`items: object[]`选项集合 | 懒加载接口远程请求成功时触发 | | deferLoadFinished (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`result: object` deferApi 懒加载远程请求成功后返回的数据 <br/>`items: object[]`选项集合 | 懒加载接口远程请求成功时触发 |
| itemClick (6.9.0 以上版本) | `value: any`表单项的值,值格式取决于具体配置<br/>`item: object` 点击的节点信息 | 节点点击时触发 |
| add不推荐 | `[name]: object` 新增的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 新增节点提交时触发 | | add不推荐 | `[name]: object` 新增的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 新增节点提交时触发 |
| edit不推荐 | `[name]: object` 编辑的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 编辑节点提交时触发 | | edit不推荐 | `[name]: object` 编辑的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 编辑节点提交时触发 |
| delete不推荐 | `[name]: object` 删除的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 删除节点提交时触发 | | delete不推荐 | `[name]: object` 删除的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 删除节点提交时触发 |
@ -1440,6 +1819,60 @@ true false false [{label: 'A/B/C', value: 'a/b/c'},{label: 'A
} }
``` ```
### itemClick
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"debug": true,
"body": [
{
"type": "input-tree",
"name": "tree",
"label": "Tree",
"nodeBehavior": [],
"onEvent": {
"itemClick": {
"actions": [
{
"actionType": "toast",
"args": {
"msg": "${event.data.tree|json}"
}
}
]
}
},
"options": [
{
"label": "Folder A",
"value": 1,
"children": [
{
"label": "file A",
"value": 2
},
{
"label": "file B",
"value": 3
}
]
},
{
"label": "file C",
"value": 4
},
{
"label": "file D",
"value": 5
}
]
}
]
}
```
## 动作表 ## 动作表
当前组件对外暴露以下特性动作,其他组件可以通过指定`actionType: 动作名称`、`componentId: 该组件id`来触发这些动作,动作配置可以通过`args: {动作配置项名称: xxx}`来配置具体的参数,详细请查看[事件动作](../../docs/concepts/event-action#触发其他组件的动作)。 当前组件对外暴露以下特性动作,其他组件可以通过指定`actionType: 动作名称`、`componentId: 该组件id`来触发这些动作,动作配置可以通过`args: {动作配置项名称: xxx}`来配置具体的参数,详细请查看[事件动作](../../docs/concepts/event-action#触发其他组件的动作)。
@ -1455,6 +1888,7 @@ true false false [{label: 'A/B/C', value: 'a/b/c'},{label: 'A
| clear | - | 清空 | | clear | - | 清空 |
| reset | - | 将值重置为初始值。6.3.0 及以下版本为`resetValue` | | reset | - | 将值重置为初始值。6.3.0 及以下版本为`resetValue` |
| setValue | `value: string` \| `string[]` 更新的值 | 更新数据,开启`multiple`支持设置多项,开启`joinValues`时,多值用`,`分隔,否则多值用数组 | | setValue | `value: string` \| `string[]` 更新的值 | 更新数据,开启`multiple`支持设置多项,开启`joinValues`时,多值用`,`分隔,否则多值用数组 |
| search | `keyword: string` 检索的值 | 检索数据 |
### clear ### clear
@ -1589,3 +2023,67 @@ true false false [{label: 'A/B/C', value: 'a/b/c'},{label: 'A
] ]
} }
``` ```
### search
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"debug": true,
"body": [
{
"type": "search-box",
"name": "keyword",
"className": "mb-4",
"style": {
"width": "100%"
},
"onEvent": {
"change": {
"actions": [
{
"componentId": "tree",
"groupType": "component",
"actionType": "search",
"args": {
"keyword": "${event.data.value}"
}
}
]
}
}
},
{
"type": "input-tree",
"id": "tree",
"name": "tree",
"label": false,
"options": [
{
"label": "Folder A",
"value": 1,
"children": [
{
"label": "file A",
"value": 2
},
{
"label": "file B",
"value": 3
}
]
},
{
"label": "file C",
"value": 4
},
{
"label": "file D",
"value": 5
}
]
}
]
}
```

View File

@ -418,6 +418,7 @@ order: 60
| editConfirm (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`item: object` 编辑的节点信息<br/>`items: object[]`选项集合 | 编辑节点提交时触发 | | editConfirm (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`item: object` 编辑的节点信息<br/>`items: object[]`选项集合 | 编辑节点提交时触发 |
| deleteConfirm (3.6.4 及以上版本) | `[name]: string` 组件的值<br/>`item: object` 删除的节点信息<br/>`items: object[]`选项集合 | 删除节点提交时触发 | | deleteConfirm (3.6.4 及以上版本) | `[name]: string` 组件的值<br/>`item: object` 删除的节点信息<br/>`items: object[]`选项集合 | 删除节点提交时触发 |
| deferLoadFinished (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`result: object` deferApi 懒加载远程请求成功后返回的数据 <br/>`items: object[]`选项集合 | 懒加载接口远程请求成功时触发 | | deferLoadFinished (3.6.4 及以上版本) | `[name]: object` 组件的值<br/>`result: object` deferApi 懒加载远程请求成功后返回的数据 <br/>`items: object[]`选项集合 | 懒加载接口远程请求成功时触发 |
| itemClick (6.9.0 以上版本) | `value: any`表单项的值,值格式取决于具体配置<br/>`item: object` 点击的节点信息 | 节点点击时触发 |
| add不推荐 | `[name]: object` 新增的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 新增节点提交时触发 | | add不推荐 | `[name]: object` 新增的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 新增节点提交时触发 |
| edit不推荐 | `[name]: object` 编辑的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 编辑节点提交时触发 | | edit不推荐 | `[name]: object` 编辑的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 编辑节点提交时触发 |
| delete不推荐 | `[name]: object` 删除的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 删除节点提交时触发 | | delete不推荐 | `[name]: object` 删除的节点信息<br/>`items: object[]`选项集合(< 2.3.2 及以下版本 `options` | 删除节点提交时触发 |
@ -812,6 +813,60 @@ order: 60
} }
``` ```
### itemClick
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"debug": true,
"body": [
{
"type": "input-tree",
"name": "tree",
"label": "Tree",
"nodeBehavior": [],
"onEvent": {
"itemClick": {
"actions": [
{
"actionType": "toast",
"args": {
"msg": "${event.data.tree|json}"
}
}
]
}
},
"options": [
{
"label": "Folder A",
"value": 1,
"children": [
{
"label": "file A",
"value": 2
},
{
"label": "file B",
"value": 3
}
]
},
{
"label": "file C",
"value": 4
},
{
"label": "file D",
"value": 5
}
]
}
]
}
```
## 动作表 ## 动作表
当前组件对外暴露以下特性动作,其他组件可以通过指定`actionType: 动作名称`、`componentId: 该组件id`来触发这些动作,动作配置可以通过`args: {动作配置项名称: xxx}`来配置具体的参数,详细请查看[事件动作](../../docs/concepts/event-action#触发其他组件的动作)。 当前组件对外暴露以下特性动作,其他组件可以通过指定`actionType: 动作名称`、`componentId: 该组件id`来触发这些动作,动作配置可以通过`args: {动作配置项名称: xxx}`来配置具体的参数,详细请查看[事件动作](../../docs/concepts/event-action#触发其他组件的动作)。

View File

@ -251,6 +251,30 @@ Page 默认将页面分为几个区域,分别是**内容区(`body`**、**
通过配置 `asideSticky` 来开关,默认是开启状态。 通过配置 `asideSticky` 来开关,默认是开启状态。
## aside 展示位置
通过配置 `asidePosition`,可以控制侧边栏的展示位置。
```schema
{
"type": "page",
"asideResizor": true,
"asidePosition": "right",
"aside": [
{
"type": "tpl",
"tpl": "这是侧边栏部分"
}
],
"body": [
{
"type": "tpl",
"tpl": "这是内容区"
}
]
}
```
## 属性表 ## 属性表
| 属性名 | 类型 | 默认值 | 说明 | | 属性名 | 类型 | 默认值 | 说明 |
@ -264,6 +288,7 @@ Page 默认将页面分为几个区域,分别是**内容区(`body`**、**
| asideMinWidth | `number` | | 页面边栏区域的最小宽度 | | asideMinWidth | `number` | | 页面边栏区域的最小宽度 |
| asideMaxWidth | `number` | | 页面边栏区域的最大宽度 | | asideMaxWidth | `number` | | 页面边栏区域的最大宽度 |
| asideSticky | `boolean` | true | 用来控制边栏固定与否 | | asideSticky | `boolean` | true | 用来控制边栏固定与否 |
| asidePosition | `"left" \| "right"` | `"left"` | 页面边栏区域的位置 |
| toolbar | [SchemaNode](../../docs/types/schemanode) | | 往页面的右上角加内容,需要注意的是,当有 title 时,该区域在右上角,没有时该区域在顶部 | | toolbar | [SchemaNode](../../docs/types/schemanode) | | 往页面的右上角加内容,需要注意的是,当有 title 时,该区域在右上角,没有时该区域在顶部 |
| body | [SchemaNode](../../docs/types/schemanode) | | 往页面的内容区域加内容 | | body | [SchemaNode](../../docs/types/schemanode) | | 往页面的内容区域加内容 |
| className | `string` | | 外层 dom 类名 | | className | `string` | | 外层 dom 类名 |

View File

@ -881,6 +881,7 @@ order: 68
| 事件名称 | 事件参数 | 说明 | | 事件名称 | 事件参数 | 说明 |
| -------- | ------------------------------------ | ---------------- | | -------- | ------------------------------------ | ---------------- |
| change | `value: number \| string` 选项卡索引 | 切换选项卡时触发 | | change | `value: number \| string` 选项卡索引 | 切换选项卡时触发 |
| delete | `value: number \| string` 选项卡索引 | 删除选项卡时触发 |
### change ### change
@ -918,6 +919,43 @@ order: 68
} }
``` ```
### delete
```schema: scope="body"
{
"type": "tabs",
"closable": true,
"mode": "line",
"tabs": [
{
"title": "选项卡1",
"body": "选项卡内容1"
},
{
"title": "选项卡2",
"body": "选项卡内容2"
},
{
"title": "选项卡3",
"body": "选项卡内容3"
}
],
"onEvent": {
"delete": {
"actions": [
{
"actionType": "toast",
"args": {
"msgType": "info",
"msg": "删除选项卡${event.data.value}"
}
}
]
}
}
}
```
## 动作表 ## 动作表
当前组件对外暴露以下特性动作,其他组件可以通过指定`actionType: 动作名称`、`componentId: 该组件id`来触发这些动作,动作配置可以通过`args: {动作配置项名称: xxx}`来配置具体的参数,详细请查看[事件动作](../../docs/concepts/event-action#触发其他组件的动作)。 当前组件对外暴露以下特性动作,其他组件可以通过指定`actionType: 动作名称`、`componentId: 该组件id`来触发这些动作,动作配置可以通过`args: {动作配置项名称: xxx}`来配置具体的参数,详细请查看[事件动作](../../docs/concepts/event-action#触发其他组件的动作)。
@ -925,6 +963,7 @@ order: 68
| 动作名称 | 动作配置 | 说明 | | 动作名称 | 动作配置 | 说明 |
| --------------- | ---------------------------------------- | ---------------- | | --------------- | ---------------------------------------- | ---------------- |
| changeActiveKey | `activeKey: number \| string` 选项卡索引 | 激活指定的选项卡 | | changeActiveKey | `activeKey: number \| string` 选项卡索引 | 激活指定的选项卡 |
| deleteTab | `deleteHash: string` 选项卡 hash | 删除指定的选项卡 |
### changeActiveKey ### changeActiveKey
@ -1007,3 +1046,88 @@ order: 68
} }
] ]
``` ```
### deleteTab
可以尝试点击下方按钮,实现选项卡删除。
```schema: scope="body"
[
{
"type": "action",
"label": "删除选项卡1",
"className": "mr-3 mb-3",
"onEvent": {
"click": {
"actions": [
{
"actionType": "deleteTab",
"componentId": "tabs-change-receiver",
"args": {
"deleteHash": "tab1"
}
}
]
}
}
},
{
"type": "action",
"label": "删除选项卡2",
"className": "mr-3 mb-3",
"onEvent": {
"click": {
"actions": [
{
"actionType": "deleteTab",
"componentId": "tabs-change-receiver",
"args": {
"deleteHash": "tab2"
}
}
]
}
}
},
{
"type": "action",
"label": "删除选项卡3",
"className": "mr-3 mb-3",
"onEvent": {
"click": {
"actions": [
{
"actionType": "deleteTab",
"componentId": "tabs-change-receiver",
"args": {
"deleteHash": "tab3"
}
}
]
}
}
},
{
"id": "tabs-change-receiver",
"type": "tabs",
"mode": "line",
"tabs": [
{
"title": "选项卡1",
"hash": "tab1",
"body": "选项卡内容1"
},
{
"title": "选项卡2",
"hash": "tab2",
"body": "选项卡内容2"
},
{
"title": "选项卡3",
"hash": "tab3",
"body": "选项卡内容3"
}
]
}
]
```

View File

@ -28,7 +28,7 @@ describe('constructor', () => {
OriginComponent.defaultProps = { OriginComponent.defaultProps = {
name: 'test' name: 'test'
}; };
const WrappedComponent = wrapControl(OriginComponent as any); const WrappedComponent = wrapControl({}, OriginComponent as any);
renderComponent(WrappedComponent, {$schema: {}}); renderComponent(WrappedComponent, {$schema: {}});
expect(screen.getByText('FormItemStore')).toBeInTheDocument(); expect(screen.getByText('FormItemStore')).toBeInTheDocument();
@ -39,7 +39,7 @@ describe('constructor', () => {
// 用于断言formItem已被注册 // 用于断言formItem已被注册
return <div>{props.formItem?.storeType}</div>; return <div>{props.formItem?.storeType}</div>;
}; };
const WrappedComponent = wrapControl(OriginComponent as any); const WrappedComponent = wrapControl({}, OriginComponent as any);
renderComponent(WrappedComponent, {$schema: {name: 'test'}}); renderComponent(WrappedComponent, {$schema: {name: 'test'}});
expect(screen.getByText('FormItemStore')).toBeInTheDocument(); expect(screen.getByText('FormItemStore')).toBeInTheDocument();
@ -50,7 +50,7 @@ describe('constructor', () => {
// 用于断言formItem已被注册 // 用于断言formItem已被注册
return <div>{props.formItem?.storeType}</div>; return <div>{props.formItem?.storeType}</div>;
}; };
const WrappedComponent = wrapControl(OriginComponent as any); const WrappedComponent = wrapControl({}, OriginComponent as any);
renderComponent(WrappedComponent, {$schema: {}}); renderComponent(WrappedComponent, {$schema: {}});
expect(screen.queryByText('FormItemStore')).not.toBeInTheDocument(); expect(screen.queryByText('FormItemStore')).not.toBeInTheDocument();

View File

@ -35,8 +35,8 @@
"typescript": "^4.6.4" "typescript": "^4.6.4"
}, },
"scripts": { "scripts": {
"build": "npm run clean-dist && NODE_ENV=production rollup -c ", "build": "npm run clean-dist && cross-env NODE_ENV=production rollup -c ",
"build-esm": "npm run clean-dist && NODE_ENV=production rollup -c rollup.esm.config.js", "build-esm": "npm run clean-dist && cross-env NODE_ENV=production rollup -c rollup.esm.config.js",
"dev": "rollup -c -w", "dev": "rollup -c -w",
"test": "jest", "test": "jest",
"update-snapshot": "jest --updateSnapshot", "update-snapshot": "jest --updateSnapshot",
@ -49,7 +49,8 @@
], ],
"dependencies": { "dependencies": {
"@rc-component/mini-decimal": "^1.0.1", "@rc-component/mini-decimal": "^1.0.1",
"amis-formula": "^6.9.0", "cross-env": "^7.0.3",
"amis-formula": "*",
"classnames": "2.3.2", "classnames": "2.3.2",
"file-saver": "^2.0.2", "file-saver": "^2.0.2",
"hoist-non-react-statics": "^3.3.2", "hoist-non-react-statics": "^3.3.2",

View File

@ -10,6 +10,7 @@ import {IContinueAction} from './ContinueAction';
import {ILoopAction} from './LoopAction'; import {ILoopAction} from './LoopAction';
import {IParallelAction} from './ParallelAction'; import {IParallelAction} from './ParallelAction';
import {ISwitchAction} from './SwitchAction'; import {ISwitchAction} from './SwitchAction';
import {debug} from '../utils/debug';
// 循环动作执行状态 // 循环动作执行状态
export enum LoopStatus { export enum LoopStatus {
@ -343,6 +344,9 @@ export const runAction = async (
console.group?.(`run action ${action.actionType}`); console.group?.(`run action ${action.actionType}`);
console.debug(`[${action.actionType}] action args, data`, args, data); console.debug(`[${action.actionType}] action args, data`, args, data);
debug('action', `run action ${action.actionType} with args`, args);
debug('action', `run action ${action.actionType} with data`, data);
let stopped = false; let stopped = false;
const actionResult = await actionInstrance.run( const actionResult = await actionInstrance.run(
{ {

View File

@ -81,7 +81,11 @@ import type {
FormControlProps, FormControlProps,
FormItemProps FormItemProps
} from './renderers/Item'; } from './renderers/Item';
import {OptionsControl, registerOptionsControl} from './renderers/Options'; import {
OptionsControl,
registerOptionsControl,
OptionsControlBase
} from './renderers/Options';
import type {OptionsControlProps} from './renderers/Options'; import type {OptionsControlProps} from './renderers/Options';
import type {FormOptionsControl} from './renderers/Options'; import type {FormOptionsControl} from './renderers/Options';
import {Schema} from './types'; import {Schema} from './types';
@ -217,6 +221,7 @@ export {
ErrorBoundary, ErrorBoundary,
addSchemaFilter, addSchemaFilter,
OptionsControlProps, OptionsControlProps,
OptionsControlBase,
FormOptionsControl, FormOptionsControl,
FormControlProps, FormControlProps,
FormBaseControl, FormBaseControl,
@ -241,6 +246,7 @@ export {
envOverwrite, envOverwrite,
getGlobalOptions, getGlobalOptions,
setGlobalOptions, setGlobalOptions,
wrapFetcher,
SchemaRenderer SchemaRenderer
}; };

View File

@ -481,6 +481,7 @@ export interface FormItemBasicConfig extends Partial<RendererConfig> {
renderDescription?: boolean; renderDescription?: boolean;
test?: RegExp | TestFunc; test?: RegExp | TestFunc;
storeType?: string; storeType?: string;
formItemStoreType?: string;
validations?: string; validations?: string;
strictMode?: boolean; strictMode?: boolean;
@ -2205,6 +2206,7 @@ export function asFormItem(config: Omit<FormItemConfig, 'component'>) {
} }
return wrapControl( return wrapControl(
config,
hoistNonReactStatic( hoistNonReactStatic(
class extends FormItemWrap { class extends FormItemWrap {
static defaultProps: any = { static defaultProps: any = {

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ import {isAlive} from 'mobx-state-tree';
import {observer} from 'mobx-react'; import {observer} from 'mobx-react';
import hoistNonReactStatic from 'hoist-non-react-statics'; import hoistNonReactStatic from 'hoist-non-react-statics';
import {withRootStore} from '../WithRootStore'; import {withRootStore} from '../WithRootStore';
import {FormBaseControl, FormItemWrap} from './Item'; import {FormBaseControl, FormItemConfig, FormItemWrap} from './Item';
import {Api, DataChangeReason} from '../types'; import {Api, DataChangeReason} from '../types';
import {TableStore} from '../store/table'; import {TableStore} from '../store/table';
import pick from 'lodash/pick'; import pick from 'lodash/pick';
@ -94,7 +94,7 @@ export interface ControlProps {
export function wrapControl< export function wrapControl<
T extends React.ComponentType<React.ComponentProps<T> & ControlProps> T extends React.ComponentType<React.ComponentProps<T> & ControlProps>
>(ComposedComponent: T) { >(config: Omit<FormItemConfig, 'component'>, ComposedComponent: T) {
type OuterProps = JSX.LibraryManagedAttributes< type OuterProps = JSX.LibraryManagedAttributes<
T, T,
Omit<React.ComponentProps<T>, keyof ControlProps> Omit<React.ComponentProps<T>, keyof ControlProps>
@ -194,7 +194,7 @@ export function wrapControl<
const model = rootStore.addStore({ const model = rootStore.addStore({
id: guid(), id: guid(),
path: this.props.$path, path: this.props.$path,
storeType: FormItemStore.name, storeType: config.formItemStoreType || FormItemStore.name,
parentId: store?.id, parentId: store?.id,
name, name,
colIndex: colIndex !== undefined ? colIndex : undefined, colIndex: colIndex !== undefined ? colIndex : undefined,

View File

@ -620,7 +620,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
} }
for (let option of options) { for (let option of options) {
if (Array.isArray(option.children)) { if (Array.isArray(option.children) && option.children.length) {
const childFirst = getFirstAvaibleOption(option.children); const childFirst = getFirstAvaibleOption(option.children);
if (childFirst !== undefined) { if (childFirst !== undefined) {
return childFirst; return childFirst;

View File

@ -66,10 +66,12 @@ export function removeApiRequestAdaptor(adaptor: RequestAdaptor) {
* *
* @param adaptor * @param adaptor
*/ */
export function addApiResponseAdator(adaptor: ResponseAdaptor) { export function addApiResponseAdaptor(adaptor: ResponseAdaptor) {
responseAdaptors.push(adaptor); responseAdaptors.push(adaptor);
return () => removeApiResponseAdaptor(adaptor); return () => removeApiResponseAdaptor(adaptor);
} }
// :( 之前写错了,这里为了让以前的代码能继续跑,暂时保留
export const addApiResponseAdator = addApiResponseAdaptor;
/** /**
* *

View File

@ -28,6 +28,8 @@ export function attachmentAdpator(
let matches = disposition.match(filenameRegex); let matches = disposition.match(filenameRegex);
if (matches && matches.length) { if (matches && matches.length) {
filename = matches[1].replace(`UTF-8''`, '').replace(/['"]/g, ''); filename = matches[1].replace(`UTF-8''`, '').replace(/['"]/g, '');
} else {
filename = disposition?.split(';')[1];
} }
// 很可能是中文被 url-encode 了 // 很可能是中文被 url-encode 了

View File

@ -6,10 +6,12 @@ import React, {Component, useEffect, useRef, useState, version} from 'react';
import cx from 'classnames'; import cx from 'classnames';
import {findDOMNode, render, unmountComponentAtNode} from 'react-dom'; import {findDOMNode, render, unmountComponentAtNode} from 'react-dom';
// import {createRoot} from 'react-dom/client'; // import {createRoot} from 'react-dom/client';
import {autorun, observable} from 'mobx'; import {autorun, observable, action} from 'mobx';
import {observer} from 'mobx-react'; import {observer} from 'mobx-react';
import {uuidv4, importLazyComponent} from './helper'; import {uuidv4, importLazyComponent} from './helper';
import position from './position'; import position from './position';
import {resolveVariableAndFilter} from './resolveVariableAndFilter';
import {callStrFunction} from './api';
export const JsonView = React.lazy(() => export const JsonView = React.lazy(() =>
import('react-json-view').then(importLazyComponent) import('react-json-view').then(importLazyComponent)
@ -19,7 +21,7 @@ class Log {
@observable cat = ''; @observable cat = '';
@observable level = ''; @observable level = '';
@observable msg = ''; @observable msg = '';
@observable ext? = ''; @observable ext?: any = '';
} }
class AMISDebugStore { class AMISDebugStore {
@ -62,6 +64,25 @@ class AMISDebugStore {
* *
*/ */
@observable ellipsisThreshold: number; @observable ellipsisThreshold: number;
@action.bound
open() {
this.isExpanded = true;
this.inspectMode = true;
}
@action.bound
close() {
this.isExpanded = false;
this.activeId = '';
this.hoverId = '';
this.inspectMode = false;
}
@action.bound
toggleInspectMode() {
this.inspectMode = !this.inspectMode;
}
} }
const store = new AMISDebugStore(); const store = new AMISDebugStore();
@ -86,12 +107,16 @@ const LogView = observer(({store}: {store: AMISDebugStore}) => {
<div className="AMISDebug-logLineMsg"> <div className="AMISDebug-logLineMsg">
[{log.cat}] {log.msg} [{log.cat}] {log.msg}
</div> </div>
{log.ext ? ( {(typeof log.ext === 'string' &&
(log.ext.startsWith('{') || log.ext.startsWith('['))) ||
typeof log.ext === 'object' ? (
<React.Suspense fallback={<div>Loading...</div>}> <React.Suspense fallback={<div>Loading...</div>}>
<JsonView <JsonView
name={null} name={null}
theme="monokai" theme="monokai"
src={JSON.parse(log.ext)} src={
typeof log.ext === 'string' ? parseJson(log.ext) : log.ext
}
collapsed={true} collapsed={true}
enableClipboard={false} enableClipboard={false}
displayDataTypes={false} displayDataTypes={false}
@ -99,7 +124,9 @@ const LogView = observer(({store}: {store: AMISDebugStore}) => {
iconStyle="square" iconStyle="square"
/> />
</React.Suspense> </React.Suspense>
) : null} ) : (
<pre className="AMISDebug-value">{JSON.stringify(log.ext)}</pre>
)}
</div> </div>
); );
})} })}
@ -188,6 +215,36 @@ const AMISDebug = observer(({store}: {store: AMISDebugStore}) => {
}; };
}, [isResizing]); }, [isResizing]);
const handleInputKeyUp = React.useCallback((e: React.KeyboardEvent<any>) => {
if (e.key === 'Enter') {
const input = e.target as HTMLInputElement;
const expression = input.value;
input.value = '';
try {
const activeId = store.activeId;
const ctx = ComponentInfo[activeId]?.component.props.data || {};
const result = expression.startsWith('${')
? resolveVariableAndFilter(expression, ctx, '| raw')
: callStrFunction(
new Function('data', `with(data) {return ${expression};}`),
['data'],
ctx
);
debug('debug', `evaluate expression \`${expression}\``, result);
} catch (e) {
debug(
'error',
`evaluate expression \`${expression}\``,
`Error: ${e.message}`
);
} finally {
store.tab = 'log';
}
}
}, []);
return ( return (
<div <div
className={cx('AMISDebug', { className={cx('AMISDebug', {
@ -196,13 +253,7 @@ const AMISDebug = observer(({store}: {store: AMISDebugStore}) => {
})} })}
ref={panelRef} ref={panelRef}
> >
<div <div className="AMISDebug-toggle" title="open debug" onClick={store.open}>
className="AMISDebug-toggle"
title="open debug"
onClick={() => {
store.isExpanded = true;
}}
>
{store.isExpanded ? ( {store.isExpanded ? (
<i className="fas fa-times"></i> <i className="fas fa-times"></i>
) : ( ) : (
@ -210,15 +261,7 @@ const AMISDebug = observer(({store}: {store: AMISDebugStore}) => {
)} )}
</div> </div>
<div className={cx('AMISDebug-content')}> <div className={cx('AMISDebug-content')}>
<div <div className="AMISDebug-close" title="Close" onClick={store.close}>
className="AMISDebug-close"
title="Close"
onClick={() => {
store.isExpanded = false;
store.activeId = '';
store.hoverId = '';
}}
>
<i className="fas fa-times" /> <i className="fas fa-times" />
</div> </div>
<div <div
@ -285,17 +328,48 @@ const AMISDebug = observer(({store}: {store: AMISDebugStore}) => {
) : null} ) : null}
{store.tab === 'inspect' ? ( {store.tab === 'inspect' ? (
<div className="AMISDebug-inspect"> <div className="AMISDebug-inspect">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 1024 1024"
className={`AMISDebug-inspectIcon ${
store.inspectMode ? 'is-active' : ''
}`}
onClick={store.toggleInspectMode}
>
<path d="M64 192L128 128h768l64 64v384H896v-384H128v512h320V768H128l-64-64v-512z m941.226667 621.226667L576 384v602.496l173.226667-173.226667h256zM640 832v-293.504l210.773333 210.773333h-128L640 832z" />
</svg>
{store.inspectMode ? (
<span>Select an element in the page to inspect it.</span>
) : (
<span>Click to inspect an element.</span>
)}
{activeId ? ( {activeId ? (
<> <>
<h3> <h3>
Component:{' '} Component:{' '}
<span className="primary">{activeComponentInspect.name}</span> <span className="primary">
{activeComponentInspect?.name}
</span>
</h3> </h3>
{stackDataView} {stackDataView}
</> </>
) : ( ) : null}
'Click component to display inspect' </div>
)} ) : null}
{activeId ? (
<div className="AMISDebug-footer">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 1024 1024"
>
<path
d="M724.48 521.728c-1.8432 7.7824-5.7344 14.848-11.3664 20.48l-341.9136 342.016c-16.6912 16.6912-43.7248 16.6912-60.3136 0s-16.6912-43.7248 0-60.3136L622.6944 512 310.8864 200.0896c-16.6912-16.6912-16.6912-43.7248 0-60.3136 16.6912-16.6912 43.7248-16.6912 60.3136 0l341.9136 341.9136c10.8544 10.8544 14.6432 26.112 11.3664 40.0384z"
fill="currentColor"
></path>
</svg>
<input type="text" placeholder="" onKeyUp={handleInputKeyUp} />
</div> </div>
) : null} ) : null}
</div> </div>
@ -307,7 +381,7 @@ const AMISDebug = observer(({store}: {store: AMISDebugStore}) => {
* *
*/ */
function handleMouseMove(e: MouseEvent) { function handleMouseMove(e: MouseEvent) {
if (!store.isExpanded) { if (!store.inspectMode) {
return; return;
} }
const dom = e.target as HTMLElement; const dom = e.target as HTMLElement;
@ -321,14 +395,16 @@ function handleMouseMove(e: MouseEvent) {
* *
*/ */
function handleMouseclick(e: MouseEvent) { function handleMouseclick(e: MouseEvent) {
if (!store.isExpanded) { if (!store.inspectMode) {
return; return;
} }
e.preventDefault();
const dom = e.target as HTMLElement; const dom = e.target as HTMLElement;
const target = dom.closest(`[data-debug-id]`); const target = dom.closest(`[data-debug-id]`);
if (target && !target.closest('.AMISDebug')) { if (target && !target.closest('.AMISDebug')) {
store.activeId = target.getAttribute('data-debug-id')!; store.activeId = target.getAttribute('data-debug-id')!;
store.tab = 'inspect'; store.tab = 'inspect';
store.inspectMode = false;
} }
} }
@ -337,6 +413,7 @@ const amisHoverBox = document.createElement('div');
amisHoverBox.className = 'AMISDebug-hoverBox'; amisHoverBox.className = 'AMISDebug-hoverBox';
const amisActiveBox = document.createElement('div'); const amisActiveBox = document.createElement('div');
amisActiveBox.className = 'AMISDebug-activeBox'; amisActiveBox.className = 'AMISDebug-activeBox';
let timer: ReturnType<typeof setTimeout> | null = null;
autorun(() => { autorun(() => {
const hoverId = store.hoverId; const hoverId = store.hoverId;
@ -366,6 +443,12 @@ autorun(() => {
amisActiveBox.style.left = `${offset.left}px`; amisActiveBox.style.left = `${offset.left}px`;
amisActiveBox.style.width = `${offset.width}px`; amisActiveBox.style.width = `${offset.width}px`;
amisActiveBox.style.height = `${offset.height}px`; amisActiveBox.style.height = `${offset.height}px`;
amisActiveBox.classList.add('shake');
clearTimeout(timer!);
timer = setTimeout(() => {
amisActiveBox.classList.remove('shake');
}, 500);
} else { } else {
amisActiveBox.style.top = '-999999px'; amisActiveBox.style.top = '-999999px';
} }
@ -403,7 +486,7 @@ export function enableDebug() {
document.body.appendChild(amisHoverBox); document.body.appendChild(amisHoverBox);
document.body.appendChild(amisActiveBox); document.body.appendChild(amisActiveBox);
document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('click', handleMouseclick); document.addEventListener('click', handleMouseclick, true);
} }
export function disableDebug() { export function disableDebug() {
@ -451,6 +534,12 @@ export class DebugWrapper extends Component<DebugWrapperProps> {
componentWillUnmount() { componentWillUnmount() {
delete ComponentInfo[this.debugId]; delete ComponentInfo[this.debugId];
if (this.debugId === store.activeId) {
store.activeId = '';
}
if (this.debugId === store.hoverId) {
store.hoverId = '';
}
} }
render() { render() {
@ -458,14 +547,22 @@ export class DebugWrapper extends Component<DebugWrapperProps> {
} }
} }
type Category = 'api' | 'event'; type Category = 'api' | 'event' | 'action' | 'debug' | 'error';
function parseJson(str: string) {
try {
return JSON.parse(str);
} catch (e) {
return e;
}
}
/** /**
* *
* @param msg * @param msg
* @param ext * @param ext
*/ */
export function debug(cat: Category, msg: string, ext?: object) { export function debug(cat: Category, msg: string, ext?: any) {
if (!isEnabled) { if (!isEnabled) {
return; return;
} }
@ -474,18 +571,11 @@ export function debug(cat: Category, msg: string, ext?: object) {
console.debug(ext); console.debug(ext);
console.groupEnd(); console.groupEnd();
let extStr = '';
try {
extStr = JSON.stringify(ext);
} catch (e) {
console.error(e);
}
const log = { const log = {
cat, cat,
level: 'debug', level: 'debug',
msg: msg, msg: msg,
ext: extStr ext: ext
}; };
store.logs.push(log); store.logs.push(log);
} }
@ -495,23 +585,16 @@ export function debug(cat: Category, msg: string, ext?: object) {
* @param msg * @param msg
* @param ext * @param ext
*/ */
export function warning(cat: Category, msg: string, ext?: object) { export function warning(cat: Category, msg: string, ext?: any) {
if (!isEnabled) { if (!isEnabled) {
return; return;
} }
let extStr = ''; const log: Log = {
try {
extStr = JSON.stringify(ext);
} catch (e) {
console.error(e);
}
const log = {
cat, cat,
level: 'warn', level: 'warn',
msg: msg, msg: msg,
ext: extStr ext: ext
}; };
console.groupCollapsed('amis debug', msg); console.groupCollapsed('amis debug', msg);

View File

@ -28,6 +28,7 @@ export * from './isPureVariable';
export * from './json-schema-2-amis-schema'; export * from './json-schema-2-amis-schema';
export * from './keyToPath'; export * from './keyToPath';
export * from './labelToString'; export * from './labelToString';
export * from './loopTooMuch';
export * from './makeSorter'; export * from './makeSorter';
export * from './normalizeLink'; export * from './normalizeLink';
export * from './normalizeOptions'; export * from './normalizeOptions';

View File

@ -0,0 +1,23 @@
const loopCount: {[key: string]: number} = {};
const loopTimer: {[key: string]: ReturnType<typeof setTimeout>} = {};
const loopResult: {[key: string]: boolean} = {};
export function loopTooMuch(key: string, maxSpeed = 20) {
if (loopResult[key]) {
return loopResult[key];
}
clearTimeout(loopTimer[key]);
loopTimer[key] = setTimeout(() => {
delete loopCount[key];
delete loopTimer[key];
}, 1000);
if (loopCount[key] && loopCount[key] > maxSpeed) {
loopResult[key] = true;
return true;
}
loopCount[key] = (loopCount[key] || 0) + 1;
return false;
}

View File

@ -35,28 +35,29 @@ export function position(node: HTMLElement, offsetParent?: HTMLElement) {
} }
if (nodeName(parent) !== 'html') parentOffset = getOffset(parent); if (nodeName(parent) !== 'html') parentOffset = getOffset(parent);
const parentStyle = getComputedStyle(parent);
const borderTop = String( const borderTop = String(
getComputedStyle(parent).getPropertyValue('border-top-width') || 0 parentStyle.getPropertyValue('border-top-width') || 0
); );
parentOffset.top += parseInt(borderTop, 10) - parent.scrollTop || 0; parentOffset.top += parseInt(borderTop, 10) - parent.scrollTop || 0;
const borderLeft = String( const borderLeft = String(
getComputedStyle(parent).getPropertyValue('border-left-width') || 0 parentStyle.getPropertyValue('border-left-width') || 0
); );
parentOffset.left += parseInt(borderLeft, 10) - parent.scrollLeft || 0; parentOffset.left += parseInt(borderLeft, 10) - parent.scrollLeft || 0;
} }
const marginTop = String( // const marginTop = String(
getComputedStyle(node).getPropertyValue('margin-top') || 0 // getComputedStyle(node).getPropertyValue('margin-top') || 0
); // );
const marginLeft = String( // const marginLeft = String(
getComputedStyle(node).getPropertyValue('margin-left') || 0 // getComputedStyle(node).getPropertyValue('margin-left') || 0
); // );
// Subtract parent offsets and node margins // Subtract parent offsets and node margins
return { return {
...offset, ...offset,
top: offset.top - parentOffset.top - (parseInt(marginTop, 10) || 0), top: offset.top - parentOffset.top /*- (parseInt(marginTop, 10) || 0)*/,
left: offset.left - parentOffset.left - (parseInt(marginLeft, 10) || 0) left: offset.left - parentOffset.left /* - (parseInt(marginLeft, 10) || 0)*/
}; };
} }

View File

@ -256,14 +256,16 @@ export const validations: {
}, },
isPhoneNumber: function (values, value) { isPhoneNumber: function (values, value) {
return ( return (
!isExisty(value) || isEmpty(value) || /^[1]([3-9])[0-9]{9}$/.test(value) !isExisty(value) ||
isEmpty(value) ||
/^(\+\d{2}-)?[1]([3-9])[0-9]{9}$/.test(value)
); );
}, },
isTelNumber: function (values, value) { isTelNumber: function (values, value) {
return ( return (
!isExisty(value) || !isExisty(value) ||
isEmpty(value) || isEmpty(value) ||
/^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/.test(value) /^(\+\d{2}-)?(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/.test(value)
); );
}, },
isZipcode: function (values, value) { isZipcode: function (values, value) {

View File

@ -27,8 +27,8 @@
}, },
"scripts": { "scripts": {
"test": "echo \"Warnings: no test specified\"", "test": "echo \"Warnings: no test specified\"",
"build": "npm run clean-dist && NODE_ENV=production rollup -c", "build": "npm run clean-dist && cross-env NODE_ENV=production rollup -c",
"build-esm": "npm run clean-dist && NODE_ENV=production rollup -c rollup.esm.config.js", "build-esm": "npm run clean-dist && cross-env NODE_ENV=production rollup -c rollup.esm.config.js",
"clean-dist": "rimraf lib/* esm/*", "clean-dist": "rimraf lib/* esm/*",
"i18n:update": "npx i18n update --config=./i18nConfig.js", "i18n:update": "npx i18n update --config=./i18nConfig.js",
"i18n:translate": "npx i18n translate --config=./i18nConfig.js --l=en-US", "i18n:translate": "npx i18n translate --config=./i18nConfig.js --l=en-US",
@ -60,6 +60,7 @@
"sortablejs": "^1.14.0" "sortablejs": "^1.14.0"
}, },
"devDependencies": { "devDependencies": {
"cross-env": "^7.0.3",
"@fortawesome/fontawesome-free": "^6.1.1", "@fortawesome/fontawesome-free": "^6.1.1",
"@rollup/plugin-commonjs": "^22.0.0", "@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-json": "^4.1.0", "@rollup/plugin-json": "^4.1.0",

View File

@ -50,8 +50,14 @@
width: 100%; width: 100%;
} }
} }
&-content-oldentry { &-header-m {
margin-top: 100px !important; margin-top: #{px2rem(45px)} !important;
}
&-content-m {
margin-top: #{px2rem(97px)} !important;
}
&-content-l {
margin-top: #{px2rem(150px)} !important;
} }
&-content { &-content {
padding: 0; padding: 0;
@ -192,13 +198,31 @@
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
.variable-left { .action-desc {
color: #2468f2; display: flex;
margin-left: #{px2rem(4px)}; .desc-tag {
} max-width: 133px;
.variable-right { color: #2468f2;
color: #2468f2; display: inline-block;
margin-right: #{px2rem(4px)}; margin-bottom: -5px;
}
.variable-left {
margin-left: #{px2rem(4px)};
}
.variable-right {
margin-right: #{px2rem(4px)};
}
.component-action-tag {
background-color: rgb(82, 142, 255);
display: inline-block;
color: #fff;
padding: 0 5px;
border-radius: 3px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
} }
} }
&--dragging { &--dragging {
@ -297,7 +321,7 @@
} }
} }
.action-config-dialog { .ae-action-config-dialog {
*:not(svg) { *:not(svg) {
font-size: 12px; font-size: 12px;
} }
@ -468,7 +492,7 @@
} }
} }
.event-item-header-tip { .ae-event-item-header-tip {
background: #070c14d9 !important; background: #070c14d9 !important;
box-shadow: 0 px2rem(2px) px2rem(8px) 0 rgba(7, 12, 20, 0.12); box-shadow: 0 px2rem(2px) px2rem(8px) 0 rgba(7, 12, 20, 0.12);
border: none; border: none;
@ -476,9 +500,6 @@
font-size: 12px; font-size: 12px;
color: #fff; color: #fff;
} }
}
.event-item-header-tip {
& > div { & > div {
&:after { &:after {
border-top-color: #070c14d9 !important; border-top-color: #070c14d9 !important;
@ -486,3 +507,9 @@
} }
} }
} }
.ae-action-relation-panel {
width: 255px;
max-height: 360px;
overflow: auto;
}

View File

@ -53,6 +53,7 @@
@import './style-control/size'; @import './style-control/size';
@import './style-control/style-common'; @import './style-control/style-common';
@import './style-control/theme-css-code'; @import './style-control/theme-css-code';
@import './style-control/single-theme-css-code';
@import './style-control/flex-layout'; @import './style-control/flex-layout';
@import './style-control/col-count'; @import './style-control/col-count';
@import './style-control/col-size'; @import './style-control/col-size';

View File

@ -0,0 +1,83 @@
.ae-SingleThemeCssCode {
position: relative;
border: 1px solid #e8e9eb;
border-radius: var(--input-default-default-top-left-border-radius)
var(--input-default-default-top-right-border-radius)
var(--input-default-default-bottom-right-border-radius)
var(--input-default-default-bottom-left-border-radius);
&-label {
margin-bottom: px2rem(10px);
color: #5c5f66;
font-size: 12px;
}
&-header,
&-footer {
padding: 0 4px;
}
&-content {
height: 120px;
}
&-button {
position: absolute;
top: 4px;
right: 12px;
z-index: 100;
}
&-icon {
cursor: pointer;
color: #5c5f66;
&:hover {
color: #151b26;
}
}
}
.ae-SingleThemeCssCode-custom-editor {
.suggest-widget {
width: auto !important;
left: 16px !important;
right: 0 !important;
.monaco-sash:first-child {
display: none;
}
}
}
.ae-SingleThemeCssCode-panel {
height: auto;
width: px2rem(460px);
padding: px2rem(16px);
position: relative;
&-title {
font-size: 14px;
margin-bottom: px2rem(16px);
}
&-close {
position: absolute;
top: px2rem(14px);
right: px2rem(16px);
button {
height: px2rem(16px);
padding: 0;
margin: 0;
}
}
&-content {
height: px2rem(500px);
width: 100%;
border: 1px solid #e8e9eb;
.ae-SingleThemeCssCode-content {
height: px2rem(454px);
}
}
}

View File

@ -17,6 +17,7 @@ import Breadcrumb from './Breadcrumb';
import {destroy, isAlive} from 'mobx-state-tree'; import {destroy, isAlive} from 'mobx-state-tree';
import {ScaffoldModal} from './ScaffoldModal'; import {ScaffoldModal} from './ScaffoldModal';
import {PopOverForm} from './PopOverForm'; import {PopOverForm} from './PopOverForm';
import {ModalForm} from './ModalForm';
import {ContextMenuPanel} from './Panel/ContextMenuPanel'; import {ContextMenuPanel} from './Panel/ContextMenuPanel';
import {LeftPanels} from './Panel/LeftPanels'; import {LeftPanels} from './Panel/LeftPanels';
import {RightPanels} from './Panel/RightPanels'; import {RightPanels} from './Panel/RightPanels';
@ -143,6 +144,11 @@ export interface EditorProps extends PluginEventListener {
getAvaiableContextFields?: (node: EditorNodeType) => Promise<any>; getAvaiableContextFields?: (node: EditorNodeType) => Promise<any>;
readonly?: boolean; readonly?: boolean;
onEditorMount?: (manager: EditorManager) => void;
onEditorUnmount?: (manager: EditorManager) => void;
children?: React.ReactNode | ((manager: EditorManager) => React.ReactNode);
} }
export default class Editor extends Component<EditorProps> { export default class Editor extends Component<EditorProps> {
@ -170,6 +176,7 @@ export default class Editor extends Component<EditorProps> {
showCustomRenderersPanel, showCustomRenderersPanel,
superEditorData, superEditorData,
hostManager, hostManager,
onEditorMount,
...rest ...rest
} = props; } = props;
@ -225,6 +232,8 @@ export default class Editor extends Component<EditorProps> {
this.toDispose.push( this.toDispose.push(
this.manager.on('preview2editor', () => this.manager.rebuild()) this.manager.on('preview2editor', () => this.manager.rebuild())
); );
onEditorMount?.(this.manager);
} }
componentDidMount() { componentDidMount() {
@ -268,6 +277,7 @@ export default class Editor extends Component<EditorProps> {
} }
componentWillUnmount() { componentWillUnmount() {
this.props.onEditorUnmount?.(this.manager);
document.removeEventListener('keydown', this.handleKeyDown); document.removeEventListener('keydown', this.handleKeyDown);
window.removeEventListener('message', this.handleMessage); window.removeEventListener('message', this.handleMessage);
this.toDispose.forEach(fn => fn()); this.toDispose.forEach(fn => fn());
@ -588,7 +598,8 @@ export default class Editor extends Component<EditorProps> {
autoFocus, autoFocus,
isSubEditor, isSubEditor,
amisEnv, amisEnv,
readonly readonly,
children
} = this.props; } = this.props;
return ( return (
@ -662,6 +673,8 @@ export default class Editor extends Component<EditorProps> {
)} )}
{!preview && <ContextMenuPanel store={this.store} />} {!preview && <ContextMenuPanel store={this.store} />}
{typeof children === 'function' ? children(this.manager) : children}
</div> </div>
<SubEditor <SubEditor
@ -677,6 +690,7 @@ export default class Editor extends Component<EditorProps> {
theme={theme} theme={theme}
/> />
<PopOverForm store={this.store} manager={this.manager} theme={theme} /> <PopOverForm store={this.store} manager={this.manager} theme={theme} />
<ModalForm store={this.store} manager={this.manager} theme={theme} />
</div> </div>
); );
} }

View File

@ -0,0 +1,161 @@
import React from 'react';
import {EditorManager} from '../manager';
import {EditorStoreType} from '../store/editor';
import {
render,
Modal,
getTheme,
Icon,
Spinner,
Button,
Overlay,
PopOver,
Drawer
} from 'amis';
import {observer} from 'mobx-react';
import {diff} from '../util';
import {autobind, createObject} from 'amis-core';
export interface ModalFormProps {
store: EditorStoreType;
manager: EditorManager;
theme?: string;
}
@observer
export class ModalForm extends React.Component<ModalFormProps> {
@autobind
async handleConfirmClick() {
const form = this.amisScope?.getComponents()[0];
if (!form) {
return;
}
const {store} = this.props;
const modalFormContext = store.modalForm!;
try {
store.markModalFormBuzy(true);
const newValue = await form.doAction(
{
type: 'submit'
},
form.props.data,
true
);
modalFormContext.callback?.(
newValue,
diff(modalFormContext.value, newValue)
);
store.closeModalForm();
} catch (e) {
console.error(e.stack);
store.setModalFormError(e.message);
}
store.markModalFormBuzy(false);
}
amisScope: any;
@autobind
scopeRef(scoped: any) {
this.amisScope = scoped;
}
buildSchema() {
const {store} = this.props;
const modalFormContext = store.modalForm!;
return {
type: 'form',
wrapWithPanel: false,
mode: 'normal',
wrapperComponent: 'div',
initApi: modalFormContext.initApi,
api: modalFormContext.api,
body: modalFormContext.body,
submitOnChange: false,
autoFocus: true
};
}
render() {
const {store, theme, manager} = this.props;
const modalFormContext = store.modalForm;
const modalMode = store.modalMode || 'dialog';
const contents = modalFormContext
? render(
this.buildSchema(),
{
data: createObject(store.ctx, modalFormContext?.value),
manager,
scopeRef: this.scopeRef
},
{
...manager.env,
session: 'modal-form',
theme: theme
}
)
: null;
return modalMode === 'drawer' ? (
<Drawer
position={(modalFormContext?.postion as any) || 'left'}
size={modalFormContext?.size || 'md'}
theme={theme}
show={!!modalFormContext}
onHide={store.closeModalForm}
>
<div className="cxd-Drawer-header">{modalFormContext?.title}</div>
<div className="cxd-Drawer-body">{contents}</div>
<div className="cxd-Drawer-footer">
<div className="cxd-Drawer-info">
{store.modalFormError ? (
<div className="cxd-Drawer-error">{store.modalFormError}</div>
) : null}
</div>
<Button
disabled={store.modalFormBuzy}
level="primary"
onClick={this.handleConfirmClick}
>
</Button>
<Button onClick={store.closeModalForm}></Button>
</div>
</Drawer>
) : (
<Modal
theme={theme}
size={modalFormContext?.size || 'md'}
show={!!modalFormContext}
onHide={store.closeModalForm}
closeOnEsc={false}
>
{modalFormContext?.title ? (
<Modal.Header onClose={store.closeModalForm}>
{modalFormContext.title}
</Modal.Header>
) : null}
<Modal.Body>{contents}</Modal.Body>
<Modal.Footer>
<div className="cxd-Dialog-info">
{store.modalFormError ? (
<div className="cxd-Dialog-error">{store.modalFormError}</div>
) : null}
</div>
<Button
disabled={store.modalFormBuzy}
level="primary"
onClick={this.handleConfirmClick}
>
</Button>
<Button onClick={store.closeModalForm}></Button>
</Modal.Footer>
</Modal>
);
}
}

View File

@ -22,7 +22,7 @@ export class AvailableRenderersPanel extends React.Component<
} }
render() { render() {
const {store, manager} = this.props; const {store, manager, children} = this.props;
const renderersTabsKey = store.renderersTabsKey || 'base-renderers'; const renderersTabsKey = store.renderersTabsKey || 'base-renderers';
const curTheme = store.theme; const curTheme = store.theme;
const customRenderersByOrder = store.customRenderersByOrder || []; const customRenderersByOrder = store.customRenderersByOrder || [];
@ -33,6 +33,7 @@ export class AvailableRenderersPanel extends React.Component<
<div className="ae-RendererPanel"> <div className="ae-RendererPanel">
<div className="panel-header"></div> <div className="panel-header"></div>
<div className="ae-RendererPanel-content"> <div className="ae-RendererPanel-content">
{typeof children === 'function' ? children(this.props) : children}
{store.showCustomRenderersPanel && {store.showCustomRenderersPanel &&
customRenderersByOrder.length > 0 && ( customRenderersByOrder.length > 0 && (
<Tabs <Tabs

View File

@ -728,7 +728,11 @@ class SmartPreview extends React.Component<SmartPreviewProps> {
locale: appLocale, locale: appLocale,
editorDialogMountNode: this.getDialogMountRef editorDialogMountNode: this.getDialogMountRef
}, },
env {
...env,
session: editable ? 'edit-mode' : 'preview-mode',
enableAMISDebug: !editable
}
)} )}
</div> </div>
); );

View File

@ -0,0 +1,130 @@
import isPlainObject from 'lodash/isPlainObject';
/**
* splice
*
* false number
*
* @param target
* @param path
* @param numberToDelete
* @param items
* @returns
*/
export function deepSplice(
target: any,
path:
| string
| ((value: any, index: number | string, stack: Array<any>) => any),
numberToDelete: number,
provider?: ((origin: any) => any) | any,
...items: any[]
) {
if (typeof path === 'function') {
path = getPathByFunction(target, path);
}
if (!path) {
return target;
}
const paths = (path as string).split('.');
const last = paths.pop()!;
let host = target;
const stack: Array<{
host: any;
key: string | number | undefined;
}> = [];
for (let i = 0; i < paths.length; i++) {
stack.unshift({
key: paths[i]!,
host: host
});
host = host[paths[i]];
}
if (!Array.isArray(host)) {
throw new Error('deepSplice: target is not an array');
}
host = host.concat();
if (provider && typeof provider === 'function') {
host.splice.apply(
host,
[last, numberToDelete].concat(provider(host[last]))
);
} else {
host.splice.apply(host, [last, numberToDelete, provider].concat(items));
}
return stack.reduce((prefix, {host, key}) => {
host = Array.isArray(host) ? host.concat() : {...host};
host[key!] = prefix;
return host;
}, host);
}
function getPathByFunction(
target: any,
fn: (value: any, index: number | string, stack: Array<any>) => any
): string {
let paths: Array<string> = [];
let resolved: boolean = false;
let stack: Array<any> = [
{
path: '',
key: '',
stack: [],
data: target
}
];
while (stack.length) {
let cur = stack.shift()!;
let data = cur.data;
let path = cur.path;
let nodeStack = cur.stack;
let key = cur.key;
const result = fn(data, key, nodeStack);
if (result) {
resolved = true;
paths = path.split('.').filter((item: any) => item);
// apply offset
if (typeof result === 'number') {
paths[paths.length - 1] = (
parseInt(paths[paths.length - 1], 10) + result
).toString();
}
break;
}
if (Array.isArray(data)) {
// 注意 Object.keys 返回的 key 是字符串,所以这里要转换一下
data.forEach((prop, key) => {
stack.push({
path: `${path}.${key}`,
key: key,
stack: [data].concat(nodeStack),
data: prop
});
});
} else if (isPlainObject(data)) {
Object.keys(data).forEach(key => {
let prop = data[key];
stack.push({
path: `${path}.${key}`,
key: key,
stack: [data].concat(nodeStack),
data: prop
});
});
}
}
return resolved ? paths.join('.') : '';
}

View File

@ -42,6 +42,9 @@ import {UnknownRendererPlugin} from './plugin/Unknown';
import ShortcutKey from './component/base/ShortcutKey'; import ShortcutKey from './component/base/ShortcutKey';
import WidthDraggableContainer from './component/base/WidthDraggableContainer'; import WidthDraggableContainer from './component/base/WidthDraggableContainer';
import {SchemaFrom} from './component/base/SchemaForm'; import {SchemaFrom} from './component/base/SchemaForm';
import {RendererThumb} from './component/RendererThumb';
import {AvailableRenderersPanel} from './component/Panel/AvailableRenderersPanel';
import {deepSplice} from './deepSplice';
export const version = '__buildVersion'; export const version = '__buildVersion';
(window as any).amisEditorVersionInfo = { (window as any).amisEditorVersionInfo = {
@ -55,6 +58,7 @@ export {
Editor, Editor,
MiniEditor, MiniEditor,
utils, utils,
deepSplice,
mapReactElement, mapReactElement,
RendererEditor, RendererEditor,
BasicEditor, BasicEditor,
@ -68,6 +72,7 @@ export {
EditorStoreType, EditorStoreType,
ContainerWrapper, ContainerWrapper,
AvailableRenderersPlugin, AvailableRenderersPlugin,
AvailableRenderersPanel,
BasicToolbarPlugin, BasicToolbarPlugin,
CodePlugin, CodePlugin,
ErrorRendererPlugin, ErrorRendererPlugin,
@ -75,5 +80,6 @@ export {
UnknownRendererPlugin, UnknownRendererPlugin,
ShortcutKey, ShortcutKey,
SchemaFrom, SchemaFrom,
WidthDraggableContainer WidthDraggableContainer,
RendererThumb
}; };

View File

@ -9,7 +9,12 @@ import debounce from 'lodash/debounce';
import findIndex from 'lodash/findIndex'; import findIndex from 'lodash/findIndex';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
import {openContextMenus, toast, alert, DataScope, DataSchema} from 'amis'; import {openContextMenus, toast, alert, DataScope, DataSchema} from 'amis';
import {getRenderers, RenderOptions, JSONTraverse} from 'amis-core'; import {
getRenderers,
RenderOptions,
JSONTraverse,
wrapFetcher
} from 'amis-core';
import { import {
PluginInterface, PluginInterface,
BasicPanelItem, BasicPanelItem,
@ -69,7 +74,7 @@ import {VariableManager} from './variable';
import type {IScopedContext} from 'amis'; import type {IScopedContext} from 'amis';
import type {SchemaObject, SchemaCollection} from 'amis'; import type {SchemaObject, SchemaCollection} from 'amis';
import type {RendererConfig} from 'amis-core'; import type {Api, Payload, RendererConfig, RendererEnv} from 'amis-core';
import {loadAsyncRenderer} from 'amis-core'; import {loadAsyncRenderer} from 'amis-core';
export interface EditorManagerConfig export interface EditorManagerConfig
@ -215,6 +220,7 @@ export class EditorManager {
/** 变量管理 */ /** 变量管理 */
readonly variableManager; readonly variableManager;
fetch?: (api: Api, data?: any, options?: object) => Promise<Payload>;
constructor( constructor(
readonly config: EditorManagerConfig, readonly config: EditorManagerConfig,
@ -223,10 +229,17 @@ export class EditorManager {
) { ) {
// 传给 amis 渲染器的默认 env // 传给 amis 渲染器的默认 env
this.env = { this.env = {
...env, // 默认的 env 中带 jumpTo ...(env as any), // 默认的 env 中带 jumpTo
...omit(config.amisEnv, 'replaceText'), // 用户也可以设置自定义环境配置,用于覆盖默认的 env ...omit(config.amisEnv, 'replaceText'), // 用户也可以设置自定义环境配置,用于覆盖默认的 env
theme: config.theme theme: config.theme!
}; };
// 内部统一使用 wrapFetcher 包装 fetcher
if (this.env.fetcher) {
this.env.fetcher = wrapFetcher(this.env.fetcher as any, this.env.tracker);
this.fetch = this.env.fetcher as any;
}
this.env.beforeDispatchEvent = this.beforeDispatchEvent.bind( this.env.beforeDispatchEvent = this.beforeDispatchEvent.bind(
this, this,
this.env.beforeDispatchEvent this.env.beforeDispatchEvent
@ -1837,8 +1850,11 @@ export class EditorManager {
this.dnd.startDrag(id, e.nativeEvent); this.dnd.startDrag(id, e.nativeEvent);
} }
async scaffold(form: any, value: any): Promise<SchemaObject> { async scaffold(form: ScaffoldForm, value: any): Promise<SchemaObject> {
const scaffoldFormData = form.pipeIn ? await form.pipeIn(value) : value; const scaffoldFormData = form.pipeIn ? await form.pipeIn(value) : value;
if (form.getSchema) {
form = Object.assign({}, form, await form.getSchema(scaffoldFormData));
}
return new Promise(resolve => { return new Promise(resolve => {
this.store.openScaffoldForm({ this.store.openScaffoldForm({
@ -1857,7 +1873,7 @@ export class EditorManager {
// 根据元素ID实时拿取上下文数据 // 根据元素ID实时拿取上下文数据
async reScaffoldV2(id: string) { async reScaffoldV2(id: string) {
const commonContext = this.buildEventContext(id); const commonContext = this.buildEventContext(id);
const scaffoldForm = commonContext.info?.scaffoldForm; const scaffoldForm = commonContext.info?.scaffoldForm!;
const curSchema = commonContext.schema; const curSchema = commonContext.schema;
const replaceWith = await this.scaffold(scaffoldForm, curSchema); const replaceWith = await this.scaffold(scaffoldForm, curSchema);
this.replaceChild(id, replaceWith); this.replaceChild(id, replaceWith);

View File

@ -335,6 +335,9 @@ export interface PopOverForm {
* @deprecated body * @deprecated body
*/ */
controls?: Array<any>; controls?: Array<any>;
initApi?: any;
api?: any;
} }
export interface ScaffoldForm extends PopOverForm { export interface ScaffoldForm extends PopOverForm {
@ -342,6 +345,7 @@ export interface ScaffoldForm extends PopOverForm {
stepsBody?: boolean; stepsBody?: boolean;
/** 是否可跳过创建向导直接创建 */ /** 是否可跳过创建向导直接创建 */
canSkip?: boolean; canSkip?: boolean;
getSchema?: (value: any) => PopOverForm | Promise<PopOverForm>;
mode?: mode?:
| 'normal' | 'normal'
| 'horizontal' | 'horizontal'
@ -453,6 +457,7 @@ export interface PanelProps {
manager: EditorManager; manager: EditorManager;
popOverContainer?: () => HTMLElement | void; popOverContainer?: () => HTMLElement | void;
readonly?: boolean; readonly?: boolean;
children?: React.ReactNode | ((props: PanelProps) => React.ReactNode);
} }
/** /**

View File

@ -122,6 +122,14 @@ export interface PopOverFormContext extends PopOverForm {
node?: EditorNodeType; node?: EditorNodeType;
} }
export interface ModalFormContext extends PopOverForm {
mode?: 'dialog' | 'drawer';
size?: string;
postion?: string;
value: any;
callback: (value: any, diff: any) => void;
}
/** /**
* name * name
*/ */
@ -233,6 +241,12 @@ export const MainStore = types
popOverForm: types.maybe(types.frozen<PopOverFormContext>()), popOverForm: types.maybe(types.frozen<PopOverFormContext>()),
// 弹出层表单
modalForm: types.maybe(types.frozen<ModalFormContext>()),
modalMode: '',
modalFormBuzy: false,
modalFormError: '',
// 弹出子编辑器相关的信息 // 弹出子编辑器相关的信息
subEditorContext: types.maybe(types.frozen<SubEditorContext>()), subEditorContext: types.maybe(types.frozen<SubEditorContext>()),
// 子编辑器中可能需要拿到父编辑器的数据 // 子编辑器中可能需要拿到父编辑器的数据
@ -278,6 +292,10 @@ export const MainStore = types
return false; return false;
}, },
get rootId() {
return this.getRootId();
},
getRootId() { getRootId() {
const curSchema = this.getSchema(); const curSchema = this.getSchema();
return curSchema?.$$id; return curSchema?.$$id;
@ -2105,6 +2123,24 @@ export const MainStore = types
self.popOverForm = undefined; self.popOverForm = undefined;
}, },
openModalForm(context: ModalFormContext) {
self.modalForm = context;
self.modalMode = context?.mode || self.modalMode;
self.modalFormError = '';
},
closeModalForm() {
self.modalForm = undefined;
},
markModalFormBuzy(value: any) {
self.modalFormBuzy = !!value;
},
setModalFormError(msg: string = '') {
self.modalFormError = msg;
},
activeHighlightNodes(ids: Array<string>) { activeHighlightNodes(ids: Array<string>) {
ids.forEach(id => { ids.forEach(id => {
const node = self.getNodeById(id); const node = self.getNodeById(id);

View File

@ -21,8 +21,8 @@
}, },
"scripts": { "scripts": {
"test": "echo \"Warnings: no test specified\"", "test": "echo \"Warnings: no test specified\"",
"build": "npm run clean-dist && NODE_ENV=production rollup -c ", "build": "npm run clean-dist && cross-env NODE_ENV=production rollup -c ",
"build-esm": "npm run clean-dist && NODE_ENV=production rollup -c rollup.esm.config.js", "build-esm": "npm run clean-dist && cross-env NODE_ENV=production rollup -c rollup.esm.config.js",
"clean-dist": "rimraf lib/** esm/**", "clean-dist": "rimraf lib/** esm/**",
"i18n:update": "npx i18n update --config=./i18nConfig.js", "i18n:update": "npx i18n update --config=./i18nConfig.js",
"i18n:translate": "npx i18n translate --config=./i18nConfig.js --l=en-US", "i18n:translate": "npx i18n translate --config=./i18nConfig.js --l=en-US",
@ -49,6 +49,7 @@
"mobx-state-tree": "^3.17.3" "mobx-state-tree": "^3.17.3"
}, },
"devDependencies": { "devDependencies": {
"cross-env": "^7.0.3",
"@fortawesome/fontawesome-free": "^6.1.1", "@fortawesome/fontawesome-free": "^6.1.1",
"@rollup/plugin-commonjs": "^22.0.0", "@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-json": "^4.1.0", "@rollup/plugin-json": "^4.1.0",

View File

@ -3,12 +3,11 @@
*/ */
import flatten from 'lodash/flatten'; import flatten from 'lodash/flatten';
import { import {NO_SUPPORT_STATIC_FORMITEM_CMPTS} from '../renderer/event-control/constants';
getEventControlConfig, import {getEventControlConfig} from '../renderer/event-control/helper';
SUPPORT_STATIC_FORMITEM_CMPTS
} from '../renderer/event-control/helper';
import {getSchemaTpl, isObject, tipedLabel} from 'amis-editor-core'; import {getSchemaTpl, isObject, tipedLabel} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core'; import type {BaseEventContext} from 'amis-editor-core';
import {getRendererByName} from 'amis-core';
// 默认动作 // 默认动作
export const BUTTON_DEFAULT_ACTION = { export const BUTTON_DEFAULT_ACTION = {
@ -199,7 +198,9 @@ export const formItemControl: (
context?: BaseEventContext context?: BaseEventContext
) => Array<any> = (panels, context) => { ) => Array<any> = (panels, context) => {
const type = context?.schema?.type || ''; const type = context?.schema?.type || '';
const supportStatic = SUPPORT_STATIC_FORMITEM_CMPTS.includes(type); const render = getRendererByName(type);
const supportStatic =
!!render?.isFormItem && !NO_SUPPORT_STATIC_FORMITEM_CMPTS.includes(type);
const collapseProps = { const collapseProps = {
type: 'collapse', type: 'collapse',
headingClassName: 'ae-formItemControl-header ae-Collapse-header', headingClassName: 'ae-formItemControl-header ae-Collapse-header',

View File

@ -5,6 +5,8 @@ export * from './builder';
import './tpl/index'; import './tpl/index';
export * from './plugin'; export * from './plugin';
export * from './validator'; export * from './validator';
export * from './renderer/event-control/actionsPanelManager';
export * from './renderer/event-control/helper';
import './renderer/OptionControl'; import './renderer/OptionControl';
import './renderer/ValueFormatControl'; import './renderer/ValueFormatControl';
@ -45,6 +47,7 @@ import './renderer/event-control/index';
import './renderer/TreeOptionControl'; import './renderer/TreeOptionControl';
import './renderer/TransferTableControl'; import './renderer/TransferTableControl';
import './renderer/style-control/ThemeCssCode'; import './renderer/style-control/ThemeCssCode';
import './renderer/style-control/SingleThemeCssCode';
import './renderer/style-control/ColCount'; import './renderer/style-control/ColCount';
import './renderer/style-control/ColSize'; import './renderer/style-control/ColSize';
import './renderer/style-control/LabelAlign'; import './renderer/style-control/LabelAlign';

View File

@ -80,6 +80,7 @@ export class AnchorNavPlugin extends BasePlugin {
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
{ {
title: '基本', title: '基本',
id: 'properties-basic',
body: [ body: [
getSchemaTpl('layout:originPosition', {value: 'left-top'}), getSchemaTpl('layout:originPosition', {value: 'left-top'}),
getSchemaTpl('combo-container', { getSchemaTpl('combo-container', {
@ -163,6 +164,7 @@ export class AnchorNavPlugin extends BasePlugin {
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
{ {
title: '基本', title: '基本',
id: 'appearance-basic',
body: [ body: [
{ {
type: 'button-group-select', type: 'button-group-select',

View File

@ -204,6 +204,7 @@ export class ButtonPlugin extends BasePlugin {
formType: 'extend', formType: 'extend',
mode: 'normal', mode: 'normal',
label: '气泡提示', label: '气泡提示',
id: 'button-tooltip', //便于扩充定位
hidden: isInDropdown, hidden: isInDropdown,
form: { form: {
body: [ body: [
@ -351,11 +352,16 @@ export class ButtonPlugin extends BasePlugin {
...buttonStateFunc("${__editorState == 'active'}", 'active') ...buttonStateFunc("${__editorState == 'active'}", 'active')
] ]
}, },
getSchemaTpl('theme:cssCode', { getSchemaTpl('theme:singleCssCode', {
themeClass: [ selectors: [
{ {
value: '', label: '按钮基本样式',
state: ['default', 'hover', 'active'] isRoot: true,
selector: '.cxd-Button'
},
{
label: '按钮内容样式',
selector: 'span'
} }
] ]
}) })

View File

@ -1,7 +1,10 @@
import {toast, normalizeApiResponseData} from 'amis'; import {toast, normalizeApiResponseData} from 'amis';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import React from 'react'; import React from 'react';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
import {genCodeSchema} from '../renderer/APIAdaptorControl'; import {genCodeSchema} from '../renderer/APIAdaptorControl';
import { import {
getI18nEnabled, getI18nEnabled,
@ -20,12 +23,12 @@ import {
RendererEventContext, RendererEventContext,
RendererInfoResolveEventContext, RendererInfoResolveEventContext,
ScaffoldForm, ScaffoldForm,
SubRendererInfo SubRendererInfo,
defaultValue,
getSchemaTpl,
JSONPipeIn
} from 'amis-editor-core'; } from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; import {setVariable, someTree, normalizeApi} from 'amis-core';
import {isObject, JSONPipeIn} from 'amis-editor-core';
import {setVariable, someTree} from 'amis-core';
import type {ActionSchema} from 'amis';
import type {CRUDCommonSchema} from 'amis'; import type {CRUDCommonSchema} from 'amis';
import {getEnv} from 'mobx-state-tree'; import {getEnv} from 'mobx-state-tree';
import type { import type {
@ -33,7 +36,6 @@ import type {
RendererPluginAction, RendererPluginAction,
RendererPluginEvent RendererPluginEvent
} from 'amis-editor-core'; } from 'amis-editor-core';
import {normalizeApi} from 'amis-core';
import isPlainObject from 'lodash/isPlainObject'; import isPlainObject from 'lodash/isPlainObject';
import findLastIndex from 'lodash/findLastIndex'; import findLastIndex from 'lodash/findLastIndex';
@ -367,12 +369,14 @@ export class CRUDPlugin extends BasePlugin {
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionLabel: '变量赋值', actionLabel: '变量赋值',
actionType: 'setValue', actionType: 'setValue',
description: '更新列表记录' description: '更新列表记录',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -30,9 +30,10 @@ import {
} from '../../builder'; } from '../../builder';
import { import {
getEventControlConfig, getEventControlConfig,
getArgsWrapper getArgsWrapper,
getActionCommonProps
} from '../../renderer/event-control/helper'; } from '../../renderer/event-control/helper';
import {CRUD2Schema} from 'amis/lib/renderers/CRUD2'; import {CRUD2Schema} from 'amis';
import {deepRemove, findObj, findSchema} from './utils'; import {deepRemove, findObj, findSchema} from './utils';
import { import {
ToolsConfig, ToolsConfig,
@ -113,9 +114,9 @@ export class BaseCRUDPlugin extends BasePlugin {
actionType: 'search', actionType: 'search',
actionLabel: '数据查询', actionLabel: '数据查询',
description: '使用指定条件完成列表数据查询', description: '使用指定条件完成列表数据查询',
descDetail: (info: any) => { descDetail: (info: any, context: any, props: any) => {
return ( return (
<div> <div className="action-desc">
<span className="variable-right">{info?.__rendererLabel}</span> <span className="variable-right">{info?.__rendererLabel}</span>
</div> </div>
@ -134,9 +135,9 @@ export class BaseCRUDPlugin extends BasePlugin {
actionType: 'loadMore', actionType: 'loadMore',
actionLabel: '加载更多', actionLabel: '加载更多',
description: '加载更多条数据到列表容器', description: '加载更多条数据到列表容器',
descDetail: (info: any) => { descDetail: (info: any, context: any, props: any) => {
return ( return (
<div> <div className="action-desc">
<span className="variable-right">{info?.__rendererLabel}</span> <span className="variable-right">{info?.__rendererLabel}</span>
</div> </div>
@ -156,7 +157,8 @@ export class BaseCRUDPlugin extends BasePlugin {
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
...(actions || []) ...(actions || [])
], ],

View File

@ -1,9 +1,15 @@
import {registerEditorPlugin, RendererPluginEvent} from 'amis-editor-core'; import {
import {BaseEventContext, BasePlugin, tipedLabel} from 'amis-editor-core'; registerEditorPlugin,
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; RendererPluginEvent,
import {getEventControlConfig} from '../renderer/event-control'; BaseEventContext,
BasePlugin,
getSchemaTpl
} from 'amis-editor-core';
import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control';
import {FormulaDateType} from '../renderer/FormulaControl'; import {FormulaDateType} from '../renderer/FormulaControl';
import type {Schema} from 'amis';
export class CalendarPlugin extends BasePlugin { export class CalendarPlugin extends BasePlugin {
static id = 'CalendarPlugin'; static id = 'CalendarPlugin';
@ -126,17 +132,20 @@ export class CalendarPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空' description: '清空',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -12,7 +12,10 @@ import {
RendererPluginEvent, RendererPluginEvent,
tipedLabel tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
const ChartConfigEditor = ({value, onChange}: any) => { const ChartConfigEditor = ({value, onChange}: any) => {
return ( return (
@ -181,12 +184,14 @@ export class ChartPlugin extends BasePlugin {
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '变量赋值', actionLabel: '变量赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
// 特性动作太多了,这里先不加了,可以通过写代码配置 // 特性动作太多了,这里先不加了,可以通过写代码配置
]; ];

View File

@ -1,12 +1,17 @@
import React from 'react';
import { import {
RendererPluginAction, RendererPluginAction,
RendererPluginEvent, RendererPluginEvent,
getI18nEnabled, getI18nEnabled,
registerEditorPlugin registerEditorPlugin,
BasePlugin,
RegionConfig,
BaseEventContext,
defaultValue,
getSchemaTpl
} from 'amis-editor-core'; } from 'amis-editor-core';
import {BasePlugin, RegionConfig, BaseEventContext} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {getEventControlConfig} from '../renderer/event-control/helper';
import {getActionCommonProps} from '../renderer/event-control/helper';
export class CollapsePlugin extends BasePlugin { export class CollapsePlugin extends BasePlugin {
static id = 'CollapsePlugin'; static id = 'CollapsePlugin';
@ -114,12 +119,21 @@ export class CollapsePlugin extends BasePlugin {
{ {
actionType: 'expand', actionType: 'expand',
actionLabel: '组件展开', actionLabel: '组件展开',
description: '组件折叠状态变更为展开' description: '组件折叠状态变更为展开',
descDetail: (info: any, context: any, props: any) => {
return (
<div className="action-desc">
<span className="variable-right">{info?.rendererLabel}</span>
</div>
);
}
}, },
{ {
actionLabel: '组件收起', actionLabel: '组件收起',
actionType: 'collapse', actionType: 'collapse',
description: '组件折叠状态变更为收起' description: '组件折叠状态变更为收起',
...getActionCommonProps('collapse')
} }
]; ];

View File

@ -27,6 +27,7 @@ export class CollapseGroupPlugin extends BasePlugin {
pluginIcon = 'collapse-plugin'; pluginIcon = 'collapse-plugin';
scaffold = { scaffold = {
type: 'collapse-group', type: 'collapse-group',
enableFieldSetStyle: true,
activeKey: ['1'], activeKey: ['1'],
body: [ body: [
{ {
@ -101,6 +102,7 @@ export class CollapseGroupPlugin extends BasePlugin {
panelJustify = true; panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isInForm = context.path.includes('/form/');
const i18nEnabled = getI18nEnabled(); const i18nEnabled = getI18nEnabled();
return [ return [
getSchemaTpl('tabs', [ getSchemaTpl('tabs', [
@ -111,6 +113,22 @@ export class CollapseGroupPlugin extends BasePlugin {
title: '基本', title: '基本',
body: [ body: [
getSchemaTpl('layout:originPosition', {value: 'left-top'}), getSchemaTpl('layout:originPosition', {value: 'left-top'}),
{
name: 'enableFieldSetStyle',
label: '展示风格',
visible: isInForm,
type: 'button-group-select',
options: [
{
label: '默认',
value: false
},
{
label: '简洁',
value: true
}
]
},
{ {
name: 'expandIconPosition', name: 'expandIconPosition',
label: '图标位置', label: '图标位置',

View File

@ -18,7 +18,10 @@ import {
ChangeEventContext, ChangeEventContext,
JSONPipeOut JSONPipeOut
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
import type {RendererConfig, Schema} from 'amis-core'; import type {RendererConfig, Schema} from 'amis-core';
import {ModalProps} from 'amis-ui/lib/components/Modal'; import {ModalProps} from 'amis-ui/lib/components/Modal';
@ -119,7 +122,8 @@ export class DialogPlugin extends BasePlugin {
{ {
actionType: 'confirm', actionType: 'confirm',
actionLabel: '确认', actionLabel: '确认',
description: '触发弹窗确认操作' description: '触发弹窗确认操作',
descDetail: (info: any) => <div></div>
}, },
{ {
actionType: 'cancel', actionType: 'cancel',
@ -129,7 +133,8 @@ export class DialogPlugin extends BasePlugin {
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '变量赋值', actionLabel: '变量赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,3 +1,4 @@
import React from 'react';
import { import {
registerEditorPlugin, registerEditorPlugin,
BaseEventContext, BaseEventContext,
@ -12,7 +13,10 @@ import {
getI18nEnabled, getI18nEnabled,
JSONPipeOut JSONPipeOut
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
import {tipedLabel} from 'amis-editor-core'; import {tipedLabel} from 'amis-editor-core';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
import {InlineModal} from './Dialog'; import {InlineModal} from './Dialog';
@ -100,7 +104,8 @@ export class DrawerPlugin extends BasePlugin {
{ {
actionType: 'confirm', actionType: 'confirm',
actionLabel: '确认', actionLabel: '确认',
description: '触发抽屉确认操作' description: '触发抽屉确认操作',
descDetail: (info: any) => <div></div>
}, },
{ {
actionType: 'cancel', actionType: 'cancel',
@ -110,7 +115,8 @@ export class DrawerPlugin extends BasePlugin {
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '变量赋值', actionLabel: '变量赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,20 +1,22 @@
import { import {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
registerEditorPlugin registerEditorPlugin,
} from 'amis-editor-core'; BasePlugin,
import {BasePlugin, BaseEventContext} from 'amis-editor-core'; BaseEventContext,
import {
RendererPluginAction, RendererPluginAction,
RendererPluginEvent, RendererPluginEvent,
tipedLabel tipedLabel,
getSchemaTpl,
defaultValue
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getSchemaTpl, defaultValue} from 'amis-editor-core'; import type {Schema} from 'amis';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util'; import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import type {Schema} from 'amis';
export class ButtonGroupControlPlugin extends BasePlugin { export class ButtonGroupControlPlugin extends BasePlugin {
static id = 'ButtonGroupControlPlugin'; static id = 'ButtonGroupControlPlugin';
@ -95,22 +97,26 @@ export class ButtonGroupControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,23 +1,21 @@
import { import {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
registerEditorPlugin registerEditorPlugin,
} from 'amis-editor-core';
import {
BasePlugin, BasePlugin,
BaseEventContext, BaseEventContext,
BasicSubRenderInfo,
RendererEventContext,
SubRendererInfo,
RendererPluginAction, RendererPluginAction,
RendererPluginEvent, RendererPluginEvent,
tipedLabel, tipedLabel,
getSchemaTpl, getSchemaTpl,
defaultValue defaultValue
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {resolveOptionEventDataSchame} from '../../util'; import {resolveOptionEventDataSchame} from '../../util';
import {inputStateTpl} from '../../renderer/style-control/helper'; import {inputStateTpl} from '../../renderer/style-control/helper';
@ -84,22 +82,26 @@ export class ChainedSelectControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -2,26 +2,24 @@ import {
defaultValue, defaultValue,
setSchemaTpl, setSchemaTpl,
getSchemaTpl, getSchemaTpl,
valuePipeOut,
undefinedPipeOut, undefinedPipeOut,
EditorNodeType, EditorNodeType,
EditorManager EditorManager,
registerEditorPlugin,
BasePlugin,
BaseEventContext,
tipedLabel,
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core'; } from 'amis-editor-core';
import {isPureVariable} from 'amis'; import {isPureVariable} from 'amis';
import {registerEditorPlugin} from 'amis-editor-core';
import {
BasePlugin,
BasicSubRenderInfo,
RendererEventContext,
SubRendererInfo,
BaseEventContext,
tipedLabel
} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
import {inputStateTpl} from '../../renderer/style-control/helper'; import {inputStateTpl} from '../../renderer/style-control/helper';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
setSchemaTpl('option', { setSchemaTpl('option', {
name: 'option', name: 'option',
@ -105,17 +103,20 @@ export class CheckboxControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {

View File

@ -5,21 +5,22 @@ import {
valuePipeOut, valuePipeOut,
EditorNodeType, EditorNodeType,
EditorManager, EditorManager,
undefinedPipeOut undefinedPipeOut,
} from 'amis-editor-core'; RendererPluginAction,
import {registerEditorPlugin} from 'amis-editor-core'; RendererPluginEvent,
import {
BasePlugin, BasePlugin,
BasicSubRenderInfo, BasicSubRenderInfo,
RendererEventContext, RendererEventContext,
SubRendererInfo, SubRendererInfo,
BaseEventContext BaseEventContext,
registerEditorPlugin
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import { import {
OPTION_EDIT_EVENTS, OPTION_EDIT_EVENTS,
resolveOptionEventDataSchame, resolveOptionEventDataSchame,
@ -109,22 +110,26 @@ export class CheckboxesControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
panelJustify = true; panelJustify = true;
@ -192,6 +197,7 @@ export class CheckboxesControlPlugin extends BasePlugin {
}, },
{ {
title: '选项', title: '选项',
id: 'properties-options',
body: [ body: [
getSchemaTpl('optionControlV2', { getSchemaTpl('optionControlV2', {
multiple: true multiple: true

View File

@ -1,12 +1,17 @@
import {EditorAvailableLanguages as availableLanguages} from 'amis'; import {EditorAvailableLanguages as availableLanguages} from 'amis';
import {defaultValue, getSchemaTpl, undefinedPipeOut} from 'amis-editor-core'; import {
import {registerEditorPlugin} from 'amis-editor-core'; defaultValue,
import {BasePlugin} from 'amis-editor-core'; getSchemaTpl,
undefinedPipeOut,
registerEditorPlugin,
BasePlugin,
RendererPluginEvent,
RendererPluginAction
} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core'; import type {BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {RendererPluginEvent, RendererPluginAction} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {getEventControlConfig} from '../../renderer/event-control/helper';
import {getActionCommonProps} from '../../renderer/event-control/helper';
export class CodeEditorControlPlugin extends BasePlugin { export class CodeEditorControlPlugin extends BasePlugin {
static id = 'CodeEditorControlPlugin'; static id = 'CodeEditorControlPlugin';
@ -115,22 +120,26 @@ export class CodeEditorControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'focus', actionType: 'focus',
actionLabel: '获取焦点', actionLabel: '获取焦点',
description: '输入框获取焦点' description: '输入框获取焦点',
...getActionCommonProps('focus')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -18,7 +18,8 @@ import {DSBuilderManager} from '../../builder/DSBuilderManager';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import { import {
getArgsWrapper, getArgsWrapper,
getEventControlConfig getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper'; } from '../../renderer/event-control/helper';
import {resolveInputTableEventDataSchame} from '../../util'; import {resolveInputTableEventDataSchame} from '../../util';
@ -249,12 +250,14 @@ export class ComboControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'addItem', actionType: 'addItem',
@ -292,7 +295,8 @@ export class ComboControlPlugin extends BasePlugin {
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -3,15 +3,14 @@ import {
defaultValue, defaultValue,
getSchemaTpl, getSchemaTpl,
undefinedPipeOut, undefinedPipeOut,
valuePipeOut registerEditorPlugin,
BasePlugin
} from 'amis-editor-core'; } from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core'; import type {BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {getEventControlConfig} from '../../renderer/event-control/helper';
import {RendererPluginEvent, RendererPluginAction} from 'amis-editor-core'; import {RendererPluginEvent, RendererPluginAction} from 'amis-editor-core';
import {getActionCommonProps} from '../../renderer/event-control/helper';
export class DiffEditorControlPlugin extends BasePlugin { export class DiffEditorControlPlugin extends BasePlugin {
static id = 'DiffEditorControlPlugin'; static id = 'DiffEditorControlPlugin';
@ -122,22 +121,26 @@ export class DiffEditorControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'focus', actionType: 'focus',
actionLabel: '获取焦点', actionLabel: '获取焦点',
description: '获取焦点,焦点落在右侧编辑面板' description: '获取焦点,焦点落在右侧编辑面板',
...getActionCommonProps('focus')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,3 +1,4 @@
import React from 'react';
import cx from 'classnames'; import cx from 'classnames';
import DeepDiff from 'deep-diff'; import DeepDiff from 'deep-diff';
import flatten from 'lodash/flatten'; import flatten from 'lodash/flatten';
@ -20,11 +21,15 @@ import {
ScaffoldForm, ScaffoldForm,
RegionConfig, RegionConfig,
registerEditorPlugin, registerEditorPlugin,
JSONPipeOut, JSONPipeOut
InsertEventContext,
MoveEventContext,
DeleteEventContext
} from 'amis-editor-core'; } from 'amis-editor-core';
import type {FormSchema} from 'amis';
import type {
IFormStore,
IFormItemStore,
Schema,
RendererConfig
} from 'amis-core';
import { import {
DSFeatureType, DSFeatureType,
DSBuilderManager, DSBuilderManager,
@ -33,17 +38,13 @@ import {
ApiDSBuilderKey ApiDSBuilderKey
} from '../../builder'; } from '../../builder';
import {FormOperatorMap} from '../../builder/constants'; import {FormOperatorMap} from '../../builder/constants';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {FieldSetting} from '../../renderer/FieldSetting'; import {FieldSetting} from '../../renderer/FieldSetting';
import {_isModelComp} from '../../util'; import {_isModelComp} from '../../util';
import type {FormSchema} from 'amis/lib/Schema';
import type {
IFormStore,
IFormItemStore,
Schema,
RendererConfig
} from 'amis-core';
import type {FormScaffoldConfig} from '../../builder'; import type {FormScaffoldConfig} from '../../builder';
export type FormPluginFeat = Extract< export type FormPluginFeat = Extract<
@ -344,32 +345,48 @@ export class FormPlugin extends BasePlugin {
{ {
actionLabel: '提交表单', actionLabel: '提交表单',
actionType: 'submit', actionType: 'submit',
description: '触发表单提交' description: '触发表单提交',
...getActionCommonProps('submit')
}, },
{ {
actionLabel: '重置表单', actionLabel: '重置表单',
actionType: 'reset', actionType: 'reset',
description: '触发表单重置' description: '触发表单重置',
...getActionCommonProps('reset')
}, },
{ {
actionLabel: '清空表单', actionLabel: '清空表单',
actionType: 'clear', actionType: 'clear',
description: '触发表单清空' description: '触发表单清空',
...getActionCommonProps('clear')
}, },
{ {
actionLabel: '校验表单', actionLabel: '校验表单',
actionType: 'validate', actionType: 'validate',
description: '触发表单校验' description: '触发表单校验',
descDetail: (info: any, context: any, props: any) => {
return (
<div className="action-desc">
<span className="variable-left variable-right">
{info?.rendererLabel}
</span>
</div>
);
}
}, },
{ {
actionLabel: '重新加载', actionLabel: '重新加载',
actionType: 'reload', actionType: 'reload',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionLabel: '变量赋值', actionLabel: '变量赋值',
actionType: 'setValue', actionType: 'setValue',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,25 +1,21 @@
import { import {
BasePlugin,
BaseEventContext,
RendererPluginAction,
RendererPluginEvent,
registerEditorPlugin,
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
defaultValue, defaultValue,
getSchemaTpl, getSchemaTpl
valuePipeOut
} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {
BasePlugin,
BasicSubRenderInfo,
RendererEventContext,
SubRendererInfo,
BaseEventContext
} from 'amis-editor-core'; } from 'amis-editor-core';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {formItemControl} from '../../component/BaseControl';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
export class CityControlPlugin extends BasePlugin { export class CityControlPlugin extends BasePlugin {
static id = 'CityControlPlugin'; static id = 'CityControlPlugin';
@ -102,17 +98,20 @@ export class CityControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置为默认值' description: '重置为默认值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,12 +1,20 @@
import {registerEditorPlugin} from 'amis-editor-core'; import {
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; registerEditorPlugin,
import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core'; RendererPluginAction,
RendererPluginEvent,
import {ValidatorTag} from '../../validator'; defaultValue,
import {getEventControlConfig} from '../../renderer/event-control/helper'; getSchemaTpl,
import {FormulaDateType} from '../../renderer/FormulaControl'; BasePlugin,
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; BaseEventContext,
tipedLabel
} from 'amis-editor-core';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {FormulaDateType} from '../../renderer/FormulaControl';
const formatX = [ const formatX = [
{ {
@ -248,17 +256,20 @@ export class DateControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空输入框内容' description: '清空输入框内容',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
@ -347,6 +358,9 @@ export class DateControlPlugin extends BasePlugin {
getSchemaTpl('clearable', { getSchemaTpl('clearable', {
pipeIn: defaultValue(true) pipeIn: defaultValue(true)
}), }),
getSchemaTpl('inputForbid', {
pipeIn: defaultValue(false)
}),
getSchemaTpl('valueFormula', { getSchemaTpl('valueFormula', {
rendererSchema: (schema: Schema) => schema, rendererSchema: (schema: Schema) => schema,
placeholder: '请选择静态值', placeholder: '请选择静态值',

View File

@ -1,14 +1,22 @@
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core'; import {
import {registerEditorPlugin} from 'amis-editor-core'; defaultValue,
import {BasePlugin, BaseEventContext} from 'amis-editor-core'; getSchemaTpl,
tipedLabel,
import {ValidatorTag} from '../../validator'; registerEditorPlugin,
import {getEventControlConfig} from '../../renderer/event-control/helper'; BasePlugin,
import {FormulaDateType} from '../../renderer/FormulaControl'; BaseEventContext,
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {getRendererByName} from 'amis-core'; import {getRendererByName} from 'amis-core';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {FormulaDateType} from '../../renderer/FormulaControl';
const formatX = [ const formatX = [
{ {
@ -294,17 +302,20 @@ export class DateRangeControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空输入框内容' description: '清空输入框内容',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
@ -404,7 +415,9 @@ export class DateRangeControlPlugin extends BasePlugin {
getSchemaTpl('clearable', { getSchemaTpl('clearable', {
pipeIn: defaultValue(true) pipeIn: defaultValue(true)
}), }),
getSchemaTpl('inputForbid', {
pipeIn: defaultValue(false)
}),
getSchemaTpl('valueFormula', { getSchemaTpl('valueFormula', {
rendererSchema: (schema: Schema) => ({ rendererSchema: (schema: Schema) => ({
...schema, ...schema,

View File

@ -1,17 +1,17 @@
/** /**
* @file input-excel * @file input-excel
*/ */
import {defaultValue, getSchemaTpl, valuePipeOut} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import { import {
BasePlugin, BasePlugin,
BaseEventContext, BaseEventContext,
BasicSubRenderInfo, RendererPluginAction,
RendererEventContext, RendererPluginEvent,
SubRendererInfo defaultValue,
getSchemaTpl,
registerEditorPlugin
} from 'amis-editor-core'; } from 'amis-editor-core';
import {formItemControl} from '../../component/BaseControl'; import {formItemControl} from '../../component/BaseControl';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; import {getActionCommonProps} from '../../renderer/event-control/helper';
export class ExcelControlPlugin extends BasePlugin { export class ExcelControlPlugin extends BasePlugin {
static id = 'ExcelControlPlugin'; static id = 'ExcelControlPlugin';
@ -80,17 +80,20 @@ export class ExcelControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {

View File

@ -1,9 +1,19 @@
import {defaultValue, getSchemaTpl, valuePipeOut} from 'amis-editor-core'; import {
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core'; defaultValue,
import {BasePlugin, BaseEventContext} from 'amis-editor-core'; getSchemaTpl,
valuePipeOut,
RendererPluginAction,
RendererPluginEvent,
registerEditorPlugin,
tipedLabel,
BasePlugin,
BaseEventContext
} from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
export class FileControlPlugin extends BasePlugin { export class FileControlPlugin extends BasePlugin {
static id = 'FileControlPlugin'; static id = 'FileControlPlugin';
@ -146,12 +156,14 @@ export class FileControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空数据', actionLabel: '清空数据',
description: '清除选择的文件' description: '清除选择的文件',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -5,10 +5,13 @@ import {
RendererPluginEvent, RendererPluginEvent,
BasePlugin, BasePlugin,
BaseEventContext, BaseEventContext,
registerEditorPlugin registerEditorPlugin,
tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import {tipedLabel} from 'amis-editor-core'; import {
import {getEventControlConfig} from '../../renderer/event-control/helper'; getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
const addBtnCssClassName = 'themeCss.addBtnControlClassName'; const addBtnCssClassName = 'themeCss.addBtnControlClassName';
@ -189,12 +192,14 @@ export class ImageControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空数据', actionLabel: '清空数据',
description: '清除选择的文件' description: '清除选择的文件',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,16 +1,15 @@
/** /**
* @file input-kv * @file input-kv
*/ */
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {defaultValue, getSchemaTpl, valuePipeOut} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import { import {
BasePlugin, RendererPluginAction,
BasicSubRenderInfo, RendererPluginEvent,
RendererEventContext, defaultValue,
SubRendererInfo getSchemaTpl,
registerEditorPlugin,
BasePlugin
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getActionCommonProps} from '../../renderer/event-control/helper';
export class KVControlPlugin extends BasePlugin { export class KVControlPlugin extends BasePlugin {
static id = 'KVControlPlugin'; static id = 'KVControlPlugin';
static scene = ['layout']; static scene = ['layout'];
@ -113,17 +112,20 @@ export class KVControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -3,25 +3,22 @@ import {
getI18nEnabled, getI18nEnabled,
RAW_TYPE_MAP, RAW_TYPE_MAP,
RendererPluginAction, RendererPluginAction,
RendererPluginEvent RendererPluginEvent,
} from 'amis-editor-core';
import flatten from 'lodash/flatten';
import {ContainerWrapper} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {isObject} from 'amis-editor-core';
import {
BasePlugin, BasePlugin,
BasicSubRenderInfo, BaseEventContext,
RendererEventContext, registerEditorPlugin,
SubRendererInfo, defaultValue,
BaseEventContext getSchemaTpl,
tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {inputStateTpl} from '../../renderer/style-control/helper';
import {Schema} from 'amis-core'; import {Schema} from 'amis-core';
import type {SchemaType} from 'amis'; import type {SchemaType} from 'amis';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {inputStateTpl} from '../../renderer/style-control/helper';
export class NumberControlPlugin extends BasePlugin { export class NumberControlPlugin extends BasePlugin {
static id = 'NumberControlPlugin'; static id = 'NumberControlPlugin';
@ -42,6 +39,7 @@ export class NumberControlPlugin extends BasePlugin {
type: 'input-number', type: 'input-number',
label: '数字', label: '数字',
name: 'number', name: 'number',
showSteps: true,
keyboard: true keyboard: true
}; };
previewSchema: any = { previewSchema: any = {
@ -137,17 +135,20 @@ export class NumberControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空数字框内容' description: '清空数字框内容',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置为默认值' description: '重置为默认值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
@ -210,6 +211,13 @@ export class NumberControlPlugin extends BasePlugin {
label: '最大值', label: '最大值',
valueType: 'number' valueType: 'number'
}), }),
{
type: 'switch',
label: '显示上下按钮',
name: 'showSteps',
value: true,
inputClassName: 'is-inline'
},
{ {
type: 'input-number', type: 'input-number',
name: 'step', name: 'step',
@ -217,6 +225,7 @@ export class NumberControlPlugin extends BasePlugin {
min: 0, min: 0,
value: 1, value: 1,
precision: '${precision}', precision: '${precision}',
visibleOn: '${showSteps}',
strictMode: false strictMode: false
}, },
{ {
@ -322,16 +331,26 @@ export class NumberControlPlugin extends BasePlugin {
) )
] ]
}, },
getSchemaTpl('theme:cssCode', { getSchemaTpl('theme:singleCssCode', {
themeClass: [ selectors: [
{ {
name: '数字输入框', label: '表单项基本样式',
value: '', isRoot: true,
className: 'inputControlClassName', selector: '.cxd-from-item'
state: ['default', 'hover', 'active'] },
{
label: '标题样式',
selector: '.cxd-Form-label'
},
{
label: '数字框基本样式',
selector: '.cxd-Number'
},
{
label: '输入框样式',
selector: '.cxd-Number-input'
} }
], ]
isFormItem: true
}) })
], ],
{...context?.schema, configTitle: 'style'} {...context?.schema, configTitle: 'style'}

View File

@ -1,4 +1,5 @@
import {isObject} from 'amis'; import {isObject} from 'amis';
import type {IFormStore, IFormItemStore} from 'amis-core';
import { import {
BasePlugin, BasePlugin,
defaultValue, defaultValue,
@ -6,10 +7,6 @@ import {
tipedLabel, tipedLabel,
registerEditorPlugin registerEditorPlugin
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import type {IFormStore, IFormItemStore} from 'amis-core';
import type { import type {
EditorNodeType, EditorNodeType,
RendererPluginAction, RendererPluginAction,
@ -17,6 +14,11 @@ import type {
BaseEventContext, BaseEventContext,
EditorManager EditorManager
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
export class RangeControlPlugin extends BasePlugin { export class RangeControlPlugin extends BasePlugin {
static id = 'RangeControlPlugin'; static id = 'RangeControlPlugin';
@ -155,17 +157,20 @@ export class RangeControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除输入框' description: '清除输入框',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -4,13 +4,19 @@ import {
getI18nEnabled, getI18nEnabled,
getSchemaTpl, getSchemaTpl,
isObject, isObject,
undefinedPipeOut undefinedPipeOut,
RendererPluginAction,
RendererPluginEvent,
registerEditorPlugin,
BasePlugin,
BaseEventContext,
tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
export class RateControlPlugin extends BasePlugin { export class RateControlPlugin extends BasePlugin {
static id = 'RateControlPlugin'; static id = 'RateControlPlugin';
@ -80,17 +86,20 @@ export class RateControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空评分值' description: '清空评分值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -12,18 +12,17 @@ import {
RendererPluginAction, RendererPluginAction,
tipedLabel, tipedLabel,
getI18nEnabled, getI18nEnabled,
repeatArray,
mockValue,
EditorNodeType, EditorNodeType,
EditorManager, EditorManager,
RAW_TYPE_MAP RAW_TYPE_MAP
} from 'amis-editor-core'; } from 'amis-editor-core';
import {setVariable, someTree} from 'amis-core'; import {someTree} from 'amis-core';
import {DSBuilderManager} from '../../builder/DSBuilderManager'; import {DSBuilderManager} from '../../builder/DSBuilderManager';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import { import {
getEventControlConfig, getEventControlConfig,
getArgsWrapper getArgsWrapper,
getActionCommonProps
} from '../../renderer/event-control/helper'; } from '../../renderer/event-control/helper';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import { import {
@ -951,7 +950,8 @@ export class TableControlPlugin extends BasePlugin {
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
}, },
{ {
actionType: 'addItem', actionType: 'addItem',
@ -1101,7 +1101,8 @@ export class TableControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空组件数据' description: '清空组件数据',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'initDrag', actionType: 'initDrag',

View File

@ -2,21 +2,17 @@ import {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
getSchemaTpl, getSchemaTpl,
tipedLabel tipedLabel,
} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {
BasePlugin, BasePlugin,
BasicSubRenderInfo, BaseEventContext,
RendererEventContext, registerEditorPlugin,
SubRendererInfo, RendererPluginAction,
BaseEventContext RendererPluginEvent
} from 'amis-editor-core'; } from 'amis-editor-core';
import {formItemControl} from '../../component/BaseControl'; import {formItemControl} from '../../component/BaseControl';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util'; import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {getActionCommonProps} from '../../renderer/event-control/helper';
export class TagControlPlugin extends BasePlugin { export class TagControlPlugin extends BasePlugin {
static id = 'TagControlPlugin'; static id = 'TagControlPlugin';
@ -153,17 +149,20 @@ export class TagControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置为默认值' description: '重置为默认值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -2,21 +2,21 @@ import {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
RAW_TYPE_MAP, RAW_TYPE_MAP,
registerEditorPlugin registerEditorPlugin,
} from 'amis-editor-core';
import {
BasePlugin, BasePlugin,
BasicSubRenderInfo, BaseEventContext,
RendererEventContext, defaultValue,
SubRendererInfo, getSchemaTpl,
BaseEventContext tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core'; import type {SchemaType} from 'amis';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {inputStateTpl} from '../../renderer/style-control/helper'; import {inputStateTpl} from '../../renderer/style-control/helper';
import {resolveOptionType} from '../../util'; import {resolveOptionType} from '../../util';
import type {SchemaType} from 'amis';
const isText = 'this.type === "input-text"'; const isText = 'this.type === "input-text"';
const isPassword = 'this.type === "input-password"'; const isPassword = 'this.type === "input-password"';
@ -187,22 +187,26 @@ export class TextControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空输入框内容' description: '清空输入框内容',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -3,20 +3,28 @@ import {
EditorNodeType, EditorNodeType,
getI18nEnabled, getI18nEnabled,
RendererPluginAction, RendererPluginAction,
RendererPluginEvent RendererPluginEvent,
registerEditorPlugin,
defaultValue,
getSchemaTpl,
BaseEventContext,
BasePlugin,
tipedLabel,
diff
} from 'amis-editor-core'; } from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; import type {Schema} from 'amis';
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import cloneDeep from 'lodash/cloneDeep';
import { import {
getArgsWrapper, getArgsWrapper,
getEventControlConfig getEventControlConfig
} from '../../renderer/event-control/helper'; } from '../../renderer/event-control/helper';
import {tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {resolveOptionType, TREE_BASE_EVENTS} from '../../util'; import {
import type {Schema} from 'amis'; resolveOptionType,
schemaArrayFormat,
schemaToArray,
TREE_BASE_EVENTS
} from '../../util';
import {getActionCommonProps} from '../../renderer/event-control/helper';
// 树组件公共动作 // 树组件公共动作
export const TreeCommonAction: RendererPluginAction[] = [ export const TreeCommonAction: RendererPluginAction[] = [
@ -176,6 +184,8 @@ export class TreeControlPlugin extends BasePlugin {
panelTitle = '树选择'; panelTitle = '树选择';
regions = [{key: 'toolbar', label: '工具栏', preferTag: '工具栏内容'}];
// 事件定义 // 事件定义
events: (schema: any) => RendererPluginEvent[] = (schema: any) => events: (schema: any) => RendererPluginEvent[] = (schema: any) =>
TREE_BASE_EVENTS(schema); TREE_BASE_EVENTS(schema);
@ -187,9 +197,9 @@ export class TreeControlPlugin extends BasePlugin {
actionLabel: '展开', actionLabel: '展开',
description: '展开指定层级', description: '展开指定层级',
innerArgs: ['openLevel'], innerArgs: ['openLevel'],
descDetail: (info: any) => { descDetail: (info: any, context: any, props: any) => {
return ( return (
<div> <div className="action-desc">
<span className="variable-right">{info?.__rendererLabel}</span> <span className="variable-right">{info?.__rendererLabel}</span>
<span className="variable-left variable-right"> <span className="variable-left variable-right">
@ -212,29 +222,101 @@ export class TreeControlPlugin extends BasePlugin {
{ {
actionType: 'collapse', actionType: 'collapse',
actionLabel: '收起', actionLabel: '收起',
description: '收起树节点' description: '收起树节点',
descDetail: (info: any, context: any, props: any) => {
return (
<div className="action-desc">
<span className="variable-right">{info?.rendererLabel}</span>
{info?.args?.closeLevel ? (
<>
<span className="variable-left variable-right">
{info?.args?.closeLevel}
</span>
</>
) : (
'收起'
)}
</div>
);
},
innerArgs: ['closeLevel'],
schema: getArgsWrapper(
getSchemaTpl('formulaControl', {
name: 'closeLevel',
label: '收起层级',
variables: '${variables}',
size: 'lg',
mode: 'horizontal',
horizontal: {
left: 'normal'
}
})
)
}, },
/** 新增、编辑、删除 */ /** 新增、编辑、删除 */
...TreeCommonAction, ...TreeCommonAction,
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除数据' description: '清除数据',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置数据' description: '重置数据',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
},
// 检索
{
actionType: 'search',
actionLabel: '搜索',
description: '搜索当前数据源内的选项',
descDetail: (info: any, context: any, props: any) => {
return (
<div className="action-desc">
<span className="variable-right">{info?.rendererLabel}</span>
{info?.args?.keyword ? (
<>
<span className="variable-left variable-right">
{info?.args?.keyword}
</span>
</>
) : (
'搜索'
)}
</div>
);
},
innerArgs: ['keyword'],
schema: getArgsWrapper(
getSchemaTpl('formulaControl', {
name: 'keyword',
label: '关键词',
variables: '${variables}',
size: 'lg',
mode: 'horizontal',
horizontal: {
left: 'normal'
}
})
)
} }
]; ];
@ -359,6 +441,14 @@ export class TreeControlPlugin extends BasePlugin {
name: 'cascade', name: 'cascade',
hiddenOn: '!this.multiple || !this.autoCheckChildren' hiddenOn: '!this.multiple || !this.autoCheckChildren'
}), }),
getSchemaTpl('switch', {
label: tipedLabel(
'子节点反选取消父节点',
'取消任意子节点选中状态的同时取消父节点选中状态'
),
name: 'autoCancelParent',
hiddenOn: '!this.multiple || !this.cascade'
}),
getSchemaTpl('switch', { getSchemaTpl('switch', {
label: tipedLabel( label: tipedLabel(
'值包含父节点', '值包含父节点',
@ -414,6 +504,25 @@ export class TreeControlPlugin extends BasePlugin {
}, },
{context} {context}
), ),
{
type: 'checkboxes',
name: 'nodeBehavior',
label: '节点行为',
value: ['check'],
joinValues: false,
extractValue: true,
inline: true,
options: [
{
label: '选中',
value: 'check'
},
{
label: '展开',
value: 'unfold'
}
]
},
getSchemaTpl('switch', { getSchemaTpl('switch', {
label: '只可选择叶子节点', label: '只可选择叶子节点',
name: 'onlyLeaf' name: 'onlyLeaf'
@ -466,7 +575,57 @@ export class TreeControlPlugin extends BasePlugin {
name: 'removeTip' name: 'removeTip'
} }
] ]
}) }),
{
type: 'select',
label: '操作栏位置',
value: '',
name: 'themeCss.actionControlClassName.marginLeft',
options: [
{
label: '左侧',
value: ''
},
{
label: '右侧',
value: 'auto'
}
]
},
{
type: 'ae-switch-more',
mode: 'normal',
label: '自定义操作',
bulk: false,
name: 'itemActions',
formType: 'extend',
form: {
body: [
{
type: 'button',
level: 'primary',
size: 'sm',
block: true,
onClick: this.editDetail.bind(this, context.id),
label: '配置自定义操作模板'
}
]
},
pipeIn: (value: any) => {
return value !== undefined;
},
pipeOut: (value: any) => {
if (value === true) {
return {
type: 'button',
icon: 'fa fa-plus',
level: 'link',
size: 'xs'
};
}
return value ? value : undefined;
}
}
] ]
}, },
{ {
@ -546,19 +705,6 @@ export class TreeControlPlugin extends BasePlugin {
label: tipedLabel('显示层级展开线', '显示树层级展开线'), label: tipedLabel('显示层级展开线', '显示树层级展开线'),
name: 'showOutline' name: 'showOutline'
}), }),
getSchemaTpl('switch', {
name: 'withChildren',
label: '数值是否携带子节点',
visibleOn: 'this.cascade !== true && this.multiple',
disabledOn: 'this.onlyChildren'
}),
getSchemaTpl('switch', {
name: 'onlyChildren',
label: '数值是否只包含子节点',
visibleOn: 'this.cascade !== true && this.multiple',
disabledOn: 'this.withChildren'
}),
{ {
type: 'ae-Switch-More', type: 'ae-Switch-More',
mode: 'normal', mode: 'normal',
@ -598,13 +744,32 @@ export class TreeControlPlugin extends BasePlugin {
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
getSchemaTpl('style:formItem', {renderer}), getSchemaTpl('theme:formItem', {
getSchemaTpl('style:classNames', { schema: {
schema: [ type: 'input-number',
getSchemaTpl('className', { label: '高度',
label: '外层容器', name: 'wrapperCustomStyle.root.height',
name: 'treeContainerClassName' clearable: true,
}) unitOptions: ['px', '%', 'em', 'vh', 'vw']
}
}),
getSchemaTpl('theme:form-label'),
getSchemaTpl('theme:form-description'),
getSchemaTpl('theme:base', {
classname: 'toolbarControlClassName',
title: '工具栏样式',
visibleOn: 'this.searchable'
}),
getSchemaTpl('theme:singleCssCode', {
selectors: [
{
label: '树基本样式',
selector: '.cxd-TreeControl'
},
{
label: '树工具栏样式',
selector: '.cxd-Tabs-toolbar'
}
] ]
}) })
]) ])
@ -671,6 +836,76 @@ export class TreeControlPlugin extends BasePlugin {
return dataSchema; return dataSchema;
} }
getSubEditorVariable(schema: any): Array<{label: string; children: any}> {
let labelField = schema?.labelField || 'label';
let valueField = schema?.valueField || 'value';
return [
{
label: '当前节点',
children: [
{
label: '节点索引',
value: 'index'
},
{
label: '节点名称',
value: labelField
},
{
label: '节点值',
value: valueField
},
{
label: '节点状态',
value: 'checked'
}
]
}
];
}
getDisplayField(data: any) {
if (
data.source ||
(data.map &&
Array.isArray(data.map) &&
data.map[0] &&
Object.keys(data.map[0]).length > 1)
) {
return data.labelField ?? 'label';
}
return 'item';
}
editDetail(id: string) {
const manager = this.manager;
const store = manager.store;
const node = store.getNodeById(id);
const value = store.getValueOf(id);
const defaultItemSchema = {
type: 'button',
icon: 'fa fa-plus',
level: 'link',
size: 'xs'
};
node &&
value &&
this.manager.openSubEditor({
title: '配置自定义操作模板',
value: schemaToArray(value.itemActions ?? defaultItemSchema),
slot: {
type: 'container',
body: '$$'
},
onChange: (newValue: any) => {
newValue = {...value, itemActions: schemaArrayFormat(newValue)};
manager.panelChangeValue(newValue, diff(value, newValue));
}
});
}
} }
registerEditorPlugin(TreeControlPlugin); registerEditorPlugin(TreeControlPlugin);

View File

@ -15,8 +15,12 @@ import {
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import find from 'lodash/find'; import find from 'lodash/find';
import {JSONDelete, JSONPipeIn, JSONUpdate} from 'amis-editor-core'; import {JSONDelete, JSONPipeIn, JSONUpdate} from 'amis-editor-core';
import {SUPPORT_STATIC_FORMITEM_CMPTS} from '../../renderer/event-control/helper'; import {NO_SUPPORT_STATIC_FORMITEM_CMPTS} from '../../renderer/event-control/constants';
import {isExpression, resolveVariableAndFilter} from 'amis-core'; import {
isExpression,
resolveVariableAndFilter,
getRendererByName
} from 'amis-core';
export class ItemPlugin extends BasePlugin { export class ItemPlugin extends BasePlugin {
static id = 'ItemPlugin'; static id = 'ItemPlugin';
@ -59,7 +63,10 @@ export class ItemPlugin extends BasePlugin {
} }
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const type = context.schema.type || ''; const type = context.schema.type || '';
const supportStatic = SUPPORT_STATIC_FORMITEM_CMPTS.includes(type); const render = getRendererByName(type);
// 支持静态表单项条件:是表单项组件,切不在不支持静态列表组件中
const supportStatic =
!!render?.isFormItem && !NO_SUPPORT_STATIC_FORMITEM_CMPTS.includes(type);
const ignoreName = ~['button', 'submit', 'reset'].indexOf(type); const ignoreName = ~['button', 'submit', 'reset'].indexOf(type);
const notRequiredName = ~[ const notRequiredName = ~[
'button-toobar', 'button-toobar',

View File

@ -2,23 +2,25 @@ import {
EditorNodeType, EditorNodeType,
JSONPipeIn, JSONPipeIn,
JSONPipeOut, JSONPipeOut,
getSchemaTpl getSchemaTpl,
registerEditorPlugin,
BasePlugin,
BaseEventContext,
diff
} from 'amis-editor-core'; } from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext, diff} from 'amis-editor-core';
import {formItemControl} from '../../component/BaseControl';
import type { import type {
EditorManager, EditorManager,
RendererPluginAction, RendererPluginAction,
RendererPluginEvent RendererPluginEvent
} from 'amis-editor-core'; } from 'amis-editor-core';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {formItemControl} from '../../component/BaseControl';
import { import {
resolveOptionEventDataSchame, resolveOptionEventDataSchame,
resolveOptionType, resolveOptionType,
schemaArrayFormat, schemaArrayFormat
schemaToArray
} from '../../util'; } from '../../util';
import {getActionCommonProps} from '../../renderer/event-control/helper';
export class ListControlPlugin extends BasePlugin { export class ListControlPlugin extends BasePlugin {
static id = 'ListControlPlugin'; static id = 'ListControlPlugin';
@ -102,22 +104,26 @@ export class ListControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,8 +1,18 @@
import {EditorNodeType, getSchemaTpl, tipedLabel} from 'amis-editor-core'; import {
import {registerEditorPlugin} from 'amis-editor-core'; EditorNodeType,
import {BasePlugin, BaseEventContext} from 'amis-editor-core'; getSchemaTpl,
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; tipedLabel,
import {getEventControlConfig} from '../../renderer/event-control/helper'; registerEditorPlugin,
BasePlugin,
BaseEventContext,
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {inputStateTpl} from '../../renderer/style-control/helper';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
export class LocationControlPlugin extends BasePlugin { export class LocationControlPlugin extends BasePlugin {
@ -89,17 +99,20 @@ export class LocationControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -10,7 +10,10 @@ import {
EditorNodeType EditorNodeType
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
export class MatrixControlPlugin extends BasePlugin { export class MatrixControlPlugin extends BasePlugin {
static id = 'MatrixControlPlugin'; static id = 'MatrixControlPlugin';
@ -95,22 +98,26 @@ export class MatrixControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置为默认值' description: '重置为默认值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -2,15 +2,20 @@ import {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
RendererPluginAction, RendererPluginAction,
RendererPluginEvent RendererPluginEvent,
getSchemaTpl,
registerEditorPlugin,
BasePlugin,
BaseEventContext,
tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import {inputStateTpl} from '../../renderer/style-control/helper'; import {inputStateTpl} from '../../renderer/style-control/helper';
export class NestedSelectControlPlugin extends BasePlugin { export class NestedSelectControlPlugin extends BasePlugin {
@ -197,22 +202,26 @@ export class NestedSelectControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {

View File

@ -3,16 +3,20 @@ import {
EditorNodeType, EditorNodeType,
RAW_TYPE_MAP, RAW_TYPE_MAP,
defaultValue, defaultValue,
getSchemaTpl getSchemaTpl,
registerEditorPlugin,
BasePlugin,
BaseEventContext,
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core'; } from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import type {Schema, SchemaType} from 'amis'; import type {Schema, SchemaType} from 'amis';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import {inputStateTpl} from '../../renderer/style-control/helper'; import {inputStateTpl} from '../../renderer/style-control/helper';
export class RadiosControlPlugin extends BasePlugin { export class RadiosControlPlugin extends BasePlugin {
@ -100,22 +104,26 @@ export class RadiosControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
@ -148,6 +156,7 @@ export class RadiosControlPlugin extends BasePlugin {
}, },
{ {
title: '选项', title: '选项',
id: 'properties-options',
body: [getSchemaTpl('optionControlV2'), getSchemaTpl('selectFirst')] body: [getSchemaTpl('optionControlV2'), getSchemaTpl('selectFirst')]
}, },
getSchemaTpl('status', {isFormItem: true}), getSchemaTpl('status', {isFormItem: true}),

View File

@ -1,27 +1,12 @@
import React from 'react'; import type {Schema, SchemaType} from 'amis';
import omit from 'lodash/omit';
import {findObjectsWithKey} from 'amis-core';
import {Button, Icon} from 'amis-ui';
import { import {
registerEditorPlugin, registerEditorPlugin,
getSchemaTpl, getSchemaTpl,
BasePlugin, BasePlugin,
tipedLabel, tipedLabel,
JSONPipeOut,
undefinedPipeOut, undefinedPipeOut,
RAW_TYPE_MAP RAW_TYPE_MAP
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
OPTION_EDIT_EVENTS,
OPTION_EDIT_EVENTS_OLD,
resolveOptionEventDataSchame,
resolveOptionType
} from '../../util';
import type {Schema, SchemaType} from 'amis';
import type { import type {
EditorNodeType, EditorNodeType,
RendererPluginAction, RendererPluginAction,
@ -29,6 +14,19 @@ import type {
BaseEventContext, BaseEventContext,
EditorManager EditorManager
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {
OPTION_EDIT_EVENTS,
OPTION_EDIT_EVENTS_OLD,
resolveOptionEventDataSchame,
resolveOptionType
} from '../../util';
import {inputStateTpl} from '../../renderer/style-control/helper'; import {inputStateTpl} from '../../renderer/style-control/helper';
export class SelectControlPlugin extends BasePlugin { export class SelectControlPlugin extends BasePlugin {
@ -173,22 +171,26 @@ export class SelectControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
@ -199,6 +201,7 @@ export class SelectControlPlugin extends BasePlugin {
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
{ {
title: '基本', title: '基本',
id: 'properties-basic',
body: [ body: [
getSchemaTpl('layout:originPosition', {value: 'left-top'}), getSchemaTpl('layout:originPosition', {value: 'left-top'}),
getSchemaTpl('formItemName', { getSchemaTpl('formItemName', {
@ -232,6 +235,7 @@ export class SelectControlPlugin extends BasePlugin {
}, },
{ {
title: '选项', title: '选项',
id: 'properties-options',
body: [ body: [
getSchemaTpl('optionControlV2'), getSchemaTpl('optionControlV2'),
getSchemaTpl('selectFirst', { getSchemaTpl('selectFirst', {

View File

@ -2,13 +2,9 @@ import {
defaultValue, defaultValue,
getSchemaTpl, getSchemaTpl,
undefinedPipeOut, undefinedPipeOut,
valuePipeOut registerEditorPlugin,
} from 'amis-editor-core'; BasePlugin,
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core'; BaseEventContext,
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import type {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
RendererPluginAction, RendererPluginAction,
@ -16,6 +12,11 @@ import type {
} from 'amis-editor-core'; } from 'amis-editor-core';
import {isExpression, isPureVariable} from 'amis-core'; import {isExpression, isPureVariable} from 'amis-core';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
import {ValidatorTag} from '../../validator';
import {
getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
export class SwitchControlPlugin extends BasePlugin { export class SwitchControlPlugin extends BasePlugin {
static id = 'SwitchControlPlugin'; static id = 'SwitchControlPlugin';
@ -97,17 +98,20 @@ export class SwitchControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除选中值' description: '清除选中值',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -3,13 +3,17 @@ import {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
getSchemaTpl, getSchemaTpl,
tipedLabel tipedLabel,
BasePlugin,
BaseEventContext,
registerEditorPlugin,
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core'; } from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core'; import {
import {BasePlugin, BaseEventContext} from 'amis-editor-core'; getEventControlConfig,
getActionCommonProps
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; } from '../../renderer/event-control/helper';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util'; import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
export class TabsTransferPlugin extends BasePlugin { export class TabsTransferPlugin extends BasePlugin {
@ -196,20 +200,22 @@ export class TabsTransferPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空选中内容' description: '清空选中内容',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置选择的内容' description: '重置选择的内容',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'changeTabKey', actionType: 'changeTabKey',
actionLabel: '修改选中tab', actionLabel: '修改选中tab',
description: '修改当前选中tab来选择其他选项', description: '修改当前选中tab来选择其他选项',
descDetail: (info: any) => { descDetail: (info: any, context: any, props: any) => {
return ( return (
<div> <div className="action-desc">
<span className="variable-right">{info?.__rendererLabel}</span> <span className="variable-right">{info?.__rendererLabel}</span>
tab tab
</div> </div>
@ -219,7 +225,8 @@ export class TabsTransferPlugin extends BasePlugin {
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,11 +1,18 @@
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; import {
import {registerEditorPlugin} from 'amis-editor-core'; defaultValue,
import {BasePlugin, tipedLabel} from 'amis-editor-core'; getSchemaTpl,
registerEditorPlugin,
BasePlugin,
tipedLabel,
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core'; import type {BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; getEventControlConfig,
getActionCommonProps
} from '../../renderer/event-control/helper';
import {inputStateTpl} from '../../renderer/style-control/helper'; import {inputStateTpl} from '../../renderer/style-control/helper';
export class TextareaControlPlugin extends BasePlugin { export class TextareaControlPlugin extends BasePlugin {
@ -115,17 +122,20 @@ export class TextareaControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空输入框内容' description: '清空输入框内容',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为初始值' description: '将值重置为初始值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -2,21 +2,20 @@ import {
EditorManager, EditorManager,
EditorNodeType, EditorNodeType,
defaultValue, defaultValue,
getSchemaTpl getSchemaTpl,
} from 'amis-editor-core'; BasePlugin,
import {registerEditorPlugin} from 'amis-editor-core'; BaseEventContext,
import {BasePlugin, BaseEventContext} from 'amis-editor-core'; registerEditorPlugin,
import {getEventControlConfig} from '../../renderer/event-control/helper'; tipedLabel,
import {
RendererPluginAction, RendererPluginAction,
RendererPluginEvent, RendererPluginEvent,
undefinedPipeOut undefinedPipeOut
} from 'amis-editor-core'; } from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {tipedLabel} from 'amis-editor-core';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import type {Schema} from 'amis'; import type {Schema} from 'amis';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {ValidatorTag} from '../../validator';
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
import {getActionCommonProps} from '../../renderer/event-control/helper';
export class TransferPlugin extends BasePlugin { export class TransferPlugin extends BasePlugin {
static id = 'TransferPlugin'; static id = 'TransferPlugin';
@ -118,22 +117,26 @@ export class TransferPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空选中内容' description: '清空选中内容',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置选择的内容' description: '重置选择的内容',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'selectAll', actionType: 'selectAll',
actionLabel: '全选', actionLabel: '全选',
description: '选中所有选项' description: '选中所有选项',
...getActionCommonProps('selectAll')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新,多值用“,”分隔' description: '触发组件数据更新,多值用“,”分隔',
...getActionCommonProps('setValue')
} }
]; ];
@ -247,11 +250,6 @@ export class TransferPlugin extends BasePlugin {
} }
}, },
getSchemaTpl('optionControl', {
visibleOn: 'this.selectMode === "list"',
multiple: true
}),
getSchemaTpl( getSchemaTpl(
'loadingConfig', 'loadingConfig',
{ {
@ -259,6 +257,10 @@ export class TransferPlugin extends BasePlugin {
}, },
{context} {context}
), ),
getSchemaTpl('optionControl', {
visibleOn: 'this.selectMode === "list"',
multiple: true
}),
{ {
type: 'ae-transferTableControl', type: 'ae-transferTableControl',
@ -291,6 +293,21 @@ export class TransferPlugin extends BasePlugin {
label: '可检索', label: '可检索',
name: 'searchable' name: 'searchable'
}), }),
getSchemaTpl('switch', {
label: tipedLabel(
'仅包含子节点的值',
'仅在autoCheckChildren=true时生效'
),
value: true,
name: 'onlyChildren',
visibleOn: 'this.selectMode === "tree"'
}),
getSchemaTpl('switch', {
label: '选中父节点自动选中子节点',
name: 'autoCheckChildren',
value: true,
visibleOn: 'this.selectMode === "tree"'
}),
getSchemaTpl('optionsMenuTpl', { getSchemaTpl('optionsMenuTpl', {
manager: this.manager, manager: this.manager,

View File

@ -1,4 +1,4 @@
import {registerEditorPlugin} from 'amis-editor-core'; import {registerEditorPlugin, RendererPluginEvent} from 'amis-editor-core';
import {TransferPlugin} from './Transfer'; import {TransferPlugin} from './Transfer';
@ -45,6 +45,32 @@ export class TransferPickerPlugin extends TransferPlugin {
] ]
}; };
events: RendererPluginEvent[] = [
...this.events,
{
eventName: 'itemClick',
eventLabel: '点击选项',
description: '选项被点击时触发',
dataSchema: [
{
type: 'object',
properties: {
data: {
type: 'object',
title: '数据',
properties: {
item: {
type: 'object',
title: '当前选项'
}
}
}
}
}
]
}
];
notRenderFormZone = true; notRenderFormZone = true;
} }

View File

@ -3,24 +3,29 @@ import {
EditorNodeType, EditorNodeType,
getI18nEnabled, getI18nEnabled,
RendererPluginAction, RendererPluginAction,
RendererPluginEvent RendererPluginEvent,
defaultValue,
getSchemaTpl,
registerEditorPlugin,
BaseEventContext,
BasePlugin,
tipedLabel,
diff
} from 'amis-editor-core'; } from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import cloneDeep from 'lodash/cloneDeep';
import { import {
getArgsWrapper, getEventControlConfig,
getEventControlConfig getActionCommonProps
} from '../../renderer/event-control/helper'; } from '../../renderer/event-control/helper';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
import {tipedLabel} from 'amis-editor-core';
import { import {
resolveOptionEventDataSchame, resolveOptionEventDataSchame,
resolveOptionType, resolveOptionType,
schemaArrayFormat,
schemaToArray,
TREE_BASE_EVENTS TREE_BASE_EVENTS
} from '../../util'; } from '../../util';
import {TreeCommonAction} from './InputTree'; import {TreeCommonAction} from './InputTree';
import {inputStateTpl} from '../../renderer/style-control/helper';
export class TreeSelectControlPlugin extends BasePlugin { export class TreeSelectControlPlugin extends BasePlugin {
static id = 'TreeSelectControlPlugin'; static id = 'TreeSelectControlPlugin';
@ -154,22 +159,26 @@ export class TreeSelectControlPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清除数据' description: '清除数据',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置数据' description: '重置数据',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
} }
]; ];
@ -297,6 +306,14 @@ export class TreeSelectControlPlugin extends BasePlugin {
name: 'cascade', name: 'cascade',
hiddenOn: '!this.multiple || !this.autoCheckChildren' hiddenOn: '!this.multiple || !this.autoCheckChildren'
}), }),
getSchemaTpl('switch', {
label: tipedLabel(
'子节点反选取消父节点',
'取消任意子节点选中状态的同时取消父节点选中状态'
),
name: 'autoCancelParent',
hiddenOn: '!this.multiple || !this.cascade'
}),
getSchemaTpl('switch', { getSchemaTpl('switch', {
label: tipedLabel( label: tipedLabel(
'值包含父节点', '值包含父节点',
@ -353,6 +370,25 @@ export class TreeSelectControlPlugin extends BasePlugin {
}, },
{context} {context}
), ),
{
type: 'checkboxes',
name: 'nodeBehavior',
label: '节点行为',
value: ['check'],
joinValues: false,
extractValue: true,
inline: true,
options: [
{
label: '选中',
value: 'check'
},
{
label: '展开',
value: 'unfold'
}
]
},
getSchemaTpl('switch', { getSchemaTpl('switch', {
label: '只可选择叶子节点', label: '只可选择叶子节点',
name: 'onlyLeaf' name: 'onlyLeaf'
@ -404,7 +440,57 @@ export class TreeSelectControlPlugin extends BasePlugin {
name: 'removeTip' name: 'removeTip'
} }
] ]
}) }),
{
type: 'select',
label: '操作栏位置',
value: '',
name: 'themeCss.actionControlClassName.marginLeft',
options: [
{
label: '左侧',
value: ''
},
{
label: '右侧',
value: 'auto'
}
]
},
{
type: 'ae-switch-more',
mode: 'normal',
label: '自定义操作',
bulk: false,
name: 'itemActions',
formType: 'extend',
form: {
body: [
{
type: 'button',
level: 'primary',
size: 'sm',
block: true,
onClick: this.editDetail.bind(this, context.id),
label: '配置自定义操作模板'
}
]
},
pipeIn: (value: any) => {
return value !== undefined;
},
pipeOut: (value: any) => {
if (value === true) {
return {
type: 'button',
icon: 'fa fa-plus',
level: 'link',
size: 'xs'
};
}
return value ? value : undefined;
}
}
] ]
}, },
{ {
@ -484,19 +570,6 @@ export class TreeSelectControlPlugin extends BasePlugin {
label: tipedLabel('显示层级展开线', '显示树层级展开线'), label: tipedLabel('显示层级展开线', '显示树层级展开线'),
name: 'showOutline' name: 'showOutline'
}), }),
getSchemaTpl('switch', {
name: 'withChildren',
label: '数值是否携带子节点',
visibleOn: 'this.cascade !== true && this.multiple',
disabledOn: 'this.onlyChildren'
}),
getSchemaTpl('switch', {
name: 'onlyChildren',
label: '数值是否只包含子节点',
visibleOn: 'this.cascade !== true && this.multiple',
disabledOn: 'this.withChildren'
}),
{ {
type: 'ae-Switch-More', type: 'ae-Switch-More',
mode: 'normal', mode: 'normal',
@ -536,15 +609,18 @@ export class TreeSelectControlPlugin extends BasePlugin {
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
getSchemaTpl('style:formItem', {renderer}), getSchemaTpl('theme:formItem'),
getSchemaTpl('style:classNames', { getSchemaTpl('theme:form-label'),
schema: [ getSchemaTpl('theme:form-description'),
getSchemaTpl('className', { {
label: '外层容器', title: '输入框样式',
name: 'treeContainerClassName' body: [
}) ...inputStateTpl(
'themeCss.inputControlClassName',
'--input-default'
)
] ]
}) }
]) ])
}, },
{ {
@ -609,6 +685,76 @@ export class TreeSelectControlPlugin extends BasePlugin {
return dataSchema; return dataSchema;
} }
getSubEditorVariable(schema: any): Array<{label: string; children: any}> {
let labelField = schema?.labelField || 'label';
let valueField = schema?.valueField || 'value';
return [
{
label: '节点选项',
children: [
{
label: '节点索引',
value: 'index'
},
{
label: '节点名称',
value: labelField
},
{
label: '节点值',
value: valueField
},
{
label: '节点状态',
value: 'checked'
}
]
}
];
}
getDisplayField(data: any) {
if (
data.source ||
(data.map &&
Array.isArray(data.map) &&
data.map[0] &&
Object.keys(data.map[0]).length > 1)
) {
return data.labelField ?? 'label';
}
return 'item';
}
editDetail(id: string) {
const manager = this.manager;
const store = manager.store;
const node = store.getNodeById(id);
const value = store.getValueOf(id);
const defaultItemSchema = {
type: 'button',
icon: 'fa fa-plus',
level: 'link',
size: 'xs'
};
node &&
value &&
this.manager.openSubEditor({
title: '配置自定义操作模板',
value: schemaToArray(value.itemActions ?? defaultItemSchema),
slot: {
type: 'container',
body: '$$'
},
onChange: (newValue: any) => {
newValue = {...value, itemActions: schemaArrayFormat(newValue)};
manager.panelChangeValue(newValue, diff(value, newValue));
}
});
}
} }
registerEditorPlugin(TreeSelectControlPlugin); registerEditorPlugin(TreeSelectControlPlugin);

View File

@ -58,6 +58,7 @@ export class MappingPlugin extends BasePlugin {
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
{ {
title: '基本', title: '基本',
id: 'properties-basic',
body: [ body: [
isUnderField isUnderField
? { ? {

View File

@ -10,7 +10,11 @@ import {
RendererPluginAction, RendererPluginAction,
tipedLabel tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
export class NavPlugin extends BasePlugin { export class NavPlugin extends BasePlugin {
static id = 'NavPlugin'; static id = 'NavPlugin';
static scene = ['layout']; static scene = ['layout'];
@ -254,12 +258,14 @@ export class NavPlugin extends BasePlugin {
{ {
actionType: 'collapse', actionType: 'collapse',
actionLabel: '菜单折叠', actionLabel: '菜单折叠',
description: '触发组件的折叠与展开' description: '触发组件的折叠与展开',
...getActionCommonProps('collapse')
}, },
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
} }
]; ];

View File

@ -1,7 +1,11 @@
import {Button} from 'amis'; import {Button} from 'amis';
import React from 'react'; import React from 'react';
import get from 'lodash/get'; import get from 'lodash/get';
import {getI18nEnabled, registerEditorPlugin} from 'amis-editor-core'; import {
getI18nEnabled,
registerEditorPlugin,
tipedLabel
} from 'amis-editor-core';
import { import {
BasePlugin, BasePlugin,
BasicRendererInfo, BasicRendererInfo,
@ -427,10 +431,35 @@ export class TableCellPlugin extends BasePlugin {
? value.replace(/\*\s*,\s*|\s*,\s*\*/g, '') ? value.replace(/\*\s*,\s*|\s*,\s*\*/g, '')
: value : value
}, },
{
name: 'textOverflow',
type: 'button-group-select',
label: '文本超出处理',
size: 'xs',
mode: 'inline',
inputClassName: 'mt-1 w-full',
pipeIn: defaultValue('default'),
options: [
{
label: '默认',
value: 'default'
},
{
label: '溢出隐藏',
value: 'ellipsis'
},
{
label: '取消换行',
value: 'noWrap'
}
]
},
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'className', name: 'className',
label: '内容强制换行', label: tipedLabel(
'允许任意字符间断行',
'开启此项换行处理将在任意字母处断行长英文单词或长英文字符会被切断如url链接'
),
pipeIn: (value: any) => pipeIn: (value: any) =>
typeof value === 'string' && /\word\-break\b/.test(value), typeof value === 'string' && /\word\-break\b/.test(value),
pipeOut: (value: any, originValue: any) => pipeOut: (value: any, originValue: any) =>

View File

@ -6,7 +6,10 @@ import {
getSchemaTpl, getSchemaTpl,
defaultValue defaultValue
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import type {SchemaObject} from 'amis'; import type {SchemaObject} from 'amis';
import {tipedLabel} from 'amis-editor-core'; import {tipedLabel} from 'amis-editor-core';
@ -110,12 +113,14 @@ export class PagePlugin extends BasePlugin {
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '变量赋值', actionLabel: '变量赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];
@ -222,6 +227,24 @@ export class PagePlugin extends BasePlugin {
inputClassName: 'is-inline', inputClassName: 'is-inline',
pipeIn: defaultValue(true), pipeIn: defaultValue(true),
hiddenOn: 'this.regions && !this.regions.includes("aside")' hiddenOn: 'this.regions && !this.regions.includes("aside")'
},
{
type: 'button-group-select',
name: 'asidePosition',
size: 'sm',
label: '边栏位置',
pipeIn: defaultValue('left'),
options: [
{
label: '左',
value: 'left'
},
{
label: '右',
value: 'right'
}
],
hiddenOn: 'this.regions && !this.regions.includes("aside")'
} }
] ]
}, },
@ -288,7 +311,7 @@ export class PagePlugin extends BasePlugin {
body: [ body: [
getSchemaTpl('collapseGroup', [ getSchemaTpl('collapseGroup', [
...getSchemaTpl('theme:common', { ...getSchemaTpl('theme:common', {
exclude: ['layout'], exclude: ['layout', 'theme-css-code'],
classname: 'baseControlClassName', classname: 'baseControlClassName',
baseTitle: '基本样式', baseTitle: '基本样式',
extra: [ extra: [
@ -320,6 +343,31 @@ export class PagePlugin extends BasePlugin {
hiddenOn: 'this.regions && !this.regions.includes("aside")' hiddenOn: 'this.regions && !this.regions.includes("aside")'
}) })
] ]
}),
getSchemaTpl('theme:singleCssCode', {
selectors: [
{
label: '页面基本样式',
isRoot: true,
selector: '.cxd-Page'
},
{
label: '页面内容区样式',
selector: '.cxd-Page-body'
},
{
label: '页面标题栏样式',
selector: '.cxd-Page-title'
},
{
label: '页面工具栏样式',
selector: '.cxd-Page-toolbar'
},
{
label: '页面边栏样式',
selector: '.cxd-Page-aside'
}
]
}) })
]) ])
] ]

View File

@ -97,6 +97,7 @@ export class PanelPlugin extends BasePlugin {
getSchemaTpl('collapseGroup', [ getSchemaTpl('collapseGroup', [
{ {
className: 'p-none', className: 'p-none',
id: 'properties-basic',
title: '基本', title: '基本',
body: [ body: [
getSchemaTpl('layout:originPosition', {value: 'left-top'}), getSchemaTpl('layout:originPosition', {value: 'left-top'}),
@ -199,6 +200,7 @@ export class PanelPlugin extends BasePlugin {
label: '主题', label: '主题',
type: 'select', type: 'select',
size: 'sm', size: 'sm',
id: 'panel-settings-panelClassName',
pipeIn: (value: any) => pipeIn: (value: any) =>
typeof value === 'string' && typeof value === 'string' &&
/(?:^|\s)(Panel\-\-(\w+))(?:$|\s)/.test(value) /(?:^|\s)(Panel\-\-(\w+))(?:$|\s)/.test(value)

View File

@ -1,9 +1,13 @@
import {registerEditorPlugin, RendererPluginAction} from 'amis-editor-core'; import {
import {BaseEventContext, BasePlugin} from 'amis-editor-core'; registerEditorPlugin,
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; RendererPluginAction,
import {tipedLabel} from 'amis-editor-core'; BaseEventContext,
import {ValidatorTag} from '../validator'; BasePlugin,
import {getEventControlConfig} from '../renderer/event-control/helper'; defaultValue,
getSchemaTpl,
tipedLabel
} from 'amis-editor-core';
import {getActionCommonProps} from '../renderer/event-control/helper';
export class ProgressPlugin extends BasePlugin { export class ProgressPlugin extends BasePlugin {
static id = 'ProgressPlugin'; static id = 'ProgressPlugin';
@ -37,12 +41,14 @@ export class ProgressPlugin extends BasePlugin {
{ {
actionType: 'reset', actionType: 'reset',
actionLabel: '重置', actionLabel: '重置',
description: '重置为默认值' description: '重置为默认值',
...getActionCommonProps('reset')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -1,15 +1,16 @@
import React from 'react';
import { import {
registerEditorPlugin, registerEditorPlugin,
BaseEventContext, BaseEventContext,
BasePlugin, BasePlugin,
RendererPluginEvent, RendererPluginEvent,
RendererPluginAction RendererPluginAction,
getSchemaTpl
} from 'amis-editor-core'; } from 'amis-editor-core';
import {getSchemaTpl} from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper';
import type {Schema} from 'amis-core'; import type {Schema} from 'amis-core';
import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
export class SearchBoxPlugin extends BasePlugin { export class SearchBoxPlugin extends BasePlugin {
static id = 'SearchBoxPlugin'; static id = 'SearchBoxPlugin';
@ -144,12 +145,14 @@ export class SearchBoxPlugin extends BasePlugin {
{ {
actionType: 'clear', actionType: 'clear',
actionLabel: '清空', actionLabel: '清空',
description: '清空输入框' description: '清空输入框',
...getActionCommonProps('clear')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '更新数据', actionLabel: '更新数据',
description: '更新数据' description: '更新数据',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -16,7 +16,10 @@ import {
} from 'amis-editor-core'; } from 'amis-editor-core';
import {DSBuilderManager} from '../builder/DSBuilderManager'; import {DSBuilderManager} from '../builder/DSBuilderManager';
import {DSFeatureEnum, ModelDSBuilderKey, ApiDSBuilderKey} from '../builder'; import {DSFeatureEnum, ModelDSBuilderKey, ApiDSBuilderKey} from '../builder';
import {getEventControlConfig} from '../renderer/event-control/helper'; import {
getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper';
import type {Schema} from 'amis-core'; import type {Schema} from 'amis-core';
import type { import type {
@ -168,7 +171,8 @@ export class ServicePlugin extends BasePlugin {
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'rebuild', actionType: 'rebuild',
@ -178,7 +182,8 @@ export class ServicePlugin extends BasePlugin {
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '变量赋值', actionLabel: '变量赋值',
description: '更新数据域数据' description: '更新数据域数据',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -107,6 +107,11 @@ export class StepsPlugin extends BasePlugin {
{ {
title: '外观', title: '外观',
body: [ body: [
getSchemaTpl('switch', {
name: 'iconPosition',
label: '图标文字垂直展示',
value: false
}),
{ {
name: 'mode', name: 'mode',
type: 'select', type: 'select',

View File

@ -1,13 +1,10 @@
import React from 'react'; import React from 'react';
import {Button, resolveVariable} from 'amis'; import {Button, resolveVariable} from 'amis';
import type {DataScope, SchemaObject} from 'amis';
import { import {
getI18nEnabled, getI18nEnabled,
RendererPluginAction, RendererPluginAction,
RendererPluginEvent RendererPluginEvent,
} from 'amis-editor-core';
import {findTree, setVariable, someTree} from 'amis-core';
import {registerEditorPlugin, repeatArray, diff} from 'amis-editor-core';
import {
BasePlugin, BasePlugin,
BaseEventContext, BaseEventContext,
PluginEvent, PluginEvent,
@ -16,13 +13,20 @@ import {
BasicRendererInfo, BasicRendererInfo,
PluginInterface, PluginInterface,
InsertEventContext, InsertEventContext,
ScaffoldForm ScaffoldForm,
registerEditorPlugin,
repeatArray,
diff,
mockValue,
EditorNodeType,
defaultValue,
getSchemaTpl,
tipedLabel
} from 'amis-editor-core'; } from 'amis-editor-core';
import type {EditorManager} from 'amis-editor-core';
import {setVariable, someTree} from 'amis-core';
import {reaction} from 'mobx';
import {DSBuilderManager} from '../builder/DSBuilderManager'; import {DSBuilderManager} from '../builder/DSBuilderManager';
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
import {mockValue} from 'amis-editor-core';
import {EditorNodeType} from 'amis-editor-core';
import type {DataScope, SchemaObject} from 'amis';
import { import {
getEventControlConfig, getEventControlConfig,
getArgsWrapper getArgsWrapper
@ -32,9 +36,7 @@ import {
schemaToArray, schemaToArray,
resolveArrayDatasource resolveArrayDatasource
} from '../util'; } from '../util';
import {reaction} from 'mobx'; import {getActionCommonProps} from '../renderer/event-control/helper';
import type {EditorManager} from 'amis-editor-core';
export class TablePlugin extends BasePlugin { export class TablePlugin extends BasePlugin {
static id = 'TablePlugin'; static id = 'TablePlugin';
@ -464,7 +466,8 @@ export class TablePlugin extends BasePlugin {
{ {
actionType: 'selectAll', actionType: 'selectAll',
actionLabel: '设置全部选中', actionLabel: '设置全部选中',
description: '设置表格全部项选中' description: '设置表格全部项选中',
...getActionCommonProps('selectAll')
}, },
{ {
actionType: 'clearAll', actionType: 'clearAll',

View File

@ -33,6 +33,7 @@ import {resolveArrayDatasource} from '../util';
import type {SchemaObject} from 'amis'; import type {SchemaObject} from 'amis';
import type {IFormItemStore, IFormStore} from 'amis-core'; import type {IFormItemStore, IFormStore} from 'amis-core';
import type {EditorManager} from 'amis-editor-core'; import type {EditorManager} from 'amis-editor-core';
import {getActionCommonProps} from '../renderer/event-control/helper';
export const Table2RenderereEvent: RendererPluginEvent[] = [ export const Table2RenderereEvent: RendererPluginEvent[] = [
{ {
@ -307,7 +308,8 @@ export const Table2RendererAction: RendererPluginAction[] = [
{ {
actionType: 'selectAll', actionType: 'selectAll',
actionLabel: '设置全部选中', actionLabel: '设置全部选中',
description: '设置表格全部项选中' description: '设置表格全部项选中',
...getActionCommonProps('selectAll')
}, },
{ {
actionType: 'clearAll', actionType: 'clearAll',

View File

@ -17,7 +17,6 @@ import findIndex from 'lodash/findIndex';
import {RegionWrapper as Region} from 'amis-editor-core'; import {RegionWrapper as Region} from 'amis-editor-core';
import {Tab} from 'amis'; import {Tab} from 'amis';
import {tipedLabel} from 'amis-editor-core'; import {tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../validator';
import { import {
getArgsWrapper, getArgsWrapper,
getEventControlConfig getEventControlConfig
@ -89,6 +88,28 @@ export class TabsPlugin extends BasePlugin {
} }
} }
] ]
},
{
eventName: 'delete',
eventLabel: '选项卡删除',
description: '选项卡删除',
dataSchema: [
{
type: 'object',
properties: {
data: {
type: 'object',
title: '数据',
properties: {
value: {
type: 'string',
title: '选项卡索引'
}
}
}
}
}
]
} }
]; ];
@ -96,11 +117,11 @@ export class TabsPlugin extends BasePlugin {
{ {
actionType: 'changeActiveKey', actionType: 'changeActiveKey',
actionLabel: '激活指定选项卡', actionLabel: '激活指定选项卡',
description: '修改当前激活tab项的key', description: '修改当前激活tab项',
config: ['activeKey'], config: ['activeKey'],
descDetail: (info: any) => { descDetail: (info: any, context: any, props: any) => {
return ( return (
<div> <div className="action-desc">
<span className="variable-left variable-right"> <span className="variable-left variable-right">
{info?.args?.activeKey} {info?.args?.activeKey}
@ -115,7 +136,39 @@ export class TabsPlugin extends BasePlugin {
label: '激活项', label: '激活项',
variables: '${variables}', variables: '${variables}',
size: 'lg', size: 'lg',
mode: 'horizontal' mode: 'horizontal',
horizontal: {
left: 'normal'
}
})
)
},
{
actionType: 'deleteTab',
actionLabel: '删除指定选项卡',
description: '删除指定hash的tab项',
descDetail: (info: any) => {
return (
<div>
hash为
<span className="variable-left variable-right">
{info?.args?.deleteHash}
</span>
tab项
</div>
);
},
schema: getArgsWrapper(
getSchemaTpl('formulaControl', {
name: 'deleteHash',
label: '删除项',
variables: '${variables}',
size: 'lg',
mode: 'horizontal',
placeholder: '请输入hash值',
horizontal: {
left: 'normal'
}
}) })
) )
} }
@ -193,7 +246,8 @@ export class TabsPlugin extends BasePlugin {
placeholder: '默认激活的选项卡', placeholder: '默认激活的选项卡',
pipeOut: (data: string) => pipeOut: (data: string) =>
data === '' || isNaN(Number(data)) ? data : Number(data) data === '' || isNaN(Number(data)) ? data : Number(data)
} },
getSchemaTpl('closable')
] ]
}, },
getSchemaTpl('status'), getSchemaTpl('status'),
@ -233,7 +287,7 @@ export class TabsPlugin extends BasePlugin {
body: [ body: [
{ {
name: 'tabsMode', name: 'tabsMode',
label: '式', label: '展示形式',
type: 'select', type: 'select',
options: [ options: [
{ {
@ -289,31 +343,54 @@ export class TabsPlugin extends BasePlugin {
}) })
] ]
}, },
getSchemaTpl('style:classNames', { getSchemaTpl('theme:base', {
isFormItem: false, classname: 'titleControlClassName',
schema: [ title: '标题样式',
getSchemaTpl('className', { hidePaddingAndMargin: true,
name: 'linksClassName', hideRadius: true,
label: '标题区' hideShadow: true,
hideBorder: true,
hideBackground: true,
state: ['default', 'hover', 'focused', 'disabled'],
extra: [
getSchemaTpl('theme:select', {
label: '宽度',
name: 'themeCss.titleControlClassName.width'
}), }),
getSchemaTpl('theme:font', {
getSchemaTpl('className', { label: '文字',
name: 'toolbarClassName', name: 'themeCss.titleControlClassName.font'
label: '工具栏'
}),
getSchemaTpl('className', {
name: 'contentClassName',
label: '内容区'
}),
getSchemaTpl('className', {
name: 'showTipClassName',
label: '提示',
visibleOn: 'this.showTip',
clearValueOnHidden: true
}) })
] ]
}),
getSchemaTpl('theme:base', {
classname: 'toolbarControlClassName',
title: '工具栏样式'
}),
getSchemaTpl('theme:base', {
classname: 'contentControlClassName',
title: '内容区样式'
}),
getSchemaTpl('theme:singleCssCode', {
selectors: [
{
label: '选项卡基本样式',
isRoot: true,
selector: '.cxd-Tabs'
},
{
label: '选项卡工具栏样式',
selector: '.cxd-Tabs-toolbar'
},
{
label: '选项卡标题样式',
selector: '.cxd-Tabs-link'
},
{
label: '选项卡内容区样式',
selector: '.cxd-Tabs-content'
}
]
}) })
]) ])
] ]
@ -377,7 +454,7 @@ export class TabsPlugin extends BasePlugin {
] ]
} }
}, },
getSchemaTpl('closable'),
{ {
label: tipedLabel( label: tipedLabel(
'Hash', 'Hash',
@ -418,8 +495,9 @@ export class TabsPlugin extends BasePlugin {
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
getSchemaTpl('style:classNames', { getSchemaTpl('theme:base', {
isFormItem: false classname: 'panelControlClassName',
title: '基本样式'
}) })
]) ])
} }

View File

@ -1,26 +1,25 @@
import React from 'react';
import { import {
EditorNodeType, EditorNodeType,
getI18nEnabled, getI18nEnabled,
jsonToJsonSchema, jsonToJsonSchema,
registerEditorPlugin registerEditorPlugin,
} from 'amis-editor-core';
import {
BaseEventContext, BaseEventContext,
BasePlugin, BasePlugin,
BasicToolbarItem, BasicToolbarItem,
RendererInfo, RendererInfo,
VRendererConfig VRendererConfig,
getSchemaTpl,
VRenderer,
mapReactElement,
RegionWrapper as Region,
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core'; } from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import React from 'react';
import {VRenderer} from 'amis-editor-core';
import {mapReactElement} from 'amis-editor-core';
import {RegionWrapper as Region} from 'amis-editor-core';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import { import {
getArgsWrapper, getArgsWrapper,
getEventControlConfig getEventControlConfig,
getActionCommonProps
} from '../renderer/event-control/helper'; } from '../renderer/event-control/helper';
export class WizardPlugin extends BasePlugin { export class WizardPlugin extends BasePlugin {
@ -252,15 +251,16 @@ export class WizardPlugin extends BasePlugin {
{ {
actionType: 'submit', actionType: 'submit',
actionLabel: '全部提交', actionLabel: '全部提交',
description: '提交全部数据' description: '提交全部数据',
...getActionCommonProps('submit')
}, },
{ {
actionType: 'stepSubmit', actionType: 'stepSubmit',
actionLabel: '分步提交', actionLabel: '分步提交',
description: '提交当前步骤数据', description: '提交当前步骤数据',
descDetail: (info: any) => { descDetail: (info: any, context: any, props: any) => {
return ( return (
<div> <div className="action-desc">
<span className="variable-right">{info?.__rendererLabel}</span> <span className="variable-right">{info?.__rendererLabel}</span>
</div> </div>
@ -270,21 +270,39 @@ export class WizardPlugin extends BasePlugin {
{ {
actionType: 'prev', actionType: 'prev',
actionLabel: '上一步', actionLabel: '上一步',
description: '返回上一步' description: '返回上一步',
descDetail: (info: any, context: any, props: any) => {
return (
<div className="action-desc">
<span className="variable-right">{info?.rendererLabel}</span>
{info?.__rendererName === 'carousel' ? '滚动至上一张' : null}
{info?.__rendererName === 'wizard' ? '返回前一步' : null}
</div>
);
}
}, },
{ {
actionType: 'next', actionType: 'next',
actionLabel: '下一步', actionLabel: '下一步',
description: '提交当前步骤数据' description: '提交当前步骤数据',
descDetail: (info: any, context: any, props: any) => {
return (
<div className="action-desc">
<span className="variable-right">{info?.rendererLabel}</span>
{info?.__rendererName === 'carousel' ? '滚动至下一张' : null}
{info?.__rendererName === 'wizard' ? '提交当前步骤数据' : null}
</div>
);
}
}, },
{ {
actionType: 'goto-step', actionType: 'goto-step',
actionLabel: '定位步骤', actionLabel: '定位步骤',
description: '切换到指定步骤', description: '切换到指定步骤',
innerArgs: ['step'], innerArgs: ['step'],
descDetail: (info: any) => { descDetail: (info: any, context: any, props: any) => {
return ( return (
<div> <div className="action-desc">
<span className="variable-right">{info?.__rendererLabel}</span> <span className="variable-right">{info?.__rendererLabel}</span>
<span className="variable-left variable-right"> <span className="variable-left variable-right">
@ -308,12 +326,14 @@ export class WizardPlugin extends BasePlugin {
{ {
actionType: 'reload', actionType: 'reload',
actionLabel: '重新加载', actionLabel: '重新加载',
description: '触发组件数据刷新并重新渲染' description: '触发组件数据刷新并重新渲染',
...getActionCommonProps('reload')
}, },
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '变量赋值', actionLabel: '变量赋值',
description: '触发组件数据更新' description: '触发组件数据更新',
...getActionCommonProps('setValue')
} }
]; ];

View File

@ -14,9 +14,10 @@ import React from 'react';
import {ActionConfig, ComponentInfo} from './types'; import {ActionConfig, ComponentInfo} from './types';
import ActionConfigPanel from './action-config-panel'; import ActionConfigPanel from './action-config-panel';
import {BASE_ACTION_PROPS} from './comp-action-select'; import {BASE_ACTION_PROPS} from './comp-action-select';
import {findActionNode} from './helper'; import {findActionNode} from './eventControlConfigHelper';
import {PlainObject, SchemaNode, Option} from 'amis-core'; import {PlainObject, SchemaNode, Option} from 'amis-core';
import {i18n as _i18n} from 'i18n-runtime'; import {i18n as _i18n} from 'i18n-runtime';
import './actionsPanelPlugins';
interface ActionDialogProp { interface ActionDialogProp {
show: boolean; show: boolean;
@ -236,7 +237,7 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
type: 'dialog', type: 'dialog',
title: '动作配置', title: '动作配置',
headerClassName: 'font-bold', headerClassName: 'font-bold',
className: 'action-config-dialog', className: 'ae-action-config-dialog',
bodyClassName: 'action-config-dialog-body', bodyClassName: 'action-config-dialog-body',
closeOnEsc: closeOnEsc, closeOnEsc: closeOnEsc,
closeOnOutside: false, closeOnOutside: false,
@ -322,30 +323,47 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
}, },
{ {
body: [ body: [
{
type: 'tpl',
tpl: '动作说明',
className: 'action-panel-title',
visibleOn: 'this.actionType',
inline: false
},
{
type: 'tpl',
className: 'action-desc',
tpl: '${__actionDesc}',
visibleOn: 'this.actionType'
},
{
type: 'tpl',
tpl: '基础设置',
className: 'action-panel-title',
visibleOn: 'this.actionType',
inline: false
},
{ {
type: 'container', type: 'container',
className: 'right-panel-container', className: 'right-panel-container',
body: [ body: [
{
type: 'container',
className: 'action-panel-title',
body: [
{
type: 'tpl',
tpl: '动作说明',
visibleOn: 'this.actionType'
},
{
type: 'tooltip-wrapper',
content: '${__actionDesc}',
visibleOn: 'this.actionType',
body: {
type: 'icon',
icon: 'far fa-question-circle',
vendor: '',
className: 'ml-0.5'
},
className: 'inline-block ml-0.5 mb-1'
}
]
},
{
name: 'description',
type: 'textarea',
label: '动作描述',
mode: 'horizontal',
visibleOn: 'this.actionType'
},
{
type: 'tpl',
tpl: '基础设置',
className: 'action-panel-title',
visibleOn: 'this.actionType',
inline: false
},
{ {
asFormItem: true, asFormItem: true,
component: ActionConfigPanel, component: ActionConfigPanel,

View File

@ -6,7 +6,8 @@ import {RendererProps, Schema} from 'amis-core';
import {RendererPluginAction} from 'amis-editor-core'; import {RendererPluginAction} from 'amis-editor-core';
import React from 'react'; import React from 'react';
import cx from 'classnames'; import cx from 'classnames';
import {COMMON_ACTION_SCHEMA_MAP, renderCmptActionSelect} from './helper'; import isFunction from 'lodash/isFunction';
import {renderCmptActionSelect} from './helper';
export default class ActionConfigPanel extends React.Component<RendererProps> { export default class ActionConfigPanel extends React.Component<RendererProps> {
render() { render() {
@ -19,10 +20,6 @@ export default class ActionConfigPanel extends React.Component<RendererProps> {
manager manager
} = this.props; } = this.props;
const actionType = data.__subActions ? data.groupType : data.actionType; const actionType = data.__subActions ? data.groupType : data.actionType;
const commonActionConfig = {
...COMMON_ACTION_SCHEMA_MAP,
...actionConfigItemsMap
};
let schema: any = null; let schema: any = null;
if (data.actionType === 'component') { if (data.actionType === 'component') {
@ -30,7 +27,8 @@ export default class ActionConfigPanel extends React.Component<RendererProps> {
const subActionSchema = const subActionSchema =
pluginActions?.[data.__rendererName]?.find( pluginActions?.[data.__rendererName]?.find(
(item: RendererPluginAction) => item.actionType === data.groupType (item: RendererPluginAction) => item.actionType === data.groupType
)?.schema ?? commonActionConfig[data.groupType]?.schema; )?.schema ??
(actionConfigItemsMap && actionConfigItemsMap[data.groupType]?.schema);
const baseSchema = renderCmptActionSelect( const baseSchema = renderCmptActionSelect(
'选择组件', '选择组件',
true, true,
@ -46,7 +44,10 @@ export default class ActionConfigPanel extends React.Component<RendererProps> {
: [subActionSchema]) : [subActionSchema])
]; ];
} else { } else {
schema = data.__actionSchema; const __originActionSchema = data.__actionSchema;
schema = isFunction(__originActionSchema)
? __originActionSchema(manager)
: __originActionSchema;
} }
return schema ? ( return schema ? (

View File

@ -0,0 +1,111 @@
import {RendererPluginAction, EditorManager} from 'amis-editor-core';
const builtInActionsPanel: Array<RendererPluginAction> = [];
export interface ActionLeftPanelTree {
actionType?: string;
actionLabel?: string;
children?: RendererPluginAction | Array<RendererPluginAction>;
}
type ActionPanel = Omit<RendererPluginAction, 'actionType' | 'actionLabel'> & {
label: string;
tag: string;
};
/**
* actionTypeTree
*
* @param actionPanel
*/
const builtInActionPanelData = (
actionType: string,
actionPanel: ActionPanel | undefined
) => {
const {label, description, ...rest} = actionPanel || {};
return {
actionType,
actionLabel: label,
description,
...rest
};
};
/**
*
*
* @param actionPanel
*/
export const registerActionPanel = (
actionType: string,
actionPanel?: ActionPanel
) => {
const {label, tag} = actionPanel || {};
if (!actionType) {
console.warn(`actionType 不能为空`);
return;
}
if (!label || !tag) {
console.warn(`label 或 tag 不能为空`);
return;
}
if (builtInActionsPanel.length === 0) {
builtInActionsPanel.push({
actionType: tag,
actionLabel: tag,
children: [builtInActionPanelData(actionType, actionPanel)]
});
return;
}
const idx = builtInActionsPanel.findIndex(item => item.actionType === tag);
if (idx === -1) {
builtInActionsPanel.push({
actionType: tag,
actionLabel: tag,
children: [builtInActionPanelData(actionType, actionPanel)]
});
} else {
const subActionsPanel = builtInActionsPanel[idx]?.children || [];
const idx2 = subActionsPanel.findIndex(
item => item.actionType === actionType
);
const processData = builtInActionPanelData(actionType, actionPanel);
if (idx2 === -1) {
subActionsPanel.push(processData);
} else {
console.warn(
`存在actionType${actionType}相同的动作面板,将会覆盖原有的动作面板`
);
subActionsPanel.splice(idx2, 1, processData);
}
}
};
/**
*
*
* @param actionType
*/
export const unRegisterActionsPanel = (actionType: string | string[]) => {
if (!Array.isArray(actionType)) {
actionType = [actionType];
}
actionType.forEach(type => {
builtInActionsPanel.forEach((item, index) => {
item.children?.forEach((subItem, index) => {
if (subItem.actionType === type) {
subItem.children?.splice(index, 1);
}
});
});
});
};
export const ACTION_TYPE_TREE = (
manager: EditorManager
): RendererPluginAction[] => {
return builtInActionsPanel;
};

View File

@ -0,0 +1,21 @@
import React from 'react';
import {registerActionPanel} from '../../actionsPanelManager';
import {renderCmptSelect, renderCmptIdInput} from './helper';
import {buildLinkActionDesc} from '../../helper';
registerActionPanel('clear', {
label: '清空表单',
tag: '组件',
description: '清空表单数据',
descDetail: (info: any, context: any, props: any) => {
return (
<div className="action-desc">
{buildLinkActionDesc(props.manager, info)}
</div>
);
},
supportComponents: 'form',
schema: () => [...renderCmptSelect('目标组件', true), renderCmptIdInput()]
});

View File

@ -0,0 +1,10 @@
import {registerActionPanel} from '../../actionsPanelManager';
import {renderCmptActionSelect} from './helper';
registerActionPanel('component', {
label: '组件特性动作',
tag: '组件',
description: '触发所选组件的特性动作',
supportComponents: '*',
schema: () => renderCmptActionSelect('目标组件', true)
});

View File

@ -0,0 +1,135 @@
import {JSONGetById, EditorManager} from 'amis-editor-core';
import {DataSchema} from 'amis-core';
import CmptActionSelect from '../../comp-action-select';
// 下拉展示可赋值属性范围
export const SELECT_PROPS_CONTAINER = ['form'];
export const renderCmptActionSelect = (
componentLabel: string,
required: boolean,
onChange?: (value: string, oldVal: any, data: any, form: any) => void,
hideAutoFill?: boolean,
manager?: EditorManager
) => {
return [
...renderCmptSelect(
componentLabel || '选择组件',
true,
async (value: string, oldVal: any, data: any, form: any) => {
// 获取组件上下文
if (form.data.__nodeId) {
if (form.data.actionType === 'setValue') {
// todo:这里会闪一下需要从amis查下问题
form.setValueByName('args.value', []);
form.setValueByName('args.__comboType', undefined);
form.setValueByName('args.__valueInput', undefined);
form.setValueByName('args.__containerType', undefined);
if (SELECT_PROPS_CONTAINER.includes(form.data.__rendererName)) {
const contextSchema: any = await form.data.getContextSchemas?.(
form.data.__nodeId,
true
);
const dataSchema = new DataSchema(contextSchema || []);
const variables = dataSchema?.getDataPropsAsOptions() || [];
form.setValueByName(
'__setValueDs',
variables.filter(item => item.value !== '$$id')
);
} else {
form.setValueByName('__setValueDs', []);
}
}
}
form.setValueByName('groupType', '');
onChange?.(value, oldVal, data, form);
},
hideAutoFill
),
{
type: 'input-text',
name: '__cmptId',
mode: 'horizontal',
size: 'lg',
required: true,
label: '组件id',
visibleOn:
'this.componentId === "customCmptId" && this.actionType === "component"',
onChange: async (value: string, oldVal: any, data: any, form: any) => {
let schema = JSONGetById(manager!.store.schema, value, 'id');
if (schema) {
form.setValues({
__rendererName: schema.type
});
} else {
form.setValues({
__rendererName: ''
});
}
}
},
{
asFormItem: true,
label: '组件动作',
name: 'groupType',
mode: 'horizontal',
required: true,
visibleOn: 'this.actionType === "component"',
component: CmptActionSelect,
description: '${__cmptActionDesc}'
}
];
};
export const renderCmptSelect = (
componentLabel: string,
required: boolean,
onChange?: (value: string, oldVal: any, data: any, form: any) => void,
hideAutoFill?: boolean
) => [
{
type: 'tree-select',
name: 'componentId',
label: componentLabel || '选择组件',
showIcon: false,
searchable: true,
required,
selfDisabledAffectChildren: false,
size: 'lg',
source: '${__cmptTreeSource}',
mode: 'horizontal',
autoFill: {
__isScopeContainer: '${isScopeContainer}',
...(hideAutoFill
? {}
: {
__rendererLabel: '${label}',
__rendererName: '${type}',
__nodeId: '${id}',
__nodeSchema: '${schema}'
})
},
onChange: async (value: string, oldVal: any, data: any, form: any) => {
onChange?.(value, oldVal, data, form);
}
}
];
export const renderCmptIdInput = (
onChange?: (value: string, oldVal: any, data: any, form: any) => void
) => {
return {
type: 'input-text',
name: '__cmptId',
mode: 'horizontal',
size: 'lg',
required: true,
label: '组件id',
visibleOn: 'this.componentId === "customCmptId"',
onChange: async (value: string, oldVal: any, data: any, form: any) => {
onChange?.(value, oldVal, data, form);
}
};
};

Some files were not shown because too many files have changed in this diff Show More