Просмотр исходного кода

Feat: 学员端登录改为首页下端上浮弹层,登录前可浏览部分内容

liaoxg 2 недель назад
Родитель
Сommit
e5c2d32028
2 измененных файлов с 171 добавлено и 5 удалено
  1. 170 4
      train-frontend/pages/index/index.vue
  2. 1 1
      train-frontend/utils/api.js

+ 170 - 4
train-frontend/pages/index/index.vue

@@ -4,6 +4,7 @@
       <text class="banner-icon">🚀</text>
       <text class="banner-title">家立方-AI管家成长营</text>
       <text class="banner-sub">L0 新人成长训练营</text>
+      <button v-if="!isLoggedIn" class="login-entry-btn" @click="showLoginSheet">点击登录</button>
     </view>
 
     <view class="status-card">
@@ -72,20 +73,44 @@
         <text class="nav-text">校友校验</text>
       </view>
     </view>
+
+    <!-- Login Bottom Sheet -->
+    <view class="login-sheet-mask" :class="{ 'sheet-open': loginSheetVisible }" @click="hideLoginSheet">
+      <view class="login-sheet-panel" @click.stop>
+        <view class="sheet-handle"></view>
+        <view class="sheet-content">
+          <view class="sheet-header">
+            <text class="sheet-title">欢迎回来</text>
+            <text class="sheet-sub">登录以解锁更多成长功能</text>
+          </view>
+          <button class="sheet-login-btn" @click="handleLogin" :loading="loginLoading" :disabled="loginLoading">
+            微信一键登录
+          </button>
+          <view class="sheet-footer">
+            <text class="sheet-footer-text">登录即代表同意服务协议</text>
+          </view>
+        </view>
+      </view>
+    </view>
   </view>
 </template>
 
 <script>
