Ver código fonte

订单时效-完成
全仓说明 -完成
全仓逐仓说明-完成
选择订单类形-完成
余额不足-完成
止盈止损提示-完成
平仓平空-完成
确认平仓-完成
平仓平多-完成

Hexinkui 1 mês atrás
pai
commit
0a0d20c1d4

+ 1 - 1
src/App.vue

@@ -1,5 +1,5 @@
 <template>
-  <router-view />
+  <router-view :key="$route.fullPath"/>
 </template>
 
 <style lang="less"></style>

Diferenças do arquivo suprimidas por serem muito extensas
+ 6 - 0
src/assets/icon/bitcoin/bt.svg


Diferenças do arquivo suprimidas por serem muito extensas
+ 111 - 0
src/assets/icon/bitcoin/querenpin.svg


+ 90 - 83
src/router/index.js

@@ -1,4 +1,4 @@
-import { createRouter, createWebHistory } from "vue-router";
+import {createRouter, createWebHistory} from "vue-router";
 import HomeIndex from "../views/HomeIndex.vue";
 import ApplyPermission from "../views/index/ApplyPermission.vue";
 import SplashScreen from "../views/index/SplashScreen.vue";
@@ -15,93 +15,100 @@ import IcoIndex from "../views/index/ico/Index.vue";
 import LoanIndex from "../views/index/loan/Index.vue";
 import LoanRules from "../views/index/loan/Rules.vue";
 import UserLoanIndex from "../views/user/loan/Index.vue";
+import FootprintIndex from "../views/bitcoin/Index.vue";
+
 
 const routes = [
-  {
-    path: "/",
-    name: "home",
-    component: HomeIndex,
-  },
-  {
-    path: "/applyPermission",
-    name: "applyPermission",
-    component: ApplyPermission,
-  },
-  {
-    path: "/splashScreen",
-    name: "splashScreen",
-    component: SplashScreen,
-  },
-  {
-    path: "/riskTips",
-    name: "riskTips",
-    component: RiskTips,
-  },
-  {
-    path: "/searchIcon",
-    name: "searchIcon",
-    component: SearchIcon,
-  },
-  {
-    path: "/notification",
-    name: "notification",
-    component: Notification,
-  },
-  {
-    path: "/indexUser",
-    name: "indexUser",
-    component: IndexUser,
-  },
-  {
-    path: "/userCenter",
-    name: "userCenter",
-    component: UserCenter,
-  },
-  {
-    path: "/marketDetails",
-    name: "marketDetails",
-    component: MarketDetails,
-  },
-  {
-    path: "/historyIndex",
-    name: "historyIndex",
-    component: HistoryIndex,
-  },
-  {
-    path: "/entrustDetails",
-    name: "entrustDetails",
-    component: EntrustDetails,
-  },
-  {
-    path: "/positionDetails",
-    name: "positionDetails",
-    component: PositionDetails,
-  },
-  {
-    path: "/icoIndex",
-    name: "icoIndex",
-    component: IcoIndex,
-  },
-  {
-    path: "/loanIndex",
-    name: "loanIndex",
-    component: LoanIndex,
-  },
-  {
-    path: "/loanRules",
-    name: "loanRules",
-    component: LoanRules,
-  },
-  {
-    path: "/userLoanIndex",
-    name: "userLoanIndex",
-    component: UserLoanIndex,
-  },
+    {
+        path: "/",
+        name: "home",
+        component: HomeIndex,
+    },
+    {
+        path: "/bitcoin",
+        name: "bitcoin",
+        component: FootprintIndex,
+    },
+    {
+        path: "/applyPermission",
+        name: "applyPermission",
+        component: ApplyPermission,
+    },
+    {
+        path: "/splashScreen",
+        name: "splashScreen",
+        component: SplashScreen,
+    },
+    {
+        path: "/riskTips",
+        name: "riskTips",
+        component: RiskTips,
+    },
+    {
+        path: "/searchIcon",
+        name: "searchIcon",
+        component: SearchIcon,
+    },
+    {
+        path: "/notification",
+        name: "notification",
+        component: Notification,
+    },
+    {
+        path: "/indexUser",
+        name: "indexUser",
+        component: IndexUser,
+    },
+    {
+        path: "/userCenter",
+        name: "userCenter",
+        component: UserCenter,
+    },
+    {
+        path: "/marketDetails",
+        name: "marketDetails",
+        component: MarketDetails,
+    },
+    {
+        path: "/historyIndex",
+        name: "historyIndex",
+        component: HistoryIndex,
+    },
+    {
+        path: "/entrustDetails",
+        name: "entrustDetails",
+        component: EntrustDetails,
+    },
+    {
+        path: "/positionDetails",
+        name: "positionDetails",
+        component: PositionDetails,
+    },
+    {
+        path: "/icoIndex",
+        name: "icoIndex",
+        component: IcoIndex,
+    },
+    {
+        path: "/loanIndex",
+        name: "loanIndex",
+        component: LoanIndex,
+    },
+    {
+        path: "/loanRules",
+        name: "loanRules",
+        component: LoanRules,
+    },
+    {
+        path: "/userLoanIndex",
+        name: "userLoanIndex",
+        component: UserLoanIndex,
+    },
 ];
 
 const router = createRouter({
-  history: createWebHistory(process.env.BASE_URL),
-  routes,
+    history: createWebHistory(process.env.BASE_URL),
+    routes,
 });
 
 export default router;

+ 705 - 537
src/views/bitcoin/Index.vue

@@ -7,13 +7,13 @@
         </div>
         <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('contract')">秒合约</div>
         <div
-          class="sys-notifi pf600 fs14 fcA8A8A8"
-          @click="messageChange('secondContract')">
+            class="sys-notifi pf600 fs14 fcA8A8A8"
+            @click="messageChange('secondContract')">
           期权
         </div>
         <div
-          class="sys-notifi pf600 fs14 fcA8A8A8"
-          @click="messageChange('secondContract')">
+            class="sys-notifi pf600 fs14 fcA8A8A8"
+            @click="messageChange('secondContract')">
           杠杆
         </div>
       </div>
@@ -21,14 +21,14 @@
     </div>
     <div class="menu">
       <div class="menu-left">
-      <img class="fc333333" src="../../assets/icon/bitcoin/menu.svg" alt="">
-      <div class="pf600 fs18 fc121212" >BTCUSDT 永续</div>
-    </div>
-    <div class="menu-right fc333333">
-      <img src="../../assets/icon/bitcoin/jisuan.svg" alt="">
-      <img src="../../assets/icon/bitcoin/hangqing.svg" alt="">
-      <img src="../../assets/icon/bitcoin/den.svg" alt="">
-    </div>
+        <img class="fc333333" src="../../assets/icon/bitcoin/menu.svg" alt="">
+        <div class="pf600 fs18 fc121212">BTCUSDT 永续</div>
+      </div>
+      <div class="menu-right fc333333">
+        <img src="../../assets/icon/bitcoin/jisuan.svg" alt="">
+        <img src="../../assets/icon/bitcoin/hangqing.svg" alt="">
+        <img src="../../assets/icon/bitcoin/den.svg" alt="">
+      </div>
     </div>
     <div class="menu-bottom">
       <div class="pf500 fs12 menu-leftb">
@@ -39,13 +39,13 @@
         <div>0.003%/1:57:32</div>
       </div>
     </div>
-    <div class="menu-content" >
-<!--      //左边-->
+    <div class="menu-content">
+      <!--      //左边-->
       <div class="menu-content-l">
         <div class="menu-content-lb pf400 fs14 fc666666">
           <span>价格</span><span>数量(USDT)</span>
         </div>
-        <div  class="menu-content-lb1">
+        <div class="menu-content-lb1">
           <div class="menu-content-lb1l pf400 fs14 fcFF7171">
             <span class="">40,166.82</span>
             <span>40,166.82</span>
@@ -75,7 +75,7 @@
           <p class="pf600 fs16 fcDF384C">5,678.00</p>
           <p class="fs12 fcA8A8A8 pf400">1,678.00</p>
         </div>
-        <div  class="menu-content-lb1">
+        <div class="menu-content-lb1">
           <div class="menu-content-lb1l pf400 fs14 fcFF7171">
             <span class="">40,166.82</span>
             <span>40,166.82</span>
@@ -103,7 +103,7 @@
         </div>
         <div class="menu-content-lb1">
           <div class="menu-content-lb1l pf400 fs12 fc333333" @click="isPickerVisible = true">
-            <span class="fs12">{{displayLabel}}</span>
+            <span class="fs12">{{ displayLabel }}</span>
             <img src="../../assets/icon/bitcoin/shendul.svg" alt="">
 
           </div>
@@ -116,139 +116,130 @@
       </div>
       <assetlessStateData v-if="isassetlessState"></assetlessStateData>
       <SellTradingStatusData v-if="isassetlessState"></SellTradingStatusData>
-<!--      //右边-->
-      <div  class="menu-content-r">
+      <!--      //右边-->
+      <div class="menu-content-r">
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
+          <div class="menu-content-rb1 fs14 fc333333" @click="showInfo = true">
             <img src="../../assets/icon/bitcoin/quancang.svg" alt="">
-            <span>全仓</span>
-         </div>
-         <img src="../../assets/icon/bitcoin/quangcang1.svg" alt="">
+            <span>{{ selectedLabel1 }}</span>
+          </div>
+          <div @click="showModal1 = true" style="font-size: 12px; margin-right: 12px;">
+            <VanIcon :style="{ fontWeight: 'bold' }" :name="showModal1 ? 'arrow-up' : 'arrow-down'"/>
+          </div>
 
 
-      </div>
+        </div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
+          <div class="menu-content-rb1 fs14 fc333333">
             <img src="../../assets/icon/bitcoin/quancang.svg" alt="">
-            <span>市价</span>
-         </div>
-         <img src="../../assets/icon/bitcoin/quangcang1.svg" alt="">
-      </div>
+            <span>{{ selectedLabel2 }}</span>
+          </div>
+          <div @click="showModal2 = true" style="font-size: 12px; margin-right: 12px;">
+            <VanIcon :style="{ fontWeight: 'bold' }" :name="showModal2 ? 'arrow-up' : 'arrow-down'"/>
+          </div>
+
+        </div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
+          <div class="menu-content-rb1 fs14 fc333333">
             <span>125000</span>
-         </div>
+          </div>
           <span>最优价</span>
-      </div>
+        </div>
         <div class="menu-content-rb pf400 fs14 fc333333">≈25.2250 USDT</div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
+          <div class="menu-content-rb1 fs14 fc333333">
             <span class="menu-content-rb1s fc999999">数量</span>
-         </div>
-         <span>USDT</span>
-      </div>
+          </div>
+          <span>USDT</span>
+        </div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
-           <span class="menu-content-rb1s fc333333">可用</span>
-         </div>
-         <div class="menu-content-rb1">
+          <div class="menu-content-rb1 fs14 fc333333">
+            <span class="menu-content-rb1s fc333333">可用</span>
+          </div>
+          <div class="menu-content-rb1">
             <span>0</span>
             <span>USDT</span>
             <img class="fs16" src="../../assets/icon/bitcoin/qianbao1.svg" alt="">
-         </div>
+          </div>
 
-      </div>
+        </div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
-           <span class="menu-content-rb1s fc333333">倍数</span>
-         </div>
-         <div class="menu-content-rb1" @click="showLeverageModal = true">
+          <div class="menu-content-rb1 fs14 fc333333">
+            <span class="menu-content-rb1s fc333333">倍数</span>
+          </div>
+          <div class="menu-content-rb1" @click="showLeverageModal = true">
             <span></span>
             <span>{{ selectedLeverage }}X</span>
             <span>更多</span>
-         </div>
-
-      </div>
+          </div>
+        </div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
-<!--           <label class="custom-checkbox-container">-->
-<!--            <input type="checkbox" checked="checked">-->
-<!--            <span class="checkmark"></span>-->
-<!--            </label>-->
-           <van-checkbox
-              v-model="isEnabled"
-              shape="square"
-              checked-color="#DC4653"
-              icon-size="16px"
-           >
-           </van-checkbox>
-<!--           <input class="fs16" type="checkbox" id="bike" value="Bike">-->
-           <span class="menu-content-rb1s fc333333">只减仓</span>
-         </div>
-         <div class="menu-content-rb1" @click="showModal = true">
+          <div class="menu-content-rb1 fs14 fc333333">
+            <van-checkbox
+                v-model="isEnabled"
+                shape="square"
+                checked-color="#DC4653"
+                icon-size="16px"
+            >
+            </van-checkbox>
+            <span class="menu-content-rb1s fc333333">只减仓</span>
+          </div>
+          <div class="menu-content-rb1" @click="showModal = true">
             <span></span>
             <span>{{ currentType }}</span>
-            <img class="fs16" src="../../assets/icon/bitcoin/quangcang1.svg" alt="">
-         </div>
-
-      </div>
+            <div style="font-size: 12px;">
+              <VanIcon :style="{ fontWeight: 'bold' }" :name="showModal ? 'arrow-up' : 'arrow-down'"/>
+            </div>
+            <!--            <img class="fs16" src="../../assets/icon/bitcoin/quangcang1.svg" alt="">-->
+          </div>
+        </div>
         <TakeProfitsTopLoss v-show="!isEnabled"></TakeProfitsTopLoss>
 
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
-           <span class="menu-content-rb1s fc333333">可用</span>
-         </div>
-         <div class="menu-content-rb1">
+          <div class="menu-content-rb1 fs14 fc333333">
+            <span class="menu-content-rb1s fc333333">可用</span>
+          </div>
+          <div class="menu-content-rb1">
             <span>0</span>
             <span>USDT</span>
-
-         </div>
-
-      </div>
+          </div>
+        </div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
-           <span class="menu-content-rb1s fc333333">保证金</span>
-         </div>
-         <div class="menu-content-rb1">
+          <div class="menu-content-rb1 fs14 fc333333">
+            <span class="menu-content-rb1s fc333333">保证金</span>
+          </div>
+          <div class="menu-content-rb1">
             <span>0</span>
             <span>USDT</span>
-
-         </div>
-
-      </div>
-
+          </div>
+        </div>
         <div class="menu-content-rb pf400 fs14" @click="showConfirm = true">
           <div class="pf400 fs16 fcFFFFFF">买入(做多)</div>
-
         </div>
-
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
-           <span class="menu-content-rb1s fc333333">可用</span>
-         </div>
-         <div class="menu-content-rb1">
+          <div class="menu-content-rb1 fs14 fc333333">
+            <span class="menu-content-rb1s fc333333">可用</span>
+          </div>
+          <div class="menu-content-rb1">
             <span>0</span>
             <span>USDT</span>
-
-         </div>
-
-      </div>
+          </div>
+        </div>
         <div class="menu-content-rb pf400 fs14">
-         <div class="menu-content-rb1 fs14 fc333333">
-           <span class="menu-content-rb1s fc333333">保证金</span>
-         </div>
-         <div class="menu-content-rb1">
+          <div class="menu-content-rb1 fs14 fc333333">
+            <span class="menu-content-rb1s fc333333">保证金</span>
+          </div>
+          <div class="menu-content-rb1">
             <span>0</span>
             <span>USDT</span>
-
-         </div>
-
-      </div>
+          </div>
+        </div>
         <div class="menu-content-rb pf400 fs14">
           <div class="pf400 fs16 fcFFFFFF" @click="showConfirm = true">卖出(做空)</div>
         </div>
       </div>
     </div>
+    <!--    订单列表组件-->
     <sellOrder></sellOrder>
     <!--    //各种弹窗-->
     <div v-if="isassetlessState">
@@ -279,64 +270,153 @@
           v-model="currentType"
       ></OrderTimeSheet>
     </div>
+    <div>
+      <MarginInfoSheet
+          v-model:visible="showInfo"
+      ></MarginInfoSheet>
+    </div>
+    <div>
+      <FundingOptions
+          v-model:visible="showModal1"
+          :selected-id="currentId1"
+          @confirm="handleConfirm1">
+      </FundingOptions>
+    </div>
+
+    <div>
+      <OrderType
+          v-model:visible="showModal2"
+          :selected-id="currentId2"
+          @confirm="handleConfirm2"
+      ></OrderType>
+    </div>
+
+    <!--    <div>-->
+    <!--      <InsufficientBalance-->
+    <!--          v-model:visible="showRechargeModal"-->
+    <!--          @confirm="handleGoRecharge"-->
+    <!--      ></InsufficientBalance>-->
+    <!--    </div>-->
+
   </div>
 
 </template>
 <script setup>
-    import { Checkbox as VanCheckbox } from 'vant';
-    // import { Icon as VanIcon, } from 'vant';
-    import { defineAsyncComponent } from 'vue';
-    import { ref ,computed} from 'vue';
-    // 懒加载多个组件
-    const priceLimit = defineAsyncComponent(() => import("./components/priceLimit.vue"));
-    const assetlessState = defineAsyncComponent(() => import("./components/assetlessState.vue"));
-    const assetlessStateData = defineAsyncComponent(() => import("./components/assetlessStateData.vue"));
-    const sellOrder = defineAsyncComponent(() => import('./components/sellOrder.vue'));
-    const SellTradingStatusData = defineAsyncComponent(() => import('./components/SellTradingStatusData.vue'));
-    const TakeProfitsTopLoss = defineAsyncComponent(() => import('./components/TakeProfitsTopLoss.vue'));
-    const ChooseThisDepth = defineAsyncComponent(() => import('./components/ChooseThisDepth.vue'));
-    const LeveragePopup = defineAsyncComponent(() => import('./components/LeveragePopup.vue'));
-    const OrderConfirmPopup = defineAsyncComponent(() => import('./components/OrderConfirmPopup.vue'));
-    const OrderTimeSheet = defineAsyncComponent(() => import('./components/OrderTimeSheet.vue'));
-    //GTC弹框
-    // 控制弹窗显示
-    const showModal = ref(false);
-
-    // 选中的值,默认为 GTC
-    const currentType = ref('GTC');
-
-
-    // --- 深度弹窗 ---
-    const isPickerVisible = ref(false); // 控制弹窗开关
-    const currentDepth = ref('depth1'); // 当前选中的深度
-    const depthMap = {
-      'depth1': '深度1',
-      'depth2': '深度2',
-      'depth3': '深度3',
-    };
-    const displayLabel = computed(() => depthMap[currentDepth.value] || '请选择');
-
-    //控制止盈止损
-    const isEnabled = ref(false);
-
-    //控制倍数
-    // 控制弹窗显示
-    const showLeverageModal = ref(false);
-    // 存储当前选中的倍数,默认 100
-    const selectedLeverage = ref(100);
-    // 处理子组件回传的确认事件
-    const handleConfirm = (value) => {
-      console.log('用户选择了:', value);
-      selectedLeverage.value = value;
-      // 这里可以继续添加发送 API 请求的逻辑
-    };
-
-    //做多买入
-    const showConfirm = ref(false);
-    const onOrderConfirmed = () => {
-      console.log('订单已提交');
-      // 这里可以添加 Toast 提示
-    };
+        import {Checkbox as VanCheckbox, Icon as VanIcon} from 'vant';
+        import {computed, defineAsyncComponent, ref} from 'vue';
+        // 懒加载多个组件
+        const priceLimit = defineAsyncComponent(() => import("./components/priceLimit.vue"));
+        const assetlessState = defineAsyncComponent(() => import("./components/assetlessState.vue"));
+        const assetlessStateData = defineAsyncComponent(() => import("./components/assetlessStateData.vue"));
+        //订单列表组件
+        const sellOrder = defineAsyncComponent(() => import('./components/sellOrder.vue'));
+        const SellTradingStatusData = defineAsyncComponent(() => import('./components/SellTradingStatusData.vue'));
+        const TakeProfitsTopLoss = defineAsyncComponent(() => import('./components/TakeProfitsTopLoss.vue'));
+        const ChooseThisDepth = defineAsyncComponent(() => import('./components/ChooseThisDepth.vue'));
+        //控制倍数组件
+        const LeveragePopup = defineAsyncComponent(() => import('./components/LeveragePopup.vue'));
+        const OrderConfirmPopup = defineAsyncComponent(() => import('./components/OrderConfirmPopup.vue'));
+        const OrderTimeSheet = defineAsyncComponent(() => import('./components/OrderTimeSheet.vue'));
+        const MarginInfoSheet = defineAsyncComponent(() => import('./components/MarginInfoSheet.vue'));
+        const FundingOptions = defineAsyncComponent(() => import('./components/FundingOptions.vue'));
+        const OrderType = defineAsyncComponent(() => import('./components/OrderType.vue'));
+        // const InsufficientBalance = defineAsyncComponent(() => import('./StatusComponent/InsufficientBalance.vue'));
+
+
+        // //余额不足提示
+        //   // 控制弹窗显示的变量
+        // const showRechargeModal = ref(false);
+        //
+        //   // 处理点击“立即充币”后的逻辑
+        // const handleGoRecharge = () => {
+        //   // console.log('用户点击了立即充币,正在跳转充值页面...');
+        //   // 这里写你的跳转逻辑,例如: router.push('/recharge')
+        // };
+
+        //订单类型选项
+        const showModal2 = ref(false);
+
+        // 定义状态用于存储
+        const currentId2 = ref(1); // 默认选中第一个
+        const selectedLabel2 = ref('市价'); // 默认值
+        const selectedUnit2 = ref('%');      // 默认值
+
+        // 回调函数:子组件选中后触发
+        const handleConfirm2 = (item) => {
+          // console.log('子组件返回的对象:', item);
+
+          // 保存ID用于下次打开时回显高亮
+          currentId2.value = item.id;
+          // const a = item.label.slice(-2)
+
+          // 核心需求:在这里将值“拆开”为两个字符串
+          selectedLabel2.value = item.label.slice(0, 2); // 字符串1: "涨跌幅"
+          selectedUnit2.value = item.unit;   // 字符串2: "%"
+        };
+
+        //全仓逐仓选项
+        const showModal1 = ref(false);
+
+        // 定义状态用于存储
+        const currentId1 = ref(1); // 默认选中第一个
+        const selectedLabel1 = ref('全仓'); // 默认值
+        const selectedUnit1 = ref('%');      // 默认值
+
+        // 回调函数:子组件选中后触发
+        const handleConfirm1 = (item) => {
+          // console.log('子组件返回的对象:', item);
+
+          // 保存ID用于下次打开时回显高亮
+          currentId1.value = item.id;
+          // const a = item.label.slice(-2)
+
+          // 核心需求:在这里将值“拆开”为两个字符串
+          selectedLabel1.value = item.label.slice(0, 2); // 字符串1: "涨跌幅"
+          selectedUnit1.value = item.unit;   // 字符串2: "%"
+        };
+
+        //全仓逐仓说明
+        const showInfo = ref(false);
+
+        //GTC弹框
+        // 控制弹窗显示
+        const showModal = ref(false);
+
+        // 选中的值,默认为 GTC
+        const currentType = ref('GTC');
+
+
+        // --- 深度弹窗 ---
+        const isPickerVisible = ref(false); // 控制弹窗开关
+        const currentDepth = ref('depth1'); // 当前选中的深度
+        const depthMap = {
+          'depth1': '深度1',
+          'depth2': '深度2',
+          'depth3': '深度3',
+        };
+        const displayLabel = computed(() => depthMap[currentDepth.value] || '请选择');
+
+        //控制止盈止损
+        const isEnabled = ref(false);
+
+        //控制倍数
+        // 控制弹窗显示
+        const showLeverageModal = ref(false);
+        // 存储当前选中的倍数,默认 100
+        const selectedLeverage = ref(100);
+        // 处理子组件回传的确认事件
+        const handleConfirm = (value) => {
+          // console.log('用户选择了:', value);
+          selectedLeverage.value = value;
+          // 这里可以继续添加发送 API 请求的逻辑
+        };
+
+        //做多买入
+        const showConfirm = ref(false);
+        const onOrderConfirmed = () => {
+          // console.log('订单已提交');
+          // 这里可以添加 Toast 提示
+        };
 
 
 </script>
@@ -345,463 +425,551 @@
 /* 容器基础样式,基于 375px 设计稿 */
 :deep(.van-checkbox__icon--square .van-icon) {
   /* 这里的 4px 是圆角大小,数值越大越圆 */
-  border-radius: 2px !important;}
-  .market {
+  border-radius: 2px !important;
+}
+
+.market {
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  align-items: center;
+  margin-bottom: 100px;
+  width: 100%;
+
+  .market-nav {
     display: flex;
-    flex-direction: column;
-    justify-content: flex-start;
+    flex-direction: row;
+    justify-content: space-between;
     align-items: center;
-    margin-bottom: 100px;
-    width: 100%;
+    margin-top: 21px;
+    width: 345px;
+    height: 24px;
 
-    .market-nav {
+    .nav-left {
       display: flex;
       flex-direction: row;
-      justify-content: space-between;
-      align-items: center;
-      margin-top: 21px;
-      width: 345px;
+      justify-content: flex-start;
+      align-items: flex-end;
+      width: 349px;
       height: 24px;
 
-      .nav-left {
-        display: flex;
-        flex-direction: row;
-        justify-content: flex-start;
-        align-items: flex-end;
-        width: 349px;
-        height: 24px;
-        div:nth-child(1){
-          position: relative;
-          .active-line{
-                position: absolute;
-                bottom: -6px;
-                left: 50%;
-                transform: translateX(-50%);
-                width: 20px;
-                height: 3px;
-                background-color: #323233;
-                border-radius: 2px;
-          }
-        }
-
-        .sys-notifi {
-          margin-left: 35px;
+      div:nth-child(1) {
+        position: relative;
+
+        .active-line {
+          position: absolute;
+          bottom: -6px;
+          left: 50%;
+          transform: translateX(-50%);
+          width: 20px;
+          height: 3px;
+          background-color: #323233;
+          border-radius: 2px;
         }
       }
 
-      .nav-right {
-        width: 20px;
-        height: 20px;
+      .sys-notifi {
+        margin-left: 35px;
       }
     }
-    .menu {
+
+    .nav-right {
+      width: 20px;
+      height: 20px;
+    }
+  }
+
+  .menu {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-top: 21px;
+    width: 345px;
+    height: 24px;
+
+    .menu-left {
       display: flex;
       flex-direction: row;
-      justify-content: space-between;
+      justify-content: flex-start;
       align-items: center;
-      margin-top: 21px;
-      width: 345px;
-      height: 24px;
+      line-height: 0px;
+
+      img {
+        margin: 0px 10px 0 0;
+      }
+    }
+
+    .menu-right {
+      img {
+        margin-left: 14px;
+      }
+    }
+  }
+
+  .menu-bottom {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-top: 8px;
+    width: 345px;
+
+    .menu-leftb {
+      width: 61px;
+      height: 25px;
+      background-color: #45b26b;
+      border-radius: 5px;
+      color: #ffffff;
+      text-align: center;
+      line-height: 25px;
+    }
 
-      .menu-left{
+    .menu-rightb {
+      text-align: right;
+    }
+  }
+
+  .menu-content {
+    width: 100%;
+    max-width: 345px;
+    display: flex;
+    flex-direction: row;
+    margin-top: 8px;
+
+    .menu-content-l {
+      flex: 1;
+
+      .menu-content-lb {
         display: flex;
         flex-direction: row;
-        justify-content: flex-start;
-        align-items: center;
-        line-height:0px;
-        img{
-          margin: 0px 10px 0 0;
-        }
+        justify-content: space-between;
+        padding-right: 14px;
       }
-      .menu-right{
-        img{
-          margin-left: 14px;
+
+      .menu-content-lb1 {
+        margin-top: 11px;
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        padding-right: 14px;
+
+        .menu-content-lb1l {
+          display: flex;
+          flex-direction: column;
+          line-height: 22px;
         }
-      }
-    }
 
-    .menu-bottom {
-       display: flex;
-      flex-direction: row;
-      justify-content: space-between;
-      align-items: center;
-      margin-top: 8px;
-      width: 345px;
-      .menu-leftb{
-        width:61px;
-        height: 25px;
-        background-color: #45b26b;
-        border-radius: 5px;
-        color: #ffffff;
-        text-align: center;
-        line-height: 25px;
+        .menu-content-lb1r {
+          display: flex;
+          flex-direction: column;
+          line-height: 22px;
+        }
       }
-      .menu-rightb{
-        text-align: right;
+
+      .menu-content-lb1:nth-child(4) {
+        .menu-content-lb1l {
+          color: #45b26b;
+        }
       }
-    }
 
-    .menu-content{
-      width: 100%;
-      max-width: 345px;
-      display: flex;
-      flex-direction: row;
-      margin-top: 8px;
-      .menu-content-l{
-        flex: 1;
-        .menu-content-lb{
+      .menu-content-lb1:nth-child(5) {
+        .menu-content-lb1l {
+          width: 100%;
           display: flex;
           flex-direction: row;
           justify-content: space-between;
-          padding-right: 14px;
+          align-items: center;
+          background-color: #f5f5f5;
+          border-radius: 6px;
+          height: 24px;
+          padding: 0 5px 0 13px;
+
+
+        }
+
+        .menu-content-lb1r {
+          margin-left: 15px;
         }
-        .menu-content-lb1{
-          margin-top: 11px;
+      }
+
+      .menu-content-lb2 {
+        margin-top: 8px;
+        line-height: 16px;
+        //span:nth-child(2){
+        //  //border-style: dashed;
+        //}
+      }
+    }
+
+    .menu-content-r {
+      flex: 1;
+      flex-basis: 63.5px;
+      max-width: 204.25px;
+
+      .menu-content-rb:nth-of-type(4) {
+        background-color: transparent;
+        height: 20px;
+
+      }
+
+      .menu-content-rb {
+        width: 100%;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        background-color: #f5f5f5;
+        border-radius: 6px;
+        margin-bottom: 8px;
+        height: 38px;
+
+        span {
+          padding-right: 12px;
+
+        }
+
+        img {
+          padding-right: 12px;
+          //height: 16px;
+          //width: 16px;
+        }
+
+        .menu-content-rb1 {
+          text-align: center;
+          margin-left: 12px;
           display: flex;
-          flex-direction: row;
-          justify-content: space-between;
-           padding-right: 14px;
-          .menu-content-lb1l{
-            display: flex;
-            flex-direction: column;
-            line-height: 22px;
-          }
-          .menu-content-lb1r{
-            display: flex;
-            flex-direction: column;
-            line-height: 22px;
+          align-content: center;
+          justify-content: center;
+          align-items: center;
+
+          img {
+            padding-right: 6px;
+
           }
+
         }
-        .menu-content-lb1:nth-child(4){
-          .menu-content-lb1l{
-            color: #45b26b;
-          }
+      }
+
+      .menu-content-rb:nth-of-type(6) {
+        background-color: transparent;
+        height: 20px;
+
+        .menu-content-rb1 {
+          margin-left: 0;
         }
-        .menu-content-lb1:nth-child(5){
-          .menu-content-lb1l{
-            width: 100%;
-            display: flex;
-            flex-direction: row;
-            justify-content: space-between;
-            align-items: center;
-            background-color: #f5f5f5;
-            border-radius: 6px;
-            height: 24px;
-            padding: 0 5px 0 13px;
 
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(1) {
 
+            font-size: 12px;
           }
-          .menu-content-lb1r{
-            margin-left: 15px;
+
+          span:nth-child(2) {
+            margin: 0 9px 0 9px;
+            font-size: 12px;
           }
         }
 
-        .menu-content-lb2{
-          margin-top: 8px;
-          line-height: 16px;
-          //span:nth-child(2){
-          //  //border-style: dashed;
-          //}
+        span {
+          padding-right: 0;
         }
-      }
-      .menu-content-r{
-        flex: 1;
-        flex-basis: 63.5px;
-        max-width: 204.25px;
-        .menu-content-rb:nth-of-type(4){
-           background-color: transparent;
-            height:20px;
-
-        }
-        .menu-content-rb {
-            width: 100%;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            background-color: #f5f5f5;
-            border-radius: 6px;
-            margin-bottom: 8px;
-            height: 38px;
-          span{
-              padding-right: 12px;
-
-            }
-          img{
-            padding-right: 12px;
-            //height: 16px;
-            //width: 16px;
-          }
 
-          .menu-content-rb1{
-            text-align: center;
-            margin-left: 12px;
-            //padding-right: 12px;
+        img {
+          padding-right: 0;
+        }
 
-            img{
-              padding-right: 6px;
+      }
 
-            }
+      .menu-content-rb:nth-of-type(7) {
+        background-color: transparent;
+        height: 20px;
 
+        .menu-content-rb1 {
+          margin-left: 0;
+        }
+
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(2) {
+            margin: 0 9px 0 9px;
+            font-size: 12px;
           }
+
+          span:nth-child(3) {
+            color: #df384c;
           }
-        .menu-content-rb:nth-of-type(6){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-              margin-left: 0;
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(1){
-
-               font-size: 12px;
-            }
-            span:nth-child(2){
-              margin:0 9px 0 9px;
-               font-size: 12px;
-            }
-          }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
-          }
+        }
+
+        span {
+          padding-right: 0;
+        }
 
+        img {
+          padding-right: 0;
         }
-        .menu-content-rb:nth-of-type(7){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-              margin-left: 0;
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(2){
-              margin:0 9px 0 9px;
-              font-size: 12px;
-            }
-            span:nth-child(3){
-              color: #df384c;
-            }
+
+      }
+
+      .menu-content-rb:nth-of-type(8) {
+        background-color: transparent;
+        height: 20px;
+
+        .menu-content-rb1 {
+          display: flex;
+          align-items: center;
+          height: 24px;
+          margin-left: 0;
+          align-content: center;
+
+          input {
+            width: 16px;
+            height: 16px;
+            margin-right: 5px;
           }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
+        }
+
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(2) {
+            margin: 0 9px 0 9px;
           }
+        }
+
+        .menu-content-rb1s {
+          margin-left: 6px;
+        }
+
+        span {
+          padding-right: 0;
+        }
 
+        img {
+          padding-right: 0;
         }
-        .menu-content-rb:nth-of-type(8){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-             display: flex;
-             align-items: center;
-             height: 24px;
-              margin-left: 0;
-             align-content: center;
-             input{
-                width:16px;
-               height: 16px;
-               margin-right: 5px;
-             }
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(2){
-              margin:0 9px 0 9px;
-            }
+
+      }
+
+      .menu-content-rb:nth-of-type(9) {
+        background-color: transparent;
+        height: 20px;
+
+        .menu-content-rb1 {
+          display: flex;
+          align-items: center;
+          height: 24px;
+          margin-left: 0;
+          align-content: center;
+
+          input {
+            width: 16px;
+            height: 16px;
+            margin-right: 5px;
           }
-          .menu-content-rb1s{
-            margin-left: 6px;
+
+          img {
+            padding-left: 5px;
+            font-size: 16px;
+            padding-top: 2px;
           }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
+        }
+
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(2) {
+            margin: 0 9px 0 9px;
           }
+        }
 
+        span {
+          padding-right: 0;
         }
-        .menu-content-rb:nth-of-type(9){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-             display: flex;
-             align-items: center;
-             height: 24px;
-              margin-left: 0;
-             align-content: center;
-             input{
-                width:16px;
-               height: 16px;
-               margin-right: 5px;
-             }
-             img{
-               padding-left: 5px;
-               font-size: 16px;
-               padding-top: 2px;
-             }
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(2){
-              margin:0 9px 0 9px;
-            }
-          }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
-          }
 
+        img {
+          padding-right: 0;
         }
-        .menu-content-rb:nth-of-type(10){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-             display: flex;
-             align-items: center;
-             height: 24px;
-              margin-left: 0;
-             align-content: center;
-             input{
-                width:16px;
-               height: 16px;
-               margin-right: 5px;
-             }
-             img{
-               padding-left: 5px;
-               font-size: 16px;
-               padding-top: 2px;
-             }
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(2){
-              margin:0 0px 0 5px;
-            }
+
+      }
+
+      .menu-content-rb:nth-of-type(10) {
+        background-color: transparent;
+        height: 20px;
+
+        .menu-content-rb1 {
+          display: flex;
+          align-items: center;
+          height: 24px;
+          margin-left: 0;
+          align-content: center;
+
+          input {
+            width: 16px;
+            height: 16px;
+            margin-right: 5px;
           }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
+
+          img {
+            padding-left: 5px;
+            font-size: 16px;
+            padding-top: 2px;
           }
+        }
 
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(2) {
+            margin: 0 0px 0 5px;
+          }
+        }
+
+        span {
+          padding-right: 0;
+        }
+
+        img {
+          padding-right: 0;
         }
-        .menu-content-rb:nth-of-type(11){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-             display: flex;
-             align-items: center;
-             height: 24px;
-              margin-left: 0;
-             align-content: center;
-             input{
-                width:16px;
-               height: 16px;
-               margin-right: 5px;
-             }
-             img{
-               padding-left: 5px;
-               font-size: 16px;
-               padding-top: 2px;
-             }
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(2){
-              margin:0 0px 0 5px;
-            }
+
+      }
+
+      .menu-content-rb:nth-of-type(11) {
+        background-color: transparent;
+        height: 20px;
+
+        .menu-content-rb1 {
+          display: flex;
+          align-items: center;
+          height: 24px;
+          margin-left: 0;
+          align-content: center;
+
+          input {
+            width: 16px;
+            height: 16px;
+            margin-right: 5px;
+          }
+
+          img {
+            padding-left: 5px;
+            font-size: 16px;
+            padding-top: 2px;
           }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
+        }
+
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(2) {
+            margin: 0 0px 0 5px;
           }
+        }
+
+        span {
+          padding-right: 0;
+        }
+
+        img {
+          padding-right: 0;
+        }
+
+      }
+
+      .menu-content-rb:nth-of-type(12) {
+        background-color: #45b26b;
 
+        div {
+          margin: auto;
         }
-        .menu-content-rb:nth-of-type(12){
-           background-color: #45b26b;
-           div{margin: auto;}
-
-        }
-        .menu-content-rb:nth-of-type(13){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-             display: flex;
-             align-items: center;
-             height: 24px;
-              margin-left: 0;
-             align-content: center;
-             input{
-                width:16px;
-               height: 16px;
-               margin-right: 5px;
-             }
-             img{
-               padding-left: 5px;
-               font-size: 16px;
-               padding-top: 2px;
-             }
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(2){
-              margin:0 0px 0 5px;
-            }
+
+      }
+
+      .menu-content-rb:nth-of-type(13) {
+        background-color: transparent;
+        height: 20px;
+
+        .menu-content-rb1 {
+          display: flex;
+          align-items: center;
+          height: 24px;
+          margin-left: 0;
+          align-content: center;
+
+          input {
+            width: 16px;
+            height: 16px;
+            margin-right: 5px;
+          }
+
+          img {
+            padding-left: 5px;
+            font-size: 16px;
+            padding-top: 2px;
           }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
+        }
+
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(2) {
+            margin: 0 0px 0 5px;
           }
+        }
+
+        span {
+          padding-right: 0;
+        }
 
+        img {
+          padding-right: 0;
         }
-        .menu-content-rb:nth-of-type(14){
-           background-color: transparent;
-            height:20px;
-           .menu-content-rb1{
-             display: flex;
-             align-items: center;
-             height: 24px;
-              margin-left: 0;
-             align-content: center;
-             input{
-                width:16px;
-               height: 16px;
-               margin-right: 5px;
-             }
-             img{
-               padding-left: 5px;
-               font-size: 16px;
-               padding-top: 2px;
-             }
-            }
-          .menu-content-rb1:nth-child(2){
-            span:nth-child(2){
-              margin:0 0px 0 5px;
-            }
+
+      }
+
+      .menu-content-rb:nth-of-type(14) {
+        background-color: transparent;
+        height: 20px;
+
+        .menu-content-rb1 {
+          display: flex;
+          align-items: center;
+          height: 24px;
+          margin-left: 0;
+          align-content: center;
+
+          input {
+            width: 16px;
+            height: 16px;
+            margin-right: 5px;
           }
-           span{
-              padding-right: 0;
-            }
-          img{
-            padding-right: 0;
+
+          img {
+            padding-left: 5px;
+            font-size: 16px;
+            padding-top: 2px;
           }
+        }
 
+        .menu-content-rb1:nth-child(2) {
+          span:nth-child(2) {
+            margin: 0 0px 0 5px;
+          }
         }
-        .menu-content-rb:nth-of-type(15){
-           background-color: #df384c;
-           div{margin: auto;}
 
+        span {
+          padding-right: 0;
+        }
+
+        img {
+          padding-right: 0;
+        }
+
+      }
+
+      .menu-content-rb:nth-of-type(15) {
+        background-color: #df384c;
+
+        div {
+          margin: auto;
         }
-        //.van-dropdown-menu__bar{
-        //  width: 214px;
-        //}
 
       }
+
+      //.van-dropdown-menu__bar{
+      //  width: 214px;
+      //}
+
     }
   }
+}
 </style>

+ 176 - 0
src/views/bitcoin/StatusComponent/ConfirmPing.vue

@@ -0,0 +1,176 @@
+<template>
+  <Teleport to="body">
+    <transition name="modal-fade">
+      <div v-if="visible" class="modal-mask" @click="handleClose">
+
+        <div class="modal-container" @click.stop>
+
+          <div class="modal-title">温馨提示</div>
+
+          <div class="modal-icon">
+            <img src="../../../assets/icon/bitcoin/querenpin.svg" alt="">
+          </div>
+
+          <p class="modal-text">确定要平仓吗?</p>
+
+          <button class="btn-primary" @click="handleConfirm">
+            确认
+          </button>
+
+          <button class="btn-secondary" @click="handleClose">
+            取消
+          </button>
+
+        </div>
+      </div>
+    </transition>
+  </Teleport>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue';
+import {useRouter} from "vue-router";
+  const router = useRouter();
+
+
+// 接收父组件传来的可见性状态
+defineProps({
+  visible: {
+    type: Boolean,
+    required: true
+  }
+});
+
+// 定义向父组件发送的事件
+const emit = defineEmits(['update:visible', 'confirm']);
+
+// 关闭弹窗
+const handleClose = () => {
+  // 发送事件让父组件把 visible 改为 false
+  emit('update:visible', false);
+};
+
+// 点击确认按钮
+const handleConfirm = () => {
+  console.log("lllll")
+  // 先触发确认操作,比如跳转充值页面
+  window.location.reload();
+  // router.replace({ path: '/bitcoin', query: { to: router.currentRoute.value.fullPath } })
+  // router.push('/bitcoin')
+  // emit('confirm');
+  // // 然后关闭弹窗
+  // handleClose();
+};
+</script>
+
+<style scoped>
+/* --- 遮罩层 --- */
+.modal-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0, 0, 0, 0.6); /* 深色半透明背景 */
+  display: flex;
+  align-items: center; /* 垂直居中 */
+  justify-content: center; /* 水平居中 */
+  z-index: 9999; /* 保证在最上层 */
+  padding: 20px; /* 防止小屏贴边 */
+}
+
+/* --- 弹窗容器 --- */
+.modal-container {
+  width: 100%;
+  max-width: 315px; /* 在375屏上两边留有约30px间距,视觉效果舒适 */
+  background: #fff;
+  border-radius: 16px; /* 大圆角 */
+  padding: 24px 20px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  box-sizing: border-box;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
+}
+
+/* --- 标题 --- */
+.modal-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #111827;
+  margin-bottom: 20px;
+}
+
+/* --- 图标区域 --- */
+.modal-icon {
+  margin-bottom: 16px;
+  /* 如果用图片,可以设置 width/height */
+}
+
+/* --- 文本 --- */
+.modal-text {
+  font-size: 15px;
+  color: #6B7280; /* 灰色的提示文字 */
+  margin: 0 0 32px 0; /* 底部留出较大空间给按钮 */
+}
+
+/* --- 通用按钮样式 --- */
+button {
+  border: none;
+  background: none;
+  font-size: 16px;
+  cursor: pointer;
+  width: 100%; /* 按钮撑满容器宽度 */
+  font-weight: 500;
+  transition: opacity 0.2s;
+}
+button:active {
+  opacity: 0.8; /* 点击反馈 */
+}
+
+/* --- 主按钮 (红色胶囊) --- */
+.btn-primary {
+  height: 48px;
+  background: #D93F4C; /* 提取的设计稿红色 */
+  color: white;
+  border-radius: 24px; /* 高度的一半,形成完美胶囊圆角 */
+  margin-bottom: 12px;
+}
+
+/* --- 次要按钮 (红色文字) --- */
+.btn-secondary {
+  height: 40px;
+  color: #D93F4C; /* 文字颜色与主按钮背景一致 */
+}
+
+/* --- 动画定义 (淡入 + 缩放弹出) --- */
+.modal-fade-enter-active,
+.modal-fade-leave-active {
+  transition: opacity 0.3s ease;
+}
+
+.modal-fade-enter-active .modal-container {
+  /* 弹窗进入时的弹性动画 */
+  animation: modal-pop-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+}
+.modal-fade-leave-active .modal-container {
+  /* 弹窗离开时的动画 */
+  animation: modal-pop-in 0.3s reverse;
+}
+
+.modal-fade-enter-from,
+.modal-fade-leave-to {
+  opacity: 0;
+}
+
+@keyframes modal-pop-in {
+  from {
+    opacity: 0;
+    transform: scale(0.9);
+  }
+  to {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+</style>

+ 175 - 0
src/views/bitcoin/StatusComponent/InsufficientBalance.vue

@@ -0,0 +1,175 @@
+<template>
+  <Teleport to="body">
+    <transition name="modal-fade">
+      <div v-if="visible" class="modal-mask" @click="handleClose">
+
+        <div class="modal-container" @click.stop>
+
+          <div class="modal-title">温馨提示</div>
+
+          <div class="modal-icon">
+            <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <circle cx="38" cy="32" r="23.5" stroke="#9CA3AF" fill="white"/>
+              <circle cx="35" cy="32" r="23.5" stroke="#9CA3AF" fill="#F3F4F6"/>
+              <circle cx="32" cy="32" r="24" fill="#1F2937"/>
+              <circle cx="32" cy="32" r="22.5" stroke="#374151" stroke-width="3"/>
+              <path d="M32 18V21M32 43V46M36.5 25C36.5 23.5 35.5 22 32 22C28.5 22 27.5 23.5 27.5 25C27.5 28 31 29 33.5 30C36 31 37 33 37 36C37 39 35 41 32 41C29 41 27 39 27 36M27.5 25H26M36.5 36H38" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
+            </svg>
+          </div>
+
+          <p class="modal-text">余额不足,去充币</p>
+
+          <button class="btn-primary" @click="handleConfirm">
+            立即充币
+          </button>
+
+          <button class="btn-secondary" @click="handleClose">
+            取消
+          </button>
+
+        </div>
+      </div>
+    </transition>
+  </Teleport>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue';
+
+// 接收父组件传来的可见性状态
+defineProps({
+  visible: {
+    type: Boolean,
+    required: true
+  }
+});
+
+// 定义向父组件发送的事件
+const emit = defineEmits(['update:visible', 'confirm']);
+
+// 关闭弹窗
+const handleClose = () => {
+  // 发送事件让父组件把 visible 改为 false
+  emit('update:visible', false);
+};
+
+// 点击确认按钮
+const handleConfirm = () => {
+  // 先触发确认操作,比如跳转充值页面
+  emit('confirm');
+  // 然后关闭弹窗
+  handleClose();
+};
+</script>
+
+<style scoped>
+/* --- 遮罩层 --- */
+.modal-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0, 0, 0, 0.6); /* 深色半透明背景 */
+  display: flex;
+  align-items: center; /* 垂直居中 */
+  justify-content: center; /* 水平居中 */
+  z-index: 9999; /* 保证在最上层 */
+  padding: 20px; /* 防止小屏贴边 */
+}
+
+/* --- 弹窗容器 --- */
+.modal-container {
+  width: 100%;
+  max-width: 315px; /* 在375屏上两边留有约30px间距,视觉效果舒适 */
+  background: #fff;
+  border-radius: 16px; /* 大圆角 */
+  padding: 24px 20px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  box-sizing: border-box;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
+}
+
+/* --- 标题 --- */
+.modal-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #111827;
+  margin-bottom: 20px;
+}
+
+/* --- 图标区域 --- */
+.modal-icon {
+  margin-bottom: 16px;
+  /* 如果用图片,可以设置 width/height */
+}
+
+/* --- 文本 --- */
+.modal-text {
+  font-size: 15px;
+  color: #6B7280; /* 灰色的提示文字 */
+  margin: 0 0 32px 0; /* 底部留出较大空间给按钮 */
+}
+
+/* --- 通用按钮样式 --- */
+button {
+  border: none;
+  background: none;
+  font-size: 16px;
+  cursor: pointer;
+  width: 100%; /* 按钮撑满容器宽度 */
+  font-weight: 500;
+  transition: opacity 0.2s;
+}
+button:active {
+  opacity: 0.8; /* 点击反馈 */
+}
+
+/* --- 主按钮 (红色胶囊) --- */
+.btn-primary {
+  height: 48px;
+  background: #D93F4C; /* 提取的设计稿红色 */
+  color: white;
+  border-radius: 24px; /* 高度的一半,形成完美胶囊圆角 */
+  margin-bottom: 12px;
+}
+
+/* --- 次要按钮 (红色文字) --- */
+.btn-secondary {
+  height: 40px;
+  color: #D93F4C; /* 文字颜色与主按钮背景一致 */
+}
+
+/* --- 动画定义 (淡入 + 缩放弹出) --- */
+.modal-fade-enter-active,
+.modal-fade-leave-active {
+  transition: opacity 0.3s ease;
+}
+
+.modal-fade-enter-active .modal-container {
+  /* 弹窗进入时的弹性动画 */
+  animation: modal-pop-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+}
+.modal-fade-leave-active .modal-container {
+  /* 弹窗离开时的动画 */
+  animation: modal-pop-in 0.3s reverse;
+}
+
+.modal-fade-enter-from,
+.modal-fade-leave-to {
+  opacity: 0;
+}
+
+@keyframes modal-pop-in {
+  from {
+    opacity: 0;
+    transform: scale(0.9);
+  }
+  to {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+</style>

+ 249 - 0
src/views/bitcoin/components/ClosePositionSheet.vue

@@ -0,0 +1,249 @@
+<template>
+  <Teleport to="body">
+    <transition name="fade">
+      <div v-if="visible" class="modal-mask" @click="close"></div>
+    </transition>
+
+    <transition name="slide-up">
+      <div v-if="visible" class="modal-panel">
+        <div class="handle-wrap"><div class="handle"></div></div>
+
+        <div class="header-section">
+          <div class="coin-icon">
+            <img src="../../../assets/icon/bitcoin/bt.svg" alt="">
+<!--            <svg viewBox="0 0 64 64" width="100%" height="100%">-->
+<!--              <circle cx="32" cy="32" r="32" fill="#F7931A"/>-->
+<!--              <path d="M44.08 25.6c-0.4-2.69-1.65-4.12-4.46-5.09l0.91-3.66-2.23-0.56-0.89 3.56c-0.59-0.15-1.21-0.29-1.83-0.43l0.9-3.62-2.23-0.56-0.91 3.65c-0.48-0.11-0.98-0.22-1.46-0.33L28.7 18l-4.3 1.08s1.2 0.28 1.17 0.29c0.65 0.16 0.77 0.6 0.75 0.94l-0.75 3.02c0.05 0.01 0.1 0.03 0.17 0.05-0.05-0.01-0.11-0.03-0.17-0.04l-1.06 4.24c-0.08 0.2-0.28 0.8-0.73 0.69 0.01 0.02-1.17-0.29-1.17-0.29l-2.3 5.3 4.06 1.01c0.55 0.14 1.09 0.28 1.64 0.41l-0.92 3.69 2.23 0.56 0.91-3.66c0.61 0.16 1.2 0.31 1.8 0.45l-0.91 3.63 2.23 0.56 0.92-3.67c3.8 0.72 6.65 0.43 7.85-3 0.96-2.76-0.05-4.35-2.04-5.39 1.45-0.33 2.54-1.29 2.83-3.26zM38.2 36.2c-0.63 2.53-4.88 1.16-6.26 0.82l1.12-4.48c1.38 0.34 5.82 1.02 5.14 3.66zm0.67-8.93c-0.57 2.3-4.2 1.13-5.37 0.84l1.01-4.06c1.17 0.29 4.94 0.83 4.36 3.22z" fill="white"/>-->
+<!--            </svg>-->
+          </div>
+          <div class="title-col">
+            <div class="main-title">BTC/USDT 永续</div>
+            <div class="tags-row">
+              <span class="tag tag-buy">买入</span>
+              <span class="tag tag-mode">逐仓 20X</span>
+            </div>
+          </div>
+        </div>
+
+        <div class="price-row">
+          <span class="label">开仓价格</span><span class="value">1000.05 USDT</span>
+        </div>
+        <div class="price-row">
+          <span class="label">标记价格</span><span class="value">1000.05 USDT</span>
+        </div>
+
+        <div class="form-area">
+          <div class="input-box">
+            <span class="input-label">委托类型</span>
+            <div class="input-value-wrap">
+              <span>市价</span>
+              <svg viewBox="0 0 1024 1024" width="10" height="10"><path d="M512 714.667l-298.667-298.667h597.334l-298.667 298.667z" fill="#666"/></svg>
+            </div>
+          </div>
+          <div class="input-box"><span class="input-text-val">市价</span></div>
+          <div class="input-box">
+            <span class="input-label">数量</span><span class="input-suffix">BTC</span>
+          </div>
+        </div>
+
+        <div class="slider-section">
+          <div class="slider-header">可平 0.2562 BTC</div>
+
+          <div class="dumbbell-slider-wrap">
+            <input
+              type="range"
+              min="0"
+              max="100"
+              step="25"
+              v-model="percent"
+              class="dumbbell-slider"
+              :style="sliderTrackStyle"
+            />
+          </div>
+
+          <div class="percent-labels">
+            <span @click="percent=0">0%</span>
+            <span @click="percent=25">25%</span>
+            <span @click="percent=50">50%</span>
+            <span @click="percent=75">75%</span>
+            <span @click="percent=100">100%</span>
+          </div>
+        </div>
+
+        <div class="footer-section">
+          <div class="pnl-row">
+            <span>预计盈亏</span><span class="pnl-val">+0.30 USDT</span>
+          </div>
+          <button class="action-btn" @click="showModal4=true">平空</button>
+        </div>
+        <div class="safe-area"></div>
+      </div>
+    </transition>
+  </Teleport>
+
+  <div>
+    <ConfirmPing
+        v-model:visible="showModal4"
+    ></ConfirmPing>
+  </div>
+</template>
+
+<script setup>
+import {ref, computed, defineProps, defineEmits, defineAsyncComponent} from 'vue';
+const ConfirmPing = defineAsyncComponent(() => import("../StatusComponent/ConfirmPing.vue"));
+
+
+defineProps({ visible: Boolean });
+const emit = defineEmits(['update:visible']);
+
+const percent = ref(0); // 默认从0开始
+
+// 计算滑块轨道背景样式,实现红/灰填充
+const sliderTrackStyle = computed(() => {
+  return {
+    // 红色填充部分 + 灰色未填充部分
+    background: `linear-gradient(to right,
+                 #E04747 ${percent.value}%,
+                 #F2F3F5 ${percent.value}%)`
+  };
+});
+
+const close = () => emit('update:visible', false);
+//确认平仓
+const showModal4 = ref(false);
+</script>
+
+<style scoped lang="less">
+/* 全局变量 */
+:root { --red: #E04747; --green: #2EBD85; }
+
+/* 弹窗基础结构 (不变) */
+.modal-mask { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 998; }
+.modal-panel { position: fixed; bottom: 0; left: 0; width: 100%; background: #fff;
+  border-radius: 16px 16px 0 0; z-index: 999; font-family: sans-serif; }
+.handle-wrap { padding: 8px 0; display: flex; justify-content: center; }
+.handle { width: 36px; height: 4px; background: #E5E6EB; border-radius: 2px; }
+
+/* 头部样式 (不变) */
+.header-section { padding: 4px 20px 16px 20px; display: flex; align-items: center; gap: 12px; }
+.coin-icon { width: 40px; height: 40px; flex-shrink: 0; }
+.title-col { display: flex; flex-direction: column; justify-content: center; gap: 4px; }
+.main-title { font-size: 17px; font-weight: 600; color: #1F2124; line-height: 1.2; }
+.tags-row { display: flex; gap: 6px; }
+.tag { font-size: 11px; padding: 1px 5px; border-radius: 3px; transform: scale(0.95);
+  transform-origin: left center; }
+.tag-buy { background: #2EBD85; color: white; }
+.tag-mode { background: #B0B5BC; color: white; }
+
+/* 价格行 & 表单 (不变) */
+.price-row { display: flex; justify-content: space-between; padding: 2px 20px;
+  font-size: 13px; color: #86909C; }
+.price-row .value { color: #1F2124; font-weight: 500; }
+.form-area { padding: 16px 20px; display: flex; flex-direction: column; gap: 12px; }
+.input-box { background: #F7F8FA; height: 40px; border-radius: 4px; padding: 0 12px;
+  display: flex; align-items: center; justify-content: space-between; font-size: 14px; color: #1F2124; }
+.input-label { color: #86909C; }
+.input-value-wrap { display: flex; align-items: center; gap: 4px; }
+.input-suffix { color: #1F2124; }
+
+/* --- 滑块样式修正 (重点) --- */
+.slider-section { padding: 0 20px 0 20px; }
+.slider-header { font-size: 12px; color: #5E6673; margin-bottom: 16px; }
+
+.dumbbell-slider-wrap {
+  position: relative;
+  height: 24px; /* 高度与滑块Thumb一致 */
+  display: flex;
+  align-items: center;
+}
+
+/* 核心:input[type="range"] 样式调整 */
+.dumbbell-slider {
+  -webkit-appearance: none;
+  appearance: none; /* 兼容性 */
+  width: 100%;
+  height: 8px; /* 轨道粗细 */
+  border-radius: 4px;
+  outline: none;
+  margin: 0;
+  cursor: pointer;
+  z-index: 2; /* 确保在其他伪元素之上 */
+  position: relative;
+  /* 轨道背景由 js 动态计算 */
+}
+
+/* 轨道左侧填充(红色)和右侧未填充(灰色) */
+/* 通过背景渐变控制,由 `sliderTrackStyle` 绑定 */
+.dumbbell-slider::-webkit-slider-runnable-track {
+  background: transparent; /* 真正的轨道背景由input本身的背景负责 */
+  border-radius: 4px;
+  height: 8px;
+}
+.dumbbell-slider::-moz-range-track {
+  background: transparent;
+  border-radius: 4px;
+  height: 8px;
+}
+
+/* 滑块拖动钮 (Thumb) */
+.dumbbell-slider::-webkit-slider-thumb {
+  -webkit-appearance: none;
+  appearance: none;
+  height: 24px; /* 直径 */
+  width: 24px; /* 直径 */
+  border-radius: 50%;
+  background: #ffffff; /* 白底 */
+  //border: 2px solid var(--red); /* 红色边框 */
+  border: 2px solid red;
+  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
+  margin-top: -8px; /* 垂直居中轨道 */
+  position: relative;
+  z-index: 3; /* 确保在最高层 */
+}
+.dumbbell-slider::-moz-range-thumb {
+  height: 24px;
+  width: 24px;
+  border-radius: 50%;
+  background: #ffffff;
+  border: 2px solid var(--red);
+  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
+  z-index: 3;
+}
+
+/* 固定在 0% 位置的圆圈 (通过伪元素实现) */
+.dumbbell-slider::before {
+  content: '';
+  position: absolute;
+  left: 0; /* 微调使其完全贴合 */
+  top: 50%;
+  transform: translateY(-50%);
+  height: 18px; /* 直径 */
+  width: 18px; /* 直径 */
+  border-radius: 50%;
+  background: #ffffff; /* 白底 */
+  //border: 2px solid var(--red); /* 红色边框 */
+  border: 2px solid red;
+
+  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
+  z-index: 1; /* 在轨道之下,但又在滑块thumb之下 */
+  pointer-events: none; /* 不会影响滑块拖动 */
+}
+
+
+.percent-labels { display: flex; justify-content: space-between; margin-top: 12px;
+  font-size: 12px; color: #86909C; }
+
+/* 底部 (不变) */
+.footer-section { padding: 20px; }
+.pnl-row { display: flex; justify-content: space-between; margin-bottom: 16px; font-size: 14px; }
+.pnl-val { color: #2EBD85; font-weight: 500; }
+.action-btn { width: 100%; height: 44px; background: #2EBD85;
+  border-radius: 22px; border: none; color: white; font-size: 16px; font-weight: 600; }
+.safe-area { height: env(safe-area-inset-bottom); }
+
+/* 动画 (不变) */
+.fade-enter-active, .fade-leave-active { transition: opacity 0.2s; }
+.fade-enter-from, .fade-leave-to { opacity: 0; }
+.slide-up-enter-active, .slide-up-leave-active { transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1); }
+.slide-up-enter-from, .slide-up-leave-to { transform: translateY(100%); }
+</style>

+ 165 - 0
src/views/bitcoin/components/FundingOptions.vue

@@ -0,0 +1,165 @@
+<template>
+  <Teleport to="body">
+    <div v-if="visible" class="modal-mask" @click="close">
+      <div class="modal-content" @click.stop>
+        <div class="handle-bar"></div>
+<!--        <div class="trigger fs18 fc333333 pf600">选择触发类型</div>-->
+        <div class="options-list">
+          <div
+            v-for="item in options"
+            :key="item.id"
+            class="option-card"
+            :class="{ 'active': selectedId === item.id }"
+            @click="handleSelect(item)"
+          >
+            <div class="card-header">
+              <span class="title">{{ item.label }}</span>
+              <div v-if="selectedId === item.id" class="check-icon">
+                <svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor"
+                     stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"
+                     class="css-i6dzq1"><polyline points="20 6 9 17 4 12"></polyline></svg>
+              </div>
+            </div>
+            <div class="description">
+              {{ item.desc }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </Teleport>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue';
+
+// 接收父组件传来的 modelValue (控制显示) 和 当前选中的ID
+const props = defineProps({
+  visible: {
+    type: Boolean,
+    default: false
+  },
+  selectedId: {
+    type: [String, Number],
+    default: 1
+  }
+});
+
+const emit = defineEmits(['update:visible', 'confirm']);
+
+// 静态数据源 (保持不变)
+const options = [
+  {
+    id: 1,
+    label: '全仓',
+    desc: '所有仓位共用保证金盈亏互抵可有效降低强平风险但强平时可能损失全部仓位'
+  },
+
+  {
+    id: 2,
+    label: '逐仓',
+    desc: '各仓位的保证金与盈亏单独核算强平时仅损失当前仓位'
+  }
+];
+
+const close = () => {
+  emit('update:visible', false);
+};
+
+const handleSelect = (item) => {
+  // 1. 触发 confirm 事件,把整个对象带回去
+  emit('confirm', item);
+  // 2. 关闭弹窗
+  close();
+};
+</script>
+
+<style lang="less" scoped>
+.modal-mask {
+  position: fixed;
+  top: 0; left: 0; width: 100%; height: 100%;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: flex-end; /* 底部对齐 */
+  z-index: 1000; /* 极高的 Z-index */
+}
+
+.modal-content {
+  width: 100%;
+  background: white;
+  border-radius: 16px 16px 0 0;
+  padding: 20px;
+  padding-bottom: 40px;
+  max-height: 80vh;
+  overflow-y: auto;
+  animation: slideUp 0.3s ease-out;
+  .trigger{margin-bottom: 15px}
+}
+
+.handle-bar {
+  width: 40px;
+  height: 4px;
+  background: #E0E0E0;
+  border-radius: 2px;
+  margin: 0 auto 20px auto;
+}
+
+.option-card {
+  border: 1px solid #E0E0E0;
+  border-radius: 12px;
+  padding: 16px;
+  margin-bottom: 16px;
+  cursor: pointer;
+  transition: all 0.2s;
+  position: relative;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 8px;
+}
+
+.title {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+}
+
+.description {
+  font-size: 13px;
+  color: #666;
+  line-height: 1.5;
+}
+
+/* 选中状态样式 */
+.option-card.active {
+  border-color: #F53F3F; /* 红色边框 */
+  background-color: #FFF9F9; /* 极淡的红色背景可选 */
+}
+
+.option-card.active .title {
+  color: #D92828; /* 红色标题 */
+}
+
+.option-card.active .description {
+  color: #D92828; /* 红色描述 */
+}
+
+.check-icon {
+  width: 24px;
+  height: 24px;
+  background: #D92828;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: white;
+}
+
+@keyframes slideUp {
+  from { transform: translateY(100%); }
+  to { transform: translateY(0); }
+}
+</style>

+ 171 - 0
src/views/bitcoin/components/MarginInfoSheet.vue

@@ -0,0 +1,171 @@
+<template>
+  <Teleport to="body">
+    <transition name="fade">
+      <div v-if="visible" class="modal-mask" @click="closeModal"></div>
+    </transition>
+
+    <transition name="slide-up">
+      <div v-if="visible" class="modal-panel">
+        <div class="panel-handle-wrap">
+          <div class="panel-handle"></div>
+        </div>
+
+        <div class="panel-content">
+          <div class="section">
+            <h3 class="section-title">逐仓模式</h3>
+            <p class="section-text">
+              根据用户操作一定数量保证金被分配到仓位上,如果仓位亏损到低于维持保证金的水平,仓位将被强平。在逐仓模式下,用户可以自行追加保证金
+            </p>
+          </div>
+
+          <div class="section">
+            <h3 class="section-title">全仓模式</h3>
+            <p class="section-text">
+              仓位保证金将共享全部同币种账户资产,如果仓位亏损低于一定比例,全仓系统将自动追加可用保证金。在强平事件中,交易者可能会损失全部保证金和账户资产
+            </p>
+          </div>
+        </div>
+
+        <div class="panel-footer">
+          <button class="confirm-btn" @click="closeModal">
+            我知道了
+          </button>
+        </div>
+
+        <div class="safe-area-bottom"></div>
+      </div>
+    </transition>
+  </Teleport>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue';
+
+// 接收 visible 属性
+const props = defineProps({
+  visible: {
+    type: Boolean,
+    default: false
+  }
+});
+
+// 定义事件
+const emit = defineEmits(['update:visible']);
+
+// 关闭弹窗的方法
+const closeModal = () => {
+  emit('update:visible', false);
+};
+</script>
+
+<style scoped>
+/* 遮罩层 */
+.modal-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  height: 100vh;
+  background-color: rgba(0, 0, 0, 0.6); /* 稍微深一点的遮罩,突出文字 */
+  z-index: 2000;
+}
+
+/* 弹窗主体 */
+.modal-panel {
+  position: fixed;
+  bottom: 0;
+  left: 50%;
+  transform: translateX(-50%); /* 水平居中 */
+  width: 100%;
+  max-width: 600px; /* PC端限制最大宽度 */
+  background: white;
+  border-radius: 16px 16px 0 0;
+  z-index: 2001;
+  display: flex;
+  flex-direction: column;
+  box-sizing: border-box;
+}
+
+/* 顶部 Handle 区域 */
+.panel-handle-wrap {
+  padding: 12px 0 20px 0;
+  display: flex;
+  justify-content: center;
+}
+.panel-handle {
+  width: 36px;
+  height: 4px;
+  background: #E0E0E0;
+  border-radius: 2px;
+}
+
+/* 内容区域 */
+.panel-content {
+  padding: 0 20px;
+  /* 防止内容过多导致无法显示,增加滚动 */
+  max-height: 60vh;
+  overflow-y: auto;
+}
+
+.section {
+  margin-bottom: 24px;
+}
+
+.section-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #1A1A1A;
+  margin: 0 0 8px 0;
+  line-height: 1.4;
+}
+
+.section-text {
+  font-size: 14px;
+  color: #444; /* 设计稿文字看起来比纯黑淡一点 */
+  line-height: 1.6; /* 增加行高,提升阅读体验 */
+  margin: 0;
+  text-align: justify; /* 两端对齐,让大段文字更整齐 */
+}
+
+/* 底部按钮区域 */
+.panel-footer {
+  padding: 20px 20px 10px 20px;
+}
+
+.confirm-btn {
+  width: 100%;
+  height: 48px;
+  background: #DC3E48; /* 提取的红色 hex */
+  color: white;
+  border: none;
+  border-radius: 24px; /* 圆角按钮 */
+  font-size: 16px;
+  font-weight: 500;
+  cursor: pointer;
+  /* 点击时的按压效果 */
+  transition: opacity 0.2s;
+}
+.confirm-btn:active {
+  opacity: 0.9;
+}
+
+/* 底部安全区 */
+.safe-area-bottom {
+  height: env(safe-area-inset-bottom, 20px);
+}
+
+/* 动画定义 */
+.fade-enter-active, .fade-leave-active {
+  transition: opacity 0.3s ease;
+}
+.fade-enter-from, .fade-leave-to {
+  opacity: 0;
+}
+
+.slide-up-enter-active, .slide-up-leave-active {
+  transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
+}
+.slide-up-enter-from, .slide-up-leave-to {
+  transform: translate(-50%, 100%);
+}
+</style>

+ 4 - 3
src/views/bitcoin/components/OrderConfirmPopup.vue

@@ -64,7 +64,6 @@
             :style="contentStyle"
           >
             <div class="tpsl-inner">
-
               <div class="strategy-block">
                 <div class="block-header">
                   <span class="sub-title">止盈</span>
@@ -209,7 +208,8 @@ const handleConfirm = () => {
     .tag.leverage { background: #EFF0F2; color: #999; }
 
     /* 信息列表 */
-    .info-row { display: flex; justify-content: space-between; margin-bottom: 12px; font-size: 14px; }
+    .info-row { display: flex; justify-content: space-between; margin-bottom: 12px;
+      font-size: 14px; }
     .info-row .label { color: #999; }
     .info-row .value { color: #333; font-weight: 500; }
 
@@ -230,7 +230,8 @@ const handleConfirm = () => {
     }
     .strategy-block { margin-bottom: 10px; }
     .mt-15 { margin-top: 15px; }
-    .block-header { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 13px; }
+    .block-header { display: flex; justify-content: space-between; margin-bottom: 8px;
+      font-size: 13px; }
     .sub-title { font-weight: 600; color: #333; }
     .right-action { color: #333; display: flex; align-items: center; gap: 2px;
       svg{

+ 165 - 0
src/views/bitcoin/components/OrderType.vue

@@ -0,0 +1,165 @@
+<template>
+  <Teleport to="body">
+    <div v-if="visible" class="modal-mask" @click="close">
+      <div class="modal-content" @click.stop>
+        <div class="handle-bar"></div>
+        <div class="trigger fs18 fc333333 pf600">选择订单类型</div>
+        <div class="options-list">
+          <div
+            v-for="item in options"
+            :key="item.id"
+            class="option-card"
+            :class="{ 'active': selectedId === item.id }"
+            @click="handleSelect(item)"
+          >
+            <div class="card-header">
+              <span class="title">{{ item.label }}</span>
+              <div v-if="selectedId === item.id" class="check-icon">
+                <svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor"
+                     stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"
+                     class="css-i6dzq1"><polyline points="20 6 9 17 4 12"></polyline></svg>
+              </div>
+            </div>
+            <div class="description">
+              {{ item.desc }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </Teleport>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue';
+
+// 接收父组件传来的 modelValue (控制显示) 和 当前选中的ID
+const props = defineProps({
+  visible: {
+    type: Boolean,
+    default: false
+  },
+  selectedId: {
+    type: [String, Number],
+    default: 1
+  }
+});
+
+const emit = defineEmits(['update:visible', 'confirm']);
+
+// 静态数据源 (保持不变)
+const options = [
+  {
+    id: 1,
+    label: '市价',
+    desc: '确保成交,快速买入或卖出'
+  },
+
+  {
+    id: 2,
+    label: '限价',
+    desc: '指定或更优价格进行买入或卖出'
+  }
+];
+
+const close = () => {
+  emit('update:visible', false);
+};
+
+const handleSelect = (item) => {
+  // 1. 触发 confirm 事件,把整个对象带回去
+  emit('confirm', item);
+  // 2. 关闭弹窗
+  close();
+};
+</script>
+
+<style lang="less" scoped>
+.modal-mask {
+  position: fixed;
+  top: 0; left: 0; width: 100%; height: 100%;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: flex-end; /* 底部对齐 */
+  z-index: 1000; /* 极高的 Z-index */
+}
+
+.modal-content {
+  width: 100%;
+  background: white;
+  border-radius: 16px 16px 0 0;
+  padding: 20px;
+  padding-bottom: 40px;
+  max-height: 80vh;
+  overflow-y: auto;
+  animation: slideUp 0.3s ease-out;
+  .trigger{margin-bottom: 15px}
+}
+
+.handle-bar {
+  width: 40px;
+  height: 4px;
+  background: #E0E0E0;
+  border-radius: 2px;
+  margin: 0 auto 20px auto;
+}
+
+.option-card {
+  border: 1px solid #E0E0E0;
+  border-radius: 12px;
+  padding: 16px;
+  margin-bottom: 16px;
+  cursor: pointer;
+  transition: all 0.2s;
+  position: relative;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 8px;
+}
+
+.title {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+}
+
+.description {
+  font-size: 13px;
+  color: #666;
+  line-height: 1.5;
+}
+
+/* 选中状态样式 */
+.option-card.active {
+  border-color: #F53F3F; /* 红色边框 */
+  background-color: #FFF9F9; /* 极淡的红色背景可选 */
+}
+
+.option-card.active .title {
+  color: #D92828; /* 红色标题 */
+}
+
+.option-card.active .description {
+  color: #D92828; /* 红色描述 */
+}
+
+.check-icon {
+  width: 24px;
+  height: 24px;
+  background: #D92828;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: white;
+}
+
+@keyframes slideUp {
+  from { transform: translateY(100%); }
+  to { transform: translateY(0); }
+}
+</style>

+ 116 - 0
src/views/bitcoin/components/ProfitAndLossPrompt.vue

@@ -0,0 +1,116 @@
+<template>
+  <Teleport to="body">
+    <transition name="fade">
+      <div v-if="visible" class="modal-mask" @click="close">
+
+        <div class="modal-container" @click.stop>
+
+          <div class="modal-title">止盈止损</div>
+
+          <div class="modal-text">
+            止盈止损是指下单时提前为该订单预设止盈价及止损价,以锁定利润或控制损失。当订单完全成交时,系统将自动进行止盈止损委托。
+          </div>
+
+          <button class="main-btn" @click="close">
+            我知道了
+          </button>
+
+        </div>
+      </div>
+    </transition>
+  </Teleport>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue';
+
+defineProps({
+  visible: Boolean
+});
+
+const emit = defineEmits(['update:visible']);
+
+const close = () => {
+  emit('update:visible', false);
+};
+</script>
+
+<style scoped>
+/* --- 布局与遮罩 --- */
+.modal-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  height: 100vh;
+  background: rgba(0, 0, 0, 0.6); /* 深色遮罩 */
+  display: flex;
+  align-items: center; /* 垂直居中 */
+  justify-content: center; /* 水平居中 */
+  z-index: 999;
+}
+
+/* --- 弹窗卡片 --- */
+.modal-container {
+  width: 310px; /* 稍微宽一点,适配文字换行 */
+  background: #fff;
+  border-radius: 16px; /* 大圆角 */
+  padding: 24px 24px;
+  box-sizing: border-box;
+  text-align: center;
+  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
+}
+
+/* --- 标题 --- */
+.modal-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #111;
+  margin-bottom: 16px;
+}
+
+/* --- 正文 --- */
+.modal-text {
+  font-size: 15px;
+  color: #555; /* 稍微柔和的深灰色 */
+  line-height: 1.6; /* 增加行高,易读 */
+  text-align: justify; /* 两端对齐,像报纸一样整齐 */
+  margin-bottom: 24px;
+}
+
+/* --- 红色按钮 --- */
+.main-btn {
+  width: 100%;
+  height: 46px;
+  background: #DE3545; /* 截图里的标准红 */
+  color: #fff;
+  font-size: 16px;
+  font-weight: 500;
+  border: none;
+  border-radius: 23px; /* 高度的一半,形成胶囊形状 */
+  cursor: pointer;
+}
+.main-btn:active {
+  opacity: 0.8; /* 点击反馈 */
+}
+
+/* --- 动画效果: 缩放弹入 --- */
+.fade-enter-active, .fade-leave-active {
+  transition: opacity 0.2s ease;
+}
+.fade-enter-active .modal-container {
+  animation: pop-in 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28); /* 弹性动画 */
+}
+.fade-leave-active .modal-container {
+  animation: pop-in 0.3s reverse;
+}
+
+.fade-enter-from, .fade-leave-to {
+  opacity: 0;
+}
+
+@keyframes pop-in {
+  0% { transform: scale(0.8); opacity: 0; }
+  100% { transform: scale(1); opacity: 1; }
+}
+</style>

+ 10 - 1
src/views/bitcoin/components/TakeProfitsTopLoss.vue

@@ -3,6 +3,10 @@
     import { Icon as VanIcon, } from 'vant';
     import {defineAsyncComponent, ref} from 'vue';
     const TPSLSmartPopup = defineAsyncComponent(() => import('../components/TPSLSmartPopup.vue'));
+    const ProfitAndLossPrompt = defineAsyncComponent(() => import('../components/ProfitAndLossPrompt.vue'));
+
+    //止盈止损提示
+    const showModal = ref(false);
 
     // 1. 状态控制
     const isEnabled = ref(false); // 控制复选框选中状态,
@@ -35,7 +39,7 @@
         </van-checkbox>
         <span class="label-text">止盈止损</span>
 
-        <van-icon name="question-o" color="#999" size="16" class="help-icon" />
+        <van-icon name="question-o" color="#999" size="16" class="help-icon" @click="showModal = true"/>
       </div>
 
       <div v-if="isEnabled" class="right-action" @click="handleAdvanced">
@@ -73,6 +77,11 @@
         v-model:visible="showSmartTPSL"
         @confirm="handleConfirm1"
     ></TPSLSmartPopup>
+    <div>
+      <ProfitAndLossPrompt
+          v-model:visible="showModal"
+      ></ProfitAndLossPrompt>
+    </div>
   </div>
 </template>
 

+ 3 - 1
src/views/bitcoin/components/TriggerPrice.vue

@@ -15,7 +15,9 @@
             <div class="card-header">
               <span class="title">{{ item.label }}</span>
               <div v-if="selectedId === item.id" class="check-icon">
-                <svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><polyline points="20 6 9 17 4 12"></polyline></svg>
+                <svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor"
+                     stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"
+                     class="css-i6dzq1"><polyline points="20 6 9 17 4 12"></polyline></svg>
               </div>
             </div>
             <div class="description">

+ 16 - 2
src/views/bitcoin/components/position.vue

@@ -1,5 +1,14 @@
 <script setup>
-import { Icon as VanIcon, Button as VanButton } from 'vant';
+    import {defineAsyncComponent, ref} from 'vue';
+
+    import { Icon as VanIcon, Button as VanButton } from 'vant';
+    const ClosePositionSheet   = defineAsyncComponent(() => import("./ClosePositionSheet.vue"));
+    //平仓平空
+    const showModal = ref(false);
+
+
+
+
 
 </script>
 
@@ -192,7 +201,7 @@ import { Icon as VanIcon, Button as VanButton } from 'vant';
         </div>
       </div>
 
-      <div class="footer-btn">
+      <div class="footer-btn" @click="showModal = true">
         <van-button block round color="#e6424a" class="close-btn">
           平仓
         </van-button>
@@ -202,6 +211,11 @@ import { Icon as VanIcon, Button as VanButton } from 'vant';
   </div>
     </div>
     </div>
+   <div>
+      <ClosePositionSheet
+          v-model:visible="showModal">
+      </ClosePositionSheet>
+    </div>
 </template>
 
 <style scoped lang="less">

+ 4 - 2
src/views/bitcoin/components/priceLimit.vue

@@ -15,7 +15,9 @@
             <div class="card-header">
               <span class="title">{{ item.label }}({{ item.unit }})</span>
               <div v-if="selectedId === item.id" class="check-icon">
-                <svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><polyline points="20 6 9 17 4 12"></polyline></svg>
+                <svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor"
+                     stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"
+                     class="css-i6dzq1"><polyline points="20 6 9 17 4 12"></polyline></svg>
               </div>
             </div>
             <div class="description">
@@ -79,7 +81,7 @@ const handleSelect = (item) => {
 };
 </script>
 
-<style>
+<style scoped>
 .modal-mask {
   position: fixed;
   top: 0; left: 0; width: 100%; height: 100%;

+ 79 - 62
src/views/bitcoin/components/sellOrder.vue

@@ -1,51 +1,59 @@
 <script setup>
-import {defineAsyncComponent, ref} from 'vue';
-const assetlessState = defineAsyncComponent(() => import("./assetlessState.vue"));
-const  position = defineAsyncComponent(() => import("./position.vue"));
-
-// 1. 模拟数据:为了还原图片,我们创建两个不同的订单对象
-const orders = ref([
-  {
-    id: 1,
-    symbol: 'BTC/USDT',
-    contractType: '永续',
-    side: 'buy', // 'buy' | 'sell'
-    leverage: '20X',
-    orderType: '市价',
-    amount: '0.215 USDT',
-    price: '0.215 USDT',
-    statusText: '止损',
-    triggerPrice: '标记价格>20',
-    time: '2025-11-04, 16:30',
-    stateText: '未触发',
-    canCancel: true // 显示红色撤单按钮
-  },
-  {
-    id: 2,
-    symbol: 'BTC/USDT',
-    contractType: '永续',
-    side: 'sell',
-    leverage: '20X',
-    orderType: '市价',
-    amount: '0.215 USDT',
-    price: '0.215 USDT',
-    statusText: '止盈',
-    triggerPrice: '标记价格>20',
-    time: '2025-11-04, 16:30',
-    stateText: '未触发',
-    canCancel: false // 显示灰色已完成/不可操作按钮
-  }
-]);
-
-// 当前选中的 Tab,默认选中 index 1 (当前委托)
-const currentTab = ref(0);
-const tabs = ['持有仓位(2)', '当前委托(2)'];
-
-// 按钮操作
-const handleCancel = (id) => {
-  console.log('撤单 ID:', id);
-  // 这里写撤单逻辑
-};
+    import {defineAsyncComponent, ref} from 'vue';
+    //状态组件
+    const assetlessState = defineAsyncComponent(() => import("./assetlessState.vue"));
+    //持有仓位组件
+    const position = defineAsyncComponent(() => import("./position.vue"));
+
+
+
+    // 1. 模拟数据:为了还原图片,我们创建两个不同的订单对象
+    const orders = ref([
+      {
+        id: 1,
+        symbol: 'BTC/USDT',
+        contractType: '永续',
+        side: 'buy', // 'buy' | 'sell'
+        leverage: '20X',
+        orderType: '市价',
+        amount: '0.215 USDT',
+        price: '0.215 USDT',
+        statusText: '止损',
+        triggerPrice: '标记价格>20',
+        time: '2025-11-04, 16:30',
+        stateText: '未触发',
+        canCancel: true // 显示红色撤单按钮
+      },
+      {
+        id: 2,
+        symbol: 'BTC/USDT',
+        contractType: '永续',
+        side: 'sell',
+        leverage: '20X',
+        orderType: '市价',
+        amount: '0.215 USDT',
+        price: '0.215 USDT',
+        statusText: '止盈',
+        triggerPrice: '标记价格>20',
+        time: '2025-11-04, 16:30',
+        stateText: '未触发',
+        canCancel: false // 显示灰色已完成/不可操作按钮
+      }
+    ]);
+
+    // 当前选中的 Tab,默认选中 index 1 (当前委托)
+    const currentTab = ref(0);
+    const tabs = ['持有仓位(2)', '当前委托(2)'];
+
+    // 按钮操作
+    const handleCancel = (id) => {
+      console.log('撤单 ID:', id);
+      // 这里写撤单逻辑
+    };
+
+    //平仓平空
+    const showModal3 = ref(false);
+
 </script>
 
 <template>
@@ -54,18 +62,18 @@ const handleCancel = (id) => {
     <div class="tabs-header">
       <div class="tabs-left">
         <div
-          v-for="(tab, index) in tabs"
-          :key="index"
-          class="tab-item"
-          :class="{ active: currentTab === index }"
-          @click="currentTab = index"
+            v-for="(tab, index) in tabs"
+            :key="index"
+            class="tab-item"
+            :class="{ active: currentTab === index }"
+            @click="currentTab = index"
         >
           {{ tab }}
           <div class="active-line" v-if="currentTab === index"></div>
         </div>
       </div>
 
-      <div  class="tabs-right">
+      <div class="tabs-right">
         <span class="history-icon" style="align-content: center; display: flex; gap: 5px; align-items: center">
           <img src="../../../assets/icon/bitcoin/shizhong.svg" alt=""> 全部</span>
       </div>
@@ -74,9 +82,9 @@ const handleCancel = (id) => {
 
     <div v-if="currentTab==1" class="order-list">
       <div
-        v-for="item in orders"
-        :key="item.id"
-        class="order-card"
+          v-for="item in orders"
+          :key="item.id"
+          class="order-card"
       >
         <div class="card-top">
           <div class="coin-info">
@@ -96,9 +104,9 @@ const handleCancel = (id) => {
           </div>
 
           <button
-            v-if="item.canCancel"
-            class="btn-cancel"
-            @click="handleCancel(item.id)"
+              v-if="item.canCancel"
+              class="btn-cancel"
+              @click="handleCancel(item.id)"
           >
             撤单
           </button>
@@ -139,6 +147,7 @@ const handleCancel = (id) => {
 
       </div>
     </div>
+
   </div>
 </template>
 
@@ -319,9 +328,17 @@ const handleCancel = (id) => {
 }
 
 /* 对齐方式 */
-.align-left { align-items: flex-start; }
-.align-center { align-items: center; }
-.align-right { align-items: flex-end; }
+.align-left {
+  align-items: flex-start;
+}
+
+.align-center {
+  align-items: center;
+}
+
+.align-right {
+  align-items: flex-end;
+}
 
 .label {
   font-size: 12px;

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff