Jelajahi Sumber

feat(miniapp): 新增扫码登录落地页 scan-login 与 wechatWebScan 接口封装

liaoxg 23 jam lalu
induk
melakukan
f17b588b7e

+ 6 - 0
cfc-frontend/pages.json

@@ -1781,6 +1781,12 @@
             "navigationBarTitleText": "登录",
             "navigationStyle": "custom"
           }
+        },
+        {
+          "path": "scan-login",
+          "style": {
+            "navigationBarTitleText": "扫码登录"
+          }
         }
       ]
     },

+ 172 - 0
cfc-frontend/pages/login/scan-login.vue

@@ -0,0 +1,172 @@
+<template>
+  <view class="page">
+    <view class="card">
+      <view class="icon">{{ icon }}</view>
+      <text class="title">{{ title }}</text>
+      <text class="desc">{{ desc }}</text>
+
+      <button
+        v-if="status === 'needlogin'"
+        class="btn btn-primary"
+        @tap="goLogin"
+      >微信一键登录</button>
+
+      <button
+        v-if="status === 'error'"
+        class="btn btn-primary"
+        @tap="tryScan"
+      >重试</button>
+
+      <button
+        v-if="status === 'success'"
+        class="btn btn-primary"
+        @tap="goHome"
+      >进入小程序首页</button>
+    </view>
+  </view>
+</template>
+
+<script>
+import { wechatWebScan } from '@/utils/api.js'
+
+export default {
+  data() {
+    return {
+      state: '',
+      status: 'loading', // loading / success / needlogin / error
+      message: ''
+    }
+  },
+  computed: {
+    icon() {
+      if (this.status === 'success') return '✅'
+      if (this.status === 'error') return '❌'
+      if (this.status === 'needlogin') return '🔑'
+      return '⏳'
+    },
+    title() {
+      if (this.status === 'success') return '登录成功'
+      if (this.status === 'error') return '登录失败'
+      if (this.status === 'needlogin') return '需要先登录'
+      return '正在确认登录…'
+    },
+    desc() {
+      if (this.status === 'success') return '已与电脑端同步登录,请返回电脑端客户端继续'
+      if (this.status === 'error') return this.message || '二维码无效或已过期,请在电脑端重新获取'
+      if (this.status === 'needlogin') return '请先登录小程序,登录后将自动完成电脑端登录'
+      return '请稍候'
+    }
+  },
+  onLoad(query) {
+    this._onLoadFired = true
+    query = query || {}
+    var state = query.state || ''
+    if (!state && query.scene) {
+      // 小程序码 scene 为 URL 编码串
+      try {
+        state = decodeURIComponent(query.scene)
+      } catch (e) {
+        state = query.scene
+      }
+    }
+    this.state = state || ''
+    this.tryScan()
+  },
+  onShow() {
+    // 首次进入:onLoad 已处理;从登录页返回时重新尝试
+    if (this._onLoadFired) {
+      this._onLoadFired = false
+      return
+    }
+    if (this.state && this.status !== 'success') {
+      this.tryScan()
+    }
+  },
+  methods: {
+    tryScan() {
+      if (!this.state) {
+        this.status = 'error'
+        this.message = '二维码缺少参数,请在电脑端重新获取'
+        return
+      }
+      var token = uni.getStorageSync('token')
+      if (!token) {
+        this.status = 'needlogin'
+        return
+      }
+      this.status = 'loading'
+      var self = this
+      wechatWebScan(this.state).then(function (res) {
+        if (res && res.code === 200) {
+          self.status = 'success'
+        } else {
+          self.status = 'error'
+          self.message = (res && res.message) || '登录失败'
+        }
+      }).catch(function (e) {
+        self.status = 'error'
+        self.message = (e && e.message) || '网络异常,请重试'
+      })
+    },
+    goLogin() {
+      uni.navigateTo({ url: '/pages/login/login' })
+    },
+    goHome() {
+      uni.switchTab({ url: '/pages/index/index' })
+    }
+  }
+}
+</script>
+
+<style scoped>
+.page {
+  padding: 40rpx;
+  min-height: 100vh;
+  background: linear-gradient(135deg, #FFF7ED 0%, #FEF3C7 100%);
+  display: flex;
+  align-items: flex-start;
+  justify-content: center;
+}
+.card {
+  width: 100%;
+  max-width: 600rpx;
+  margin-top: 16vh;
+  background: #FFFFFF;
+  border-radius: 24rpx;
+  padding: 60rpx 40rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
+}
+.icon {
+  font-size: 96rpx;
+  margin-bottom: 24rpx;
+}
+.title {
+  font-size: 36rpx;
+  font-weight: 700;
+  color: #1E293B;
+  margin-bottom: 16rpx;
+}
+.desc {
+  font-size: 28rpx;
+  color: #64748B;
+  text-align: center;
+  line-height: 1.6;
+  margin-bottom: 40rpx;
+}
+.btn {
+  width: 100%;
+  padding: 28rpx;
+  border-radius: 16rpx;
+  font-size: 30rpx;
+  font-weight: 600;
+  text-align: center;
+  border: none;
+}
+.btn-primary {
+  background: linear-gradient(135deg, #F97316, #EA580C);
+  color: #FFFFFF;
+}
+</style>

+ 5 - 0
cfc-frontend/utils/api.js

@@ -368,6 +368,11 @@ export const phoneLogin = (data) => {
   return request('/api/auth/phone-login', 'POST', data)
 }
 
+// 桌面端「小程序码」扫码登录:小程序端确认登录(携带小程序 JWT,后端据此写 state=U{userId})
+export const wechatWebScan = (state) => {
+  return request('/api/auth/wechat-web/scan', 'POST', { state: state })
+}
+
 //  街道地址相关 
 
 // 获取所有省份