# CRUD快速集成

# 开始之前

  • 在diboot-antd-admin中,我们对CRUD等常用功能进行了一些抽象,将常用的列表、详情、新建、更新、删除等功能需要的相关属性与方法都抽象成了vue的mixins文件,这些文件在src/components/diboot/mixins文件夹下。
  • 也可以对已有的一些页面组件代码进行阅读,比如src/views/system/iamUser文件夹下的相关组件代码。

TIP

在阅读文档之前,建议您准备好diboot-antd-admin 最新版的环境 (opens new window)源码环境,搭配代码使用更佳。

# 列表页

  1. 引入列表的mixins文件,如下:
import list from '@/components/diboot/mixins/list'

export default {
  mixins: [list]
}
1
2
3
4
5
  1. 配置列表页的接口前缀,这个接口前缀在mixins的处理中,会自动拼接'/list',如果后端代码是通过diboot自动生成的,这也是后端默认的接口规则;
  2. 自定义列表接口:如果您的列表接口最后面不是'/list',而是'/getList',那么可以在data中设置listApi属性,如下:
export default {
  data () {
    return {
        listApi: 'getList'
    }
  }
}
1
2
3
4
5
6
7
  1. 配置columns数据:columns数据是定义该列表页需要显示哪些列的,默认的column只需要配置title与dataIndex属性即可,如下:
