Zhangbw hace 3 meses
padre
commit
71d7b691d8
Se han modificado 39 ficheros con 182 adiciones y 1039 borrados
  1. 7 2
      dist/dev/mp-weixin/app.json
  2. 2 1
      dist/dev/mp-weixin/components/UserInfoPopup.js
  3. 0 1
      dist/dev/mp-weixin/pages/index/index.json
  4. 0 0
      dist/dev/mp-weixin/pages/index/index.wxml
  5. 0 18
      dist/dev/mp-weixin/pages/index/index.wxss
  6. 67 26
      dist/dev/mp-weixin/pages/login/login.js
  7. 0 1
      dist/dev/mp-weixin/pages/login/login.json
  8. 1 1
      dist/dev/mp-weixin/pages/login/login.wxml
  9. 0 1
      dist/dev/mp-weixin/pages/mine/mine.json
  10. 1 1
      dist/dev/mp-weixin/pages/mine/mine.wxml
  11. 0 13
      dist/dev/mp-weixin/pages/mine/mine.wxss
  12. 0 1
      dist/dev/mp-weixin/pages/points/points.json
  13. 0 1
      dist/dev/mp-weixin/pages/pool/pool.json
  14. 0 0
      dist/dev/mp-weixin/pages/pool/pool.wxml
  15. 0 13
      dist/dev/mp-weixin/pages/pool/pool.wxss
  16. 0 1
      dist/dev/mp-weixin/pages/profile/edit.json
  17. 0 1
      dist/dev/mp-weixin/pages/rank/rank.json
  18. 1 1
      dist/dev/mp-weixin/pages/rank/rank.wxml
  19. 0 13
      dist/dev/mp-weixin/pages/rank/rank.wxss
  20. 0 1
      dist/dev/mp-weixin/pages/strong/strong.json
  21. 0 0
      dist/dev/mp-weixin/pages/strong/strong.wxml
  22. 0 13
      dist/dev/mp-weixin/pages/strong/strong.wxss
  23. 0 1
      dist/dev/mp-weixin/pages/transaction/transaction.json
  24. 0 75
      src/components/AdvantageCard.vue
  25. 0 100
      src/components/LoginGuide.vue
  26. 0 189
      src/components/ResultCard.vue
  27. 0 67
      src/components/RiskCard.vue
  28. 0 116
      src/components/SearchCard.vue
  29. 0 206
      src/components/StockListCard.vue
  30. 2 1
      src/components/UserInfoPopup.vue
  31. 13 23
      src/pages.json
  32. 0 24
      src/pages/index/index.vue
  33. 84 27
      src/pages/login/login.vue
  34. 0 20
      src/pages/mine/mine.vue
  35. 0 19
      src/pages/pool/pool.vue
  36. 0 20
      src/pages/rank/rank.vue
  37. 0 19
      src/pages/strong/strong.vue
  38. 4 3
      src/utils/auth.js
  39. 0 19
      utils/util.js

+ 7 - 2
dist/dev/mp-weixin/app.json

