From 2140c5aae2032673cef7055df9738b9bacf37816 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期三, 23 九月 2026 16:46:20 +0800
Subject: [PATCH] 青岛维护

---
 pagesSub/my/profile.vue |  810 ++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 485 insertions(+), 325 deletions(-)

diff --git a/pagesSub/my/profile.vue b/pagesSub/my/profile.vue
index 825292b..6c83346 100644
--- a/pagesSub/my/profile.vue
+++ b/pagesSub/my/profile.vue
@@ -1,240 +1,387 @@
 <template>
   <view class="profile-container">
     <!-- 澶村儚鍖哄煙 -->
-    <view class="avatar-section">
-      <view class="avatar-wrapper" @tap="changeAvatar">
-        <image :src="userInfo.avatar" mode="aspectFill" class="avatar" />
+    <view class="avatar-section" @tap="changeAvatar">
+      <view class="avatar-wrapper">
+        <image :src="avatarUrl" mode="aspectFill" class="avatar" />
         <view class="edit-icon">
-          <text class="iconfont icon-camera"></text>
+          <text class="plus">+</text>
         </view>
       </view>
       <text class="tip">鐐瑰嚮鏇存崲澶村儚</text>
     </view>
-    
-    <!-- 鍩烘湰淇℃伅 -->
+
+    <!-- 涓汉淇℃伅 -->
     <view class="info-card">
-      <view class="info-item" @tap="editNickname">
-        <text class="label">鏄电О</text>
-        <view class="value">
-          <text>{{ userInfo.nickname }}</text>
-          <text class="iconfont icon-arrow-right"></text>
-        </view>
-      </view>
-      
-      <view class="info-item" @tap="editGender">
-        <text class="label">鎬у埆</text>
-        <view class="value">
-          <text>{{ userInfo.gender === 1 ? '鐢�' : '濂�' }}</text>
-          <text class="iconfont icon-arrow-right"></text>
-        </view>
-      </view>
-      
-      <view class="info-item" @tap="editBirthday">
-        <text class="label">鐢熸棩</text>
-        <view class="value">
-          <text>{{ userInfo.birthday || '璇烽�夋嫨' }}</text>
-          <text class="iconfont icon-arrow-right"></text>
-        </view>
-      </view>
-      
-      <view class="info-item" @tap="editPhone">
-        <text class="label">鎵嬫満鍙�</text>
-        <view class="value">
-          <text>{{ formatPhone(userInfo.phone) }}</text>
-          <text class="iconfont icon-arrow-right"></text>
-        </view>
-      </view>
-      
-      <view class="info-item" @tap="editEmail">
-        <text class="label">閭</text>
-        <view class="value">
-          <text>{{ userInfo.email || '鏈粦瀹�' }}</text>
-          <text class="iconfont icon-arrow-right"></text>
-        </view>
-      </view>
-    </view>
-    
-    <!-- 瀹炲悕璁よ瘉 -->
-    <view class="verify-card" @tap="goVerify">
-      <view class="verify-info">
-        <text class="title">瀹炲悕璁よ瘉</text>
-        <text class="status">{{ userInfo.verified ? '宸茶璇�' : '鏈璇�' }}</text>
-      </view>
-      <text class="iconfont icon-arrow-right"></text>
-    </view>
-    
-    <!-- 闅愮璁剧疆 -->
-    <view class="privacy-card">
       <view class="card-header">
-        <text class="title">闅愮璁剧疆</text>
+        <text class="title">涓汉淇℃伅</text>
       </view>
