From 13b3d6407b0886a72786ffe465cbf4d35b96107d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Mon, 18 Aug 2025 01:18:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(dealer):=20=E6=B7=BB=E5=8A=A0=E7=BB=8F?= =?UTF-8?q?=E9=94=80=E5=95=86=E7=94=B3=E8=AF=B7=E5=8A=9F=E8=83=BD=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=94=A8=E6=88=B7=E7=9B=B8=E5=85=B3=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增经销商申请页面和相关组件- 更新用户中心页面,增加经销商状态显示和申请入口 - 修改登录逻辑,支持获取用户手机号- 优化用户钩子,增加获取用户ID和判断超级管理员权限的功能 --- src/api/shop/shopDealerApply/model/index.ts | 2 + src/api/shop/shopDealerUser/model/index.ts | 2 + src/app.config.ts | 1 + src/components/FixedButton.tsx | 14 +- src/dealer/apply/add.config.ts | 4 + src/dealer/apply/add.tsx | 187 ++++++++++++++++++++ src/hooks/useUser.ts | 12 +- src/pages/index/Login.tsx | 37 +++- src/pages/user/components/IsDealer.tsx | 121 +++++++++++++ src/pages/user/components/UserCell.tsx | 39 +--- src/pages/user/user.tsx | 3 + 11 files changed, 376 insertions(+), 46 deletions(-) create mode 100644 src/dealer/apply/add.config.ts create mode 100644 src/dealer/apply/add.tsx create mode 100644 src/pages/user/components/IsDealer.tsx diff --git a/src/api/shop/shopDealerApply/model/index.ts b/src/api/shop/shopDealerApply/model/index.ts index f181689..8ea27cc 100644 --- a/src/api/shop/shopDealerApply/model/index.ts +++ b/src/api/shop/shopDealerApply/model/index.ts @@ -37,5 +37,7 @@ export interface ShopDealerApply { */ export interface ShopDealerApplyParam extends PageParam { applyId?: number; + mobile?: string; + userId?: number; keywords?: string; } diff --git a/src/api/shop/shopDealerUser/model/index.ts b/src/api/shop/shopDealerUser/model/index.ts index 98c904f..2af5f3f 100644 --- a/src/api/shop/shopDealerUser/model/index.ts +++ b/src/api/shop/shopDealerUser/model/index.ts @@ -45,5 +45,7 @@ export interface ShopDealerUser { */ export interface ShopDealerUserParam extends PageParam { id?: number; + phone?: string; + userId?: number; keywords?: string; } diff --git a/src/app.config.ts b/src/app.config.ts index 8a884d7..0feffcd 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -50,6 +50,7 @@ export default defineAppConfig({ "root": "dealer", "pages": [ "index", + "apply/add", "withdraw/index", "orders/index", "team/index", diff --git a/src/components/FixedButton.tsx b/src/components/FixedButton.tsx index cf41943..0757d26 100644 --- a/src/components/FixedButton.tsx +++ b/src/components/FixedButton.tsx @@ -1,11 +1,18 @@ +import React from 'react'; import {View} from '@tarojs/components'; import {Button} from '@nutui/nutui-react-taro' -function FixedButton({text, onClick, icon}) { +interface FixedButtonProps { + text?: string; + onClick?: () => void; + icon?: React.ReactNode; + disabled?: boolean; +} + +function FixedButton({text, onClick, icon, disabled}: FixedButtonProps) { return ( <> - {/* 底部安全区域占位 */ - } + {/* 底部安全区域占位 */} @@ -14,6 +21,7 @@ function FixedButton({text, onClick, icon}) { size="large" block icon={icon} + disabled={disabled} className="px-6" onClick={onClick}> {text || '新增'} diff --git a/src/dealer/apply/add.config.ts b/src/dealer/apply/add.config.ts new file mode 100644 index 0000000..682bd9c --- /dev/null +++ b/src/dealer/apply/add.config.ts @@ -0,0 +1,4 @@ +export default definePageConfig({ + navigationBarTitleText: '注册成为经销商', + navigationBarTextStyle: 'black' +}) diff --git a/src/dealer/apply/add.tsx b/src/dealer/apply/add.tsx new file mode 100644 index 0000000..3aaddf0 --- /dev/null +++ b/src/dealer/apply/add.tsx @@ -0,0 +1,187 @@ +import {useEffect, useState, useRef} from "react"; +import {Loading, CellGroup, Cell, Input, Form} 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 {ShopDealerApply} from "@/api/shop/shopDealerApply/model"; +import { + addShopDealerApply, + pageShopDealerApply, + updateShopDealerApply +} from "@/api/shop/shopDealerApply"; + +const AddUserAddress = () => { + const {user} = useUser() + const [loading, setLoading] = useState(true) + const [FormData, setFormData] = useState({}) + const formRef = useRef(null) + const [isEditMode, setIsEditMode] = useState(false) + const [existingApply, setExistingApply] = useState(null) + + // 获取审核状态文字 + const getApplyStatusText = (status?: number) => { + switch (status) { + case 10: + return '待审核' + case 20: + return '审核通过' + case 30: + return '驳回' + default: + return '未知状态' + } + } + + const reload = async () => { + // 判断用户是否登录 + if(!user?.userId){ + return false; + } + // 查询当前用户ID是否已有申请记录 + try { + const res = await pageShopDealerApply({userId: user?.userId}); + if (res && res.count > 0) { + setIsEditMode(true); + setExistingApply(res.list[0]); + // 如果有记录,填充表单数据 + setFormData(res.list[0]); + } else { + setFormData({}) + setIsEditMode(false); + setExistingApply(null); + } + } catch (error) { + console.error('查询申请记录失败:', error); + setIsEditMode(false); + setExistingApply(null); + setFormData({}) + } + } + + // 提交表单 + const submitSucceed = async (values: any) => { + try { + // 准备提交的数据 + const submitData = { + ...values, + realName: values.realName || user?.nickname, + mobile: user?.phone, + refereeId: values.refereeId, + applyStatus: 10, + auditTime: undefined + }; + + // 如果是编辑模式,添加现有申请的id + if (isEditMode && existingApply?.applyId) { + submitData.applyId = existingApply.applyId; + } + + // 执行新增或更新操作 + if (isEditMode) { + await updateShopDealerApply(submitData); + } else { + await addShopDealerApply(submitData); + } + + Taro.showToast({ + title: `${isEditMode ? '更新' : '保存'}成功`, + icon: 'success' + }); + + setTimeout(() => { + Taro.navigateBack(); + }, 1000); + + } catch (error) { + console.error('保存失败:', error); + Taro.showToast({ + title: `${isEditMode ? '更新' : '保存'}失败`, + icon: 'error' + }); + } + } + + // 处理固定按钮点击事件 + const handleFixedButtonClick = () => { + // 触发表单提交 + formRef.current?.submit(); + }; + + const submitFailed = (error: any) => { + console.log(error, 'err...') + } + + useEffect(() => { + reload().then(() => { + setLoading(false) + }) + }, [user?.userId]); // 依赖用户ID,当用户变化时重新加载 + + if (loading) { + return 加载中 + } + + return ( + <> +
submitSucceed(values)} + onFinishFailed={(errors) => submitFailed(errors)} + > + + + + + + + + + + + + +
+ {/* 审核状态显示(仅在编辑模式下显示) */} + {isEditMode && ( + + + {getApplyStatusText(FormData.applyStatus)} + + } + /> + {FormData.applyStatus === 20 && ( + + )} + {FormData.applyStatus === 30 && ( + + )} + + )} + + + {/* 底部浮动按钮 */} + {(!isEditMode || FormData.applyStatus === 10 || FormData.applyStatus === 30) && ( + } + text={isEditMode ? '保存修改' : '提交申请'} + disabled={FormData.applyStatus === 10} + onClick={handleFixedButtonClick} + /> + )} + + + ); +}; + +export default AddUserAddress; diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts index 85607c4..4bd8304 100644 --- a/src/hooks/useUser.ts +++ b/src/hooks/useUser.ts @@ -164,6 +164,10 @@ export const useUser = () => { return user?.avatar || user?.avatarUrl || ''; }; + const getUserId = () => { + return user?.userId; + }; + // 获取用户显示名称 const getDisplayName = () => { return user?.nickname || user?.realName || user?.username || '未登录'; @@ -196,6 +200,10 @@ export const useUser = () => { return user?.isAdmin === true; }; + const isSuperAdmin = () => { + return user?.isSuperAdmin === true; + }; + // 获取用户余额 const getBalance = () => { return user?.balance || 0; @@ -233,6 +241,8 @@ export const useUser = () => { isCertified, isAdmin, getBalance, - getPoints + getPoints, + getUserId, + isSuperAdmin }; }; diff --git a/src/pages/index/Login.tsx b/src/pages/index/Login.tsx index ef06a95..d5cbbc6 100644 --- a/src/pages/index/Login.tsx +++ b/src/pages/index/Login.tsx @@ -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() /* 获取用户手机号 */ - 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 { diff --git a/src/pages/user/components/IsDealer.tsx b/src/pages/user/components/IsDealer.tsx new file mode 100644 index 0000000..1e968a5 --- /dev/null +++ b/src/pages/user/components/IsDealer.tsx @@ -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(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 ( + <> + + navTo('/admin/index', true)}> + + 管理中心 + + } + extra={} + /> +
+ + ) + } + + /** + * 分销中心 + */ + if (isDealer) { + return ( + <> + + navTo('/dealer/index', true)}> + + 分销中心 + 门店核销 + + } + extra={} + /> + + + ) + } + + /** + * 分销中心 + */ + return ( + <> + + + + 成为经销商 + 享优惠 + + } + extra={} + onClick={() => navTo('/dealer/apply/add', true)} + /> + + + ) +} +export default UserCell diff --git a/src/pages/user/components/UserCell.tsx b/src/pages/user/components/UserCell.tsx index 1991619..412edb8 100644 --- a/src/pages/user/components/UserCell.tsx +++ b/src/pages/user/components/UserCell.tsx @@ -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 = () => { <> - {/*是否分销商*/} - {!hasRole('dealer') && !isAdmin() && ( - navTo('/dealer/index', true)}> - - 开通会员 - 享优惠 - - } - extra={} - /> - )} - - {/*是否管理员*/} - {isAdmin() && ( - navTo('/admin/article/index', true)}> - - 管理中心 - - } - extra={} - /> - )} - 我的服务 diff --git a/src/pages/user/user.tsx b/src/pages/user/user.tsx index f67404d..da20805 100644 --- a/src/pages/user/user.tsx +++ b/src/pages/user/user.tsx @@ -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() { }}> + @@ -37,6 +39,7 @@ function User() { }}> +