首页 文章 精选 留言 我的

精选列表

搜索[apicloud],共50篇文章
优秀的个人博客,低调大师

apicloud,aliyunlive,测试成功

1.推流 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"> <title>直播测试</title> <link rel="stylesheet" type="text/css" href="../../css/aui.2.0.css" /> </head> <body style="overflow: hidden;"> <header class="aui-bar aui-bar-nav"> 发起直播 </header> <script type="text/javascript" src="../../script/api.js"></script> <script type="text/javascript" src="../../script/common.js"></script> <script> var aliyunLive; apiready = function () { fix_status_bar(); aliyunLive = api.require('aliyunLive'); aliyunLive.configStream({ rect: { x: 0, y: 0, w: 375, h: 667 }, url: 'rtmp://video-center.alivecdn.com/yunlutong/test?vhost=live.yunlutong.com&auth_key=1490162678-0-0-0a084668d1f4b0eb1066a33c04c3bcf8', bitRate: { videoMaxBitRate: 1500 * 1000, videoMinBitRate: 400 * 1000, videoBitRate: 600 * 1000, audioBitRate: 64 * 1000 }, fps: 20, screenOrientation: 'vertical', reconnectTimeout: 5, videoResolution: '240P', videoPreset: '1280*720', cameraPosition: 'front', waterMarkImage: { path: '', location: 'leftTop', maginX: 20, maginY: 20 }, fixed: true },function(ret) { startStream(); }); } // 增加连接状态监听 function addConnectStatusListener() { aliyunLive.addConnectStatusListener(function(ret){ alert(JSON.stringify(ret)); }); } // 销毁推流,测试有效 function destroyStream() { aliyunLive.destroyStream(); } // 转换摄像头,测试有效 function toggleCamera() { aliyunLive.toggleCamera(); } // 设置美颜,测试有效 function setBeauty() { aliyunLive.setBeauty({ beauty: 'on' }); } // 设置静音 function setMute() { aliyunLive.setMute({ mute: 'on' }); } // 设置闪光灯,测试有效,对后置摄像头有效 function setFlash() { aliyunLive.setFlash({ flash: 'on' }); } // 停止推流 function stopStream() { aliyunLive.stopStream(function(ret){ alert(JSON.stringify(ret)); }); } // 开始推流 function startStream() { aliyunLive.startStream(function(ret){ alert(JSON.stringify(ret)); }); } </script> </body> </html> 2.拉流 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"> <title>直播测试</title> <link rel="stylesheet" type="text/css" href="../../css/aui.2.0.css" /> </head> <body style="overflow: hidden;"> <header id="aui-header" class="aui-bar aui-bar-nav"> 看直播 </header> <script type="text/javascript" src="../../script/api.js"></script> <script type="text/javascript" src="../../script/common.js"></script> <script type="text/javascript" src="../../script/jquery.min.js"></script> <script> var mediaPlayer; apiready = function () { fix_status_bar(); mediaPlayer = api.require('aliyunLive'); mediaPlayer.init({ rect: { x: 0, y: $("#aui-header").height(), w: api.winWidth, h: api.winHeight - $("#aui-header").height() }, accessKeyId : 'xxxxx', accessKeySecret : 'xxxxx', businessId : 'yunlutong' }, function(ret, err) { prepareToPlay(); play(); }); } // 添加监听 function addEventListener() { mediaPlayer.addEventListener(function(ret){ alert(JSON.stringify(ret)); }); } // 设置缓冲时长 function setMaxBufferDuration() { mediaPlayer.setMaxBufferDuration({ duration:10000 }); } // 设置默认解码器,0硬件解码器,1软件解码器 function setDefaultDecoder() { mediaPlayer.setDefaultDecoder({ type : 1 }); } // 视频缩放,0等比例缩放,1剪切缩放 function setVideoScalingMode() { mediaPlayer.setVideoScalingMode({ mode : 1 }); } // 设置静音 function setMuteMode() { mediaPlayer.setMuteMode({ isMute:true }); } // 设置媒体类型 function setMediaType() { var mediaPlayer = api.require('aliyunLive'); mediaPlayer.setMediaType({ type:0 }); } // 请求超时时间 function setTimeout() { mediaPlayer.setTimeout({ timeout:5000 }); } // 获取视频高度 function getVideoHeight() { mediaPlayer.getVideoHeight(function(ret){ if(ret){ alert("Video height : " + ret.height); } }); } // 获取视频宽度 function getVideoWidth() { mediaPlayer.getVideoWidth(function(ret){ if(ret){ alert("Video width : " + ret.width); } }); } // 摧毁直播 function destroy() { mediaPlayer.destroy(); } // 停止播放 function stop() { mediaPlayer.stop(); } // 暂停 function pause() { mediaPlayer.pause(); } // 播放 function play() { mediaPlayer.play(); } // 准备播放 function prepareToPlay() { mediaPlayer.prepareToPlay({ url:'http://live.yunlutong.com/yunlutong/test.m3u8?auth_key=1490164347-0-0-a19f94a4fcd8a033f6b778bedd48545c' }, function(ret, err) { if(ret && ret.status){ } }); } </script> </body> </html> ps: 1.这里需要申请Access Key ID,Access Key Secret 2.配置好推流和拉流的url。 3.这里只是初步实现了视频直播的功能,具体的还是需要配合服务器,把直播列表的数据获取到,展示到app中。 最好能够支持用户发言,发送小礼物,或者查看在线人数,和观看视频的人数。这些都需要处理。 本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/6599906.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Apicloud自定义模块

