Ver Fonte

个人中心修改

Zhangbw há 3 meses atrás
pai
commit
1ae5322815

+ 54 - 60
dist/dev/mp-weixin/pages/mine/mine.js

@@ -30,50 +30,38 @@ const _sfc_main = {
         }
       }
     };
-    const handleEditProfile = () => {
-      if (!utils_auth.checkLogin()) {
-        return;
+    const handleUserCardClick = () => {
+      if (!isLoggedIn.value) {
+        handleLogin();
       }
-      common_vendor.index.navigateTo({
-        url: "/pages/profile/edit"
-      });
-    };
-    const handleLogin = () => {
-      console.log("[我的] 显示手机号授权弹窗");
-      showPhoneAuth.value = true;
     };
-    const onGetPhoneNumber = async (e) => {
-      console.log("[我的] 获取手机号回调:", e.detail);
-      if (e.detail.errMsg === "getPhoneNumber:ok") {
-        const phoneCode = e.detail.code;
-        console.log("[我的] phoneCode:", phoneCode);
-        common_vendor.index.showLoading({
-          title: "登录中...",
-          mask: true
-        });
-        try {
-          const loginRes = await common_vendor.index.login();
-          console.log("[我的] uni.login完整响应:", loginRes);
-          console.log("[我的] 微信登录code:", loginRes.code);
-          if (!loginRes.code) {
-            throw new Error("获取微信登录code失败");
-          }
-          const result = await utils_auth.wxAuthLogin(loginRes.code, phoneCode);
-          common_vendor.index.hideLoading();
-          if (result) {
-            showPhoneAuth.value = false;
-            loadUserInfo();
-          }
-        } catch (error) {
-          common_vendor.index.hideLoading();
-          console.error("[我的] 登录失败:", error);
+    const handleLogin = async () => {
+      console.log("[我的] 开始登录流程");
+      common_vendor.index.showLoading({
+        title: "登录中...",
+        mask: true
+      });
+      try {
+        const loginRes = await common_vendor.index.login();
+        console.log("[我的] uni.login完整响应:", loginRes);
+        if (!loginRes.code) {
+          throw new Error("获取微信登录code失败");
         }
-      } else {
-        showPhoneAuth.value = false;
+        common_vendor.index.hideLoading();
+        showPhoneAuth.value = true;
+        common_vendor.index.showModal({
+          title: "授权提示",
+          content: "需要授权手机号才能完成登录",
+          showCancel: false,
+          success: () => {
+          }
+        });
+      } catch (error) {
+        common_vendor.index.hideLoading();
+        console.error("[我的] 登录失败:", error);
         common_vendor.index.showToast({
-          title: "需要授权手机号才能完成登录",
-          icon: "none",
-          duration: 2e3
+          title: "登录失败,请重试",
+          icon: "none"
         });
       }
     };
@@ -91,6 +79,12 @@ const _sfc_main = {
         }
       });
     };
+    const handleViewPoints = () => {
+      if (!utils_auth.checkLogin()) {
+        return;
+      }
+      common_vendor.index.showToast({ title: `当前积分: ${points.value}`, icon: "none" });
+    };
     const handleRecharge = () => {
       if (!utils_auth.checkLogin()) {
         return;
@@ -101,30 +95,30 @@ const _sfc_main = {
       if (!utils_auth.checkLogin()) {
         return;
       }
-      common_vendor.index.showToast({ title: "记录功能开发中", icon: "none" });
+      common_vendor.index.showToast({ title: "积分记录功能开发中", icon: "none" });
+    };
+    const handleTransactionRecord = () => {
+      if (!utils_auth.checkLogin()) {
+        return;
+      }
+      common_vendor.index.navigateTo({
+        url: "/pages/transaction/transaction"
+      });
     };
     return (_ctx, _cache) => {
       return common_vendor.e({
         a: isLoggedIn.value && userInfo.value.avatar ? userInfo.value.avatar : "/static/images/head.png",
-        b: common_vendor.o(handleEditProfile),
-        c: common_vendor.t(isLoggedIn.value ? userInfo.value.nickname || "微信用户" : "游客"),
-        d: isLoggedIn.value && userInfo.value.phone
-      }, isLoggedIn.value && userInfo.value.phone ? {
-        e: common_vendor.t(userInfo.value.phone)
-      } : {}, {
-        f: common_vendor.t(isLoggedIn.value ? points.value : 0),
-        g: common_vendor.o(handleRecharge),
-        h: common_vendor.o(handleHistory),
-        i: !isLoggedIn.value && !showPhoneAuth.value
-      }, !isLoggedIn.value && !showPhoneAuth.value ? {
-        j: common_vendor.o(handleLogin)
-      } : !isLoggedIn.value && showPhoneAuth.value ? {
-        l: common_vendor.o(onGetPhoneNumber)
-      } : {
-        m: common_vendor.o(handleLogout)
-      }, {
-        k: !isLoggedIn.value && showPhoneAuth.value
-      });
+        b: common_vendor.t(isLoggedIn.value ? userInfo.value.nickname || "微信用户" : "登录/注册"),
+        c: common_vendor.o(handleUserCardClick),
+        d: common_vendor.t(isLoggedIn.value ? points.value : 0),
+        e: common_vendor.o(handleViewPoints),
+        f: common_vendor.o(handleRecharge),
+        g: common_vendor.o(handleHistory),
+        h: common_vendor.o(handleTransactionRecord),
+        i: isLoggedIn.value
+      }, isLoggedIn.value ? {
+        j: common_vendor.o(handleLogout)
+      } : {});
     };
   }
 };

