|
|
@ -1,26 +1,16 @@ |
|
|
|
import {useEffect, useState, useRef} from "react"; |
|
|
|
import {Loading, CellGroup, Input, Form, Avatar, Radio, Button, Space, InputNumber, TextArea, ConfigProvider} from '@nutui/nutui-react-taro' |
|
|
|
import {Loading, CellGroup, Input, Form, Radio, InputNumber, TextArea, ConfigProvider} from '@nutui/nutui-react-taro' |
|
|
|
import {Edit} from '@nutui/icons-react-taro' |
|
|
|
import Taro from '@tarojs/taro' |
|
|
|
import {View} from '@tarojs/components' |
|
|
|
import FixedButton from "@/components/FixedButton"; |
|
|
|
import {useUser} from "@/hooks/useUser"; |
|
|
|
import {TenantId} from "@/config/app"; |
|
|
|
import {updateUser} from "@/api/system/user"; |
|
|
|
import {User} from "@/api/system/user/model"; |
|
|
|
import {getStoredInviteParams, handleInviteRelation} from "@/utils/invite"; |
|
|
|
import {addShopDealerUser} from "@/api/shop/shopDealerUser"; |
|
|
|
import {listUserRole, updateUserRole} from "@/api/system/userRole"; |
|
|
|
import {DictData} from "@/api/system/dict-data/model"; |
|
|
|
import {listDictData} from "@/api/system/dict-data"; |
|
|
|
|
|
|
|
// 类型定义
|
|
|
|
interface ChooseAvatarEvent { |
|
|
|
detail: { |
|
|
|
avatarUrl: string; |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
const customTheme = { |
|
|
|
nutuiInputnumberButtonWidth: '30px', |
|
|
|
nutuiInputnumberButtonHeight: '30px', |
|
|
@ -30,7 +20,7 @@ const customTheme = { |
|
|
|
nutuiInputnumberInputMargin: '0 2px', |
|
|
|
} |
|
|
|
|
|
|
|
const AddUserAddress = () => { |
|
|
|
const AddApply = () => { |
|
|
|
const {user, loginUser} = useUser() |
|
|
|
const [loading, setLoading] = useState<boolean>(true) |
|
|
|
const [FormData, setFormData] = useState<User>() |
|
|
@ -38,103 +28,11 @@ const AddUserAddress = () => { |
|
|
|
const formRef = useRef<any>(null) |
|
|
|
|
|
|
|
const reload = async () => { |
|
|
|
const inviteParams = getStoredInviteParams() |
|
|
|
if (inviteParams?.inviter) { |
|
|
|
setFormData({ |
|
|
|
...user, |
|
|
|
refereeId: Number(inviteParams.inviter), |
|
|
|
// 清空昵称,强制用户手动输入
|
|
|
|
nickname: '', |
|
|
|
}) |
|
|
|
} else { |
|
|
|
// 如果没有邀请参数,也要确保昵称为空
|
|
|
|
setFormData({ |
|
|
|
...user, |
|
|
|
nickname: '', |
|
|
|
}) |
|
|
|
} |
|
|
|
listDictData({dictCode: 'UserType'}).then((data) => { |
|
|
|
setUserType(data) |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const uploadAvatar = ({detail}: ChooseAvatarEvent) => { |
|
|
|
// 先更新本地显示的头像(临时显示)
|
|
|
|
const tempFormData = { |
|
|
|
...FormData, |
|
|
|
avatar: `${detail.avatarUrl}`, |
|
|
|
} |
|
|
|
setFormData(tempFormData) |
|
|
|
|
|
|
|
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) { |
|
|
|
const finalAvatarUrl = `${data.data.thumbnail}` |
|
|
|
|
|
|
|
try { |
|
|
|
// 使用 useUser hook 的 updateUser 方法更新头像
|
|
|
|
await updateUser({ |
|
|
|
avatar: finalAvatarUrl |
|
|
|
}) |
|
|
|
|
|
|
|
Taro.showToast({ |
|
|
|
title: '头像上传成功', |
|
|
|
icon: 'success', |
|
|
|
duration: 1500 |
|
|
|
}) |
|
|
|
} catch (error) { |
|
|
|
console.error('更新用户头像失败:', error) |
|
|
|
} |
|
|
|
|
|
|
|
// 无论用户信息更新是否成功,都要更新本地FormData
|
|
|
|
const finalFormData = { |
|
|
|
...tempFormData, |
|
|
|
avatar: finalAvatarUrl |
|
|
|
} |
|
|
|
setFormData(finalFormData) |
|
|
|
|
|
|
|
// 同步更新表单字段
|
|
|
|
if (formRef.current) { |
|
|
|
formRef.current.setFieldsValue({ |
|
|
|
avatar: finalAvatarUrl |
|
|
|
}) |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 上传失败,恢复原来的头像
|
|
|
|
setFormData({ |
|
|
|
...FormData, |
|
|
|
avatar: user?.avatar || '' |
|
|
|
}) |
|
|
|
Taro.showToast({ |
|
|
|
title: '上传失败', |
|
|
|
icon: 'error' |
|
|
|
}) |
|
|
|
} |
|
|
|
}, |
|
|
|
fail: (error) => { |
|
|
|
console.error('上传头像失败:', error) |
|
|
|
Taro.showToast({ |
|
|
|
title: '上传失败', |
|
|
|
icon: 'error' |
|
|
|
}) |
|
|
|
// 恢复原来的头像
|
|
|
|
setFormData({ |
|
|
|
...FormData, |
|
|
|
avatar: user?.avatar || '' |
|
|
|
}) |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
// 提交表单
|
|
|
|
const submitSucceed = async (values: any) => { |
|
|
|
try { |
|
|
@ -188,6 +86,8 @@ const AddUserAddress = () => { |
|
|
|
const roles = await listUserRole({userId: user?.userId}) |
|
|
|
console.log(roles, 'roles...') |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
// 准备提交的数据
|
|
|
|
await updateUser({ |
|
|
|
userId: user?.userId, |
|
|
@ -226,110 +126,6 @@ const AddUserAddress = () => { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* 获取用户手机号 */ |
|
|
|
const handleGetPhoneNumber = ({detail}: { detail: { code?: string, encryptedData?: string, iv?: string } }) => { |
|
|
|
const {code, encryptedData, iv} = detail |
|
|
|
Taro.login({ |
|
|
|
success: (loginRes) => { |
|
|
|
if (code) { |
|
|
|
Taro.request({ |
|
|
|
url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', |
|
|
|
method: 'POST', |
|
|
|
data: { |
|
|
|
authCode: loginRes.code, |
|
|
|
code, |
|
|
|
encryptedData, |
|
|
|
iv, |
|
|
|
notVerifyPhone: true, |
|
|
|
refereeId: 0, |
|
|
|
sceneType: 'save_referee', |
|
|
|
tenantId: TenantId |
|
|
|
}, |
|
|
|
header: { |
|
|
|
'content-type': 'application/json', |
|
|
|
TenantId |
|
|
|
}, |
|
|
|
success: async function (res) { |
|
|
|
if (res.data.code == 1) { |
|
|
|
Taro.showToast({ |
|
|
|
title: res.data.message, |
|
|
|
icon: 'error', |
|
|
|
duration: 2000 |
|
|
|
}) |
|
|
|
return false; |
|
|
|
} |
|
|
|
// 登录成功
|
|
|
|
const token = res.data.data.access_token; |
|
|
|
const userData = res.data.data.user; |
|
|
|
console.log(userData, 'userData...') |
|
|
|
// 使用useUser Hook的loginUser方法更新状态
|
|
|
|
loginUser(token, userData); |
|
|
|
|
|
|
|
if (userData.phone) { |
|
|
|
console.log('手机号已获取', userData.phone) |
|
|
|
const updatedFormData = { |
|
|
|
...FormData, |
|
|
|
phone: userData.phone, |
|
|
|
// 不自动填充微信昵称,保持用户已输入的昵称
|
|
|
|
nickname: FormData?.nickname || '', |
|
|
|
// 只在没有头像时才使用微信头像
|
|
|
|
avatar: FormData?.avatar || userData.avatar |
|
|
|
} |
|
|
|
setFormData(updatedFormData) |
|
|
|
|
|
|
|
// 更新表单字段值
|
|
|
|
if (formRef.current) { |
|
|
|
formRef.current.setFieldsValue({ |
|
|
|
phone: userData.phone, |
|
|
|
// 不覆盖用户已输入的昵称
|
|
|
|
realName: FormData?.nickname || '', |
|
|
|
avatar: FormData?.avatar || userData.avatar |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
Taro.showToast({ |
|
|
|
title: '手机号获取成功', |
|
|
|
icon: 'success', |
|
|
|
duration: 1500 |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 处理邀请关系
|
|
|
|
if (userData?.userId) { |
|
|
|
try { |
|
|
|
const inviteSuccess = await handleInviteRelation(userData.userId) |
|
|
|
if (inviteSuccess) { |
|
|
|
Taro.showToast({ |
|
|
|
title: '邀请关系建立成功', |
|
|
|
icon: 'success', |
|
|
|
duration: 2000 |
|
|
|
}) |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('处理邀请关系失败:', error) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 显示登录成功提示
|
|
|
|
// Taro.showToast({
|
|
|
|
// title: '注册成功',
|
|
|
|
// icon: 'success',
|
|
|
|
// duration: 1500
|
|
|
|
// })
|
|
|
|
|
|
|
|
// 不需要重新启动小程序,状态已经通过useUser更新
|
|
|
|
// 可以选择性地刷新当前页面数据
|
|
|
|
// await reload();
|
|
|
|
} |
|
|
|
}) |
|
|
|
} else { |
|
|
|
console.log('登录失败!') |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
// 处理固定按钮点击事件
|
|
|
|
const handleFixedButtonClick = () => { |
|
|
|
// 触发表单提交
|
|
|
@ -372,52 +168,8 @@ const AddUserAddress = () => { |
|
|
|
onFinish={(values) => submitSucceed(values)} |
|
|
|
onFinishFailed={(errors) => submitFailed(errors)} |
|
|
|
> |
|
|
|
<View className={'bg-gray-100 h-3'}></View> |
|
|
|
<CellGroup style={{padding: '4px 0'}}> |
|
|
|
{ |
|
|
|
FormData?.phone && <Form.Item name="avatar" label="头像" initialValue={FormData?.avatar} required> |
|
|
|
<Button open-type="chooseAvatar" style={{height: '58px'}} onChooseAvatar={uploadAvatar}> |
|
|
|
<Avatar src={FormData?.avatar || user?.avatar} size="54"/> |
|
|
|
</Button> |
|
|
|
</Form.Item> |
|
|
|
} |
|
|
|
<Form.Item name="phone" label="手机号" initialValue={FormData?.phone} required> |
|
|
|
<View className="flex items-center justify-between"> |
|
|
|
<Input |
|
|
|
placeholder="请填写手机号" |
|
|
|
disabled={true} |
|
|
|
maxLength={11} |
|
|
|
value={FormData?.phone || ''} |
|
|
|
/> |
|
|
|
<Button style={{color: '#ffffff'}} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}> |
|
|
|
<Space> |
|
|
|
<Button size="small">点击获取</Button> |
|
|
|
</Space> |
|
|
|
</Button> |
|
|
|
</View> |
|
|
|
</Form.Item> |
|
|
|
{FormData?.refereeId && <Form.Item name="refereeId" label="邀请人ID" initialValue={FormData?.refereeId} required><Input placeholder="邀请人ID" disabled={true}/></Form.Item>} |
|
|
|
</CellGroup> |
|
|
|
<View className={'h-3 bg-gray-100'}></View> |
|
|
|
<CellGroup style={{padding: '4px 0'}}> |
|
|
|
<Form.Item label="姓名" name="realName" required> |
|
|
|
<Input placeholder={'请填写真实姓名'} value={FormData?.realName || ''} /> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label="性别" name="sex" required> |
|
|
|
<Radio.Group defaultValue="0" direction="horizontal"> |
|
|
|
<Radio value="1"> |
|
|
|
男 |
|
|
|
</Radio> |
|
|
|
<Radio value="2"> |
|
|
|
女 |
|
|
|
</Radio> |
|
|
|
</Radio.Group> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label="年龄" name="age" initialValue={18}> |
|
|
|
<ConfigProvider theme={customTheme}> |
|
|
|
<InputNumber value={FormData?.age || 18} /> |
|
|
|
</ConfigProvider> |
|
|
|
</Form.Item> |
|
|
|
{JSON.stringify(FormData)} |
|
|
|
<Form.Item label="用户类型" name="type" initialValue={FormData?.type} required> |
|
|
|
<Radio.Group |
|
|
|
defaultValue="1" |
|
|
@ -437,34 +189,57 @@ const AddUserAddress = () => { |
|
|
|
))} |
|
|
|
</Radio.Group> |
|
|
|
</Form.Item> |
|
|
|
{FormData?.type == 0 && ( |
|
|
|
<Form.Item label="个人签名" name="introduction"> |
|
|
|
<TextArea |
|
|
|
placeholder={'个人签名'} |
|
|
|
style={{ |
|
|
|
height: '50px', |
|
|
|
backgroundColor: '#fafafa', |
|
|
|
padding: '10px', |
|
|
|
<Form.Item label="姓名" name="realName" required> |
|
|
|
<Input |
|
|
|
placeholder={'请填写真实姓名'} |
|
|
|
value={FormData?.realName || ''} |
|
|
|
onChange={(e) => { |
|
|
|
setFormData({ |
|
|
|
...FormData, |
|
|
|
realName: e.detail.value |
|
|
|
}) |
|
|
|
}} |
|
|
|
/> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label="性别" name="sex" required> |
|
|
|
<Radio.Group |
|
|
|
direction="horizontal" |
|
|
|
value={FormData?.sex || "0"} |
|
|
|
> |
|
|
|
<Radio value="1"> |
|
|
|
男 |
|
|
|
</Radio> |
|
|
|
<Radio value="2"> |
|
|
|
女 |
|
|
|
</Radio> |
|
|
|
</Radio.Group> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label="年龄" name="age" initialValue={FormData?.age || 18} required> |
|
|
|
<ConfigProvider theme={customTheme}> |
|
|
|
<InputNumber |
|
|
|
value={FormData?.age || 18} |
|
|
|
onChange={(value) => { |
|
|
|
setFormData({ |
|
|
|
...FormData, |
|
|
|
age: Number(value) |
|
|
|
}) |
|
|
|
}} |
|
|
|
value={FormData?.introduction || ''} |
|
|
|
min={1} |
|
|
|
max={120} |
|
|
|
step={1} |
|
|
|
/> |
|
|
|
</Form.Item> |
|
|
|
)} |
|
|
|
{ |
|
|
|
FormData?.type == 1 && ( |
|
|
|
<Form.Item label="医生简介" name="introduction"> |
|
|
|
<TextArea |
|
|
|
placeholder={'医生简介'} |
|
|
|
style={{ |
|
|
|
height: '50px', |
|
|
|
backgroundColor: '#fafafa', |
|
|
|
padding: '10px', |
|
|
|
}} |
|
|
|
value={FormData?.introduction || ''} |
|
|
|
/> |
|
|
|
</Form.Item> |
|
|
|
) |
|
|
|
} |
|
|
|
</ConfigProvider> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label={FormData?.type == 1 ? '医生简介' : '个人简介'} name="introduction"> |
|
|
|
<TextArea |
|
|
|
style={{ |
|
|
|
height: '50px', |
|
|
|
backgroundColor: '#fafafa', |
|
|
|
padding: '10px', |
|
|
|
}} |
|
|
|
value={FormData?.introduction || ''} |
|
|
|
/> |
|
|
|
</Form.Item> |
|
|
|
</CellGroup> |
|
|
|
</Form> |
|
|
|
|
|
|
@ -479,4 +254,4 @@ const AddUserAddress = () => { |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
export default AddUserAddress; |
|
|
|
export default AddApply; |
|
|
|