-      <view class="setting-list">
-        <view class="setting-item">
-          <text class="label">鍏紑涓汉涓婚〉</text>
-          <switch 
-            :checked="privacy.publicProfile"
-            @change="e => togglePrivacy('publicProfile', e.detail.value)"
-            color="#0f95b0"
+      <view class="info-list">
+        <view class="info-item">
+          <text class="label">鐢ㄦ埛鍚嶇О</text>
+          <text class="value">{{ user.userName }}</text>
+        </view>
+        <view class="info-item">
+          <text class="label">鎵嬫満鍙风爜</text>
+          <text class="value">{{ user.phonenumber }}</text>
+        </view>
+        <view class="info-item">
+          <text class="label">鐢ㄦ埛閭</text>
+          <text class="value">{{ user.email }}</text>
+        </view>
+        <view class="info-item" v-if="user.dept">
+          <text class="label">鎵�灞為儴闂�</text>
+          <text class="value">{{ user.dept.deptName }} / {{ postGroup }}</text>
+        </view>
+        <view class="info-item">
+          <text class="label">鎵�灞炶鑹�</text>
+          <text class="value">{{ roleGroup }}</text>
+        </view>
+        <view class="info-item">
+          <text class="label">鍒涘缓鏃ユ湡</text>
+          <text class="value">{{ user.createTime }}</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- 鍩烘湰璧勬枡 -->
+    <view class="info-card">
+      <view class="card-header">
+        <text class="title">鍩烘湰璧勬枡</text>
+      </view>
+      <view class="form-list">
+        <view class="form-item">
+          <text class="label required">鐢ㄦ埛鏄电О</text>
+          <input
+            v-model="form.nickName"
+            placeholder="璇疯緭鍏ョ敤鎴锋樀绉�"
+            maxlength="30"
           />
         </view>
-        <view class="setting-item">
-          <text class="label">鍏佽闄岀敓浜虹淇�</text>
-          <switch 
-            :checked="privacy.allowMessage"
-            @change="e => togglePrivacy('allowMessage', e.detail.value)"
-            color="#0f95b0"
+        <view class="form-item">
+          <text class="label required">鎵嬫満鍙风爜</text>
+          <input
+            v-model="form.phonenumber"
+            type="number"
+            placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�"
+            maxlength="11"
+          />
+        </view>
+        <view class="form-item">
+          <text class="label required">閭</text>
+          <input
+            v-model="form.email"
+            placeholder="璇疯緭鍏ラ偖绠�"
+            maxlength="50"
+          />
+        </view>
+        <view class="form-item">
+          <text class="label">鎬у埆</text>
+          <view class="gender-types">
+            <view
+              class="gender-item"
+              :class="{ active: form.sex === '0' }"
+              @tap="form.sex = '0'"
+            >
+              <text class="radio"></text>
+              <text>鐢�</text>
+            </view>
+            <view
+              class="gender-item"
+              :class="{ active: form.sex === '1' }"
+              @tap="form.sex = '1'"
+            >
+              <text class="radio"></text>
+              <text>濂�</text>
+            </view>
+          </view>
+        </view>
+      </view>
+      <button class="save-btn" @tap="saveProfile">淇濆瓨</button>
+    </view>
+
+    <!-- 淇敼瀵嗙爜 -->
+    <view class="info-card">
+      <view class="card-header">
+        <text class="title">淇敼瀵嗙爜</text>
+      </view>
+      <view class="form-list">
+        <view class="form-item">
+          <text class="label required">鏃у瘑鐮�</text>
+          <input
+            v-model="pwdForm.oldPassword"
+            :password="true"
+            placeholder="璇疯緭鍏ユ棫瀵嗙爜"
+          />
+        </view>
+        <view class="form-item">
+          <text class="label required">鏂板瘑鐮�</text>
+          <input
+            v-model="pwdForm.newPassword"
+            :password="true"
+            placeholder="璇疯緭鍏ユ柊瀵嗙爜锛�8-20浣嶏級"
+          />
+        </view>
+        <view class="form-item">
+          <text class="label required">纭瀵嗙爜</text>
+          <input
+            v-model="pwdForm.confirmPassword"
+            :password="true"
+            placeholder="璇风‘璁ゆ柊瀵嗙爜"
           />
         </view>
       </view>
+      <button class="save-btn" @tap="savePassword">淇濆瓨</button>
     </view>
