diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..fb7df44 Binary files /dev/null and b/.DS_Store differ diff --git a/components/kline/tradingView/chartConfig.js b/components/kline/tradingView/chartConfig.js index 3b39bef..7b8d680 100644 --- a/components/kline/tradingView/chartConfig.js +++ b/components/kline/tradingView/chartConfig.js @@ -39,7 +39,7 @@ var chartConfig = { "header_resolutions", "left_toolbar", "header_screenshot", - "header_chart_type", + //"header_chart_type", "header_settings", "header_fullscreen_button", "header_undo_redo", diff --git a/components/kline/tradingView/contract.js b/components/kline/tradingView/contract.js new file mode 100644 index 0000000..5f00b34 --- /dev/null +++ b/components/kline/tradingView/contract.js @@ -0,0 +1,1841 @@ +var fav = null; +var usdt = null; +var marketTrades = null; +var orderbook = null; +var orderbook1 = null; +var Contracts = null; +var contractsTableData = new Array(); +var HistoryDelegate = null; +var historyDelegateTableData = new Array();//HistoryDelegate-表格数据 +var ClosedDelegate = null; +var closedDelegateTableData = new Array(); +var RvokedDelegate = null; +var rvokedDelegateTableData = new Array(); + +var currentBaseCoin = $("#currentBaseCoin").val();//"USDT"; +var currentSymbolCoin = $("#currentSymbolCoin").val();//"BTC"; + +//是否指定时间内有提交过 +var didsim = false; +//设置5秒内不可重复提交 +var simTime = 5000; + +//币种与对应的精度json,key=coin,value=baseCoinScale +var coinAndScale = null; + +layui.config({base: '/static/coinexchange/layui/plug/tablePlug/'}).use(['table', 'element', 'tablePlug', 'form'], function () { + var table = layui.table; + var form = layui.form; //表单 + // fav + fav = table.render({ + elem: '#fav', + data: [], + text: {none: "No Data"}, + cols: [[ + { field: 'pair', title: $("#lang-coin").html(), width: '40%', templet: renderFavorCoin }, + { field: 'price', title: $("#lang-latest").html(), width: '35%', templet: renderLatest, align: 'right', sort: true }, + { field: 'percent', title: $("#lang-change").html(), width: '25%', templet: renderChange, align: 'right', sort: true } + ]], + skin: 'nob', + page: false + }); + //监听杠杆下拉框 + form.on('select(sellleverage)', function (data) { + calculateBuyNum('sell') + }); + //监听杠杆下拉框 + form.on('select(buy)', function (data) { + calculateBuyNum('buy') + }); + table.on('row(fav)', function(data){ + updatePage(data.data); + }); + + + // usdt + usdt = table.render({ + elem: '#usdt', + data: [], + text: {none: "No Data"}, + cols: [[ + { field: 'coinSymbol', title: $("#lang-coin").html(), width: '30%', templet: renderCoin }, + { field: 'price', title: $("#lang-latest").html(), width: '35%', templet: renderLatest, align: 'right', sort: true }, + { field: 'percent', title: $("#lang-change").html(), width: '35%', templet: renderChange, align: 'right', sort: true } + ]], + skin: 'nob', + page: false + }); + //监听行单击事件 + table.on('row(usdt)', function(data){ + updatePage(data.data); + }); + // marketTrades + marketTrades = table.render({ + elem: '#marketTrades', + data: [], + cols: [[ + { field: 'price', title: $("#lang-price").html(), width: '33%', templet: renderPrice }, + { field: 'amount', title: $("#lang-amount").html(), width: '33%', templet: renderAmount, align: 'right' }, + { field: 'ts', title: $("#lang-time").html(), width: '33%', templet: renderTime, align: 'right' } + ]], + skin: 'nob', + limit: 4, + page: false, + text: {none: "No Data"}, + }); + // orderbook buy + orderbook = table.render({ + elem: '#orderbook', + data: [], + cols: [[ + { field: 'price', title: $("#lang-price").html(), width: '33%', templet: renderPrice }, + { field: 'size', title: $("#lang-amount").html(), width: '33%', templet: renderSize, align: 'right' }, + { field: 'total', title: $("#lang-total").html(), width: '33%', templet: renderTotalAmount, align: 'right' } + ]], + skin: 'nob', + limit: 14, + page: false, + text: {none: "No Data"}, + }); + // orderbook buy + orderbook1 = table.render({ + elem: '#orderbook1', + data: [], + cols: [[ + { field: 'price', title: $("#lang-price").html(), width: '33%', templet: renderPrice }, + { field: 'size', title: $("#lang-amount").html(), width: '33%', templet: renderSize, align: 'right' }, + { field: 'total', title: $("#lang-total").html(), width: '33%', templet: renderTotalAmount, align: 'right' } + ]], + skin: 'nob', + page: false, + text: {none: "No Data"}, + }); + + // 撤销挂单 + table.on('tool(HistoryDelegate)', function (obj) { + console.log(obj) + var data = obj.data; + + if (obj.event === 'cancel') { + cancelOrder(data.orderNo); + } + }); + + // 平仓 + table.on('tool(Contracts)', function (obj) { + console.log(obj) + var data = obj.data; + + if (obj.event === 'closed') { + closed(data.orderNo); + } + if (obj.event === 'setPrice') { + setPrice(data.orderNo); + } + }); + + +}); + function renderFavorCoin(data) { + if(data.flag == 1){ + return ""+data.pair+""; + }else{ + return ""+data.pair+""; + } + } + function renderCoin(data) { + if(data.flag == 1){ + return ""+data.coinSymbol+""; + }else{ + return ""+data.coinSymbol+""; + } + } + function renderLatest (data) { + return Number(data.price).toFixed(parseInt(data.baseCoinScale)); + } + function renderChange (data) { + var isBuy = data.percent > 0; + if(isBuy){ + return ""+Number(data.percent).toFixed(2)+"%"; + }else{ + return ""+Number(data.percent).toFixed(2)+"%"; + } + } + function renderPrice (data) { + var isBuy = data.direction == 'buy'; + if(isBuy){ + return ""+Number(data.price).toFixed(parseInt(data.baseCoinScale))+""; + }else{ + return ""+Number(data.price).toFixed(parseInt(data.baseCoinScale))+""; + } + } + function renderAmount (data) { + var scale = data.coinScale; + if(data.symbol.indexOf('hsh') != -1 || data.symbol.indexOf('qyc') != -1) scale=2; + return Number(data.amount).toFixed(parseInt(scale)); + } + function renderSize (data) { + var scale = data.coinScale; + if(data.symbol.indexOf('hsh') != -1 || data.symbol.indexOf('qyc') != -1) scale=2; + return Number(data.size).toFixed(parseInt(scale)); + } + function renderTotalAmount (data) { + var scale = data.coinScale; + if(data.symbol.indexOf('hsh') != -1 || data.symbol.indexOf('qyc') != -1) scale=2; + return Number(data.total).toFixed(parseInt(scale)); + } + function renderTime (data) { + return getMyDate(data.ts); + } + var marketPath = 'https://market.acefinex.com'; +// var marketPath = 'http://127.0.0.1:8082'; + var ctx = null; + var wsPath = 'wss://market.acefinex.com/wss/'; +// var wsPath = 'ws://127.0.0.1:9999/'; + var userId = null; + var currentSymbol = $("#symbol").val();//"btcusdt"; + // var currentBaseCoin = "USDT"; + // var currentSymbolCoin = "BTC"; + var clientId = null; + var _TVjsApi = null; + var _socket = null; + +//setTimeout(function () { getFavor(); }, 1000); +//setTimeout(function () { getKline(); }, 1000); +function startWebsocket(){ +// console.log(wsPath); + _socket = new WebSocket(wsPath); + _socket.onopen = function(evt) { +// console.log("Socket has opend"); +// console.log(JSON.stringify(evt)); + }; + _socket.onmessage = function (evt) { + var res = JSON.parse(evt.data); +// console.log("Socket evt",evt); + if(res.channel == 'conn'){ + clientId = res.data; + //init TVjsApi + _TVjsApi = new TVjsApi(currentSymbol, wsPath); + _TVjsApi.init(); + //send subscribe detail、trade、bbo、kline、pairsgroup + var channel = {}; + channel.event='sub'; + channel.id=clientId; + channel.model='contract'; + channel.channel=["market."+currentSymbol+".detail","market.pairsgroup","market."+currentSymbol+".trade","market."+currentSymbol+".bbo"/**,"market."+currentSymbol+".kline.1min"*/]; + _socket.send(JSON.stringify(channel)); + //send req kline +// channel.event='req'; +// channel.number='1000'; +// channel.channel=["market."+currentSymbol+".kline.1min"]; +// _socket.send(JSON.stringify(channel)); + }else if(res.channel == "market."+currentSymbol+".detail"){ +// console.log("res data",res.data); + var top = $(document).scrollTop(); + buildDetail(res.data); + updateDelegateTableData(res.data); + $(document).scrollTop(top); + }else if(res.channel == "market."+currentSymbol+".trade" && (null != marketTrades)){ +// console.log("res data",res.data); + if(res.data == null || res.data == '' || res.data == undefined){ + return; + } + var top = $(document).scrollTop(); + marketTrades.reload({ + data: res.data + }); + $(document).scrollTop(top); + }else if(res.channel == "market."+currentSymbol+".bbo"){ +// console.log("res data",res.data); + if(res.data == null || res.data == '' || res.data == undefined){ + return; + } + if(null != orderbook && res.data.buy != null || res.data.buy != '' || res.data.buy != undefined){ + var top = $(document).scrollTop(); + orderbook.reload({ + data: res.data.buy + }); + $(document).scrollTop(top); + } + if(null != orderbook1 && res.data.sell != null || res.data.sell != '' || res.data.sell != undefined){ + var top = $(document).scrollTop(); + orderbook1.reload({ + data: res.data.sell + }); + $(document).scrollTop(top); + } + }else if(res.channel == "market.pairsgroup"){ +// console.log("res data",res.data); + if(res.data == null || res.data == '' || res.data == undefined || res.event!='pairsgroupcontract'){ + return; + } + var data = res.data; + if(null != usdt && data.USDT != null || data.USDT != '' || data.USDT != undefined){ + var top = $(document).scrollTop(); + usdt.reload({ + data: data.USDT + }); + $(document).scrollTop(top); + } + } + }; + //close + _socket.onclose = function() { + console.log("Socket closed"); + _socket.doOpen(); + _socket.on('open', function() { + console.log(' >> : 已重连'); + //send subscribe detail、trade、bbo、kline、pairsgroup + var channel = {}; + channel.event='sub'; + channel.id=clientId; + channel.model='contract'; + channel.channel=["market."+currentSymbol+".detail","market.pairsgroup","market."+currentSymbol+".trade","market."+currentSymbol+".bbo"/**,"market."+currentSymbol+".kline.1min"*/]; + _socket.send(JSON.stringify(channel)); + }); + }; + //error + _socket.onerror = function() { + console.log("Socket error"); + } +} + +function getFavor(){ + $.post(marketPath+"/market/favor",{"userId":userId,"model":"contract"},function(data){ + if(data.code == 0 && (null != fav)){ + var top = $(document).scrollTop(); + fav.reload({ + data: data.data, + limit:data.data.length + }); + $(document).scrollTop(top); + } + }, "json"); +} +function addFavor(obj){ + if(userId == null || userId == '' || userId == undefined){ + location.href = ctx + "/login"; + } + var pair = null; + var baseCoin = $('.main-sidebar-left .layui-tab-title .layui-this').text(); + if(baseCoin == 'FAV'){ + pair = $(obj).parent().parent().attr("data-content"); + }else{ + var symbolCoin = $(obj).parent().parent().attr("data-content"); + pair = symbolCoin + "/" + baseCoin; + } + $.post(marketPath+"/market/addFavor",{"pair":pair,"userId":userId,"model":"contract"},function(data){ + getFavor();//refresh favor + }, "json"); +} +function removeFavor(obj){ + if(userId == null || userId == '' || userId == undefined){ + location.href = ctx + "/login"; + } + var pair = null; + var baseCoin = $('.main-sidebar-left .layui-tab-title .layui-this').text(); + if(baseCoin == 'FAV'){ + pair = $(obj).parent().parent().attr("data-content"); + }else{ + var symbolCoin = $(obj).parent().parent().attr("data-content"); + pair = symbolCoin + "/" + baseCoin; + } + $.post(marketPath+"/market/removeFavor",{"pair":pair,"userId":userId,"model":"contract"},function(data){ + getFavor();//refresh favor + }, "json"); +} +function getSymbols(coin){ + + $.post(marketPath+"/market/symbolInfo",{"baseCoin":coin, "userId":userId, "model":"contract"},function(data){ + if(data.code == 0){ + var top = $(document).scrollTop(); + if(coin == 'USDT' && (null != usdt)){ + usdt.reload({ + data: data.data, + limit:data.data.length + }); + setCoinAndScale(data.data); + } + $(document).scrollTop(top); + } + }, "json"); +} +function getTrade(symbol){ + $.post(marketPath+"/market/tradeList",{"symbol":symbol},function(data){ + if(data.code == 0 && (null != marketTrades)){ + var top = $(document).scrollTop(); + marketTrades.reload({ + data: data.data + }); + $(document).scrollTop(top); + } + + }, "json"); +} +function getOrderbook(symbol){ + $.post(marketPath+"/market/bboList",{"symbol":currentSymbol},function(data){ + if(data.code == 0){ + var top = $(document).scrollTop(); + if(null != orderbook){ + orderbook.reload({ + data: data.data.buy + }); + } + if(null != orderbook1){ + orderbook1.reload({ + data: data.data.sell + }); + } + $(document).scrollTop(top); + } + + }, "json"); +} +function getDetail(symbol){ + $.post(marketPath+"/market/detail",{"symbol":symbol},function(data){ + if(data.code == 0){ + var top = $(document).scrollTop(); + //24H + $("#detailPairSymbol").html(data.data.pair.split("/")[0]); + $("#detailPairBase").html('/ '+data.data.pair.split("/")[1]); + var isBuy = data.data.percent > 0; + if(isBuy){ + $("#detailPrice").removeClass().addClass("buy-color"); + $("#detailChange").removeClass().addClass("buy-color"); + $("#detailPrice").html(Number(data.data.close).toFixed(parseInt(data.data.baseCoinScale))); + $("#detailChange").html(Number(data.data.percent).toFixed(2)+"%"); + }else{ + $("#detailPrice").removeClass().addClass("sell-color"); + $("#detailChange").removeClass().addClass("sell-color"); + $("#detailPrice").html(Number(data.data.close).toFixed(parseInt(data.data.baseCoinScale))); + $("#detailChange").html(Number(data.data.percent).toFixed(2)+"%"); + } + $("#detailOpen").html(Number(data.data.open).toFixed(parseInt(data.data.baseCoinScale))); + $("#detailHigh").html(Number(data.data.high).toFixed(parseInt(data.data.baseCoinScale))); + $("#detailLow").html(Number(data.data.low).toFixed(parseInt(data.data.baseCoinScale))); + $("#detailVol").html(Number(data.data.vol).toFixed(parseInt(data.data.baseCoinScale))+" "+data.data.pair.split("/")[0]); + var title = Number(data.data.close).toFixed(parseInt(data.data.baseCoinScale)) + " " + Number(data.data.percent).toFixed(2) + "% " + data.data.pair + " " + $("#websiteName").val() + "-" + $("#title").val(); + $("title").html(title); + //change price + $("#pairTitle").html($("#lang-lastest").html()+" "+Number(data.data.close).toFixed(parseInt(data.data.baseCoinScale))+" "+ data.data.pair.split("/")[1]+" ≈ $" + (Number(data.data.usdRate)*Number(data.data.close)).toFixed(6)+""); + $(document).scrollTop(top); + } + }, "json"); +} +function buildDetail(data){ + if(data == null || data == '' || typeof(data) == 'undefined'){ + return; + } + // console.log(JSON.stringify(data)); + var top = $(document).scrollTop(); + //24H + $("#detailPairSymbol").html(data.pair.split("/")[0]); + $("#detailPairBase").html('/ '+data.pair.split("/")[1]); + var isBuy = data.percent > 0; + if(isBuy){ + $("#detailPrice").removeClass().addClass("buy-color"); + $("#detailChange").removeClass().addClass("buy-color"); + $("#detailPrice").html(Number(data.close).toFixed(parseInt(data.baseCoinScale))); + $("#detailChange").html(Number(data.percent).toFixed(2)+"%"); + }else{ + $("#detailPrice").removeClass().addClass("sell-color"); + $("#detailChange").removeClass().addClass("sell-color"); + $("#detailPrice").html(Number(data.close).toFixed(parseInt(data.baseCoinScale))); + $("#detailChange").html(Number(data.percent).toFixed(2)+"%"); + } + $("#detailOpen").html(Number(data.open).toFixed(parseInt(data.baseCoinScale))); + $("#detailHigh").html(Number(data.high).toFixed(parseInt(data.baseCoinScale))); + $("#detailLow").html(Number(data.low).toFixed(parseInt(data.baseCoinScale))); + $("#detailVol").html(Number(data.vol).toFixed(parseInt(data.baseCoinScale))+" "+data.pair.split("/")[0]); + var title = Number(data.close).toFixed(parseInt(data.baseCoinScale)) + " " + Number(data.percent).toFixed(2) + "% " + data.pair + " " + $("#websiteName").val() + "-" + $("#title").val(); + $("title").html(title); + //change price + $("#pairTitle").html($("#lang-lastest").html()+" "+Number(data.close).toFixed(parseInt(data.baseCoinScale))+" "+ data.pair.split("/")[1]+" ≈ $" + (Number(data.usdRate)*Number(data.close)).toFixed(6)+""); + $(document).scrollTop(top); +} + +function getAccount(baseCoin,symbolCoin){ + + if(null == baseCoin || baseCoin == undefined || baseCoin == '' ){ + return; + } + if(null == symbolCoin || symbolCoin == undefined || symbolCoin == '' ){ + return; + } + if(baseCoin == symbolCoin){ + return; + } + + currentBaseCoin = baseCoin; + currentSymbolCoin = symbolCoin; + + //loading覆盖层 + var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + + $.post(ctx+"/trade/getAccount",{"currentBaseCoin":baseCoin,"currentSymbolCoin":symbolCoin},function(data){ + + layer.close(loadindex); + + if(data.code == 0){ + + var useCapitalSymbol = scientificToNumber(data.data.useCapitalSymbol); + var useCapitalSymbolArr = useCapitalSymbol.toString().split("."); + if(useCapitalSymbolArr[1] > 6){ + useCapitalSymbol = useCapitalSymbolArr[0]+"."+useCapitalSymbolArr[1].substr(0,6); + } + if(parseFloat(useCapitalSymbol) == 0){ + useCapitalSymbol = 0; + } + + var useCapitalBase = scientificToNumber(data.data.useCapitalBase); + var useCapitalBaseFloatArr = useCapitalBase.toString().split("."); + if(useCapitalBaseFloatArr[1] > 6){ + useCapitalBase = useCapitalBaseFloatArr[0]+"."+useCapitalBaseFloatArr[1].substr(0,6); + } + if(parseFloat(useCapitalBase) == 0){ + useCapitalBase = 0; + } + $("#currentBaseCoin").val(data.data.currentBaseCoin); + $("#currentSymbolCoin").val(data.data.currentSymbolCoin); + $("#useCapitalBase").val(useCapitalBase); + $("#useCapitalSymbol").val(useCapitalSymbol); + $("#currentPrice").val(scientificToNumber(parseFloat(data.data.currentPrice))); + $("#buyCapital").html(useCapitalBase + " " + data.data.currentBaseCoin); + // $("[name='buyPrice']").val(scientificToNumber(parseFloat(data.data.currentPrice))); + $("[name='buyBaseCoin']").html(data.data.currentBaseCoin); + $("#buySymbolCoin").html(data.data.currentSymbolCoin); + $("#buyCoinSpan").html(data.data.currentSymbolCoin); + $("#sellCoinSpan").html(data.data.currentSymbolCoin); + $("#sellCapital").html(useCapitalSymbol + " " + data.data.currentSymbolCoin); + $("[name='sellBaseCoin']").html(data.data.currentBaseCoin); + $("#sellSymbolCoin").html(data.data.currentSymbolCoin); + $("#buyCapitalInp").val(useCapitalBase); + $("#sellCapitalInp").val(useCapitalSymbol); + $("#buyTotalInp").val(0); + $("#sellTotalInp").val(0); + //系统币不给卖出 + if(currentSymbolCoin == $("#coinCode").val()){ + $("#sell_btn").removeAttr("onclick"); + $("#sell_btn").attr("style","border : 1px solid #c8c8c8 !important;color:#c8c8c8 !important;cursor: not-allowed !important;background-color: #ffff !important;"); + }else{ + $("#sell_btn").attr("onclick","submitTrade('sell')"); + $("#sell_btn").removeAttr("style"); + } + //计算金额 + calculateBuyNum('buy'); + calculateBuyNum('sell'); + $("#sellCode").html(currentSymbolCoin) + $("#buyCode").html(currentSymbolCoin) + if((null != $("#userId").val()) && ($("#userId").val() != '')) { + getDelegateTableData(); + getHistoryDelegateData(); + getClosedDelegateData(); + getRvokedDelegateData(); + } + // calculateSellNum(); + } + }, "json"); + var tradeModel = $(".greactive").attr("name"); + //切换的时候默认切换市价 + cutover(tradeModel); + //加载配置 + contractConfig(currentBaseCoin, currentSymbolCoin); +} + +/** + * 获取杠杆配置 + * @param baseCoin + * @param symbolCoin + */ +function contractConfig(baseCoin,symbolCoin) { + var str = {"pair":symbolCoin + "/" +baseCoin}; + // document.get + $.ajax({ + cache: true, + type: "POST", + url: ctx + "/contract/contractConfig", + data: str, + error: function (request) { + layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + data = JSON.parse(data) + if (data.code == 0) { + var leverage = data.data.leverage; + var split = leverage.split(","); + var msg1 = ""; + for (var i = 0; i < split.length; i++) { + msg1 += ""; + } + $("[name='buyleverage']").html(msg1); + $("[name='sellleverage']").html(msg1); + layui.form.render("select"); + } + } + }); +} + +function cutover(tradeModel) { + if (tradeModel == 'market') { + $("[name='buyPrice']").val(""); + $("[name='sellPrice']").val(""); + $("[name='market']").addClass("greactive"); + $("[name='limit']").removeClass("greactive"); + $("[name='buyPrice']").attr("type", "text"); + $("[name='sellPrice']").attr("type", "text"); + $("[name='buyPrice']").val($("#lang-market_optimal_price").html()); + $("[name='sellPrice']").val($("#lang-market_optimal_price").html()); + $("[name='buyPrice']").attr("readOnly",true); + $("[name='sellPrice']").attr("readOnly",true); + } + if (tradeModel == 'limit') { + $("[name='buyPrice']").val(""); + $("[name='sellPrice']").val(""); + $("[name='limit']").addClass("greactive"); + $("[name='market']").removeClass("greactive"); + $("[name='buyPrice']").attr("type", "number").val($("#currentPrice").val()); + $("[name='sellPrice']").attr("type", "number").val($("#currentPrice").val()); + $("[name='buyPrice']").attr("readOnly",false); + $("[name='sellPrice']").attr("readOnly",false); + } +} +/** +//定时刷新 +var symbolUSDTInterval = setInterval(function(){ + //update symbol + getSymbols('USDT'); +}, 500); +var symbolBTCInterval = setInterval(function(){ + //update symbol + getSymbols('BTC'); +}, 500); +var symbolETHInterval = setInterval(function(){ + //update symbol + getSymbols('ETH'); +}, 500); +var tradeInterval = setInterval(function(){ + //update trade + getTrade(currentSymbol); +}, 500); +var bookInterval = setInterval(function(){ + //update orderbook口 + getOrderbook(currentSymbol); +}, 500); +var detailInterval = setInterval(function(){ + //update 24H trade count + getDetail(currentSymbol); +}, 500); +*/ +function updatePage(data){ + var top = $(document).scrollTop(); + //fav + if(data && data.flag){ + data.symbol = ((data.pair).replace('/','')).toLowerCase(); + data.baseSymbol = ((data.pair).split('/')[1]).toLowerCase(); + data.coinSymbol = ((data.pair).split('/')[0]).toLowerCase(); + } + currentSymbol = data.symbol; + //unsubscribe all + var channel = {}; + channel.event='un_sub'; + channel.id=clientId; + _socket.send(JSON.stringify(channel)); + //recover subscribe + channel.event='sub'; + channel.id=clientId; + channel.model='contract'; + channel.channel=["market."+currentSymbol+".detail","market.pairsgroup","market."+currentSymbol+".trade","market."+currentSymbol+".bbo"/**,"market."+currentSymbol+".kline.1min"*/]; + _socket.send(JSON.stringify(channel)); +// //update trade + getTrade(currentSymbol); +// //update orderbook + getOrderbook(currentSymbol); +// //update 24H trade count + getDetail(currentSymbol); + //update trade form + getAccount(data.baseSymbol,data.coinSymbol); + //update kline + _TVjsApi.symbol = currentSymbol; + _TVjsApi.widgets.chart().setSymbol(currentSymbol.toLocaleUpperCase()); +// _TVjsApi.changeSymbol(currentSymbol.toLocaleUpperCase()); + $(document).scrollTop(top); +// _TVjsApi.widgets.chart().setResolution("1"); + +} +//update favor +$('.main-sidebar-left').on('click','.coinClass',function(event){ + event.stopPropagation(); + event.preventDefault(); + var flag = $(this).hasClass('layui-icon-rate-solid'); + if(flag){ + $(this).removeClass('layui-icon-rate-solid').addClass('layui-icon-rate'); + removeFavor(this); + } else { + $(this).removeClass('layui-icon-rate').addClass('layui-icon-rate-solid'); + addFavor(this); + } +}); +function getKline() { + var top = $(document).scrollTop(); + _TVjsApi = new TVjsApi(currentSymbol, wsPath); +// alert(currentSymbol+","+wsPath); +// setTimeout(function () { _TVjsApi.init(); }, 800); + _TVjsApi.init(); + $(document).scrollTop(top); +// var $select = document.querySelector('#symbol-list'); +// $select.onchange = function(){ +// var symbol = this.value; +// _TVjsApi.symbol = symbol; +// _TVjsApi.widgets.chart().setSymbol(symbol.toLocaleUpperCase()); +// } +// _TVjsApi.resetTheme('black') //切换皮肤 +} +function getMyDate(str){ + var oDate = new Date(str), + oYear = oDate.getFullYear(), + oMonth = oDate.getMonth()+1, + oDay = oDate.getDate(), + oHour = oDate.getHours(), + oMin = oDate.getMinutes(), + oSen = oDate.getSeconds(), + oTime = getzf(oHour) +':'+ getzf(oMin) +':'+getzf(oSen);//最后拼接时间 + return oTime; +}; +//补0操作 +function getzf(num){ + if(parseInt(num) < 10){ + num = '0'+num; + } + return num; +} +$('[name="buyAmount"]').on('keyup', function() { + var amount = $(this).val(); + if(amount == null || amount == '' || $.trim(amount) == '' || typeof(amount) == 'undefined'|| !/^\d+(\.\d+)?$/.test(amount) || parseFloat(amount) <= 0){ + $('[name="buyTotal"]').val("0").change(); + return false; + } + var price = $('[name="buyPrice"]').val(); + if(price == null || price == '' || $.trim(price) == '' || typeof(price) == 'undefined'|| !/^\d+(\.\d+)?$/.test(price) || parseFloat(price) <= 0){ + $('[name="buyTotal"]').val("0").change(); + return false; + } + $('[name="buyTotal"]').val((new BigNumber(price)*new BigNumber(amount)).toFixed(10)).change(); +}); +$('[name="buyPrice"]').on('keyup', function() { + var price = $(this).val(); + if(price == null || price == '' || $.trim(price) == '' || typeof(price) == 'undefined'|| !/^\d+(\.\d+)?$/.test(price) || parseFloat(price) <= 0){ + $('[name="buyTotal"]').val("0").change(); + return false; + } + var amount = $('[name="buyAmount"]').val(); + if(amount == null || amount == '' || $.trim(amount) == '' || typeof(amount) == 'undefined'|| !/^\d+(\.\d+)?$/.test(amount) || parseFloat(amount) <= 0){ + $('[name="buyTotal"]').val("0").change(); + return false; + } + $('[name="buyTotal"]').val((new BigNumber(price)*new BigNumber(amount)).toFixed(10)).change(); +}); +$('[name="sellAmount"]').on('keyup', function() { + var amount = $(this).val(); + if(amount == null || amount == '' || $.trim(amount) == '' || typeof(amount) == 'undefined'|| !/^\d+(\.\d+)?$/.test(amount) || parseFloat(amount) <= 0){ + $('[name="sellTotal"]').val("0").change(); + return false; + } + var price = $('[name="sellPrice"]').val(); + if(price == null || price == '' || $.trim(price) == '' || typeof(price) == 'undefined'|| !/^\d+(\.\d+)?$/.test(price) || parseFloat(price) <= 0){ + $('[name="sellTotal"]').val("0").change(); + return false; + } + $('[name="sellTotal"]').val((new BigNumber(price)*new BigNumber(amount)).toFixed(10)).change(); +}); +$('[name="sellPrice"]').on('keyup', function() { + var price = $(this).val(); + if(price == null || price == '' || $.trim(price) == '' || typeof(price) == 'undefined'|| !/^\d+(\.\d+)?$/.test(price) || parseFloat(price) <= 0){ + $('[name="sellTotal"]').val("0").change(); + return false; + } + var amount = $('[name="sellAmount"]').val(); + if(amount == null || amount == '' || $.trim(amount) == '' || typeof(amount) == 'undefined'|| !/^\d+(\.\d+)?$/.test(amount) || parseFloat(amount) <= 0){ + $('[name="sellTotal"]').val("0").change(); + return false; + } + $('[name="sellTotal"]').val((new BigNumber(price)*new BigNumber(amount)).toFixed(10)).change(); +}); +/** + * 购买操作 + */ +function submitTrade(direction){ + if (didsim) { + layer.msg($("#lang-please_do_not_submit_repeatedly").html(),{offset:"400px"}); + return; + } + var amountStr = $("input[name='"+direction+"Amount']").val(); + var amount = parseFloat(amountStr); // 购买数量 + var leverage = parseFloat($("select[name='"+direction+"leverage']").val()); + var tradeModel = $(".greactive").attr("name"); + var openedPrice = 0; + if(tradeModel == null || tradeModel == '' || $.trim(tradeModel) == '' || typeof(tradeModel) == 'undefined'){ + // layer.msg("Price is incorrect."); + // layer.msg($("#lang-price_is_incorrect").html(),{offset:"400px"}); + return; + } + if(tradeModel == 'limit' ){ + openedPrice = $("input[name='"+direction+"Price']").val(); + if(openedPrice == null || openedPrice == '' || $.trim(openedPrice) == '' || typeof(openedPrice) == 'undefined' || !/^\d+(\.\d+)?$/.test(openedPrice) || parseFloat(openedPrice) <= 0){ + // layer.msg("Price is incorrect."); + layer.msg($("#lang-price_is_incorrect").html(),{offset:"400px"}); + return; + } + } + var str = { + amount: amount, //数量 + direction: direction, //方向 buy:买 sell:卖 + leverage: leverage, //杠杆 + tradeModel: tradeModel, //交易模式 + pair: currentSymbolCoin +"/"+currentBaseCoin, //交易对 + source: "H5", //来源 + openedPrice: openedPrice //开盘价 + }; + + didsim = true; + + //loading覆盖层 + var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + + $.ajax({ + cache: true, + type: "POST", + url: "/contract/order", + data: str, + error: function (request) { + layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + layer.close(loadindex); + var obj = toLogin(data); + if(!obj){ + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + if (obj.code == 0) { + layer.msg($("#lang-the_transaction_application_has_been_successfully_submitted").html(),{offset:"400px"}); + console.log(data.data) + console.log(obj.data) + if (obj.data != null) { + $("#sellUsable").val(obj.data); + $("#buyUsable").val(obj.data); + } + setTimeout(function (){ + //重载表格数据 + getDelegateTableData(); + getHistoryDelegateData(); + getClosedDelegateData(); + getRvokedDelegateData(); + //update trade form + getAccount(currentBaseCoin,currentSymbolCoin); + },2000); + }else if(obj.code == 6){ + vefificationDialog();//跳转实名验证 + }else if(obj.code == 7){ + invitationVerification();//跳转填写邀请码 + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); + //状态到期后自动改回 + setTimeout(function () { + didsim = false; + }, simTime); + +} + + +/** + * 计算兑换数量-购买模块 + */ +function calculateBuyNum(direction){ + var amountStr = $("input[name='"+direction+"Amount']").val(); + var amount = parseFloat(amountStr); // 购买数量 + var leverage = parseFloat($("select[name='"+direction+"leverage']").val()); + var tradeModel = $(".greactive").attr("name"); + var openedPrice = $("#currentPrice").val(); + var rate = $("#rate").val(); + if (tradeModel == 'limit') { + openedPrice = $("input[name='"+direction+"Price']").val(); + } + var total = openedPrice * amount; + var bond = openedPrice / leverage * amount; + var fee = openedPrice / leverage * amount * rate; + $("input[name='"+direction+"Total']").val(total.toFixed(8)); + $("input[name='"+direction+"bond']").val(bond.toFixed(8)); + $("input[name='"+direction+"fee']").val(fee.toFixed(8)); + } + +/** + * 计算兑换数量-出售模块 + */ +function calculateSellNum(){ + + var sellPrice = $("#sellPriceInp").val() + var sellAmount = $("#sellAmountInp").val() + + if(null == sellPrice && sellPrice == ''){ + $("#sellTotalInp").val(0.00000000); + return; + } + if(null == sellAmount && sellAmount == ''){ + $("#sellTotalInp").val(0.00000000); + return; + } + + var sellTotal = Number(sellPrice) * Number(sellAmount); + $("#sellTotalInp").val(sellTotal.toFixed(8)); + +} + +/** + * 获取表格数据-Delegate + */ +function getDelegateTableData (){ + + // //loading覆盖层 + // var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + var pair = currentSymbolCoin + "/" +currentBaseCoin; + var str = {status: 'opened', pair: pair}; + $.ajax({ + cache: true, + type: "POST", + url: "/contract/orderList", + data: str, + error: function (request) { + // layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + // layer.close(loadindex); + var obj = toLogin(data); + if(!obj){ + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + if (obj.code == 0) { + if(null != obj.data.content){ + contractsTableData = obj.data.content; + } + //渲染-Delegate-表格 + showDelegateTable(); + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); + +} + + +/** + * 获取表格数据-Delegate + */ +function getClosedDelegateData (){ + + //loading覆盖层 + // var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + var pair = currentSymbolCoin + "/" +currentBaseCoin; + var str = {"status": 'closed', "pair":pair}; + $.ajax({ + cache: true, + type: "POST", + url: "/contract/orderList", + data: str, + error: function (request) { + // layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + // layer.close(loadindex); + var obj = toLogin(data); + if(!obj){ + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + if (obj.code == 0) { + if(null != obj.data.content){ + closedDelegateTableData = obj.data.content; + } + //渲染-Delegate-表格 + showClosedDelegateTable(); + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); + +} +/** + * 渲染-closed-表格 + */ +function showClosedDelegateTable() { + layui.use(['table'], function () { + var table = layui.table; //表格 + // Delegate + ClosedDelegate = table.render({ + elem: '#ClosedDelegate', + data: closedDelegateTableData, + id: 'ClosedDelegate', + text: {none: "No Data"}, + cols: [[ + { + field: 'pair', + title: $("#lang-pair").html(), + width: '10%', + align: 'center', + templet: showPair + // templet: '
{{ layui.util.toDateString(d.addTime, "dd/MM/yyyy HH:mm:ss") }}
' + }, + { + field: 'openedPrice', + title: $("#lang-openedPrice").html(), + width: '8%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.openedPrice); + } + }, + { + field: 'currentPrice', + // title: $("#lang-currentPrice").html(), + title: 'Close price', + width: '8%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.closedPrice); + } + }, + {field: 'Amount', + title: $("#lang-amount").html(), + width: '8%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.hand); + } + }, + {field: 'bondAmount', + title: $("#lang-bondAmount").html(), + width: '10%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.bondAmount); + } + }, + {field: 'winStopPrice', + title: $("#lang-winStopPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.winStopPrice); + } + }, + {field: 'lossStopPrice', + title: $("#lang-lossStopPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.lossStopPrice); + } + }, + {field: 'openedTime', + title: $("#lang-openedTime").html(), + width: '10%', + align: 'center', + templet: function (d) { + return dateForm(getLocalDate(d.openedTime)); + } + // '
{{ layui.util.toDateString(d.openedTime, "dd/MM/yyyy HH:mm:ss") }}
' + }, + {field: 'profitAmount', + title: $("#lang-profitAmount").html(), + width: '10%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.profitAmount-d.fee); + } + } + ]], + skin: 'nob', + // page: false, + page: { //支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档 + layout: ['count', 'prev', 'page', 'next'], //自定义分页布局 + groups: 7, // 只显示 7 个连续页码 + first: false, //不显示首页 + last: false, //不显示尾页 + size: 10, + }, + text: {none: "No Data"}, + }); + + }); + +} + +/** + * 获取表格数据-Delegate + */ +function getRvokedDelegateData (){ + + //loading覆盖层 + // var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + var pair = currentSymbolCoin + "/" +currentBaseCoin; + var str = {"status": 'revoked', "pair":pair}; + $.ajax({ + cache: true, + type: "POST", + url: "/contract/orderList", + data: str, + error: function (request) { + // layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + // layer.close(loadindex); + var obj = toLogin(data); + if(!obj){ + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + if (obj.code == 0) { + if(null != obj.data.content){ + rvokedDelegateTableData = obj.data.content; + } + //渲染-Delegate-表格 + showRvokedDelegateTable(); + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); + +} + +/** + * 渲染-Delegate-表格 + */ +function showRvokedDelegateTable() { + layui.use(['table'], function () { + var table = layui.table; //表格 + // Delegate + RvokedDelegate = table.render({ + elem: '#RvokedDelegate', + data: rvokedDelegateTableData, + id: 'RvokedDelegate', + text: {none: "No Data"}, + cols: [[ + { + field: 'pair', + title: $("#lang-pair").html(), + width: '10%', + align: 'center', + templet: showPair + // templet: '
{{ layui.util.toDateString(d.addTime, "dd/MM/yyyy HH:mm:ss") }}
' + }, + { + field: 'openedPrice', + title: $("#lang-openedPrice").html(), + width: '20%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.openedPrice); + } + }, + // { + // field: 'currentPrice', + // title: $("#lang-currentPrice").html(), + // width: '10%', + // align: 'center', + // templet: function (d) { + // return tablePriceShow(d.pair,d.currentPrice); + // } + // }, + {field: 'Amount', + title: $("#lang-amount").html(), + width: '8%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.hand); + } + }, + {field: 'bondAmount', + title: $("#lang-bondAmount").html(), + width: '20%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.bondAmount); + } + }, + {field: 'winStopPrice', + title: $("#lang-winStopPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.winStopPrice); + } + }, + {field: 'lossStopPrice', + title: $("#lang-lossStopPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.lossStopPrice); + } + }, + {field: 'openedTime', + title: $("#lang-time").html(), + width: '20%', + align: 'center', + templet: function (d) { + return dateForm(getLocalDate(d.revokedTime)); + } + // '
{{ layui.util.toDateString(d.openedTime, "dd/MM/yyyy HH:mm:ss") }}
' + } + ]], + skin: 'nob', + // page: false, + page: { //支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档 + layout: ['count', 'prev', 'page', 'next'], //自定义分页布局 + groups: 7, // 只显示 7 个连续页码 + first: false, //不显示首页 + last: false, //不显示尾页 + size: 10, + }, + text: {none: "No Data"}, + }); + + }); + +} + + + +/** + * 渲染-Delegate-表格 + */ +function showDelegateTable() { + layui.use(['table'], function () { + var table = layui.table; //表格 + // Delegate + Contracts = table.render({ + elem: '#Contracts', + data: contractsTableData, + id: 'Contracts', + text: {none: "No Data"}, + cols: [[ + { + field: 'pair', + title: $("#lang-pair").html(), + width: '10%', + align: 'center', + templet: showPair + // templet: '
{{ layui.util.toDateString(d.addTime, "dd/MM/yyyy HH:mm:ss") }}
' + }, + { + field: 'openedPrice', + title: $("#lang-openedPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.openedPrice); + } + }, + { + field: 'currentPrice', + title: $("#lang-currentPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.currentPrice); + } + }, + {field: 'Amount', + title: $("#lang-amount").html(), + width: '10%', + align: 'center', + templet: function (d) { + // return scientificToNumber(d.hand); + return d.hand; + } + }, + {field: 'bondAmount', + title: $("#lang-bondAmount").html(), + width: '8%', + align: 'center', + templet: function (d) { + // return scientificToNumber(d.bondAmount); + return (d.bondAmount); + } + }, + {field: 'winStopPrice', + title: $("#lang-winStopPrice").html(), + width: '8%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.winStopPrice); + } + }, + {field: 'lossStopPrice', + title: $("#lang-lossStopPrice").html(), + width: '8%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.lossStopPrice); + } + }, + {field: 'openedTime', + title: $("#lang-openedTime").html(), + width: '8%', + align: 'center', + templet: function (d) { + return dateForm(getLocalDate(d.openedTime)); + } + // '
{{ layui.util.toDateString(d.openedTime, "dd/MM/yyyy HH:mm:ss") }}
' + }, + {field: 'profitAmount', + title: $("#lang-profitAmount").html(), + width: '8%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.profitAmount); + // return (d.profitAmount); + } + }, + { + title: $("#lang-action").html(), + width: '14%', + align: 'center', + toolbar: '#cancelButton' + } + ]], + skin: 'nob', + // page: false, + page: { //支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档 + layout: ['count', 'prev', 'page', 'next'], //自定义分页布局 + groups: 7, // 只显示 7 个连续页码 + first: false, //不显示首页 + last: false, //不显示尾页 + size: 10, + }, + text: {none: "No Data"}, + }); + + }); + +} + +/** + * 获取表格数据-HistoryDelegate + */ +function getHistoryDelegateData(){ + //loading覆盖层 + // var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + var pair = currentSymbolCoin + "/" +currentBaseCoin; + var str = {status: 'undone', pair: pair}; + $.ajax({ + cache: true, + type: "POST", + url: "/contract/orderList", + data: str, + error: function (request) { + // layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + // layer.close(loadindex); + var obj = toLogin(data); + if(!obj){ + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + + if (obj.code == 0) { + + if(null != obj.data.content){ + historyDelegateTableData = obj.data.content; + } + //渲染-Delegate-表格 + showHistoryDelegateTable(); + + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); +} + +/** + * 渲染-HistoryDelegate-表格 + */ +function showHistoryDelegateTable() { + layui.use(['table'], function () { + var table = layui.table; //表格 + + // HistoryDelegate + HistoryDelegate = table.render({ + elem: '#HistoryDelegate', + data: historyDelegateTableData, + cols: [[ + { + field: 'pair', + title: $("#lang-pair").html(), + width: '10%', + align: 'center', + templet: showPair + }, + { + field: 'openedPrice', + title: $("#lang-openedPrice").html(), + width: '15%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.openedPrice); + } + }, + // { + // field: 'currentPrice', + // // title: $("#lang-currentPrice").html(), + // title: 'Close price', + // width: '10%', + // align: 'center', + // templet: function (d) { + // return tablePriceShow(d.pair,d.closePrice); + // } + // }, + {field: 'Amount', + title: $("#lang-amount").html(), + width: '10%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.hand); + } + }, + {field: 'bondAmount', + title: $("#lang-bondAmount").html(), + width: '15%', + align: 'center', + templet: function (d) { + return scientificToNumber(d.bondAmount); + } + }, + {field: 'winStopPrice', + title: $("#lang-winStopPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.winStopPrice); + } + }, + {field: 'lossStopPrice', + title: $("#lang-lossStopPrice").html(), + width: '10%', + align: 'center', + templet: function (d) { + return tablePriceShow(d.pair,d.lossStopPrice); + } + }, + {field: 'openedTime', + title: $("#lang-time").html(), + width: '20%', + align: 'center', + templet: function (d) { + return dateForm(getLocalDate(d.addTime)); + } + // '
{{ layui.util.toDateString(d.openedTime, "dd/MM/yyyy HH:mm:ss") }}
' + }, + // {field: 'profitAmount', + // title: $("#lang-profitAmount").html(), + // width: '10%', + // align: 'center', + // templet: function (d) { + // return scientificToNumber(d.profitAmount-d.fee); + // } + // }, + { + title: $("#lang-action").html(), + width: '10%', + align: 'center', + toolbar: '#cancelButton' + } + ]], + skin: 'nob', + // page: false, + page: { //支持传入 laypage 组件的所有参数(某些参数除外,如:jump/elem) - 详见文档 + layout: ['count', 'prev', 'page', 'next'], //自定义分页布局 + groups: 7, // 只显示 7 个连续页码 + first: false, //不显示首页 + last: false, //不显示尾页 + size: 10, + }, + text: {none: "No Data"}, + }); + + }); +} + + +/** + * 点击撤销订单 + */ +function cancelOrder(orderNo) { + layer.open({ + type: 1 + , title: $("#lang-warning").html() + , offset: '250px' //具体配置参考:http://www.layui.com/doc/modules/layer.html#offset + , id: 'layerDemo' //防止重复弹出 + , content: '
'+$("#lang-are_you_sure_to_cancel_this_order").html()+'
' + , btn: [$("#lang-ok").html(), $("#lang-cancel").html()] + , btnAlign: 'c' //按钮居中 + , shade: 0 //不显示遮罩 + , yes: function () { + layer.closeAll(); + + //loading覆盖层 + var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + + $.ajax({ + cache: true, + type: "POST", + url: "/contract/cancel", + data: {orderNo: orderNo}, + error: function (request) { + layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + + layer.close(loadindex); + var obj = toLogin(data); + if (!obj) { + // layer.msg("Login expired !", {offset: "400px"}); + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + if (obj.code == 0) { + // layer.msg("Order has been cancelled"); + layer.msg($("#lang-order_has_been_cancelled").html(),{offset:"400px"}); + //渲染表格 + getDelegateTableData(); + getHistoryDelegateData(); + getClosedDelegateData(); + getRvokedDelegateData(); + //update trade form + getAccount($("#currentBaseCoin").val(), $("#currentSymbolCoin").val()); + + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); + } + }); + +} + + +/** + * 点击平仓 + */ +function closed(orderNo) { + layer.open({ + type: 1 + , title: $("#lang-warning").html() + , offset: '250px' //具体配置参考:http://www.layui.com/doc/modules/layer.html#offset + , id: 'layerDemo' //防止重复弹出 + , content: '
'+$("#lang-are_you_sure_to_closed_this_order").html()+'
' + , btn: [$("#lang-ok").html(), $("#lang-cancel").html()] + , btnAlign: 'c' //按钮居中 + , shade: 0 //不显示遮罩 + , yes: function () { + layer.closeAll(); + + //loading覆盖层 + var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + + $.ajax({ + cache: true, + type: "POST", + url: "/contract/closed", + data: {orderNo: orderNo}, + error: function (request) { + + layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + + layer.close(loadindex); + var obj = toLogin(data); + if (!obj) { + // layer.msg("Login expired !", {offset: "400px"}); + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + if (obj.code == 0) { + // layer.msg("Order has been cancelled"); + layer.msg($("#lang-order_has_been_cancelled").html(),{offset:"400px"}); + //渲染表格 + getDelegateTableData(); + getHistoryDelegateData(); + getClosedDelegateData(); + getRvokedDelegateData(); + //update trade form + getAccount($("#currentBaseCoin").val(), $("#currentSymbolCoin").val()); + + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); + } + }); + +} + +/** + * 设置止盈止损 + */ +function setPrice(orderNo) { + var openIndex = layer.open({ + type: 1 + , title: $("#lang-setPrice").html() + , area: ['580px', '420px'] + , offset: '200px' + , type: 2 + ,fixed: false //不固定 + , id: 'layerDemo' //防止重复弹出 + , content: [ctx + '/contract/setPrice?orderNo=' + orderNo, 'no'] + , btn: [$("#lang-ok").html(), $("#lang-cancel").html()] + , btnAlign: 'c' //按钮居中 + , shade: 0 //不显示遮罩 + , yes: function (index, layero) { + + //取到页面对象 + var body = layer.getChildFrame('body', index); + + var winStopPrice = body.contents().find("#winStopPrice").val(); + var lossStopPrice = body.contents().find("#lossStopPrice").val(); + + //loading覆盖层 + var loadindex = layer.load(1, {shade: [0.5, '#fff'], offset: '400px'}); + var str = { + orderNo: orderNo, + winStopPrice: winStopPrice, + lossStopPrice: lossStopPrice + }; + $.ajax({ + cache: true, + type: "POST", + url: "/contract/setWinOrLossStopPrice", + data: str, + error: function (request) { + + layer.close(loadindex); + layer.msg(request.msg,{offset:"400px"}); + }, + success: function (data) { + + layer.close(loadindex); + var obj = toLogin(data); + if (!obj) { + // layer.msg("Login expired !", {offset: "400px"}); + layer.msg($("#lang-login_expired").html(),{offset:"400px"}); + return; + } + if (obj.code == 0) { + layer.close(openIndex); + // layer.msg("Order has been cancelled"); + layer.msg($("#lang-successfully").html(),{offset:"400px"}); + //渲染表格 + getDelegateTableData(); + getHistoryDelegateData(); + getClosedDelegateData(); + getRvokedDelegateData(); + //update trade form + getAccount($("#currentBaseCoin").val(), $("#currentSymbolCoin").val()); + + } else { + layer.msg(obj.msg,{offset:"400px"}); + } + } + }); + } + }); + +} + + +/** + * 去实名弹出框 + */ +function vefificationDialog(){ + layer.open({ + type: 1 + , + title: $("#lang-message").html() + , + offset: '250px' //具体配置参考:http://www.layui.com/doc/modules/layer.html#offset + , + id: 'layerCheckOpen' //防止重复弹出 + , + content: '
'+$("#lang-you_have_not_complete_real_name").html()+'
' + , + btn: [$("#lang-to_certification").html(), $("#lang-cancel").html()] + , + btnAlign: 'c' //按钮居中 + , + shade: 0 //不显示遮罩 + , + yes: function () { + window.location.href = $("#ctx").val() + "/finance/securityCenter?certification=true"; + return; + } + }); +} +/** + * 去 填写邀请码 弹出框 + */ +function invitationVerification(){ + layer.open({ + type: 1 + , + title: $("#lang-message").html() + , + offset: '250px' //具体配置参考:http://www.layui.com/doc/modules/layer.html#offset + , + id: 'layerCheckOpen' //防止重复弹出 + , + content: '
You have not bind the invite code,Whether bind now?
' + , + btn: [$("#lang-to_certification").html(), $("#lang-cancel").html()] + , + btnAlign: 'c' //按钮居中 + , + shade: 0 //不显示遮罩 + , + yes: function () { + // window.location.href = $("#ctx").val() + "/finance/invite"; + window.location.href = $("#ctx").val() + "/finance/newInnovation2"; + return; + } + }); +} + +// +// setInterval(function () { +// updateDelegateTableData(); +// }, 3000); + +//更新图表中 收益 以及当前价格 +function updateDelegateTableData(data) { + //contractsTableData + if (contractsTableData.length > 0) { + var currentPrice = data.close; + var profitAmount = 0.00; + for (var i in contractsTableData) { + contractsTableData[i].currentPrice = currentPrice; + if (contractsTableData[i].direction == 'buy' && contractsTableData[i].leverage != 0) { + profitAmount = (currentPrice - contractsTableData[i].openedPrice) * contractsTableData[i].hand - contractsTableData[i].fee; + } + if (contractsTableData[i].direction == 'sell' && contractsTableData[i].leverage != 0) { + profitAmount = (contractsTableData[i].openedPrice - currentPrice) * contractsTableData[i].hand - contractsTableData[i].fee; + } + contractsTableData[i].profitAmount = profitAmount; + } + //渲染-Delegate-表格 + showDelegateTable(); + } + } + + //存一下币种与对应精度 +function setCoinAndScale(data){ + var baseCoinScale = 0; + var coinSymbol = ""; + coinAndScale = {} + if(null != data){ + for(var i in data){ + baseCoinScale = data[i].baseCoinScale; + coinSymbol = data[i].coinSymbol; + if(null != baseCoinScale && baseCoinScale != undefined && baseCoinScale != ""){ + coinAndScale[coinSymbol] = baseCoinScale; + } + } + } +} + +function tablePriceShow(pair,amount){ + if(null != pair && pair != undefined && pair != '' && null != amount && amount != undefined && amount != ''){ + var coinSymbol = pair.split("/")[0]; + if(null != coinAndScale && null != coinAndScale[coinSymbol]){ + return parseFloat(amount).toFixed(coinAndScale[coinSymbol]); + }else{ + scientificToNumber(amount); + } + }else{ + return 0.00 + } +} + +function showPair(data){ + var direction = data.direction; + if(direction == "buy"){ + return ""+ data.pair +" "+ data.leverage +"X ↑"; + }else { + return ""+ data.pair +" "+ data.leverage +"X ↓"; + } +} + +$(function(){ +// marketPath = $("#marketPath").val(); +// if($("#wsPath").val() != null && $("#wsPath").val() != '' && $("#wsPath").val() != undefined){ +// wsPath = $("#wsPath").val(); +// } + ctx = $("#ctx").val(); + userId = $("#userId").val(); + currentSymbol = $("#symbol").val(); + currentBaseCoin = $("#currentBaseCoin").val(); + currentSymbolCoin = $("#currentSymbolCoin").val(); + //get favor +// getFavor(); +// //init get symbol + setTimeout(function (){ + getSymbols('USDT'); + },2000); +// //init get trade list + getTrade(currentSymbol); +// //init get orderbook list + getOrderbook(currentSymbol); +// //init get 24H trade cout + getDetail(currentSymbol); + //start websocket + startWebsocket(); + //init get kline +// getKline(); + + //加载配置 + cutover('market'); + + setTimeout(function (){ + contractConfig(currentBaseCoin, currentSymbolCoin); + + if((null != $("#userId").val()) && ($("#userId").val() != '')){ + //获取表格数据-Delegate + getDelegateTableData(); + getHistoryDelegateData(); + getClosedDelegateData(); + getRvokedDelegateData(); + }else{ + showDelegateTable(); + showHistoryDelegateTable(); + showClosedDelegateTable(); + showRvokedDelegateTable(); + } + },3000); +}); \ No newline at end of file diff --git a/components/kline/tradingView/datafeed.js b/components/kline/tradingView/datafeed.js index 0edecf7..877c611 100644 --- a/components/kline/tradingView/datafeed.js +++ b/components/kline/tradingView/datafeed.js @@ -15,7 +15,7 @@ import { // 历史数据 第一条数据的 时间撮 因为k线图一次性历史数据只拿一部分,用户吧图往前滑动,就会用这个时间撮去请求更早的 历史数据 -var detafeed_historyTime = null +var detafeed_historyTime = 0 // 上一次的 K线周期 切换产品的时候 需要从websock 取消订阅这个 var detafeed_lastResolution = null // 上一次的产品 切换产品的时候 需要从websock 取消订阅这个 @@ -32,7 +32,7 @@ FeedBase.prototype.getSendSymbolName = function(symbolName) { var name = symbolName.split('/') return (name[0] + name[1]).toLocaleLowerCase() } - + FeedBase.prototype.resolveSymbol = function(symbolName, onResolve, onError) { onResolve({ "name": symbolName, @@ -45,15 +45,10 @@ FeedBase.prototype.resolveSymbol = function(symbolName, onResolve, onError) { "session": "24x7", "type": "bitcoin", "volume_precision": 10, - "has_intraday": true, - "seconds_multipliers":['1', '5', '15', '30', '60', '1D', '1W','1M'], - "intraday_multipliers": ['1', '5', '15', '30', '60', '1D', '1W','1M'], - "has_seconds":true, - "supports_marks": true, - "supports_timescale_marks": true, - "supported_time": true, - "has_weekly_and_monthly": true, - "has_no_volume": true, + "has_intraday": true, + "intraday_multipliers": ['1', '5', '15', '30', '60', '240', '1440'], // 时间 + "has_weekly_and_monthly": false, + "has_no_volume": false, "regular_session": "24x7", }) @@ -70,7 +65,7 @@ FeedBase.prototype.resolveSymbol = function(symbolName, onResolve, onError) { const resolutionFormat = (resolution, name, to) => { let req = `market.${name}.kline.${resolution}min`; let minutes = resolution; - console.log(resolution) + if (resolution.includes('D')) { if (resolution.length < 2) resolution = '1' + resolution; req = `market.${name}.kline.${parseInt(resolution)}day`; @@ -91,12 +86,11 @@ const resolutionFormat = (resolution, name, to) => { let from = null; if (to) { - from = to - 50 * minutes * 500; + from = to - 50 * minutes * 60; if (resolution.includes('M') || resolution.includes('W')) { // 周线月线控制条数,时间超出火币规定范围, ws报错 - from = to - 50 * minutes * 500; + from = to - 50 * minutes * 60; } - } - + } return { minutes, req, @@ -106,13 +100,11 @@ const resolutionFormat = (resolution, name, to) => { }; FeedBase.prototype.getBars = function(symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) { - console.log("获取历史数据",periodParams) + console.log("获取历史数据") // 切换产品周期 或者 切换产品 会执行这个函数 - let reso = resolutionFormat(resolution, symbolInfo.name, periodParams.to) - // if (resolution.includes('M') || resolution.includes('W')|| resolution.includes('D')) { // 周线月线控制条数,时间超出火币规定范围, ws报错 - // reso = resolutionFormat(resolution, symbolInfo.name, periodParams.to) - // } - + let reso = resolutionFormat(resolution, symbolInfo.name, periodParams.to > detafeed_historyTime ? periodParams + .to : + detafeed_historyTime) // 是历史数据 var history = true /* @@ -135,19 +127,16 @@ FeedBase.prototype.getBars = function(symbolInfo, resolution, periodParams, onHi 第二个参数订阅实时数据 第三个参数 是 是否是历史数据 */ - socket.sendData({ - event: "req", - type: "kline", - channel: [reso.req], - fromDate:reso.from, - toDate:reso.to + socket.sendData({ + req: reso.req, + id: "id10", + from: reso.from, + to: reso.to, }, reso.req, history) - Event.off('data') - Event.on('data', data => { - + Event.on('data', data => { if (data && Array.isArray(data)) { // 记录这次请求的时间周期 detafeed_lastResolution = resolution @@ -162,14 +151,13 @@ FeedBase.prototype.getBars = function(symbolInfo, resolution, periodParams, onHi i.volume = i.vol datas.push(i) } - } else { - console.log('进来') + } else { meta = { - noData: 'no_data', + noData: true, nextTime: detafeed_historyTime } } - onHistoryCallback(datas, {noData:data.length==0}) + onHistoryCallback(datas, meta) } }) } diff --git a/components/kline/tradingView/datafeed1.js b/components/kline/tradingView/datafeed2.js similarity index 85% rename from components/kline/tradingView/datafeed1.js rename to components/kline/tradingView/datafeed2.js index 877c611..4254937 100644 --- a/components/kline/tradingView/datafeed1.js +++ b/components/kline/tradingView/datafeed2.js @@ -1,205 +1,217 @@ -/*********************************************/ - -// 次文件只需要关注 getBars 和 subscribeBars 函数即可 - -/******************************************/ - - -import { - socket -} from './websocket.js' - -import { - Event -} from './event.js' - - -// 历史数据 第一条数据的 时间撮 因为k线图一次性历史数据只拿一部分,用户吧图往前滑动,就会用这个时间撮去请求更早的 历史数据 -var detafeed_historyTime = 0 -// 上一次的 K线周期 切换产品的时候 需要从websock 取消订阅这个 -var detafeed_lastResolution = null -// 上一次的产品 切换产品的时候 需要从websock 取消订阅这个 -var detafeed_lastSymbol = null - - -function FeedBase() {} - -FeedBase.prototype.onReady = function(callback) { - callback(this._configuration) -} - -FeedBase.prototype.getSendSymbolName = function(symbolName) { - var name = symbolName.split('/') - return (name[0] + name[1]).toLocaleLowerCase() -} - -FeedBase.prototype.resolveSymbol = function(symbolName, onResolve, onError) { - onResolve({ - "name": symbolName, - "timezone": "Asia/Shanghai", - "pricescale": 10000000000000000, - "minmov": 1, - "minmov2": 0, - "ticker": symbolName, - "description": "", - "session": "24x7", - "type": "bitcoin", - "volume_precision": 10, - "has_intraday": true, - "intraday_multipliers": ['1', '5', '15', '30', '60', '240', '1440'], // 时间 - "has_weekly_and_monthly": false, - "has_no_volume": false, +/*********************************************/ + +// 次文件只需要关注 getBars 和 subscribeBars 函数即可 + +/******************************************/ + + +import { + socket +} from './websocket.js' + +import { + Event +} from './event.js' + + +// 历史数据 第一条数据的 时间撮 因为k线图一次性历史数据只拿一部分,用户吧图往前滑动,就会用这个时间撮去请求更早的 历史数据 +var detafeed_historyTime = null +// 上一次的 K线周期 切换产品的时候 需要从websock 取消订阅这个 +var detafeed_lastResolution = null +// 上一次的产品 切换产品的时候 需要从websock 取消订阅这个 +var detafeed_lastSymbol = null + + +function FeedBase() {} + +FeedBase.prototype.onReady = function(callback) { + callback(this._configuration) +} + +FeedBase.prototype.getSendSymbolName = function(symbolName) { + var name = symbolName.split('/') + return (name[0] + name[1]).toLocaleLowerCase() +} + +FeedBase.prototype.resolveSymbol = function(symbolName, onResolve, onError) { + onResolve({ + "name": symbolName, + "timezone": "Asia/Shanghai", + "pricescale": 10000000000000000, + "minmov": 1, + "minmov2": 0, + "ticker": symbolName, + "description": "", + "session": "24x7", + "type": "bitcoin", + "volume_precision": 10, + "has_intraday": true, + "seconds_multipliers":['1', '5', '15', '30', '60', '1D', '1W','1M'], + "intraday_multipliers": ['1', '5', '15', '30', '60', '1D', '1W','1M'], + "has_seconds":true, + "supports_marks": true, + "supports_timescale_marks": true, + "supported_time": true, + "has_weekly_and_monthly": true, + "has_no_volume": true, "regular_session": "24x7", - - }) -} - - -/** - * 更多时间类型在这里添加 时间类型请看火币文档 - * @param resolution 订阅周期 按照自己喜欢的来 如 30 30分钟、 1D 一天 - * @param name 交易对symbol - * @param to 结束时间 - * @returns {object} - */ -const resolutionFormat = (resolution, name, to) => { - let req = `market.${name}.kline.${resolution}min`; - let minutes = resolution; - - if (resolution.includes('D')) { - if (resolution.length < 2) resolution = '1' + resolution; - req = `market.${name}.kline.${parseInt(resolution)}day`; - minutes = parseInt(resolution) * 24 * 60; - } else if (resolution.includes('W')) { - if (resolution.length < 2) resolution = '1' + resolution; - req = `market.${name}.kline.${parseInt(resolution)}week`; - minutes = parseInt(resolution) * 24 * 60 * 7; - } else if (resolution.includes('M')) { - if (resolution.length < 2) resolution = '1' + resolution; - req = `market.${name}.kline.${parseInt(resolution)}mon`; - minutes = parseInt(resolution) * 24 * 60 * 30; - } else { - if (resolution / 60 > 1) { - req = `market.${name}.kline.${resolution / 60}hour`; - } - } - - let from = null; - if (to) { - from = to - 50 * minutes * 60; - if (resolution.includes('M') || resolution.includes('W')) { // 周线月线控制条数,时间超出火币规定范围, ws报错 - from = to - 50 * minutes * 60; - } - } - return { - minutes, - req, - from, - to, - }; -}; - -FeedBase.prototype.getBars = function(symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) { - console.log("获取历史数据") - // 切换产品周期 或者 切换产品 会执行这个函数 - let reso = resolutionFormat(resolution, symbolInfo.name, periodParams.to > detafeed_historyTime ? periodParams - .to : - detafeed_historyTime) - // 是历史数据 - var history = true - /* - !detafeed_historyTime 如果没请请求过这个产品或者这个周期的历史数据 - resolution !== detafeed_lastResolution 是否更换了产品周期 - detafeed_lastSymbol !== symbolInfo.name 是否切换了产品 - */ - if (!detafeed_historyTime || (resolution !== detafeed_lastResolution) || detafeed_lastSymbol !== symbolInfo - .name) { - // 那就不是历史数据 - history = false - // 储存请求过的产品 - detafeed_lastSymbol = symbolInfo.name - // 记录目前时间戳,就用目前时间戳往前请求历史数据 - detafeed_historyTime = window.parseInt((Date.now() / 1000)) - } - /* - @socket.sendData - 第一个参数订阅历史数据 - 第二个参数订阅实时数据 - 第三个参数 是 是否是历史数据 - */ - socket.sendData({ - req: reso.req, - id: "id10", - from: reso.from, - to: reso.to, - }, reso.req, history) - - Event.off('data') - - Event.on('data', data => { - if (data && Array.isArray(data)) { - // 记录这次请求的时间周期 - detafeed_lastResolution = resolution - var meta = { - noData: false - } - const datas = [] - if (data.length) { - detafeed_historyTime = data[0].id - for (let i of data) { - i.time = i.id * 1000 - i.volume = i.vol - datas.push(i) - } - } else { - meta = { - noData: true, - nextTime: detafeed_historyTime - } - } - onHistoryCallback(datas, meta) - } - }) -} - -FeedBase.prototype.subscribeBars = function(symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) { - Event.off('realTime') - // 拿到实时数据 在这里画 - Event.on('realTime', data => { - if (Object.prototype.toString.call(data) === '[object Object]' && data.hasOwnProperty('open')) { - //因为有的数值为科学计数法,故增加了转换函数,因为修改了源码中处理小数点的代码,所以需要二次元运算 - //如果大于1则根据float形式进行toFixed(2),如果小于1则按照string形式进行截取处理显示 - let realtimeData = { - time: data.id * 1000, - volume: data.vol <= 0.00001 ? transferToNumber(data.vol) : data.vol, - close: data.close <= 0.00001 ? transferToNumber(data.close) : data.close, - open: data.open <= 0.00001 ? transferToNumber(data.open) : data.open, - high: data.high <= 0.00001 ? transferToNumber(data.high) : data.high, - low: data.low <= 0.00001 ? transferToNumber(data.low) : data.low - } - onRealtimeCallback(realtimeData) - } - }) -} - -FeedBase.prototype.unsubscribeBars = function(listenerGuid) { - // 取消订阅产品的callback -} - - - - -//处理科学计数法 -function transferToNumber(inputNumber) { - if (isNaN(inputNumber)) { - return inputNumber - } - inputNumber = '' + inputNumber - inputNumber = parseFloat(inputNumber) - let eformat = inputNumber.toExponential() // 转换为标准的科学计数法形式(字符串) - let tmpArray = eformat.match(/\d(?:\.(\d*))?e([+-]\d+)/) // 分离出小数值和指数值 - let number = inputNumber.toFixed(Math.max(0, (tmpArray[1] || '').length - tmpArray[2])) - return number -} - + + }) +} + + +/** + * 更多时间类型在这里添加 时间类型请看火币文档 + * @param resolution 订阅周期 按照自己喜欢的来 如 30 30分钟、 1D 一天 + * @param name 交易对symbol + * @param to 结束时间 + * @returns {object} + */ +const resolutionFormat = (resolution, name, to) => { + let req = `market.${name}.kline.${resolution}min`; + let minutes = resolution; + console.log(resolution) + if (resolution.includes('D')) { + if (resolution.length < 2) resolution = '1' + resolution; + req = `market.${name}.kline.${parseInt(resolution)}day`; + minutes = parseInt(resolution) * 24 * 60; + } else if (resolution.includes('W')) { + if (resolution.length < 2) resolution = '1' + resolution; + req = `market.${name}.kline.${parseInt(resolution)}week`; + minutes = parseInt(resolution) * 24 * 60 * 7; + } else if (resolution.includes('M')) { + if (resolution.length < 2) resolution = '1' + resolution; + req = `market.${name}.kline.${parseInt(resolution)}mon`; + minutes = parseInt(resolution) * 24 * 60 * 30; + } else { + if (resolution / 60 > 1) { + req = `market.${name}.kline.${resolution / 60}hour`; + } + } + + let from = null; + if (to) { + from = to - 50 * minutes * 500; + if (resolution.includes('M') || resolution.includes('W')) { // 周线月线控制条数,时间超出火币规定范围, ws报错 + from = to - 50 * minutes * 500; + } + } + + return { + minutes, + req, + from, + to, + }; +}; + +FeedBase.prototype.getBars = function(symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) { + console.log("获取历史数据",periodParams) + // 切换产品周期 或者 切换产品 会执行这个函数 + let reso = resolutionFormat(resolution, symbolInfo.name, periodParams.to) + // if (resolution.includes('M') || resolution.includes('W')|| resolution.includes('D')) { // 周线月线控制条数,时间超出火币规定范围, ws报错 + // reso = resolutionFormat(resolution, symbolInfo.name, periodParams.to) + // } + + // 是历史数据 + var history = true + /* + !detafeed_historyTime 如果没请请求过这个产品或者这个周期的历史数据 + resolution !== detafeed_lastResolution 是否更换了产品周期 + detafeed_lastSymbol !== symbolInfo.name 是否切换了产品 + */ + if (!detafeed_historyTime || (resolution !== detafeed_lastResolution) || detafeed_lastSymbol !== symbolInfo + .name) { + // 那就不是历史数据 + history = false + // 储存请求过的产品 + detafeed_lastSymbol = symbolInfo.name + // 记录目前时间戳,就用目前时间戳往前请求历史数据 + detafeed_historyTime = window.parseInt((Date.now() / 1000)) + } + /* + @socket.sendData + 第一个参数订阅历史数据 + 第二个参数订阅实时数据 + 第三个参数 是 是否是历史数据 + */ + socket.sendData({ + event: "req", + type: "kline", + channel: [reso.req], + fromDate:reso.from, + toDate:reso.to + }, reso.req, history) + + + Event.off('data') + + Event.on('data', data => { + + if (data && Array.isArray(data)) { + // 记录这次请求的时间周期 + detafeed_lastResolution = resolution + var meta = { + noData: false + } + const datas = [] + if (data.length) { + detafeed_historyTime = data[0].id + for (let i of data) { + i.time = i.id * 1000 + i.volume = i.vol + datas.push(i) + } + } else { + console.log('进来') + meta = { + noData: 'no_data', + nextTime: detafeed_historyTime + } + } + onHistoryCallback(datas, {noData:data.length==0}) + } + }) +} + +FeedBase.prototype.subscribeBars = function(symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) { + Event.off('realTime') + // 拿到实时数据 在这里画 + Event.on('realTime', data => { + if (Object.prototype.toString.call(data) === '[object Object]' && data.hasOwnProperty('open')) { + //因为有的数值为科学计数法,故增加了转换函数,因为修改了源码中处理小数点的代码,所以需要二次元运算 + //如果大于1则根据float形式进行toFixed(2),如果小于1则按照string形式进行截取处理显示 + let realtimeData = { + time: data.id * 1000, + volume: data.vol <= 0.00001 ? transferToNumber(data.vol) : data.vol, + close: data.close <= 0.00001 ? transferToNumber(data.close) : data.close, + open: data.open <= 0.00001 ? transferToNumber(data.open) : data.open, + high: data.high <= 0.00001 ? transferToNumber(data.high) : data.high, + low: data.low <= 0.00001 ? transferToNumber(data.low) : data.low + } + onRealtimeCallback(realtimeData) + } + }) +} + +FeedBase.prototype.unsubscribeBars = function(listenerGuid) { + // 取消订阅产品的callback +} + + + + +//处理科学计数法 +function transferToNumber(inputNumber) { + if (isNaN(inputNumber)) { + return inputNumber + } + inputNumber = '' + inputNumber + inputNumber = parseFloat(inputNumber) + let eformat = inputNumber.toExponential() // 转换为标准的科学计数法形式(字符串) + let tmpArray = eformat.match(/\d(?:\.(\d*))?e([+-]\d+)/) // 分离出小数值和指数值 + let number = inputNumber.toFixed(Math.max(0, (tmpArray[1] || '').length - tmpArray[2])) + return number +} + exports.FeedBase = FeedBase diff --git a/components/kline/tradingView/websocket.js b/components/kline/tradingView/websocket.js index c6b3187..69cbc99 100644 --- a/components/kline/tradingView/websocket.js +++ b/components/kline/tradingView/websocket.js @@ -1,47 +1,45 @@ -import - constant - from '@/utils/constant.js' import { Event } from './event.js' + import pakoJs from './pako.js' var pako = pakoJs var socket = { - socket: null, // socket name - id:null, + socket: null, // socket name realTimeData: null, // 请求实时数据的参数 intervalObj: null, // 定时器的名字 lastRealTimeData: null, // 上一次请求的产品 sendData(historyData, realTimeDatas, history) { // 储存历史数据 - this.historyData = historyData - + this.historyData = historyData this.realTimeData = realTimeDatas // 如果上一次订阅过产品 if (this.lastRealTimeData) { - + // 如果不是订阅历史产品 那么肯定就是切换周期咯 或者 切换产品 + // 那么就取消订阅上一次的产品实时数据 + if (!history) { + console.log('取消订阅' + this.lastRealTimeData) + this.sendWsRequest({ + "unsub": this.lastRealTimeData, + "id": "id1" + }) + } - // 请求这一次的历史 - this.historyData.id=this.id + // 请求这一次的历史 this.sendWsRequest(this.historyData) - + console.log(111111,realTimeDatas) // 如果不是订阅历史产品 那么肯定就是切换周期咯 或者切换产品咯 // 那么就订阅一下 这次产品的或者周期的 实时数据 if (!history) { - //console.log('订阅新的' + realTimeDatas) - //console.log(111111,realTimeDatas) - this.sendWsRequest({ - event: 'un_sub', - type: 'kline', - id: this.id, - channel:[this.lastRealTimeData], - }) - this.lastRealTimeData = this.realTimeData + console.log('订阅新的' + realTimeDatas) + this.sendWsRequest({ + "sub": realTimeDatas, + "id": "id1" + }) } - } else { - + } else { // 如果是第一次订阅,就是说刚进入交易所, // 先存起来这一次请求的产品 作为历史产品 this.lastRealTimeData = this.realTimeData @@ -50,9 +48,13 @@ var socket = { } }, initWs() { - this.socket = new WebSocket(constant.WSSURL) + this.socket = new WebSocket('wss://api.huobi.pro/ws') this.socket.onopen = () => { - + this.sendWsRequest(this.historyData) + this.sendWsRequest({ + "sub": this.historyData.req, + "id": "id1" + }) } this.socket.onmessage = resp => { this.message(resp) @@ -65,52 +67,46 @@ var socket = { } }, error(err) { - //console.log(err, 'depth-socket::error') + console.log(err, 'depth-socket::error') }, close() { // 如果websocket关闭的话,就从新打开一下。 this.initWs() - //console.log('depth-socket::close') + console.log('depth-socket::close') }, message(resp) { - resp=JSON.parse(resp.data) - if (resp.channel === 'conn') { - this.id = resp.data - - this.historyData.id=this.id - this.sendWsRequest(this.historyData) - - - }else { - if(resp.event === 'req'){ - - //Event.emit('data', resp.data) - if (resp.data && Array.isArray(resp.data)) { - Event.emit('data', resp.data) - } - this.sendWsRequest({ - event: 'un_sub', - type: 'kline', - id: this.id, - channel:[this.lastRealTimeData], - }) - this.sendWsRequest({ - event: 'sub', - type: 'kline', - id: this.id, - channel:[this.lastRealTimeData], - }) - }else{ - - - Event.emit('realTime', resp.data) - - } - - - } - - + //console.log(resp) + let this_ = this + let reader = new FileReader() + reader.onload = function(e) { + // 对数据进行解压 + let msg = JSON.parse(pako.ungzip(reader.result, { + to: 'string' + })) + // console.log(msg) + // 如果是实时数据触发Event('realTime') 喂数据 + if (msg.tick) { + Event.emit('realTime', msg.tick) + } + + //响应服务器,避免断开连接 + if (msg.ping) { + this_.socket.send(JSON.stringify({ + pong: msg.ping + })); + this_.hasCheck = true + } + + this_.lastRealTimeData = this_.realTimeData + // 如果是历史数据触发Event('data') 绘制数据 + if (msg.data && Array.isArray(msg.data)) { + console.log(msg.data) + Event.emit('data', msg.data) + } + + } + // //将返回的数据解析为字符串格式 + reader.readAsArrayBuffer(resp.data); }, checkSendMessage(options) { // 这里处理websocket 连接不上的问题 @@ -126,7 +122,7 @@ var socket = { } if (i >= checkTimes) { clearInterval(this.intervalObj) - //console.log('send post_data_str timeout.') + console.log('send post_data_str timeout.') } }, 500) }, @@ -139,13 +135,13 @@ var socket = { this.socket.send(JSON.stringify(options)) break case 2: - //console.log('ws关闭状态') + console.log('ws关闭状态') break case 3: this.initWs() break default: - //console.log('ws未知错误') + console.log('ws未知错误') } } } diff --git a/components/kline/tradingView/websocket1.js b/components/kline/tradingView/websocket2.js similarity index 55% rename from components/kline/tradingView/websocket1.js rename to components/kline/tradingView/websocket2.js index 69cbc99..5be04ef 100644 --- a/components/kline/tradingView/websocket1.js +++ b/components/kline/tradingView/websocket2.js @@ -1,149 +1,153 @@ -import { - Event -} from './event.js' - -import pakoJs from './pako.js' - -var pako = pakoJs -var socket = { - socket: null, // socket name - realTimeData: null, // 请求实时数据的参数 - intervalObj: null, // 定时器的名字 - lastRealTimeData: null, // 上一次请求的产品 - sendData(historyData, realTimeDatas, history) { - // 储存历史数据 - this.historyData = historyData - this.realTimeData = realTimeDatas - // 如果上一次订阅过产品 - if (this.lastRealTimeData) { - // 如果不是订阅历史产品 那么肯定就是切换周期咯 或者 切换产品 - // 那么就取消订阅上一次的产品实时数据 - if (!history) { - console.log('取消订阅' + this.lastRealTimeData) - this.sendWsRequest({ - "unsub": this.lastRealTimeData, - "id": "id1" - }) - } - - // 请求这一次的历史 +import + constant + from '@/utils/constant.js' +import { + Event +} from './event.js' +import pakoJs from './pako.js' + +var pako = pakoJs +var socket = { + socket: null, // socket name + id:null, + realTimeData: null, // 请求实时数据的参数 + intervalObj: null, // 定时器的名字 + lastRealTimeData: null, // 上一次请求的产品 + sendData(historyData, realTimeDatas, history) { + // 储存历史数据 + this.historyData = historyData + + this.realTimeData = realTimeDatas + // 如果上一次订阅过产品 + if (this.lastRealTimeData) { + + + // 请求这一次的历史 + this.historyData.id=this.id this.sendWsRequest(this.historyData) - console.log(111111,realTimeDatas) - - // 如果不是订阅历史产品 那么肯定就是切换周期咯 或者切换产品咯 - // 那么就订阅一下 这次产品的或者周期的 实时数据 - if (!history) { - console.log('订阅新的' + realTimeDatas) - this.sendWsRequest({ - "sub": realTimeDatas, - "id": "id1" - }) - } - } else { - // 如果是第一次订阅,就是说刚进入交易所, - // 先存起来这一次请求的产品 作为历史产品 - this.lastRealTimeData = this.realTimeData - // 然后 初始化一下websocket - this.initWs() - } - }, - initWs() { - this.socket = new WebSocket('wss://api.huobi.pro/ws') - this.socket.onopen = () => { - this.sendWsRequest(this.historyData) - this.sendWsRequest({ - "sub": this.historyData.req, - "id": "id1" - }) - } - this.socket.onmessage = resp => { - this.message(resp) - } - this.socket.onclose = () => { - this.close() - } - this.socket.onerror = err => { - this.error(err) - } - }, - error(err) { - console.log(err, 'depth-socket::error') - }, - close() { - // 如果websocket关闭的话,就从新打开一下。 - this.initWs() - console.log('depth-socket::close') - }, + + + // 如果不是订阅历史产品 那么肯定就是切换周期咯 或者切换产品咯 + // 那么就订阅一下 这次产品的或者周期的 实时数据 + if (!history) { + //console.log('订阅新的' + realTimeDatas) + //console.log(111111,realTimeDatas) + this.sendWsRequest({ + event: 'un_sub', + type: 'kline', + id: this.id, + channel:[this.lastRealTimeData], + }) + this.lastRealTimeData = this.realTimeData + } + } else { + + // 如果是第一次订阅,就是说刚进入交易所, + // 先存起来这一次请求的产品 作为历史产品 + this.lastRealTimeData = this.realTimeData + // 然后 初始化一下websocket + this.initWs() + } + }, + initWs() { + this.socket = new WebSocket(constant.WSSURL) + this.socket.onopen = () => { + + } + this.socket.onmessage = resp => { + this.message(resp) + } + this.socket.onclose = () => { + this.close() + } + this.socket.onerror = err => { + this.error(err) + } + }, + error(err) { + //console.log(err, 'depth-socket::error') + }, + close() { + // 如果websocket关闭的话,就从新打开一下。 + this.initWs() + //console.log('depth-socket::close') + }, message(resp) { - //console.log(resp) - let this_ = this - let reader = new FileReader() - reader.onload = function(e) { - // 对数据进行解压 - let msg = JSON.parse(pako.ungzip(reader.result, { - to: 'string' - })) - // console.log(msg) - // 如果是实时数据触发Event('realTime') 喂数据 - if (msg.tick) { - Event.emit('realTime', msg.tick) - } - - //响应服务器,避免断开连接 - if (msg.ping) { - this_.socket.send(JSON.stringify({ - pong: msg.ping - })); - this_.hasCheck = true - } - - this_.lastRealTimeData = this_.realTimeData - // 如果是历史数据触发Event('data') 绘制数据 - if (msg.data && Array.isArray(msg.data)) { - console.log(msg.data) - Event.emit('data', msg.data) - } - - } - // //将返回的数据解析为字符串格式 - reader.readAsArrayBuffer(resp.data); - }, - checkSendMessage(options) { - // 这里处理websocket 连接不上的问题 - var checkTimes = 10 - var i = 0 - this.intervalObj = setInterval(() => { - i += 1 - if (this.socket.readyState === 1) { - // ... - this.socket.send(options) - clearInterval(this.intervalObj) - return - } - if (i >= checkTimes) { - clearInterval(this.intervalObj) - console.log('send post_data_str timeout.') - } - }, 500) - }, - sendWsRequest(options) { - switch (this.socket.readyState) { - case 0: - this.checkSendMessage(JSON.stringify(options)) - break - case 1: - this.socket.send(JSON.stringify(options)) - break - case 2: - console.log('ws关闭状态') - break - case 3: - this.initWs() - break - default: - console.log('ws未知错误') - } - } -} - + resp=JSON.parse(resp.data) + if (resp.channel === 'conn') { + this.id = resp.data + + this.historyData.id=this.id + this.sendWsRequest(this.historyData) + + + }else { + if(resp.event === 'req'){ + + //Event.emit('data', resp.data) + if (resp.data && Array.isArray(resp.data)) { + Event.emit('data', resp.data) + } + this.sendWsRequest({ + event: 'un_sub', + type: 'kline', + id: this.id, + channel:[this.lastRealTimeData], + }) + this.sendWsRequest({ + event: 'sub', + type: 'kline', + id: this.id, + channel:[this.lastRealTimeData], + }) + }else{ + + + Event.emit('realTime', resp.data) + + } + + + } + + + }, + checkSendMessage(options) { + // 这里处理websocket 连接不上的问题 + var checkTimes = 10 + var i = 0 + this.intervalObj = setInterval(() => { + i += 1 + if (this.socket.readyState === 1) { + // ... + this.socket.send(options) + clearInterval(this.intervalObj) + return + } + if (i >= checkTimes) { + clearInterval(this.intervalObj) + //console.log('send post_data_str timeout.') + } + }, 500) + }, + sendWsRequest(options) { + switch (this.socket.readyState) { + case 0: + this.checkSendMessage(JSON.stringify(options)) + break + case 1: + this.socket.send(JSON.stringify(options)) + break + case 2: + //console.log('ws关闭状态') + break + case 3: + this.initWs() + break + default: + //console.log('ws未知错误') + } + } +} + exports.socket = socket