|
@@ -3,7 +3,12 @@
|
|
|
<view class="bg-shape shadow"></view>
|
|
<view class="bg-shape shadow"></view>
|
|
|
<view class="bg-shape2 shadow"></view>
|
|
<view class="bg-shape2 shadow"></view>
|
|
|
|
|
|
|
|
- <view class="login-box">
|
|
|
|
|
|
|
+ <view v-if="showOAuthLoading" class="loading-box">
|
|
|
|
|
+ <uv-loading-icon color="#3b82f6" size="30"></uv-loading-icon>
|
|
|
|
|
+ <text class="loading-text">正在登录中...</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view v-else class="login-box">
|
|
|
<view class="header">
|
|
<view class="header">
|
|
|
<text class="title">欢迎登录</text>
|
|
<text class="title">欢迎登录</text>
|
|
|
<text class="subtitle">登录科研微信平台</text>
|
|
<text class="subtitle">登录科研微信平台</text>
|
|
@@ -63,7 +68,7 @@
|
|
|
customStyle="height: 100rpx; font-size: 32rpx; font-weight: 600; letter-spacing: 2rpx; box-shadow: 0 10rpx 20rpx rgba(37, 99, 235, 0.3); border: none; margin-top: 20rpx;" />
|
|
customStyle="height: 100rpx; font-size: 32rpx; font-weight: 600; letter-spacing: 2rpx; box-shadow: 0 10rpx 20rpx rgba(37, 99, 235, 0.3); border: none; margin-top: 20rpx;" />
|
|
|
|
|
|
|
|
<!-- 企业微信一键登录 -->
|
|
<!-- 企业微信一键登录 -->
|
|
|
- <view style="margin-top: 30rpx;">
|
|
|
|
|
|
|
+ <!-- <view style="margin-top: 30rpx;">
|
|
|
<uv-button text="企业微信登录" @click="handleEnterpriseLoginClick" :loading="loading" shape="circle" plain
|
|
<uv-button text="企业微信登录" @click="handleEnterpriseLoginClick" :loading="loading" shape="circle" plain
|
|
|
color="#07c160"
|
|
color="#07c160"
|
|
|
customStyle="height: 100rpx; font-size: 30rpx; font-weight: 500; border: 2rpx solid #07c160; color: #07c160;">
|
|
customStyle="height: 100rpx; font-size: 30rpx; font-weight: 500; border: 2rpx solid #07c160; color: #07c160;">
|
|
@@ -71,12 +76,12 @@
|
|
|
<uv-icon name="weixin-fill" size="24" color="#07c160" customStyle="margin-right: 12rpx"></uv-icon>
|
|
<uv-icon name="weixin-fill" size="24" color="#07c160" customStyle="margin-right: 12rpx"></uv-icon>
|
|
|
</template>
|
|
</template>
|
|
|
</uv-button>
|
|
</uv-button>
|
|
|
- </view>
|
|
|
|
|
|
|
+ </view> -->
|
|
|
|
|
|
|
|
- <view class="footer">
|
|
|
|
|
|
|
+ <!-- <view class="footer">
|
|
|
<text class="footer-text">还没有账号?</text>
|
|
<text class="footer-text">还没有账号?</text>
|
|
|
<text class="footer-link" @click="goToRegister">立即注册</text>
|
|
<text class="footer-link" @click="goToRegister">立即注册</text>
|
|
|
- </view>
|
|
|
|
|
|
|
+ </view> -->
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<uv-toast ref="toastRef"></uv-toast>
|
|
<uv-toast ref="toastRef"></uv-toast>
|
|
@@ -93,14 +98,12 @@ import { CACHE_KEY } from '@/constants/index';
|
|
|
import { Local } from '@/utils/storage';
|
|
import { Local } from '@/utils/storage';
|
|
|
import { useLoginApi } from '@/api/system/login';
|
|
import { useLoginApi } from '@/api/system/login';
|
|
|
import { encryptWithBackendConfig } from '@/utils/aesCrypto';
|
|
import { encryptWithBackendConfig } from '@/utils/aesCrypto';
|
|
|
-import { getDingTalkAuthCode } from '@/utils/dingtalk';
|
|
|
|
|
-import * as dd from 'dingtalk-jsapi';
|
|
|
|
|
|
|
|
|
|
const userStore = useUserStore();
|
|
const userStore = useUserStore();
|
|
|
|
|
|
|
|
const { configSetting } = storeToRefs(userStore);
|
|
const { configSetting } = storeToRefs(userStore);
|
|
|
|
|
|
|
|
-const { checkCaptcha, login, dingTalkLogin } = userStore;
|
|
|
|
|
|
|
+const { checkCaptcha, login } = userStore;
|
|
|
|
|
|
|
|
const loginApi = useLoginApi();
|
|
const loginApi = useLoginApi();
|
|
|
|
|
|
|
@@ -117,8 +120,11 @@ const loading = ref(false);
|
|
|
const showPassword = ref(false);
|
|
const showPassword = ref(false);
|
|
|
const rememberMeArr = ref<string[]>([]);
|
|
const rememberMeArr = ref<string[]>([]);
|
|
|
const toastRef = ref<any>(null);
|
|
const toastRef = ref<any>(null);
|
|
|
-// 是否在钉钉环境中
|
|
|
|
|
-const isInDingTalk = ref(dd.env.platform !== 'notInDingTalk');
|
|
|
|
|
|
|
+
|
|
|
|
|
+// 企业微信免登回调通常会在 URL 上带 `code`,进入本页后直接走免登并展示加载态
|
|
|
|
|
+const rawLaunchCode = (uni.getLaunchOptionsSync()?.query as any)?.code as undefined | string | string[];
|
|
|
|
|
+const initialUrlCode = Array.isArray(rawLaunchCode) ? rawLaunchCode[0] : rawLaunchCode;
|
|
|
|
|
+const showOAuthLoading = ref<boolean>(!!initialUrlCode);
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
|
// --- 新增:登录拦截 ---
|
|
// --- 新增:登录拦截 ---
|
|
@@ -126,6 +132,7 @@ onMounted(async () => {
|
|
|
// 不应该停留在当前登录大厅,直接跳走回首页
|
|
// 不应该停留在当前登录大厅,直接跳走回首页
|
|
|
const existingToken = Local.get(CACHE_KEY.TOKEN);
|
|
const existingToken = Local.get(CACHE_KEY.TOKEN);
|
|
|
if (existingToken) {
|
|
if (existingToken) {
|
|
|
|
|
+ showOAuthLoading.value = false;
|
|
|
uni.switchTab({ url: '/pages/home/index' }).catch((err) => {
|
|
uni.switchTab({ url: '/pages/home/index' }).catch((err) => {
|
|
|
console.warn('switchTab failed, trying reLaunch:', err);
|
|
console.warn('switchTab failed, trying reLaunch:', err);
|
|
|
uni.reLaunch({ url: '/pages/home/index' });
|
|
uni.reLaunch({ url: '/pages/home/index' });
|
|
@@ -144,10 +151,8 @@ onMounted(async () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 检测 URL 是否携带 code (企业微信免登)
|
|
// 检测 URL 是否携带 code (企业微信免登)
|
|
|
- const options = uni.getLaunchOptionsSync()?.query;
|
|
|
|
|
- const urlCode = options?.code;
|
|
|
|
|
- if (urlCode) {
|
|
|
|
|
- handleEnterpriseLogin(urlCode);
|
|
|
|
|
|
|
+ if (initialUrlCode) {
|
|
|
|
|
+ await handleEnterpriseLogin(initialUrlCode);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -246,6 +251,10 @@ const handleEnterpriseLogin = async (code: string) => {
|
|
|
message: error.message || '企业快捷登录失败',
|
|
message: error.message || '企业快捷登录失败',
|
|
|
type: 'error'
|
|
type: 'error'
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ // 免登失败后切回手动登录表单
|
|
|
|
|
+ showOAuthLoading.value = false;
|
|
|
|
|
+
|
|
|
// 如果免登失败,正常加载验证码进入手动登录模式
|
|
// 如果免登失败,正常加载验证码进入手动登录模式
|
|
|
await checkCaptcha();
|
|
await checkCaptcha();
|
|
|
if (configSetting.value.isCaptcha === '10') {
|
|
if (configSetting.value.isCaptcha === '10') {
|
|
@@ -284,6 +293,24 @@ const handleEnterpriseLoginClick = () => {
|
|
|
padding: 0 40rpx;
|
|
padding: 0 40rpx;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.loading-box {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ border-radius: 20rpx;
|
|
|
|
|
+ background: #f1f5f9;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ padding: 40rpx 30rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.loading-text {
|
|
|
|
|
+ margin-top: 20rpx;
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #64748b;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.bg-shape {
|
|
.bg-shape {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
top: -100rpx;
|
|
top: -100rpx;
|