From ef52095f5e9f0a9fe2da779bb1573947d77d75b6 Mon Sep 17 00:00:00 2001
From: jhzh <1628036192@qq.com>
Date: Fri, 22 May 2026 10:53:01 +0800
Subject: [PATCH] 1

---
 src/components/Transform/perpetual-position-list/index.vue |  626 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 520 insertions(+), 106 deletions(-)

diff --git a/src/components/Transform/perpetual-position-list/index.vue b/src/components/Transform/perpetual-position-list/index.vue
index 0207f3c..e494a52 100644
--- a/src/components/Transform/perpetual-position-list/index.vue
+++ b/src/components/Transform/perpetual-position-list/index.vue
@@ -1,130 +1,286 @@
 <template>
-  <!-- 持有仓位列表 -->
-  <div id="cryptos">
-    <!--        <div class="flex justify-between" v-if="listData.length">-->
-    <!--            <div class="flex" @click.stop="changeIcon">-->
-    <!--                <img v-show="!iconShow" src="../../assets/image/public/grey-rounded.png" alt="" class="w-38 h-38"/>-->
-    <!--                <img v-show="iconShow" src="../../assets/image/public/blue-rounded.png" alt="" class="w-38 h-38"/>-->
-    <!--                <div class="ml-37xw">{{ $t('隐藏其它合约') }}</div>-->
-    <!--            </div>-->
-    <!--            <button class="border-none all-cancel-btn pl-34 pr-34 pt-10 pb-10 font-25" @click="onSellAll">{{ $t('一键平仓') }}</button>-->
-    <!--        </div>-->
-    <div class="border-b-color" v-for="item in listData" :key="item.order_no">
-      <div class="flex justify-between pt-44 pb-44">
-        <div class="flex flex-col">
-          <div class="flex items-center">
-            <div class="pl-18 pr-18 pt-3 pb-3 text-white open-btn font-28"
-              :class="item.direction == 'buy' ? ' bg-green' : 'bg-red'">
-              {{ item.direction == 'buy' ? $t('开多') : $t('开空') }}
-            </div>
-            <div class="ml-22 font-31 font-600 ">
-              <span class="textColor">{{ item.name }} {{ $t('永续') }}</span>
-              <span class="text-grey font-28 font-400 ml-17 mr-17">
-                {{ item.locationType == 1 ? $t('全仓') : $t('逐仓') }}
-                {{ item.lever_rate }}x</span>
-            </div>
-            <img v-if="item.direction == 'buy'" src="@/assets/image/public/green-leverage.png" alt=""
-              class="w-32 h-32" />
-            <img v-else src="@/assets/image/public/red-leverage.png" alt="" class="w-32 h-32" />
+  <!-- 持有仓位列表:参考图样式 border-b-color 细浅灰、右上分享、保证金加号弹框 -->
+  <div >
+    <div class="position-card border-b-color" v-for="item in listData" :key="item.order_no">
+      <!-- 顶部:Buy/Sell 标签 + 交易对 Cross 100X + 刷新 + 分享 -->
+      <div class="flex justify-between items-center pt-44 pb-24">
+        <div class="flex items-center">
+          <div class="position-tag font-28" :class="item.direction == 'buy' ? 'bg-green' : 'bg-red'">
+            {{ item.direction == 'buy' ? $t('买入') : $t('卖出') }}
+          </div>
+          <div class="ml-22 font-31 font-600 textColor">
+            <span>{{ item.name }}</span>
+            <span class="text-grey font-28 font-400 ml-17">
+              {{ item.locationType == 1 ? 'Cross' : 'Part' }} {{ item.lever_rate }}X</span>
+          </div>
+        </div>
+        <div class="flex items-center" style="gap: 12px;">
+          <van-icon name="replay" class="position-icon text-grey" size="20" />
+          <van-icon name="share-o" class="position-icon text-grey" size="20" @click.stop="openShare(item)" />
+        </div>
+      </div>
+      <!-- PnL -->
+      <div class="flex justify-between font-28 pb-24">
+        <div>
+          <div class="text-grey">{{ $t('PnL(USDT)') || 'PnL(USDT)' }}</div>
+          <div class="mt-12" :class="item.profit > 0 ? 'text-green' : 'text-red'">
+            {{ item.profit > 0 ? '+' : '' }}{{ (item.profit != null ? item.profit : 0).toFixed(4) }}
+            <span class="ml-8">[{{ item.change_ratio != null ? item.change_ratio : 0 }}%]</span>
           </div>
         </div>
       </div>
-      <div class="flex justify-between font-28">
+      <!-- Size / Margin(USDT)+加号 / Margin Ratio -->
+      <div class="flex font-28 pb-20">
         <div class="flex-1">
-          <div class="text-grey">{{ routeType == 'cryptos' ? $t('未实现盈亏(USDT)') : $t('未实现盈亏(USD)') }}</div>
-          <div class="mt-20" :class="item.profit > 0 ? 'text-green' : 'text-red'">
-            {{ item.profit > 0 ? '+' + item.profit.toFixed(4) : item.profit.toFixed(4) }}</div>
+          <div class="text-grey">{{ $t('Size') || 'Size' }}</div>
+          <div class="mt-12 textColor">{{ item.volume != null ? item.volume : (item.deposit != null ? item.deposit : '-') }}</div>
         </div>
-        <div class="flex-1">
-          <div class="text-grey text-center">ROE</div>
-          <div class="mt-20 text-center" :class="item.change_ratio / 1 > 0 ? 'text-green' : 'text-red'">{{
-            item.change_ratio
-          }}%
+        <div class="flex-1 flex items-center justify-center">
+          <div>
+            <div class="text-grey">{{ $t('margin') }}(USDT)</div>
+            <div class="mt-12 flex items-center justify-center">
+              <span class="textColor">{{ item.deposit }}</span>
+              <span class="position-plus ml-8" @click.stop="openQuickAdd(item)" v-if="item.locationType == 0">+</span>
+            </div>
           </div>
         </div>
-        <div class="flex-1 flex justify-end">
-          <button class="font-30 detail-btn border-light-blue greyBg colorMain w-125 h-60" @click="goDetail(item)">{{
-            $t('详情') }}</button>
+        <div class="flex-1 text-right">
+          <div class="text-grey">{{ $t('Margin Ratio') || 'Margin Ratio' }}</div>
+          <div class="mt-12 textColor">{{ item.margin_ratio != null ? item.margin_ratio + '%' : '-' }}</div>
         </div>
       </div>
-      <div class="flex pt-44 pb-32 font-28">
+      <!-- Entry Price / Mark Price / Liq. Price -->
+      <div class="flex font-28 pb-24">
         <div class="flex-1">
-          <div class="text-grey">{{ $t('持仓数量') }}</div>
-          <div class="mt-20 textColor">{{ reserve(item.volume / (item.lever_rate ? item.lever_rate : 1),4) }}*{{
-            item.lever_rate ? item.lever_rate : 1 }}x</div>
+          <div class="text-grey">{{ $t('Entry Price') || 'Entry Price' }}</div>
+          <div class="mt-12 textColor">{{ item.trade_avg_price }}</div>
         </div>
-        <div class="flex-1 text-center  font-28">
-          <div class="text-grey">{{ $t('交易金额') }} ( {{ routeType == 'cryptos' ? 'USDT' : 'USD' }})</div>
-          <div class="mt-20 textColor">{{ item.deposit }}</div>
+        <div class="flex-1 text-center">
+          <div class="text-grey">{{ $t('Mark Price') || 'Mark Price' }}</div>
+          <div class="mt-12 textColor">{{ item.mark_price }}</div>
         </div>
-        <div class="flex-1 flex flex-col items-end  font-28">
-          <div class="text-grey">{{ $t('开仓价格') }}</div>
-          <div class="mt-20 textColor">{{ item.trade_avg_price }}</div>
+        <div class="flex-1 text-right">
+          <div class="text-grey">{{ $t('Liq. Price') || 'Liq. Price' }}</div>
+          <div class="mt-12 textColor">{{ item.force_close_rice || '-' }}</div>
         </div>
       </div>
