npm i -S vuedraggable@next & yarn add vuedraggable@next
### components/tableHeades/index.vue
<template>
<div style="display: inline-block; margin-right: 10px">
<el-dropdown ref="dropdown" trigger="contextmenu">
<el-button icon="Setting" type="primary" plain @click="showClick">字段设置</el-button>
<template #dropdown>
<el-dropdown-menu>
<div class="flex-between" style="height: 30px">
<p>展示字段</p>
<el-button type="text" @click="defineFieldReset()">重置</el-button>
</div>
<el-dropdown-item style="height:300px;">
<el-scrollbar>
<Draggable class="t_table_column_setting_dropdown" v-model="state.columnSet" item-key="prop">
<template #item="{ element, index }">
<el-checkbox @mouseover.native="CheckBoxClick(index)"
:class="[{ ActiveDashed: index == state.activeIndex }]" :checked="!element.hidden"
v-model="element.AllSelect" @click.native.stop :disabled="element.checkBoxDisabled"
@change="checked => checkChanged(checked, index)">
{{ element.label }}
</el-checkbox>
</template>
</Draggable>
</el-scrollbar>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<script lang="ts">
export default {
name: 'tableheades'
}
</script>
<script setup lang="ts">
import Draggable from 'vuedraggable'
import { watch, onMounted, reactive, nextTick } from 'vue'
import { ref } from 'vue'
const dropdown = ref()
const props = defineProps({
columns: {
type: Array,//字段设置
default: () => []
},
tableId: {
type: String,//每个页面table标识
default: ''
}
})
const showClick = () => {
dropdown.value.handleOpen()
}
const hideClick = () => {
dropdown.value.handleClose()
}
//鼠标移动到每个复选框
const CheckBoxClick = (i) => {
state.activeIndex = i;
}
const state: any = reactive({
columnSet: [],//列
defaultColumn: [],//重置默认列
activeIndex: 0,
visible: false,
})
// 获取缓存数据
const getColumnSetCache = () => {
let value: any = localStorage.getItem(`columnSet-${props.tableId}`)
let columnOption = initColumnSet()
let valueArr = JSON.parse(value) || []
columnOption.map(item => {
let findEle = valueArr.find(ele => ele.label === item.label && ele.prop === item.prop)
item.hidden = findEle ? findEle.hidden : false
})
value = JSON.stringify(columnOption)
console.log(value)
return value ? JSON.parse(value) : initColumnSet()
}
// 初始化
const initColumnSet = () => {
const columnSet = props.columns.map((col: any, index) => ({
label: col.label,
prop: col.prop,
hidden: false,
checkBoxDisabled: false
}))
return columnSet
}
// 抛出事件
const emits = defineEmits(['columnSetting'])
onMounted(() => {
state.defaultColumn = props.columns
state.columnSet = getColumnSetCache()
emits('columnSetting', state.columnSet)
})
watch(() => state.columnSet, (val) => {
emits('columnSetting', val)
localStorage.setItem(`columnSet-${props.tableId}`, JSON.stringify(val))
},
{ deep: true }
)
// checkbox改变选中状态
const checkChanged = (checked, index) => {
state.columnSet[index].hidden = !checked
let obj: any = {}
state.columnSet.map(val => {
val.hidden in obj || (obj[val.hidden] = [])
obj[val.hidden].push(val.hidden)
})
if (obj.false.length < 2) {
state.columnSet.map((val, key) => {
if (!val.hidden) {
state.columnSet[key].checkBoxDisabled = true
}
})
} else {
state.columnSet.map((val, key) => {
if (!val.hidden) {
state.columnSet[key].checkBoxDisabled = false
}
})
}
}
// // 重置
const defineFieldReset = () => {
const columnSet = state.defaultColumn.map((col: any, index) => ({
label: col.label,
prop: col.prop,
hidden: false,
checkBoxDisabled: false,
AllSelect: true
}))
state.columnSet = columnSet
//保存到后端接口
// tableHeaderReset(props.tableId).then((res) => { });
}
</script>
<style lang="scss">
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px 0 15px;
}
.ActiveDashed {
width: 100%;
border: 1px dashed #ccc;
margin: 0 auto;
cursor: move;
}
.el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
.el-dropdown-menu {
padding: 10px;
font-size: 14px;
.el-dropdown-menu__item {
display: flex;
flex-direction: column;
align-items: flex-start;
.title {
font-weight: bold;
margin-bottom: 5px;
}
.t_table_column_setting_dropdown {
display: flex;
flex-direction: column;
.el-checkbox {
vertical-align: middle;
.el-checkbox__input.is-checked+.el-checkbox__label {
color: #409eff;
vertical-align: middle;
}
}
}
}
}
</style>
<style scoped>
/deep/ .el-dropdown-menu__item:not(.is-disabled):focus {
background-color: #fff;
}
</style>
//这个必须要写 不写的话页面刷新 存储在本地的数据会被刷新掉
<script lang="ts">
export default {
name: 'qualityInspectionTask'
}
</script>
<script setup lang='ts'>
import { qualityInspectionTask } from "/@/constants/quality";//column所用到的字段
import tableHeades from "/@/components/tableHeades/index.vue";//字段设置组件
// 所有列(表头数据)
// 初始化数据
let state = reactive({
columnSet: [],
})
const renderColumns = computed(() => {
return state.columnSet.length > 0
? state.columnSet.reduce((acc: any, cur: any) => {
if (!cur.hidden) {
let columnByProp: any = qualityInspectionTask.reduce((acc: any, cur: any) => {
acc[cur.prop] = cur
return acc
}, {})
acc.push(columnByProp[cur.prop])
}
return acc
}, [])
: qualityInspectionTask
})
</script>
<template>
<tableHeades v-bind="$attrs" :columns="renderColumns" tableId="qualityInspectionTask"
@columnSetting="v => (state.columnSet = v)" />
<el-table :height="height" :data="source.list" v-loading="source.loading" :cell-style="cellStyle"
:header-cell-style="headerCellStyle">
<el-table-column v-for="(item, index) in renderColumns" :key="index + 'i'" :label="item.label" :prop="item.prop"
:width="item.width" align="center" show-overflow-tooltip>
<template v-slot="{ row }">
<span v-if="item.code">
<el-button type="primary" link @click="onView(row)">{{
row.code
}}</el-button>
</span>
<span v-else-if="item.materialInfoList">
<span>{{ viewMaterialInfo(row.materialInfoList) }}</span>
</span>
<span v-else-if="item.status">
<span>{{ ['待执行','执行中','已完成'][row.status] }}</span>
</span>
<span v-else>{{row[item.prop] }}</span>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="100">
<template v-slot="{ row }">
<el-button type="danger" size="small" @click="onDelete(row)">删 除</el-button>
</template>
</el-table-column>
</el-table>
</template>
constants这个文件是跟components同级 主要用来放页面表头字段
export const qualityInspectionTask = [
{
label: "质检单号",
prop: "code",
code: true
},
{
label: "工单号",
prop: "orderNo"
},
{
label: "工作中心",
prop: "workCenterName",
width: "120"
},
{
label: "产品编码/名称",
prop: "materialInfoList",
materialInfoList: true
},
{
label: "任务状态",
prop: "status",
width: "120",
status: true
},
{
label: "检验时间",
prop: "inspectionTime",
width: "120"
},
{
label: "检验人",
prop: "inspectionUser",
width: "120"
},
{
label: "创建时间",
prop: "createTime",
width: "120"
}
];