Jelajahi Sumber

今日工作12.5 页面增加Tab选项动画 1,消息通知 2,OTC-C2C交易 3,OTC-订单列表 4,ICO 页面美化 1,行情详情 2,贷款-提交信息 实现功能 1,解决行情详情-切换币种弹窗,弹窗显示bug问题 2,熟悉行情模块代码 3,行情委托挂单功能实现 4,行情最新成交功能实现 5,数据监视,做到实时更新

jhaoG 3 minggu lalu
induk
melakukan
47d8511c4d

+ 39 - 38
src/utils/time.js

@@ -5,19 +5,20 @@
  * @returns '1970-01-01 08:00:00'
  */
 export function timestampToTime(time) {
-  var date = new Date(time * 1000)
-  let y = date.getFullYear()
-  let MM = date.getMonth() + 1
-  MM = MM < 10 ? ('0' + MM) : MM
-  let d = date.getDate()
-  d = d < 10 ? ('0' + d) : d
-  let h = date.getHours()
-  h = h < 10 ? ('0' + h) : h
-  let m = date.getMinutes()
-  m = m < 10 ? ('0' + m) : m
-  let s = date.getSeconds()
-  s = s < 10 ? ('0' + s) : s
-  return y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s
+  var date = new Date(time * 1000);
+  let y = date.getFullYear();
+  let MM = date.getMonth() + 1;
+  MM = MM < 10 ? "0" + MM : MM;
+  let d = date.getDate();
+  d = d < 10 ? "0" + d : d;
+  let h = date.getHours();
+  h = h < 10 ? "0" + h : h;
+  let m = date.getMinutes();
+  m = m < 10 ? "0" + m : m;
+  let s = date.getSeconds();
+  s = s < 10 ? "0" + s : s;
+  return h + ":" + m + ":" + s;
+  // return y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s
 }
 
 /**
@@ -26,29 +27,29 @@ export function timestampToTime(time) {
  * @returns Jan
  */
 export function monthChangeEnglish(month) {
-  if (month == '1' || month == '01') {
-    return 'Jan'
-  } else if (month == '2' || month == '02') {
-    return 'Feb'
-  } else if (month == '3' || month == '03') {
-    return 'Mar'
-  } else if (month == '4' || month == '04') {
-    return 'Apr'
-  } else if (month == '5' || month == '05') {
-    return 'May'
-  } else if (month == '6' || month == '06') {
-    return 'Jun'
-  } else if (month == '7' || month == '07') {
-    return 'Jul'
-  } else if (month == '8' || month == '08') {
-    return 'Aug'
-  } else if (month == '9' || month == '09') {
-    return 'Sept'
-  } else if (month == '10' || month == '10') {
-    return 'Oct'
-  } else if (month == '11') {
-    return 'Nov'
-  } else if (month == '12') {
-    return 'Dec'
+  if (month == "1" || month == "01") {
+    return "Jan";
+  } else if (month == "2" || month == "02") {
+    return "Feb";
+  } else if (month == "3" || month == "03") {
+    return "Mar";
+  } else if (month == "4" || month == "04") {
+    return "Apr";
+  } else if (month == "5" || month == "05") {
+    return "May";
+  } else if (month == "6" || month == "06") {
+    return "Jun";
+  } else if (month == "7" || month == "07") {
+    return "Jul";
+  } else if (month == "8" || month == "08") {
+    return "Aug";
+  } else if (month == "9" || month == "09") {
+    return "Sept";
+  } else if (month == "10" || month == "10") {
+    return "Oct";
+  } else if (month == "11") {
+    return "Nov";
+  } else if (month == "12") {
+    return "Dec";
   }
-}
+}

+ 49 - 6
src/views/asset/otc/order/Index.vue

@@ -5,16 +5,34 @@
         class="left-arrow-image"
         src="@/assets/icon/index/left-arrow.svg"
         @click="toPath()" />
-      贷款
+      订单列表
       <div class="save">
         <img src="@/assets/icon/asset/rili.png" alt="" />
       </div>
     </div>
   </div>
   <div class="notifi-classifi">
-    <div class="pf600 fs18 fc121212" @click="messageChange('all')">全部</div>
-    <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('buy')">购买</div>
-    <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('sell')">出售</div>
+    <div
+      class="classifi-item pf600 fs18 fc121212"
+      :class="current == 'all' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+      @click="messageChange('all')">
+      全部
+      <div class="active-line" v-if="current == 'all'"></div>
+    </div>
+    <div
+      class="classifi-item pf600 fs14 fcA8A8A8"
+      :class="current == 'buy' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+      @click="messageChange('buy')">
+      购买
+      <div class="active-line" v-if="current == 'buy'"></div>
+    </div>
+    <div
+      class="classifi-item pf600 fs14 fcA8A8A8"
+      :class="current == 'sell' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+      @click="messageChange('sell')">
+      出售
+      <div class="active-line" v-if="current == 'sell'"></div>
+    </div>
   </div>
   <component :is="currentComponent" />
 </template>
@@ -94,8 +112,33 @@
     width: 345px;
     height: 24px;
 
-    .sys-notifi {
-      margin-left: 40px;
+    .classifi-item {
+      position: relative;
+      margin-left: 43px;
+
+      .active-line {
+        position: absolute;
+        bottom: -6px;
+        left: 50%;
+        transform: translateX(-50%);
+        width: 20px;
+        height: 3px;
+        background-color: #323233;
+        border-radius: 2px;
+      }
+
+      &:first-child {
+        margin-left: 0;
+      }
+    }
+
+    .current-classifi {
+      font-family: "PingFang SC";
+      font-style: normal;
+      font-weight: 600;
+      font-size: 18px;
+      color: #121212;
+      transition: color 0.3s, font-size 0.3s;
     }
   }
 </style>

+ 44 - 5
src/views/asset/otc/transaction/Index.vue

@@ -14,12 +14,26 @@
   </div>
   <div class="index">
     <div class="notifi-classifi">
-      <div class="pf600 fs18 fc121212" @click="messageChange('c2c')">C2C</div>
-      <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('fast')">
+      <div
+        class="classifi-item pf600 fs18 fc121212"
+        :class="current == 'c2c' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('c2c')">
+        C2C
+        <div class="active-line" v-if="current == 'c2c'"></div>
+      </div>
+      <div
+        class="classifi-item pf600 fs14 fcA8A8A8"
+        :class="current == 'fast' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('fast')">
         快捷交易
+        <div class="active-line" v-if="current == 'fast'"></div>
       </div>
-      <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('bulk')">
+      <div
+        class="classifi-item pf600 fs14 fcA8A8A8"
+        :class="current == 'bulk' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('bulk')">
         大宗交易
+        <div class="active-line" v-if="current == 'bulk'"></div>
       </div>
     </div>
     <component :is="currentComponent" />
@@ -118,8 +132,33 @@
       width: 349px;
       height: 24px;
 
-      .sys-notifi {
-        margin-left: 42px;
+      .classifi-item {
+        position: relative;
+        margin-left: 43px;
+
+        .active-line {
+          position: absolute;
+          bottom: -6px;
+          left: 50%;
+          transform: translateX(-50%);
+          width: 20px;
+          height: 3px;
+          background-color: #323233;
+          border-radius: 2px;
+        }
+
+        &:first-child {
+          margin-left: 0;
+        }
+      }
+
+      .current-classifi {
+        font-family: "PingFang SC";
+        font-style: normal;
+        font-weight: 600;
+        font-size: 18px;
+        color: #121212;
+        transition: color 0.3s, font-size 0.3s;
       }
     }
   }

+ 55 - 5
src/views/index/ico/Index.vue

@@ -3,18 +3,40 @@
   <HeaderNav headerText="ICO"></HeaderNav>
   <div class="ico-index">
     <div class="index-classifi">
-      <div class="pf600 fs18 fc121212" @click="messageChange('subscription')">认购</div>
-      <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('placement')">
+      <div
+        class="classifi-item pf600 fs18 fc121212"
+        :class="current == 'subscription' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('subscription')">
+        认购
+        <div class="active-line" v-if="current == 'subscription'"></div>
+      </div>
+      <div
+        class="classifi-item pf600 fs14 fcA8A8A8"
+        :class="current == 'placement' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('placement')">
         配售
+        <div class="active-line" v-if="current == 'placement'"></div>
       </div>
-      <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('lotteryResult')">
+      <div
+        class="classifi-item pf600 fs14 fcA8A8A8"
+        :class="current == 'lotteryResult' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('lotteryResult')">
         中签结果
+        <div class="active-line" v-if="current == 'lotteryResult'"></div>
       </div>
-      <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('coinPreview')">
+      <div
+        class="classifi-item pf600 fs14 fcA8A8A8"
+        :class="current == 'coinPreview' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('coinPreview')">
         新币预览
+        <div class="active-line" v-if="current == 'coinPreview'"></div>
       </div>
-      <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('relus')">
+      <div
+        class="classifi-item pf600 fs14 fcA8A8A8"
+        :class="current == 'relus' ? 'current-classifi' : 'pf600 fs14 fcA8A8A8'"
+        @click="messageChange('relus')">
         ICO规则
+        <div class="active-line" v-if="current == 'relus'"></div>
       </div>
     </div>
     <component :is="currentComponent" />
@@ -59,6 +81,34 @@
       margin-top: 48px;
       width: 349px;
       height: 24px;
+
+      .classifi-item {
+        position: relative;
+
+        .active-line {
+          position: absolute;
+          bottom: -6px;
+          left: 50%;
+          transform: translateX(-50%);
+          width: 20px;
+          height: 3px;
+          background-color: #323233;
+          border-radius: 2px;
+        }
+
+        &:first-child {
+          margin-left: 0;
+        }
+      }
+
+      .current-classifi {
+        font-family: "PingFang SC";
+        font-style: normal;
+        font-weight: 600;
+        font-size: 18px;
+        color: #121212;
+        transition: color 0.3s, font-size 0.3s;
+      }
     }
   }
 </style>

+ 3 - 3
src/views/index/loan/CommitMessage.vue

@@ -93,7 +93,6 @@
     flex-direction: column;
     justify-content: flex-start;
     align-items: center;
-    margin-bottom: 100px;
     margin-top: 48px;
     width: 100%;
 
