diff --git a/docs/zh-CN/components/crud.md b/docs/zh-CN/components/crud.md index 62dc42d5dd5..cc45a7d7276 100755 --- a/docs/zh-CN/components/crud.md +++ b/docs/zh-CN/components/crud.md @@ -207,12 +207,13 @@ CRUD 组件对数据源接口的数据结构要求如下: `syncLocation`开启后,CRUD 在初始化数据域时,将会对 url 中的 Query 进行转换,将原始类型的字符串格式的转化为同位类型。`3.6.0`版本后支持对象格式,该配置默认开启,且默认仅转化布尔值。 #### ParsePrimitiveQueryOptions + ```typescript interface ParsePrimitiveQueryOptions { parsePrimitiveQuery: { enable: boolean; - types?: ('boolean' | 'number')[] - } + types?: ('boolean' | 'number')[]; + }; } ``` @@ -225,7 +226,7 @@ interface ParsePrimitiveQueryOptions { "123.4" ==> 123.4 ``` -如果只想保持字符串格式,可以设置`"parsePrimitiveQuery": false` 或者 `"parsePrimitiveQuery": {"enable": false}` 关闭该特性,具体效果参考[示例](../../../examples/crud/parse-primitive-query)。如果想实现字段定制化转化类型,可以使用[配置API请求数据](../../docs/types/api#配置请求数据),通过表达式控制接口传递的参数类型。 +如果只想保持字符串格式,可以设置`"parsePrimitiveQuery": false` 或者 `"parsePrimitiveQuery": {"enable": false}` 关闭该特性,具体效果参考[示例](../../../examples/crud/parse-primitive-query)。如果想实现字段定制化转化类型,可以使用[配置 API 请求数据](../../docs/types/api#配置请求数据),通过表达式控制接口传递的参数类型。 ## 功能 @@ -2923,12 +2924,13 @@ interface CRUDMatchFunc { 它其实是个简化的 `button` 组件,可以参考 `button` 组件的文档做调整。 -#### 刷新CRUD触发方式 +#### 刷新 CRUD 触发方式 -触发CRUD刷新的方式有3种: -1. **reload类型按钮**:使用`{"type": "reload", ...}`,CRUD内部会对点击事件做处理 -2. **reload动作按钮**:使用`{"type": "action", "actionType": "reload", "target": "targetName", ...}`,指定`target`为要刷新的CRUD组件的`name` -3. **reload事件动作**:使用[事件动作](../../docs/concepts/event-action),指定`id`为要刷新的CRUD组件的`id` +触发 CRUD 刷新的方式有 3 种: + +1. **reload 类型按钮**:使用`{"type": "reload", ...}`,CRUD 内部会对点击事件做处理 +2. **reload 动作按钮**:使用`{"type": "action", "actionType": "reload", "target": "targetName", ...}`,指定`target`为要刷新的 CRUD 组件的`name` +3. **reload 事件动作**:使用[事件动作](../../docs/concepts/event-action),指定`id`为要刷新的 CRUD 组件的`id` ```schema { @@ -3626,13 +3628,13 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据, | footerToolbar | Array | `['statistics', 'pagination']` | 底部工具栏配置 | | alwaysShowPagination | `boolean` | `false` | 是否总是显示分页 | | affixHeader | `boolean` | `true` | 是否固定表头(table 下) | +| affixFooter | `boolean` | `false` | 是否固定表格底部工具栏 | | autoGenerateFilter | `Object \| boolean` | | 是否开启查询区域,开启后会根据列元素的 `searchable` 属性值,自动生成查询条件表单 | | resetPageAfterAjaxItemAction | `boolean` | `false` | 单条数据 ajax 操作后是否重置页码为第一页 | | autoFillHeight | `boolean` 丨 `{height: number}` | | 内容区域自适应高度 | | canAccessSuperData | `boolean` | `true` | 指定是否可以自动获取上层的数据并映射到表格行数据上,如果列也配置了该属性,则列的优先级更高 | | matchFunc | `string` | [`CRUDMatchFunc`](#匹配函数) | 自定义匹配函数, 当开启`loadDataOnce`时,会基于该函数计算的匹配结果进行过滤,主要用于处理列字段类型较为复杂或者字段值格式和后端返回不一致的场景 | `3.5.0` | -| parsePrimitiveQuery | [`ParsePrimitiveQueryOptions`](#ParsePrimitiveQueryOptions) | `true` | 是否开启Query信息转换,开启后将会对url中的Query进行转换,默认开启,默认仅转化布尔值 | `3.6.0` | - +| parsePrimitiveQuery | [`ParsePrimitiveQueryOptions`](#ParsePrimitiveQueryOptions) | `true` | 是否开启 Query 信息转换,开启后将会对 url 中的 Query 进行转换,默认开启,默认仅转化布尔值 | `3.6.0` | 注意除了上面这些属性,CRUD 在不同模式下的属性需要参考各自的文档,比如 diff --git a/docs/zh-CN/components/table.md b/docs/zh-CN/components/table.md index 639d6fb80fe..ed7c69266f7 100755 --- a/docs/zh-CN/components/table.md +++ b/docs/zh-CN/components/table.md @@ -1832,6 +1832,7 @@ popOver 的其它配置请参考 [popover](./popover) | source | `string` | `${items}` | 数据源, 绑定当前环境变量 | | | deferApi | [API](../../docs/types/api) | | 当行数据中有 defer 属性时,用此接口进一步加载内容 | | affixHeader | `boolean` | `true` | 是否固定表头 | | +| affixFooter | `boolean` | `false` | 是否固定表格底部工具栏 | | | columnsTogglable | `auto` 或者 `boolean` | `auto` | 展示列显示开关, 自动即:列数量大于或等于 5 个时自动开启 | | | placeholder | `string` 或者 `SchemaTpl` | `暂无数据` | 当没数据的时候的文字提示 | | | className | `string` | `panel-default` | 外层 CSS 类名 | | diff --git a/packages/amis-ui/scss/components/_cards.scss b/packages/amis-ui/scss/components/_cards.scss index e040e04f357..6ad5329de14 100644 --- a/packages/amis-ui/scss/components/_cards.scss +++ b/packages/amis-ui/scss/components/_cards.scss @@ -1,7 +1,8 @@ .#{$ns}Cards { &-toolbar { @include clearfix(); - margin: 0 var(--Cards-toolbar-marginX) var(--Cards-toolbar-marginY); + padding: var(--Cards-toolbar-marginY) var(--Cards-toolbar-marginX) + var(--Cards-toolbar-marginY); } &-actions { @@ -95,6 +96,14 @@ flex: unset; } } + + &-footToolbar--affix, + &-footer--affix { + position: sticky; + bottom: var(--affix-offset-bottom); + background: var(--Table-bg); + z-index: $zindex-sticky; + } } @include media-breakpoint-up(sm) { diff --git a/packages/amis-ui/scss/components/_list.scss b/packages/amis-ui/scss/components/_list.scss index 340728314d6..ac124bfb63e 100644 --- a/packages/amis-ui/scss/components/_list.scss +++ b/packages/amis-ui/scss/components/_list.scss @@ -12,7 +12,8 @@ @include clearfix(); display: flex; flex-wrap: wrap; - margin: 0 var(--List-toolbar-marginX) var(--List-toolbar-marginY); + padding: var(--List-toolbar-marginY) var(--List-toolbar-marginX) + var(--List-toolbar-marginY); } &-actions { @@ -78,6 +79,14 @@ min-height: var(--List-placeholder-height); line-height: var(--List-placeholder-height); } + + &-footToolbar--affix, + &-footer--affix { + position: sticky; + bottom: var(--affix-offset-bottom); + background: var(--Table-bg); + z-index: $zindex-sticky; + } } .#{$ns}ListGroup { diff --git a/packages/amis-ui/scss/components/_table.scss b/packages/amis-ui/scss/components/_table.scss index 5751d983a16..9c72b23d36e 100644 --- a/packages/amis-ui/scss/components/_table.scss +++ b/packages/amis-ui/scss/components/_table.scss @@ -143,6 +143,14 @@ } } + &-footerToolbar--affix, + &-footer--affix { + position: sticky; + bottom: var(--affix-offset-bottom); + background: var(--Table-bg); + z-index: $zindex-sticky; + } + &.is-mobile { .#{$ns}Table-toolbar { .#{$ns}Form-item { diff --git a/packages/amis/src/renderers/Cards.tsx b/packages/amis/src/renderers/Cards.tsx index de31601bf84..d9875d4a9c2 100644 --- a/packages/amis/src/renderers/Cards.tsx +++ b/packages/amis/src/renderers/Cards.tsx @@ -104,6 +104,11 @@ export interface CardsSchema extends BaseSchema, SpinnerExtraProps { */ affixHeader?: boolean; + /** + * 是否固底 + */ + affixFooter?: boolean; + /** * 顶部区域 */ @@ -735,7 +740,8 @@ export default class Cards extends React.Component { render, showFooter, store, - classnames: cx + classnames: cx, + affixFooter } = this.props; if (showFooter === false) { @@ -755,18 +761,33 @@ export default class Cards extends React.Component { : null; const actions = this.renderActions('footer'); + const footerNode = footer ? ( +
+ {render('footer', footer)} +
+ ) : null; + const toolbarNode = actions || child ? ( -
+
{actions} {child}
) : null; - const footerNode = footer ? ( -
- {render('footer', footer)} -
- ) : null; + return footerNode && toolbarNode ? [toolbarNode, footerNode] : footerNode || toolbarNode || null; diff --git a/packages/amis/src/renderers/List.tsx b/packages/amis/src/renderers/List.tsx index f2768a5e050..c291ea79b12 100644 --- a/packages/amis/src/renderers/List.tsx +++ b/packages/amis/src/renderers/List.tsx @@ -202,6 +202,11 @@ export interface ListSchema extends BaseSchema { */ affixHeader?: boolean; + /** + * 是否固底 + */ + affixFooter?: boolean; + /** * 配置某项是否可以点选 */ @@ -810,7 +815,8 @@ export default class List extends React.Component { render, showFooter, store, - classnames: cx + classnames: cx, + affixFooter } = this.props; if (showFooter === false) { @@ -830,22 +836,35 @@ export default class List extends React.Component { : null; const actions = this.renderActions('footer'); + const footerNode = + footer && (!Array.isArray(footer) || footer.length) ? ( +
+ {render('footer', footer)} +
+ ) : null; + const toolbarNode = actions || child ? (
{actions} {child}
) : null; - const footerNode = - footer && (!Array.isArray(footer) || footer.length) ? ( -
- {render('footer', footer)} -
- ) : null; + return footerNode && toolbarNode ? [toolbarNode, footerNode] : footerNode || toolbarNode || null; diff --git a/packages/amis/src/renderers/Table/index.tsx b/packages/amis/src/renderers/Table/index.tsx index 3f2cf8037f4..2ecdcc0caa0 100644 --- a/packages/amis/src/renderers/Table/index.tsx +++ b/packages/amis/src/renderers/Table/index.tsx @@ -222,6 +222,11 @@ export interface TableSchema extends BaseSchema { */ affixHeader?: boolean; + /** + * 是否固底 + */ + affixFooter?: boolean; + /** * 表格的列信息 */ @@ -2544,7 +2549,8 @@ export default class Table extends React.Component { showFooter, store, data, - classnames: cx + classnames: cx, + affixFooter } = this.props; if (showFooter === false) { @@ -2564,13 +2570,30 @@ export default class Table extends React.Component { : null; const actions = this.renderActions('footer'); + const footerNode = + footer && (!Array.isArray(footer) || footer.length) ? ( +
+ {render('footer', footer, { + data: store.getData(data) + })} +
+ ) : null; + const toolbarNode = actions || child ? (
@@ -2578,14 +2601,6 @@ export default class Table extends React.Component { {child}
) : null; - const footerNode = - footer && (!Array.isArray(footer) || footer.length) ? ( -
- {render('footer', footer, { - data: store.getData(data) - })} -
- ) : null; return footerNode && toolbarNode ? [toolbarNode, footerNode] : footerNode || toolbarNode || null;