Avue表单个别字段实现全选的思路
目录
- 前言
- 正文
前言
爬虫神器,无代码爬取,就来:bright.cn
Java基本知识:
- java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
- 【Java项目】实战CRUD的功能整理(持续更新)
本文主要通过实战中 记录日常笔记
由于本架构是Avue下的,对应有些插件不支持更加灵活
比如tree格式 以及 seleect格式
后续通过官网发现checkBox格式支持:Form属性文档
正文
需求如下:全选对应的数据,反之联动另外一个字段
全集(后台设备字典) - 工作设备 = 停用设备
整体表单样式如下:
{label: "xxxxx",prop: "stopGantryCrane",multiple: true, // ✅ 多选关键配置width:"250px",span: 24, // 表单中占一半宽度(24 栅格的一半)dicUrl: `${baseUrl}/info/queryByManyEqNoTeandId?eqNos=YC&tenantId=${website.tenantId}`,type: "tree",display: false, // 不在表单中显示search: false,searchSpan: 4,props: {label: 'equipmentNo',value: 'equipmentNo'}
},
-
指定某些设备为“工作中”(workXXX)
-
自动显示剩余设备为“停用中”(stopXXX)
🚀 全选联动与差集逻辑分离步骤
1️⃣ 加载全集:设备类型 → 对应设备编号全集
loadEquipmentOptions() {const eqMap = {A: 'workQuayCrane',B: 'workPortalCrane',C: 'workGantryCrane',D: 'workRailCrane'};// axios请求批量加载字典
}
2️⃣ 自动计算“停用设备”:全集 - 工作设备
getStopCraneFromWorkCrane(row) {const craneFields = [{ work: 'workGantryCrane', stop: 'stopGantryCrane', prefix: 'A' },...];craneFields.forEach(({ work, stop, prefix }) => {const allOptions = this.equipmentOptions[prefix] || [];const selected = (typeof row[work] === 'string' ? row[work].split(',') : row[work] || []).map(s => s.trim()).filter(Boolean);const uniqueWork = [...new Set(selected)];const stopList = allOptions.filter(eq => !uniqueWork.includes(eq));// 👇更新表单字段row[work] = uniqueWork.join(',');row[stop] = stopList.join(',');});
}
3️⃣ 排序和标准化,确保 work/stop 字段干净且有序
normalizeCraneFields(row) {// 数组转字符串 + 排序
}
总体代码如下:
// 全集减去work集合,但本身work和stop是相对的情况,否则更新的时候字段显示不及时
getStopCraneFromWorkCrane(row) {const craneFields = [{ work: 'workQuayCrane', stop: 'stopQuayCrane', prefix: 'A' },{ work: 'workPortalCrane', stop: 'stopPortalCrane', prefix: 'b' },{ work: 'workGantryCrane', stop: 'stopGantryCrane', prefix: 'c' },{ work: 'workRailCrane', stop: 'stopRailCrane', prefix: 'd' }];const getNumber = str => {const match = str.match(/\d+/);return match ? parseInt(match[0], 10) : 0;};craneFields.forEach(({ work, stop, prefix }) => {const allOptions = this.equipmentOptions[prefix] || [];// 标准化 work 字段const selected = (typeof row[work] === 'string' ? row[work].split(',') : row[work] || []).map(s => s.trim()).filter(Boolean);const uniqueWork = [...new Set(selected)].sort((a, b) => getNumber(a) - getNumber(b));const stopList = allOptions.filter(eq => !uniqueWork.includes(eq)).sort((a, b) => getNumber(a) - getNumber(b));row[work] = uniqueWork.join(',');row[stop] = stopList.join(',');});
},
// 排序
normalizeCraneFields(row) {// 1. 保证数组转换为字符串,本身 update的时候可能会以 | 进行分割,所以保证用逗号分割const craneFields = ['workQuayCrane','workPortalCrane','workGantryCrane','workRailCrane','stopQuayCrane','stopPortalCrane','stopGantryCrane','stopRailCrane'];// 数组转字符串craneFields.forEach(k => {if (Array.isArray(row[k])) {row[k] = row[k].join(',');}});// 2. 再次进行排序const fieldPrefixMap = {workQuayCrane: 'a',stopQuayCrane: 'A',workPortalCrane: 'B',stopPortalCrane: 'B',workGantryCrane: 'C',stopGantryCrane: 'C',workRailCrane: 'D',stopRailCrane: 'D'};const getNumber = str => {const match = str.match(/\d+/);return match ? parseInt(match[0], 10) : 0;};// 排序Object.keys(fieldPrefixMap).forEach(k => {if (typeof row[k] === 'string' && row[k].trim() !== '') {row[k] = row[k].split(',').map(s => s.trim()).sort((a, b) => {const numA = getNumber(a);const numB = getNumber(b);return numA - numB;}).join(',');}});
},// *****------- 以下是 新增以及更新
rowSave(row, done, loading) {this.getStopCraneFromWorkCrane(row);this.normalizeCraneFields(row); // 👈 添加这行,排序add(row).then(() => {this.onLoad(this.page);this.$message({type: "success",message: "操作成功!"});done();}, error => {loading();window.console.log(error);});
},rowUpdate(row, index, done, loading) {this.getStopCraneFromWorkCrane(row);this.normalizeCraneFields(row); // 👈 添加这行update(row).then(() => {this.onLoad(this.page);this.$message({type: "success",message: "操作成功!"});done();}, error => {loading();console.log(error);});
},