-      <div class="flex pb-32  font-28">
-        <div class="flex-1">
-          <div class="text-grey">{{ $t('标记价格') }}</div>
-          <div class="mt-20 textColor">{{ item.mark_price }}</div>
-        </div>
-        <div class="flex-1">
-          <div class="text-grey text-center">{{ $t('强平价格') }}</div>
-          <div class="mt-20 textColor text-center">{{ item.force_close_rice }}</div>
-        </div>
-        <div class="flex-1 flex flex-col items-end justify-end">
-          <button class="greyBg textColor border-none pl-34 pr-34 pt-10 pb-10 rounded-ban"
-            @click="onSell(item.order_no)">
-            {{ $t('平仓') }}</button>
+      <!-- 细浅灰分隔线 + 底部时间与 TP/SL、Close -->
+      <div class="position-card-border"></div>
+      <div class="flex justify-between items-center pt-24 pb-32 font-24">
+        <span class="text-grey">{{ formatTime(item.create_time) }}</span>
+        <div class="flex" style="gap: 12px;">
+          <button class="position-bottom-btn" @click.stop="onSell(item.order_no)">{{ $t('平仓') }}</button>
+          <button class="position-bottom-btn" @click.stop="goTpSl(item)">{{ $t('TP/SL') || 'TP/SL' }}</button>
         </div>
       </div>
-      <!-- <div class="flex  pb-32  font-28">
-        <div class="flex-1 flex flex-col items-center justify-end">
-          <button class="font-30 detail-btn border-light-blue greyBg colorMain w-125 h-60" @click="goDetail(item)">{{
-            $t('详情') }}</button>
-        </div>
-      </div> -->
     </div>
     <div class="text-grey text-center py-300 font-30" v-if="!listData.length">{{ $t('您目前没有持仓') }}</div>
