feat: Table重构

This commit is contained in:
kailong321200875 2023-07-10 17:46:15 +08:00
parent 002d03a0ad
commit 94800b0120
13 changed files with 576 additions and 308 deletions

View File

@ -142,6 +142,14 @@ const adminList = [
title: 'UseTable' title: 'UseTable'
} }
}, },
{
path: 'tree-table',
component: 'views/Components/Table/TreeTable',
name: 'TreeTable',
meta: {
title: 'TreeTable'
}
},
{ {
path: 'ref-table', path: 'ref-table',
component: 'views/Components/Table/RefTable', component: 'views/Components/Table/RefTable',
@ -481,6 +489,7 @@ const testList: string[] = [
'/components/table', '/components/table',
'/components/table/default-table', '/components/table/default-table',
'/components/table/use-table', '/components/table/use-table',
'/components/table/tree-table',
'/components/table/ref-table', '/components/table/ref-table',
'/components/editor-demo', '/components/editor-demo',
'/components/editor-demo/editor', '/components/editor-demo/editor',

View File

@ -12,7 +12,7 @@ const count = 100
const baseContent = const baseContent =
'<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>' '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
let List: { interface ListProps {
id: string id: string
author: string author: string
title: string title: string
@ -20,7 +20,20 @@ let List: {
importance: number importance: number
display_time: string display_time: string
pageviews: number pageviews: number
}[] = [] }
interface TreeListProps {
id: string
author: string
title: string
content: string
importance: number
display_time: string
pageviews: number
children: TreeListProps[]
}
let List: ListProps[] = []
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
List.push( List.push(
@ -38,7 +51,114 @@ for (let i = 0; i < count; i++) {
) )
} }
const treeList: TreeListProps[] = []
for (let i = 0; i < count; i++) {
treeList.push(
Mock.mock({
id: toAnyString(),
// timestamp: +Mock.Random.date('T'),
author: '@first',
title: '@title(5, 10)',
content: baseContent,
importance: '@integer(1, 3)',
display_time: '@datetime',
pageviews: '@integer(300, 5000)',
children: [
{
id: toAnyString(),
// timestamp: +Mock.Random.date('T'),
author: '@first',
title: '@title(5, 10)',
content: baseContent,
importance: '@integer(1, 3)',
display_time: '@datetime',
pageviews: '@integer(300, 5000)',
children: [
{
id: toAnyString(),
// timestamp: +Mock.Random.date('T'),
author: '@first',
title: '@title(5, 10)',
content: baseContent,
importance: '@integer(1, 3)',
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
},
{
id: toAnyString(),
// timestamp: +Mock.Random.date('T'),
author: '@first',
title: '@title(5, 10)',
content: baseContent,
importance: '@integer(1, 3)',
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
}
]
},
{
id: toAnyString(),
// timestamp: +Mock.Random.date('T'),
author: '@first',
title: '@title(5, 10)',
content: baseContent,
importance: '@integer(1, 3)',
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
},
{
id: toAnyString(),
// timestamp: +Mock.Random.date('T'),
author: '@first',
title: '@title(5, 10)',
content: baseContent,
importance: '@integer(1, 3)',
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
},
{
id: toAnyString(),
// timestamp: +Mock.Random.date('T'),
author: '@first',
title: '@title(5, 10)',
content: baseContent,
importance: '@integer(1, 3)',
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
}
]
// image_uri
})
)
}
export default [ export default [
// 树形列表接口
{
url: '/example/treeList',
method: 'get',
timeout,
response: ({ query }) => {
const { title, pageIndex, pageSize } = query
const mockList = treeList.filter((item) => {
if (title && item.title.indexOf(title) < 0) return false
return true
})
const pageList = mockList.filter(
(_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1)
)
return {
data: {
code: code,
data: {
total: mockList.length,
list: pageList
}
}
}
}
},
// 列表接口 // 列表接口
{ {
url: '/example/list', url: '/example/list',

View File

@ -5,6 +5,10 @@ export const getTableListApi = (params: any) => {
return request.get({ url: '/example/list', params }) return request.get({ url: '/example/list', params })
} }
export const getTreeTableListApi = (params: any) => {
return request.get({ url: '/example/treeList', params })
}
export const saveTableApi = (data: Partial<TableData>): Promise<IResponse> => { export const saveTableApi = (data: Partial<TableData>): Promise<IResponse> => {
return request.post({ url: '/example/save', data }) return request.post({ url: '/example/save', data })
} }

View File

@ -1,6 +1,6 @@
import Table from './src/Table.vue' import Table from './src/Table.vue'
import { ElTable } from 'element-plus' import { ElTable } from 'element-plus'
import { TableSetProps } from './src/types' import { TableColumn, TableSetProps } from './src/types'
export type { export type {
TableColumn, TableColumn,
@ -13,6 +13,8 @@ export type {
export interface TableExpose { export interface TableExpose {
setProps: (props: Recordable) => void setProps: (props: Recordable) => void
setColumn: (columnProps: TableSetProps[]) => void setColumn: (columnProps: TableSetProps[]) => void
addColumn: (column: TableColumn, index?: number) => void
delColumn: (field: string) => void
selections: Recordable[] selections: Recordable[]
elTableRef: ComponentRef<typeof ElTable> elTableRef: ComponentRef<typeof ElTable>
} }

View File

@ -6,14 +6,13 @@ import { setIndex } from './helper'
import type { TableProps, TableColumn, Pagination, TableSetProps } from './types' import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
import { set } from 'lodash-es' import { set } from 'lodash-es'
import { CSSProperties } from 'vue' import { CSSProperties } from 'vue'
import { getSlot } from '@/utils/tsxHelper'
export default defineComponent({ export default defineComponent({
name: 'Table', name: 'Table',
props: { props: {
pageSize: propTypes.number.def(10), pageSize: propTypes.number.def(10),
currentPage: propTypes.number.def(1), currentPage: propTypes.number.def(1),
//
selection: propTypes.bool.def(true),
// schemashowOverflowTooltip, // schemashowOverflowTooltip,
showOverflowTooltip: propTypes.bool.def(true), showOverflowTooltip: propTypes.bool.def(true),
// //
@ -49,7 +48,7 @@ export default defineComponent({
height: propTypes.oneOfType([Number, String]), height: propTypes.oneOfType([Number, String]),
maxHeight: propTypes.oneOfType([Number, String]), maxHeight: propTypes.oneOfType([Number, String]),
stripe: propTypes.bool.def(false), stripe: propTypes.bool.def(false),
border: propTypes.bool.def(false), border: propTypes.bool.def(true),
size: { size: {
type: String as PropType<ComponentSize>, type: String as PropType<ComponentSize>,
validator: (v: ComponentSize) => ['medium', 'small', 'mini'].includes(v) validator: (v: ComponentSize) => ['medium', 'small', 'mini'].includes(v)
@ -103,10 +102,7 @@ export default defineComponent({
>, >,
default: () => undefined default: () => undefined
}, },
rowKey: { rowKey: propTypes.string.def('id'),
type: [Function, String] as PropType<(row: Recordable) => string | string>,
default: () => 'id'
},
emptyText: propTypes.string.def('No Data'), emptyText: propTypes.string.def('No Data'),
defaultExpandAll: propTypes.bool.def(false), defaultExpandAll: propTypes.bool.def(false),
expandRowKeys: { expandRowKeys: {
@ -164,7 +160,7 @@ export default defineComponent({
default: () => undefined default: () => undefined
}, },
treeProps: { treeProps: {
type: Object as PropType<{ hasChildren: string; children: string; label: string }>, type: Object as PropType<{ hasChildren?: string; children?: string; label?: string }>,
default: () => ({ hasChildren: 'hasChildren', children: 'children', label: 'label' }) default: () => ({ hasChildren: 'hasChildren', children: 'children', label: 'label' })
}, },
tableLayout: { tableLayout: {
@ -175,7 +171,7 @@ export default defineComponent({
flexible: propTypes.bool.def(false) flexible: propTypes.bool.def(false)
}, },
emits: ['update:pageSize', 'update:currentPage', 'register'], emits: ['update:pageSize', 'update:currentPage', 'register'],
setup(props, { attrs, emit, expose }) { setup(props, { attrs, emit, slots, expose }) {
const elTableRef = ref<ComponentRef<typeof ElTable>>() const elTableRef = ref<ComponentRef<typeof ElTable>>()
// //
@ -217,6 +213,23 @@ export default defineComponent({
} }
} }
const addColumn = (column: TableColumn, index?: number) => {
const { columns } = unref(getProps)
if (index) {
columns.splice(index, 0, column)
} else {
columns.push(column)
}
}
const delColumn = (field: string) => {
const { columns } = unref(getProps)
const index = columns.findIndex((item) => item.field === field)
if (index > -1) {
columns.splice(index, 1)
}
}
const selections = ref<Recordable[]>([]) const selections = ref<Recordable[]>([])
const selectionChange = (selection: Recordable[]) => { const selectionChange = (selection: Recordable[]) => {
@ -226,6 +239,8 @@ export default defineComponent({
expose({ expose({
setProps, setProps,
setColumn, setColumn,
delColumn,
addColumn,
selections, selections,
elTableRef elTableRef
}) })
@ -275,42 +290,17 @@ export default defineComponent({
) )
const getBindValue = computed(() => { const getBindValue = computed(() => {
const bindValue: Recordable = { ...attrs, ...props } const bindValue: Recordable = { ...attrs, ...unref(getProps) }
delete bindValue.columns delete bindValue.columns
delete bindValue.data delete bindValue.data
console.log(bindValue)
return bindValue return bindValue
}) })
const renderTableSelection = () => {
const { selection, reserveSelection, align, headerAlign } = unref(getProps)
//
return selection ? (
<ElTableColumn
type="selection"
reserveSelection={reserveSelection}
align={align}
headerAlign={headerAlign}
width="50"
></ElTableColumn>
) : undefined
}
// const renderTableExpand = () => {
// const { align, headerAlign, expand } = unref(getProps)
// //
// return expand ? (
// <ElTableColumn type="expand" align={align} headerAlign={headerAlign}>
// {{
// // @ts-ignore
// default: (data: TableSlotDefault) => getSlot(slots, 'expand', data)
// }}
// </ElTableColumn>
// ) : undefined
// }
const renderTreeTableColumn = (columnsChildren: TableColumn[]) => { const renderTreeTableColumn = (columnsChildren: TableColumn[]) => {
const { align, headerAlign, showOverflowTooltip } = unref(getProps) const { align, headerAlign, showOverflowTooltip } = unref(getProps)
return columnsChildren.map((v) => { return columnsChildren.map((v) => {
if (v.hidden) return null
const props = { ...v } as any const props = { ...v } as any
if (props.children) delete props.children if (props.children) delete props.children
@ -318,11 +308,13 @@ export default defineComponent({
const slots = { const slots = {
default: (...args: any[]) => { default: (...args: any[]) => {
if (props?.slots?.default) { const data = args[0]
return slots.default(args) return children && children.length
} else if (children && children.length) { ? renderTreeTableColumn(children)
return renderTreeTableColumn(children) : props?.slots?.default
} ? props.slots.default(args)
: v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
data.row[v.field]
} }
} }
if (props?.slots?.header) { if (props?.slots?.header) {
@ -351,59 +343,69 @@ export default defineComponent({
currentPage, currentPage,
align, align,
headerAlign, headerAlign,
showOverflowTooltip showOverflowTooltip,
reserveSelection
} = unref(getProps) } = unref(getProps)
return [renderTableSelection()].concat(
(columnsChildren || columns).map((v) => {
//
if (v.type === 'index') {
return (
<ElTableColumn
type="index"
index={
v.index
? v.index
: (index) => setIndex(reserveIndex, index, pageSize, currentPage)
}
align={v.align || align}
headerAlign={v.headerAlign || headerAlign}
label={v.label}
width="65px"
></ElTableColumn>
)
} else {
const props = { ...v } as any
if (props.children) delete props.children
const children = v.children return (columnsChildren || columns).map((v) => {
if (v.hidden) return null
const slots = { if (v.type === 'index') {
default: (...args: any[]) => { return (
if (props?.slots?.default) { <ElTableColumn
return slots.default(args) type="index"
} else if (children && children.length) { index={
return renderTreeTableColumn(children) v.index ? v.index : (index) => setIndex(reserveIndex, index, pageSize, currentPage)
}
} }
} align={v.align || align}
if (props?.slots?.header) { headerAlign={v.headerAlign || headerAlign}
slots['header'] = (...args: any[]) => props.slots.header(args) label={v.label}
} width="65px"
></ElTableColumn>
)
} else if (v.type === 'selection') {
return (
<ElTableColumn
type="selection"
reserveSelection={reserveSelection}
align={align}
headerAlign={headerAlign}
width="50"
></ElTableColumn>
)
} else {
const props = { ...v } as any
if (props.children) delete props.children
return ( const children = v.children
<ElTableColumn
showOverflowTooltip={showOverflowTooltip} const slots = {
align={align} default: (...args: any[]) => {
headerAlign={headerAlign} const data = args[0]
{...props} return children && children.length
prop={v.field} ? renderTreeTableColumn(children)
> : props?.slots?.default
{slots} ? props.slots.default(args)
</ElTableColumn> : v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
) data.row[v.field]
}
} }
}) if (props?.slots?.header) {
) slots['header'] = (...args: any[]) => props.slots.header(args)
}
return (
<ElTableColumn
showOverflowTooltip={showOverflowTooltip}
align={align}
headerAlign={headerAlign}
{...props}
prop={v.field}
>
{slots}
</ElTableColumn>
)
}
})
} }
return () => ( return () => (
@ -415,7 +417,9 @@ export default defineComponent({
{...unref(getBindValue)} {...unref(getBindValue)}
> >
{{ {{
default: () => renderTableColumn() default: () => renderTableColumn(),
empty: () => getSlot(slots, 'empty') || props.emptyText,
append: () => getSlot(slots, 'append')
}} }}
</ElTable> </ElTable>
{unref(getProps).pagination ? ( {unref(getProps).pagination ? (

View File

@ -2,6 +2,11 @@ import { TableProps as ElTableProps } from 'element-plus'
export interface TableColumn { export interface TableColumn {
field: string field: string
label?: string label?: string
type?: string
/**
*
*/
hidden?: boolean
children?: TableColumn[] children?: TableColumn[]
slots?: { slots?: {
default?: (...args: any[]) => JSX.Element | JSX.Element[] | null default?: (...args: any[]) => JSX.Element | JSX.Element[] | null
@ -69,8 +74,6 @@ export interface TableSetProps {
export interface TableProps extends Omit<Partial<ElTableProps<any[]>>, 'data'> { export interface TableProps extends Omit<Partial<ElTableProps<any[]>>, 'data'> {
pageSize?: number pageSize?: number
currentPage?: number currentPage?: number
// 是否多选
selection?: boolean
// 是否所有的超出隐藏优先级低于schema中的showOverflowTooltip, // 是否所有的超出隐藏优先级低于schema中的showOverflowTooltip,
showOverflowTooltip?: boolean showOverflowTooltip?: boolean
// 表头 // 表头

View File

@ -32,7 +32,7 @@ export const useForm = () => {
const methods = { const methods = {
/** /**
* @description form组件的props * @description form组件的props
* @param field FormItem的field * @param props form组件的props
*/ */
setProps: async (props: FormProps = {}) => { setProps: async (props: FormProps = {}) => {
const form = await getForm() const form = await getForm()

View File

@ -1,107 +1,46 @@
import { Table, TableExpose, TableProps, TableSetProps } from '@/components/Table' import { Table, TableExpose, TableProps, TableSetProps, TableColumn } from '@/components/Table'
import { ElTable, ElMessageBox, ElMessage } from 'element-plus' import { ElTable } from 'element-plus'
import { ref, reactive, watch, computed, unref, nextTick, onMounted } from 'vue' import { ref, watch, unref, nextTick, onMounted } from 'vue'
import { get } from 'lodash-es'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
interface TableResponse<T = any> {
total: number
list: T[]
pageNumber: number
pageSize: number
}
interface UseTableConfig { interface UseTableConfig {
// 是否初始化请求一次 /**
*
*/
immediate?: boolean immediate?: boolean
// 获取数据字段映射
props?: {
list?: string
total?: string
}
fetchDataApi: () => Promise<{ fetchDataApi: () => Promise<{
list: any[] list: any[]
total: number total: number
}> }>
// getListApi: (option: any) => Promise<IResponse<TableResponse<T>>>
// delListApi?: (option: any) => Promise<IResponse>
// 返回数据格式配置
// response: {
// list: string
// total?: string
// }
// 默认传递的参数
// defaultParams?: Recordable
// props?: TableProps
}
interface TableObject<T = any> {
pageSize: number
currentPage: number
total: number
list: T[]
params: any
loading: boolean
currentRow: Nullable<T>
} }
export const useTable = (config: UseTableConfig) => { export const useTable = (config: UseTableConfig) => {
const { immediate = true } = config const { immediate = true } = config
const loading = ref(false) const loading = ref(false)
const pageIndex = ref(1) const currentPage = ref(1)
const pageSize = ref(10) const pageSize = ref(10)
const total = ref(0) const total = ref(0)
const dataList = ref<any[]>([]) const dataList = ref<any[]>([])
const tableObject = reactive<TableObject>({ watch(
// 页数 () => currentPage.value,
pageSize: 10, () => {
// 当前页 methods.getList()
currentPage: 1,
// 总条数
total: 10,
// 表格数据
list: [],
// AxiosConfig 配置
params: {
// ...(config?.defaultParams || {})
},
// 加载中
loading: true,
// 当前行的数据
currentRow: null
})
const paramsObj = computed(() => {
return {
...tableObject.params,
pageSize: tableObject.pageSize,
pageIndex: tableObject.currentPage
} }
}) )
// watch( watch(
// () => tableObject.currentPage, () => pageSize.value,
// () => { () => {
// methods.getList() // 当前页不为1时修改页数后会导致多次调用getList方法
// } if (unref(currentPage) === 1) {
// ) methods.getList()
} else {
// watch( currentPage.value = 1
// () => tableObject.pageSize, methods.getList()
// () => { }
// // 当前页不为1时修改页数后会导致多次调用getList方法 }
// if (tableObject.currentPage === 1) { )
// methods.getList()
// } else {
// tableObject.currentPage = 1
// methods.getList()
// }
// }
// )
onMounted(() => { onMounted(() => {
if (immediate) { if (immediate) {
@ -148,6 +87,9 @@ export const useTable = (config: UseTableConfig) => {
// } // }
const methods = { const methods = {
/**
*
*/
getList: async () => { getList: async () => {
loading.value = true loading.value = true
try { try {
@ -162,36 +104,62 @@ export const useTable = (config: UseTableConfig) => {
} finally { } finally {
loading.value = false loading.value = false
} }
// const res = await config?.getListApi(unref(paramsObj)).finally(() => { },
// tableObject.loading = false
// }) /**
// if (res) { * @description table组件的props
// tableObject.list = get(res.data || {}, config?.response.list as string) * @param props table组件的props
// tableObject.total = get(res.data || {}, config?.response?.total as string) || 0 */
// } setProps: async (props: TableProps = {}) => {
const table = await getTable()
table?.setProps(props)
},
/**
* @description column
* @param columnProps
*/
setColumn: async (columnProps: TableSetProps[]) => {
const table = await getTable()
table?.setColumn(columnProps)
},
/**
* @description column
* @param tableColumn
* @param index
*/
addColumn: async (tableColumn: TableColumn, index?: number) => {
const table = await getTable()
table?.addColumn(tableColumn, index)
},
/**
* @description column
* @param field
*/
delColumn: async (field: string) => {
const table = await getTable()
table?.delColumn(field)
},
/**
* @description
* @returns
*/
getSelections: async () => {
const table = await getTable()
return table?.selections || []
},
/**
* @description ElTable组件的实例
* @returns ElTable instance
*/
getElTableExpose: async () => {
await getTable()
return unref(elTableRef)
} }
// setProps: async (props: TableProps = {}) => {
// const table = await getTable()
// table?.setProps(props)
// },
// setColumn: async (columnProps: TableSetProps[]) => {
// const table = await getTable()
// table?.setColumn(columnProps)
// },
// getSelections: async () => {
// const table = await getTable()
// return (table?.selections || []) as T[]
// },
// // 与Search组件结合
// setSearchParams: (data: Recordable) => {
// tableObject.currentPage = 1
// tableObject.params = Object.assign(tableObject.params, {
// pageSize: tableObject.pageSize,
// pageIndex: tableObject.currentPage,
// ...data
// })
// methods.getList()
// },
// // 删除数据 // // 删除数据
// delList: async (ids: string[] | number[], multiple: boolean, message = true) => { // delList: async (ids: string[] | number[], multiple: boolean, message = true) => {
// const tableRef = await getTable() // const tableRef = await getTable()
@ -222,11 +190,9 @@ export const useTable = (config: UseTableConfig) => {
return { return {
tableRegister: register, tableRegister: register,
elTableRef, tableMethods: methods,
tableObject,
methods,
tableState: { tableState: {
pageIndex, currentPage,
pageSize, pageSize,
total, total,
dataList, dataList,

View File

@ -417,7 +417,11 @@ export default {
hiddenExpandedRows: 'Hidden expanded rows', hiddenExpandedRows: 'Hidden expanded rows',
changeTitle: 'Change title', changeTitle: 'Change title',
header: 'Header', header: 'Header',
selectAllNone: 'Select all / none' selectAllNone: 'Select all / none',
delOrAddAction: 'Delete or add action',
showOrHiddenStripe: 'Show or hidden stripe',
showOrHiddenBorder: 'Show or hidden border',
fixedHeaderOrAuto: 'Fixed header or auto'
}, },
richText: { richText: {
richText: 'Rich text', richText: 'Rich text',

View File

@ -412,7 +412,11 @@ export default {
hiddenExpandedRows: '隐藏展开行', hiddenExpandedRows: '隐藏展开行',
changeTitle: '修改标题', changeTitle: '修改标题',
header: '头部', header: '头部',
selectAllNone: '全选/全不选' selectAllNone: '全选/全不选',
delOrAddAction: '删除/添加操作列',
showOrHiddenStripe: '显示/隐藏斑马纹',
showOrHiddenBorder: '显示/隐藏边框',
fixedHeaderOrAuto: '固定头部/自动'
}, },
richText: { richText: {
richText: '富文本', richText: '富文本',

View File

@ -184,6 +184,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
meta: { meta: {
title: 'UseTable' title: 'UseTable'
} }
},
{
path: 'tree-table',
component: () => import('@/views/Components/Table/TreeTable.vue'),
name: 'TreeTable',
meta: {
title: 'TreeTable'
}
} }
] ]
}, },

View File

@ -0,0 +1,115 @@
<script setup lang="tsx">
import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n'
import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
import { getTreeTableListApi } from '@/api/table'
import { reactive, unref } from 'vue'
import { ElTag, ElButton } from 'element-plus'
import { useTable } from '@/hooks/web/useTable'
const { tableRegister, tableState } = useTable({
fetchDataApi: async () => {
const { currentPage, pageSize } = tableState
const res = await getTreeTableListApi({
pageIndex: unref(currentPage),
pageSize: unref(pageSize)
})
return {
list: res.data.list,
total: res.data.total
}
}
})
const { loading, dataList, total, currentPage, pageSize } = tableState
const { t } = useI18n()
const columns = reactive<TableColumn[]>([
{
field: 'selection',
type: 'selection'
},
{
field: 'index',
label: t('tableDemo.index'),
type: 'index'
},
{
field: 'content',
label: t('tableDemo.header'),
children: [
{
field: 'title',
label: t('tableDemo.title')
},
{
field: 'author',
label: t('tableDemo.author')
},
{
field: 'display_time',
label: t('tableDemo.displayTime')
},
{
field: 'importance',
label: t('tableDemo.importance'),
formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
return (
<ElTag type={cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'}>
{cellValue === 1
? t('tableDemo.important')
: cellValue === 2
? t('tableDemo.good')
: t('tableDemo.commonly')}
</ElTag>
)
}
},
{
field: 'pageviews',
label: t('tableDemo.pageviews')
}
]
},
{
field: 'action',
label: t('tableDemo.action'),
slots: {
default: (data) => {
return (
<ElButton type="primary" onClick={() => actionFn(data)}>
{t('tableDemo.action')}
</ElButton>
)
}
}
}
])
const actionFn = (data: TableSlotDefault) => {
console.log(data)
}
</script>
<template>
<ContentWrap :title="`TreeTable ${t('tableDemo.example')}`">
<Table
v-model:pageSize="pageSize"
v-model:currentPage="currentPage"
:columns="columns"
:data="dataList"
row-key="id"
:loading="loading"
:pagination="{
total: total
}"
@register="tableRegister"
/>
</ContentWrap>
</template>
<style lang="less" scoped>
.el-button {
margin-top: 10px;
}
</style>

View File

@ -1,18 +1,17 @@
<script setup lang="tsx"> <script setup lang="tsx">
import { ContentWrap } from '@/components/ContentWrap' import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { Table, Pagination, TableColumn, TableSlotDefault } from '@/components/Table' import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
import { getTableListApi } from '@/api/table' import { getTableListApi } from '@/api/table'
import { TableData } from '@/api/table/types' import { ref, reactive, unref } from 'vue'
import { ref, h, reactive, unref } from 'vue'
import { ElTag, ElButton } from 'element-plus' import { ElTag, ElButton } from 'element-plus'
import { useTable } from '@/hooks/web/useTable' import { useTable } from '@/hooks/web/useTable'
const { tableRegister, tableObject, methods, elTableRef, tableState } = useTable({ const { tableRegister, tableMethods, tableState } = useTable({
fetchDataApi: async () => { fetchDataApi: async () => {
const { pageIndex, pageSize } = tableState const { currentPage, pageSize } = tableState
const res = await getTableListApi({ const res = await getTableListApi({
pageIndex: unref(pageIndex), pageIndex: unref(currentPage),
pageSize: unref(pageSize) pageSize: unref(pageSize)
}) })
return { return {
@ -20,37 +19,39 @@ const { tableRegister, tableObject, methods, elTableRef, tableState } = useTable
total: res.data.total total: res.data.total
} }
} }
// getListApi: getTableListApi,
// response: {
// list: 'list',
// total: 'total'
// }
}) })
const { loading, dataList, total, pageIndex, pageSize } = tableState const { loading, dataList, total, currentPage, pageSize } = tableState
const { setProps, setColumn, getElTableExpose, addColumn, delColumn } = tableMethods
// const { getList } = methods
// getList()
// const {
// register: register2,
// tableObject: tableObject2,
// methods: methods2
// } = useTable<TableData>({
// getListApi: getTableListApi,
// response: {
// list: 'list',
// total: 'total'
// }
// })
// const { getList: getList2 } = methods2
// getList2()
const { t } = useI18n() const { t } = useI18n()
const columns = reactive<TableColumn[]>([ const columns = reactive<TableColumn[]>([
{
field: 'expand',
type: 'expand',
slots: {
default: (data: TableSlotDefault[]) => {
const { row } = data[0]
return (
<div class="ml-30px">
<div>
{t('tableDemo.title')}{row.title}
</div>
<div>
{t('tableDemo.author')}{row.author}
</div>
<div>
{t('tableDemo.displayTime')}{row.display_time}
</div>
</div>
)
}
}
},
{
field: 'selection',
type: 'selection'
},
{ {
field: 'index', field: 'index',
label: t('tableDemo.index'), label: t('tableDemo.index'),
@ -112,36 +113,30 @@ const actionFn = (data: TableSlotDefault) => {
console.log(data) console.log(data)
} }
const paginationObj = ref<Pagination>() const canShowPagination = ref(true)
const showPagination = (show: boolean) => { const showPagination = (show: boolean) => {
if (show) { canShowPagination.value = show
paginationObj.value = {
total: tableObject.total
}
} else {
paginationObj.value = undefined
}
} }
const reserveIndex = (custom: boolean) => { const reserveIndex = (custom: boolean) => {
const { setProps } = methods
setProps({ setProps({
reserveIndex: custom reserveIndex: custom
}) })
} }
const showSelections = (show: boolean) => { const showSelections = (show: boolean) => {
const { setProps } = methods setColumn([
setProps({ {
selection: show field: 'selection',
}) path: 'hidden',
value: !show
}
])
} }
const index = ref(1) const index = ref(1)
const changeTitle = () => { const changeTitle = () => {
const { setColumn } = methods
setColumn([ setColumn([
{ {
field: 'title', field: 'title',
@ -153,19 +148,69 @@ const changeTitle = () => {
} }
const showExpandedRows = (show: boolean) => { const showExpandedRows = (show: boolean) => {
const { setProps } = methods setColumn([
setProps({ {
expand: show field: 'expand',
}) path: 'hidden',
value: !show
}
])
} }
const selectAllNone = () => { const selectAllNone = async () => {
unref(elTableRef)?.toggleAllSelection() const elTableRef = await getElTableExpose()
elTableRef?.toggleAllSelection()
}
const showAction = ref(true)
const delOrAddAction = () => {
if (unref(showAction)) {
delColumn('action')
showAction.value = false
} else {
addColumn({
field: 'action',
label: t('tableDemo.action'),
slots: {
default: (data) => {
return (
<ElButton type="primary" onClick={() => actionFn(data)}>
{t('tableDemo.action')}
</ElButton>
)
}
}
})
showAction.value = true
}
}
const showStripe = ref(false)
const showOrHiddenStripe = () => {
setProps({
stripe: !unref(showStripe)
})
showStripe.value = !unref(showStripe)
}
const height = ref<string | number>('auto')
const fixedHeaderOrAuto = () => {
if (unref(height) === 'auto') {
setProps({
height: 300
})
height.value = 300
} else {
setProps({
height: 'auto'
})
height.value = 'auto'
}
} }
</script> </script>
<template> <template>
<ContentWrap :title="`UseTable ${t('tableDemo.operate')}`"> <ContentWrap :title="`UseTable ${t('tableDemo.operate')}`" style="margin-bottom: 20px">
<ElButton @click="showPagination(true)"> <ElButton @click="showPagination(true)">
{{ t('tableDemo.show') }} {{ t('tableDemo.pagination') }} {{ t('tableDemo.show') }} {{ t('tableDemo.pagination') }}
</ElButton> </ElButton>
@ -185,50 +230,34 @@ const selectAllNone = () => {
<ElButton @click="showExpandedRows(false)">{{ t('tableDemo.hiddenExpandedRows') }}</ElButton> <ElButton @click="showExpandedRows(false)">{{ t('tableDemo.hiddenExpandedRows') }}</ElButton>
<ElButton @click="selectAllNone">{{ t('tableDemo.selectAllNone') }}</ElButton> <ElButton @click="selectAllNone">{{ t('tableDemo.selectAllNone') }}</ElButton>
<ElButton @click="delOrAddAction">{{ t('tableDemo.delOrAddAction') }}</ElButton>
<ElButton @click="showOrHiddenStripe">{{ t('tableDemo.showOrHiddenStripe') }}</ElButton>
<ElButton @click="fixedHeaderOrAuto">{{ t('tableDemo.fixedHeaderOrAuto') }}</ElButton>
</ContentWrap> </ContentWrap>
<ContentWrap :title="`UseTable ${t('tableDemo.example')}`"> <ContentWrap :title="`UseTable ${t('tableDemo.example')}`">
<Table <Table
v-model:pageSize="pageSize" v-model:pageSize="pageSize"
v-model:currentPage="pageIndex" v-model:currentPage="currentPage"
:columns="columns" :columns="columns"
:data="dataList" :data="dataList"
:loading="loading" :loading="loading"
:pagination="paginationObj" :pagination="
canShowPagination
? {
total: total
}
: undefined
"
@register="tableRegister" @register="tableRegister"
> />
<template #expand="data">
<div class="ml-30px">
<div>{{ t('tableDemo.title') }}{{ data.row.title }}</div>
<div>{{ t('tableDemo.author') }}{{ data.row.author }}</div>
<div>{{ t('tableDemo.displayTime') }}{{ data.row.display_time }}</div>
</div>
</template>
</Table>
</ContentWrap> </ContentWrap>
<!-- <ContentWrap :title="`UseTable 2 ${t('tableDemo.example')}`">
<Table
v-model:pageSize="tableObject2.pageSize"
v-model:currentPage="tableObject2.currentPage"
:columns="columns"
:data="tableObject2.tableList"
:loading="tableObject2.loading"
:pagination="paginationObj"
@register="register2"
>
<template #action="data">
<ElButton type="primary" @click="actionFn(data as TableSlotDefault)">
{{ t('tableDemo.action') }}
</ElButton>
</template>
<template #expand="data">
<div class="ml-30px">
<div>{{ t('tableDemo.title') }}{{ data.row.title }}</div>
<div>{{ t('tableDemo.author') }}{{ data.row.author }}</div>
<div>{{ t('tableDemo.displayTime') }}{{ data.row.display_time }}</div>
</div>
</template>
</Table>
</ContentWrap> -->
</template> </template>
<style lang="less" scoped>
.el-button {
margin-top: 10px;
}
</style>