-    
-    <!-- 璐﹀彿瀹夊叏 -->
-    <view class="security-card">
-      <view class="card-header">
-        <text class="title">璐﹀彿瀹夊叏</text>
-      </view>
-      <view class="security-list">
-        <view class="security-item" @tap="changePassword">
-          <view class="info">
-            <text class="label">淇敼瀵嗙爜</text>
-            <text class="desc">寤鸿瀹氭湡鏇存崲瀵嗙爜锛岀‘淇濊处鍙峰畨鍏�</text>
-          </view>
-          <text class="iconfont icon-arrow-right"></text>
-        </view>
-        <view class="security-item" @tap="bindPhone">
-          <view class="info">
-            <text class="label">鎵嬫満缁戝畾</text>
-            <text class="desc">宸茬粦瀹氭墜鏈哄彿锛歿{ formatPhone(userInfo.phone) }}</text>
-          </view>
-          <text class="iconfont icon-arrow-right"></text>
-        </view>
-      </view>
-    </view>
-    
+
     <!-- 閫�鍑虹櫥褰� -->
     <button class="logout-btn" @tap="logout">閫�鍑虹櫥褰�</button>
   </view>
 </template>
 
 <script setup>
-import { ref } from 'vue'
+import { ref, computed } from "vue";
+import { onLoad } from "@dcloudio/uni-app";
+import { useUserStore } from "@/stores/user";
 
-// 鐢ㄦ埛淇℃伅
-const userInfo = ref({
-  avatar: '/static/avatar/default.jpg',
-  nickname: '寮犱笁',
-  gender: 1,
-  birthday: '1990-01-01',
-  phone: '13800138000',
-  email: 'example@email.com',
-  verified: true
-})
+const userStore = useUserStore();
 
-// 闅愮璁剧疆
-const privacy = ref({
-  publicProfile: true,
-  allowMessage: false
-})
+// 鐢ㄦ埛淇℃伅锛堟潵鑷� /system/user/profile锛�
+const user = ref({});
+const roleGroup = ref("");
+const postGroup = ref("");
 
-// 鏍煎紡鍖栨墜鏈哄彿
-const formatPhone = (phone) => {
-  if (!phone) return '鏈粦瀹�'
-  return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
-}
+// 鍩烘湰璧勬枡琛ㄥ崟
+const form = ref({
+  nickName: "",
+  phonenumber: "",
+  email: "",
+  sex: "0",
+});
+
+// 淇敼瀵嗙爜琛ㄥ崟
+const pwdForm = ref({
+  oldPassword: "",
+  newPassword: "",
+  confirmPassword: "",
+});
+
+// 澶村儚鍦板潃锛堢浉瀵硅矾寰勬嫾鎺ユ湇鍔″櫒鍦板潃锛�
+const avatarUrl = computed(() => {
+  const avatar = user.value.avatar;
+  if (!avatar) return "/static/avatar/default.png";
+  if (/^https?:\/\//.test(avatar)) return avatar;
+  // #ifdef H5
+  return `/api${avatar}`;
+  // #endif
+  // #ifndef H5
+  return `${userStore.baseUrlHt}${avatar}`;
+  // #endif
+});
+
+onLoad(() => {
+  loadProfile();
+});
+
+// 鍔犺浇涓汉淇℃伅
+const loadProfile = async () => {
+  // 鍏堢敤 store 涓殑鐢ㄦ埛淇℃伅鍏滃簳鏄剧ず
+  if (userStore.userInfo) {
+    user.value = { ...userStore.userInfo };
+    fillForm();
+  }
+  try {
+    const res = await uni.$uapi.get("/system/user/profile");
+    user.value = res.data || {};
+    roleGroup.value = res.roleGroup || "";
+    postGroup.value = res.postGroup || "";
+    fillForm();
+  } catch (e) {
+    // 鎷︽埅鍣ㄥ凡缁熶竴鎻愮ず
+  }
+};
+
+// 鐢ㄧ敤鎴蜂俊鎭洖濉熀鏈祫鏂欒〃鍗�
+const fillForm = () => {
+  form.value.nickName = user.value.nickName || "";
+  form.value.phonenumber = user.value.phonenumber || "";
+  form.value.email = user.value.email || "";
+  form.value.sex = String(user.value.sex ?? "0");
+};
 
 // 鏇存崲澶村儚
 const changeAvatar = () => {
   uni.chooseImage({
     count: 1,
+    sizeType: ["compressed"],
+    sourceType: ["album", "camera"],
     success: (res) => {
-      // 杩欓噷澶勭悊澶村儚涓婁紶閫昏緫
-      userInfo.value.avatar = res.tempFilePaths[0]
-    }
-  })
-}
+      uploadAvatar(res.tempFilePaths[0]);
+    },
+  });
+};
 
