You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
6.9 KiB
244 lines
6.9 KiB
/** |
|
* 编辑个人信息页 |
|
*/ |
|
import { View, Text, Image, Input, Button as WxButton } from '@tarojs/components' |
|
import Taro, { useLoad } from '@tarojs/taro' |
|
import { useState } from 'react' |
|
import { observer } from 'mobx-react' |
|
import { Image as TaroifyImage, Button, ActionSheet } from '@taroify/core' |
|
import { updateCustomer, readImageAsBase64 } from '../../api/customer' |
|
import { userStore } from '../../store' |
|
import myAvatar from '../../assets/icon/my_avatar.png' |
|
import './index.scss' |
|
|
|
const EditProfile = observer(() => { |
|
const info = userStore.userInfo |
|
|
|
const [nickname, setNickname] = useState(info?.name || info?.nickname || '') |
|
const [phone, setPhone] = useState(info?.phone || '') |
|
const [wchart, setWchart] = useState(info?.wchart || '') |
|
const [avatarUrl, setAvatarUrl] = useState(info?.avatar || myAvatar) |
|
// 是否选了新的本地头像(需要上传) |
|
const [newAvatarPath, setNewAvatarPath] = useState<string>('') |
|
const [loading, setLoading] = useState(false) |
|
const [avatarActionOpen, setAvatarActionOpen] = useState(false) |
|
|
|
useLoad(() => { |
|
console.log('编辑个人信息页面加载') |
|
}) |
|
|
|
// 点击头像区域 |
|
const handleAvatarClick = () => { |
|
setAvatarActionOpen(true) |
|
} |
|
|
|
// 微信头像回调 |
|
const handleChooseAvatar = (e: any) => { |
|
const url = e.detail.avatarUrl |
|
setAvatarUrl(url) |
|
setNewAvatarPath(url) |
|
setAvatarActionOpen(false) |
|
} |
|
|
|
// 从相册选择 |
|
const handleChooseFromAlbum = () => { |
|
setAvatarActionOpen(false) |
|
Taro.chooseImage({ |
|
count: 1, |
|
sizeType: ['compressed'], |
|
sourceType: ['album'], |
|
success: (res) => { |
|
const path = res.tempFilePaths[0] |
|
setAvatarUrl(path) |
|
setNewAvatarPath(path) |
|
}, |
|
}) |
|
} |
|
|
|
// 拍照 |
|
const handleTakePhoto = () => { |
|
setAvatarActionOpen(false) |
|
Taro.chooseImage({ |
|
count: 1, |
|
sizeType: ['compressed'], |
|
sourceType: ['camera'], |
|
success: (res) => { |
|
const path = res.tempFilePaths[0] |
|
setAvatarUrl(path) |
|
setNewAvatarPath(path) |
|
}, |
|
}) |
|
} |
|
|
|
// 保存 |
|
const handleSave = async () => { |
|
if (loading) return |
|
|
|
const userId = info?.id |
|
if (!userId) { |
|
Taro.showToast({ title: '用户信息异常,请重新登录', icon: 'none', duration: 2000 }) |
|
return |
|
} |
|
|
|
if (!nickname.trim()) { |
|
Taro.showToast({ title: '昵称不能为空', icon: 'none', duration: 2000 }) |
|
return |
|
} |
|
|
|
setLoading(true) |
|
|
|
try { |
|
// 如果选了新头像,先转成 Base64 |
|
let avatarImage: string | undefined |
|
if (newAvatarPath) { |
|
try { |
|
avatarImage = await readImageAsBase64(newAvatarPath) |
|
} catch (e) { |
|
console.warn('头像转 Base64 失败,跳过头像更新:', e) |
|
} |
|
} |
|
|
|
await updateCustomer(userId, { |
|
id: userId, |
|
name: nickname.trim(), |
|
phone: phone.trim() || undefined, |
|
wchart: wchart.trim() || undefined, |
|
avatarImage, |
|
}) |
|
|
|
// 同步更新本地 store |
|
userStore.setUserInfo({ |
|
...userStore.userInfo!, |
|
name: nickname.trim(), |
|
nickname: nickname.trim(), |
|
phone: phone.trim() || userStore.userInfo?.phone, |
|
wchart: wchart.trim() || userStore.userInfo?.wchart, |
|
avatar: newAvatarPath || userStore.userInfo?.avatar, |
|
}) |
|
|
|
Taro.showToast({ title: '保存成功', icon: 'success', duration: 2000 }) |
|
setTimeout(() => Taro.navigateBack(), 1500) |
|
} catch (error: any) { |
|
console.error('保存失败:', error) |
|
// 错误提示由 request 拦截器统一处理 |
|
} finally { |
|
setLoading(false) |
|
} |
|
} |
|
|
|
return ( |
|
<View className="edit-profile-page"> |
|
<View className="content-area"> |
|
{/* 头像区域 */} |
|
<View className="avatar-section" onClick={handleAvatarClick}> |
|
<View className="avatar-wrapper"> |
|
<TaroifyImage |
|
className="avatar" |
|
src={avatarUrl || myAvatar} |
|
round |
|
mode="aspectFill" |
|
/> |
|
<View className="camera-icon"> |
|
<Image |
|
className="camera-img" |
|
src={require('../../assets/icon/phototake.png')} |
|
mode="widthFix" |
|
/> |
|
</View> |
|
</View> |
|
</View> |
|
|
|
{/* 表单区域 */} |
|
<View className="form-section"> |
|
{/* 昵称 */} |
|
<View className="form-item"> |
|
<Text className="form-label">昵称</Text> |
|
<Input |
|
className="form-input" |
|
value={nickname} |
|
onInput={(e) => setNickname(e.detail.value)} |
|
placeholder="请输入昵称" |
|
placeholderClass="form-placeholder" |
|
maxlength={20} |
|
/> |
|
</View> |
|
|
|
{/* 手机号 */} |
|
<View className="form-item"> |
|
<Text className="form-label">手机号</Text> |
|
<Input |
|
className="form-input" |
|
value={phone} |
|
onInput={(e) => setPhone(e.detail.value)} |
|
placeholder="请输入手机号" |
|
placeholderClass="form-placeholder" |
|
type="number" |
|
maxlength={11} |
|
/> |
|
</View> |
|
|
|
{/* 微信号 */} |
|
<View className="form-item"> |
|
<Text className="form-label">微信号</Text> |
|
<Input |
|
className="form-input" |
|
value={wchart} |
|
onInput={(e) => setWchart(e.detail.value)} |
|
placeholder="请输入微信号" |
|
placeholderClass="form-placeholder" |
|
maxlength={30} |
|
/> |
|
</View> |
|
</View> |
|
|
|
{/* 保存按钮 */} |
|
<Button |
|
className={`save-button ${loading ? 'disabled' : ''}`} |
|
loading={loading} |
|
onClick={handleSave} |
|
> |
|
{loading ? '保存中...' : '保存'} |
|
</Button> |
|
</View> |
|
|
|
{/* 头像选择菜单 */} |
|
<ActionSheet |
|
open={avatarActionOpen} |
|
onSelect={() => {}} |
|
onClose={() => setAvatarActionOpen(false)} |
|
> |
|
<WxButton |
|
className="avatar-action-item wechat-avatar-btn" |
|
openType="chooseAvatar" |
|
onChooseAvatar={handleChooseAvatar} |
|
> |
|
<Text className="avatar-emoji">🤵</Text> |
|
<Text>用微信头像</Text> |
|
</WxButton> |
|
|
|
<ActionSheet.Action |
|
className="avatar-action-item" |
|
onClick={handleChooseFromAlbum} |
|
> |
|
从相册选择 |
|
</ActionSheet.Action> |
|
|
|
<ActionSheet.Action |
|
className="avatar-action-item" |
|
onClick={handleTakePhoto} |
|
> |
|
拍照 |
|
</ActionSheet.Action> |
|
|
|
<ActionSheet.Action |
|
className="avatar-action-item cancel-action" |
|
onClick={() => setAvatarActionOpen(false)} |
|
> |
|
取消 |
|
</ActionSheet.Action> |
|
</ActionSheet> |
|
</View> |
|
) |
|
}) |
|
|
|
export default EditProfile
|
|
|