需求:新增编辑时必学范围只能在已勾选可学范围内进行勾选。
![](https://img-blog.csdnimg.cn/direct/a5c7c20635064799aae5ba5a5de11722.png)
1.页面展示部分代码
<el-form-item label="课程可见范围" prop="visibleRangeList">
<el-cascader-panel
v-model="visibleRangeCode"
ref="visibleCascaderRef"
:options="visibleRangeOptions"
:props="props"
@change="changeVisibleRange"
/>
</el-form-item>
<el-space fill>
<el-alert type="warning" show-icon :closable="false">
<p>请先选择课程可见范围</p>
</el-alert>
<el-form-item label="课程必学范围" prop="mustLearnRangeList">
<el-cascader-panel
placeholder="请先选择课程可见范围"
v-model="mustLearnRangeCode"
ref="cascaderRef"
:options="mustLearnRangeOptionsAll"
:props="props"
@change="changeMustLearnRange"
/>
</el-cascader-panel>
</el-form-item>
</el-space>
2.数据结构(数据稍微改了下,会和图不对应)
[
{
"name": "旅行社",
"value": "test_lxs",
"children": []
},
{
"name": "景区",
"value": "test_jq",
"children": []
},
{
"name": "导游",
"value": "test_dy",
"children": []
},
{
"name": "司机",
"value": "test_sj",
"children": []
},
{
"name": "涉旅企业",
"value": "z_slqy",
"children": [
{
"name": "酒店",
"value": "test_jd",
"children": []
},
{
"name": "餐饮",
"value": "test_cy",
"children": []
},
]
},
{
"name": "监管部门",
"value": "z_jgbm",
"children": [
{
"name": "测试景区0511",
"value": "1789209771683909634",
"children": []
},
{
"name": "测试",
"value": "1787288242855383041",
"children": []
},
{
"name": "测试旅行社",
"value": "1786713494085734402",
"children": []
},
{
"name": "发展厅",
"value": "1669223640972222467",
"children": [
{
"name": "后勤中心",
"value": "1736963498807672833",
"children": []
},
{
"name": "测试332",
"value": "1668529668710735873",
"children": []
},
{
"name": "测试333",
"value": "1669222189977919490",
"children": [
{
"name": "局党组",
"value": "1737051406323433473",
"children": []
},
]
},
}
]
}
]
3.功能代码
const mustLearnRangeCode = ref([]); //必学范围 已选择的value 值存放
const visibleRangeCode = ref([]); //可见范围 已选择的value 值存放
const show = async (row) => {
isVisible.value = true;
getMustLearnRangeData()
if (row) {
title.value = "编辑";
formData.value = Object.assign({}, row);
let res = await infoByid_videoCourse(formData.value.id);
if (res.code === "200") {
formData.value = Object.assign({}, res.data);
//根据value 值回显
mustLearnRangeCode.value = formData.value.mustLearnRangeList.map(
(item) => {
return item.value;
}
);
visibleRangeCode.value = formData.value.visibleRangeList.map((item) => {
return item.value;
});
//课程必学范围是否可选择判断
setTimeout(() => {
if (formData.value.mustLearnRangeList.length > 0) {
addFieldToTreeArray(
mustLearnRangeOptions.value,
formData.value.mustLearnRangeList,
"disabled"
);
}
//重新给数组赋值,加延时是为了覆盖初始化的traverseTree 方法
mustLearnRangeOptionsAll.value = mustLearnRangeOptions.value;
}, 100);
}
} else {
title.value = "新增";
mustLearnRangeCode.value = [];
visibleRangeCode.value = [];
}
};
const props = { multiple: true, label: "name", value: "value" };
const mustLearnRangeOptions = ref([]); //用于编辑回显
const mustLearnRangeOptionsAll = ref([]);//必学范围初始化数据
const visibleRangeOptions = ref([]);//可见范围初始化数据
//初始化 必学范围所有选框都不能选择
function traverseTree(nodes, newValue) {
nodes.forEach((node) => {
node.disabled = newValue;
if (node.children && node.children.length) {
traverseTree(node.children, newValue);
}
});
}
//获取数据
const getMustLearnRangeData = async () => {
let res = await xxx();//接口信息
if (res.code === "200") {
//cloneObject 深拷贝方法,防止数据污染
mustLearnRangeOptions.value = cloneObject(res.data);
let tempOptions = cloneObject(res.data);
traverseTree(tempOptions, true);
mustLearnRangeOptionsAll.value = tempOptions; //必学范围树
visibleRangeOptions.value = cloneObject(res.data); //可见范围树
}
};
//可见范围
const visibleCascaderRef = ref();
const changeVisibleRange = (value) => {
let nodesInfo = visibleCascaderRef.value.getCheckedNodes(); //获取选择的节点
let selectData = [];
nodesInfo.forEach((item) => {
selectData.push(item.data);
});
//处理成后端需要的结构
let endData = selectData.map((item) => {
return {
name: item.name,
value: item.value,
};
});
formData.value.visibleRangeList = endData;
//判断可见范围是否有选择
if (endData.length > 0) {
//有选择的话 处理数组 判断必学范围的哪些选框可以选择,哪些不能选择
addFieldToTreeArray(mustLearnRangeOptionsAll.value, endData, "disabled");
} else {
//没有重新初始化赋值
mustLearnRangeOptionsAll.value = cloneObject(visibleRangeOptions.value);
}
};
function addFieldToTreeArray(treeArray, oneDimArray, fieldName) {
// 使用 Set 存储一维数组中的元素,以便快速查找
let tempArr = oneDimArray.map((item) => {
return item.value;
});
const oneDimSet = new Set(tempArr);
// 递归函数用于添加字段
function addField(nodes) {
nodes.forEach((node) => {
if (oneDimSet.has(node.value) || node.children.length > 0) {
// 如果节点的值在一维数组中,或者children有值 ,一级节点都可选择
node[fieldName] = false;
} else {
node[fieldName] = true;
}
// 递归处理子节点
if (node.children.length > 0) {
// 如果节点的值不在一级节点里,判断子节点中是否有该值,有的话一级节点可选择
let result = node.children.some((item) => oneDimSet.has(item.value));
if (result) {
node[fieldName] = false;
} else {
node[fieldName] = true;
}
addField(node.children);
}
});
}
// 开始添加字段
addField(treeArray);
}
效果:
1.新增
![](https://img-blog.csdnimg.cn/direct/5056a8f3a58442baabe033c9acfa426f.png)
2.有选择
![](https://img-blog.csdnimg.cn/direct/7ff22b4f876f415e9a328f641e51d957.png)
3.编辑回显
![](https://img-blog.csdnimg.cn/direct/79a3f913d2a54e50be63bd6baa399201.png)