2025-11-14 18:10:59 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="loading-container">
|
|
|
|
|
|
<!-- 背景装饰元素 -->
|
|
|
|
|
|
<view class="bg-decoration">
|
|
|
|
|
|
<view class="bg-circle bg-circle-1"></view>
|
|
|
|
|
|
<view class="bg-circle bg-circle-2"></view>
|
|
|
|
|
|
<view class="bg-circle bg-circle-3"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Loading内容 -->
|
|
|
|
|
|
<view class="loading-content">
|
|
|
|
|
|
<!-- 图标区域 -->
|
|
|
|
|
|
<view class="icon-section">
|
|
|
|
|
|
<view class="icon-wrapper">
|
|
|
|
|
|
<uni-icons type="idcard-filled" size="80" color="#FFFFFF"></uni-icons>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Loading动画 -->
|
|
|
|
|
|
<view class="loading-animation">
|
|
|
|
|
|
<view class="spinner"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 文字内容 -->
|
|
|
|
|
|
<view class="text-section">
|
|
|
|
|
|
<view class="loading-text">登录中,请稍候...</view>
|
|
|
|
|
|
<view class="loading-subtext">正在验证您的社保卡信息</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 进度指示器 -->
|
|
|
|
|
|
<view class="progress-section">
|
|
|
|
|
|
<view class="progress-bar">
|
|
|
|
|
|
<view class="progress-fill"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="progress-text">验证中...</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部信息 -->
|
|
|
|
|
|
<view class="footer">
|
|
|
|
|
|
<view class="footer-text">© 2024 社保就业服务平台</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { inject, onMounted } from 'vue'
|
|
|
|
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
|
|
|
|
import useUserStore from '@/stores/useUserStore'
|
|
|
|
|
|
|
|
|
|
|
|
const { $api } = inject("globalFunction")
|
|
|
|
|
|
const userStore = useUserStore()
|
|
|
|
|
|
|
|
|
|
|
|
// 处理身份证号码登录
|
|
|
|
|
|
const handleIdCardLogin = async (idCard) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 调用身份证号码登录接口
|
|
|
|
|
|
const res = await $api.createRequest('/app/idCardLogin', {
|
|
|
|
|
|
idCard: idCard
|
|
|
|
|
|
}, 'post')
|
|
|
|
|
|
|
|
|
|
|
|
if (res.token) {
|
|
|
|
|
|
// 登录成功,存储token并获取用户信息
|
|
|
|
|
|
await userStore.loginSetToken(res.token)
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户详细信息
|
|
|
|
|
|
await userStore.getUserResume()
|
|
|
|
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '登录成功',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 跳转到首页
|
2025-11-14 19:05:03 +08:00
|
|
|
|
// uni.reLaunch({
|
|
|
|
|
|
// url: '/pages/index/index'
|
|
|
|
|
|
// })
|
2025-11-14 18:10:59 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '登录失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
// 登录失败,返回登录页面
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
|
}, 1500)
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('身份证登录失败:', error)
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: error.msg || '登录失败,请重试',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
// 登录失败,返回登录页面
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
|
}, 1500)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Base64解码
|
|
|
|
|
|
const decodeBase64 = (base64Str) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 在H5环境中使用atob解码
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
return atob(base64Str)
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
// 在小程序环境中使用uni.base64ToArrayBuffer
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
const arrayBuffer = uni.base64ToArrayBuffer(base64Str)
|
|
|
|
|
|
const uint8Array = new Uint8Array(arrayBuffer)
|
|
|
|
|
|
let result = ''
|
|
|
|
|
|
for (let i = 0; i < uint8Array.length; i++) {
|
|
|
|
|
|
result += String.fromCharCode(uint8Array[i])
|
|
|
|
|
|
}
|
|
|
|
|
|
return result
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
// 在App环境中
|
|
|
|
|
|
// #ifdef APP-PLUS
|
|
|
|
|
|
return plus.base64.decode(base64Str)
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('Base64解码失败:', error)
|
|
|
|
|
|
throw new Error('身份证号码解码失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析URL参数
|
|
|
|
|
|
const getUrlParams = (url) => {
|
|
|
|
|
|
const params = {}
|
|
|
|
|
|
const urlObj = new URL(url)
|
|
|
|
|
|
const searchParams = new URLSearchParams(urlObj.search)
|
|
|
|
|
|
for (const [key, value] of searchParams) {
|
|
|
|
|
|
params[key] = value
|
|
|
|
|
|
}
|
|
|
|
|
|
return params
|
|
|
|
|
|
}
|
|
|
|
|
|
onLoad((options) => {
|
|
|
|
|
|
// 处理第三方跳转过来的身份证登录
|
2025-11-14 19:05:03 +08:00
|
|
|
|
if (options.idCard) {
|
2025-11-14 18:10:59 +08:00
|
|
|
|
// 直接通过参数传递
|
2025-11-14 19:05:03 +08:00
|
|
|
|
processIdCardLogin(options.idCard)
|
2025-11-14 18:10:59 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 从当前URL中获取参数
|
|
|
|
|
|
const currentPages = getCurrentPages()
|
|
|
|
|
|
const currentPage = currentPages[currentPages.length - 1]
|
|
|
|
|
|
const url = currentPage.$page.fullPath
|
|
|
|
|
|
const params = getUrlParams(url)
|
|
|
|
|
|
|
2025-11-14 19:05:03 +08:00
|
|
|
|
if (params.idCard) {
|
|
|
|
|
|
processIdCardLogin(params.idCard)
|
2025-11-14 18:10:59 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '缺少身份证号码参数',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
|
}, 1500)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 处理身份证登录流程
|
2025-11-14 19:05:03 +08:00
|
|
|
|
const processIdCardLogin = async (idCard) => {
|
2025-11-14 18:10:59 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 解码Base64身份证号码
|
2025-11-14 19:05:03 +08:00
|
|
|
|
const decodedIdCard = decodeBase64(idCard)
|
2025-11-14 18:10:59 +08:00
|
|
|
|
|
|
|
|
|
|
// 验证身份证号码格式(简单验证)
|
2025-11-14 19:05:03 +08:00
|
|
|
|
if (!decodedIdCard || decodedIdCard.length < 15) {
|
2025-11-14 18:10:59 +08:00
|
|
|
|
throw new Error('身份证号码格式不正确')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用登录接口
|
2025-11-14 19:05:03 +08:00
|
|
|
|
await handleIdCardLogin(decodedIdCard)
|
2025-11-14 18:10:59 +08:00
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('处理身份证登录失败:', error)
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: error.message || '处理身份证信息失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
|
}, 1500)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
// 页面挂载后的逻辑
|
2025-11-14 19:05:03 +08:00
|
|
|
|
// 这里可以添加页面挂载后的其他逻辑
|
2025-11-14 18:10:59 +08:00
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="stylus" scoped>
|
|
|
|
|
|
.loading-container
|
|
|
|
|
|
padding: 0 40rpx
|
|
|
|
|
|
min-height: 100vh
|
|
|
|
|
|
background: linear-gradient(135deg, #4778EC 0%, #256BFA 100%)
|
|
|
|
|
|
position: relative
|
|
|
|
|
|
overflow: hidden
|
|
|
|
|
|
display: flex
|
|
|
|
|
|
flex-direction: column
|
|
|
|
|
|
justify-content: center
|
|
|
|
|
|
align-items: center
|
|
|
|
|
|
|
|
|
|
|
|
.bg-decoration
|
|
|
|
|
|
position: absolute
|
|
|
|
|
|
top: 0
|
|
|
|
|
|
left: 0
|
|
|
|
|
|
width: 100%
|
|
|
|
|
|
height: 100%
|
|
|
|
|
|
pointer-events: none
|
|
|
|
|
|
z-index: 1
|
|
|
|
|
|
|
|
|
|
|
|
.bg-circle
|
|
|
|
|
|
position: absolute
|
|
|
|
|
|
border-radius: 50%
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.1)
|
|
|
|
|
|
|
|
|
|
|
|
.bg-circle-1
|
|
|
|
|
|
width: 400rpx
|
|
|
|
|
|
height: 400rpx
|
|
|
|
|
|
top: -200rpx
|
|
|
|
|
|
right: -100rpx
|
|
|
|
|
|
|
|
|
|
|
|
.bg-circle-2
|
|
|
|
|
|
width: 300rpx
|
|
|
|
|
|
height: 300rpx
|
|
|
|
|
|
bottom: 100rpx
|
|
|
|
|
|
left: -150rpx
|
|
|
|
|
|
|
|
|
|
|
|
.bg-circle-3
|
|
|
|
|
|
width: 200rpx
|
|
|
|
|
|
height: 200rpx
|
|
|
|
|
|
bottom: -50rpx
|
|
|
|
|
|
right: 100rpx
|
|
|
|
|
|
|
|
|
|
|
|
.loading-content
|
|
|
|
|
|
position: relative
|
|
|
|
|
|
z-index: 2
|
|
|
|
|
|
text-align: center
|
|
|
|
|
|
color: #FFFFFF
|
|
|
|
|
|
width: 100%
|
|
|
|
|
|
max-width: 600rpx
|
|
|
|
|
|
|
|
|
|
|
|
.icon-section
|
|
|
|
|
|
margin-bottom: 60rpx
|
|
|
|
|
|
|
|
|
|
|
|
.icon-wrapper
|
|
|
|
|
|
display: inline-flex
|
|
|
|
|
|
align-items: center
|
|
|
|
|
|
justify-content: center
|
|
|
|
|
|
width: 160rpx
|
|
|
|
|
|
height: 160rpx
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.2)
|
|
|
|
|
|
border-radius: 50%
|
|
|
|
|
|
backdrop-filter: blur(10rpx)
|
|
|
|
|
|
border: 2rpx solid rgba(255, 255, 255, 0.3)
|
|
|
|
|
|
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2)
|
|
|
|
|
|
|
|
|
|
|
|
.loading-animation
|
|
|
|
|
|
margin-bottom: 60rpx
|
|
|
|
|
|
|
|
|
|
|
|
.spinner
|
|
|
|
|
|
width: 80rpx
|
|
|
|
|
|
height: 80rpx
|
|
|
|
|
|
margin: 0 auto
|
|
|
|
|
|
border: 6rpx solid rgba(255, 255, 255, 0.3)
|
|
|
|
|
|
border-radius: 50%
|
|
|
|
|
|
border-top: 6rpx solid #FFFFFF
|
|
|
|
|
|
animation: spin 1s linear infinite
|
|
|
|
|
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.2)
|
|
|
|
|
|
|
|
|
|
|
|
.text-section
|
|
|
|
|
|
margin-bottom: 60rpx
|
|
|
|
|
|
|
|
|
|
|
|
.loading-text
|
|
|
|
|
|
font-size: 40rpx
|
|
|
|
|
|
font-weight: 700
|
|
|
|
|
|
margin-bottom: 20rpx
|
|
|
|
|
|
text-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.2)
|
|
|
|
|
|
|
|
|
|
|
|
.loading-subtext
|
|
|
|
|
|
font-size: 30rpx
|
|
|
|
|
|
opacity: 0.9
|
|
|
|
|
|
font-weight: 500
|
|
|
|
|
|
|
|
|
|
|
|
.progress-section
|
|
|
|
|
|
.progress-bar
|
|
|
|
|
|
width: 100%
|
|
|
|
|
|
height: 8rpx
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.3)
|
|
|
|
|
|
border-radius: 4rpx
|
|
|
|
|
|
overflow: hidden
|
|
|
|
|
|
margin-bottom: 20rpx
|
|
|
|
|
|
|
|
|
|
|
|
.progress-fill
|
|
|
|
|
|
width: 60%
|
|
|
|
|
|
height: 100%
|
|
|
|
|
|
background: linear-gradient(90deg, #FFFFFF 0%, rgba(255, 255, 255, 0.8) 100%)
|
|
|
|
|
|
border-radius: 4rpx
|
|
|
|
|
|
animation: progress 2s ease-in-out infinite alternate
|
|
|
|
|
|
|
|
|
|
|
|
.progress-text
|
|
|
|
|
|
font-size: 26rpx
|
|
|
|
|
|
opacity: 0.8
|
|
|
|
|
|
font-weight: 500
|
|
|
|
|
|
|
|
|
|
|
|
.footer
|
|
|
|
|
|
position: absolute
|
|
|
|
|
|
bottom: 40rpx
|
|
|
|
|
|
left: 0
|
|
|
|
|
|
right: 0
|
|
|
|
|
|
text-align: center
|
|
|
|
|
|
z-index: 2
|
|
|
|
|
|
|
|
|
|
|
|
.footer-text
|
|
|
|
|
|
font-size: 24rpx
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.7)
|
|
|
|
|
|
|
|
|
|
|
|
// 动画定义
|
|
|
|
|
|
@keyframes spin
|
|
|
|
|
|
0%
|
|
|
|
|
|
transform: rotate(0deg)
|
|
|
|
|
|
100%
|
|
|
|
|
|
transform: rotate(360deg)
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes progress
|
|
|
|
|
|
0%
|
|
|
|
|
|
width: 30%
|
|
|
|
|
|
transform: translateX(-100%)
|
|
|
|
|
|
50%
|
|
|
|
|
|
width: 60%
|
|
|
|
|
|
100%
|
|
|
|
|
|
width: 30%
|
|
|
|
|
|
transform: translateX(233%)
|
|
|
|
|
|
|
|
|
|
|
|
// 响应式设计
|
|
|
|
|
|
@media (max-width: 750px)
|
|
|
|
|
|
.loading-container
|
|
|
|
|
|
padding: 0 32rpx
|
|
|
|
|
|
|
|
|
|
|
|
.loading-content
|
|
|
|
|
|
max-width: 500rpx
|
|
|
|
|
|
|
|
|
|
|
|
.icon-section
|
|
|
|
|
|
margin-bottom: 40rpx
|
|
|
|
|
|
|
|
|
|
|
|
.icon-wrapper
|
|
|
|
|
|
width: 120rpx
|
|
|
|
|
|
height: 120rpx
|
|
|
|
|
|
|
|
|
|
|
|
.loading-animation
|
|
|
|
|
|
margin-bottom: 40rpx
|
|
|
|
|
|
|
|
|
|
|
|
.text-section
|
|
|
|
|
|
margin-bottom: 40rpx
|
|
|
|
|
|
|
|
|
|
|
|
.loading-text
|
|
|
|
|
|
font-size: 36rpx
|
|
|
|
|
|
|
|
|
|
|
|
.loading-subtext
|
|
|
|
|
|
font-size: 28rpx
|
|
|
|
|
|
|
|
|
|
|
|
.progress-section
|
|
|
|
|
|
.progress-text
|
|
|
|
|
|
font-size: 24rpx
|
|
|
|
|
|
</style>
|