|
@@ -0,0 +1,340 @@
|
|
|
+<template>
|
|
|
+ <div class="wechat-auth-container">
|
|
|
+ <div class="auth-content">
|
|
|
+ <!-- <div class="logo">
|
|
|
+ <img src="@/assets/images/logo.png" alt="Logo" />
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ <div class="auth-status" v-if="authStatus === 'loading'">
|
|
|
+ <van-loading type="spinner" color="#1989fa" />
|
|
|
+ <p>正在授权中...</p>
|
|
|
+ </div>
|
|
|
+ <!--
|
|
|
+ <div class="auth-status" v-else-if="authStatus === 'success'">
|
|
|
+ <van-icon name="success" color="#07c160" size="48" />
|
|
|
+ <p>授权成功</p>
|
|
|
+ <p class="user-info">{{ userInfo.nickname }}</p>
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ <div class="auth-status" v-else-if="authStatus === 'error'">
|
|
|
+ <van-icon name="cross" color="#ee0a24" size="48" />
|
|
|
+ <p>授权失败</p>
|
|
|
+ <p class="error-message">{{ errorMessage }}</p>
|
|
|
+ <van-button type="primary" @click="retryAuth">重新授权</van-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="auth-status" v-else>
|
|
|
+ <van-icon name="wechat" color="#07c160" size="48" />
|
|
|
+ <p>微信授权</p>
|
|
|
+ <p class="auth-desc">请点击下方按钮进行微信授权</p>
|
|
|
+ <van-button type="primary" @click="startAuth">开始授权</van-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { mapActions } from 'vuex'
|
|
|
+import { wechatAuth, wechatRegister } from '@/api/wechat'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'WechatAuth',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ authStatus: 'init', // init, loading, success, error
|
|
|
+ userInfo: {},
|
|
|
+ errorMessage: '',
|
|
|
+ redirect: '',
|
|
|
+ code: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ // 微信授权配置
|
|
|
+ wechatConfig() {
|
|
|
+ return {
|
|
|
+ appId: 'wxf8a72764a38a40b2',
|
|
|
+ // appId: 'wx3a8dd28881c2c41f',
|
|
|
+ scope: 'snsapi_userinfo', // snsapi_base 或 snsapi_userinfo
|
|
|
+ redirectUri: encodeURIComponent(window.location.origin + '/wechat-auth'),
|
|
|
+ state: 'wechat_auth'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ $route: {
|
|
|
+ handler: function(route) {
|
|
|
+ // 从URL中提取参数,包括#之前的参数
|
|
|
+ const url = window.location.href
|
|
|
+ const urlParams = new URLSearchParams(url.split('?')[1]?.split('#')[0] || '')
|
|
|
+
|
|
|
+ this.code = urlParams.get('code') || route.query.code
|
|
|
+ this.state = urlParams.get('state') || route.query.state
|
|
|
+
|
|
|
+ // redirect参数可能在#之后
|
|
|
+ this.redirect = route.query.redirect || this.extractRedirectFromHash()
|
|
|
+
|
|
|
+ console.log('URL参数解析:', {
|
|
|
+ url: url,
|
|
|
+ code: this.code,
|
|
|
+ state: this.state,
|
|
|
+ redirect: this.redirect,
|
|
|
+ routeQuery: route.query
|
|
|
+ })
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ ...mapActions({
|
|
|
+ login: 'user/login',
|
|
|
+ getInfo: 'user/getInfo'
|
|
|
+ }),
|
|
|
+
|
|
|
+ // 开始微信授权
|
|
|
+ startAuth() {
|
|
|
+ this.authStatus = 'loading'
|
|
|
+
|
|
|
+ // 构建微信授权URL
|
|
|
+ const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.wechatConfig.appId}&redirect_uri=${this.wechatConfig.redirectUri}&response_type=code&scope=${this.wechatConfig.scope}&state=${this.wechatConfig.state}#wechat_redirect`
|
|
|
+
|
|
|
+ // 跳转到微信授权页面
|
|
|
+ window.location.href = authUrl
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理微信授权回调
|
|
|
+ async handleAuthCallback() {
|
|
|
+ if (!this.code) {
|
|
|
+ this.authStatus = 'error'
|
|
|
+ this.errorMessage = '未获取到授权码'
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ this.authStatus = 'loading'
|
|
|
+
|
|
|
+ // 调用后端接口,用code换取access_token和用户信息
|
|
|
+ const result = await this.exchangeCodeForToken(this.code)
|
|
|
+ console.log(result)
|
|
|
+
|
|
|
+ if (result.openid) {
|
|
|
+ this.userInfo = result
|
|
|
+ this.authStatus = 'success'
|
|
|
+ const res = await wechatRegister({
|
|
|
+ username: result.openid,
|
|
|
+ mail: result.openid + '@wechat.com'
|
|
|
+ })
|
|
|
+ console.log(res)
|
|
|
+
|
|
|
+ // console.log(res)
|
|
|
+ const loginData = JSON.stringify({
|
|
|
+ openid: result.openid,
|
|
|
+ edu: true
|
|
|
+ })
|
|
|
+ const myHeaders = new Headers()
|
|
|
+ myHeaders.append('Content-Type', 'application/json')
|
|
|
+ const requestOptionsLogin = {
|
|
|
+ method: 'POST',
|
|
|
+ headers: myHeaders,
|
|
|
+ body: loginData,
|
|
|
+ redirect: 'follow',
|
|
|
+ credentials: 'include'
|
|
|
+ }
|
|
|
+
|
|
|
+ fetch('https://beta.api.cocorobo.cn/api/user', requestOptionsLogin)
|
|
|
+ .then(response => response.text())
|
|
|
+ .then(() => {
|
|
|
+ this.$router.replace('/login')
|
|
|
+ })
|
|
|
+ .catch(error => {
|
|
|
+ console.log('error', error)
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$router.replace('/login')
|
|
|
+ }, 2000)
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ throw new Error(result.message || '授权失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('微信授权失败:', error)
|
|
|
+ this.authStatus = 'error'
|
|
|
+ this.errorMessage = error.message || '授权失败,请重试'
|
|
|
+
|
|
|
+ // 如果授权失败,跳转到登录页面
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$router.replace('/login')
|
|
|
+ }, 2000)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 用code换取access_token和用户信息
|
|
|
+ async exchangeCodeForToken(code) {
|
|
|
+ try {
|
|
|
+ const response = await wechatAuth({
|
|
|
+ code: code,
|
|
|
+ state: this.state
|
|
|
+ })
|
|
|
+
|
|
|
+ // 根据实际API响应格式调整
|
|
|
+ if (response && response.data) {
|
|
|
+ return response.data
|
|
|
+ } else if (response && response.success !== undefined) {
|
|
|
+ return response
|
|
|
+ } else {
|
|
|
+ // 如果API还没有实现,模拟成功响应
|
|
|
+ return {
|
|
|
+ success: true,
|
|
|
+ userInfo: {
|
|
|
+ openid: 'test_openid_' + Date.now(),
|
|
|
+ nickname: '微信用户',
|
|
|
+ headimgurl: '',
|
|
|
+ unionid: 'test_unionid_' + Date.now()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('API调用失败:', error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 跳转到目标页面
|
|
|
+ redirectToTarget() {
|
|
|
+ let targetPath = '/'
|
|
|
+
|
|
|
+ // 使用已解析的redirect参数
|
|
|
+ if (this.redirect) {
|
|
|
+ targetPath = this.redirect
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('跳转到目标页面:', targetPath)
|
|
|
+ this.$router.replace(targetPath)
|
|
|
+ },
|
|
|
+
|
|
|
+ // 重试授权
|
|
|
+ retryAuth() {
|
|
|
+ this.authStatus = 'init'
|
|
|
+ this.errorMessage = ''
|
|
|
+ this.startAuth()
|
|
|
+ },
|
|
|
+
|
|
|
+ // 检查是否在微信浏览器中
|
|
|
+ isWechatBrowser() {
|
|
|
+ const ua = navigator.userAgent.toLowerCase()
|
|
|
+ return ua.indexOf('micromessenger') !== -1
|
|
|
+ },
|
|
|
+
|
|
|
+ // 从URL hash中提取redirect参数
|
|
|
+ extractRedirectFromHash() {
|
|
|
+ const hash = window.location.hash
|
|
|
+ if (hash && hash.includes('redirect=')) {
|
|
|
+ const match = hash.match(/redirect=([^&]+)/)
|
|
|
+ if (match) {
|
|
|
+ return decodeURIComponent(match[1])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ mounted() {
|
|
|
+ // 检查是否在微信浏览器中
|
|
|
+ if (!this.isWechatBrowser()) {
|
|
|
+ this.authStatus = 'error'
|
|
|
+ this.errorMessage = '请在微信中打开此页面'
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果有code参数,说明是从微信授权回调过来的
|
|
|
+ if (this.code) {
|
|
|
+ this.handleAuthCallback()
|
|
|
+ } else {
|
|
|
+ // 没有code参数,开始授权流程
|
|
|
+ this.startAuth()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.wechat-auth-container {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 20px;
|
|
|
+
|
|
|
+ .auth-content {
|
|
|
+ background: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ padding: 40px 30px;
|
|
|
+ text-align: center;
|
|
|
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
|
|
+ max-width: 400px;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .logo {
|
|
|
+ margin-bottom: 30px;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 80px;
|
|
|
+ height: 80px;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .auth-status {
|
|
|
+ .van-loading,
|
|
|
+ .van-icon {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ margin: 10px 0;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #333;
|
|
|
+
|
|
|
+ &.user-info {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.auth-desc {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #999;
|
|
|
+ margin: 15px 0 25px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.error-message {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #ee0a24;
|
|
|
+ margin: 15px 0 25px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .van-button {
|
|
|
+ margin-top: 20px;
|
|
|
+ width: 200px;
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 22px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 响应式设计
|
|
|
+@media (max-width: 480px) {
|
|
|
+ .wechat-auth-container {
|
|
|
+ padding: 10px;
|
|
|
+
|
|
|
+ .auth-content {
|
|
|
+ padding: 30px 20px;
|
|
|
+
|
|
|
+ .auth-status {
|
|
|
+ .van-button {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|