<!--suppress ALL -->
<template>
    <div style="">
        <el-tree
            :data="menus"
            :render-content="renderContent"
            :highlight-current="true"
            :expand-on-click-node="true"
            node-key="id"
            default-expand-all>
        </el-tree>
        <el-button size="mini" type="text" @click="addRootMenu" style="margin-left: 24px">添加</el-button>
        <el-dialog :visible.sync="dialogVisible" title="添加菜单">
            <el-form :model="menu" ref="form" label-position="top" size="small">
                <el-form-item label="菜单名" prop="name" :rules="[{required: true, message: '请填写菜单名', trigger: 'blur'}]">
                    <el-input v-model="menu.name"></el-input>
                </el-form-item>
                <el-form-item label="菜单地址" prop="href">
                    <el-input v-model="menu.href"></el-input>
                </el-form-item>
                <el-form-item prop="icon">
                    <template slot="label">图标
                        <a href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free" target="_blank" class="available-icons">查看所有可用图标</a></template>
                    <el-input v-model="icon">
                        <template slot="append"><span ref="iconContainer" style="font-size: 18px"><i class="fas fa-"></i></span></template>
                    </el-input>
                </el-form-item>
            </el-form>
            <div slot="footer">
                <el-button @click="dialogVisible = false" size="small">取消</el-button>
                <el-button type="primary" @click="addMenu" :loading="loading" size="small">保存</el-button>
            </div>
        </el-dialog>
    </div>
