zhaoxing
2022-08-22 74bb50ce93d0c9cd20a0b84f63db46f433a39e91
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
<template>
    <div class="cl-menu-perms">
        <el-cascader
            v-model="value"
            separator=":"
            clearable
            filterable
            :options="options"
            :props="{ multiple: true }"
            @change="onChange"
        />
    </div>
</template>
 
<script lang="ts">
import { defineComponent, ref, watch } from "vue";
import { useCool } from "/@/cool";
 
export default defineComponent({
    name: "cl-menu-perms",
 
    props: {
        modelValue: {
            type: String,
            default: ""
        }
    },
 
    emits: ["update:modelValue"],
 
    setup(props, { emit }) {
        const { service } = useCool();
 
        // 绑定值
        const value = ref<any[]>([]);
 
        // 权限列表
        const options = ref<any[]>([]);
 
        // 监听改变
        function onChange(row: any) {
            emit("update:modelValue", row.map((e: any) => e.join(":")).join(","));
        }
 
        // 解析权限
        (function parsePerm() {
            const list: any[] = [];
            let perms: any[] = [];
 
            const flat = (obj: any) => {
                for (const i in obj) {
                    const { permission } = obj[i];
 
                    if (permission) {
                        perms = [...perms, Object.values(permission)].flat();
                    } else {
                        flat(obj[i]);
                    }
                }
            };
 
            flat(service);
 
            perms
                .filter((e) => e.includes(":"))
                .map((e) => e.split(":"))
                .forEach((arr) => {
                    const col = (i: number, d: any[]) => {
                        const key = arr[i];
 
                        if (d) {
                            const index = d.findIndex((e: any) => e.label == key);
 
                            if (index >= 0) {
                                col(i + 1, d[index].children);
                            } else {
                                const isLast = i == arr.length - 1;
 
                                d.push({
                                    label: key,
                                    value: key,
                                    children: isLast ? null : []
                                });
 
                                if (!isLast) {
                                    col(i + 1, d[d.length - 1].children || []);
                                }
                            }
                        }
                    };
 
                    col(0, list);
                });
 
            options.value = list;
        })();
 
        // 监听值
        watch(
            () => props.modelValue,
            (val: string) => {
                value.value = val ? val.split(",").map((e: string) => e.split(":")) : [];
            },
            {
                immediate: true
            }
        );
 
        return {
            value,
            options,
            onChange
        };
    }
});
</script>
 
<style lang="scss">
.cl-menu-perms {
    .el-cascader {
        width: 100%;
    }
}
</style>