vue.js
复制代码
<template>
<div class="top-right-btn" :style="style">
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
<el-button circle icon="Search" @click="toggleSearch()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button circle icon="Refresh" @click="refresh()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns">
<el-button circle icon="Menu" @click="showColumn()" v-if="showColumnsType == 'transfer'"/>
<el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px" v-if="showColumnsType == 'checkbox'">
<el-button circle icon="Menu" />
<template #dropdown>
<el-dropdown-menu>
<!-- 全选/反选 按钮 -->
<el-dropdown-item>
<el-checkbox :indeterminate="isIndeterminate" v-model="isChecked" @change="toggleCheckAll"> 列展示 </el-checkbox>
</el-dropdown-item>
<div class="check-line"></div>
<template v-for="item in columns" :key="item.key">
<el-dropdown-item>
<el-checkbox v-model="item.visible" @change="checkboxChange($event, item.prop)" :label="item.label" />
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-tooltip>
</el-row>
<el-dialog :title="title" v-model="open" append-to-body>
<el-transfer
:titles="['显示', '隐藏']"
v-model="value"
:data="columns"
@change="dataChange"
></el-transfer>
</el-dialog>
</div>
</template>
<script setup>
const props = defineProps({
/* 是否显示检索条件 */
showSearch: {
type: Boolean,
default: true
},
/* 显隐列信息 */
columns: {
type: Array
},
/* 是否显示检索图标 */
search: {
type: Boolean,
default: true
},
/* 显隐列类型(transfer穿梭框、checkbox复选框) */
showColumnsType: {
type: String,
default: "checkbox"
},
/* 右外边距 */
gutter: {
type: Number,
default: 10
},
})
const emits = defineEmits(['update:showSearch', 'queryTable','updateStorage'])
// 显隐数据
const value = ref([])
// 弹出层标题
const title = ref("显示/隐藏")
// 是否显示弹出层
const open = ref(false)
const style = computed(() => {
const ret = {}
if (props.gutter) {
ret.marginRight = `${props.gutter / 2}px`
}
return ret
})
// 是否全选/半选 状态
const isChecked = computed({
get: () => props.columns.every(col => col.visible),
set: () => {}
})
const isIndeterminate = computed(() => props.columns.some((col) => col.visible) && !isChecked.value)
// 搜索
function toggleSearch() {
emits("update:showSearch", !props.showSearch)
}
// 刷新
function refresh() {
emits("queryTable")
}
// 右侧列表元素变化
function dataChange(data) {
for (let item in props.columns) {
const key = props.columns[item].key
props.columns[item].visible = !data.includes(key)
}
}
// 打开显隐列dialog
function showColumn() {
open.value = true
}
if (props.showColumnsType == 'transfer') {
// 显隐列初始默认隐藏列
for (let item in props.columns) {
if (props.columns[item].visible === false) {
value.value.push(parseInt(item))
}
}
}
// 单勾选
function checkboxChange(event, prop) {
props.columns.filter(item => item.prop == prop)[0].visible = event
emits("updateStorage")
}
// 切换全选/反选
function toggleCheckAll() {
const newValue = !isChecked.value
props.columns.forEach((col) => (col.visible = newValue))
emits("updateStorage")
}
</script>
<style lang='scss' scoped>
:deep(.el-transfer__button) {
border-radius: 50%;
display: block;
margin-left: 0px;
}
:deep(.el-transfer__button:first-child) {
margin-bottom: 10px;
}
:deep(.el-dropdown-menu__item) {
line-height: 30px;
padding: 0 17px;
}
.check-line {
width: 90%;
height: 1px;
background-color: #ccc;
margin: 3px auto;
}
</style>
js
复制代码
// src/utils/storageByUI.js
import localforage from 'localforage'
// 强制使用 IndexedDB 作为存储驱动
localforage.config({
name: 'okFactura',
storeName: 'ui_data',
description: 'Local storage using IndexedDB',
driver: localforage.INDEXEDDB
})
/** 设置数据 */
const setItem = (key, value) => {
const raw = JSON.parse(JSON.stringify(value)); // 脱响应式
return localforage.setItem(key, raw);
}
/** 获取数据 */
const getItem = (key) => {
return localforage.getItem(key)
}
/** 删除数据 */
const removeItem = (key) => {
return localforage.removeItem(key)
}
/** 清空数据 */
const clear = () => {
return localforage.clear()
}
export default {
setItem,
getItem,
removeItem,
clear
}
js
复制代码
<template>
<div class="app-container">
<!-- 1 引用工具组件,常用组件注册到主进程main.js -->
<right-toolbar
v-model:showSearch="showSearch"
@queryTable="getList"
@updateStorage="updateStorageByColumns"
:columns="columns"
/>
... ...
<el-table class="table-container" v-loading="loading" :data="printConfigList" @selection-change="handleSelectionChange"
<!-- 2 border column-resizable 可调整列宽 -->
size="small" stripe border column-resizable
<!-- 3 header-dragend 更改列宽触发 -->
@header-dragend="handleColumnWidthChange"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="序号" type="index" align="center" width="50" />
<el-table-column label="模板类型" align="center" prop="templateType"
<!-- 4 获取持久化列宽 -->
:width="getColumnWidth(0)"
<!-- 5 获取持久化显隐状态 -->
v-if="columns[0]?.visible"
>
<template #default="scope">
<dict-tag :options="print_template_type" :value="scope.row.templateType"/>
</template>
</el-table-column>
... ...
</el-table>
... ...
</div>
</template>
<script setup name="PrintConfig">
... ...
// 引入封装的持久化
import storageByUI from "@/utils/storageByUI";
... ...
// ----------------------------------- 列宽设计 start -----------------------------------
const columns = ref([])
const columnsKey = "printConfigColumns"
// 6 prop-控制索引,visible-显隐状态,width-列宽
const initColumns = [
{ key: 0, label: `模板类型`, prop:'templateType', visible: true , width: 80 },
{ key: 1, label: `绑定的模板名称`, prop:'templateName', visible: true, width: 120 },
{ key: 2, label: `打印宽度`, prop:'templateWidth', visible: true , width: 80 },
{ key: 3, label: `打印高度`, prop:'templateHeight', visible: true , width: 80 },
{ key: 4, label: `更新时间`, prop:'updateTime', visible: true , width: 120 },
{ key: 5, label: `更新人`, prop:'updateBy', visible: true , width: 80 },
{ key: 6, label: `备注描述`, prop:'remark', visible: true , width: 120 }
]
/** 7 获取持久化列信息 */
function getColumns() {
storageByUI.getItem(columnsKey).then(storeColumns => {
if(storeColumns) {
columns.value = storeColumns;
} else {
columns.value = initColumns;
}
})
}
getColumns()
// 8 更新持久化列信息
function updateStorageByColumns(){
storageByUI.setItem(columnsKey, columns.value);
}
/** 9 修改列宽 */
function handleColumnWidthChange(newWidth, oldWidth, column, event){
console.log("修改列宽......",column,newWidth)
// 9.1 找到对应的列索引
const columnIndex = columns.value.findIndex(col => col.prop === column.property);
if (columnIndex !== -1) {
// 9.2 更新列宽
columns.value[columnIndex].width = newWidth;
// 9.3 存储更新后的列配置
updateStorageByColumns();
}
};
// 10 获取列宽方法
const getColumnWidth = (index) => {
if (columns.value[index] && columns.value[index].width) {
return columns.value[index].width;
}
return undefined; // 返回undefined让element-ui使用默认宽度
};
// ----------------------------------- 列宽设计 end -----------------------------------
... ...