You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
501 lines
14 KiB
501 lines
14 KiB
<template>
|
|
<div id="tradingview_1355aw2"></div>
|
|
</template>
|
|
|
|
<script>
|
|
// import pako from "pako";
|
|
import VDatafeed from "./VDatafeed";
|
|
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,
|
|
getSymbol(name) {
|
|
return name.split("/").join("").toLowerCase();
|
|
},
|
|
msg: "Kline_",
|
|
};
|
|
let contractAjax = {
|
|
getKline: Contract.getKline,
|
|
getSymbol(name) {
|
|
return name.split("/")[0];
|
|
},
|
|
msg: "swapKline_",
|
|
};
|
|
export default {
|
|
props: {
|
|
contract: {
|
|
default: false,
|
|
type: Boolean,
|
|
required: false,
|
|
},
|
|
activeCoin: {
|
|
default: {},
|
|
type: Object,
|
|
required: false,
|
|
},
|
|
wsUrl: {
|
|
default: "",
|
|
type: String,
|
|
required: false,
|
|
},
|
|
},
|
|
watch: {
|
|
activeCoin(n, o) {
|
|
if (!n) return;
|
|
let boo = this.contract
|
|
? n.pair_name != o.pair_name
|
|
: n.pair_time_name != o.pair_time_name;
|
|
if (boo) {
|
|
// 获取准备取消订阅的消息的精度值
|
|
let timer = this.timer;
|
|
this.page[n.pair_name] = 1;
|
|
this.TView.setSymbol(n.pair_name, this.timer);
|
|
// 取消订阅
|
|
if (n.pair_id != o.pair_id) {
|
|
this.unsub(o.pair_id, timer);
|
|
}
|
|
}
|
|
},
|
|
symbol(n, o) {
|
|
if (n != o && o) {
|
|
this.unsub(this.ajaxTv.getSymbol(o), this.timer);
|
|
}
|
|
},
|
|
},
|
|
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";
|
|
}
|
|
}
|
|
return local;
|
|
},
|
|
symbol() {
|
|
return this.activeCoin.pair_name;
|
|
},
|
|
...mapState({
|
|
theme: "theme",
|
|
}),
|
|
ajaxTv() {
|
|
return this.contract ? contractAjax : exchangeAjax;
|
|
},
|
|
msg() {
|
|
return `${this.ajaxTv.msg}${this.ajaxTv.getSymbol(
|
|
this.symbol
|
|
)}_${this.resolution(this.interval)}`;
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
TView: undefined,
|
|
ws: undefined,
|
|
onLoadedCallback: undefined,
|
|
onRealtimeCallback: undefined,
|
|
timer: "15",
|
|
// timer: "1D",
|
|
sub: "",
|
|
|
|
isCreateSocket: false,
|
|
page: {},
|
|
tt:undefined
|
|
};
|
|
},
|
|
methods: {
|
|
reconnect() {
|
|
if(this.isCreateSocket) {
|
|
return;
|
|
};
|
|
let msgObj = {
|
|
cmd: "sub",
|
|
msg: this.sub,
|
|
};
|
|
this.isCreateSocket = true;
|
|
//没连接上会一直重连,设置延迟避免请求过多
|
|
this.tt && clearTimeout(this.tt);
|
|
let th=this
|
|
th.tt = setTimeout(function () {
|
|
th.isCreateSocket = false;
|
|
th.linkSocket(() => {
|
|
th.ws.send(msgObj);
|
|
});
|
|
|
|
}, 4000);
|
|
},
|
|
// 链接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) {
|
|
if(sub.indexOf("BTC")!= -1) (data.close).toFixed(1)
|
|
this.onRealtimeCallback(this.getMap(data));
|
|
bus.$emit('collapse', data);
|
|
} else if (type == "ping" || cmd == "ping") {
|
|
this.ws.send({
|
|
cmd: "pong",
|
|
});
|
|
}
|
|
});
|
|
ws.on('close',()=>{
|
|
console.log('链接关闭');
|
|
this.reconnect();
|
|
})
|
|
ws.on('error',()=>{
|
|
console.log('发生异常了');
|
|
this.reconnect();
|
|
})
|
|
|
|
},
|
|
// 取消订阅
|
|
unsub(pair_id, timer) {
|
|
let msgObj = {
|
|
cmd: "unsub",
|
|
msg: `${this.ajaxTv.msg}${pair_id}_${this.resolution(timer)}`,
|
|
};
|
|
this.ws.send(msgObj);
|
|
},
|
|
getConfig() {
|
|
return {};
|
|
},
|
|
getSymbol() {
|
|
return {};
|
|
},
|
|
getMap(data) {
|
|
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";
|
|
} else {
|
|
T = resolution + "min";
|
|
}
|
|
}
|
|
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;
|
|
},
|
|
getBars(
|
|
symbolInfo,
|
|
resolution,
|
|
rangeStartDate,
|
|
rangeEndDate,
|
|
onLoadedCallback,
|
|
onErrorCallback
|
|
) {
|
|
// handleClick
|
|
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 {
|
|
}
|
|
|
|
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) {
|
|
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);
|
|
} 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);
|
|
}
|
|
},
|
|
initView() {
|
|
let _this = this;
|
|
let Tdata = new VDatafeed(this);
|
|
let widget=(_this.TView = new TradingView.widget({
|
|
width: "100%",
|
|
height: 610,//合约页面K线图的宽高设置
|
|
interval: _this.timer,
|
|
// timezone: "Asia/Shanghai",
|
|
timezone: "America/Toronto",
|
|
theme: "dark", // 自定义主题
|
|
style: "1",
|
|
library_path: "/static/Kline/charting_library/",
|
|
datafeed: Tdata,
|
|
locale: _this.lang,
|
|
// toolbar_bg: _this.theme == "black" ? "#f1f3f6" : "#222e3d",
|
|
toolbar_bg: _this.theme == "black" ? "#f1f3f6" : "#fff",
|
|
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',
|
|
],
|
|
enabled_features:['header_indicators'],
|
|
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 == "black" ? "white" : "black"
|
|
}.css`,
|
|
drawings_access: {
|
|
type: "black",
|
|
tools: [
|
|
{ name: "Trend Line", grayed: true },
|
|
{ name: "Trend Angle", grayed: true }
|
|
]
|
|
},
|
|
}));
|
|
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 === _this.timer) {
|
|
button.css({
|
|
color: "#5786d2",
|
|
"border-bottom": "1px solid #5786d2",
|
|
});
|
|
// localStorage.setItem("tim", v.resolution);
|
|
}
|
|
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);
|
|
localStorage.setItem("tim", v.resolution);
|
|
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");
|
|
};
|
|
widget.chart().createStudy(
|
|
"Moving Average",
|
|
false,
|
|
true,
|
|
[5, "close", 0],
|
|
null,
|
|
{
|
|
"Plot.color": "#e843da",
|
|
}
|
|
);
|
|
widget.chart().createStudy(
|
|
"Moving Average",
|
|
false,
|
|
true,
|
|
[10, "close", 0],
|
|
null,
|
|
{
|
|
"Plot.color": "#53b987",
|
|
}
|
|
);
|
|
widget.chart().createStudy(
|
|
"Moving Average",
|
|
false,
|
|
true,
|
|
[30, "close", 0],
|
|
null,
|
|
{
|
|
"Plot.color": "#ff231f",
|
|
}
|
|
);
|
|
});
|
|
},
|
|
},
|
|
created(){
|
|
let tim=localStorage.getItem("tim");
|
|
if(tim){
|
|
this.timer=tim
|
|
}
|
|
},
|
|
mounted() {
|
|
this.initView();
|
|
},
|
|
};
|
|
</script>
|
|
<style scoped lang="scss">
|
|
|
|
</style>
|
|
|