From 27ff0a8fe751e3900b4352b69b3f259798cce087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Tue, 26 Aug 2025 19:39:11 +0800 Subject: [PATCH] =?UTF-8?q?refactor(user):=20=E9=87=8D=E6=9E=84=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E9=A1=B5=E9=9D=A2=E5=B9=B6=E6=B7=BB=E5=8A=A0=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E5=88=B7=E6=96=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 HeaderWithHook 和 IndexWithHook 组件 - 优化了 UserCard 组件,使用 forwardRef 和 useImperativeHandle暴露刷新方法 - 在 User 页面中添加 PullToRefresh组件实现下拉刷新 -集成了 useUserData 钩子用于刷新用户数据 --- src/pages/index/HeaderWithHook.tsx | 227 ------------------------- src/pages/index/IndexWithHook.tsx | 189 -------------------- src/pages/user/components/UserCard.tsx | 47 +---- src/pages/user/user.tsx | 52 ++++-- 4 files changed, 45 insertions(+), 470 deletions(-) delete mode 100644 src/pages/index/HeaderWithHook.tsx delete mode 100644 src/pages/index/IndexWithHook.tsx diff --git a/src/pages/index/HeaderWithHook.tsx b/src/pages/index/HeaderWithHook.tsx deleted file mode 100644 index 07523cf..0000000 --- a/src/pages/index/HeaderWithHook.tsx +++ /dev/null @@ -1,227 +0,0 @@ -import {useEffect, useState} from "react"; -import Taro from '@tarojs/taro'; -import {Button, Space} from '@nutui/nutui-react-taro' -import {TriangleDown} from '@nutui/icons-react-taro' -import {Popup, Avatar, NavBar} from '@nutui/nutui-react-taro' -import {getUserInfo, getWxOpenId} from "@/api/layout"; -import {TenantId} from "@/config/app"; -import {getOrganization} from "@/api/system/organization"; -import {myUserVerify} from "@/api/system/userVerify"; -import {User} from "@/api/system/user/model"; -import { useShopInfo } from '@/hooks/useShopInfo'; -import { useUser } from '@/hooks/useUser'; -import {handleInviteRelation, getStoredInviteParams} from "@/utils/invite"; -import MySearch from "./MySearch"; -import './Header.scss'; - -const Header = (props: any) => { - // 使用新的hooks - const { - shopInfo, - loading: shopLoading, - getWebsiteName, - getWebsiteLogo - } = useShopInfo(); - - const { - user, - isLoggedIn, - loading: userLoading - } = useUser(); - - const [showBasic, setShowBasic] = useState(false) - const [statusBarHeight, setStatusBarHeight] = useState() - - const reload = async () => { - Taro.getSystemInfo({ - success: (res) => { - setStatusBarHeight(res.statusBarHeight) - }, - }) - - // 注意:商店信息现在通过useShopInfo自动管理,不需要手动获取 - // 用户信息现在通过useUser自动管理,不需要手动获取 - - // 如果需要获取openId,可以在用户登录后处理 - if (user && !user.openid) { - Taro.login({ - success: (res) => { - getWxOpenId({code: res.code}).then(() => { - console.log('OpenId获取成功'); - }) - } - }) - } - - // 检查用户认证状态 - if (user?.userId) { - // 获取组织信息 - getOrganization({userId: user.userId}).then((data) => { - console.log('组织信息>>>', data) - }).catch(() => { - console.log('获取组织信息失败') - }); - - // 检查用户认证 - myUserVerify({userId: user.userId}).then((data) => { - console.log('认证信息>>>', data) - }).catch(() => { - console.log('获取认证信息失败') - }); - } - } - - // 获取手机号授权 - const handleGetPhoneNumber = ({detail}: {detail: {code?: string, encryptedData?: string, iv?: string}}) => { - const {code, encryptedData, iv} = detail - - // 获取存储的邀请参数 - const inviteParams = getStoredInviteParams() - const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter) : 0 - - Taro.login({ - success: function () { - if (code) { - Taro.request({ - url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', - method: 'POST', - data: { - code, - encryptedData, - iv, - notVerifyPhone: true, - refereeId: refereeId, // 使用解析出的推荐人ID - sceneType: 'save_referee', - tenantId: TenantId - }, - success: async function (res) { - if (res.data.code == 1) { - Taro.showToast({ - title: res.data.message, - icon: 'error', - duration: 2000 - }) - return false; - } - // 登录成功 - Taro.setStorageSync('access_token', res.data.data.access_token) - Taro.setStorageSync('UserId', res.data.data.user.userId) - - // 处理邀请关系 - if (res.data.data.user?.userId) { - try { - const inviteSuccess = await handleInviteRelation(res.data.data.user.userId) - if (inviteSuccess) { - Taro.showToast({ - title: '邀请关系建立成功', - icon: 'success', - duration: 2000 - }) - } - } catch (error) { - console.error('处理邀请关系失败:', error) - } - } - - // 重新加载小程序 - Taro.reLaunch({ - url: '/pages/index/index' - }) - } - }) - } else { - console.log('登录失败!') - } - } - }) - } - - useEffect(() => { - reload().then() - }, []) - - // 显示加载状态 - if (shopLoading || userLoading) { - return ( -
-
- 加载中... -
-
- ); - } - - return ( - <> -
- -
- { - }} - left={ - !isLoggedIn ? ( -
- - -
- ) : ( -
- - {getWebsiteName()} - -
- )}> -
- { - setShowBasic(false) - }} - > -
-

