<template>
|
<div class="flex flex-col flex-1">
|
<div class="flex items-center h-66 tabBackground text-grey">
|
<p
|
class="font-28 flex-1 flex items-center justify-center h-66 buy-item"
|
:class="currentType == 'open' ? 'open' : ''"
|
@click="changeTab('open')"
|
>
|
{{ $t("买入") }}
|
</p>
|
<p
|
class="font-28 flex-1 flex items-center justify-center h-66 buy-item"
|
:class="currentType == 'close' ? 'close' : ''"
|
@click="changeTab('close')"
|
>
|
{{ $t("卖出") }}
|
</p>
|
</div>
|
|
<div class="mt-22 mb-22 inputBackground" style="position: relative">
|
<div
|
class="flex justify-between items-center w-full h-70"
|
@click="selectBtn"
|
>
|
<!-- <img src="@/assets/image/public/warn.png" alt="warn-icon" class="w-25 h-25 pl-20"/> -->
|
<div class="pl-16 textColor" style="width: 80%">{{ title }}</div>
|
<img
|
src="@/assets/image/public/grey-select.png"
|
alt="select-icon"
|
class="w-22 h-11 pr-20"
|
/>
|
</div>
|
<div class="option-box" v-if="isShow">
|
<div
|
class="font-30"
|
v-for="item in selectData"
|
:key="item.type"
|
@click="selectItem(item)"
|
>
|
{{ item.title }}
|
</div>
|
</div>
|
</div>
|
<div
|
class="h-70 lh-70 inputBackground mb-25 flex justify-center px-16 textColor2"
|
>
|
<input
|
placeholder=""
|
class="targetPrice w-full h-70 border-none"
|
v-model="form.price"
|
:disabled="type / 1 === 1"
|
/>
|
<span>USDT</span>
|
</div>
|
<div
|
class="h-70 lh-70 inputBackground mb-25 flex justify-center px-16 textColor2"
|
>
|
<span>{{ title }}</span>
|
</div>
|
<div class="flex total-list">
|
<div
|
class="total-div"
|
:class="[!isTotal ? 'active-bg' : '']"
|
@click="checkIsTotal(false)"
|
>
|
{{ $t("数量") }}
|
</div>
|
<div
|
class="total-div"
|
:class="[isTotal ? 'active-bg' : '']"
|
@click="checkIsTotal(true)"
|
>
|
{{ $t("总额") }}
|
</div>
|
</div>
|
<div
|
v-if="!isTotal"
|
class="h-70 lh-70 inputBackground mb-36 flex justify-center px-16"
|
>
|
<input
|
:placeholder="$t('数量')"
|
class="w-full h-70 border-none textColor"
|
v-model="form.volume"
|
@input="onInput"
|
/>
|
<span class="textColor">{{ symbolname }}</span>
|
</div>
|
<div
|
v-if="isTotal"
|
class="h-70 lh-70 inputBackground mb-36 flex justify-center px-16"
|
>
|
<input
|
:placeholder="$t('总额')"
|
class="w-full h-70 border-none textColor"
|
v-model="form.total"
|
@input="onInputTotal"
|
/>
|
<span class="textColor">{{ "USDT" }}</span>
|
</div>
|
<!-- <vue-slider v-bind="options" v-model="form.volume" :interval="interval"></vue-slider> -->
|
<!-- <vue-slider class="mainBox" v-bind="options" :interval="interval" v-model="form.volume" :hide-label="true" :railStyle="{ background: '#404040', height: '10px' }"
|
:processStyle="{ background: '#266BFF', height: '10px' }">
|
<template v-slot:step="{ active }">
|
<div :class="['custom-step', { active }]"></div>
|
</template>
|
</vue-slider> -->
|
<div
|
style="color: #868d9a"
|
class="font-24 w-full flex justify-between items-center"
|
>
|
<!-- <span class="flex-1 text-left">0%</span> -->
|
<span
|
class="flex-1 tab-item"
|
:class="[percentageVal == 25 ? 'select-active' : '']"
|
@click="exchangeVal(25)"
|
>25%</span
|
>
|
<span
|
class="flex-1 tab-item"
|
:class="[percentageVal == 50 ? 'select-active' : '']"
|
@click="exchangeVal(50)"
|
>50%</span
|
>
|
<span
|
class="flex-1 tab-item"
|
:class="[percentageVal == 75 ? 'select-active' : '']"
|
@click="exchangeVal(75)"
|
>75%</span
|
>
|
<span
|
class="flex-1 tab-item"
|
:class="[percentageVal == 100 ? 'select-active' : '']"
|
@click="exchangeVal(100)"
|
>100%</span
|
>
|
</div>
|
<div class="flex justify-between items-center mt-40">
|
<div class="flex flex-col font-24">
|
<p class="text-grey" v-if="this.currentType === 'open'">
|
{{ $t("可用")
|
}}<span class="textColor ml-8">
|
{{ initOpen.volume | nan }} USDT</span
|
>
|
</p>
|
<p class="text-grey" v-else>
|
{{ $t("可卖")
|
}}<span class="textColor ml-8"
|
>{{ initClose.volume | nan }} {{ symbolname }}</span
|
>
|
</p>
|
</div>
|
<van-icon
|
name="add-o"
|
@click="$router.push('/exchange/exchangePage')"
|
class="font-30 add-icon"
|
/>
|
<!-- <img @click="$router.push('/exchange/exchangePage')" src="@/assets/image/public/switch.png" class="w-24 h-24" /> -->
|
</div>
|
<div
|
style=""
|
class="w-full h-90 lh-90 flex justify-center text-white text-center rounded buyandSell mt-70"
|
:class="currentType === 'open' ? 'bg-green' : 'bg-red'"
|
@click="order()"
|
>
|
{{ currentType == "open" ? $t("买入") : $t("卖出") }}
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import config from "@/config";
|
import { Popup, Tabs, Tab } from "vant";
|
import VueSlider from "vue-slider-component";
|
import "vue-slider-component/theme/default.css";
|
import { _getBalance } from "@/API/trade.api";
|
import TradeApi from "@/API/trading.js";
|
import { mapGetters } from "vuex";
|
// import PopupConfirmOrder from '@/components/popup-confirm-order'
|
export default {
|
name: "perpetualPosition",
|
components: {
|
VueSlider,
|
[Popup.name]: Popup,
|
[Tabs.name]: Tabs,
|
[Tab.name]: Tab,
|
},
|
props: {
|
symbol: {
|
type: String,
|
default: "",
|
},
|
symbolname: {
|
type: String,
|
default: "--",
|
},
|
price: {
|
type: [Number, String],
|
default: "0.00",
|
},
|
initOpen: {
|
type: Object,
|
default() {
|
return {};
|
},
|
},
|
initClose: {
|
type: Object,
|
default() {
|
return {};
|
},
|
},
|
},
|
computed: {
|
...mapGetters("user", ["userInfo"]),
|
},
|
activated() {
|
this.selectData = [
|
{ title: this.$t("市价委托"), type: "1" },
|
{ title: this.$t("限价委托"), type: "2" },
|
];
|
this.title = this.selectData[0].title;
|
this.type = this.selectData[0].type;
|
},
|
watch: {
|
initOpen: {
|
// 处理滚动条初始值
|
deep: true,
|
handler(val) {
|
console.log(val);
|
if (val.volume / 1 > 0) {
|
this.handleInitSliderOption();
|
}
|
},
|
},
|
initClose: {
|
// 处理滚动条初始值
|
deep: true,
|
handler(newVal, oldVal) {
|
if (newVal.volume / 1 > 0) {
|
this.handleInitSliderOption(true);
|
}
|
},
|
},
|
price(val) {
|
if (this.type === "1") {
|
// !this.focus &&
|
this.form.price = val;
|
}
|
},
|
},
|
filters: {
|
nan(val) {
|
return isNaN(val) ? "--" : val;
|
},
|
},
|
data() {
|
return {
|
options: config.sliderOptions,
|
value: 0,
|
isShow: false,
|
title: this.$t("市价委托"),
|
selectData: [],
|
form: {
|
volume: "",
|
session_token: "",
|
symbol: "", // 币种
|
price: "",
|
total: "",
|
order_price_type: "opponent", // 市价or限价
|
},
|
type: "1", //选中市价或限价类型
|
currentType: "open", //开仓类型
|
interval: 0.001,
|
marks: (val) => val % 25 === 0,
|
isTotal: false,
|
percentageVal: 0,
|
};
|
},
|
mounted() {},
|
methods: {
|
checkIsTotal(val) {
|
this.isTotal = val;
|
this.percentageVal = 0;
|
this.form.total = "";
|
this.form.volume = "";
|
},
|
exchangeVal(val) {
|
this.percentageVal = val;
|
if (!this.isTotal) {
|
if (this.currentType == "open") {
|
let sum =
|
(parseFloat(this.initOpen.volume) * (val / 100)) /
|
parseFloat(this.form.price);
|
this.form.volume = Math.floor(sum * 100000) / 100000;
|
} else {
|
let sum = parseFloat(this.initClose.volume);
|
this.form.volume = Math.floor(sum * (val / 100) * 100000) / 100000;
|
}
|
} else {
|
if (this.currentType == "open") {
|
this.form.total = this.initOpen.volume * (val / 100);
|
} else {
|
this.form.total =
|
Math.floor(
|
this.initClose.volume *
|
(val / 100) *
|
parseFloat(this.form.price) *
|
1000
|
) / 1000;
|
}
|
}
|
},
|
handleInitSliderOption(volume) {
|
if (!volume) {
|
// 金额是否需要变动
|
this.form.volume = "";
|
}
|
console.log(this.initOpen.volume);
|
let vol;
|
if (this.currentType === "open") {
|
vol = this.initOpen.volume / 1;
|
} else {
|
vol = this.initClose.volume / 1;
|
}
|
this.options.max = Number(vol.toFixed(3));
|
if (this.options.max > 0) {
|
this.options.disabled = false;
|
} else {
|
this.options.disabled = true;
|
}
|
},
|
onInput() {
|
// 数量变化
|
if (this.currentType === "open") {
|
let maxSum =
|
parseFloat(this.initOpen.volume) / parseFloat(this.form.price);
|
console.log(this.initOpen.volume);
|
console.log(this.form.price);
|
console.log(maxSum);
|
if (this.form.volume * 1 > maxSum / 1) {
|
this.form.volume = maxSum;
|
}
|
} else {
|
if ((this.form.volume * 1) / 1 > this.options.max / 1) {
|
this.form.volume = this.options.max / 1;
|
}
|
}
|
},
|
onInputTotal() {
|
//总额变化
|
//最大额度
|
if (this.form.total > 0) {
|
if (this.currentType === "open") {
|
console.log(this.initOpen.volume);
|
if (this.form.total * 1 > this.initOpen.volume * 1) {
|
this.form.total = this.initOpen.volume;
|
}
|
} else {
|
let sum = (
|
parseFloat(this.form.total) / parseFloat(this.form.price)
|
).toFixed(5);
|
if (parseFloat(sum) > parseFloat(this.initClose.volume)) {
|
this.form.total = (
|
parseFloat(this.initClose.volume) * parseFloat(this.form.price)
|
).toFixed(5);
|
}
|
}
|
}
|
},
|
//价格类型下拉框切换
|
selectBtn() {
|
this.isShow = !this.isShow;
|
},
|
//选择价格类型
|
selectItem(item) {
|
if (item.type == 1) {
|
this.form.price = this.price;
|
}
|
this.form.order_price_type = item.type === "1" ? "opponent" : "limit";
|
this.title = item.title;
|
this.type = item.type;
|
this.isShow = false;
|
},
|
//选择开仓类型
|
changeTab(type) {
|
// 开仓和
|
this.percentageVal = 0;
|
this.isTotal = false;
|
this.form.total = "";
|
console.log("changeTab", type);
|
// TODO: 这里应该是换函数
|
// this.form.direction = type === 'open' ? 'buy' : 'sell'
|
if (this.currentType === type) {
|
return;
|
}
|
this.currentType = type;
|
if (this.currentType === "close") {
|
this.$emit("ordered", "close"); // 更新平仓初始化参数
|
} else {
|
this.$emit("ordered", "open"); // 更新平仓初始化参数
|
}
|
this.handleInitSliderOption();
|
},
|
order() {
|
if (!this.userInfo.token) {
|
this.$router.push("/login");
|
return;
|
}
|
let volume = "";
|
if (this.isTotal) {
|
if (!this.form.total) {
|
this.$toast.fail(this.$t("请输入总额"));
|
return;
|
}
|
if (this.currentType === "open") {
|
this.form.volume = parseFloat(this.form.total).toFixed(5);
|
} else {
|
this.form.volume =
|
parseFloat(this.form.total) / parseFloat(this.form.price);
|
this.form.volume = this.form.volume.toFixed(5);
|
}
|
volume = this.form.volume;
|
} else {
|
if (!this.form.volume) {
|
this.$toast.fail(this.$t("请输入数量"));
|
return;
|
}
|
if (this.currentType === "open") {
|
volume = parseFloat(this.form.volume) * parseFloat(this.form.price);
|
} else {
|
volume = this.form.volume;
|
}
|
}
|
this.form.symbol = this.$route.params.symbol;
|
let _order = null; // api
|
let emitFunc = null; // 触发函数
|
|
if (this.currentType === "open") {
|
this.form.session_token = this.initOpen.session_token;
|
} else {
|
this.form.session_token = this.initClose.session_token;
|
}
|
_order =
|
this.currentType === "open" ? TradeApi.tradeBuy : TradeApi.tradeSell;
|
emitFunc = this.currentType;
|
_order({
|
volume: volume,
|
session_token: this.form.session_token,
|
symbol: this.form.symbol, // 币种
|
price: this.form.price,
|
total: this.form.total,
|
order_price_type: this.form.order_price_type, // 市价or限价
|
})
|
.then((res) => {
|
this.$toast(this.$t("操作成功"));
|
this.form.volume = "";
|
this.form.total = "";
|
_getBalance().then((data) => {
|
// 刷新余额
|
this.$store.commit("user/SET_USERINFO", { balance: data.money });
|
});
|
this.$emit("ordered", emitFunc);
|
})
|
.catch(() => {
|
// 也需要重新初始化
|
this.$emit("ordered", emitFunc);
|
});
|
},
|
},
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
// .buy-item {
|
// @include themify() {
|
// background: themed("input_background");
|
// }
|
// }
|
|
.bg-f3 {
|
background: #f3f3f3;
|
}
|
|
.options {
|
box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.3);
|
border-radius: 6px;
|
|
div {
|
font-size: 22px;
|
text-align: center;
|
width: 140px;
|
height: 60px;
|
line-height: 60px;
|
|
&.option-active {
|
background-color: #f5f5f5;
|
}
|
}
|
}
|
|
.right-word {
|
top: 50%;
|
transform: translateY(-50%);
|
right: 19px;
|
position: absolute;
|
border-radius: 6px;
|
}
|
|
.vue-slider {
|
height: 3px !important;
|
padding: 0 10px !important;
|
}
|
|
.vue-slider-dot {
|
width: 28px !important;
|
height: 28px !important;
|
}
|
|
.vue-slider-mark-label {
|
font-size: 16px;
|
margin-top: 14px !important;
|
}
|
|
.vue-slider-mark-label-active {
|
color: #868d9a !important;
|
}
|
|
.vue-slider-dot-handle {
|
border: 3px solid #2c78f8;
|
}
|
|
.vue-slider-mark {
|
width: 20px !important;
|
height: 20px !important;
|
|
&:nth-child(1) {
|
.vue-slider-mark-label {
|
transform: translateX(-14px) !important;
|
}
|
}
|
|
&:nth-child(5) {
|
.vue-slider-mark-label {
|
transform: translateX(-60px) !important;
|
}
|
}
|
}
|
|
// 开仓样式
|
.tabcon {
|
// padding-bottom: 16%;
|
position: relative;
|
height: 80px;
|
}
|
|
.tab {
|
position: absolute;
|
left: 0px;
|
right: 0px;
|
top: 0px;
|
bottom: 0px;
|
display: flex;
|
align-items: center;
|
background-color: #f3f3f3;
|
border-radius: 5px;
|
overflow: hidden;
|
}
|
|
.tab > * {
|
height: 100%;
|
}
|
|
.tab > img {
|
margin-left: -2px;
|
margin-right: -2px;
|
}
|
|
.tab > a {
|
flex-grow: 1;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
cursor: pointer;
|
}
|
|
.open {
|
// background-color: #2EBD85;
|
background: url(@/assets/image/public/open-bg.png) no-repeat right center;
|
background-size: 100% 100%;
|
color: white;
|
}
|
|
.close {
|
// background-color: #F6465D;
|
background: url(@/assets/image/public/close-bg.png) no-repeat left center;
|
background-size: 100% 100%;
|
color: white;
|
}
|
|
// 下拉
|
.option-box {
|
position: absolute;
|
left: 0;
|
right: 0;
|
top: 90px;
|
width: 100%;
|
z-index: 3;
|
|
@include themify() {
|
background: themed("grey_bg");
|
}
|
|
text-align: center;
|
|
@include themify() {
|
box-shadow: 0px 0px 3px 3px themed("grey_bg");
|
}
|
|
border-radius: 4px;
|
|
@include themify() {
|
color: themed("text_color3");
|
}
|
}
|
|
.option-box > div {
|
padding: 30px 0;
|
}
|
|
.option-box > div:hover {
|
// background-color: #F5F5F5;
|
}
|
|
.num-text-color {
|
color: #4c4a54;
|
}
|
|
select {
|
appearance: none;
|
/* 去掉默认图标 */
|
-moz-appearance: none;
|
/* Firefox */
|
-webkit-appearance: none;
|
/* Safari and Chrome */
|
padding: 0 20px 0 20px;
|
background: url("../../assets/image/public/grey-select.png") no-repeat scroll
|
right center transparent;
|
/* 自己的图*/
|
background-size: 20px 11px;
|
}
|
|
.with100 {
|
width: 100%;
|
}
|
|
.height100 {
|
height: 100%;
|
}
|
|
.targetPrice {
|
opacity: 1;
|
}
|
|
.inputBackground {
|
input {
|
background: transparent !important;
|
}
|
}
|
|
.custom-step {
|
width: 20px;
|
height: 20px;
|
border-radius: 50%;
|
background: fff;
|
border: solid 1px #2256f7;
|
background: #fff;
|
}
|
|
.custom-step.active {
|
box-shadow: 0 0 0 2px #2256f7;
|
background-color: #2256f7;
|
}
|
|
.tab-item {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
|
@include themify() {
|
background: themed("input_background");
|
}
|
|
border-radius: 4px;
|
margin-right: 10px;
|
padding: 10px 0;
|
}
|
|
.total-list {
|
@include themify() {
|
background: themed("grey_bg");
|
}
|
|
display: flex;
|
|
@include themify() {
|
color: themed("text_color");
|
}
|
|
font-size: 26px;
|
align-items: center;
|
justify-content: center;
|
margin-bottom: 20px;
|
position: relative;
|
|
// ::after {
|
// position: absolute;
|
// content: '';
|
// top: 20%;
|
// left: 50%;
|
// height: 40px;
|
// background: #373737;
|
// width: 1px;
|
|
// }
|
|
.total-div {
|
flex: 1;
|
text-align: center;
|
padding: 20px 0;
|
}
|
}
|
|
.add-icon {
|
color: #1194f7;
|
}
|
|
.active-bg {
|
@include themify() {
|
background: themed("bg_dark");
|
}
|
}
|
|
.select-active {
|
background: #2ebd85;
|
|
@include themify() {
|
color: themed("text_color") !important;
|
}
|
}
|
|
.buyandSell {
|
position: relative;
|
z-index: 9;
|
}
|
</style>
|