vue3:Table组件动态的字段(列)权限、显示隐藏和左侧固定

article/2025/6/7 0:45:01

 效果展示

根据后端接口返回,当前登录用户详情中的页面中el-table组件的显示隐藏等功能。根据菜单id查询该菜单下能后显示的列。

后端返回的数据类型:

接收到后端返回的数据后处理数据结构. Table组件文件

<!-- 自己封装的Table组件文件 -->
onMounted(()=>{
//判断页面传递过来的数据对象:PropTableS中keySrequest是否为true;为true则请求后端的table列数据,否则使用自己定义的。(因为还没有定义所有页面的 列字段权限。所有得区分开来,不然其他页面在后端中不存在数据,table显示都会是空的)if(props.PropTableS.keySrequest){tablekey()}
})onActivated(() => {
//如果不是第一次进入这个页面,可以直接拿之前第一次进入保存的数据.if(props.PropTableS.keySrequest &&  proxy.$router.currentRoute.value.meta.key){TabKys = proxy.$router.currentRoute.value.meta.key}
})//请求后端数据,处理数据格式
function tablekey(){proxy.$axios.get('/system/user/list_fields', {permission_id:proxy.$router.currentRoute.value.meta.id}).then((res) => {let keycopy = JSON.parse(JSON.stringify(TabKys))let list = {}res.data.map(item=>{list[item.code] = {title :item.name, //列名left_fixed:item.left_fixed == 1 ? true : false, //是否固定fixed:item.left_fixed == 1 ? 'left' : false, //默认固定左侧id:item.id, //字段idsort:item.sort, //排序status:item.status == 1 ? true : false, //显示/隐藏isshow:item.isshow, //也是显示/隐藏,这个可以在自定义的数据中传递过来,因为之前的页面都是用的isshow,后端用的是status,前面页面太多不想改了。width:keycopy[item.code].width, //自定义传递过来的列宽度type:keycopy[item.code].type, //自定义传递过来的列类型,如('text','selelct','input'等等)permission_id:proxy.$router.currentRoute.value.meta.id//提交给后端的菜单id。}})//TabKys :渲染el-table组件的列对象数据  list:处理后端数据.TabKys = list//此处理是将进入页面请求后的数据保存,可以避免切换页面,丢失当前页面的table列。出现问题的场景(进入页面A,table组件列正常显示,切换到页面B后,在回到页面A。页面A没有列的名称了。因为路由设置页页面记住缓存。)proxy.$router.options.routes[1].children.forEach(route=>{route.meta.id == proxy.$router.currentRoute.value.meta.id ?  route.meta.key == undefined ?  route.meta.key = TabKys : '' : ''})tablekeyindex.value++});
}

页面中定义的数据:

页面中定义的table数据let PropTableS = reactive({ tableStyle: { //table的csswidth: "99%",margin: "auto",},keySrequest:true, //是否需要后端数据渲染//自己定义的列的数据 keyS: proxy.$PublicAPI.SetTableCotentWidth({ //这不是一个完整列对象数据,因为其他值都在后端返回了。这里的意义就是可以自定义列的类型。后端中没有定义当前列类型字段,也可以不需要后端保存,可以自定义,danjuleixing: {type:'select' //类型:下拉widht:'120px' //定义的宽度 },status: {type:'select'},}),
});

Table组件中右侧定义设置的组件(小齿轮)

<template><div class="Drawer"><el-drawerz-index="12":modal="false":before-close="beforeClose"append-to="el-main"class="drawerBox"v-model="Props.DrawerObject.visible":close-on-click-modal="false":destroy-on-close="true":show-close="false"><template #header="{ close, titleId, titleClass }"><div class="deawerTitle"><span>表单固定设置</span><span><Icons @click="close" :theme="'outline'" :size="20" :is="'close'"/></span></div></template><div class="deawerScanner"><el-inputv-model="input2"@input="handelInput"class="deawerScanner_input"size="small"placeholder="搜索关键词":prefix-icon="Search"/></div><div><el-tabsv-model="TabactiveName"class="demo-tabs"@tab-click="handleTableActiveClick"><el-tab-pane label="固定列" name="0"></el-tab-pane><el-tab-pane label="隐藏/显示" name="1"></el-tab-pane></el-tabs></div><div class="deawerTop" :style="{ height: TopHeght + 'px' }"><div class="deawerTop_All"><el-checkbox@click="handelCheack"v-model="checked4"label="全部固定"/></div><div><FromDataref="From":key="formkey"@Drawer_switchChange="Drawer_switchChange"class="FromDataDom":fromlist="fromlist"style="":style="{ 'margin-top': '0px', height: domHeight + 'px' }"></FromData></div><div class="botton_but"><Buttonplain:title="'取消'"@click="ButtonClick('')":pattern="'centre'"/><Button:plain="fromlist.scannerIsPlain":type="'primary'":title="'保存'"@click="ButtonClick('save')":pattern="'centre'"/></div></div></el-drawer></div>
</template><script lang="ts" setup>
import {ref,reactive,onMounted,defineProps,watch,onActivated,getCurrentInstance,onBeforeUnmount,onUnmounted,
} from "vue";
import { Search } from "@element-plus/icons-vue";
import { FromData, Drawer, Icons, Button } from "@/components";
let Props = defineProps(["DrawerObject", "primarytablelist"]);
import { ElMessage, ElMessageBox } from "element-plus";
const primarytablelist = Props.primarytablelist;
const { proxy } = getCurrentInstance();
const From = ref(null);
let fromlist = reactive({});
let input2 = ref("");
let checked4 = ref(false);
let isEmit = ref(true);
let formkey = ref(0);
let TabactiveName = ref("0");
let domHeight = ref(0);
let TopHeght = ref(0);
onMounted(() => {GelTableTitleUpdate(Props.DrawerObject.TabKys);window.addEventListener("resize", resizeFun);setTimeout(() => {resizeFun();}, 1);});onUnmounted(() => {proxy.$bus.emit("addEvent", false);
});function resizeFun() {domHeight.value =document.querySelector(".drawerBox").offsetHeight - 41 - 39 - 54 - 84 - 50;TopHeght.value =document.querySelector(".drawerBox").offsetHeight - 41 - 39 - 64;
}function GelTableTitleUpdate(obj: object) {let index = 0;let objlength = 0;for (const key in obj) {if (key != "operate" && key != "selection" && key != "index") {objlength++;obj[key].type = "switch";obj[key].icon = "drag";if (obj[key].fixed) {index++;obj[key].value = true;} else if (obj[key].value == "" || obj[key].value == false) {delete obj[key].value;}} else if (key == "operate" || key == "selection" || key == "index") {delete obj[key];}}fromlist = {index: "2",labelwidth: 130,formInline: false,isInput: true,position: "left",component: "rigthoptins",listData: obj,newListData: JSON.parse(JSON.stringify(obj)),};handleTableActiveClick({props:{name:'0'}})proxy.$bus.emit("addEvent", true);index == objlength ? (checked4.value = true) : "";
}function ButtonClick(type: string) {let keys = Object.keys(fromlist.listData)let list = {permission_id:fromlist.listData[keys[0]].permission_id,details:[]}if (type === "save") {for (const key in fromlist.listData) {let aa ={'field_id':fromlist.listData[key].id,'status':fromlist.listData[key].status,'left_fixed':fromlist.listData[key].left_fixed}list.details.push(aa)}proxy.$axios.post('/system/user/list_set_fields', list).then((res) => {if(res.code == 200){ElMessage.success(res.message)proxy.$bus.emit('UpdataTablerowKeys')}else if(res.code == 500){ElMessage.error(res.message)}})}
}function beforeClose() {Props.DrawerObject.visible = false;proxy.$bus.emit("addEvent", false);
}proxy.$bus.on("UpdataRouterPath", (val: boolean) => {Props.DrawerObject.visible = val;
});function Drawer_switchChange(key:string,TableList:any
) {fromlist.listData[key][TabactiveName.value == '0' ? 'left_fixed'  : 'status'] = TableList[key]Object.keys(TableList).length  == Object.keys(fromlist.listData).length  && Object.values(TableList).every(Boolean) ? checked4.value = true : checked4.value = false
}function handelCheack() {let bol = !checked4.valueFrom.value.getUpdataRigthOptions(bol);for (const key in fromlist.listData) {fromlist.listData[key][TabactiveName.value == '0' ? 'left_fixed'  : 'status'] = From.value.TableList[key]}}let inputval = ref("");
function handelInput(value: string) {inputval.value = value;setTimeout(() => {aa(value);}, 1000);
}function aa(val: string) {if (inputval.value == val) {let list = JSON.parse(JSON.stringify(fromlist.newListData));for (const key in list) {if (val == "") {fromlist.listData = JSON.parse(JSON.stringify(fromlist.newListData));}if (list[key].title.indexOf(val) == -1) {delete list[key];}}fromlist.listData = list;formkey.value++;}
}function handleTableActiveClick(value: any) {TabactiveName.value = value.props.name;for (const key in fromlist.listData) {fromlist.listData[key].value = fromlist.listData[key][TabactiveName.value == '0' ? 'left_fixed'  : 'status'] }checked4.value = Object.keys(fromlist.listData).every(item => fromlist.listData[item].value == true)formkey.value++;
}
</script><style lang="less" scoped>
::v-deep el-drawer {background: saddlebrown !important;
}
::v-deep .el-icon {height: none;
}::v-deep .drawerBox {.el-drawer__header {padding: 0px !important;margin-bottom: 0px !important;}.el-drawer__body {padding: 0px !important;}.el-input__wrapper {box-shadow: none !important;}.deawerScanner {border: none;width: 100%;padding: 0 9px;border-bottom: 1px solid #e8eaf2;height: 40px;.input__wrapper {box-shadow: none !important;border: none !important;}.deawerScanner_input {height: 39px !important;border: none !important;}}.elForm {max-height: none !important;}.FromDataDom {overflow: hidden;overflow-y: auto;scrollbar-width: thin; /* 设置滚动条为细条 */// scrollbar-color: #888 #f1f1f1; /* 设置滚动条和轨道的颜色 */}.deawerTop {width: 100%;height: 87%;padding: 0px 0px 0 12px;.deawerTop_All {height: 40px;display: flex;align-items: center;}}width: 244px !important;.deawerTitle {padding: 0px 15px !important;color: #5b6070 !important;font-size: 14px !important;width: 214px;height: 40px;display: flex;justify-content: space-between;align-items: center;border-bottom: 1px solid #e8eaf2;}.botton_but {width: 83%;height: 84px;display: flex;justify-items: center;align-items: center;margin-left: 8%;.ButBox {display: contents;background: salmon;}}.bottonMax_but {position: fixed;bottom: 0;}
}::v-deep.elForm {padding: 0px !important;
}
::v-deep .el-drawer {height: 89%;top: 11% !important;bottom: 0 !important;
}// ::v-deep .drawerBox {
//   position: absolute !important;
//   top: 100 !important;
//   right: 0 !important;
//   bottom: 0 !important;
//   z-index: 12;
// }::v-deep .drawerDiv {inset: 100% !important;position: absolute !important;top: 0 !important;right: 0 !important;bottom: 0 !important;
}
::v-deep .el-switch.is-checked .el-switch__core {background: var(--Click_Nav_FontColor) !important;
}
::v-deep .el-button--primary {background: var(--Click_Nav_FontColor) !important;
}::v-deep .el-form-item__label {display: block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;
}::v-deep .el-tabs__nav-wrap::after {height: 1px;
}::v-deep .el-tabs__nav {width: 100%;display: flex;justify-content: center;
}::v-deep .switchClass {display: flex;i {display: block;height: 32px;display: flex;justify-content: center;}
}
::v-deep .el-tabs__item:hover,
::v-deep .el-checkbox__input.is-checked + .el-checkbox__label {color: var(--Click_Nav_FontColor) !important;
}
::v-deep .el-tabs__item.is-active {color: var(--Click_Nav_FontColor) !important;
}
::cv-deep .el-tabs__active-bar {background-color: var(--Click_Nav_FontColor) !important;
}
</style>

table组件

<template><div class="TableBox" id="TableBox"><div class="DateilsTitle" v-if="props.PropTableS.title">{{ props.PropTableS.title }}</div><div v-if="props.PropTableS.headerRemarks" class="headerRemarks">{{ props.PropTableS.headerRemarks }}</div><el-tablev-if="TabKys"class="singleTableRef"ref="singleTableRef":data="getTables()":key="tablekeyindex"><template v-for="(child, key, index) in TabKys"><!-- 存在显示隐藏标识的字段 控制显示列  evalRowShow--><el-table-columnv-if="props.PropTableS.keySrequest ? evalRowShow(child.status||child.isshow) : true"></el-table-column></template><!-- 小齿轮在右侧显示 --><template v-if="PropTableS.tables" class="aaaaaa"><el-table-column fixed="right" width="20px"><template #header><Icons@click="handelRightIcon(TabKys)":theme="'outline'":size="36":is="'config'"/></template></el-table-column></template></el-table><!-- 小齿轮组件 --><Drawerv-if="DrawerObject.visible":DrawerObject="DrawerObject":primarytablelist="TabKys"></Drawer></div>
</template><script setup lang="ts">onMounted(() => {//判断是否包含keySrequest ,否则去自定义传递过来的table数据对象if(props.PropTableS.keySrequest){tablekey()}
});onActivated(() => {//看看列信息是否在路由中有存起来,有值就是代表不是第一次进入该页面if(props.PropTableS.keySrequest &&  proxy.$router.currentRoute.value.meta.key){TabKys = proxy.$router.currentRoute.value.meta.key}
});//点击右侧设置按钮
function handelRightIcon(params: object) {DrawerObject.visible = true;DrawerObject.TabKys = JSON.parse(JSON.stringify(TabKys));
}
function evalRowShow(params:any){return eval(params);
}proxy.$bus.on('UpdataTablerowKeys',()=>{tablekey()})
function tablekey(){proxy.$axios.get('/system/user/list_fields', {permission_id:proxy.$router.currentRoute.value.meta.id}).then((res) => {let keycopy = JSON.parse(JSON.stringify(TabKys))let list = {}res.data.map(item=>{list[item.code] = {title :item.name,left_fixed:item.left_fixed == 1 ? true : false,fixed:item.left_fixed == 1 ? 'left' : false,id:item.id,sort:item.sort,status:item.status == 1 ? true : false,isshow:item.isshow,width:keycopy[item.code].width,type:keycopy[item.code].type,permission_id:proxy.$router.currentRoute.value.meta.id}})TabKys = list//进入页面将列值数据保存proxy.$router.options.routes[1].children.forEach(route=>{route.meta.id == proxy.$router.currentRoute.value.meta.id ?  route.meta.key == undefined ?  route.meta.key = TabKys : '' : ''})tablekeyindex.value++});
}


http://www.hkcw.cn/article/OHyZBubaqd.shtml

相关文章

力扣HOT100之多维动态规划:1143. 最长公共子序列

这道题之前刷代码随想录的时候做过&#xff0c;但是现在又给忘干净了&#xff0c;这道题需要用二维dp数组来做&#xff0c;看了一下自己当时写的博客&#xff0c;一下子就看懂了。这道题的子序列可以不连续&#xff0c;所以dp数组的定义和最长重复子数组不一样&#xff0c;我总…

无锁队列—C++内存序最佳实践

叙述方式&#xff1a; 1.背景介绍 &#xff08;使用场景&#xff09; 2.讲结论 (无锁队列实现) 3.讲内存序的使用&#xff08;通用方式&#xff09; 一、背景 本文通过一个“单生产者-单消费者”模型的场景&#xff0c;讲解基于C原子操作和内存序实现的无锁队列 在生产者…

ADC模数转换控制

目录 1. Convst信号的功能本质 1.1 核心作用 1.2 关键优势 1.3 Convst与SPI接口的协作关系 2.实际设计要点 2.1 硬件连接方案 2.2 时序约束&#xff08;以AD7685为例&#xff09; 2.3 多片ADC同步策略 3.高级应用技巧 3.1 动态调整采样率 3.2 抗干扰设计 3.3 故障排查 4.总…

QT常用控件(1)

控件是构成QT的基础元素&#xff0c;例如Qwidget也是一个控件&#xff0c;提供了一个‘空’的矩形&#xff0c;我们可以往里面添加内容和处理用户输入&#xff0c;例如&#xff1a;按钮&#xff08;QpushButton&#xff09;&#xff0c;基础显示控件&#xff08;Lable&#xff…

Linux系统-基本指令(5)

文章目录 mv 指令cat 指令&#xff08;查看小文件&#xff09;知识点&#xff08;简单阐述日志&#xff09;more 和 less 指令&#xff08;查看大文件&#xff09;head 和 tail 指令&#xff08;跟查看文件有关&#xff09;知识点&#xff08;管道&#xff09;时间相关的指令&a…

C 语言学习笔记(预处理和库文件)

内容提要 预处理库文件 预处理 预处理编译汇编链接 什么是预处理 预处理就是在源文件&#xff08;.c文件&#xff09;编译之前&#xff0c;所进行的一部分预备操作&#xff0c;这部分操作是由预处理器&#xff08;预处理程序&#xff09;自动完成。当源文件在编译时&#x…

谷歌地图高清卫星地图软件(Google Earth)v6.0.3.2197 中文版 - 前端工具导航

谷歌地图6.0Google Earth是一款谷歌地图高清卫星地图软件&#xff0c;能够实时监测并提供最准确的地图信息&#xff0c;地球上的任意一块地区都能够准确定位并放大查看&#xff0c;覆盖范围广&#xff0c;精度高&#xff0c;非常实用&#xff01; 谷歌卫星高清地图 下载链接&a…

全球治理指标数据(1996-2023)

1945 全球治理指标&#xff08;WGI&#xff09;(1996-2023&#xff09; 数据简介 全球治理指标&#xff08;WGI&#xff09;是一个由世界银行开发的综合性数据库&#xff0c;通过政治稳定、政府效能、监管质量、法治水平、腐败控制和公民话语权六个维度系统衡量全球各国的治理…

Blocked aria-hidden on an element because its descendant retained focus.

问题出在 Element UI 的 el-table 组件 全选功能上&#xff0c;这是一个常见的无障碍&#xff08;a11y&#xff09;问题。这个错误提示与网页 accessibility&#xff08;无障碍访问&#xff09;相关&#xff0c;涉及 aria-hidden 属性的不当使用。 问题原因分析 1. Element U…

2025 年人脸识别技术应用备案政策已落地

在 AI 技术深度渗透的当下&#xff0c;人脸识别作为重要的生物识别技术&#xff0c;已广泛应用于安防、金融、零售等多领域。但随之而来的个人信息安全风险也备受关注。2025 年 6 月 1 日起《人脸识别技术应用安全管理办法》正式实施&#xff0c;企业需重视人脸识别技术应用备案…

01电气设计-380V强电部分设计

目标&#xff1a;在电气设计过程中380V的强电部分&#xff0c;一般来自与工厂&#xff0c;一般为3相5线制的380V&#xff0c;下面的应用场景是当我的用电设备&#xff08;电机&#xff0c;冷水机&#xff0c;控制器&#xff0c;驱动器&#xff0c;激光器等等&#xff09;总功率…

文件批量重命名

mv只支持单个文件命名 批量重命名用rename 例子&#xff1a; #touch命令批量创建空文件&#xff0c;文件10-15 touch file{10..15}.txt批量重命名 # 批量重命名&#xff0c;file10-15重命名为test10-15 #这里file1? 匹配的是单个字符。比如10,11等 rename file1 test1 file1…

ES的开始

ES作用 在海量数据中&#xff0c;执行搜索功能&#xff0c;使用mysql&#xff0c;效率过低&#xff0c; 如果关键字输入不准确&#xff0c;一样可以搜索到想要的数据 讲搜索关键字&#xff0c;以红色字体展示 ES介绍 ES是基于java语言并且基于Lucene编写的搜索引擎框架&#x…

【论文解读】ReAct:从思考脱离行动, 到行动反馈思考

认识从实践开始&#xff0c;经过实践得到了理论的认识&#xff0c;还须再回到实践去。 ——《实践论》,毛泽东 1st author: About – Shunyu Yao – 姚顺雨 paper [2210.03629] ReAct: Synergizing Reasoning and Acting in Language ModelsReAct: Synergizing Reasoning and…

AXURE-动态面板

1.概述 动态面板原件&#xff0c;容器类的原件一个动态面板可以有多种状态 同一时刻只展示一个状态 默认展示第一个状态 主要用于多个状态的切换可拖动 1.1 创建 将原件库中的“动态面板”原件&#xff0c;直接拖动到工作区中&#xff0c;创建空白动态面板将页面中原件选中…

AI地面垃圾检测算法智能分析网关V4打造城市/公园/校园等场景环保卫生监管解决方案

一、方案背景​ 在城市管理与场所运营中&#xff0c;地面垃圾的及时清理是环境品质的重要指标。传统人工巡检效率低、成本高&#xff0c;存在明显滞后性&#xff0c;难以满足现代环境管理需求。随着人工智能与计算机视觉技术发展&#xff0c;智能化管理成为趋势。AI智能分析网…

帝国CMS QQ登录插件最新版 获取QQ头像和QQ昵称

帝国CMS QQ登录插件最新版 获取QQ头像和QQ昵称 QQ一键登录&#xff0c;免邮箱 随机密码 获取QQ头像 获取QQ昵称 直接下载上传到帝国CMS&#xff1a;/e/memberconnect UTF-8版本 GBK的自己转换 QQ登录后的默认密码 是随机的邮箱账号前面的随机6个字母和数字 【下图字母数…

Kafka 的优势是什么?

Kafka 作为分布式流处理平台的核心组件&#xff0c;其设计哲学围绕高吞吐、低延迟、高可扩展性展开&#xff0c;在实时数据管道和大数据生态中具有不可替代的地位。 一、超高吞吐量与低延迟 1. 磁盘顺序 I/O 优化 突破磁盘瓶颈&#xff1a;Kafka 将消息持久化到磁盘&#xff…

低谷才是出成绩

有些朋友说我现在是高光&#xff0c;其实不然 之所以有这样的误解&#xff0c;是我个人的简历上是不断增加名誉。这点属实&#xff0c;看看我的词条&#xff1a;https://www.modb.pro/wiki/4245的确如此。但是其实也有误会。事情可以反过来看。因为&#xff0c;如果做技术的在…

Bash shell四则运算

文章目录 四则运算1. ‌expr 命令‌2. ‌$(( )) 表达式&#xff08;推荐&#xff09;‌3. ‌$[ ] 表达式&#xff08;已弃用&#xff09;‌4. ‌let 命令‌小数运算i 和 i 区别 四则运算 算术运算&#xff1a; - * / %&#xff08;取模&#xff0c;求余数&#xff09; Bash sh…