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.
 
 
 
 
 
 

583 lines
17 KiB

<template>
<div class="contract-page" style="background-color: black;padding-top: 5px;">
<!-- <div class="banner-block col-xs-8">-->
<!-- <el-carousel :interval="6000" height="450px">-->
<!-- <el-carousel-item v-for="item in pcBannerList" :key="item.id">-->
<!-- <img :src="item.imgurl" width="100%" height="100%" />-->
<!-- </el-carousel-item>-->
<!-- </el-carousel>-->
<!-- </div>-->
<div class="d-flex align-items-center" style="background-color: #121212;min-height:58px;">
<div class="price px-3">
<img :src="currentIcon" alt="" style="width: 26px;height: 26px;">
</div>
<div class="price">
<div class="item fn-16" style="font-weight: bold;">{{ activeContract.pair_name }}</div>
</div>
<div class="d-flex fn-14 px-4 p-l-A align-items-center py-2">
<div class="item px-2 min-width-A">
<div class="title" :class="{
decreace2: activeContract.increase < 0,
increase: activeContract.increase >= 0
}">
{{ price1 }}
<!-- {{set_price}} -->
</div>
<!-- <div class="title mb-1 text-secondary">
{{ $t("contract.h6") }}
</div> -->
<div :class="{
decreace2: activeContract.increase < 0,
increase: activeContract.increase >= 0
}">
{{ activeContract.increaseStr }}
</div>
</div>
</div>
<!-- 币种价值数据 -->
<div class="d-flex fn-14">
<div class="item px-2 min-width-B">
<div class="title mb-1 text-secondary">
24h {{ $t("contract.h7") }}
</div>
<div class="fn-12" style="color: #a8263b;">
{{ activeContract.high }}
</div>
</div>
<div class="item px-2 min-width-B">
<div class="title mb-1 text-secondary">
24h {{ $t("contract.h8") }}
</div>
<div class="fn-12" style="color: #a8263b;">
{{ activeContract.low }}
</div>
</div>
<div class="item px-2 min-width-B">
<div class="title mb-1 text-secondary">
24h {{ $t("contract.h9") }}
(USDT)
</div>
<div class="fn-12" style="color: #a8263b;">
{{ activeContract.vol }}
</div>
</div>
</div>
</div>
<div class="page-top d-flex pt-2">
<!-- 交易对 -->
<div style="width: 24%;background-color: #121212;margin-right: 7px;">
<div
class="coin-change d-flex align-items-center py-2 pl-2 heading justify-content-between" style="border-bottom: 1px solid #2e2e2e;height: 43px;font-size: 16px;"
>{{ $t("contact.market") }}
</div>
<div class="d-flex search_box">
<i class="el-icon-search"></i>
<input type="text" :placeholder="$t('exchange.search')" v-model="filterCoin" @input="enterFilter">
</div>
<div class="bottom-box-left">
<template v-for="parent in contractList">
<table class="table" :key="parent.coin_name + 1">
<thead>
<tr>
<th class="" style="display:block;width:100%">
<!-- {{ $t("contract.h5") }} -->
<div class="width-32">{{ $t("contract.h5") }}</div>
<div class="text-right width-32">{{ $t("contract.g3") }}</div>
<div class="text-right width-32">{{ $t("contract.h6") }}</div>
</th>
<!-- <th>{{ $t("contract.g3") }}</th>
<th>{{ $t("contract.h6") }}</th> -->
</tr>
</thead>
<tbody class="trade-list">
<tr
v-for="item in parent.marketInfoList"
:key="item.symbol"
:class="{ active: item.symbol == activeSymbol }"
@click="ispopover1(item.symbol)"
v-if="isShow(item)"
style="display:block"
>
<td style="display:block;width:100%;border:none;">
<div class="width-32">
<div class="d-flex">
<div v-for="items in Liste" :key="items.symbol">
<img :src="items.icon" width="20" height="20" v-if="items.symbol==item.symbol" />
</div>
<div style="margin-left: 10px;">{{ item.symbol }}/{{ parent.coin_name }}</div>
</div>
</div>
<div class="text-right width-32">
{{ item.symbol == activeSymbol ? price1 : item.price }}
</div>
<div class="text-right width-32" :class="item.increase < 0 ? 'decreace' : 'increase'">
{{ item.increaseStr }}
</div>
</td>
<!-- <td class="text-right" style="">
:class="item.increase < 0 ? 'decreace' : 'increase'"
{{ item.close }}
</td>
<td class="text-right" :class="item.increase < 0 ? 'decreace' : 'increase'"
style="">
{{ item.increaseStr }}
</td> -->
</tr>
</tbody>
</table>
</template>
</div>
</div>
<div class="kline-box flex-fill mr-2">
<div
class="d-flex align-items-center py-2 pl-2 heading justify-content-between" style="border-bottom: 1px solid #2e2e2e;height: 43px;font-size: 16px;"
>{{ $t("contact.chart") }}
</div>
<kline
:activeCoin="{ pair_name: activeContract.pair_name }"
v-if="activeContract.pair_name"
:contract="true"
:wsUrl="wsUrl"
:newPriceObj1="newPriceObj"
/>
<!-- 交易 -->
<exchange-store
:holdPositionList="holdPositionList"
:symbol="activeSymbol"
:defaultPrice="defaultPrice"
:newPriceObj="newPriceObj"
:contractOpen="contractOpen"
@accountInfo="accountInfo = $event"
@position="holdPosition"
@getSymbolDetail="symbolDetail=$event"
/>
</div>
<div style="width: 24%;">
<!-- 盘口 -->
<handicap
@input="newPriceObj = $event"
@selectprice="defaultPrice = $event"
:symbol="activeSymbol"
:wsUrl="wsUrl"
:ws="ws"
class=""
ref="handicap"
/>
<!-- 合约账户 -->
<div style="margin-top: 8px;">
<account class="bg-plain" :accountInfo="accountInfo"/>
</div>
</div>
</div>
<page-bottom
@position="holdPosition"
@isall="
holdPositionAll = $event;
holdPosition();
"
@setactiveItem="setactiveItem"
:accountInfo="accountInfo"
:newPriceObj="newPriceObj"
:holdPositionList="holdPositionList"
:holdPositionAll="holdPositionAll"
:symbol="activeSymbol"
:symbolDetail="symbolDetail"
/>
<div
class="modal fade"
id="openContract"
tabindex="-1"
role="dialog"
aria-labelledby="contractClose"
aria-hidden="true"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="contractClose">
{{ contractAgreement.title }}
</h5>
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div v-html="contractAgreement.body"></div>
</div>
<div class="modal-footer d-flex justify-content-center">
<button type="button" class="btn btn-primary" @click="opening">
{{$t('contract.j8')}}
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import kline from "../option/kline";
import handicap from "./handicap.vue";
import account from "./account.vue";
import exchangeStore from "./exchange-store.vue";
import pageBottom from "./page-bottom.vue";
import Contract from "../../api/contract";
import Socket from "@/api/server/Socket.js";
import Home from "@/api/home";
import bus from "@/components/bus.js";
export default {
components: {
kline,
handicap,
account,
exchangeStore,
pageBottom
},
data() {
return {
contractList: [],
activeSymbol: "",
holdPositionAll: false,
holdPositionList: [],
newPriceObj: {},
pcBannerList:[],
accountInfo: {},
defaultPrice: "",
wsUrl: this.Globals.Server.Path.WS1,
ws: new Socket(this.Globals.Server.Path.WS1),
_time: null,
contractOpen: false,
contractAgreement: {},
symbolDetail:{},
currentIcon: '',
filterCoin: "",
contractListFilter: [],
Liste:[],
price1:0,
intervalId:''
};
},
computed: {
activeContract(val) {
let contractList=this.contractList
.map(item => item.marketInfoList)
.flat()
.find(item => item.symbol == this.activeSymbol) || {}
if(val.price){
delete contractList.price
}
return contractList;
},
isLogin() {
return Boolean(localStorage.token);
},
// set_price() {
// return this.$store.getters.set_price; // 从 Vuex 获取共享值
// }
// contractListFilter(){
// return this.contractList.map((item1, index1)=>{
// item1.marketInfoList.filter(item2=>{
// return item2.symbol.indexOf(this.filterCoin)!=-1
// })
// return item1;
// })
// }
},
watch: {
activeSymbol() {
this.holdPosition();
},
// filterCoin: {
// handler(n,o){
// if(!n){
// this.contractListFilter = this.contractList;
// }else{
// this.contractListFilter = this.contractList.map((item1, index1)=>{
// let arr = item1;
// arr.marketInfoList = item1.marketInfoList.filter(item2=>{
// return item2.symbol.indexOf(n.toUpperCase())!=-1
// })
// return arr;
// })
// }
// },
// immediate: true
// }
},
destroyed() {
clearInterval(this._time);
},
created() {
// this.openStatus();
this.getMarketList();
this.holdPosition();
this.indexList();
this._time = setInterval(() => {
if (this.contractOpen) {
this.holdPosition();
}
}, 3000);
this.ws.on("open", () => {
this.swapMarketList();
});
// console.info(this.$refs)
bus.$on('collapse', msg => {
this.activeContract.price =this.activeContract.symbol=='BTC'? (msg.close).toFixed(1):(msg.close).toFixed(3);
this.holdPositionList.map(item=>{
if(item.symbol==this.activeContract.symbol) item.realtimePrice=this.activeContract.price
})
});
this.startWatchingPrice();
},
//三秒更新一次数据
mounted: function () {
setInterval(() => {
this.holdPosition();
}, 2000)
},
beforeDestroy() {
this.stopWatchingPrice(); // 组件销毁时停止监听
},
methods: {
startWatchingPrice(){
this.intervalId = setInterval(() => {
let newPrice = localStorage.getItem('price');
this.price1 = newPrice;
}, 100); // 每秒检查一次
},
stopWatchingPrice() {
clearInterval(this.intervalId); // 清除定时器
},
ispopover1(item){
this.activeSymbol=item;
// this.$refs.popover.showPopper = false;
this.getMarketList();
},
swapMarketList() {
let msg = "swapMarketList";
this.ws.send({
cmd: "sub",
msg: msg
});
this.ws.on("message", res => {
let { data, sub,cmd } = res;
if (sub == msg) {
if( data.symbol=='BTC' )(data.price).toFixed(1)
this.contractList = data;
if(this.filterCoin==''){
// console.log('123');
this.contractListFilter = data;
// this.Listes();
}
}else if (cmd == "ping") {
this.ws.send({
cmd: "pong"
});
}
});
this.ws.on('close',()=>{
this.ws= new Socket(this.Globals.Server.Path.WS1),
console.log('链接关闭');
this.wsOpen();
})
},
Listes(){
this.Liste = []
this.contractList[0].marketInfoList.map(item=>{
this.Liste.push({
pair_name: item.pair_name,
symbol: item.symbol,
icon:item.icon
})
})
},
wsOpen(){
this.ws.on("open", () => {
this.swapMarketList();
this.$refs.handicap.linkSocket()
});
},
// 获取合约市场
getMarketList() {
this.currentIcon = "";
Contract.getMarketList().then(res => {
if(this.activeSymbol==''){
// 页面初始获取
this.contractList = res;
// this.Listes();
if(this.filterCoin==''){
// console.log('1234');
this.contractListFilter = res;
this.Listes();
}
// 默认值
let firstParent = res[0];
if (firstParent) {
let first = firstParent.marketInfoList[0];
if (first) this.activeSymbol = first.symbol;
this.currentIcon = res[0].marketInfoList[0].icon;
}
}else{
// 币种切换获取icon
for(let item of res[0].marketInfoList){
if(this.activeSymbol==item.symbol){
this.currentIcon = item.icon;
}
}
}
});
},
// 获取持仓
holdPosition() {
if (!this.isLogin) return;
let data = {
symbol: (this.holdPositionAll && this.activeSymbol) || ""
};
Contract.holdPosition(data, { loading: false }).then(res => {
// console.info(res)
res.map(item=>{
if(item.symbol==this.activeContract.symbol) item.realtimePrice=this.activeContract.price
})
this.holdPositionList = res;
});
},
// 获取永续合约开通状态
openStatus() {
if(!this.isLogin) return;
Contract.openStatus().then(res => {
this.contractOpen = res.open;
if (!this.contractOpen) {
this.contractAgreement = res.contractAgreement;
$("#openContract").modal("show");
}
});
},
// 开通永续合约
opening() {
Contract.opening().then(res => {
$("#openContract").modal("hide");
this.contractOpen = true;
this.$message.success(this.$t('contract.j9'));
});
},
indexList() {
Home.indexList().then((res) => {
this.pcBannerList = res.pcBannerList
// setTimeout(() => {
// this.skroll();
// }, 100);
}).catch((res) => {});
},
//获取某一个持仓订单的数据
setactiveItem(index=0){
this.accountInfo=this.holdPositionList[index]
},
enterFilter(){
},
isShow(symbol) {
if (!this.filterCoin) return true;
let name = symbol.pair_name || symbol.symbol;
return name.toLowerCase().includes(this.filterCoin.toLowerCase());
// const reg = new RegExp(this.filterCoin, "gi");
// if (!this.filterCoin) return true;
// else {
// // let name = symbol.coinName || symbol.pair;
// // return name.search(reg) >= 0;
// let name = symbol.pair_name || symbol.symbol;
// console.log(reg.test(name),'12345');
// return reg.test(name);
// // return name.search(reg) >= 0;
// }
// return !this.keyword || symbol.coinName.concat(symbol.pair).search(reg) >= 0;
},
}
};
</script>
<style lang="scss" scoped>
.justify-content-between ::v-deep .dark-app .theme-switch .theme-switch-button .left, .dark-app .theme-switch .theme-switch-button .right{
color:white !important
}
thead th, table td{
font-size: 14px;
}
.trade-list{
// width: 23vw;
height: 1110px;
overflow-y: auto;
display: block;
}
tbody tr{
cursor: pointer;
}
.page-top table tbody tr:hover{
background-color: #242424;
td:first-child{
color: #2C60DC;
}
}
.page-top table tbody tr.active{
background-color: #242424;
td:first-child{
color: #2C60DC;
}
}
.page-top table tbody td{
border: none;
}
.decreace{
color: #E33F31;
}
.increase{
color: #6EB189;
}
.decreace2{
color: #BB4965;
}
.text-secondary{
color: #636363 !important;
}
.search_box{
width: 95%;
height: 40px;
margin: 10px auto;
border: 1px solid #2e2e2e;
border-radius: 5px;
color: #2e2e2e;
align-items: center;
i{
width: 40px;
text-align: center;
font-size: 16px;
}
input{
background-color: transparent;
border: none;
border-left: 1px solid #2e2e2e;
padding: 0px 10px;
height: 40px;
font-size: 16px;
color: #fff;
}
}
.min-width-B{
min-width: 130px;
}
.width-32{
display: inline-block !important;
vertical-align: top !important;
width: 32% !important;
}
</style>