<!DOCTYPE html>
<html>

<head>
    <title>LyApi Coder 在线代码编辑器</title>

    <link rel="stylesheet" href="{{domain}}/resource/admin/mini/lib/layui-v2.5.5/css/layui.css" media="all">

    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="{{domain}}/resource/admin/mini/lib/layui-v2.5.5/layui.js" charset="utf-8"></script>

    <script src="https://cdn.bootcss.com/mousetrap/1.6.3/mousetrap.min.js"></script>

    <script src="https://cdn.bootcss.com/ace/1.4.8/ace.js"></script>
    <script src="https://cdn.bootcss.com/ace/1.4.8/ext-beautify.js"></script>
    <script src="https://cdn.bootcss.com/ace/1.4.8/ext-language_tools.js"></script>
    <style>
        #editor {
            position: absolute;
            width: 100%;
            height: 100%;
        }

        /*滚动条的宽度*/

        ::-webkit-scrollbar {
            width: 9px;
            height: 9px;
        }

        /*外层轨道。可以用display:none让其不显示，也可以添加背景图片，颜色改变显示效果*/

        ::-webkit-scrollbar-track {
            width: 6px;
            background-color: #0d1b20;
            -webkit-border-radius: 2em;
            -moz-border-radius: 2em;
            border-radius: 2em;
        }

        /*滚动条的设置*/

        ::-webkit-scrollbar-thumb {
            background-color: #606d71;
            background-clip: padding-box;
            min-height: 28px;
            -webkit-border-radius: 2em;
            -moz-border-radius: 2em;
            border-radius: 2em;
        }

        /*滚动条移上去的背景*/

        ::-webkit-scrollbar-thumb:hover {
            background-color: #fff;
        }
    </style>
</head>

