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.
 
 
 
 
 
 

886 lines
35 KiB

<template>
<div class="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>
<div class="px-4 py-2 heading" v-if="0">
<!-- <theme-change/> -->
<el-tooltip placement="bottom" effect="light">
<div slot="content" class="market">
<div class="coin p-md color-light fn-20">
<img :src="detail.coin_icon" width="20" height="20" alt="">
{{detail.full_name}}
</div>
<div class="list">
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('nav.c3')}}:</div>
<div class="color-light">
{{detail.total_issuance}}
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('nav.c4')}}:</div>
<div class="color-light">
{{detail.total_circulation}}
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('nav.c5')}}:</div>
<div class="color-light">
{{detail.crowdfunding_price}}
</div>
</div>
<div class="d-flex justify-between p-x-md p-y-xs">
<div>{{$t('nav.c6')}}:</div>
<div class="color-light">
{{detail.publish_time}}
</div>
</div>
<div class=" p-x-md p-y-xs">
<div>{{$t('nav.c7')}}:</div>
<div class="color-light ov">
{{detail.white_paper_link}}
</div>
</div>
<div class=" p-x-md p-y-xs">
<div>{{$t('nav.c8')}}:</div>
<div class="color-light ov">
{{detail.official_website_link}}
</div>
</div>
</div>
<div class="p-md">
<div class="fn-20 color-light">
{{$t('nav.c9')}}
</div>
<div class="p-y-md edit-content" v-html="detail.coin_content">
</div>
</div>
</div>
<!-- <el-button><img src="../../assets/img/shuoming.png" width="20" height="20" alt=""></el-button> -->
</el-tooltip>
</div>
<!-- 生成K线图 -->
<k-line :symbol="symbol" :socket="socket" :priceDecimals="priceDecimals"></k-line>
<!-- 交易处理 -->
<div class="market-trade " style="background-color: #121212;">
<div class="px-3 pri">
<div class="nav nav-pills" style="background-color: transparent;border-bottom: 1px solid #2e2e2e;">
<div class="nav-item">
<a class="nav-link" :class="[`nav-link`, {active:!isCondition&&isMarket}]" @click.prevent="isCondition=false;isMarket=true;">{{ $t("common.market") }}</a>
</div>
<div class="nav-item">
<a class="nav-link" :class="[`nav-link`, {active:!isCondition&&!isMarket}]" @click.prevent="isCondition=false;isMarket=false;">{{ $t("common.limit") }}</a>
</div>
</div>
</div>
<ul class="px-3 nav nav-pills" v-if="0">
<!-- <li class="nav-item">
<a href :class="[`nav-link`, {active:isCondition&&!isMarket}]" @click.prevent="isCondition=true;isMarket=false;">
{{ $t("common.stop-limit") }}</a>
</li>
<li class="nav-item">
<a href :class="[`nav-link`, {active:isCondition&&isMarket}]" @click.prevent="isCondition=true;isMarket=true;">
{{ $t("common.stop-market") }}</a>
</li> -->
</ul>
<div class="tab-content">
<div class="tab-pane fade show active">
<div class="d-flex justify-content-between">
<!------------- Buy Order -------------->
<div class="market-trade-buy">
<!-- Trigger Price -->
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.buy.trigger">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.buy[0] }}
</span>
<div class="input-group" v-if="isCondition" slot="reference">
<input type="number" v-model="buyorder.trigger_price" class="form-control" :placeholder="$t('exchange.trigger-price')">
<div class="input-group-append">
<span class="input-group-text">{{pair.from}}</span>
</div>
</div>
</el-popover>
<template v-if="isMarket">
<div class="input-group">
<!-- Market Price -->
<input type="text" class="form-control" disabled :placeholder="$t('exchange.at-best-price')">
</div>
</template>
<template v-else>
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.buy.limitPrice">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.buy[1] }}
</span>
<div class="input-group" slot="reference">
<!-- Entrust Price -->
<input type="number" v-model="buyorder.entrust_price" class="form-control" :placeholder="$t('exchange.enter-price')">
<div class="input-group-append">
<span class="input-group-text">{{pair.from}}</span>
</div>
</div>
</el-popover>
</template>
<!-- Amount/Total -->
<template v-if="isMarket">
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.buy.marketTotal">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.buy[3] }}
</span>
<div class="input-group" slot="reference">
<input type="number" v-model="buyTotal" class="form-control" min=0 :placeholder="$t('exchange.enter-total')">
<div class="input-group-append">
<span class="input-group-text">{{pair.from}}</span>
</div>
</div>
</el-popover>
</template>
<template v-else>
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.buy.limitAmount">
<!-- 提示框的内容 -->
<span class="content">
<!-- 图标 -->
<i class="el-icon-warning-outline"></i>
<!-- 提示 -->
{{ msgList.buy[2] }}
</span>
<div class="input-group" slot="reference">
<input type="number" v-model="buyorder.amount" class="form-control" min=0 :placeholder="$t('exchange.enter-amount')">
<div class="input-group-append">
<span class="input-group-text">{{pair.to}}</span>
</div>
</div>
</el-popover>
</template>
<!-- Percent -->
<ul class="market-trade-list" v-if="false">
<li v-for="(item,index) in percentage" :key="index" :class="{buyPercentActive:index == buyPercentIndex}" @click="renderBuyAmount(item.value, index)">
<a href="javascript:void 0">{{ item.label }}</a>
</li>
</ul>
<div class="px-2">
<el-slider
v-model="activeStepBuy"
@change="sliderChangeBuy"
:format-tooltip="tooltip"
:marks="marks"
:step="25"
></el-slider>
</div>
<div class="d-flex justify-content-between mb-3 color_7c fn-10">
<div>0</div>
<div>100%</div>
</div>
<!-- Total -->
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.buy.orderTotal">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.buy[5] }}
</span>
<p slot="reference" class="color_7c">
{{$t('exchange.order-total')}}
<span style="color: #fff;"> <b>{{buyTotal}}</b> {{pair.from}} </span>
</p>
</el-popover>
<!-- Available -->
<p class="color_7c">
{{ $t('exchange.amount') }}
<span style="color: #fff;"> {{toBalance}} {{pair.to}}</span><br />
{{ $t('exchange.balance') }}
<span style="color: #fff;"> {{fromBalance}} {{pair.from}}</span>
</p>
<button class="btn buy" @click="handleBuyOrder">{{ $t("otc.a1") }} {{pair.to}}</button>
</div>
<!------------ Sell Order ----------->
<div class="market-trade-sell">
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.sell.trigger">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.sell[0] }}
</span>
<!-- Trigger Price -->
<div class="input-group" v-if="isCondition" slot="reference">
<input type="number" v-model="sellorder.trigger_price" class="form-control" min=0 :placeholder="$t('exchange.trigger-price')">
<div class="input-group-append">
<span class="input-group-text">{{pair.from}}</span>
</div>
</div>
</el-popover>
<template v-if="isMarket">
<div class="input-group">
<!-- Market Price -->
<input type="text" class="form-control" disabled :placeholder="$t('exchange.at-best-price')">
</div>
</template>
<template v-else>
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.sell.limitPrice">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.sell[1] }}
</span>
<div class="input-group" slot="reference">
<!-- Entrust Price -->
<input type="number" v-model="sellorder.entrust_price" class="form-control" min=0 :placeholder="$t('exchange.enter-price')">
<div class="input-group-append">
<span class="input-group-text">{{pair.from}}</span>
</div>
</div>
</el-popover>
</template>
<!-- Amount -->
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.sell.limitAmount">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.sell[2] }}
</span>
<div class="input-group" slot="reference">
<input type="number" v-model="sellorder.amount" class="form-control" min=0 :placeholder="$t('exchange.enter-amount')">
<div class="input-group-append">
<span class="input-group-text">{{pair.to}}</span>
</div>
</div>
</el-popover>
<ul class="market-trade-list" v-if="false">
<li v-for="(item,index) in percentage" :key="index" :class="{sellPercentActive:index == sellPercentIndex}" @click="renderSellAmount(item.value, index)">
<a href="javascript:void 0">{{ item.label }}</a>
</li>
</ul>
<div class="px-2">
<el-slider
v-model="activeStepSell"
@change="sliderChangeSell"
:format-tooltip="tooltip"
:marks="marks"
:step="25"
></el-slider>
</div>
<div class="d-flex justify-content-between mb-3 color_7c fn-10">
<div>0</div>
<div>100%</div>
</div>
<!-- Total -->
<el-popover popper-class='popover-tips' placement="top-start" trigger="manual" v-model="visibles.sell.orderTotal">
<span class="content">
<i class="el-icon-warning-outline"></i>
{{ msgList.sell[5] }}
</span>
<p slot="reference" class="color_7c">
{{ $t('exchange.order-total') }}
<span style="color: #fff;">
<b>{{sellTotal}}</b> {{pair.from}} </span>
</p>
</el-popover>
<p class="color_7c">
{{$t('exchange.amount')}}
<span style="color: #fff;"> {{toBalance}} {{pair.to}} </span><br />
{{ $t('exchange.balance') }}
<span style="color: #fff;"> {{fromBalance}} {{pair.from}}</span>
</p>
<button class="btn sell" @click="handleSellOrder">{{ $t("otc.a2") }} {{pair.to}}</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Exchange from "@/api/exchange";
import Market from "@/api/market";
import {
Message
} from 'element-ui'
export default {
props: ["isLogin", "socket", "symbol", "pair", "buyorder", "sellorder", "fromBalance", "toBalance", "newTrade", "minQty", "minTotal", "priceDecimals", "qtyDecimals"],
data() {
return {
detail:[],
isMarket: true,
isCondition: false,
userBanlance: null,
cacheTotal: 0, // 存放市价单输入的总值
cachePrice: null, // 存放最新价格
// 气泡弹框内容和触发
visibles: {
"buy": {
limitPrice: false, // 限制价格
limitAmount: false, // 限制数量
marketTotal: false, // 限制总额
marketAmount: false, // 市价数量
trigger: false, // 触发价格
orderTotal: false, // 订单总额
},
"sell": {
limitPrice: false,
limitAmount: false,
marketTotal: false,
marketAmount: false,
trigger: false,
orderTotal: false,
},
},
msgList: {
"buy": Array(6).fill(''), // 5个空字符串的数组
"sell": Array(6).fill('')
},
// 百分比集合
percentage: [{
label: "25%",
value: 0.25
},
{
label: "50%",
value: 0.5
},
{
label: "75%",
value: 0.75
},
{
label: "100%",
value: 1
},
],
marks:{
25:'',
50:'',
75:''
},
//
buyPercentIndex: null,
sellPercentIndex: null,
activeStepBuy: 0,
activeStepSell: 0
}
},
computed: {
// 获取type类型值
type() {
if (!this.isCondition) {
return this.isMarket ? 2 : 1;
} else {
return this.isMarket ? 4 : 3;
}
},
theme() {
return localStorage.theme ? localStorage.theme : "light";
},
buyTotal: {
get() {
// console.log(333)
if (!this.isMarket) {
return Math.multiple(this.buyorder.entrust_price, this.buyorder.amount);
} else {
return this.cacheTotal;
}
},
set(val) {
// console.log(444)
// 根据总值 计算数量
if (!this.isMarket) {
this.buyorder.amount = Math.division(val, this.buyorder.entrust_price);
} else { // 市价单 缓存总值
this.cacheTotal = val;
}
}
},
sellTotal: {
get() {
return Math.multiple(this.sellorder.entrust_price, this.sellorder.amount);
}
},
// activeStepBuy(){
// console.log(this.buyorder.amount, this.buyTotal, '000000')
// let num = 0;
// if(this.isMarket){
// num = this.buyTotal / (this.fromBalance * 100);
// }else{
// num = this.buyorder.amount / (this.fromBalance * 100);
// }
// return num;
// },
// activeStepSell(){
// console.log(1111)
// let num = this.sellorder.amount / (this.toBalance * 100);
// return num;
// },
// 当前语言
lang() {
let browser_Lang = navigator.language.includes('zh') ? 'zh' : 'en';
return localStorage.lang || browser_Lang;
},
},
watch: {
custom(newVal) {
console.log(newVal)
},
type() {
// 切换订单类型时 清空价格和数量
// 数量改变时 触发percentage更新
this.reset();
},
// 有新交易时触发 给限价单设定初始价格
newTrade(newVal, oldVal) {
// if (!this.isMarket ) {
// 新交易对有trade数据
if (!oldVal && newVal) { // 没值到初始化值
// 修改order里面price的值
this.cachePrice = newVal.price;
this.reset();
}
// 切换交易对时 清空了数据
if (oldVal && !newVal) { // 有值到没值的过程
this.cachePrice = null;
this.reset();
}
// }
},
symbol(){
this.getCoinInfo()
}
},
methods: {
getCoinInfo(){
// console.log(this.symbol.indexOf('usdt')!=-1)
if(this.symbol.indexOf('usdt')!=-1){
var market=this.symbol.substring(0,this.symbol.length-4);
}else{
var market=this.symbol.substring(0,this.symbol.length-3);
}
console.log(market)
let data = {
coin_name:market,
lang:this.lang
}
Market.getCoinInfo(data).then(res => {
this.detail = res;
this.$emit('changeCoinLogo', res);
}).catch(err => {
});
},
renderBuyAmount(val, index) {
console.info(val)
console.info(this.buyorder)
if (!this.buyorder.entrust_price) {
this.visibles.buy.limitPrice = true;
this.msgList.buy[1] = this.$t('nav.set');
this.clearAll();
return;
}
this.buyPercentIndex = index;
this.buyTotal = Math.multiple(this.fromBalance, val);
// console.info(this.buyTotal, '------------')
},
sliderChangeBuy($ev){
// console.log($ev, 22222);
if(this.isMarket){
this.buyTotal = Math.multiple(this.fromBalance, $ev/100);
}else{
if (!this.buyorder.entrust_price) {
this.visibles.buy.limitPrice = true;
this.msgList.buy[1] = this.$t('nav.set');
this.clearAll();
return;
}
// this.buyorder.entrust_price = Math.multiple(this.fromBalance, $ev/100);
this.buyorder.amount = Math.multiple(this.fromBalance / this.detail.total_issuance, $ev/100);
}
},
renderSellAmount(val, index) {
if (!this.sellorder.entrust_price) {
this.visibles.sell.limitPrice = true;
this.msgList.sell[1] = this.$t('nav.set');
this.clearAll();
return;
}
this.sellPercentIndex = index;
this.sellorder.amount = Math.multiple(this.toBalance, val);
},
sliderChangeSell($ev){
if (!this.sellorder.entrust_price) {
this.visibles.sell.limitPrice = true;
this.msgList.sell[1] = this.$t('nav.set');
this.clearAll();
return;
}
this.sellorder.amount = Math.multiple(this.toBalance, $ev/100);
},
handleBuyOrder() {
// 执行前端的有效性验证
if (!this.chkValidate(this.buyorder, this.buyTotal, "buy")) return;
const baseArgs = {
symbol: this.pair.to.concat('/', this.pair.from),
type: this.type,
};
// 区分限价、市价和条件委托单
// 1、限价单买入时 需要的参数:价格、数量、
// 2、市价单买入时 需要的参数:总值
// 3、条件单买入时 需要的参数:触发价、价格数量或者总值
// 4、卖出时 需要价格和数量
Exchange.storeEntrust(Object.assign(this.buyorder, {
total: this.buyTotal,
}, baseArgs)).then(data => {
Message.success('succes')
// 触发父组件的方法 更新余额和订单
this.$emit('update');
// 清空表单
this.reset();
}).catch(err => {
});
},
handleSellOrder() {
// 执行前端的有效性验证
if (!this.chkValidate(this.sellorder, this.sellTotal, "sell")) return;
// console.info(this.sellTotal)
const baseArgs = {
symbol: this.pair.to.concat('/', this.pair.from),
type: this.type,
};
Exchange.storeEntrust(Object.assign(this.sellorder, {
total: this.sellTotal
}, baseArgs)).then(data => {
Message.success('succes')
// 触发父组件的方法 更新余额和订单
this.$emit('update');
// 清空表单
this.reset();
}).catch(err => {
});
},
reset() {
// 如果没有newTrade时 则没有缓存价格 重置为最小值0
// 由于输入框去除了精度空值 这里还需要手动设置精度值
let price = this.cachePrice || 0;
// console.info(price)
// console.info(this.priceDecimals)
this.buyorder.entrust_price = Math.omitTo(price, this.priceDecimals);
this.buyorder.trigger_price = Math.omitTo(price, this.priceDecimals);
this.sellorder.entrust_price = Math.omitTo(price, this.priceDecimals);
// console.info(this.sellorder.entrust_price)
this.sellorder.trigger_price = Math.omitTo(price, this.priceDecimals);
// 清空数量
this.buyorder.amount = 0;
this.sellorder.amount = 0;
// total赋值会触发set方法
// this.buyTotal = 0;
// this.cacheTotal = 0;
// 去除百分比样式
this.buyPercentIndex = -1;
this.sellPercentIndex = -1;
},
clearAll() {
// 5s后统一清除提示框
setTimeout(function () {
Object.keys(this.visibles.buy).forEach(key => this.visibles.buy[key] = false);
Object.keys(this.visibles.sell).forEach(key => this.visibles.sell[key] = false);
}.bind(this), 5000);
},
empty(val) {
let ret;
switch (typeof val) {
case "number":
ret = val == 0;
break;
case "string":
ret = val == "0" || /^\s?$/.test(val);
break;
case "boolean":
ret = val;
break;
default:
ret = Boolean(val);
break;
}
return ret;
},
chkValidate(order, total, orderType) {
//
// 验证登录
if (!this.isLogin) {
this.$confirm(this.$t('nav.login'), {
confirmButtonText:this.$t('common.confirmBtn'),
cancelButtonText: this.$t('common.cancelBtn'),
type: 'warning'
}).then(() => {
this.$router.push(`/sign-in`);
}).catch();
return;
}
let flag = true;
switch (this.type) {
case 1: // limit
if (this.empty(order.entrust_price)) {
flag = false;
this.visibles[orderType].limitPrice = true;
this.msgList[orderType][1] = this.$t('nav.a1');
} else if (this.empty(order.amount)) {
flag = false;
this.visibles[orderType].limitAmount = true;
this.msgList[orderType][2] = this.$t('nav.a2');
} else {
if (order.amount < this.minQty) {
flag = false;
this.visibles[orderType].limitAmount = true;
this.msgList[orderType][2] = this.$t('nav.a3')+`${this.minQty}`;
}
if (total < this.minTotal) {
flag = false;
this.visibles[orderType].orderTotal = true;
this.msgList[orderType][5] = this.$t('exchange.total')+`${this.minTotal}`;
}
}
break;
case 2: // market
if (order.direction == "buy") { // 买
if (this.empty(total)) {
flag = false;
this.visibles[orderType].marketTotal = true;
this.msgList[orderType][3] = this.$t('nav.a4');
} else if (this.total < this.minTotal) {
flag = false;
this.visibles.marketTotal = true;
this.msgList[3] = this.$t('nav.a5')+` ${this.minTotal}`;
}
}
if (order.direction == "sell") { // 卖
if (this.empty(order.amount)) {
flag = false;
this.visibles[orderType].marketAmount = true;
this.msgList[orderType][4] = this.$t('nav.a6');
} else if (order.amount < this.minQty) {
flag = false;
this.visibles[orderType].marketAmount = true;
this.msgList[orderType][4] = this.$t('nav.a7')+` ${this.minQty}`;
}
}
break;
case 3: // stop-limit
if (this.empty(order.trigger_price)) {
flag = false;
this.visibles[orderType].trigger = true;
this.msgList[orderType][0] = this.$t('nav.a8')
} else if (this.empty(order.entrust_price)) {
flag = false;
this.visibles[orderType].limitPrice = true;
this.msgList[orderType][1] = this.$t('nav.a9')
} else if (this.empty(order.amount)) {
flag = false;
this.visibles[orderType].limitAmount = true;
this.msgList[orderType][2] = this.$t('nav.b1')
}
break;
case 4: // stop-market
if (this.empty(order.trigger_price)) {
flag = false;
this.visibles[orderType].trigger = true;
this.msgList[orderType][0] = this.$t('nav.b2')
} else {
if (order.direction == "buy") {
if (this.empty(total)) {
flag = false;
this.visibles[orderType].marketTotal = true;
this.msgList[orderType][3] = this.$t('nav.b3')
} else if (total < this.minTotal) {
flag = false;
this.visibles[orderType].marketTotal = true;
this.msgList[orderType][3] = this.$t('nav.b5')+` ${this.minTotal}`
}
}
if (order.direction == "sell") {
if (this.empty(order.amount)) {
flag = false;
this.visibles[orderType].marketAmount = true;
this.msgList[orderType][4] = this.$t('nav.b6')
} else if (order.amount < this.minQty) {
flag = false;
this.visibles[orderType].marketAmount = true;
this.msgList[orderType][4] =this.$t('nav.b7')+ ` ${this.minQty}`
}
}
}
break;
}
// 清除所有样式
this.clearAll();
// 返回验证结果
return flag;
},
// 保证金滑动条提示
tooltip($ev) {
return Math.round($ev) + "%";
},
},
created() {
this.getCoinInfo()
this.reset();
},
}
</script>
<style lang="scss" scoped>
.buyPercentActive {
a:link {
font-weight: bold;
background: #26a69a;
color: #fff;
}
}
.sellPercentActive {
a:link {
font-weight: bold;
background: #ef5350;
color: #fff;
}
}
.input-group-text {
width: 68px;
@include flexible(row, center, center);
}
.market-trade {
border: none;
border-color: transparent;
.pri .nav-link.active{color: #fff;position: relative;}
.pri .nav-link.active::after{
content: "";
display: block;
position: absolute;
bottom: -7px;
left: 50%;
width: 100%;
height: 4px;
background-color: #fff;
border-radius: 0px;
transform: translateX(-50%);
margin-left: 0px;
}
.nav{
padding: 7px 0px;
font-size: 14px;
}
}
.market{
width: 300px;
height: 500px;
overflow: scroll;
display: flex;
flex-wrap: wrap;
padding: 10px;
display: -webkit-box;
color: black;
.ov{
width: 100%;
table-layout:fixed;
word-break:break-all;
overflow:hidden;
}
}
.p-y-xs{
padding: 5px 0;
}
.el-button{
padding: 0!important;
background: transparent!important;
}
.market-trade button.buy{
background-color: #52A45A;
border-radius: 100px;
box-shadow: none;
}
.market-trade button.sell{
background-color: #BB4965;
border-radius: 100px;
box-shadow: none;
}
.market-trade .form-control{
height: 44px !important;
border-color: #404040;
}
.market-trade .input-group-text{
background-color: transparent;
color: #E4E5E4;
border-color: #404040;
}
.color_7c{
color: #7c7c7c !important;
}
</style>