Hexinkui 3 недель назад
Родитель
Сommit
9c2526bc87

Разница между файлами не показана из-за своего большого размера
+ 241 - 152
package-lock.json


+ 1 - 1
package.json

@@ -10,7 +10,7 @@
     "amfe-flexible": "^2.2.1",
     "amfe-flexible": "^2.2.1",
     "axios": "^1.13.2",
     "axios": "^1.13.2",
     "html2canvas": "^1.4.1",
     "html2canvas": "^1.4.1",
-    "klinecharts": "^8.6.3",
+    "klinecharts": "^9.7.1",
     "postcss-pxtorem": "^6.1.0",
     "postcss-pxtorem": "^6.1.0",
     "vant": "^4.9.21",
     "vant": "^4.9.21",
     "vue": "^3.2.13",
     "vue": "^3.2.13",

+ 7 - 7
src/views/bitcoin/lever/CryptocurrencyTrading.vue

@@ -1,12 +1,12 @@
-<script setup>
-
-</script>
-
 <template>
 <template>
-  <div style="margin-top: 60px">开发中</div>
-
+  <div class="trade-page">
+    <h2>BTC/USDT 永续</h2>
+  </div>
 </template>
 </template>
 
 
-<style scoped lang="less">
+<script setup>
+</script>
+
+<style>
 
 
 </style>
 </style>

+ 2 - 2
src/views/bitcoin/lever/TradeSeconds.vue

@@ -63,7 +63,7 @@
     <!-- 这里的 chart-wrapper 负责控制 padding 和高度 -->
     <!-- 这里的 chart-wrapper 负责控制 padding 和高度 -->
     <div class="chart-wrapper">
     <div class="chart-wrapper">
       <!-- 引入封装好的组件,只需传数据和高度 -->
       <!-- 引入封装好的组件,只需传数据和高度 -->
-      <KlineChart
+      <TradeChart
         :data="kLineData"
         :data="kLineData"
         height="100%"
         height="100%"
       />
       />
@@ -83,7 +83,7 @@ import ChooseThisCycle from './components/ChooseThisCycle.vue'
 import sellOrder from '@/views/bitcoin/components/sellOrder.vue'
 import sellOrder from '@/views/bitcoin/components/sellOrder.vue'
 
 
 // 1. 引入新封装的组件 (请确保路径正确)
 // 1. 引入新封装的组件 (请确保路径正确)
-import KlineChart from '@/views/bitcoin/lever/components/KLineChart.vue'
+import TradeChart from '@/views/bitcoin/lever/components/TradeChart.vue'
 
 
 const route = useRoute()
 const route = useRoute()
 const symbolTitle = ref(route.params.id || 'BTCUSDT')
 const symbolTitle = ref(route.params.id || 'BTCUSDT')

+ 0 - 133
src/views/bitcoin/lever/components/KLineChart.vue

@@ -1,133 +0,0 @@
-<template>
-  <div class="kline-wrapper" :style="{ height: height }">
-    <div ref="chartContainer" class="kline-chart"></div>
-  </div>
-</template>
-
-<script setup>
-import { onMounted, onBeforeUnmount, ref, watch, nextTick, toRaw } from 'vue'
-import * as klinecharts from 'klinecharts'
-
-const props = defineProps({
-  data: { type: Array, default: () => [] },
-  height: { type: String, default: '100%' },
-  precision: { type: Object, default: () => ({ price: 2, volume: 2 }) },
-  colors: {
-    type: Object,
-    default: () => ({
-      up: '#2EBD85',
-      down: '#F6465D',
-      grid: '#F2F4F6',
-      text: '#929AA5',
-      targetLine: '#4A6EF5'
-    })
-  }
-})
-
-const chartContainer = ref(null)
-let chartInstance = null
-
-const initChart = () => {
-  if (!chartContainer.value) return
-  if (chartInstance) klinecharts.dispose(chartContainer.value)
-
-  chartInstance = klinecharts.init(chartContainer.value)
-
-  // 设置精度
-  const { price, volume } = props.precision
-  if (chartInstance.setPriceVolumePrecision) {
-    chartInstance.setPriceVolumePrecision(price, volume)
-  } else if (chartInstance.setPrecision) {
-    chartInstance.setPrecision(price, volume)
-  }
-
-  // 样式配置
-  const { up, down, grid, text, targetLine } = props.colors
-  chartInstance.setStyleOptions({
-    grid: { show: true, horizontal: { show: true, size: 1, color: grid, style: 'dash', dashValue: [5, 5] }, vertical: { show: false } },
-    candle: {
-      type: 'candle_solid',
-      bar: { upColor: up, downColor: down, noChangeColor: up },
-      priceMark: {
-        show: true,
-        last: { show: true, upColor: up, downColor: down, line: { show: true, style: 'dash' }, text: { show: true, color: '#FFF', paddingLeft: 4, paddingRight: 4, borderRadius: 2 } }
-      },
-      tooltip: { showRule: 'follow_cross', showType: 'rect', dataSource: 'none' }
-    },
-    xAxis: { axisLine: { show: false }, tickLine: { show: false }, tickText: { color: text, size: 10, paddingTop: 8 } },
-    yAxis: { inside: true, axisLine: { show: false }, tickLine: { show: false }, tickText: { color: text, size: 10, paddingLeft: 8 } },
-  })
-
-  chartInstance.createTechnicalIndicator('VOL', false, { id: 'pane_1', heightRatio: 0.2 })
-
-  // 初始加载
-  if (props.data && props.data.length > 0) {
-    chartInstance.applyNewData(toRaw(props.data))
-  }
-}
-
-// --- 🔥 核心修复:智能判断是“更新”还是“重置” ---
-watch(() => props.data, (newData) => {
-  if (!chartInstance) return
-
-  const rawData = toRaw(newData)
-  const currentList = chartInstance.getDataList()
-
-  // 1. 如果新数据为空,清空图表
-  if (rawData.length === 0) {
-    chartInstance.clearData()
-    return
-  }
-
-  // 2. 如果当前图表为空,直接加载
-  if (currentList.length === 0) {
-    chartInstance.applyNewData(rawData)
-    return
-  }
-
-  // 3. 🔥 关键判断:
-  // 如果第一根 K 线的时间戳变了,说明切换了周期或币种 -> 全量重置
-  const firstOld = currentList[0]
-  const firstNew = rawData[0]
-  if (firstOld.timestamp !== firstNew.timestamp) {
-    chartInstance.applyNewData(rawData)
-    return
-  }
-
-  // 4. 如果第一根时间没变,说明是实时跳动或追加 -> 增量更新
-  if (rawData.length > 0) {
-    const lastData = rawData[rawData.length - 1]
-    chartInstance.updateData(lastData)
-  }
-}, { deep: true })
-
-// 监听精度
-watch(() => props.precision, (val) => {
-  if (chartInstance) {
-    if (chartInstance.setPriceVolumePrecision) chartInstance.setPriceVolumePrecision(val.price, val.volume)
-    else if (chartInstance.setPrecision) chartInstance.setPrecision(val.price, val.volume)
-  }
-}, { deep: true })
-
-onMounted(() => {
-  nextTick(() => initChart())
-  window.addEventListener('resize', handleResize)
-})
-
-onBeforeUnmount(() => {
-  window.removeEventListener('resize', handleResize)
-  if (chartInstance) {
-    klinecharts.dispose(chartContainer.value)
-    chartInstance = null
-  }
-})
-
-const handleResize = () => {
-  if (chartInstance) chartInstance.resize()
-}
-</script>
-
-<style scoped>
-.kline-wrapper { width: 100%; position: relative; }
-.kline-chart { width: 100%; height: 100%; }
-</style>