+ 1 - 1
dist/dev/mp-weixin/pages/mine/mine.wxml

@@ -1 +1 @@
-<view class="page-mine"><view class="user-card"><view class="avatar-container" bindtap="{{b}}"><image class="avatar" src="{{a}}" mode="aspectFill"></image><view class="edit-icon">✏️</view></view><view class="user-info"><text class="username">{{c}}</text><text wx:if="{{d}}" class="phone">{{e}}</text></view></view><view class="section-card"><view class="card-header"><view class="header-icon-box"><text class="header-icon-text">🪙</text></view><text class="header-title">积分值</text></view><view class="card-content points-content"><text class="points-value">积分值:{{f}}</text><view class="points-actions"><button class="mini-btn" bindtap="{{g}}">充值</button><button class="mini-btn" bindtap="{{h}}">积分记录</button></view></view></view><view class="section-card"><view class="card-header"><view class="header-icon-box"><text class="header-icon-text">📝</text></view><text class="header-title">交易记录</text></view><view class="card-content transaction-content"><text class="empty-text">暂无交易记录</text></view></view><view class="action-area"><button wx:if="{{i}}" class="main-btn" bindtap="{{j}}"> 微信授权登录 </button><button wx:elif="{{k}}" class="main-btn phone-auth-btn" open-type="getPhoneNumber" bindgetphonenumber="{{l}}"> 授权手机号 </button><button wx:else class="main-btn" bindtap="{{m}}"> 退出登录 </button></view></view>
+<view class="page-mine"><view class="page-title-card"><text class="page-title-text">量化选股大师</text></view><scroll-view class="scroll-view" scroll-y><view class="content-wrapper"><view class="user-info-card" bindtap="{{c}}"><view class="user-header"><image class="user-avatar" src="{{a}}" mode="aspectFill"></image><view class="user-details"><text class="user-name">{{b}}</text></view><view class="arrow-icon">›</view></view></view><view class="my-tasks-section"><view class="tasks-grid"><view class="task-item" bindtap="{{e}}"><view class="task-icon-wrapper points"><text class="task-icon">💰</text></view><view class="task-info"><text class="task-label">积分</text><text class="task-value">{{d}}</text></view></view><view class="task-item" bindtap="{{f}}"><view class="task-icon-wrapper recharge"><text class="task-icon">💳</text></view><view class="task-info"><text class="task-label">充值</text></view></view><view class="task-item" bindtap="{{g}}"><view class="task-icon-wrapper history"><text class="task-icon">📋</text></view><view class="task-info"><text class="task-label">积分记录</text></view></view></view></view><view class="menu-list"><view class="menu-item" bindtap="{{h}}"><view class="menu-left"><text class="menu-icon">📝</text><text class="menu-label">交易记录</text></view><text class="menu-arrow">›</text></view></view><view wx:if="{{i}}" class="logout-section"><button class="logout-btn" bindtap="{{j}}"> 退出登录 </button></view><view class="bottom-safe-area"></view></view></scroll-view></view>

+ 135 - 110
dist/dev/mp-weixin/pages/mine/mine.wxss

@@ -1,164 +1,189 @@
 
 .page-mine {
+  height: 100vh;
   display: flex;
   flex-direction: column;
   background: #f5f6fb;
-  min-height: 100vh;
-  padding: 30rpx;
-  box-sizing: border-box;
+}
+.page-title-card {
+  background: #ffffff;
+  padding: 30rpx 0;
+  text-align: center;
+  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
+  border-radius: 0;
+}
+.page-title-text {
+  font-size: 36rpx;
+  font-weight: 800;
+  color: #3F51F7;
+  letter-spacing: 2rpx;
+}
+.scroll-view {
+  flex: 1;
+  height: 0;
+}
+.content-wrapper {
+  padding: 32rpx;
+  background: #f5f6fb;
+  min-height: 100%;
 }
 
