<template>
    <ap-container>
        <ap-aside margin="1111" width="250px">
            <div class="layout-aside-header">
                <div class="layout-aside-header-title">功能角色</div>
                <div class="layout-aside-header-icon">
                    <i class="el-icon-plus" @click="addRole"/>
                    <i class="el-icon-edit-outline" @click="editRole"/>
                    <i class="el-icon-delete" @click="deleteRole"/>
                    <el-popover ref="popoverRef" placement="bottom" trigger="click">
                        <el-button-group>
                            <el-button type="primary" icon="el-icon-top" @click="doSortChange('prev')">上移
                            </el-button>
                            <el-button type="primary" icon="el-icon-bottom" @click="doSortChange('next')">下移
                            </el-button>
                            <el-button type="primary" icon="el-icon-s-operation" @click="sortByIndex">一键排序
                            </el-button>
                        </el-button-group>
                        <i class="el-icon-sort" slot="reference"/>
                    </el-popover>
                </div>
            </div>
            <div>
                <el-input placeholder="关键字过滤" v-model="treeFilterText"></el-input>
            </div>
            <div class="layout-aside-content" v-loading="loadingTreeFlag">
                <el-tree
                    ref="tSysRoleTree"
                    node-key="fdId"
                    :data="treeData"
                    :props="{children: 'children',label: 'fdName'}"
                    default-expand-all
                    :check-on-click-node="true"
                    :highlight-current="true"
                    :expand-on-click-node="false"
                    :check-strictly="false"
                    :filter-node-method="filterTreeNode"
                    @node-click="clickTreeEvent">
                    <div slot-scope="{ node, data }">
                        <div v-if="data.fdIsGroup == 1" class="tree-node">
                            <span style="color: #2e6d91">{{data.fdName}}</span>
                        </div>
                        <div v-else class="tree-node ap-ellipse">
                            <span style="color: #1890FF"><i class="el-icon-s-custom"/>&nbsp;{{data.fdName}}</span>
                        </div>
                    </div>
                </el-tree>
            </div>
        </ap-aside>
        <ap-split-panel></ap-split-panel>
        <ap-container>
            <ap-main margin="1110" style="padding: 0px;">
                <ap-container>
                    <ap-aside style="border-right: 1px dashed #cccccc;" width="33%">
                        <div class="layout-aside-header">
                            <div class="layout-aside-header-title">应用列表{{selectedRoleName}}</div>
                            <i class="el-icon-supervise" v-if="checkPermission('SYS-FUNCTION-SECRET')"  @click="secretDialogVisible = true"/>
                        </div>
                        <div class="layout-aside-content">
                            <el-tree
                                ref="functionTypeTree"
                                node-key="fdId"
                                :data="functionTypeData"
                                :default-checked-keys="functionTypeCheckedKeys"
                                :props="{children: 'children',label: 'fdName'}"
                                default-expand-all
                                show-checkbox
                                :check-on-click-node="false"
                                :highlight-current="true"
                                :expand-on-click-node="false"
                                :check-strictly="true"
                                @node-click="clickFunctionTypeTreeEvent"
                                @check-change="checkFunctionTypeTreeEvent"
                            >
                            </el-tree>
                        </div>
                    </ap-aside>

                    <ap-aside style="border-right: 1px dashed #cccccc;" width="33%">
                        <div class="layout-aside-header">
                            <div class="layout-aside-header-title">菜单列表{{selectedFunctionTypeName}}</div>
                        </div>
                        <div>
                            <el-input placeholder="关键字过滤" v-model="menuTreeFilterText"></el-input>
                        </div>
                        <div class="layout-aside-content">
                            <el-tree
                                ref="menuTree"
                                node-key="fdId"
                                :data="menuTreeData"
                                :default-checked-keys="menuCheckedKeys"
                                :props="{children: 'children',label: 'fdName'}"
                                default-expand-all
                                show-checkbox
                                :check-on-click-node="false"
                                :highlight-current="true"
                                :expand-on-click-node="false"
                                :check-strictly="true"
                                :filter-node-method="filterMenuTreeNode"
                                @node-click="clickMenuTreeEvent"
                                @check-change="checkMenuTreeEvent">
                            </el-tree>
                        </div>
                    </ap-aside>
                    <ap-main>
                        <div class="tree-title">功能权限{{selectedMenuName}}</div>
                        <el-tree
                            ref="functionTree"
                            node-key="fdId"
                            :data="functionTreeData"
                            :default-checked-keys="functionCheckedKeys"
                            :props="{children: 'children',label: 'fdName'}"
                            default-expand-all
                            show-checkbox
                            :check-on-click-node="true"
                            :highlight-current="true"
                            :expand-on-click-node="false"
                            :check-strictly="false"
                            @check-change="checkMenuTreeEvent">
                        </el-tree>

                    </ap-main>
                </ap-container>
            </ap-main>
        </ap-container>
        <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="350px">
            <el-form ref="dialogForm"
                     :inline="true"
                     :model="dialogForm" :rules="dialogFormRules" label-width="80px">
                <el-form-item label="父节点">
                    <el-select v-model="dialogForm.fdParentId" filterable placeholder="请选择父节点">
                        <el-option label="无" value=""></el-option>
                        <el-option
                            v-for="item in roleGroupList"
                            :key="item.fdId"
                            :label="item.fdName"
                            :value="item.fdId">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="名称" prop="fdName">
                    <el-input v-model="dialogForm.fdName"></el-input>
                </el-form-item>
                <el-form-item label="分组">
                    <el-radio v-model="dialogForm.fdIsGroup" :label="1">是</el-radio>
                    <el-radio v-model="dialogForm.fdIsGroup" :label="0">否</el-radio>
                </el-form-item>
                <el-form-item label="排序" prop="fdSort">
                    <el-input-number v-model="dialogForm.fdSort" controls-position="right"></el-input-number>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="saveDialog" :loading="saveDialogLoadingFlag">确 定</el-button>
            </span>
        </el-dialog>
        <el-dialog title="加密应用" :visible.sync="secretDialogVisible" width="350px">
            <el-input v-model="secretCode" placeholder="密文" show-password></el-input>
            <span slot="footer" class="dialog-footer">
                <el-button @click="secretDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="showSecret" >确 定</el-button>
            </span>
        </el-dialog>
    </ap-container>
</template>

<script>
import {convertToTreeData} from 'ap-util/util/DataUtil'
import {getNodeByCurrent, getSortListByIndex} from 'ap-util/util/TreeUtil'
import md5 from "js-md5";
import {hasPermission} from "ap-util/util/LoginUserUtil";

export default {
    name: 'SysRoleFunction',
    data() {
        return {
            // ----- 左侧树 -----
            loadingTreeFlag: false,
            saveDialogLoadingFlag: false,
            dialogVisible: false,
            dialogTitle: '',
            isAddDialog: true,
            treeFilterText: '',
            treeData: [],
            roleGroupList: [],
            selectedRoleId: "",
            selectedRoleName: '',
            dialogForm: {
                fdId: '',
                fdName: '',
                fdIsGroup: 0,
                fdParentId: '',
                fdSort: 0,
                fdType: 0,
            },

            dialogFormRules: {
                fdName: [
                    {required: true, message: '请输角色名称', trigger: 'blur'},
                    {min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'blur'}
                ],
            },
            secretDialogVisible: false,
            secretCode: '',
            // ----- 右侧 -----
            functionTypeData: [],
            functionTypeCheckedKeys: [],
            selectedFunctionTypeName: '',
            selectedFunctionTypeId: '',
            menuTreeFilterText: '',
            menuTreeData: [],
            menuCheckedKeys: [],
            selectedMenuName: '',
            selectedMenuId: '',
            functionTreeData: [],
            functionCheckedKeys: [],
        }
    },
    watch: {
        treeFilterText(val) {
            // 过滤值修改，更新tree
            this.$refs.tSysRoleTree.filter(val);
        },
        menuTreeFilterText(val) {
            this.$refs.menuTree.filter(val);
        }
    },
    created() {
        this.loadTreeData();
    },
    methods: {
        // 左侧树：加载数据
        loadTreeData() {
            this.loadingTreeFlag = true;
            // 加载数据
            this.$request({
                url: '/apm/sys/TSysRole/getTSysRoleList',
                method: 'post',
                data: {
                    type: 0
                }
            }).then(response => {
                let res = response.data;
                // 数据格式转换：数组 -> tree
                this.treeData = convertToTreeData(res, {
                    idKey: "fdId",
                    parentKey: "fdParentId",
                    childrenKey: "children",
                });

                let roleGroupList = [];
                for (let i = 0; i < res.length; i++) {
                    if (res[i].fdIsGroup == 1) {
                        roleGroupList.push(res[i]);
                    }
                }
                this.roleGroupList = roleGroupList;
            }).finally(() => {
                this.loadingTreeFlag = false;
            })
        },
        // 左侧树：重新加载数据
        reLoadTreeData() {
            // 重置当前选择节点
            this.$refs.tSysRoleTree.setCurrentKey();
            this.loadTreeData();
        },
        // 左侧树：过滤节点
        filterTreeNode(value, data) {
            if (!value) return true;
            return data.fdName.indexOf(value) !== -1;
        },
        // 左侧树：click事件
        clickTreeEvent(data, node, comp) {
            this.selectedRoleName = ` -【${data.fdName}】`;
            this.selectedRoleId = data.fdId;
            if (data.fdIsGroup == 1) return;
            this.resetFunctionTypeTree();
            this.resetMenuTree();
            this.resetFunctionTree();
            this.loadFunctionTypeData();
        },
        //重置表单数据
        resetDialogForm() {
            this.dialogForm = {
                fdId: '',
                fdName: '',
                fdIsGroup: 0,
                fdParentId: '',
                fdSort: 0,
                fdType: 0,
            };
        },
        // 获取树的节点信息
        getCurrentNode() {
            return this.$refs.tSysRoleTree.getCurrentNode() || {}
        },
        // dialog：添加数据
        addRole() {
            let currentNodeFdId = this.getCurrentNode().fdId;
            this.resetDialogForm();
            this.dialogVisible = true;
            this.dialogTitle = '添加角色';
            this.isAddDialog = true;
            this.dialogForm.fdParentId = currentNodeFdId;
        },

        // dialog：编辑数据
        editRole() {
            let currentNodeFdId = this.getCurrentNode().fdId;
            if (!currentNodeFdId) {
                this.$message.error('请选择需要编辑的数据！');
                return
            }

            this.resetDialogForm();
            this.dialogVisible = true;
            this.dialogTitle = '编辑角色';
            this.isAddDialog = false;
            this.dialogForm.fdId = currentNodeFdId;

            this.$request({
                url: '/apm/sys/TSysRole/getTSysRoleByFdId',
                method: 'post',
                data: {
                    fdId: currentNodeFdId
                }
            }).then(response => {
                this.dialogForm.fdId = response.data.fdId;
                this.dialogForm.fdParentId = response.data.fdParentId;
                this.dialogForm.fdName = response.data.fdName;
                this.dialogForm.fdIsGroup = response.data.fdIsGroup;
                this.dialogForm.fdSort = response.data.fdSort;
            })
        },
        deleteRole() {
            let currentNode = this.getCurrentNode();
            let currentNodeFdId = currentNode.fdId;
            if (!currentNodeFdId) {
                this.$message.error('请选择需要删除的数据！');
                return
            }

            this.$confirm(`确定要删除【${currentNode.fdName}】?`, '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.$request({
                    url: '/apm/sys/TSysRole/updateTSysRoleForDelete',
                    method: 'post',
                    data: {
                        fdId: currentNodeFdId
                    }
                }).then(response => {
                    this.$message.success(`删除成功！已删除${response.data}条数据！`);
                    this.loadTreeData();
                })
            })
        },
        saveDialog() {
            this.saveDialogLoadingFlag = true;
            this.$refs.dialogForm.validate((valid) => {
                if (!valid) {
                    this.$message.error(`数据校验失败，请重新填写信息！`);
                    return false;
                }

                if (this.isAddDialog) {
                    // 添加数据
                    this.$request({
                        url: '/apm/sys/TSysRole/insertTSysRole',
                        method: 'post',
                        data: this.dialogForm
                    }).then(response => {
                        this.$message.success(`添加成功！已添加${response.data}条数据！`)
                        this.dialogVisible = false;
                        this.reLoadTreeData();
                    }).finally(() => {
                        this.saveDialogLoadingFlag = false;
                    })
                } else {
                    // 更新数据
                    this.$request({
                        url: '/apm/sys/TSysRole/updateTSysRole',
                        method: 'post',
                        data: this.dialogForm
                    }).then(response => {
                        this.$message.success(`更新成功！已更新${response.data}条数据！`)
                        this.dialogVisible = false;
                        this.reLoadTreeData();
                    }).finally(() => {
                        this.saveDialogLoadingFlag = false;
                    })
                }
            });
        },
        showSecret() {
            this.secretDialogVisible = false;
            this.loadFunctionTypeData();
        },
        checkPermission(code) {
            return hasPermission(code);
        },
        // 修改排序
        doSortChange(type) {
            let currentNode = this.getCurrentNode();
            if (!currentNode.fdId) {
                this.$message.error(`请选择需要操作的节点！`);
                return;
            }
            let exchangeNode = getNodeByCurrent(this.$refs.tSysRoleTree, type);
            if (exchangeNode == null) {
                this.$message.error(`无需排序！`);
                return;
            }

            this.$request({
                url: '/apm/sys/TSysRole/updateRoleSort',
                method: 'post',
                data: {
                    rowFdId: currentNode.fdId,
                    rowFdSort: exchangeNode.fdSort,
                    exchangeRowFdId: exchangeNode.fdId,
                    exchangeRowFdSort: currentNode.fdSort
                }
            }).then(response => {
                this.$message.success(`修改成功！`)
                this.$refs.popoverRef.doClose();
                this.loadTreeData();
            })
        },
        // 一键排序
        sortByIndex() {
            let list = getSortListByIndex(this.$refs.tSysRoleTree.data);
            this.$request({
                url: '/apm/sys/TSysRole/updateRoleSortList',
                method: 'post',
                data: {list: JSON.stringify(list)}
            }).then(response => {
                this.$message.success(`排序成功！`)
                this.$refs.popoverRef.doClose();
                this.loadTreeData();
            })
        },
        clickFunctionTypeTreeEvent(data, node, comp) {
            this.resetMenuTree();
            this.resetFunctionTree();
            this.selectedFunctionTypeName = ` -【${data.fdName}】`;
            this.selectedFunctionTypeId = data.fdId;
            this.loadMenuTreeData();

            // 功能权限
            this.loadFunctionTreeData();
        },
        checkFunctionTypeTreeEvent(data, checked, indeterminate) {
            if (checked) {
                this.addRoleFunction( "functionType", data.fdId)
            } else {
                this.deleteRoleFunction( "functionType", data.fdId)
            }
        },
        loadFunctionTypeData() {
            this.functionTypeData = [];
            let code = "";
            if (this.secretCode != null && this.secretCode != '') {
                code = md5(this.secretCode);
            }
            this.$request({
                url: '/apm/sys/TSysRole/getSysFunctionTypeList',
                method: 'post',
                data: {
                    roleId: this.selectedRoleId,
                    secretCode: code
                }
            }).then(response => {
                let functionTypeList = response.data.functionTypeList;
                this.functionTypeData = convertToTreeData(functionTypeList, {});
                this.functionTypeCheckedKeys = response.data.roleFunctionTypeList;
            })
        },

        filterMenuTreeNode(value, data) {
            if (!value) return true;
            return data.fdName.indexOf(value) !== -1;
        },
        clickMenuTreeEvent(data, node, comp) {
            this.selectedMenuName = ` -【${data.fdName}】`;
            this.selectedMenuId = data.fdId;
            this.resetFunctionTree();
            this.loadFunctionTreeData();
        },
        checkMenuTreeEvent(data, checked, indeterminate) {
            if (checked) {
                this.addRoleFunction( "function", data.fdId)
            } else {
                this.deleteRoleFunction( "function", data.fdId)
            }
        },
        loadMenuTreeData() {
            this.menuTreeData = [];
            this.$request({
                url: '/apm/sys/TSysRole/getSysRoleMenuList',
                method: 'post',
                data: {
                    roleId: this.selectedRoleId,
                    functionTypeId: this.selectedFunctionTypeId
                }
            }).then(response => {
                let menuList = response.data.menuList;
                this.menuTreeData = convertToTreeData(menuList, {});
                this.menuCheckedKeys = response.data.roleMenuList;
            })
        },
        loadFunctionTreeData() {
            this.functionTreeData = [];
            this.$request({
                url: '/apm/sys/TSysRole/getSysRoleFunctionList',
                method: 'post',
                data: {
                    roleId: this.selectedRoleId,
                    parentId: this.selectedMenuId,
                    functionTypeId: this.selectedFunctionTypeId
                }
            }).then(response => {
                this.functionTreeData = response.data.functionList;
                this.functionCheckedKeys = response.data.roleFunctionList;
            })
        },
        addRoleFunction(type, id) {
            this.$request({
                url: '/apm/sys/TSysRole/addRoleFunction',
                method: 'post',
                data: {
                    roleId: this.selectedRoleId,
                    type: type,
                    id: id
                }
            }).then(response => {
                this.$notify({
                    title: '自动保存成功',
                    type: 'success'
                });
            })
        },
        deleteRoleFunction(type, id) {
            this.$request({
                url: '/apm/sys/TSysRole/deleteRoleFunction',
                method: 'post',
                data: {
                    roleId: this.selectedRoleId,
                    type: type,
                    id: id
                }
            }).then(response => {
                this.$notify({
                    title: '自动保存成功',
                    type: 'success'
                });
            })
        },
        resetFunctionTypeTree(){
            this.functionTypeData = [];
            this.functionTypeCheckedKeys = [];
            this.selectedFunctionTypeName = '';
            this.selectedFunctionTypeId = '';
        },
        resetMenuTree(){
            this.menuTreeData = [];
            this.menuCheckedKeys = [];
            this.selectedMenuName = '';
            this.selectedMenuId = '';
        },
        resetFunctionTree(){
            this.functionTreeData = [];
            this.functionCheckedKeys = [];
        }

    }
}
</script>

<style scoped>
.tree-node {
    font-size: 14px;
}

.tree-title {
    font-weight: bold;
    font-size: 14px;
    line-height: 32px;
    border-bottom: 1px solid #cccccc;
    padding: 2px 10px;
}
.layout-aside-content /deep/ .el-tree-node__content {
    height: 20px;
}
</style>
