前言
爬虫神器,无代码爬取,就来:bright.cn
Java基本知识:
本文主要通过实战中 记录日常笔记
由于本架构是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);
});
},