<body style="background-color: #393D49;">

    <div class="layui-layout layui-layout-admin">
        <div class="layui-header">
            <div class="layui-logo">LyApi Coder</div>
            <ul class="layui-nav layui-layout-left">
                <li class="layui-nav-item">
                    <a href="javascript:;">编辑器设置</a>
                    <dl class="layui-nav-child">
                        <dd><a href="javascript:;" id="changeTheme">切换样式</a></dd>
                        <dd><a href="javascript:;" id="changeLanguage">切换语言</a></dd>
                    </dl>
                </li>
                <li class="layui-nav-item">
                    <a href="javascript:;">文件设置</a>
                    <dl class="layui-nav-child">
                        <dd><a href="javascript:;" id="saveFile">保存文件</a></dd>
                    </dl>
                </li>
                <li class="layui-nav-item">
                    <a href="javascript:;" id="coder-open">命令行</a>
                </li>
            </ul>
            <ul class="layui-nav layui-layout-right">
                <li class="layui-nav-item">
                    <a href="javascript:;">当前文件:
                        {{# nowfile}}
                        <span id="filename">{{nowfile}}</span>
                        {{/ nowfile}}

                        {{^ nowfile}}
                        <span id="filename">welcome.md</span>
                        {{/ nowfile}}
                    </a>
                </li>
            </ul>
        </div>

        <div class="layui-side layui-bg-black">
            <div class="layui-side-scroll" style="background-color: #23262E;">
                <!-- 左侧导航区域（可配合layui已有的垂直导航） -->


                <!-- 当用户已登录 -->
                {{# islogin}}
                <ul class="layui-nav layui-nav-tree" lay-filter="test">
                    <li class="layui-nav-item layui-nav-itemed">
                        <a class="" href="javascript:;">接口程序</a>
                        <dl class="layui-nav-child">
                            {{# apis}}
                            <dd><a href="javascript:;" name="fn_open" lya-type="api"
                                    lya-file="{{apipath}}">{{apiname}}</a></dd>
                            {{/ apis}}
                        </dl>
                    </li>
                    <li class="layui-nav-item">
                        <a href="javascript:;">生成器库</a>
                        <dl class="layui-nav-child">
                            {{# makers}}
                            <dd><a href="javascript:;" name="fn_open" lya-type="maker"
                                    lya-file="MAKERC.{{code}}">{{name}} [{{func}}]</a></dd>
                            {{/ makers}}
                        </dl>
                    </li>
                    <!-- <li class="layui-nav-item">
                        <a href="javascript:;">视图程序</a>
                        <dl class="layui-nav-child">
                            <dd><a href="javascript:;">视图系统开发中</a></dd>
                        </dl>
                    </li> -->

                    {{# overview}}
                    {{^ use_ovoften}}
                    <li class="layui-nav-item">
                        <a href="javascript:;" id="allDir">文件总览</a>
                    </li>
                    {{/ use_ovoften}}
                    {{# use_ovoften}}
                    <li class="layui-nav-item">
                        <a href="javascript:;">文件总览</a>
                        <dl class="layui-nav-child">
                            {{# overview_often}}
                            <dd><a href="javascript:;" name="fn_open" lya-type="{{path}}" lya-file="{{file}}"
                                    lya-do="overview">{{title}}</a></dd>
                            {{/ overview_often}}
                            <dd><a href="javascript:;" id="allDir">所有文件</a></dd>
                        </dl>
                    </li>
                    {{/ use_ovoften}}
                    {{/ overview}}

                    <li class="layui-nav-item">
                        <a href="javascript:;" id="open_setting">编辑器设置</a>
                    </li>
                </ul>
                {{/ islogin}}

                {{^ islogin}}
                <ul class="layui-nav layui-nav-tree" lay-filter="test">
                    <li class="layui-nav-item layui-nav-itemed">
                        <a class="" href="javascript:;">接口程序</a>
                        <dl class="layui-nav-child"></dl>
                    </li>
                    <li class="layui-nav-item">
                        <a href="javascript:;" id="none_notlogin">编辑器设置</a>
                    </li>
                </ul>
                {{/ islogin}}

            </div>
        </div>

        <div class="layui-body">
            <input style="display: none;" type="text" id="fromov">
            <div id="editor" class="mousetrap" style="display: none;">{{code}}</div><br>
        </div>

        <div class="layui-footer" style="background-color: #23262E;color:white;">
            <!-- 底部固定区域 -->
            <span>© lyapi.wwsg18.com</span>&nbsp;&nbsp;&nbsp;
            <span>最后保存: <span id="new_saveTime" style="color:aqua;">未保存</span></span>&nbsp;&nbsp;&nbsp;
            <span style="color:gold;" id="more_ps"></span>
            <span class="layui-breadcrumb" lay-separator="|" style="float: right;">
                <a href="javascript:;" id="bottom_store">应用中心</a>
                <a href="https://gitee.com/LyApi-Development/LyMaster/issues" target="_blank" id="bottom_help">问题反馈</a>
                <a href="javascript:;" id="bottom_info">系统信息</a>
            </span> </div>

    </div>

    <div>

        <script>
            layui.use('element', function () {
                var element = layui.element;
            });
        </script>


    </div>

    <script>
        var is_overview = false;
        var ovpath = '';
        var funcnm = '';

        window.addEventListener('keydown', function (e) {
            if (e.keyCode == 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
                e.preventDefault();
            }
            if (e.keyCode == 71 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
                e.preventDefault();
            }
        })

        layui.use(['layer'], function () {

            var layer = layui.layer;

            // 页面数据
            var now_file = '{{nowfile}}';
            var now_type = '{{nowtype}}';

            // 编辑器程序设置
            var theme = '{{theme}}';
            var lanuage = '{{language}}';
            var fontsize = Number("{{fontsize}}");

            // 按钮事件绑定
            $('#changeTheme').click(function () {
                if (theme == 'twilight') {
                    theme = 'clouds';
                } else {
                    theme = 'twilight';
                }
                editor.setTheme("ace/theme/" + theme);
            });

            $('#changeLanguage').click(function () {

                layer.prompt({
                    title: '目标语言包 - 切换语言包'
                }, function (pass, index) {
                    editor.session.setMode('ace/mode/' + pass);
                    layer.close(index);
                });
            });

            $('#saveFile').click(save_file);

            $('#allDir').click(function () {
                // {{domain}}/admin/api/summit/folders?from=coder-administator
                layer.open({
                    type: 2,
                    title: 'Coder OverView - 系统文件索引',
                    shadeClose: true,
                    shade: false,
                    maxmin: true, //开启最大化最小化按钮
                    area: ['893px', '600px'],
                    content: '{{domain}}/admin/coder?child=overview'
                });
            });

            $('a[name="fn_open"]').click(function () {
                var file = $(this).attr('lya-file');
                var type = $(this).attr('lya-type');

                if ($(this).attr('lya-do') == 'overview') {
                    open_file(file, type, true);
                } else {
                    open_file(file, type);
                }

            });

            $('#open_setting').click(() => {
                open_file('setting.json', '');
            });

            $("#coder-open").click(function () {
                layer.open({
                    type: 2,
                    title: 'Cmder - 命令行工具',
                    offset: 'cmder',
                    shadeClose: true,
                    shade: false,
                    maxmin: false,
                    area: ['900px', '620px'],
                    content: '{{domain}}/admin/cmder'
                });
            });

            // 编辑器程序
            var editor = ace.edit('editor');
            editor.setTheme('ace/theme/' + theme);
            editor.session.setMode('ace/mode/' + lanuage);

            editor.setFontSize(fontsize);

            // {{# readonly}}
            editor.setReadOnly(true);
            // {{/ readonly}}

            editor.getSession().setUseWrapMode(true);

            var languageTools = ace.require("ace/ext/language_tools");

            $.get('{{domain}}/admin/api/coder?do=setting&which=custom-block', function (res) {
                languageTools.addCompleter({
                    getCompletions: function (editor, session, pos, prefix,
                        callback) {
                        callback(null, res.data);
                    }
                });
            });

            editor.setOptions({
                enableBasicAutocompletion: true,
                enableSnippets: true,
                enableLiveAutocompletion: true
            });

            // 页面渲染完毕后再显示
            $('#editor').css('display', 'block');

            // 编辑器内部按键绑定
            editor.commands.addCommand({
                name: 'saveFile',
                bindKey: {
                    win: 'Ctrl-S',
                    mac: 'Command-S'
                },
                exec: save_file,
                readOnly: false
            });

            editor.commands.addCommand({
                name: 'openCmder',
                bindKey: {
                    win: 'Ctrl-U',
                    mac: 'Command-U'
                },
                exec: function () {
                    layer.open({
                        type: 2,
                        title: 'Cmder - 命令行工具',
                        offset: 'cmder',
                        shadeClose: true,
                        shade: false,
                        maxmin: false,
                        area: ['900px', '620px'],
                        content: '{{domain}}/admin/cmder'
                    });
                    return false;
                },
                readOnly: false
            });

            Mousetrap.bind(['command+s', 'ctrl+s'], save_file);

            Mousetrap.bind(['command+u', 'ctrl+u'], function () {
                layer.open({
                    type: 2,
                    title: 'Cmder - 命令行工具',
                    offset: 'cmder',
                    shadeClose: true,
                    shade: false,
                    maxmin: false,
                    area: ['900px', '620px'],
                    content: '{{domain}}/admin/cmder'
                });
                return false;
            });


            // 快捷键处理函数
            function save_file(e) {

                if (now_file == 'setting.json') {
                    // var context = JSON.parse(editor.getValue());

                    var context = editor.getValue();

                    try {
                        var obj = JSON.parse(context);
                        if (!(typeof obj == 'object' && obj)) {
                            layer.msg('保存错误：内容不符合格式要求！');
                            return false;
                        }

                    } catch (e) {
                        layer.msg('保存错误：内容不符合格式要求！');
                        return false;
                    }
                } else {
                    var context = editor.getValue();
                }

                if (now_file != '') {

                    // 预处理Maker代码式
                    if (now_type == 'maker') {
                        var reg = new RegExp();
                        var context = context.match("public function " +
                            funcnm + "\\(\\$type,\\$args\\)\\{" +
                            "((.|\n(?!\\{|\\}))*)" +
                            "\\}");

                        console.log(context);

                        if (context != null) {
                            context = context[1];
                        } else {
                            layer.msg("无法匹配的缓存函数！");
                            return;
                        }

                    }

                    if (is_overview) {
                        var url = '{{domain}}/admin/api/coder?do=overview&type=write';
                        var parm = {
                            context: context,
                            file: now_file,
                            path: ovpath,
                            time: new Date().getTime()
                        };

                    } else {
                        var url = '{{domain}}/admin/api/coder?do=save';
                        var parm = {
                            context: context,
                            file: now_file,
                            type: now_type,
                            time: new Date().getTime()
                        };
                    }

                    $.post(url, parm, function (res) {
                        if (res.msg == '' && res.data == 'OK') {
                            var date = new Date();

                            $('#new_saveTime').html(date.getHours() + ':' + date
                                .getMinutes() + ':' +
                                date.getSeconds());
                        } else if (res.msg == '文件数据不存在') {
                            layer.msg('您保存的文件不存在或已过期...');
                        } else {
                            layer.msg(res.msg + '！');
                        }
                    }).fail(function (res) {

                        if (res.responseJSON.msg == '文件不可写') {
                            layer.msg('当前文件无写入权限，无法保存...');
                        } else {
                            layer.msg('操作异常：' + res.responseJSON.msg + '！');
                        }

                    });
                } else {
                    layer.msg('您还没有打开任何文件哦！');
                }
            }

            function open_file(which, type = 'api', overview = false) {
                now_file = which;
                now_type = type;
                $('#filename').html(which);

                is_overview = overview;
                ovpath = type;

                if (type == 'maker') {
                    $('#more_ps').html("警告: 当前文件为缓存文件，并非本地文件！");
                    $.get("{{domain}}/admin/api/coder?do=open&type=maker&file=" + which, function (res) {
                        var code = "<?php\n\n//Maker缓存数据:" +
                            which +
                            "\n\n" +
                            "// 本结构为编辑器自动生成，不代表缓存结果\n" +
                            "class _online_preview_ {\n\n" +
                            "\t// 缓存函数本体(可修改)\n" +
                            res.data.code + '\n\n}';
                        editor.session.setMode('ace/mode/php');
                        editor.setValue(code, -1);
                        funcnm = res.data.info.func;
                    });
                    return;
                } else {
                    $('#more_ps').html("");
                }

                if (!overview) {
                    $('#more_ps').html("");
                    var url = '{{domain}}/admin/api/coder?do=open&file=' + which + '&type=' + type;
                } else {
                    $('#more_ps').html("警告: 当前文件为全局文件，操作有风险！");
                    var url = '{{domain}}/admin/api/coder?do=overview&file=' + which + '&path=' +
                        type;
                }

                $.get(url, function (res) {
                    if (typeof res.data == "object") {
                        res.data = JSON.stringify(res.data, null, 4);
                    }

                    // 取得文件后缀名
                    var fileName = which.lastIndexOf("."); //取到文件名开始到最后一个点的长度
                    var fileNameLength = which.length; //取到文件名长度
                    var fileFormat = which.substring(fileName + 1, fileNameLength); //截

                    // 文件后缀切换
                    switch (fileFormat) {
                        case 'php':
                            editor.session.setMode('ace/mode/php');
                            break;
                        case 'md':
                            editor.session.setMode('ace/mode/markdown');
                            break;
                        case 'json':
                        case 'lock':
                            editor.session.setMode('ace/mode/json');
                            break;
                        case 'html':
                        case 'htm':
                        case 'tpl':
                            editor.session.setMode('ace/mode/php');
                            break;
                        case 'sql':
                            editor.session.setMode('ace/mode/mysql');
                            break;
                        case 'py':
                            editor.session.setMode('ace/mode/python');
                            break;
                        case 'ini':
                            editor.session.setMode('ace/mode/ini');
                            break;
                        default:
                            editor.session.setMode('ace/mode/text');

                    }

                    editor.setValue(res.data, -1);
                });
            }

            // 可供外部访问的函数
            window.ovOpen = function (which, type = 'api', overview = true) {
                open_file(which, type, overview);
            }

            $(document).keydown(

                function (e) {

                    if (e.which === 27) {

                        layer.closeAll();

                    }

                }
            );

            // 底部操作栏函数
            $('#bottom_info').click(function () {
                layer.open({
                    type: 2,
                    title: 'System Info - 系统信息',
                    shadeClose: true,
                    shade: false,
                    maxmin: false,
                    area: ['420px', '360px'],
                    content: '{{domain}}/admin/coder?child=sysinfo'
                });
            });

        });
    </script>

</body>

</html>