Files
art-design-uniapp/pages/login/index.vue
T
2026-02-06 14:39:37 +08:00

213 lines
5.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="auth-page">
<view class="auth-card">
<!-- 这里如果你有站点 logo,可替换为自己的路径;没有也不影响 -->
<!-- <image class="logo" src="/static/logo.png" mode="heightFix"></image> -->
<view class="spinner"></view>
<view class="text-wrap">
<text class="title">{{ title }}</text>
<text class="desc">{{ desc }}<text class="dots">{{ dots }}</text></text>
</view>
<view class="progress">
<view class="bar"></view>
</view>
</view>
</view>
</template>
<script>
import { request, showToast } from '@/api/apiT.js'
export default {
data() {
return {
corp_abbr: '',
corp_id: '',
title: '正在为你登录',
desc: '加载中',
dots: '',
_dotTimer: null,
// 最短停留时间,避免“闪一下就跳”的割裂感
minStayMs: 600,
_startedAt: 0
}
},
onLoad(options) {
this.corp_abbr = options.corp_abbr || '';
this.corp_id = options.corp_id || '';
uni.setStorageSync('corp_abbr', this.corp_abbr);
uni.setStorageSync('corp_id', this.corp_id);
// uni.setStorageSync('token', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmZGVzay5obnhpbnlvdWhlLmNvbSIsImp0aSI6ImEwNzFlYTE1ODQ1NWNmYzA1YTkyOTgxOWUxNzQwNTJkIiwic3ViIjoidXNlcl8xIiwiYXVkIjoiZmRlc2siLCJpYXQiOjE3Njc2NjM0MTcsIm5iZiI6MTc2NzY2MzQxNywiZXhwIjoxNzcwMjU1NDE3LCJ0eXAiOiJhY2Nlc3MiLCJ1aWQiOjEsInVuYW1lIjoiXHU2NzRlXHU0ZjczXHU1MzVhIiwicm9sZV9pZHMiOlsxLDIsNF0sInN5c3RlbV9pZHMiOlsxLDIsM119.vyhbWUVIvEF4VGv1hHi3-4cja9r8q7K8dhSW1ejhKgk')
// console.log(uni.getStorageSync('token'))
this._startedAt = Date.now()
this.startDots()
this.silentAuth()
},
onUnload() {
this.stopDots()
},
methods: {
startDots() {
this.stopDots()
let n = 0
this._dotTimer = setInterval(() => {
n = (n + 1) % 4
this.dots = '.'.repeat(n)
}, 350)
},
stopDots() {
if (this._dotTimer) {
clearInterval(this._dotTimer)
this._dotTimer = null
}
},
async silentAuth() {
try {
// 1) 如果本地已有 token,直接进首页(丝滑)
const token = uni.getStorageSync('token')
if (token) {
this.title = '已登录'
this.desc = '正在进入首页'
return this.goHomeSmooth()
}
// 2) 获取飞书授权跳转地址(静默授权/免登)
this.title = '正在跳转飞书授权'
this.desc = '准备中'
const res = await request({
url: 'common/auth/feishu/scope',
method: 'get',
data:{is_mob:1}
})
const auth_url = res?.data?.data?.auth_url
if (!auth_url) {
throw new Error('未获取到授权地址')
}
// 3) 给一点点过渡时间,让动画先跑起来再跳转
await this.sleep(180)
// 仅 H5 才能用 window.location
// #ifdef H5
window.location.replace(auth_url)
// #endif
// #ifndef H5
showToast && showToast('仅 H5 环境支持飞书静默授权')
// #endif
} catch (err) {
console.error('[feishu silentAuth] error:', err)
uni.showToast({ title: err?.message || '登录失败', icon: 'none' })
}
},
goHomeSmooth() {
const elapsed = Date.now() - this._startedAt
const wait = Math.max(0, this.minStayMs - elapsed)
setTimeout(() => {
uni.reLaunch({
url: '/pages/index/index'
})
}, wait)
},
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
}
}
</script>
<style scoped lang="scss">
.auth-page {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40rpx;
box-sizing: border-box;
/* 更“高级”的登录背景 */
background: linear-gradient(180deg, #3074F7 0%, #F4F6F8 38%, #F4F6F8 100%);
}
.auth-card {
width: 100%;
max-width: 640rpx;
background: rgba(255, 255, 255, 0.92);
border-radius: 20rpx;
padding: 44rpx 36rpx 32rpx;
box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
align-items: center;
backdrop-filter: blur(10px);
}
.logo {
height: 72rpx;
margin-bottom: 26rpx;
}
.spinner {
width: 88rpx;
height: 88rpx;
border-radius: 50%;
border: 8rpx solid rgba(48, 116, 247, 0.18);
border-top-color: rgba(48, 116, 247, 1);
animation: spin 0.9s linear infinite;
margin-bottom: 24rpx;
}
.text-wrap {
text-align: center;
}
.title {
display: block;
font-size: 34rpx;
color: #1f2937;
font-weight: 600;
margin-bottom: 8rpx;
}
.desc {
display: block;
font-size: 26rpx;
color: #6b7280;
}
.dots {
display: inline-block;
width: 40rpx; /* 固定宽度避免文字抖动 */
text-align: left;
}
.progress {
width: 100%;
height: 10rpx;
border-radius: 999rpx;
background: rgba(48, 116, 247, 0.10);
overflow: hidden;
margin-top: 26rpx;
}
.progress .bar {
height: 100%;
width: 40%;
border-radius: 999rpx;
background: rgba(48, 116, 247, 0.55);
animation: move 1.1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes move {
0% { transform: translateX(-60%); }
50% { transform: translateX(140%); }
100% { transform: translateX(-60%); }
}
</style>