各种坑,折腾了两天才有点头绪。我用的是Android Studio编辑器,官网是Eclipse的视频。文档也比较蛋疼。 自定义模块的目录结构要按照下面来处理 其中res_模块名,存放res和AndroidMainfest.xml AndroidMainfest.xml需要处理一下,去掉不需要的东西。 res中可以把一些drawable融合到一起。 AndroidMainfest.xml中把一些权限和服务保留,其他的东西删除掉! source下面的这个jar包最核心 需要通过android studio处理才能导出。 其他的依赖包,复制进来就可以了。 target中存放一些so文件 module.json中存放模块名称和类 剩下的就是把它压缩成zip格式,上传使用了。测试可以使用。 具体的可以看官方的文档处理!!! 严格按照这种格式处理!!! 安卓功力不深,各种被打击!!!官方文档和视频太操蛋!!! 本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/7762582.html如需转载请自行联系原作者

优秀的个人博客,低调大师

apiCloud中图片裁剪模块FNImageClip的使用

思路 1.获取需裁剪图片的地址 2.跳转到裁剪页面 3.裁剪成功返回新图片地址 4.替换原有图片地址 增加修饰和事件 str += '<li class="tu image" id="'+imgType+'_'+i+'" style="background: url('+ret.list[i].path+')no-repeat;background-size:cover;" onclick="showClip(\''+imgType+'_'+i+'\',\''+ret.list[i].path+'\')"><input type="hidden" value="'+ret.list[i].path+'"><div class="badge" onclick="delPic(this,\''+imgType+'\')"><i class="aui-iconfont aui-icon-close"></i></div></li>'; 上面是动态生成的图片html布局数据,增加一个id标识id="'+imgType+'_'+i+'",增加一个点击事件onclick="showClip(\''+imgType+'_'+i+'\',\''+ret.list[i].path+'\')" 打开裁剪页面,并传入参数element_id和img_url // 裁剪图片 function showClip(element_id,img_url) { // 处理图片裁剪 openWinPro('clip','element_id:'+element_id+',img_url:'+img_url); } 裁剪页面进行处理 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"> <meta name="format-detection" content="telephone=no,email=no,date=no,address=no"> <title>图片裁剪</title> <link rel="stylesheet" type="text/css" href="../css/api.css"> <link rel="stylesheet" type="text/css" href="../css/aui.2.0.css"> <style> body{ background: #fff; } .aui-btn{ padding:0.3rem 2rem; } .footer{ position: fixed; z-index: 999; bottom: 1rem; left:20%; } </style> </head> <body> <header class="aui-bar aui-bar-nav aui-margin-b-15 header"> <a class="aui-pull-left aui-btn" onclick="api.closeWin({});"> <span class="aui-iconfont aui-icon-left"></span> </a> <div class="aui-title">图片裁剪</div> </header> <div class="aui-list-item-inner aui-list-item-center aui-list-item-btn footer"> <div class="aui-btn aui-btn-info aui-margin-r-5" onclick="fnSave();">提交</div> <div class="aui-btn aui-btn-danger aui-margin-l-5" onclick="fnReset();">重置</div> </div> <script type="text/javascript" src="../script/api.js"></script> <script type="text/javascript" src="../script/common.js"></script> <script type="text/javascript"> var FNImageClip; var element_id; apiready = function() { var header=$api.dom('header'); $api.fixStatusBar(header); element_id = api.pageParam.element_id; var img_url = api.pageParam.img_url; // alert(element_id+"----"+img_url); FNImageClip = api.require('FNImageClip'); FNImageClip.open({ rect: { x: 0, y: document.querySelector('.header').offsetHeight, w: api.winWidth, h: api.winHeight - 150 }, srcPath: img_url, style: { mask: '#fff', clip: { w: 250, h: 250, x: 60, y: 80, borderColor: '#0f0', borderWidth: 1, appearance: 'rectangle' } } }); }; function fnSave(){ FNImageClip.save({ destPath: 'fs://image/temp'+new Date().getTime()+'.png', copyToAlbum: false, quality: 1 },function(ret, err){ if(ret) { // 提示裁剪成功 toast("裁剪成功"); // 发送事件监听 api.sendEvent({ name: 'clip_success', extra: { element_id: element_id, new_img_url: ret.destPath } }); // 关闭页面 setTimeout("api.closeWin({});",1000); } else{ alert('裁剪失败,请重试'); } }); } function fnReset(){ FNImageClip.reset(); } </script> </body> </html> 裁剪页面获取参数,负责裁剪图片,并发送事件监听和传递参数 api.sendEvent({ name: 'clip_success', extra: { element_id: element_id, new_img_url: ret.destPath } }); 原页面增加监听事件和处理 // 监听图片裁剪 api.addEventListener({ name: 'clip_success' }, function(ret, err) { if (ret) { $("#"+ret.value.element_id).css('background-image','url('+ret.value.new_img_url+')'); $("#"+ret.value.element_id+" input").val(ret.value.new_img_url); } }); 一切都ok了 裁剪前 裁剪中 裁剪后 本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/6208600.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

