--- title: CRUD 增删改查 description: type: 0 group: ⚙ 组件 menuName: CRUD 增删改查 icon: order: 25 --- CRUD,即增删改查组件,主要用来展现数据列表,并支持各类【增】【删】【改】【查】等操作。 ## 基本用法 最基本的用法是配置 **数据源接口(api)** 以及 **展示列(columns)** ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" }, { "name": "grade", "label": "CSS grade" } ] } ``` ## 数据源接口数据结构要求 - `items`或`rows`:用于返回数据源数据,格式是数组 - `total`: 用于返回数据库中一共有多少条数据,用于生成分页 ```json { "status": 0, "msg": "", "data": { "items": [ { // 每一行的数据 "id": 1, "xxx": "xxxx" } ], "total": 200 // 注意!!!这里不是当前请求返回的 items 的长度,而是数据库中一共有多少条数据,用于生成分页组件 // 如果你不想要分页,把这个不返回就可以了。 } } ``` 如果无法知道数据总数,只能知道是否有下一页,请返回如下格式,amis 会简单生成一个简单版本的分页控件。 ```json { "status": 0, "msg": "", "data": { "items": [ { // 每个成员的数据。 "id": 1, "xxx": "xxxx" } ], "hasNext": true // 是否有下一页。 } } ``` 如果不需要分页,或者配置了 `loadDataOnce` 则可以忽略掉 `total` 和 `hasNext` 参数。 ## 功能 既然这个渲染器叫增删改查,那接下来分开介绍这几个功能吧。 ### 增 其实这个渲染器并不没有包含新增功能,新增功能其实还是依靠其他位置放个弹框表单完成,弹框完事了会自动让页面里面的 CRUD 刷新如: ```schema:height="600" scope="body" [ { "label": "新增", "type": "button", "actionType": "dialog", "level": "primary", "className": "m-b-sm", "dialog": { "title": "新增表单", "body": { "type": "form", "api": "post:/api/sample?waitSeconds=1", "controls": [ { "type": "text", "name": "engine", "label": "Engine" }, { "type": "text", "name": "browser", "label": "Browser" } ] } } }, { "type": "crud", "api": "/api/sample?waitSeconds=1&orderBy=id&orderDir=desc", "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" }, { "name": "grade", "label": "CSS grade" } ] } ] ``` 当然如果你不想要自动刷新,那么给按钮配置 reload: "none" 就行了。 ### 删 删除功能主要有三种实现:[单条操作](#单条操作)、[批量操作](#批量操作)或者直接添加一个操作栏,在里面放个类型为 ajax 类型的按钮即可。在这个按钮里面能获得对应的行数据,而且完成后也会自动刷新这个 CRUD 列表。 ```schema:height="600" scope="body" { "type": "crud", "api": "/api/sample?waitSeconds=1&orderBy=id&orderDir=desc", "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "type": "operation", "label": "操作", "buttons": [ { "label": "删除", "type": "button", "actionType": "ajax", "level": "danger", "confirmText": "确认要删除?", "api": "delete:/api/sample/${id}?waitSeconds=1" } ] } ] } ``` ### 改 改和删其实是差不多的,唯一的区别在于,配置不同的 api,按钮类型改成弹框。 ```schema:height="600" scope="body" { "type": "crud", "api": "/api/sample?waitSeconds=1&orderBy=id&orderDir=desc", "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "type": "operation", "label": "操作", "buttons": [ { "label": "修改", "type": "button", "actionType": "drawer", "drawer": { "title": "新增表单", "body": { "type": "form", "initApi": "/api/sample/${id}", "api": "post:/api/sample/${id}?waitSeconds=1", "controls": [ { "type": "text", "name": "engine", "label": "Engine" }, { "type": "text", "name": "browser", "label": "Browser" } ] } } } ] } ] } ``` 弹框里面可用数据自动就是点击的那一行的行数据,如果列表没有返回,可以在 form 里面再配置个 initApi 初始化数据,如果行数据里面有倒是不需要再拉取了。表单项的 name 跟数据 key 对应上便自动回显了。默认发送给表单的保存接口只会包含配置了的表单项,如果不够,请在 api 上配置数据映射,或者直接添加 hidden 类型的表单项(即隐藏域 input[type=hidden])。 ### 查 查,就不单独介绍了,这个文档绝大部分都是关于查的。 ## 展示模式 CRUD 支持下面 3 种展示模式,默认为 Table 表格模式。 ### Table 表格模式 Table 模式支持 [Table](./table) 中的所有功能。 ```schema:height="700" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample", "syncLocation": false, "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" } ] } ``` ### List 列表模式 List 模式支持 [List](./list) 中的所有功能。 ```schema:height="700" scope="body" { "type": "crud", "api": "raw:https://houtai.baidu.com/api/mock2/crud/permissions", "mode": "list", "placeholder": "当前组内, 还没有配置任何权限.", "syncLocation": false, "title": null, "listItem": { "title": "$name", "subTitle": "$description", "actions": [ { "icon": "fa fa-edit", "tooltip": "编辑", "actionType": "dialog", "dialog": { "title": "编辑能力(权限)", "body": { "type": "form", "controls": [ { "type": "hidden", "name": "id" }, { "name": "name", "label": "权限名称", "type": "text", "disabled": true }, { "type": "divider" }, { "name": "description", "label": "描述", "type": "textarea" } ] } } }, { "tooltip": "删除", "disabledOn": "~[\"admin:permission\", \"admin:user\", \"admin:role\", \"admin:acl\", \"admin:page\", \"page:readAll\", \"admin:settings\"].indexOf(name)", "icon": "fa fa-times", "confirmText": "您确定要移除该权限?", "actionType": "ajax", "api": "delete:https://houtai.baidu.com/api/mock2/notFound" } ] } } ``` ### Cards 卡片模式 Cards 模式支持 [Cards](./cards) 中的所有功能。 ```schema:height="400" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/mock2/crud/users", "syncLocation": false, "mode": "cards", "defaultParams": { "perPage": 6 }, "switchPerPage": false, "placeholder": "没有用户信息", "columnsCount": 2, "card": { "header": { "className": "bg-white", "title": "$name", "subTitle": "$realName", "description": "$email", "avatar": "${avatar | raw}", "highlight": "$isSuperAdmin", "avatarClassName": "pull-left thumb-md avatar b-3x m-r" }, "bodyClassName": "padder", "body": "\n <% if (data.roles && data.roles.length) { %>\n <% data.roles.map(function(role) { %>\n <%- role.name %>\n <% }) %>\n <% } else { %>\n
没有分配角色
\n <% } %>\n ", "actions": [ { "label": "编辑", "actionType": "dialog", "dialog": { "title": null, "body": { "api": "", "type": "form", "tabs": [ { "title": "基本信息", "controls": [ { "type": "hidden", "name": "id" }, { "name": "name", "label": "帐号", "disabled": true, "type": "text" }, { "type": "divider" }, { "name": "email", "label": "邮箱", "type": "text", "disabled": true }, { "type": "divider" }, { "name": "isAmisOwner", "label": "管理员", "description": "设置是否为超级管理", "type": "switch" } ] }, { "title": "角色信息", "controls": [] }, { "title": "设置权限", "controls": [] } ] } } }, { "label": "移除", "confirmText": "您确定要移除该用户?", "actionType": "ajax", "api": "delete:https://houtai.baidu.com/api/mock2/notFound" } ] } } ``` ## 查询条件表单 大部分表格展示有对数据进行检索的需求,CRUD 自身支持通过配置`filter`,实现查询条件过滤表单 `filter` 配置实际上同 [Form](./form/index) 组件,因此支持绝大部分`form`的功能。 ```schema:height="800" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "filter": { "title": "条件搜索", "controls": [ { "type": "text", "name": "keywords", "placeholder": "通过关键字搜索" } ] }, "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" }, { "name": "grade", "label": "CSS grade" } ] } ``` **请注意**:在默认没有自定义配置 api 数据映射时,提交查询条件表单,会自动将表单中的表单项值,发送给`crud`所配置的接口,然后通过后端接口,实现对数据的过滤操作,前端默认是不会进行任何的数据过滤操作 如果想前端实现过滤功能,请看[前端一次性加载](#前端一次性加载)部分。 ## 配置默认请求参数 可以配置`defaultParams`,来指定拉取接口时的默认参数: ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample", "defaultParams": { "perPage": 50 }, "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" }, { "name": "grade", "label": "CSS grade" } ] } ``` 例如上例中,配置`{ perPage: 50 }`,指定分页的默认每页数据条数为 50 条。 ## 数据源接口轮训 可以配置`interval`来实现数据接口轮训功能,默认最低为`3000`毫秒, ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "interval": 3000, "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" }, { "name": "grade", "label": "CSS grade" } ] } ``` 配置`stopAutoRefreshWhen`表达式,来实现满足条件,停止轮训 ## 列配置 除了支持 [Table 中的列配置](./table#%E5%88%97%E9%85%8D%E7%BD%AE) 以外,crud 还支持下面这些配置,帮助更好的操作数据 ### 排序检索 可以在列上配置`"sortable": true`,该列表头右侧会渲染一个可点击的排序图标,可以切换`正序`和`倒序`。 ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine", "sortable": true } ] } ``` amis 只负责生成排序组件,并将排序参数传递给接口,而不会在前端对数据进行排序处理。参数格式如下: ```json { "orderBy": "engine", // 这里为所配置列的 name "orderDir": "asc" // asc 为升序,desc 为降序 } ``` 你可以通过[数据映射](../concepts/data-mapping),在`api`中获取这些参数。 ### 快速搜索 可以在列上配置`"sortable": true`,该列表头右侧会渲染一个可点击的搜索图标,点击可以输入关键字进行该列的搜索: ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine", "searchable": true } ] } ``` amis 只负责生成搜索组件,并将搜索参数传递给接口,而不会在前端对数据进行搜索处理。参数格式如下: ```json { "engine": "xxx" // 这里的key是列的 name,value是输入的关键字 } ``` 你可以通过[数据映射](../concepts/data-mapping),在`api`中获取这些参数。 ### 快速过滤 可以在列上配置`filterable`属性,该列表头右侧会渲染一个可点击的过滤图标,点击显示下拉框,选中进行过滤: ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "columns": [ { "name": "id", "label": "ID" }, { "name": "grade", "label": "CSS grade", "filterable": { "options": [ "A", "B", "C", "D", "X" ] } } ] } ``` amis 只负责生成下拉选择器组件,并将搜索参数传递给接口,而不会在前端对数据进行搜索处理。参数格式如下: ```json { "grade": "xxx" // 这里的key是列的 name,value是选中项的value值 } ``` 你可以通过[数据映射](../concepts/data-mapping),在`api`中获取这些参数。 ### 快速编辑 可以通过给列配置:`"quickEdit":true`和`quickSaveApi` 可以实现表格内快速编辑并批量保存的功能。 如下`Rendering engine`列的每一行中,会生成可编辑图标,点击后会显示弹框,用于编辑该列的值, ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "quickSaveApi": "https://houtai.baidu.com/api/sample/bulkUpdate", "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine", "quickEdit":true } ] } ``` #### 指定编辑表单项类型 `quickEdit`也可以配置对象形式,可以指定编辑表单项的类型,例如`"type": "select"`: ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "quickSaveApi": "https://houtai.baidu.com/api/sample/bulkUpdate", "columns": [ { "name": "id", "label": "ID" }, { "name": "grade", "label": "CSS grade", "quickEdit": { "type": "select", "options": [ "A", "B", "C", "D", "X" ] } } ] } ``` #### 内联模式 配置`quickEdit`的`mode`为`inline`。可以直接将编辑表单项渲染至表格内,可以直接操作编辑。 ```schema:height="750" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "quickSaveApi": "https://houtai.baidu.com/api/sample/bulkUpdate", "columns": [ { "name": "id", "label": "ID" }, { "name": "grade", "label": "CSS grade", "quickEdit": { "mode": "inline", "type": "select", "size": "xs", "options": [ "A", "B", "C", "D", "X" ] } } ] } ``` #### 即时保存 如果想编辑完表单项之后,不想点击顶部确认按钮来进行保存,而是即时保存当前标记的数据,则需要配置`quickEdit`中`"saveImmediately": true`,然后配置接口`quickSaveItemApi`。可以直接将编辑表单项渲染至表格内,可以直接操作编辑。 ```schema:height="750" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "quickSaveItemApi": "https://houtai.baidu.com/api/sample/$id", "columns": [ { "name": "id", "label": "ID" }, { "name": "grade", "label": "CSS grade", "quickEdit": { "mode": "inline", "type": "select", "size": "xs", "options": [ "A", "B", "C", "D", "X" ], "saveImmediately": true } } ] } ``` 你也可以在`saveImmediately`中配置 api,实现即时保存 ```schema:height="750" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "columns": [ { "name": "id", "label": "ID" }, { "name": "grade", "label": "CSS grade", "quickEdit": { "mode": "inline", "type": "select", "size": "xs", "options": [ "A", "B", "C", "D", "X" ], "saveImmediately": { "api": "https://houtai.baidu.com/api/sample/$id" } } } ] } ``` ## 顶部和底部工具栏 crud 组件支持通过配置`headerToolbar`和`footerToolbar`属性,实现在表格顶部和底部渲染组件, ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "headerToolbar": [ { "type": "tpl", "tpl": "一共有${count}条数据" } ], "footerToolbar": [ { "type": "action", "actionType": "dialog", "label": "底部工具栏按钮", "dialog": { "title": "一个弹框", "body": { "type": "tpl", "tpl": "一个简单的弹框" } } } ], "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" }, { "name": "grade", "label": "CSS grade" } ] } ``` 上例中我们在顶部渲染了一段模板,通过`${count}`取到数据域中,CRUD 返回的`count`变量值;然后我们在底部渲染了一个按钮。 从上面一些例子中你可能已经发现,当我们不配置该属性时,crud 默认会在顶部和底部渲染一些组件,实际上,`headerToolbar`和`footerToolbar`默认会有下面这些配置: ```json { "headerToolbar": ["bulkActions", "pagination"], "footerToolbar": ["statistics", "pagination"] } ``` - 在顶部工具栏中:渲染批量操作按钮(如果在 crud 中,配置了 bulkActions 的话)和 分页组件 - 在底部工具栏中:渲染数据统计组件 和 分页组件 > 如果你不希望在顶部或者底部渲染默认组件,你可以设置`headerToolbar`和`footerToolbar`为空数组`[]` 除了可以配置[SchemaNode 类型](../types/schemanode)以外,`headerToolbar`和`footerToolbar`还支持一些针对列表场景而内置的一些常用组件,下面分别介绍: ### 分页 在`headerToolbar`或者`footerToolbar`数组中添加`pagination`字符串,并且在数据源接口中返回了数据总数`count`,即可以渲染分页组件;添加`switch-per-page`字符串,可以渲染切换每页条数组件 ```schema:height="700" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "headerToolbar": [], "footerToolbar": ["switch-per-page", "pagination"], "columns": [ { "name": "id", "label": "ID" }, { "name": "grade", "label": "CSS grade", "quickEdit": { "mode": "inline", "type": "select", "size": "xs", "options": [ "A", "B", "C", "D", "X" ], "saveImmediately": { "api": "https://houtai.baidu.com/api/sample/$id" } } } ] } ``` `crud`默认不会处理数据分页,只是会把分页参数传给后端,由后端实现分页,并返回需要展示的数据 和 总数据数`total`变量: 默认传给后端的分页参数格式为: ```json { "page": 1, "perPage": 10 } ``` 你可以通过配置`pageField`和`perPageField`来修改传给后端的分页数据格式,如: ```json { "pageField": "pageNo", "perPageField": "pageSize" } ``` 这样传给后端的参数格式将为: ```json { "pageNo": 1, "pageSize": 10 } ``` 你可以通过[数据映射](../concepts/data-mapping),在`api`中获取这些参数。 ```json { "type": "crud", "api": { "method": "get", "url": "xxxxxx", "data": { "pageNo": "${page}", "pageSize": "${perPage}", ... // 一些其他参数 } } } ``` 分页有两种模式: ##### 1. 知道数据总数 如果后端可以知道数据总数时,接口返回格式如下: ```json { "status": 0, "msg": "", "data": { "items": [ { // 每一行的数据。 "id": 1, "xxx": "xxxx" } ], "total": 200 // 注意这里不是当前请求返回的 items 的长度,而是数据库一共有多少条数据,用于生成分页, } } ``` 该模式下,会自动计算总页码数,渲染出有页码的分页组件 ##### 2. 不知道数据总数 如果后端无法知道数据总数,那么可以返回`hasNext`字段,来标识是否有下一页。 ```json { "status": 0, "msg": "", "data": { "items": [ { // 每个成员的数据。 "id": 1, "xxx": "xxxx" } ], "hasNext": true // 标识是否有下一页。 } } ``` 这样 amis 会在配置分页组件的地方,渲染出一个简单的页面跳转控件。 ### 批量操作 在`headerToolbar`或者`footerToolbar`数组中添加`bulkActions`字符串,并且在 crud 上配置`bulkActions`行为按钮数组,可以实现选中表格项并批量操作的功能。 > 需要设置`primaryField`用于标识选中状态,配置当前行数据中的某一**唯一标识字段**,例如`id`,否则可能会出现无法选中的问题 ```schema:height="600" scope="body" { "type": "crud", "api": "https://houtai.baidu.com/api/sample?waitSeconds=1", "headerToolbar": [ "bulkActions" ], "bulkActions": [ { "label": "批量删除", "actionType": "ajax", "api": "delete:https://houtai.baidu.com/api/sample/${ids|raw}", "confirmText": "确定要批量删除?" }, { "label": "批量修改", "actionType": "dialog", "dialog": { "title": "批量编辑", "body": { "type": "form", "api": "https://houtai.baidu.com/api/sample/bulkUpdate2", "controls": [ { "type": "hidden", "name": "ids" }, { "type": "text", "name": "engine", "label": "Engine" } ] } } } ], "columns": [ { "name": "id", "label": "ID" }, { "name": "engine", "label": "Rendering engine" }, { "name": "browser", "label": "Browser" }, { "name": "platform", "label": "Platform(s)" }, { "name": "version", "label": "Engine version" }, { "name": "grade", "label": "CSS grade" } ] } ``` 批量操作会默认将下面数据添加到数据域中以供按钮行为使用 - `items` `Array