183 lines
6.1 KiB
TypeScript
183 lines
6.1 KiB
TypeScript
import { View, Text, Button, Checkbox, CheckboxGroup } from '@tarojs/components'
|
|
import { useEffect, useState } from 'react'
|
|
import Taro from '@tarojs/taro'
|
|
import { getToken, wechatLogin } from '@/services/auth'
|
|
import './index.scss'
|
|
|
|
export default function Login() {
|
|
const [submitting, setSubmitting] = useState(false)
|
|
const [agreementAccepted, setAgreementAccepted] = useState(false)
|
|
|
|
useEffect(() => {
|
|
if (getToken()) {
|
|
const redirectUrl = String(Taro.getStorageSync('postLoginRedirect') || '').trim()
|
|
if (redirectUrl) {
|
|
Taro.removeStorageSync('postLoginRedirect')
|
|
Taro.reLaunch({ url: redirectUrl })
|
|
return
|
|
}
|
|
Taro.reLaunch({ url: '/pages/device/index' })
|
|
return
|
|
}
|
|
|
|
}, [])
|
|
|
|
const handleLogin = async () => {
|
|
if (submitting) return
|
|
if (!agreementAccepted) {
|
|
Taro.showToast({
|
|
title: '请先阅读并同意协议',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
setSubmitting(true)
|
|
Taro.showLoading({ title: '登录中...' })
|
|
|
|
try {
|
|
const loginRes = await Taro.login()
|
|
if (!loginRes.code) {
|
|
throw new Error('未获取到微信登录凭证')
|
|
}
|
|
|
|
const session = await wechatLogin({
|
|
code: loginRes.code,
|
|
})
|
|
|
|
const nextUserInfo = {
|
|
nickname: session.nickname || '',
|
|
}
|
|
|
|
if (nextUserInfo.nickname) {
|
|
Taro.setStorageSync('userInfo', {
|
|
nickname: nextUserInfo.nickname,
|
|
})
|
|
} else {
|
|
Taro.removeStorageSync('userInfo')
|
|
}
|
|
|
|
Taro.showToast({ title: '登录成功', icon: 'success' })
|
|
setTimeout(() => {
|
|
const redirectUrl = String(Taro.getStorageSync('postLoginRedirect') || '').trim()
|
|
if (redirectUrl) {
|
|
Taro.removeStorageSync('postLoginRedirect')
|
|
Taro.reLaunch({ url: redirectUrl })
|
|
return
|
|
}
|
|
Taro.reLaunch({ url: '/pages/device/index' })
|
|
}, 300)
|
|
} catch (error: any) {
|
|
console.error('[login] failed:', error)
|
|
const message = String(error?.message || '登录失败,请重试')
|
|
Taro.showModal({
|
|
title: '登录失败',
|
|
content: message,
|
|
showCancel: false,
|
|
})
|
|
} finally {
|
|
Taro.hideLoading()
|
|
setSubmitting(false)
|
|
}
|
|
}
|
|
|
|
const handleAgreementChange = (event) => {
|
|
const values = event.detail.value || []
|
|
setAgreementAccepted(values.includes('accepted'))
|
|
}
|
|
|
|
const openUserAgreement = () => {
|
|
Taro.showModal({
|
|
title: '用户服务协议',
|
|
content: '欢迎使用伴伴。您在使用本小程序前,应阅读并同意本协议。我们将为您提供设备绑定、状态查看、消息互动、定位展示等服务。请您遵守法律法规,不得利用本服务从事违法或侵犯他人权益的行为。',
|
|
showCancel: false,
|
|
confirmText: '我知道了',
|
|
})
|
|
}
|
|
|
|
const openPrivacyPolicy = () => {
|
|
const taroWithPrivacy = Taro as typeof Taro & {
|
|
openPrivacyContract?: (option?: {
|
|
success?: () => void
|
|
fail?: (error: unknown) => void
|
|
}) => void
|
|
}
|
|
|
|
if (typeof taroWithPrivacy.openPrivacyContract === 'function') {
|
|
taroWithPrivacy.openPrivacyContract({
|
|
fail: () => {
|
|
Taro.showModal({
|
|
title: '隐私政策',
|
|
content: '暂时无法打开隐私保护指引,请稍后重试。',
|
|
showCancel: false,
|
|
confirmText: '我知道了',
|
|
})
|
|
},
|
|
})
|
|
return
|
|
}
|
|
|
|
Taro.showModal({
|
|
title: '隐私政策',
|
|
content: '伴伴会在提供设备绑定、消息互动、定位展示等功能时,按需处理您的账号信息、设备信息和位置信息。我们仅在实现相关功能所必需的范围内使用上述信息。',
|
|
showCancel: false,
|
|
confirmText: '我知道了',
|
|
})
|
|
}
|
|
|
|
return (
|
|
<View className='login-page'>
|
|
<View className='login-header'>
|
|
<View className='logo'>
|
|
<Text className='logo-icon'>🤖</Text>
|
|
</View>
|
|
<Text className='title'>伴伴</Text>
|
|
<Text className='subtitle'>让关爱随时随地</Text>
|
|
</View>
|
|
|
|
<View className='login-content'>
|
|
<View className='features'>
|
|
<View className='feature-item'>
|
|
<Text className='feature-icon'>💬</Text>
|
|
<Text className='feature-text'>AI 智能对话</Text>
|
|
</View>
|
|
<View className='feature-item'>
|
|
<Text className='feature-icon'>📍</Text>
|
|
<Text className='feature-text'>实时定位追踪</Text>
|
|
</View>
|
|
<View className='feature-item'>
|
|
<Text className='feature-icon'>🔋</Text>
|
|
<Text className='feature-text'>设备状态监控</Text>
|
|
</View>
|
|
</View>
|
|
|
|
<View className='login-info-card'>
|
|
<Text className='login-info-title'>登录后启用设备管理</Text>
|
|
<Text className='login-info-desc'>仅在绑定设备、查看定位和管理孩子资料时需要登录。</Text>
|
|
</View>
|
|
|
|
<View className='login-btn-wrapper'>
|
|
<Button className='login-btn' loading={submitting} disabled={submitting} onClick={handleLogin}>
|
|
<Text className='btn-icon'>🌐</Text>
|
|
<Text className='btn-text'>{submitting ? '登录中...' : '登录后继续'}</Text>
|
|
</Button>
|
|
</View>
|
|
|
|
<View className='agreement-panel'>
|
|
<CheckboxGroup value={agreementAccepted ? ['accepted'] : []} onChange={handleAgreementChange}>
|
|
<View className='agreement-row'>
|
|
<Checkbox className='agreement-checkbox' value='accepted' checked={agreementAccepted} color='#07C160' />
|
|
<View className='agreement-text-wrap'>
|
|
<Text className='agreement-text'>我已阅读并同意</Text>
|
|
<Text className='agreement-link' onClick={openUserAgreement}>《用户服务协议》</Text>
|
|
<Text className='agreement-text'>和</Text>
|
|
<Text className='agreement-link' onClick={openPrivacyPolicy}>《隐私政策》</Text>
|
|
</View>
|
|
</View>
|
|
</CheckboxGroup>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
)
|
|
}
|