add banbanmini
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationStyle: 'custom'
|
||||
})
|
||||
@@ -0,0 +1,195 @@
|
||||
.bind-page {
|
||||
min-height: 100%;
|
||||
background: #F5F7FA;
|
||||
padding-bottom: 120px;
|
||||
padding-bottom: calc(120px + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(120px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.icon-bg {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&.orange {
|
||||
background: #FFF0E6;
|
||||
}
|
||||
|
||||
.control-icon-img {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.bind-header {
|
||||
padding: 80px 32px 32px;
|
||||
text-align: center;
|
||||
|
||||
.title {
|
||||
font-size: 44px;
|
||||
font-weight: 700;
|
||||
color: #1A1A1A;
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 28px;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
.scan-area {
|
||||
margin: 0 48px 48px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.scan-frame {
|
||||
background: #FFFFFF;
|
||||
border-radius: 24px;
|
||||
padding: 60px 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
|
||||
|
||||
&:active {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.scan-text {
|
||||
font-size: 36px;
|
||||
font-weight: 600;
|
||||
color: #FF8C42;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.scan-hint {
|
||||
font-size: 26px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.scan-corners {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
|
||||
.corner {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-color: #FF8C42;
|
||||
border-style: solid;
|
||||
|
||||
&.top-left {
|
||||
top: -4px;
|
||||
left: -4px;
|
||||
border-width: 6px 0 0 6px;
|
||||
border-radius: 24px 0 0 0;
|
||||
}
|
||||
|
||||
&.top-right {
|
||||
top: -4px;
|
||||
right: -4px;
|
||||
border-width: 6px 6px 0 0;
|
||||
border-radius: 0 24px 0 0;
|
||||
}
|
||||
|
||||
&.bottom-left {
|
||||
bottom: -4px;
|
||||
left: -4px;
|
||||
border-width: 0 0 6px 6px;
|
||||
border-radius: 0 0 0 24px;
|
||||
}
|
||||
|
||||
&.bottom-right {
|
||||
bottom: -4px;
|
||||
right: -4px;
|
||||
border-width: 0 6px 6px 0;
|
||||
border-radius: 0 0 24px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bind-options {
|
||||
margin: 0 48px 48px;
|
||||
|
||||
.option-item {
|
||||
background: #FFFFFF;
|
||||
border-radius: 20px;
|
||||
padding: 28px 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.option-icon {
|
||||
font-size: 36px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.option-text {
|
||||
flex: 1;
|
||||
font-size: 30px;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.option-arrow {
|
||||
font-size: 32px;
|
||||
color: #CCCCCC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bind-tips {
|
||||
margin: 0 48px;
|
||||
|
||||
.tips-title {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
color: #1A1A1A;
|
||||
margin-bottom: 24px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.tip-number {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: #FF8C42;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
color: #FFFFFF;
|
||||
font-weight: 600;
|
||||
margin-right: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
flex: 1;
|
||||
font-size: 28px;
|
||||
color: #666666;
|
||||
line-height: 1.5;
|
||||
padding-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import { View, Text, Button, Image } from '@tarojs/components'
|
||||
import { useState, useEffect } from 'react'
|
||||
import Taro from '@tarojs/taro'
|
||||
import './index.scss'
|
||||
|
||||
export default function Bind() {
|
||||
const [isScanning, setIsScanning] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
// 检查是否已登录
|
||||
const isLoggedIn = Taro.getStorageSync('isLoggedIn')
|
||||
if (!isLoggedIn) {
|
||||
// 未登录,跳转到登录页面
|
||||
Taro.redirectTo({ url: '/pages/login/index' })
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否已绑定设备
|
||||
const hasDevice = Taro.getStorageSync('hasDevice')
|
||||
if (hasDevice) {
|
||||
// 已绑定设备,跳转到首页
|
||||
Taro.reLaunch({ url: '/pages/device/index' })
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleScanCode = () => {
|
||||
setIsScanning(true)
|
||||
|
||||
Taro.scanCode({
|
||||
onlyFromCamera: true,
|
||||
scanType: ['qrCode', 'barCode'],
|
||||
success: (res) => {
|
||||
setIsScanning(false)
|
||||
console.log('扫码结果:', res.result)
|
||||
|
||||
// 模拟绑定设备
|
||||
Taro.showLoading({ title: '绑定中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.hideLoading()
|
||||
|
||||
// 保存设备信息
|
||||
Taro.setStorageSync('hasDevice', true)
|
||||
Taro.setStorageSync('deviceInfo', {
|
||||
id: res.result || 'DEVICE_' + Date.now(),
|
||||
name: '小夏的伴伴',
|
||||
status: 'online',
|
||||
battery: 82,
|
||||
bindTime: new Date().toLocaleString()
|
||||
})
|
||||
|
||||
Taro.showToast({
|
||||
title: '设备绑定成功',
|
||||
icon: 'success',
|
||||
duration: 2000,
|
||||
complete: () => {
|
||||
// 绑定成功,跳转到首页
|
||||
setTimeout(() => {
|
||||
Taro.reLaunch({ url: '/pages/device/index' })
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
}, 1500)
|
||||
},
|
||||
fail: (err) => {
|
||||
setIsScanning(false)
|
||||
console.error('扫码失败:', err)
|
||||
|
||||
// 用户取消扫码,不显示错误
|
||||
if (err.errMsg && err.errMsg.includes('cancel')) {
|
||||
return
|
||||
}
|
||||
|
||||
Taro.showToast({
|
||||
title: '扫码失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleManualInput = () => {
|
||||
Taro.showModal({
|
||||
title: '手动输入设备码',
|
||||
editable: true,
|
||||
placeholderText: '请输入设备底部的设备码',
|
||||
success: (res) => {
|
||||
if (res.confirm && res.content) {
|
||||
// 模拟绑定设备
|
||||
Taro.showLoading({ title: '绑定中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.hideLoading()
|
||||
|
||||
Taro.setStorageSync('hasDevice', true)
|
||||
Taro.setStorageSync('deviceInfo', {
|
||||
id: res.content,
|
||||
name: '小夏的伴伴',
|
||||
status: 'online',
|
||||
battery: 82,
|
||||
bindTime: new Date().toLocaleString()
|
||||
})
|
||||
|
||||
Taro.showToast({
|
||||
title: '设备绑定成功',
|
||||
icon: 'success',
|
||||
duration: 2000,
|
||||
complete: () => {
|
||||
setTimeout(() => {
|
||||
Taro.reLaunch({ url: '/pages/device/index' })
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='bind-page'>
|
||||
<View className='bind-header'>
|
||||
<Text className='title'>绑定设备</Text>
|
||||
<Text className='subtitle'>请扫描设备底部的二维码进行绑定</Text>
|
||||
</View>
|
||||
|
||||
<View className='scan-area'>
|
||||
<View className='scan-frame' onClick={handleScanCode}>
|
||||
<View className='icon-bg orange'>
|
||||
<Image
|
||||
className='control-icon-img'
|
||||
src={require('../../assets/tab-icons/rings.png')}
|
||||
mode='aspectFit'
|
||||
/>
|
||||
</View>
|
||||
<Text className='scan-text'>{isScanning ? '正在扫码...' : '点击扫码'}</Text>
|
||||
<Text className='scan-hint'>请将二维码放入框内</Text>
|
||||
</View>
|
||||
|
||||
<View className='scan-corners'>
|
||||
<View className='corner top-left'></View>
|
||||
<View className='corner top-right'></View>
|
||||
<View className='corner bottom-left'></View>
|
||||
<View className='corner bottom-right'></View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='bind-options'>
|
||||
<View className='option-item' onClick={handleManualInput}>
|
||||
<Text className='option-icon'>⌨️</Text>
|
||||
<Text className='option-text'>手动输入设备码</Text>
|
||||
<Text className='option-arrow'>›</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='bind-tips'>
|
||||
<Text className='tips-title'>绑定帮助</Text>
|
||||
<View className='tip-item'>
|
||||
<Text className='tip-number'>1</Text>
|
||||
<Text className='tip-text'>找到设备底部的二维码或设备码</Text>
|
||||
</View>
|
||||
<View className='tip-item'>
|
||||
<Text className='tip-number'>2</Text>
|
||||
<Text className='tip-text'>点击上方扫码区域进行扫描</Text>
|
||||
</View>
|
||||
<View className='tip-item'>
|
||||
<Text className='tip-number'>3</Text>
|
||||
<Text className='tip-text'>等待绑定成功提示</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user