-import { getMyGroup, getClassInfo } from '@/utils/api.js'
+import { getMyGroup, getClassInfo, wechatLogin } from '@/utils/api.js'
 
 export default {
   data() {
     return {
       groupInfo: null,
-      classInfo: null
+      classInfo: null,
+      loginSheetVisible: false,
+      loginLoading: false
     }
   },
   computed: {
+    isLoggedIn() {
+      return this.$store.getters.isLoggedIn
+    },
     verifyLabel() {
       var v = this.$store.state.alumniVerify
       if (v === 'accepted') return '✅ 已通过'
@@ -106,8 +131,17 @@ export default {
   onShow() {
     this.loadInfo()
   },
+  created() {
+    uni.$on('showLoginSheet', function() {
+      this.showLoginSheet()
+    }.bind(this))
+  },
+  beforeDestroy() {
+    uni.$off('showLoginSheet')
+  },
   methods: {
     loadInfo() {
+      if (!this.isLoggedIn) return
       var self = this
       if (this.$store.state.classId) {
         getClassInfo().then(function(resp) {
@@ -118,6 +152,41 @@ export default {
         self.groupInfo = resp.data
       }).catch(function() {})
     },
+    showLoginSheet() {
+      this.loginSheetVisible = true
+    },
+    hideLoginSheet() {
+      this.loginSheetVisible = false
+    },
+    handleLogin() {
+      if (this.loginLoading) return
+      this.loginLoading = true
+      var self = this
+      wx.login({
+        success: function(res) {
+          if (res.code) {
+            wechatLogin(res.code).then(function(resp) {
+              var data = resp.data
+              self.$store.dispatch('login', data)
+              uni.showToast({ title: '登录成功', icon: 'success' })
+              self.hideLoginSheet()
+              self.loadInfo()
+            }).catch(function(err) {
+              console.error('登录失败', err)
+            }).finally(function() {
+              self.loginLoading = false
+            })
+          } else {
+            uni.showToast({ title: '微信登录失败', icon: 'none' })
+            self.loginLoading = false
+          }
+        },
+        fail: function() {
+          uni.showToast({ title: '微信登录失败', icon: 'none' })
+          self.loginLoading = false
+        }
+      })
+    },
     goTo(url) {
       uni.navigateTo({ url: url })
     },
@@ -130,10 +199,22 @@ export default {
 
 <style scoped>
 .home-page { min-height: 100vh; background: #F5F5F5; padding: 0 32rpx 32rpx; }
-.banner { background: linear-gradient(135deg, #F97316, #EA580C); border-radius: 0 0 32rpx 32rpx; padding: 60rpx 32rpx 48rpx; text-align: center; margin: 0 -32rpx 24rpx; }
+.banner { background: linear-gradient(135deg, #F97316, #EA580C); border-radius: 0 0 32rpx 32rpx; padding: 60rpx 32rpx 48rpx; text-align: center; margin: 0 -32rpx 24rpx; position: relative; }
 .banner-icon { font-size: 72rpx; display: block; margin-bottom: 16rpx; }
 .banner-title { display: block; font-size: 40rpx; font-weight: 700; color: #FFF; margin-bottom: 8rpx; }
-.banner-sub { display: block; font-size: 26rpx; color: rgba(255,255,255,0.85); }
+.banner-sub { display: block; font-size: 26rpx; color: rgba(255,255,255,0.85); margin-bottom: 24rpx; }
+.login-entry-btn { 
+  background: #FFF; 
+  color: #EA580C; 
+  font-size: 24rpx; 
+  font-weight: 600; 
+  border-radius: 100rpx; 
+  padding: 0 32rpx; 
+  height: 64rpx; 
+  line-height: 64rpx; 
+  margin: 0 auto;
+  border: none;
+}
 .status-card { background: #FFF; border-radius: 16rpx; padding: 24rpx 32rpx; margin-bottom: 24rpx; }
 .status-row { display: flex; justify-content: space-between; padding: 14rpx 0; border-bottom: 1rpx solid #F1F5F9; }
 .status-row:last-child { border-bottom: none; }
@@ -148,4 +229,89 @@ export default {
 .nav-item:active { background: #F8FAFC; }
 .nav-icon { font-size: 44rpx; margin-bottom: 8rpx; }
 .nav-text { font-size: 24rpx; color: #1E293B; text-align: center; }
+
+/* Bottom Sheet Styles */
+.login-sheet-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0, 0, 0, 0.5);
+  z-index: 100;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-end;
+  opacity: 0;
+  visibility: hidden;
+  pointer-events: none;
+  transition: opacity 0.3s ease;
+}
+.login-sheet-mask.sheet-open {
+  opacity: 1;
+  visibility: visible;
+  pointer-events: auto;
+}
+.login-sheet-panel {
+  background: #FFF;
+  border-radius: 32rpx 32rpx 0 0;
+  padding-bottom: calc(constant(safe-area-inset-bottom) + 40rpx);
+  width: 100%;
+  transform: translateY(100%);
+  transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
+}
+.login-sheet-mask.sheet-open .login-sheet-panel {
+  transform: translateY(0);
+}
+.sheet-handle {
+  width: 80rpx;
+  height: 8rpx;
+  background: #E2E8F0;
+  border-radius: 4rpx;
+  margin: 24rpx auto;
+}
+.sheet-content {
+  padding: 0 60rpx 40rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.sheet-header {
+  text-align: center;
+  margin-bottom: 48rpx;
+}
+.sheet-title {
+  display: block;
+  font-size: 36rpx;
+  font-weight: 700;
+  color: #1E293B;
+  margin-bottom: 12rpx;
+}
+.sheet-sub {
+  display: block;
+  font-size: 26rpx;
+  color: #64748B;
+}
+.sheet-login-btn {
+  width: 100%;
+  height: 96rpx;
+  line-height: 96rpx;
+  background: linear-gradient(135deg, #F97316, #EA580C);
+  color: #FFF;
+  font-size: 32rpx;
+  font-weight: 600;
+  border-radius: 48rpx;
+  border: none;
+  margin-bottom: 32rpx;
+}
+.sheet-login-btn:active {
+  opacity: 0.9;
+}
+.sheet-footer {
+  text-align: center;
+}
+.sheet-footer-text {
+  font-size: 22rpx;
+  color: #94A3B8;
+}
 </style>

+ 1 - 1
train-frontend/utils/api.js

@@ -21,7 +21,7 @@ function _clearAuthAndRedirect() {
   } catch (e) {}
   uni.showToast({ title: '登录已过期,请重新登录', icon: 'none' })
   setTimeout(function() {
-    uni.reLaunch({ url: '/pages/login/index' })
+    uni.$emit('showLoginSheet', {})
     _redirectingToLogin = false
   }, 1500)
 }