+
+    <!-- Quick addition 弹框 图三样式 -->
+    <van-popup v-model:show="showQuickAdd" position="bottom" round class="quick-add-popup">
+      <div class="quick-add-wrap">
+        <div class="quick-add-header">
+          <span class="quick-add-title">{{ $t('Quick addition') }}</span>
+          <span class="quick-add-close" @click="showQuickAdd = false">×</span>
+        </div>
+        <div class="quick-add-row">
+          <label class="quick-add-label">{{ $t('Quantity') || 'Quantity' }}:</label>
+          <input v-model.number="quickAddAmount" type="number" class="quick-add-input" />
+          <span class="quick-add-unit">USDT</span>
+        </div>
+        <div class="quick-add-slider-wrap">
+          <van-slider v-model="quickAddPercent" :min="0" :max="100" bar-height="4px" active-color="#7c3aed" />
+          <span class="quick-add-percent">{{ quickAddPercent }}%</span>
+        </div>
+        <div class="quick-add-balance">{{ $t('Futures asset balance') }}: {{ quickAddBalance }} USDT</div>
+        <div class="quick-add-submit" @click="submitQuickAdd">{{ $t('Submit') }}</div>
+      </div>
+    </van-popup>
+
+    <!-- TP/SL 止盈止损弹框:底部弹出,展示仓位信息 + 止盈/止损值 + Submit -->
+    <van-popup v-model:show="showTpSl" position="bottom" round class="tpsl-popup">
+      <div class="tpsl-wrap">
+        <div class="tpsl-header">
+          <h2 class="tpsl-title">{{ tpSlItem.name || 'BTC USDT' }} {{ tpSlItem.direction == 'buy' ? $t('Long') : $t('Short') }} {{ tpSlItem.lever_rate }}X {{ $t('Take Profit') }} {{ $t('Stop Loss') }}</h2>
+          <span class="tpsl-close" @click="showTpSl = false">×</span>
+        </div>
+        <div class="tpsl-info-grid">
+          <div class="tpsl-info-item">
+            <div class="tpsl-info-label">{{ $t('Entry Price') }}</div>
+            <div class="tpsl-info-value">{{ tpSlItem.trade_avg_price || '-' }}</div>
+          </div>
+          <div class="tpsl-info-item">
+            <div class="tpsl-info-label">{{ $t('Mark Price') }}</div>
+            <div class="tpsl-info-value">{{ tpSlItem.mark_price || '-' }}</div>
+          </div>
+          <div class="tpsl-info-item">
+            <div class="tpsl-info-label">{{ $t('Margin(USDT)') }}</div>
+            <div class="tpsl-info-value">{{ tpSlItem.deposit || '-' }}</div>
+          </div>
+          <div class="tpsl-info-item">
+            <div class="tpsl-info-label">{{ $t('Liq. Price') }}</div>
+            <div class="tpsl-info-value tpsl-liq">{{ tpSlItem.force_close_rice || '-' }}</div>
+          </div>
+        </div>
+        <div class="tpsl-row">
+          <label class="tpsl-row-label">{{ $t('Take Profit') }}</label>
+          <input v-model="tpSlTakeProfit" type="number" class="tpsl-input" :placeholder="$t('Please enter') || 'Please enter'" />
+        </div>
+        <div class="tpsl-row">
+          <label class="tpsl-row-label">{{ $t('Stop Loss') }}</label>
+          <input v-model="tpSlStopLoss" type="number" class="tpsl-input" :placeholder="$t('Please enter') || 'Please enter'" />
+        </div>
+        <div class="tpsl-submit" @click="submitTpSl">{{ $t('Submit') }}</div>
+      </div>
+    </van-popup>
+
+    <!-- 分享弹框:按参考图样式,背景 share-order.jpg,居中圆角卡片 -->
+    <van-popup v-model:show="showShare" position="bottom" round class="share-popup-wrap" :style="{ height: '100%', backgroundColor: 'transparent' }" @click.self="showShare = false">
+      <div class="share-mask" :style="{ backgroundColor: 'transparent' }" @click="showShare = false"></div>
+      <div class="share-popup-body">
+        <div ref="shareCardRef" class="share-card" :style="shareCardBgStyle" @click.stop>
+          <div class="share-card-close" @click="showShare = false">×</div>
+          <div class="share-card-top" :style="{ marginTop: '20%' }">
+            <div class="share-card-pair">{{ shareItem.name || 'BTC USDT' }}</div>
+            <div class="share-card-pos">{{ shareItem.direction == 'buy' ? $t('Long') : $t('Short') }} / {{ shareItem.lever_rate }}X</div>
+          </div>
+          <div class="share-card-pnl" :class="(shareItem.profit != null && shareItem.profit >= 0) ? 'share-pnl-green' : 'share-pnl-red'">{{ shareItem.change_ratio != null ? shareItem.change_ratio : 0 }}%</div>
+          <div class="share-card-entry" :style="{ marginTop: '60px' }">{{ $t('Entry Price') }}: {{ shareItem.trade_avg_price || '-' }}</div>
+          <div class="share-card-pnl-usdt">{{ $t('PnL(USDT)') }}: {{ shareItem.profit != null ? shareItem.profit.toFixed(4) : '-' }}</div>
+          <div class="share-card-ref-row">
+            <div class="share-card-ref-left">
+              <div class="share-card-ref">{{ $t('Referral Code') }}</div>
+              <div class="share-card-code">{{ userInfo.usercode || '91872511' }}</div>
+            </div>
+            <div class="share-card-qr"><canvas ref="shareQrRef" width="160" height="160"></canvas></div>
+          </div>
+          <button type="button" class="share-card-copy" @click="copyShareLink">{{ $t('复制链接') }}</button>
+          <!-- <div class="share-card-save-link" @click="saveShareImage">{{ $t('保存图片') }}</div> -->
+        </div>
+      </div>
+    </van-popup>
   </div>
 </template>
 
 <script>
-import { _orderSellBatch, _contractOrderClose } from "@/service/trade.api";
+import { _orderSellBatch, _contractOrderClose, _addDepositOpen, _setStopPrice } from "@/service/trade.api";
 import { showConfirmDialog, showToast } from 'vant';
 import { reserve } from "@/utils/utis";
