|
|
@@ -0,0 +1,1155 @@
|
|
|
+<template>
|
|
|
+ <div class="calculator-page">
|
|
|
+ <div class="nav-bar">
|
|
|
+ <div class="nav-left" @click="$router.back()">
|
|
|
+ <div>
|
|
|
+ <VanIcon size="18" name="arrow-left"/>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="nav-title">期权</div>
|
|
|
+ <div class="nav-right"></div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div class="page-container">
|
|
|
+ <header class="header">
|
|
|
+ <div class="left" style="display: flex; align-items: center;">
|
|
|
+ <img class="fc333333" src="@/assets/icon/bitcoin/menu.svg" alt="">
|
|
|
+ <h1 class="title">BTCUSDT</h1>
|
|
|
+ </div>
|
|
|
+ <div class="right">
|
|
|
+ <img src="@/assets/icon/bitcoin/den.svg" alt="" @click="showFunctions = true">
|
|
|
+ </div>
|
|
|
+ </header>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ <nav class="time-tabs">
|
|
|
+ <div
|
|
|
+ v-for="tab in tabs"
|
|
|
+ :key="tab"
|
|
|
+ class="tab-item"
|
|
|
+ :class="{ active: currentTab === 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="">
|
|
|
+ </div>
|
|
|
+ </nav>
|
|
|
+
|
|
|
+ <div class="chart-wrapper">
|
|
|
+ <div id="k-line-chart" class="kline-container"></div>
|
|
|
+ </div>
|
|
|
+ <section class="market-info">
|
|
|
+ <div class="price-block">
|
|
|
+ <div class="fs12 fcA8A8A8">指数价格</div>
|
|
|
+ <div class="current-price">78,776.76</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="stat-grid">
|
|
|
+ <div class="stat-item">
|
|
|
+ <span class="label fcA8A8A8">24h 最高价</span>
|
|
|
+ <span class="label fcDF384C">24h 成交量 </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <span class="label fcA8A8A8">24h 最低价</span>
|
|
|
+ <span class="value">78,776.76</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <div class="stat-item">
|
|
|
+
|
|
|
+ <span class="label fcA8A8A8">到期时间</span>
|
|
|
+ <span class="value">01:00:00</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </section>
|
|
|
+ <div style="margin: 0 auto">
|
|
|
+ <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-lb1l pf400 fs14 fcFF7171">
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ </div>
|
|
|
+ <div class="menu-content-lb1r pf400 fs14 fc444444">
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="menu-content-lb2">
|
|
|
+ <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-lb1l pf400 fs14 fc333333">
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+ <span>40,166.82</span>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ </div>
|
|
|
+ <div class="menu-content-lb1r pf400 fs14 fc444444">
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+ <span>37.80K</span>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="menu-content-lb1">
|
|
|
+ <div class="menu-content-lb1l pf400 fs12 fc333333" @click="isPickerVisible = true">
|
|
|
+ <span class="fs12">{{ displayLabel }}</span>
|
|
|
+ <img src="@/assets/icon/bitcoin/shendul.svg" alt="">
|
|
|
+ </div>
|
|
|
+ <div class="menu-content-lb1r pf400 fs14 fc444444">
|
|
|
+ <img src="@/assets/icon/bitcoin/shendur.svg" alt="">
|
|
|
+ <img v-if="isassetlessState" src="@/assets/icon/bitcoin/wuzichan.svg" alt="">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <assetlessStateData v-if="isassetlessState"></assetlessStateData>
|
|
|
+ <SellTradingStatusData v-if="isassetlessState"></SellTradingStatusData>
|
|
|
+
|
|
|
+ <div class="menu-content-r">
|
|
|
+ <div class="menu-content-rb pf400 fs14">
|
|
|
+ <div class="menu-content-rb1 fs14 fc333333" @click="showInfo = true">
|
|
|
+ <img src="@/assets/icon/bitcoin/quancang.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 class="menu-content-rb pf400 fs14">
|
|
|
+ <div class="menu-content-rb1 fs14 fc333333" @click="showModal3 = true">
|
|
|
+ <img src="@/assets/icon/bitcoin/quancang.svg" alt="">
|
|
|
+ <span>限价委托</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">
|
|
|
+ <span>125000</span>
|
|
|
+ </div>
|
|
|
+ <span>最优价</span>
|
|
|
+ </div>
|
|
|
+ <div class="menu-content-rb pf400 fs12 fc333333">
|
|
|
+ <span>买入最高限价</span>
|
|
|
+ <span class="fcDF384C" style="padding-right: 0">20924</span>
|
|
|
+ </div>
|
|
|
+ <div class="menu-content-rb pf400 fs14">
|
|
|
+ <div class="menu-content-rb1 fs14 fc333333" @click="showInfo = true">
|
|
|
+ <img src="@/assets/icon/bitcoin/quancang.svg" alt="">
|
|
|
+ <span>隐含波动率</span>
|
|
|
+ </div>
|
|
|
+ <div @click="showModal1 = true" style="font-size: 12px; margin-right: 12px;">
|
|
|
+ 53.6%
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="menu-content-rb pf400 fs14">
|
|
|
+ <div class="menu-content-rb1 fs14 fc333333">
|
|
|
+ <span class="menu-content-rb1s fc999999">数量</span>
|
|
|
+ </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">
|
|
|
+ <span>0</span>
|
|
|
+ <span>USDT</span>
|
|
|
+ <img class="fs16" src="@/assets/icon/bitcoin/qianbao1.svg" alt="">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ <div class="menu-content-rb pf400 fs14">
|
|
|
+ <div class="menu-content-rb1 fs14 fc333333">
|
|
|
+
|
|
|
+ <span style="margin-left: 0" class="menu-content-rb1s fc333333">只减仓</span>
|
|
|
+ </div>
|
|
|
+ <div class="menu-content-rb1" @click="showM = true">
|
|
|
+ <span></span>
|
|
|
+ <span>{{ currentType }}</span>
|
|
|
+ <div style="font-size: 12px;">
|
|
|
+ <VanIcon :style="{ fontWeight: 'bold' }" :name="showM ? 'arrow-up' : 'arrow-down'"/>
|
|
|
+ </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">
|
|
|
+ <span>0</span>
|
|
|
+ <span>USDT</span>
|
|
|
+ </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">
|
|
|
+ <span>0</span>
|
|
|
+ <span>USDT</span>
|
|
|
+ </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="pf400 fs16 fcFFFFFF" @click="showConfirm = true">卖出(做空)</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <sellOrder1></sellOrder1>
|
|
|
+
|
|
|
+ <div v-if="isassetlessState">
|
|
|
+ <assetlessState></assetlessState>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <ChooseThisDepth
|
|
|
+ v-model:show="isPickerVisible"
|
|
|
+ v-model="currentDepth"
|
|
|
+ ></ChooseThisDepth>
|
|
|
+
|
|
|
+ <LeveragePopup
|
|
|
+ v-model:visible="showLeverageModal"
|
|
|
+ :initial-value="selectedLeverage"
|
|
|
+ @confirm="handleConfirm">
|
|
|
+ </LeveragePopup>
|
|
|
+
|
|
|
+ <OrderConfirmPopup
|
|
|
+ v-model:visible="showConfirm"
|
|
|
+ @confirm="onOrderConfirmed">
|
|
|
+ </OrderConfirmPopup>
|
|
|
+
|
|
|
+ <OrderTimeSheet
|
|
|
+ v-model:visible="showM"
|
|
|
+ v-model="currentType"
|
|
|
+ teleport="body"
|
|
|
+ ></OrderTimeSheet>
|
|
|
+
|
|
|
+ <MarginInfoSheet
|
|
|
+ v-model:visible="showInfo"
|
|
|
+ ></MarginInfoSheet>
|
|
|
+
|
|
|
+ <FundingOptions
|
|
|
+ v-model:visible="showModal1"
|
|
|
+ :selected-id="currentId1"
|
|
|
+ @confirm="handleConfirm1">
|
|
|
+ </FundingOptions>
|
|
|
+
|
|
|
+ <OrderType
|
|
|
+ v-model:visible="showModal2"
|
|
|
+ :selected-id="currentId2"
|
|
|
+ @confirm="handleConfirm2"
|
|
|
+ ></OrderType>
|
|
|
+
|
|
|
+ <LimitOrderModal
|
|
|
+ v-model:visible="showModal3"
|
|
|
+ ></LimitOrderModal>
|
|
|
+ <CommonFunctionsPopup
|
|
|
+ v-model:visible="showFunctions"
|
|
|
+ ></CommonFunctionsPopup>
|
|
|
+ <div style="margin-bottom: 80px">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { Icon as VanIcon,Popup as VanPopup} from 'vant';
|
|
|
+import {Checkbox as VanCheckbox, } from 'vant';
|
|
|
+import { onMounted, onUnmounted } from 'vue'
|
|
|
+
|
|
|
+import {computed, defineAsyncComponent, ref} from 'vue';
|
|
|
+import { useRouter } from 'vue-router'; // 【新增】 引入路由
|
|
|
+
|
|
|
+const router = useRouter(); // 【新增】 实例化路由
|
|
|
+
|
|
|
+// --- 异步组件引入 ---
|
|
|
+const priceLimit = defineAsyncComponent(() => import("@/views/bitcoin/components/priceLimit.vue"));
|
|
|
+const assetlessState = defineAsyncComponent(() => import("@/views/bitcoin/components/assetlessState.vue"));
|
|
|
+const assetlessStateData = defineAsyncComponent(() => import("@/views/bitcoin/components/assetlessStateData.vue"));
|
|
|
+const sellOrder1 = defineAsyncComponent(() => import('@/views/bitcoin/lever/components/sellOrder1.vue'));
|
|
|
+const SellTradingStatusData = defineAsyncComponent(() => import('@/views/bitcoin/components/SellTradingStatusData.vue'));
|
|
|
+const ChooseThisDepth = defineAsyncComponent(() => import('@/views/bitcoin/components/ChooseThisDepth.vue'));
|
|
|
+const LeveragePopup = defineAsyncComponent(() => import('@/views/bitcoin/components/LeveragePopup.vue'));
|
|
|
+const OrderConfirmPopup = defineAsyncComponent(() => import('@/views/bitcoin/components/OrderConfirmPopup.vue'));
|
|
|
+const OrderTimeSheet = defineAsyncComponent(() => import('@/views/bitcoin/components/OrderTimeSheet.vue'));
|
|
|
+const MarginInfoSheet = defineAsyncComponent(() => import('@/views/bitcoin/lever/components/impliedVolatility.vue'));
|
|
|
+const FundingOptions = defineAsyncComponent(() => import('@/views/bitcoin/components/FundingOptions.vue'));
|
|
|
+const OrderType = defineAsyncComponent(() => import('@/views/bitcoin/components/OrderType.vue'));
|
|
|
+const LimitOrderModal = defineAsyncComponent(() => import('@/views/bitcoin/components/LimitOrderModal.vue'));
|
|
|
+// 假设您的组件在 @/components/CommonFunctionsPopup.vue (请根据实际路径修改)
|
|
|
+const CommonFunctionsPopup = defineAsyncComponent(() => import('@/views/bitcoin/CommonFunctionsPopup/CommonFunctionsPopup.vue'));
|
|
|
+
|
|
|
+// 控制弹窗显示的变量
|
|
|
+const showFunctions = ref(false);
|
|
|
+
|
|
|
+// --- 状态定义 ---
|
|
|
+const isassetlessState = ref(false);
|
|
|
+
|
|
|
+const isPickerVisible = ref(false);
|
|
|
+const currentDepth = ref('depth1');
|
|
|
+const depthMap = {
|
|
|
+ 'depth1': '深度1',
|
|
|
+ 'depth2': '深度2',
|
|
|
+ 'depth3': '深度3',
|
|
|
+};
|
|
|
+const displayLabel = computed(() => depthMap[currentDepth.value] || '请选择');
|
|
|
+
|
|
|
+/* 市价说明 */
|
|
|
+const showModal3 = ref(false);
|
|
|
+
|
|
|
+/* 订单类型选项 */
|
|
|
+const showModal2 = ref(false);
|
|
|
+const currentId2 = ref(1);
|
|
|
+const selectedLabel2 = ref('市价');
|
|
|
+const selectedUnit2 = ref('%');
|
|
|
+const handleConfirm2 = (item) => {
|
|
|
+ currentId2.value = item.id;
|
|
|
+ selectedLabel2.value = item.label.slice(0, 2);
|
|
|
+ selectedUnit2.value = item.unit;
|
|
|
+};
|
|
|
+
|
|
|
+/* 全仓逐仓选项 */
|
|
|
+const showModal1 = ref(false);
|
|
|
+const currentId1 = ref(1);
|
|
|
+const selectedLabel1 = ref('全仓');
|
|
|
+const selectedUnit1 = ref('%');
|
|
|
+const handleConfirm1 = (item) => {
|
|
|
+ currentId1.value = item.id;
|
|
|
+ selectedLabel1.value = item.label.slice(0, 2);
|
|
|
+ selectedUnit1.value = item.unit;
|
|
|
+};
|
|
|
+
|
|
|
+/* 全仓逐仓说明 */
|
|
|
+const showInfo = ref(false);
|
|
|
+
|
|
|
+/* GTC 弹框 */
|
|
|
+const showM = ref(false);
|
|
|
+const currentType = ref('GTC');
|
|
|
+
|
|
|
+/* 控制倍数 */
|
|
|
+const showLeverageModal = ref(false);
|
|
|
+const selectedLeverage = ref(100);
|
|
|
+const handleConfirm = (value) => {
|
|
|
+ selectedLeverage.value = value;
|
|
|
+};
|
|
|
+
|
|
|
+/* 交易确认 */
|
|
|
+const showConfirm = ref(false);
|
|
|
+const onOrderConfirmed = () => {
|
|
|
+ // console.log('订单已提交');
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+// ✅ 使用 namespace 引入,防止报错
|
|
|
+import * as klinecharts from 'klinecharts'
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// --- 状态管理 ---
|
|
|
+const currentTab = ref('24h')
|
|
|
+const tabs = ['1h', '6h', '24h', '1w', '1m']
|
|
|
+let chartInstance = null
|
|
|
+
|
|
|
+// --- 数据生成逻辑 ---
|
|
|
+const generateData = (baseVal = 3812.74) => {
|
|
|
+ const data = []
|
|
|
+ let baseTime = new Date().getTime()
|
|
|
+ let basePrice = baseVal
|
|
|
+ for (let i = 0; i < 80; i++) {
|
|
|
+ const change = (Math.random() - 0.5) * 30
|
|
|
+ const close = basePrice + change
|
|
|
+ const open = basePrice + (Math.random() - 0.5) * 10
|
|
|
+ const high = Math.max(open, close) + Math.random() * 10
|
|
|
+ const low = Math.min(open, close) - Math.random() * 10
|
|
|
+ const volume = Math.random() * 100 + 50
|
|
|
+
|
|
|
+ data.push({ timestamp: baseTime, open, high, low, close, volume })
|
|
|
+ baseTime += 60 * 60 * 1000 // 1h 间隔
|
|
|
+ basePrice = close + (Math.random() * 2) // 稍微向上的趋势
|
|
|
+ }
|
|
|
+ return data
|
|
|
+}
|
|
|
+
|
|
|
+// --- 切换周期逻辑 ---
|
|
|
+const switchPeriod = (period) => {
|
|
|
+ currentTab.value = period
|
|
|
+ if (chartInstance) {
|
|
|
+ // 模拟数据刷新
|
|
|
+ const randomStart = 3800 + Math.random() * 100
|
|
|
+ chartInstance.applyNewData(generateData(randomStart))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// --- 初始化与配置 ---
|
|
|
+onMounted(() => {
|
|
|
+ const chartDOM = document.getElementById('k-line-chart')
|
|
|
+ if (!chartDOM) return
|
|
|
+
|
|
|
+ // 1. 初始化图表
|
|
|
+ chartInstance = klinecharts.init(chartDOM)
|
|
|
+ if (!chartInstance) return
|
|
|
+
|
|
|
+ // 2. 样式常量
|
|
|
+ const targetBlue = '#4A6EF5' // 截图中的蓝色虚线颜色
|
|
|
+ const gridColor = '#F2F4F6' // 极淡的网格线
|
|
|
+ const textColor = '#929AA5' // 灰色文字
|
|
|
+
|
|
|
+ // 3. 核心配置 (setStyleOptions)
|
|
|
+ chartInstance.setStyleOptions({
|
|
|
+ grid: {
|
|
|
+ show: true,
|
|
|
+ horizontal: {
|
|
|
+ show: true,
|
|
|
+ size: 1,
|
|
|
+ color: gridColor,
|
|
|
+ style: 'dash',
|
|
|
+ dashValue: [5, 5]
|
|
|
+ },
|
|
|
+ vertical: { show: false }
|
|
|
+ },
|
|
|
+ candle: {
|
|
|
+ type: 'candle_solid',
|
|
|
+ bar: {
|
|
|
+ upColor: '#2EBD85',
|
|
|
+ downColor: '#F6465D',
|
|
|
+ noChangeColor: '#2EBD85'
|
|
|
+ },
|
|
|
+ // ✅ 重点:蓝色价格指示线配置
|
|
|
+ priceMark: {
|
|
|
+ show: true,
|
|
|
+ high: { show: false },
|
|
|
+ low: { show: false },
|
|
|
+ last: {
|
|
|
+ show: true,
|
|
|
+ // 强制无论涨跌都显示蓝色
|
|
|
+ upColor: targetBlue,
|
|
|
+ downColor: targetBlue,
|
|
|
+ line: { show: true, style: 'dash', dashValue: [4, 3] },
|
|
|
+ text: {
|
|
|
+ show: true,
|
|
|
+ color: '#FFFFFF',
|
|
|
+ size: 11,
|
|
|
+ paddingLeft: 4,
|
|
|
+ paddingRight: 4,
|
|
|
+ borderRadius: 2
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ // 只有按压时才显示十字光标
|
|
|
+ showRule: 'follow_cross',
|
|
|
+ showType: 'rect',
|
|
|
+ dataSource: 'none', // 隐藏浮层数据,保持清爽
|
|
|
+ crosshair: {
|
|
|
+ show: true,
|
|
|
+ horizontal: { line: { style: 'dash', color: textColor } },
|
|
|
+ vertical: { line: { style: 'dash', color: textColor } }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // ✅ 重点:技术指标(VOL)颜色
|
|
|
+ technicalIndicator: {
|
|
|
+ bar: {
|
|
|
+ upColor: '#2EBD85',
|
|
|
+ downColor: '#F6465D',
|
|
|
+ noChangeColor: '#2EBD85'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // ✅ 重点:隐藏坐标轴线,只保留文字
|
|
|
+ xAxis: {
|
|
|
+ axisLine: { show: false },
|
|
|
+ tickLine: { show: false },
|
|
|
+ tickText: { color: textColor, size: 10, paddingTop: 8 }
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'normal',
|
|
|
+ position: 'right',
|
|
|
+ inside: true,
|
|
|
+ axisLine: { show: false },
|
|
|
+ tickLine: { show: false },
|
|
|
+ tickText: { color: textColor, size: 10, paddingLeft: 8 }
|
|
|
+ },
|
|
|
+ separator: { size: 0 } // 去掉指标和K线之间的分割线
|
|
|
+ })
|
|
|
+
|
|
|
+ // 4. 创建副图指标 (VOL)
|
|
|
+ chartInstance.createTechnicalIndicator('VOL', false, { id: 'pane_1', heightRatio: 0.2 })
|
|
|
+
|
|
|
+ // 5. 加载数据并设置缩放
|
|
|
+ chartInstance.applyNewData(generateData())
|
|
|
+ if (chartInstance.setDataSpace) {
|
|
|
+ chartInstance.setDataSpace(7)
|
|
|
+}
|
|
|
+ // chartInstance.setBarSpace(7) // 设置蜡烛宽度
|
|
|
+})
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ if (chartInstance) {
|
|
|
+ klinecharts.dispose('k-line-chart')
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped>
|
|
|
+* {
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.menu-content {
|
|
|
+ width: 100%;
|
|
|
+ max-width: 345px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ margin-top: 8px;
|
|
|
+ margin-left: 15px;
|
|
|
+
|
|
|
+ .menu-content-l {
|
|
|
+ flex: 1;
|
|
|
+
|
|
|
+ .menu-content-lb {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding-right: 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-content-lb1r {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ line-height: 22px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu-content-lb1:nth-child(4) {
|
|
|
+ .menu-content-lb1l {
|
|
|
+ color: #45b26b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .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-lb1r {
|
|
|
+ margin-left: 15px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .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;
|
|
|
+ align-content: center;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ 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(1) {
|
|
|
+
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ span:nth-child(2) {
|
|
|
+ margin: 0 9px 0 9px;
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ img {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu-content-rb:nth-of-type(8) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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-rb1s {
|
|
|
+ margin-left: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ img {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .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 0px 0 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ img {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu-content-rb:nth-of-type(11) {
|
|
|
+ background-color: #45b26b;
|
|
|
+
|
|
|
+ div {
|
|
|
+ margin: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu-content-rb:nth-of-type(12) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ img {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ img {
|
|
|
+ padding-right: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu-content-rb:nth-of-type(12) {
|
|
|
+ background-color: #df384c;
|
|
|
+ height: 38px;
|
|
|
+
|
|
|
+ div {
|
|
|
+ margin: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //.van-dropdown-menu__bar{
|
|
|
+ // width: 214px;
|
|
|
+ //}
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+.calculator-page {
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', sans-serif;
|
|
|
+ background: #fff;
|
|
|
+ padding-bottom: 90px;
|
|
|
+ color: #333;
|
|
|
+ //z-index: 99;
|
|
|
+ //position: relative; /* 固定定位 */
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+/* 导航 & 头部 */
|
|
|
+.nav-bar { display: flex; justify-content: space-between; align-items: center;
|
|
|
+ height: 44px; padding: 0 16px; margin-bottom: 5px; }
|
|
|
+.nav-left { font-size: 24px; cursor: pointer; }
|
|
|
+.nav-title { font-size: 18px; font-weight: 600; }
|
|
|
+.nav-right { width: 20px; }
|
|
|
+
|
|
|
+/* --- 布局容器 --- */
|
|
|
+.page-container {
|
|
|
+ width: 100%;
|
|
|
+ max-width: 375px;
|
|
|
+ margin: 0 auto;
|
|
|
+ background-color: #fff;
|
|
|
+ /* 使用系统字体,还原原生质感 */
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Roboto, Arial, sans-serif;
|
|
|
+ color: #333;
|
|
|
+ /* 防止横向滚动条 */
|
|
|
+ overflow-x: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+/* 🔥🔥 核心修改:定义一个公共的左右内边距
|
|
|
+ 给 header, market-info, time-tabs, chart-wrapper 都加上
|
|
|
+*/
|
|
|
+.header,
|
|
|
+.time-tabs,
|
|
|
+.chart-wrapper {
|
|
|
+ padding-left: 15px;
|
|
|
+ padding-right: 15px;
|
|
|
+ /* 关键:确保 padding 不会撑大 width: 100% */
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+/* --- 1. 头部 --- */
|
|
|
+.header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ /* padding-top: 12px;*/
|
|
|
+ padding-bottom: 12px;
|
|
|
+}
|
|
|
+.title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ display: inline-block;
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+/* --- 2. 行情信息 --- */
|
|
|
+.market-info {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 0 15px;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
+.price-block .current-price {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #111;
|
|
|
+ /* 稍微调整一下字间距,防止数字太紧 */
|
|
|
+ letter-spacing: -0.5px;
|
|
|
+}
|
|
|
+.sub-info {
|
|
|
+ font-size: 12px;
|
|
|
+ margin-top: 4px;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+.sub-info .fiat {
|
|
|
+ color: #999;
|
|
|
+ margin-right: 8px;
|
|
|
+}
|
|
|
+.sub-info .percent.up {
|
|
|
+ color: #2EBD85;
|
|
|
+}
|
|
|
+
|
|
|
+/* 统计网格 */
|
|
|
+
|
|
|
+.stat-item {
|
|
|
+ span{
|
|
|
+ display: flex;
|
|
|
+ }
|
|
|
+}
|
|
|
+.stat-item .label {
|
|
|
+ font-size: 11px;
|
|
|
+
|
|
|
+}
|
|
|
+.stat-item .value {
|
|
|
+ font-size: 11px;
|
|
|
+ color: #333;
|
|
|
+ font-family: "DIN", -apple-system, sans-serif; /* 如果有数字字体更好 */
|
|
|
+}
|
|
|
+
|
|
|
+/* --- 3. Tabs --- */
|
|
|
+.time-tabs {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ /*gap: 5px;*/
|
|
|
+ justify-content: space-between;
|
|
|
+ /*//padding-top: 8px;*/
|
|
|
+ /*padding-bottom: 8px;*/
|
|
|
+ /* 你的截图中似乎没有底边框,这里保持干净 */
|
|
|
+}
|
|
|
+.tab-item {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #929AA5;
|
|
|
+ padding: 4px 10px; /* 稍微减小内边距,适应 15px 的两侧挤压 */
|
|
|
+ border-radius: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ font-weight: 500;
|
|
|
+ transition: all 0.2s;
|
|
|
+}
|
|
|
+.tab-item.active {
|
|
|
+ background-color: #F6465D;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+.tab-item.icon {
|
|
|
+ color: #929AA5;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+.triangle {
|
|
|
+ font-size: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+/* --- 4. 图表容器 --- */
|
|
|
+.chart-wrapper {
|
|
|
+ width: 100%;
|
|
|
+ height: 275px;
|
|
|
+ /*margin-top: 5px;*/
|
|
|
+ /* 🔥 这里加了 padding 后,K线图就会自动往里缩,左右留出白边 */
|
|
|
+}
|
|
|
+.kline-container {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|