@@ -13,8 +13,13 @@
   "window": {
     "navigationBarBackgroundColor": "#ffffff",
     "navigationBarTextStyle": "black",
-    "navigationBarTitleText": "量化选股大师",
-    "backgroundColor": "#f5f6fb"
+    "navigationBarTitleText": "量化交易大师",
+    "backgroundColor": "#f5f6fb",
+    "titleNView": {
+      "titleColor": "#3F51F7",
+      "titleSize": "18",
+      "titleWeight": "800"
+    }
   },
   "tabBar": {
     "color": "#999999",

+ 2 - 1
dist/dev/mp-weixin/components/UserInfoPopup.js

@@ -16,8 +16,9 @@ const _sfc_main = {
   methods: {
     /**
      * 打开弹窗
+     * @param userData 可选,后端返回的用户数据(新流程中不再需要)
      */
-    open(userData) {
+    open(userData = null) {
       this.visible = true;
       this.userData = userData;
       this.nickname = "";

+ 0 - 1
dist/dev/mp-weixin/pages/index/index.json

@@ -1,4 +1,3 @@
 {
-  "navigationBarTitleText": "量化选股大师",
   "usingComponents": {}
 }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/dev/mp-weixin/pages/index/index.wxml


+ 0 - 18
dist/dev/mp-weixin/pages/index/index.wxss

@@ -1,29 +1,11 @@
 
 /** 首页量化查询界面样式 **/
-.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;
-}
 .page-container {
   height: 100vh;
   display: flex;
   flex-direction: column;
   background: #f5f6fb;
 }
-
-/* 移除旧的 custom-header 样式,或者保留也无妨,因为 HTML 中不再使用 */
-.custom-header {
-  display: none;
-}
 .scroll-view {
   flex: 1;
   height: 0;

+ 67 - 26
dist/dev/mp-weixin/pages/login/login.js

@@ -11,12 +11,16 @@ const _sfc_main = {
     return {
       showOneClickLogin: true,
       // 是否显示一键登录按钮
+      showPhoneAuth: false,
+      // 是否显示手机号授权按钮(新用户第二步)
       agreedToTerms: false,
       // 是否同意协议
       loginCode: "",
       // 微信登录code
-      tempUserData: null
-      // 临时存储的用户数据
+      tempUserData: null,
+      // 临时存储的用户数据(openid, unionid等)
+      tempUserProfile: null
+      // 临时存储的用户头像昵称信息
     };
   },
   methods: {
@@ -56,8 +60,9 @@ const _sfc_main = {
           console.log("[登录] 老用户登录成功");
           this.handleLoginSuccess();
         } else if (result && result.isSign === "false") {
-          console.log("[登录] 新用户,需要授权手机号");
+          console.log("[登录] 新用户,需要先获取头像昵称");
           this.showOneClickLogin = false;
+          this.showPhoneAuth = false;
         } else if (result && result.code === 103) {
           common_vendor.index.showModal({
             title: "账号异常",
@@ -78,7 +83,39 @@ const _sfc_main = {
       }
     },
     /**
-     * 第二步:获取手机号授权(新用户)
+     * 第二步:获取用户头像昵称(新用户)
+     */
+    handleGetUserProfile() {
+      if (!this.agreedToTerms) {
+        common_vendor.index.showToast({
+          title: "请先阅读并同意用户协议",
+          icon: "none",
+          duration: 2e3
+        });
+        return;
+      }
+      console.log("[登录] 打开用户信息弹窗");
+      this.$refs.userInfoPopup.open();
+    },
+    /**
+     * 用户信息弹窗确认回调(新用户第二步完成后)
+     */
+    handleUserInfoConfirm(userInfo) {
+      console.log("[登录] 用户信息已获取:", userInfo);
+      this.tempUserProfile = {
+        nickname: userInfo.nickname,
+        avatarUrl: userInfo.avatarUrl,
+        tempAvatarPath: userInfo.tempAvatarPath
+      };
+      this.showPhoneAuth = true;
+      common_vendor.index.showToast({
+        title: "请继续授权手机号",
+        icon: "none",
+        duration: 2e3
+      });
+    },
+    /**
+     * 第三步:获取手机号授权(新用户)
      */
     async handleGetPhoneNumber(e) {
       console.log("[登录] 手机号授权回调:", e);
@@ -86,7 +123,7 @@ const _sfc_main = {
         if (e.detail.errMsg.includes("no permission")) {
           common_vendor.index.showModal({
             title: "权限不足",
-            content: '获取手机号功能需要:\n1. 小程序企业认证\n2. 开通"手机号快速验证组件"权限\n3. 在真机上测试',
+            content: '获取手机号功能需要:\n1. 小程序企业认证"权限 \n2. 在真机上测试',
             showCancel: false
           });
         } else {
@@ -111,9 +148,13 @@ const _sfc_main = {
         const result = await utils_auth.wxPhoneLogin(params);
         common_vendor.index.hideLoading();
         if (result && result.isSign === "false") {
-          console.log("[登录] 需要完善用户信息");
-          this.tempUserData = result;
-          this.$refs.userInfoPopup.open(result);
+          console.log("[登录] 需要完成注册");
+          this.tempUserData = {
+            openid: result.openid,
+            unionid: result.unionid,
+            phoneNumber: result.phoneNumber
+          };
+          await this.submitRegistration();
         } else if (result && result.isSign === "true") {
           console.log("[登录] 已注册用户,登录成功");
           this.handleLoginSuccess();
@@ -150,28 +191,26 @@ const _sfc_main = {
       }
     },
     /**
-     * 第三步:完善用户信息(首次登录
+     * 第四步:提交注册(新用户完成所有授权后
      */
-    async handleUserInfoConfirm(userInfo) {
+    async submitRegistration() {
       try {
         common_vendor.index.showLoading({ title: "注册中..." });
         const completeInfo = {
           openid: this.tempUserData.openid,
           unionid: this.tempUserData.unionid,
           phoneNumber: this.tempUserData.phoneNumber,
-          nickname: userInfo.nickname,
-          avatarUrl: userInfo.avatarUrl
-          // 微信临时URL,先存着
+          nickname: this.tempUserProfile.nickname,
+          avatarUrl: this.tempUserProfile.avatarUrl
         };
         console.log("[登录] 提交用户信息");
         await utils_auth.wxCompleteUserInfo(completeInfo);
-        if (userInfo.tempAvatarPath) {
-          console.log("[登录] 开始上传头像到服务器, tempAvatarPath:", userInfo.tempAvatarPath);
+        if (this.tempUserProfile.tempAvatarPath) {
+          console.log("[登录] 开始上传头像到服务器");
           try {
-            const uploadedUrl = await this.uploadAvatarWithToken(userInfo.tempAvatarPath);
-            console.log("[登录] 头像上传成功, uploadedUrl:", uploadedUrl);
+            const uploadedUrl = await this.uploadAvatarWithToken(this.tempUserProfile.tempAvatarPath);
+            console.log("[登录] 头像上传成功:", uploadedUrl);
             if (uploadedUrl) {
-              console.log("[登录] 调用updateUserProfile更新头像");
               const updateResult = await utils_api.updateUserProfile({ avatar: uploadedUrl });
               console.log("[登录] updateUserProfile返回:", updateResult);
               const userInfoLocal = common_vendor.index.getStorageSync("user_info");
@@ -180,7 +219,6 @@ const _sfc_main = {
                 parsed.avatar = uploadedUrl;
                 common_vendor.index.setStorageSync("user_info", JSON.stringify(parsed));
               }
-              console.log("[登录] 头像上传成功:", uploadedUrl);
             }
           } catch (uploadErr) {
             console.warn("[登录] 头像上传失败:", uploadErr);
@@ -290,15 +328,18 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
     b: $data.showOneClickLogin
   }, $data.showOneClickLogin ? {
     c: common_vendor.o((...args) => $options.handleWxLogin && $options.handleWxLogin(...args))
+  } : $data.showPhoneAuth ? {
+    e: common_vendor.o((...args) => $options.handleGetPhoneNumber && $options.handleGetPhoneNumber(...args))
   } : {
-    d: common_vendor.o((...args) => $options.handleGetPhoneNumber && $options.handleGetPhoneNumber(...args))
+    f: common_vendor.o((...args) => $options.handleGetUserProfile && $options.handleGetUserProfile(...args))
   }, {
-    e: $data.agreedToTerms,
-    f: common_vendor.o(($event) => $options.showAgreement("user")),
-    g: common_vendor.o(($event) => $options.showAgreement("privacy")),
-    h: common_vendor.o((...args) => $options.handleAgreementChange && $options.handleAgreementChange(...args)),
-    i: common_vendor.sr("userInfoPopup", "cdfe2409-0"),
-    j: common_vendor.o($options.handleUserInfoConfirm)
+    d: $data.showPhoneAuth,
+    g: $data.agreedToTerms,
+    h: common_vendor.o(($event) => $options.showAgreement("user")),
+    i: common_vendor.o(($event) => $options.showAgreement("privacy")),
+    j: common_vendor.o((...args) => $options.handleAgreementChange && $options.handleAgreementChange(...args)),
+    k: common_vendor.sr("userInfoPopup", "cdfe2409-0"),
+    l: common_vendor.o($options.handleUserInfoConfirm)
   });
 }
 const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-cdfe2409"], ["__file", "D:/program/gupiao-wx/src/pages/login/login.vue"]]);

+ 0 - 1
dist/dev/mp-weixin/pages/login/login.json

@@ -1,5 +1,4 @@
 {
-  "navigationBarTitleText": "登录",
   "navigationStyle": "custom",
   "usingComponents": {
     "user-info-popup": "../../components/UserInfoPopup"

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

@@ -1 +1 @@
-<view class="login-container data-v-cdfe2409"><view class="back-button data-v-cdfe2409" bindtap="{{a}}"><text class="back-icon data-v-cdfe2409">←</text><text class="back-text data-v-cdfe2409">返回</text></view><view class="bg-decoration data-v-cdfe2409"><view class="circle circle-1 data-v-cdfe2409"></view><view class="circle circle-2 data-v-cdfe2409"></view></view><view class="header data-v-cdfe2409"><image class="logo data-v-cdfe2409" src="/static/images/logo.png" mode="aspectFit"></image><text class="title data-v-cdfe2409">量化选股大师</text><text class="subtitle data-v-cdfe2409">专业的股票量化分析工具</text></view><view class="login-actions data-v-cdfe2409"><button wx:if="{{b}}" class="login-btn primary-btn data-v-cdfe2409" bindtap="{{c}}"><text class="btn-text data-v-cdfe2409">微信一键登录</text></button><button wx:else class="login-btn primary-btn data-v-cdfe2409" open-type="getPhoneNumber" bindgetphonenumber="{{d}}"><text class="btn-icon data-v-cdfe2409">🔐</text><text class="btn-text data-v-cdfe2409">授权手机号登录</text></button><view class="agreement data-v-cdfe2409"><checkbox-group class="data-v-cdfe2409" bindchange="{{h}}"><label class="agreement-label data-v-cdfe2409"><checkbox class="data-v-cdfe2409" checked="{{e}}" color="#5d55e8"/><text class="agreement-text data-v-cdfe2409"> 我已阅读并同意 <text class="link data-v-cdfe2409" catchtap="{{f}}">《用户协议》</text> 和 <text class="link data-v-cdfe2409" catchtap="{{g}}">《隐私政策》</text></text></label></checkbox-group></view></view><user-info-popup class="r data-v-cdfe2409" u-r="userInfoPopup" bindconfirm="{{j}}" u-i="cdfe2409-0" bind:__l="__l"/></view>
+<view class="login-container data-v-cdfe2409"><view class="back-button data-v-cdfe2409" bindtap="{{a}}"><text class="back-icon data-v-cdfe2409">←</text><text class="back-text data-v-cdfe2409">返回</text></view><view class="bg-decoration data-v-cdfe2409"><view class="circle circle-1 data-v-cdfe2409"></view><view class="circle circle-2 data-v-cdfe2409"></view></view><view class="header data-v-cdfe2409"><image class="logo data-v-cdfe2409" src="/static/images/logo.png" mode="aspectFit"></image><text class="title data-v-cdfe2409">量化交易大师</text><text class="subtitle data-v-cdfe2409">专业的股票量化分析工具</text></view><view class="login-actions data-v-cdfe2409"><button wx:if="{{b}}" class="login-btn primary-btn data-v-cdfe2409" bindtap="{{c}}"><text class="btn-text data-v-cdfe2409">微信一键登录</text></button><button wx:elif="{{d}}" class="login-btn primary-btn data-v-cdfe2409" open-type="getPhoneNumber" bindgetphonenumber="{{e}}"><text class="btn-icon data-v-cdfe2409">🔐</text><text class="btn-text data-v-cdfe2409">授权手机号完成注册</text></button><button wx:else class="login-btn primary-btn data-v-cdfe2409" bindtap="{{f}}"><text class="btn-icon data-v-cdfe2409">👤</text><text class="btn-text data-v-cdfe2409">授权登录</text></button><view class="agreement data-v-cdfe2409"><checkbox-group class="data-v-cdfe2409" bindchange="{{j}}"><label class="agreement-label data-v-cdfe2409"><checkbox class="data-v-cdfe2409" checked="{{g}}" color="#5d55e8"/><text class="agreement-text data-v-cdfe2409"> 我已阅读并同意 <text class="link data-v-cdfe2409" catchtap="{{h}}">《用户协议》</text> 和 <text class="link data-v-cdfe2409" catchtap="{{i}}">《隐私政策》</text></text></label></checkbox-group></view></view><user-info-popup class="r data-v-cdfe2409" u-r="userInfoPopup" bindconfirm="{{l}}" u-i="cdfe2409-0" bind:__l="__l"/></view>

+ 0 - 1
dist/dev/mp-weixin/pages/mine/mine.json

@@ -1,4 +1,3 @@
 {
-  "navigationBarTitleText": "个人中心",
   "usingComponents": {}
 }

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

@@ -1 +1 @@
-<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="points-row"><view class="points-display"><view class="points-icon-wrapper"><text class="points-icon">💰</text></view><view class="points-info"><text class="points-label">我的积分</text><text class="points-value">{{d}}</text></view></view><button class="recharge-button" bindtap="{{e}}"><text class="recharge-text">充值</text></button></view></view><view class="menu-list"><view class="menu-item" bindtap="{{f}}"><view class="menu-left"><text class="menu-icon">📋</text><text class="menu-label">积分记录</text></view><text class="menu-arrow">›</text></view><view class="menu-item" bindtap="{{g}}"><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="{{h}}" class="logout-section"><button class="logout-btn" bindtap="{{i}}"> 退出登录 </button></view><view class="bottom-safe-area"></view></view></scroll-view></view>
+<view class="page-mine"><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="points-row"><view class="points-display"><view class="points-icon-wrapper"><text class="points-icon">💰</text></view><view class="points-info"><text class="points-label">我的积分</text><text class="points-value">{{d}}</text></view></view><button class="recharge-button" bindtap="{{e}}"><text class="recharge-text">充值</text></button></view></view><view class="menu-list"><view class="menu-item" bindtap="{{f}}"><view class="menu-left"><text class="menu-icon">📋</text><text class="menu-label">积分记录</text></view><text class="menu-arrow">›</text></view><view class="menu-item" bindtap="{{g}}"><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="{{h}}" class="logout-section"><button class="logout-btn" bindtap="{{i}}"> 退出登录 </button></view><view class="bottom-safe-area"></view></view></scroll-view></view>

+ 0 - 13
dist/dev/mp-weixin/pages/mine/mine.wxss

@@ -5,19 +5,6 @@
   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;

+ 0 - 1
dist/dev/mp-weixin/pages/points/points.json

@@ -1,5 +1,4 @@
 {
-  "navigationBarTitleText": "积分记录",
   "navigationStyle": "custom",
   "usingComponents": {}
 }

+ 0 - 1
dist/dev/mp-weixin/pages/pool/pool.json

@@ -1,4 +1,3 @@
 {
-  "navigationBarTitleText": "超短池",
   "usingComponents": {}
 }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/dev/mp-weixin/pages/pool/pool.wxml


+ 0 - 13
dist/dev/mp-weixin/pages/pool/pool.wxss

@@ -14,19 +14,6 @@
   background: #f5f6fb;
   min-height: 100%;
 }
-.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;
-}
 .card {
   background: #ffffff;
   border-radius: 24rpx;

+ 0 - 1
dist/dev/mp-weixin/pages/profile/edit.json

@@ -1,4 +1,3 @@
 {
-  "navigationBarTitleText": "编辑资料",
   "usingComponents": {}
 }

+ 0 - 1
dist/dev/mp-weixin/pages/rank/rank.json

@@ -1,4 +1,3 @@
 {
-  "navigationBarTitleText": "模拟排名",
   "usingComponents": {}
 }

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

@@ -1 +1 @@
-<view class="page-rank"><view class="page-title-card"><text class="page-title-text">量化选股大师</text></view><scroll-view class="scroll-view" scroll-y><view class="{{['content-wrapper', j && 'blur-content']}}"><view class="portfolio-card"><view class="portfolio-header"><view class="portfolio-icon">💼</view><text class="portfolio-title">我的模拟资产</text></view><view class="portfolio-content"><view class="portfolio-main"><view class="portfolio-label">当前账户余额 (¥)</view><view class="portfolio-amount">{{a}}</view></view><view class="portfolio-profit"><view class="profit-label">总盈亏 / 收益率</view><view class="{{['profit-value', d]}}"> ¥ {{b}} ({{c}}%) </view></view></view></view><view class="leaderboard-section"><view class="section-header"><view class="trophy-icon">🏆</view><text class="section-title">模拟交易排行榜</text></view><view class="my-rank-card"><view class="rank-number">#{{e}}</view><view class="rank-info"><text class="rank-name">您 (本期收益)</text></view><view class="{{['rank-rate', h]}}">{{f}}{{g}}% </view></view><view class="leaderboard-list"><view wx:for="{{i}}" wx:for-item="item" wx:key="g" class="leaderboard-item"><view class="{{['rank-badge', item.b]}}"> #{{item.a}}</view><view class="user-info"><text class="user-name">{{item.c}}</text></view><view class="{{['user-rate', item.f]}}">{{item.d}}{{item.e}}% </view></view></view><view class="leaderboard-note"><text class="note-text">排名每日更新,收益基于系统信号的模拟交易。</text></view></view><view class="bottom-safe-area"></view></view></scroll-view><view wx:if="{{k}}" class="login-mask"><view class="login-prompt"><view class="lock-icon">🔒</view><text class="prompt-title">登录后查看完整数据</text><text class="prompt-desc">使用微信授权快速登录</text><button class="login-button-native" bindtap="{{l}}"><text>登录</text></button></view></view></view>
+<view class="page-rank"><scroll-view class="scroll-view" scroll-y><view class="{{['content-wrapper', j && 'blur-content']}}"><view class="portfolio-card"><view class="portfolio-header"><view class="portfolio-icon">💼</view><text class="portfolio-title">我的模拟资产</text></view><view class="portfolio-content"><view class="portfolio-main"><view class="portfolio-label">当前账户余额 (¥)</view><view class="portfolio-amount">{{a}}</view></view><view class="portfolio-profit"><view class="profit-label">总盈亏 / 收益率</view><view class="{{['profit-value', d]}}"> ¥ {{b}} ({{c}}%) </view></view></view></view><view class="leaderboard-section"><view class="section-header"><view class="trophy-icon">🏆</view><text class="section-title">模拟交易排行榜</text></view><view class="my-rank-card"><view class="rank-number">#{{e}}</view><view class="rank-info"><text class="rank-name">您 (本期收益)</text></view><view class="{{['rank-rate', h]}}">{{f}}{{g}}% </view></view><view class="leaderboard-list"><view wx:for="{{i}}" wx:for-item="item" wx:key="g" class="leaderboard-item"><view class="{{['rank-badge', item.b]}}"> #{{item.a}}</view><view class="user-info"><text class="user-name">{{item.c}}</text></view><view class="{{['user-rate', item.f]}}">{{item.d}}{{item.e}}% </view></view></view><view class="leaderboard-note"><text class="note-text">排名每日更新,收益基于系统信号的模拟交易。</text></view></view><view class="bottom-safe-area"></view></view></scroll-view><view wx:if="{{k}}" class="login-mask"><view class="login-prompt"><view class="lock-icon">🔒</view><text class="prompt-title">登录后查看完整数据</text><text class="prompt-desc">使用微信授权快速登录</text><button class="login-button-native" bindtap="{{l}}"><text>登录</text></button></view></view></view>

+ 0 - 13
dist/dev/mp-weixin/pages/rank/rank.wxss

@@ -5,19 +5,6 @@
   background: #f5f6fb;
   height: 100vh;
 }
-.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;

+ 0 - 1
dist/dev/mp-weixin/pages/strong/strong.json

@@ -1,4 +1,3 @@
 {
-  "navigationBarTitleText": "强势池",
   "usingComponents": {}
 }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
dist/dev/mp-weixin/pages/strong/strong.wxml


+ 0 - 13
dist/dev/mp-weixin/pages/strong/strong.wxss

@@ -14,19 +14,6 @@
   background: #f5f6fb;
   min-height: 100%;
 }
-.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;
-}
 .card {
   background: #ffffff;
   border-radius: 24rpx;

+ 0 - 1
dist/dev/mp-weixin/pages/transaction/transaction.json

@@ -1,5 +1,4 @@
 {
-  "navigationBarTitleText": "交易记录",
   "navigationStyle": "custom",
   "usingComponents": {}
 }

+ 0 - 75
src/components/AdvantageCard.vue

@@ -1,75 +0,0 @@
-<template>
-  <view class="card advantage-card">
-    <view class="card-header">
-      <view class="icon-circle">
-        <text class="icon-check">✓</text>
-      </view>
-      <text class="card-header-title">量化投资的优势</text>
-    </view>
-
-    <view class="advantage-item">
-      <text class="advantage-label">客观纪律性:</text>
-      <text class="advantage-desc">排除情绪干扰,严格执行预设的交易信号。</text>
-    </view>
-    <view class="advantage-item">
-      <text class="advantage-label">高效覆盖广度:</text>
-      <text class="advantage-desc">能同时分析数千只股票,人工无法企及。</text>
-    </view>
-  </view>
-</template>
-
-<script setup>
-</script>
-
-<style scoped>
-.card {
-  background: #ffffff;
-  border-radius: 24rpx;
-  padding: 32rpx 32rpx 36rpx;
-  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 32rpx;
-}
-
-.card-header {
-  display: flex;
-  align-items: center;
-  margin-bottom: 24rpx;
-}
-
-.card-header-title {
-  font-size: 30rpx;
-  font-weight: 600;
-  color: #222222;
-}
-
-.icon-circle {
-  width: 40rpx;
-  height: 40rpx;
-  border-radius: 50%;
-  background: #e7f7ef;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-right: 16rpx;
-}
-
-.icon-check {
-  font-size: 24rpx;
-  color: #28a745;
-}
-
-.advantage-item {
-  margin-bottom: 12rpx;
-  font-size: 26rpx;
-  line-height: 1.6;
-  color: #4a4f63;
-}
-
-.advantage-label {
-  font-weight: 600;
-}
-
-.advantage-desc {
-  font-weight: 400;
-}
-</style>

+ 0 - 100
src/components/LoginGuide.vue

@@ -1,100 +0,0 @@
-<template>
-  <view class="login-guide" v-if="!isLoggedIn">
-    <view class="guide-content">
-      <image class="guide-icon" src="/static/images/login-icon.png" mode="aspectFit"></image>
-      <text class="guide-title">{{ title || '登录后查看更多内容' }}</text>
-      <text class="guide-desc">{{ desc || '登录后可以使用完整功能' }}</text>
-      <button class="guide-btn" @click="goToLogin">立即登录</button>
-    </view>
-  </view>
-</template>
-
-<script>
-import { isLoggedIn } from '@/utils/auth.js'
-
-export default {
-  props: {
-    title: {
-      type: String,
-      default: '登录后查看更多内容'
-    },
-    desc: {
-      type: String,
-      default: '登录后可以使用完整功能'
-    }
-  },
-  
-  data() {
-    return {
-      isLoggedIn: false
-    }
-  },
-  
-  onShow() {
-    this.checkLoginStatus()
-  },
-  
-  methods: {
-    checkLoginStatus() {
-      this.isLoggedIn = isLoggedIn()
-    },
-    
-    goToLogin() {
-      uni.navigateTo({
-        url: '/pages/login/login'
-      })
-    }
-  }
-}
-</script>
-
-<style scoped>
-.login-guide {
-  min-height: 100vh;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  background: #f5f6fb;
-}
-
-.guide-content {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 80rpx 40rpx;
-}
-
-.guide-icon {
-  width: 200rpx;
-  height: 200rpx;
-  margin-bottom: 40rpx;
-  opacity: 0.6;
-}
-
-.guide-title {
-  font-size: 32rpx;
-  font-weight: 500;
-  color: #333;
-  margin-bottom: 16rpx;
-}
-
-.guide-desc {
-  font-size: 26rpx;
-  color: #999;
-  margin-bottom: 60rpx;
-}
-
-.guide-btn {
-  width: 400rpx;
-  height: 88rpx;
-  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-  color: #fff;
-  border-radius: 44rpx;
-  font-size: 30rpx;
-  font-weight: 500;
-  border: none;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-</style>

+ 0 - 189
src/components/ResultCard.vue

@@ -1,189 +0,0 @@
-<template>
-  <view class="card result-card">
-    <view v-if="loading">
-      <text class="result-loading">正在查询,请稍候...</text>
-    </view>
-    <view v-else-if="errorMsg">
-      <text class="result-error">{{ errorMsg }}</text>
-    </view>
-    <view v-else-if="result">
-      <view class="detail-header">
-        <view>
-          <view class="detail-name">{{ result.stockName }}({{ result.stockCode }})</view>
-          <view class="detail-sub">最新量化系统评分</view>
-        </view>
-        <view class="score-badge">{{ result.score }}</view>
-      </view>
-
-      <view class="section">
-        <view class="section-title">历史评分趋势</view>
-        <block v-for="item in result.history" :key="item.date">
-          <view class="history-row">
-            <text class="history-date">{{ item.date }} 的量化评分:</text>
-            <text :class="['history-score', item.score >= 90 ? 'tag-danger' : (item.score >= 80 ? 'tag-success' : 'tag-info')]">
-              {{ item.score }}
-            </text>
-          </view>
-        </block>
-        <text class="history-note">(注意:此为模拟历史数据,仅供展示。)</text>
-      </view>
-
-      <view class="section">
-        <view class="section-title">评分因子构成</view>
-        <block v-for="item in result.factors" :key="item.name">
-          <view class="factor-row">
-            <text class="factor-name">{{ item.name }}</text>
-            <text class="factor-score">{{ item.value }}</text>
-          </view>
-        </block>
-      </view>
-    </view>
-  </view>
-</template>
-
-<script setup>
-defineProps({
-  loading: {
-    type: Boolean,
-    default: false
-  },
-  errorMsg: {
-    type: String,
-    default: ''
-  },
-  result: {
-    type: Object,
-    default: null
-  }
-})
-</script>
-
-<style scoped>
-.card {
-  background: #ffffff;
-  border-radius: 24rpx;
-  padding: 32rpx 32rpx 36rpx;
-  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 32rpx;
-}
-
-.result-card {
-  margin-top: 8rpx;
-}
-
-.result-loading {
-  font-size: 26rpx;
-  color: #666a7f;
-}
-
-.result-error {
-  font-size: 26rpx;
-  color: #ff5b5b;
-}
-
-.detail-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 24rpx;
-}
-
-.detail-name {
-  font-size: 30rpx;
-  font-weight: 700;
-  color: #1f1f2e;
-}
-
-.detail-sub {
-  margin-top: 8rpx;
-  font-size: 24rpx;
-  color: #9da3b5;
-}
-
-.score-badge {
-  min-width: 140rpx;
-  padding: 12rpx 22rpx;
-  border-radius: 20rpx;
-  background: #f16565;
-  color: #ffffff;
-  font-size: 40rpx;
-  font-weight: 700;
-  text-align: right;
-  box-shadow: 0 10rpx 24rpx rgba(241, 101, 101, 0.35);
-}
-
-.section {
-  margin-top: 20rpx;
-}
-
-.section-title {
-  font-size: 28rpx;
-  font-weight: 700;
-  color: #1f1f2e;
-  margin-bottom: 16rpx;
-}
-
-.history-row {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 18rpx 0;
-  border-bottom: 1rpx solid #f1f2f6;
-}
-
-.history-row:last-child {
-  border-bottom: none;
-}
-
-.history-date {
-  font-size: 26rpx;
-  color: #3c4050;
-}
-
-.history-score {
-  min-width: 96rpx;
-  text-align: center;
-  padding: 6rpx 18rpx;
-  border-radius: 30rpx;
-  font-size: 28rpx;
-  font-weight: 700;
-  color: #ffffff;
-}
-
-.tag-danger {
-  background: #f16565;
-}
-
-.tag-success {
-  background: #3abf81;
-}
-
-.tag-info {
-  background: #4c86ff;
-}
-
-.history-note {
-  display: block;
-  margin-top: 12rpx;
-  font-size: 22rpx;
-  color: #9da3b5;
-}
-
-.factor-row {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 14rpx 0;
-}
-
-.factor-name {
-  font-size: 26rpx;
-  color: #3c4050;
-}
-
-.factor-score {
-  font-size: 28rpx;
-  font-weight: 600;
-  color: #4c86ff;
-}
-</style>

+ 0 - 67
src/components/RiskCard.vue

@@ -1,67 +0,0 @@
-<template>
-  <view class="card risk-card">
-    <view class="card-header">
-      <view class="icon-warning">
-        <text class="icon-warning-text">!</text>
-      </view>
-      <text class="card-header-title">风险提示(免责声明)</text>
-    </view>
-
-    <text class="risk-text">
-      本系统的量化分数和股票池信息均基于历史数据和特定模型计算,并非对未来市场的保证或预测。市场环境瞬息万变,
-      量化模型可能存在失效或回撤风险。请勿将本系统数据作为投资决策的唯一依据,请您充分理解股票投资风险,并独立做出投资判断。
-    </text>
-  </view>
-</template>
-
-<script setup>
-</script>
-
-<style scoped>
-.card {
-  background: #ffffff;
-  border-radius: 24rpx;
-  padding: 32rpx 32rpx 36rpx;
-  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 32rpx;
-}
-
-.risk-card {
-  margin-bottom: 24rpx;
-}
-
-.card-header {
-  display: flex;
-  align-items: center;
-  margin-bottom: 24rpx;
-}
-
-.card-header-title {
-  font-size: 30rpx;
-  font-weight: 600;
-  color: #222222;
-}
-
-.icon-warning {
-  width: 40rpx;
-  height: 40rpx;
-  border-radius: 50%;
-  background: #ffecef;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-right: 16rpx;
-}
-
-.icon-warning-text {
-  font-size: 26rpx;
-  color: #ff5b5b;
-}
-
-.risk-text {
-  display: block;
-  font-size: 24rpx;
-  line-height: 1.8;
-  color: #666a7f;
-}
-</style>

+ 0 - 116
src/components/SearchCard.vue

@@ -1,116 +0,0 @@
-<template>
-  <view class="card search-card">
-    <text class="card-title">量化分数实时查询 & 历史数据</text>
-
-    <view class="search-row">
-      <input
-        class="search-input"
-        type="text"
-        placeholder="输入股票代码或名称 (如: 600030 或 中信)"
-        placeholder-class="search-placeholder"
-        confirm-type="search"
-        :value="keyword"
-        @input="onKeywordChange"
-        @confirm="handleSearch"
-      />
-      <view class="search-button" @click="handleSearch">
-        <image class="search-icon" src="/static/images/tab_search.png" mode="aspectFit"></image>
-      </view>
-    </view>
-
-    <text class="search-tip">支持模糊搜索股票代码或名称,快速找到相关股票</text>
-  </view>
-</template>
-
-<script setup>
-import { ref, watch } from 'vue'
-
-const props = defineProps({
-  keyword: {
-    type: String,
-    default: ''
-  }
-})
-
-const emit = defineEmits(['update:keyword', 'search'])
-
-const keyword = ref(props.keyword)
-
-watch(() => props.keyword, (newVal) => {
-  keyword.value = newVal
-})
-
-const onKeywordChange = (e) => {
-  keyword.value = e.detail.value || ''
-  emit('update:keyword', keyword.value)
-}
-
-const handleSearch = () => {
-  emit('search')
-}
-</script>
-
-<style scoped>
-.card {
-  background: #ffffff;
-  border-radius: 24rpx;
-  padding: 32rpx 32rpx 36rpx;
-  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 32rpx;
-}
-
-.search-card {
-  margin-top: 16rpx;
-}
-
-.card-title {
-  display: block;
-  font-size: 32rpx;
-  font-weight: 600;
-  color: #222222;
-  margin-bottom: 32rpx;
-}
-
-.search-row {
-  display: flex;
-  align-items: center;
-  background: #f7f8fc;
-  border-radius: 999rpx;
-  padding: 0 8rpx 0 32rpx;
-  height: 96rpx;
-  box-sizing: border-box;
-}
-
-.search-input {
-  flex: 1;
-  font-size: 28rpx;
-  color: #222222;
-}
-
-.search-placeholder {
-  color: #b4b8c6;
-}
-
-.search-button {
-  width: 96rpx;
-  height: 80rpx;
-  margin-left: 12rpx;
-  border-radius: 999rpx;
-  background: #f5f6fb;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-.search-icon {
-  width: 48rpx;
-  height: 48rpx;
-}
-
-.search-tip {
-  display: block;
-  margin-top: 20rpx;
-  font-size: 24rpx;
-  color: #9ca2b5;
-}
-</style>

+ 0 - 206
src/components/StockListCard.vue

@@ -1,206 +0,0 @@
-<template>
-  <view class="card stock-list-card">
-    <text class="card-title">搜索结果</text>
-
-    <view v-if="loading" class="loading-container">
-      <text class="loading-text">加载中...</text>
-    </view>
-
-    <view v-else-if="errorMsg" class="error-container">
-      <text class="error-text">{{ errorMsg }}</text>
-    </view>
-
-    <view v-else-if="stocks && stocks.length > 0" class="stock-list">
-      <view
-        v-for="stock in stocks"
-        :key="stock.stockCode"
-        class="stock-item"
-        @click="handleStockClick(stock)"
-      >
-        <view class="stock-info">
-          <text class="stock-name">{{ stock.stockName }}</text>
-          <text class="stock-code">{{ stock.stockCode }}</text>
-        </view>
-        <view class="stock-meta">
-          <text v-if="stock.market" class="stock-market">{{ stock.market }}</text>
-          <text v-if="stock.score !== undefined" class="stock-score">
-            评分: {{ stock.score }}
-          </text>
-        </view>
-      </view>
-
-      <view v-if="hasMore" class="load-more" @click="handleLoadMore">
-        <text class="load-more-text">{{ loadingMore ? '加载中...' : '加载更多' }}</text>
-      </view>
-
-      <view v-else class="no-more">
-        <text class="no-more-text">没有更多数据了</text>
-      </view>
-    </view>
-
-    <view v-else class="empty-container">
-      <text class="empty-text">暂无搜索结果</text>
-    </view>
-  </view>
-</template>
-
-<script setup>
-const props = defineProps({
-  loading: {
-    type: Boolean,
-    default: false
-  },
-  loadingMore: {
-    type: Boolean,
-    default: false
-  },
-  errorMsg: {
-    type: String,
-    default: ''
-  },
-  stocks: {
-    type: Array,
-    default: () => []
-  },
-  hasMore: {
-    type: Boolean,
-    default: false
-  }
-})
-
-const emit = defineEmits(['stockClick', 'loadMore'])
-
-const handleStockClick = (stock) => {
-  emit('stockClick', stock)
-}
-
-const handleLoadMore = () => {
-  if (!props.loadingMore) {
-    emit('loadMore')
-  }
-}
-</script>
-
-<style scoped>
-.card {
-  background: #ffffff;
-  border-radius: 24rpx;
-  padding: 32rpx;
-  box-shadow: 0 16rpx 40rpx rgba(37, 52, 94, 0.08);
-  margin-bottom: 32rpx;
-}
-
-.stock-list-card {
-  margin-top: 16rpx;
-}
-
-.card-title {
-  display: block;
-  font-size: 32rpx;
-  font-weight: 600;
-  color: #222222;
-  margin-bottom: 24rpx;
-}
-
-.loading-container,
-.error-container,
-.empty-container {
-  padding: 80rpx 0;
-  text-align: center;
-}
-
-.loading-text {
-  font-size: 28rpx;
-  color: #9ca2b5;
-}
-
-.error-text {
-  font-size: 28rpx;
-  color: #ff6b6b;
-}
-
-.empty-text {
-  font-size: 28rpx;
-  color: #9ca2b5;
-}
-
-.stock-list {
-  display: flex;
-  flex-direction: column;
-}
-
-.stock-item {
-  padding: 24rpx;
-  background: #f7f8fc;
-  border-radius: 16rpx;
-  margin-bottom: 16rpx;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  transition: all 0.3s;
-}
-
-.stock-item:active {
-  background: #eef0f6;
-  transform: scale(0.98);
-}
-
-.stock-info {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-}
-
-.stock-name {
-  font-size: 30rpx;
-  font-weight: 600;
-  color: #222222;
-  margin-bottom: 8rpx;
-}
-
-.stock-code {
-  font-size: 24rpx;
-  color: #9ca2b5;
-}
-
-.stock-meta {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-end;
-}
-
-.stock-market {
-  font-size: 22rpx;
-  color: #5d55e8;
-  background: rgba(93, 85, 232, 0.1);
-  padding: 4rpx 12rpx;
-  border-radius: 8rpx;
-  margin-bottom: 8rpx;
-}
-
-.stock-score {
-  font-size: 26rpx;
-  font-weight: 600;
-  color: #5d55e8;
-}
-
-.load-more {
-  padding: 32rpx 0;
-  text-align: center;
-}
-
-.load-more-text {
-  font-size: 28rpx;
-  color: #5d55e8;
-}
-
-.no-more {
-  padding: 32rpx 0;
-  text-align: center;
-}
-
-.no-more-text {
-  font-size: 24rpx;
-  color: #9ca2b5;
-}
-</style>

+ 2 - 1
src/components/UserInfoPopup.vue

@@ -63,8 +63,9 @@ export default {
   methods: {
     /**
      * 打开弹窗
+     * @param userData 可选,后端返回的用户数据(新流程中不再需要)
      */
-    open(userData) {
+    open(userData = null) {
       this.visible = true
       this.userData = userData
       this.nickname = ''

+ 13 - 23
src/pages.json

@@ -2,58 +2,43 @@
   "pages": [
     {
       "path": "pages/index/index",
-      "style": {
-        "navigationBarTitleText": "量化选股大师"
-      }
+      "style": {}
     },
     {
       "path": "pages/login/login",
       "style": {
-        "navigationBarTitleText": "登录",
         "navigationStyle": "custom"
       }
     },
     {
       "path": "pages/pool/pool",
-      "style": {
-        "navigationBarTitleText": "超短池"
-      }
+      "style": {}
     },
     {
       "path": "pages/strong/strong",
-      "style": {
-        "navigationBarTitleText": "强势池"
-      }
+      "style": {}
     },
     {
       "path": "pages/rank/rank",
-      "style": {
-        "navigationBarTitleText": "模拟排名"
-      }
+      "style": {}
     },
     {
       "path": "pages/mine/mine",
-      "style": {
-        "navigationBarTitleText": "个人中心"
-      }
+      "style": {}
     },
     {
       "path": "pages/profile/edit",
-      "style": {
-        "navigationBarTitleText": "编辑资料"
-      }
+      "style": {}
     },
     {
       "path": "pages/transaction/transaction",
       "style": {
-        "navigationBarTitleText": "交易记录",
         "navigationStyle": "custom"
       }
     },
     {
       "path": "pages/points/points",
       "style": {
-        "navigationBarTitleText": "积分记录",
         "navigationStyle": "custom"
       }
     }
@@ -61,8 +46,13 @@
   "globalStyle": {
     "navigationBarBackgroundColor": "#ffffff",
     "navigationBarTextStyle": "black",
-    "navigationBarTitleText": "量化选股大师",
-    "backgroundColor": "#f5f6fb"
+    "navigationBarTitleText": "量化交易大师",
+    "backgroundColor": "#f5f6fb",
+    "titleNView": {
+      "titleColor": "#3F51F7",
+      "titleSize": "18",
+      "titleWeight": "800"
+    }
   },
   "tabBar": {
     "color": "#999999",

+ 0 - 24
src/pages/index/index.vue

@@ -1,9 +1,5 @@
 <template>
   <view class="page-container">
-    <!-- 顶部标题卡片 -->
-    <view class="page-title-card">
-      <text class="page-title-text">量化选股大师</text>
-    </view>
     <scroll-view class="scroll-view" scroll-y>
       <view class="content-wrapper">
 
@@ -293,21 +289,6 @@ const onInputBlur = () => {
 <style>
 /** 首页量化查询界面样式 **/
 
-.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;
-}
-
 .page-container {
   height: 100vh;
   display: flex;
@@ -315,11 +296,6 @@ const onInputBlur = () => {
   background: #f5f6fb;
 }
 
-/* 移除旧的 custom-header 样式,或者保留也无妨,因为 HTML 中不再使用 */
-.custom-header {
-  display: none; 
-}
-
 .scroll-view {
   flex: 1;
   height: 0;

+ 84 - 27
src/pages/login/login.vue

@@ -15,7 +15,7 @@
     <!-- Logo和标题 -->
     <view class="header">
       <image class="logo" src="/static/images/logo.png" mode="aspectFit"></image>
-      <text class="title">量化选股大师</text>
+      <text class="title">量化交易大师</text>
       <text class="subtitle">专业的股票量化分析工具</text>
     </view>
 
@@ -30,15 +30,25 @@
         <text class="btn-text">微信一键登录</text>
       </button>
 
-      <!-- 新用户:授权手机号登录 -->
+      <!-- 新用户第二步:授权手机号登录(已完成头像昵称授权后显示) -->
       <button 
-        v-else
+        v-else-if="showPhoneAuth"
         class="login-btn primary-btn"
         open-type="getPhoneNumber"
         @getphonenumber="handleGetPhoneNumber"
       >
         <text class="btn-icon">🔐</text>
-        <text class="btn-text">授权手机号登录</text>
+        <text class="btn-text">授权手机号完成注册</text>
+      </button>
+
+      <!-- 新用户第一步:获取头像昵称 -->
+      <button 
+        v-else
+        class="login-btn primary-btn"
+        @click="handleGetUserProfile"
+      >
+        <text class="btn-icon">👤</text>
+        <text class="btn-text">授权登录</text>
       </button>
 
       <!-- 用户协议 -->
@@ -78,9 +88,11 @@ export default {
   data() {
     return {
       showOneClickLogin: true,  // 是否显示一键登录按钮
+      showPhoneAuth: false,     // 是否显示手机号授权按钮(新用户第二步)
       agreedToTerms: false,     // 是否同意协议
       loginCode: '',            // 微信登录code
-      tempUserData: null        // 临时存储的用户数据
+      tempUserData: null,       // 临时存储的用户数据(openid, unionid等)
+      tempUserProfile: null     // 临时存储的用户头像昵称信息
     }
   },
 
@@ -134,9 +146,10 @@ export default {
           console.log('[登录] 老用户登录成功')
           this.handleLoginSuccess()
         } else if (result && result.isSign === 'false') {
-          // 新用户,需要授权手机号
-          console.log('[登录] 新用户,需要授权手机号')
+          // 新用户,需要先获取头像昵称
+          console.log('[登录] 新用户,需要先获取头像昵称')
           this.showOneClickLogin = false
+          this.showPhoneAuth = false
         } else if (result && result.code === 103) {
           // 账号被禁用
           uni.showModal({
@@ -160,7 +173,48 @@ export default {
     },
 
     /**
-     * 第二步:获取手机号授权(新用户)
+     * 第二步:获取用户头像昵称(新用户)
+     */
+    handleGetUserProfile() {
+      // 检查是否同意协议
+      if (!this.agreedToTerms) {
+        uni.showToast({
+          title: '请先阅读并同意用户协议',
+          icon: 'none',
+          duration: 2000
+        })
+        return
+      }
+      
+      console.log('[登录] 打开用户信息弹窗')
+      this.$refs.userInfoPopup.open()
+    },
+
+    /**
+     * 用户信息弹窗确认回调(新用户第二步完成后)
+     */
+    handleUserInfoConfirm(userInfo) {
+      console.log('[登录] 用户信息已获取:', userInfo)
+      
+      // 保存用户头像昵称信息
+      this.tempUserProfile = {
+        nickname: userInfo.nickname,
+        avatarUrl: userInfo.avatarUrl,
+        tempAvatarPath: userInfo.tempAvatarPath
+      }
+      
+      // 显示手机号授权按钮
+      this.showPhoneAuth = true
+      
+      uni.showToast({
+        title: '请继续授权手机号',
+        icon: 'none',
+        duration: 2000
+      })
+    },
+
+    /**
+     * 第三步:获取手机号授权(新用户)
      */
     async handleGetPhoneNumber(e) {
       console.log('[登录] 手机号授权回调:', e)
@@ -170,7 +224,7 @@ export default {
         if (e.detail.errMsg.includes('no permission')) {
           uni.showModal({
             title: '权限不足',
-            content: '获取手机号功能需要:\n1. 小程序企业认证\n2. 开通"手机号快速验证组件"权限\n3. 在真机上测试',
+            content: '获取手机号功能需要:\n1. 小程序企业认证"权限 \n2. 在真机上测试',
             showCancel: false
           })
         } else {
@@ -205,10 +259,16 @@ export default {
         uni.hideLoading()
         
         if (result && result.isSign === 'false') {
-          // 需要完善用户信息
-          console.log('[登录] 需要完善用户信息')
-          this.tempUserData = result
-          this.$refs.userInfoPopup.open(result)
+          // 需要完成注册(已有头像昵称,现在有手机号)
+          console.log('[登录] 需要完成注册')
+          // 保存手机号相关信息
+          this.tempUserData = {
+            openid: result.openid,
+            unionid: result.unionid,
+            phoneNumber: result.phoneNumber
+          }
+          // 直接提交注册
+          await this.submitRegistration()
         } else if (result && result.isSign === 'true') {
           // 已注册,直接登录成功
           console.log('[登录] 已注册用户,登录成功')
@@ -253,35 +313,34 @@ export default {
     },
 
     /**
-     * 第三步:完善用户信息(首次登录
+     * 第四步:提交注册(新用户完成所有授权后
      */
-    async handleUserInfoConfirm(userInfo) {
+    async submitRegistration() {
       try {
         uni.showLoading({ title: '注册中...' })
         
-        // 构建用户信息(先用微信临时头像URL)
+        // 构建用户信息
         const completeInfo = {
           openid: this.tempUserData.openid,
           unionid: this.tempUserData.unionid,
           phoneNumber: this.tempUserData.phoneNumber,
-          nickname: userInfo.nickname,
-          avatarUrl: userInfo.avatarUrl  // 微信临时URL,先存着
+          nickname: this.tempUserProfile.nickname,
+          avatarUrl: this.tempUserProfile.avatarUrl
         }
         
         console.log('[登录] 提交用户信息')
         
-        // 调用后端接口完成注册(此时会拿到token)
+        // 调用后端接口完成注册
         await wxCompleteUserInfo(completeInfo)
         
-        // 注册成功后,有了token,上传头像到服务器
-        if (userInfo.tempAvatarPath) {
-          console.log('[登录] 开始上传头像到服务器, tempAvatarPath:', userInfo.tempAvatarPath)
+        // 注册成功后,上传头像到服务器
+        if (this.tempUserProfile.tempAvatarPath) {
+          console.log('[登录] 开始上传头像到服务器')
           try {
-            const uploadedUrl = await this.uploadAvatarWithToken(userInfo.tempAvatarPath)
-            console.log('[登录] 头像上传成功, uploadedUrl:', uploadedUrl)
+            const uploadedUrl = await this.uploadAvatarWithToken(this.tempUserProfile.tempAvatarPath)
+            console.log('[登录] 头像上传成功:', uploadedUrl)
             if (uploadedUrl) {
               // 更新用户头像为服务器URL
-              console.log('[登录] 调用updateUserProfile更新头像')
               const updateResult = await updateUserProfile({ avatar: uploadedUrl })
               console.log('[登录] updateUserProfile返回:', updateResult)
               
@@ -292,11 +351,9 @@ export default {
                 parsed.avatar = uploadedUrl
                 uni.setStorageSync('user_info', JSON.stringify(parsed))
               }
-              console.log('[登录] 头像上传成功:', uploadedUrl)
             }
           } catch (uploadErr) {
             console.warn('[登录] 头像上传失败:', uploadErr)
-            // 头像上传失败不影响登录,下次打开小程序头像可能显示不出来
           }
         }
         

+ 0 - 20
src/pages/mine/mine.vue

@@ -1,10 +1,5 @@
 <template>
   <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">
         <!-- 用户信息卡片 -->
@@ -242,21 +237,6 @@ const handleTransactionRecord = () => {
   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;

+ 0 - 19
src/pages/pool/pool.vue

@@ -1,9 +1,5 @@
 <template>
   <view class="page-container">
-    <!-- 顶部标题卡片 -->
-    <view class="page-title-card">
-      <text class="page-title-text">量化选股大师</text>
-    </view>
     <scroll-view class="scroll-view" scroll-y>
       <view class="content-wrapper">
         <!-- 性能指标卡片 -->
@@ -364,21 +360,6 @@ onShow(() => {
   min-height: 100%;
 }
 
-.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;
-}
-
 .card {
   background: #ffffff;
   border-radius: 24rpx;

+ 0 - 20
src/pages/rank/rank.vue

@@ -1,10 +1,5 @@
 <template>
   <view class="page-rank">
-    <!-- 顶部标题卡片 -->
-    <view class="page-title-card">
-      <text class="page-title-text">量化选股大师</text>
-    </view>
-    
     <scroll-view class="scroll-view" scroll-y>
       <view class="content-wrapper" :class="{ 'blur-content': !isLoggedIn }">
         <!-- 我的模拟资产卡片 -->
@@ -204,21 +199,6 @@ onShow(() => {
   height: 100vh;
 }
 
-.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;

+ 0 - 19
src/pages/strong/strong.vue

@@ -1,9 +1,5 @@
 <template>
   <view class="page-container">
-    <!-- 顶部标题卡片 -->
-    <view class="page-title-card">
-      <text class="page-title-text">量化选股大师</text>
-    </view>
     <scroll-view class="scroll-view" scroll-y>
       <view class="content-wrapper" :class="{ 'blur-content': !isLoggedIn }">
         <!-- 强势趋势池标题 -->
@@ -428,21 +424,6 @@ onShow(() => {
   min-height: 100%;
 }
 
-.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;
-}
-
 .card {
   background: #ffffff;
   border-radius: 24rpx;

+ 4 - 3
src/utils/auth.js

@@ -4,9 +4,10 @@
  * 
  * 完整登录流程:
  * 1. 老用户静默登录:wx.login() -> POST /v1/auth/wx/silent-login
- * 2. 新用户手机号授权:getPhoneNumber -> POST /v1/auth/wx/phone-verify
- * 3. 完善用户信息:头像+昵称 -> POST /v1/auth/wx/register
- * 4. 获取用户信息:token -> GET /v1/user/info
+ * 2. 新用户获取头像昵称:弹窗选择头像和输入昵称
+ * 3. 新用户手机号授权:getPhoneNumber -> POST /v1/auth/wx/phone-verify
+ * 4. 完善用户信息:头像+昵称+手机号 -> POST /v1/auth/wx/register
+ * 5. 获取用户信息:token -> GET /v1/user/info
  */
 
 import { 

+ 0 - 19
utils/util.js

@@ -1,19 +0,0 @@
-const formatTime = date => {
-  const year = date.getFullYear()
-  const month = date.getMonth() + 1
-  const day = date.getDate()
-  const hour = date.getHours()
-  const minute = date.getMinutes()
-  const second = date.getSeconds()
-
-  return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
-}
-
-const formatNumber = n => {
-  n = n.toString()
-  return n[1] ? n : `0${n}`
-}
-
-module.exports = {
-  formatTime
-}

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio