1.对表格复用的查询、重置、分页等方法进行抽取封装hooks
import { ref, reactive, onMounted } from 'vue'
// 表格通用代码抽取hook,具体用法参考财务管理-发票台账或者合同管理-合同台账
export default function () {
// 搜索按钮加载
const searchLoading = ref(false)
// 重置按钮加载
const resetLoading = ref(false)
// 表格高度
const height = ref(500)
// 表格加载标志
const tableLoading = ref(false)
// 分页数据
const pagination = reactive({
current: 1,
total: 0,
size: 20,
})
onMounted(() => {
// 根据表格上方的el-form行数,动态减取高度,换行请使用el-form包裹
const line = document.querySelectorAll('.el-form').length
height.value = window.innerHeight - (280 + (line - 1) * 45)
})
// 搜索
const handleSearch = (getData: () => void) => {
searchLoading.value = true
pagination.current = 1
getData()
}
// 重置
const handleReset = (queryParam: any, getData: () => void) => {
resetLoading.value = true
pagination.size = 20
pagination.current = 1
// ------只适用全部重置为空字符串的场景--------
const keys = Object.keys(queryParam)
const obj: { [proName: string]: string } = {}
keys.forEach((item) => {
obj[item] = ''
})
Object.assign(queryParam, obj)
getData()
}
// 改变每页条数
const handleSizeChange = (val: number, getData: () => void) => {
pagination.size = val
getData()
}
// 改变页数
const handleCurrentChange = (val: number, getData: () => void) => {
pagination.current = val
getData()
}
// 表格行样式控制
const tableRowClassName = ({ rowIndex }: any) => {
if (rowIndex % 2 == 0) {
return 'warning-row'
} else {
return 'success-row'
}
}
const returnObj = {
searchLoading,
resetLoading,
height,
pagination,
tableLoading,
handleSearch,
handleReset,
tableRowClassName,
handleSizeChange,
handleCurrentChange,
}
return returnObj
}
页面使用
import useTableCode from '@/hooks/useTableCode'
const {
searchLoading,
resetLoading,
height,
pagination,
tableLoading,
handleSearch,
handleReset,
tableRowClassName,
handleSizeChange,
handleCurrentChange,
} = useTableCode()
<template>
<div class="herded_box">
<el-form :inline="true" style="height: 44px" @keyup.enter="handleSearch(getData)">
<el-form-item>
<el-input size="small" clearable v-model="queryParam.invoiceNo" placeholder="请输入发票号码"></el-input>
</el-form-item>
<el-form-item v-if="systemType == '2'">
<el-input size="small" clearable v-model="queryParam.buyerName" placeholder="请输入发票抬头"></el-input>
</el-form-item>
<el-form-item v-if="systemType == '2'">
<el-select v-model="queryParam.status" placeholder="请选择发票状态" clearable>
<el-option
v-for="(item, index) in $getDictOptions('INVOICE_STATUS')"
:key="index"
:label="item.name"
:value="item.code"></el-option>
</el-select>
</el-form-item>
<!-- --------- -->
<el-form-item>
<el-button type="primary" @click="handleSearch(getData)" :loading="searchLoading">查询 </el-button>
<el-button @click="handleReset(queryParam, getData)" type="info" :loading="resetLoading">重置</el-button>
</el-form-item>
</el-form>
</div>
<div class="content">
<el-table
size="small"
header-cell-class-name="headerCell"
:cell-style="{ height: '37px' }"
:data="data"
highlight-current-row
:row-class-name="tableRowClassName"
:height="newHeight"
v-loading="tableLoading"
border
element-loading-text="拼命加载中"
style="width: 100%">
<el-table-column :resizable="false" type="index" width="50" label="序号"></el-table-column>
<el-table-column prop="applyInfo.code" label="申请单号"> </el-table-column>
<el-table-column prop="applicantName" label="申请方"> </el-table-column>
<el-table-column prop="handlerName" label="开票方"></el-table-column>
<el-table-column prop="applyInfo.buyerName" label="发票抬头"></el-table-column>
<el-table-column prop="applyInfo.orderNo" label="订单编号">
<template #default="{ row }">
<a class="blueCell" @click="tableOperation(row.applyInfo.orderNo, 'order')">{{ row.applyInfo.orderNo }}</a>
</template>
</el-table-column>
<el-table-column prop="invoiceAmount" label="开票金额(元)">
<template #default="{ row }">
{{ row.amountTax || row.applyInfo.actualAmount }}
</template>
</el-table-column>
<el-table-column prop="applyInfo.createTime" label="申请时间"> </el-table-column>
<el-table-column prop="invoiceTime" label="开票日期">
<template #default="{ row }">
{{ row.invoiceTime && $dayjs.toD(row.invoiceTime) }}
</template>
</el-table-column>
<el-table-column prop="invoiceStatus" label="状态">
<template #default="{ row }">
{{ $transDictName('INVOICE_STATUS', row.invoiceStatus) }}
</template>
</el-table-column>
<el-table-column prop="invoiceNo" label="发票号码">
<template #default="{ row }">
<a class="blueCell" @click="tableOperation(row.invoiceUrl, 'invoice')">{{ row.invoiceNo }}</a>
</template>
</el-table-column>
<el-table-column prop="originalInvoiceNo" label="原发票号码"></el-table-column>
<el-table-column label="电话/邮箱">
<template #default="{ row }">
{{ $transList2String([row.applyInfo.buyerPhone, row.applyInfo.buyerEmail], '/') }}
</template>
</el-table-column>
</el-table>
<div class="footerBox">
<el-pagination
v-model:page-size="pagination.size"
@size-change="handleSizeChange($event, getData)"
@current-change="handleCurrentChange($event, getData)"
:current-page="pagination.current"
:page-sizes="$page.pageSizes"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
background>
</el-pagination>
</div>
</div>
</template>
2.表格封装
页面使用
<script setup lang="ts">
import { ref, reactive, getCurrentInstance } from 'vue'
import { getPostsale, getPostsaleMake } from '@/api/postsale/index'
import { PostsaleItem } from '@/types/api/postsale/postsale'
import OrderDetail from '@/views/order/components/Info.vue'
import OrderDetailMake from '@/views/order/components/InfoMake.vue'
import PostsaleDetail from './components/postsaleDetail/index.vue'
import PostsaleHandler from './components/postsaleHandler/index.vue'
import useTableCode from '@/hooks/useTableCode'
import { DictEnum } from '@/enums/DictEnum'
const { searchLoading, resetLoading, pagination, tableLoading, handleSearch, handleReset, handleSizeChange, handleCurrentChange } =
useTableCode()
// 订单详情组件实例
const orderDetailRef = ref<InstanceType<typeof OrderDetail>>()
const orderDetailMakeRef = ref<InstanceType<typeof OrderDetailMake>>()
// 售后详情组件实例
const postsaleDetailRef = ref<InstanceType<typeof PostsaleDetail>>()
// 售后处理组件实例
const postsaleHandlerRef = ref<InstanceType<typeof PostsaleHandler>>()
// 表格数据
const data = ref<PostsaleItem[]>([])
// 查询参数
let queryParam = reactive({
code: '',
status: '',
type: '',
size: 20,
})
const height = ref(500)
height.value = window.innerHeight - 280 - 65
// 列数据
const columnData = reactive([
{ text: true, prop: 'applyTime', label: '申请时间' },
{ open: true, prop: 'code', label: '售后编号', query: 'id', type: 'code' },
{ open: true, prop: 'orderNo', label: '关联订单', query: 'orderNo', type: 'orderNo' },
{ text: true, prop: 'orderAmount', label: '订单金额(元)' },
{ transDictName: true, prop: 'type', label: '售后类型', color: '#8400ff', query: DictEnum.AFTER_SALE_TYPE },
{ transDictName: true, prop: 'requirement', label: '售后要求', color: '#8400ff', query: DictEnum.AFTER_SALE_REQUIREMENT },
{ text: true, prop: 'problemDesc', label: '问题描述' },
{ text: true, prop: 'demandTenantName', label: '需求方' },
{ text: true, prop: 'serviceTenantName', label: '供应方' },
{ slot: true, label: '售后状态', slotName: 'status' },
])
// 系统类型
const systemType = ref('1')
// 请求数据
const nowTime = new Date().getTime()
const getData = () => {
tableLoading.value = true
queryParam.size = pagination.size
let apiFn = null as any
if (systemType.value == '1') {
apiFn = getPostsale
} else if (systemType.value == '2') {
apiFn = getPostsaleMake
}
apiFn(pagination.current, queryParam)
.then((res: any) => {
res.data.list.map((item: any) => {
// 是否显示倒计时 超过48小时则不显示 item.updateTime为客服介入的时间
item.time = Date.parse(item.updateTime) + 48 * 60 * 60 * 1000 - nowTime > 0 ? true : false
})
data.value = res.data.list
pagination.total = res.data.total
Loading()
})
.catch(() => {
Loading()
})
}
getData()
// 重置loading
const Loading = () => {
tableLoading.value = false
searchLoading.value = false
resetLoading.value = false
}
// 表格操作
const tableOperation = (id: string, type: string) => {
const operationTypeMap: { [propName: string]: () => void } = {
code: () => postsaleDetailRef.value?.openDialog(id), // 打开售后详情弹框
orderNo: () => {
if (systemType.value == '1') {
orderDetailRef.value?.openDialog(null, id)
} else if (systemType.value == '2') {
orderDetailMakeRef.value?.openDialog(null, id)
}
}, // 打开订单详情弹框
handler: () => postsaleHandlerRef.value?.openDialog(id), // 打开售后处理弹框
}
operationTypeMap[type] ? operationTypeMap[type]() : ''
}
const toHHmmss = (data: any) => {
let s
let hours = parseInt(((data % (1000 * 60 * 60 * 48)) / (1000 * 60 * 60)).toString())
let minutes = parseInt(((data % (1000 * 60 * 60)) / (1000 * 60)).toString())
let seconds = parseInt(((data % (1000 * 60)) / 1000).toString())
s =
(hours < 10 ? '0' + hours : hours) +
'h:' +
(minutes < 10 ? '0' + minutes : minutes) +
'm:' +
(seconds < 10 ? '0' + seconds : seconds) +
's'
return s
}
const setTimeoutXX = (data: any, successTime: any) => {
setTimeout(() => {
data.updateTimeStr = toHHmmss(successTime)
successTime -= 1000
if (successTime > 0) {
setTimeoutXX(data, successTime)
}
}, 1000)
}
// 倒计时时间转换
const timeFormat = (data: PostsaleItem) => {
if (data.updateTime && !data.updateTimeStr && data.time) {
const kTime = Date.parse(data.updateTime)
let successTime = kTime + 48 * 60 * 60 * 1000 - nowTime
setTimeoutXX(data, successTime)
}
}
</script>
<template>
<div class="box-card">
<el-radio-group v-model="systemType" class="typeRadioButton" @change="handleReset(queryParam, getData)">
<el-radio-button
v-for="item in $getDictOptions(DictEnum.SYSTEM_TYPE)"
:key="item.code"
:label="item.code"
style="margin-bottom: 0"
>{{ item.name + '订单' }}
</el-radio-button>
</el-radio-group>
<!-- 表格封装 具体用法 '@/components/FsTable/index.vue' @/components/FsPagination/index.vue-->
<FsTable
:table-loading="tableLoading"
:table-data="data"
:pagination-obj="pagination"
:column-data="columnData"
:table-height="height"
@open-dialog-or-blank="tableOperation">
<template #search-form>
<el-form :inline="true" style="height: 44px" @keyup.enter="handleSearch(getData)">
<el-form-item>
<el-select v-model="queryParam.type" placeholder="请选择售后类型" size="small">
<el-option
v-for="(item, index) in $getDictOptions(DictEnum.AFTER_SALE_TYPE)"
:key="index"
:label="item.foregroundName"
:value="item.code" />
</el-select>
</el-form-item>
<el-form-item>
<el-select v-model="queryParam.status" placeholder="请选择售后状态" size="small">
<el-option
v-for="(item, index) in $getDictOptions(DictEnum.AFTER_SALE_STATUS)"
:key="index"
:label="item.foregroundName"
:value="item.code" />
</el-select>
</el-form-item>
<el-form-item>
<el-input size="small" clearable v-model="queryParam.code" placeholder="请输入售后编号"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch(getData)" :loading="searchLoading">查询 </el-button>
<el-button @click="handleReset(queryParam, getData)" type="info" :loading="resetLoading">重置</el-button>
</el-form-item>
</el-form>
</template>
<template v-slot:status="{ data }">
<span :style="{ color: data.status == '6' ? '#91D28B' : '#e6757d' }">{{
$transDictName(DictEnum.AFTER_SALE_STATUS, data.status)
}}</span>
<div v-if="data.status == '8' && data.updateTime && data.time" style="color: #e6757d">
倒计时:{{ timeFormat(data) }} {{ data.updateTimeStr }}
</div>
</template>
<template #operation>
<el-table-column label="操作" width="128">
<template #default="{ row }">
<el-button size="small" type="danger" @click="tableOperation(row.id, 'handler')" v-if="row.status == '8'"
>处理</el-button
>
<el-button size="small" type="primary" @click="tableOperation(row.id, 'code')">详情</el-button>
</template>
</el-table-column>
</template>
<template #pagination>
<FsPagination
:pagination-obj="pagination"
@sizeChange="handleSizeChange($event, getData)"
@currentChange="handleCurrentChange($event, getData)"></FsPagination>
</template>
</FsTable>
<OrderDetail ref="orderDetailRef" />
<OrderDetailMake ref="orderDetailMakeRef" />
<PostsaleDetail ref="postsaleDetailRef" />
<PostsaleHandler ref="postsaleHandlerRef" @getPageData="handleSearch(getData)" />
</div>
</template>
<style lang="scss" scoped></style>
表格组件
<script setup lang="ts">
import { ref, onMounted, getCurrentInstance } from 'vue'
import { ElInput } from 'element-plus'
const inputRef = ref<InstanceType<typeof ElInput>>()
const props = defineProps<{
tableData: Array<{ [propName: string]: any }> //表格数据
tableLoading: boolean //表格加载
selection?: boolean //是否显示表格多选列
columnData: Array<{ [propName: string]: any }> //列的数据
paginationObj: { current: number; total: number; size: number } //分页数据
tableHeight?: number
}>()
/**
* columnData用法
*
* text:文本、 open:打开弹窗或者网页、 time:时间、 transDictName:数据字典转状态、 transList2String:传递数组和分隔符 分割文字
* label:列标题
* prop: 列数据 (复杂情况,如深层次prop:applyInfo.code,请传递函数 (row: any) => row.applyInfo.code)
* query:需要传递的数据,例:1.open为true时,传递query: (row: any) => row.applyInfo.orderNo, 2.transDictName为true时,传递query: DictEnum.INVOICE_STATUS, 3.transList2String为true时,传递query: (row: any) => [row.applyInfo.buyerPhone, row.applyInfo.buyerEmail],
* type:区分类型,例: open为true时,传递type: 'orderNo',区分点击的是哪列
*
* const columnData = reactive([
*
* ---------文本用法--------
* { text: true, prop: 'applicantName', label: '申请方' },
* { text: true, label: '发票抬头', prop: (row: any) => row.applyInfo.buyerName },
* {
* text: true,
* prop: (row: ContractTemplateTable) => (row.status == 0 ? '停用' : '启用'),
* label: '状态',
* color: (row: ContractTemplateTable) => (row.status == 0 ? '#f59a23' : '#22a417'),
* },
* { text: true, label: '申请单号', prop: (row: any) => [{ text: '10', color: 'red', fontSize: '16px' },{ text: '12', color: 'blue', fontSize: '16px' },{ text: '12', color: 'blue', fontSize: '16px' }] ,separator: ' / '},
*
* ---------点击打开用法--------
* { open: true, prop: 'code', label: '合同模板编号', query: (row: ContractTemplateTable) => row },
* {
* open: true,
* prop: (row: any) => row.applyInfo.orderNo,
* label: '订单编号',
* query: (row: any) => row.applyInfo.orderNo,
* type: 'orderNo',
* },
* // 下载文件 query传数组
* {
* open: true,
* prop: fileName,
* label: '订单编号',
* query: (row: any) => [row.fileUrl,row.fileName],
* },
* ---------时间用法--------
* { time: true, label: '申请时间', prop: (row: any) => row.applyInfo.createTime },
* { time: true, prop: 'invoiceTime', label: '开票日期' },
*
* ---------转换分隔符用法--------
* { transList2String: true,label: '合同类型', query: (row: ContractTemplateTable) => [row.typePName, row.typeName], separator: '/',},
*
* ---------数据字典用法--------
* { transDictName: true, prop: 'invoiceStatus', label: '状态', query: DictEnum.INVOICE_STATUS },
* { transDictName: true, prop: (row: any) => row.applyInfo.invoiceStatus , label: '状态', query: DictEnum.INVOICE_STATUS },
*
* ---------数据字典与转换分隔符结合用法---------
* prop为['0','1']
* {transList2StringAndDictName:true, prop:'typeList',label:'发布范围', query: DictEnum.INVOICE_STATUS, separator: ',',}
*
* ----------switch用法------------
* { switch: true, prop: 'status', label: '是否禁用', query: ['1', '0'], switchFlag: (row: any) => row ,type:'switch'},
*
* ----------tag用法------------
* { tag: true, prop: (row:any)=>row.type == 0 ? '菜单' :row.type == 1 ?'按钮':'外链', label: '菜单类型', query: (row:any)=>row.type == 0 ? 'success' :row.type == 1 ?'danger':'info', },
*
* ----------图片用法------------
* { picture: true, prop: 'avatar', label: '头像' },
*
* ----------复杂列 使用插槽--------
* { slot: true, prop: 'applicantName', label: '申请方', slotName: 'tag' },
* // =>父组件使用插槽,data接收数据
* <template v-slot:tag="{ data }">
* <el-tag v-if="data.applyInfo.actualAmount == 200000">123</el-tag> {{ data.applicantName }}
* </template>
*
*
])
*/
const emits = defineEmits(['openDialogOrBlank', 'switchChange', 'editCellInput', 'selectionArr'])
/**
* 表格高度
*/
const height = ref(500)
/**
* 根据表格上方的el-form行数,动态减取高度,换行请使用el-form包裹
*/
onMounted(() => {
const line = document.querySelectorAll('.el-form').length
height.value = window.innerHeight - (280 + (line - 1) * 45)
})
/**
* 表格行样式控制
*/
const tableRowClassName = ({ rowIndex }: any) => {
if (rowIndex % 2 == 0) {
return 'warning-row'
} else {
return 'success-row'
}
}
/**
* 打开弹窗或者网页
*
* @param query 打开时需要传递的东西
* @param type 如果有多个点击的,传递类型去判断点击的是哪个
*/
const openDialogOrBlank = (query: any, type: string) => {
emits('openDialogOrBlank', query, type)
}
/**
* switch按钮切换
*
*/
const switchChange = (status: number | boolean | string, row: any) => {
emits('switchChange', status, row)
}
/**
* 图片预览
*
*/
const showViewer = ref(false)
const ImgUrlList = ref<Array<string>>([])
const closeImg = () => {
ImgUrlList.value = []
showViewer.value = false
}
/**
* 点击图片
*
*/
const clickImage = (url: string) => {
// 如果url为空,不打开预览
if (!url) {
return
}
ImgUrlList.value.push(url)
showViewer.value = true
}
/**
* 表格单元格双击触发
*
* @param row 单元格所在行
* @param column 单元格所在列
*/
const currentCell = ref<string | null>(null)
const cellClick = (row: any, column: any) => {
currentCell.value = row.id + ',' + column.id
// nextTick(() => {
// inputRef.value[0]?.focus()
// })
}
/**
* 更新表格数据
*
* @param event.target.value 为输入框的值
*/
const hideInput = (event: any, row: any) => {
currentCell.value = null
emits('editCellInput', event.target?.value, row)
}
/**
* 表格多选
*
* @param selectionArr 选中的每一行全部数据组成的数组
*/
const handleSelectionChange = (selectionArr: any) => {
emits('selectionArr', selectionArr)
}
/**
* 根据数据字典转换为数组
*
* @param propArr 传过来的状态值 数组
* @param dictType 数据字典类型
*/
const transDitNameArr = (propArr: string[] | any, dictType: string) => {
let dictArr = []
dictArr = propArr?.map((propItem: string) => getCurrentInstance()?.proxy?.$transDictName(dictType, propItem))
return dictArr
}
</script>
<template>
<div>
<div class="herded_box">
<slot name="search-form"></slot>
</div>
<div class="content">
<el-table
size="small"
header-cell-class-name="headerCell"
highlight-current-row
v-loading="props.tableLoading"
border
element-loading-text="拼命加载中"
style="width: 100%"
:cell-style="{ height: '37px' }"
:data="props.tableData"
:row-class-name="tableRowClassName"
:height="tableHeight ? tableHeight : height"
@cell-dblclick="cellClick"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" v-if="props.selection" />
<el-table-column :resizable="false" type="index" width="50" label="序号"></el-table-column>
<!-- 列封装 -->
<el-table-column
v-for="(columnItem, columIndex) in columnData"
:key="columIndex"
:label="columnItem.label"
:width="columnItem?.width">
<template #default="{ row, column }">
<!-- 1.纯文字 -->
<template v-if="columnItem.text">
<!-- 1.1深层次prop 例如传递的prop是applyInfo.code-->
<template v-if="typeof columnItem?.prop == 'function'">
<!-- 1.1.1 需要根据状态去显示不同颜色的文本,需要传递prop函数:[{text:'文本',color:'red',fontSize:'16px'}] 多个文本-->
<template v-if="columnItem?.prop(row) instanceof Array">
<a
v-for="(item, index) in columnItem?.prop(row)"
:key="index"
:style="{ color: item.color, 'font-size': item.fontSize }">
{{ item.text }}
<span v-if="index + 1 != columnItem?.prop(row).length" style="color: #334155 !important">{{
columnItem?.separator
}}</span>
</a>
</template>
<!-- 1.1.2 需要根据状态去显示不同颜色的文本,需要传递color函数 单个文本-->
<span
v-else
:style="{ color: typeof columnItem.color == 'function' ? columnItem.color(row) : columnItem.color }"
>{{ columnItem.prop(row) }}</span
>
</template>
<!-- 1.2单层prop -->
<template v-else>
<!-- 1.2.1 需要根据状态去显示不同颜色的文本,需要传递color函数 -->
<span
:style="{ color: typeof columnItem.color == 'function' ? columnItem.color(row) : columnItem.color }"
>{{ row[columnItem.prop] }}</span
>
</template>
</template>
<!-- 2.蓝色文字可点击 -->
<a v-if="columnItem.open" class="blueCell">
<!-- 2.1深层次prop 例如传递的prop是applyInfo.code, deepQuery:如果需要传递的-->
<span
v-if="typeof columnItem?.prop == 'function'"
@click="
openDialogOrBlank(
typeof columnItem.query == 'function' ? columnItem.query(row) : row[columnItem.query],
columnItem.type
)
">
{{ columnItem.prop(row) }}
</span>
<!-- 2.2单层prop -->
<span
v-else
@click="
openDialogOrBlank(
typeof columnItem.query == 'function' ? columnItem.query(row) : row[columnItem.query],
columnItem.type
)
"
>{{ row[columnItem.prop] }}</span
>
</a>
<!-- 3.时间文本 -->
<template v-if="columnItem.time">
<span>
{{
typeof columnItem?.prop == 'function'
? columnItem.prop(row) && $dayjs.toM(columnItem.prop(row))
: row[columnItem.prop] && $dayjs.toM(row[columnItem.prop])
}}
</span>
</template>
<!-- 4.根据数据字典转换 -->
<template v-if="columnItem.transDictName">
<span :style="{ color: typeof columnItem.color == 'function' ? columnItem.color(row) : columnItem.color }">
{{
$transDictName(
columnItem.query,
typeof columnItem?.prop == 'function' ? columnItem.prop(row) : row[columnItem.prop]
)
}}
</span>
</template>
<!-- 5.根据数组去使用分隔符转换为文本 -->
<template v-if="columnItem.transList2String">{{
$transList2String(columnItem.query(row), columnItem.separator)
}}</template>
<!-- 5.1 根据数据字典转换成数组 再转换为文本 -->
<template v-if="columnItem.transList2StringAndDictName">{{
$transList2String(transDitNameArr(row[columnItem.prop], columnItem.query), columnItem.separator)
}}</template>
<!-- 6.switch切换 -->
<template v-if="columnItem.switch">
<el-switch
style="--el-switch-on-color: #f56c6c"
:active-value="columnItem.query[0]"
:inactive-value="columnItem.query[1]"
v-model="row[columnItem.prop]"
@change="switchChange($event, columnItem.switchFlag(row))" />
</template>
<!-- 7.el-tag -->
<template v-if="columnItem.tag">
<el-tag :type="columnItem.query">{{ columnItem.prop }} </el-tag>
</template>
<!-- 8.图片 -->
<span v-if="columnItem.picture" @click="clickImage(row[columnItem.prop])" class="span-image">
<el-image class="click-image" :src="row[columnItem.prop]">
<template #error>
<img src="@/assets/images/avatar-default.png" />
</template>
</el-image>
</span>
<!-- 9.单元格编辑 -->
<template v-if="columnItem.cellClick">
<!--v-if去判断双击的是不是当前单元格-->
<el-input
@blur="hideInput($event, row)"
size="small"
ref="inputRef"
v-model="row[columnItem.prop]"
style="margin-left: 10px; width: calc(100% - 20px)"
v-if="row.id + ',' + column.id == currentCell">
</el-input>
<span v-else style="margin-left: 15px">{{ row[columnItem.prop] }}</span>
</template>
<!-- 10.复杂列 使用插槽 -->
<slot v-if="columnItem.slot" :name="columnItem.slotName" :data="row"> </slot>
</template>
</el-table-column>
<!-- 操作列 -->
<slot name="operation"></slot>
</el-table>
<!-- 分页 -->
<div class="footerBox">
<slot name="pagination"></slot>
</div>
</div>
<el-image-viewer v-if="showViewer" :url-list="ImgUrlList" @close="closeImg" />
</div>
</template>
<style lang="scss" scoped>
.span-image {
width: 30px;
display: inline-block;
.click-image {
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
}
}
</style>
分页组件
<script setup lang="ts">
const props = defineProps<{
paginationObj: { current: number; total: number; size: number }
}>()
const emits = defineEmits(['sizeChange', 'currentChange'])
// 改变每页条数
const handleSizeChange = (val: number) => {
emits('sizeChange', val)
}
// 改变页数
const handleCurrentChange = (val: number) => {
emits('currentChange', val)
}
</script>
<template>
<el-pagination
:page-size="props.paginationObj.size"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="props.paginationObj.current"
:page-sizes="$page.pageSizes"
layout="total, sizes, prev, pager, next, jumper"
:total="props.paginationObj.total"
background>
</el-pagination>
</template>
<style lang="scss" scoped></style>