mxd 5 лет назад
Родитель
Сommit
c1351d188d
22 измененных файлов с 1837 добавлено и 821 удалено
  1. 731 146
      src/main/resources/magicapi-support/css/index.css
  2. BIN
      src/main/resources/magicapi-support/images/logo.png
  3. 148 133
      src/main/resources/magicapi-support/index.html
  4. 949 488
      src/main/resources/magicapi-support/js/index.js
  5. 1 0
      src/main/resources/magicapi-support/js/jquery.min.js
  6. 0 1
      src/main/resources/magicapi-support/layui/css/layui.css
  7. 0 1
      src/main/resources/magicapi-support/layui/css/layui.mobile.css
  8. 0 2
      src/main/resources/magicapi-support/layui/css/modules/code.css
  9. 0 1
      src/main/resources/magicapi-support/layui/css/modules/laydate/default/laydate.css
  10. BIN
      src/main/resources/magicapi-support/layui/css/modules/layer/default/icon-ext.png
  11. BIN
      src/main/resources/magicapi-support/layui/css/modules/layer/default/icon.png
  12. 0 1
      src/main/resources/magicapi-support/layui/css/modules/layer/default/layer.css
  13. BIN
      src/main/resources/magicapi-support/layui/css/modules/layer/default/loading-0.gif
  14. BIN
      src/main/resources/magicapi-support/layui/css/modules/layer/default/loading-1.gif
  15. BIN
      src/main/resources/magicapi-support/layui/css/modules/layer/default/loading-2.gif
  16. BIN
      src/main/resources/magicapi-support/layui/font/iconfont.eot
  17. 0 25
      src/main/resources/magicapi-support/layui/font/iconfont.svg
  18. BIN
      src/main/resources/magicapi-support/layui/font/iconfont.ttf
  19. BIN
      src/main/resources/magicapi-support/layui/font/iconfont.woff
  20. BIN
      src/main/resources/magicapi-support/layui/font/iconfont.woff2
  21. 0 1
      src/main/resources/magicapi-support/layui/layui.all.js
  22. 8 22
      src/main/resources/magicapi-support/monaco/language/magicscript.js

+ 731 - 146
src/main/resources/magicapi-support/css/index.css

