Allow browsing before mini login
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
export default defineAppConfig({
|
export default defineAppConfig({
|
||||||
pages: [
|
pages: [
|
||||||
|
"pages/device/index",
|
||||||
"pages/login/index",
|
"pages/login/index",
|
||||||
"pages/bind/index",
|
"pages/bind/index",
|
||||||
"pages/device/index",
|
|
||||||
"pages/notification/index",
|
"pages/notification/index",
|
||||||
"pages/chat/index",
|
"pages/chat/index",
|
||||||
"pages/chat/detail/index",
|
"pages/chat/detail/index",
|
||||||
|
|||||||
@@ -25,6 +25,53 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.guest-card {
|
||||||
|
margin: 0 24px;
|
||||||
|
padding: 44px 32px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-card-icon {
|
||||||
|
display: block;
|
||||||
|
font-size: 56px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-card-title {
|
||||||
|
display: block;
|
||||||
|
margin-top: 18px;
|
||||||
|
font-size: 34px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1A1A1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-card-desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 14px;
|
||||||
|
font-size: 26px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-card-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 84px;
|
||||||
|
margin-top: 30px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #07C160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-card-btn-text {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
.conversation-item {
|
.conversation-item {
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export default function Chat() {
|
|||||||
const systemBanner = useSystemBanner()
|
const systemBanner = useSystemBanner()
|
||||||
const [conversations, setConversations] = useState<ChatConversation[]>([])
|
const [conversations, setConversations] = useState<ChatConversation[]>([])
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
|
const [isGuest, setIsGuest] = useState(false)
|
||||||
|
|
||||||
useDidShow(() => {
|
useDidShow(() => {
|
||||||
void loadConversations()
|
void loadConversations()
|
||||||
@@ -17,10 +18,13 @@ export default function Chat() {
|
|||||||
|
|
||||||
const loadConversations = async () => {
|
const loadConversations = async () => {
|
||||||
if (!getToken()) {
|
if (!getToken()) {
|
||||||
Taro.reLaunch({ url: '/pages/login/index' })
|
setConversations([])
|
||||||
|
setIsGuest(true)
|
||||||
|
setLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsGuest(false)
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const data = await getConversations()
|
const data = await getConversations()
|
||||||
@@ -55,13 +59,27 @@ export default function Chat() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleGuestLogin = () => {
|
||||||
|
Taro.setStorageSync('postLoginRedirect', '/pages/chat/index')
|
||||||
|
Taro.navigateTo({ url: '/pages/login/index' })
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className='chat-page'>
|
<View className='chat-page'>
|
||||||
<View className='page-header'>
|
<View className='page-header'>
|
||||||
<Text className='page-title'>玩伴</Text>
|
<Text className='page-title'>玩伴</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{loading ? (
|
{isGuest ? (
|
||||||
|
<View className='guest-card'>
|
||||||
|
<Text className='guest-card-icon'>💬</Text>
|
||||||
|
<Text className='guest-card-title'>亲子互动会话</Text>
|
||||||
|
<Text className='guest-card-desc'>绑定设备后,可以在这里查看孩子、家长和 AI 玩伴之间的消息记录。</Text>
|
||||||
|
<View className='guest-card-btn' onClick={handleGuestLogin}>
|
||||||
|
<Text className='guest-card-btn-text'>登录后查看</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
) : loading ? (
|
||||||
<View className='loading'>
|
<View className='loading'>
|
||||||
<Text>加载中...</Text>
|
<Text>加载中...</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -18,6 +18,119 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.guest-hero {
|
||||||
|
padding: 88px 40px 32px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-device-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 132px;
|
||||||
|
height: 132px;
|
||||||
|
margin: 0 auto 24px;
|
||||||
|
border-radius: 32px;
|
||||||
|
background: #FEF3E8;
|
||||||
|
|
||||||
|
.robot-img {
|
||||||
|
width: 72px;
|
||||||
|
height: 72px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 44px;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1A1A1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-subtitle {
|
||||||
|
display: block;
|
||||||
|
margin-top: 18px;
|
||||||
|
font-size: 28px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-feature-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 18px;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-feature-card {
|
||||||
|
min-height: 204px;
|
||||||
|
padding: 26px 22px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-feature-icon {
|
||||||
|
width: 54px;
|
||||||
|
height: 54px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-feature-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1A1A1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-feature-desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 1.45;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-action-card {
|
||||||
|
margin: 0 24px 24px;
|
||||||
|
padding: 30px 26px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-action-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1A1A1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-action-desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 25px;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-primary-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 88px;
|
||||||
|
margin-top: 24px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #07C160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-primary-btn-text {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
.status-card {
|
.status-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ function formatSleepRange(status: DeviceStatus | null): string {
|
|||||||
return `${start}-${end}`
|
return `${start}-${end}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goLoginWithRedirect(url = '/pages/device/index') {
|
||||||
|
Taro.setStorageSync('postLoginRedirect', url)
|
||||||
|
Taro.navigateTo({ url: '/pages/login/index' })
|
||||||
|
}
|
||||||
|
|
||||||
function formatAlarmTime(value?: string | null): string {
|
function formatAlarmTime(value?: string | null): string {
|
||||||
if (!value) return '--'
|
if (!value) return '--'
|
||||||
const date = new Date(value)
|
const date = new Date(value)
|
||||||
@@ -129,6 +134,7 @@ export default function Device() {
|
|||||||
const [isSavingVolume, setIsSavingVolume] = useState(false)
|
const [isSavingVolume, setIsSavingVolume] = useState(false)
|
||||||
const [sleepWakePending, setSleepWakePending] = useState<'on' | 'off' | null>(null)
|
const [sleepWakePending, setSleepWakePending] = useState<'on' | 'off' | null>(null)
|
||||||
const [volumeValue, setVolumeValue] = useState(0)
|
const [volumeValue, setVolumeValue] = useState(0)
|
||||||
|
const [isGuest, setIsGuest] = useState(false)
|
||||||
const volumeCommandInFlightRef = useRef(false)
|
const volumeCommandInFlightRef = useRef(false)
|
||||||
|
|
||||||
useDidShow(() => {
|
useDidShow(() => {
|
||||||
@@ -137,11 +143,18 @@ export default function Device() {
|
|||||||
|
|
||||||
const loadDeviceInfo = async () => {
|
const loadDeviceInfo = async () => {
|
||||||
if (!getToken()) {
|
if (!getToken()) {
|
||||||
Taro.reLaunch({ url: '/pages/login/index' })
|
setBinding(null)
|
||||||
|
setChild(null)
|
||||||
|
setDeviceStatus(null)
|
||||||
|
setDeviceAlarms([])
|
||||||
|
setVolumeValue(0)
|
||||||
|
setIsGuest(true)
|
||||||
|
setIsLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
|
setIsGuest(false)
|
||||||
try {
|
try {
|
||||||
const context = await loadCurrentChildBindingContext()
|
const context = await loadCurrentChildBindingContext()
|
||||||
setChild(context.currentChild)
|
setChild(context.currentChild)
|
||||||
@@ -264,6 +277,52 @@ export default function Device() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isGuest) {
|
||||||
|
return (
|
||||||
|
<View className='device-page'>
|
||||||
|
<View className='guest-hero'>
|
||||||
|
<View className='guest-device-icon'>
|
||||||
|
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
|
||||||
|
</View>
|
||||||
|
<Text className='guest-title'>伴伴儿童陪伴设备</Text>
|
||||||
|
<Text className='guest-subtitle'>查看设备状态、定位轨迹、亲子消息和休眠管理。浏览功能后,可在需要绑定设备时登录。</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className='guest-feature-grid'>
|
||||||
|
<View className='guest-feature-card'>
|
||||||
|
<Image className='guest-feature-icon' src={require('../../assets/tab-icons/device-icon.png')} mode='aspectFit' />
|
||||||
|
<Text className='guest-feature-title'>设备状态</Text>
|
||||||
|
<Text className='guest-feature-desc'>查看电量、信号、版本和告警记录。</Text>
|
||||||
|
</View>
|
||||||
|
<View className='guest-feature-card'>
|
||||||
|
<Image className='guest-feature-icon' src={require('../../assets/tab-icons/location-icon.png')} mode='aspectFit' />
|
||||||
|
<Text className='guest-feature-title'>定位展示</Text>
|
||||||
|
<Text className='guest-feature-desc'>绑定后可查看设备当前位置。</Text>
|
||||||
|
</View>
|
||||||
|
<View className='guest-feature-card'>
|
||||||
|
<Image className='guest-feature-icon' src={require('../../assets/tab-icons/chat-icon.png')} mode='aspectFit' />
|
||||||
|
<Text className='guest-feature-title'>亲子互动</Text>
|
||||||
|
<Text className='guest-feature-desc'>查看孩子和设备的消息会话。</Text>
|
||||||
|
</View>
|
||||||
|
<View className='guest-feature-card'>
|
||||||
|
<Image className='guest-feature-icon' src={require('../../assets/tab-icons/manage-icon.png')} mode='aspectFit' />
|
||||||
|
<Text className='guest-feature-title'>设备管理</Text>
|
||||||
|
<Text className='guest-feature-desc'>管理孩子资料、绑定设备和休眠设置。</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className='guest-action-card'>
|
||||||
|
<Text className='guest-action-title'>准备绑定或管理设备</Text>
|
||||||
|
<Text className='guest-action-desc'>登录后可创建孩子资料、绑定设备并开启完整功能。</Text>
|
||||||
|
<View className='guest-primary-btn' onClick={() => goLoginWithRedirect('/pages/device/index')}>
|
||||||
|
<Text className='guest-primary-btn-text'>登录后继续</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{systemBanner}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (!child) {
|
if (!child) {
|
||||||
return (
|
return (
|
||||||
<View className='device-page'>
|
<View className='device-page'>
|
||||||
|
|||||||
@@ -56,6 +56,10 @@
|
|||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.guest-map-section {
|
||||||
|
height: 42vh;
|
||||||
|
}
|
||||||
|
|
||||||
.map {
|
.map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ export default function Location() {
|
|||||||
const [emptyState, setEmptyState] = useState<{ title: string; desc: string; actionText: string; actionUrl: string } | null>(
|
const [emptyState, setEmptyState] = useState<{ title: string; desc: string; actionText: string; actionUrl: string } | null>(
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
const [isGuest, setIsGuest] = useState(false)
|
||||||
|
|
||||||
useDidShow(() => {
|
useDidShow(() => {
|
||||||
void loadLocation(true)
|
void loadLocation(true)
|
||||||
@@ -144,10 +145,18 @@ export default function Location() {
|
|||||||
const targetMode = nextMode || trajectoryMode
|
const targetMode = nextMode || trajectoryMode
|
||||||
|
|
||||||
if (!getToken()) {
|
if (!getToken()) {
|
||||||
Taro.reLaunch({ url: '/pages/login/index' })
|
setDeviceLocation(null)
|
||||||
|
setTrajectory([])
|
||||||
|
setSelectedPoint(null)
|
||||||
|
setCoordinates(DEFAULT_COORDINATES)
|
||||||
|
setEmptyState(null)
|
||||||
|
setLocationNotice(null)
|
||||||
|
setIsGuest(true)
|
||||||
|
setLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsGuest(false)
|
||||||
if (showToast) {
|
if (showToast) {
|
||||||
Taro.showLoading({ title: '刷新中...' })
|
Taro.showLoading({ title: '刷新中...' })
|
||||||
}
|
}
|
||||||
@@ -372,7 +381,36 @@ export default function Location() {
|
|||||||
<Text className='page-title'>设备定位</Text>
|
<Text className='page-title'>设备定位</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{emptyState ? (
|
{isGuest ? (
|
||||||
|
<>
|
||||||
|
<View className='map-section guest-map-section'>
|
||||||
|
<Map
|
||||||
|
className='map'
|
||||||
|
latitude={DEFAULT_COORDINATES.latitude}
|
||||||
|
longitude={DEFAULT_COORDINATES.longitude}
|
||||||
|
scale={11}
|
||||||
|
onError={(event) => {
|
||||||
|
console.error('[location] guest map error:', event.detail)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View className='location-empty-shell'>
|
||||||
|
<View className='location-empty-card'>
|
||||||
|
<Text className='location-empty-title'>设备定位与轨迹</Text>
|
||||||
|
<Text className='location-empty-desc'>绑定设备后,可在这里查看孩子设备的位置、更新时间和定位精度。</Text>
|
||||||
|
<View
|
||||||
|
className='location-empty-action'
|
||||||
|
onClick={() => {
|
||||||
|
Taro.setStorageSync('postLoginRedirect', '/pages/location/index')
|
||||||
|
Taro.navigateTo({ url: '/pages/login/index' })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text className='location-empty-action-text'>登录后查看</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
) : emptyState ? (
|
||||||
<View className='location-empty-shell'>
|
<View className='location-empty-shell'>
|
||||||
<View className='location-empty-card'>
|
<View className='location-empty-card'>
|
||||||
<Text className='location-empty-title'>{emptyState.title}</Text>
|
<Text className='location-empty-title'>{emptyState.title}</Text>
|
||||||
|
|||||||
@@ -72,30 +72,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nickname-card {
|
.login-info-card {
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 28px 24px;
|
padding: 28px 24px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
.nickname-label {
|
.login-info-title {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
color: #1A1A1A;
|
color: #1A1A1A;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nickname-input {
|
.login-info-desc {
|
||||||
width: 100%;
|
display: block;
|
||||||
height: 88px;
|
margin-top: 12px;
|
||||||
box-sizing: border-box;
|
font-size: 25px;
|
||||||
padding: 0 24px;
|
line-height: 1.5;
|
||||||
border-radius: 16px;
|
color: #666666;
|
||||||
background: #F5F7FA;
|
|
||||||
font-size: 30px;
|
|
||||||
color: #1A1A1A;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { View, Text, Button, Input, Checkbox, CheckboxGroup } from '@tarojs/components'
|
import { View, Text, Button, Checkbox, CheckboxGroup } from '@tarojs/components'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import { getToken, wechatLogin } from '@/services/auth'
|
import { getToken, wechatLogin } from '@/services/auth'
|
||||||
@@ -6,7 +6,6 @@ import './index.scss'
|
|||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
const [submitting, setSubmitting] = useState(false)
|
const [submitting, setSubmitting] = useState(false)
|
||||||
const [nickname, setNickname] = useState('')
|
|
||||||
const [agreementAccepted, setAgreementAccepted] = useState(false)
|
const [agreementAccepted, setAgreementAccepted] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -21,12 +20,6 @@ export default function Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const cachedUserInfo = (Taro.getStorageSync('userInfo') || {}) as {
|
|
||||||
nickname?: string
|
|
||||||
}
|
|
||||||
if (cachedUserInfo.nickname) {
|
|
||||||
setNickname(cachedUserInfo.nickname)
|
|
||||||
}
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
@@ -39,12 +32,6 @@ export default function Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const cachedUserInfo = (Taro.getStorageSync('userInfo') || {}) as {
|
|
||||||
nickname?: string
|
|
||||||
avatar_url?: string
|
|
||||||
}
|
|
||||||
const normalizedNickname = nickname.trim() || cachedUserInfo.nickname?.trim() || ''
|
|
||||||
|
|
||||||
setSubmitting(true)
|
setSubmitting(true)
|
||||||
Taro.showLoading({ title: '登录中...' })
|
Taro.showLoading({ title: '登录中...' })
|
||||||
|
|
||||||
@@ -56,24 +43,18 @@ export default function Login() {
|
|||||||
|
|
||||||
const session = await wechatLogin({
|
const session = await wechatLogin({
|
||||||
code: loginRes.code,
|
code: loginRes.code,
|
||||||
nickname: normalizedNickname || undefined,
|
|
||||||
avatar_url: cachedUserInfo.avatar_url,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const nextUserInfo = {
|
const nextUserInfo = {
|
||||||
nickname: session.nickname || normalizedNickname,
|
nickname: session.nickname || '',
|
||||||
avatar_url: cachedUserInfo.avatar_url,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextUserInfo.nickname || nextUserInfo.avatar_url) {
|
if (nextUserInfo.nickname) {
|
||||||
Taro.setStorageSync('userInfo', {
|
Taro.setStorageSync('userInfo', {
|
||||||
nickname: nextUserInfo.nickname,
|
nickname: nextUserInfo.nickname,
|
||||||
avatar_url: nextUserInfo.avatar_url,
|
|
||||||
})
|
})
|
||||||
setNickname(nextUserInfo.nickname || '')
|
|
||||||
} else {
|
} else {
|
||||||
Taro.removeStorageSync('userInfo')
|
Taro.removeStorageSync('userInfo')
|
||||||
setNickname('')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Taro.showToast({ title: '登录成功', icon: 'success' })
|
Taro.showToast({ title: '登录成功', icon: 'success' })
|
||||||
@@ -170,22 +151,15 @@ export default function Login() {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View className='nickname-card'>
|
<View className='login-info-card'>
|
||||||
<Text className='nickname-label'>家长昵称</Text>
|
<Text className='login-info-title'>登录后启用设备管理</Text>
|
||||||
<Input
|
<Text className='login-info-desc'>仅在绑定设备、查看定位和管理孩子资料时需要登录。</Text>
|
||||||
className='nickname-input'
|
|
||||||
type='nickname'
|
|
||||||
maxlength={64}
|
|
||||||
placeholder='请输入家长昵称'
|
|
||||||
value={nickname}
|
|
||||||
onInput={(event) => setNickname(event.detail.value)}
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View className='login-btn-wrapper'>
|
<View className='login-btn-wrapper'>
|
||||||
<Button className='login-btn' loading={submitting} disabled={submitting} onClick={handleLogin}>
|
<Button className='login-btn' loading={submitting} disabled={submitting} onClick={handleLogin}>
|
||||||
<Text className='btn-icon'>🌐</Text>
|
<Text className='btn-icon'>🌐</Text>
|
||||||
<Text className='btn-text'>{submitting ? '登录中...' : '微信一键登录'}</Text>
|
<Text className='btn-text'>{submitting ? '登录中...' : '登录后继续'}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,85 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.guest-manage-card {
|
||||||
|
margin: 0 24px 24px;
|
||||||
|
padding: 44px 32px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-icon {
|
||||||
|
display: block;
|
||||||
|
font-size: 58px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-title {
|
||||||
|
display: block;
|
||||||
|
margin-top: 18px;
|
||||||
|
font-size: 34px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1A1A1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 14px;
|
||||||
|
font-size: 26px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 84px;
|
||||||
|
margin-top: 30px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #07C160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-btn-text {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-list {
|
||||||
|
margin: 0 24px 24px;
|
||||||
|
border-radius: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-item {
|
||||||
|
padding: 26px 24px;
|
||||||
|
border-bottom: 1px solid #F0F0F0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-item-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1A1A1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guest-manage-item-desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 25px;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-card {
|
.menu-card {
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ export default function Sleep() {
|
|||||||
const [familyMemberDisplayName, setFamilyMemberDisplayName] = useState('')
|
const [familyMemberDisplayName, setFamilyMemberDisplayName] = useState('')
|
||||||
const [parentInfo, setParentInfo] = useState<Parent | null>(null)
|
const [parentInfo, setParentInfo] = useState<Parent | null>(null)
|
||||||
const [wechatMpStatus, setWechatMpStatus] = useState<WechatMpBindStatus | null>(null)
|
const [wechatMpStatus, setWechatMpStatus] = useState<WechatMpBindStatus | null>(null)
|
||||||
|
const [isGuest, setIsGuest] = useState(false)
|
||||||
const [isLoadingWechatMp, setIsLoadingWechatMp] = useState(false)
|
const [isLoadingWechatMp, setIsLoadingWechatMp] = useState(false)
|
||||||
const [isStartingWechatMpBind, setIsStartingWechatMpBind] = useState(false)
|
const [isStartingWechatMpBind, setIsStartingWechatMpBind] = useState(false)
|
||||||
const [isAuthorizingPhone, setIsAuthorizingPhone] = useState(false)
|
const [isAuthorizingPhone, setIsAuthorizingPhone] = useState(false)
|
||||||
@@ -135,10 +136,23 @@ export default function Sleep() {
|
|||||||
|
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
if (!getToken()) {
|
if (!getToken()) {
|
||||||
Taro.reLaunch({ url: '/pages/login/index' })
|
setChildren([])
|
||||||
|
setBindings([])
|
||||||
|
setBinding(null)
|
||||||
|
setCurrentChild(null)
|
||||||
|
setParentInfo(null)
|
||||||
|
setFirmwareStatus(null)
|
||||||
|
setDeviceRole(null)
|
||||||
|
setRoles([])
|
||||||
|
setCurrentCardGroup(null)
|
||||||
|
setFamilyInfo(null)
|
||||||
|
setWechatMpStatus(null)
|
||||||
|
setIsGuest(true)
|
||||||
|
setLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsGuest(false)
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const context = await loadCurrentChildBindingContext()
|
const context = await loadCurrentChildBindingContext()
|
||||||
@@ -798,7 +812,7 @@ export default function Sleep() {
|
|||||||
clearSelectedBindingDeviceId()
|
clearSelectedBindingDeviceId()
|
||||||
clearSelectedChildId()
|
clearSelectedChildId()
|
||||||
Taro.removeStorageSync('userInfo')
|
Taro.removeStorageSync('userInfo')
|
||||||
Taro.reLaunch({ url: '/pages/login/index' })
|
void loadData()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -951,6 +965,47 @@ export default function Sleep() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isGuest) {
|
||||||
|
return (
|
||||||
|
<View className='manage-page'>
|
||||||
|
<View className='page-header'>
|
||||||
|
<Text className='page-title'>设置与管理</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className='guest-manage-card'>
|
||||||
|
<Text className='guest-manage-icon'>⚙️</Text>
|
||||||
|
<Text className='guest-manage-title'>管理孩子资料和设备</Text>
|
||||||
|
<Text className='guest-manage-desc'>登录后可创建孩子资料、绑定伴伴设备、管理卡片、设置休眠时间和家庭成员。</Text>
|
||||||
|
<View
|
||||||
|
className='guest-manage-btn'
|
||||||
|
onClick={() => {
|
||||||
|
Taro.setStorageSync('postLoginRedirect', '/pages/sleep/index')
|
||||||
|
Taro.navigateTo({ url: '/pages/login/index' })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text className='guest-manage-btn-text'>登录后管理</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className='guest-manage-list'>
|
||||||
|
<View className='guest-manage-item'>
|
||||||
|
<Text className='guest-manage-item-title'>孩子资料</Text>
|
||||||
|
<Text className='guest-manage-item-desc'>为不同孩子维护独立设备和会话。</Text>
|
||||||
|
</View>
|
||||||
|
<View className='guest-manage-item'>
|
||||||
|
<Text className='guest-manage-item-title'>设备绑定</Text>
|
||||||
|
<Text className='guest-manage-item-desc'>扫码或 NFC 绑定伴伴设备。</Text>
|
||||||
|
</View>
|
||||||
|
<View className='guest-manage-item'>
|
||||||
|
<Text className='guest-manage-item-title'>休眠设置</Text>
|
||||||
|
<Text className='guest-manage-item-desc'>设置设备休眠时间和远程控制。</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{systemBanner}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const parentDisplayName = parentInfo?.nickname?.trim() || '家长'
|
const parentDisplayName = parentInfo?.nickname?.trim() || '家长'
|
||||||
const parentPhone = String(parentInfo?.phone || '').trim()
|
const parentPhone = String(parentInfo?.phone || '').trim()
|
||||||
const parentPhoneLabel = parentPhone ? `${parentPhone.slice(0, 3)}****${parentPhone.slice(-4)}` : '未开启'
|
const parentPhoneLabel = parentPhone ? `${parentPhone.slice(0, 3)}****${parentPhone.slice(-4)}` : '未开启'
|
||||||
|
|||||||
Reference in New Issue
Block a user