Explorar el Código

补发30号工作:
底部tab模块我的
安全设置-完成
注销登陆-完成
设置app自动锁定时间-完成
支付密码设置-完成
通行密钥添加-完成
配置vue.config.js文件配置,把开发端(dev)代码打包成生产端(prod)代码

Hexinkui hace 1 mes
padre
commit
d3862abb84

+ 10 - 0
src/router/index.js

@@ -197,6 +197,16 @@ const routes = [
     name: 'SecuritySettings',
     component: () => import('@/views/user/SecuritySettings.vue') // 核心页面
   },
+  {
+    path: '/set-password',
+    name: 'SetPassword',
+    component: () => import('@/views/user/SetPassword.vue') // 新页面
+  },
+  {
+    path: '/delete-account',
+    name: 'DeleteAccount',
+    component: () => import('@/views/user/DeleteAccount.vue') // 新页面
+  },
   {
     // 地址认证:复用同一个组件,通过 query 参数 type 来区分是 "home" 还是 "work"
     path: '/auth/address',

+ 132 - 31
src/views/user/DeleteAccount.vue

@@ -1,37 +1,138 @@
 <template>
-  <!-- 注销账号 -->
-  <HeaderNav headerText="注销账号"></HeaderNav>
-  <div class="delete-account pf400 fs14 fc666666">
-    注销账户后,您可能需要考虑以下几点:<br />
-    数据无法恢复:一旦注销账户,您在该账户中的所有数据可能会永久丢失。因此,请务必在注销前做好数据备份。<br />
-    影响其他服务:有些账户可能与其他服务相关联,例如通过社交媒体账户登录的应用。如果您注销了这些账户,可能会影响您使用的其他服务。<br />
-    等待期:一些平台在您申请注销后,可能会设置一个等待期。在此期间,您仍然可以取消注销请求,恢复账户。<br />
-    隐私设置:即使您注销了某些账户,您在其他平台上的信息仍然可能被保留。定期检查您的隐私设置,确保您的信息安全。<br />
-    注销账户是保护个人隐私和安全的重要步骤。在决定注销之前,确保备份所有重要的数据,了解注销的具体步骤和后果。每个平台的注销流程可能有所不同,因此在操作时请务必仔细阅读相关说明。<br />
+  <div class="page-container">
+    <!-- 导航栏 -->
+    <div class="nav-bar">
+      <div class="nav-left" @click="$router.back()">
+        <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">
+      <p class="intro-text">注销账户后,您可能需要考虑以下几点:</p>
+
+      <div class="text-block">
+        <span class="block-title">数据无法恢复:</span>
+        一旦注销账户,您在该账户中的所有数据可能会永久丢失。因此,请务必在注销前做好数据备份。
+      </div>
+
+      <div class="text-block">
+        <span class="block-title">影响其他服务:</span>
+        有些账户可能与其他服务相关联,例如通过社交媒体账户登录的应用。如果您注销了这些账户,可能会影响您使用的其他服务。
+      </div>
+
+      <div class="text-block">
+        <span class="block-title">等待期:</span>
+        一些平台在您申请注销后,可能会设置一个等待期。在此期间,您仍然可以取消注销请求,恢复账户。
+      </div>
+
+      <div class="text-block">
+        <span class="block-title">隐私设置:</span>
+        即使您注销了某些账户,您在其他平台上的信息仍然可能被保留。定期检查您的隐私设置,确保您的信息安全。
+      </div>
+
+      <div class="text-block summary-text">
+        注销账户是保护个人隐私和安全的重要步骤。在决定注销之前,确保备份所有重要的数据,了解注销的具体步骤和后果。每个平台的注销流程可能有所不同,因此在操作时请务必仔细阅读相关说明。
+      </div>
+    </div>
+
+    <!-- 底部按钮 -->
+    <div class="footer-action">
+      <button class="delete-btn" @click="handleDelete">注销</button>
+    </div>
   </div>
-  <div class="submit pf600 fs14 fcFFFFFF">注销</div>
 </template>
+
 <script setup>
-  import HeaderNav from "../index/components/HeaderNav.vue";
-</script>
-<style lang="less" scoped>
-  .delete-account {
-    margin: 0 auto;
-    margin-top: 48px;
-    width: 345px;
-    line-height: 24px;
-    letter-spacing: 0.2px;
-  }
+import { useRouter } from 'vue-router';
+// import { showConfirmDialog, showToast } from 'vant'; // 如果有 Vant
+
+const router = useRouter();
 
-  .submit {
-    margin: 0 auto;
-    margin-top: 235px;
-    width: 311px;
-    height: 40px;
-    line-height: 40px;
-    text-align: center;
-    border-radius: 100px;
-    background: #df384c;
-    letter-spacing: 0.2px;
+const handleDelete = () => {
+  // 模拟确认弹窗
+  const isConfirmed = confirm('确定要注销账号吗?此操作无法撤销。');
+  if (isConfirmed) {
+    console.log('执行注销逻辑...');
+    alert('申请已提交');
+    router.push('/');
   }
-</style>
+};
+</script>
+
+<style scoped>
+.page-container {
+  min-height: 100vh;
+  background-color: #fff;
+  display: flex; flex-direction: column;
+}
+
+/* 导航栏 */
+.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;
+}
+.nav-title { font-size: 18px; font-weight: 600; color: #333; }
+.nav-left, .nav-right { width: 40px; display: flex; align-items: center; }
+
+/* 内容区域 */
+.content {
+  padding: 16px 20px 100px; /* 底部留出按钮空间 */
+  flex: 1;
+  overflow-y: auto;
+}
+
+.intro-text {
+  font-size: 14px; color: #666;
+  margin-bottom: 20px;
+  line-height: 1.6;
+}
+
+.text-block {
+  font-size: 14px;
+  color: #666;
+  line-height: 1.8; /* 较大的行高,增加可读性 */
+  margin-bottom: 20px;
+  text-align: justify; /* 两端对齐,使大段文字边缘整齐 */
+}
+
+/* 重点文字加深颜色 */
+.block-title {
+  color: #333;
+  font-weight: 500;
+}
+
+/* 底部总结段落 */
+.summary-text {
+  margin-top: 30px;
+}
+
+/* 底部固定按钮区 */
+.footer-action {
+  position: fixed;
+  bottom: 0; left: 0; right: 0;
+  padding: 10px 20px 30px; /* 适配 iPhone 底部安全区 */
+  background: #fff;
+  /* 可选:加个上边框或阴影让层次更分明 */
+  /* border-top: 1px solid #eee; */
+}
+
+.delete-btn {
+  width: 100%;
+  height: 48px;
+  background: #E02F44; /* 警示红 */
+  color: #fff;
+  border: none;
+  border-radius: 24px;
+  font-size: 16px;
+  font-weight: 600;
+  cursor: pointer;
+}
+
+.delete-btn:active {
+  opacity: 0.9;
+}
+</style>

+ 146 - 0
src/views/user/LockTimeModal.vue

@@ -0,0 +1,146 @@
+<template>
+  <Teleport to="body">
+    <!-- 遮罩层 -->
+    <transition name="fade">
+      <div class="modal-mask" v-if="visible" @click="close"></div>
+    </transition>
+
+    <!-- 底部弹窗面板 -->
+    <transition name="slide-up">
+      <div class="modal-panel" v-if="visible">
+        <!-- 顶部小灰条 -->
+        <div class="panel-handle"></div>
+
+        <!-- 标题 -->
+        <div class="panel-header">
+          <h3 class="panel-title">设置自动锁定时间</h3>
+        </div>
+
+        <!-- 选项列表 -->
+        <div class="option-list">
+          <div
+            class="option-item"
+            v-for="item in options"
+            :key="item"
+            @click="selectItem(item)"
+          >
+            <span class="option-text">{{ item }}</span>
+
+            <!-- 选中状态显示的红色对勾图标 -->
+            <div class="check-icon" v-if="localSelected === item">
+              <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
+                <circle cx="12" cy="12" r="10" fill="#E02F44"/> <!-- 红色圆底 -->
+                <path d="M7 12L10 15L17 8" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+              </svg>
+            </div>
+          </div>
+        </div>
+
+        <!-- 底部按钮 -->
+        <div class="footer-action">
+          <button class="confirm-btn" @click="handleConfirm">确认</button>
+        </div>
+
+        <!-- 底部安全区 -->
+        <div class="safe-area-bottom"></div>
+      </div>
+    </transition>
+  </Teleport>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue';
+
+const props = defineProps({
+  visible: Boolean,
+  currentValue: String // 接收父组件当前的值
+});
+
+const emit = defineEmits(['update:visible', 'confirm']);
+
+// 选项数据
+const options = ['立即', '5分钟', '10分钟'];
+
+// 内部维护一个选中状态,用于显示对勾
+const localSelected = ref('');
+
+// 每次打开弹窗时,把父组件传来的值赋给内部状态
+watch(() => props.visible, (val) => {
+  if (val) {
+    localSelected.value = props.currentValue;
+  }
+});
+
+const close = () => {
+  emit('update:visible', false);
+};
+
+// 点击列表项(只更新 UI,不提交)
+const selectItem = (item) => {
+  localSelected.value = item;
+};
+
+// 点击确认按钮(提交数据并关闭)
+const handleConfirm = () => {
+  emit('confirm', localSelected.value);
+  close();
+};
+</script>
+
+<style scoped>
+.modal-mask {
+  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
+  background: rgba(0,0,0,0.5); z-index: 998;
+}
+
+.modal-panel {
+  position: fixed; left: 0; right: 0; bottom: 0;
+  background: #fff;
+  z-index: 999;
+  border-radius: 16px 16px 0 0;
+  padding-bottom: 20px;
+}
+
+.panel-handle {
+  width: 36px; height: 4px; background: #E0E0E0;
+  border-radius: 2px; margin: 10px auto;
+}
+
+.panel-header {
+  padding: 10px 20px 20px;
+}
+.panel-title {
+  font-size: 18px; font-weight: 600; color: #333;
+}
+
+.option-list {
+  padding: 0 20px 20px;
+}
+.option-item {
+  display: flex; justify-content: space-between; align-items: center;
+  height: 50px;
+  font-size: 16px; color: #333;
+  /* border-bottom: 1px solid #f5f5f5; 可选分割线 */
+  cursor: pointer;
+}
+
+/* 底部按钮区 */
+.footer-action {
+  padding: 10px 20px;
+}
+.confirm-btn {
+  width: 100%; height: 48px;
+  background: #E02F44; /* 截图中的红色 */
+  color: #fff; border: none; border-radius: 24px;
+  font-size: 16px; font-weight: 600;
+}
+.confirm-btn:active { opacity: 0.9; }
+
+.safe-area-bottom { height: env(safe-area-inset-bottom); }
+
+/* 动画 */
+.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; }
+.slide-up-enter-from, .slide-up-leave-to { transform: translateY(100%); }
+</style>

+ 29 - 4
src/views/user/SecuritySettings.vue

@@ -88,7 +88,7 @@
         <div class="list-item" @click="handleSetting('payment')">
           <span class="item-label">支付密码</span>
           <div class="item-right">
-             <span class="item-value">设置</span>
+             <span class="item-value" @click="router.push({name: 'SetPassword'})">设置</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>
@@ -125,7 +125,7 @@
         <div class="list-item" @click="handleSetting('appLock')">
           <span class="item-label">APP锁定</span>
           <div class="item-right">
-             <span class="item-value">5分钟</span>
+             <span class="item-value">{{ lockTime }}</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>
@@ -133,6 +133,14 @@
       </div>
 
     </div>
+     <!-- 引入弹窗组件 -->
+    <!-- currentValue: 传入当前值,保证弹窗打开时回显正确 -->
+    <!-- @confirm: 接收子组件选中的新值 -->
+    <LockTimeModal
+      v-model:visible="showModal"
+      :currentValue="lockTime"
+      @confirm="updateLockTime"
+    />
   </div>
 </template>
 
@@ -142,6 +150,21 @@ import { useRouter } from 'vue-router';
 
 const router = useRouter();
 
+import { ref } from 'vue';
+import LockTimeModal from '@/views/user/LockTimeModal.vue';
+//锁定APP
+const showModal = ref(false);
+
+// 核心状态:当前锁定的时间,默认 "5分钟"
+const lockTime = ref('5分钟');
+
+// 处理子组件传回来的值
+const updateLockTime = (newValue) => {
+  lockTime.value = newValue;
+  console.log('用户选择了:', newValue);
+  // 这里可以调用 API 保存设置
+};
+
 // 页面状态
 const settings = reactive({
   hideWallet: true,
@@ -155,8 +178,10 @@ const handleCardClick = (type) => {
 
 const handleSetting = (type) => {
   console.log('点击设置:', type);
-  if (type === 'payment') {
-    // router.push('/security/payment');
+  if (type === 'logout') {
+    router.push({name: 'DeleteAccount'});
+  }else if(type === 'appLock') {
+    showModal.value = true
   }
 };
 </script>

+ 164 - 0
src/views/user/SetPassword.vue

@@ -0,0 +1,164 @@
+<template>
+  <div class="page-container">
+    <!-- 导航栏 -->
+    <div class="nav-bar">
+      <div class="nav-left" @click="$router.back()">
+        <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">
+
+      <!-- 表单区域 -->
+      <div class="form-group">
+        <label class="form-label">填写支付密码</label>
+        <div class="input-wrapper">
+          <input
+            type="password"
+            v-model="password"
+            placeholder="请输入"
+            class="custom-input"
+            maxlength="6"
+          />
+        </div>
+      </div>
+
+      <div class="form-group">
+        <label class="form-label">请确认支付密码</label>
+        <!-- 这里的 class 用于演示截图中的选中状态效果,实际使用中浏览器自带 focus 样式 -->
+        <div class="input-wrapper">
+          <input
+            type="password"
+            v-model="confirmPassword"
+            placeholder="请输入"
+            class="custom-input"
+            maxlength="6"
+          />
+        </div>
+      </div>
+
+      <!-- 提交按钮 -->
+      <div class="footer-action">
+        <button class="submit-btn" @click="handleSubmit">提交</button>
+      </div>
+
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+import { useRouter } from 'vue-router';
+// 引入 Vant Toast (如果你的项目有安装 Vant,没有则用 alert)
+// import { showToast } from 'vant';
+
+const router = useRouter();
+
+const password = ref('');
+const confirmPassword = ref('');
+
+const handleSubmit = () => {
+  if (!password.value || !confirmPassword.value) {
+    alert('请输入密码');
+    return;
+  }
+  if (password.value !== confirmPassword.value) {
+    alert('两次输入的密码不一致');
+    return;
+  }
+  if (password.value.length < 6) {
+    alert('密码长度不能少于6位');
+    return;
+  }
+
+  // 提交逻辑...
+  console.log('提交密码:', password.value);
+  alert('设置成功');
+  router.back();
+};
+</script>
+
+<style scoped>
+.page-container {
+  min-height: 100vh;
+  background-color: #fff;
+  display: flex; flex-direction: column;
+}
+
+/* 导航栏 */
+.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;
+}
+.nav-title { font-size: 18px; font-weight: 600; color: #333; }
+.nav-left, .nav-right { width: 40px; display: flex; align-items: center; }
+
+/* 内容区 */
+.content {
+  padding: 20px;
+  flex: 1;
+  display: flex; flex-direction: column;
+}
+
+.form-group {
+  margin-bottom: 24px;
+}
+
+.form-label {
+  display: block;
+  font-size: 16px;
+  color: #333;
+  font-weight: 500;
+  margin-bottom: 12px;
+}
+
+/* 输入框样式 */
+.custom-input {
+  width: 100%;
+  height: 50px;
+  background: #F7F8FA; /* 截图中的浅灰背景 */
+  border: 1px solid transparent; /* 默认无边框 */
+  border-radius: 8px;
+  padding: 0 16px;
+  font-size: 16px;
+  color: #333;
+  box-sizing: border-box;
+  outline: none; /* 去掉浏览器默认的黑框 */
+  transition: all 0.2s;
+}
+
+/* 占位符颜色 */
+.custom-input::placeholder {
+  color: #C2C4CC;
+}
+
+/* 核心细节:输入框聚焦时变蓝 */
+.custom-input:focus {
+  border-color: #2B6BFF; /* 截图中的亮蓝色边框 */
+  background: #fff;      /* 聚焦时背景可能变白,视设计而定,这里保留灰底或变白均可 */
+}
+
+/* 底部按钮区域 */
+.footer-action {
+  margin-top: auto; /* 把按钮推到最底部 */
+  padding-bottom: 30px;
+}
+
+.submit-btn {
+  width: 100%;
+  height: 48px;
+  background: #E02F44; /* 截图中的红色 */
+  color: #fff;
+  border: none;
+  border-radius: 24px;
+  font-size: 16px;
+  font-weight: 600;
+  cursor: pointer;
+}
+.submit-btn:active {
+  opacity: 0.9;
+}
+</style>