feat: Table重构
This commit is contained in:
parent
002d03a0ad
commit
94800b0120
|
@ -142,6 +142,14 @@ const adminList = [
|
|||
title: 'UseTable'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'tree-table',
|
||||
component: 'views/Components/Table/TreeTable',
|
||||
name: 'TreeTable',
|
||||
meta: {
|
||||
title: 'TreeTable'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'ref-table',
|
||||
component: 'views/Components/Table/RefTable',
|
||||
|
@ -481,6 +489,7 @@ const testList: string[] = [
|
|||
'/components/table',
|
||||
'/components/table/default-table',
|
||||
'/components/table/use-table',
|
||||
'/components/table/tree-table',
|
||||
'/components/table/ref-table',
|
||||
'/components/editor-demo',
|
||||
'/components/editor-demo/editor',
|
||||
|
|
|
@ -12,7 +12,7 @@ const count = 100
|
|||
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>'
|
||||
|
||||
let List: {
|
||||
interface ListProps {
|
||||
id: string
|
||||
author: string
|
||||
title: string
|
||||
|
@ -20,7 +20,20 @@ let List: {
|
|||
importance: number
|
||||
display_time: string
|
||||
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++) {
|
||||
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 [
|
||||
// 树形列表接口
|
||||
{
|
||||
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',
|
||||
|
|
|
@ -5,6 +5,10 @@ export const getTableListApi = (params: any) => {
|
|||
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> => {
|
||||
return request.post({ url: '/example/save', data })
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Table from './src/Table.vue'
|
||||
import { ElTable } from 'element-plus'
|
||||
import { TableSetProps } from './src/types'
|
||||
import { TableColumn, TableSetProps } from './src/types'
|
||||
|
||||
export type {
|
||||
TableColumn,
|
||||
|
@ -13,6 +13,8 @@ export type {
|
|||
export interface TableExpose {
|
||||
setProps: (props: Recordable) => void
|
||||
setColumn: (columnProps: TableSetProps[]) => void
|
||||
addColumn: (column: TableColumn, index?: number) => void
|
||||
delColumn: (field: string) => void
|
||||
selections: Recordable[]
|
||||
elTableRef: ComponentRef<typeof ElTable>
|
||||
}
|
||||
|
|
|
@ -6,14 +6,13 @@ import { setIndex } from './helper'
|
|||
import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
|
||||
import { set } from 'lodash-es'
|
||||
import { CSSProperties } from 'vue'
|
||||
import { getSlot } from '@/utils/tsxHelper'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Table',
|
||||
props: {
|
||||
pageSize: propTypes.number.def(10),
|
||||
currentPage: propTypes.number.def(1),
|
||||
// 是否多选
|
||||
selection: propTypes.bool.def(true),
|
||||
// 是否所有的超出隐藏,优先级低于schema中的showOverflowTooltip,
|
||||
showOverflowTooltip: propTypes.bool.def(true),
|
||||
// 表头
|
||||
|
@ -49,7 +48,7 @@ export default defineComponent({
|
|||
height: propTypes.oneOfType([Number, String]),
|
||||
maxHeight: propTypes.oneOfType([Number, String]),
|
||||
stripe: propTypes.bool.def(false),
|
||||
border: propTypes.bool.def(false),
|
||||
border: propTypes.bool.def(true),
|
||||
size: {
|
||||
type: String as PropType<ComponentSize>,
|
||||
validator: (v: ComponentSize) => ['medium', 'small', 'mini'].includes(v)
|
||||
|
@ -103,10 +102,7 @@ export default defineComponent({
|
|||
>,
|
||||
default: () => undefined
|
||||
},
|
||||
rowKey: {
|
||||
type: [Function, String] as PropType<(row: Recordable) => string | string>,
|
||||
default: () => 'id'
|
||||
},
|
||||
rowKey: propTypes.string.def('id'),
|
||||
emptyText: propTypes.string.def('No Data'),
|
||||
defaultExpandAll: propTypes.bool.def(false),
|
||||
expandRowKeys: {
|
||||
|
@ -164,7 +160,7 @@ export default defineComponent({
|
|||
default: () => undefined
|
||||
},
|
||||
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' })
|
||||
},
|
||||
tableLayout: {
|
||||
|
@ -175,7 +171,7 @@ export default defineComponent({
|
|||
flexible: propTypes.bool.def(false)
|
||||
},
|
||||
emits: ['update:pageSize', 'update:currentPage', 'register'],
|
||||
setup(props, { attrs, emit, expose }) {
|
||||
setup(props, { attrs, emit, slots, expose }) {
|
||||
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 selectionChange = (selection: Recordable[]) => {
|
||||
|
@ -226,6 +239,8 @@ export default defineComponent({
|
|||
expose({
|
||||
setProps,
|
||||
setColumn,
|
||||
delColumn,
|
||||
addColumn,
|
||||
selections,
|
||||
elTableRef
|
||||
})
|
||||
|
@ -275,42 +290,17 @@ export default defineComponent({
|
|||
)
|
||||
|
||||
const getBindValue = computed(() => {
|
||||
const bindValue: Recordable = { ...attrs, ...props }
|
||||
const bindValue: Recordable = { ...attrs, ...unref(getProps) }
|
||||
delete bindValue.columns
|
||||
delete bindValue.data
|
||||
console.log(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 { align, headerAlign, showOverflowTooltip } = unref(getProps)
|
||||
return columnsChildren.map((v) => {
|
||||
if (v.hidden) return null
|
||||
const props = { ...v } as any
|
||||
if (props.children) delete props.children
|
||||
|
||||
|
@ -318,11 +308,13 @@ export default defineComponent({
|
|||
|
||||
const slots = {
|
||||
default: (...args: any[]) => {
|
||||
if (props?.slots?.default) {
|
||||
return slots.default(args)
|
||||
} else if (children && children.length) {
|
||||
return renderTreeTableColumn(children)
|
||||
}
|
||||
const data = args[0]
|
||||
return children && children.length
|
||||
? 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) {
|
||||
|
@ -351,19 +343,18 @@ export default defineComponent({
|
|||
currentPage,
|
||||
align,
|
||||
headerAlign,
|
||||
showOverflowTooltip
|
||||
showOverflowTooltip,
|
||||
reserveSelection
|
||||
} = unref(getProps)
|
||||
return [renderTableSelection()].concat(
|
||||
(columnsChildren || columns).map((v) => {
|
||||
// 自定生成序号
|
||||
|
||||
return (columnsChildren || columns).map((v) => {
|
||||
if (v.hidden) return null
|
||||
if (v.type === 'index') {
|
||||
return (
|
||||
<ElTableColumn
|
||||
type="index"
|
||||
index={
|
||||
v.index
|
||||
? v.index
|
||||
: (index) => setIndex(reserveIndex, index, pageSize, currentPage)
|
||||
v.index ? v.index : (index) => setIndex(reserveIndex, index, pageSize, currentPage)
|
||||
}
|
||||
align={v.align || align}
|
||||
headerAlign={v.headerAlign || headerAlign}
|
||||
|
@ -371,6 +362,16 @@ export default defineComponent({
|
|||
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
|
||||
|
@ -379,11 +380,13 @@ export default defineComponent({
|
|||
|
||||
const slots = {
|
||||
default: (...args: any[]) => {
|
||||
if (props?.slots?.default) {
|
||||
return slots.default(args)
|
||||
} else if (children && children.length) {
|
||||
return renderTreeTableColumn(children)
|
||||
}
|
||||
const data = args[0]
|
||||
return children && children.length
|
||||
? 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) {
|
||||
|
@ -403,7 +406,6 @@ export default defineComponent({
|
|||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
return () => (
|
||||
|
@ -415,7 +417,9 @@ export default defineComponent({
|
|||
{...unref(getBindValue)}
|
||||
>
|
||||
{{
|
||||
default: () => renderTableColumn()
|
||||
default: () => renderTableColumn(),
|
||||
empty: () => getSlot(slots, 'empty') || props.emptyText,
|
||||
append: () => getSlot(slots, 'append')
|
||||
}}
|
||||
</ElTable>
|
||||
{unref(getProps).pagination ? (
|
||||
|
|
|
@ -2,6 +2,11 @@ import { TableProps as ElTableProps } from 'element-plus'
|
|||
export interface TableColumn {
|
||||
field: string
|
||||
label?: string
|
||||
type?: string
|
||||
/**
|
||||
* 是否隐藏
|
||||
*/
|
||||
hidden?: boolean
|
||||
children?: TableColumn[]
|
||||
slots?: {
|
||||
default?: (...args: any[]) => JSX.Element | JSX.Element[] | null
|
||||
|
@ -69,8 +74,6 @@ export interface TableSetProps {
|
|||
export interface TableProps extends Omit<Partial<ElTableProps<any[]>>, 'data'> {
|
||||
pageSize?: number
|
||||
currentPage?: number
|
||||
// 是否多选
|
||||
selection?: boolean
|
||||
// 是否所有的超出隐藏,优先级低于schema中的showOverflowTooltip,
|
||||
showOverflowTooltip?: boolean
|
||||
// 表头
|
||||
|
|
|
@ -32,7 +32,7 @@ export const useForm = () => {
|
|||
const methods = {
|
||||
/**
|
||||
* @description 设置form组件的props
|
||||
* @param field FormItem的field
|
||||
* @param props form组件的props
|
||||
*/
|
||||
setProps: async (props: FormProps = {}) => {
|
||||
const form = await getForm()
|
||||
|
|
|
@ -1,107 +1,46 @@
|
|||
import { Table, TableExpose, TableProps, TableSetProps } from '@/components/Table'
|
||||
import { ElTable, ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { ref, reactive, watch, computed, 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
|
||||
}
|
||||
import { Table, TableExpose, TableProps, TableSetProps, TableColumn } from '@/components/Table'
|
||||
import { ElTable } from 'element-plus'
|
||||
import { ref, watch, unref, nextTick, onMounted } from 'vue'
|
||||
|
||||
interface UseTableConfig {
|
||||
// 是否初始化请求一次
|
||||
/**
|
||||
* 是否初始化的时候请求一次
|
||||
*/
|
||||
immediate?: boolean
|
||||
// 获取数据字段映射
|
||||
props?: {
|
||||
list?: string
|
||||
total?: string
|
||||
}
|
||||
fetchDataApi: () => Promise<{
|
||||
list: any[]
|
||||
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) => {
|
||||
const { immediate = true } = config
|
||||
|
||||
const loading = ref(false)
|
||||
const pageIndex = ref(1)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const total = ref(0)
|
||||
const dataList = ref<any[]>([])
|
||||
|
||||
const tableObject = reactive<TableObject>({
|
||||
// 页数
|
||||
pageSize: 10,
|
||||
// 当前页
|
||||
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(
|
||||
() => currentPage.value,
|
||||
() => {
|
||||
methods.getList()
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
// watch(
|
||||
// () => tableObject.currentPage,
|
||||
// () => {
|
||||
// methods.getList()
|
||||
// }
|
||||
// )
|
||||
|
||||
// watch(
|
||||
// () => tableObject.pageSize,
|
||||
// () => {
|
||||
// // 当前页不为1时,修改页数后会导致多次调用getList方法
|
||||
// if (tableObject.currentPage === 1) {
|
||||
// methods.getList()
|
||||
// } else {
|
||||
// tableObject.currentPage = 1
|
||||
// methods.getList()
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
watch(
|
||||
() => pageSize.value,
|
||||
() => {
|
||||
// 当前页不为1时,修改页数后会导致多次调用getList方法
|
||||
if (unref(currentPage) === 1) {
|
||||
methods.getList()
|
||||
} else {
|
||||
currentPage.value = 1
|
||||
methods.getList()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
if (immediate) {
|
||||
|
@ -148,6 +87,9 @@ export const useTable = (config: UseTableConfig) => {
|
|||
// }
|
||||
|
||||
const methods = {
|
||||
/**
|
||||
* 获取表单数据
|
||||
*/
|
||||
getList: async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
|
@ -162,36 +104,62 @@ export const useTable = (config: UseTableConfig) => {
|
|||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
// const res = await config?.getListApi(unref(paramsObj)).finally(() => {
|
||||
// tableObject.loading = false
|
||||
// })
|
||||
// if (res) {
|
||||
// tableObject.list = get(res.data || {}, config?.response.list as string)
|
||||
// tableObject.total = get(res.data || {}, config?.response?.total as string) || 0
|
||||
// }
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 设置table组件的props
|
||||
* @param props table组件的props
|
||||
*/
|
||||
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) => {
|
||||
// const tableRef = await getTable()
|
||||
|
@ -222,11 +190,9 @@ export const useTable = (config: UseTableConfig) => {
|
|||
|
||||
return {
|
||||
tableRegister: register,
|
||||
elTableRef,
|
||||
tableObject,
|
||||
methods,
|
||||
tableMethods: methods,
|
||||
tableState: {
|
||||
pageIndex,
|
||||
currentPage,
|
||||
pageSize,
|
||||
total,
|
||||
dataList,
|
||||
|
|
|
@ -417,7 +417,11 @@ export default {
|
|||
hiddenExpandedRows: 'Hidden expanded rows',
|
||||
changeTitle: 'Change title',
|
||||
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: 'Rich text',
|
||||
|
|
|
@ -412,7 +412,11 @@ export default {
|
|||
hiddenExpandedRows: '隐藏展开行',
|
||||
changeTitle: '修改标题',
|
||||
header: '头部',
|
||||
selectAllNone: '全选/全不选'
|
||||
selectAllNone: '全选/全不选',
|
||||
delOrAddAction: '删除/添加操作列',
|
||||
showOrHiddenStripe: '显示/隐藏斑马纹',
|
||||
showOrHiddenBorder: '显示/隐藏边框',
|
||||
fixedHeaderOrAuto: '固定头部/自动'
|
||||
},
|
||||
richText: {
|
||||
richText: '富文本',
|
||||
|
|
|
@ -184,6 +184,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
|
|||
meta: {
|
||||
title: 'UseTable'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'tree-table',
|
||||
component: () => import('@/views/Components/Table/TreeTable.vue'),
|
||||
name: 'TreeTable',
|
||||
meta: {
|
||||
title: 'TreeTable'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -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>
|
|
@ -1,18 +1,17 @@
|
|||
<script setup lang="tsx">
|
||||
import { ContentWrap } from '@/components/ContentWrap'
|
||||
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 { TableData } from '@/api/table/types'
|
||||
import { ref, h, reactive, unref } from 'vue'
|
||||
import { ref, reactive, unref } from 'vue'
|
||||
import { ElTag, ElButton } from 'element-plus'
|
||||
import { useTable } from '@/hooks/web/useTable'
|
||||
|
||||
const { tableRegister, tableObject, methods, elTableRef, tableState } = useTable({
|
||||
const { tableRegister, tableMethods, tableState } = useTable({
|
||||
fetchDataApi: async () => {
|
||||
const { pageIndex, pageSize } = tableState
|
||||
const { currentPage, pageSize } = tableState
|
||||
const res = await getTableListApi({
|
||||
pageIndex: unref(pageIndex),
|
||||
pageIndex: unref(currentPage),
|
||||
pageSize: unref(pageSize)
|
||||
})
|
||||
return {
|
||||
|
@ -20,37 +19,39 @@ const { tableRegister, tableObject, methods, elTableRef, tableState } = useTable
|
|||
total: res.data.total
|
||||
}
|
||||
}
|
||||
// getListApi: getTableListApi,
|
||||
// response: {
|
||||
// list: 'list',
|
||||
// total: 'total'
|
||||
// }
|
||||
})
|
||||
const { loading, dataList, total, pageIndex, pageSize } = tableState
|
||||
|
||||
// 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 { loading, dataList, total, currentPage, pageSize } = tableState
|
||||
const { setProps, setColumn, getElTableExpose, addColumn, delColumn } = tableMethods
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
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',
|
||||
label: t('tableDemo.index'),
|
||||
|
@ -112,36 +113,30 @@ const actionFn = (data: TableSlotDefault) => {
|
|||
console.log(data)
|
||||
}
|
||||
|
||||
const paginationObj = ref<Pagination>()
|
||||
|
||||
const canShowPagination = ref(true)
|
||||
const showPagination = (show: boolean) => {
|
||||
if (show) {
|
||||
paginationObj.value = {
|
||||
total: tableObject.total
|
||||
}
|
||||
} else {
|
||||
paginationObj.value = undefined
|
||||
}
|
||||
canShowPagination.value = show
|
||||
}
|
||||
|
||||
const reserveIndex = (custom: boolean) => {
|
||||
const { setProps } = methods
|
||||
setProps({
|
||||
reserveIndex: custom
|
||||
})
|
||||
}
|
||||
|
||||
const showSelections = (show: boolean) => {
|
||||
const { setProps } = methods
|
||||
setProps({
|
||||
selection: show
|
||||
})
|
||||
setColumn([
|
||||
{
|
||||
field: 'selection',
|
||||
path: 'hidden',
|
||||
value: !show
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
const index = ref(1)
|
||||
|
||||
const changeTitle = () => {
|
||||
const { setColumn } = methods
|
||||
setColumn([
|
||||
{
|
||||
field: 'title',
|
||||
|
@ -153,19 +148,69 @@ const changeTitle = () => {
|
|||
}
|
||||
|
||||
const showExpandedRows = (show: boolean) => {
|
||||
const { setProps } = methods
|
||||
setProps({
|
||||
expand: show
|
||||
})
|
||||
setColumn([
|
||||
{
|
||||
field: 'expand',
|
||||
path: 'hidden',
|
||||
value: !show
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
const selectAllNone = () => {
|
||||
unref(elTableRef)?.toggleAllSelection()
|
||||
const selectAllNone = async () => {
|
||||
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>
|
||||
|
||||
<template>
|
||||
<ContentWrap :title="`UseTable ${t('tableDemo.operate')}`">
|
||||
<ContentWrap :title="`UseTable ${t('tableDemo.operate')}`" style="margin-bottom: 20px">
|
||||
<ElButton @click="showPagination(true)">
|
||||
{{ t('tableDemo.show') }} {{ t('tableDemo.pagination') }}
|
||||
</ElButton>
|
||||
|
@ -185,50 +230,34 @@ const selectAllNone = () => {
|
|||
<ElButton @click="showExpandedRows(false)">{{ t('tableDemo.hiddenExpandedRows') }}</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 :title="`UseTable ${t('tableDemo.example')}`">
|
||||
<Table
|
||||
v-model:pageSize="pageSize"
|
||||
v-model:currentPage="pageIndex"
|
||||
v-model:currentPage="currentPage"
|
||||
:columns="columns"
|
||||
:data="dataList"
|
||||
:loading="loading"
|
||||
:pagination="paginationObj"
|
||||
:pagination="
|
||||
canShowPagination
|
||||
? {
|
||||
total: total
|
||||
}
|
||||
: undefined
|
||||
"
|
||||
@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 :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>
|
||||
<style lang="less" scoped>
|
||||
.el-button {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue