<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <base th:href="${#request.getContextPath() + '/'}">
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="assets/easyui/themes/default/easyui.css"/>
    <link rel="stylesheet" href="assets/js/vendor/zTree3/css/metroStyle/metroStyle.css"/>
    <link rel="stylesheet" href="assets/js/vendor/codemirror/codemirror.css" media="all">
    <link rel="stylesheet" href="assets/js/vendor/codemirror/addon/hint/show-hint.css"/>
    <link rel="stylesheet" href="assets/css/query-easyui.css"/>
</head>
<body>
<div id="app" class="easyui-layout">
    <div id="appTop" data-options="region:'north',split:false" style="height:35px;">
        <div id="connectionBtnBox" class="layui-btn-group">
            <button id="connectionBtn" class="layui-btn layui-btn-xs">打开连接</button>
            <button id="closeConnectionBtn" class="layui-btn layui-btn-xs layui-btn-danger">关闭连接</button>
        </div>
    </div>
    <div id="appLeft" data-options="region:'west',split:true" style="width:200px;">
        <ul id="leftTree" class="ztree"></ul>
    </div>
    <div id="appCenter" data-options="region:'center'">
        <div id="mainTab" class="easyui-tabs" data-options="border:false" style="visibility: hidden;">
            <div title="首页" data-options="border:false">
                <div id="queryTopBox">
                    <div id="queryTopOptionBox">
                        <button id="executeSqlBtn" class="layui-btn layui-btn-xs">运行</button>
                    </div>
                    <textarea id="queryTopTextarea"></textarea>
                </div>
                <div id="queryResultTab" class="easyui-tabs" data-options="border:false"></div>
            </div>
        </div>
    </div>
</div>
<div id="zTreeSchemataRightMenu">
    <ul>
        <li id="openSchemataBtn">打开</li>
        <li id="closeSchemataBtn" style="display: none;">关闭</li>
        <li id="refreshSchemataBtn" style="display: none;">刷新</li>
    </ul>
</div>
<script src="assets/js/vendor/codemirror/codemirror.js"></script>
<script src="assets/js/vendor/codemirror/mode/sql/sql.js"></script>
<script src="assets/js/vendor/codemirror/addon/hint/show-hint.js"></script>
<script src="assets/js/vendor/codemirror/addon/hint/sql-hint.js"></script>
<script src="assets/js/vendor/codemirror/addon/selection/active-line.js"></script>
<script src="assets/js/vendor/codemirror/addon/display/placeholder.js"></script>
<script src="assets/js/jquery-3.5.1.min.js"></script>
<script src="assets/js/vendor/zTree3/js/jquery.ztree.all.js"></script>
<script src="assets/easyui/jquery.easyui.min.js"></script>
<script src="assets/easyui/locale/easyui-lang-zh_CN.js"></script>
<script>
    var mysqlId = top.restAjax.params(window.location.href).mysqlId;
    function EasyUI(option) {
        this.el = option.el;
        this.mounted = option.mounted;
        if(option.data) {
            for(var k in option.data) {
                this[k] = option.data[k];
            }
        }
        if(option.methods) {
            for(var k in option.methods) {
                this[k] = option.methods[k];
            }
        }
    }
    var easyUI = new EasyUI({
        el: '#app',
        data: {
            win: $(window),
            zTree: null,

            rightSelectedTreeNode: null,
            queryTopEditor: null,
            queryTopEditorSqlTables: {},
            queryResultTable: null,
            queryResultTabs: []
        },
        methods: {
            initLayout: function() {
                var self = this;
                $('#app').css({width: self.win.width() +'px', height: self.win.height() +'px'});
                $('#mainTab').css({width: '100%', height: '100%'});
            },
            getTabByTitle: function(title) {
                return $('#mainTab').tabs('getTab', title);
            },
            // 更新tab内容
            updateTabContent: function(tabId, tab, content) {
                $(tabId).tabs('update', {
                    tab: tab,
                    options: {
                        content: content
                    }
                })
            },
            // 清空tab
            clearTabs: function(tabId, tabTitleArray) {
                for(var i = 0, tabTitle; tabTitle = tabTitleArray[i++];) {
                    $(tabId).tabs('close', tabTitle);
                }
                tabTitleArray = [];
            },
            // 执行的SQL列表，目前只去最后一条非空内容
            listExecuteSql: function(sqlContent) {
                var sqlArray = sqlContent.split(';');
                var executeSql = [];
                for(var i = 0, sql; sql = sqlArray[i++];) {
                    if(!sql) {
                        break;
                    }
                    if(!sql.replace(/\s+/g, '')) {
                        break;
                    }
                    executeSql.push(sql);
                }
                return executeSql;
            },
            // 初始化查询结果
            initSqlQueryResult: function(tabIndex, tab, sql, data, page, size) {
                var self = this;
                // 查询
                var cols = [];
                var datas = [];
                for(var i = 0, item; item = data.rows[i++];) {
                    if(i === 1) {
                        for(var k in item) {
                            cols.push({
                                field: k,
                                title: k
                            })
                        }
                    }
                    datas.push(item);
                }
                var dataGridId = 't_result_'+ tabIndex;
                self.updateTabContent('#queryResultTab', tab, '<table id="'+ dataGridId +'"></table>');
                $('#'+ dataGridId).datagrid({
                    columns:[cols],
                    data: datas,
                    width: (self.win.width() - 205) +'px',
                    height: (self.win.height() / 2 - 24)+'px',
                    selectOnCheck: true,
                    rownumbers: true,
                    pagination: true,
                });
                var pager = $('#'+ dataGridId).datagrid('getPager');
                pager.pagination({
                    total: data.total,
                    pageSize: size,
                    pageNumber: page,
                    pageList:  [20, 40, 60, 80, 100, 200],
                    onSelectPage: function(pageNumber, pageSize) {
                        self.initExecuteResult(tabIndex, sql, pageNumber, pageSize)
                    },
                    onChangePageSize: function(pageSize) {
                        self.initExecuteResult(tabIndex, sql, page, pageSize)
                    }
                });
            },
            // 初始化执行结果
            initExecuteResult: function(tabIndex, sql, page, size) {
                var self = this;
                var tab = $('#queryResultTab').tabs('getTab', '结果'+ tabIndex);
                page = page ? page : 1;
                size = size ? size : 20;
                top.restAjax.post(top.restAjax.path('api/mysql/jdbc/execute-sql/{mysqlId}?page={page}&size={size}', [mysqlId, page, size]), {
                    sql: sql
                }, {
                    tabIndex: tabIndex
                }, function(code, data, args) {
                    if(data.rows) {
                        self.initSqlQueryResult(args.tabIndex, tab, sql, data, page, size);
                    } else {
                        // 更新
                        self.updateTabContent('#queryResultTab', tab, '执行成功');
                    }
                }, function(code, data) {
                    self.updateTabContent('#queryResultTab', tab, data.msg);
                }, function() {
                    self.updateTabContent('#queryResultTab', tab, '正在请求...');
                }, function() {
                    // self.updateTabContent('#queryResultTab', tab, '请求成功');
                });
            },
            // 执行SQL
            executeSql: function() {
                var self = this;
                var sqlContnt = self.queryTopEditor.getValue();
                var executeSqlArray = self.listExecuteSql(sqlContnt);
                self.clearTabs('#queryResultTab', self.queryResultTabs);
                for(var i = 0, sql; sql = executeSqlArray[i++];) {
                    $('#queryResultTab').tabs('add', {
                        title: '结果'+ i,
                        closable: true,
                    });
                    self.queryResultTabs.push('结果'+ i);
                    self.initExecuteResult(i, sql);
                }
            },
            initQueryTopTextArea: function() {
                var self = this;
                self.queryTopEditor = CodeMirror.fromTextArea(document.getElementById('queryTopTextarea'), {
                    mode: 'text/x-mysql',
                    placeholder: '请输入要执行的SQL，只运行最后一条非空语句。请使用 database.table 的方式来操作具体的表',
                    indentWithTabs: true,
                    smartIndent: true,
                    lineNumbers: false,
                    matchBrackets : true,
                    autofocus: true,
                    hintOptions: {
                        completeSingle: false,
                        completeOnSingleClick: true,
                        tables: self.queryTopEditorSqlTables
                    },
                    indentUnit: 4,
                    lineWrapping: true,
                    autofocus: false,
                });
                self.queryTopEditor.setSize('auto', (self.win.height() / 2 - 115) + 'px');
                self.queryTopEditor.on("inputRead", function(value) {
                    if (!value.state.completionActive) {
                        var cursor = value.getCursor();
                        cursor = value.getTokenAt(cursor);
                        var cursorValue = '';
                        cursor.string.match(/^[.`\w@]\w*$/) && (cursorValue = cursor.string);
                        0 < cursorValue.length && CodeMirror.commands.autocomplete(value)
                    }
                });
            },
            initHomePage: function() {
                var self = this;
                $('#mainTab').css({'visibility': 'visible'});
                self.initQueryTopTextArea();
            },
            /**
             * newTableData
             * @param schemata
             * @param table
             * @param page
             * @param size
             */
            initTableData: function(schemata, table, page, size) {
                page = page ? page : 1;
                size = size ? size : 20;
                var self = this;
                var loadLayerIndex;
                top.restAjax.get(top.restAjax.path('api/mysql/jdbc/listpage-data/{mysqlId}/{schemata}/{table}', [mysqlId, schemata, table]), {
                    page: page,
                    size: size
                }, null, function(code, data) {
                    var cols = [];
                    var datas = [];
                    for(var i = 0, item; item = data.rows[i++];) {
                        if(i === 1) {
                            for(var k in item) {
                                cols.push({
                                    field: k,
                                    title: k
                                })
                            }
                        }
                        datas.push(item);
                    }

                    var dataGridId = '#t_'+ schemata +'_'+ table;
                    $(dataGridId).datagrid({
                        columns:[cols],
                        data: datas,
                        height: (self.win.height() - 72)+'px',
                        selectOnCheck: true,
                        rownumbers: true,
                        pagination: true,
                    });
                    var pager = $(dataGridId).datagrid('getPager');
                    pager.pagination({
                        total: data.total,
                        pageSize: size,
                        pageNumber: page,
                        pageList:  [20, 40, 60, 80, 100, 200],
                        onSelectPage: function(pageNumber, pageSize) {
                            self.initTableData(schemata, table, pageNumber, pageSize)
                        },
                        onChangePageSize: function(pageSize) {
                            self.initTableData(schemata, table, page, pageSize)
                        }
                    });
                }, function(code, data) {
                    top.dialog.msg(data.msg);
                }, function() {
                    loadLayerIndex = top.dialog.msg(top.dataMessage.loading, {icon: 16, time: 0, shade: 0.3});
                }, function() {
                    top.dialog.close(loadLayerIndex);
                });
            },
            /**
             * 初始化表
             * @param schemataTreeNode
             */
            initTable: function(schemataTreeNode) {
                var self = this;
                var loadLayerIndex;
                top.restAjax.get(top.restAjax.path('api/mysql/jdbc/list-table/{mysqlId}/{schemata}', [mysqlId, schemataTreeNode.id]), {}, null, function(code, data) {
                    self.zTree.removeChildNodes(schemataTreeNode);
                    var tableTreeNodes = [];
                    for(var i = 0, item; item = data[i++];) {
                        self.queryTopEditorSqlTables[schemataTreeNode.id].push(item.TABLE_NAME);
                        self.queryTopEditorSqlTables[item.TABLE_NAME] = [];
                        tableTreeNodes.push({
                            id: item.TABLE_NAME,
                            name: item.TABLE_NAME,
                            pId: schemataTreeNode.id,
                            nodeType: 'table',
                            icon: 'assets/images/tree/tree-table.png'
                        });
                    }
                    self.zTree.addNodes(schemataTreeNode, tableTreeNodes);
                }, function(code, data) {
                    top.dialog.msg(data.msg);
                }, function() {
                    loadLayerIndex = top.dialog.msg(top.dataMessage.loading, {icon: 16, time: 0, shade: 0.3});
                }, function() {
                    top.dialog.close(loadLayerIndex);
                });
            },
            /**
             * 显示数据库右键菜单
             * @param treeNode
             * @param x
             * @param y
             */
            showZTreeSchemataRightMenu: function(treeNode, x, y) {
                var self = this;
                self.rightSelectedTreeNode = treeNode;
                if(treeNode.children) {
                    $("#openSchemataBtn").hide();
                    $("#closeSchemataBtn").show();
                    $("#refreshSchemataBtn").show();
                } else {
                    $("#openSchemataBtn").show();
                    $("#closeSchemataBtn").hide();
                    $("#refreshSchemataBtn").hide();
                }
                y += document.body.scrollTop;
                x += document.body.scrollLeft;
                $('#zTreeSchemataRightMenu').css({'top': y +'px', 'left': x + 'px', 'visibility': 'visible'});
            },
            /**
             * 隐藏数据库右键菜单
             */
            hideZTreeSchemataRightMenu: function() {
                this.rightSelectedTreeNode = null;
                $('#zTreeSchemataRightMenu').css('visibility', 'hidden');
                $(document.body).unbind('mousedown');
            },
            /**
             * 初始化树
             */
            initThree: function() {
                var self = this;
                var setting = {
                    async: {
                        enable: true,
                        autoLoad: true,
                        type: 'get',
                        url: top.restAjax.path('api/mysql/jdbc/list-schemata/{mysqlId}', [mysqlId]),
                        autoParam: ['id'],
                        otherParam: {},
                        dataFilter: function (treeId, parentNode, childNodes) {
                            if (!childNodes) return null;
                            for(var i = 0, item; item = childNodes[i++];) {
                                self.queryTopEditorSqlTables[item.SCHEMA_NAME] = [];
                                item.id = item.SCHEMA_NAME;
                                item.name = item.SCHEMA_NAME;
                                item.pId = '0';
                                item.url = 'javascript:void(0);';
                                item.icon = 'assets/images/tree/tree-database.png';
                                item.nodeType = 'schemata';
                            }
                            return childNodes;
                        }
                    },
                    callback: {
                        onClick: function (event, treeId, treeNode) {
                            if(!treeNode) {
                                return;
                            }
                            // 数据库单点无效
                            if(treeNode.nodeType == 'schemata') {
                                return;
                            }
                            var tab = self.getTabByTitle(treeNode.id);
                            // 添加tab
                            if(!tab) {
                                $('#mainTab').tabs('add', {
                                    title: treeNode.id,
                                    content:'<table id="t_'+ treeNode.pId +'_'+ treeNode.id +'"></table>',
                                    closable: true,
                                });
                            } else {
                                $('#mainTab').tabs('select', treeNode.id);
                            }
                            self.initTableData(treeNode.pId, treeNode.id);
                            return false;
                        },
                        onDblClick: function(event, treeId, treeNode) {
                            if(!treeNode) {
                                return;
                            }
                            // 表双点无效
                            if(treeNode.nodeType == 'table') {
                                return;
                            }
                            self.initTable(treeNode);
                            return false;
                        },
                        onRightClick: function(event, treeId, treeNode) {
                            if(!treeNode) {
                                return;
                            }
                            // 表右键无效
                            if(treeNode.nodeType == 'table') {
                                return;
                            }
                            self.showZTreeSchemataRightMenu(treeNode, event.clientX, event.clientY);
                        }
                    },
                };
                self.zTree = $.fn.zTree.init($("#leftTree"), setting);
            },
            // 关闭连接
            closeConnection: function() {
                var loadLayerIndex;
                $('#closeConnectionBtn').hide();
                top.restAjax.get(top.restAjax.path('api/mysql/jdbc/close-connection/{mysqlId}', [mysqlId]), {}, null, function(code, data) {
                    window.location.reload();
                }, function(code, data) {
                    $('#closeConnectionBtn').show();
                    top.dialog.msg(data.msg);
                }, function() {
                    loadLayerIndex = top.dialog.msg(top.dataMessage.loading, {icon: 16, time: 0, shade: 0.3});
                }, function() {
                    top.dialog.close(loadLayerIndex);
                });
            },
            // 打开连接
            openConnection: function(callback) {
                var loadLayerIndex;
                $('#connectionBtn').hide();
                top.restAjax.get(top.restAjax.path('api/mysql/jdbc/open-connection/{mysqlId}', [mysqlId]), {}, null, function(code, data) {
                    $('#closeConnectionBtn').show();
                    callback();
                }, function(code, data) {
                    $('#connectionBtn').show();
                    top.dialog.msg(data.msg);
                }, function() {
                    loadLayerIndex = top.dialog.msg(top.dataMessage.loading, {icon: 16, time: 0, shade: 0.3});
                }, function() {
                    top.dialog.close(loadLayerIndex);
                });
            },
            // 是否连接
            isConnected: function(callback) {
                var loadLayerIndex;
                top.restAjax.get(top.restAjax.path('api/mysql/jdbc/is-connected/{mysqlId}', [mysqlId]), {}, null, function(code, data) {
                    if(!data.data) {
                        $('#connectionBtn').show();
                        return;
                    }
                    $('#closeConnectionBtn').show();
                    callback();
                }, function(code, data) {
                    $('#connectionBtn').show();
                    top.dialog.msg(data.msg);
                }, function() {
                    loadLayerIndex = top.dialog.msg(top.dataMessage.loading, {icon: 16, time: 0, shade: 0.3});
                }, function() {
                    top.dialog.close(loadLayerIndex);
                });
            }
        },
        mounted: function() {
            var self = this;
            self.initLayout();
            self.isConnected(function() {
                self.initThree();
                self.initHomePage();
            });
            $('#connectionBtn').on('click', function() {
                self.openConnection(function() {
                    self.initThree();
                    self.initHomePage();
                });
            });
            $('#closeConnectionBtn').on('click', function() {
                self.closeConnection();
            });
            $('#openSchemataBtn').on('click', function() {
                self.initTable(self.rightSelectedTreeNode);
                self.hideZTreeSchemataRightMenu();
            })
            $('#closeSchemataBtn').on('click', function() {
                self.zTree.removeChildNodes(self.rightSelectedTreeNode);
                self.hideZTreeSchemataRightMenu();
            })
            $('#refreshSchemataBtn').on('click', function() {
                self.initTable(self.rightSelectedTreeNode);
                self.hideZTreeSchemataRightMenu();
            })
            $(self.el).on('click', function() {
                self.hideZTreeSchemataRightMenu();
            })
            $('#executeSqlBtn').on('click', function() {
                self.executeSql();
            })
        }
    })

    easyUI.mounted();
</script>
</body>
</html>