-// 缂栬緫鏄电О
-const editNickname = () => {
-  uni.navigateTo({
-    url: '/pages/my/edit-nickname'
-  })
-}
+// 涓婁紶澶村儚
+const uploadAvatar = (filePath) => {
+  uni.showLoading({ title: "涓婁紶涓�...", mask: true });
+  const token = uni.getStorageSync("token");
+  // #ifdef H5
+  const uploadUrl = "/api/system/user/profile/avatar";
+  // #endif
+  // #ifndef H5
+  const uploadUrl = `${userStore.baseUrlHt}/system/user/profile/avatar`;
+  // #endif
 
-// 缂栬緫鎬у埆
-const editGender = () => {
-  uni.showActionSheet({
-    itemList: ['鐢�', '濂�'],
+  uni.uploadFile({
+    url: uploadUrl,
+    filePath,
+    name: "avatarfile",
+    header: { Authorization: `Bearer ${token}` },
     success: (res) => {
-      userInfo.value.gender = res.tapIndex + 1
-    }
-  })
-}
+      uni.hideLoading();
+      if (res.statusCode === 200) {
+        try {
+          const data = JSON.parse(res.data);
+          if (data.code === 200) {
+            user.value.avatar = data.imgUrl;
+            userStore.refreshUserInfo();
+            uni.showToast({ title: "澶村儚淇敼鎴愬姛", icon: "success" });
+          } else {
+            uni.showToast({ title: data.msg || "涓婁紶澶辫触", icon: "none" });
+          }
+        } catch (e) {
+          uni.showToast({ title: "鍝嶅簲瑙f瀽澶辫触", icon: "none" });
+        }
+      } else {
+        uni.showToast({
+          title: `涓婁紶澶辫触锛岀姸鎬佺爜: ${res.statusCode}`,
+          icon: "none",
+        });
+      }
+    },
+    fail: () => {
+      uni.hideLoading();
+      uni.showToast({ title: "涓婁紶澶辫触", icon: "none" });
+    },
+  });
+};
 
-// 缂栬緫鐢熸棩
-const editBirthday = () => {
-  uni.showDatePicker({
-    current: userInfo.value.birthday,
-    success: (res) => {
-      userInfo.value.birthday = res.date
-    }
-  })
-}
+// 淇濆瓨鍩烘湰璧勬枡
+const saveProfile = async () => {
+  if (!form.value.nickName) {
+    uni.showToast({ title: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", icon: "none" });
+    return;
+  }
+  if (!form.value.phonenumber) {
+    uni.showToast({ title: "鎵嬫満鍙风爜涓嶈兘涓虹┖", icon: "none" });
+    return;
+  }
+  if (!/^1[3|4|5|6|7|8|9][0-9]\d{8}$/.test(form.value.phonenumber)) {
+    uni.showToast({ title: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", icon: "none" });
+    return;
+  }
+  if (!form.value.email) {
+    uni.showToast({ title: "閭鍦板潃涓嶈兘涓虹┖", icon: "none" });
+    return;
+  }
+  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.value.email)) {
+    uni.showToast({ title: "璇疯緭鍏ユ纭殑閭鍦板潃", icon: "none" });
+    return;
+  }
 
-// 缂栬緫鎵嬫満鍙�
-const editPhone = () => {
-  uni.navigateTo({
-    url: '/pages/my/edit-phone'
-  })
-}
+  uni.showLoading({ title: "淇濆瓨涓�...", mask: true });
+  try {
+    await uni.$uapi.post("/system/user/profile/updateProfile", {
+      nickName: form.value.nickName,
+      phonenumber: form.value.phonenumber,
+      email: form.value.email,
+      sex: form.value.sex,
+    });
+    uni.hideLoading();
+    uni.showToast({ title: "淇敼鎴愬姛", icon: "success" });
 
-// 缂栬緫閭
-const editEmail = () => {
-  uni.navigateTo({
-    url: '/pages/my/edit-email'
-  })
-}
+    // 鍚屾鏈湴鏄剧ず涓� store
+    user.value.nickName = form.value.nickName;
+    user.value.phonenumber = form.value.phonenumber;
+    user.value.email = form.value.email;
+    user.value.sex = form.value.sex;
+    userStore.refreshUserInfo();
+  } catch (e) {
+    uni.hideLoading();
+  }
+};
 
-// 鍓嶅線瀹炲悕璁よ瘉
-const goVerify = () => {
-  uni.navigateTo({
-    url: '/pages/my/verify'
-  })
-}
+// 瀵嗙爜澶嶆潅搴︽牎楠岋細闇�鍚屾椂鍖呭惈澶у啓銆佸皬鍐欍�佹暟瀛楀拰鐗规畩瀛楃鍏朵腑涓夐」
+const checkPwdLegal = (pwd) => {
+  if (!pwd || pwd.length < 8 || pwd.length > 20) return false;
+  let count = 0;
+  if (/[a-z]/.test(pwd)) count++;
+  if (/[A-Z]/.test(pwd)) count++;
+  if (/[0-9]/.test(pwd)) count++;
+  if (/[\W_]/.test(pwd)) count++;
+  return count >= 3;
+};
 
-// 鍒囨崲闅愮璁剧疆
-const togglePrivacy = (key, value) => {
-  privacy.value[key] = value
-}
+// 淇濆瓨瀵嗙爜
+const savePassword = async () => {
+  const { oldPassword, newPassword, confirmPassword } = pwdForm.value;
+  if (!oldPassword) {
+    uni.showToast({ title: "鏃у瘑鐮佷笉鑳戒负绌�", icon: "none" });
+    return;
+  }
+  if (!newPassword) {
+    uni.showToast({ title: "鏂板瘑鐮佷笉鑳戒负绌�", icon: "none" });
+    return;
+  }
+  if (newPassword.length < 8 || newPassword.length > 20) {
+    uni.showToast({ title: "瀵嗙爜闀垮害鍦� 8 鍒� 20 涓瓧绗�", icon: "none" });
+    return;
+  }
+  if (!checkPwdLegal(newPassword)) {
+    uni.showToast({
+      title: "瀵嗙爜蹇呴』鍚屾椂鍖呭惈澶у啓銆佸皬鍐欍�佹暟瀛楀拰鐗规畩瀛楃鍏朵腑涓夐」",
+      icon: "none",
+    });
+    return;
+  }
+  if (!confirmPassword) {
+    uni.showToast({ title: "纭瀵嗙爜涓嶈兘涓虹┖", icon: "none" });
+    return;
+  }
+  if (confirmPassword !== newPassword) {
+    uni.showToast({ title: "涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�", icon: "none" });
+    return;
+  }
 
-// 淇敼瀵嗙爜
-const changePassword = () => {
-  uni.navigateTo({
-    url: '/pages/my/change-password'
-  })
-}
-
-// 缁戝畾鎵嬫満
-const bindPhone = () => {
-  uni.navigateTo({
-    url: '/pages/my/bind-phone'
-  })
-}
+  uni.showLoading({ title: "淇濆瓨涓�...", mask: true });
+  try {
+    await uni.$uapi.post("/system/user/profile/updatePwd", {
+      oldPassword,
+      newPassword,
+    });
+    uni.hideLoading();
+    uni.showToast({ title: "瀵嗙爜淇敼鎴愬姛", icon: "success" });
+    pwdForm.value = { oldPassword: "", newPassword: "", confirmPassword: "" };
+  } catch (e) {
+    uni.hideLoading();
+  }
+};
 
 // 閫�鍑虹櫥褰�
 const logout = () => {
   uni.showModal({
-    title: '鎻愮ず',
-    content: '纭畾瑕侀��鍑虹櫥褰曞悧锛�',
+    title: "鎻愮ず",
+    content: "纭畾瑕侀��鍑虹櫥褰曞悧锛�",
     success: (res) => {
       if (res.confirm) {
-        // 杩欓噷澶勭悊閫�鍑虹櫥褰曢�昏緫
+        uni.clearStorageSync();
         uni.reLaunch({
-          url: '/pages/login/Login'
-        })
+          url: "/pages/login/Login",
+        });
       }
-    }
-  })
-}
+    },
+  });
+};
 </script>
 
 <style lang="scss">
