refactor(user-profile): 调整个人信息页面布局优化结构

- 调整用户ID位置至头像之上以强化信息层次
- 统一并优化代码格式排版,提升代码可读性
- 合并重复的用户ID展示,避免冗余
- 保持功能一致,未改动交互逻辑
- 优化注释及空白行,代码风格更规范
This commit is contained in:
2026-07-17 11:42:04 +08:00
parent ceba1cabec
commit 955b156399

View File

@@ -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>}