Преглед на файлове

补发26号工作:
底部tab模块我的-高级认证-完成
认证中心-基础认证-完成
认证中心-高级认证-完成
查看所有的权限- 完成
基础身份认证-完成

Hexinkui преди 1 месец
родител
ревизия
32dc41ff0c

+ 4 - 4
package-lock.json

@@ -9,7 +9,7 @@
       "version": "0.1.0",
       "dependencies": {
         "axios": "^1.13.2",
-        "klinecharts": "^10.0.0-beta1",
+        "klinecharts": "^8.6.3",
         "vant": "^4.9.21",
         "vue": "^3.2.13",
         "vue-router": "^4.0.3",
@@ -4273,9 +4273,9 @@
       }
     },
     "node_modules/klinecharts": {
-      "version": "10.0.0-beta1",
-      "resolved": "https://registry.npmjs.org/klinecharts/-/klinecharts-10.0.0-beta1.tgz",
-      "integrity": "sha512-5ZxFGjJeZqt9+q45lZDhApC3kdgrk51i27uSpIELgXJLNgfSc0anlb8XkU+52LVrBYnTv9dFr8/Q7lG81vIV1w==",
+      "version": "8.6.3",
+      "resolved": "https://registry.npmjs.org/klinecharts/-/klinecharts-8.6.3.tgz",
+      "integrity": "sha512-hGDtWiMNywEDneZFmt+vZ6tOYutCDWV5FPBcXcn7L8kGwe73Q5yJayk8UzP9pIQSBWyxswWIySKh/BVFA6GhuQ==",
       "license": "Apache-2.0"
     },
     "node_modules/klona": {

+ 1 - 1
package.json

@@ -8,7 +8,7 @@
   },
   "dependencies": {
     "axios": "^1.13.2",
-    "klinecharts": "^10.0.0-beta1",
+    "klinecharts": "^8.6.3",
     "vant": "^4.9.21",
     "vue": "^3.2.13",
     "vue-router": "^4.0.3",

+ 1 - 7
src/App.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="content">
-    <router-view />
+    <router-view  />
   </div>
 
 </template>
@@ -11,10 +11,4 @@
 }
 </style>
 <script setup >
-import {onMounted} from "vue";
-
-onMounted(() => {
-  // 强制滚动到顶部
-  window.scrollTo(0, 0);
-});
 </script>

+ 38 - 26
src/router/index.js

@@ -99,7 +99,7 @@ const routes = [
         },
         {
             path: 'PnLAnalysis',
-            name: 'PnLAnalysis.vue',
+            name: 'PnLAnalysis',
             component: () => import('@/views/bitcoin/lever/PnLAnalysis.vue'),
             meta: { title: '' }
          },
@@ -124,6 +124,18 @@ const routes = [
       },
     ],
   },