@@ -133,7 +132,7 @@
     }
 
     .card-type {
-      margin-top: 10px;
+      margin-top: 20px;
       width: 345px;
 
       .type-select {
@@ -161,7 +160,7 @@
       width: 345px;
 
       .number-input {
-        margin-top: 5px;
+        margin-top: -10px;
         width: 345px;
         height: 45px;
 
@@ -268,6 +267,7 @@
 
     .submit {
       margin-top: 21px;
+      margin-bottom: 50px;
       width: 311px;
       height: 40px;
       line-height: 40px;

+ 41 - 6
src/views/market/details/EntrustingOrder.vue

@@ -8,14 +8,21 @@
       <div class="header-sell">卖盘</div>
     </div>
     <div class="order-body">
-      <div class="order-item" v-for="(item, index) in 15" :key="index">
+      <!-- ⭐ 正确循环 newOrderPlacement -->
+      <div class="order-item" v-for="(item, index) in newOrderPlacement" :key="index">
         <div class="item-buy fs400 fs12 fcA8A8A8">{{ index + 1 }}</div>
-        <div class="item-number fs400 fs12 fc444444">37.80K</div>
+        <!-- 买价 -->
+        <div class="item-number fs400 fs12 fc444444">
+          {{ Number(item[0][0]).toFixed(2) }}
+        </div>
         <div class="item-price fs400 fs12">
-          <div class="fc45B26B">40,166.82</div>
-          <div class="price-second fcFF7171">39,962.74</div>
+          <div class="fc45B26B">{{ Number(item[0][1]).toFixed(2) }}</div>
+          <div class="price-second fcFF7171">{{ Number(item[1][1]).toFixed(2) }}</div>
+        </div>
+        <!-- 卖价 -->
+        <div class="item-number2 fs400 fs12 fc444444">
+          {{ Number(item[1][0]).toFixed(2) }}
         </div>
-        <div class="item-number2 fs400 fs12 fc444444">37.80K</div>
         <div class="item-sell fs400 fs12 fcA8A8A8">{{ index + 1 }}</div>
       </div>
     </div>
@@ -25,7 +32,35 @@
     </div>
   </div>
 </template>
-<script setup></script>
+<script setup>
+  import { toRef, watch, defineProps, ref } from "vue";
+
+  const props = defineProps({
+    orderPlacement: {
+      type: [String, Number, Object, Array, Boolean],
+      default: null,
+    },
+  });
+
+  const valueFromParent = toRef(props, "orderPlacement");
+
+  // ⭐ 作为展示用的新数组
+  const newOrderPlacement = ref([]);
+
+  // ⭐ 监听父组件传来的 orderPlacement,自动转换
+  watch(
+    valueFromParent,
+    (newVal) => {
+      if (!newVal || !newVal.bids || !newVal.asks) return;
+
+      // ⭐ 正确转换 bids + asks → newOrderPlacement
+      newOrderPlacement.value = newVal.bids.map((bid, index) => {
+        return [bid, newVal.asks[index]];
+      });
+    },
+    { immediate: true }
+  );
+</script>
 <style lang="less" scoped>
   .entrusting-order {
     width: 100%;

+ 7 - 4
src/views/market/details/Index.vue

@@ -5,7 +5,7 @@
         <img src="../../../assets/icon/market/left-arrow.svg" alt="" />
       </div>
       <div class="header-icon pf600 fs18 fc121212" @click="changeIconFlag = true">
-        BTCUSDT
+        {{ title }}
         <img src="../../../assets/icon/market/btn_triangle_down_bk.svg" alt="" />
       </div>
       <div class="header-func">
@@ -17,14 +17,14 @@
       <div class="pf600 fs18 fc121212" @click="messageChange('marketConditions')">
         行情
       </div>
-      <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('info')">
+      <!-- <div class="sys-notifi pf600 fs14 fcA8A8A8" @click="messageChange('info')">
         信息
       </div>
       <div
         class="sys-notifi pf600 fs14 fcA8A8A8"
         @click="messageChange('transactionData')">
         交易数据
-      </div>
+      </div> -->
     </div>
     <component :is="currentComponent" />
     <ChangeIcon v-show="changeIconFlag" @changeIconClose="changeIconClose"></ChangeIcon>
@@ -36,9 +36,12 @@
   import TransactionData from "./TransactionData.vue";
   import ChangeIcon from "../dialog/ChangeIcon.vue";
   import { ref, computed } from "vue";
-  import { useRouter } from "vue-router";
+  import { useRouter, useRoute } from "vue-router";
 
   const router = useRouter();
+  const route = useRoute();
+
+  const title = route.query.type ? route.query.type.toUpperCase() : "";
 
   const changeIconFlag = ref(false);
   const changeIconClose = () => {

+ 46 - 7
src/views/market/details/LatestTransactions.vue

@@ -7,13 +7,17 @@
       <div class="header-number2">数量(AVAX)</div>
     </div>
     <div class="order-body">
-      <div class="order-item" v-for="(item, index) in 15" :key="index">
-        <div class="item-buy fs400 fs12 fcA8A8A8">13:44:25</div>
-        <div class="item-number fs400 fs12 fc45B26B">买入</div>
+      <div class="order-item" v-for="(item, index) in transactions" :key="index">
+        <div class="item-buy fs400 fs12 fcA8A8A8">{{ timestampToTime(item.T) }}</div>
+        <div
+          class="item-number fs400 fs12"
+          :class="item.m == true ? 'fcDF384C' : 'fc45B26B'">
+          {{ item.m == true ? "卖出" : "买入" }}
+        </div>
         <div class="item-price fs400 fs12">
-          <div class="fc444444">1.2505</div>
+          <div class="fc444444">{{ Number(item.p).toFixed(2) }}</div>
         </div>
-        <div class="item-number2 fs400 fs12 fc444444">40,166.82</div>
+        <div class="item-number2 fs400 fs12 fc444444">{{ item.q }}</div>
       </div>
     </div>
     <div class="buy-sell pf500 fs16 fcFFFFFF">
@@ -22,9 +26,43 @@
     </div>
   </div>
 </template>
-<script setup></script>
+<script setup>
+  import { toRef, watch, defineProps, ref } from "vue";
+  import { timestampToTime } from "../../../utils/time";
+
+  const props = defineProps({
+    latestTransactionData: {
+      type: [Object, Array],
+      default: () => [],
+    },
+  });
+
+  const transactions = ref([]);
+
+  // 处理最新交易数据,始终保留20条
+  watch(
+    () => props.latestTransactionData,
+    (newVal) => {
+      if (Array.isArray(newVal)) {
+        // 如果是数组,直接取最后20条
+        transactions.value = newVal.slice(-20);
+      } else if (newVal && typeof newVal === "object") {
+        // 如果是单条对象
+        transactions.value.push(newVal);
+        if (transactions.value.length > 20) {
+          transactions.value.shift();
+        }
+      }
+    },
+    { immediate: true, deep: true }
+  );
+</script>
 <style lang="less" scoped>
   .latest-order {
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-start;
+    align-items: center;
     width: 100%;
 
     .order-header {
@@ -32,7 +70,7 @@
       flex-direction: row;
       justify-content: flex-start;
       margin-top: 6px;
-      width: 100%;
+      width: 345px;
       height: 24px;
 
       .header-buy {
@@ -68,6 +106,7 @@
       display: flex;
       flex-direction: column;
       justify-content: flex-start;
+      width: 345px;
 
       .order-item {
         display: flex;

+ 473 - 408
src/views/market/details/MarketConditions.vue

@@ -2,16 +2,16 @@
   <div class="market-conditions">
     <div class="market-price">
       <div class="price-left">
-        <div class="left-price pf400 fs14 fc333333">
-          实时价格
-        </div>
-        <div class="left-number pf600 fs20 fc1F2937" :class="getPriceColor(marketInfo.change)">
+        <div class="left-price pf400 fs14 fc333333">实时价格</div>
+        <div
+          class="left-number pf600 fs20 fc1F2937"
+          :class="getPriceColor(marketInfo.change)">
           {{ formatNumber(marketInfo.price) }}
         </div>
         <div class="left-appro pf500 fs14 fcA8A8A8">
           ≈{{ formatNumber(marketInfo.fiatPrice) }}
           <span class="appro pf500 fs14" :class="getUpDownClass(marketInfo.change)">
-            {{ marketInfo.change > 0 ? '+' : '' }}{{ marketInfo.change }}%
+            {{ marketInfo.change > 0 ? "+" : "" }}{{ marketInfo.change }}%
           </span>
         </div>
       </div>
@@ -34,7 +34,9 @@
           </div>
           <div class="right-number-top-number">
             <div class="pf400 fs10 fcA8A8A8">24h 成交额</div>
-            <div class="pf400 fs10 fc2C3131">{{ abbreviateNumber(marketInfo.amount) }}</div>
+            <div class="pf400 fs10 fc2C3131">
+              {{ abbreviateNumber(marketInfo.amount) }}
+            </div>
           </div>
         </div>
       </div>
@@ -47,13 +49,12 @@
         :key="tab"
         class="tab-item"
         :style="currentTab === tab ? { backgroundColor: '#F6465D', color: '#fff' } : {}"
-        @click="switchPeriod(tab)"
-      >
+        @click="switchPeriod(tab)">
         {{ tab }}
       </div>
       <div class="tab-item icon">更多 <span class="triangle">◢</span></div>
       <div class="tab-item icon">
-        <img src="@/assets/icon/bitcoin/lishidingdan.svg" alt="">
+        <img src="@/assets/icon/bitcoin/lishidingdan.svg" alt="" />
       </div>
     </nav>
 
@@ -62,468 +63,532 @@
         ref="klineRef"
         :data="kLineData"
         height="100%"
-        :precision="{ price: getPricePrecision(marketInfo.price), volume: 2 }"
-      />
+        :precision="{ price: getPricePrecision(marketInfo.price), volume: 2 }" />
     </div>
 
     <div class="notifi-classifi">
-      <div class="pf600 fs14" :class="current === 'entrustingOrder' ? 'fc121212' : 'fcA8A8A8'" @click="messageChange('entrustingOrder')">委托挂单</div>
-      <div class="sys-notifi pf600 fs14" :class="current === 'latestTransactions' ? 'fc121212' : 'fcA8A8A8'" @click="messageChange('latestTransactions')">最新成交</div>
+      <div
+        class="pf600 fs14"
+        :class="current === 'entrustingOrder' ? 'fc121212' : 'fcA8A8A8'"
+        @click="messageChange('entrustingOrder')">
+        委托挂单
+      </div>
+      <div
+        class="sys-notifi pf600 fs14"
+        :class="current === 'latestTransactions' ? 'fc121212' : 'fcA8A8A8'"
+        @click="messageChange('latestTransactions')">
+        最新成交
+      </div>
     </div>
 
-    <component :is="currentComponent" :symbol-id="symbolId" />
+    <component
+      :is="currentComponent"
+      :symbol-id="symbolId"
+      :latestTransactionData="latestTransactionData"
+      :orderPlacement="orderPlacement" />
   </div>
 </template>
 
 <script setup>
-import { ref, computed, onMounted, onUnmounted, watch, onBeforeUnmount } from "vue";
-import { useRoute } from "vue-router";
-import { GetCandlestickChart } from "@/api/index.js";
-import EntrustingOrder from "./EntrustingOrder.vue";
-import LatestTransactions from "./LatestTransactions.vue";
-import KlineChart from "@/views/bitcoin/lever/components/KLineChart.vue";
-
-const route = useRoute();
-const symbolId = computed(() => route.query.id || '6');
-
-const currentTab = ref('1d');
-const tabs = ['1h', '6h', '1d', '1w', '1m'];
-const kLineData = ref([]);
-const socket = ref(null);
-const WS_BASE_URL = 'ws://backend.66linknow.com/ws/kline/';
-
-// --- 生产级配置 ---
-const HEARTBEAT_INTERVAL = 15000; // 心跳间隔 15s
-const RECONNECT_DELAY = 3000;     // 重连延迟 3s
-let heartbeatTimer = null;
-let reconnectTimer = null;
-let isUnmounted = false;
-
-const marketInfo = ref({
-  price: '0.00', fiatPrice: '0.00', change: 0.00, high: '0.00', low: '0.00', vol: '0', amount: '0'
-});
-
-const current = ref("entrustingOrder");
-const componentsMap = { entrustingOrder: EntrustingOrder, latestTransactions: LatestTransactions };
-const currentComponent = computed(() => componentsMap[current.value]);
-
-// --- 1. 切换周期 ---
-const switchPeriod = (period) => {
-  if (currentTab.value === period) return;
-
-  currentTab.value = period;
-
-  // 清空数据,触发子组件重置,并重新请求
-  kLineData.value = [];
-  getKlineData();
-};
-
-// --- 2. HTTP 获取历史数据 ---
-const getKlineData = async () => {
-  if (typeof GetCandlestickChart !== 'function') return;
-
-  try {
-    const res = await GetCandlestickChart({
-      symbol: symbolId.value,
-      period: currentTab.value
-    });
+  import { ref, computed, onMounted, onUnmounted, watch, onBeforeUnmount } from "vue";
+  import { useRoute } from "vue-router";
+  import { GetCandlestickChart } from "@/api/index.js";
+  import EntrustingOrder from "./EntrustingOrder.vue";
+  import LatestTransactions from "./LatestTransactions.vue";
+  import KlineChart from "@/views/bitcoin/lever/components/KLineChart.vue";
+
+  const route = useRoute();
+  const symbolId = computed(() => route.query.id || "6");
+
+  const currentTab = ref("1d");
+  const tabs = ["1h", "6h", "1d", "1w", "1m"];
+  const kLineData = ref([]);
+  const socket = ref(null);
+  const WS_BASE_URL = "ws://backend.66linknow.com/ws/kline/";
+
+  // --- 生产级配置 ---
+  const HEARTBEAT_INTERVAL = 15000; // 心跳间隔 15s
+  const RECONNECT_DELAY = 3000; // 重连延迟 3s
+  let heartbeatTimer = null;
+  let reconnectTimer = null;
+  let isUnmounted = false;
+
+  const marketInfo = ref({
+    price: "0.00",
+    fiatPrice: "0.00",
+    change: 0.0,
+    high: "0.00",
+    low: "0.00",
+    vol: "0",
+    amount: "0",
+  });
+
+  const orderPlacement = ref();
+  const latestTransactionData = ref();
+
+  const current = ref("entrustingOrder");
+  const componentsMap = {
+    entrustingOrder: EntrustingOrder,
+    latestTransactions: LatestTransactions,
+  };
+  const currentComponent = computed(() => componentsMap[current.value]);
 
-    let rawList = [];
-    if (Array.isArray(res)) rawList = res;
-    else if (res && Array.isArray(res.data)) rawList = res.data;
-
-    if (rawList.length > 0) {
-      const formattedData = rawList.map(item => ({
-        timestamp: Number(item[0]),
-        open: parseFloat(item[1]),
-        high: parseFloat(item[2]),
-        low: parseFloat(item[3]),
-        close: parseFloat(item[4]),
-        volume: parseFloat(item[5])
-      }));
-      formattedData.sort((a, b) => a.timestamp - b.timestamp);
-      kLineData.value = formattedData;
-
-      // 同步合并:如果 WS 已经有最新价,立即修正历史数据最后一根,防止回跳
-      if (marketInfo.value.price !== '0.00') {
-        const lastBar = formattedData[formattedData.length - 1];
-        const realTimePrice = parseFloat(marketInfo.value.price);
-        lastBar.close = realTimePrice;
-        // 修正高低
-        if (realTimePrice > lastBar.high) lastBar.high = realTimePrice;
-        if (realTimePrice < lastBar.low) lastBar.low = realTimePrice;
-      }
+  // --- 1. 切换周期 ---
+  const switchPeriod = (period) => {
+    if (currentTab.value === period) return;
+
+    currentTab.value = period;
+
+    // 清空数据,触发子组件重置,并重新请求
+    kLineData.value = [];
+    getKlineData();
+  };
+
+  // --- 2. HTTP 获取历史数据 ---
+  const getKlineData = async () => {
+    if (typeof GetCandlestickChart !== "function") return;
+
+    try {
+      const res = await GetCandlestickChart({
+        symbol: symbolId.value,
+        period: currentTab.value,
+      });
+
+      let rawList = [];
+      if (Array.isArray(res)) rawList = res;
+      else if (res && Array.isArray(res.data)) rawList = res.data;
+
+      if (rawList.length > 0) {
+        const formattedData = rawList.map((item) => ({
+          timestamp: Number(item[0]),
+          open: parseFloat(item[1]),
+          high: parseFloat(item[2]),
+          low: parseFloat(item[3]),
+          close: parseFloat(item[4]),
+          volume: parseFloat(item[5]),
+        }));
+        formattedData.sort((a, b) => a.timestamp - b.timestamp);
+        kLineData.value = formattedData;
+
+        // 同步合并:如果 WS 已经有最新价,立即修正历史数据最后一根,防止回跳
+        if (marketInfo.value.price !== "0.00") {
+          const lastBar = formattedData[formattedData.length - 1];
+          const realTimePrice = parseFloat(marketInfo.value.price);
+          lastBar.close = realTimePrice;
+          // 修正高低
+          if (realTimePrice > lastBar.high) lastBar.high = realTimePrice;
+          if (realTimePrice < lastBar.low) lastBar.low = realTimePrice;
+        }
 
-      updateMarketInfoFromKline(formattedData);
+        updateMarketInfoFromKline(formattedData);
+      }
+    } catch (error) {
+      console.error("API Error", error);
     }
-  } catch (error) { console.error("API Error", error); }
-};
-
-const updateMarketInfoFromKline = (data) => {
-  if (!data.length) return;
-  const lastBar = data[data.length - 1];
-
-  // 仅当没数据或 WS 未连接时使用历史数据兜底
-  if (marketInfo.value.price === '0.00' || !socket.value || socket.value.readyState !== 1) {
-    const firstBar = data[0];
-    let maxHigh = -Infinity, minLow = Infinity, totalVol = 0;
-    data.forEach(item => {
-      if (item.high > maxHigh) maxHigh = item.high;
-      if (item.low < minLow) minLow = item.low;
-      totalVol += item.volume;
-    });
-    const changeRate = firstBar.open ? ((lastBar.close - firstBar.open) / firstBar.open) * 100 : 0;
+  };
 
-    marketInfo.value = {
-      price: lastBar.close,
-      change: changeRate.toFixed(2),
-      high: maxHigh, low: minLow, vol: totalVol, amount: totalVol * lastBar.close,
-      fiatPrice: lastBar.close
-    };
-  }
-};
+  const updateMarketInfoFromKline = (data) => {
+    if (!data.length) return;
+    const lastBar = data[data.length - 1];
+
+    // 仅当没数据或 WS 未连接时使用历史数据兜底
+    if (
+      marketInfo.value.price === "0.00" ||
+      !socket.value ||
+      socket.value.readyState !== 1
+    ) {
+      const firstBar = data[0];
+      let maxHigh = -Infinity,
+        minLow = Infinity,
+        totalVol = 0;
+      data.forEach((item) => {
+        if (item.high > maxHigh) maxHigh = item.high;
+        if (item.low < minLow) minLow = item.low;
+        totalVol += item.volume;
+      });
+      const changeRate = firstBar.open
+        ? ((lastBar.close - firstBar.open) / firstBar.open) * 100
+        : 0;
 
-// --- 3. WS 连接 (含心跳设计) ---
-const connectWebSocket = () => {
-  // 清理旧资源
-  closeWebSocket();
+      marketInfo.value = {
+        price: lastBar.close,
+        change: changeRate.toFixed(2),
+        high: maxHigh,
+        low: minLow,
+        vol: totalVol,
+        amount: totalVol * lastBar.close,
+        fiatPrice: lastBar.close,
+      };
+    }
+  };
 
-  const symbolStr = String(route.query.type || 'btcusdt').toLowerCase();
-  const url = `${WS_BASE_URL}?symbol=${symbolStr}`;
+  // --- 3. WS 连接 (含心跳设计) ---
+  const connectWebSocket = () => {
+    // 清理旧资源
+    closeWebSocket();
+    const symbolStr = String(route.query.type || "btcusdt").toLowerCase();
+    const url = `${WS_BASE_URL}?symbol=${symbolStr}`;
 
-  console.log('WS 连接:', url);
+    console.log("WS 连接:", url);
 
-  try {
-    socket.value = new WebSocket(url);
+    try {
+      socket.value = new WebSocket(url);
 
-    socket.value.onopen = () => {
-      console.log('✅ WS Connected');
-      startHeartbeat(); // 启动心跳
-    };
+      socket.value.onopen = () => {
+        console.log("✅ WS Connected");
+        startHeartbeat(); // 启动心跳
+      };
 
-    socket.value.onmessage = (event) => {
-      handleSocketMessage(event.data);
-    };
+      socket.value.onmessage = (event) => {
+        handleSocketMessage(event.data);
+      };
 
-    socket.value.onclose = () => {
-      stopHeartbeat(); // 停止心跳
+      socket.value.onclose = () => {
+        stopHeartbeat(); // 停止心跳
+        if (!isUnmounted) {
+          console.log("⚠️ WS Closed, reconnecting...");
+          clearTimeout(reconnectTimer);
+          reconnectTimer = setTimeout(() => connectWebSocket(), RECONNECT_DELAY);
+        }
+      };
+
+      socket.value.onerror = (err) => {
+        // onerror 通常会触发 onclose,由 onclose 处理重连
+        console.error("❌ WS Error", err);
+      };
+    } catch (e) {
       if (!isUnmounted) {
-        console.log('⚠️ WS Closed, reconnecting...');
-        clearTimeout(reconnectTimer);
         reconnectTimer = setTimeout(() => connectWebSocket(), RECONNECT_DELAY);
       }
-    };
-
-    socket.value.onerror = (err) => {
-      // onerror 通常会触发 onclose,由 onclose 处理重连
-      console.error('❌ WS Error', err);
-    };
-  } catch (e) {
-    if (!isUnmounted) {
-      reconnectTimer = setTimeout(() => connectWebSocket(), RECONNECT_DELAY);
     }
-  }
-};
+  };
 
-const closeWebSocket = () => {
-  if (socket.value) {
-    socket.value.close();
-    socket.value = null;
-  }
-  stopHeartbeat();
-  clearTimeout(reconnectTimer);
-};
-
-// --- 心跳逻辑 ---
-const startHeartbeat = () => {
-  stopHeartbeat();
-  heartbeatTimer = setInterval(() => {
-    if (socket.value && socket.value.readyState === WebSocket.OPEN) {
-      // 发送 ping,具体格式看后端要求,一般是字符串 'ping' 或 JSON
-      socket.value.send("ping");
+  const closeWebSocket = () => {
+    if (socket.value) {
+      socket.value.close();
+      socket.value = null;
     }
-  }, HEARTBEAT_INTERVAL);
-};
-
-const stopHeartbeat = () => {
-  if (heartbeatTimer) {
-    clearInterval(heartbeatTimer);
-    heartbeatTimer = null;
-  }
-};
-
-// --- 辅助:获取周期对应的毫秒数 ---
-const getPeriodMs = (period) => {
-  const map = {
-    '1m': 60 * 1000,
-    '5m': 5 * 60 * 1000,
-    '15m': 15 * 60 * 1000,
-    '30m': 30 * 60 * 1000,
-    '1h': 60 * 60 * 1000,
-    '4h': 4 * 60 * 60 * 1000,
-    '6h': 6 * 60 * 60 * 1000,
-    '1d': 24 * 60 * 60 * 1000,
-    '1w': 7 * 24 * 60 * 60 * 1000,
-    '1M': 30 * 24 * 60 * 60 * 1000
+    stopHeartbeat();
+    clearTimeout(reconnectTimer);
   };
-  return map[period] || 60 * 60 * 1000;
-}
 
-// --- 4. 核心:处理实时消息 (24hrTicker) ---
-const handleSocketMessage = (msgStr) => {
-  try {
-    // 忽略心跳响应
-    if (msgStr === 'pong') return;
+  // --- 心跳逻辑 ---
+  const startHeartbeat = () => {
+    stopHeartbeat();
+    heartbeatTimer = setInterval(() => {
+      if (socket.value && socket.value.readyState === WebSocket.OPEN) {
+        // 发送 ping,具体格式看后端要求,一般是字符串 'ping' 或 JSON
+        socket.value.send("ping");
+      }
+    }, HEARTBEAT_INTERVAL);
+  };
 
-    const rawData = JSON.parse(msgStr);
-    const msg = rawData.data || rawData;
+  const stopHeartbeat = () => {
+    if (heartbeatTimer) {
+      clearInterval(heartbeatTimer);
+      heartbeatTimer = null;
+    }
+  };
 
-    if (msg.e === "24hrTicker") {
-      marketInfo.value = {
-        price: msg.c, change: parseFloat(msg.P), high: msg.h, low: msg.l, vol: msg.v, amount: msg.q, fiatPrice: msg.c
-      };
+  // --- 辅助:获取周期对应的毫秒数 ---
+  const getPeriodMs = (period) => {
+    const map = {
+      "1m": 60 * 1000,
+      "5m": 5 * 60 * 1000,
+      "15m": 15 * 60 * 1000,
+      "30m": 30 * 60 * 1000,
+      "1h": 60 * 60 * 1000,
+      "4h": 4 * 60 * 60 * 1000,
+      "6h": 6 * 60 * 60 * 1000,
+      "1d": 24 * 60 * 60 * 1000,
+      "1w": 7 * 24 * 60 * 60 * 1000,
+      "1M": 30 * 24 * 60 * 60 * 1000,
+    };
+    return map[period] || 60 * 60 * 1000;
+  };
 
-      if (kLineData.value.length > 0) {
-        const lastIndex = kLineData.value.length - 1;
-        const lastBar = kLineData.value[lastIndex];
-        const newPrice = parseFloat(msg.c);
-        const currentTime = Number(msg.E); // 事件时间
-        const periodMs = getPeriodMs(currentTab.value);
-
-        // 标准时间戳对齐算法: (当前时间 / 周期) * 周期
-        const currentBarStart = Math.floor(currentTime / periodMs) * periodMs;
-
-        // 如果计算出的起始时间 > 最后一根的起始时间,说明跨周期了,生成新 K 线
-        if (currentBarStart > lastBar.timestamp) {
-          const newBar = {
-            timestamp: currentBarStart,
-            open: newPrice,
-            high: newPrice,
-            low: newPrice,
-            close: newPrice,
-            volume: 0
-          };
-          // 扩展运算符触发更新
-          kLineData.value = [...kLineData.value, newBar];
-
-        } else {
-          // 还在当前周期内,更新最后一根
-          const updatedBar = {
-            ...lastBar,
-            close: newPrice,
-            high: Math.max(lastBar.high, newPrice),
-            low: Math.min(lastBar.low, newPrice)
-          };
-          kLineData.value.splice(lastIndex, 1, updatedBar);
+  // --- 4. 核心:处理实时消息 (24hrTicker) ---
+  const handleSocketMessage = (msgStr) => {
+    try {
+      // 忽略心跳响应
+      if (msgStr === "pong") return;
+
+      const rawData = JSON.parse(msgStr);
+      const msg = rawData.data || rawData;
+      // console.log(rawData);
+      if (msg.e === "24hrTicker") {
+        marketInfo.value = {
+          price: msg.c,
+          change: parseFloat(msg.P),
+          high: msg.h,
+          low: msg.l,
+          vol: msg.v,
+          amount: msg.q,
+          fiatPrice: msg.c,
+        };
+
+        if (kLineData.value.length > 0) {
+          const lastIndex = kLineData.value.length - 1;
+          const lastBar = kLineData.value[lastIndex];
+          const newPrice = parseFloat(msg.c);
+          const currentTime = Number(msg.E); // 事件时间
+          const periodMs = getPeriodMs(currentTab.value);
+
+          // 标准时间戳对齐算法: (当前时间 / 周期) * 周期
+          const currentBarStart = Math.floor(currentTime / periodMs) * periodMs;
+
+          // 如果计算出的起始时间 > 最后一根的起始时间,说明跨周期了,生成新 K 线
+          if (currentBarStart > lastBar.timestamp) {
+            const newBar = {
+              timestamp: currentBarStart,
+              open: newPrice,
+              high: newPrice,
+              low: newPrice,
+              close: newPrice,
+              volume: 0,
+            };
+            // 扩展运算符触发更新
+            kLineData.value = [...kLineData.value, newBar];
+          } else {
+            // 还在当前周期内,更新最后一根
+            const updatedBar = {
+              ...lastBar,
+              close: newPrice,
+              high: Math.max(lastBar.high, newPrice),
+              low: Math.min(lastBar.low, newPrice),
+            };
+            kLineData.value.splice(lastIndex, 1, updatedBar);
+          }
         }
+      } else if (rawData.stream == String(route.query.type) + "@depth20@1000ms") {
+        orderPlacement.value = rawData.data;
+      } else if (rawData.stream == String(route.query.type) + "@aggTrade") {
+        latestTransactionData.value = rawData.data;
+      }
+    } catch (e) {}
+  };
+
+  // --- 页面可见性监听 (切屏回来自动重连) ---
+  const handleVisibilityChange = () => {
+    if (document.visibilityState === "visible") {
+      if (!socket.value || socket.value.readyState !== WebSocket.OPEN) {
+        console.log("👀 Page Visible, reconnecting...");
+        connectWebSocket();
       }
     }
-  } catch (e) {}
-};
-
-// --- 页面可见性监听 (切屏回来自动重连) ---
-const handleVisibilityChange = () => {
-  if (document.visibilityState === 'visible') {
-    if (!socket.value || socket.value.readyState !== WebSocket.OPEN) {
-      console.log('👀 Page Visible, reconnecting...');
+  };
+
+  onMounted(() => {
+    isUnmounted = false;
+    getKlineData();
+    connectWebSocket();
+    document.addEventListener("visibilitychange", handleVisibilityChange);
+  });
+
+  onBeforeUnmount(() => {
+    isUnmounted = true;
+    closeWebSocket();
+    document.removeEventListener("visibilitychange", handleVisibilityChange);
+  });
+
+  watch(
+    symbolId,
+    () => {
+      kLineData.value = [];
+      getKlineData();
       connectWebSocket();
-    }
-  }
-};
-
-onMounted(() => {
-  isUnmounted = false;
-  getKlineData();
-  connectWebSocket();
-  document.addEventListener('visibilitychange', handleVisibilityChange);
-});
-
-onBeforeUnmount(() => {
-  isUnmounted = true;
-  closeWebSocket();
-  document.removeEventListener('visibilitychange', handleVisibilityChange);
-});
-
-watch(symbolId, () => {
-  kLineData.value = [];
-  getKlineData();
-  connectWebSocket();
-}, { immediate: false });
-
-const messageChange = (key) => { current.value = key; };
-const formatNumber = (num) => {
-  if (!num) return '0.00';
-  const n = Number(num);
-  return n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 6 });
-};
-const abbreviateNumber = (value) => {
-  if (!value) return '0.00';
-  let num = parseFloat(value);
-  if (isNaN(num)) return '0.00';
-  if (num >= 1e9) return (num / 1e9).toFixed(2) + 'B';
-  if (num >= 1e6) return (num / 1e6).toFixed(2) + 'M';
-  if (num >= 1e3) return (num / 1e3).toFixed(2) + 'K';
-  return num.toFixed(2);
-};
-const getPricePrecision = (price) => price < 1 ? 6 : (price < 10 ? 4 : 2);
-const getPriceColor = (change) => change >= 0 ? 'fc45B26B' : 'fcF6465D';
-const getUpDownClass = (change) => change >= 0 ? 'fc45B26B' : 'fcF6465D';
+    },
+    { immediate: false }
+  );
+
+  const messageChange = (key) => {
+    current.value = key;
+  };
+  const formatNumber = (num) => {
+    if (!num) return "0.00";
+    const n = Number(num);
+    return n.toLocaleString("en-US", {
+      minimumFractionDigits: 2,
+      maximumFractionDigits: 6,
+    });
+  };
+  const abbreviateNumber = (value) => {
+    if (!value) return "0.00";
+    let num = parseFloat(value);
+    if (isNaN(num)) return "0.00";
+    if (num >= 1e9) return (num / 1e9).toFixed(2) + "B";
+    if (num >= 1e6) return (num / 1e6).toFixed(2) + "M";
+    if (num >= 1e3) return (num / 1e3).toFixed(2) + "K";
+    return num.toFixed(2);
+  };
+  const getPricePrecision = (price) => (price < 1 ? 6 : price < 10 ? 4 : 2);
+  const getPriceColor = (change) => (change >= 0 ? "fc45B26B" : "fcF6465D");
+  const getUpDownClass = (change) => (change >= 0 ? "fc45B26B" : "fcF6465D");
 </script>
 
 <style lang="less" scoped>
-.fc45B26B { color: #2EBD85 !important; }
-.fcF6465D { color: #F6465D !important; }
-.fc1F2937 { color: #1F2937; }
-
-/* 保持之前的样式布局 */
-.time-tabs {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  width: 100%;
-  box-sizing: border-box;
-  padding-top: 10px;
-  padding-bottom: 0px;
-  padding-left: 15px;
-  padding-right: 15px;
-}
-
-.tab-item {
-  font-size: 14px;
-  color: #929AA5;
-  padding: 4px 10px;
-  border-radius: 6px;
-  cursor: pointer;
-  font-weight: 500;
-  transition: all 0.2s;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-.tab-item.icon {
-  color: #929AA5;
-  font-size: 12px;
-  padding: 4px 4px;
-}
-
-.triangle {
-  font-size: 8px;
-  margin-left: 2px;
-  transform: scale(0.9);
-}
-
-.tab-item img {
-  display: block;
-  height: 16px;
-  width: auto;
-}
-
-.market-conditions {
-  display: flex;
-  flex-direction: column;
-  justify-content: flex-start;
-  align-items: center;
-  width: 100%;
-
-  .market-price {
+  .fc45B26B {
+    color: #2ebd85 !important;
+  }
+  .fcF6465D {
+    color: #f6465d !important;
+  }
+  .fc1F2937 {
+    color: #1f2937;
+  }
+
+  /* 保持之前的样式布局 */
+  .time-tabs {
     display: flex;
-    flex-direction: row;
+    align-items: center;
     justify-content: space-between;
-    margin-top: 8px;
     width: 100%;
-    height: 73px;
-    padding: 0 15px;
     box-sizing: border-box;
+    padding-top: 10px;
+    padding-bottom: 0px;
+    padding-left: 15px;
+    padding-right: 15px;
+  }
 
-    .price-left {
-      display: flex;
-      flex-direction: column;
-      justify-content: flex-start;
-      width: 144px;
-      height: 69px;
+  .tab-item {
+    font-size: 14px;
+    color: #929aa5;
+    padding: 4px 10px;
+    border-radius: 6px;
+    cursor: pointer;
+    font-weight: 500;
+    transition: all 0.2s;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
 
-      .left-price {
-        display: flex;
-        flex-direction: row;
-        justify-content: flex-start;
-        align-items: center;
-        height: 18px;
+  .tab-item.icon {
+    color: #929aa5;
+    font-size: 12px;
+    padding: 4px 4px;
+  }
 
-        img {
-          margin-left: 5px;
-          width: 8px;
-          height: 4px;
-        }
-      }
+  .triangle {
+    font-size: 8px;
+    margin-left: 2px;
+    transform: scale(0.9);
+  }
 
-      .left-number {
-        margin-top: 5px;
-      }
+  .tab-item img {
+    display: block;
+    height: 16px;
+    width: auto;
+  }
 
-      .left-appro {
+  .market-conditions {
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-start;
+    align-items: center;
+    margin-bottom: 50px;
+    width: 100%;
+
+    .market-price {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      margin-top: 8px;
+      width: 100%;
+      height: 73px;
+      padding: 0 15px;
+      box-sizing: border-box;
+
+      .price-left {
         display: flex;
-        flex-direction: row;
+        flex-direction: column;
         justify-content: flex-start;
-        align-items: center;
-        margin-top: 3px;
+        width: 144px;
+        height: 69px;
+
+        .left-price {
+          display: flex;
+          flex-direction: row;
+          justify-content: flex-start;
+          align-items: center;
+          height: 18px;
+
+          img {
+            margin-left: 5px;
+            width: 8px;
+            height: 4px;
+          }
+        }
 
-        .appro {
-          margin-left: 9px;
+        .left-number {
+          margin-top: 5px;
         }
-      }
-    }
 
-    .price-right {
-      display: flex;
-      flex-direction: column;
-      justify-content: flex-start;
-      height: 100%;
+        .left-appro {
+          display: flex;
+          flex-direction: row;
+          justify-content: flex-start;
+          align-items: center;
+          margin-top: 3px;
 
-      .right-number-top, .right-number-bottom {
+          .appro {
+            margin-left: 9px;
+          }
+        }
+      }
+
+      .price-right {
         display: flex;
-        flex-direction: row;
-        justify-content: flex-end;
-        width: 100%;
-        height: 32px;
-
-        .right-number-top-price, .right-number-top-number {
-           margin-left: 10px;
-           text-align: right;
+        flex-direction: column;
+        justify-content: flex-start;
+        height: 100%;
+
+        .right-number-top,
+        .right-number-bottom {
+          display: flex;
+          flex-direction: row;
+          justify-content: flex-end;
+          width: 100%;
+          height: 32px;
+
+          .right-number-top-price,
+          .right-number-top-number {
+            margin-left: 10px;
+            text-align: right;
             div {
               height: 16px;
               line-height: 16px;
               text-align: end;
             }
+          }
+        }
+        .right-number-bottom {
+          margin-top: 9px;
         }
-      }
-      .right-number-bottom {
-        margin-top: 9px;
       }
     }
-  }
-
-  .k-line-main {
-    height: 50vh;
-    min-height: 350px;
-    width: 100%;
-    padding: 0 15px;
-  }
 
-  .notifi-classifi {
-    display: flex;
-    flex-direction: row;
-    justify-content: flex-start;
-    align-items: flex-end;
-    margin-top: 15px;
-    width: 100%;
-    padding: 0 15px;
-    box-sizing: border-box;
-    height: 24px;
+    .k-line-main {
+      height: 50vh;
+      min-height: 350px;
+      width: 100%;
+      padding: 0 15px;
+    }
 
-    .sys-notifi {
-      margin-left: 47px;
+    .notifi-classifi {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: flex-end;
+      margin-top: 15px;
+      width: 100%;
+      padding: 0 15px;
+      box-sizing: border-box;
+      height: 24px;
+
+      .sys-notifi {
+        margin-left: 47px;
+      }
     }
   }
-}
-</style>
+</style>

+ 2 - 2
src/views/market/dialog/ChangeIcon.vue

@@ -83,7 +83,7 @@
     position: fixed;
     left: 0;
     top: 0;
-    z-index: 1;
+    z-index: 10;
     display: flex;
     flex-direction: column;
     justify-content: flex-end;
@@ -151,7 +151,7 @@
 
         img {
           position: absolute;
-          top: 15px;
+          top: 26.5px;
           left: 14px;
           width: 17px;
           height: 17px;