feat(shop): 新增用户管理模块- 添加用户记录表模型定义,包含用户基本信息、认证信息、统计信息等字段

- 实现用户记录表的增删改查接口,支持分页查询和批量删除功能
- 在医生申请页面集成用户信息提交功能,支持个人和企业用户类型- 优化用户表单验证逻辑,添加年龄必填校验- 调整用户类型单选框默认值为个人用户
- 添加证件上传功能,支持企业用户上传资质证明
- 移除文章分类和详情相关页面组件
- 调整请求工具中后台配置API地址的日志输出为注释状态
This commit is contained in:
2025-10-07 12:42:14 +08:00
parent e3fc34db8f
commit 1005fd0718
13 changed files with 351 additions and 339 deletions

View File

@@ -2,14 +2,14 @@ import {useEffect, useState, useRef} from "react";
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 {Image} from '@tarojs/components';
import FixedButton from "@/components/FixedButton";
import {useUser} from "@/hooks/useUser";
import {updateUser} from "@/api/system/user";
import {User} from "@/api/system/user/model";
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";
import {addShopUser, getShopUser} from "@/api/shop/shopUser";
import {ShopUser} from "@/api/shop/shopUser/model";
import {uploadFile} from "@/api/system/file";
import {useUser} from "@/hooks/useUser";
const customTheme = {
nutuiInputnumberButtonWidth: '30px',
@@ -21,97 +21,49 @@ const customTheme = {
}
const AddApply = () => {
const {user, loginUser} = useUser()
const {user} = useUser()
const [loading, setLoading] = useState<boolean>(true)
const [FormData, setFormData] = useState<User>()
const [FormData, setFormData] = useState<ShopUser>()
const [userType, setUserType] = useState<DictData[]>()
const formRef = useRef<any>(null)
const reload = async () => {
listDictData({dictCode: 'UserType'}).then((data) => {
setUserType(data)
})
const userId = Taro.getStorageSync('UserId')
if(!userId || userId == '') return
const shopUser = await getShopUser(Number(Taro.getStorageSync('UserId')))
if(shopUser){
console.log(shopUser.type,'shopUsershopUsershopUsershopUsershopUsershopUsershopUser')
setFormData({
...shopUser,
type : Number(shopUser.type)
})
}
const userType = await listDictData({dictCode: 'UserType'})
if(userType){
setUserType(userType)
}
}
// 提交表单
const submitSucceed = async (values: any) => {
try {
// 验证必填字段
if (!values.phone && !FormData?.phone) {
Taro.showToast({
title: '请先获取手机号',
icon: 'error'
});
return;
}
// 验证昵称:必须填写且不能是默认的微信昵称
const nickname = values.realName || FormData?.nickname || '';
if (!nickname || nickname.trim() === '') {
Taro.showToast({
title: '请填写昵称',
icon: 'error'
});
return;
}
// 检查是否为默认的微信昵称(常见的默认昵称)
const defaultNicknames = ['微信用户', 'WeChat User', '微信昵称'];
if (defaultNicknames.includes(nickname.trim())) {
Taro.showToast({
title: '请填写真实昵称,不能使用默认昵称',
icon: 'error'
});
return;
}
// 验证昵称长度
if (nickname.trim().length < 2) {
Taro.showToast({
title: '昵称至少需要2个字符',
icon: 'error'
});
return;
}
if (!values.avatar && !FormData?.avatar) {
Taro.showToast({
title: '请上传头像',
icon: 'error'
});
return;
}
console.log(values,FormData)
const roles = await listUserRole({userId: user?.userId})
console.log(roles, 'roles...')
return false;
// 准备提交的数据
await updateUser({
userId: user?.userId,
nickname: values.realName || FormData?.nickname,
phone: values.phone || FormData?.phone,
avatar: values.avatar || FormData?.avatar,
refereeId: values.refereeId || FormData?.refereeId
if (!FormData?.age || FormData?.age == 0) {
Taro.showToast({
title: `请填写年龄`,
icon: 'error'
});
await addShopDealerUser({
userId: user?.userId,
return;
}
try {
// 准备提交的数据
await addShopUser({
userId: Taro.getStorageSync('UserId'),
type: values.type,
username: user?.username,
nickname: user?.nickname,
realName: values.realName || FormData?.nickname,
mobile: values.phone || FormData?.phone,
refereeId: values.refereeId || FormData?.refereeId
phone: values.phone || FormData?.phone
})
if (roles.length > 0) {
await updateUserRole({
...roles[0],
roleId: 1848
})
}
Taro.showToast({
title: `注册成功`,
icon: 'success'
@@ -136,17 +88,25 @@ const AddApply = () => {
console.log(error, 'err...')
}
const uploadImg1 = () => {
uploadFile().then(data => {
setFormData({
...FormData,
uploadImg1: data.url
})
});
}
useEffect(() => {
reload().then(() => {
setLoading(false)
})
}, [user?.userId]); // 依赖用户ID当用户变化时重新加载
}, []); // 依赖用户ID当用户变化时重新加载
// 当FormData变化时同步更新表单字段值
useEffect(() => {
if (formRef.current && FormData) {
formRef.current.setFieldsValue({
refereeId: FormData.refereeId,
phone: FormData.phone,
avatar: FormData.avatar,
realName: FormData.nickname
@@ -172,7 +132,7 @@ const AddApply = () => {
{JSON.stringify(FormData)}
<Form.Item label="用户类型" name="type" initialValue={FormData?.type} required>
<Radio.Group
defaultValue="1"
defaultValue="0"
direction="horizontal"
value={FormData?.type}
onChange={(value: any) => {
@@ -193,10 +153,10 @@ const AddApply = () => {
<Input
placeholder={'请填写真实姓名'}
value={FormData?.realName || ''}
onChange={(e) => {
onChange={(value) => {
setFormData({
...FormData,
realName: e.detail.value
realName: value
})
}}
/>
@@ -214,17 +174,17 @@ const AddApply = () => {
</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="年龄" name="age" initialValue={FormData?.age || 18} required>
<Form.Item label="年龄" name="age" initialValue={FormData?.age} required>
<ConfigProvider theme={customTheme}>
<InputNumber
value={FormData?.age || 18}
value={FormData?.age}
onChange={(value) => {
setFormData({
...FormData,
age: Number(value)
})
}}
min={1}
min={0}
max={120}
step={1}
/>
@@ -240,6 +200,34 @@ const AddApply = () => {
value={FormData?.introduction || ''}
/>
</Form.Item>
{FormData?.type == 1 && (
<>
<Form.Item label="证书编号" name="userCode" required>
<Input
placeholder={'请填证书编号'}
value={FormData?.userCode || ''}
onChange={(value) => {
setFormData({
...FormData,
idCard: value
})
}}
/>
</Form.Item>
<Form.Item
label={'上传证件'}
name="uploadImg1"
required
rules={[{message: '请上传医师资格证书'}
]}
>
<div onClick={uploadImg1}>
<Image src={FormData.uploadImg1 || ''} mode={'scaleToFill'} lazyLoad={false} />
</div>
</Form.Item>
</>
)}
</CellGroup>
</Form>