商店信息

-
网站名称: {getWebsiteName()}
-
Logo: logo
- -

用户信息

-
登录状态: {isLoggedIn ? '已登录' : '未登录'}
- {user && ( - <> -
用户ID: {user.userId}
-
手机号: {user.phone}
-
昵称: {user.nickname}
- - )} - - -
-
- - ) -} - -export default Header; diff --git a/src/pages/index/IndexWithHook.tsx b/src/pages/index/IndexWithHook.tsx deleted file mode 100644 index c537314..0000000 --- a/src/pages/index/IndexWithHook.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import Header from './Header'; -import BestSellers from './BestSellers'; -import Taro from '@tarojs/taro'; -import {useShareAppMessage, useShareTimeline} from "@tarojs/taro" -import {useEffect, useState} from "react"; -import {Sticky} from '@nutui/nutui-react-taro' -import { useShopInfo } from '@/hooks/useShopInfo'; -import { useUser } from '@/hooks/useUser'; -import Menu from "./Menu"; -import Banner from "./Banner"; -import './index.scss' - -const Home = () => { - const [stickyStatus, setStickyStatus] = useState(false); - - // 使用新的hooks - const { - shopInfo, - loading: shopLoading, - error: shopError, - getWebsiteName, - getWebsiteLogo, - refreshShopInfo - } = useShopInfo(); - - const { - user, - isLoggedIn, - loading: userLoading - } = useUser(); - - const onSticky = (args: any) => { - setStickyStatus(args[0].isFixed); - }; - - const showAuthModal = () => { - Taro.showModal({ - title: '授权提示', - content: '需要获取您的用户信息', - confirmText: '去授权', - cancelText: '取消', - success: (res) => { - if (res.confirm) { - // 用户点击确认,打开授权设置页面 - Taro.openSetting({ - success: (settingRes) => { - if (settingRes.authSetting['scope.userInfo']) { - console.log('用户已授权'); - } else { - console.log('用户拒绝授权'); - } - } - }); - } - } - }); - }; - - // 分享给好友 - useShareAppMessage(() => { - return { - title: `${getWebsiteName()} - 精选商城`, - path: '/pages/index/index', - imageUrl: getWebsiteLogo(), - success: function (res: any) { - console.log('分享成功', res); - Taro.showToast({ - title: '分享成功', - icon: 'success', - duration: 2000 - }); - }, - fail: function (res: any) { - console.log('分享失败', res); - Taro.showToast({ - title: '分享失败', - icon: 'none', - duration: 2000 - }); - } - }; - }); - - // 分享到朋友圈 - useShareTimeline(() => { - return { - title: `${getWebsiteName()} - 精选商城`, - imageUrl: getWebsiteLogo(), - success: function (res: any) { - console.log('分享到朋友圈成功', res); - }, - fail: function (res: any) { - console.log('分享到朋友圈失败', res); - } - }; - }); - - useEffect(() => { - // 设置页面标题 - if (shopInfo?.appName) { - Taro.setNavigationBarTitle({ - title: shopInfo.appName - }); - } - }, [shopInfo]); - - useEffect(() => { - // 检查用户授权状态 - Taro.getSetting({ - success: (res) => { - if (res.authSetting['scope.userInfo']) { - console.log('用户已经授权过,可以直接获取用户信息'); - } else { - console.log('用户未授权,需要弹出授权窗口'); - showAuthModal(); - } - } - }); - - // 获取用户基本信息(头像、昵称等) - Taro.getUserInfo({ - success: (res) => { - const avatar = res.userInfo.avatarUrl; - console.log('用户头像:', avatar); - }, - fail: (err) => { - console.log('获取用户信息失败:', err); - } - }); - }, []); - - // 处理错误状态 - if (shopError) { - return ( -
-
加载商店信息失败: {shopError}
- -
- ); - } - - // 显示加载状态 - if (shopLoading) { - return ( -
-
加载中...
-
- ); - } - - return ( - <> - onSticky(args)}> -
- -
- - - - - {/* 调试信息面板 - 仅在开发环境显示 */} - {process.env.NODE_ENV === 'development' && ( -
-
商店: {getWebsiteName()}
-
用户: {isLoggedIn ? (user?.nickname || '已登录') : '未登录'}
-
加载: {userLoading ? '用户加载中' : '已完成'}
-
- )} -
- - ) -} - -export default Home; diff --git a/src/pages/user/components/UserCard.tsx b/src/pages/user/components/UserCard.tsx index 1f856e7..def1e74 100644 --- a/src/pages/user/components/UserCard.tsx +++ b/src/pages/user/components/UserCard.tsx @@ -4,16 +4,15 @@ import {View, Text} from '@tarojs/components' import {Scan} from '@nutui/icons-react-taro'; import {getUserInfo, getWxOpenId} from '@/api/layout'; import Taro from '@tarojs/taro'; -import {useEffect, useState} from "react"; +import {useEffect, useState, forwardRef, useImperativeHandle} from "react"; import {User} from "@/api/system/user/model"; import navTo from "@/utils/common"; import {TenantId} from "@/config/app"; -import {getMyAvailableCoupons} from "@/api/shop/shopUserCoupon"; import {useUser} from "@/hooks/useUser"; import {useUserData} from "@/hooks/useUserData"; import {getStoredInviteParams} from "@/utils/invite"; -function UserCard() { +const UserCard = forwardRef((_, ref) => { const { isAdmin } = useUser(); @@ -21,9 +20,6 @@ function UserCard() { const {getDisplayName, getRoleName} = useUser(); const [IsLogin, setIsLogin] = useState(false) const [userInfo, setUserInfo] = useState() - const [couponCount, setCouponCount] = useState(0) - const [pointsCount, setPointsCount] = useState(0) - const [giftCount, setGiftCount] = useState(0) // 下拉刷新 const handleRefresh = async () => { @@ -34,6 +30,11 @@ function UserCard() { }) } + // 暴露方法给父组件 + useImperativeHandle(ref, () => ({ + handleRefresh + })) + useEffect(() => { // Taro.getSetting:获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。 Taro.getSetting({ @@ -51,33 +52,6 @@ function UserCard() { }); }, []); - const loadUserStats = (userId: number) => { - // 加载优惠券数量 - getMyAvailableCoupons() - .then((coupons: any) => { - setCouponCount(coupons?.length || 0) - }) - .catch((error: any) => { - console.error('Coupon count error:', error) - }) - - // 加载积分数量 - console.log(userId) - setPointsCount(0) - // getUserPointsStats(userId) - // .then((res: any) => { - // setPointsCount(res.currentPoints || 0) - // }) - // .catch((error: any) => { - // console.error('Points stats error:', error) - // }) - // 加载礼品劵数量 - setGiftCount(0) - // pageUserGiftLog({userId, page: 1, limit: 1}).then(res => { - // setGiftCount(res.count || 0) - // }) - } - const reload = () => { Taro.getUserInfo({ success: (res) => { @@ -93,11 +67,6 @@ function UserCard() { setIsLogin(true); Taro.setStorageSync('UserId', data.userId) - // 加载用户统计数据 - if (data.userId) { - loadUserStats(data.userId) - } - // 获取openId if (!data.openid) { Taro.login({ @@ -268,6 +237,6 @@ function UserCard() { ) -} +}) export default UserCard; diff --git a/src/pages/user/user.tsx b/src/pages/user/user.tsx index da20805..c4f4930 100644 --- a/src/pages/user/user.tsx +++ b/src/pages/user/user.tsx @@ -1,9 +1,11 @@ -import {useEffect} from 'react' +import {useEffect, useRef} from 'react' +import {PullToRefresh} from '@nutui/nutui-react-taro' import UserCard from "./components/UserCard"; import UserOrder from "./components/UserOrder"; import UserCell from "./components/UserCell"; import UserFooter from "./components/UserFooter"; import {useUser} from "@/hooks/useUser"; +import {useUserData} from "@/hooks/useUserData"; import './user.scss' import IsDealer from "./components/IsDealer"; @@ -12,6 +14,18 @@ function User() { isAdmin } = useUser(); + const { refresh } = useUserData() + const userCardRef = useRef() + + // 下拉刷新处理 + const handleRefresh = async () => { + await refresh() + // 如果 UserCard 组件有自己的刷新方法,也可以调用 + if (userCardRef.current?.handleRefresh) { + await userCardRef.current.handleRefresh() + } + } + useEffect(() => { }, []); @@ -19,31 +33,39 @@ function User() { * 门店核销管理 */ if (isAdmin()) { - return <> -
- - - - - -
- + return ( + +
+ + + + + +
+
+ ) } return ( - <> +
- +
- +
) }