feat: 重构表格组件封装demo

This commit is contained in:
a20070322 2024-03-06 14:18:30 +08:00
parent c2babe6ef9
commit 9d98130693
2 changed files with 152 additions and 115 deletions

View File

@ -1,9 +1,9 @@
<template>
<div>
<a-table v-bind="$attrs" :columns="customColumn" :size="tableSize">
<template v-if="props.isShowTools || $slots.title" #title="slotProps">
<a-table v-bind="props" :columns="customColumn" :size="tableSize">
<template v-if="props.isShowTools || slots.title" #title="slotProps">
<div class="table-title">
<slot v-if="$slots.title" name="title" v-bind="slotProps"></slot>
<slot v-if="slots.title" name="title" v-bind="slotProps"></slot>
<div v-if="props.isShowTools" class="table-action__box">
<!-- 增加工具栏部分 -->
<a-space class="table-action">
@ -53,135 +53,170 @@
</div>
</template>
<script lang="ts">
export default {
name: 'CustomTable'
}
</script>
<script lang="ts" setup>
// props
import { useUserStore } from '@/stores/user'
import { CheckboxValueType } from 'ant-design-vue/es/checkbox/interface'
import { CustomSlotsType } from 'ant-design-vue/es/_util/type'
import { SizeType } from 'ant-design-vue/es/config-provider'
import { ColumnProps, TableProps } from 'ant-design-vue/es/table'
import { defineProps } from 'vue'
import { ColumnType, tableProps } from 'ant-design-vue/es/table'
import { RenderExpandIconProps } from 'ant-design-vue/es/vc-table/interface'
const userStore = useUserStore()
const $slots = useSlots()
const otherSlots = computed(() => {
return Object.keys($slots).filter((key) => key !== 'title')
})
const $attrs = useAttrs()
const props = withDefaults(
defineProps<{
columns: ColumnProps[]
tableName?: string
isShowTools?: boolean
isHideRefresh?: boolean
}>(),
{
columns: () => [],
size: 'middle',
tableName: '', //
isShowTools: false, //
isHideRefresh: false //
}
)
const emit = defineEmits(['refresh'])
const refreshClick = () => {
emit('refresh', 666)
}
const COLUMN = 'column'
const SIZE = 'size'
const isCatchOPtions = () => {
return props.tableName && userStore?.userInfo?.id
}
const getTableCatchKey = (type: string) => {
return `table:catch__${userStore.userInfo.id}__${props.tableName}__${type}`
}
import { initDefaultProps } from 'ant-design-vue/es/_util/props-util'
import { CheckboxValueType } from 'ant-design-vue/es/checkbox/interface'
//
const tableSizeList = [
{
value: 'large',
label: '大'
label: '超大'
},
{
value: 'middle',
label: '中'
label: '中等'
},
{
value: 'small',
label: ''
label: '紧凑'
}
]
const tableSize = ref<SizeType>('middle')
watch(
() => tableSize.value,
(val) => {
if (!isCatchOPtions()) return
//
if (val !== 'middle') {
localStorage.setItem(getTableCatchKey(SIZE), JSON.stringify(val))
} else {
localStorage.removeItem(getTableCatchKey(SIZE))
}
}
)
//
onMounted(() => {
//
const size = localStorage.getItem(getTableCatchKey(SIZE))
tableSize.value = size ? JSON.parse(size) : props.size || 'middle'
})
let customColumnList = ref<CheckboxValueType[]>([])
const customColumn = computed(() => {
if (!isCatchOPtions()) return props.columns
return props.columns.filter((item) => {
return customColumnList.value.includes(String(item?.dataIndex))
})
export default defineComponent({
// name: 'CustomTable',
inheritAttrs: false,
props: initDefaultProps(
{
...tableProps(),
isShowTools: Boolean,
isHideRefresh: Boolean,
tableName: {
type: String,
required: true
},
columns: {
type: Array<ColumnType>,
default: () => []
}
},
{
isShowTools: false,
isHideRefresh: false
}
),
slots: Object as CustomSlotsType<{
emptyText?: any
expandIcon?: RenderExpandIconProps<any>
title?: any
footer?: any
summary?: any
expandedRowRender?: any
expandColumnTitle?: any
bodyCell?: (props: {
text: any
value: any
record: Record<string, any>
index: number
column: ColumnType
}) => void
headerCell?: (props: { title: any; column: ColumnType }) => void
customFilterIcon?: any
customFilterDropdown?: any
default: any
}>,
emits: ['refresh'],
setup(props, { attrs, slots, emit }) {
const otherSlots = computed(() => {
return Object.keys(slots).filter((key) => key !== 'title')
})
const userStore = useUserStore()
const COLUMN = 'column'
const SIZE = 'size'
//
const isCatchOPtions = () => {
return props.tableName && userStore?.userInfo?.id
}
// key
const getTableCatchKey = (type: string) => {
return `table:catch__${userStore.userInfo.id}__${props.tableName}__${type}`
}
const refreshClick = () => {
emit('refresh', 666)
}
// hooks
const tableSize = ref<SizeType>('middle')
watch(
() => tableSize.value,
(val) => {
if (!isCatchOPtions()) return
//
if (val !== 'middle') {
localStorage.setItem(getTableCatchKey(SIZE), JSON.stringify(val))
} else {
localStorage.removeItem(getTableCatchKey(SIZE))
}
}
)
//
onMounted(() => {
//
const size = localStorage.getItem(getTableCatchKey(SIZE))
tableSize.value = size ? JSON.parse(size) : props.size || 'middle'
})
let customColumnList = ref<CheckboxValueType[]>([])
const customColumn = computed(() => {
if (!isCatchOPtions()) return props.columns
return props.columns.filter((item) => {
return customColumnList.value.includes(String(item.dataIndex))
})
})
const resetCustomColumn = () => {
customColumnList.value = props.columns.map((item) => String(item.dataIndex))
}
// ,customColumnList
watch(
() => props.columns,
(val) => {
if (!isCatchOPtions()) return
const catchKeys = JSON.parse(localStorage.getItem(getTableCatchKey(COLUMN)) || '[]') as string[]
if (
catchKeys.filter((key) => val.findIndex((item) => item.dataIndex === key) > -1).length == 0 ||
catchKeys.length == 0
) {
customColumnList.value = val.map((item) => String(item.dataIndex))
} else {
customColumnList.value = catchKeys
}
},
{
immediate: true
}
)
// ,
watch(
() => customColumnList.value,
(val) => {
if (!isCatchOPtions()) return
if (props.columns.filter((item) => !val.includes(String(item.dataIndex))).length > 0 && val.length > 0) {
localStorage.setItem(getTableCatchKey(COLUMN), JSON.stringify(val))
} else {
localStorage.removeItem(getTableCatchKey(COLUMN))
}
},
{
immediate: true
}
)
return {
attrs,
props,
slots,
refreshClick,
otherSlots,
tableSizeList: tableSizeList,
tableSize,
customColumnList,
customColumn,
resetCustomColumn
}
}
})
const resetCustomColumn = () => {
customColumnList.value = props.columns.map((item) => String(item.dataIndex))
}
// ,customColumnList
watch(
() => props.columns,
(val) => {
if (!isCatchOPtions()) return
const catchKeys = JSON.parse(localStorage.getItem(getTableCatchKey(COLUMN)) || '[]') as string[]
if (
catchKeys.filter((key) => val.findIndex((item) => item.dataIndex === key) > -1).length == 0 ||
catchKeys.length == 0
) {
customColumnList.value = val.map((item) => String(item.dataIndex))
} else {
customColumnList.value = catchKeys
}
},
{
immediate: true
}
)
// ,
watch(
() => customColumnList.value,
(val) => {
if (!isCatchOPtions()) return
if (props.columns.filter((item) => !val.includes(String(item.dataIndex))).length > 0 && val.length > 0) {
localStorage.setItem(getTableCatchKey(COLUMN), JSON.stringify(val))
} else {
localStorage.removeItem(getTableCatchKey(COLUMN))
}
},
{
immediate: true
}
)
</script>
<style lang="less" scoped>
.table-title {

View File

@ -103,6 +103,7 @@ declare module 'vue' {
CodeOutlined: typeof import('@ant-design/icons-vue')['CodeOutlined']
ColumnHeightOutlined: typeof import('@ant-design/icons-vue')['ColumnHeightOutlined']
CompositionTransfer: typeof import('./../components/compositionTransfer/composition-transfer.vue')['default']
copy: typeof import('./../components/customTable/index copy.vue')['default']
CustomInput: typeof import('./../components/customInput/index.vue')['default']
CustomSelect: typeof import('./../components/customSelect/index.vue')['default']
CustomTable: typeof import('./../components/customTable/index.vue')['default']
@ -123,6 +124,7 @@ declare module 'vue' {
FullscreenOutlined: typeof import('@ant-design/icons-vue')['FullscreenOutlined']
HighlightOutlined: typeof import('@ant-design/icons-vue')['HighlightOutlined']
HomeOutlined: typeof import('@ant-design/icons-vue')['HomeOutlined']
'Index.bak': typeof import('./../components/customTable/index.bak.vue')['default']
Index2: typeof import('./../components/logView/index2.vue')['default']
InfoCircleOutlined: typeof import('@ant-design/icons-vue')['InfoCircleOutlined']
InfoOutlined: typeof import('@ant-design/icons-vue')['InfoOutlined']