Commit b5ffdbbe by 周海峰

no message

parent f0e1db21
<template>
<div style="padding:1vh;">
<div v-show="getTreeData.length > 0">
<div style="position: relative;">
<!-- Loading遮罩层 - 覆盖整个组件 -->
<div
class="component-loading-overlay"
:style="{ display: checkLoading ? 'flex' : 'none' }"
>
处理中...
</div>
<div v-show="treeData.length > 0">
<div class="search-container">
<div class="search-wrapper">
<q-input
......@@ -83,21 +91,16 @@
</div>
</div>
</div>
<div style="padding-top: 6vh">
<div style="padding-top: 6vh;">
<Tree
v-if="getTreeData.length > 0"
v-if="treeData.length > 0"
ref="tree"
checkable
:checkedKeys="checkedKeys"
@expand="onExpand"
:expandedKeys="expandedKeys"
:autoExpandParent="autoExpandParent"
:treeData="getTreeData"
:defaultExpandedKeys="defaultExpandedKeys"
:checkedKeys="checkedKeys"
:treeData="treeData"
@check="onCheck"
@select="onSelect"
>
<template slot="title" slot-scope="node">
<span style="color: rgb(33, 186, 69);" v-if="checkedKeys.indexOf(node.key)>-1" ></span>
<span v-if="node.title.indexOf(searchValue) > -1">
......@@ -114,7 +117,7 @@
</Tree>
</div>
</div>
<div v-show="!getTreeData.length > 0">
<div v-show="!treeData.length > 0">
正在加载组织机构组件...
</div>
</div>
......@@ -186,7 +189,11 @@
nodeCache: null,
// 搜索相关
searchOptions: [],
showSearchMenu: false
showSearchMenu: false,
// 勾选操作loading状态
checkLoading: false,
// 保存body原始样式
originalBodyStyle: null
};
},
props: {
......@@ -236,33 +243,76 @@
onCheck(checkedKeys, e) {
console.log('onCheck', checkedKeys, e);
let finalCheckedKeys = [...checkedKeys];
// 显示loading
this.checkLoading = true;
console.log('Loading set to true:', this.checkLoading);
// 当勾选父节点时,自动勾选所有叶子节点
if (e.checked && e.node.children && e.node.children.length > 0) {
const leafKeys = this.getAllLeafKeys(e.node.children);
finalCheckedKeys = [...new Set([...finalCheckedKeys, ...leafKeys])];
}
// 防止页面滚动
this.preventBodyScroll();
// 当取消勾选父节点时,取消勾选所有叶子节点
if (!e.checked && e.node.children && e.node.children.length > 0) {
const leafKeys = this.getAllLeafKeys(e.node.children);
finalCheckedKeys = finalCheckedKeys.filter(key => !leafKeys.includes(key));
}
// 强制Vue重新渲染
this.$forceUpdate();
// 只在最终结果不同时才更新,避免不必要的触发
if (JSON.stringify(finalCheckedKeys) !== JSON.stringify(this.checkedKeys)) {
this.checkedKeys = finalCheckedKeys;
// 使用setTimeout强制分离到下一个事件循环,确保loading先显示
setTimeout(() => {
console.log('Processing check operation...');
this.processCheckOperation(checkedKeys, e);
}, 0);
},
// 分离的处理逻辑
processCheckOperation(checkedKeys, e) {
try {
// 更新本地状态
this.checkedKeys = checkedKeys;
// 更新选中的人员列表
this.updateSelectedStaff();
// 双向绑定会通过watch自动处理
// 处理完成后,延迟一点时间再隐藏loading,确保用户能看到
setTimeout(() => {
this.checkLoading = false;
// 恢复页面滚动
this.restoreBodyScroll();
}, 200); // 最少显示200ms,让用户看到反馈
} catch (error) {
console.error('勾选处理出错:', error);
this.checkLoading = false; // 出错时也要隐藏loading
this.restoreBodyScroll(); // 恢复页面滚动
}
},
// 防止body滚动
preventBodyScroll() {
// 保存原始样式
if (!this.originalBodyStyle) {
this.originalBodyStyle = {
overflow: document.body.style.overflow,
position: document.body.style.position
};
}
// 防止滚动
document.body.style.overflow = 'hidden';
document.body.style.position = 'fixed';
document.body.style.width = '100%';
},
// 恢复body滚动
restoreBodyScroll() {
// 恢复原始样式
if (this.originalBodyStyle) {
document.body.style.overflow = this.originalBodyStyle.overflow || '';
document.body.style.position = this.originalBodyStyle.position || '';
document.body.style.width = '';
this.originalBodyStyle = null;
}
},
onSelect(selectedKeys, info) {
// 在复选模式下,onSelect 可以用来处理一些辅助功能,比如展开/折叠
// console.log('onSelect', selectedKeys, info);
},
// 搜索输入处理
onSearchInput(value) {
this.searchValue = value || '';
......@@ -285,14 +335,12 @@
this.showSearchMenu = false;
}
},
// 手动搜索
manualSearch() {
if (this.searchText && this.searchText.length > 0) {
this.onSearchInput(this.searchText);
}
},
// 隐藏搜索菜单
hideSearchMenu() {
// 延迟隐藏,以便点击选项时能正常触发
......@@ -300,25 +348,27 @@
this.showSearchMenu = false;
}, 500);
},
// 选择搜索选项
selectSearchOption(option) {
this.checkLoading = true;
// 强制Vue重新渲染
this.$forceUpdate();
console.log(option,'selectSearchOption=======')
// 勾选选中的节点
if (!this.checkedKeys.includes(option.key)) {
this.checkedKeys = [...this.checkedKeys, option.key];
this.updateSelectedStaff();
}
// 展开到选中节点的路径
const parentKeys = this.getParentKeys(option.key, this.treeData);
this.expandedKeys = [...new Set([...this.expandedKeys, ...parentKeys])];
this.autoExpandParent = false;
// 清空搜索状态
// 清空搜索状态
this.searchText = '';
this.searchOptions = [];
this.showSearchMenu = false;
setTimeout(() => {
// 勾选选中的节点
if (!this.checkedKeys.includes(option.key)) {
this.checkedKeys = [option.key, ...this.checkedKeys];
}else{
//根据 key 移除
this.checkedKeys = this.checkedKeys.filter(item => item !== option.key);
}
this.updateSelectedStaff();
this.checkLoading = false;
}, 0);
},
// 获取节点到根节点的路径
......@@ -346,17 +396,17 @@
this.searchValue = value;
// 展开包含搜索结果的节点
const expandedKeys = dataList.map((item) => {
if (item.title.indexOf(value) > -1) {
return getParentKey(item.key, this.getTreeData)
}
return null
}).filter((item, i, self) => item && self.indexOf(item) === i)
if (expandedKeys.length > 0) {
this.expandedKeys = [...new Set([...this.expandedKeys, ...expandedKeys])];
this.autoExpandParent = true;
}
// const expandedKeys = dataList.map((item) => {
// if (item.title.indexOf(value) > -1) {
// return getParentKey(item.key, this.getTreeData)
// }
// return null
// }).filter((item, i, self) => item && self.indexOf(item) === i)
// if (expandedKeys.length > 0) {
// this.expandedKeys = [...new Set([...this.expandedKeys, ...expandedKeys])];
// this.autoExpandParent = true;
// }
},
// 获取节点下的所有叶子节点key
getAllLeafKeys(nodes) {
......@@ -377,27 +427,7 @@
// 更新选中的人员列表
updateSelectedStaff() {
this.checkedPeople = [];
this.checkedDepartment = [];
// 使用 Map 缓存节点查找结果,避免重复遍历
if (!this.nodeCache) {
this.nodeCache = new Map();
this.buildNodeCache(this.treeData);
}
// 遍历所有选中的key,区分人员和部门
this.checkedKeys.forEach(key => {
const node = this.nodeCache.get(key);
if (node) {
if (key < 1000000) { // 人员
this.checkedPeople.push(node);
} else { // 部门
this.checkedDepartment.push(node);
}
}
});
this.checkedPeople = dataList.filter(node => node.key < 1000000 && this.checkedKeys.includes(node.key))
// 向父组件发送选中的人员列表
this.$emit('staffNode', this.checkedPeople);
},
......@@ -467,7 +497,7 @@
position: fixed;
width: 17vw;
z-index: 9999;
padding: 1vh;
padding: 0 1vh;
}
.search-wrapper {
......@@ -684,6 +714,23 @@
background: rgba(0, 0, 0, 0.3);
}
/* 组件Loading遮罩层样式 - 覆盖整个组件 */
.component-loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(3px);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
overflow: hidden; /* 防止遮罩层内部滚动 */
}
/* 响应式设计 */
@media (max-width: 768px) {
.search-container {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论