-/* User Card */
-.user-card {
+/* 用户信息卡片 */
+.user-info-card {
   background: #ffffff;
-  border-radius: 20rpx;
-  padding: 40rpx;
-  display: flex;
-  align-items: center;
+  border-radius: 24rpx;
+  padding: 40rpx 32rpx;
+  margin-bottom: 32rpx;
   box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 30rpx;
 }
-.avatar-container {
-  width: 120rpx;
-  height: 120rpx;
-  border-radius: 50%;
-  overflow: hidden;
-  background-color: #eee;
-  flex-shrink: 0;
-  position: relative;
-  cursor: pointer;
-}
-.edit-icon {
-  position: absolute;
-  bottom: 0;
-  right: 0;
-  width: 36rpx;
-  height: 36rpx;
-  background: #5d55e8;
-  border-radius: 50%;
+.user-header {
   display: flex;
   align-items: center;
-  justify-content: center;
-  font-size: 20rpx;
-  border: 2rpx solid #fff;
 }
-.avatar {
-  width: 100%;
-  height: 100%;
+.user-avatar {
+  width: 100rpx;
+  height: 100rpx;
+  border-radius: 50%;
+  background: #f5f6fb;
+  margin-right: 24rpx;
+  border: 4rpx solid #f5f6fb;
 }
-.user-info {
-  margin-left: 30rpx;
+.user-details {
   flex: 1;
   display: flex;
   flex-direction: column;
 }
-.username {
-  font-size: 36rpx;
-  font-weight: bold;
+.user-name {
+  font-size: 32rpx;
+  font-weight: 600;
   color: #222222;
-  margin-bottom: 10rpx;
+  margin-bottom: 8rpx;
 }
-.phone {
-  font-size: 24rpx;
-  color: #999999;
+.arrow-icon {
+  font-size: 48rpx;
+  color: #9ca2b5;
+  font-weight: 300;
 }
 
-/* Section Cards */
-.section-card {
+/* 积分区域 */
+.my-tasks-section {
   background: #ffffff;
-  border-radius: 20rpx;
-  overflow: hidden;
+  border-radius: 24rpx;
+  padding: 32rpx;
+  margin-bottom: 32rpx;
   box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 30rpx;
 }
-.card-header {
-  background: linear-gradient(135deg, #5d55e8, #7568ff);
-  padding: 20rpx 30rpx;
+.tasks-grid {
+  display: flex;
+  flex-direction: column;
+  gap: 24rpx;
+}
+.task-item {
   display: flex;
   align-items: center;
+  padding: 24rpx;
+  background: #f7f8fc;
+  border-radius: 16rpx;
 }
-.header-icon-box {
-  width: 40rpx;
-  height: 40rpx;
+.task-icon-wrapper {
+  width: 80rpx;
+  height: 80rpx;
+  border-radius: 50%;
   display: flex;
   align-items: center;
   justify-content: center;
-  margin-right: 15rpx;
+  margin-right: 24rpx;
+  flex-shrink: 0;
+  box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1);
 }
-.header-icon-text {
-  font-size: 32rpx;
-  color: #fff;
+.task-icon-wrapper.points {
+  background: linear-gradient(135deg, #00BFA5, #00D4B5);
 }
-.header-title {
-  color: #ffffff;
-  font-size: 32rpx;
-  font-weight: bold;
+.task-icon-wrapper.recharge {
+  background: linear-gradient(135deg, #5d55e8, #7568ff);
+}
+.task-icon-wrapper.history {
+  background: linear-gradient(135deg, #FF9800, #FFA726);
 }
-.card-content {
-  padding: 30rpx;
-  background: #fff;
+.task-icon {
+  font-size: 40rpx;
 }
-
-/* Points Content */
-.points-content {
+.task-info {
+  flex: 1;
   display: flex;
-  justify-content: space-between;
   align-items: center;
+  justify-content: space-between;
 }
-.points-value {
-  font-size: 32rpx;
+.task-label {
+  font-size: 28rpx;
   color: #222222;
   font-weight: 500;
 }
-.points-actions {
-  display: flex;
-  gap: 20rpx;
+.task-value {
+  font-size: 32rpx;
+  font-weight: 700;
+  color: #00BFA5;
 }
-.mini-btn {
-  background: linear-gradient(135deg, #5d55e8, #7568ff);
-  color: #fff;
-  font-size: 24rpx;
-  padding: 10rpx 30rpx;
-  border-radius: 30rpx;
-  line-height: 2;
-  margin: 0;
-  border: none;
-  box-shadow: 0 4rpx 12rpx rgba(93, 85, 232, 0.3);
+
+/* 菜单列表 */
+.menu-list {
+  background: #ffffff;
+  border-radius: 24rpx;
+  overflow: hidden;
+  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
+  margin-bottom: 32rpx;
 }
-.mini-btn::after {
-  border: none;
+.menu-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 32rpx;
+  border-bottom: 1rpx solid #f5f6fb;
 }
-
-/* Transaction Content */
-.transaction-content {
+.menu-item:last-child {
+  border-bottom: none;
+}
+.menu-left {
   display: flex;
-  justify-content: center;
-  padding: 60rpx 30rpx;
+  align-items: center;
 }
-.empty-text {
-  color: #999;
+.menu-icon {
+  font-size: 36rpx;
+  margin-right: 20rpx;
+}
+.menu-label {
   font-size: 28rpx;
+  color: #222222;
+}
+.menu-arrow {
+  font-size: 40rpx;
+  color: #9ca2b5;
+  font-weight: 300;
 }
 
-/* Bottom Action */
-.action-area {
-  margin-top: 40rpx;
+/* 退出登录按钮 */
+.logout-section {
+  margin-top: 20rpx;
 }
-.main-btn {
-  background: linear-gradient(135deg, #5d55e8, #7568ff);
-  color: #fff;
-  font-size: 32rpx;
-  border-radius: 50rpx;
-  padding: 10rpx 0;
+.logout-btn {
   width: 100%;
-  box-shadow: 0 12rpx 24rpx rgba(93, 85, 232, 0.4);
-  line-height: 2.5;
+  background: #5d55e8;
+  color: #ffffff;
+  border-radius: 16rpx;
+  padding: 28rpx 0;
+  text-align: center;
+  font-size: 30rpx;
+  font-weight: 600;
+  box-shadow: 0 12rpx 24rpx rgba(93, 85, 232, 0.3);
+  border: none;
+  line-height: 1;
 }
-.main-btn:active {
-  opacity: 0.9;
+.logout-btn::after {
+  border: none;
 }
-.phone-auth-btn {
-  background: linear-gradient(135deg, #FF9800, #FFA726);
-  box-shadow: 0 12rpx 24rpx rgba(255, 152, 0, 0.4);
+.logout-btn:active {
+  opacity: 0.8;
+}
+.bottom-safe-area {
+  height: 80rpx;
 }
-

+ 293 - 203
src/pages/mine/mine.vue

@@ -1,82 +1,82 @@
 <template>
   <view class="page-mine">
-    <!-- User Info Card -->
-    <view class="user-card">
-      <view class="avatar-container" @click="handleEditProfile">
-        <!-- Default avatar if not logged in or no avatar -->
-        <image 
-          class="avatar" 
-          :src="isLoggedIn && userInfo.avatar ? userInfo.avatar : '/static/images/head.png'" 
-          mode="aspectFill"
-        ></image>
-        <view class="edit-icon">✏️</view>
-      </view>
-      <view class="user-info">
-        <text class="username">{{ isLoggedIn ? (userInfo.nickname || '微信用户') : '游客' }}</text>
-        <text class="phone" v-if="isLoggedIn && userInfo.phone">{{ userInfo.phone }}</text>
-      </view>
+    <!-- 顶部标题卡片 -->
+    <view class="page-title-card">
+      <text class="page-title-text">量化选股大师</text>
     </view>
 
-    <!-- Points Card -->
-    <view class="section-card">
-      <view class="card-header">
-        <view class="header-icon-box">
-          <text class="header-icon-text">🪙</text>
+    <scroll-view class="scroll-view" scroll-y>
+      <view class="content-wrapper">
+        <!-- 用户信息卡片 -->
+        <view class="user-info-card" @click="handleUserCardClick">
+          <view class="user-header">
+            <image 
+              class="user-avatar" 
+              :src="isLoggedIn && userInfo.avatar ? userInfo.avatar : '/static/images/head.png'" 
+              mode="aspectFill"
+            ></image>
+            <view class="user-details">
+              <text class="user-name">{{ isLoggedIn ? (userInfo.nickname || '微信用户') : '登录/注册' }}</text>
+            </view>
+            <view class="arrow-icon">›</view>
+          </view>
         </view>
-        <text class="header-title">积分值</text>
-      </view>
-      <view class="card-content points-content">
-        <text class="points-value">积分值:{{ isLoggedIn ? points : 0 }}</text>
-        <view class="points-actions">
-          <button class="mini-btn" @click="handleRecharge">充值</button>
-          <button class="mini-btn" @click="handleHistory">积分记录</button>
+
+        <!-- 积分区域 -->
+        <view class="my-tasks-section">
+          <view class="tasks-grid">
+            <view class="task-item" @click="handleViewPoints">
+              <view class="task-icon-wrapper points">
+                <text class="task-icon">💰</text>
+              </view>
+              <view class="task-info">
+                <text class="task-label">积分</text>
+                <text class="task-value">{{ isLoggedIn ? points : 0 }}</text>
+              </view>
+            </view>
+
+            <view class="task-item" @click="handleRecharge">
+              <view class="task-icon-wrapper recharge">
+                <text class="task-icon">💳</text>
+              </view>
+              <view class="task-info">
+                <text class="task-label">充值</text>
+              </view>
+            </view>
+
+            <view class="task-item" @click="handleHistory">
+              <view class="task-icon-wrapper history">
+                <text class="task-icon">📋</text>
+              </view>
+              <view class="task-info">
+                <text class="task-label">积分记录</text>
+              </view>
+            </view>
+          </view>
         </view>
-      </view>
-    </view>
 
-    <!-- Transaction Record Card -->
-    <view class="section-card">
-      <view class="card-header">
-        <view class="header-icon-box">
-          <text class="header-icon-text">📝</text>
+        <!-- 菜单列表 -->
+        <view class="menu-list">
+          <view class="menu-item" @click="handleTransactionRecord">
+            <view class="menu-left">
+              <text class="menu-icon">📝</text>
+              <text class="menu-label">交易记录</text>
+            </view>
+            <text class="menu-arrow">›</text>
+          </view>
         </view>
-        <text class="header-title">交易记录</text>
-      </view>
-      <view class="card-content transaction-content">
-        <text class="empty-text">暂无交易记录</text>
-      </view>
-    </view>
 
-    <!-- Login/Logout Button -->
-    <view class="action-area">
-      <!-- 未登录且未开始授权 -->
-      <button 
-        v-if="!isLoggedIn && !showPhoneAuth"
-        class="main-btn" 
-        @click="handleLogin"
-      >
-        微信授权登录
-      </button>
-      
-      <!-- 未登录但已获取用户信息,等待手机号授权 -->
-      <button 
-        v-else-if="!isLoggedIn && showPhoneAuth"
-        class="main-btn phone-auth-btn" 
-        open-type="getPhoneNumber"
-        @getphonenumber="onGetPhoneNumber"
-      >
-        授权手机号
-      </button>
-      
-      <!-- 已登录 -->
-      <button 
-        v-else
-        class="main-btn" 
-        @click="handleLogout"
-      >
-        退出登录
-      </button>
-    </view>
+        <!-- 退出登录按钮(仅登录后显示) -->
+        <view class="logout-section" v-if="isLoggedIn">
+          <button class="logout-btn" @click="handleLogout">
+            退出登录
+          </button>
+        </view>
+
+        <!-- 预留底部空间 -->
+        <view class="bottom-safe-area"></view>
+      </view>
+    </scroll-view>
   </view>
 </template>
 
@@ -86,7 +86,7 @@ import { onShow } from '@dcloudio/uni-app'
 import { isLoggedIn as checkLogin, getUserInfo as getStoredUserInfo, logout, checkLogin as requireLogin, wxAuthLogin } from '@/utils/auth.js'
 
 const isLoggedIn = ref(false)
-const showPhoneAuth = ref(false)  // 是否显示手机号授权按钮
+const showPhoneAuth = ref(false)
 const userInfo = ref({
   nickname: '',
   avatar: '',
@@ -102,7 +102,7 @@ onMounted(() => {
 })
 
 /**
- * 页面显示时刷新用户信息(从登录页返回时会触发)
+ * 页面显示时刷新用户信息
  */
 onShow(() => {
   loadUserInfo()
@@ -124,31 +124,61 @@ const loadUserInfo = () => {
 }
 
 /**
- * 编辑个人资料
+ * 点击用户卡片
  */
-const handleEditProfile = () => {
-  if (!requireLogin(() => {
-    handleEditProfile()
-  })) {
-    return
+const handleUserCardClick = () => {
+  if (!isLoggedIn.value) {
+    handleLogin()
   }
-  
-  // 跳转到编辑资料页面
-  uni.navigateTo({
-    url: '/pages/profile/edit'
-  })
 }
 
 /**
- * 处理登录按钮点击 - 直接显示手机号授权
+ * 处理登录
  */
-const handleLogin = () => {
-  console.log('[我的] 显示手机号授权弹窗')
-  showPhoneAuth.value = true
+const handleLogin = async () => {
+  console.log('[我的] 开始登录流程')
+  
+  uni.showLoading({
+    title: '登录中...',
+    mask: true
+  })
+  
+  try {
+    // 获取微信登录code
+    const loginRes = await uni.login()
+    console.log('[我的] uni.login完整响应:', loginRes)
+    
+    if (!loginRes.code) {
+      throw new Error('获取微信登录code失败')
+    }
+    
+    // 获取手机号授权
+    uni.hideLoading()
+    
+    // 显示手机号授权按钮
+    showPhoneAuth.value = true
+    
+    // 触发手机号授权
+    uni.showModal({
+      title: '授权提示',
+      content: '需要授权手机号才能完成登录',
+      showCancel: false,
+      success: () => {
+        // 用户需要点击授权按钮
+      }
+    })
+  } catch (error) {
+    uni.hideLoading()
+    console.error('[我的] 登录失败:', error)
+    uni.showToast({
+      title: '登录失败,请重试',
+      icon: 'none'
+    })
+  }
 }
 
 /**
- * 处理手机号授权并完成登录
+ * 处理手机号授权
  */
 const onGetPhoneNumber = async (e) => {
   console.log('[我的] 获取手机号回调:', e.detail)
@@ -165,7 +195,6 @@ const onGetPhoneNumber = async (e) => {
     try {
       const loginRes = await uni.login()
       console.log('[我的] uni.login完整响应:', loginRes)
-      console.log('[我的] 微信登录code:', loginRes.code)
       
       if (!loginRes.code) {
         throw new Error('获取微信登录code失败')
@@ -212,12 +241,23 @@ const handleLogout = () => {
 }
 
 /**
- * 处理充值按钮点击
- * 需要登录才能操作
+ * 查看积分
+ */
+const handleViewPoints = () => {
+  if (!requireLogin(() => {
+    handleViewPoints()
+  })) {
+    return
+  }
+  
+  uni.showToast({ title: `当前积分: ${points.value}`, icon: 'none' })
+}
+
+/**
+ * 充值
  */
 const handleRecharge = () => {
   if (!requireLogin(() => {
-    // 登录成功后的回调
     handleRecharge()
   })) {
     return
@@ -227,201 +267,251 @@ const handleRecharge = () => {
 }
 
 /**
- * 处理积分记录按钮点击
- * 需要登录才能操作
+ * 积分记录
  */
 const handleHistory = () => {
   if (!requireLogin(() => {
-    // 登录成功后的回调
     handleHistory()
   })) {
     return
   }
   
-  uni.showToast({ title: '记录功能开发中', icon: 'none' })
+  uni.showToast({ title: '积分记录功能开发中', icon: 'none' })
+}
+
+/**
+ * 交易记录
+ */
+const handleTransactionRecord = () => {
+  if (!requireLogin(() => {
+    handleTransactionRecord()
+  })) {
+    return
+  }
+  
+  // 跳转到交易记录页面
+  uni.navigateTo({
+    url: '/pages/transaction/transaction'
+  })
 }
 </script>
 
 <style>
 .page-mine {
+  height: 100vh;
   display: flex;
   flex-direction: column;
   background: #f5f6fb;
-  min-height: 100vh;
-  padding: 30rpx;
-  box-sizing: border-box;
 }
 
-/* User Card */
-.user-card {
+.page-title-card {
   background: #ffffff;
-  border-radius: 20rpx;
-  padding: 40rpx;
-  display: flex;
-  align-items: center;
-  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 30rpx;
+  padding: 30rpx 0;
+  text-align: center;
+  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
+  border-radius: 0;
 }
 
-.avatar-container {
-  width: 120rpx;
-  height: 120rpx;
-  border-radius: 50%;
-  overflow: hidden;
-  background-color: #eee;
-  flex-shrink: 0;
-  position: relative;
-  cursor: pointer;
+.page-title-text {
+  font-size: 36rpx;
+  font-weight: 800;
+  color: #3F51F7;
+  letter-spacing: 2rpx;
 }
 
-.edit-icon {
-  position: absolute;
-  bottom: 0;
-  right: 0;
-  width: 36rpx;
-  height: 36rpx;
-  background: #5d55e8;
-  border-radius: 50%;
+.scroll-view {
+  flex: 1;
+  height: 0;
+}
+
+.content-wrapper {
+  padding: 32rpx;
+  background: #f5f6fb;
+  min-height: 100%;
+}
+
+/* 用户信息卡片 */
+.user-info-card {
+  background: #ffffff;
+  border-radius: 24rpx;
+  padding: 40rpx 32rpx;
+  margin-bottom: 32rpx;
+  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
+}
+
+.user-header {
   display: flex;
   align-items: center;
-  justify-content: center;
-  font-size: 20rpx;
-  border: 2rpx solid #fff;
 }
 
-.avatar {
-  width: 100%;
-  height: 100%;
+.user-avatar {
+  width: 100rpx;
+  height: 100rpx;
+  border-radius: 50%;
+  background: #f5f6fb;
+  margin-right: 24rpx;
+  border: 4rpx solid #f5f6fb;
 }
 
-.user-info {
-  margin-left: 30rpx;
+.user-details {
   flex: 1;
   display: flex;
   flex-direction: column;
 }
 
-.username {
-  font-size: 36rpx;
-  font-weight: bold;
+.user-name {
+  font-size: 32rpx;
+  font-weight: 600;
   color: #222222;
-  margin-bottom: 10rpx;
+  margin-bottom: 8rpx;
 }
 
-.phone {
-  font-size: 24rpx;
-  color: #999999;
+.arrow-icon {
+  font-size: 48rpx;
+  color: #9ca2b5;
+  font-weight: 300;
 }
 
-/* Section Cards */
-.section-card {
+/* 积分区域 */
+.my-tasks-section {
   background: #ffffff;
-  border-radius: 20rpx;
-  overflow: hidden;
+  border-radius: 24rpx;
+  padding: 32rpx;
+  margin-bottom: 32rpx;
   box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 30rpx;
 }
 
-.card-header {
-  background: linear-gradient(135deg, #5d55e8, #7568ff);
-  padding: 20rpx 30rpx;
+.tasks-grid {
+  display: flex;
+  flex-direction: column;
+  gap: 24rpx;
+}
+
+.task-item {
   display: flex;
   align-items: center;
+  padding: 24rpx;
+  background: #f7f8fc;
+  border-radius: 16rpx;
 }
 
-.header-icon-box {
-  width: 40rpx;
-  height: 40rpx;
+.task-icon-wrapper {
+  width: 80rpx;
+  height: 80rpx;
+  border-radius: 50%;
   display: flex;
   align-items: center;
   justify-content: center;
-  margin-right: 15rpx;
+  margin-right: 24rpx;
+  flex-shrink: 0;
+  box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1);
 }
 
-.header-icon-text {
-  font-size: 32rpx;
-  color: #fff;
+.task-icon-wrapper.points {
+  background: linear-gradient(135deg, #00BFA5, #00D4B5);
 }
 
-.header-title {
-  color: #ffffff;
-  font-size: 32rpx;
-  font-weight: bold;
+.task-icon-wrapper.recharge {
+  background: linear-gradient(135deg, #5d55e8, #7568ff);
+}
+
+.task-icon-wrapper.history {
+  background: linear-gradient(135deg, #FF9800, #FFA726);
 }
 
-.card-content {
-  padding: 30rpx;
-  background: #fff;
+.task-icon {
+  font-size: 40rpx;
 }
 
-/* Points Content */
-.points-content {
+.task-info {
+  flex: 1;
   display: flex;
-  justify-content: space-between;
   align-items: center;
+  justify-content: space-between;
 }
 
-.points-value {
-  font-size: 32rpx;
+.task-label {
+  font-size: 28rpx;
   color: #222222;
   font-weight: 500;
 }
 
-.points-actions {
-  display: flex;
-  gap: 20rpx;
+.task-value {
+  font-size: 32rpx;
+  font-weight: 700;
+  color: #00BFA5;
 }
 
-.mini-btn {
-  background: linear-gradient(135deg, #5d55e8, #7568ff);
-  color: #fff;
-  font-size: 24rpx;
-  padding: 10rpx 30rpx;
-  border-radius: 30rpx;
-  line-height: 2;
-  margin: 0;
-  border: none;
-  box-shadow: 0 4rpx 12rpx rgba(93, 85, 232, 0.3);
+/* 菜单列表 */
+.menu-list {
+  background: #ffffff;
+  border-radius: 24rpx;
+  overflow: hidden;
+  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
+  margin-bottom: 32rpx;
 }
-.mini-btn::after {
-  border: none;
+
+.menu-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 32rpx;
+  border-bottom: 1rpx solid #f5f6fb;
+}
+
+.menu-item:last-child {
+  border-bottom: none;
 }
 
-/* Transaction Content */
-.transaction-content {
+.menu-left {
   display: flex;
-  justify-content: center;
-  padding: 60rpx 30rpx;
+  align-items: center;
+}
+
+.menu-icon {
+  font-size: 36rpx;
+  margin-right: 20rpx;
 }
 
-.empty-text {
-  color: #999;
+.menu-label {
   font-size: 28rpx;
+  color: #222222;
 }
 
-/* Bottom Action */
-.action-area {
-  margin-top: 40rpx;
+.menu-arrow {
+  font-size: 40rpx;
+  color: #9ca2b5;
+  font-weight: 300;
 }
 
-.main-btn {
-  background: linear-gradient(135deg, #5d55e8, #7568ff);
-  color: #fff;
-  font-size: 32rpx;
-  border-radius: 50rpx;
-  padding: 10rpx 0;
+/* 退出登录按钮 */
+.logout-section {
+  margin-top: 20rpx;
+}
+
+.logout-btn {
   width: 100%;
-  box-shadow: 0 12rpx 24rpx rgba(93, 85, 232, 0.4);
-  line-height: 2.5;
+  background: #5d55e8;
+  color: #ffffff;
+  border-radius: 16rpx;
+  padding: 28rpx 0;
+  text-align: center;
+  font-size: 30rpx;
+  font-weight: 600;
+  box-shadow: 0 12rpx 24rpx rgba(93, 85, 232, 0.3);
+  border: none;
+  line-height: 1;
 }
 
-.main-btn:active {
-  opacity: 0.9;
+.logout-btn::after {
+  border: none;
 }
 
-.phone-auth-btn {
-  background: linear-gradient(135deg, #FF9800, #FFA726);
-  box-shadow: 0 12rpx 24rpx rgba(255, 152, 0, 0.4);
+.logout-btn:active {
+  opacity: 0.8;
 }
 
+.bottom-safe-area {
+  height: 80rpx;
+}
 </style>

+ 344 - 0
src/pages/transaction/transaction.vue

@@ -0,0 +1,344 @@
+<template>
+  <view class="page-transaction">
+    <!-- 顶部标题卡片 -->
+    <view class="page-title-card">
+      <text class="page-title-text">交易记录</text>
+    </view>
+
+    <scroll-view class="scroll-view" scroll-y>
+      <view class="content-wrapper">
+        <!-- 统计卡片 -->
+        <view class="stats-card">
+          <view class="stat-item">
+            <text class="stat-label">总交易次数</text>
+            <text class="stat-value">{{ totalTransactions }}</text>
+          </view>
+          <view class="stat-divider"></view>
+          <view class="stat-item">
+            <text class="stat-label">总盈亏</text>
+            <text :class="['stat-value', totalProfit >= 0 ? 'profit' : 'loss']">
+              {{ totalProfit >= 0 ? '+' : '' }}¥{{ Math.abs(totalProfit).toFixed(2) }}
+            </text>
+          </view>
+        </view>
+
+        <!-- 交易列表 -->
+        <view class="transaction-list">
+          <view v-if="transactions.length === 0" class="empty-state">
+            <text class="empty-icon">📋</text>
+            <text class="empty-text">暂无交易记录</text>
+            <text class="empty-desc">开始您的模拟交易之旅吧</text>
+          </view>
+
+          <view 
+            v-else
+            v-for="(item, index) in transactions" 
+            :key="index"
+            class="transaction-item"
+          >
+            <view class="transaction-header">
+              <view class="stock-info">
+                <text class="stock-name">{{ item.stockName }}</text>
+                <text class="stock-code">{{ item.stockCode }}</text>
+              </view>
+              <view :class="['transaction-type', item.type]">
+                <text class="type-text">{{ item.type === 'buy' ? '买入' : '卖出' }}</text>
+              </view>
+            </view>
+
+            <view class="transaction-details">
+              <view class="detail-row">
+                <text class="detail-label">价格:</text>
+                <text class="detail-value">¥{{ item.price.toFixed(2) }}</text>
+              </view>
+              <view class="detail-row">
+                <text class="detail-label">数量:</text>
+                <text class="detail-value">{{ item.quantity }}股</text>
+              </view>
+              <view class="detail-row">
+                <text class="detail-label">总额:</text>
+                <text class="detail-value amount">¥{{ item.totalAmount.toFixed(2) }}</text>
+              </view>
+            </view>
+
+            <view class="transaction-footer">
+              <text class="transaction-time">{{ formatTime(item.timestamp) }}</text>
+            </view>
+          </view>
+        </view>
+
+        <!-- 预留底部空间 -->
+        <view class="bottom-safe-area"></view>
+      </view>
+    </scroll-view>
+  </view>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue'
+
+const transactions = ref([])
+
+// 计算总交易次数
+const totalTransactions = computed(() => {
+  return transactions.value.length
+})
+
+// 计算总盈亏(简化计算:买入为负,卖出为正)
+const totalProfit = computed(() => {
+  return transactions.value.reduce((sum, item) => {
+    if (item.type === 'buy') {
+      return sum - item.totalAmount
+    } else {
+      return sum + item.totalAmount
+    }
+  }, 0)
+})
+
+// 格式化时间
+const formatTime = (timestamp) => {
+  const date = new Date(timestamp)
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  const hours = String(date.getHours()).padStart(2, '0')
+  const minutes = String(date.getMinutes()).padStart(2, '0')
+  return `${year}-${month}-${day} ${hours}:${minutes}`
+}
+
+// 加载交易记录
+const loadTransactions = () => {
+  try {
+    const storedTransactions = uni.getStorageSync('simulated_transactions') || []
+    // 按时间倒序排列
+    transactions.value = storedTransactions.sort((a, b) => b.timestamp - a.timestamp)
+  } catch (e) {
+    console.error('加载交易记录失败:', e)
+    transactions.value = []
+  }
+}
+
+onMounted(() => {
+  loadTransactions()
+})
+</script>
+
+<style>
+.page-transaction {
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background: #f5f6fb;
+}
+
+.page-title-card {
+  background: #ffffff;
+  padding: 30rpx 0;
+  text-align: center;
+  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
+  border-radius: 0;
+}
+
+.page-title-text {
+  font-size: 36rpx;
+  font-weight: 800;
+  color: #3F51F7;
+  letter-spacing: 2rpx;
+}
+
+.scroll-view {
+  flex: 1;
+  height: 0;
+}
+
+.content-wrapper {
+  padding: 32rpx;
+  background: #f5f6fb;
+  min-height: 100%;
+}
+
+/* 统计卡片 */
+.stats-card {
+  background: linear-gradient(135deg, #5d55e8, #7568ff);
+  border-radius: 24rpx;
+  padding: 40rpx 32rpx;
+  margin-bottom: 32rpx;
+  box-shadow: 0 16rpx 40rpx rgba(93, 85, 232, 0.3);
+  display: flex;
+  align-items: center;
+}
+
+.stat-item {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.stat-divider {
+  width: 2rpx;
+  height: 60rpx;
+  background: rgba(255, 255, 255, 0.3);
+}
+
+.stat-label {
+  font-size: 24rpx;
+  color: rgba(255, 255, 255, 0.8);
+  margin-bottom: 12rpx;
+}
+
+.stat-value {
+  font-size: 40rpx;
+  font-weight: 700;
+  color: #ffffff;
+}
+
+.stat-value.profit {
+  color: #4fffb0;
+}
+
+.stat-value.loss {
+  color: #ff6b9d;
+}
+
+/* 交易列表 */
+.transaction-list {
+  background: #ffffff;
+  border-radius: 24rpx;
+  overflow: hidden;
+  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
+}
+
+/* 空状态 */
+.empty-state {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 100rpx 40rpx;
+}
+
+.empty-icon {
+  font-size: 80rpx;
+  margin-bottom: 24rpx;
+}
+
+.empty-text {
+  font-size: 28rpx;
+  color: #666a7f;
+  margin-bottom: 12rpx;
+}
+
+.empty-desc {
+  font-size: 24rpx;
+  color: #9ca2b5;
+}
+
+/* 交易项 */
+.transaction-item {
+  padding: 32rpx;
+  border-bottom: 1rpx solid #f5f6fb;
+}
+
+.transaction-item:last-child {
+  border-bottom: none;
+}
+
+.transaction-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20rpx;
+}
+
+.stock-info {
+  display: flex;
+  align-items: center;
+  gap: 16rpx;
+}
+
+.stock-name {
+  font-size: 30rpx;
+  font-weight: 600;
+  color: #222222;
+}
+
+.stock-code {
+  font-size: 24rpx;
+  color: #9ca2b5;
+}
+
+.transaction-type {
+  padding: 8rpx 20rpx;
+  border-radius: 20rpx;
+  font-size: 24rpx;
+}
+
+.transaction-type.buy {
+  background: #e7f7ef;
+}
+
+.transaction-type.sell {
+  background: #ffe7e7;
+}
+
+.type-text {
+  font-weight: 600;
+}
+
+.transaction-type.buy .type-text {
+  color: #3abf81;
+}
+
+.transaction-type.sell .type-text {
+  color: #f16565;
+}
+
+.transaction-details {
+  background: #f7f8fc;
+  border-radius: 12rpx;
+  padding: 20rpx 24rpx;
+  margin-bottom: 16rpx;
+}
+
+.detail-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 12rpx;
+}
+
+.detail-row:last-child {
+  margin-bottom: 0;
+}
+
+.detail-label {
+  font-size: 24rpx;
+  color: #666a7f;
+}
+
+.detail-value {
+  font-size: 26rpx;
+  color: #222222;
+  font-weight: 500;
+}
+
+.detail-value.amount {
+  font-size: 28rpx;
+  font-weight: 700;
+  color: #5d55e8;
+}
+
+.transaction-footer {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.transaction-time {
+  font-size: 22rpx;
+  color: #9ca2b5;
+}
+
+.bottom-safe-area {
+  height: 80rpx;
+}
+</style>