AdvancedTable
基于FTable封装的表格组件。
- 统一UI样式,未来若样式变更只需升级组件即可,无需侵入业务
- 统一交互行为,如表格头部标题处理,按钮处理,分页查询处理
- 统一编码风格,便于长期维护
与FTable
区别?
此组件适用于页面表格查询场景,仅简化大量通用配置,比如头部标题和按钮组的处理,底部分页信息的维护等,剥离变量维护与相关交互逻辑关注。
非此场景可直接使用FTable
。
说明,
后续会根据通用的业务场景继续扩展,如处理ellipsis+tooltip
,status
等。
排序,过滤等规则也应该固化,以进一步提效,类pagination
固化。
提示
鉴于现有业务暂未完全梳理出可固化的场景,因此AdvancedTable也并未进一步扩展更多业务场景,但是未来可能会有一些逐渐固定下来的东西,届时可进一步丰富AdvancedTable的能力。
业务场景
- 符合UI规范的查询表格场景,多与
SearchForm
组件组合使用。
如何使用
vue
<script setup lang="ts">
import { h, onMounted } from 'vue'
import { useCommonPage } from '@fs/lib'
const { loading, advTable, tableModel } = useCommonPage()
// 表格配置
const tabConfig = {
title: '仓库管理列表',
actions: [
{
label: '新增',
type: 'primary',
icon: 'icon-tianjia2',
// permission: 'WMS.Function.WarehouseManagementNew',
},
{
label: '导出',
icon: 'icon-daochu',
// permission: 'WMS.Function.WarehouseManagementNew',
},
],
columns: [
{
title: '编码',
dataIndex: 'code',
fixed: 'left',
},
{
title: '名称',
dataIndex: 'localName',
customRender: ({ text }: any) => {
return text?.[`zh_CN`]
},
},
{
title: '邮箱',
dataIndex: 'contactEmail',
},
{
title: '操作',
key: 'operation',
fixed: 'right',
// permission: ['WMS.Function.Edit', 'WMS.Function.Delete'],
},
],
}
const query = () => {
loading.value = true
api
.fetchTableList()
.then((res: any) => {
advTable.value.setDataSource(res?.list ?? [], res?.totalCount ?? 0)
})
.finally(() => {
loading.value = false
})
}
const handleAction = (action: any) => {
console.log(action)
}
const handleCreate = (id: string) => {
console.log(id)
}
const handleDelete = (id: string) => {
console.log(id)
}
onMounted(() => {
query()
})
</script>
<template>
<AdvancedTable
ref="advTable"
v-model="tableModel"
:config="tabConfig"
:loading="loading"
:scroll="null"
@query="query"
@action="handleAction"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<f-space :size="12">
<f-button v-permission="'WMS.Function.Edit'" type="link" @click="handleCreate(record.id)"> 编辑 </f-button>
<f-button v-permission="['WMS.Function.Delete']" type="link" @click="handleDelete(record.id)">
删除
</f-button>
</f-space>
</template>
</template>
</AdvancedTable>
</template>
代码示例
基本使用
适用于绝大部分常规业务场景。
<script setup lang="ts">
import { onMounted } from 'vue'
import { message } from '@fs/smart-design'
import { useCommonPage, mockApi } from '@fs/lib'
const { loading, advTable, tableModel } = useCommonPage()
// 表格配置
const tabConfig = {
title: '仓库管理列表',
actions: [
{
label: '新增',
type: 'primary',
icon: 'icon-tianjia2',
// permission: 'WMS.Function.WarehouseManagementNew',
},
{
label: '导出',
icon: 'icon-daochu',
// permission: 'WMS.Function.WarehouseManagementNew',
},
],
columns: [
{
title: '编码',
dataIndex: 'code',
},
{
title: '名称',
dataIndex: 'localName',
customRender: ({ text }: any) => {
return text?.[`zh_CN`]
},
},
{
title: '邮箱',
dataIndex: 'contactEmail',
},
{
title: '操作',
key: 'operation',
fixed: 'right',
// permission: ['WMS.Function.Edit', 'WMS.Function.Delete'],
},
],
}
const query = () => {
loading.value = true
mockApi
.fetchTableList({
currPage: tableModel.value.pagination.current,
pageSize: tableModel.value.pagination.pageSize,
})
.then((res: any) => {
advTable.value?.setDataSource(res?.list || [], res?.totalCount || 0)
})
.finally(() => {
loading.value = false
})
}
const handleAction = (action: any) => {
console.log(action)
message.info(action.label)
}
const handleRowAction = (id: string) => {
console.log(id)
message.info(id)
}
onMounted(() => {
query()
})
</script>
<template>
<AdvancedTable
ref="advTable"
v-model="tableModel"
:config="tabConfig"
:loading="loading"
:scroll="null"
@query="query"
@action="handleAction"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<f-space :size="12">
<!-- v-permission="'WMS.Function.Edit'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 编辑 </f-button>
<!-- v-permission="'WMS.Function.Delete'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 删除 </f-button>
</f-space>
</template>
</template>
</AdvancedTable>
</template>
头部按钮
- 头部按钮支持权限配置
permission
,适用于通过权限控制的按钮,也可以同具名插槽,自定义显示隐藏逻辑。 - 支持
type
,disabled
属性配置,也可通过props
透传,API详见基础组件FButton
。 - 关于按钮icon,推荐通过配置
icon
属性实现(即组件库icon+具体业务icon),详见FIcon
API设计。当然也可通过设置iconfont
属性实现。 - 也可通过配置具名插槽,实现自定义内容,如UI差异很大的按钮,或者不仅仅受权限码控制,还需要其他业务逻辑。
<script setup lang="ts">
import { onMounted, computed } from 'vue'
import { message, FIcon, FButton } from '@fs/smart-design'
import { useCommonPage, p, mockApi } from '@fs/lib'
const { loading, advTable, tableModel } = useCommonPage()
// 表格配置
const tabConfig = {
title: '仓库管理列表',
actions: [
{
label: '新增',
type: 'primary',
icon: 'icon-tianjia2',
// permission: 'WMS.Function.WarehouseManagementNew',
},
{
slot: 'export',
},
// 自定义插槽
{
slot: 'fullScreen',
},
{
slot: 'setColumns',
},
],
columns: [
{
title: '编码',
dataIndex: 'code',
},
{
title: '名称',
dataIndex: 'localName',
customRender: ({ text }: any) => {
return text?.[`zh_CN`]
},
},
{
title: '邮箱',
dataIndex: 'contactEmail',
},
{
title: '操作',
key: 'operation',
fixed: 'right',
// permission: ['WMS.Function.Edit', 'WMS.Function.Delete'],
},
],
}
const query = () => {
loading.value = true
mockApi
.fetchTableList({
currPage: tableModel.value.pagination.current,
pageSize: tableModel.value.pagination.pageSize,
})
.then((res: any) => {
advTable.value?.setDataSource(res?.list ?? [], res?.totalCount ?? 0)
})
.finally(() => {
loading.value = false
})
}
const handleAction = (action: any) => {
console.log(action)
message.info(action.label)
}
const handleRowAction = (id: string) => {
console.log(id)
message.info(id)
}
onMounted(() => {
query()
})
// 自定义显示逻辑 如权限code+业务相关
const isAllowExport = computed(() => {
return p('WMS.Function.WarehouseManagementNew') && p('WMS.Function.WarehouseManagementNew')
})
</script>
<template>
<AdvancedTable
ref="advTable"
v-model="tableModel"
:config="tabConfig"
:loading="loading"
:scroll="null"
@query="query"
@action="handleAction"
>
<template #export>
<FButton v-if="isAllowExport">
<template #icon>
<FIcon type="icon-daochu" />
</template>
导出
</FButton>
</template>
<template #setColumns>
<FButton shape="circle">
<template #icon>
<FIcon type="icon-shezhi1" />
</template>
</FButton>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<f-space :size="12">
<!-- v-permission="'WMS.Function.Edit'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 编辑 </f-button>
<!-- v-permission="'WMS.Function.Delete'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 删除 </f-button>
</f-space>
</template>
</template>
</AdvancedTable>
</template>
完全自定义头部
- 不设置
title
,actions
表头不会出现。 - 如果需要其他表头呈现,可通过
slot:header
实现,也可通过组件组合的方式实现具体业务。
<script setup lang="ts">
import { onMounted } from 'vue'
import { message } from '@fs/smart-design'
import { useCommonPage, mockApi } from '@fs/lib'
const { loading, advTable, tableModel } = useCommonPage()
// 表格配置
const tabConfig = {
pagination: false,
columns: [
{
title: '编码',
dataIndex: 'code',
},
{
title: '名称',
dataIndex: 'localName',
customRender: ({ text }: any) => {
return text?.[`zh_CN`]
},
},
{
title: '邮箱',
dataIndex: 'contactEmail',
},
{
title: '操作',
key: 'operation',
fixed: 'right',
// permission: ['WMS.Function.Edit', 'WMS.Function.Delete'],
},
],
}
const query = () => {
loading.value = true
mockApi
.fetchTableList({
currPage: tableModel.value.pagination.current,
pageSize: tableModel.value.pagination.pageSize,
})
.then((res: any) => {
advTable.value?.setDataSource(res?.list || [], res?.totalCount || 0)
})
.finally(() => {
loading.value = false
})
}
const handleAction = (action: any) => {
console.log(action)
message.info(action.label)
}
const handleRowAction = (id: string) => {
console.log(id)
message.info(id)
}
onMounted(() => {
query()
})
</script>
<template>
<AdvancedTable
ref="advTable"
v-model="tableModel"
:config="tabConfig"
:loading="loading"
:scroll="null"
@query="query"
@action="handleAction"
>
<template #header>
<div>完全自定义header</div>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<f-space :size="12">
<!-- v-permission="'WMS.Function.Edit'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 编辑 </f-button>
<!-- v-permission="'WMS.Function.Delete'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 删除 </f-button>
</f-space>
</template>
</template>
</AdvancedTable>
</template>
直接传入dataSource
可通过直接设置dataSource
,即和FTable
API保持一致,数据源交由父组件。
<script setup lang="ts">
import { useCommonPage } from '@fs/lib'
const { loading, advTable, tableModel } = useCommonPage()
// 表格配置
const tabConfig = {
pagination: false,
columns: [
{
title: '编码',
dataIndex: 'code',
},
{
title: '名称',
dataIndex: 'localName',
customRender: ({ text }: any) => {
return text?.[`zh_CN`]
},
},
{
title: '邮箱',
dataIndex: 'contactEmail',
},
{
title: '操作',
key: 'operation',
fixed: 'right',
// permission: ['WMS.Function.Edit', 'WMS.Function.Delete'],
},
],
}
const dataSource = [
{
id: 0.1435498553846657,
code: 'CS0',
localName: {
zh_CN: '仓库0',
en: 'warehouse0',
},
description: '描述信息~~0~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.47271867926452393,
code: 'CS1',
localName: {
zh_CN: '仓库1',
en: 'warehouse1',
},
description: '描述信息~~1~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.026548785827699595,
code: 'CS2',
localName: {
zh_CN: '仓库2',
en: 'warehouse2',
},
description: '描述信息~~2~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.1810888184874626,
code: 'CS3',
localName: {
zh_CN: '仓库3',
en: 'warehouse3',
},
description: '描述信息~~3~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.8185781857135921,
code: 'CS4',
localName: {
zh_CN: '仓库4',
en: 'warehouse4',
},
description: '描述信息~~4~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.724627050725462,
code: 'CS5',
localName: {
zh_CN: '仓库5',
en: 'warehouse5',
},
description: '描述信息~~5~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.6569273174448551,
code: 'CS6',
localName: {
zh_CN: '仓库6',
en: 'warehouse6',
},
description: '描述信息~~6~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.9928902310845029,
code: 'CS7',
localName: {
zh_CN: '仓库7',
en: 'warehouse7',
},
description: '描述信息~~7~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.028812088717129924,
code: 'CS8',
localName: {
zh_CN: '仓库8',
en: 'warehouse8',
},
description: '描述信息~~8~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
{
id: 0.1844870850704896,
code: 'CS9',
localName: {
zh_CN: '仓库9',
en: 'warehouse9',
},
description: '描述信息~~9~~',
createdBy: '',
createdAt: null,
updatedBy: '潘伟(Buck.Pan)',
updatedAt: '2023-11-28T09:56:18',
},
]
</script>
<template>
<AdvancedTable
ref="advTable"
v-model="tableModel"
:config="tabConfig"
:loading="loading"
:scroll="null"
:dataSource="dataSource"
>
<template #bodyCell="{ column }">
<template v-if="column.key === 'operation'">
<f-space :size="12">
<!-- v-permission="'WMS.Function.Edit'" -->
<f-button type="link"> 编辑 </f-button>
<!-- v-permission="'WMS.Function.Delete'" -->
<f-button type="link"> 删除 </f-button>
</f-space>
</template>
</template>
</AdvancedTable>
</template>
可勾选
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { message } from '@fs/smart-design'
import { useCommonPage, mockApi } from '@fs/lib'
const { loading, advTable, tableModel } = useCommonPage()
// 表格配置
const tabConfig = {
title: '仓库管理列表',
actions: [
{
slot: 'export',
},
{
label: '新增',
type: 'primary',
icon: 'icon-tianjia2',
// permission: 'WMS.Function.WarehouseManagementNew',
},
],
columns: [
{
title: '编码',
dataIndex: 'code',
},
{
title: '名称',
dataIndex: 'localName',
customRender: ({ text }: any) => {
return text?.[`zh_CN`]
},
},
{
title: '邮箱',
dataIndex: 'contactEmail',
},
{
title: '操作',
key: 'operation',
fixed: 'right',
// permission: ['WMS.Function.Edit', 'WMS.Function.Delete'],
},
],
}
const query = () => {
loading.value = true
mockApi
.fetchTableList({
currPage: tableModel.value.pagination.current,
pageSize: tableModel.value.pagination.pageSize,
})
.then((res: any) => {
advTable.value?.setDataSource(res?.list ?? [], res?.totalCount ?? 0)
})
.finally(() => {
loading.value = false
})
}
const handleRowAction = (id: string) => {
console.log(id)
message.info(id)
}
onMounted(() => {
query()
})
// 表格勾选配置项
const selectedRowKeys = ref<string[]>([])
// 表格勾选
function onSelectChange(keys: string[], selectedRows: object[]) {
console.log(keys, selectedRows)
selectedRowKeys.value = keys
}
</script>
<template>
<AdvancedTable
ref="advTable"
v-model="tableModel"
:config="tabConfig"
:loading="loading"
:scroll="null"
:row-selection="{ selectedRowKeys, onChange: onSelectChange }"
@query="query"
>
<template #export>
<f-button :disabled="selectedRowKeys.length <= 0">
<template #icon>
<FIcon type="icon-daochu" />
</template>
导出
</f-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<f-space :size="12">
<!-- v-permission="'WMS.Function.Edit'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 编辑 </f-button>
<!-- v-permission="'WMS.Function.Delete'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 删除 </f-button>
</f-space>
</template>
</template>
</AdvancedTable>
</template>
可展开
<script setup lang="ts">
import { onMounted, getCurrentInstance } from 'vue'
import { message } from '@fs/smart-design'
import { useCommonPage } from '@fs/lib'
const { loading, advTable, tableModel } = useCommonPage()
// 表格配置
const tabConfig = {
title: '仓库管理列表',
columns: [
{
title: '编码',
dataIndex: 'code',
},
{
title: '名称',
dataIndex: 'localName',
customRender: ({ text }: any) => {
return text?.[`zh_CN`]
},
},
{
title: '邮箱',
dataIndex: 'contactEmail',
},
{
title: '操作',
key: 'operation',
fixed: 'right',
// permission: ['WMS.Function.Edit', 'WMS.Function.Delete'],
},
],
}
const $api = getCurrentInstance()?.appContext.config.globalProperties.$api
const query = () => {
loading.value = true
$api
.fetchTableList({
currPage: tableModel.value.pagination.current,
pageSize: tableModel.value.pagination.pageSize,
})
.then((res: any) => {
advTable.value?.setDataSource(res?.list || [], res?.totalCount || 0)
})
.finally(() => {
loading.value = false
})
}
const handleAction = (action: any) => {
console.log(action)
message.info(action.label)
}
const handleRowAction = (id: string) => {
console.log(id)
message.info(id)
}
onMounted(() => {
query()
})
const handleExpand = (expanded: boolean, record: any) => {
console.log(expanded, record)
}
</script>
<template>
<AdvancedTable
ref="advTable"
v-model="tableModel"
:config="tabConfig"
:loading="loading"
:scroll="null"
@query="query"
@action="handleAction"
@expand="handleExpand"
>
<template #expandedRowRender="{ record }">
{{ record.description }}
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'operation'">
<f-space :size="12">
<!-- v-permission="'WMS.Function.Edit'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 编辑 </f-button>
<!-- v-permission="'WMS.Function.Delete'" -->
<f-button type="link" @click="handleRowAction(record.id)"> 删除 </f-button>
</f-space>
</template>
</template>
</AdvancedTable>
</template>
API
参数 | 说明 | 类型 | 默认值 | 版本 |
---|---|---|---|---|
value(v-model) | 表格响应式内容 | object | - | - |
config | 表格配置 | IAdvancedTableConfig | - | - |
说明,config
类型约束如下,其余属性和事件可透传。
ts
export interface IAdvancedTableConfig {
title?: string // 标题
actions?: IAdvancedTableAction[] // 头部操作安妮
columns: Record<string, any>[] // columns
pagination?: boolean | Record<string, any> // 分页器 参考分页器配置
rowKey?: string | ((record: Record<string, any>) => string) // 注意唯一性
}
export interface IAdvancedTableAction {
label: string
type?: string
disabled?: boolean
icon?: string // icon type fs-icon smart-design基础组件库
iconfont?: string // iconfont 业务iconfont
props?: Record<string, any>
slot?: string | ((action: IAdvancedTableAction) => string) // 动态slot
permission?: string | string[] // 权限
}
export interface IAdvancedTableProps {
modelValue?: Record<string, any>
loading?: boolean
dataSource?: Record<string, any>[] // 数据
config: IAdvancedTableConfig
}
说明,
- 拓展了官方
column.ellipsis
属性,true
为一行省略,number
时,最多支持3行省略。
插槽
- header
- action.slot
事件
事件名 | 说明 | 回调参数 | 版本 |
---|---|---|---|
query | 触发表格查询,如分页操作,排序操作 | function(model: object) | - |
change | 分页、排序、筛选变化时触发 | function(pagination, filters, sorter, { currentDataSource }) | - |
action | 表格头部按钮组点击回调 | function(action: any) | - |
init | 表格初始化时回调 | function(modelValue: any) | - |
说明:
方法
方法名 | 说明 | 回调参数 | 版本 |
---|---|---|---|
setDataSource | 写入datas | function(datas: Record<string, any>[], total: number) | - |
getDataSource | 获取datas | function(): Record<string, any>[] | - |