+   {
+    path: '/AdvancedCertification',
+    name: 'AdvancedCertification',
+    component: () => import('@/views/user/AdvancedCertification.vue'),
+    meta: { title: '' }
+   },
+   {
+      path: '/basic-verify',
+      name: 'BasicVerify',
+      component: () => import('@/views/user/BasicVerify.vue'),
+      meta: { title: '基础认证' }
+   },
   {
     path: "/applyPermission",
     name: "applyPermission",
@@ -325,31 +337,31 @@ const routes = [
         name: "userLoanIndex",
         component: UserLoanIndex,
     },
-    {
-        path: "/rechargeHistory",
-        name: "rechargeHistory",
-        component: RechargeHistory,
-    },
-    {
-        path: "/withdrawHistory",
-        name: "withdrawHistory",
-        component: WithdrawHistory,
-    },
-    {
-        path: "/financialIndex",
-        name: "financialIndex",
-        component: FinancialIndex,
-    },
-    {
-        path: "/financialBuy",
-        name: "financialBuy",
-        component: FinancialBuy,
-    },
-    {
-        path: "/myFinancial",
-        name: "myFinancial",
-        component: MyFinancial,
-    },
+    // {
+    //     path: "/rechargeHistory",
+    //     name: "rechargeHistory",
+    //     component: RechargeHistory,
+    // },
+    // {
+    //     path: "/withdrawHistory",
+    //     name: "withdrawHistory",
+    //     component: WithdrawHistory,
+    // },
+    // {
+    //     path: "/financialIndex",
+    //     name: "financialIndex",
+    //     component: FinancialIndex,
+    // },
+    // {
+    //     path: "/financialBuy",
+    //     name: "financialBuy",
+    //     component: FinancialBuy,
+    // },
+    // {
+    //     path: "/myFinancial",
+    //     name: "myFinancial",
+    //     component: MyFinancial,
+    // },
 ];
 
 const router = createRouter({

+ 1 - 4
src/views/bitcoin/TradeFutures.vue

@@ -281,10 +281,7 @@
 import {Checkbox as VanCheckbox, Icon as VanIcon} from 'vant';
 import {computed, defineAsyncComponent, ref, onMounted} from 'vue';
 import { useRouter } from 'vue-router'; // 【新增】 引入路由
-onMounted(() => {
-  // 强制滚动到顶部
-  window.scrollTo(0, 0);
-});
+
 const router = useRouter(); // 【新增】 实例化路由
 
 // --- 异步组件引入 ---

+ 16 - 4
src/views/bitcoin/TradeLayout.vue

@@ -40,18 +40,31 @@
       </div>
     </div>
 
-    <router-view></router-view>
+    <router-view :key="$route.fullPath"></router-view>
   </div>
 </template>
 
 <script setup>
+import { onMounted, onUnmounted, ref , watch} from 'vue'
 import { useRouter, useRoute } from 'vue-router';
 
 const router = useRouter();
 const route = useRoute();
 
+// 监听路由路径变化
+watch(
+  () => route.path,
+  () => {
+    window.scrollTo(0, 0);
+    const scrollBox = document.querySelector('.page-container');
+    if (scrollBox) {
+      scrollBox.scrollTop = 0;
+    }
+  }
+);
+
 const switchTab = (name) => {
-  router.push({ name });
+  router.push({ name })
 };
 
 const isCurrent = (name) => {
@@ -62,8 +75,7 @@ const isCurrent = (name) => {
 <style lang="less" scoped>
 .market-layout {
   display: flex;
-  flex-direction: column;
-  justify-content: flex-start;
+
   align-items: center;
   width: 100%;
   height: auto;

+ 12 - 4
src/views/bitcoin/components/sellOrder.vue

@@ -1,5 +1,5 @@
 <script setup>
-    import {defineAsyncComponent, ref} from 'vue';
+    import {defineAsyncComponent, ref, nextTick} from 'vue';
     //状态组件
     const assetlessState = defineAsyncComponent(() => import("./assetlessState.vue"));
     //持有仓位组件
@@ -40,10 +40,13 @@
         canCancel: false // 显示灰色已完成/不可操作按钮
       },
     ]);
-
+    const containerRef = ref(null)
     // 当前选中的 Tab,默认选中 index 1 (当前委托)
     const currentTab = ref(0);
     const tabs = ['持有仓位(0)', '当前委托(2)'];
+    const TabActive = (index) => {
+        currentTab.value = index
+    }
 
     // 按钮操作
     const handleCancel = (id) => {
@@ -66,7 +69,7 @@
             :key="index"
             class="tab-item"
             :class="{ active: currentTab === index }"
-            @click="currentTab = index"
+            @click="TabActive(index)"
         >
           {{ tab }}
           <div class="active-line" v-if="currentTab === index"></div>
@@ -161,7 +164,12 @@
 /* 基础设置 */
 .page-container1 {
   width: 100%;
-  height: auto;
+  /* 1. 必须限制高度 (例如占满屏幕) */
+  //height: 100vh;
+  /* 或者 height: calc(100vh - 头部高度); */
+
+  /* 2. 必须开启溢出滚动 */
+  //overflow-y: auto;
   //background-color: #FAFAFA; /* 浅灰背景 */
   font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif;
 }

+ 116 - 116
src/views/bitcoin/lever/TradeMargin.vue

@@ -66,102 +66,102 @@
 </template>
 
 <script setup>
-import { onMounted, onUnmounted, ref } from 'vue'
-// ✅ 使用 namespace 引入,防止报错
-import * as klinecharts from 'klinecharts'
-import MarketPriceAndPlan from'./components/MarketPriceAndPlan.vue'
-import sellOrder from '@/views/bitcoin/components/sellOrder.vue';
+      import { onMounted, onUnmounted, ref } from 'vue'
+      // ✅ 使用 namespace 引入,防止报错
+      import * as klinecharts from 'klinecharts'
+      import MarketPriceAndPlan from './components/MarketPriceAndPlan.vue'
+      import sellOrder from '@/views/bitcoin/components/sellOrder.vue';
 
 
-// --- 状态管理 ---
-const currentTab = ref('24h')
-const tabs = ['1h', '6h', '24h', '1w', '1m']
-let chartInstance = null
+      // --- 状态管理 ---
+      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
+      // --- 数据生成逻辑 ---
+      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
-}
+          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))
-  }
-}
+      // --- 切换周期逻辑 ---
+      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
+      // --- 初始化与配置 ---
+      onMounted(() => {
+        const chartDOM = document.getElementById('k-line-chart')
+        if (!chartDOM) return
 
-  // 1. 初始化图表
-  chartInstance = klinecharts.init(chartDOM)
-  if (!chartInstance) return
+        // 1. 初始化图表
+        chartInstance = klinecharts.init(chartDOM)
+        if (!chartInstance) return
 
-  // 2. 样式常量
-  const targetBlue = '#4A6EF5' // 截图中的蓝色虚线颜色
-  const gridColor = '#F2F4F6'  // 极淡的网格线
-  const textColor = '#929AA5'  // 灰色文字
+        // 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: {
+        // 3. 核心配置 (setStyleOptions)
+        chartInstance.setStyleOptions({
+          grid: {
             show: true,
-            color: '#FFFFFF',
-            size: 11,
-            paddingLeft: 4,
-            paddingRight: 4,
-            borderRadius: 2
-          }
-        }
+            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: {
         // 只有按压时才显示十字光标
@@ -183,39 +183,39 @@ onMounted(() => {
         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线之间的分割线
-  })
+      // ✅ 重点:隐藏坐标轴线,只保留文字
+      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 })
+        // 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) // 设置蜡烛宽度
-})
+        // 5. 加载数据并设置缩放
+        chartInstance.applyNewData(generateData())
+        if (chartInstance.setDataSpace) {
+        chartInstance.setDataSpace(7)
+      }
+        // chartInstance.setBarSpace(7) // 设置蜡烛宽度
+      })
 
