add banbanmini

This commit is contained in:
HycJack
2026-03-24 13:15:03 +08:00
parent 42567b7605
commit 0d0f995dc2
59 changed files with 26319 additions and 0 deletions
@@ -0,0 +1,3 @@
export default definePageConfig({
navigationStyle: 'custom'
})
+195
View File
@@ -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;
}
}
}
+173
View File
@@ -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>
)
}