</template>
<script>
    import axios from 'axios'

    export default {
        created() {
            this.getData();
        },
        data() {
            return {
                dialogVisible: false,
                curr: null,
                loading: false,
                menus: [],
                menu: {
                    name: '',
                    href: '',
                    icon: ''
                },
                icon: ''
            }
        },
        methods: {
            addRootMenu() {
                this.menu = {
                    parentId: 0,
                    name: '',
                    href: '',
                    icon: 'bars'
                };
                this.icon = 'bars';
                if (this.menus && this.menus.length > 0) {
                    this.menu.sort = this.menus[this.menus.length - 1].sort + 1;
                } else {
                    this.menu.sort = 1;
                }
                this.dialogVisible = true;
                setTimeout(()=>{
                    this.showIcon('bars');
                }, 100)
            },
            showAddDialog(node, data) {
                this.menu = {
                    parentId: node.data.id,
                    name: '',
                    href: '',
                    icon: null
                };
                this.icon = '';
                if (node.childNodes && node.childNodes.length > 0) {
                    this.menu.sort = node.childNodes[node.childNodes.length - 1].data.sort + 1;
                } else {
                    this.menu.sort = 1;
                }
                this.dialogVisible = true;
                setTimeout(() => {
                    this.showIcon('');
                }, 100)
            },
            showEditDialog(node, data) {
                const getIconName = icon => {
                    let iconName = '';
                    if (icon) {
                        iconName = icon.replace('fas ', '').replace('fab ', '').replace('fa-', '');
                    }
                    return iconName || null;
                }
                let iconName = getIconName(data.icon);
                this.menu = {
                    id: data.id,
                    name: data.name,
                    href: data.href,
                    icon: iconName
                };
                this.icon = iconName;
                this.dialogVisible = true;
                setTimeout(() => {
                    this.showIcon(iconName);
                }, 100)
            },
            addMenu() {
                this.$refs.form.validate(valid => {
                    if (valid) {
                        this.loading = true;
                        this.$http.post({
                            url: this.menu.id ? '/sysMenu/update' : '/sysMenu/save',
                            data: this.menu
                        }).then(res => {
                            this.loading = false;
                            if (res.success) {
                                this.$message.success('添加成功')
                                this.dialogVisible = false;
                                this.getData();
                            } else {
                                this.$message.warning('添加失败')
                            }
                        })
                    }
                });
            },
            remove(node, data) {
                this.$confirm('确定删除菜单？', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'error'
                }).then(() => {
                    this.$http.post({
                        url: '/sysMenu/del',
                        data: {
                            id: data.id
                        }
                    }).then(res => {
                        if (res.success) {
                            this.$message.success('删除成功');
                            this.getData();
                        } else {
                            this.$message.error('删除失败');
                        }
                    })
                }).catch(() => {
                });
            },
            moveUp(node, data) {
                const formData = d => {
                    let formData = new FormData();
                    for (let key in d) {
                        if (d.hasOwnProperty(key)) {
                            formData.append(key, d[key]);
                        }
                    }
                    return formData;
                }
                if (node.previousSibling) {
                    axios.all([axios.post(this.$baseUrl + '/sysMenu/update', formData({
                        id: node.data.id,
                        sort: node.previousSibling.data.sort
                    })), axios.post(this.$baseUrl + '/sysMenu/update', formData({
                        id: node.previousSibling.data.id,
                        sort: node.data.sort
                    }))]).then(axios.spread((acct, perms) => {
                        this.getData();
                    }));
                }
            },
            moveDown(node, data) {
                const formData = d => {
                    let formData = new FormData();
                    for (let key in d) {
                        if (d.hasOwnProperty(key)) {
                            formData.append(key, d[key]);
                        }
                    }
                    return formData;
                }
                if (node.nextSibling) {
                    axios.all([axios.post(this.$baseUrl + '/sysMenu/update', formData({
                        id: node.data.id,
                        sort: node.nextSibling.data.sort
                    })), axios.post(this.$baseUrl + '/sysMenu/update', formData({
                        id: node.nextSibling.data.id,
                        sort: node.data.sort
                    }))]).then(axios.spread((acct, perms) => {
                        this.getData();
                    }));
                }
            },
            getData() {
                this.$http.get({
                    url: '/sysMenu/menuTree'
                }).then(res => {
                    if (res.success) {
                        this.menus = res.data
                    }
                })
            },
            renderContent(h, {node, data, store}) {
                return (
                    <span class="custom-tree-node">
                        <span>{data.name}</span>
                        <span class="url">{data.href}</span>
                        <span class="opt">
                            <el-button size="mini" type="text" on-click={ (e) => {this.moveUp(node, data), e.stopPropagation()} } class="up">上移</el-button>
                            <el-button size="mini" type="text" on-click={ (e) => {this.moveDown(node, data), e.stopPropagation()} }>下移</el-button>
                            <el-button size="mini" type="text" on-click={ (e) => {this.showEditDialog(node, data), e.stopPropagation()} }>编辑</el-button>
                            <el-button size="mini" type="text" on-click={ (e) => {this.showAddDialog(node, data), e.stopPropagation()} }>添加</el-button>
                            <el-button size="mini" type="text" on-click={ (e) => {this.remove(node, data), e.stopPropagation()} }>删除</el-button>
                        </span>
                    </span>
                );
            },
            showIcon(val) {
                if (!this.$refs.iconContainer) return;
                if (FontAwesome.icon({prefix: 'fas', iconName: val})) {
                    this.$refs.iconContainer.innerHTML = '';
                    let i = document.createElement('i');
                    i.className = 'fas fa-' + val;
                    this.$refs.iconContainer.append(i);
                    FontAwesome.dom.i2svg();
                    this.menu.icon = 'fas fa-' + val;
                } else if (FontAwesome.icon({prefix: 'fab', iconName: val})) {
                    this.$refs.iconContainer.innerHTML = '';
                    let i = document.createElement('i');
                    i.className = 'fab fa-' + val;
                    this.$refs.iconContainer.append(i);
                    FontAwesome.dom.i2svg();
                    this.menu.icon = 'fab fa-' + val;
                } else {
                    this.$refs.iconContainer.innerHTML = '';
                    let i = document.createElement('i');
                    i.className = 'fab fa-' + val;
                    this.$refs.iconContainer.append(i);
                    FontAwesome.dom.i2svg();
                    this.menu.icon = '';
                }
            }
        },
        watch: {
            icon(val) {
                this.showIcon(val);
            }
        }
    }
</script>
<style lang="less">
    .custom-tree-node {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        font-size: 14px;
        padding-right: 8px;
        .url {
            flex-grow: 1;
            text-align: right;
            margin-right: 20px;
            color: #999;
        }
        .opt {
            opacity: 0;
        }
    }

    .custom-tree-node:hover {
        .opt {
            opacity: 1;
        }
    }

    .available-icons {
        color: #409EFF;
        text-decoration: none;
        &:hover {
            color: #409EFF;
            text-decoration: none;
        }
    }
</style>
