feat(dealer): 添加经销商申请功能并优化用户相关页面

- 新增经销商申请页面和相关组件- 更新用户中心页面,增加经销商状态显示和申请入口
- 修改登录逻辑,支持获取用户手机号- 优化用户钩子,增加获取用户ID和判断超级管理员权限的功能
This commit is contained in:
2025-08-18 01:18:19 +08:00
parent f73bfeb743
commit 13b3d6407b
11 changed files with 376 additions and 46 deletions

View File

@@ -5,12 +5,39 @@ import {TenantId} from "@/config/app";
import './login.scss';
import {saveStorageByLoginUser} from "@/utils/server";
const Login = (props:any) => {
// 微信获取手机号回调参数类型
interface GetPhoneNumberDetail {
code?: string;
encryptedData?: string;
iv?: string;
errMsg: string;
}
interface GetPhoneNumberEvent {
detail: GetPhoneNumberDetail;
}
interface LoginProps {
done?: (user: any) => void;
[key: string]: any;
}
// 登录接口返回数据类型
interface LoginResponse {
data: {
data: {
access_token: string;
user: any;
};
};
}
const Login = (props: LoginProps) => {
const [isAgree, setIsAgree] = useState(false)
const [env, setEnv] = useState<string>()
/* 获取用户手机号 */
const handleGetPhoneNumber = ({detail}) => {
const handleGetPhoneNumber = ({detail}: GetPhoneNumberEvent) => {
const {code, encryptedData, iv} = detail
Taro.login({
success: function () {
@@ -31,9 +58,9 @@ const Login = (props:any) => {
'content-type': 'application/json',
TenantId
},
success: function (res) {
saveStorageByLoginUser(res.data.data.access_token,res.data.data.user)
props.done(res.data.data.user);
success: function (res: LoginResponse) {
saveStorageByLoginUser(res.data.data.access_token, res.data.data.user)
props.done?.(res.data.data.user);
}
})
} else {

View File

@@ -0,0 +1,121 @@
import {Cell} from '@nutui/nutui-react-taro'
import navTo from "@/utils/common";
import Taro from '@tarojs/taro'
import {View, Text} from '@tarojs/components'
import {ArrowRight, Reward, Setting} from '@nutui/icons-react-taro'
import {useUser} from '@/hooks/useUser'
import {useEffect, useState} from "react";
import {pageShopDealerUser} from "@/api/shop/shopDealerUser";
const UserCell = () => {
const {isSuperAdmin} = useUser();
const [isDealer, setIsDealer] = useState<boolean>(false)
const reload = async () => {
const userId = Taro.getStorageSync('UserId')
console.log('当前用户ID:', userId)
const params = {
userId: Number(userId),
page: 1,
limit: 1
}
console.log('查询分销商参数:', params)
try {
const res = await pageShopDealerUser(params)
console.log('分销商查询结果:', res)
if (res?.count && res?.count > 0) {
setIsDealer(true)
} else {
setIsDealer(false)
}
} catch (error) {
console.error('查询分销商信息失败:', error)
setIsDealer(false)
}
}
useEffect(() => {
reload().then()
}, [])
/**
* 管理中心
*/
if (isSuperAdmin()) {
return (
<>
<View className={'px-4'}>
<Cell
className="nutui-cell-clickable"
style={{
backgroundImage: 'linear-gradient(to right bottom, #e53e3e, #c53030)',
}}
title={
<View style={{display: 'inline-flex', alignItems: 'center'}} onClick={() => navTo('/admin/index', true)}>
<Setting className={'text-white '} size={16}/>
<Text style={{fontSize: '16px'}} className={'pl-3 text-white font-medium'}></Text>
</View>
}
extra={<ArrowRight color="#ffffff" size={18}/>}
/>
</View>
</>
)
}
/**
* 分销中心
*/
if (isDealer) {
return (
<>
<View className={'px-4'}>
<Cell
className="nutui-cell-clickable"
style={{
backgroundImage: 'linear-gradient(to right bottom, #54a799, #177b73)',
}}
title={
<View style={{display: 'inline-flex', alignItems: 'center'}} onClick={() => navTo('/dealer/index', true)}>
<Reward className={'text-orange-100 '} size={16}/>
<Text style={{fontSize: '16px'}} className={'pl-3 text-orange-100 font-medium'}></Text>
<Text className={'text-white opacity-80 pl-3'}></Text>
</View>
}
extra={<ArrowRight color="#cccccc" size={18}/>}
/>
</View>
</>
)
}
/**
* 分销中心
*/
return (
<>
<View className={'px-4'}>
<Cell
className="nutui-cell-clickable"
style={{
backgroundImage: 'linear-gradient(to right bottom, #54a799, #177b73)',
}}
title={
<View style={{display: 'inline-flex', alignItems: 'center'}}>
<Reward className={'text-orange-100 '} size={16}/>
<Text style={{fontSize: '16px'}} className={'pl-3 text-orange-100 font-medium'}></Text>
<Text className={'text-white opacity-80 pl-3'}></Text>
</View>
}
extra={<ArrowRight color="#cccccc" size={18}/>}
onClick={() => navTo('/dealer/apply/add', true)}
/>
</View>
</>
)
}
export default UserCell

View File

@@ -2,11 +2,11 @@ import {Cell} from '@nutui/nutui-react-taro'
import navTo from "@/utils/common";
import Taro from '@tarojs/taro'
import {View, Text} from '@tarojs/components'
import {ArrowRight, ShieldCheck, LogisticsError, Location, Reward, Tips, Ask, Setting} from '@nutui/icons-react-taro'
import {ArrowRight, ShieldCheck, LogisticsError, Location, Tips, Ask} from '@nutui/icons-react-taro'
import {useUser} from '@/hooks/useUser'
const UserCell = () => {
const {logoutUser, isCertified, hasRole, isAdmin} = useUser();
const {logoutUser, isCertified} = useUser();
const onLogout = () => {
Taro.showModal({
@@ -28,41 +28,6 @@ const UserCell = () => {
<>
<View className={'px-4'}>
{/*是否分销商*/}
{!hasRole('dealer') && !isAdmin() && (
<Cell
className="nutui-cell-clickable"
style={{
backgroundImage: 'linear-gradient(to right bottom, #54a799, #177b73)',
}}
title={
<View style={{display: 'inline-flex', alignItems: 'center'}} onClick={() => navTo('/dealer/index', true)}>
<Reward className={'text-orange-100 '} size={16}/>
<Text style={{fontSize: '16px'}} className={'pl-3 text-orange-100 font-medium'}></Text>
<Text className={'text-white opacity-80 pl-3'}></Text>
</View>
}
extra={<ArrowRight color="#cccccc" size={18}/>}
/>
)}
{/*是否管理员*/}
{isAdmin() && (
<Cell
className="nutui-cell-clickable"
style={{
backgroundImage: 'linear-gradient(to right bottom, #ff8e0c, #ed680d)',
}}
title={
<View style={{display: 'inline-flex', alignItems: 'center'}} onClick={() => navTo('/admin/article/index', true)}>
<Setting className={'text-orange-100 '} size={16}/>
<Text style={{fontSize: '16px'}} className={'pl-3 text-orange-100 font-medium'}></Text>
</View>
}
extra={<ArrowRight color="#cccccc" size={18}/>}
/>
)}
<Cell.Group divider={true} description={
<View style={{display: 'inline-flex', alignItems: 'center'}}>
<Text style={{marginTop: '12px'}}></Text>

View File

@@ -5,6 +5,7 @@ import UserCell from "./components/UserCell";
import UserFooter from "./components/UserFooter";
import {useUser} from "@/hooks/useUser";
import './user.scss'
import IsDealer from "./components/IsDealer";
function User() {
const {
@@ -24,6 +25,7 @@ function User() {
}}>
<UserCard/>
<UserOrder/>
<IsDealer/>
<UserCell/>
<UserFooter/>
</div>
@@ -37,6 +39,7 @@ function User() {
}}>
<UserCard/>
<UserOrder/>
<IsDealer/>
<UserCell/>
<UserFooter/>
</div>