1
jhzh
2026-05-22 ef52095f5e9f0a9fe2da779bb1573947d77d75b6
src/components/Transform/trade-order-area/index.vue
@@ -1,85 +1,72 @@
<template>
  <div class="flex flex-col flex-1 font-28">
    <div class="flex items-center h-66 tabBackground text-grey area_tabs">
      <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 class="order-area order-area-wrap flex flex-col flex-1 font-28">
    <!-- 父:order-area_tabs;子1:两个按钮的 div;子2:中间图片 div(父相子绝,图片在中间) -->
    <div class="order-area_tabs">
      <div class="order-tabs-buttons">
        <p class="order-tab order-tab--left font-28 flex items-center justify-center"
          :class="currentType == 'open' ? 'order-tab--buy' : 'order-tab-buy'" @click="changeTab('open')">{{ $t('买入') }}</p>
        <p class="order-tab order-tab--right font-28 flex items-center justify-center"
          :class="currentType == 'close' ? 'order-tab--sell' : 'order-tab-sell'" @click="changeTab('close')">{{ $t('卖出') }}</p>
      </div>
      <div class="order-tabs-bg">
        <img src="@/assets/imgs/new/contract-slash.png" alt="" class="order-tabs-bg-img" />
      </div>
    </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" />
    <!-- Limit 下拉 -->
    <div class="order-field order-field--select mt-18 mb-18" style="position:relative;">
      <div class="order-field-inner flex justify-between items-center w-full h-70 px-16" @click="selectBtn">
        <div class="order-field-label">{{ title }}</div>
        <img src="@/assets/image/public/grey-select.png" alt="select-icon" class="w-22 h-11" />
      </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 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 class="order-field h-70 lh-70 mb-18 flex items-center px-16">
      <input placeholder="" class="order-input flex-1 border-none" v-model="form.price" :disabled="type / 1 === 1" />
      <span class="order-unit">USDT</span>
    </div>
    <div class="h-70 lh-70  inputBackground mb-25 flex justify-center px-16 textColor2">
    <!-- 数量/总额 标题行 -->
    <div class="order-field h-70 lh-70 mb-18 flex items-center px-16 textColor2">
      <span>{{ title }}</span>
    </div>
    <!-- <template  v-if="initClose.status / 1 === 0">
      <div class="flex justify-center items-center h-66 buy-item">{{ $t('停牌中,禁止交易') }}</div>
    </template> -->
    <!-- <template v-else> -->
    <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 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 font-28" v-model="form.volume"
        @input="onInput" />
      <span class="textColor font-28">{{ strToArr(symbolName.toLocaleUpperCase(), '/')[0] }}</span>
    <div v-if="!isTotal" class="order-field h-70 lh-70 mb-18 flex items-center px-16">
      <input :placeholder="$t('数量')" class="order-input flex-1 border-none textColor font-28" v-model="form.volume" @input="onInput" />
      <span class="order-unit textColor font-28">{{ strToArr(symbolName.toLocaleUpperCase(), '/')[0] }}</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 font-28" v-model="form.total"
        @input="onInputTotal" />
      <span class="textColor font-28">{{ 'USDT' }}</span>
    <div v-if="isTotal" class="order-field h-70 lh-70 mb-18 flex items-center px-16">
      <input :placeholder="$t('总额')" class="order-input flex-1 border-none textColor font-28" v-model="form.total" @input="onInputTotal" />
      <span class="order-unit textColor font-28">USDT</span>
    </div>
    <div class="font-24 w-full flex justify-between items-center textColor1">
      <!-- <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>
    <!-- 25% 50% 75% 100% -->
    <div class="order-percent-row w-full flex justify-between items-center gap-8">
      <span class="order-percent-btn" :class="{ 'order-percent-btn--active': percentageVal == 25 }" @click="exchangeVal(25)">25%</span>
      <span class="order-percent-btn" :class="{ 'order-percent-btn--active': percentageVal == 50 }" @click="exchangeVal(50)">50%</span>
      <span class="order-percent-btn" :class="{ 'order-percent-btn--active': percentageVal == 75 }" @click="exchangeVal(75)">75%</span>
      <span class="order-percent-btn" :class="{ 'order-percent-btn--active': percentageVal == 100 }" @click="exchangeVal(100)">100%</span>
    </div>
    <div class="flex justify-between items-center mt-40">
    <!-- 可用 + 加号 -->
    <div class="flex justify-between items-center mt-20 order-available-row">
      <div class="flex flex-col font-24">
        <p class="text-grey" v-if="this.currentType === 'open'">{{ $t('可用') }}<span class="textColor ml-8">
            {{ initOpen.volume }}&nbsp;USDT</span>
        </p>
        <p class="text-grey" v-else>{{ $t('可卖') }}
          <span class="textColor ml-8">
            {{ initClose.volume }}&nbsp;{{ strToArr(symbolName.toLocaleUpperCase(), '/')[0] }}
          </span>
        </p>
        <p v-if="currentType === 'open'"><span class="order-available-label">{{ $t('可用') }}</span><span class="order-available-value ml-8">{{ initOpen.volume }} USDT</span></p>
        <p v-else><span class="order-available-label">{{ $t('可卖') }}</span><span class="order-available-value ml-8">{{ initClose.volume }} {{ strToArr(symbolName.toLocaleUpperCase(), '/')[0] }}</span></p>
      </div>
      <van-icon name="add-o" @click="$router.push('/cryptos/exchangePage')" class="font-30 add-icon" />
      <!-- <img @click="$router.push('/exchange/exchangePage')" src="@/assets/image/public/switch.png" class="w-24 h-24" /> -->
      <div class="order-add-btn" @click="$router.push('/cryptos/exchangePage')">
        <van-icon name="add-o" class="font-30" />
      </div>
    </div>
    <div style="border-radius: 3.5rem;"
      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()">
    <!-- 买入/卖出 主按钮 -->
    <div class="order-submit-btn w-full h-68 lh-90 flex justify-center items-center text-white text-center font-28 mt-10"
      :class="currentType === 'open' ? 'order-submit-btn--buy' : 'order-submit-btn--sell'" @click="order()">
      {{ currentType == 'open' ? $t('买入') : $t('卖出') }}
    </div>
    <!-- </template> -->
  </div>
</template>
@@ -206,19 +193,29 @@
        return
      }
      this.percentageVal = val
      const isFull = (val === 100)
      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
          this.form.volume = isFull ? sum : (Math.floor(sum * 100000) / 100000)
        } else {
          let sum = parseFloat(this.initClose.volume)
          this.form.volume = (Math.floor(sum * (val / 100) * 100000)) / 100000
          let sum = parseFloat(this.initClose.volume) * (val / 100)
          if (isFull) {
            this.form.volume = this.initClose.volume != null ? String(this.initClose.volume) : sum
          } else {
            this.form.volume = Math.floor(sum * 100000) / 100000
          }
        }
      } else {
        if (this.currentType == 'open') {
          this.form.total = this.initOpen.volume * (val / 100)
          if (isFull) {
            this.form.total = this.initOpen.volume != null ? String(this.initOpen.volume) : (this.initOpen.volume * (val / 100))
          } else {
            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
          const total = this.initClose.volume * (val / 100) * parseFloat(this.form.price)
          this.form.total = isFull ? total : (Math.floor(total * 1000) / 1000)
        }
      }
    },
@@ -315,11 +312,12 @@
          showFailToast(this.$t('请输入总额'))
          return
        }
        const noDecimalLimit = (this.percentageVal === 100)
        if (this.currentType === 'open') {
          this.form.volume = parseFloat(this.form.total).toFixed(5)
          this.form.volume = noDecimalLimit ? parseFloat(this.form.total) : 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)
          this.form.volume = parseFloat(this.form.total) / parseFloat(this.form.price)
          this.form.volume = noDecimalLimit ? this.form.volume : this.form.volume.toFixed(5)
        }
        volume = this.form.volume
      } else {
@@ -373,22 +371,145 @@
<style lang="scss">
@import "@/assets/init.scss";
.area_tabs {
  border-radius: 2.5rem;
/* 一比一还原图片样式:白底容器 + 绿/红标签 + 浅灰输入框 + 蓝字百分比 + 绿/红主按钮 */
$order-input-bg: #f5f5f5;
$order-input-border: #dcdcdc;
$order-text: #333333;
$order-unit: #666666;
$order-placeholder: #999999;
$order-buy: #38c172;
$order-sell: #f4374b;
$order-percent: #3b82f6;
$order-add-border: #8a2be2;
  .open,
  .close {
    border-radius: 2.5rem;
.order-area-wrap {
  background: #fff;
  border-radius: 12px;
  padding: 0 0 0 0;
  overflow: hidden;
}
.order-area_tabs {
  position: relative; /* 父相 */
  height: 66px;
  border-radius: 8px 8px 0 0;
  overflow: hidden;
  /* 子1:两个按钮的 div,flex 左右分布,中间留缝 */
  .order-tabs-buttons {
    display: flex;
    justify-content: space-between;
    align-items: stretch;
    width: 100%;
    height: 100%;
    position: relative;
    z-index: 0;
  }
  .open {
    background: #06CDA5;
  .order-tab {
    flex: 0 0 calc(50% );
    width: calc(50% );
    font-weight: 500;
    transition: background 0.2s, color 0.2s;
    cursor: pointer;
  }
  .close {
    background: #f43368;
  .order-tab--left {
    border-radius: 8px 0 0 0;
  }
  .order-tab--right {
    border-radius: 0 8px 0 0;
  }
  .order-tab--buy {
    background: $order-buy;
    color: #fff;
  }
  .order-tab-buy {
    background: #e8e8e8;
    color: #000;
  }
  .order-tab--sell {
    background: $order-sell;
    color: #fff;
  }
  .order-tab-sell {
    background: #e8e8e8;
    color: #000;
  }
  /* 子2:中间图片 div,父相子绝,居中在两按钮中间,直接显示 img */
  .order-tabs-bg {
    position: absolute;
    left: 49.3%;
    transform: translateX(-50%);
    width: 90px;
    height: 130%;
    top: -5px;
    bottom: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .order-tabs-bg-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }
}
.order-field {
  background: $order-input-bg;
  border: none;
  border-radius: 8px;
  color: $order-text;
  .order-field-inner { color: $order-text; }
  .order-field-label { color: $order-text; flex: 1; }
  .order-input { background: transparent !important; color: $order-text; font-size: 28px; }
  .order-unit { color: $order-unit; margin-left: 8px; font-size: 26px; }
  input::placeholder { color: $order-placeholder; }
}
.order-field--select .order-field-inner {
  min-height: 70px;
}
.order-percent-row {
  margin-bottom: 4px;
}
.order-percent-btn {
  flex: 1;
  text-align: center;
  padding: 2px 0;
  background: $order-input-bg;
  border: none;
  border-radius: 8px;
  color: $order-text;
  font-size: 24px;
  margin-right: 8px;
  &:last-child { margin-right: 0; }
}
.order-percent-btn--active {
  color: $order-text;
  font-weight: 500;
}
.order-available-label { color: $order-placeholder; }
.order-available-value { color: $order-unit; }
.order-add-btn {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  border: none;
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  color: $order-add-border;
}
.order-submit-btn {
  border-radius: 10px;
  font-weight: 700;
}
.order-submit-btn--buy { background: $order-buy; }
.order-submit-btn--sell { background: $order-sell; }
.bg-f3 {
  background: $border-grey;
@@ -497,41 +618,30 @@
  cursor: pointer;
}
.open {
  background-color: $green;
  background: url(@/assets/image/public/open-bg.png) no-repeat right center;
  background-size: 100% 100%;
  color: white;
}
/* .open / .close 已由 .order-tab--buy / .order-tab--sell 替代 */
.close {
  background-color: $green;
  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;
  top: 100%;
  margin-top: 4px;
  width: 100%;
  background-color: $grey_bg;
  background: #fff;
  border: none;
  border-radius: 8px;
  text-align: center;
  box-shadow: 0px 0px 3px 3px $grey_bg;
  border-radius: 4px;
  color: $text-color;
  color: $order-text;
  z-index: 10;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.option-box>div {
  padding: 30px 0;
.option-box > div {
  padding: 24px 0;
}
.option-box>div:hover {
  background-color: rgba($color: $bg_yellow, $alpha: 0.6);
.option-box > div:hover {
  background: $order-input-bg;
}
.num-text-color {
@@ -564,56 +674,32 @@
  opacity: 1;
}
.inputBackground {
  border-radius: 2.5rem;
  input {
    background: transparent !important;
  }
}
.tab-item {
  display: flex;
  align-items: center;
  justify-content: center;
  background: $input_background;
  border-radius: 2.5rem;
  margin-right: 10px !important;
  padding: 10px 0;
}
/* 输入框样式已统一到 .order-field */
.total-list {
  background: transparent;
  display: flex;
  color: $text_color3;
  color: $order-text;
  font-size: 26px;
  align-items: center;
  justify-content: center;
  margin-bottom: 20px !important;
  position: relative;
  gap: 8px;
  .total-div {
    flex: 1;
    text-align: center;
    padding: 20px 0 !important;
    padding: 8px 0 !important;
    background: $order-input-bg;
    border: none;
    border-radius: 8px;
    color: $order-unit;
  }
}
.active-bg {
  background: $input_background;
  border-radius: 2.5rem;
  color: $text_color;
}
.buyandSell {
  position: relative;
  z-index: 100;
}
.select-active {
  color: $text_color;
  background: #fff !important;
  border: none;
  color: $order-text !important;
  font-weight: 500;
}
</style>