- 新增页面加载状态,加载中显示提示 - 等待 useUser 初始化完成后再加载用户数据 - 添加获取数据字典和用户信息的异常处理及错误提示 - 同步更新备注信息表单控件,修正校验提示文案 - 修正备注信息输入框的name属性,确保表单数据绑定正确
267 lines
7.4 KiB
TypeScript
267 lines
7.4 KiB
TypeScript
import {Cell, Avatar} from '@nutui/nutui-react-taro';
|
||
import {ArrowRight} from '@nutui/icons-react-taro'
|
||
import {useEffect, useState} from "react";
|
||
import {ConfigProvider} from '@nutui/nutui-react-taro'
|
||
import Taro, {getCurrentInstance} from '@tarojs/taro'
|
||
import {View, Text} from '@tarojs/components'
|
||
import {getUserInfo} from "@/api/layout";
|
||
import {TenantId} from "@/config/app";
|
||
import { TextArea } from '@nutui/nutui-react-taro'
|
||
import './profile.scss'
|
||
|
||
const {router} = getCurrentInstance()
|
||
import {
|
||
Form,
|
||
Button,
|
||
Input,
|
||
Radio,
|
||
} from '@nutui/nutui-react-taro'
|
||
import {DictData} from "@/api/system/dict-data/model";
|
||
import {pageDictData} from "@/api/system/dict-data";
|
||
import {User} from "@/api/system/user/model";
|
||
import {useUser} from "@/hooks/useUser";
|
||
|
||
// 类型定义
|
||
interface ChooseAvatarEvent {
|
||
detail: {
|
||
avatarUrl: string;
|
||
};
|
||
}
|
||
|
||
interface InputEvent {
|
||
detail: {
|
||
value: string;
|
||
};
|
||
}
|
||
function Profile() {
|
||
const formId = Number(router?.params.id)
|
||
const {user, updateUser, loading} = useUser()
|
||
|
||
const [sex, setSex] = useState<DictData[]>()
|
||
const [FormData, setFormData] = useState<User>(
|
||
{
|
||
userId: undefined,
|
||
nickname: undefined,
|
||
realName: undefined,
|
||
avatar: undefined,
|
||
sex: undefined,
|
||
phone: undefined,
|
||
address: undefined,
|
||
comments: undefined
|
||
}
|
||
)
|
||
const [pageLoading, setPageLoading] = useState(true)
|
||
|
||
const reload = () => {
|
||
// 获取数据字典
|
||
pageDictData({limit: 200}).then(res => {
|
||
setSex(res?.list.filter((item) => item.dictCode === 'sex'))
|
||
}).catch(err => {
|
||
console.error('获取数据字典失败:', err)
|
||
})
|
||
// 获取用户信息
|
||
getUserInfo().then((data) => {
|
||
// 更新表单数据
|
||
setFormData(data);
|
||
}).catch(err => {
|
||
console.error('获取用户信息失败:', err)
|
||
Taro.showToast({
|
||
title: '获取用户信息失败',
|
||
icon: 'none'
|
||
})
|
||
}).finally(() => {
|
||
setPageLoading(false)
|
||
})
|
||
}
|
||
|
||
// 提交表单
|
||
const submitSucceed = async (values: User) => {
|
||
console.log(values, 'values')
|
||
console.log(formId, 'formId>>')
|
||
try {
|
||
// 使用 useUser hook 的 updateUser 方法,它会自动更新状态和本地存储
|
||
await updateUser(values)
|
||
// 由于 useEffect 监听了 user 变化,FormData 会自动同步更新
|
||
setTimeout(() => {
|
||
return Taro.navigateBack()
|
||
}, 1000)
|
||
} catch (error) {
|
||
// updateUser 方法已经处理了错误提示,这里不需要重复显示
|
||
console.error('提交表单失败:', error)
|
||
}
|
||
}
|
||
const submitFailed = (error: unknown) => {
|
||
console.log(error, 'err...')
|
||
}
|
||
|
||
const uploadAvatar = ({detail}: ChooseAvatarEvent) => {
|
||
// 先更新本地显示的头像
|
||
setFormData({
|
||
...FormData,
|
||
avatar: `${detail.avatarUrl}`,
|
||
})
|
||
|
||
Taro.uploadFile({
|
||
url: 'https://server.websoft.top/api/oss/upload',
|
||
filePath: detail.avatarUrl,
|
||
name: 'file',
|
||
header: {
|
||
'content-type': 'application/json',
|
||
TenantId
|
||
},
|
||
success: async (res) => {
|
||
const data = JSON.parse(res.data);
|
||
if (data.code === 0) {
|
||
try {
|
||
// 使用 useUser hook 的 updateUser 方法更新头像
|
||
await updateUser({
|
||
avatar: `${data.data.thumbnail}`
|
||
})
|
||
// 由于 useEffect 监听了 user 变化,FormData 会自动同步更新
|
||
} catch (error) {
|
||
console.error('更新头像失败:', error)
|
||
// 如果更新失败,恢复原来的头像
|
||
setFormData({
|
||
...FormData,
|
||
avatar: user?.avatar || ''
|
||
})
|
||
}
|
||
}
|
||
},
|
||
fail: (error) => {
|
||
console.error('上传头像失败:', error)
|
||
Taro.showToast({
|
||
title: '上传失败',
|
||
icon: 'error'
|
||
})
|
||
// 恢复原来的头像
|
||
setFormData({
|
||
...FormData,
|
||
avatar: user?.avatar || ''
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
// 获取微信昵称
|
||
const getWxNickname = (nickname: string) => {
|
||
// 更新表单数据
|
||
setFormData({
|
||
...FormData,
|
||
nickname: nickname
|
||
});
|
||
}
|
||
|
||
// 等待 useUser 初始化完成后再加载数据
|
||
useEffect(() => {
|
||
if (!loading) {
|
||
reload()
|
||
}
|
||
}, [loading]);
|
||
|
||
// 监听 useUser hook 中的用户信息变化,同步更新表单数据
|
||
useEffect(() => {
|
||
if (user) {
|
||
setFormData(user)
|
||
}
|
||
}, [user]);
|
||
|
||
// 加载中显示
|
||
if (loading || pageLoading) {
|
||
return (
|
||
<View className={'flex justify-center items-center h-screen'}>
|
||
<Text>加载中...</Text>
|
||
</View>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<div className={'p-4'}>
|
||
<Cell.Group>
|
||
<Cell title={'头像'} align={'center'} extra={
|
||
<>
|
||
<Button open-type="chooseAvatar" style={{height: '58px'}} onChooseAvatar={uploadAvatar}>
|
||
<Avatar src={FormData?.avatar} size="54"/>
|
||
</Button>
|
||
<ArrowRight color="#cccccc" className={'ml-1'} size={20}/>
|
||
</>
|
||
}
|
||
/>
|
||
<Cell title={'手机号码'} align={'center'} extra={FormData?.phone}/>
|
||
</Cell.Group>
|
||
<ConfigProvider>
|
||
<Form
|
||
divider
|
||
initialValues={FormData}
|
||
labelPosition="left"
|
||
onFinish={(values) => submitSucceed(values)}
|
||
onFinishFailed={(errors) => submitFailed(errors)}
|
||
footer={
|
||
<div
|
||
style={{
|
||
display: 'flex',
|
||
justifyContent: 'center',
|
||
width: '100%'
|
||
}}
|
||
>
|
||
<Button nativeType="submit" block type="info">
|
||
提交
|
||
</Button>
|
||
</div>
|
||
}
|
||
>
|
||
<Form.Item
|
||
label={'昵称'}
|
||
name="nickname"
|
||
initialValue={FormData.nickname}
|
||
rules={[{message: '请获取微信昵称'}]}
|
||
>
|
||
<Input
|
||
type="nickname"
|
||
className="info-content__input"
|
||
placeholder="请输入昵称"
|
||
value={FormData?.nickname}
|
||
onInput={(e: InputEvent) => getWxNickname(e.detail.value)}
|
||
/>
|
||
</Form.Item>
|
||
<Form.Item
|
||
label="性别"
|
||
name="sex"
|
||
initialValue={FormData.sex}
|
||
rules={[
|
||
{message: '请选择性别'}
|
||
]}
|
||
>
|
||
<Radio.Group value={FormData?.sex} direction="horizontal">
|
||
{
|
||
sex?.map((item, index) => (
|
||
<Radio key={index} value={item.dictDataCode}>
|
||
{item.dictDataName}
|
||
</Radio>
|
||
))
|
||
}
|
||
</Radio.Group>
|
||
</Form.Item>
|
||
<Form.Item
|
||
label="备注信息"
|
||
name="comments"
|
||
initialValue={FormData.comments}
|
||
rules={[{message: '请输入备注信息'}]}
|
||
>
|
||
<TextArea
|
||
name="comments"
|
||
placeholder={'个性签名'}
|
||
value={FormData?.comments}
|
||
onChange={(value) => setFormData({...FormData, comments: value})}
|
||
/>
|
||
</Form.Item>
|
||
</Form>
|
||
</ConfigProvider>
|
||
</div>
|
||
</>
|
||
)
|
||
}
|
||
|
||
export default Profile
|