@@ -1,204 +1,789 @@
-*{
-    margin:0;
-    padding:0;
+* {
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
 }
-html,body{
+
+html{
+    font-size: 12px;
     width: 100%;
-    height:100%;
-    overflow: hidden;
+    height: 100%;
+    font-family: 'Consolas','微软雅黑';
+    letter-spacing: 1px;
 }
-.layui-header{
-    background: #1890FF;
+body {
+    overflow: auto;
+    display: flex;
+    flex-direction: column;
+    position: relative;
+    width: 100%;
+    height: 100%;
+    min-width: 1280px;
+    min-height: 768px;
 }
-.layui-logo{
-    background: url("../images/logo.png");
-    background-size: 100% 100%;
-    height : 60px;
-    width : 225px;
+ul li {
+    list-style: none;
 }
-.layui-nav{
-    background-color : transparent;
+
+.not-select {
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -ms-user-select: none;
+    -khtml-user-select: none;
+    user-select: none;
 }
-.layui-nav .layui-nav-item a{
-    color : #fff;
-    padding : 0 10px;
+
+::-webkit-scrollbar {
+    width: 7px;
+    height: 7px;
+    background: rgba(221, 221, 221, .3);
 }
-.layui-layout-right{
-    z-index: 1024;
+
+::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    background: rgba(170, 170, 170, .4);
 }
-.layui-layout-right .layui-nav-item a img{
-    background: #fff;
-    border-radius: 4px;
+
+::-webkit-scrollbar-thumb:hover {
+    background: rgba(170, 170, 170, .7);
 }
-.layui-bottom{
-    position: absolute;
-    top : 60px;
-    bottom : 0px;
-    width : 100%;
+
+::-webkit-scrollbar-corner {
+    background: rgba(221, 221, 221, .3);
 }
-.layui-left,.editor-container,.layui-right{
-    box-shadow: 1px 0 5px 0 #ddd;
-    height : 100%;
+
+.top-toolbar-container,
+.footer-container {
+    height: 24px;
+    line-height: 24px;
+    background: #f2f2f2;
+    flex: none;
+}
+
+.top-toolbar-container {
+    height: 30px;
+    line-height: 30px;
+    text-align: right;
+    color : #6e6e6e;
+}
+.skin-selector{
     position: absolute;
-    bottom:0;
-    left : 0;
-    width : 225px;
+    top : 30px;
+    right : 130px;
+    z-index: 20;
+    background: #F2F2F2;
+    border : 1px solid #CDCDCD;
+    border-top: none;
+    display: none;
+}
+.skin-selector ul li {
+    height : 24px;
+    line-height: 24px;
+    text-align: center;
+    cursor: pointer;
+}
+.skin-selector ul li:hover{
+    background: #d9d9d9;
+}
+.skin-selector ul li:not(:last-child){
+    border-bottom: 1px solid #CDCDCD;
+    padding : 2px 5px;
+}
+.top-toolbar-container span{
+    cursor: pointer;
+    padding : 0 3px;
+    height: 22px;
+    line-height: 22px;
+    display: inline-block;
+    vertical-align: middle;
+    border-radius: 2px;
+    text-align: center;
+}
+.top-toolbar-container span:last-child{
+    margin-right: 15px;
+}
+.top-toolbar-container span:hover:not(.disabled){
+    background: #d9d9d9;
 }
-.layui-right-container{
+.main-container {
     position: absolute;
-    left : 225px;
-    right : 0;
-    height : 100%;
+    top: 30px;
+    left: 22px;
+    bottom: 24px;
+    right: 0px;
+    display: flex;
+    flex-direction: column;
 }
-.properties-container{
-    height : 58px;
-    border-bottom: 1px solid #eee;
-    box-sizing: border-box;
-    padding-top:2px;
-    padding-left : 3px;
+
+.main-container .middle-container {
+    flex: 1;
+    display: flex;
+    overflow: auto;
+    background: #F0F0F0;
 }
-.properties-container .layui-input-placeholder{
-    height : 16px;
-    font-size: 12px;
-    line-height: 16px;
+.middle-container .api-list-container{
+    float: left;
+    border-right: 1px solid #c0c0c0;
+    overflow: auto;
+    width : 250px;
+    min-width: 250px;
+    background: #ffffff;
+}
+.group-item .group-list{
+    display: none;
+}
+.group-item .group-list li{
+    height: 20px;
+    line-height: 20px;
+    padding-left : 25px;
+    padding-right: 5px;
+    white-space: nowrap;
+}
+.group-item .group-list li:hover,
+.group-item .group-list li.selected,
+.group-item .group-header:hover{
+    background : #d4d4d4;
+}
+.group-item.opened .group-list{
+    display: block;
+}
+.group-item .group-header{
+    font-weight: bold;
+    height : 20px;
+    line-height: 20px;
+    padding: 0 5px;
+}
+.group-item .group-list li label{
     color : #333;
 }
-.properties-container .layui-btn-group{
-    padding : 2px 10px;
-    color : #1890ff;
-    border: 1px solid #D2D2D2;
-    border-radius: 20px;
+.group-item .group-list li span{
+    color : #999;
+    margin-left: 5px;
+}
+.group-item .group-header i{
+    color : #b3b3b3
+}
+.group-item .group-header .icon-list{
+    color : #aeb9c0;
+    padding-left : 8px;
+    padding-right: 2px;
+    font-size : 14px;
+}
+.group-item .group-list li i{
+    color : #AEB9C0;
+    padding : 0 2px;
+}
+.middle-container .editor-container-wrapper{
+    flex :1;
+    height: 100%;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+    margin-left: -5px;
+}
+.middle-container .editor-container-wrapper .properties-container{
+    height : 30px;
+    line-height: 30px;
+    background: #F2F2F2;
+    border-bottom: 1px solid #C9C9C9;
+    text-align: right;
+    padding-right: 15px;
+    font-size: 0;
+}
+.middle-container .editor-container-wrapper .properties-container label{
+    font-size : 12px;
+    margin:0 3px;
+}
+.properties-container input{
+    height: 22px;
+    line-height: 22px;
+    border-radius: 0;
+    outline: 0;
+    border: 1px solid #BDBDBD;
+    padding-left: 5px;
+}
+.select{
+    position: relative;
+    display: inline-block;
+    background: #E3E3E3;
+    height : 22px;
+    line-height: 22px;
+    border : 1px solid #BDBDBD;
+    width: 80px;
+    font-size: 12px;
+}
+.select.input{
+    background: #ffffff;
+}
+.select::after{
+    content :"\efa2";
+    font-family: 'iconfont';
+    position: absolute;
+    right : 5px;
+}
+.button-run,.bottom-container .bottom-item-toolbar span.button-continue{
+    color: #59A869;
+}
+.select input{
+    cursor: default;
+    width: 100%;
+}
+.select:hover:not(.input){
+    background: #E3F1FA;
 }
-.properties-container .layui-btn-group li {
+.select input{
+    background: none;
+    border : none;
+}
+.select ul {
+    display: none;
+    position: absolute;
+    width: 100%;
+    z-index: 10;
+    background: #fff;
+    border: 1px solid #808080;
+    margin-top: -2px;
+    padding: 0px;
+    box-sizing: content-box;
+    margin-left: -1px;
+}
+.select ul li{
+    padding : 0 5px;
+    text-align: left;
+}
+.select ul li:hover,
+.context-menu li:hover,
+.bottom-container .bottom-item-body table tr:hover td{
+    background: #1A7DC4;
+    color: #ffffff;
+}
+.context-menu{
+    position: absolute;
+    z-index: 1000;
+    border: 1px solid #CDCDCD;
+    background: #f2f2f2;
+    width : 200px;
+}
+.context-menu li{
+    height : 24px;
+    line-height: 24px;
+    padding : 0 10px;
+}
+.context-menu li label{
     float : left;
-    cursor: pointer;
 }
-.properties-container .layui-btn-group li.disabled{
-    color : #ccc;
+.context-menu li span{
+    text-align: right;
+    float : right;
+    color : #505050;
 }
-.properties-container .layui-btn-group li i{
-    font-size: 20px;
+.context-menu li:hover span{
+    color: #fff;
 }
-.properties-container .layui-btn-group li:not(:last-child){
-    border-right: 1px solid #d2d2d2;
-    padding-right: 4px;
+.context-menu li:not(:last-child){
+    border-bottom: 1px solid #CDCDCD;
 }
-.properties-container .layui-btn-group li:not(:first-child){
-    padding-left: 4px;
+.middle-container .editor-container-wrapper .editor-container{
+    flex: 1;
 }
-.properties-container .layui-btn-group li:hover:not(.disabled) i{
-    background : #ddd;
+.left-toolbar-container {
+    background: #f2f2f2;
+    border-right: 1px solid #c9c9c9;
+    width: 22px;
+    position: absolute;
+    left: 0;
+    bottom: 24px;
+    top: 30px;
 }
-.properties-container .layui-btn-group li:active:not(.disabled) i{
-    background : #ccc;
+
+.left-toolbar-container li {
+    padding: 6px 3px;
+    cursor: pointer;
+    letter-spacing: 2px;
+    text-align: center;
 }
-.editor-container{
-    left : 0px;
-    right : 400px;
-    width : auto;
-    top : 58px;
-    box-shadow: 1px 3px 5px 0 #ddd;
-    z-index: 20;
+
+.top-toolbar-container,
+.main-container .middle-container {
+    border-bottom: 1px solid #cdcdcd;
 }
-.layui-right{
-    left : auto;
-    right : 0;
-    width : 400px;
-    box-shadow: none;
-    top : 58px;
+.top-toolbar-container .header{
+    float : left;
+    color : #000;
+    font-weight: bold;
+    font-size: 0px;
+    letter-spacing: 0px;
+}
+.top-toolbar-container .header label{
+    font-size : 16px;
+    width: 85px;
+    display: inline-block;
+    text-align: left;
+}
+.top-toolbar-container .header label.version{
+    font-size: 13px;
+    color: #333;
+}
+.top-toolbar-container .header img{
+    height : 24px;
+    width: 22px;
+    vertical-align: middle;
+    margin-top: -6px;
+}
+.left-toolbar-container li:hover {
+    background: #d9d9d9;
 }
-.request-container{
-    position: relative;
-    height: 400px;
+
+.left-toolbar-container li.selected {
+    background: #bdbdbd;
+}
+
+.main-container .bottom-container {
+    background: #f2f2f2;
 }
-.layui-right .layui-tab-content{
+
+.footer-container {
     position: absolute;
-    top : 40px;
-    bottom : 0;
-    left : 0;
-    right : 0
+    bottom: 0px;
+    height: 24px;
+    width: 100%;
+    border-top: 1px solid #919191;
+    padding-left: 20px;
+}
+
+.main-container .bottom-container .bottom-content-container {
+    border-bottom: 1px solid #c9c9c9;
+    display: none;
+    height: 300px;
 }
-.layui-right .layui-tab-content .layui-tab-item{
+
+.main-container .bottom-container .bottom-content-container .bottom-content-item {
+    display: none;
+    background: #fff;
+    overflow: auto;
     height: 100%;
+    position: relative;
+}
+
+.resizer-y {
+    position: absolute;
+    width: 100%;
+    height: 10px;
+    margin-top: -5px;
+    background: none;
+    cursor: n-resize;
 }
-.layui-right .layui-tab-content .layui-tab-item > *{
+.resizer-x {
+    float : left;
+    width: 10px;
     height: 100%;
-    resize: none;
-    margin-top: 1px;
+    margin-left: -5px;
+    background: none;
+    cursor: e-resize;
+    z-index: 1000;
+}
+.main-container .bottom-container .bottom-content-container .bottom-content-item.selected {
+    display: block;
+}
+
+.main-container .bottom-container ul li {
+    float: left;
+    cursor: pointer;
+    padding: 0 10px;
+    height: 24px;
+    line-height: 24px;
+}
+.main-container .bottom-container ul li i{
+    color: #6e6e6e;
+    padding : 0 2px;
+    display: inline-block;
+}
+.left-toolbar-container li i{
+    color: #6e6e6e;
+    font-size: 14px;
+}
+
+.main-container .bottom-container ul li:hover {
+    background: #d9d9d9;
+}
+
+.main-container .bottom-container ul li.selected {
+    background: #bdbdbd;
+}
+
+
+.bottom-item-toolbar{
+    background: #f2f2f2;
+    border-bottom : 1px solid #C9C9C9;
+    height :24px;
+    line-height: 24px;
+    padding-left: 10px;
+}
+.bottom-container .bottom-item-toolbar label{
+    display: inline-block;
+    height: 18px;
+    line-height: 18px;
+    font-size: 12px;
+    vertical-align: middle;
+    margin-top: -6px;
+    padding-right: 5px;
+    border-right: 1px solid #CDCDCD;
+}
+.bottom-container .bottom-item-toolbar span{
+    color : #6e6e6e;
+    cursor: pointer;
+    padding : 0 3px;
+    display: inline-block;
+    height: 24px;
+    line-height: 24px;
 }
-.output-container{
+.top-toolbar-container span.disabled,
+.bottom-container .bottom-item-toolbar span.disabled{
+    color: #BDBDBD;
+}
+.bottom-container .bottom-item-toolbar span:hover:not(.disabled){
+    background: #d9d9d9;
+}
+.bottom-container .bottom-item-body{
     position: absolute;
-    top : 400px;
+    top : 24px;
     bottom : 0px;
-    width : 100%;
-    border-top: 1px solid #eee;
+    width: 100%;
+    overflow:auto;
 }
-.layui-side{
-    width : 225px;
-    top : 98px;
+.bottom-container .bottom-item-body table{
+    width: 100%;
+    background: #fff;
+    border-collapse:collapse;
 }
-.api-list{
-    height : 100%;
+.bottom-container .bottom-item-body table th{
+    text-align: left;
 }
-.scroller{
-    overflow: auto;
+.bottom-container .bottom-item-body table td,
+.bottom-container .bottom-item-body table th{
+    border-bottom : 1px solid #C0C0C0;
+    height : 24px;
+    line-height: 24px;
+    padding-left : 5px;
 }
-.scroller::-webkit-scrollbar {
-    width: 7px;
-    height: 7px;
-    background: #ddd;
+.bottom-container .bottom-item-body table tbody tr:nth-child(even){
+    background: #F2F5F9;
 }
-.scroller::-webkit-scrollbar-thumb {
-    border-radius: 5px;
-    background: #aaa;
+.bottom-container .bottom-item-body table tr th:not(:last-child),
+.bottom-container .bottom-item-body table tr td:not(:last-child){
+    border-right: 1px solid #E5E5E5;
 }
-.scroller::-webkit-scrollbar-thumb:hover {
-    background: #999;
+
+.margin-view-overlays{
+    border-right : 1px solid #c0c0c0;
 }
-.scroller::-webkit-scrollbar-corner{
-    background: #ddd;
+
+.dialog-wrapper{
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    z-index: 999999;
+    text-align: center;
 }
-.layui-form-select dl dd.layui-this{
-    background-color: #1890FF;
+.dialog-wrapper:before {
+    content: '';
+    display: inline-block;
+    height: 100%;
+    vertical-align: middle;
+    margin-right: -0.25em; /* Adjusts for spacing */
+}
+.dialog-wrapper .dialog{
+    background: #F2F2F2;
+    border : 1px solid #707070;
+    display: inline-block;
+    vertical-align: middle;
+    position: relative;
+    padding-left: 5px;
+    min-width : 250px;
+    box-shadow: 0px 0px 8px #CFCFCF;
+}
+.dialog-wrapper .dialog .dialog-header{
+    height : 30px;
+    line-height: 30px;
+    padding-left : 25px;
+    padding-right: 75px;
+    background-image: url(../images/logo.png);
+    background-size: 22px 24px;
+    background-position: 0px 4px;
+    background-repeat: no-repeat;
+    text-align: left;
+}
+.dialog-wrapper .dialog .dialog-header span{
+    display: inline-block;
+    width: 40px;
+    position: absolute;
+    right: 0px;
+    text-align: center;
+    cursor: pointer;
+    font-size: 12px;
 }
-.layout-resizer-x{
-    position:absolute;
-    right : 400px;
-    top : 58px;
-    bottom : 0px;
-    width : 11px;
-    margin-left: -5px;
-    border-left: 5px solid hsla(0,0%,100%,0);
-    border-right: 5px solid hsla(0,0%,100%,0);
-    cursor: col-resize;
-    z-index: 100;
-}
-
-.layout-resizer-y{
-    position:absolute;
-    right : 0px;
-    left : 0px;
-    top : 400px;
-    height : 11px;
-    margin-top: -5px;
-    border-top: 5px solid hsla(0,0%,100%,0);
-    border-bottom: 5px solid hsla(0,0%,100%,0);
-    cursor: row-resize;
-    z-index: 100;
+.dialog-wrapper .dialog .dialog-header span:hover:not(.disabled){
+    background: #E81123;
+    color: #fff;
+}
+.dialog-wrapper .dialog .dialog-content{
+    padding : 5px 10px;
+    text-align: left;
+}
+.dialog-wrapper .dialog .dialog-buttons{
+    padding : 5px 0;
 }
+.dialog-wrapper .dialog .dialog-buttons button:not(:last-child){
+    margin-right: 10px;
+}
+.dialog-wrapper .dialog .dialog-buttons button{
+    height : 22px;
+    line-height: 22px;
+    background: #E3E3E3;
+    text-align: center;
+    padding : 0 15px ;
+    border : 1px solid #ADADAD;
+    outline: 0;
+    cursor: pointer;
+}
+.dialog-wrapper .dialog .dialog-buttons.button-align-right{
+    text-align: right;
+    margin-right: 10px;
+}
+.dialog-wrapper .dialog .dialog-buttons button.active,
+.dialog-wrapper .dialog .dialog-buttons button:hover{
+    background: #E3F1FA;
+    border-color: #0784DE;
+}
+
 .breakpoints{
     background: #db5860;
     width: 10px !important;
     height: 10px !important;
     right: 0px !important;
-    margin-left: 10px;
-    top: 3px;
+    margin-left: 12px;
+    top: 5px;
     border-radius: 5px;
 }
-.breakpoint-line{
-    background: #faeae6;
-}
 .debug-line{
     background: #2154A6;
     color: #fff !important;
+}
+.breakpoint-line{
+    background: #FAEAE6;
+}
+
+/* skin dark*/
+.skin-dark .skin-selector{
+    background: #3C3F41;
+    color : #bbb;
+    border-color: #515151;
+}
+.skin-dark .skin-selector ul li:hover,
+.skin-dark .bottom-container .bottom-item-body table tr:hover td{
+    background :#4B6EAF;
+}
+.skin-dark .skin-selector ul li:not(:last-child){
+    border-bottom-color: #515151;
+}
+.skin-dark .top-toolbar-container{
+    background: #3C3F41;
+    color : #AFB1B3;
+    border-bottom : #323232
+}
+
+.skin-dark .middle-container .api-list-container{
+    background: #3C3F41;
+    color : #bbb;
+}
+.skin-dark .left-toolbar-container{
+    background: #3C3F41;
+    border-right-color : #323232
+}
+.skin-dark .left-toolbar-container li.selected{
+    background : #323232;
+    color : #fff;
+}
+.skin-dark .left-toolbar-container li,
+.skin-dark .left-toolbar-container li i{
+    color : #AFB1B3;
+}
+.skin-dark .top-toolbar-container, .skin-dark .main-container .middle-container{
+    border-bottom: 1px solid #323232;
+}
+.skin-dark .bottom-item-toolbar,
+.skin-dark .middle-container .editor-container-wrapper .properties-container{
+    background: #3C3F41;
+    border-bottom: 1px solid #323232;
+}
+.skin-dark .bottom-container .bottom-item-toolbar span{
+    color : #AFB1B3;
+}
+.skin-dark .left-toolbar-container li,
+.skin-dark .bottom-tab,
+.skin-dark .footer-container,
+.skin-dark .middle-container .editor-container-wrapper .properties-container,
+.skin-dark .group-item .group-list li label{
+    color:#bbb;
+}
+.skin-dark .left-toolbar-container li:hover,
+.skin-dark .main-container .bottom-container ul li:hover{
+    background: #353739;
+}
+.skin-dark .top-toolbar-container span.disabled,
+.skin-dark .bottom-container .bottom-item-toolbar span.disabled{
+    color : #5A5A5A;
+}
+.skin-dark .top-toolbar-container span:hover:not(.disabled),
+.skin-dark .bottom-container .bottom-item-toolbar span:hover:not(.disabled){
+    background: #2D2F30;
+}
+.skin-dark .main-container .bottom-container,
+.skin-dark .footer-container{
+    background: #3C3F41;
+}
+.skin-dark .main-container .bottom-container ul li i{
+    color : #AFB1B3;
+}
+.skin-dark .group-item .group-list li span{
+    color : #787878
+}
+.skin-dark .main-container .bottom-container ul li.selected{
+    background: #2D2F30;
+    color : #fff;
+}
+.skin-dark .main-container .bottom-container .bottom-content-container .bottom-content-item{
+    background: #2B2B2B;
+    color : #bbb;
+}
+.skin-dark .main-container .bottom-container .bottom-content-container{
+    border-bottom : 1px solid #323232;
+}
+.skin-dark .footer-container{
+    border-top: 1px solid #464646;
+}
+.skin-dark .middle-container .api-list-container,
+.skin-dark .margin-view-overlays,
+.skin-dark .bottom-container .bottom-item-toolbar label{
+    border-right-color: #555555;
+}
+.skin-dark .group-item .group-list li:hover,
+.skin-dark .group-item .group-list li.selected,
+.skin-dark .group-item .group-header:hover{
+    background: #0D293E;
+}
+.skin-dark .main-container .middle-container{
+    background: #313335;
+}
+.skin-dark .properties-container input{
+    border: 1px solid #646464;
+    background: #45494A;
+    color : #bbb;
+}
+.skin-dark .select{
+    background: #3C3F41;
+    border : 1px solid #646464;
+}
+.skin-dark .select.input{
+    background: #45494A;
+    border : 1px solid #646464;
+}
+.skin-dark .select input{
+    border: none;
+    background: transparent;
+}
+.skin-dark .select:hover:not(.input){
+    background: #3C3F41;
+}
+.skin-dark .select ul ,
+.skin-dark .context-menu{
+    background: #3C3F41;
+    border: 1px solid #616161;
+}
+.skin-dark .context-menu li,
+.skin-dark .context-menu li span,
+.skin-dark .context-menu li:hover span,
+.skin-dark .top-toolbar-container .header label{
+    color: #bbb;
+}
+.skin-dark .context-menu li:not(:last-child){
+    border-bottom: 1px solid #616161;
+}
+.skin-dark .context-menu li:not(:last-child){
+
+}
+.skin-dark .select ul li:hover,.skin-dark .skin-dark .context-menu li:hover{
+    background: #4B6EAF;
+    color: #bbbbbb;
+}
+.skin-dark .dialog-wrapper .dialog{
+    background: #3C3F41;
+    border : 1px solid #282828;
+    color : #bbb;
+    box-shadow: 0px 0px 8px #151515
+}
+.skin-dark .dialog-wrapper .dialog .dialog-buttons button{
+    background: #4C5052;
+    border : 1px solid #5E6060;
+    border-radius: 2px;
+    color: #bbb;
+}
+.skin-dark .dialog-wrapper .dialog .dialog-buttons button.active,
+.skin-dark .dialog-wrapper .dialog .dialog-buttons button:hover{
+    background: #365880;
+    border-color: #43688C;
+}
+.skin-dark .bottom-container .bottom-item-body table{
+    background: #2B2B2B
+}
+.skin-dark .bottom-container .bottom-item-body table thead{
+    background: #45484A;
+}
+.skin-dark .bottom-container .bottom-item-body table td,
+.skin-dark .bottom-container .bottom-item-body table th{
+    border-bottom : 1px solid #333638;
+}
+.skin-dark .bottom-container .bottom-item-body table tbody tr:nth-child(even){
+    background: #414547;
+}
+.skin-dark .bottom-container .bottom-item-body table tr th:not(:last-child),
+.skin-dark .bottom-container .bottom-item-body table tr td:not(:last-child){
+    border-right: 1px solid #333638;
+}
+.skin-dark .select ul li:hover, .context-menu li:hover,
+.skin-dark .bottom-container .bottom-item-body table tr:hover td{
+    background:#4B6EAF;
+}
+.skin-dark .breakpoint-line{
+    background: #3a2323
+}
+.skin-dark .breakpoints{
+    background: #C75450;
+}
+.skin-dark .debug-line{
+    background: #2D6099;
+}
+.skin-dark .button-run,
+.skin-dark .bottom-container .bottom-item-toolbar span.button-continue:not(.disabled){
+    color : #499C54;
+}
+.skin-dark{
+    background: #323232;
+}
+.skin-dark .top-toolbar-container .header label.version{
+    color: #999;
+}
+.monaco-editor .view-line,
+.monaco-editor .view-overlays > div{
+    padding-left: 5px;
+}
+.monaco-editor .cursor,
+.monaco-editor .selectionHighlight,
+.monaco-editor .bracket-match,
+.monaco-editor .cslr.selected-text,
+.monaco-editor .bottom-left-radius,
+.monaco-editor .top-left-radius,
+.monaco-editor .view-overlays .cigr,
+.monaco-editor .editor-widget{
+    margin-left: 5px;
 }

BIN
src/main/resources/magicapi-support/images/logo.png


+ 148 - 133
src/main/resources/magicapi-support/index.html

@@ -1,139 +1,154 @@
 <!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>Magic API</title>
-		<meta charset="utf-8" />
-		<link rel="icon" href="images/favicon.png" />
-		<link rel="stylesheet" href="layui/css/layui.css" />
-		<link rel="stylesheet" href="css/index.css" />
-		<script type="text/javascript" src="monaco/loader.js"></script>
-		<script type="text/javascript">require.config({ paths: { 'vs': 'monaco' }});</script>
-		<script type="text/javascript" src="monaco/language/magicscript.js"></script>
-		<script type="text/javascript" src="layui/layui.all.js"></script>
-		<script type="text/javascript" src="js/index.js"></script>
-	</head>
-	<body>
-		<div class="layui-layout">
-			<div class="layui-header">
-				<div class="layui-logo"></div>
+<html>
+<head>
+	<meta charset="UTF-8">
+	<title>MagicAPIv0.2.1 - Powered by ssssssss-team</title>
+	<link rel="icon" href="images/favicon.png" />
+	<style type="text/css">.loading-wrapper{position:fixed;top:0;bottom:0;left:0;right:0;z-index:2147483647;text-align:center;background:#fff}.loading{position:absolute;top:50%;left:50%;width:500px;height:100px;margin-left:-250px;margin-top:-50px;text-align:center}.loading .title{font-size:0;color:#0075ff;letter-spacing:0}.loading .title label{font-size:36px;display:inline-block;margin-top:5px;vertical-align:top}.loading .title span{font-size:72px;display:inline-block;padding:0 3px;animation:stretch 1s infinite}.loading .title span:nth-child(1){animation-delay:calc(1s / 8 * 0 / 2)}.loading .title span:nth-child(2){animation-delay:calc(1s / 8 * 1 / 2)}.loading .title span:nth-child(3){animation-delay:calc(1s / 8 * 2 / 2)}.loading .title span:nth-child(4){animation-delay:calc(1s / 8 * 3 / 2)}.loading .title span:nth-child(5){animation-delay:calc(1s / 8 * 4 / 2)}.loading .title span:nth-child(6){animation-delay:calc(1s / 8 * 5 / 2)}.loading .title span:nth-child(7){animation-delay:calc(1s / 8 * 6 / 2)}.loading .title span:nth-child(8){animation-delay:calc(1s / 8 * 7 / 2)}.loading .loading-text{text-align:center;font-weight:bolder;font-style:italic;color:#889aa4;font-size:32px;animation:blink-loading 2s ease-in infinite}@keyframes stretch{0%{transform:scale(1)}25%{transform:scale(1.2)}50%{transform:scale(1)}100%{transform:scale(1)}}@keyframes blink-loading{0%{opacity:100%}50%{opacity:50%}100%{opacity:100%}}</style>
+	<link rel="stylesheet" href="css/index.css" />
+	<link rel="stylesheet" href="//at.alicdn.com/t/font_1928593_lje7zmyxv7.css">
+	<script type="text/javascript" src="monaco/loader.js"></script>
+	<script type="text/javascript">require.config({ paths: { 'vs': 'monaco' }});</script>
+	<script type="text/javascript" src="monaco/language/magicscript.js"></script>
+	<script type="text/javascript" src="js/jquery.min.js"></script>
+	<script type="text/javascript" src="js/index.js"></script>
+</head>
+<body>
+<div class="loading-wrapper">
+	<div class="loading">
+		<div class="title">
+			<span>M</span>
+			<span>A</span>
+			<span>G</span>
+			<span>I</span>
+			<span>C</span>
+			<span>A</span>
+			<span>P</span>
+			<span>I</span>
+			<label>v0.2.1</label>
+		</div>
+		<div class="loading-text">Loading...</div>
+	</div>
+</div>
+<div class="top-toolbar-container not-select">
+	<div class="header">
+		<img src="images/logo.png"/>
+		<label>magic-api</label>
+		<label class="version">v0.2.1</label>
+	</div>
+	<span class="button-run" title="运行(Ctrl+Q)"><i class="iconfont icon-run"></i></span>
+	<span class="button-save" title="保存(Ctrl+S)"><i class="iconfont icon-save"></i></span>
+	<span class="button-delete" title="删除"><i class="iconfont icon-delete"></i></span>
+	<span class="button-skin" title="换肤"><i class="iconfont icon-skin"></i></span>
+	<span class="button-gitee" title="Gitee"><i class="iconfont icon-gitee"></i></span>
+	<span class="button-github" title="Github"><i class="iconfont icon-git"></i></span>
+	<span class="button-qq" title="加入QQ群"><i class="iconfont icon-qq"></i></span>
+	<span class="button-help" title="帮助文档"><i class="iconfont icon-help"></i></span>
+</div>
+<div class="skin-selector">
+	<ul>
+		<li>default</li>
+		<li class="selected">dark</li>
+	</ul>
+</div>
+<ul class="left-toolbar-container not-select">
+	<li class="selected">接口列表<i class="iconfont icon-list"></i></li>
+</ul>
+<div class="main-container">
+	<div class="middle-container">
+		<div class="api-list-container not-select">
+			<div class="group-item opened">
+				<div class="group-header"><i class="iconfont icon-arrow-bottom"></i><i class="iconfont icon-list"></i>未分组</div>
+			</div>
+		</div>
+		<div class="resizer-x"></div>
+		<div class="editor-container-wrapper">
+			<div class="properties-container">
+				<label>接口分组:</label>
+				<div class="select input" style="width:120px">
+					<input type="text" value="未分组" name="group"/>
+					<ul class="not-select">
+						<li>未分组</li>
+						<li>组1</li>
+						<li>组2</li>
+					</ul>
+				</div>
+				<label>请求方法:</label>
+				<div class="select not-select">
+					<input type="text" value="GET" readonly="readonly" name="method"/>
+					<ul>
+						<li>GET</li>
+						<li>POST</li>
+						<li>PUT</li>
+						<li>DELETE</li>
+					</ul>
+				</div>
+				<label>接口名称:</label>
+				<input type="text" style="width : 160px" name="name"/>
+				<label>接口地址:</label>
+				<input type="text" name="path"/>
+			</div>
+			<div class="editor-container"></div>
+		</div>
+	</div>
+	<div class="bottom-container">
+		<div class="bottom-content-container" style="display: block;">
+			<div class="resizer-y"></div>
+			<div class="bottom-content-item" style="display: block;">
+				<div class="bottom-item-toolbar">
+					<label>请求参数</label>
+					<span title="清空参数" class="button-clear"><i class="iconfont icon-clear"></i></span>
+					<span title="格式化参数" class="button-format"><i class="iconfont icon-format"></i></span>
+				</div>
+				<div class="bottom-item-body request-editor"></div>
+			</div>
+			<div class="bottom-content-item">
+				<div class="bottom-item-toolbar">
+					<label>接口选项</label>
+					<span title="清空参数" class="button-clear"><i class="iconfont icon-clear"></i></span>
+					<span title="格式化参数" class="button-format"><i class="iconfont icon-format"></i></span>
+				</div>
+				<div class="bottom-item-body options-editor"></div>
+			</div>
+			<div class="bottom-content-item">
+				<div class="bottom-item-toolbar">
+					<label>执行结果</label>
+					<span title="清空参数" class="button-clear"><i class="iconfont icon-clear"></i></span>
+					<span title="格式化参数" class="button-format"><i class="iconfont icon-format"></i></span>
+				</div>
+				<div class="bottom-item-body result-editor"></div>
 			</div>
-			<ul class="layui-nav layui-layout-right">
-				<li class="layui-nav-item"><a target="_blank" href="http://www.ssssssss.org">帮助文档</a></li>
-				<li class="layui-nav-item">
-					<a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=10faa4cf9743e0aa379a72f2ad12a9e576c81462742143c8f3391b52e8c3ed8d">加入QQ群</a>
-				</li>
-				<li class="layui-nav-item">
-					<a target="_blank" href="https://gitee.com/ssssssss-team/magic-api">
-						<img src="https://gitee.com/ssssssss-team/magic-api/badge/star.svg?theme=white" alt="gitee star">
-					</a>
-				</li>
-				<li class="layui-nav-item">
-					<a target="_blank" href="https://github.com/ssssssss-team/magic-api">
-						<img src="https://img.shields.io/github/stars/ssssssss-team/magic-api.svg?style=social" alt="github star" style="background: none">
-					</a>
-				</li>
-				<span class="layui-nav-bar" style="width: 0px; left: 0px; opacity: 0; top: 55px;"></span>
-			</ul>
-			<div class="layui-bottom">
-				<div class="layui-left">
-					<div class="api-search">
-						<input class="layui-input" type="text" placeholder="请输入接口名称或地址搜索"/>
-					</div>
-					<div class="layui-side">
-						<div class="layui-side-scroll scroller">
-							<div class="api-list" id="api-list" >
-
-							</div>
-						</div>
-					</div>
+			<div class="bottom-content-item">
+				<div class="bottom-item-toolbar">
+					<label>调试信息</label>
+					<span class="button-continue disabled" title="继续(F8)"><i class="iconfont icon-continue"></i></span>
 				</div>
-				<div class="layui-right-container">
-					<div class="properties-container layui-form">
-						<div class="layui-input-placeholder">
-							<div class="layui-input-inline" style="width: 150px;margin-left: 145px;">接口分组</div>
-							<div class="layui-input-inline" style="width: 100px;margin-left: 5px;">请求方法</div>
-							<div class="layui-input-inline" style="width: 200px;margin-left: 5px;">接口名称</div>
-							<div class="layui-input-inline" style="width: 300px;margin-left: 5px;">接口地址</div>
-						</div>
-						<div>
-							<ul class="layui-btn-group">
-								<li title="新增" class="btn-create"><i class="layui-icon layui-icon-add-1"></i></li>
-								<li title="测试(Ctrl+Q)" class="btn-test"><i class="layui-icon layui-icon-triangle-r"></i></li>
-								<li title="保存(Ctrl+S)" class="btn-save"><i class="layui-icon layui-icon-release"></i></li>
-								<li title="删除" class="btn-delete"><i class="layui-icon layui-icon-delete"></i></li>
-							</ul>
-							<div class="layui-input-inline" style="width: 150px;margin-left: 5px;">
-								<select name="group" lay-search>
-									<option value="">请输入组名</option>
-									<option value="未分组">未分组</option>
-								</select>
-							</div>
-							<div class="layui-input-inline" style="width: 100px;margin-left: 5px;">
-								<select name="method">
-									<option value="GET">GET</option>
-									<option value="POST">POST</option>
-									<option value="PUT">PUT</option>
-									<option value="DELETE">DELETE</option>
-								</select>
-							</div>
-							<div class="layui-input-inline" style="width: 200px;margin-left: 5px;">
-								<input type="text" name="name" class="layui-input" placeholder="请输入接口名称"/>
-							</div>
-							<div class="layui-input-inline" style="position: absolute;left:615px;right:10px;">
-								<input type="text" name="path" class="layui-input" placeholder="请输入接口地址"/>
-							</div>
-						</div>
-					</div>
-					<div class="editor-container" id="editor"></div>
-					<div class="layout-resizer-x"></div>
-					<div class="layui-right">
-						<div class="request-container">
-							<div class="layui-tab" lay-filter="request">
-								<ul class="layui-tab-title">
-									<li class="layui-this">请求参数</li>
-									<li>接口选项</li>
-								</ul>
-								<div class="layui-tab-content">
-									<div class="layui-tab-item layui-show">
-										<div id="request-parameter"></div>
-									</div>
-									<div class="layui-tab-item">
-										<div id="option-parameter"></div>
-									</div>
-								</div>
-							</div>
-						</div>
-						<div class="layout-resizer-y"></div>
-						<div class="output-container">
-							<div class="layui-tab" lay-filter="output-container">
-								<ul class="layui-tab-title">
-									<li lay-id="output" class="layui-this">请求结果</li>
-									<li lay-id="debug">调试信息</li>
-								</ul>
-								<div class="layui-tab-content">
-									<div class="layui-tab-item layui-show">
-										<div id="output-result"></div>
-									</div>
-									<div class="layui-tab-item scroller">
-										<table class="layui-table" lay-size="sm" style="height: auto">
-											<thead>
-											<tr>
-												<th>变量名</th>
-												<th>变量值</th>
-												<th>变量类型</th>
-											</tr>
-											</thead>
-											<tbody id="debug-tbody">
-
-											</tbody>
-										</table>
-									</div>
-								</div>
-							</div>
-						</div>
-					</div>
+				<div class="bottom-item-body">
+					<table>
+						<thead>
+						<tr>
+							<th>变量名称</th>
+							<th>变量值</th>
+							<th>变量类型</th>
+						</tr>
+						</thead>
+						<tbody>
+						<tr>
+							<td colspan="3" align="center">no message.</td>
+						</tr>
+						</tbody>
+					</table>
 				</div>
 			</div>
 		</div>
-	</body>
-</html>
+		<ul class="bottom-tab not-select">
+			<li class="selected"><i class="iconfont icon-parameter"></i>请求参数</li>
+			<li><i class="iconfont icon-options"></i>接口选项</li>
+			<li><i class="iconfont icon-run"></i>执行结果</li>
+			<li><i class="iconfont icon-debug-info"></i>调试信息</li>
+		</ul>
+	</div>
+</div>
+<div class="footer-container"></div>
+</body>
+</html>

+ 949 - 488
src/main/resources/magicapi-support/js/index.js

@@ -1,336 +1,382 @@
-var $ = layui.$;
-var apiList = [];
-var apiId;
-var debugSessionId;
-var _ajax = function(options){
-    $.ajax({
-        url : options.url,
-        async : options.async,
-        type : 'post',
-        dataType : 'json',
-        contentType : options.contentType,
-        data : options.data,
-        success : function(json){
-            if(json.code == 1){
-                options&&options.success(json.data,json);
-            }else if(options.exception){
-                options.exception(json.code,json.message,json);
-            }else{
-                layui.layer.alert(json.message);
-            }
-        },
-        error : function(){
-            layui.layer.alert('ajax请求失败');
-            options.error&&options.error();
+var MagicEditor = {
+    init : function(){
+        var skin = this.getValue('skin');
+        if(skin){
+            $('body').addClass('skin-' + skin);
         }
-    })
-}
-$(function(){
-    layui.form.render();
-    //更新检测
-    $.ajax({
-        url : 'https://img.shields.io/maven-central/v/org.ssssssss/magic-api.json',
-        dataType : 'json',
-        success : function(data){
-            if(data.value != 'v0.2.0'){
-                layui.layer.alert('检测到已有新版本'+data.value+',是否更新?',{
-                    title : '更新提示',
-                    btn : ['更新日志','残忍拒绝']
-                },function(index){
-                    layui.layer.close(index);
-                    window.open('http://www.ssssssss.org/changelog.html')
-                })
+        this.apiId = null;
+        this.apiList = [];
+        this.debugSessionId = null;
+        this.defaultRequestValue = '{\r\n\t"request" : {\r\n\t\t"message" : "Hello MagicAPI!"\r\n\t},\r\n\t"path" : {\r\n\t\t"id" : "123456"\r\n\t},\r\n\t"header" : {\r\n\t\t"token" : "tokenValue"\r\n\t},\r\n\t"cookie" : {\r\n\t\t"cookieName" : "cookieValue"\r\n\t},\r\n\t"session" : {\r\n\t\t"userId" : "123"\r\n\t}\r\n}';
+        this.initMTA();
+        this.loadAPI();
+        this.initShortKey();
+        this.initSkin();
+        this.initLeftToobarContainer();
+        this.initBottomContainer();
+        this.initSelect();
+        this.initContextMenu();
+        this.initScriptEditor();
+        this.resetEditor();
+        this.checkUpdate();
+    },
+    initSkin : function(){
+        var skinSelector = $('.skin-selector');
+        $('.button-skin').on('click',function(){
+            skinSelector.toggle();
+            return false;
+        });
+        var $body = $('body');
+        $body.on('click',function(){
+            skinSelector.hide();
+        })
+        var _this = this;
+        skinSelector.on('click','li',function(){
+            skinSelector.hide();
+            $(this).siblings().each(function(){
+                $body.removeClass('skin-' + $(this).text())
+            })
+            _this.setSkin($(this).text());
+        })
+    },
+    resetEditor : function(){
+        $('input[name=group]').val('未分组');
+        $('input[name=method]').val('GET');
+        $('input[name=name]').val('');
+        $('input[name=path]').val('');
+        this.apiId = null;
+        this.scriptEditor&&this.scriptEditor.setValue('return message;');
+        this.requestEditor && this.requestEditor.setValue(this.defaultRequestValue);
+        this.resultEditor&&this.resultEditor.setValue('');
+        this.optionsEditor && this.optionsEditor.setValue('{\r\n}');
+    },
+    addBreakPoint : function(line){
+        var model = this.scriptEditor.getModel();
+        model.deltaDecorations([],[{
+            range : new monaco.Range(line, 1, line, 1),
+            options: {
+                isWholeLine: true,
+                linesDecorationsClassName: 'breakpoints',
+                className : 'breakpoint-line',
             }
+        }])
+    },
+    removeBreakPoint : function(line){
+        var model = this.scriptEditor.getModel();
+        var decorations = [];
+        if (line !== undefined) {
+            decorations = model.getLineDecorations(line);
+        } else {
+            decorations = model.getAllDecorations();
         }
-    })
-    var editor;
-    var requestEditor;
-    var outputEditor;
-    var optionEditor;
-    var editorLayout = function(){
-        editor&&editor.layout();
-        requestEditor&&requestEditor.layout();
-        optionEditor && optionEditor.layout();
-        outputEditor&&outputEditor.layout();
-    }
-    var defaultRequestValue = '{\r\n\t"request" : {\r\n\t\t"message" : "Hello MagicAPI!"\r\n\t},\r\n\t"path" : {\r\n\t\t"id" : "123456"\r\n\t},\r\n\t"header" : {\r\n\t\t"token" : "tokenValue"\r\n\t},\r\n\t"cookie" : {\r\n\t\t"cookieName" : "cookieValue"\r\n\t},\r\n\t"session" : {\r\n\t\t"userId" : "123"\r\n\t}\r\n}';
-    var resetEditor = function(){
-        resetGroup('未分组')
-        editor&&editor.setValue('return message;');
-        requestEditor && requestEditor.setValue(defaultRequestValue);
-        outputEditor&&outputEditor.setValue('');
-        optionEditor && optionEditor.setValue('{\r\n}');
-    }
-    var addBreakPoint = function(line){
-        if(editor){
-            var model = editor.getModel();
-            model.deltaDecorations([],[{
-                range : new monaco.Range(line, 1, line, 1),
-                options: {
-                    isWholeLine: true,
-                    linesDecorationsClassName: 'breakpoints',
-                    className : 'breakpoint-line',
-                }
-            }])
-        }
-    }
-    var removeBreakPoint = function(line){
-        if(editor) {
-            var model = editor.getModel();
-            var decorations = [];
-            if (line !== undefined) {
-                decorations = model.getLineDecorations(line);
-            } else {
-                decorations = model.getAllDecorations();
-            }
-            var ids = [];
-            for (var i=0,len =decorations.length;i<len;i++) {
-                if (decorations[i].options.linesDecorationsClassName === 'breakpoints') {
-                    ids.push(decorations[i].id)
-                }
+        var ids = [];
+        for (var i=0,len =decorations.length;i<len;i++) {
+            if (decorations[i].options.linesDecorationsClassName === 'breakpoints') {
+                ids.push(decorations[i].id)
             }
-            model.deltaDecorations(ids, [])
         }
-    }
-    var hasBreakPoint = function(line){
-        var decorations = editor.getLineDecorations(line);
+        model.deltaDecorations(ids, [])
+    },
+    hasBreakPoint : function(line){
+        var decorations = this.scriptEditor.getLineDecorations(line);
         for (var i=0,len =decorations.length;i<len;i++) {
             if (decorations[i].options.linesDecorationsClassName === 'breakpoints') {
                 return true;
             }
         }
-    }
-
-    var loadAPI = function () {
-        _ajax({
-            url : 'list',
-            success : function(list){
-                apiList = list;
-                renderApiList();
+    },
+    renderApiList : function(){
+        var empty = true;
+        var root = [];
+        var groups = {
+            "未分组" : {
+                id : '未分组',
+                children : [],
+                spread : true,
+                title : '未分组'
             }
-        })
-    }
-    var deleteAPIGroup = function(groupName,ids){
-        _ajax({
-            url : 'group/delete',
-            data : {
-                apiIds : ids.join(','),
-                groupName : groupName
-            },
-            success : function(){
-                loadAPI();
+        };
+        var apiList = this.apiList;
+        if(apiList&&apiList.length > 0){
+            for(var i=0,len = apiList.length;i<len;i++){
+                var info = apiList[i];
+                info.groupName = info.groupName || '未分组';
+                if(!groups[info.groupName]){
+                    groups[info.groupName] = {
+                        id : info.groupName,
+                        children : [],
+                        spread : true,
+                        title : info.groupName
+                    }
+                }
+                if(info.show!==false){
+                    groups[info.groupName].children.push({
+                        id : info.id,
+                        groupName : info.groupName,
+                        name : info.name,
+                        title : '<label style="padding-right: 4px;color:#000">' + info.name + "</label>" + info.path,
+                        path : info.path
+                    });
+                }
             }
-        })
-    }
-
-    var deleteAPI = function(id){
-        _ajax({
-            url : 'delete',
-            data : {
-                id : id
-            },
-            success : function(){
-                loadAPI();
+        }
+        var $dom = $('.api-list-container').html('');
+        for(var key in groups){
+            var $item = $('<div/>').addClass('group-item')
+                .addClass('opened')
+                .append($('<div/>').addClass('group-header').append('<i class="iconfont icon-arrow-bottom"></i><i class="iconfont icon-list"></i>').append(key));
+            var $ul = $('<ul/>').addClass('group-list');
+            for(var i =0,len = groups[key].children.length;i<len;i++){
+                var info = groups[key].children[i];
+                $ul.append($('<li/>').attr('data-id',info.id).append('<i class="iconfont icon-script"></i>')
+                    .append('<label>'+info.name+'</label>')
+                    .append('<span>('+info.path+')</span>'));
             }
-        })
-    }
+            $item.append($ul);
+            $dom.append($item);
+        }
+    },
+    loadAPI : function(id){
+        var _this = this;
+        if(id){
+            this.ajax({
+                url : 'get',
+                data : {
+                    id : id
+                },
+                success : function(info){
+                    _this.resetEditor();
+                    _this.apiId = id;
+                    $('.button-delete').removeClass('disabled');
+                    $('input[name=name]').val(info.name);
+                    $('input[name=path]').val(info.path);
+                    MagicEditor.setStatusBar('编辑接口:' + info.name + '(' + info.path + ')')
+                    $('select[name=method]').val(info.method);
+                    $('select[name=group]').val(info.groupName || '未分组');
+                    $('.button-run,.button-delete').removeClass('disabled');
+                    _this.scriptEditor && _this.scriptEditor.setValue(info.script);
+                    _this.requestEditor && _this.requestEditor.setValue(info.parameter || _this.defaultRequestValue);
+                    _this.optionsEditor && _this.optionsEditor.setValue(info.option || '{\r\n}');
 
-    var resetGroup = function(selValue){
-        var $dom = $("select[name='group']").next().find("input");
-        $dom.unbind("blur");
-        if(!$dom.attr('bind-event')){
-            $dom.attr('bind-event','true');
-            $dom.css({
-                "cursor" : "default"
+                }
             })
-            $dom.focus(function () {
-                window.setTimeout(function(){
-                    var sourceSelect =  $dom.next();
-                    var selectText = $(sourceSelect).find(".layui-anim-upbit .layui-this");
-                    var selectVal = $(sourceSelect).find("input").val();
-                    if (selectVal !== selectText.text()) {
-                        $(selectText).removeClass("layui-this");
-                    }
-                },100)
+        }else{
+            this.ajax({
+                url : 'list',
+                success : function(list){
+                    _this.apiList = list;
+                    _this.renderApiList();
+                }
             })
         }
-        if(selValue !== undefined){
-            $dom.val(selValue);
-        }
-        return $dom;
-    }
-    _ajax({
-        url: 'classes',
-        success: function (data) {
-            Parser.scriptClass = data || {};
-        }
-    })
-    resetGroup();
-    // 初始化编辑器
-    require(['vs/editor/editor.main'], function() {
-        requestEditor = monaco.editor.create(document.getElementById('request-parameter'), {
-            minimap : {
-                enabled : false
-            },
-            language: 'json',
-            folding:false,
-            fixedOverflowWidgets :true,
-            theme : 'json'
-        });
-        optionEditor = monaco.editor.create(document.getElementById('option-parameter'), {
-            minimap: {
-                enabled: false
-            },
-            language: 'json',
-            folding: false,
-            fixedOverflowWidgets: true,
-            theme: 'json'
-        });
-        outputEditor = monaco.editor.create(document.getElementById('output-result'), {
-            minimap : {
-                enabled : false
-            },
-            language: 'json',
-            folding:false,
-            readOnly : true,
-            fixedOverflowWidgets :true,
-            theme : 'json'
-        });
-        editor = monaco.editor.create(document.getElementById('editor'), {
-            minimap : {
-                enabled : false
-            },
-            language: 'magicscript',
-            fixedOverflowWidgets :true,
-            theme : 'magicscript'
-        });
-        resetEditor();
-        editor.onMouseDown(function(e){
-            if (e.target.detail && e.target.detail.offsetX && e.target.detail.offsetX >= 0 && e.target.detail.offsetX <= 60) {
-                var line = e.target.position.lineNumber;
-                if (editor.getModel().getLineContent(line).trim() === '') {
-                    return
+    },
+    createNew : function(){
+        MagicEditor.createDialog({
+            title : '新建接口',
+            content : '新建接口会清空当前编辑器,是否继续?',
+            buttons : [{
+                name : '继续',
+                click : function(){
+                    $('.group-item .group-list li.selected').removeClass('selected');
+                    MagicEditor.resetEditor();
+                    $('.button-delete').addClass('disabled');
+                    MagicEditor.setStatusBar('创建接口');
                 }
-                if(hasBreakPoint(line)){
-                    removeBreakPoint(line);
-                }else{
-                    addBreakPoint(line);
-                }
-            }
-        });
-    });
-
-    var formatJson = function (val, defaultVal) {
-        return (val ? JSON.stringify(val, null, 4) : defaultVal) || '';
-    }
-
-    var $tbody = $('#debug-tbody');
-    var debugDecorations;
-    var debugIn = function(id,data){
-        debugSessionId = id;
-        for(var i =0,len = data.variables.length;i<len;i++){
-            var item = data.variables[i];
-            var $tr = $('<tr/>');
-            $tr.append($('<td/>').html(item.name))
-            $tr.append($('<td/>').html(item.value))
-            $tr.append($('<td/>').html(item.type))
-            $tbody.append($tr);
-        }
-        debugDecorations = [editor&&editor.deltaDecorations([],[{
-            range :  new monaco.Range(data.range[0],1,data.range[0],1),
-            options: {
-                isWholeLine: true,
-                inlineClassName : 'debug-line',
-                className : 'debug-line',
-            }
-        }])];
-    }
-    var doSave = function(){
-        var name = $('input[name=name]').val();
-        var path = $('input[name=path]').val();
-        var method = $('select[name=method]').val();
-        var groupName = resetGroup().val() || '未分组';
-        _ajax({
-            url : 'save',
-            data : {
-                script : editor.getValue(),
-                path : path,
-                method : method,
-                id : apiId,
-                groupName : groupName,
-                parameter: requestEditor.getValue(),
-                option: optionEditor.getValue(),
-                name : name
-            },
-            async : false,
-            success : function(id){
-                if(apiId){
-                    for(var i=0,len = apiList.length;i<len;i++){
-                        if(apiList[i].id == apiId){
-                            apiList[i].name = name;
-                            apiList[i].path = path;
-                            apiList[i].method = method;
-                            apiList[i].groupName = groupName;
-                            break;
+            },{
+                name : '取消'
+            }]
+        })
+    },
+    setStatusBar : function(value){
+        $('.footer-container').html(value);
+    },
+    initMTA : function(){
+        window._mtac = {};
+        var mta = document.createElement("script");
+        mta.src = "//pingjs.qq.com/h5/stats.js?v2.0.4";
+        mta.setAttribute("name", "MTAH5");
+        mta.setAttribute("sid", "500724136");
+        mta.setAttribute("cid", "500724141");
+        var s = document.getElementsByTagName("script")[0];
+        s.parentNode.insertBefore(mta, s);
+        this.report('visit');
+    },
+    deleteGroup : function($header){
+        var groupName = $header.text();
+        MagicEditor.createDialog({
+            title : '删除接口分组',
+            content : '是否要删除接口分组「'+groupName + '」',
+            buttons : [{
+                name : '删除',
+                click : function(){
+                    MagicEditor.report('group_delete');
+                    var ids = [];
+                    $header.next().find('li').each(function(){
+                        ids.push($(this).data('id'));
+                    });
+                    MagicEditor.setStatusBar('准备删除接口分组「'+groupName + '」');
+                    MagicEditor.ajax({
+                        url : 'group/delete',
+                        data : {
+                            apiIds : ids.join(','),
+                            groupName : groupName
+                        },
+                        success : function(){
+                            MagicEditor.setStatusBar('接口分组「'+groupName + '」已删除');
+                            MagicEditor.loadAPI();  //重新加载
                         }
+                    })
+                }
+            },{
+                name : '取消'
+            }]
+        })
+    },
+    report : function(eventId){
+        try{
+            MtaH5.clickStat(eventId);
+        }catch(ignored){}
+    },
+    deleteApi : function($li){
+        var text = $li.text();
+        MagicEditor.createDialog({
+            title : '删除接口',
+            content : '是否要删除接口「'+text + '」',
+            buttons : [{
+                name : '删除',
+                click : function(){
+                    MagicEditor.setStatusBar('准备删除接口');
+                    MagicEditor.report('script_delete')
+                    var apiId = $li.data('id');
+                    if(MagicEditor.apiId == apiId){
+                        MagicEditor.apiId = null;
                     }
-                }else{
-                    apiId = id;
-                    apiList.unshift({
-                        id : id,
-                        name : name,
-                        path : path,
-                        method : method,
-                        groupName : groupName || '未分组',
-                        show : true
+                    MagicEditor.ajax({
+                        url : 'delete',
+                        data : {
+                            id : apiId
+                        },
+                        success : function(){
+                            MagicEditor.setStatusBar('接口「'+text + '」已删除');
+                            MagicEditor.loadAPI();  //重新加载
+                        }
                     })
                 }
-                renderApiList();
-                layui.layer.msg('保存成功');
+            },{
+                name : '取消'
+            }]
+        })
+    },
+    ajax : function(options){
+        $.ajax({
+            url : options.url,
+            async : options.async,
+            type : 'post',
+            dataType : 'json',
+            contentType : options.contentType,
+            data : options.data,
+            success : function(json){
+                if(json.code == 1){
+                    options&&options.success(json.data,json);
+                }else{
+                    var val = options.exception&&options.exception(json.code,json.message,json);
+                    if(val !== false){
+                        MagicEditor.createDialog({
+                            title : 'Error',
+                            content : json.message,
+                            buttons : [{name : 'OK'}]
+                        });
+                    }
+                }
+            },
+            error : function(){
+                MagicEditor.setStatusBar('ajax请求失败');
+                MagicEditor.createDialog({
+                    title : '网络错误',
+                    content : 'ajax请求失败',
+                    buttons : [{
+                        name : '关闭'
+                    }]
+                });
+                options.error&&options.error();
             }
         })
-    }
-    var doContinue = function(){
-        if($('.btn-continue').hasClass('disabled')){
+    },
+    copyApi : function(){
+        MagicEditor.createDialog({
+            title : '复制接口',
+            content : '功能暂未实现!',
+            buttons : [{name : '知道了'}]
+        })
+    },
+    copyApiPath : function(){
+        MagicEditor.createDialog({
+            title : '复制接口路径',
+            content : '功能暂未实现!',
+            buttons : [{name : '知道了'}]
+        })
+    },
+    resetDebugContent : function(){
+        $('.bottom-item-body table tbody').html('<tr><td colspan="3" align="center">no message.</td></tr>');
+    },
+    doContinue : function(){
+        if($('.button-continue').hasClass('disabled')){
             return;
         }
-        $('.btn-continue').addClass('disabled');
-        if(debugSessionId){
-            _ajax({
+        if(this.debugSessionId){
+            MagicEditor.resetDebugContent();
+            $('.button-continue').addClass('disabled');
+            var _this = this;
+            this.ajax({
                 url : 'continue',
                 data : {
-                    id : debugSessionId
+                    id : this.debugSessionId
                 },
                 success : function(data,json){
-                    convertResult(json.code,json.message,json);
+                    _this.convertResult(json.code,json.message,json);
                 },
                 exception : function(code,message,json){
-                    convertResult(code,message,json);
+                    return _this.convertResult(code,message,json);
                 },
                 error : function(){
-                    $(".btn-test,.btn-continue").addClass('btn-test').removeClass('btn-continue').removeClass('disabled').find('.layui-icon-next').removeClass('layui-icon-next').addClass('layui-icon-triangle-r').parent('li').attr('title','测试(Ctrl+Q)');
+                    $('.button-run').removeClass('disabled');
                 }
             })
         }
-    }
-    var doTest = function(){
-        if($('.btn-test').hasClass('disabled')){
+    },
+    doTest : function(){
+        if($('.button-run').hasClass('disabled')){
             return;
         }
-        var request = requestEditor.getValue();
+        var request = this.requestEditor.getValue();
         try{
             request = JSON.parse(request);
             if(typeof request != 'object'){
-                layui.layer.alert('请求参数有误!');
+                MagicEditor.setStatusBar('请求参数有误!');
+                this.createDialog({
+                    title : '运行测试',
+                    content : '请求参数有误!',
+                    buttons : [{
+                        name : '确定'
+                    }]
+                });
                 return;
             }
         }catch(e){
-            layui.layer.alert('请求参数有误!');
+            MagicEditor.setStatusBar('请求参数有误!');
+            this.createDialog({
+                title : '运行测试',
+                content : '请求参数有误!',
+                buttons : [{
+                    name : '确定'
+                }]
+            });
             return;
         }
-        $('.btn-test').addClass('disabled');
-        request.script = editor.getValue();
-        var decorations = editor.getModel().getAllDecorations();
+        MagicEditor.setStatusBar('开始测试...');
+        MagicEditor.report('run');
+        request.script = this.scriptEditor.getValue();
+        var decorations = this.scriptEditor.getModel().getAllDecorations();
         var breakpoints = [];
         for (var i=0,len =decorations.length;i<len;i++) {
             if (decorations[i].options.linesDecorationsClassName === 'breakpoints') {
@@ -338,30 +384,96 @@ $(function(){
             }
         }
         request.breakpoints = breakpoints;
-        _ajax({
+        this.resetDebugContent();
+        $('.button-run').addClass('disabled');
+        $('.button-continue').addClass('disabled');
+        var _this = this;
+        this.ajax({
             url : 'test',
             data : JSON.stringify(request),
             contentType : 'application/json;charset=utf-8',
             success : function(data,json){
-                convertResult(json.code,json.message,json);
+                _this.convertResult(json.code,json.message,json);
             },
             exception : function(code,message,json){
-                convertResult(code,message,json);
+                return _this.convertResult(code,message,json);
             }
         })
-    }
-
-    var convertResult = function(code,message,json){
-        debugSessionId = null;
-        $tbody.html('');
-        debugDecorations&&editor&&editor.deltaDecorations(debugDecorations,[]);
-        debugDecorations = null;
+    },
+    doSave : function(){
+        if($('.button-save').hasClass('disabled')){
+            return;
+        }
+        $('.button-save').addClass('disabled');
+        var name = $('input[name=name]').val();
+        var path = $('input[name=path]').val();
+        var method = $('input[name=method]').val();
+        var groupName = $('input[name=group]').val();
+        this.setStatusBar('准备保存接口:' + name + "(" + path + ")");
+        var _this = this;
+        this.ajax({
+            url : 'save',
+            data : {
+                script : this.scriptEditor.getValue(),
+                path : path,
+                method : method,
+                id : this.apiId,
+                groupName : groupName,
+                parameter: this.requestEditor.getValue(),
+                option: this.optionsEditor.getValue(),
+                name : name
+            },
+            async : false,
+            exception : function(){
+                $('.button-save').removeClass('disabled');
+            },
+            error : function(){
+                $('.button-save').removeClass('disabled');
+            },
+            success : function(id){
+                $('.button-save,.button-delete').removeClass('disabled');
+                if(_this.apiId){
+                    _this.report('script_save');
+                    for(var i=0,len = _this.apiList.length;i<len;i++){
+                        if(_this.apiList[i].id == _this.apiId){
+                            _this.apiList[i].name = name;
+                            _this.apiList[i].path = path;
+                            _this.apiList[i].method = method;
+                            _this.apiList[i].groupName = groupName;
+                            break;
+                        }
+                    }
+                }else{
+                    _this.report('script_add');
+                    _this.apiId = id;
+                    _this.apiList.unshift({
+                        id : id,
+                        name : name,
+                        path : path,
+                        method : method,
+                        groupName : groupName || '未分组',
+                    })
+                }
+                _this.setStatusBar('保存成功!');
+                _this.renderApiList();
+            }
+        })
+    },
+    convertResult : function(code,message,json){
+        this.debugSessionId = null;
+        this.resetDebugContent();
+        this.debugDecorations&&this.scriptEditor&&this.scriptEditor.deltaDecorations(this.debugDecorations,[]);
+        this.debugDecorations = null;
+        var _this = this;
         if(code === -1000){
-            $(".btn-continue,.btn-test").addClass('btn-test').removeClass('.btn-continue');
-            layui.element.tabChange('output-container', 'output');
+            MagicEditor.setStatusBar('脚本执行出错..');
+            MagicEditor.report('script_error');
+            $(".button-run").removeClass('disabled');
+            $('.button-continue').addClass('disabled');
+            this.navigateTo(2);
             if (json.body) {
                 var line = json.body;
-                var decorations = editor&&editor.deltaDecorations([],[{
+                var decorations = this.scriptEditor&&this.scriptEditor.deltaDecorations([],[{
                     range: new monaco.Range(line[0], line[2], line[1], line[3] + 1),
                     options : {
                         hoverMessage : {
@@ -371,216 +483,565 @@ $(function(){
                     }
                 }])
                 setTimeout(function(){
-                    editor&&editor.deltaDecorations(decorations,[])
+                    _this.scriptEditor&&_this.scriptEditor.deltaDecorations(decorations,[])
                 },10000)
             }
         }else if(code === 1000){ // debug断点
-            $(".btn-test,.btn-continue").addClass('btn-continue').removeClass('btn-test').removeClass('disabled').find('.layui-icon-triangle-r').removeClass('layui-icon-triangle-r').addClass('layui-icon-next').parent('li').attr('title','继续(F8)');
-            layui.element.tabChange('output-container', 'debug');
-            debugIn(message, json.body);
-            return;
+            $(".button-run").addClass('disabled');
+            $('.button-continue').removeClass('disabled');
+            this.navigateTo(3);
+            this.debugIn(message, json.body);
+            return false;
         }
-        $(".btn-test,.btn-continue").addClass('btn-test').removeClass('btn-continue').removeClass('disabled').find('.layui-icon-next').removeClass('layui-icon-next').addClass('layui-icon-triangle-r').parent('li').attr('title','测试(Ctrl+Q)');
-        layui.element.tabChange('output-container', 'output');
-        outputEditor.setValue(formatJson(json.data))
-    }
-    // 窗口改变大小时,刷新编辑器
-    $(window).resize(editorLayout);
-    var $tree;
-    // 渲染接口列表
-    var renderApiList = function(){
-        var $ul = $(".layui-left .api-list").html('');
-        var empty = true;
-        var root = [];
-        var groups = {
-            "未分组" : {
-                id : '未分组',
-                children : [],
-                spread : true,
-                title : '未分组'
+        MagicEditor.setStatusBar('脚本执行完毕');
+        $(".button-run").removeClass('disabled');
+        $('.button-continue').addClass('disabled');
+        this.navigateTo(2)
+        this.resultEditor.setValue(this.formatJson(json.data))
+    },
+    debugIn : function(id,data){
+        MagicEditor.setStatusBar('进入断点...');
+        MagicEditor.report('debug_in');
+        this.debugSessionId = id;
+        if(data.variables.length > 0){
+            var $tbody = $('.bottom-item-body table tbody').html('');
+            for(var i =0,len = data.variables.length;i<len;i++){
+                var item = data.variables[i];
+                var $tr = $('<tr/>');
+                $tr.append($('<td/>').html(item.name))
+                $tr.append($('<td/>').html(item.value))
+                $tr.append($('<td/>').html(item.type))
+                $tbody.append($tr);
             }
-        };
-        if(apiList&&apiList.length > 0){
-            for(var i=0,len = apiList.length;i<len;i++){
-                var info = apiList[i];
-                info.groupName = info.groupName || '未分组';
-                if(!groups[info.groupName]){
-                    groups[info.groupName] = {
-                        id : info.groupName,
-                        children : [],
-                        spread : true,
-                        title : info.groupName
-                    }
+        }else{
+            this.resetDebugContent();
+        }
+        this.debugDecorations = [this.scriptEditor&&this.scriptEditor.deltaDecorations([],[{
+            range :  new monaco.Range(data.range[0],1,data.range[0],1),
+            options: {
+                isWholeLine: true,
+                inlineClassName : 'debug-line',
+                className : 'debug-line',
+            }
+        }])];
+    },
+    // 初始化快捷键
+    initShortKey : function(){
+        var _this = this;
+        $('body').on('keydown',function(e){
+            if(e.keyCode == 119){ //F8
+                _this.doContinue();
+                e.preventDefault();
+            }else if(e.keyCode == 81 && (e.metaKey || e.ctrlKey)){  //Ctrl + Q
+                _this.doTest();
+                e.preventDefault();
+            }else if(e.keyCode == 83 && (e.metaKey || e.ctrlKey)){  //Ctrl + S
+                _this.doSave();
+                e.preventDefault();
+            }else if(e.keyCode == 78 && e.altKey){  //Ctrl + O
+                _this.createNew();
+                e.preventDefault();
+            }
+        })
+    },
+    //检测更新
+    checkUpdate : function(){
+        var _this = this;
+        $.ajax({
+            url : 'https://img.shields.io/maven-central/v/org.ssssssss/magic-api.json',
+            dataType : 'json',
+            success : function(data){
+                if(data.value != 'v0.2.1'){
+                    _this.createDialog({
+                        title : '更新提示',
+                        content : '检测到已有新版本'+data.value+',是否更新?',
+                        buttons : [{
+                            name : '更新日志',
+                            click : function(){
+                                window.open('http://www.ssssssss.org/changelog.html')
+                            }
+                        },{
+                            name : '残忍拒绝'
+                        }]
+                    })
+                    MagicEditor.setStatusBar('版本检测完毕,最新版本为:' + data.value+',建议更新!!');
+                }else{
+                    MagicEditor.setStatusBar('版本检测完毕,当前已是最新版');
                 }
-                if(info.show!==false){
-                    groups[info.groupName].children.push({
-                        id : info.id,
-                        groupName : info.groupName,
-                        name : info.name,
-                        title : '<label style="padding-right: 4px;color:#000">' + info.name + "</label>" + info.path,
-                        path : info.path
-                    });
+            },
+            error : function(){
+                MagicEditor.setStatusBar('版本检测失败');
+            }
+        })
+    },
+    //初始化右键菜单
+    initContextMenu : function(){
+        var _this = this;
+        $('.api-list-container').on('contextmenu','.group-header',function(e){
+            _this.createContextMenu([{
+                name : '新建接口',
+                shortKey : 'Alt+N',
+                click : _this.createNew
+            },{
+                name : '删除组',
+                shortKey : '',
+                click : _this.deleteGroup
+            }],e.pageX,e.pageY,$(this));
+            return false;
+        }).on('contextmenu','.group-list li',function(e){
+            var $li = $(this);
+            _this.createContextMenu([{
+                name : '复制接口',
+                shortKey : 'Ctrl+C',
+                click : _this.copyApi,
+            },{
+                name : '复制路径',
+                shortKey : 'Ctrl+Shift+C',
+                click : _this.copyApiPath
+            },{
+                name : '移动',
+                shortKey : 'Ctrl+M',
+                click : function(){
+                    _this.createDialog({
+                        title : '移动接口',
+                        content : '功能暂未实现!',
+                        buttons : [{name : '知道了'}]
+                    })
+                }
+            },{
+                name : '删除接口',
+                shortKey : '',
+                click : _this.deleteApi
+            }],e.pageX,e.pageY,$li)
+            return false;
+        }).on('contextmenu',function(){
+            return false;
+        })
+    },
+    initSelect : function(){
+        var _this = this;
+        $('body').on('click','.select',function(){
+            $('.select ul').hide();
+            $(this).find('ul').show();
+            return false;
+        }).on('click','.select ul li',function(){
+            var $this = $(this);
+            $this.parent().hide().parent().find('input').val($this.text());
+            $this.addClass('selected').siblings().removeClass('selected');
+            return false;
+        }).on('click',function(){
+            $('.select ul').hide();
+        }).on('click','.api-list-container ul li',function(){
+            $('.api-list-container ul li.selected').removeClass('selected');
+            _this.loadAPI($(this).addClass('selected').data('id'))
+        }).on('click','.button-run',function(){
+            _this.doTest();
+        }).on('click','.button-delete',function(){
+            if($(this).hasClass('disabled')){
+                return;
+            }
+            if(_this.apiId){
+                var $li = $('.group-list li[data-id='+_this.apiId+']');
+                if($li.length > 0){
+                    _this.deleteApi($li);
                 }
             }
+        }).on('click','.button-save',function(){
+            _this.doSave();
+        }).on('click','.button-continue',function(){
+            _this.doContinue();
+        }).on('click','.button-gitee',function(){
+            MagicEditor.report('button-gitee');
+            window.open('https://gitee.com/ssssssss-team/magic-api');
+        }).on('click','.button-github',function(){
+            MagicEditor.report('button-github');
+            window.open('https://github.com/ssssssss-team/magic-api')
+        }).on('click','.button-qq',function(){
+            window.open('https://shang.qq.com/wpa/qunwpa?idkey=10faa4cf9743e0aa379a72f2ad12a9e576c81462742143c8f3391b52e8c3ed8d')
+        }).on('click','.button-help',function(){
+            MagicEditor.report('button-help');
+            window.open('https://ssssssss.org')
+        });
+    },
+    getValue : function(key){
+        return localStorage&&localStorage.getItem(key) || '';
+    },
+    setValue : function(key,value){
+        if(Array.isArray(value) || typeof value == 'object'){
+            value = JSON.stringify(value);
         }
-        for(var key in groups){
-            root.push(groups[key]);
-        }
-        if($tree){
-            layui.tree.reload('api-list',{
-                data : root
-            })
-        }else{
-            $tree = layui.tree.render({
-                elem : '#api-list',
-                id : 'api-list',
-                data : root,
-                edit : ['del'],
-                onlyIconControl : true,
-                operate : function(obj){
-                    var data = obj.data;
-                    if(data.children){
-                        var ids = [];
-                        for(var i=0,len=data.children.length;i<len;i++){
-                            ids.push(data.children[i].id);
-                            if(data.children[i].id == apiId){
-                                apiId = null;
-                                resetEditor();
-                            }
-                        }
-                        deleteAPIGroup(data.id,ids);
-                    }else{
-                        deleteAPI(data.id)
-                    }
-                    if(data.id == apiId){
-                        apiId = null;
-                        resetEditor();
-                    }
-                },
-                click : function(obj){
-                    if(!obj.data.children){
-                        var id = obj.data.id;
-                        _ajax({
-                            url : 'get',
-                            data : {
-                                id : id
-                            },
-                            success : function(info){
-                                apiId = id;
-                                $('input[name=name]').val(info.name);
-                                $('input[name=path]').val(info.path);
-                                $('select[name=method]').val(info.method);
-                                layui.form.render();
-                                resetEditor();
-                                resetGroup().val(info.groupName || '未分组');
-                                editor && editor.setValue(info.script);
-                                requestEditor && requestEditor.setValue(info.parameter || defaultRequestValue);
-                                optionEditor && optionEditor.setValue(info.option || '{\r\n}');
+        localStorage&&localStorage.setItem(key,value) || '';
+    },
+    bindEditorShortKey : function(editor){
+        // Alt + / 代码提示
+        editor.addCommand(monaco.KeyMod.Alt | monaco.KeyCode.US_SLASH,function(){
+            editor.trigger(null, 'editor.action.triggerSuggest', {})
+        },'!findWidgetVisible && !inreferenceSearchEditor && !editorHasSelection');
+        // Ctrl + Shift + U 转大写
+        editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_U,function(){
+            editor.trigger(null, 'editor.action.transformToUppercase', {})
+        });
+        // Ctrl + Shift + X 转小写
+        editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_X,function(){
+            editor.trigger(null, 'editor.action.transformToLowercase', {})
+        });
+        // Ctrl + Alt + L 代码格式化
+        editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KEY_L,function(){
+            editor.trigger(null, 'editor.action.formatDocument', {})
+        },'editorHasDocumentFormattingProvider && editorTextFocus && !editorReadonly');
+        // Ctrl + Alt + L 选中代码格式化
+        editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Alt | monaco.KeyCode.KEY_L,function(){
+            editor.trigger(null, 'editor.action.formatSelection', {})
+        },'editorHasDocumentFormattingProvider && editorHasSelection && editorTextFocus && !editorReadonly');
 
-                            }
-                        })
-                    }
+
+    },
+    // 初始化脚本编辑器
+    initScriptEditor : function(){
+        this.ajax({
+            url: 'classes',
+            async : false,
+            success: function (data) {
+                Parser.scriptClass = data || {};
+            }
+        })
+
+        monaco.editor.defineTheme('default', {
+            base: 'vs',
+            inherit: true,
+            rules: [
+                { background: '#ffffff' },
+                { token: 'keywords', foreground: '000080',fontStyle : 'bold'},
+                { token: 'number', foreground: '0000FF' },
+                { token: 'keyword', foreground: '000080',fontStyle : 'bold'},
+                { token: 'string.sql', foreground: '000000'},
+                { token: 'predefined.sql', foreground: '000000'},
+                { token: 'operator.sql', foreground: '000080',fontStyle : 'bold'},
+                { token: 'key', foreground: '660E7A' },
+                { token: 'string.key.json', foreground: '660E7A' },
+                { token: 'string.value.json', foreground: '008000' },
+                { token: 'keyword.json', foreground: '0000FF' },
+                { token: 'string', foreground: '008000',fontStyle : 'bold' },
+                { token: 'string.invalid', foreground: '008000' ,background : 'FFCCCC'},
+                { token: 'string.escape.invalid', foreground: '008000' ,background : 'FFCCCC'},
+                { token: 'string.escape', foreground: '000080',fontStyle : 'bold'},
+                { token: 'comment', foreground: '808080'},
+                { token: 'comment.doc', foreground: '808080'},
+                { token: 'string.escape', foreground: '000080'}
+            ],
+            colors: {
+                'editor.foreground': '#000000',
+                'editor.background': '#ffffff',
+//		        'editor.lineHighlightBorder' : '#00000000',
+                'editorLineNumber.foreground': '#999999',	//行号的颜色
+                'editorGutter.background' : '#f0f0f0',	//行号背景色
+                'editor.lineHighlightBackground' : '#FFFAE3',	//光标所在行的颜色
+                'dropdown.background' : '#F2F2F2',	//右键菜单
+                'dropdown.foreground' : '#000000',	//右键菜单文字颜色
+                'list.activeSelectionBackground': '#1A7DC4',	//右键菜单悬浮背景色
+                'list.activeSelectionForeground' : '#ffffff',	//右键菜单悬浮文字颜色
+            }
+        });
+
+        monaco.editor.defineTheme('dark', {
+            base: 'vs-dark',
+            inherit: true,
+            rules: [
+                { foreground: 'A9B7C6' },
+                { token: 'keywords', foreground: 'CC7832',fontStyle : 'bold'},
+                { token: 'keyword', foreground: 'CC7832',fontStyle : 'bold'},
+                { token: 'number', foreground: '6897BB' },
+                { token: 'string', foreground: '6A8759',fontStyle : 'bold' },
+                { token: 'string.sql', foreground: 'A9B7C6'},
+                { token: 'predefined.sql', foreground: 'A9B7C6'},
+                { token: 'key', foreground: '9876AA' },
+                { token: 'string.key.json', foreground: '9876AA' },
+                { token: 'string.value.json', foreground: '6A8759' },
+                { token: 'keyword.json', foreground: '6897BB' },
+                { token: 'operator.sql', foreground: 'CC7832',fontStyle : 'bold'},
+                { token: 'string.invalid', foreground: '008000' ,background : 'FFCCCC'},
+                { token: 'string.escape.invalid', foreground: '008000' ,background : 'FFCCCC'},
+                { token: 'string.escape', foreground: '000080',fontStyle : 'bold'},
+                { token: 'comment', foreground: '808080'},
+                { token: 'comment.doc', foreground: '629755'},
+                { token: 'string.escape', foreground: 'CC7832'}
+            ],
+            colors: {
+                'editor.background': '#2B2B2B',
+//		        'editor.lineHighlightBorder' : '#00000000',
+                'editorLineNumber.foreground': '#999999',	//行号的颜色
+                'editorGutter.background' : '#313335',	//行号背景色
+                'editor.lineHighlightBackground' : '#323232',	//光标所在行的颜色
+                'dropdown.background' : '#3C3F41',	//右键菜单
+                'dropdown.foreground' : '#BBBBBB',	//右键菜单文字颜色
+                'list.activeSelectionBackground': '#4B6EAF',	//右键菜单悬浮背景色
+                'list.activeSelectionForeground' : '#FFFFFF',	//右键菜单悬浮文字颜色
+            }
+        });
+        var theme = this.getValue('skin') || 'default';
+        this.report('theme_' + theme);
+        this.scriptEditor = monaco.editor.create($('.editor-container')[0], {
+            minimap : {
+                enabled : false
+            },
+            language: 'magicscript',
+            folding : false,
+            lineDecorationsWidth : 35,
+            fixedOverflowWidgets :false,
+            theme : theme
+        })
+        this.requestEditor = monaco.editor.create($('.request-editor')[0], {
+            value: "{}",
+            minimap : {
+                enabled : false
+            },
+            language: 'json',
+            folding : false,
+            fixedOverflowWidgets :true,
+            theme : theme
+        })
+        this.optionsEditor = monaco.editor.create($('.options-editor')[0], {
+            value: "{}",
+            minimap : {
+                enabled : false
+            },
+            language: 'json',
+            folding : false,
+            fixedOverflowWidgets :true,
+            theme : theme
+        })
+        this.resultEditor = monaco.editor.create($('.result-editor')[0], {
+            value: "{}",
+            minimap : {
+                enabled : false
+            },
+            language: 'json',
+            folding : false,
+            readOnly : true,
+            fixedOverflowWidgets : true,
+            theme : theme
+        })
+        var _this = this;
+        this.scriptEditor.onMouseDown(function(e){
+            if (e.target.detail && e.target.detail.offsetX && e.target.detail.offsetX >= 0 && e.target.detail.offsetX <= 60) {
+                var line = e.target.position.lineNumber;
+                if (_this.scriptEditor.getModel().getLineContent(line).trim() === '') {
+                    return
+                }
+                if(_this.hasBreakPoint(line)){
+                    _this.removeBreakPoint(line);
+                }else{
+                    _this.addBreakPoint(line);
                 }
-            })
-        }
-    }
-    var resizeX = $(".layout-resizer-x")[0];
-    resizeX.onmousedown = function(e){
-        var box = $(".layui-right-container")[0];
-        var body = $('body')[0];
-        var mx = body.clientWidth - box.clientWidth;
-        document.onmousemove = function(e){
-            var move = ((e.clientX - mx) / box.clientWidth);
-            if((1 - move) * box.clientWidth < 300 || move * box.clientWidth  < 500){
-                return;
             }
-            move = (1 - move) * 100;
-            $(".editor-container").css('right',move + '%');
-            $(".layui-right").css('width',move + '%');
-            resizeX.style.right = move + '%';
-            editorLayout();
+        });
+        this.bindEditorShortKey(this.scriptEditor);
+        this.bindEditorShortKey(this.requestEditor);
+        this.bindEditorShortKey(this.optionsEditor);
+    },
+    navigateTo : function(index){
+        var $parent = $('.bottom-container');
+        var $dom = $parent.find('.bottom-content-container').show();
+        $parent.find('.bottom-tab li').eq(index).addClass('selected').siblings().removeClass('selected');
+        $dom.find('.bottom-content-item').eq(index).show().siblings().hide();
+        this.layout();
+    },
+    createDialog : function(options){
+        options = options || {};
+        var $dialog = $('<div/>').addClass('dialog');
+        var $header = $('<div/>').addClass('dialog-header').append(options.title || '');
+        var $close = $('<span/>').append('<i class="iconfont icon-close"></i>');
+        $header.append($close);
+        $close.on('click',function(){
+            options.close&&options.close();
+            $wrapper.remove();
+        })
+        $dialog.append($header);
+        $dialog.append('<div class="dialog-content">' + options.content + '</div>');
+        var buttons = options.buttons || [];
+        var $buttons = $('<div/>').addClass('dialog-buttons');
+        if(buttons.length > 1){
+            $buttons.addClass('button-align-right');
         }
-        document.onmouseup = function(evt){
-            document.onmousemove = null;
-            document.onmouseup = null;
-            resizeX.releaseCapture && resizeX.releaseCapture();
+        for(var i=0,len = buttons.length;i<len;i++){
+            var button = buttons[i];
+            $buttons.append($('<button/>').html(button.name || '').addClass(button.className || '').addClass(i == 0 ? 'active' : ''));
         }
-        resizeX.setCapture && resizeX.setCapture();
-        return false;
-    }
-    var resizeY = $(".layout-resizer-y")[0];
-    resizeY.onmousedown = function(e){
-        var box = $(".layui-right")[0].getClientRects()[0];
-        document.onmousemove = function(e){
-            var move = ((e.clientY - box.y) / box.height);
-            if((1 - move) * box.height < 150 || move * box.height  < 150){
+        $dialog.append($buttons);
+        var $wrapper = $('<div/>').addClass('dialog-wrapper').append($dialog);
+        $buttons.on('click','button',function(){
+            var index = $(this).index();
+            if(buttons[index].click&&buttons[index].click() === false){
                 return;
             }
-            move = move * 100;
-            $(".output-container").css('top',move + '%');
-            $(".request-container").css('height',move + '%');
-            resizeY.style.top = move + '%';
-            editorLayout();
+            options.close&&options.close();
+            $wrapper.remove();
+        })
+        $('body').append($wrapper);
+    },
+    createContextMenu : function(menus,left,top,$dom){
+        $('.context-menu').remove();
+        var $ul = $('<ul/>').addClass('context-menu').addClass('not-select');
+        for(var i=0,len = menus.length;i<len;i++){
+            var menu = menus[i];
+            $ul.append($('<li/>').append('<label>'+menu.name+'</label>').append('<span>'+(menu.shortKey || '')+'<span>'));
         }
-        document.onmouseup = function(evt){
-            document.onmousemove = null;
-            document.onmouseup = null;
-            resizeY.releaseCapture && resizeY.releaseCapture();
+        $ul.on('click','li',function(){
+            var menu = menus[$(this).index()]
+            menu&&menu.click&&menu.click($dom);
+        });
+        $ul.css({
+            left : left + 'px',
+            top : top + 'px'
+        })
+        $('body').append($ul).on('click',function(){
+            $ul.remove();
+        });
+    },
+    // 初始化左侧工具条
+    initLeftToobarContainer : function(){
+        var $apiContainr = $('.api-list-container');
+        var value = this.getValue('left-toolbar-width');
+        if(value && !isNaN(Number(value))){
+            $apiContainr.width(value);
         }
-        resizeY.setCapture && resizeY.setCapture();
-        return false;
-    }
-    layui.element.on('tab', function () {
-        editorLayout();
-    });
-    $('body').on('keydown',function(e){
-        if(e.keyCode == 119){ //F8
-            doContinue();
-            e.preventDefault();
-        }else if(e.keyCode == 81 && (e.metaKey || e.ctrlKey)){  //Ctrl + Q
-            doTest();
-            e.preventDefault();
-        }else if(e.keyCode == 83 && (e.metaKey || e.ctrlKey)){  //Ctrl + S
-            doSave();
-            e.preventDefault();
+        if('false' == this.getValue('left-toolbar-show')){
+            $('.left-toolbar-container li').removeClass('selected');
+            $apiContainr.hide();
         }
-    }).on('click','.btn-create',function(){
-        layui.layer.confirm('新建接口会清空当前编辑器,是否继续?',{
-            title : "创建接口"
-        },function(index){
-            layui.layer.close(index);
-            $('input[name=name]').val('');
-            $('input[name=path]').val('');
-            $('select[name=method]').val('GET');
-            layui.form.render();
-            apiId = null;
-            resetEditor();
+        var _this = this;
+        $('.left-toolbar-container').on('click','li',function(){
+            var $this = $(this);
+            if($this.hasClass('selected')){	//当前是选中状态
+                $this.removeClass('selected');
+                _this.setValue('left-toolbar-show',false);
+                $apiContainr.hide();
+            }else{
+                $this.addClass('selected');
+                _this.setValue('left-toolbar-show',true);
+                $apiContainr.show();
+            }
+            _this.layout();
         })
-    }).on('click','.btn-test',function(){
-        doTest();
-    }).on('click','.btn-continue',function(){
-        doContinue();
-    }).on('click','.btn-delete',function(){
-        //确认删除该节点 "test/{id}/{id2}" 吗?
-        if(apiId){
-            layui.layer.confirm('确定要删除当前接口吗?',function(index){
-                layui.layer.close(index);
-                deleteAPI(apiId);
-                if(data.id == apiId){
-                    apiId = null;
-                    resetEditor();
+        var $middleContainer = $('.middle-container');
+        // 调整宽度
+        var resizer = $middleContainer.find('.resizer-x')[0];
+        resizer.onmousedown = function(){
+            var box = $apiContainr[0].getClientRects()[0];
+            document.onmousemove = function(e){
+                var move = e.clientX - 22;
+                if(move > 150 && move < 700){
+                    _this.layout();
+                    _this.setValue('left-toolbar-width',move);
+                    $apiContainr.width(move);
                 }
-            })
+            }
+            document.onmouseup = function(evt){
+                document.onmousemove = null;
+                document.onmouseup = null;
+                resizer.releaseCapture && resizer.releaseCapture();
+            }
+            resizer.setCapture && resizer.setCapture();
+        }
+    },
+    formatJson : function (val, defaultVal) {
+        return (val ? JSON.stringify(val, null, 4) : defaultVal) || '';
+    },
+    // 初始化底部
+    initBottomContainer : function(){
+        var $contentContainer = $('.bottom-container .bottom-content-container');
+        var value = this.getValue('bottom-container-height');
+        if(value && !isNaN(Number(value))){
+            $contentContainer.height(value);
+        }
+        if('false' == this.getValue('bottom-tab-show')){
+            $contentContainer.hide();	//隐藏全部
+            $('.bottom-container .bottom-tab li').removeClass('selected');
+        }else{
+            var index = Number(this.getValue('bottom-tab-index'));
+            if(!isNaN(index)){
+                this.navigateTo(index);
+            }
         }
-    }).on('click','.btn-save',function(){
-        doSave();
-    }).on('keyup','.layui-left .api-search input',function(){
-        var value = this.value;
-        for(var i=0,len = apiList.length;i<len;i++){
-            var info = apiList[i];
-            info.show = value ? info.path.indexOf(value) > -1 || info.name.indexOf(value) > -1 : true;
+        var _this = this;
+        $('.bottom-container').on('click','.bottom-tab li',function(){
+            var $this = $(this);
+            if($this.hasClass('selected')){	//当前是选中状态
+                $contentContainer.hide();	//隐藏全部
+                $this.removeClass('selected')
+                _this.setValue('bottom-tab-show',true);
+            }else{
+                $this.addClass('selected').siblings().removeClass('selected');	//选中选择项,取消其他选择项
+                var index = $(this).index();
+                _this.setValue('bottom-tab-index',index);
+                _this.setValue('bottom-tab-show',true);
+                $contentContainer.show().find('.bottom-content-item').hide().eq(index).show();
+            }
+            _this.layout();
+        });
+        // 调整底部高度
+        var resizer = $contentContainer.find('.resizer-y')[0];
+        resizer.onmousedown = function(){
+            var box = $contentContainer[0].getClientRects()[0];
+            document.onmousemove = function(e){
+                if(e.clientY > 150){
+                    var move = box.height - (e.clientY - box.y);
+                    if(move > 30){
+                        _this.setValue('bottom-container-height',move);
+                        _this.layout();
+                        $contentContainer.height(move);
+                    }
+                }
+            }
+            document.onmouseup = function(evt){
+                document.onmousemove = null;
+                document.onmouseup = null;
+                resizer.releaseCapture && resizer.releaseCapture();
+            }
+            resizer.setCapture && resizer.setCapture();
         }
-        renderApiList()
+        $('.bottom-container').on('click','.bottom-content-item:eq(0) .button-clear',function(){
+            _this.requestEditor&&_this.requestEditor.setValue('{}');
+        }).on('click','.bottom-content-item:eq(0) .button-format',function(){
+            try{
+                _this.requestEditor.setValue(_this.formatJson(JSON.parse(_this.requestEditor.getValue()),'{\r\n}'));
+            }catch(e){}
+        }).on('click','.bottom-content-item:eq(1) .button-clear',function(){
+            _this.optionsEditor&&_this.optionsEditor.setValue('{}');
+        }).on('click','.bottom-content-item:eq(1) .button-format',function(){
+            try{
+                _this.optionsEditor.setValue(_this.formatJson(JSON.parse(_this.optionsEditor.getValue()),'{\r\n}'));
+            }catch(e){}
+        }).on('click','.bottom-content-item:eq(2) .button-clear',function(){
+            _this.resultEditor&&_this.resultEditor.setValue('{}');
+        }).on('click','.bottom-content-item:eq(2) .button-format',function(){
+            try{
+                _this.resultEditor.setValue(_this.formatJson(JSON.parse(_this.resultEditor.getValue()),'{\r\n}'));
+            }catch(e){}
+        })
+    },
+    setSkin : function(skin){
+        $('body').addClass('skin-' + skin);
+        this.setValue('skin',skin);
+        monaco.editor.setTheme(skin);
+        MagicEditor.report('theme_' + skin);
+        MagicEditor.setStatusBar('切换皮肤至:' + skin);
+        //this.scriptEditor&&this.scriptEditor.setTheme(skin);
+    },
+    layout : function(){
+        this.scriptEditor&&this.scriptEditor.layout();
+        this.optionsEditor&&this.optionsEditor.layout();
+        this.requestEditor&&this.requestEditor.layout();
+        this.resultEditor&&this.resultEditor.layout();
+    }
+}
+$(function(){
+    require(['vs/editor/editor.main'],function(){
+        MagicEditor.init();
+        $('.loading-wrapper').remove();
     })
-    loadAPI();
-});
+    $(window).resize(function(){
+        MagicEditor.layout();
+    });
+
+});

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
src/main/resources/magicapi-support/js/jquery.min.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
src/main/resources/magicapi-support/layui/css/layui.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
src/main/resources/magicapi-support/layui/css/layui.mobile.css


+ 0 - 2
src/main/resources/magicapi-support/layui/css/modules/code.css

@@ -1,2 +0,0 @@
-/** layui-v2.5.6 MIT License By https://www.layui.com */
- html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}

Разница между файлами не показана из-за своего большого размера
+ 0 - 1
src/main/resources/magicapi-support/layui/css/modules/laydate/default/laydate.css


BIN
src/main/resources/magicapi-support/layui/css/modules/layer/default/icon-ext.png


BIN
src/main/resources/magicapi-support/layui/css/modules/layer/default/icon.png


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
src/main/resources/magicapi-support/layui/css/modules/layer/default/layer.css


BIN
src/main/resources/magicapi-support/layui/css/modules/layer/default/loading-0.gif


BIN
src/main/resources/magicapi-support/layui/css/modules/layer/default/loading-1.gif


BIN
src/main/resources/magicapi-support/layui/css/modules/layer/default/loading-2.gif


BIN
src/main/resources/magicapi-support/layui/font/iconfont.eot


Разница между файлами не показана из-за своего большого размера
+ 0 - 25
src/main/resources/magicapi-support/layui/font/iconfont.svg


BIN
src/main/resources/magicapi-support/layui/font/iconfont.ttf


BIN
src/main/resources/magicapi-support/layui/font/iconfont.woff


BIN
src/main/resources/magicapi-support/layui/font/iconfont.woff2


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
src/main/resources/magicapi-support/layui/layui.all.js


+ 8 - 22
src/main/resources/magicapi-support/monaco/language/magicscript.js

@@ -1114,20 +1114,6 @@ var AST = {
 }
 require(['vs/editor/editor.main'], function() {
     monaco.languages.register({ id :'magicscript'});
-    monaco.editor.defineTheme('magicscript', {
-        base: 'vs',
-        inherit: true,
-        rules: [
-            { token: 'keywords.null', foreground: 'ff0001' },
-            { token: 'keywords', foreground: '0000ff' },
-            { token: 'keywords.true', foreground: '0000ff' },
-            { token: 'keywords.false', foreground: '0000ff' },
-            { token: 'number', foreground: '0000ff' },
-            { token: 'comment', foreground: '008000' },
-            { token: 'comment.mul', foreground: '008000' },
-            { token: 'method.call.empty', foreground: 'ff0000', fontStyle: 'bold' },
-        ]
-    });
     monaco.languages.setLanguageConfiguration('magicscript',{
         wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
         brackets: [
@@ -1332,7 +1318,7 @@ require(['vs/editor/editor.main'], function() {
                 }],
                 [/[{}()\[\]]/, '@brackets'],
                 [/(@digits)[lLbBsSdDfF]?/, 'number'],
-                [/\/\*\*(?!\/)/, 'comment.mul', '@mulcomment'],
+                [/\/\*\*(?!\/)/, 'comment.doc', '@mulcomment'],
                 [/\/\*/, 'comment', '@comment'],
                 [/\/\/.*$/, 'comment'],
                 [/[;,.]/, 'delimiter'],
@@ -1350,15 +1336,15 @@ require(['vs/editor/editor.main'], function() {
                 [/[\/*]/, 'comment']
             ],
             mulcomment: [
-                [/[^\/*]+/, 'comment.mul'],
+                [/[^\/*]+/, 'comment.doc'],
                 // [/\/\*/, 'comment.doc', '@push' ],    // nested comment not allowed :-(
-                [/\/\*/, 'comment.mul.invalid'],
-                [/\*\//, 'comment.mul', '@pop'],
-                [/[\/*]/, 'comment.mul']
+                [/\/\*/, 'comment.doc.invalid'],
+                [/\*\//, 'comment.doc', '@pop'],
+                [/[\/*]/, 'comment.doc']
             ],
             string_multi: [
-                [/"""/, {token: 'string.multi', next: '@pop'}],
-                [/"/, {token: 'string.multi', next: '@string_multi_embedded', nextEmbedded: 'sql'}]
+                [/"""/, {token: 'string', next: '@pop'}],
+                [/"/, {token: 'string', next: '@string_multi_embedded', nextEmbedded: 'sql'}]
             ],
             string_multi_embedded: [
                 [/"""/, {token: '@rematch', next: '@pop', nextEmbedded: '@pop'}],
@@ -1366,7 +1352,7 @@ require(['vs/editor/editor.main'], function() {
             ],
             string_double: [
                 [/[^\\"]+/, 'string'],
-                // [/@escapes/, 'string.escape'],
+                [/@escapes/, 'string.escape'],
                 [/\\./, 'string.escape.invalid'],
                 [/"/, 'string', '@pop']
             ],

Некоторые файлы не были показаны из-за большого количества измененных файлов