Hexinkui há 1 mês atrás
pai
commit
4d0381b009

Diff do ficheiro suprimidas por serem muito extensas
+ 15 - 0
src/assets/icon/user/yaoqi.svg


+ 36 - 31
src/router/index.js

@@ -100,12 +100,6 @@ const routes = [
 
          ]
         },
-      {
-            path: 'PnLAnalysis',
-            name: 'PnLAnalysis',
-            component: () => import('@/views/bitcoin/lever/PnLAnalysis.vue'),
-            meta: { title: '' }
-      },
       { path: 'calculator',
             name: 'calculator',
             component: Calculator },
@@ -133,6 +127,12 @@ const routes = [
     component: () => import('@/views/user/AdvancedCertification.vue'),
     meta: { title: '' }
    },
+  {
+            path: '/PnLAnalysis',
+            name: 'PnLAnalysis',
+            component: () => import('@/views/bitcoin/lever/PnLAnalysis.vue'),
+            meta: { title: '' }
+  },
   {
     path: '/detail',
     name: 'HelpCenter',
@@ -190,6 +190,11 @@ const routes = [
     name: 'KycUpload',
     component: () => import('@/views/user/KycUpload.vue') // 上传证件
   },
+  {
+    path: '/security',
+    name: 'SecuritySettings',
+    component: () => import('@/views/user/SecuritySettings.vue') // 核心页面
+  },
   {
     // 地址认证:复用同一个组件,通过 query 参数 type 来区分是 "home" 还是 "work"
     path: '/auth/address',
@@ -415,31 +420,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({

+ 6 - 3
src/views/bitcoin/lever/PnLAnalysis.vue

@@ -34,7 +34,7 @@
       </div>
 
       <div class="history-section">
-        <div class="section-title">
+        <div class="section-title" @click="showModal = true">
           历史盈亏 <van-icon name="question-o" color="#999" size="14" style="margin-left:4px" />
         </div>
 
@@ -62,6 +62,7 @@
       </div>
 
     </div>
+    <ExplanationModal v-model:visible="showModal"></ExplanationModal>
   </div>
 </template>
 
@@ -69,6 +70,7 @@
 import { ref } from 'vue';
 import { useRouter } from 'vue-router'; // 引入路由钩子
 import { Popup as vanPopup, Icon as vanIcon } from 'vant';
+import ExplanationModal from '@/views/bitcoin/lever/components/ExplanationModal.vue'
 
 const router = useRouter();
 
@@ -88,7 +90,8 @@ const statsData = ref([
   { label: '盈利天数', value: '10 天' },
   { label: '持平天数', value: '10 天' },
 ]);
-
+//历史盈亏说明
+const showModal = ref(false);
 // 模拟数据:历史记录
 const historyList = ref([
   {
@@ -243,7 +246,7 @@ const historyList = ref([
   border-bottom: 1px solid #F2F3F5;
 }
 .card-body {
-  padding: 12px 0;
+  padding: 8px 0;
 }
 .info-row {
   display: flex;

+ 138 - 0
src/views/bitcoin/lever/components/ExplanationModal.vue

@@ -0,0 +1,138 @@
+<template>
+  <Teleport to="body">
+    <!-- 1. 遮罩层 (点击关闭) -->
+    <transition name="fade">
+      <div
+        class="modal-mask"
+        v-if="visible"
+        @click="close"
+      ></div>
+    </transition>
+
+    <!-- 2. 弹窗面板 (底部滑出) -->
+    <transition name="slide-up">
+      <div class="modal-panel" v-if="visible">
+        <!-- 顶部小灰条 (Handle) -->
+        <div class="panel-handle-bar"></div>
+
+        <!-- 内容区域 (可滚动) -->
+        <div class="panel-content">
+          <div class="info-item" v-for="(item, index) in infoList" :key="index">
+            <h3 class="item-title">{{ item.title }}</h3>
+            <p class="item-desc">{{ item.desc }}</p>
+            <p v-if="item.subDesc" class="item-desc">{{ item.subDesc }}</p>
+          </div>
+        </div>
+
+        <!-- 底部安全区 (适配 iPhone X 等) -->
+        <div class="safe-area-bottom"></div>
+      </div>
+    </transition>
+  </Teleport>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+// 接收父组件传来的 visible 状态
+const props = defineProps({
+  visible: {
+    type: Boolean,
+    default: false
+  }
+});
+
+const emit = defineEmits(['update:visible']);
+
+// 关闭弹窗
+const close = () => {
+  emit('update:visible', false);
+};
+
+// 静态文案数据 (完全还原截图)
+const infoList = [
+  {
+    title: '账户总权益',
+    desc: '期权账户名目资产总额。',
+    subDesc: '账户总权益=保证金余额+期权市值'
+  },
+  {
+    title: '每日盈亏',
+    desc: '每日盈亏=日终账户总权益-初始账户总权益-每日' // 截图文字似乎截断了,这里照抄
+  },
+  {
+    title: '累计盈亏',
+    desc: '累计盈亏=期间每日盈亏加总'
+  },
+  {
+    title: '累计盈亏率%',
+    desc: '累计盈亏率=累计盈亏/期间保证金余额',
+    subDesc: '期间保证金余额=初始保证金余额+期间累计转入金'
+  },
+  {
+    title: '净划入',
+    desc: '每日净划转=总划入-总划出'
+  }
+];
+</script>
+
+<style scoped>
+/* --- 遮罩层样式 --- */
+.modal-mask {
+  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
+  background: rgba(0, 0, 0, 0.4); /* 半透明黑底 */
+  z-index: 998;
+}
+
+/* --- 面板样式 --- */
+.modal-panel {
+  position: fixed; left: 0; right: 0; bottom: 0;
+  background: #fff;
+  z-index: 999;
+  border-radius: 16px 16px 0 0; /* 顶部圆角 */
+  max-height: 80vh; /* 最大高度占屏幕80% */
+  display: flex; flex-direction: column;
+}
+
+/* 顶部灰色小把手 */
+.panel-handle-bar {
+  width: 36px; height: 4px;
+  background: #E0E0E0;
+  border-radius: 2px;
+  margin: 10px auto; /* 居中 */
+  flex-shrink: 0;
+}
+
+/* 内容区 */
+.panel-content {
+  padding: 10px 20px 30px;
+  overflow-y: auto; /* 内容过长可滚动 */
+}
+
+.info-item {
+  margin-bottom: 24px;
+}
+.item-title {
+  font-size: 16px; font-weight: 600; color: #333;
+  margin-bottom: 8px;
+}
+.item-desc {
+  font-size: 14px; color: #666; line-height: 1.5;
+  margin-bottom: 4px; text-align: justify;
+}
+
+/* 底部安全区 */
+.safe-area-bottom {
+  height: env(safe-area-inset-bottom);
+  flex-shrink: 0;
+}
+
+/* --- 动画效果 --- */
+/* 遮罩渐隐渐现 */
+.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; }
+.fade-enter-from, .fade-leave-to { opacity: 0; }
+
+/* 面板从底部滑出 */
+.slide-up-enter-active, .slide-up-leave-active { transition: transform 0.3s ease-out; }
+.slide-up-enter-from, .slide-up-leave-to { transform: translateY(100%); }
+</style>

+ 1 - 1
src/views/bitcoin/lever/components/sellOrder1.vue

@@ -46,7 +46,7 @@
 
     // 当前选中的 Tab,默认选中 index 1 (当前委托)
     const currentTab = ref(0);
-    const tabs = ['持有仓位(0)', '当前委托(2)'];
+    const tabs = ['持有仓位(2)', '当前委托(2)'];
 
     // 按钮操作
     const handleCancel = (id) => {

+ 2 - 1
src/views/market/Index.vue

@@ -60,9 +60,10 @@
         flex-direction: row;
         justify-content: flex-start;
         align-items: flex-end;
-        width: 349px;
+        width: 345px;
         height: 24px;
 
+
         .sys-notifi {
           margin-left: 35px;
         }

+ 263 - 19
src/views/user/Index.vue

@@ -1,20 +1,95 @@
 <template>
   <!-- 我的 -->
   <div class="user-index">
-    <div class="loan-info">
-      <div class="info-left">
-        <img src="../../assets/img/index/user/default-head.png" alt="" />
-        <div class="info-name" @click="deleteAccount">
-          <div class="name-area pf500 fs18 fc121212">
-            用户昵称
-            <div class="level pf500 fs12 fcDF384C" @click.stop="router.push({name: 'VipCenter'})">V2</div>
+    <!-- 导航栏 -->
+
+    <div class="content">
+      <div class="user-card">
+        <!-- 左侧信息保持不变 -->
+        <div class="card-left">
+          <div class="avatar-box">
+            <img :src="userInfo.avatar" alt="Avatar" class="avatar-img" />
+          </div>
+          <div class="info-box">
+            <div class="name-row">
+              <span class="user-name">{{ userInfo.nickname }}</span>
+              <span class="vip-badge">{{ userInfo.level }}</span>
+            </div>
+            <div class="user-id">ID: {{ userInfo.id }}</div>
+          </div>
+        </div>
+
+        <!-- 右侧:动态信用分仪表盘 -->
+        <div class="card-right">
+          <div class="score-chart">
+            <svg viewBox="0 0 100 100" class="chart-svg">
+              <!--
+                第一层:灰色底轨 (Background Segments)
+                遍历配置生成4段灰色轨迹,作为槽位
+              -->
+              <circle
+                v-for="(item, index) in backgroundSegments"
+                :key="`bg-${index}`"
+                cx="50" cy="50" :r="radius"
+                fill="none"
+                stroke="#E5E9F2"
+                stroke-width="6"
+                :stroke-dasharray="item.dashArray"
+                stroke-linecap="round"
+                :transform="item.transform"
+              />
+
+              <!--
+                第二层:彩色进度 (Progress Segments)
+                根据分数覆盖在底轨之上
+              -->
+              <circle
+                v-for="(item, index) in progressSegments"
+                :key="`prog-${index}`"
+                cx="50" cy="50" :r="radius"
+                fill="none"
+                :stroke="item.color"
+                stroke-width="6"
+                :stroke-dasharray="item.dashArray"
+                stroke-linecap="round"
+                :transform="item.transform"
+              />
+            </svg>
+
+            <!-- 环内文字 -->
+            <div class="score-text">
+              <div class="score-num">{{ creditScore }}</div>
+              <div class="score-label">信用分</div>
+            </div>
           </div>
-          <div class="pf400 fs14 fc6A7187" >ID: 658908</div>
         </div>
       </div>
-      <div class="info-right"></div>
+
+      <!-- 调试滑块 (实际使用可删除) -->
+<!--      <div class="debug-slider">-->
+<!--        <div class="slider-header">-->
+<!--          <span>当前分数: {{ creditScore }}</span>-->
+<!--          <span style="font-size:12px; color:#999">拖动查看未填满时的灰色效果</span>-->
+<!--        </div>-->
+<!--        <input type="range" min="0" max="100" v-model.number="creditScore" class="custom-range" />-->
+<!--      </div>-->
+
     </div>
-    <img src="../../assets/img/user/Invite Friends.svg" class="invite-friend" alt="" @click="router.push('/invite')"/>
+<!--    <div class="loan-info">-->
+<!--      <div class="info-left">-->
+<!--        <img src="../../assets/img/index/user/default-head.png" alt="" />-->
+<!--        <div class="info-name" @click="deleteAccount">-->
+<!--          <div class="name-area pf500 fs18 fc121212">-->
+<!--            用户昵称-->
+<!--            <div class="level pf500 fs12 fcDF384C" @click.stop="router.push({name: 'VipCenter'})">V2</div>-->
+<!--          </div>-->
+<!--          <div class="pf400 fs14 fc6A7187" >ID: 658908</div>-->
+<!--        </div>-->
+<!--      </div>-->
+<!--      <div class="info-right"></div>-->
+<!--    </div>-->
+<!--    <div style="width: 375px; b"></div>-->
+    <img  src="@/assets/icon/user/yaoqi.svg" class="invite-friend" alt="" @click="router.push('/invite')"/>
     <div class="user-func">
       <div
         class="func-item"
@@ -30,17 +105,114 @@
         <img src="../../assets/icon/user/right-arrow.svg" class="right-arrow" alt="" />
       </div>
     </div>
-    <div class="submit pf600 fs14 fcFFFFFF">退出</div>
+    <div class="submit pf600 fs14 fcFFFFFF" @click="out=true">退出</div>
   </div>
+  <logout v-model:visible="out"></logout>
 </template>
 <script setup>
+  import logout from '@/views/user/Logout.vue'
+  import { ref, computed } from 'vue';
   import { useRoute, useRouter } from "vue-router";
 
   const router = useRouter();
+  const out = ref(false);
+const userInfo = ref({
+  nickname: '用户昵称',
+  id: '658908',
+  level: 'V2',
+  avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix'
+});
 
-  const deleteAccount = () => {
-    router.push("/deleteAccount");
-  };
+// --- 核心配置 ---
+const creditScore = ref(90); // 当前分数
+const maxScore = 100; // 满分
+
+const radius = 42;
+const circumference = 2 * Math.PI * radius; // 周长 ≈ 263.89
+
+// 修改 1: 起始角度改为 -90 度 (从顶部正中间开始,顺时针绘制)
+const startAngle = -270;
+const gapLength = 10;    // 每一段之间的间隙 (像素)
+
+// 修改 2: 总有效长度改为完整圆周长 (不再乘 0.75,变成闭合圆环)
+const totalArcLength = circumference;
+
+// 颜色段配置 (总分需等于100)
+// 这里的顺序决定了圆环颜色的排列顺序
+const configSegments = [
+  { max: 50, color: '#2B6BFF' }, // 蓝色
+  { max: 20, color: '#FF4D6A' }, // 红色
+  { max: 15, color: '#FFAA00' }, // 黄色
+  { max: 15, color: '#00C087' }, // 绿色
+];
+
+// --- 辅助函数:计算一段圆弧的几何信息 ---
+const calculateSegmentGeometry = (segmentMaxScore, currentStartAngle) => {
+  // 1. 计算这一段理论上应该占多长 (像素)
+  const ratio = segmentMaxScore / maxScore;
+  let arcLength = ratio * totalArcLength;
+
+  // 2. 减去间隙 (视觉上扣除,防止连在一起)
+  // 实际绘制长度不能小于0
+  const drawLength = Math.max(0, arcLength - gapLength);
+
+  // 3. 计算这一段占用的角度 (包含被扣除的间隙,用于计算下一段的起点)
+  const angleSpan = (arcLength / circumference) * 360;
+
+  return { drawLength, angleSpan };
+};
+
+// --- 计算属性 1: 底轨片段 (灰色) ---
+const backgroundSegments = computed(() => {
+  let currentAngle = startAngle;
+  return configSegments.map(seg => {
+    const { drawLength, angleSpan } = calculateSegmentGeometry(seg.max, currentAngle);
+
+    const result = {
+      dashArray: `${drawLength}, ${circumference}`,
+      transform: `rotate(${currentAngle}, 50, 50)`
+    };
+
+    currentAngle += angleSpan; // 移动到下一段起点
+    return result;
+  });
+});
+
+// --- 计算属性 2: 进度片段 (彩色) ---
+const progressSegments = computed(() => {
+  let currentAngle = startAngle;
+  let remainingScore = creditScore.value;
+
+  return configSegments.map(seg => {
+    const { drawLength, angleSpan } = calculateSegmentGeometry(seg.max, currentAngle);
+
+    // 计算这一段应该填满多少
+    let fillRatio = 0;
+    if (remainingScore >= seg.max) {
+      fillRatio = 1; // 填满
+    } else if (remainingScore > 0) {
+      fillRatio = remainingScore / seg.max; // 填一部分
+    } else {
+      fillRatio = 0; // 不填
+    }
+
+    const currentDrawLength = drawLength * fillRatio;
+
+    const result = {
+      color: seg.color,
+      dashArray: `${currentDrawLength}, ${circumference}`,
+      transform: `rotate(${currentAngle}, 50, 50)`
+    };
+
+    currentAngle += angleSpan;
+    remainingScore -= seg.max;
+
+    return result;
+  });
+});
+  // const deleteAccount = () => {
+  //   router.push("/deleteAccount");
+  // };
 
   const goMenuRouter = (index, item) => {
     if (index == 1) {
@@ -51,13 +223,14 @@
       router.push({ name: 'AdvancedCertification' });
     }else if (index === 3) {
       router.push({ name: 'KycForm' });
-    }
-    else if (index === 5) {
+    }else if (index === 5) {
       router.push({ name: 'LanguageSwitch' });
     }else if (index === 7) {
       router.push({ name: 'HelpCenter' });
     }else if (index === 8) {
       router.push({ name: 'AboutUs' });
+    }else if (index === 0) {
+      router.push({ name: 'SecuritySettings' });
     }
   };
 
@@ -171,9 +344,11 @@
     }
 
     .invite-friend {
-      margin-top: 20px;
-      width: 327px;
+      margin: 0 auto;
+      //margin-top: 20px;
+      width: 360px ;
       height: 68px;
+      padding-left: 15px;
     }
 
     .user-func {
@@ -185,7 +360,7 @@
         justify-content: space-between;
         align-items: center;
         margin-top: 26.5px;
-        width: 340px;
+        width: 355px;
         height: 24px;
 
         &:first-child {
@@ -231,4 +406,73 @@
       letter-spacing: 0.2px;
     }
   }
+
+
+  //xin
+.nav-bar {
+  display: flex; justify-content: space-between; align-items: center;
+  height: 44px; padding: 0 16px; background: #fff;
+  position: sticky; top: 0; z-index: 10;
+  width: 100%;
+  .icon1{ padding-left: 15px;}
+}
+.nav-title { font-size: 18px; font-weight: 500; color: #333; }
+.nav-left, .nav-right { width: 40px; }
+
+.content { width:100%;padding: 15px; }
+
+.user-card {
+  background: #fff; border-radius: 16px; padding: 0px 0 0 15px;
+  display: flex; justify-content: space-between; align-items: center;
+  //box-shadow: 0 4px 12px rgba(0,0,0,0.03);
+}
+
+.card-left { display: flex; align-items: center; }
+.avatar-box {
+  width: 56px; height: 56px; border-radius: 50%; overflow: hidden;
+  background: #E0E6ED; margin-right: 12px; border: 1px solid #f0f0f0;
+}
+.avatar-img { width: 100%; height: 100%; object-fit: cover; }
+
+.info-box { display: flex; flex-direction: column; justify-content: center; }
+.name-row { display: flex; align-items: center; margin-bottom: 6px; }
+.user-name { font-size: 18px; font-weight: 600; color: #1A1A1A; margin-right: 8px; }
+.vip-badge {
+  background-color: #FDEEEE; color: #E02F44; font-size: 10px; font-weight: 700;
+  padding: 1px 5px; border-radius: 4px; line-height: 1.4; font-style: italic;
+}
+.user-id { font-size: 14px; color: #858B9C; }
+
+.card-right { position: relative; }
+.score-chart {
+  width: 90px; height: 90px; position: relative;
+  display: flex; align-items: center; justify-content: center;
+}
+.chart-svg {
+  width: 100%; height: 100%;
+  transform: rotate(0deg);
+}
+
+.score-text {
+  position: absolute; text-align: center;
+  top: 50%; left: 50%;
+  transform: translate(-50%, -50%);
+}
+.score-num {
+  font-size: 22px; font-weight: 700; color: #1A1A1A; line-height: 1; margin-bottom: 2px;
+}
+.score-label {
+  font-size: 10px; color: #858B9C; transform: scale(0.9);
+}
+
+/* 调试滑块样式 */
+.debug-slider {
+  margin-top: 20px; padding: 15px; background: #fff; border-radius: 12px;
+}
+.slider-header {
+  display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 14px; color: #333;
+}
+.custom-range {
+  width: 100%; accent-color: #2B6BFF;
+}
 </style>

+ 115 - 0
src/views/user/Logout.vue

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

+ 279 - 0
src/views/user/SecuritySettings.vue

@@ -0,0 +1,279 @@
+<template>
+  <div class="security-page">
+    <!-- 导航栏 -->
+    <div class="nav-bar">
+      <div class="nav-left" @click="$router.back()">
+        <van-icon size="20" name="arrow-left"></van-icon>
+<!--        <svg width="24" height="24" viewBox="0 0 24 24" fill="none">-->
+<!--          <path d="M15 18L9 12L15 6" stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>-->
+<!--        </svg>-->
+      </div>
+      <div class="nav-title">安全设置</div>
+      <div class="nav-right"></div>
+    </div>
+
+    <div class="content">
+      <!-- 1. 安全验证头部 -->
+      <h2 class="section-title">安全验证</h2>
+
+      <div class="security-dashboard">
+        <!-- 圆环进度条 -->
+        <div class="circle-chart">
+          <svg viewBox="0 0 36 36" class="circular-chart">
+            <path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
+            <path class="circle" stroke-dasharray="30, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
+          </svg>
+        </div>
+        <div class="dashboard-info">
+          <div class="security-level">账户安全等级较低</div>
+          <div class="security-tip">为了您的账户安全,建议至少开启2项安全验证</div>
+        </div>
+      </div>
+
+      <!-- 2. 四宫格卡片 -->
+      <div class="auth-grid">
+        <!-- 卡片 1: 通行密钥 -->
+        <div class="auth-card" @click="handleCardClick('passkey')">
+          <div class="card-header">
+            <div class="icon-box red-icon">
+               <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
+            </div>
+            <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+          </div>
+          <div class="card-title">通行密钥</div>
+          <div class="card-status unbind">未启用</div>
+        </div>
+
+        <!-- 卡片 2: Google验证 -->
+        <div class="auth-card" @click="handleCardClick('google')">
+          <div class="card-header">
+            <div class="icon-box google-icon">
+              <!-- 简单的 G 图标 -->
+              <span style="font-weight:bold; font-size:14px;">G+</span>
+            </div>
+            <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+          </div>
+          <div class="card-title">Google验证</div>
+          <div class="card-status unbind">未启用</div>
+        </div>
+
+        <!-- 卡片 3: 手机验证 -->
+        <div class="auth-card" @click="handleCardClick('phone')">
+          <div class="card-header">
+            <div class="icon-box blue-icon">
+               <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>
+            </div>
+            <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+          </div>
+          <div class="card-title">手机验证</div>
+          <div class="card-status bind">190****1520</div>
+        </div>
+
+        <!-- 卡片 4: 邮箱验证 -->
+        <div class="auth-card" @click="handleCardClick('email')">
+          <div class="card-header">
+            <div class="icon-box purple-icon">
+               <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
+            </div>
+            <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+          </div>
+          <div class="card-title">邮箱验证</div>
+          <div class="card-status bind">36*****90@qq.com</div>
+        </div>
+      </div>
+
+      <!-- 3. 列表区域 -->
+      <div class="setting-list">
+        <!-- 支付密码 -->
+        <div class="list-item" @click="handleSetting('payment')">
+          <span class="item-label">支付密码</span>
+          <div class="item-right">
+             <span class="item-value">设置</span>
+             <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+          </div>
+        </div>
+
+        <h2 class="section-title mt-20">高级安全设置</h2>
+
+        <!-- 隐藏钱包地址 (开关) -->
+        <div class="list-item">
+          <span class="item-label">隐藏钱包地址</span>
+          <div class="switch-box">
+            <input type="checkbox" id="hideWallet" v-model="settings.hideWallet" />
+            <label for="hideWallet"></label>
+          </div>
+        </div>
+
+        <!-- 注销登录 -->
+        <div class="list-item" @click="handleSetting('logout')">
+          <span class="item-label">注销登录</span>
+          <div class="item-right">
+             <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+          </div>
+        </div>
+
+        <!-- 保持登录 (开关) -->
+        <div class="list-item">
+          <span class="item-label">保持登录</span>
+          <div class="switch-box">
+             <input type="checkbox" id="keepLogin" v-model="settings.keepLogin" />
+             <label for="keepLogin"></label>
+          </div>
+        </div>
+
+        <!-- APP锁定 -->
+        <div class="list-item" @click="handleSetting('appLock')">
+          <span class="item-label">APP锁定</span>
+          <div class="item-right">
+             <span class="item-value">5分钟</span>
+             <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
+          </div>
+        </div>
+
+      </div>
+
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { reactive } from 'vue';
+import { useRouter } from 'vue-router';
+
+const router = useRouter();
+
+// 页面状态
+const settings = reactive({
+  hideWallet: true,
+  keepLogin: true
+});
+
+const handleCardClick = (type) => {
+  console.log('点击卡片:', type);
+  // router.push('/security/' + type);
+};
+
+const handleSetting = (type) => {
+  console.log('点击设置:', type);
+  if (type === 'payment') {
+    // router.push('/security/payment');
+  }
+};
+</script>
+
+<style scoped>
+.security-page {
+  min-height: 100vh;
+  background: #fff;
+  padding-bottom: 40px;
+}
+.nav-bar {
+  display: flex; justify-content: space-between; align-items: center;
+  height: 44px; padding: 0 16px; position: sticky; top: 0; background: #fff; z-index: 10;
+}
+.nav-title { font-size: 18px; font-weight: 600; color: #333; }
+.nav-left, .nav-right { width: 40px; display: flex; align-items: center; }
+
+.content { padding: 0 20px; }
+
+/* 标题样式 */
+.section-title {
+  font-size: 16px; font-weight: 600; color: #333; margin: 10px 0 15px;
+}
+.mt-20 { margin-top: 30px; }
+
+/* 仪表盘区域 */
+.security-dashboard {
+  display: flex; align-items: center; margin-bottom: 25px;
+}
+.circle-chart {
+  width: 50px; height: 50px; margin-right: 12px;
+}
+.circular-chart {
+  display: block; margin: 0 auto; max-width: 100%; max-height: 100%;
+}
+.circle-bg {
+  fill: none; stroke: #eee; stroke-width: 3.8;
+}
+.circle {
+  fill: none; stroke-width: 2.8; stroke-linecap: round;
+  stroke: #4A90E2; /* 蓝色进度 */
+  animation: progress 1s ease-out forwards;
+}
+@keyframes progress {
+  0% { stroke-dasharray: 0 100; }
+}
+
+.dashboard-info { flex: 1; }
+.security-level { font-size: 16px; font-weight: 600; color: #333; margin-bottom: 4px; }
+.security-tip { font-size: 12px; color: #999; line-height: 1.4; }
+
+/* 四宫格卡片 */
+.auth-grid {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 12px;
+  margin-bottom: 30px;
+}
+
+.auth-card {
+  background: #fff;
+  border: 1px solid #f5f5f5;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.03);
+  border-radius: 12px;
+  padding: 16px;
+  display: flex; flex-direction: column;
+}
+
+.card-header {
+  display: flex; justify-content: space-between; align-items: flex-start;
+  margin-bottom: 12px;
+}
+.icon-box {
+  width: 32px; height: 32px; border-radius: 8px;
+  display: flex; align-items: center; justify-content: center;
+}
+/* 不同卡片的图标颜色 */
+.red-icon { background: #ECA8A8; }   /* 浅红背景 */
+.google-icon { background: #eee; color: #DB4437; } /* Google灰底红字 */
+.blue-icon { background: #A8C8EC; }  /* 浅蓝背景 */
+.purple-icon { background: #D4A8EC; } /* 浅紫背景 */
+
+.card-title { font-size: 15px; font-weight: 600; color: #333; margin-bottom: 6px; }
+.card-status { font-size: 12px; }
+.card-status.unbind { color: #999; }
+.card-status.bind { color: #999; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+
+/* 列表样式 */
+.list-item {
+  display: flex; justify-content: space-between; align-items: center;
+  height: 50px;
+  /* border-bottom: 1px solid #f9f9f9;  原图好像没有分割线,或者很淡,这里省略 */
+  margin-bottom: 10px;
+}
+.item-label { font-size: 15px; color: #333; font-weight: 500; }
+.item-right { display: flex; align-items: center; }
+.item-value { font-size: 14px; color: #999; margin-right: 4px; }
+
+/* 开关组件 Switch */
+.switch-box {
+  position: relative; width: 50px; height: 30px;
+}
+.switch-box input { display: none; }
+.switch-box label {
+  position: absolute; top: 0; left: 0; right: 0; bottom: 0;
+  background-color: #ccc;
+  border-radius: 34px; cursor: pointer; transition: 0.4s;
+}
+.switch-box label:before {
+  position: absolute; content: ""; height: 26px; width: 26px;
+  left: 2px; bottom: 2px;
+  background-color: white; border-radius: 50%; transition: 0.4s;
+}
+.switch-box input:checked + label {
+  background-color: #E02F44; /* 选中时的红色 */
+}
+.switch-box input:checked + label:before {
+  transform: translateX(20px);
+}
+</style>

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff