master
2022-02-14 1684d66eaf39f77980b987359f413d2ff5714940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<template>
    <div class="cl-menu-tree__wrap">
        <el-popover
            v-model:visible="visible"
            placement="bottom-start"
            trigger="click"
            width="500px"
            popper-class="cl-menu-tree"
        >
            <el-input v-model="keyword" size="small">
                <template #prefix>
                    <i class="el-input__icon el-icon-search"></i>
                </template>
            </el-input>
 
            <div class="cl-menu-tree__scroller scroller1">
                <el-tree
                    ref="treeRef"
                    node-key="menuId"
                    :data="treeList"
                    :props="{
                        label: 'name',
                        children: 'children'
                    }"
                    :highlight-current="true"
                    :expand-on-click-node="false"
                    :default-expanded-keys="expandedKeys"
                    :filter-node-method="filterNode"
                    @current-change="onCurrentChange"
                />
            </div>
 
            <template #reference>
                <el-input v-model="name" readonly placeholder="请选择" @click="visible = true" />
            </template>
        </el-popover>
    </div>
</template>
 
<script lang="ts">
import { computed, defineComponent, onMounted, ref, watch } from "vue";
import { useCool } from "/@/cool";
import { deepTree } from "/@/cool/utils";
 
export default defineComponent({
    name: "cl-menu-tree",
 
    props: {
        modelValue: [Number, String]
    },
 
    emits: ["update:modelValue"],
 
    setup(props, { emit }) {
        // 请求服务
        const { service } = useCool();
 
        // 关键字
        const keyword = ref<string>("");
 
        const visible = ref<boolean>(false);
 
        // 树形列表
        const list = ref<any[]>([]);
 
        // 展开值
        const expandedKeys = ref<any[]>([]);
 
        // el-tree 组件
        const treeRef = ref<any>({});
 
        // 绑定值回调
        function onCurrentChange({ id }: any) {
            emit("update:modelValue", id);
            visible.value = false;
        }
 
        // 刷新列表
        function refresh() {
            service.base.sys.menu.list().then((res: any) => {
                const _list = res.filter((e: any) => e.type != 2);
 
                _list.unshift({
                    name: "一级菜单",
                    id: null
                });
 
                list.value = _list;
            });
        }
 
        // 过滤节点
        function filterNode(value: string, data: any) {
            if (!value) return true;
            return data.name.indexOf(value) !== -1;
        }
 
        // 节点名称
        const name = computed(() => {
            const item = list.value.find((e) => e.id == props.modelValue);
            return item ? item.name : "一级菜单";
        });
 
        // 树形列表
        const treeList = computed(() => deepTree(list.value));
 
        // 监听关键字过滤
        watch(keyword, (val: string) => {
            treeRef.value.filter(val);
        });
 
        onMounted(function () {
            refresh();
        });
 
        return {
            visible,
            keyword,
            list,
            expandedKeys,
            treeRef,
            name,
            treeList,
            refresh,
            filterNode,
            onCurrentChange
        };
    }
});
</script>
 
<style lang="scss">
.cl-menu-tree {
    box-sizing: border-box;
 
    .el-input {
        margin-bottom: 10px;
    }
 
    &__scroller {
        max-height: 400px;
        overflow: hidden auto;
    }
}
</style>