<template>
|
<view class="container">
|
<view class="loading-content" v-if="loading">
|
<image class="loading-icon" src="/static/images/loading.gif"></image>
|
<text class="loading-text">正在企业微信免登中...</text>
|
</view>
|
|
<view class="error-content" v-else-if="error">
|
<image class="error-icon" src="/static/images/error.png"></image>
|
<text class="error-text">{{ errorMessage }}</text>
|
<button class="retry-btn" @click="retryLogin">重新尝试</button>
|
</view>
|
|
<view class="success-content" v-else>
|
<image class="success-icon" src="/static/images/success.png"></image>
|
<text class="success-text">企业微信免登成功</text>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import { qyWechatAutoLogin } from "@/api/login";
|
import { buildUrlWithParams } from "@/utils/wechat";
|
|
export default {
|
data() {
|
return {
|
loading: true,
|
error: false,
|
errorMessage: "",
|
// 保存页面参数
|
pageOptions: {},
|
};
|
},
|
|
onLoad(options) {
|
// 添加容错处理
|
try {
|
// 保存页面参数
|
this.pageOptions = options || {};
|
|
// 打印环境信息
|
this.logEnvironmentInfo();
|
|
// 页面加载时执行免登流程
|
this.qyWechatAutoLogin();
|
} catch (e) {
|
console.error('页面加载出错:', e);
|
this.loading = false;
|
this.error = true;
|
this.errorMessage = "页面初始化失败,请重试";
|
}
|
},
|
|
methods: {
|
/**
|
* 打印环境信息(调试用)
|
*/
|
logEnvironmentInfo() {
|
// #ifdef MP-WEIXIN
|
console.log('========== 环境信息 ==========');
|
console.log('wx 是否存在:', typeof wx !== 'undefined');
|
console.log('wx.qy 是否存在:', typeof wx !== 'undefined' && typeof wx.qy !== 'undefined');
|
|
if (typeof wx !== 'undefined') {
|
console.log('wx.login 是否存在:', typeof wx.login === 'function');
|
|
if (typeof wx.qy !== 'undefined') {
|
console.log('wx.qy.login 是否存在:', typeof wx.qy.login === 'function');
|
console.log('wx.qy 对象:', wx.qy);
|
} else {
|
console.warn('⚠️ wx.qy 不存在!');
|
console.warn('可能原因:');
|
console.warn('1. 当前在开发者工具中,wx.qy API 可能不可用');
|
console.warn('2. 需要在真机上调试');
|
console.warn('3. appid 配置可能不正确');
|
}
|
|
// 获取系统信息
|
try {
|
const systemInfo = wx.getSystemInfoSync();
|
console.log('系统信息:', systemInfo);
|
} catch (e) {
|
console.error('获取系统信息失败:', e);
|
}
|
|
// 获取账号信息
|
try {
|
const accountInfo = wx.getAccountInfoSync();
|
console.log('账号信息:', accountInfo);
|
} catch (e) {
|
console.error('获取账号信息失败:', e);
|
}
|
}
|
console.log('==============================');
|
// #endif
|
},
|
|
/**
|
* 企业微信免登流程
|
*/
|
async qyWechatAutoLogin() {
|
try {
|
this.loading = true;
|
this.error = false;
|
|
// #ifdef MP-WEIXIN
|
// 在微信小程序环境中,通过企业微信免登
|
console.log("企业微信小程序环境免登");
|
|
// 直接通过企业微信API获取code,不使用URL中的code
|
const code = await this.getLoginCode();
|
|
if (!code) {
|
throw new Error("无法获取企业微信授权code");
|
}
|
|
// 调用后端接口进行免登
|
const response = await qyWechatAutoLogin(code);
|
|
if (response.code === 200) {
|
// 免登成功,保存token
|
const token = response.data.token;
|
|
this.$store.commit('SET_TOKEN', token)
|
// 必须调用setToken保存到本地存储
|
const { setToken } = require('@/utils/auth')
|
setToken(token)
|
// 获取用户信息
|
await this.$store.dispatch("GetInfo");
|
|
// 跳转到首页或其他指定页面
|
this.redirectAfterLogin();
|
} else {
|
throw new Error(response.msg || "免登失败");
|
}
|
// #endif
|
|
// #ifdef H5
|
// 检查是否在企业微信环境中
|
if (!this.isWxWorkEnvironment()) {
|
throw new Error("请在企业微信客户端中打开");
|
}
|
|
// 获取URL参数中的code
|
let codeH5 = this.getUrlParam("code");
|
|
// 如果URL中没有code,则跳转到企业微信授权页面
|
if (!codeH5) {
|
this.redirectToWxWorkAuth();
|
return;
|
}
|
|
// 调用后端接口进行免登
|
const responseH5 = await qyWechatAutoLogin(codeH5);
|
|
if (responseH5.code === 200) {
|
// 免登成功,保存token
|
const token = responseH5.data.token;
|
this.$store.commit("SET_TOKEN", token);
|
uni.setStorageSync("token", token);
|
|
// 获取用户信息
|
await this.$store.dispatch("GetInfo");
|
|
// 跳转到首页或其他指定页面
|
this.redirectAfterLogin();
|
} else {
|
throw new Error(responseH5.msg || "免登失败");
|
}
|
// #endif
|
|
// #ifndef MP-WEIXIN || H5
|
throw new Error("该功能仅支持在企业微信中使用");
|
// #endif
|
} catch (err) {
|
console.error("企业微信免登失败:", err);
|
this.loading = false;
|
this.error = true;
|
this.errorMessage = err.message || "免登失败,请稍后重试";
|
}
|
},
|
|
/**
|
* 等待 wx.qy 对象初始化
|
*/
|
waitForWxQy(timeout = 5000) {
|
return new Promise((resolve, reject) => {
|
const startTime = Date.now();
|
let checkCount = 0;
|
|
const checkWxQy = () => {
|
checkCount++;
|
const elapsed = Date.now() - startTime;
|
|
if (typeof wx !== 'undefined' && typeof wx.qy !== 'undefined' && typeof wx.qy.login === 'function') {
|
console.log(`✅ wx.qy 已初始化 (耗时: ${elapsed}ms, 检查次数: ${checkCount})`);
|
resolve(true);
|
} else if (elapsed > timeout) {
|
console.error(`❌ 等待 wx.qy 初始化超时 (${timeout}ms)`);
|
console.error('当前状态:', {
|
wx存在: typeof wx !== 'undefined',
|
'wx.qy存在': typeof wx !== 'undefined' && typeof wx.qy !== 'undefined',
|
检查次数: checkCount
|
});
|
|
// 提供更详细的错误信息
|
const errorMsg = '企业微信环境初始化超时。\n\n' +
|
'可能的原因:\n' +
|
'1. 当前在开发者工具中,wx.qy API 不可用\n' +
|
'2. 请使用真机预览或真机调试\n' +
|
'3. 检查小程序 appid 是否配置正确';
|
reject(new Error(errorMsg));
|
} else {
|
if (checkCount % 10 === 1) {
|
console.log(`⏳ 等待 wx.qy 初始化... (${elapsed}ms, 第${checkCount}次检查)`);
|
}
|
setTimeout(checkWxQy, 100);
|
}
|
};
|
|
checkWxQy();
|
});
|
},
|
|
/**
|
* 获取企业微信登录code
|
*/
|
getLoginCode() {
|
return new Promise(async (resolve, reject) => {
|
// #ifdef MP-WEIXIN
|
try {
|
// 检查是否在企业微信小程序环境
|
console.log('检查企业微信环境,wx.qy 是否存在:', typeof wx !== 'undefined' && typeof wx.qy !== 'undefined');
|
|
// 等待 wx.qy 初始化完成
|
await this.waitForWxQy();
|
|
// 使用企业微信小程序API获取code
|
console.log('使用 wx.qy.login 获取code');
|
wx.qy.login({
|
success: (res) => {
|
if (res.code) {
|
console.log("企业微信小程序 ---> code:", res.code);
|
resolve(res.code);
|
} else {
|
reject(new Error("获取code失败:" + (res.errMsg || '未知错误')));
|
}
|
},
|
fail: (err) => {
|
console.error("wx.qy.login调用失败:", err);
|
reject(new Error("企业微信登录接口调用失败:" + (err.errMsg || '未知错误')));
|
},
|
});
|
} catch (error) {
|
console.error('获取登录code异常:', error);
|
reject(error);
|
}
|
// #endif
|
|
// #ifndef MP-WEIXIN
|
resolve(null);
|
// #endif
|
});
|
},
|
|
/**
|
* 检查是否在企业微信环境
|
*/
|
isWxWorkEnvironment() {
|
// #ifdef H5
|
const userAgent = navigator.userAgent.toLowerCase();
|
return userAgent.includes("wxwork");
|
// #endif
|
|
// #ifndef H5
|
return false;
|
// #endif
|
},
|
|
/**
|
* 获取URL参数
|
*/
|
getUrlParam(name) {
|
// #ifdef H5
|
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
|
const r = window.location.search.substr(1).match(reg);
|
if (r != null) return decodeURIComponent(r[2]);
|
// #endif
|
|
// #ifdef MP-WEIXIN
|
// 在小程序中,参数通过onLoad的options传递
|
if (this.pageOptions && this.pageOptions[name]) {
|
return decodeURIComponent(this.pageOptions[name]);
|
}
|
// #endif
|
|
return null;
|
},
|
|
/**
|
* 跳转到企业微信授权页面(H5环境)
|
*/
|
redirectToWxWorkAuth() {
|
// #ifdef H5
|
// 从全局配置中获取企业微信配置
|
const config = getApp().globalData.config;
|
const corpId = config.qyWechatCorpId || "your_corp_id"; // 企业ID
|
const agentId = config.qyWechatAgentId || "your_agent_id"; // 应用ID
|
const redirectUri = encodeURIComponent(window.location.href);
|
const state = Date.now(); // 防重放攻击
|
|
const authUrl = `https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=${corpId}&agentid=${agentId}&redirect_uri=${redirectUri}&state=${state}`;
|
|
window.location.href = authUrl;
|
// #endif
|
},
|
|
/**
|
* 登录成功后的跳转处理
|
*/
|
redirectAfterLogin() {
|
try {
|
// 检查是否有redirect参数指定跳转页面
|
let redirectUrl = this.getUrlParam("redirect");
|
|
// 如果没有redirect参数,检查是否有保存的目标页面
|
if (!redirectUrl) {
|
const { getTargetUrl } = require('@/utils/auth')
|
redirectUrl = getTargetUrl()
|
}
|
|
if (redirectUrl) {
|
// 解码redirect参数
|
redirectUrl = decodeURIComponent(redirectUrl);
|
console.log("自动跳转到指定页面:", redirectUrl);
|
this.$tab.reLaunch(redirectUrl);
|
} else {
|
// 默认跳转到首页
|
console.log("跳转到首页");
|
this.$tab.reLaunch("/pages/index");
|
}
|
} catch (e) {
|
console.error("跳转失败,使用默认跳转:", e);
|
// 出现异常时,默认跳转到首页
|
this.$tab.reLaunch("/pages/index");
|
}
|
},
|
|
/**
|
* 重新尝试登录
|
*/
|
retryLogin() {
|
this.qyWechatAutoLogin();
|
},
|
},
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.container {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
min-height: 100vh;
|
padding: 40rpx;
|
background-color: #f8f8f8;
|
}
|
|
.loading-content,
|
.error-content,
|
.success-content {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
text-align: center;
|
}
|
|
.loading-icon,
|
.error-icon,
|
.success-icon {
|
width: 120rpx;
|
height: 120rpx;
|
margin-bottom: 30rpx;
|
}
|
|
.loading-text,
|
.error-text,
|
.success-text {
|
font-size: 32rpx;
|
color: #333;
|
margin-bottom: 40rpx;
|
}
|
|
.error-text,
|
.success-text {
|
font-weight: bold;
|
}
|
|
.error-text {
|
color: #ff0000;
|
}
|
|
.success-text {
|
color: #00cc00;
|
}
|
|
.retry-btn {
|
width: 80%;
|
height: 80rpx;
|
background-color: #007aff;
|
color: #fff;
|
border-radius: 10rpx;
|
font-size: 32rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
</style>
|