ZaiZai 2 жил өмнө
parent
commit
0b485a8619

+ 2 - 2
src/styles/app/element.scss

@@ -396,7 +396,7 @@
 }
 
 //树
-.el-tree.hc-tree-node {
+.el-tree.hc-tree-node, .el-tree.hc-tree-node-v2 {
     --el-fill-color-blank: transparent;
     --el-tree-node-hover-bg-color: var(--el-color-primary-light-9);
     --el-tree-text-color: #50545E;
@@ -547,7 +547,7 @@
 }
 
 // 树样式
-.hc-tree-node {
+.hc-tree-node, .el-tree.hc-tree-node-v2 {
     .data-custom-tree-node {
         position: relative;
         display: flex;

+ 82 - 14
src/styles/app/tree.scss

@@ -1,14 +1,9 @@
 // 树的线样式
-
-
 .tree-line {
     :deep(.el-tree-node) {
         position: relative;
         padding-left: 12px; // 缩进量
-        // width: 100%;
-
     }
- 
     :deep(.el-tree-node__children) {
         padding-left: 12px; // 缩进量
     }
@@ -19,7 +14,7 @@
         width: 1px;
         position: absolute;
         left: 1px;
-        top: 0px;
+        top: 0;
         border-width: 1px;
         border-left: 2px dashed var(--el-color-primary);
     }
@@ -41,7 +36,7 @@
     // 去掉最顶层的虚线,放最下⾯样式才不会被上⾯的覆盖了
     & > :deep(.el-tree-node::after) {
         border-top: none !important;
-        border-top: 0px !important;
+        border-top: 0 !important;
     }
     & > :deep(.el-tree-node::before) {
         border-left: none;
@@ -60,16 +55,12 @@
     }
 }
 
-
-
 .tree-line1 {
     :deep(.el-tree-node) {
         position: relative;
         padding-left: 12px; // 缩进量
         width: 100%;
-
     }
- 
     :deep(.el-tree-node__children) {
         padding-left: 12px; // 缩进量
     }
@@ -85,7 +76,7 @@
         border-left: 2px dashed var(--el-color-primary);
     }
     // 当前层最后⼀个节点的竖线⾼度固定
-    :deep(.el-tree-node:last-child::before) {
+    :deep(.el-tree-node:last-child::before){
         height: 15px; // 可以⾃⼰调节到合适数值
     }
     // 横线
@@ -102,7 +93,7 @@
     // 去掉最顶层的虚线,放最下⾯样式才不会被上⾯的覆盖了
     & > :deep(.el-tree-node::after) {
         border-top: none !important;
-        border-top: 0px !important;
+        border-top: 0 !important;
     }
     & > :deep(.el-tree-node::before) {
         border-left: none;
@@ -112,11 +103,88 @@
         font-size: 16px;
         &.is-leaf {
             color: transparent;
-            font-size: 0px;
+            font-size: 0;
         }
     }
     :deep(.el-tree__empty-block) {
       min-width: 300px;
+    }
+}
 
+//虚拟树
+.hc-tree-node-v2.tree-line1 {
+    :deep(.el-virtual-scrollbar) {
+        right: -12px !important;
+    }
+    :deep(.el-tree-node) {
+        padding-left: 0;
+    }
+    :deep(.el-tree-node:first-child::before) {
+        border-left: none;
+    }
+    :deep(.el-tree-node:first-child::after) {
+        border-top: none !important;
+        border-top: 0 !important;
     }
+    // 竖线
+    :deep(.el-tree-node::before) {
+        left: 12px;
+    }
+    // 横线
+    :deep(.el-tree-node::after) {
+        left: 14px;
+    }
+    :deep([class*='line-i-']) {
+        position: relative;
+        //竖线
+        &::before {
+            content:"";
+            height: 26px;
+            width: 1px;
+            position: absolute;
+            left: 12px;
+            top: 0;
+            border-width: 1px;
+            border-left: 2px dashed var(--el-color-primary);
+        }
+        //横线
+        &::after {
+            content:"";
+            width: 16px;
+            height: 20px;
+            position: absolute;
+            left: 14px;
+            top: 12px;
+            border-width: 1px;
+            border-top: 2px dashed var(--el-color-primary);
+        }
+    }
+    //自动生成子级线条
+    @for $i from 1 through 20 {
+        //竖线
+        :deep(.line-i-#{$i}::before) {
+            left: #{(($i + 1) * 24) - 11}px;
+        }
+        //横线
+        :deep(.line-i-#{$i}::after) {
+            left: #{(($i + 1) * 24) - 9}px;
+        }
+
+        //消除非主要线条
+        @if $i >= 3 {
+            :deep(.el-tree-node[level="#{$i}"]) {
+                &::after {
+                    display: none;
+                }
+                @if $i >= 4 {
+                    @for $x from 1 through ($i - 3) {
+                        .line-i-#{$x}::after {
+                            display: none;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
 }

+ 112 - 50
src/views/data-fill/components/HcTreeDataV2.vue

@@ -1,22 +1,22 @@
 <template>
     <el-tree-v2
-        ref="ElTreeRef" 
-        :class="[ui,submitCounts?'tree-line1':'']"
-        :data="datas" 
+        ref="ElTreeRef"
+        :class="[ui, submitCounts ? 'tree-line1' : '', isTreeShow ? 'is-tree-show': '']"
+        :data="datas"
         :props="ElTreeProps"
-        class="hc-tree-node tree-line el-radio-group"
-        :filter-method="filterMethod" 
+        class="hc-tree-node-v2 tree-line  el-radio-group"
+        :filter-method="filterMethod"
         :height="treeHeight"
         @node-click="ElTreeClick"
         accordion
         highlight-current
         :default-expand-all="false"
         node-key="primaryKeyId"
-     
+        :indent="24"
         @node-contextmenu="ElTreeLabelContextMenu"
         >
             <template #default="{ node, data }">
-                <div :id="`${idPrefix}${data['primaryKeyId']}`" class="data-custom-tree-node">
+                <div  :id="`${idPrefix}${data['primaryKeyId']}`" class="data-custom-tree-node">
                     <!--树组件,节点名称-->
                     <div :class="node.level === 1?'level-name':''" class="label">
                         <span
@@ -45,8 +45,7 @@
             </template>
         </el-tree-v2>
          <!--右键菜单-->
-             <!--右键菜单-->
-    <!-- <HcContextMenu v-if="menusData.length > 0" ref="contextMenuRef" :datas="menusData" @item-click="handleMenuSelect">
+    <HcContextMenu v-if="menusData.length > 0" ref="contextMenuRef" :datas="menusData" @closed="handleMenuClosed" @item-click="handleMenuSelect">
         <template #mark="{item}">
             <HcIcon :fill="treeRefData?.isFirst" :name="item.icon" class="menu-item-icon"/>
             <span class="menu-item-name">{{ treeRefData?.isFirst ? '取消标记为首件' : '标记为首件' }}</span>
@@ -55,19 +54,30 @@
             <HcIcon :line="false" :name="item.icon" class="menu-item-icon"/>
             <span class="menu-item-name">{{ item.label }}</span>
         </template>
-    </HcContextMenu> -->
+    </HcContextMenu>
 
 </template>
 
 <script setup>
-import {ref, watch, nextTick} from "vue";
+import {ref, watch, nextTick, onMounted, onUnmounted} from "vue";
 import {getTreeNodeType} from '~uti/utils';
+import { ElTreeV2 } from 'z-element-plus'
+import {isNullES} from "js-fast-way";
+
 //参数
 const props = defineProps({
     ui: {
         type: String,
         default: ''
     },
+    isMark: {
+        type: Boolean,
+        default: false
+    },
+    menus: {
+        type: Array,
+        default: () => ([])
+    },
     height: {
         type: [Number, String],
         default: 0
@@ -90,7 +100,7 @@ const props = defineProps({
     },
     idPrefix: {
         type: String,
-        default: 'tree-data-'
+        default: 'tree-data-v2-'
     },
     isColor: {
         type: Boolean,
@@ -100,6 +110,10 @@ const props = defineProps({
         type: Boolean,
         default: true
     },
+    isShow: {
+        type: Boolean,
+        default: false
+    },
 })
 
 //变量
@@ -110,50 +124,53 @@ const ElTreeProps = ref({
     children: 'children',
 })
 const treeHeight = ref(0)
-
+const menuMark = ref(props.isMark)
 const isSubmitCounts = ref(props.submitCounts);
 const searchInfo = ref(props.searchTreeVal)
 const idPrefix = ref(props.idPrefix);
 const menusData = ref(props.menus)
 const isAutoKeys = ref(props.isAutoKeys)
 const treeRefData = ref(null)
-
+const isTreeShow = ref(props.isShow)
 
 //监听
 watch(() => [
     props.height,
     props.submitCounts,
-    props.searchTreeVal,
-    props.datas,
-    props.ElTreeLoadNode,
     props.idPrefix,
     props.menus,
     props.isAutoKeys,
-], ([height, submitCounts, searchTreeVal,UserIdPrefix,menus,AutoKeys]) => {
-    console.log('height', height)
+    props.isMark,
+    props.isShow,
+], ([height, submitCounts,UserIdPrefix,menus,AutoKeys,isMark, isShow]) => {
     treeHeight.value = height
     isSubmitCounts.value = submitCounts
-    searchInfo.value = searchTreeVal
     idPrefix.value = UserIdPrefix
     menusData.value = menus
     isAutoKeys.value = AutoKeys
+    menuMark.value = isMark
+    isTreeShow.value = isShow
 })
 
-watch(searchInfo, (val) => {
-        if (val) {
-            nextTick(() => {
-              
-                ElTreeRef?.value.filter(val)
-            })
+watch(() => [
+    props.searchTreeVal,
+], ([val]) => {
+    searchInfo.value = val
+    if (val) {
+        nextTick(() => {
+            ElTreeRef?.value.filter(val)
+        })
+    } else {
+        emit('changeSearch')
+    }
+})
 
-        } else {
-            emit('changeSearch')
-        }
 
-    },
+onMounted(() => {
+    getOffsetHeight()
+    windowResize()
+})
 
-    {immediate: true}
-)
 //事件
 const emit = defineEmits(['menuTap', 'nodeTap', 'changeSearch', 'changetreelaod'])
 
@@ -169,6 +186,7 @@ const getNodeExpandKeys = async (node, newKeys) => {
 }
 //节点被点击
 const ElTreeClick = async (data, node) => {
+    console.log(node)
     if (isAutoKeys.value) {
         let autoKeysArr = []
         await getNodeExpandKeys(node, autoKeysArr)
@@ -178,21 +196,21 @@ const ElTreeClick = async (data, node) => {
         emit('nodeTap', {node, data, keys: []})
     }
 }
+
 const getReturnNode = (node, _array, value) => {
-    let isPass = node && node.title && node.title.indexOf(value) !== -1;
- 
+    let isPass = node.data && node.data.title && node.data.title.indexOf(value) !== -1;
     isPass ? _array.push(isPass) : '';
     if (!isPass && node.level != 1 && node.parent) {
         getReturnNode(node.parent, _array, value);
     }
 }
 //筛选树节点
-const filterMethod = (query, node) => {
+const filterMethod = (query,data) => {
     if (!query) {
         return true;
     }
-    let level = node.title;
     let _array = [];//这里使用数组存储 只是为了存储值。
+    let node=ElTreeRef?.value.getNode(data.primaryKeyId)
     getReturnNode(node, _array, query);
     let result = false;
     _array.forEach((item) => {
@@ -202,16 +220,18 @@ const filterMethod = (query, node) => {
         emit('changetreelaod', false)
     }, 1000)
     return result;
- 
+
 }
 //鼠标右键事件
 const contextMenuRef = ref(null)
+const treeRefNode = ref(null)
 const ElTreeLabelContextMenu = (e, data, node) => {
     const rows = menusData.value || [];
     if (node.level !== 1 && rows.length > 0) {
         e.preventDefault();
         treeRefNode.value = node;
         treeRefData.value = data;
+        node.showTreeMenu = true
         //展开菜单
         contextMenuRef.value?.showMenu(e)
     }
@@ -230,6 +250,7 @@ const handleMenuSelect = async ({key}) => {
     } else {
         // emit('menuTap', {key, node, data})
         if (isAutoKeys.value) {
+            console.log(11111);
             let autoKeysArr = []
             await getNodeExpandKeys(node, autoKeysArr)
             const autoKeys = autoKeysArr.reverse()
@@ -237,6 +258,15 @@ const handleMenuSelect = async ({key}) => {
         }
     }
 }
+
+const handleMenuClosed = () => {
+    const node = treeRefNode.value;
+    if (!isNullES(node)) {
+        treeRefNode.value['showTreeMenu'] = false
+    }
+}
+
+
 //设置树菜单的标记数据
 const setElTreeMenuMark = (keys, isFirst) => {
     keys.forEach(item => {
@@ -252,6 +282,31 @@ const removeElTreeNode = (key) => {
     //删除 Tree 中的一个节点,使用此方法必须设置 node-key 属性
     ElTreeRef.value.remove(node)
 }
+
+//监听浏览器窗口变化
+const windowResize = () => {
+    window.addEventListener("resize", resizeEvent);
+}
+
+const resizeEvent = () => {
+    window.requestAnimationFrame(() => {
+        getOffsetHeight()
+    })
+}
+
+const getOffsetHeight = () => {
+    try {
+        treeHeight.value = document.getElementById('hc-tree-scrollbar').offsetHeight;
+    } catch {
+        console.log('hc-tree-scrollbar 元素,不存在,获取高度失败')
+    }
+}
+
+//被卸载
+onUnmounted(() => {
+    window.removeEventListener("resize", resizeEvent);
+})
+
 // 暴露出去
 defineExpose({
     setElTreeMenuMark,
@@ -282,15 +337,15 @@ defineExpose({
         font-size: 14px;
     }
     .menu-icon1 {
-        position: unset;
+        position: relative;
         vertical-align: bottom;
         display: inline-block;
+        width: 0;
+        right: -45px;
+        border-radius: 2px;
         pointer-events: none;
-        transition: opacity 0.2s;
-        opacity: 0;
-        right: 0;
         background: rgba(255, 255, 255, 0.25);
-        border-radius: 2px;
+        transition: width 0.2s;
         .cu-tree-node-popover-menu-icon {
             display: flex;
             align-items: center;
@@ -299,28 +354,35 @@ defineExpose({
     }
     &:hover {
         .menu-icon1 {
-            opacity: 1;
+            right: 0;
+            width: 24px;
             pointer-events: all;
             cursor: context-menu;
         }
     }
     .menu-icon1.show {
-        opacity: 1;
+        right: 0;
+        width: 24px;
         pointer-events: all;
         cursor: context-menu;
     }
 }
 </style>
 <style lang="scss">
-
-.el-tree.hc-tree-node .el-tree-node {
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    .el-tree-node_content {
+.hc-tree-node-v2.el-tree {
+    display: none;
+    .el-tree-node {
         white-space: nowrap;
         overflow: hidden;
         text-overflow: ellipsis;
+        .el-tree-node_content {
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+        }
+    }
+    &.is-tree-show {
+        display: block;
     }
 }
 </style>

+ 2 - 2
src/views/data-fill/wbs.vue

@@ -127,7 +127,7 @@
                     </div>
                     <div v-loading="treeLoading" id="hc-tree-scrollbar" class="hc-tree-scrollbar" element-loading-text="获取数据中...">
                         <HcTreeDataV2
-                            v-show="isSearchTree"
+                            :isShow="isSearchTree"
                             :datas="searchTreeData"
                             :height="searchTreeHeight"
                             :isMark="TreeMark"
@@ -907,7 +907,7 @@ const changetreelaod = (val) => {
 const treeLoading = ref(false)
 const searchTreeClick = async () => {
     searchTreeHeight.value = document.getElementById('hc-tree-scrollbar').offsetHeight;
-    //  isSearchTree.value=true
+    isSearchTree.value = true
     //treeLoading.value = true
     if (searchElTreeLoadNode.value === true) {
         treeLoading.value = true