![](https://i-blog.csdnimg.cn/blog_migrate/e6c48d78ef732e5bd0da9e07b5968a03.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e8b1a1efea357a550780112e448c32df.png)
新建三个文件
src\components\page-content\page-content.vue 表格公共文件
src\view\main\system\department\config\content.config.ts表格数据配置
src\view\main\system\department\department.vue 父组件,传输数据
department.vue
<template>
<div class="department">
<div class="user">
<div class="content">
<page-content ref="contentRef" @addClickBtn="handleAddClick" @editClickBtn="handleEditClick" :contentConfig="contentConfig">
<template #leader="scope">
<!-- 接受插槽传输过来的scoped数据,获取插槽数据, -->
<div class="slot">{{ scope.row[scope.prop] }}</div>
</template>
<template #parentId="scope">
<!-- 接受插槽传输过来的scoped数据,对scoped数据进行处理 -->
<div class="slot">{{ scope.row[scope.prop] }}</div>
</template>
</page-content>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import pageContent from '@/components/page-content/page-content.vue'
import contentConfig from './config/content.config'
</script>
<style lang="scss" scoped>
.department {}
.slot {
color: red
}
</style>
page-content.vue
条件渲染column数据(timer、handler、custom)
slot插槽对column数据进行处理和样式修改
编辑、删除方法的网络请求
<template>
<div class="user-content">
<!-- 头部header -->
<div class="header">
<h3>{{ contentConfig.header?.title ?? '数据列表' }}</h3>
<el-button type="primary" @click="addPage">{{ contentConfig.header?.btnTitle ?? '添加数据' }}</el-button>
</div>
<!-- 中间表格 table-->
<div class="table">
<el-table :data="pageList" border style="width: 100%" ref="pageListRef">
<!-- 可以用v-bind来绑定,等同于上面的数据 -->
<template v-for="item in contentConfig.tableColumn" :key="item.prop">
<!-- 当表格数据为时间数据时,处理数据-->
<template v-if="item.type === 'timer'">
<el-table-column v-bind="item">
<template #default="scoped">
{{ formatUTC(scoped.row[item.prop]) }}
</template>
</el-table-column>
</template>
<!-- 当表格为按钮时 -->
<template v-else-if="item.type === 'handler'">
<el-table-column :label="item.label" width="200">
<template #default="scoped">
<el-button icon="Edit" @click="editClickBtn(scoped.row)">编辑</el-button>
<el-button icon="Delete" @click="deleteClickBtn(scoped.row.id)">删除</el-button>
</template>
</el-table-column>
</template>
<!-- 插槽 -->
<template v-else-if="item.type === 'custom'">
<el-table-column :label="item.label">
<template #default="scope">
<!-- 将数据绑定在scope上,把scope数据传输给父组件,给scope数据添加prop属性-->
<slot :name="item.slotName" v-bind="scope" :prop="item.prop"></slot>
</template>
</el-table-column>
</template>
<!-- 表格数据为普通数据时 -->
<template v-else>
<el-table-column v-bind="item" />
</template>
</template>
</el-table>
</div>
<!-- 分页-pagination -->
<div class="pagination">
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20]"
:small="small" :disabled="disabled" :background="background" layout="total, sizes, prev, pager, next, jumper"
:total="totalPageCount" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { formatUTC } from '@/utils/format'
import userSystemStore from '@/store/main/system/system'
import userMainStore from '@/store/main/main'
import { storeToRefs } from 'pinia'
interface IContent {
contentConfig: {
header?: {
title?: string
btnTitle?: string
}
tableColumn: any[]
width?: {
type: number
default: 120
}
pageName: string
}
}
const prop = defineProps<IContent>()
console.log('contentConfig.tableColumn :>> ', prop)
const userSystem = userSystemStore()
const userMain = userMainStore()
//由于这个方法是异步的,所以拿不到userSystem里的数据,可以用computed方法和storeToRefs方法
// userSystem.postpageListAction()
const { pageList } = storeToRefs(userSystem)
const { totalPageCount } = storeToRefs(userSystem)
// 编辑用户
function editClickBtn(item: any) {
console.log('item0000000 :>> ', item)
emit('editClickBtn', item)
}
//删除用户
function deleteClickBtn(id: number) {
userSystem.deletePageAction(prop.contentConfig.pageName, id)
}
const emit = defineEmits(['addClickBtn', 'editClickBtn'])
//新建用户
function addPage() {
emit('addClickBtn')
}
//==============================分页器==================================
const currentPage = ref(1)
const pageSize = ref(10)
const small = ref(false)
const background = ref(false)
const disabled = ref(false)
fetchpageListData()
//页码和每页数据条数改变时重新发送请求
function fetchpageListData(fetchpageListData: any = {}) {
const size = pageSize.value
const offset = (currentPage.value - 1) * size
const info = { size, offset }
//数据偏移量offset
const queryInfo = { ...info, ...fetchpageListData }
userSystem.postPageListAction(prop.contentConfig.pageName, queryInfo)
}
//将方法暴露给父组件
defineExpose({ fetchpageListData })
// 每页展示数据条数
const handleSizeChange = (val: number) => {
pageSize.value = val
fetchpageListData()
}
// 前往第几页和点击页数
const handleCurrentChange = (val: number) => {
currentPage.value = val
fetchpageListData()
}
</script>
<style lang="scss" scoped>
.user-content {
background-color: #fff;
}
.header {
margin-top: 20px;
padding: 20px;
display: flex;
justify-content: space-between;
}
// 分页器
.pagination {
display: flex;
justify-content: right;
padding: 10px;
}
</style>
content.config.ts
// 配置department的serach区域的数据
const contentConfig = {
pageName: 'department',
title: '部门列表',
button: '新建部门',
tableColumn: [
{
type: 'selection',
width: '60px'
},
{
type: 'index',
label: '序号',
width: '80px'
},
{
label: '部门名称',
prop: 'name',
width: '120px'
},
{
label: '部门领导',
prop: 'leader'
},
{
label: '上级部门',
prop: 'parentId'
},
{
type: 'timer',
label: '创建时间',
prop: 'createAt',
width: '170px'
},
{
type: 'timer',
label: '更新时间',
prop: 'updateAt',
width: '170px'
},
{
type: 'handler',
label: '编辑'
// prop: 'createAt'
},
{
// 插槽数据
type: 'custom',
slotName: 'leader',
label: '上级',
prop: 'leader'
// width: '150px'
},
{
// 插槽数据
type: 'custom',
slotName: 'parentId',
label: '级',
prop: 'parentId'
// width: '150px'
}
]
}
export default contentConfig