smart_archives_web/src/views/common/fileTree.vue

353 lines
9.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 小型弹窗用于完成删除保存等操作 -->
<el-dialog class="l-dialog" :class="lDialog" :title="title" :visible.sync="dialogVisible" :showClose="true"
:closeOnClickModal="false" @close="handleClose" :append-to-body="true">
<el-row :gutter="24" style="display: flex; align-items: center">
<el-col :span="16">
<el-input v-model="filterText" placeholder="输入关键字" @keyup.enter.native="onHandleSearch">
</el-input>
</el-col>
<el-col :span="8">
<el-button type="primary" size="small" @click="onHandleSearch">
查询
</el-button>
</el-col>
</el-row>
<div class="tree-container" style="max-height: calc(80vh - 190px); overflow-y: auto;">
<el-tree ref="leftTreeRef" :data="treeDataList" default-expand-all class="left-tree-list"
@node-click="onHandleNodeClick" :filter-node-method="filterNode" highlight-current node-key="id">
<span class="custom-tree-node" slot-scope="{ node }">
<span class="node-label">{{ node.label }}</span>
</span>
</el-tree>
</div>
<span slot="footer" class="dialog-footer">
<el-button class="clear-btn" @click="handleClose">取消</el-button>
<el-button type="primary" class="search-btn" @click="handleSave">确认</el-button>
</span>
</el-dialog>
</template>
<script>
import _ from 'lodash'
import {
getFileManageTreeApi
} from '@/api/filesTransfer/apply'
export default {
name: "FileTree",
props: ["width", "title", "rowData"],
data() {
return {
lDialog: this.width > 500 ? "w700" : "w500",
dialogVisible: true,
isDisabled: true,
treeDataList: [],
filterText: '',
originalTreeData: [], // 保存原始数据,
selectedNodeId: null, // 保存当前选中的节点ID
};
},
created() {
this.getLeftTreeList();
},
computed: {
// 过滤后的树数据
filteredTreeData() {
if (!this.filterText) {
return this.treeDataList
}
return this.filterTreeData(this.treeDataList)
}
},
methods: {
// 获取树列表
async getLeftTreeList() {
const proId = this.rowData.proId;
const res = await getFileManageTreeApi({ proId })
const transformedData = this.convertToVueTree(res.data)
this.treeDataList = transformedData;
// 保存原始数据
this.originalTreeData = JSON.parse(JSON.stringify(this.treeDataList))
},
/* 刷新树节点 */
async handleQuery() {
// 保存当前选中的节点ID
const currentNode = this.$refs.leftTreeRef.getCurrentNode();
if (currentNode) {
this.selectedNodeId = currentNode.id;
}
// 重新获取树数据
await this.getLeftTreeList();
// 恢复选中状态
this.$nextTick(() => {
if (this.selectedNodeId) {
this.$refs.leftTreeRef.setCurrentKey(this.selectedNodeId);
}
});
},
// 树数据过滤 - 支持无限层级转换
convertToVueTree(data) {
if (!data || !Array.isArray(data)) {
return [];
}
return data.map(item => {
const node = {
id: item.id,
label: item.contentName,
level: item.level,
parentId: item.parentId
};
// 递归处理子节点
if (item.children && Array.isArray(item.children) && item.children.length > 0) {
const children = this.convertToVueTree(item.children);
// 只有当子节点不为空时才添加 children 属性
if (children.length > 0) {
node.children = children;
}
}
return node;
});
},
// 节点点击事件
onHandleNodeClick(data) {
// 保存选中的节点ID
this.selectedNodeId = data.id;
},
// 搜索
onHandleSearch() {
this.$refs.leftTreeRef.filter(this.filterText)
},
// 树节点过滤方法
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
// 递归过滤树数据
filterTreeData(treeData) {
const result = []
for (const node of treeData) {
const newNode = { ...node }
if (node.children && node.children.length > 0) {
const filteredChildren = this.filterTreeData(node.children)
if (filteredChildren.length > 0) {
newNode.children = filteredChildren
result.push(newNode)
} else if (node.label.indexOf(this.filterText) !== -1) {
// 如果父节点匹配,保留所有子节点
result.push(node)
}
} else if (node.label.indexOf(this.filterText) !== -1) {
result.push(newNode)
}
}
return result
},
/*关闭弹窗 */
handleClose() {
this.dialogVisible = false;
this.$emit("closeDialog");
/* setTimeout(() => {
this.dialogVisible = true;
}); */
},
/**确认弹窗 */
sureBtnClick() {
this.dialogVisible = false;
this.$emit("closeDialog");
/* setTimeout(() => {
this.dialogVisible = true;
}); */
},
// 保存数据
handleSave(){
this.$emit('getTreeData', this.selectedNodeId);
this.handleClose();
}
}
};
</script>
<style lang="scss" scoped>
.w700 ::v-deep .el-dialog {
width: 700px;
}
.w500 ::v-deep .el-dialog {
width: 500px;
}
.w500 ::v-deep .el-dialog__header,
.w700 ::v-deep .el-dialog__header {
// background: #eeeeee;
.el-dialog__title {
font-size: 16px;
}
}
.yxq .el-range-separator {
margin-right: 7px !important;
}
.el-date-editor--daterange.el-input__inner {
width: 260px;
}
.form-item {
width: 100%;
}
.select-style {
display: flex;
justify-content: space-between;
}
.tree-container {
margin-top: 10px;
overflow-x: hidden;
}
/* 自定义滚动条样式 */
.tree-container::-webkit-scrollbar {
width: 6px;
background: #f5f5f5;
}
.tree-container::-webkit-scrollbar-track {
background: #f5f5f5;
border-radius: 3px;
}
.tree-container::-webkit-scrollbar-thumb {
background: #c0c4cc;
border-radius: 3px;
transition: background 0.3s;
}
.tree-container::-webkit-scrollbar-thumb:hover {
background: #909399;
}
.left-tree-list {
width: 100%;
}
/* 自定义节点行:左右布局,支持多行文本 */
.custom-tree-node {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
min-height: 20px;
padding: 1px 0;
}
.node-label {
flex: 1;
min-width: 0;
overflow: visible;
text-overflow: initial;
white-space: normal;
word-break: break-word;
word-wrap: break-word;
line-height: 1.2;
padding-right: 4px;
}
/* 使行容器自适应高度,单行文本居中对齐,多行文本顶部对齐 */
.left-tree-list .el-tree-node__content {
display: flex;
align-items: center;
height: auto;
min-height: 20px;
padding: 1px 4px;
line-height: 1.2;
}
/* 多行文本时改为顶部对齐 */
.left-tree-list .el-tree-node__content:has(.node-label[style*="height"]) {
align-items: flex-start;
}
/* 高亮选中状态同样自适应高度 */
.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
height: auto !important;
align-items: center;
line-height: 1.2;
}
/* 选中节点的背景色 */
.left-tree-list .el-tree-node.is-current>.el-tree-node__content {
background-color: #b3d9ff;
color: #006e6a !important;
}
/* 确保选中节点的文字颜色正确应用 */
.left-tree-list .el-tree-node.is-current>.el-tree-node__content .el-tree-node__label {
color: #006e6a !important;
}
/* 确保自定义树节点中的文字颜色正确应用 */
.left-tree-list .el-tree-node.is-current>.el-tree-node__content .custom-tree-node {
color: #006e6a !important;
}
/* 悬停效果 */
.left-tree-list .el-tree-node__content:hover {
background-color: #f5f5f5;
}
.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
height: auto;
}
/* 选中节点的悬停效果 */
.left-tree-list .el-tree-node.is-current>.el-tree-node__content:hover {
background-color: #8cc8ff;
}
.btn-box {
margin-left: 4px;
opacity: 0;
transition: opacity 0.15s ease-in-out;
flex-shrink: 0;
display: flex;
align-items: center;
gap: 1px;
}
/* 悬浮到整行时显示操作按钮 */
.left-tree-list .el-tree-node__content:hover .btn-box {
opacity: 1;
}
/* 确保树节点内容正确显示 */
::v-deep .el-tree-node__content {
display: flex;
align-items: center;
cursor: pointer;
height: auto;
min-height: 38px;
padding: 1px 4px;
}
/* 树节点展开/收起图标 */
::v-deep .el-tree-node__expand-icon {
padding: 1px;
margin-right: 1px;
flex-shrink: 0;
}
/* 树节点图标容器 */
::v-deep .el-tree-node__content>.el-tree-node__expand-icon {
flex-shrink: 0;
}
</style>