+ 0 - 0
src/views/bitcoin/lever/components/TradeChart.vue


+ 0 - 594
src/views/market/details/MarketConditions.vue

@@ -1,594 +0,0 @@
-<template>
-  <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)">
-          {{ 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 }}%
-          </span>
-        </div>
-      </div>
-
-      <div class="price-right">
-        <div class="right-number-top">
-          <div class="right-number-top-price">
-            <div class="pf400 fs10 fcA8A8A8">24h 最高价</div>
-            <div class="pf400 fs10 fc2C3131">{{ formatNumber(marketInfo.high) }}</div>
-          </div>
-          <div class="right-number-top-number">
-            <div class="pf400 fs10 fcA8A8A8">24h 成交量</div>
-            <div class="pf400 fs10 fc2C3131">{{ abbreviateNumber(marketInfo.vol) }}</div>
-          </div>
-        </div>
-        <div class="right-number-bottom">
-          <div class="right-number-top-price">
-            <div class="pf400 fs10 fcA8A8A8">24h 最低价</div>
-            <div class="pf400 fs10 fc2C3131">{{ formatNumber(marketInfo.low) }}</div>
-          </div>
-          <div class="right-number-top-number">
-            <div class="pf400 fs10 fcA8A8A8">24h 成交额</div>
-            <div class="pf400 fs10 fc2C3131">
-              {{ abbreviateNumber(marketInfo.amount) }}
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <!-- 周期切换 Tab -->
-    <nav class="time-tabs">
-      <div
-        v-for="tab in tabs"
-        :key="tab"
-        class="tab-item"
-        :style="currentTab === tab ? { backgroundColor: '#F6465D', color: '#fff' } : {}"
-        @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="" />
-      </div>
-    </nav>
-
-    <div class="k-line-main">
-      <KlineChart
-        ref="klineRef"
-        :data="kLineData"
-        height="100%"
-        :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>
-
-    <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.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]);
-
-  // --- 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);
-      }
-    } 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,
-      };
-    }
-  };
-
-  // --- 3. WS 连接 (含心跳设计) ---
-  const connectWebSocket = () => {
-    // 清理旧资源
-    closeWebSocket();
-    const symbolStr = String(route.query.type || "btcusdt").toLowerCase();
-    const url = `${WS_BASE_URL}?symbol=${symbolStr}`;
-
-    console.log("WS 连接:", url);
-
-    try {
-      socket.value = new WebSocket(url);
-
-      socket.value.onopen = () => {
-        console.log("✅ WS Connected");
-        startHeartbeat(); // 启动心跳
-      };
-
-      socket.value.onmessage = (event) => {
-        handleSocketMessage(event.data);
-      };
-
-      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) {
-        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");
-      }
-    }, 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,
-    };
-    return map[period] || 60 * 60 * 1000;
-  };
-
-  // --- 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();
-      }
-    }
-  };
-
-  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");
-</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;
-    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: column;
-        justify-content: flex-start;
-        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;
-          }
-        }
-
-        .left-number {
-          margin-top: 5px;
-        }
-
-        .left-appro {
-          display: flex;
-          flex-direction: row;
-          justify-content: flex-start;
-          align-items: center;
-          margin-top: 3px;
-
-          .appro {
-            margin-left: 9px;
-          }
-        }
-      }
-
-      .price-right {
-        display: flex;
-        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;
-        }
-      }
-    }
-
-    .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;
-
-      .sys-notifi {
-        margin-left: 47px;
-      }
-    }
-  }
-</style>

Некоторые файлы не были показаны из-за большого количества измененных файлов