|
|
|
@ -9,6 +9,7 @@ import Option from "@/api/option"; |
|
|
|
import Contract from "@/api/contract"; |
|
|
|
import Socket from "@/api/server/Socket.js"; |
|
|
|
import tvStyle from "@/assets/js/tvStyle.js"; |
|
|
|
import bus from "@/components/bus.js"; |
|
|
|
import { mapState } from "vuex"; |
|
|
|
let exchangeAjax = { |
|
|
|
getKline: Option.getKline, |
|
|
|
@ -67,33 +68,33 @@ export default { |
|
|
|
}, |
|
|
|
computed: { |
|
|
|
lang() { |
|
|
|
let local; |
|
|
|
if (localStorage.lang) { |
|
|
|
if (localStorage.lang == "tw") { |
|
|
|
local = "zh_TW"; |
|
|
|
} else if (localStorage.lang == "cn") { |
|
|
|
local = "zh"; |
|
|
|
} else if (localStorage.lang == "kor") { |
|
|
|
local = "ko"; |
|
|
|
} else if (localStorage.lang == "jp") { |
|
|
|
local = "ja"; |
|
|
|
} else if (localStorage.lang == "de") { |
|
|
|
local = "de_DE"; |
|
|
|
} else if (localStorage.lang == "fra") { |
|
|
|
local = "fr"; |
|
|
|
} else if (localStorage.lang == "it") { |
|
|
|
local = "it"; |
|
|
|
} else if (localStorage.lang == "pt") { |
|
|
|
local = "pt"; |
|
|
|
} else if (localStorage.lang == "spa") { |
|
|
|
local = "es"; |
|
|
|
} else if (localStorage.lang == "en") { |
|
|
|
local = "en"; |
|
|
|
}else { |
|
|
|
local = "en"; |
|
|
|
let local; |
|
|
|
if (localStorage.lang) { |
|
|
|
if (localStorage.lang == "tw") { |
|
|
|
local = "zh_TW"; |
|
|
|
} else if (localStorage.lang == "cn") { |
|
|
|
local = "zh"; |
|
|
|
} else if (localStorage.lang == "kor") { |
|
|
|
local = "ko"; |
|
|
|
} else if (localStorage.lang == "jp") { |
|
|
|
local = "ja"; |
|
|
|
} else if (localStorage.lang == "de") { |
|
|
|
local = "de_DE"; |
|
|
|
} else if (localStorage.lang == "fra") { |
|
|
|
local = "fr"; |
|
|
|
} else if (localStorage.lang == "it") { |
|
|
|
local = "it"; |
|
|
|
} else if (localStorage.lang == "pt") { |
|
|
|
local = "pt"; |
|
|
|
} else if (localStorage.lang == "spa") { |
|
|
|
local = "es"; |
|
|
|
} else if (localStorage.lang == "en") { |
|
|
|
local = "en"; |
|
|
|
}else { |
|
|
|
local = "en"; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return local; |
|
|
|
return local; |
|
|
|
}, |
|
|
|
symbol() { |
|
|
|
return this.activeCoin.pair_name; |
|
|
|
@ -105,226 +106,309 @@ export default { |
|
|
|
return this.contract ? contractAjax : exchangeAjax; |
|
|
|
}, |
|
|
|
msg() { |
|
|
|
return `${this.ajaxTv.msg}${this.ajaxTv.getSymbol( |
|
|
|
this.symbol |
|
|
|
)}_${this.resolution(this.interval)}`; |
|
|
|
return `${this.ajaxTv.msg}${this.ajaxTv.getSymbol( |
|
|
|
this.symbol |
|
|
|
)}_${this.resolution(this.interval)}`; |
|
|
|
}, |
|
|
|
}, |
|
|
|
data() { |
|
|
|
data() { |
|
|
|
return { |
|
|
|
TView: undefined, |
|
|
|
ws: undefined, |
|
|
|
onLoadedCallback: undefined, |
|
|
|
onRealtimeCallback: undefined, |
|
|
|
timer: "15", |
|
|
|
sub: "", |
|
|
|
isCreateSocket: false, |
|
|
|
page: {}, |
|
|
|
TView: undefined, |
|
|
|
ws: undefined, |
|
|
|
onLoadedCallback: undefined, |
|
|
|
onRealtimeCallback: undefined, |
|
|
|
timer: "15", |
|
|
|
sub: "", |
|
|
|
isCreateSocket: false, |
|
|
|
page: {}, |
|
|
|
}; |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
// 链接socket |
|
|
|
linkSocket(call) { |
|
|
|
const ws = new Socket(this.wsUrl); |
|
|
|
ws.on("open", () => { |
|
|
|
this.ws = ws; |
|
|
|
call && call(); |
|
|
|
}); |
|
|
|
ws.on("message", (res) => { |
|
|
|
let { data, msg, code, sub, type, status, req, cmd } = res; |
|
|
|
if (sub == this.sub && this.onRealtimeCallback) { |
|
|
|
this.onRealtimeCallback(this.getMap(data)); |
|
|
|
} else if (type == "ping" || cmd == "ping") { |
|
|
|
this.ws.send({ |
|
|
|
cmd: "pong", |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
const ws = new Socket(this.wsUrl); |
|
|
|
ws.on("open", () => { |
|
|
|
this.ws = ws; |
|
|
|
call && call(); |
|
|
|
}); |
|
|
|
ws.on("message", (res) => { |
|
|
|
let { data, msg, code, sub, type, status, req, cmd } = res; |
|
|
|
if (sub == this.sub && this.onRealtimeCallback) { |
|
|
|
this.onRealtimeCallback(this.getMap(data)); |
|
|
|
bus.$emit('collapse', data); |
|
|
|
} else if (type == "ping" || cmd == "ping") { |
|
|
|
this.ws.send({ |
|
|
|
cmd: "pong", |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
}, |
|
|
|
// 取消订阅 |
|
|
|
unsub(pair_id, timer) { |
|
|
|
let msgObj = { |
|
|
|
cmd: "unsub", |
|
|
|
msg: `${this.ajaxTv.msg}${pair_id}_${this.resolution(timer)}`, |
|
|
|
}; |
|
|
|
this.ws.send(msgObj); |
|
|
|
let msgObj = { |
|
|
|
cmd: "unsub", |
|
|
|
msg: `${this.ajaxTv.msg}${pair_id}_${this.resolution(timer)}`, |
|
|
|
}; |
|
|
|
this.ws.send(msgObj); |
|
|
|
}, |
|
|
|
getConfig() { |
|
|
|
return {}; |
|
|
|
return {}; |
|
|
|
}, |
|
|
|
getSymbol() { |
|
|
|
return {}; |
|
|
|
return {}; |
|
|
|
}, |
|
|
|
getMap(data) { |
|
|
|
return { |
|
|
|
time: data.id * 1000, |
|
|
|
close: data.close, |
|
|
|
open: data.open, |
|
|
|
high: data.high, |
|
|
|
low: data.low, |
|
|
|
volume: data.vol, |
|
|
|
}; |
|
|
|
return { |
|
|
|
time: data.id * 1000, |
|
|
|
close: data.close, |
|
|
|
open: data.open, |
|
|
|
high: data.high, |
|
|
|
low: data.low, |
|
|
|
volume: data.vol, |
|
|
|
}; |
|
|
|
}, |
|
|
|
resolution(resolution) { |
|
|
|
let T = ""; |
|
|
|
if (isNaN(resolution * 1)) { |
|
|
|
T = resolution |
|
|
|
.replace("D", "day") |
|
|
|
.replace("W", "week") |
|
|
|
.replace("M", "mon"); |
|
|
|
} else { |
|
|
|
if (resolution > 60) { |
|
|
|
T = Math.floor(resolution / 60) + "hours"; |
|
|
|
let T = ""; |
|
|
|
if (isNaN(resolution * 1)) { |
|
|
|
T = resolution |
|
|
|
.replace("D", "day") |
|
|
|
.replace("W", "week") |
|
|
|
.replace("M", "mon"); |
|
|
|
} else { |
|
|
|
T = resolution + "min"; |
|
|
|
if (resolution > 60) { |
|
|
|
T = Math.floor(resolution / 60) + "hours"; |
|
|
|
} else { |
|
|
|
T = resolution + "min"; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return T; |
|
|
|
return T; |
|
|
|
}, |
|
|
|
// 解压 |
|
|
|
unzip(b64Data) { |
|
|
|
let u8 = window.atob(b64Data); |
|
|
|
let jiya = window.pako.inflate(u8) |
|
|
|
let str = this.Uint8ArrayToString(jiya); |
|
|
|
return JSON.parse(str); |
|
|
|
}, |
|
|
|
Uint8ArrayToString(fileData) { |
|
|
|
var dataString = ""; |
|
|
|
for (var i = 0; i < fileData.length; i++) { |
|
|
|
dataString += String.fromCharCode(fileData[i]); |
|
|
|
} |
|
|
|
return dataString; |
|
|
|
let u8 = window.atob(b64Data); |
|
|
|
let jiya = window.pako.inflate(u8) |
|
|
|
let str = this.Uint8ArrayToString(jiya); |
|
|
|
return JSON.parse(str); |
|
|
|
}, |
|
|
|
Uint8ArrayToString(fileData) { |
|
|
|
var dataString = ""; |
|
|
|
for (var i = 0; i < fileData.length; i++) { |
|
|
|
dataString += String.fromCharCode(fileData[i]); |
|
|
|
} |
|
|
|
return dataString; |
|
|
|
}, |
|
|
|
getBars( |
|
|
|
symbolInfo, |
|
|
|
resolution, |
|
|
|
rangeStartDate, |
|
|
|
rangeEndDate, |
|
|
|
onLoadedCallback, |
|
|
|
onErrorCallback |
|
|
|
) { |
|
|
|
this.page[this.symbol] = this.page[this.symbol] || 1; |
|
|
|
let page = this.page[this.symbol] > 3 ? 3 : this.page[this.symbol]; |
|
|
|
let data = { |
|
|
|
symbol: this.ajaxTv.getSymbol(symbolInfo.name), |
|
|
|
period: this.resolution(resolution), |
|
|
|
form: rangeStartDate, |
|
|
|
to: rangeEndDate, |
|
|
|
size: page * 200, |
|
|
|
zip: 1, |
|
|
|
}; |
|
|
|
|
|
|
|
this.onLoadedCallback = onLoadedCallback; |
|
|
|
// 检测接口币种是不是后台返回的 |
|
|
|
if (!this.activeCoin.pair_name) { |
|
|
|
onLoadedCallback([]); |
|
|
|
return; |
|
|
|
} |
|
|
|
// 取消订阅 |
|
|
|
if (this.timer && this.timer != resolution) { |
|
|
|
this.unsub( |
|
|
|
this.ajaxTv.getSymbol(this.activeCoin.pair_name), |
|
|
|
this.timer |
|
|
|
); |
|
|
|
} else { |
|
|
|
} |
|
|
|
symbolInfo, |
|
|
|
resolution, |
|
|
|
rangeStartDate, |
|
|
|
rangeEndDate, |
|
|
|
onLoadedCallback, |
|
|
|
onErrorCallback |
|
|
|
) { |
|
|
|
console.info(resolution) |
|
|
|
this.page[this.symbol] = this.page[this.symbol] || 1; |
|
|
|
let page = this.page[this.symbol] > 3 ? 3 : this.page[this.symbol]; |
|
|
|
let data = { |
|
|
|
symbol: this.ajaxTv.getSymbol(symbolInfo.name), |
|
|
|
period: this.resolution(resolution), |
|
|
|
form: rangeStartDate, |
|
|
|
to: rangeEndDate, |
|
|
|
size: page * 200, |
|
|
|
zip: 1, |
|
|
|
}; |
|
|
|
|
|
|
|
this.timer = resolution; |
|
|
|
this.ajaxTv.getKline(data).then((res) => { |
|
|
|
let arr = this.unzip(res.data).map((item) => { |
|
|
|
return this.getMap(item); |
|
|
|
}); |
|
|
|
this.page[this.symbol]++; |
|
|
|
onLoadedCallback(arr); |
|
|
|
setTimeout(() => { |
|
|
|
if (this.page[this.symbol] > 3) { |
|
|
|
this.onLoadedCallback = onLoadedCallback; |
|
|
|
// 检测接口币种是不是后台返回的 |
|
|
|
if (!this.activeCoin.pair_name) { |
|
|
|
onLoadedCallback([]); |
|
|
|
} |
|
|
|
}, 60); |
|
|
|
}); |
|
|
|
|
|
|
|
// 发送消息 |
|
|
|
let msgObj = { |
|
|
|
cmd: "sub", |
|
|
|
msg: `${this.ajaxTv.msg}${data.symbol}_${data.period}`, |
|
|
|
}; |
|
|
|
this.sub = msgObj.msg; |
|
|
|
let send = (msgObj) => { |
|
|
|
if (this.ws) { |
|
|
|
this.ws.send(msgObj); |
|
|
|
return; |
|
|
|
} |
|
|
|
// 取消订阅 |
|
|
|
if (this.timer && this.timer != resolution) { |
|
|
|
this.unsub( |
|
|
|
this.ajaxTv.getSymbol(this.activeCoin.pair_name), |
|
|
|
this.timer |
|
|
|
); |
|
|
|
} else { |
|
|
|
if (this.isCreateSocket) { |
|
|
|
} |
|
|
|
|
|
|
|
this.timer = resolution; |
|
|
|
this.ajaxTv.getKline(data).then((res) => { |
|
|
|
let arr = this.unzip(res.data).map((item) => { |
|
|
|
return this.getMap(item); |
|
|
|
}); |
|
|
|
this.page[this.symbol]++; |
|
|
|
onLoadedCallback(arr); |
|
|
|
setTimeout(() => { |
|
|
|
send(msgObj); |
|
|
|
}, 200); |
|
|
|
return; |
|
|
|
} |
|
|
|
this.isCreateSocket = true; |
|
|
|
this.linkSocket(() => { |
|
|
|
this.isCreateSocket = false; |
|
|
|
if (this.page[this.symbol] > 3) { |
|
|
|
onLoadedCallback([]); |
|
|
|
} |
|
|
|
}, 60); |
|
|
|
}); |
|
|
|
// 发送消息 |
|
|
|
let msgObj = { |
|
|
|
cmd: "sub", |
|
|
|
msg: `${this.ajaxTv.msg}${data.symbol}_${data.period}`, |
|
|
|
}; |
|
|
|
this.sub = msgObj.msg; |
|
|
|
let send = (msgObj) => { |
|
|
|
if (this.ws) { |
|
|
|
this.ws.send(msgObj); |
|
|
|
}); |
|
|
|
} |
|
|
|
}; |
|
|
|
send(msgObj); |
|
|
|
} else { |
|
|
|
if (this.isCreateSocket) { |
|
|
|
setTimeout(() => { |
|
|
|
send(msgObj); |
|
|
|
}, 200); |
|
|
|
return; |
|
|
|
} |
|
|
|
this.isCreateSocket = true; |
|
|
|
this.linkSocket(() => { |
|
|
|
this.isCreateSocket = false; |
|
|
|
this.ws.send(msgObj); |
|
|
|
}); |
|
|
|
} |
|
|
|
}; |
|
|
|
send(msgObj); |
|
|
|
}, |
|
|
|
subscribeBars( |
|
|
|
symbolInfo, |
|
|
|
resolution, |
|
|
|
onRealtimeCallback, |
|
|
|
subscriberUID, |
|
|
|
onResetCacheNeededCallback |
|
|
|
) { |
|
|
|
this.onRealtimeCallback = onRealtimeCallback; |
|
|
|
if (!this.activeCoin.pair_name) { |
|
|
|
setTimeout(() => { |
|
|
|
onResetCacheNeededCallback(); |
|
|
|
}, 100); |
|
|
|
} |
|
|
|
symbolInfo, |
|
|
|
resolution, |
|
|
|
onRealtimeCallback, |
|
|
|
subscriberUID, |
|
|
|
onResetCacheNeededCallback |
|
|
|
) { |
|
|
|
this.onRealtimeCallback = onRealtimeCallback; |
|
|
|
if (!this.activeCoin.pair_name) { |
|
|
|
setTimeout(() => { |
|
|
|
onResetCacheNeededCallback(); |
|
|
|
}, 100); |
|
|
|
} |
|
|
|
}, |
|
|
|
initView() { |
|
|
|
let Tdata = new VDatafeed(this); |
|
|
|
this.TView = new TradingView.widget({ |
|
|
|
width: "100%", |
|
|
|
height: 590, |
|
|
|
interval: this.timer, |
|
|
|
timezone: "Asia/Shanghai", |
|
|
|
theme: "light", // 自定义主题 |
|
|
|
style: "1", |
|
|
|
library_path: "/static/Kline/charting_library/", |
|
|
|
datafeed: Tdata, |
|
|
|
locale: this.lang, |
|
|
|
toolbar_bg: this.theme == "light" ? "#f1f3f6" : "#222e3d", |
|
|
|
enable_publishing: false, |
|
|
|
withdateranges: true, |
|
|
|
hide_side_toolbar: false, |
|
|
|
allow_symbol_change: true, |
|
|
|
show_popup_button: true, |
|
|
|
popup_width: "1000", |
|
|
|
popup_height: "650", |
|
|
|
container_id: "tradingview_1355aw2", |
|
|
|
disabled_features: [ |
|
|
|
"header_symbol_search", |
|
|
|
"header_compare", |
|
|
|
"volume_force_overlay", |
|
|
|
"header_widget_dom_node", |
|
|
|
'timeframes_toolbar', |
|
|
|
"control_bar", |
|
|
|
"main_series_scale_menu", |
|
|
|
"header_resolutions", |
|
|
|
"legend_context_menu", |
|
|
|
"symbol_search_hot_key", |
|
|
|
"symbol_info", |
|
|
|
"pane_context_menu", |
|
|
|
"header_widget_dom_node", |
|
|
|
'timeframes_toolbar', |
|
|
|
], |
|
|
|
supported_resolutions: ["5", "15", "30", "60", "240", "1D", "1W", "1M"], |
|
|
|
overrides: tvStyle[this.theme], |
|
|
|
custom_css_url: `/static/Kline/charting_library/static/css/tradingview_${ |
|
|
|
this.theme == "light" ? "white" : "black" |
|
|
|
}.css`, |
|
|
|
}); |
|
|
|
let _this = this; |
|
|
|
let Tdata = new VDatafeed(this); |
|
|
|
console.info(Tdata) |
|
|
|
let widget=(_this.TView = new TradingView.widget({ |
|
|
|
width: "100%", |
|
|
|
height: 590, |
|
|
|
interval: _this.timer, |
|
|
|
timezone: "Asia/Shanghai", |
|
|
|
theme: "light", // 自定义主题 |
|
|
|
style: "1", |
|
|
|
library_path: "/static/Kline/charting_library/", |
|
|
|
datafeed: Tdata, |
|
|
|
locale: _this.lang, |
|
|
|
toolbar_bg: _this.theme == "light" ? "#f1f3f6" : "#222e3d", |
|
|
|
enable_publishing: false, |
|
|
|
withdateranges: true, |
|
|
|
hide_side_toolbar: false, |
|
|
|
allow_symbol_change: true, |
|
|
|
show_popup_button: true, |
|
|
|
popup_width: "1000", |
|
|
|
popup_height: "650", |
|
|
|
container_id: "tradingview_1355aw2", |
|
|
|
disabled_features: [ |
|
|
|
"header_symbol_search", |
|
|
|
// "widget_logo", |
|
|
|
"header_compare", |
|
|
|
"volume_force_overlay", |
|
|
|
'timeframes_toolbar', |
|
|
|
"control_bar", |
|
|
|
"main_series_scale_menu", |
|
|
|
"header_resolutions", |
|
|
|
"legend_context_menu", |
|
|
|
"symbol_search_hot_key", |
|
|
|
"symbol_info", |
|
|
|
"pane_context_menu", |
|
|
|
// "header_widget_dom_node", |
|
|
|
'timeframes_toolbar', |
|
|
|
], |
|
|
|
supported_resolutions: ["5", "15", "30", "60", "240", "1D", "1W", "1M"], |
|
|
|
overrides: tvStyle[_this.theme], |
|
|
|
custom_css_url: `/static/Kline/charting_library/static/css/tradingview_${ |
|
|
|
_this.theme == "light" ? "white" : "black" |
|
|
|
}.css`, |
|
|
|
})); |
|
|
|
widget.onChartReady(function () { |
|
|
|
let buttonArr = [ |
|
|
|
{ |
|
|
|
title: "1" + _this.$t("exchange.min"), |
|
|
|
resolution: "1", |
|
|
|
chartType: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: "5" + _this.$t("exchange.min"), |
|
|
|
resolution: "5", |
|
|
|
chartType: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: "15" + _this.$t("exchange.min"), |
|
|
|
resolution: "15", |
|
|
|
chartType: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: "30" + _this.$t("exchange.min"), |
|
|
|
resolution: "30", |
|
|
|
chartType: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: "1" + _this.$t("exchange.hour"), |
|
|
|
resolution: "60", |
|
|
|
chartType: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: "1" + _this.$t("exchange.day"), |
|
|
|
resolution: "1D", |
|
|
|
chartType: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: "1" + _this.$t("exchange.week"), |
|
|
|
resolution: "1W", |
|
|
|
chartType: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: "1" + _this.$t("exchange.month"), |
|
|
|
resolution: "1M", |
|
|
|
chartType: 1 |
|
|
|
} |
|
|
|
]; |
|
|
|
let btn = {}; |
|
|
|
let nowTime = ""; |
|
|
|
|
|
|
|
buttonArr.forEach((v, i) => { |
|
|
|
let button = widget.createButton(); |
|
|
|
button.attr("title", v.title).addClass("my-date").text(v.title); |
|
|
|
if (v.resolution === "1") { |
|
|
|
button.css({ |
|
|
|
color: "#5786d2", |
|
|
|
"border-bottom": "1px solid #5786d2", |
|
|
|
}); |
|
|
|
localStorage.setItem("tim", "1"); |
|
|
|
} |
|
|
|
btn = button.on("click", function (e) { |
|
|
|
$(this).parents(".left").children().find(".my-date").removeAttr("style"); |
|
|
|
handleClick(e, v.resolution); |
|
|
|
button.css({ |
|
|
|
color: "#5786d2", |
|
|
|
"border-bottom": "1px solid #5786d2", |
|
|
|
}); |
|
|
|
// _this.$store.commit("upType", v.type); |
|
|
|
widget.chart().setChartType(v.chartType); //改变K线类型 |
|
|
|
}); |
|
|
|
}); |
|
|
|
let handleClick = (e, value) => { |
|
|
|
_this.setSymbol = function (symbol, value) { |
|
|
|
gh.chart().setSymbol(symbol, value); |
|
|
|
}; |
|
|
|
widget.chart().setResolution(value, function onReadyCallback() {}); //改变分辨率 |
|
|
|
$(e.target) |
|
|
|
.addClass("mydate") |
|
|
|
.closest("div.space-single") |
|
|
|
.siblings("div.space-single") |
|
|
|
.find("div.button") |
|
|
|
.removeClass("mydate"); |
|
|
|
}; |
|
|
|
}); |
|
|
|
}, |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
|