178 lines
6.9 KiB
TypeScript
178 lines
6.9 KiB
TypeScript
import { View, Text, Image, Input, Button } from '@tarojs/components'
|
||
import Taro from '@tarojs/taro'
|
||
import { useState, useEffect, useCallback } from 'react'
|
||
import './index.scss'
|
||
import { useThemeContext } from '../../context/ThemeContext'
|
||
import { useSafeArea } from '../../hooks/useSafeArea'
|
||
import { useStatusBar } from '../../hooks/useStatusBar'
|
||
import ThemedPageMeta from '../../components/ThemedPageMeta'
|
||
import { getUserInfo, setUserInfo, clearUserInfo, getAddressList, getDefaultAddress, type AddressItem } from '../../utils/store'
|
||
|
||
const THEME_OPTIONS: { label: string; value: 'light' | 'dark' | 'auto' }[] = [
|
||
{ label: '浅色模式', value: 'light' },
|
||
{ label: '深色模式', value: 'dark' },
|
||
{ label: '跟随系统', value: 'auto' }
|
||
]
|
||
|
||
const MENU = [
|
||
{ label: '个人信息', icon: '/icon/个人.png', action: (s: any) => s.setShowEdit(true) },
|
||
{ label: '账号管理', icon: '/icon/账号管理.png', action: () => Taro.navigateTo({ url: '/pages/userDatabase/index' }) },
|
||
{ label: '定制协议', icon: '/icon/定制协议.png', action: () => Taro.navigateTo({ url: '/pages/agreement/index' }) },
|
||
{ label: '关于我们', icon: '/icon/关于我们.png', action: () => Taro.showToast({ title: '智绘微刻 v1.0', icon: 'none' }) }
|
||
]
|
||
|
||
export default function SettingsPage() {
|
||
const { theme, setTheme, resolvedTheme } = useThemeContext()
|
||
const safe = useSafeArea()
|
||
useStatusBar(resolvedTheme)
|
||
const [user, setUser] = useState<any>({})
|
||
const [editName, setEditName] = useState('')
|
||
const [editAvatar, setEditAvatar] = useState('')
|
||
const [showEdit, setShowEdit] = useState(false)
|
||
|
||
const loadUser = () => {
|
||
const u = getUserInfo() || {}
|
||
setUser(u)
|
||
setEditName(u.nickName || '')
|
||
setEditAvatar(u.avatarUrl || '')
|
||
}
|
||
|
||
useEffect(() => {
|
||
loadUser()
|
||
}, [])
|
||
|
||
const handleSaveInfo = () => {
|
||
setUserInfo({ ...user, nickName: editName, avatarUrl: editAvatar })
|
||
Taro.showToast({ title: '修改成功', icon: 'success' })
|
||
setShowEdit(false)
|
||
loadUser()
|
||
}
|
||
|
||
const handleLogout = () => {
|
||
Taro.showModal({
|
||
title: '确认退出',
|
||
content: '退出后将清空当前登录状态,确定吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
clearUserInfo()
|
||
Taro.switchTab({ url: '/pages/index/index' })
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const onChooseAvatar = (e: any) => {
|
||
setEditAvatar(e.detail.avatarUrl || '')
|
||
}
|
||
|
||
return (
|
||
<View className={`theme-${resolvedTheme}`} style={{ minHeight: '100vh' }}>
|
||
<ThemedPageMeta />
|
||
<View className='settings-page'>
|
||
<View className='settings-area'>
|
||
|
||
<View className='page-header dashed-card mt-20' style={{ marginTop: `${safe.headerPaddingTop}px` }}>
|
||
<View className='flex-between' style={{ width: '100%' }}>
|
||
<Text className='back-btn' onTap={() => Taro.navigateBack()}>←</Text>
|
||
<Text className='page-title'>设置</Text>
|
||
<View style={{ width: '60px' }} />
|
||
</View>
|
||
</View>
|
||
|
||
{/* 用户卡片 */}
|
||
<View className='settings-user dashed-card mt-20'>
|
||
<View className='flex-between' onTap={() => setShowEdit(true)}>
|
||
<View className='flex-center'>
|
||
{user.avatarUrl ? (
|
||
<Image className='settings-avatar' src={user.avatarUrl} mode='aspectFill' />
|
||
) : (
|
||
<View className='settings-avatar-placeholder'>
|
||
<Image className='settings-avatar-icon' src='/icon/个人.png' mode='aspectFit' />
|
||
</View>
|
||
)}
|
||
<View style={{ marginLeft: '20px' }}>
|
||
<Text className='settings-name'>{user.nickName || '未登录'}</Text>
|
||
<Text className='settings-id'>ID: {user.openid ? user.openid.slice(-8) : '---'}</Text>
|
||
</View>
|
||
</View>
|
||
<Text className='arrow'>›</Text>
|
||
</View>
|
||
</View>
|
||
|
||
{/* 主题设置 */}
|
||
<View className='settings-section dashed-card mt-20'>
|
||
<Text className='section-label'>外观</Text>
|
||
<View className='theme-options'>
|
||
{THEME_OPTIONS.map(opt => (
|
||
<View
|
||
key={opt.value}
|
||
className={`theme-option ${theme === opt.value ? 'active' : ''}`}
|
||
onTap={() => setTheme(opt.value)}
|
||
>
|
||
<Text className='theme-option-text'>{opt.label}</Text>
|
||
{theme === opt.value && <View className='theme-check' />}
|
||
</View>
|
||
))}
|
||
</View>
|
||
{theme === 'auto' && (
|
||
<Text className='theme-hint'>当前跟随系统:{resolvedTheme === 'dark' ? '深色模式' : '浅色模式'}</Text>
|
||
)}
|
||
</View>
|
||
|
||
{/* 菜单列表 */}
|
||
<View className='settings-list dashed-card mt-20'>
|
||
{MENU.map((item, idx) => (
|
||
<View key={idx} className={`settings-item ${idx < MENU.length - 1 ? 'bordered' : ''}`} onTap={() => item.action({ setShowEdit })}>
|
||
<Image className='settings-item-icon-img' src={item.icon} mode='aspectFit' />
|
||
<Text className='settings-item-label'>{item.label}</Text>
|
||
<Text className='arrow'>›</Text>
|
||
</View>
|
||
))}
|
||
</View>
|
||
|
||
{/* 退出登录 */}
|
||
{user?.openid && (
|
||
<View className='mt-20'>
|
||
<View className='btn-outline logout-btn' onTap={handleLogout}>
|
||
<Text>退出登录</Text>
|
||
</View>
|
||
</View>
|
||
)}
|
||
|
||
<View style={{ height: '40px' }} />
|
||
|
||
{/* 编辑弹窗 */}
|
||
{showEdit && (
|
||
<View className='modal-overlay'>
|
||
<View className='modal-card dashed-card'>
|
||
<Text className='modal-title'>修改信息</Text>
|
||
<Button className='avatar-btn' openType='chooseAvatar' onChooseAvatar={onChooseAvatar}>
|
||
{editAvatar ? (
|
||
<Image className='avatar-img' src={editAvatar} mode='aspectFill' />
|
||
) : (
|
||
<Image className='avatar-placeholder-img' src='/icon/个人.png' mode='aspectFit' />
|
||
)}
|
||
</Button>
|
||
<Input
|
||
className='nickname-input'
|
||
placeholder='请输入昵称'
|
||
value={editName}
|
||
onInput={(e: any) => setEditName(e.detail.value)}
|
||
/>
|
||
<View className='form-actions'>
|
||
<View className='btn-outline' onTap={() => setShowEdit(false)}>
|
||
<Text>取消</Text>
|
||
</View>
|
||
<View className='btn-gradient' onTap={handleSaveInfo}>
|
||
<Text>保存</Text>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
)}
|
||
</View>
|
||
</View>
|
||
</View>
|
||
)
|
||
}
|