@@ -242,209 +389,222 @@
   min-height: 100vh;
   background: $bg-color;
   padding-bottom: 40rpx;
-  
+
   .avatar-section {
     display: flex;
     flex-direction: column;
     align-items: center;
-    padding: 60rpx 0;
-    background: #fff;
-    
+    padding: 60rpx 0 40rpx;
+    background: $primary-gradient;
+
     .avatar-wrapper {
       position: relative;
-      margin-bottom: 20rpx;
-      
+      margin-bottom: 16rpx;
+
       .avatar {
         width: 160rpx;
         height: 160rpx;
         border-radius: 50%;
+        border: 4rpx solid rgba(255, 255, 255, 0.4);
       }
-      
+
       .edit-icon {
         position: absolute;
         right: 0;
         bottom: 0;
         width: 48rpx;
         height: 48rpx;
-        background: $primary-color;
+        background: #fff;
         border-radius: 50%;
         display: flex;
         align-items: center;
         justify-content: center;
-        
-        .iconfont {
-          font-size: 28rpx;
-          color: #fff;
+
+        .plus {
+          font-size: 40rpx;
+          font-weight: bold;
+          color: $primary-color;
+          line-height: 1;
         }
       }
     }
-    
+
     .tip {
-      font-size: 26rpx;
-      color: $text-secondary;
+      font-size: 24rpx;
+      color: rgba(255, 255, 255, 0.9);
     }
   }
-  
+
   .info-card {
     background: #fff;
-    margin: 20rpx 0;
-    
-    .info-item {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-      padding: 30rpx;
-      border-bottom: 1rpx solid $border-color;
-      
-      &:last-child {
-        border-bottom: none;
-      }
-      
-      .label {
-        font-size: 30rpx;
-        color: $text-primary;
-      }
-      
-      .value {
-        display: flex;
-        align-items: center;
-        
-        text {
-          font-size: 30rpx;
-          color: $text-regular;
-          
-          &.iconfont {
-            font-size: 32rpx;
-            color: $text-secondary;
-            margin-left: 12rpx;
-          }
-        }
-      }
-      
-      &:active {
-        background: $bg-color;
-      }
-    }
-  }
-  
-  .verify-card {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    background: #fff;
-    padding: 30rpx;
-    margin: 20rpx 0;
-    
-    .verify-info {
-      .title {
-        font-size: 30rpx;
-        color: $text-primary;
-        margin-bottom: 8rpx;
-        display: block;
-      }
-      
-      .status {
-        font-size: 26rpx;
-        color: $success;
-      }
-    }
-    
-    .iconfont {
-      font-size: 32rpx;
-      color: $text-secondary;
-    }
-    
-    &:active {
-      background: $bg-color;
-    }
-  }
-  
-  .privacy-card,
-  .security-card {
-    background: #fff;
-    margin: 20rpx 0;
-    
+    margin: 20rpx 20rpx 0;
+    border-radius: $radius-lg;
+    overflow: hidden;
+    box-shadow: $shadow-sm;
+
     .card-header {
       padding: 30rpx;
-      border-bottom: 1rpx solid $border-color;
-      
+      border-bottom: 1rpx solid #eee;
+
       .title {
         font-size: 32rpx;
         color: $text-primary;
         font-weight: bold;
       }
     }
-    
-    .setting-list {
-      .setting-item {
+
+    .info-list {
+      .info-item {
         display: flex;
         justify-content: space-between;
         align-items: center;
-        padding: 30rpx;
-        border-bottom: 1rpx solid $border-color;
-        
+        padding: 28rpx 30rpx;
+        border-bottom: 1rpx solid #f5f5f5;
+
         &:last-child {
           border-bottom: none;
         }
-        
+
         .label {
-          font-size: 30rpx;
+          font-size: 28rpx;
+          color: $text-regular;
+        }
+
+        .value {
+          font-size: 28rpx;
           color: $text-primary;
+          text-align: right;
+          flex: 1;
+          margin-left: 20rpx;
         }
       }
     }
-    
-    .security-list {
-      .security-item {
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-        padding: 30rpx;
-        border-bottom: 1rpx solid $border-color;
-        
+
+    .form-list {
+      padding: 0 30rpx;
+
+      .form-item {
+        margin-top: 30rpx;
+
         &:last-child {
-          border-bottom: none;
+          margin-bottom: 30rpx;
         }
-        
-        .info {
-          .label {
-            font-size: 30rpx;
-            color: $text-primary;
-            margin-bottom: 8rpx;
-            display: block;
-          }
-          
-          .desc {
-            font-size: 26rpx;
-            color: $text-secondary;
+
+        .label {
+          font-size: 28rpx;
+          color: $text-primary;
+          margin-bottom: 16rpx;
+          display: block;
+
+          &.required::before {
+            content: "*";
+            color: $danger;
+            margin-right: 4rpx;
           }
         }
-        
-        .iconfont {
-          font-size: 32rpx;
-          color: $text-secondary;
-        }
-        
-        &:active {
+
+        input {
+          width: 100%;
+          height: 88rpx;
           background: $bg-color;
+          border-radius: $radius-lg;
+          padding: 0 30rpx;
+          font-size: 28rpx;
+          color: $text-primary;
+          box-sizing: border-box;
         }
+
+        .gender-types {
+          display: flex;
+          gap: 30rpx;
+
+          .gender-item {
+            flex: 1;
+            height: 88rpx;
+            background: $bg-color;
+            border-radius: $radius-lg;
+            display: flex;
+            align-items: center;
+            padding: 0 30rpx;
+
+            .radio {
+              width: 32rpx;
+              height: 32rpx;
+              border: 2rpx solid $text-secondary;
+              border-radius: 50%;
+              margin-right: 16rpx;
+              position: relative;
+
+              &::after {
+                content: "";
+                position: absolute;
+                left: 50%;
+                top: 50%;
+                transform: translate(-50%, -50%);
+                width: 16rpx;
+                height: 16rpx;
+                background: $primary-color;
+                border-radius: 50%;
+                opacity: 0;
+                transition: all 0.3s;
+              }
+            }
+
+            text {
+              font-size: 28rpx;
+              color: $text-regular;
+            }
+
+            &.active {
+              background: $primary-light;
+
+              .radio {
+                border-color: $primary-color;
+
+                &::after {
+                  opacity: 1;
+                }
+              }
+
+              text {
+                color: $primary-color;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    .save-btn {
+      width: calc(100% - 60rpx);
+      height: 80rpx;
+      line-height: 80rpx;
+      margin: 0 30rpx 30rpx;
+      font-size: 30rpx;
+      color: #fff;
+      background: $primary-gradient;
+      border-radius: $radius-xl;
+      box-shadow: 0 4rpx 12rpx rgba($primary-color, 0.3);
+
+      &:active {
+        opacity: 0.85;
       }
     }
   }
-  
+
   .logout-btn {
     width: calc(100% - 60rpx);
     height: 88rpx;
     line-height: 88rpx;
-    margin: 40rpx auto;
+    margin: 40rpx auto 0;
     font-size: 32rpx;
-    color: $warning;
+    color: $danger;
     background: #fff;
     border-radius: $radius-lg;
-    
+
     &:active {
       opacity: 0.8;
     }
   }
 }
-</style>
\ No newline at end of file
+</style>

--
Gitblit v1.9.3