-
Notifications
You must be signed in to change notification settings - Fork 698
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7f5ef99
commit f648424
Showing
28 changed files
with
2,577 additions
and
174 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<script lang="ts"> | ||
import { defineComponent, inject, h, PropType } from 'vue' | ||
export default defineComponent({ | ||
name: 'Slot', | ||
props: { | ||
row: { | ||
type: Object as PropType<object>, | ||
default: () => null | ||
}, | ||
index: { | ||
type: Number as PropType<number>, | ||
default: null | ||
}, | ||
column: { | ||
type: Object as PropType<object>, | ||
default: () => null | ||
}, | ||
slotName: { | ||
type: String as PropType<string>, | ||
default: '' | ||
} | ||
}, | ||
render(props: any) { | ||
const _this: any = inject('tableRoot') | ||
return h( | ||
'span', | ||
_this.slots[props.slotName]({ | ||
row: props.row, | ||
column: props.column, | ||
$index: props.index | ||
}) | ||
) | ||
} | ||
}) | ||
</script> | ||
|
||
<style></style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<template> | ||
<el-table-column v-bind="{ ...getItemBindValue(child) }" :prop="child.key"> | ||
<template v-for="item in child.children"> | ||
<!-- 树型数据 --> | ||
<template v-if="item.children && item.children.length"> | ||
<table-column :key="item[item.field]" :child="item" /> | ||
</template> | ||
|
||
<template v-else> | ||
<el-table-column | ||
:key="item[item.field]" | ||
v-bind="{ ...getItemBindValue(item) }" | ||
:prop="item.field" | ||
> | ||
<!-- 表头插槽 --> | ||
<template v-if="item.slots && item.slots.header" #header="scope"> | ||
<table-slot | ||
v-if="item.slots && item.slots.header" | ||
:slot-name="item.slots.header" | ||
:column="item" | ||
:index="scope.$index" | ||
/> | ||
</template> | ||
|
||
<!-- 表格内容插槽自定义 --> | ||
<template v-if="item.slots && item.slots.default" #default="scope"> | ||
<table-slot | ||
:slot-name="item.slots.default" | ||
:row="scope.row" | ||
:column="item" | ||
:index="scope.$index" | ||
/> | ||
</template> | ||
</el-table-column> | ||
</template> | ||
</template> | ||
</el-table-column> | ||
</template> | ||
|
||
<script setup lang="ts" name="TableColumn"> | ||
import { PropType } from 'vue' | ||
import TableSlot from './Slot.vue' | ||
import { deepClone } from '@/utils' | ||
defineProps({ | ||
child: { | ||
type: Object as PropType<IObj>, | ||
required: true | ||
} | ||
}) | ||
function getItemBindValue(item: any) { | ||
const delArr: string[] = ['children'] | ||
const obj = deepClone(item) | ||
for (const key in obj) { | ||
if (delArr.indexOf(key) !== -1) { | ||
delete obj[key] | ||
} | ||
} | ||
return obj | ||
} | ||
</script> | ||
|
||
<style></style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
<template> | ||
<el-table ref="elTable" :border="true" v-bind="getBindValue" @header-dragend="headerDragend"> | ||
<!-- 多选 --> | ||
<el-table-column | ||
v-if="selection" | ||
type="selection" | ||
:reserve-selection="reserveSelection" | ||
width="40" | ||
/> | ||
<template v-for="item in columns"> | ||
<!-- 自定义索引 --> | ||
<template v-if="item.type === 'index'"> | ||
<el-table-column | ||
:key="item[item.field]" | ||
v-bind="{ ...getItemBindValue(item) }" | ||
type="index" | ||
:index="item.index" | ||
/> | ||
</template> | ||
|
||
<!-- 树型数据 --> | ||
<template v-else-if="item.children && item.children.length"> | ||
<table-column :key="item[item.field]" :child="item" /> | ||
</template> | ||
|
||
<template v-else> | ||
<el-table-column | ||
:key="item[item.field]" | ||
v-bind="{ ...getItemBindValue(item) }" | ||
:prop="item.field" | ||
> | ||
<!-- 表头插槽 --> | ||
<template v-if="item.slots && item.slots.header" #header="scope"> | ||
<table-slot | ||
v-if="item.slots && item.slots.header" | ||
:slot-name="item.slots.header" | ||
:column="item" | ||
:index="scope.$index" | ||
/> | ||
</template> | ||
|
||
<!-- 表格内容插槽自定义 --> | ||
<template v-if="item.slots && item.slots.default" #default="scope"> | ||
<table-slot | ||
v-if="item.slots && item.slots.default" | ||
:slot-name="item.slots.default" | ||
:row="scope.row" | ||
:column="item" | ||
:index="scope.$index" | ||
/> | ||
</template> | ||
</el-table-column> | ||
</template> | ||
</template> | ||
</el-table> | ||
|
||
<div v-if="pagination" class="pagination__wrap"> | ||
<el-pagination | ||
:style="paginationStyle" | ||
:page-sizes="[10, 20, 30, 40, 50, 100]" | ||
layout="total, sizes, prev, pager, next, jumper" | ||
v-bind="getPaginationBindValue" | ||
@size-change="sizeChange" | ||
@current-change="currentChange" | ||
/> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts" name="ComTable"> | ||
import { PropType, computed, ref, unref, useAttrs } from 'vue' | ||
import { deepClone } from '@/utils' | ||
import { isObject } from '@/utils/validate' | ||
import TableColumn from './components/TableColumn.vue' | ||
import TableSlot from './components/Slot.vue' | ||
const props = defineProps({ | ||
// 表头 | ||
columns: { | ||
type: Array as PropType<IObj[]>, | ||
default: () => [] | ||
}, | ||
// 是否多选 | ||
selection: { | ||
type: Boolean as PropType<boolean>, | ||
default: false | ||
}, | ||
// 是否展示分页 | ||
pagination: { | ||
type: [Boolean, Object] as PropType<boolean | IObj>, | ||
default: false | ||
}, | ||
// 仅对 type=selection 的列有效,类型为 Boolean,为 true 则会在数据更新之后保留之前选中的数据(需指定 row-key) | ||
reserveSelection: { | ||
type: Boolean as PropType<boolean>, | ||
default: false | ||
} | ||
}) | ||
const attrs = useAttrs() | ||
const elTable = ref<HTMLElement | null>(null) | ||
function getTableRef() { | ||
return unref(elTable as any) | ||
} | ||
// const _this = getCurrentInstance() | ||
// provide('tableRoot', _this) | ||
const getBindValue = computed((): IObj => { | ||
const bindValue = { ...attrs, ...props } as IObj | ||
delete bindValue.columns | ||
return bindValue | ||
}) | ||
function getItemBindValue(item: IObj) { | ||
const delArr: string[] = [] | ||
const obj = deepClone(item) | ||
for (const key in obj) { | ||
if (delArr.indexOf(key) !== -1) { | ||
delete obj[key] | ||
} | ||
} | ||
return obj | ||
} | ||
const getPaginationBindValue = computed((): IObj => { | ||
const PaginationBindValue = | ||
props.pagination && isObject(props.pagination) ? { ...props.pagination } : {} | ||
return PaginationBindValue | ||
}) | ||
const paginationStyle = computed(() => { | ||
return { | ||
textAlign: (props.pagination && (props.pagination as IObj).position) || 'right' | ||
} | ||
}) | ||
function headerDragend(newWidth: number, _: number, column: IObj) { | ||
// 不懂为啥无法自动计算宽度,只能手动去计算了。。失望ing,到时候看看能不能优化吧。 | ||
const htmlArr = document.getElementsByClassName(column.id) | ||
for (const v of htmlArr as any) { | ||
if (v.firstElementChild) { | ||
;(v.firstElementChild as any).style.width = newWidth + 'px' | ||
} | ||
} | ||
} | ||
function sizeChange(val: number) { | ||
if (props.pagination && (props.pagination as IObj).onSizeChange) { | ||
;(props.pagination as IObj).onSizeChange(val) | ||
} | ||
} | ||
function currentChange(val: number) { | ||
if (props.pagination && (props.pagination as IObj).onCurrentChange) { | ||
;(props.pagination as IObj).onCurrentChange(val) | ||
} | ||
} | ||
defineExpose({ | ||
getTableRef | ||
}) | ||
</script> | ||
|
||
<style lang="less" scoped> | ||
.pagination__wrap { | ||
padding: 10px; | ||
margin-top: 15px; | ||
background: #fff; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.