From 0a10afcea26dbc8560c75d3b3623dcb82ba69a35 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com>
Date: Wed, 10 Sep 2025 16:29:58 +0800
Subject: [PATCH] =?UTF-8?q?feat(user):=20=E5=AE=9E=E7=8E=B0=E8=87=AA?=
=?UTF-8?q?=E5=8A=A8=E7=99=BB=E5=BD=95=E5=B9=B6=E4=BC=98=E5=8C=96=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 添加自动登录功能,通过 OpenID 实现一键登录
- 优化用户数据加载和保存逻辑,确保数据完整性
- 处理邀请关系,自动登录时建立邀请关系
- 更新订单统计钩子,增加用户身份检查
- 修复首页轮播图点击事件,实现跳转功能
---
src/admin/index.tsx | 12 ++++-
src/hooks/useOrderStats.ts | 3 ++
src/hooks/useUser.ts | 105 +++++++++++++++++++++++++++++++++----
src/pages/index/Banner.tsx | 5 +-
4 files changed, 113 insertions(+), 12 deletions(-)
diff --git a/src/admin/index.tsx b/src/admin/index.tsx
index 8fd127e..16f0cab 100644
--- a/src/admin/index.tsx
+++ b/src/admin/index.tsx
@@ -1,5 +1,6 @@
import {useEffect} from 'react'
import {useUser} from "@/hooks/useUser";
+import {Empty} from '@nutui/nutui-react-taro';
import {Text} from '@tarojs/components';
function Admin() {
@@ -12,7 +13,16 @@ function Admin() {
if (!isAdmin()) {
return (
- 您不是管理员
+
+
+
);
}
return (
diff --git a/src/hooks/useOrderStats.ts b/src/hooks/useOrderStats.ts
index 14b4c05..a26c29e 100644
--- a/src/hooks/useOrderStats.ts
+++ b/src/hooks/useOrderStats.ts
@@ -28,6 +28,9 @@ export const useOrderStats = () => {
setLoading(true);
setError(null);
+ if(!Taro.getStorageSync('UserId')){
+ return false;
+ }
// TODO 读取订单数量
const pending = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 0})
const paid = await pageShopOrder({ page: 1, limit: 1, userId: Taro.getStorageSync('UserId'), statusFilter: 1})
diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts
index 4bd8304..479a0f3 100644
--- a/src/hooks/useUser.ts
+++ b/src/hooks/useUser.ts
@@ -1,7 +1,9 @@
import { useState, useEffect } from 'react';
import Taro from '@tarojs/taro';
import { User } from '@/api/system/user/model';
-import { getUserInfo, updateUserInfo } from '@/api/layout';
+import { getUserInfo, updateUserInfo, loginByOpenId } from '@/api/layout';
+import { TenantId } from '@/config/app';
+import {getStoredInviteParams, handleInviteRelation} from '@/utils/invite';
// 用户Hook
export const useUser = () => {
@@ -9,8 +11,62 @@ export const useUser = () => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [loading, setLoading] = useState(true);
+ // 自动登录(通过OpenID)
+ const autoLoginByOpenId = async () => {
+ try {
+ const res = await new Promise((resolve, reject) => {
+ Taro.login({
+ success: (loginRes) => {
+ loginByOpenId({
+ code: loginRes.code,
+ tenantId: TenantId
+ }).then(async (data) => {
+ if (data) {
+ // 保存登录信息
+ saveUserToStorage(data.access_token, data.user);
+ setUser(data.user);
+ setIsLoggedIn(true);
+
+ // 处理邀请关系
+ if (data.user?.userId) {
+ try {
+ const inviteSuccess = await handleInviteRelation(data.user.userId);
+ if (inviteSuccess) {
+ console.log('自动登录时邀请关系建立成功');
+ }
+ } catch (error) {
+ console.error('自动登录时处理邀请关系失败:', error);
+ }
+ }
+
+ resolve(data.user);
+ } else {
+ reject(new Error('自动登录失败'));
+ }
+ }).catch(_ => {
+ // 首次注册,跳转到邀请注册页面
+ const pages = Taro.getCurrentPages();
+ const currentPage = pages[pages.length - 1];
+ const inviteParams = getStoredInviteParams()
+ if (currentPage?.route !== 'dealer/apply/add' && inviteParams?.inviter) {
+ return Taro.navigateTo({
+ url: '/dealer/apply/add'
+ });
+ }
+ });
+ },
+ fail: reject
+ });
+ });
+ return res;
+ } catch (error) {
+ console.error('自动登录失败:', error);
+ return null;
+ }
+ };
+
// 从本地存储加载用户数据
- const loadUserFromStorage = () => {
+ const loadUserFromStorage = async () => {
try {
const token = Taro.getStorageSync('access_token');
const userData = Taro.getStorageSync('User');
@@ -26,8 +82,13 @@ export const useUser = () => {
setIsLoggedIn(true);
setUser({ userId, tenantId } as User);
} else {
- setUser(null);
- setIsLoggedIn(false);
+ // 没有本地登录信息,尝试自动登录
+ console.log('没有本地登录信息,尝试自动登录...');
+ const autoLoginResult = await autoLoginByOpenId();
+ if (!autoLoginResult) {
+ setUser(null);
+ setIsLoggedIn(false);
+ }
}
} catch (error) {
console.error('加载用户数据失败:', error);
@@ -43,9 +104,24 @@ export const useUser = () => {
try {
Taro.setStorageSync('access_token', token);
Taro.setStorageSync('User', userInfo);
- Taro.setStorageSync('UserId', userInfo.userId);
- Taro.setStorageSync('TenantId', userInfo.tenantId);
- Taro.setStorageSync('Phone', userInfo.phone);
+
+ // 确保关键字段不为空时才保存,避免覆盖现有数据
+ if (userInfo.userId) {
+ Taro.setStorageSync('UserId', userInfo.userId);
+ }
+ if (userInfo.tenantId) {
+ Taro.setStorageSync('TenantId', userInfo.tenantId);
+ }
+ if (userInfo.phone) {
+ Taro.setStorageSync('Phone', userInfo.phone);
+ }
+ // 保存头像和昵称信息
+ if (userInfo.avatar) {
+ Taro.setStorageSync('Avatar', userInfo.avatar);
+ }
+ if (userInfo.nickname) {
+ Taro.setStorageSync('Nickname', userInfo.nickname);
+ }
} catch (error) {
console.error('保存用户数据失败:', error);
}
@@ -114,9 +190,16 @@ export const useUser = () => {
}
try {
- const updatedUser = { ...user, ...userData };
+ // 先获取最新的用户信息,确保我们有完整的数据
+ const latestUserInfo = await getUserInfo();
+
+ // 合并最新的用户信息和要更新的数据
+ const updatedUser = { ...latestUserInfo, ...userData };
+
+ // 调用API更新用户信息
await updateUserInfo(updatedUser);
+ // 更新本地状态
setUser(updatedUser);
// 更新本地存储
@@ -216,7 +299,10 @@ export const useUser = () => {
// 初始化时加载用户数据
useEffect(() => {
- loadUserFromStorage();
+ loadUserFromStorage().catch(error => {
+ console.error('初始化用户数据失败:', error);
+ setLoading(false);
+ });
}, []);
return {
@@ -231,6 +317,7 @@ export const useUser = () => {
fetchUserInfo,
updateUser,
loadUserFromStorage,
+ autoLoginByOpenId,
// 工具方法
hasPermission,
diff --git a/src/pages/index/Banner.tsx b/src/pages/index/Banner.tsx
index 7f3942d..4a07466 100644
--- a/src/pages/index/Banner.tsx
+++ b/src/pages/index/Banner.tsx
@@ -3,6 +3,7 @@ import { Swiper } from '@nutui/nutui-react-taro'
import {CmsAd} from "@/api/cms/cmsAd/model";
import {Image} from '@nutui/nutui-react-taro'
import {getCmsAd} from "@/api/cms/cmsAd";
+import navTo from "@/utils/common";
const MyPage = () => {
const [item, setItem] = useState()
@@ -18,10 +19,10 @@ const MyPage = () => {
return (
<>
-
+
{item?.imageList?.map((item) => (
-
+ navTo(`${item.path}`)} lazyLoad={false} style={{ height: item.height + 'px' }} />
))}