-//import { i18n } from "@/i18n";
+import { mapGetters } from 'vuex';
+import QRCode from 'qrcode';
+import html2canvas from 'html2canvas';
+import shareOrderBg from '@/assets/imgs/new/share-order.jpg';
+
 export default {
   name: "perpetualPositionList",
   data() {
     return {
       iconShow: false,
-      routeType: 'cryptos'
+      routeType: 'cryptos',
+      showQuickAdd: false,
+      quickAddAmount: 0,
+      quickAddPercent: 0,
+      quickAddBalance: '0',
+      _skipQuickAddSync: false,
+      quickAddItem: null,
+      showShare: false,
+      shareItem: {},
+      showTpSl: false,
+      tpSlItem: {},
+      tpSlTakeProfit: '',
+      tpSlStopLoss: ''
     }
   },
   props: {
-    type: {
-      type: String,
-      default: '2' // 2 永续合约历史持仓,3交割合约持仓
+    type: { type: String, default: '2' },
+    listData: { type: Array, default: () => [] },
+    futuresBalance: { type: [String, Number], default: '0' }
+  },
+  computed: {
+    ...mapGetters('user', ['userInfo']),
+    quickAddBalanceNum() {
+      return Math.max(0, parseFloat(this.quickAddBalance) || 0);
     },
-    listData: {
-      type: Array,
-      default() {
-        return []
-      }
+    shareCardBgStyle() {
+      return {
+        backgroundImage: `url(${shareOrderBg})`,
+        backgroundSize: 'cover',
+        backgroundRepeat: 'no-repeat',
+        backgroundPosition: 'center'
+      };
     }
   },
   mounted() {
-    this.routeType = this.$route.query.type
+    this.routeType = this.$route.query.type || 'cryptos';
+  },
+  watch: {
+    showShare(val) {
+      if (val && this.shareItem && this.$refs.shareQrRef) {
+        this.$nextTick(() => this.drawShareQr());
+      }
+    },
+    quickAddPercent(val) {
+      if (this._skipQuickAddSync) return;
+      this._skipQuickAddSync = true;
+      const num = this.quickAddBalanceNum;
+      const amount = num <= 0 ? 0 : Math.min(num, (num * val) / 100);
+      this.quickAddAmount = Math.round(amount * 100) / 100;
+      this.$nextTick(() => { this._skipQuickAddSync = false; });
+    },
+    quickAddAmount(val) {
+      if (this._skipQuickAddSync) return;
+      const num = this.quickAddBalanceNum;
+      if (num <= 0) {
+        this._skipQuickAddSync = true;
+        this.quickAddPercent = 0;
+        this.$nextTick(() => { this._skipQuickAddSync = false; });
+        return;
+      }
+      this._skipQuickAddSync = true;
+      const pct = Math.min(100, Math.max(0, (Number(val) || 0) / num * 100));
+      this.quickAddPercent = Math.round(pct * 100) / 100;
+      this.$nextTick(() => { this._skipQuickAddSync = false; });
+    }
   },
   methods: {
     reserve,
-    changeIcon() {
-      this.iconShow = !this.iconShow;
+    formatTime(t) {
+      if (!t) return '-';
+      const d = new Date(typeof t === 'number' ? t * 1000 : t);
+      const pad = n => (n + '').padStart(2, '0');
+      return `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
     },
     goDetail(item) {
       this.$router.push({ path: "/cryptos/orderDetail", query: { order_no: item.order_no } });
     },
-    onSell(order_no) { // 平仓单个
+    goTpSl(item) {
+      this.tpSlItem = { ...item };
+      this.tpSlTakeProfit = item.take_profit_price != null ? String(item.take_profit_price) : (item.profit_price != null ? String(item.profit_price) : '');
+      this.tpSlStopLoss = item.stop_loss_price != null ? String(item.stop_loss_price) : (item.loss_price != null ? String(item.loss_price) : '');
+      this.showTpSl = true;
+    },
+    submitTpSl() {
+      if (!this.tpSlItem || !this.tpSlItem.order_no) {
+        showToast(this.$t('请选择仓位'));
+        return;
+      }
+      const stopPriceProfit = String(this.tpSlTakeProfit || '').trim();
+      const stopPriceLoss = String(this.tpSlStopLoss || '').trim();
+      if (!stopPriceProfit && !stopPriceLoss) {
+        showToast(this.$t('请输入止盈或止损价格'));
+        return;
+      }
+      _setStopPrice({
+        orderNo: this.tpSlItem.order_no,
+        stopPriceProfit: stopPriceProfit || undefined,
+        stopPriceLoss: stopPriceLoss || undefined
+      }).then(() => {
+        showToast(this.$t('提交成功'));
+        this.showTpSl = false;
+        this.$emit('sell');
+      }).catch(() => {});
+    },
+    onSell(order_no) {
       showConfirmDialog({
         confirmButtonText: this.$t('确定'),
         cancelButtonText: this.$t('取消'),
@@ -132,16 +288,63 @@
         message: this.$t('是否平仓?'),
       }).then(() => {
         _contractOrderClose({ order_no }).then(() => {
-          showToast(this.$t('平仓成功'))
-          this.$emit('sell', order_no)
-        })
-      }).catch(() => { });
+          showToast(this.$t('平仓成功'));
+          this.$emit('sell', order_no);
+        });
+      }).catch(() => {});
     },
-    onSellAll() { // 平仓全部
-      _orderSellBatch().then(() => {
-        this.showToast(this.$t('平仓成功'))
-        this.$emit('sell')
-      })
+    openQuickAdd(item) {
+      this.quickAddItem = item;
+      this.quickAddBalance = (this.userInfo && this.userInfo.balance) || '0';
+      this.quickAddAmount = 0;
+      this.quickAddPercent = 0;
+      this.showQuickAdd = true;
+    },
+    submitQuickAdd() {
+      if (!this.quickAddItem || !this.quickAddItem.order_no) {
+        showToast(this.$t('请选择仓位'));
+        return;
+      }
+      const amount = Number(this.quickAddAmount);
+      if (isNaN(amount) || amount <= 0) {
+        showToast(this.$t('请输入有效追加金额'));
+        return;
+      }
+      _addDepositOpen({
+        orderNo: this.quickAddItem.order_no,
+        addDepositOpen: amount
+      }).then(() => {
+        showToast(this.$t('提交成功'));
+        this.showQuickAdd = false;
+        this.$emit('sell'); // 刷新持仓列表
+      }).catch(() => {});
+    },
+    openShare(item) {
+      this.shareItem = { ...item };
+      this.showShare = true;
+    },
+    drawShareQr() {
+      const url = (this.userInfo && this.userInfo.url) || window.location.origin + '/#/register?code=' + (this.userInfo && this.userInfo.usercode);
+      const canvas = this.$refs.shareQrRef;
+      if (canvas) QRCode.toCanvas(canvas, url, { width: 160, margin: 2 });
+    },
+    copyShareLink() {
+      const url = (this.userInfo && this.userInfo.url) || window.location.origin + '/#/register?code=' + (this.userInfo && this.userInfo.usercode);
+      navigator.clipboard.writeText(url).then(() => showToast(this.$t('复制成功')));
+    },
+    async saveShareImage() {
+      const el = this.$refs.shareCardRef;
+      if (!el) return;
+      try {
+        const canvas = await html2canvas(el, { useCORS: true, backgroundColor: '#1e1e2e', scale: 2 });
+        const link = document.createElement('a');
+        link.download = 'share-position.png';
+        link.href = canvas.toDataURL('image/png');
+        link.click();
+        showToast(this.$t('保存成功'));
+      } catch (e) {
+        showToast(this.$t('保存失败'));
+      }
     }
   }
 }
@@ -149,20 +352,231 @@
 <style lang="scss" scoped>
 @import "@/assets/init.scss";
 
+/* 与参考图一致:细浅灰分隔线 */
+.border-b-color {
+  border-bottom: 1px solid #e8e8e8;
+}
+.position-card-border {
+  border-bottom: 1px solid #e8e8e8;
+  margin: 0 -20px;
+}
+.position-tag {
+  padding: 4px 12px;
+  border-radius: 6px;
+  color: #fff;
+  font-weight: 600;
+}
+.bg-green { background: #0ecb81; }
+.bg-red { background: #f6465d; }
+.position-icon { cursor: pointer; }
+.position-plus {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  background: linear-gradient(135deg, #7c3aed, #5b21b6);
+  color: #fff;
+  font-size: 18px;
+  line-height: 1;
+  cursor: pointer;
+}
+.position-bottom-btn {
+  padding: 8px 20px;
+  font-size: 24px;
+  color: #333;
+  background: #fff;
+  border: 1px solid #e8e8e8;
+  border-radius: 8px;
+  cursor: pointer;
+}
+
+/* Quick addition 弹框 图三样式(字体放大1倍,上下左右边距加一倍) */
+.quick-add-popup.van-popup { background: #fff; border-radius: 16px 16px 0 0; }
+.quick-add-wrap { padding: 48px 40px 64px; }
+.quick-add-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 48px; }
+.quick-add-title { font-size: 36px; font-weight: 600; color: #1e1e1e; }
+.quick-add-close { font-size: 56px; color: #999; cursor: pointer; }
+.quick-add-row { display: flex; align-items: center; margin-bottom: 40px; }
+.quick-add-label { font-size: 28px; color: #333; margin-right: 24px; flex-shrink: 0; }
+.quick-add-input { flex: 1; height: 88px; border: 1px solid #e8e8e8; border-radius: 8px; padding: 0 24px; font-size: 28px; }
+.quick-add-unit { margin-left: 24px; font-size: 28px; color: #666; }
+.quick-add-slider-wrap { margin-bottom: 24px; position: relative; }
+.quick-add-slider-wrap .van-slider { margin: 0;width: 85%; }
+.quick-add-percent { position: absolute; right: 0; top: -8px; font-size: 24px; color: #999; }
+.quick-add-balance { font-size: 24px; color: #999; margin-bottom: 48px; }
+.quick-add-submit {
+  height: 96px; line-height: 96px; text-align: center; font-size: 32px; font-weight: 600; color: #fff;
+  background: linear-gradient(90deg, #7c3aed, #5b21b6); border-radius: 10px; cursor: pointer;
+}
+
+/* TP/SL 止盈止损弹框:白底、数据一排、输入框 F6F5FA */
+.tpsl-popup.van-popup { background: #fff; border-radius: 16px 16px 0 0; }
+.tpsl-wrap { padding: 48px 40px 64px; background: #fff; }
+.tpsl-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 40px; }
+.tpsl-title { font-size: 32px; font-weight: 600; color: #1e1e1e; line-height: 1.4; margin: 0; flex: 1; padding-right: 16px; }
+.tpsl-close { font-size: 56px; color: #999; cursor: pointer; flex-shrink: 0; }
+.tpsl-info-grid { display: flex; flex-wrap: nowrap; gap: 16px; margin-bottom: 40px; }
+.tpsl-info-item { flex: 1; min-width: 0; }
+.tpsl-info-label { font-size: 22px; color: #999; margin-bottom: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.tpsl-info-value { font-size: 24px; color: #333; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.tpsl-info-value.tpsl-liq { color: #7c3aed; }
+.tpsl-row { display: flex; align-items: center; margin-bottom: 32px; }
+.tpsl-row-label { font-size: 28px; color: #333; margin-right: 24px; flex-shrink: 0; width: 140px; }
+.tpsl-input { flex: 1; height: 88px; background: #F6F5FA; border: none; border-radius: 8px; padding: 0 24px; font-size: 28px; }
+.tpsl-submit {
+  height: 96px; line-height: 96px; text-align: center; font-size: 32px; font-weight: 600; color: #fff;
+  background: linear-gradient(90deg, #7c3aed, #5b21b6); border-radius: 10px; cursor: pointer; margin-top: 48px;
+}
+
+/* 分享弹框:弹层与内容区透明,自管遮罩半透明,背后露出页面 */
+.share-popup-wrap.van-popup { background: transparent !important; }
+.share-popup-wrap :deep(.van-popup__content) {
+  background: transparent !important;
+  min-height: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+/* 自管遮罩:铺满、半透明黑,点击关闭 */
+.share-mask {
+  position: absolute;
+  inset: 0;
+  background: rgba(0, 0, 0, 0.5);
+  z-index: 0;
+}
+.share-popup-body {
+  position: relative;
+  z-index: 1;
+  min-height: 100vh;
+  height: 100%;
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 40px 20px 60px;
+  box-sizing: border-box;
+  background: transparent !important;
+  pointer-events: none;
+}
+.share-popup-body .share-card { pointer-events: auto; }
+.share-popup-body .share-card {
+  max-width: 90vw;
+  width: 85%;
+  flex-shrink: 0;
+}
+/* 卡片:背景 share-order.jpg,宽高由外层控制,内部用相对单位响应 */
+.share-card {
+  position: relative;
+  width: 100%;
+  min-height: 40%;
+  padding: 5% 6% 5%;
+  border-radius: 16px;
+  overflow: hidden;
+  color: #fff;
+  display: flex;
+  flex-direction: column;
+  box-sizing: border-box;
+  font-size: clamp(12px, 2.2vw, 20px);
+}
+.share-card-close {
+  position: absolute;
+  top: 3%;
+  right: 3%;
+  width: 2.2em;
+  height: 2.2em;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 3em;
+  line-height: 1;
+  color: #fff;
+  cursor: pointer;
+  z-index: 2;
+}
+.share-card-top {
+  margin-bottom: 0.3em;
+}
+.share-card-pair {
+  font-size: 1.5em;
+  font-weight: 700;
+  color: #fff;
+  line-height: 1.3;
+}
+.share-card-pos {
+  font-size: 1.15em;
+  color: rgba(255,255,255,0.9);
+  margin-top: 0.2em;
+}
+.share-card-pnl {
+  font-size: 2.2em;
+  font-weight: 700;
+  margin: 0.5em 0 0.6em;
+  line-height: 1.2;
+}
+.share-pnl-green { color: #0ecb81; }
+.share-pnl-red { color: #f6465d; }
+.share-card-entry,
+.share-card-pnl-usdt {
+  font-size: 1.1em;
+  color: #fff;
+  margin-bottom: 0.25em;
+}
+.share-card-ref-row {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-top: 1em;
+  margin-bottom: 0.8em;
+  gap: 0.5em;
+}
+.share-card-ref-left { flex: 1; min-width: 0; }
+.share-card-ref {
+  font-size: 1em;
+  color: rgba(255,255,255,0.9);
+  margin-bottom: 0.2em;
+}
+.share-card-code {
+  font-size: 1.35em;
+  font-weight: 700;
+  color: #fff;
+}
+.share-card-qr {
+  width: 22%;
+  max-width: 110px;
+  aspect-ratio: 1;
+  flex-shrink: 0;
+  background: #fff;
+  padding: 4%;
+  border-radius: 8px;
+}
+.share-card-qr canvas { width: 100% !important; height: 100% !important; display: block; }
+.share-card-copy {
+  width: 100%;
+  height: 2.8em;
+  line-height: 2.8em;
+  text-align: center;
+  font-size: 1em;
+  font-weight: 600;
+  color: #fff;
+  background: linear-gradient(90deg, #7c3aed, #5b21b6);
+  border: none;
+  border-radius: 10px;
+  cursor: pointer;
+  z-index: 2;
+  margin-top: auto;
+}
+.share-card-save-link {
+  text-align: center;
+  font-size: 0.85em;
+  color: rgba(255,255,255,0.8);
+  margin-top: 0.6em;
+  cursor: pointer;
+  z-index: 2;
+}
+
 #cryptos {
-  .open-btn {
-    border-radius: 5px;
-  }
-
-  .detail-btn {
-    border: 1px solid;
-    border-radius: 2.5rem;
-    background: $US_tabActice_background;
-    color: $color_main;
-  }
-
-  .text-green {
-    color: #06AD95;
-  }
+  .text-green { color: #06AD95; }
 }
 </style>

--
Gitblit v1.9.3