forked from gxwebsoft/mp-10550
- 新增邀请统计页面,包含统计概览、邀请记录和排行榜三个标签页 - 实现邀请统计数据的获取和展示,包括总邀请数、成功注册数、转化率等 - 添加邀请记录的查询和展示功能 - 实现邀请排行榜的查询和展示功能 - 新增生成小程序码和处理邀请场景值的接口
223 lines
6.6 KiB
TypeScript
223 lines
6.6 KiB
TypeScript
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} 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<number>()
|
||
|
||
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
|
||
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: 0,
|
||
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 (
|
||
<div className={'fixed top-0 header-bg'} style={{
|
||
height: !props.stickyStatus ? '180px' : '148px',
|
||
}}>
|
||
<div style={{padding: '20px', textAlign: 'center', color: '#fff'}}>
|
||
加载中...
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<div className={'fixed top-0 header-bg'} style={{
|
||
height: !props.stickyStatus ? '180px' : '148px',
|
||
}}>
|
||
<MySearch/>
|
||
</div>
|
||
<NavBar
|
||
style={{marginTop: `${statusBarHeight}px`, marginBottom: '0px', backgroundColor: 'transparent'}}
|
||
onBackClick={() => {
|
||
}}
|
||
left={
|
||
!isLoggedIn ? (
|
||
<div style={{display: 'flex', alignItems: 'center'}}>
|
||
<Button style={{color: '#000'}} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
||
<Space>
|
||
<Avatar
|
||
size="22"
|
||
src={getWebsiteLogo()}
|
||
/>
|
||
<span style={{color: '#000'}}>{getWebsiteName()}</span>
|
||
</Space>
|
||
</Button>
|
||
<TriangleDown size={9}/>
|
||
</div>
|
||
) : (
|
||
<div style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
|
||
<Avatar
|
||
size="22"
|
||
src={getWebsiteLogo()}
|
||
/>
|
||
<span className={'text-white'}>{getWebsiteName()}</span>
|
||
<TriangleDown className={'text-white'} size={9}/>
|
||
</div>
|
||
)}>
|
||
</NavBar>
|
||
<Popup
|
||
visible={showBasic}
|
||
position="bottom"
|
||
style={{width: '100%', height: '100%'}}
|
||
onClose={() => {
|
||
setShowBasic(false)
|
||
}}
|
||
>
|
||
<div style={{padding: '20px'}}>
|
||
<h3>商店信息</h3>
|
||
<div>网站名称: {getWebsiteName()}</div>
|
||
<div>Logo: <img src={getWebsiteLogo()} alt="logo" style={{width: '50px', height: '50px'}} /></div>
|
||
|
||
<h3>用户信息</h3>
|
||
<div>登录状态: {isLoggedIn ? '已登录' : '未登录'}</div>
|
||
{user && (
|
||
<>
|
||
<div>用户ID: {user.userId}</div>
|
||
<div>手机号: {user.phone}</div>
|
||
<div>昵称: {user.nickname}</div>
|
||
</>
|
||
)}
|
||
|
||
<button
|
||
onClick={() => setShowBasic(false)}
|
||
style={{marginTop: '20px', padding: '10px 20px'}}
|
||
>
|
||
关闭
|
||
</button>
|
||
</div>
|
||
</Popup>
|
||
</>
|
||
)
|
||
}
|
||
|
||
export default Header;
|