-onUnmounted(() => {
-  if (chartInstance) {
-    klinecharts.dispose('k-line-chart')
-  }
-})
+      onUnmounted(() => {
+        if (chartInstance) {
+          klinecharts.dispose('k-line-chart')
+        }
+      })
 </script>
 
 <style scoped>

+ 15 - 6
src/views/bitcoin/lever/TradeSeconds.vue

@@ -3,7 +3,7 @@
     <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>
+        <h1 class="title">{{symbolTitle}}</h1>
       </div>
       <div class="right">
         <img src="@/assets/icon/bitcoin/den.svg" alt="" @click="showFunctions = true">
@@ -21,7 +21,8 @@
       </div>
 
       <div class="stat-grid">
-        <div class="stat-item">
+        <div>
+          <div class="stat-item">
           <span class="label">24h 最高价</span>
           <span class="value">78,776.76</span>
         </div>
@@ -29,7 +30,9 @@
           <span class="label">24h 成交量 (BTC)</span>
           <span class="value">78,776.76</span>
         </div>
-        <div class="stat-item">
+        </div>
+        <div>
+          <div class="stat-item">
           <span class="label">24h 最低价</span>
           <span class="value">78,776.76</span>
         </div>
@@ -37,6 +40,8 @@
           <span class="label">24h 成交额 (BTC)</span>
           <span class="value">78,776.76</span>
         </div>