apiCloud如何打开新页面的同时,关掉当前页

方法很多,只要不同时open、close都可行。给你一个简单的方式: api.addEventListener({ name:'viewdisappear' },function(){ api.closeWin({ name:api.winName }); }); 谢谢官方提供的方案,棒棒的! 使用场景,选择好友加入群组! 群生成之后,关闭选择页面! <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/> <title>title</title> <link rel="stylesheet" type="text/css" href="api.css"/> <link rel="stylesheet" type="text/css" href="../css/aui.2.0.css"/> <style> body{ } </style> </head> <body style="background: #eae6e6;"> <header class="aui-bar aui-bar-nav aui-margin-b-15" id="aui-header"> <a class="aui-pull-left aui-btn" tapmode onclick="closeWin()"> <span class="aui-iconfont aui-icon-left"></span>取消 </a> <div class="aui-title">选择朋友</div> <a class="aui-pull-right aui-btn"> <span class="aui-iconfont" style="color:#3F8A2C;" onclick="confirmChooseEvent();">确定</span> </a> </header> </body> <script type="text/javascript" src="../script/api.js"></script> <script type="text/javascript" src="../script/config.js"></script> <script type="text/javascript" src="../script/jquery.min.js"></script> <script type="text/javascript" src="../script/message_common.js"></script> <script type="text/javascript" src="../script/common.js"></script> <script type="text/javascript"> apiready = function () { fix_status_bar(); var header_height = $api.dom("header").offsetHeight; api.openFrame({ name: 'message_choose_friends_frm', url: 'message_choose_friends_frm.html', rect: { x: 0, y: header_height, w:'auto', //宽度,若传'auto',页面从x位置开始自动充满父页面宽度 h:api.winHeight - header_height //高度,若传'auto',页面从y位置开始自动充满父页面高度 }, bgColor:'rgba(0,0,0,0)', bounces:false, vScrollBarEnabled:false, hScrollBarEnabled:false }); // 监听页面消失的时候,关掉页面就可以了 api.addEventListener({ name:'viewdisappear' },function(){ api.closeWin(); }); } function confirmChooseEvent() { api.sendEvent({ name: 'confirmChooseEvent', extra: { } }); } </script> </html> frm页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"> <title>选择朋友</title> <link rel="stylesheet" type="text/css" href="../css/aui.2.0.css"/> <link rel="stylesheet" href="../css/message_style.css"> <style> .s_mapul { position: absolute; top: 0; left: 0; width: 100%; max-height: 350px; overflow: scroll; background: #fff; overflow-y: auto; } .s_mapul li { border-bottom: 1px solid #ededed; padding: 0.3rem 5%; position: relative; } .s_mapul li h2 { font-size: 0.8rem; } .s_mapul li h2 img { position: absolute; right: 5%; height: 1rem; } .s_mapul li p { font-size: 0.6rem; color: #b0b0b0; margin-top: 0.2rem; } </style> </head> <body> <script type="text/javascript" src="../script/api.js"></script> <script type="text/javascript" src="../script/common.js"></script> <script type="text/javascript" src="../script/message_common.js"></script> <script type="text/javascript" src="../script/config.js"></script> <script type="text/javascript" src="../script/doT.min.js"></script> <script type="text/javascript" src="../script/jquery.min.js"></script> <script type="text/javascript" src="../script/convertPinyin.js"></script> <script> var user; var UIListCheck; apiready = function () { fix_status_bar(); user = $api.getStorage('user'); // 监听页面关闭 api.addEventListener({ name: 'confirmChooseEvent' }, function (ret, err) { getSelectedSync(); }); api.ajax({ url: BASE_URL_ACTION+'/RongCloud/GetFriends', method: 'post', data: { values: { customerId: user.person_id, } } }, function (json, err) { if (json.result) { dealFriendsData(json.info,function(contacts) { UIListCheck = api.require('UIListCheck'); UIListCheck.open({ rect: { x: 0, y: 22, w: api.frameWidth, h: api.frameHeight - 22 }, contacts: contacts, fixedOn: 'message_choose_friends_frm' }, function (ret) { if (ret) { } }); }); } else { toast('获取好友数据失败'); } }); } function dealFriendsData(data,callback) { var contacts = []; for (var i=0;i<data.length;i++) { var item = {}; item.employee_id = data[i].Id; item.remark = data[i].NickName; item.position = ""; item.phonetic = convertPinyin(data[i].NickName); contacts[i] = item; } if (typeof callback == 'function') { callback(contacts); } } function getSelectedSync() { var ret = UIListCheck.getSelectedSync(); var contacts = ret.contacts; if (contacts.length == 0) { toast('请选择好友'); return; } var values = { systemName : 'yunlutong', customerId : user.person_id } for(var i = 0;i<contacts.length;i++) { var key='contactIds['+i+']'; values[key]= contacts[i].employee_id; } api.ajax({ url : BASE_URL_ACTION+'/RongCloud/AddGroup', method : 'post', data : { values : values } }, function(json, err) { if (json.result) { toast('创建成功'); setTimeout(openChatPage('',json.groupid,0,'群聊','GROUP','index',''),500); // 本来想在这里处理的,发现不管用 } else { toast('创建失败'); } }); } </script> </body> </html>本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/7212227.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

apiCloud中实现头部与内容分离与操作规范,App头部header固定,头部与内容分离

官方案例 1.头部拆分成一个页面比如news-text <!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=0, width=device-width"/> <title>api</title> <link rel="stylesheet" type="text/css" href="../css/api.css" /> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/news-text.css" /> </head> <body> <div id="wrap"> <div id="header"> <a class="back-icon" tapmode="" onclick="api.closeWin()"></a> <h1>热点新闻</h1> </div> </div> </body> <script type="text/javascript" src="../script/api.js"></script> <script type="text/javascript" src="../script/news-text.js"></script> </html> 2.内容拆分成另一个页面比如news-textCon <!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=0, width=device-width"/> <title>api</title> <link rel="stylesheet" type="text/css" href="../css/api.css" /> <link rel="stylesheet" type="text/css" href="../css/common.css" /> <link rel="stylesheet" type="text/css" href="../css/news-text.css" /> </head> <body> <div id="wrap"> <div id="main"> <script id="news-template" type="text/x-dot-template"> <h1>{{=it.title}}</h1> <label> {{? it.from }} {{=it.from}} {{?}} <em>{{=it.date}}</em> </label> <div id="summary"> {{=it.summary}} </div> <div> {{=it.content}} </div> <a id="fav" class="btn" tapmode="active" news-id="{{=it.id}}" >收藏</a> </script> <div id="content"></div> </div> </div> </body> <script type="text/javascript" src="../script/api.js"></script> <script type="text/javascript" src="../script/common.js"></script> <script type="text/javascript" src="../script/doT.min.js"></script> <script type="text/javascript" src="../script/zepto.js"></script> <script type="text/javascript" src="../script/news-textCon.js"></script> </html> 以上就是一个非常规范的内容 1.css在头部 引入必要的css,api.css 引入通用的css,common.css 引入页面特有的css,news-text.css 2.js在尾部 引入必要的css,api.js 引入通用的css,common.js 引入页面特有的css,news-text.js 根据页面需要,引入doT模板和zepto(手机端的jQuery替代品) 来看看news-text.js中的内容 apiready = function(){ var header = $api.byId('header'); // 获取头部 $api.fixStatusBar(header); // 处理ios兼容 var newsId = api.pageParam.newsId; // 获取参数 var pos = $api.offset(header); // 获取位置数据 api.openFrame({ // 打开Frame name: 'news-textCon', url: 'news-textCon.html', pageParam: {newsId: newsId}, // 传递参数 rect:{ x: 0, y: pos.h, // 头部留位置 w: 'auto', h: 'auto' }, bounces: true, vScrollBarEnabled: false }); }; 打开frame,保证头部留有位置,同时可以传递参数 再看看news-textCon.js中的内容 apiready = function () { var newsId = api.pageParam.newsId; // 获取参数 var getNewsByIdUrl = '/news/?filter='; var urlParam = {where: {id: newsId}}; api.showProgress({ title: '加载中...', modal: false }); ajaxRequest(getNewsByIdUrl+JSON.stringify(urlParam),'get','',function(ret,err){ if (ret) { api.toast({ ... }) } else { api.toast({ ... }) } api.hideProgress(); }); }; 获取传入的参数, 获取数据与相应的页面处理 我的案例 商品详情拆分 1.goods_detail.html <!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=0, width=device-width"/> <title>api</title> <link rel="stylesheet" type="text/css" href="../css/api.css" /> <link rel="stylesheet" type="text/css" href="../css/aui.2.0.css" /> </head> <body> <div id="wrap"> <div id="main"> <header class="aui-bar aui-bar-nav fix-status-bar" id="aui-header"> <a class="aui-btn aui-pull-left" tapmode onclick="api.closeWin();"> <span class="aui-iconfont aui-icon-left"></span> </a> <div class="aui-title"><!-- 商品名称 --></div> </header> </div> </div> </body> <script type="text/javascript" src="../script/api.js"></script> <script type="text/javascript" src="../script/goods_detail.js"></script> </html> 2.goods_detailCon.html 移除头部的 <header class="aui-bar aui-bar-nav fix-status-bar" id="aui-header"> <a class="aui-btn aui-pull-left" tapmode onclick="api.closeWin();"> <span class="aui-iconfont aui-icon-left"></span> </a> <div class="aui-title"><!-- 商品名称 --></div> </header> 3.goods_detail.js apiready = function(){ var header = $api.byId('main'); // 获取头部 $api.fixStatusBar(header); // 处理ios var pos = $api.offset(header); // 获取头部位置 var title = $api.dom(header,'.aui-title'); // 获取标题位置 $api.html(title,api.pageParam.title); // 设置标题内容 api.openFrame({ // 打开内容页,并传递参数 name: 'goods_detailCon', url: 'goods_detailCon.html', rect:{ x: 0, y: pos.h, w: 'auto', h: 'auto' }, bounces: true, opaque: true, vScrollBarEnabled: false, pageParam:{ goods_id:api.pageParam.goods_id } }); }; 4.goods_detailCon.js apiready = function(){ fix_status_bar();// 修复头部 var goods_id = api.pageParam.goods_id; // 获取商品相关信息 api.ajax({ url: 'http://zhudianbao.yunlutong.com/?g=Api&m=Goods&a=getGoodsInfo', method: 'get', data: { values: { goods_id: goods_id } } }, function(json, err) { if (json.status == '1') { var interText = doT.template($("#goodstmpl").text()); $("#info_area").html(interText(json.info)); var swiper = new Swiper('.swiper-container', { pagination: '.swiper-pagination', paginationClickable: true, spaceBetween: 30, centeredSlides: true, autoplay: 3500, autoplayDisableOnInteraction: false }); } else { var toast = new auiToast(); toast.fail({ title:json.msg, duration:2000 }); } }); } 获取参数,根据参数获取数据,并使用doT进行页面布局。 看效果 本文转自TBHacker博客园博客,原文链接:http://www.cnblogs.com/jiqing9006/p/5952935.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册