1083 lines
28 KiB
Vue
1083 lines
28 KiB
Vue
<template>
|
||
<view class="login-page">
|
||
<!-- 装饰背景 -->
|
||
<view class="bg-decoration">
|
||
<view class="circle circle-1"></view>
|
||
<view class="circle circle-2"></view>
|
||
<view class="circle circle-3"></view>
|
||
</view>
|
||
|
||
<!-- 主内容区 -->
|
||
<view class="login-container">
|
||
<!-- Logo 和标题 -->
|
||
<view class="header-section">
|
||
<view class="logo-wrapper">
|
||
<image class="logo" src="/static/image/car.png" mode="aspectFit"></image>
|
||
</view>
|
||
<text class="app-name">二手车采集</text>
|
||
<text class="app-desc">欢迎登录,二手车采集平台</text>
|
||
</view>
|
||
|
||
<!-- 登录卡片 -->
|
||
<view class="login-card">
|
||
<!-- 登录方式切换 -->
|
||
<view class="tab-bar">
|
||
<view
|
||
class="tab-item"
|
||
:class="{ active: loginType === 'password' }"
|
||
@tap="switchLoginType('password')"
|
||
>
|
||
<text class="tab-text">账号登录</text>
|
||
<view class="tab-line" v-if="loginType === 'password'"></view>
|
||
</view>
|
||
<view
|
||
class="tab-item"
|
||
:class="{ active: loginType === 'feishu' }"
|
||
@tap="switchLoginType('feishu')"
|
||
>
|
||
<text class="tab-text">飞书登录</text>
|
||
<view class="tab-line" v-if="loginType === 'feishu'"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 账号密码登录表单 -->
|
||
<view v-if="loginType === 'password'" class="form-section">
|
||
<!-- 账号输入框 -->
|
||
<view class="input-group">
|
||
<view class="input-wrapper">
|
||
<uni-icons type="person" size="20" color="#999"></uni-icons>
|
||
<input
|
||
class="input-field"
|
||
type="text"
|
||
placeholder="请输入账号/手机号"
|
||
v-model="formData.account"
|
||
placeholder-class="input-placeholder"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 密码输入框 -->
|
||
<view class="input-group">
|
||
<view class="input-wrapper">
|
||
<uni-icons type="locked" size="20" color="#999"></uni-icons>
|
||
<input
|
||
class="input-field"
|
||
:type="showPassword ? 'text' : 'password'"
|
||
placeholder="请输入密码"
|
||
v-model="formData.password"
|
||
placeholder-class="input-placeholder"
|
||
/>
|
||
<uni-icons
|
||
:type="showPassword ? 'eye' : 'eye-slash'"
|
||
size="20"
|
||
:color="showPassword ? '#2E6CF6' : '#999'"
|
||
@tap="togglePassword"
|
||
></uni-icons>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 记住密码和忘记密码 -->
|
||
<!-- <view class="form-options">
|
||
<view class="remember-me" @tap="toggleRemember">
|
||
<view class="checkbox" :class="{ checked: rememberMe }">
|
||
<uni-icons v-if="rememberMe" type="checkmarkempty" size="14" color="#fff"></uni-icons>
|
||
</view>
|
||
<text class="option-text">记住密码</text>
|
||
</view>
|
||
<text class="forget-pwd" @tap="goToForgetPwd">忘记密码?</text>
|
||
</view> -->
|
||
|
||
<!-- 登录按钮 -->
|
||
<view class="login-btn" :class="{ loading: isLoading }" @tap="handlePasswordLogin">
|
||
<text class="btn-text">{{ isLoading ? '登录中...' : '登录' }}</text>
|
||
<uni-icons v-if="isLoading" type="spinner-cycle" size="18" color="#fff"></uni-icons>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 飞书登录 -->
|
||
<view v-else class="feishu-section">
|
||
<!-- 公司选择 -->
|
||
<view class="input-group">
|
||
<view class="input-wrapper" style="display: flex;align-items: center;gap: 10px;">
|
||
<uni-icons type="home" size="20" color="#999"></uni-icons>
|
||
<picker
|
||
mode="selector"
|
||
:range="companyList"
|
||
range-key="name"
|
||
:value="selectedCompanyIndex"
|
||
@change="onCompanyChange"
|
||
>
|
||
<view class="picker-input">
|
||
<text class="picker-text" :class="{ placeholder: !selectedCompany }">
|
||
{{ selectedCompany ? selectedCompany.name : '请选择公司' }}
|
||
</text>
|
||
<uni-icons type="arrowdown" size="14" color="#999"></uni-icons>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 飞书内环境:自动登录 -->
|
||
<view v-if="isInFeishu && selectedCompany" class="feishu-auto-login">
|
||
<view class="feishu-loading">
|
||
<uni-icons type="spinner-cycle" size="40" color="#2E6CF6"></uni-icons>
|
||
<text class="loading-text">正在跳转飞书授权...</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 非飞书环境:显示二维码 -->
|
||
<view v-else-if="!isInFeishu && selectedCompany" class="feishu-qrcode-section">
|
||
<view class="qrcode-container" id="feishu_qrcode_container">
|
||
<view v-if="sdkLoadFailed" class="sdk-error">
|
||
<text class="error-text">二维码加载失败</text>
|
||
<view class="retry-btn" @tap="reloadFeishuSDK">
|
||
<text>点击重试</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<text class="qrcode-tip">请使用飞书App扫码登录</text>
|
||
</view>
|
||
|
||
<!-- 未选择公司 -->
|
||
<view v-else class="feishu-content">
|
||
<text class="feishu-desc">请先选择公司</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部提示 -->
|
||
<!-- <view class="footer-tip">
|
||
<text class="tip-text">登录即表示同意</text>
|
||
<text class="link-text">《用户协议》</text>
|
||
<text class="tip-text">和</text>
|
||
<text class="link-text">《隐私政策》</text>
|
||
</view> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { request } from '@/api/apiT.js'
|
||
import { saveRoles } from '@/common/role.js'
|
||
import { getVisibleTabBar } from '@/common/tabbar.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
loginType: 'password', // password | feishu
|
||
isLoading: false,
|
||
showPassword: false,
|
||
rememberMe: false,
|
||
fsappid: '',
|
||
// 公司相关
|
||
companyList: [],
|
||
selectedCompany: null,
|
||
selectedCompanyIndex: -1,
|
||
feishuConfig: null,
|
||
// 是否在飞书内环境
|
||
isInFeishu: false,
|
||
// SDK加载状态
|
||
sdkLoadFailed: false,
|
||
formData: {
|
||
account: '',
|
||
password: ''
|
||
}
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
// 检测是否在飞书内环境
|
||
this.isInFeishu = /Lark|Feishu/i.test(navigator.userAgent || '')
|
||
|
||
// 获取飞书 appid
|
||
this.fsappid = options.appid || '';
|
||
uni.setStorageSync('fsappid', this.fsappid);
|
||
|
||
// 保存登录成功后的回跳地址
|
||
const redirect = options.redirect || options.r || ''
|
||
if (redirect) {
|
||
try {
|
||
uni.setStorageSync('post_login_redirect', decodeURIComponent(redirect))
|
||
} catch (e) {
|
||
uni.setStorageSync('post_login_redirect', redirect)
|
||
}
|
||
}
|
||
|
||
// 加载记住的密码
|
||
this.loadRememberedPassword();
|
||
|
||
// 获取公司列表
|
||
this.getCompanyList();
|
||
|
||
// 检查URL参数中的公司ID
|
||
const companyId = options.corp_id
|
||
if (companyId) {
|
||
this.selectCompanyById(Number(companyId))
|
||
}
|
||
|
||
// #ifdef H5
|
||
// 检查SDK初始状态(延迟1秒后检查)
|
||
setTimeout(() => {
|
||
console.log('[飞书登录] 页面加载后SDK状态检查:', {
|
||
typeofQRLogin: typeof window.QRLogin,
|
||
typeofQRLoginGlobal: typeof QRLogin,
|
||
hasWindow: typeof window !== 'undefined',
|
||
windowKeys: Object.keys(window).filter(k => k.includes('QR') || k.includes('Lark'))
|
||
})
|
||
|
||
// 检查脚本标签是否存在
|
||
const scripts = document.querySelectorAll('script')
|
||
const feishuScript = Array.from(scripts).find(s => s.src && s.src.includes('feishu'))
|
||
console.log('[飞书登录] 飞书SDK脚本标签:', {
|
||
found: !!feishuScript,
|
||
src: feishuScript?.src,
|
||
loaded: feishuScript?.onload ? 'has onload' : 'no onload',
|
||
error: feishuScript?.onerror ? 'has onerror' : 'no onerror',
|
||
readyState: feishuScript?.readyState
|
||
})
|
||
|
||
// 如果SDK没加载,尝试动态加载
|
||
if (typeof window.QRLogin === 'undefined') {
|
||
console.log('[飞书登录] SDK未加载,尝试动态加载...')
|
||
this.loadFeishuSDKScript()
|
||
}
|
||
}, 1000)
|
||
// #endif
|
||
},
|
||
methods: {
|
||
// 切换登录方式
|
||
switchLoginType(type) {
|
||
this.loginType = type
|
||
// 切换时清空二维码容器
|
||
// #ifdef H5
|
||
const container = document.getElementById('feishu_qrcode_container')
|
||
if (container) {
|
||
container.innerHTML = ''
|
||
}
|
||
// #endif
|
||
},
|
||
|
||
// 切换密码显示
|
||
togglePassword() {
|
||
this.showPassword = !this.showPassword
|
||
},
|
||
|
||
// 切换记住密码
|
||
toggleRemember() {
|
||
this.rememberMe = !this.rememberMe
|
||
},
|
||
|
||
// 加载记住的密码
|
||
loadRememberedPassword() {
|
||
const remembered = uni.getStorageSync('remembered_password')
|
||
if (remembered) {
|
||
this.formData.account = remembered.account || ''
|
||
this.formData.password = remembered.password || ''
|
||
this.rememberMe = true
|
||
}
|
||
},
|
||
|
||
// 保存记住的密码
|
||
saveRememberedPassword() {
|
||
if (this.rememberMe) {
|
||
uni.setStorageSync('remembered_password', {
|
||
account: this.formData.account,
|
||
password: this.formData.password
|
||
})
|
||
} else {
|
||
uni.removeStorageSync('remembered_password')
|
||
}
|
||
},
|
||
|
||
// 验证表单
|
||
validateForm() {
|
||
if (!this.formData.account) {
|
||
uni.showToast({ title: '请输入账号/手机号', icon: 'none' })
|
||
return false
|
||
}
|
||
if (!this.formData.password) {
|
||
uni.showToast({ title: '请输入密码', icon: 'none' })
|
||
return false
|
||
}
|
||
if (this.formData.password.length < 6) {
|
||
uni.showToast({ title: '密码长度不能少于6位', icon: 'none' })
|
||
return false
|
||
}
|
||
return true
|
||
},
|
||
|
||
// 账号密码登录
|
||
async handlePasswordLogin() {
|
||
if (!this.validateForm()) return
|
||
if (this.isLoading) return
|
||
|
||
this.isLoading = true
|
||
|
||
try {
|
||
const res = await request({
|
||
url: 'common/auth/login',
|
||
method: 'post',
|
||
loginType: 'upwd', // 账号密码登录
|
||
data: {
|
||
account: this.formData.account,
|
||
password: this.formData.password
|
||
}
|
||
})
|
||
|
||
if (res.data.code === 200) {
|
||
const data = res.data.data
|
||
|
||
// 保存登录类型
|
||
uni.setStorageSync('loginType', 'upwd')
|
||
|
||
// 统一使用 union_id 作为 token(与PC端保持一致)
|
||
const token = data.union_id || data.token
|
||
if (token) {
|
||
uni.setStorageSync('token', token)
|
||
}
|
||
|
||
// 处理用户信息
|
||
const userInfo = {
|
||
...data,
|
||
token: token
|
||
}
|
||
uni.setStorageSync('userInfo', userInfo)
|
||
|
||
// 处理角色信息(统一使用 role.js 工具)
|
||
saveRoles(data.role, data.role_wp)
|
||
|
||
// 保存记住的密码
|
||
this.saveRememberedPassword()
|
||
|
||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||
|
||
setTimeout(() => {
|
||
this.goToRedirect()
|
||
}, 1000)
|
||
} else {
|
||
uni.showToast({ title: res.data.message || '登录失败', icon: 'none' })
|
||
}
|
||
} catch (err) {
|
||
console.error('[password login] error:', err)
|
||
uni.showToast({ title: err.message || '登录失败,请稍后重试', icon: 'none' })
|
||
} finally {
|
||
this.isLoading = false
|
||
}
|
||
},
|
||
|
||
// ========== 公司相关方法 ==========
|
||
// 获取公司列表
|
||
async getCompanyList() {
|
||
try {
|
||
const res = await request({
|
||
url: 'common/preset/corps',
|
||
method: 'get'
|
||
})
|
||
if (res.data.code === 200) {
|
||
this.companyList = res.data.data || []
|
||
}
|
||
} catch (err) {
|
||
console.error('[getCompanyList] error:', err)
|
||
}
|
||
},
|
||
|
||
// 公司选择变更
|
||
onCompanyChange(e) {
|
||
const index = e.detail.value
|
||
this.selectedCompanyIndex = index
|
||
this.selectedCompany = this.companyList[index]
|
||
|
||
if (this.selectedCompany) {
|
||
// 保存公司信息
|
||
uni.setStorageSync('companyId', this.selectedCompany.id)
|
||
uni.setStorageSync('companyAbbr', this.selectedCompany.abbr || '')
|
||
|
||
// 构建飞书配置
|
||
this.feishuConfig = {
|
||
...this.selectedCompany,
|
||
app_id: this.selectedCompany.app_id,
|
||
r_url: this.selectedCompany.m_url,
|
||
state: this.selectedCompany.state || 'xinyouhe'
|
||
}
|
||
uni.setStorageSync('fsappid', this.selectedCompany.app_id);
|
||
// 保存 app_id 供回调页面使用
|
||
if (this.feishuConfig.app_id) {
|
||
uni.setStorageSync('fsappid', this.feishuConfig.app_id)
|
||
this.fsappid = this.feishuConfig.app_id
|
||
}
|
||
|
||
// 初始化飞书登录
|
||
this.initFeishuLogin()
|
||
}
|
||
},
|
||
|
||
// 通过ID选择公司
|
||
selectCompanyById(companyId) {
|
||
const index = this.companyList.findIndex(c => c.id === companyId)
|
||
if (index !== -1) {
|
||
this.onCompanyChange({ detail: { value: index } })
|
||
}
|
||
},
|
||
|
||
// 初始化飞书登录
|
||
async initFeishuLogin() {
|
||
if (!this.selectedCompany || !this.feishuConfig) return
|
||
|
||
if (this.isInFeishu) {
|
||
// 飞书内环境,自动跳转授权
|
||
await this.handleFeishuLogin()
|
||
} else {
|
||
// 普通浏览器环境,显示二维码
|
||
await this.loadFeishuQRCode()
|
||
}
|
||
},
|
||
|
||
// 加载飞书二维码
|
||
async loadFeishuQRCode() {
|
||
// #ifdef H5
|
||
console.log('[飞书登录] 开始加载二维码')
|
||
this.sdkLoadFailed = false
|
||
|
||
try {
|
||
// 等待SDK加载完成(已在index.html中预加载)
|
||
await this.waitForFeishuSDK()
|
||
console.log('[飞书登录] SDK加载完成')
|
||
|
||
await this.$nextTick()
|
||
|
||
const container = document.getElementById('feishu_qrcode_container')
|
||
console.log('[飞书登录] 容器:', container)
|
||
if (!container) {
|
||
uni.showToast({ title: '二维码容器未找到', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
container.innerHTML = ''
|
||
|
||
const { app_id, r_url, state } = this.feishuConfig
|
||
console.log('[飞书登录] 飞书配置:', { app_id, r_url, state })
|
||
|
||
if (!app_id || !r_url || !state) {
|
||
uni.showToast({ title: '飞书配置不完整', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
// URL编码
|
||
const encodedRedirectUri = encodeURIComponent(r_url)
|
||
|
||
const gotoUrl = `https://passport.feishu.cn/suite/passport/oauth/authorize?client_id=${app_id}&redirect_uri=${encodedRedirectUri}&response_type=code&state=${state}`
|
||
|
||
// 检查SDK是否加载
|
||
if (typeof window.QRLogin === 'undefined') {
|
||
console.error('[飞书登录] QRLogin 未定义')
|
||
this.sdkLoadFailed = true
|
||
uni.showToast({ title: '飞书SDK未加载,请点击重试', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
console.log('[飞书登录] 开始生成二维码, gotoUrl:', gotoUrl)
|
||
|
||
// 生成二维码(使用 window.QRLogin)
|
||
const QRLoginObj = window.QRLogin({
|
||
id: 'feishu_qrcode_container',
|
||
goto: gotoUrl,
|
||
width: '200',
|
||
height: '200',
|
||
style: 'width:270px;height:270px;border:none'
|
||
})
|
||
console.log('[飞书登录] 二维码生成成功:', QRLoginObj)
|
||
|
||
// 监听扫码消息
|
||
const handleMessage = (event) => {
|
||
console.log('[飞书登录] 收到消息:', event)
|
||
if (
|
||
QRLoginObj.matchOrigin &&
|
||
QRLoginObj.matchData &&
|
||
QRLoginObj.matchOrigin(event.origin) &&
|
||
QRLoginObj.matchData(event.data)
|
||
) {
|
||
const loginTmpCode = event.data.tmp_code
|
||
console.log('[飞书登录] 扫码成功,跳转授权')
|
||
window.location.href = `${gotoUrl}&tmp_code=${loginTmpCode}`
|
||
}
|
||
}
|
||
|
||
window.addEventListener('message', handleMessage, false)
|
||
} catch (error) {
|
||
console.error('[飞书登录] 加载二维码失败:', error)
|
||
this.sdkLoadFailed = true
|
||
uni.showToast({ title: error.message || '二维码加载失败,请重试', icon: 'none' })
|
||
}
|
||
// #endif
|
||
},
|
||
|
||
// 重新加载飞书SDK
|
||
reloadFeishuSDK() {
|
||
// #ifdef H5
|
||
console.log('[飞书登录] 手动重新加载SDK')
|
||
this.sdkLoadFailed = false
|
||
this.loadFeishuSDKScript()
|
||
// #endif
|
||
},
|
||
|
||
// 动态加载飞书SDK脚本
|
||
loadFeishuSDKScript() {
|
||
// #ifdef H5
|
||
// 检查是否已经加载过
|
||
if (typeof window.QRLogin === 'function') {
|
||
console.log('[飞书登录] SDK已加载,无需重复加载')
|
||
if (this.selectedCompany && !this.isInFeishu) {
|
||
this.loadFeishuQRCode()
|
||
}
|
||
return
|
||
}
|
||
|
||
// 检查是否已有正在加载的脚本
|
||
const existingScript = document.querySelector('script[data-feishu-sdk]')
|
||
if (existingScript) {
|
||
console.log('[飞书登录] SDK脚本已在加载中')
|
||
return
|
||
}
|
||
|
||
console.log('[飞书登录] 开始动态加载SDK脚本...')
|
||
const script = document.createElement('script')
|
||
script.setAttribute('data-feishu-sdk', 'true')
|
||
script.src = 'https://lf-package-cn.feishucdn.com/obj/feishu-static/lark/passport/qrcode/LarkSSOSDKWebQRCode-1.0.3.js'
|
||
script.crossOrigin = 'anonymous'
|
||
|
||
script.onload = () => {
|
||
console.log('[飞书登录] ✅ SDK脚本加载成功')
|
||
console.log('[飞书登录] QRLogin类型:', typeof window.QRLogin)
|
||
if (typeof window.QRLogin === 'function') {
|
||
console.log('[飞书登录] SDK已准备就绪')
|
||
// 如果已选择公司且在非飞书环境,加载二维码
|
||
if (this.selectedCompany && !this.isInFeishu) {
|
||
this.loadFeishuQRCode()
|
||
}
|
||
} else {
|
||
console.error('[飞书登录] ⚠️ 脚本加载成功但QRLogin未定义')
|
||
this.sdkLoadFailed = true
|
||
}
|
||
}
|
||
|
||
script.onerror = (event) => {
|
||
console.error('[飞书登录] ❌ SDK脚本加载失败:', event)
|
||
console.error('[飞书登录] 脚本URL:', script.src)
|
||
this.sdkLoadFailed = true
|
||
uni.showToast({ title: 'SDK加载失败,请检查网络', icon: 'none' })
|
||
}
|
||
|
||
script.onabort = () => {
|
||
console.error('[飞书登录] ❌ SDK脚本加载被中断')
|
||
this.sdkLoadFailed = true
|
||
}
|
||
|
||
// 添加到head而不是body
|
||
document.head.appendChild(script)
|
||
console.log('[飞书登录] SDK脚本标签已添加到head')
|
||
// #endif
|
||
},
|
||
|
||
// 等待飞书SDK加载完成(带超时)
|
||
async waitForFeishuSDK() {
|
||
// #ifdef H5
|
||
return new Promise((resolve, reject) => {
|
||
const startTime = Date.now()
|
||
const timeoutMs = 15000 // 15秒超时
|
||
|
||
const timeout = setTimeout(() => {
|
||
const elapsed = Date.now() - startTime
|
||
console.error('[飞书登录] SDK加载超时,等待时间:', elapsed, 'ms')
|
||
console.log('[飞书登录] 当前window上的属性:', Object.keys(window).filter(k => k.includes('QR') || k.includes('qr') || k.includes('Lark')))
|
||
console.log('[飞书登录] window.QRLogin类型:', typeof window.QRLogin)
|
||
console.log('[飞书登录] QRLogin类型:', typeof QRLogin)
|
||
// 检查是否有网络错误
|
||
if (typeof window.QRLogin === 'undefined') {
|
||
console.error('[飞书登录] 请检查网络连接或是否被浏览器扩展阻止')
|
||
}
|
||
this.sdkLoadFailed = true
|
||
uni.showToast({ title: '飞书SDK加载超时,请点击重试', icon: 'none' })
|
||
reject(new Error('飞书SDK加载超时,请刷新页面重试'))
|
||
}, timeoutMs)
|
||
|
||
let count = 0
|
||
const checkInterval = 200 // 每200ms检查一次
|
||
const maxCount = Math.ceil(timeoutMs / checkInterval)
|
||
|
||
const check = () => {
|
||
try {
|
||
count++
|
||
const elapsed = Date.now() - startTime
|
||
|
||
// 每1秒打印一次详细日志
|
||
if (count % 5 === 0) {
|
||
console.log(`[飞书登录] SDK检测 ${count}/${maxCount}, 已等待: ${elapsed}ms, window.QRLogin: ${typeof window.QRLogin}`)
|
||
}
|
||
|
||
// 检查全局对象 window.QRLogin
|
||
if (typeof window.QRLogin === 'function') {
|
||
clearTimeout(timeout)
|
||
console.log('[飞书登录] SDK加载成功,总耗时:', elapsed, 'ms')
|
||
resolve(true)
|
||
} else if (elapsed >= timeoutMs) {
|
||
clearTimeout(timeout)
|
||
reject(new Error('SDK加载超时'))
|
||
} else {
|
||
setTimeout(check, checkInterval)
|
||
}
|
||
} catch (err) {
|
||
console.error('[飞书登录] 检查过程出错:', err)
|
||
clearTimeout(timeout)
|
||
this.sdkLoadFailed = true
|
||
reject(err)
|
||
}
|
||
}
|
||
|
||
// 立即开始检查
|
||
check()
|
||
})
|
||
// #endif
|
||
},
|
||
|
||
// 飞书登录(飞书内环境)
|
||
async handleFeishuLogin() {
|
||
if (!this.feishuConfig) {
|
||
uni.showToast({ title: '请先选择公司', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
try {
|
||
console.log('[飞书内登录] 请求参数:', {
|
||
app_id: this.feishuConfig.app_id,
|
||
config: this.feishuConfig
|
||
})
|
||
|
||
const res = await request({
|
||
url: 'common/auth/feishu/scope',
|
||
method: 'get',
|
||
loginType: 'feishu',
|
||
data: {
|
||
app_id: this.feishuConfig.app_id,
|
||
is_pc:0
|
||
}
|
||
})
|
||
|
||
console.log('[飞书内登录] 接口返回:', res)
|
||
|
||
const auth_url = res?.data?.data?.auth_url
|
||
if (!auth_url) {
|
||
console.error('[飞书内登录] 返回数据结构:', res)
|
||
throw new Error('未获取到授权地址')
|
||
}
|
||
|
||
// H5 环境跳转飞书授权
|
||
// #ifdef H5
|
||
window.location.replace(auth_url)
|
||
// #endif
|
||
} catch (err) {
|
||
console.error('[feishu login] error:', err)
|
||
uni.showToast({ title: err?.message || '跳转失败,请稍后重试', icon: 'none' })
|
||
this.isLoading = false
|
||
}
|
||
},
|
||
|
||
// 忘记密码
|
||
goToForgetPwd() {
|
||
uni.navigateTo({ url: '/pages/index/forget-password' })
|
||
},
|
||
|
||
// 跳转到目标页面(根据角色TabBar显示规则)
|
||
goToRedirect() {
|
||
// 获取用户可见的TabBar列表
|
||
const visibleTabs = getVisibleTabBar()
|
||
// 检查是否包含首页Tab
|
||
const hasIndexTab = visibleTabs.some(tab => tab.pagePath === 'pages/index/index')
|
||
// 默认跳转目标:有首页进入首页,否则进入我的页面
|
||
const defaultTarget = hasIndexTab ? '/pages/index/index' : '/pages/index/mine'
|
||
// 优先使用存储的跳转地址
|
||
const target = uni.getStorageSync('post_login_redirect') || defaultTarget
|
||
uni.removeStorageSync('post_login_redirect')
|
||
uni.reLaunch({ url: target })
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.login-page {
|
||
min-height: 100vh;
|
||
position: relative;
|
||
overflow: hidden;
|
||
background: linear-gradient(180deg, #FF972F 0%, #FF8A2C 25%, #FFF4E8 50%, #F4F6F8 100%);
|
||
}
|
||
|
||
/* 装饰背景 */
|
||
.bg-decoration {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 50vh;
|
||
overflow: hidden;
|
||
|
||
.circle {
|
||
position: absolute;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
animation: float 6s ease-in-out infinite;
|
||
|
||
&.circle-1 {
|
||
width: 400rpx;
|
||
height: 400rpx;
|
||
top: -150rpx;
|
||
left: -100rpx;
|
||
animation-delay: 0s;
|
||
}
|
||
|
||
&.circle-2 {
|
||
width: 300rpx;
|
||
height: 300rpx;
|
||
top: -80rpx;
|
||
right: -80rpx;
|
||
animation-delay: 1s;
|
||
}
|
||
|
||
&.circle-3 {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
top: 100rpx;
|
||
right: 100rpx;
|
||
animation-delay: 2s;
|
||
}
|
||
}
|
||
}
|
||
|
||
@keyframes float {
|
||
0%, 100% {
|
||
transform: translateY(0) scale(1);
|
||
}
|
||
50% {
|
||
transform: translateY(-20rpx) scale(1.05);
|
||
}
|
||
}
|
||
|
||
/* 主容器 */
|
||
.login-container {
|
||
position: relative;
|
||
z-index: 1;
|
||
padding: 40rpx 32rpx;
|
||
min-height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 头部区域 */
|
||
.header-section {
|
||
padding-top: 80rpx;
|
||
padding-bottom: 40rpx;
|
||
text-align: center;
|
||
|
||
.logo-wrapper {
|
||
width: 140rpx;
|
||
height: 140rpx;
|
||
margin: 0 auto 24rpx;
|
||
// background: rgba(255, 255, 255, 0.95);
|
||
border-radius: 32rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 151, 47, 0.25);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
|
||
.logo {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
}
|
||
}
|
||
|
||
.app-name {
|
||
display: block;
|
||
font-size: 40rpx;
|
||
font-weight: 700;
|
||
color: #1f2937;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.app-desc {
|
||
display: block;
|
||
font-size: 26rpx;
|
||
color: #6b7280;
|
||
}
|
||
}
|
||
|
||
/* 登录卡片 */
|
||
.login-card {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
border-radius: 32rpx;
|
||
padding: 40rpx 32rpx;
|
||
box-shadow: 0 16rpx 48rpx rgba(255, 151, 47, 0.12);
|
||
backdrop-filter: blur(20px);
|
||
}
|
||
|
||
/* Tab 切换 */
|
||
.tab-bar {
|
||
display: flex;
|
||
margin-bottom: 40rpx;
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 1px;
|
||
// background: #e5e7eb;
|
||
}
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: 20rpx 0;
|
||
position: relative;
|
||
|
||
.tab-text {
|
||
font-size: 30rpx;
|
||
color: #6b7280;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.tab-line {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 48rpx;
|
||
height: 6rpx;
|
||
background: #FF972F;
|
||
border-radius: 3rpx;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
&.active .tab-text {
|
||
color: #FF972F;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 表单区域 */
|
||
.form-section {
|
||
.input-group {
|
||
margin-bottom: 24rpx;
|
||
|
||
.input-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 24rpx 28rpx;
|
||
background: #F8F9FB;
|
||
border-radius: 16rpx;
|
||
border: 2rpx solid transparent;
|
||
transition: all 0.3s;
|
||
|
||
&:focus-within {
|
||
background: #fff;
|
||
border-color: #FF972F;
|
||
box-shadow: 0 0 0 6rpx rgba(255, 151, 47, 0.08);
|
||
}
|
||
|
||
.input-field {
|
||
flex: 1;
|
||
margin: 0 16rpx;
|
||
font-size: 28rpx;
|
||
color: #1f2937;
|
||
border: none;
|
||
background: none;
|
||
}
|
||
|
||
.input-placeholder {
|
||
color: #9CA3AF;
|
||
}
|
||
}
|
||
}
|
||
|
||
.form-options {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 32rpx;
|
||
|
||
.remember-me {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.checkbox {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
border-radius: 8rpx;
|
||
border: 2rpx solid #d1d5db;
|
||
background: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 12rpx;
|
||
transition: all 0.2s;
|
||
|
||
&.checked {
|
||
background: #FF972F;
|
||
border-color: #FF972F;
|
||
}
|
||
}
|
||
|
||
.option-text {
|
||
font-size: 26rpx;
|
||
color: #6b7280;
|
||
}
|
||
}
|
||
|
||
.forget-pwd {
|
||
font-size: 26rpx;
|
||
color: #FF972F;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 飞书登录区域 */
|
||
.feishu-section {
|
||
padding: 20rpx 0;
|
||
|
||
.feishu-content {
|
||
text-align: center;
|
||
padding: 40rpx 20rpx;
|
||
|
||
.feishu-icon-wrapper {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
margin: 0 auto 24rpx;
|
||
background: linear-gradient(135deg, #FF972F 0%, #FF8A2C 100%);
|
||
border-radius: 28rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 12rpx 32rpx rgba(255, 151, 47, 0.3);
|
||
|
||
.feishu-logo {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
}
|
||
}
|
||
|
||
.feishu-title {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #1f2937;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.feishu-desc {
|
||
display: block;
|
||
font-size: 26rpx;
|
||
color: #6b7280;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 登录按钮 */
|
||
.login-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
background: linear-gradient(135deg, #FF972F 0%, #FF8A2C 100%);
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 12rpx;
|
||
box-shadow: 0 12rpx 32rpx rgba(255, 151, 47, 0.35);
|
||
transition: all 0.3s;
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
box-shadow: 0 8rpx 24rpx rgba(255, 151, 47, 0.25);
|
||
}
|
||
|
||
&.loading {
|
||
opacity: 0.7;
|
||
}
|
||
|
||
// &.feishu-btn {
|
||
// background: linear-gradient(135deg, #3370FF 0%, #2956CC 100%);
|
||
// box-shadow: 0 12rpx 32rpx rgba(51, 112, 255, 0.35);
|
||
|
||
// &:active {
|
||
// box-shadow: 0 8rpx 24rpx rgba(51, 112, 255, 0.25);
|
||
// }
|
||
// }
|
||
|
||
.btn-text {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
/* 底部提示 */
|
||
.footer-tip {
|
||
text-align: center;
|
||
padding-top: 32rpx;
|
||
font-size: 24rpx;
|
||
|
||
.tip-text {
|
||
color: #9CA3AF;
|
||
}
|
||
|
||
.link-text {
|
||
color: #FF972F;
|
||
margin: 0 4rpx;
|
||
}
|
||
}
|
||
|
||
/* 飞书登录新增样式 */
|
||
/* 公司选择下拉框 */
|
||
.picker-input {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
font-size: 28rpx;
|
||
color: #111827;
|
||
min-height: 88rpx;
|
||
}
|
||
|
||
.picker-text {
|
||
flex: 1;
|
||
color: #111827;
|
||
|
||
&.placeholder {
|
||
color: #9CA3AF;
|
||
}
|
||
}
|
||
|
||
/* 飞书内环境自动登录 */
|
||
.feishu-auto-login {
|
||
padding: 60rpx 40rpx;
|
||
text-align: center;
|
||
|
||
.feishu-loading {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
|
||
.loading-text {
|
||
font-size: 28rpx;
|
||
color: #2E6CF6;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 飞书二维码区域 */
|
||
.feishu-qrcode-section{
|
||
text-align: center;
|
||
}
|
||
</style>
|