+        </div>
+
       </div>
     </section>
 
@@ -66,13 +71,15 @@
 </template>
 
 <script setup>
-import { onMounted, onUnmounted, ref } from 'vue'
+import { onMounted, onUnmounted, ref , watch} from 'vue'
+import { useRoute } from 'vue-router' // 1. 引入 useRoute
 // ✅ 使用 namespace 引入,防止报错
 import * as klinecharts from 'klinecharts'
 import MarketPriceAndPlan from'./components/MarketPriceAndPlan.vue'
 import ChooseThisCycle from'./components/ChooseThisCycle.vue'
 import sellOrder from '@/views/bitcoin/components/sellOrder.vue';
-
+const route = useRoute()
+const symbolTitle = ref(route.params.id || 'BTCUSDT')
 
 // --- 状态管理 ---
 const currentTab = ref('24h')
@@ -293,10 +300,12 @@ onUnmounted(() => {
 .sub-info .percent.up {
   color: #2EBD85;
 }
-
 /* 统计网格 */
 .stat-grid {
+  display: flex;
+  flex-direction: row;
   text-align: right;
+  gap: 5px;
 
 }
 .stat-item {

+ 315 - 0
src/views/user/AdvancedCertification.vue

@@ -0,0 +1,315 @@
+<template>
+  <div class="page-container">
+    <header class="nav-bar sticky-header">
+      <div class="left" @click="$router.back()">
+        <div>
+          <VanIcon size="19" name="arrow-left"/>
+        </div>
+      </div>
+      <div class="title">认证中心</div>
+      <div class="right"></div>
+    </header>
+
+    <div class="main-header">
+      <h1 class="page-title fs18">身份认证</h1>
+      <p class="subtitle">在平台上进行购买和交易前请先进行身份认证</p>
+    </div>
+
+    <div class="tabs">
+      <div
+        class="tab-item"
+        :class="{ active: currentTab === 'basic' }"
+        @click="currentTab = 'basic'"
+      >
+        基础认证
+        <div class="active-line" v-if="currentTab === 'basic'"></div>
+      </div>
+
+      <div
+        class="tab-item"
+        :class="{ active: currentTab === 'advanced' }"
+        @click="currentTab = 'advanced'"
+      >
+        高级认证
+        <div class="active-line" v-if="currentTab === 'advanced'"></div>
+      </div>
+    </div>
+
+    <div class="scroll-content">
+      <div class="auth-card">
+        <div class="card-title">认证要求</div>
+
+        <div
+          class="card-row"
+          v-for="(item, index) in currentRequirements"
+          :key="index"
+        >
+          <span class="label">{{ item.label }}</span>
+          <span class="tag" :class="item.status === 'done' ? 'gray' : 'red'">
+            {{ item.status === 'done' ? '已认证' : '尚未认证' }}
+          </span>
+        </div>
+
+        <button class="btn-verify" @click="handleVerifyClick">立即认证</button>
+      </div>
+
+      <div class="features-section">
+        <div class="section-title">功能与限制</div>
+        <div v-for="(item, index) in permissions" :key="index" class="feature-item">
+          <div class="f-label" :class="{ 'red-text': item.isHighlight }">{{ item.label }}</div>
+          <div class="f-value" :class="{ 'light': item.desc }">{{ item.value || item.desc }}</div>
+        </div>
+      </div>
+
+      <div class="footer-action">
+        <button class="btn-footer" @click="showModal = true">查看当前拥有的权限</button>
+      </div>
+    </div>
+
+    <div class="overlay" v-if="showModal" @click="showModal = false"></div>
+
+    <div class="bottom-sheet" :class="{ 'is-open': showModal }">
+      <div class="sheet-handle"></div>
+      <div class="sheet-title">您当前拥有的权限</div>
+
+      <div class="sheet-content">
+        <div v-for="(item, index) in permissions" :key="index" class="feature-item">
+          <div class="f-label" :class="{ 'red-text': item.isHighlight }">{{ item.label }}</div>
+          <div class="f-value" :class="{ 'light': item.desc }">{{ item.value || item.desc }}</div>
+        </div>
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue';
+import { useRouter } from 'vue-router';
+import {Icon as VanIcon } from "vant";
+
+const router = useRouter();
+const handleVerifyClick = () => {
+  // 跳转到刚刚写好的新页面
+      if (currentTab.value === 'basic') {
+        router.push({name: 'BasicVerify'}); // 确保路由里配了这个 name
+        // 或者 router.push('/basic-verify');
+
+
+      }else{
+
+      }
+}
+
+
+// --- 状态管理 ---
+const currentTab = ref('basic'); // 当前选中的 Tab: 'basic' 或 'advanced'
+const showModal = ref(false);    // 控制弹框显示
+
+// --- 数据源:认证要求 ---
+const requirementsData = {
+  // 基础认证数据 (图1)
+  basic: [
+    { label: '个人信息', status: 'done' }, // done: 已认证
+    { label: '政府发行身份证', status: 'undone' } // undone: 尚未认证
+  ],
+  // 高级认证数据 (图2)
+  advanced: [
+    { label: '家庭地址', status: 'done' },
+    { label: '工作地址', status: 'undone' },
+    { label: '亲属联系方式', status: 'undone' }
+  ]
+};
+
+// 计算属性:根据当前 Tab 返回对应的数据
+const currentRequirements = computed(() => {
+  return requirementsData[currentTab.value];
+});
+
+// --- 数据源:权限列表 (页面和弹框共用) ---
+const permissions = [
+  { label: '每日充值', value: '无限额', isHighlight: false },
+  { label: '8M USDT 每日', desc: '数字货币提现限额', isHighlight: true }, // Highlight 变红
+  { label: 'C2C交易限额', value: '无限额', isHighlight: false },
+  { label: '其他功能', value: '无限额', isHighlight: false },
+];
+</script>
+
+<style scoped>
+/* --- 布局容器 (基于 375px) --- */
+.page-container {
+  width: 100%;
+  max-width: 375px;
+  min-height: 100vh;
+  margin: 0 auto;
+  background-color: #fff;
+  padding: 0 16px 40px 16px; /* 底部留白给按钮 */
+  box-sizing: border-box;
+  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
+  /*overflow-x: hidden;*/
+  position: relative;
+  /*overflow:auto;*/
+}
+
+/* 给包裹层设置固定定位 */
+.sticky-header {
+  position: sticky;
+  top: 0;
+  z-index: 100;
+  background-color: #fff; /* 统一背景色 */
+  /* 稍微加点 padding 保持美观 */
+  padding-bottom: 5px;
+}
+/* --- 导航栏 --- */
+.nav-bar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 44px;
+  margin-bottom: 10px;
+}
+.title { font-size: 18px; font-weight: 600; }
+.back-arrow { font-size: 20px; cursor: pointer; color: #333; }
+
+/* --- 大标题 --- */
+.main-header { margin-bottom: 20px; }
+.page-title { font-size: 18px; font-weight: 700; margin: 0 0 8px 0; color: #111; }
+.subtitle { font-size: 13px; color: #999; line-height: 1.4; }
+
+/* --- Tabs 切换样式 (关键) --- */
+.tabs {
+  display: flex;
+  margin-bottom: 20px;
+  border-bottom: 1px solid transparent; /* 预留位置 */
+  /* 关键:使用 baseline 让大小不同的文字底部对齐,不然会上下乱跳 */
+  align-items: flex-end;
+  gap: 20px;
+  height: 28px;
+}
+.tab-item {
+  position: relative;
+  cursor: pointer;
+  color: #C2C2C2; /* 默认灰色 (未选中) */
+  padding-bottom: 6px;
+  line-height: 1;
+
+  /* 1. 默认状态 (未选中):字号较小,颜色较淡 */
+  font-size: 16px;
+  font-weight: 500;
+  /* 2. 加上过渡动画,让忽大忽小的过程很丝滑 */
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+.tab-item.active {
+  /* 3. 选中状态:字号变大,颜色变黑,加粗 */
+  font-size: 20px;
+  font-weight: 700;
+  color: #111;
+}
+.active-line {
+  position: absolute;
+  /* 因为上面的 line-height: 1 和 flex-end 稳住了底部 */
+  /* 这里的 bottom 定位就会非常稳定 */
+  bottom: -4px; /* 可以稍微调一下距离 */
+  left: 50%;
+  transform: translateX(-50%);
+  width: 20px; /* 稍微改回 20px 显得精致点,或者按你喜好保持 24 */
+  height: 3px;
+  background-color: #111;
+  border-radius: 2px;
+}
+
+/* --- 认证卡片 --- */
+.auth-card {
+  border: 1px solid #eee;
+  border-radius: 12px;
+  padding: 16px;
+  box-shadow: 0 2px 10px rgba(0,0,0,0.02);
+  margin-bottom: 30px;
+}
+.card-title { font-size: 14px; color: #333; margin-bottom: 16px; font-weight: 500; }
+.card-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+.label { font-size: 15px; color: #666; }
+
+/* Tag 样式 */
+.tag {
+  font-size: 12px;
+  padding: 4px 8px;
+  border-radius: 4px;
+}
+.tag.gray { background-color: #A6A6A6; color: #fff; }
+.tag.red { background-color: #EA3F54; color: #fff; }
+
+.btn-verify {
+  width: 100%;
+  height: 44px;
+  background-color: #EA3F54; /* 红色按钮 */
+  color: white;
+  border: none;
+  border-radius: 22px;
+  font-size: 15px;
+  font-weight: 500;
+  margin-top: 5px;
+}
+
+/* --- 功能列表 (通用样式) --- */
+.section-title { font-size: 15px; color: #333; margin-bottom: 20px; font-weight: 500; }
+.feature-item { margin-bottom: 20px; }
+.f-label { font-size: 15px; color: #333; margin-bottom: 4px; font-weight: 500; }
+.f-label.red-text { color: #EA3F54; }
+.f-value { font-size: 14px; color: #999; }
+.f-value.light { color: #999; }
+
+/* --- 底部按钮 --- */
+.footer-action { margin-top: 30px; text-align: center; }
+.btn-footer {
+  width: 100%;
+  height: 46px;
+  background-color: #EA3F54;
+  color: white;
+  border: none;
+  border-radius: 23px;
+  font-size: 15px;
+  font-weight: 500;
+}
+
+/* ================= 弹框 CSS 动画 ================= */
+.overlay {
+  position: fixed; top: 0; left: 0;
+  width: 100vw; height: 100vh;
+  background-color: rgba(0, 0, 0, 0.4);
+  z-index: 998;
+  animation: fade 0.3s;
+}
+
+.bottom-sheet {
+  position: fixed; bottom: 0; left: 50%;
+  width: 100%; max-width: 375px;
+  transform: translateX(-50%) translateY(100%); /* 默认隐藏 */
+  background-color: #fff;
+  border-top-left-radius: 16px;
+  border-top-right-radius: 16px;
+  padding: 10px 20px 40px 20px;
+  box-sizing: border-box;
+  z-index: 999;
+  transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); /* 丝滑缓动 */
+}
+
+.bottom-sheet.is-open {
+  transform: translateX(-50%) translateY(0);
+}
+
+.sheet-handle {
+  width: 36px; height: 4px;
+  background-color: #E0E0E0;
+  border-radius: 2px;
+  margin: 0 auto 20px auto;
+}
+.sheet-title { font-size: 18px; font-weight: 600; color: #111; margin-bottom: 30px; }
+
+@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
+</style>

+ 257 - 0
src/views/user/BasicVerify.vue

@@ -0,0 +1,257 @@
+<template>
+  <div class="page-container">
+    <header class="nav-bar sticky-nav">
+      <div class="left" @click="$router.back()">
+        <div>
+          <VanIcon size="19" name="arrow-left"/>
+        </div>
+      </div>
+      <div class="title">基础认证</div>
+      <div class="right"></div>
+    </header>
+
+    <div class="form-content">
+
+      <div class="form-row-double">
+        <div class="form-col">
+          <label>法定名</label>
+          <input type="text" placeholder="名" v-model="form.firstName" />
+        </div>
+        <div class="form-col">
+          <label>法定姓</label>
+          <input type="text" placeholder="姓" v-model="form.lastName" />
+        </div>
+      </div>
+
+      <div class="form-item">
+        <label>证件类型</label>
+        <div class="input-box select-mode">
+          <span>{{ form.idType || '身份证' }}</span>
+          <span class="arrow">▼</span>
+        </div>
+      </div>
+
+      <div class="form-item">
+        <label>证件号码</label>
+        <input type="text" placeholder="请输入证件号码" v-model="form.idNumber" />
+      </div>
+
+      <div class="form-item">
+        <label>所在地区</label>
+        <div class="input-box select-mode">
+          <span :class="{ placeholder: !form.region }">{{ form.region || '请选择' }}</span>
+          <span class="arrow">▼</span>
+        </div>
+      </div>
+
+      <div class="form-item">
+        <label>详细地址</label>
+        <textarea
+          placeholder="请输入"
+          v-model="form.address"
+          rows="3"
+        ></textarea>
+      </div>
+
+      <div class="upload-section">
+        <h3 class="section-title">上传证件照</h3>
+        <p class="section-desc">确保件照清晰可见</p>
+
+        <div class="upload-card">
+          <div class="card-content">
+            <p class="card-tip">确保件照清晰可见</p>
+            <h4 class="card-title">身份证人像面</h4>
+            <div class="upload-btn">
+              上传 <span class="upload-icon">↑</span>
+            </div>
+          </div>
+        </div>
+
+        <div class="upload-card">
+          <div class="card-content">
+            <p class="card-tip">确保件照清晰可见</p>
+            <h4 class="card-title">身份证国徽面</h4>
+            <div class="upload-btn">
+              上传 <span class="upload-icon">↑</span>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="footer-note">
+        <p>支持小于8M的JPG、JPEG或PNG格式的图片</p>
+        <p>上传您身份证件的完整照片,</p>
+        <p>请确保上传图片中的所有细节都清晰可见</p>
+        <p>请确保证件为原件并在有效期内</p>
+        <p>请将证件置于纯色背景下</p>
+      </div>
+
+    </div>
+
+    <div class="bottom-action">
+      <button class="btn-submit" @click="handleSubmit">提交</button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { reactive } from 'vue';
+import { useRouter } from 'vue-router';
+import {Icon as VanIcon } from "vant";
+
+const router = useRouter();
+
+const form = reactive({
+  firstName: '',
+  lastName: '',
+  idType: '身份证',
+  idNumber: '',
+  region: '',
+  address: ''
+});
+
+const handleSubmit = () => {
+  console.log('提交表单', form);
+  // 这里写提交逻辑
+  // router.push('/success');
+};
+</script>
+
+<style scoped>
+/* 全局容器 */
+.page-container {
+  width: 100%;
+  max-width: 375px;
+  min-height: 100vh;
+  margin: 0 auto;
+  background-color: #fff;
+  padding-bottom: 80px; /* 给底部按钮留位置 */
+  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
+}
+
+/* 导航栏 */
+.nav-bar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 44px;
+  padding: 0 16px;
+  background: #fff;
+  border-bottom: 1px solid #f5f5f5;
+}
+.sticky-nav { position: sticky; top: 0; z-index: 100; }
+.title { font-size: 17px; font-weight: 600; color: #333; }
+.icon-back { font-size: 20px; color: #333; cursor: pointer; }
+.right { width: 20px; }
+
+/* 表单内容区 */
+.form-content {
+  padding: 20px 16px;
+}
+
+/* 通用 Input 样式 */
+input, textarea, .input-box {
+  width: 100%;
+  background-color: #F7F8FA; /* 极淡的灰色背景 */
+  border: none;
+  border-radius: 4px;
+  padding: 12px;
+  font-size: 14px;
+  color: #333;
+  box-sizing: border-box;
+  outline: none;
+}
+textarea { resize: none; }
+input::placeholder, textarea::placeholder { color: #C2C2C2; }
+
+/* Label 样式 */
+label {
+  display: block;
+  font-size: 14px;
+  color: #333;
+  margin-bottom: 8px;
+  font-weight: 500;
+}
+
+/* 姓名左右分栏 */
+.form-row-double {
+  display: flex;
+  gap: 15px;
+  margin-bottom: 20px;
+}
+.form-col { flex: 1; }
+
+/* 单个表单项 */
+.form-item { margin-bottom: 20px; }
+
+/* 模拟 Select 下拉框 */
+.input-box.select-mode {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.arrow { font-size: 12px; color: #999; transform: scale(0.8); }
+.placeholder { color: #C2C2C2; }
+
+/* 上传区域 */
+.upload-section { margin-top: 30px; margin-bottom: 20px; }
+.section-title { font-size: 16px; font-weight: 600; margin-bottom: 4px; }
+.section-desc { font-size: 12px; color: #999; margin-bottom: 16px; }
+
+.upload-card {
+  background-color: #F7F8FA;
+  border-radius: 8px;
+  height: 160px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 16px;
+  text-align: center;
+}
+.card-tip { font-size: 12px; color: #999; margin-bottom: 6px; }
+.card-title { font-size: 16px; font-weight: 600; color: #333; margin: 0 0 16px 0; }
+
+/* 上传按钮 */
+.upload-btn {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  background-color: #EA3F54;
+  color: #fff;
+  padding: 8px 24px;
+  border-radius: 20px;
+  font-size: 14px;
+  font-weight: 500;
+}
+.upload-icon { margin-left: 4px; font-weight: bold; }
+
+/* 底部说明 */
+.footer-note {
+  font-size: 12px;
+  color: #999;
+  line-height: 1.6;
+  margin-bottom: 20px;
+}
+
+/* 底部固定按钮 */
+.bottom-action {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  padding: 10px 16px 20px 16px;
+  background-color: #fff;
+  box-sizing: border-box;
+  box-shadow: 0 -2px 10px rgba(0,0,0,0.03);
+}
+.btn-submit {
+  width: 100%;
+  height: 44px;
+  background-color: #EA3F54;
+  color: #fff;
+  border: none;
+  border-radius: 22px;
+  font-size: 16px;
+  font-weight: 600;
+}
+</style>

+ 4 - 2
src/views/user/Index.vue

@@ -20,7 +20,7 @@
         class="func-item"
         v-for="(item, index) in userMenu"
         :key="index"
-        @click="goMenuRouter(index)">
+        @click="goMenuRouter(index, item)">
         <div class="item-left pf500 fs14 fc333333">
           <div class="left-img">
             <img :src="item.img" class="anquan-set" alt="" />
@@ -42,11 +42,13 @@
     router.push("/deleteAccount");
   };
 
-  const goMenuRouter = (index) => {
+  const goMenuRouter = (index, item) => {
     if (index == 1) {
       router.push("/userLoanIndex");
     } else if (index == 4) {
       router.push("/userAsset");
+    }else if (item.name == "高级认证") {
+      router.push({ name: 'AdvancedCertification' });
     }
   };