refactor(user-profile): 调整个人信息页面布局优化结构
- 调整用户ID位置至头像之上以强化信息层次 - 统一并优化代码格式排版,提升代码可读性 - 合并重复的用户ID展示,避免冗余 - 保持功能一致,未改动交互逻辑 - 优化注释及空白行,代码风格更规范
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, {useState, useEffect} from 'react'
|
||||||
import { View, Text, Image, Input, Button as TaroButton } from '@tarojs/components'
|
import {View, Text, Image, Input, Button as TaroButton} from '@tarojs/components'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import BottomButton from '@/components/common/BottomButton'
|
import BottomButton from '@/components/common/BottomButton'
|
||||||
import { useUser } from '@/hooks/useUser'
|
import {useUser} from '@/hooks/useUser'
|
||||||
import { updateUser } from '@/api/system/user'
|
import {updateUser} from '@/api/system/user'
|
||||||
import type { User } from '@/api/system/user/model'
|
import type {User} from '@/api/system/user/model'
|
||||||
import { TenantId } from '@/config/app'
|
import {TenantId} from '@/config/app'
|
||||||
|
|
||||||
definePageConfig({
|
definePageConfig({
|
||||||
navigationBarTitleText: '个人信息',
|
navigationBarTitleText: '个人信息',
|
||||||
@@ -14,7 +14,7 @@ definePageConfig({
|
|||||||
const genderOptions = ['保密', '男', '女']
|
const genderOptions = ['保密', '男', '女']
|
||||||
|
|
||||||
const ProfilePage: React.FC = () => {
|
const ProfilePage: React.FC = () => {
|
||||||
const { user, refreshUser } = useUser()
|
const {user, refreshUser} = useUser()
|
||||||
const [form, setForm] = useState<Partial<User>>({})
|
const [form, setForm] = useState<Partial<User>>({})
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [showGenderSheet, setShowGenderSheet] = useState(false)
|
const [showGenderSheet, setShowGenderSheet] = useState(false)
|
||||||
@@ -35,9 +35,9 @@ const ProfilePage: React.FC = () => {
|
|||||||
|
|
||||||
// 微信头像选择回调(open-type="chooseAvatar")
|
// 微信头像选择回调(open-type="chooseAvatar")
|
||||||
const handleWechatAvatar = (e: any) => {
|
const handleWechatAvatar = (e: any) => {
|
||||||
const { avatarUrl } = e.detail
|
const {avatarUrl} = e.detail
|
||||||
if (!avatarUrl) return
|
if (!avatarUrl) return
|
||||||
Taro.showLoading({ title: '上传中...' })
|
Taro.showLoading({title: '上传中...'})
|
||||||
Taro.uploadFile({
|
Taro.uploadFile({
|
||||||
url: 'https://server.websoft.top/api/oss/upload',
|
url: 'https://server.websoft.top/api/oss/upload',
|
||||||
filePath: avatarUrl,
|
filePath: avatarUrl,
|
||||||
@@ -49,14 +49,14 @@ const ProfilePage: React.FC = () => {
|
|||||||
success: (uploadRes) => {
|
success: (uploadRes) => {
|
||||||
const data = JSON.parse(uploadRes.data)
|
const data = JSON.parse(uploadRes.data)
|
||||||
if (data.code === 0 && data.data?.url) {
|
if (data.code === 0 && data.data?.url) {
|
||||||
setForm(prev => ({ ...prev, avatar: data.data.url }))
|
setForm(prev => ({...prev, avatar: data.data.url}))
|
||||||
Taro.showToast({ title: '上传成功', icon: 'success' })
|
Taro.showToast({title: '上传成功', icon: 'success'})
|
||||||
} else {
|
} else {
|
||||||
Taro.showToast({ title: data.message || '上传失败', icon: 'none' })
|
Taro.showToast({title: data.message || '上传失败', icon: 'none'})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail: () => {
|
fail: () => {
|
||||||
Taro.showToast({ title: '上传失败', icon: 'none' })
|
Taro.showToast({title: '上传失败', icon: 'none'})
|
||||||
},
|
},
|
||||||
complete: () => {
|
complete: () => {
|
||||||
Taro.hideLoading()
|
Taro.hideLoading()
|
||||||
@@ -66,24 +66,24 @@ const ProfilePage: React.FC = () => {
|
|||||||
|
|
||||||
// 选择性别
|
// 选择性别
|
||||||
const handleGenderSelect = (index: number) => {
|
const handleGenderSelect = (index: number) => {
|
||||||
setForm(prev => ({ ...prev, gender: index }))
|
setForm(prev => ({...prev, gender: index}))
|
||||||
setShowGenderSheet(false)
|
setShowGenderSheet(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存
|
// 保存
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
if (!form.nickname?.trim()) {
|
if (!form.nickname?.trim()) {
|
||||||
Taro.showToast({ title: '昵称不能为空', icon: 'none' })
|
Taro.showToast({title: '昵称不能为空', icon: 'none'})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
await updateUser(form as User)
|
await updateUser(form as User)
|
||||||
await refreshUser()
|
await refreshUser()
|
||||||
Taro.showToast({ title: '保存成功', icon: 'success' })
|
Taro.showToast({title: '保存成功', icon: 'success'})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('保存失败:', error)
|
console.error('保存失败:', error)
|
||||||
Taro.showToast({ title: '保存失败', icon: 'none' })
|
Taro.showToast({title: '保存失败', icon: 'none'})
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
@@ -94,6 +94,11 @@ const ProfilePage: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View className='min-h-screen bg-gray-50 pb-32'>
|
<View className='min-h-screen bg-gray-50 pb-32'>
|
||||||
|
{/* 用户ID */}
|
||||||
|
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
||||||
|
<Text className='text-sm text-gray-700 w-20'>用户ID</Text>
|
||||||
|
<Text className='text-sm text-gray-600'>{displayId || '未设置'}</Text>
|
||||||
|
</View>
|
||||||
{/* 头像 - 使用 Taro 原生 Button 支持 open-type="chooseAvatar" */}
|
{/* 头像 - 使用 Taro 原生 Button 支持 open-type="chooseAvatar" */}
|
||||||
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
||||||
<Text className='text-sm text-gray-700 w-20'>头像</Text>
|
<Text className='text-sm text-gray-700 w-20'>头像</Text>
|
||||||
@@ -113,7 +118,7 @@ const ProfilePage: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{form.avatar ? (
|
{form.avatar ? (
|
||||||
<Image className='w-10 h-10 rounded-full' src={form.avatar} mode='aspectFill' />
|
<Image className='w-10 h-10 rounded-full' src={form.avatar} mode='aspectFill'/>
|
||||||
) : (
|
) : (
|
||||||
<View className='w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center'>
|
<View className='w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center'>
|
||||||
<Text className='text-gray-300 text-xs'>头像</Text>
|
<Text className='text-gray-300 text-xs'>头像</Text>
|
||||||
@@ -131,14 +136,15 @@ const ProfilePage: React.FC = () => {
|
|||||||
className='flex-1 text-right text-sm text-gray-600'
|
className='flex-1 text-right text-sm text-gray-600'
|
||||||
placeholder='请输入昵称'
|
placeholder='请输入昵称'
|
||||||
value={form.nickname || ''}
|
value={form.nickname || ''}
|
||||||
onInput={(e: any) => setForm(prev => ({ ...prev, nickname: e.detail.value }))}
|
onInput={(e: any) => setForm(prev => ({...prev, nickname: e.detail.value}))}
|
||||||
maxlength={20}
|
maxlength={20}
|
||||||
type='nickname'
|
type='nickname'
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 性别 */}
|
{/* 性别 */}
|
||||||
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50' onClick={() => setShowGenderSheet(true)}>
|
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'
|
||||||
|
onClick={() => setShowGenderSheet(true)}>
|
||||||
<Text className='text-sm text-gray-700 w-20'>性别</Text>
|
<Text className='text-sm text-gray-700 w-20'>性别</Text>
|
||||||
<View className='flex items-center gap-2'>
|
<View className='flex items-center gap-2'>
|
||||||
<Text className='text-sm text-gray-600'>{genderOptions[form.gender ?? 0]}</Text>
|
<Text className='text-sm text-gray-600'>{genderOptions[form.gender ?? 0]}</Text>
|
||||||
@@ -152,42 +158,12 @@ const ProfilePage: React.FC = () => {
|
|||||||
<Text className='text-sm text-gray-600'>{form.phone || '未绑定'}</Text>
|
<Text className='text-sm text-gray-600'>{form.phone || '未绑定'}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 用户ID */}
|
|
||||||
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
|
||||||
<Text className='text-sm text-gray-700 w-20'>用户ID</Text>
|
|
||||||
<Text className='text-sm text-gray-600'>{displayId || '未设置'}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* 注册时间 */}
|
{/* 注册时间 */}
|
||||||
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
||||||
<Text className='text-sm text-gray-700 w-20'>注册时间</Text>
|
<Text className='text-sm text-gray-700 w-20'>注册时间</Text>
|
||||||
<Text className='text-sm text-gray-600'>{registerTime || '未知'}</Text>
|
<Text className='text-sm text-gray-600'>{registerTime || '未知'}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 门店名称 */}
|
|
||||||
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
|
||||||
<Text className='text-sm text-gray-700 w-20'>门店名称</Text>
|
|
||||||
<Input
|
|
||||||
className='flex-1 text-right text-sm text-gray-600'
|
|
||||||
placeholder='请输入门店名称'
|
|
||||||
value={(form as any)?.merchantName || ''}
|
|
||||||
onInput={(e: any) => setForm(prev => ({ ...prev, merchantName: e.detail.value }))}
|
|
||||||
maxlength={50}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* 门店地址 */}
|
|
||||||
<View className='flex items-center justify-between px-4 py-3 bg-white border-b border-gray-50'>
|
|
||||||
<Text className='text-sm text-gray-700 w-20'>门店地址</Text>
|
|
||||||
<Input
|
|
||||||
className='flex-1 text-right text-sm text-gray-600'
|
|
||||||
placeholder='请输入门店地址'
|
|
||||||
value={(form as any)?.address || ''}
|
|
||||||
onInput={(e: any) => setForm(prev => ({ ...prev, address: e.detail.value }))}
|
|
||||||
maxlength={100}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* 保存按钮 */}
|
{/* 保存按钮 */}
|
||||||
<BottomButton
|
<BottomButton
|
||||||
text='保存'
|
text='保存'
|
||||||
@@ -199,7 +175,8 @@ const ProfilePage: React.FC = () => {
|
|||||||
{/* 性别选择弹窗 */}
|
{/* 性别选择弹窗 */}
|
||||||
{showGenderSheet && (
|
{showGenderSheet && (
|
||||||
<View className='fixed inset-0 z-50'>
|
<View className='fixed inset-0 z-50'>
|
||||||
<View className='absolute inset-0 bg-black bg-opacity-50' onClick={() => setShowGenderSheet(false)} />
|
<View className='absolute inset-0 bg-black bg-opacity-50'
|
||||||
|
onClick={() => setShowGenderSheet(false)}/>
|
||||||
<View className='absolute bottom-0 left-0 right-0 bg-white rounded-t-xl'>
|
<View className='absolute bottom-0 left-0 right-0 bg-white rounded-t-xl'>
|
||||||
<View className='px-4 py-3 border-b border-gray-50'>
|
<View className='px-4 py-3 border-b border-gray-50'>
|
||||||
<Text className='text-base font-medium text-gray-800'>选择性别</Text>
|
<Text className='text-base font-medium text-gray-800'>选择性别</Text>
|
||||||
@@ -210,7 +187,8 @@ const ProfilePage: React.FC = () => {
|
|||||||
className='px-4 py-3 border-b border-gray-50 flex items-center justify-between'
|
className='px-4 py-3 border-b border-gray-50 flex items-center justify-between'
|
||||||
onClick={() => handleGenderSelect(index)}
|
onClick={() => handleGenderSelect(index)}
|
||||||
>
|
>
|
||||||
<Text className={`text-sm ${(form.gender ?? 0) === index ? 'text-green-600 font-medium' : 'text-gray-700'}`}>
|
<Text
|
||||||
|
className={`text-sm ${(form.gender ?? 0) === index ? 'text-green-600 font-medium' : 'text-gray-700'}`}>
|
||||||
{label}
|
{label}
|
||||||
</Text>
|
</Text>
|
||||||
{(form.gender ?? 0) === index && <Text className='text-green-600'>✓</Text>}
|
{(form.gender ?? 0) === index && <Text className='text-green-600'>✓</Text>}
|
||||||
|
|||||||
Reference in New Issue
Block a user