diff --git a/config/env.ts b/config/env.ts index c3f95e2..de8e281 100644 --- a/config/env.ts +++ b/config/env.ts @@ -2,7 +2,7 @@ export const ENV_CONFIG = { // 开发环境 development: { - API_BASE_URL: 'http://127.0.0.1:9200/api', + API_BASE_URL: 'https://cms-api.websoft.top/api', APP_NAME: '开发环境', DEBUG: 'true', }, diff --git a/src/components/UniversalScanner.tsx b/src/components/UniversalScanner.tsx index 3ae4b0d..9f01c24 100644 --- a/src/components/UniversalScanner.tsx +++ b/src/components/UniversalScanner.tsx @@ -27,7 +27,7 @@ export function useUniversalScanner(props: UniversalScannerProps = {}) { showToast = true } = props; - const { user, isLoggedIn, isAdmin, loginUser } = useUser(); + const { user, isLoggedIn, isAdmin } = useUser(); /** * 启动扫码 @@ -95,7 +95,7 @@ export function useUniversalScanner(props: UniversalScannerProps = {}) { } catch (error) { console.error('处理扫码结果失败:', error); - const errorMsg = error.message || '处理扫码结果失败'; + const errorMsg = error instanceof Error ? error.message : '处理扫码结果失败'; if (showToast) { Taro.showToast({ title: errorMsg, @@ -157,7 +157,6 @@ export function useUniversalScanner(props: UniversalScannerProps = {}) { platform: 'miniprogram', wechatInfo: { openid: user?.openid, - unionid: user?.unionid, nickname: user?.nickname || user?.realName, avatar: user?.avatar } @@ -194,12 +193,13 @@ export function useUniversalScanner(props: UniversalScannerProps = {}) { // 根据错误类型显示不同的提示 let errorMessage = '登录确认失败'; - if (error.message?.includes('过期')) { + const errorMsg = error instanceof Error ? error.message : ''; + if (errorMsg?.includes('过期')) { errorMessage = '二维码已过期,请重新生成'; - } else if (error.message?.includes('无效')) { + } else if (errorMsg?.includes('无效')) { errorMessage = '无效的登录二维码'; - } else if (error.message) { - errorMessage = error.message; + } else if (errorMsg) { + errorMessage = errorMsg; } if (showToast) { @@ -294,10 +294,12 @@ export function useUniversalScanner(props: UniversalScannerProps = {}) { */ const UniversalScanner: React.FC = (props) => { const { startScan } = useUniversalScanner(props); - + console.log(startScan,'startScan333') // 这个组件主要提供Hook,不渲染UI // 如果需要可以返回一个扫码按钮 return null; }; + + export default UniversalScanner; diff --git a/src/dealer/team/index.tsx b/src/dealer/team/index.tsx index a62b934..a175970 100644 --- a/src/dealer/team/index.tsx +++ b/src/dealer/team/index.tsx @@ -1,6 +1,6 @@ import React, {useState, useEffect, useCallback} from 'react' import {View, Text} from '@tarojs/components' -import {Space,Empty, Avatar} from '@nutui/nutui-react-taro' +import {Space,Empty, Avatar, Button} from '@nutui/nutui-react-taro' import Taro from '@tarojs/taro' import {useDealerUser} from '@/hooks/useDealerUser' import {listShopDealerReferee} from '@/api/shop/shopDealerReferee' @@ -24,16 +24,29 @@ interface TeamMemberWithStats extends ShopDealerReferee { dealerPhone?: string; } +// 层级信息接口 +interface LevelInfo { + dealerId: number + dealerName?: string + level: number +} + const DealerTeam: React.FC = () => { const [teamMembers, setTeamMembers] = useState([]) const {dealerUser} = useDealerUser() const [dealerId, setDealerId] = useState() + // 层级栈,用于支持返回上一层 + const [levelStack, setLevelStack] = useState([]) + const [loading, setLoading] = useState(false) + // 当前查看的用户名称 + const [currentDealerName, setCurrentDealerName] = useState('') // 获取团队数据 const fetchTeamData = useCallback(async () => { if (!dealerUser?.userId && !dealerId) return try { + setLoading(true) console.log(dealerId, 'dealerId>>>>>>>>>') // 获取团队成员关系 const refereeResult = await listShopDealerReferee({ @@ -52,20 +65,30 @@ const DealerTeam: React.FC = () => { joinTime: member.createTime })) - // 并行获取每个成员的订单统计 + // 并行获取每个成员的订单统计和下级成员数量 const memberStats = await Promise.all( processedMembers.map(async (member) => { try { + // 获取订单统计 const orderResult = await pageShopDealerOrder({ page: 1, limit: 100, userId: member.userId }) + // 获取下级成员数量 + const subMembersResult = await listShopDealerReferee({ + dealerId: member.userId + }) + + let orderCount = 0 + let commission = '0.00' + let status: 'active' | 'inactive' = 'inactive' + if (orderResult?.list) { const orders = orderResult.list - const orderCount = orders.length - const commission = orders.reduce((sum, order) => { + orderCount = orders.length + commission = orders.reduce((sum, order) => { const levelCommission = member.level === 1 ? order.firstMoney : member.level === 2 ? order.secondMoney : order.thirdMoney @@ -78,17 +101,18 @@ const DealerTeam: React.FC = () => { const hasRecentOrder = orders.some(order => new Date(order.createTime || '') > thirtyDaysAgo ) - - return { - ...member, - orderCount, - commission, - status: hasRecentOrder ? 'active' as const : 'inactive' as const - } + status = hasRecentOrder ? 'active' : 'inactive' + } + + return { + ...member, + orderCount, + commission, + status, + subMembers: subMembersResult?.length || 0 } - return member } catch (error) { - console.error(`获取成员${member.userId}订单失败:`, error) + console.error(`获取成员${member.userId}数据失败:`, error) return member } }) @@ -103,12 +127,58 @@ const DealerTeam: React.FC = () => { title: '获取团队数据失败', icon: 'error' }) + } finally { + setLoading(false) } }, [dealerUser?.userId, dealerId]) + // 查看下级成员 const getNextUser = (item: TeamMemberWithStats) => { + // 检查层级限制:最多只能查看2层(levelStack.length >= 1 表示已经是第2层了) + if (levelStack.length >= 1) { + return + } + + // 如果没有下级成员,不允许点击 + if (!item.subMembers || item.subMembers === 0) { + return + } + console.log('点击用户:', item.userId, item.name) + + // 将当前层级信息推入栈中 + const currentLevel: LevelInfo = { + dealerId: dealerId || dealerUser?.userId || 0, + dealerName: currentDealerName || (dealerId ? '上级' : dealerUser?.realName || '我'), + level: levelStack.length + } + setLevelStack(prev => [...prev, currentLevel]) + + // 切换到下级 setDealerId(item.userId) + setCurrentDealerName(item.nickname || item.dealerName || `用户${item.userId}`) + } + + // 返回上一层 + const goBack = () => { + if (levelStack.length === 0) { + // 如果栈为空,返回首页或上一页 + Taro.navigateBack() + return + } + + // 从栈中弹出上一层信息 + const prevLevel = levelStack[levelStack.length - 1] + setLevelStack(prev => prev.slice(0, -1)) + + if (prevLevel.dealerId === (dealerUser?.userId || 0)) { + // 返回到根层级 + setDealerId(undefined) + setCurrentDealerName('') + } else { + setDealerId(prevLevel.dealerId) + setCurrentDealerName(prevLevel.dealerName || '') + } } // 监听数据变化,获取团队数据 @@ -118,8 +188,25 @@ const DealerTeam: React.FC = () => { } }, [fetchTeamData]) - const renderMemberItem = (member: TeamMemberWithStats) => ( - getNextUser(member)}> + // 初始化当前用户名称 + useEffect(() => { + if (!dealerId && dealerUser?.realName && !currentDealerName) { + setCurrentDealerName(dealerUser.realName) + } + }, [dealerUser, dealerId, currentDealerName]) + + const renderMemberItem = (member: TeamMemberWithStats) => { + // 判断是否可以点击:有下级成员且未达到层级限制 + const canClick = member.subMembers && member.subMembers > 0 && levelStack.length < 1 + + return ( + getNextUser(member)} + > { {member.nickname} - {/*{getLevelIcon(Number(member.level))}*/} - {/**/} - {/* {member.level}级*/} - {/**/} + {canClick && ( + 可查看下级 + )} + {!canClick && member.subMembers && member.subMembers > 0 && levelStack.length >= 1 && ( + 已达层级限制 + )} 加入时间:{member.joinTime} - {/**/} - {/* */} - {/* {member.status === 'active' ? '活跃' : '沉默'}*/} - {/* */} - {/**/} @@ -164,20 +246,48 @@ const DealerTeam: React.FC = () => { 团队成员 - - {member.subMembers} + + {member.subMembers || 0} - ) + ) + } const renderOverview = () => ( - {teamMembers.slice(0, 3).map(renderMemberItem)} + {teamMembers.map(renderMemberItem)} ) + // 渲染顶部导航栏 + const renderHeader = () => { + if (levelStack.length === 0) return null + + return ( + + + + + {currentDealerName}的团队成员 + + + + + + ) + } + if (!dealerUser) { return ( @@ -191,7 +301,13 @@ const DealerTeam: React.FC = () => { return ( <> - {teamMembers.length > 0 ? ( + {renderHeader()} + + {loading ? ( + + 加载中... + + ) : teamMembers.length > 0 ? ( renderOverview() ) : ( @@ -206,4 +322,4 @@ const DealerTeam: React.FC = () => { ) } -export default DealerTeam +export default DealerTeam; diff --git a/src/pages/user/components/UserCard.tsx b/src/pages/user/components/UserCard.tsx index 4d55cdd..9b9bd21 100644 --- a/src/pages/user/components/UserCard.tsx +++ b/src/pages/user/components/UserCard.tsx @@ -14,10 +14,10 @@ import {useUniversalScanner} from "@/components/UniversalScanner"; function UserCard() { const { user, + isAdmin, isLoggedIn, loginUser, fetchUserInfo, - isAdmin, getDisplayName, getRoleName } = useUser(); @@ -33,6 +33,7 @@ function UserCard() { } }); + console.log(startScan, 'startScan') useEffect(() => { // Taro.getSetting:获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。 Taro.getSetting({ @@ -189,7 +190,7 @@ function UserCard() { ) } - {getDisplayName()} + {getDisplayName()} {isLoggedIn ? ( @@ -201,51 +202,12 @@ function UserCard() { ) : ''} - {isLoggedIn && ( - { - console.log('扫码按钮被点击了'); - - // 检查 Taro.scanCode 是否存在 - if (typeof Taro.scanCode === 'function') { - console.log('Taro.scanCode 函数存在'); - - // 直接测试 Taro.scanCode - Taro.scanCode({ - success: (res) => { - console.log('直接扫码成功:', res.result); - Taro.showModal({ - title: '扫码成功', - content: res.result, - showCancel: false - }); - }, - fail: (err) => { - console.error('直接扫码失败:', err); - Taro.showModal({ - title: '扫码失败', - content: `错误信息: ${JSON.stringify(err)}`, - showCancel: false - }); - } - }); - } else { - console.error('Taro.scanCode 函数不存在'); - Taro.showModal({ - title: '错误', - content: 'Taro.scanCode 函数不存在,请检查 Taro 版本', - showCancel: false - }); - } - }} - className="p-2 bg-blue-100 rounded cursor-pointer" - > - + + {isAdmin() && navTo('/user/store/verification', true)} />} + navTo('/user/profile/profile', true)}> + {'个人资料'} - )} - navTo('/user/profile/profile', true)}> - {'个人资料'} diff --git a/src/user/store/verification.tsx b/src/user/store/verification.tsx index 6ecc6a5..f6ce353 100644 --- a/src/user/store/verification.tsx +++ b/src/user/store/verification.tsx @@ -29,6 +29,8 @@ const StoreVerification: React.FC = () => { } }); + console.log(startScan,'startScan222') + // 页面加载时检查是否有传递的扫码数据 useEffect(() => { const handlePageLoad = async () => {