bash
<template>
<div class="jw-tables" @click="handleClickOutside">
<div class="jw-title">
<span>{{ title || '-' }}</span>
</div>
<div :style="{maxHeight: boxHeight+'px'}">
<el-table ref="jwTables" tooltip-effect="light" :data="tableData" :max-height="boxHeight" @row-click="rowClick"
@selection-change="handleSelectionChange" style="width: 100%">
<el-table-column :fixed="true" type="selection" :selectable="selectable" width="55" v-if="showSelection"/>
<el-table-column :fixed="true" type="index" v-if="showIndex" width="100" label="序号" align="center" :index="indexMethod"/>
<el-table-column v-for="(item,index) in tableHeader" :key="index"
:label="item.label" :align="item.align==undefined?align:item.align" :fixed="item.fixed"
:width="item.width">
<template #header v-if="item.isFilter">
<el-popover placement="bottom" trigger="click" :width="'fit-content'">
<template #default>
<div>
<remoteSelect @handleChange="remoteSelectChange"
v-if="item.formType === 'remoteSelect'" :taskId="taskId" :values="data.filterValue[item.prop]"
:receiveId="receiveId" :submitLogId="submitLogId" :url="item.url" :propName="item.prop"
style="margin-top: 10px;width: 150px;"
/>
<el-select v-else-if="item.formType === 'multipleSelect'" filterable
:reserve-keyword="false" v-model="data.filterValue[item.prop]"
@change="searchFilter(item.prop, data.filterValue[item.prop])" placeholder="请选择" style="margin-top: 10px;width: 150px;">
<el-option v-for="mult in item.selectList" :key="mult.value" :label="mult.text" :value="mult.value" />
</el-select>
<el-select v-else-if="item.formType === 'select'" filterable
:reserve-keyword="false" v-model="data.filterValue[item.prop]" placeholder="请选择"
@change="searchFilter(item.prop, data.filterValue[item.prop])" clearable style="margin-top: 10px; width: 150px;">
<el-option v-for="selVal in item.selectList" :key="selVal" :value="selVal.value"
:label="selVal.text" />
</el-select>
<el-select v-else-if="item.formType === 'select_group'" filterable
:reserve-keyword="false" v-model="data.filterValue[item.prop]" placeholder="请选择"
@change="searchFilter(item.prop, data.filterValue[item.prop])" clearable style="margin-top: 10px; width: 150px;">
<el-option-group v-for="selVal in item.selectList" :key="selVal.value"
:label="selVal.text" >
<el-option v-for="(op) in selVal.option"
:key="op.value"
:label="op.text"
:value="op.value"
/>
</el-option-group>
</el-select>
<el-input v-else v-model="data.filterValue[item.prop]" placeholder="请输入关键字" class="marginT5" />
<div class="marginT10" style="text-align: right;">
<el-button type="info" link @click="cancelFilter(item.prop)">重置</el-button>
<el-button type="primary" link @click="searchFilter(item.prop, data.filterValue[item.prop])">筛选
</el-button>
</div>
</div>
</template>
<template #reference>
<div class="flexCenter">
<span>{{ item.label }}</span>
<el-icon style="cursor: pointer; margin-left: 6px;" size="20"
:style="{ color: data.filterValue[item.prop] ? '#ffffff !important' : '#ffffff80 !important' }">
<Filter/>
</el-icon>
</div>
</template>
</el-popover>
</template>
<el-table-column v-if="item.children != ''"
v-for="(item1,index1) in item.children" :key="index1" :label="item1.label"
:align="item1.align==undefined?align:item1.align" :width="item1.width">
<template #header v-if="item1.isFilter">
<el-popover placement="bottom" trigger="click" :width="'fit-content'">
<template #default>
<div>
<remoteSelect @handleChange="remoteSelectChange"
v-if="item1.formType === 'remoteSelect'" :taskId="taskId" :values="data.filterValue[item.prop]"
:receiveId="receiveId" :submitLogId="submitLogId" :url="item1.url" :propName="item1.prop"
style="margin-top: 10px;width: 150px;"
/>
<el-select v-else-if="item1.formType === 'multipleSelect'" filterable
:reserve-keyword="false" v-model="data.filterValue[item1.prop]"
@change="searchFilter(item1.prop, data.filterValue[item1.prop])" placeholder="请选择" style="margin-top: 10px;width: 150px;">
<el-option v-for="mult in item1.selectList" :key="mult.value" :label="mult.text" :value="mult.value" />
</el-select>
<el-select v-else-if="item1.formType === 'select'" filterable :multiple="item1.multiple || false"
:reserve-keyword="false" v-model="data.filterValue[item1.prop]" placeholder="请选择"
@change="searchFilter(item1.prop, data.filterValue[item1.prop])" clearable style="margin-top: 10px; width: 150px;">
<el-option v-for="selVal in item1.selectList" :key="selVal" :value="selVal.value"
:label="selVal.text" />
</el-select>
<el-select v-else-if="item.formType === 'select_group'" filterable
:reserve-keyword="false" v-model="data.filterValue[item1.prop]" placeholder="请选择"
@change="searchFilter(item1.prop, data.filterValue[item1.prop])" clearable style="margin-top: 10px; width: 150px;">
<el-option-group v-for="selVal in item.selectList" :key="selVal"
:label="selVal.text" >
<el-option v-for="(op,index) in item.option"
:key="index"
:label="op.text"
:value="op.value"
/>
</el-option-group>
</el-select>
<el-input v-else v-model="data.filterValue[item1.prop]" placeholder="请输入关键字" class="marginT5" />
<div class="marginT10" style="text-align: right;">
<el-button type="info" link @click="cancelFilter(item1.prop)">重置</el-button>
<el-button type="primary" link @click="searchFilter(item1.prop, data.filterValue[item1.prop])">
筛选
</el-button>
</div>
</div>
</template>
<template #reference>
<div class="flexCenter">
<span>{{ item1.label }}</span>
<el-icon style="cursor: pointer; margin-left: 6px;" size="20"
:style="{ color: data.filterValue[item1.prop] ? '#ffffff !important' : '#ffffff80 !important' }">
<Filter/>
</el-icon>
</div>
</template>
</el-popover>
</template>
<el-table-column v-if="item1.children != ''"
v-for="(item2,index2) in item1.children" :key="index2" :label="item2.label"
:align="item2.align==undefined?align:item2.align" :width="item2.width">
<template #default="scope">
<el-tooltip placement="top" :disabled="!isShowTooltip" effect="light">
<template #content>
<div>{{ item2.formatter==undefined?scope.row[item2.prop]:item2.formatter(scope.row,scope.row[item2.prop]) }}</div>
</template>
<div class="ellipsis-2" :class="item2.align==undefined?'text-center':`text-${item2.align}`" @mouseenter="visibilityChange($event)">{{ item2.formatter==undefined?scope.row[item2.prop]:item2.formatter(scope.row,scope.row[item2.prop]) }}</div>
</el-tooltip>
</template>
</el-table-column>
<template v-else #default="scope" v-if="item.children==undefined || item1.children == ''">
<el-tooltip placement="top" :disabled="!isShowTooltip" effect="light">
<template #content>
<div>{{ item1.formatter==undefined?scope.row[item1.prop]:item1.formatter(scope.row,scope.row[item1.prop]) }}</div>
</template>
<div class="ellipsis-2" :class="item1.align==undefined?'text-center':`text-${item1.align}`" @mouseenter="visibilityChange($event)">{{ item1.formatter==undefined?scope.row[item1.prop]:item1.formatter(scope.row,scope.row[item2.prop]) }}</div>
</el-tooltip>
</template>
</el-table-column>
<template #default="scope" v-if="item.children==undefined || item.children==null || item.children == ''">
<el-tooltip placement="top" :disabled="!isShowTooltip" effect="light">
<template #content>
<div>{{ item.formatter==undefined?scope.row[item.prop]:item1.formatter(scope.row,scope.row[item.prop]) }}</div>
</template>
<div class="ellipsis-2" :class="item.align==undefined?'text-center':`text-${item.align}`" @mouseenter="visibilityChange($event)">{{ item.formatter==undefined?scope.row[item.prop]:item.formatter(scope.row,scope.row[item2.prop]) }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column
align="center"
:label="opColumnLabel"
:width="buttonWidth"
fixed="right"
v-if="isShow">
<template #default="scope">
<template v-if="isShowUserOp">
<div v-if="selectUser && !scope.row.selectedUser" class="flex items-center"
style="justify-content: space-between;" @click.stop="selectWriteUser(scope.row.id, scope.row.fillObj)">
<div class="paddingH10 css-users ellipsis-2">
<span v-for="user in (scope.row.fillObj)">{{ user.userName + '-' + user.orgName }}</span>
</div>
<span style="color: #0079fe;cursor: pointer;">选择人员</span>
</div>
<div v-else class="flex items-center" style="justify-content: space-between;">
<div class="paddingH10 css-users ellipsis-2">
<span v-for="user in (scope.row.fillObj)">{{ user.userName + '-' + user.orgName }}</span>
</div>
<span style="color: #555;cursor: pointer;">已下发</span>
</div>
</template>
<template v-for="(btn,index) in buttons">
<el-link v-if="(btn.isShow ==undefined?true:btn.isShow(scope.row)) && !btn.url && btn.label!='删除'"
class="marginR20"
v-permission="btn.permission"
:underline="false" :type="btn.type==undefined?'primary':btn.type" :key="btn.label"
@click.stop="btn.click(scope.row)" :class="btn.click?'pointer':'no-pointer'"
:style="{color: btn.color}" size="small">
{{ btn.label }}
</el-link>
<el-popconfirm v-else-if="btn.label=='删除'"
class="box-item"
title="确定删除当条数据吗?"
placement="left"
@confirm="btn.click(scope.row)"
>
<template #reference>
<el-link size="small" :type="btn.type==undefined?'primary':btn.type" @click.stop="">
{{ btn.label }}
</el-link>
</template>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
</div>
<el-pagination
v-if="tableData.length > 0 && isPage"
class="comtable-pagination marginT20" style="justify-content: flex-end;"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="pageSizes"
:page-size="pageSize"
layout="total, prev, pager, next, sizes"
:total="total"
>
</el-pagination>
</div>
</template>
<script setup>
import {computed, reactive, ref, onMounted} from 'vue'
import remoteSelect from './remoteSelect.vue';
import router from "@/router";
const props = defineProps({
title: '',
description: '',
tableHeader: Array,
tableData: Array,
align: {
type: String,
default: 'center'
},
// 是否显示选择人员审批
isShowUserOp: {
type: Boolean,
default: true,
},
// 是否显示选择框
showSelection: {
type: Boolean,
default: false,
},
// 是否显示序号
showIndex: {
type: Boolean,
default: true,
},
// 操作列宽度
buttonWidth: {
type: Number,
default: 300
},
// 操作按钮
buttons: {
type: Array,
default: []
},
// 固定列
fixed: {
type: Boolean,
default: true
},
selectUser: {
type: Boolean,
default: false,
},
selectedInfo: {
type: Array,
default: []
},
currentPage: {
type: Number,
default: 1
},
pageSize: {
type: Number,
default: 15
},
total: {
type: Number,
default: 0
},
isPage: {
type: Boolean,
default: true,
},
pageSizes: {
type: Array,
default: [10, 15, 20, 50, 100]
},
tableScrollHeight: {
type: Number,
default: 0
},
selectableFileds: {
type: Array,
default: []
},
opColumnLabel: {
type: String,
default: '操作'
},
isShowTableFormatter:{
type:Boolean,
default:false
},
taskId: {
type: String,
default: ''
},
receiveId: {
type: String,
default: ''
},
submitLogId: {
type: String,
default: ''
}
})
const boxHeight = computed(() => window.innerHeight - props.tableScrollHeight);
const data = reactive({
filterValue: []
})
const tableFormatter = ref("完整版")
const selectVal = ref([]);
const selectData = ref([]);
const emit = defineEmits(['searchFilter', 'cancelFilter', 'rowClick', 'selectWriteUser', 'handleSizeChange', 'handleCurrentChange', 'handleSelectionChange', 'cancelSelectRow'])
const tableFormatterChange = ()=>{
emit("tableFormatterChange",tableFormatter.value)
}
const handleSelectionChange = (val) => {
selectVal.value = val;
selectVal.value.map((rows) => rows.checked = true);
emit('handleSelectionChange', selectVal.value);
}
const selectable = (row) => {
// 获取需要禁用checkbox的数据 id
return !props.selectableFileds.includes(row.id)
// return !row.selectedUser;
}
const jwTables = ref()
const toggleSelection = (rows, ignoreSelectable) => {
if (rows) {
rows.forEach((row) => {
jwTables.value.toggleRowSelection(
row,
undefined,
ignoreSelectable
)
})
} else {
jwTables.value.clearSelection()
}
}
const handleSizeChange = (pageSize) => {
emit("handleSizeChange", pageSize);
}
const handleCurrentChange = (currentPage) => {
emit("handleCurrentChange", currentPage);
}
const remoteSelectChange = (prop, value) => {
data.filterValue[prop] = value
searchFilter(prop, value)
}
// 筛选
const searchFilter = (prop, value) => {
data.filterValue[prop] = value;
emit('searchFilter', data.filterValue)
}
// 重置
const cancelFilter = (prop) => {
data.filterValue[prop] = '';
emit('searchFilter', data.filterValue)
}
// 行点击事件
const rowClick = (row) => {
emit('rowClick', row, props.tableData.indexOf(row))
}
const selectWriteUser = (id, fillObj) => {
toggleSelection()
emit('selectWriteUser', id, fillObj)
}
const isShow = computed(() => {
if (props.buttons <= 0 && !props.selectUser) {
return false;
}
return true;
})
const indexMethod=(index) => {
return (props.currentPage-1) * props.pageSize + index + 1;
}
const isShowTooltip = ref(false);
// 判断是否显示 溢出的文本 el-tooltip
const visibilityChange = (event) => {
const ev = event.target;
// 获取当前内容是否需要显示tooTip,鼠标移入显示所有内容,((获取当前内容数据字数*字体大小)/两行)+两边边距
const evWeight = ((ev.innerText.length*14)/2)+4;
const contentWeight = ev.clientWidth;
if (evWeight > contentWeight) {
// 实际宽度 > 可视宽度 文字溢出
isShowTooltip.value = true;
} else {
// 否则为不溢出
isShowTooltip.value = false;
}
};
defineExpose({toggleSelection});
</script>
<style scoped>
.css-users {
width: 75%;
height: 50px;
border: 1px solid rgb(210 210 210);
border-radius: 4px;
display: flex;
align-items: center;
}
.css-users span::after {
display: inline-block;
content: '、';
margin-left: 5px;
}
.css-users span:last-child::after {
display: none;
}
.jw-title {
position: relative;
text-align: center;
padding: 10px;
font-weight: 600;
font-size: 1.1rem;
background-color: #e3effb;
border-top: 1px solid #000000;
border-left: 1px solid #000000;
border-right: 1px solid #000000;
}
.jw-tables >>> .el-table .el-table__cell {
border-left: 1px solid #000000 !important;
}
.jw-tables >>> .el-table__header .el-table__cell[rowspan="1"],
.jw-tables >>> .el-table__header .el-table__cell[rowspan="2"] {
/* border-bottom: 0 !important; */
}
.jw-tables >>> .el-table__header .el-table__cell[rowspan="1"],
.jw-tables >>> .el-table__header .el-table__cell[rowspan="2"] {
/* border-left: 0 !important; */
}
.jw-tables >>> .el-table thead th,
.jw-tables >>> .el-table__header tr:last-child .el-table__cell,
.jw-tables >>> .el-table__header td.el-table__cell {
border-bottom: 1px solid #000000 !important;
}
.jw-tables >>> .el-table__header th.el-table__cell {
background-color: #5299da;
color: #fff;
}
.jw-tables >>> .el-table__header tr:first-child th.el-table__cell {
border-top: 1px solid #000000;
}
.jw-tables >>> .el-table thead {
color: #333333;
}
/* .jw-tables >>> .is-center.el-table-fixed-column--left.is-last-column.is-leaf.el-table__cell,
.jw-tables >>> .is-center.el-table-fixed-column--left.is-last-column.el-table__cell {
border-right: 1px solid #000000 !important;
} */
.jw-tables >>> .el-table td:not(.el-table-fixed-column--right).el-table__cell>div {
margin-top: 2px;
margin-bottom: 2px;
min-height: 23px;
}
.jw-tables >>> .el-table .cell,
.jw-tables >>> .el-table thead th div.cell {
padding: 2px 4px;
white-space: pre-line;
}
.jw-tables >>> .el-table__body tr:hover td.el-table__cell div {
color: var(--fontColor) !important;
}
.multi-table :deep td {
height: 45px;
}
:deep .bold-row {
font-weight: bold;
}
.jw-tables >>> .el-table thead tr:first-child th:first-child {
border-left: 1px solid #000000 !important;
}
.jw-tables >>> .el-table thead tr:not(:first-child) th:last-child {
border-right: 0px !important;
}
.jw-tables >>> .el-table tr td:last-child {
border-right: 1px solid #000000 !important;
}
.jw-tables >>> .el-table tr td {
border-bottom: 1px solid #000000;
}
.jw-tables >>> .el-table tbody tr td:first-child {
border-left: 1px solid #000000 !important;
}
.jw-tables >>> .el-table .el-table__cell {
padding: 0;
}
.jw-tables >>> .el-table thead th:last-child {
border-right: 1px solid #000000 !important;
}
:deep(.el-popover) {
width: fit-content !important;
}
:deep(.el-popover.el-popper) {
width: fit-content !important;
}
:deep .el-link.is-hover-underline:hover:after {
border-bottom: 0;
}
.jw-tables >>> .el-table__row:nth-child(odd) > td {
background-color: #e3effb !important;
}
.jw-tables >>> .el-table__row:nth-child(even) > td {
background-color: #fff !important;
}
.jw-tables:hover >>> .el-scrollbar__thumb {
background-color: #94c2f0 !important;
}
.no-pointer {
cursor: default;
}
.table-title-btns {
position: absolute;
right: -8px;
top: 3px;
z-index: 2;
transform: scale(0.75);
}
>>> .el-radio-button .el-radio-button__inner {
border: 1px solid #409eff;
color: #409eff;
}
>>> .el-radio-button:first-child .el-radio-button__inner {
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
>>> .el-radio-button:last-child .el-radio-button__inner {
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
>>> .el-radio-button.is-active .el-radio-button__inner {
color: #fff;
}
>>> .el-select__input::placeholder,
>>> .el-select__placeholder.is-transparent,
>>> .el-input.is-disabled .el-input__inner::placeholder,
>>> .el-input__inner::placeholder {
color: #a8abb2 !important;
-webkit-text-fill-color: #a8abb2 !important;
}
</style>