export default {
  data () {
    return {
      columns: [
          {
            title: '姓名',
            dataIndex: 'realname'
          }
      ]
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
  1. 属性配置
属性 说明 类型 默认值 版本
baseApi 请求接口基础路径(必须配置) String / -
listApi 列表数据接口 String /list -
deleteApiPrefix 删除接口前缀 String / -
exportApi 导出接口 String /export /excel/export 2.0.5 2.1.x
customQueryParam 自定义参数(不被查询表单重置和改变的参数) object {} -
queryParam 与查询条件绑定的参数(会被查询表单重置和改变的参数) object {} -
dateRangeQuery 日期区间选择配置
时间区间字段请放在这个对象中,会自动构建参与查询
object {} 2.1.x
advanced 高级搜索 展开/关闭 boolean false 2.1.x
data 存储列表数据 array [] -
getMore 是否使mixin在当前业务的attachMore接口中自动获取关联数据
👉业务对象关联详解
boolean false -
attachMoreList 获取关联数据列表的配置列表
👉业务对象关联详解
array [] 2.1.x
more 存储当前对象的关联数据对象
👉业务对象关联详解
object {} -
getListFromMixin 是否在页面初始化时自动加载列表数据 boolean true -
loadingData 标记页面加载数据状态 boolean false -
pagination 分页配置 object {pageSize: 10,current: 1,total: 0,showSizeChanger: true,pageSizeOptions: ['10', '20', '30', '50', '100'],showTotal: (total, range) => 当前显示 ${range[0]} - ${range[1]} 条/共 ${total} 条 } -
  1. 功能函数
名称 说明 参数 版本
handleTableChange 分页、排序、筛选变化时触发 function(pagination, filters, sorter) -
appendSorterParam 构建排序 handleTableChange调用 function(sorter) 2.1.x
toggleAdvanced 切换展示更多搜索框(绑定advanced属性) - 2.1.x
onSearch 搜索,查询第一页(默认查询按钮触发) - -
postList post请求的获取列表(可以传递更长、更复杂参数) - -
getList get请求获取列表 - -
attachMore 加载当前页面关联的对象或者字典,参考属性:getMore、attachMoreList、more - -
reset 重置查询 - -
remove 根据id删除 function(id) -
exportData 导出数据至excel - 2.1.x
downloadFile 下载文件 function(res) 2.1.x
getPopupContainer 解决带有下拉框组件在滚动时下拉框不随之滚动的问题 function(trigger) -
contentTransform 处理查询参数中的moment数据 默认转化为YYYY-MM-DD function(content, transform = {}) 2.1.x
dateRange2queryParam 构建区间查询参数,(转化dateRangeQuery属性内容) - 2.1.x
  1. 钩子函数
名称 说明 参数 版本
afterLoadList 加载数据之后操作 function(list) -
rebuildQuery 重新构建查询条件 (接收已经定义的customQueryParam与queryParam的合并值) function(query) -

# 新建与更新

  1. 引入表单的mixins文件,如下:
import form from '@/components/diboot/mixins/form'

export default {
  mixins: [form]
}
1
2
3
4
5
  1. 属性配置:
属性 说明 类型 默认值 版本
primaryKey 主键字段名 string id 2.1.x
baseApi 请求接口基础路径(必须配置) String / -
createApi 新建接口,自动拼接在baseApi之后 String / -
updateApiPrefix 更新接口前缀,自动拼接在baseApi之后 String / -
labelCol label 默认布局样式 object {xs: {span: 24}, sm: {span: 5}} -
wrapperCol form控件默认布局样式 object {xs: {span: 24}, sm: {span: 16}} -
model 存放form数据 object {} -
title 标题 String 新建/更新 -
more 存储当前对象的关联数据对象
👉业务对象关联详解
object {} -
attachMoreList 获取关联数据列表的配置列表
👉业务对象关联详解
array [] 2.1.x
getMore 是否使mixin在当前业务的attachMore接口中自动获取关联数据
👉业务对象关联详解
boolean false -
state 当前组件状态对象 object {visible: false, confirmSubmit: false} -
isUpload 当前form是否包含上传
👉文件上传详解
boolean false 2.1.x
fileWrapper 文件包装容器
👉文件上传详解
object {} 2.1.x
fileUuidList 文件存储服务器后返回的唯一标识集合
👉文件上传详解
array [] 2.1.x
  1. 功能函数
名称 说明 参数 版本
moment moment时间相关操作 - -
open 打开表单 (根据参数id存在与否,设置为更新or新建操作) function(id) -
close 关闭表单 - -
validate 提交前的验证流程 - -
add 新建记录的提交 function(values) -
update 更新记录的提交 function(values) -
onSubmit 表单提交事件 - -
getPopupContainer 解决带有下拉框组件在滚动时下拉框不随之滚动的问题 function(trigger) -
attachMore 加载当前页面关联的对象或者字典,参考属性:getMore、attachMoreList、more - -
filterOption select选择框启用search功能后的过滤器 - -
clearForm 清除form内容(关闭的时候自动调用) - -
setFileUuidList 设置文件uuid,参考属性:isUpload、fileWrapper、fileUuidList - -
defaultFileWrapperKeys 初始化fileWrapper(关闭时候自动调用) - -
  1. 钩子函数
名称 说明 参数 版本
afterOpen 在组件打开后,或者更新时数据加载完毕后,执行该函数 function(id) -
afterClose 在组件关闭后,执行该函数 - -
enhance 在校验完成后,对提交数据进行处理的函数 function(values) -
submitSuccess 提交成功后,执行该函数,默认关闭该组件,并发送complete和changeKey事件 function(result) -
submitFailed 提交失败后,执行该函数,默认提示错误消息 function(result) -

# 查看详情

  1. 引入表单的mixins文件,如下:
import detail from '@/components/diboot/mixins/detail'

export default {
  mixins: [detail]
}
1
2
3
4
5
  1. 属性配置
属性 说明 类型 默认值 版本
baseApi 请求接口基础路径(必须配置) String / -
visible 当前组件显示状态 String / -
model 当前详情框详情数据 object {} -
title 标题 String 详情 -
spinning loading状态 boolean false -

3.功能函数

名称 说明 参数 版本
open 打开详情(加载服务端数据) function(id) -
close 关闭详情 - -
downloadFile 下载文件(传入接口地址) function(path) 2.1.x
  1. 钩子函数
属性 说明 参数
afterOpen 打开之后的操作 function(id)
afterClose 关闭之后操作 -

# 详解

  • 业务对象关联详解

    • more: 值来源于getMoreattachMoreListattachMoreLoader 配置请求接口后返回的结果;

    • getMore: 开启关联数据会从当前业务的/attachMore接口中读取,可与attachMoreList结合使用;

    • attachMoreList: 实现关联数据从/common/attachMore接口统一获取,配置如下:
      (仅适用于数据量小的统一获取,数据量大建议通过attachMoreLoader获取数据)







       













      // 未指定 label 属性时,为关联字典,指定 label 属性时则为关联对象
      attachMoreList: [
          {
            target: 'GENDER'      // 指向字典 type = GENDER 的字典值
          },
          {
            module: 'user-center',// 模块名(用于cloud指定module,默认当前module)
            target: 'IamUser',    // 指向IamUser对象(cloud:指定module中对象)
            alias: 'iamUserList', // 指定别名(默认为:target的小驼峰+Options)since v2.5.0
            label: 'name',        // 指向IamUser#name属性,需要查询作为label的属性名称
            value: 'id',          // 指向IamUser#id属性,需要查询作为value的属性名称
            ext: 'userNum',       // 指向IamUser#userNum,需要查询作为ext的属性名称 (扩展值,一般用于特殊情景)
            condition: {          // 筛选条件,多个条件and连接(选项的过滤条件,用于特殊场景扩展)
              status: 'A',           // 状态为A的 在职(A)员工(后端SQL是eq比较)
              orgId: [1,2,3],        // 组织ID是 1或2或3 的用户(后端SQL是in查询)
              email: null            // 邮箱为空的用户(后端SQL是is null)
            }
          }
      ]
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      • 特殊场景attachMore的condition无法满足时,可通过开启getMore结合当前业务的/attachMore接口获取数据;如需要全局自定义筛选条件规则,后端可尝试重写BaseController#buildAttachMoreCondition方法,自定义筛选条件规则。
      • attachMoreList 返回值会自动绑定至more属性中,上述配置样例返回值为(⚠️data的key默认规则是上述target的小驼峰命名 + Options):
        {
            "code":0,
            "data":{
                "genderOptions":[
                    {
                        "label":"女",
                        "value":"F"
                    },
                    {
                        "label":"男",
                        "value":"M"
                    }
                ],
                "iamUserList":[
                    {
                        "label":"超级管理员",
                        "value":10000,
                        "ext": '000'
                    }
                ]
            },
            "msg":"操作成功"
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
    • attachMoreLoader:实现关联数据从/common/attachMoreFilter接口获取(since v2.4.0

      • 仅支持 attachMoreList 中的关联表数据过滤获取,规则与其相同


         












        attachMoreLoader: {
            iamUser: {
                module: 'user-center',// 模块名(用于cloud指定module,默认当前module)
                target: 'IamUser',    // 指向IamUser对象(cloud:指定module中对象)
                label: 'name',        // 指向IamUser#name属性,需要查询作为label的属性名称
                value: 'id',          // 指向IamUser#id属性,需要查询作为value的属性名称
                ext: 'userNum',       // 指向IamUser#userNum,需要查询作为ext的属性名称 (扩展值,一般用于特殊情景)
                condition: {          // 筛选条件,多个条件and连接(选项的过滤条件,用于特殊场景扩展)
                  status: 'A',           // 状态为A的 在职(A)员工(后端SQL是eq比较)
                  orgId: [1,2,3],        // 组织ID是 1或2或3 的用户(后端SQL是in查询)
                  email: null            // 邮箱为空的用户(后端SQL是is null)
                }
            }
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
      • 示例(远程搜索)





         
         
         
         


         


















         
         
         
         
         
         
         
         





        <template>
          <a-select
            v-model="form.userId"
            placeholder="请输入用户姓名"
            allow-clear
            show-search
            :show-arrow="false"
            :filter-option="false"
            @search="value => attachMoreFilter(value, 'iamUser')"
            @change="onSearch"
          >
            <a-spin v-if="attachMoreLoading" slot="notFoundContent" size="small" />
            <a-select-option
              v-for="(item, index) in more.iamUserOptions || []"
              :key="index"
              :value="item.value"
            >
              {{ item.label }}
            </a-select-option>
          </a-select>
        </template>
        
        <script>
        import form from '@/components/diboot/mixins/form'
        
        export default {
          name: 'Form',
          mixins: [form],
          data () {
            return {
              attachMoreLoader: {
                iamUser: {
                  module: 'user-center'
                  target: 'IamUser',
                  label: 'name',
                  value: 'id'
                }
              }
            }
          }
        }
        </script>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
    • lazyLoadMore:异步加载(Cascader/TreeSelect

      • 示例



         















         
         
         
         
         
         
         
         
         
         
         






        <template>
          <a-cascader
           :options="(more.cascaderOptions||[]).map(e=>{e.isLeaf= false;return e})"
           :load-data="node => lazyLoadMore(node, 'cascader')"
          />
        </template>
        <script>
        export default {
          data () {
            return {
              attachMoreList: [
                { // 加载组织树第一层(因lazy默认未true)
                  alias: 'cascaderOptions', // 别名
                  target: 'IamOrg',
                  label: 'name',
                  tree: true
                }
              ],
              attachMoreLoader: {
                cascader: {
                  target: 'IamOrg',
                  label: 'name',
                  parent: 'parentId',
                  tree: true,
                  next: { // 下一层关联数据
                    target: 'IamUser',
                    label: 'realname',
                    parent: 'orgId' // 当前对象存储父级ID属性名
                  }
                }
              }
            }
          }
        }
        </script>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
    • controlRelationOptions:选项联动(多个选择器层级受控)

      • 示例






         







         
         
         
         

         






























         


         



         
         
         
         
         
         
         
         






        <template>
          <a-form layout="vertical" :form="form">
            <a-form-item label="联动(父)">
              <a-cascader
                :options="more.iamOrgOptions"
                v-decorator="[ 'orgId', { initialValue: model.orgId } ]"
                @change="value=> controlRelationOptions(value[value.length-1], 'controlUser')"
              />
            </a-form-item>
            <a-form-item label="联动(子)">
              <a-select
                v-decorator="[ 'userId', { initialValue: model.userId } ]"
                placeholder="请输入用户姓名"
                allow-clear
                show-search
                :show-arrow="false"
                :filter-option="false"
                @search="value => attachMoreFilter(value, 'user')"
              >
                <a-spin v-if="attachMoreLoading" slot="notFoundContent" size="small" />
                <a-select-option
                  v-for="(item, index) in more.userOptions || []"
                  :key="index"
                  :value="item.value"
                >
                  {{ item.label }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-form>
        </template>
        
        <script>
        import form from '@/components/diboot/mixins/form'
        export default {
          name: 'Form',
          mixins: [form],
          data () {
            return {
              form: this.$form.createForm(this),
              attachMoreList: [
                {
                  target: 'IamOrg',
                  label: 'name',
                  parent: 'parentId', // tree为true时,parent默认为parentId,可省略不写
                  tree: true,
                  lazy: false
                }
              ],
              attachMoreLoader: {
                user: {
                  target: 'IamUser',
                  label: 'realname',
                  disabled: true // 受控的远程搜索需默认禁用
                }
              },
              control: {
                controlUser: [ // 单个时可为对象多个时为数组
                  {
                    name: 'userId', // 受控的属性名
                    loader: 'user', // 选项加载器
                    condition: 'orgId', // 加载器条件属性
                    lazy: true // 远程搜索异步加载(可选)
                  }
                ]
              }
            }
          }
        }
        </script>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
  • 文件上传详解(since v2.1.x

    以下属性讲解,基于Upload组件 👉 Upload.vue组件概述

    • isUpload: 标记当前form表单中是否包含上传属性,使用如:图片、文件,默认不包含,如果引入组件,请手动开启:
     data() {
       return {
         isUpload: true
       }
     }
    
    1
    2
    3
    4
    5
    • fileWrapper: 所有文件的集合都放置与fileWrapper对象中,提交的时候会自动遍历,然后提交至服务端进行数据处理:
      • template内容




       








      <upload
        v-if="state.visible"
        :prefix="filePrefix"
        :action="fileAction"
        :file-list="fileWrapper.slideshowImgsList"
        :rel-obj-type="relObjType"
        rel-obj-field="slideshowImgs"
        :limit-count="9"
        :is-image="true"
        list-type="picture-card"
        v-model="form.slideshowImgs"
      ></upload>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      • script内容
        data() {
          return {
            // 包含属性
            fileWrapper: {
             //存储form.slideshowImgs属性对应的文件集合
             slideshowImgsList: []
            }
          }
        }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
    • fileUuidList: 如果包含上传,那么会自动构建文件的提交数据用于绑定当前对象