- 在用户注册时支持从邀请参数中获取推荐人ID并绑定 - 修改管理员面板UI,添加统一扫码功能入口- 更新用户管理相关API地址,统一使用SERVER_API_URL - 调整优惠券卡片样式,移除小程序不支持的CSS属性 - 添加聊天会话和消息管理相关API模块 - 新增分销商银行卡管理API接口 - 修改系统用户模型,增加推荐人ID字段 - 更新广告位查询接口,支持根据code获取广告位 - 调整邀请绑定接口参数,将refereeId改为dealerId - 修改环境配置中的应用名称为"时里院子市集" - 移除分享到朋友圈的相关代码 - 添加管理员面板组件,提供统一扫码等管理功能 -修复用户管理API请求参数传递问题 - 添加聊天消息和会话管理的完整CRUD接口 - 更新系统用户相关接口URL,确保正确调用后端服务 - 添加分销商银行卡管理的完整API接口实现 - 修改邀请绑定接口,使用dealerId替代refereeId参数 - 修复扫码登录相关API的URL拼接问题 - 添加二维码内容解析功能,支持多种格式的token提取 - 更新用户信息模型,增加推荐人ID字段 -优化管理员面板样式和交互逻辑- 调整优惠券组件样式,兼容小程序环境限制- 修复用户管理模块的API调用问题 - 添加聊天相关数据模型和接口定义 - 更新环境配置中的应用名称 -修复邀请绑定相关的参数传递问题- 添加扫码登录状态枚举和相关数据结构定义- 优化管理员功能面板的UI展示和交互体验- 修复系统用户管理接口的请求参数问题 - 添加分销商银行卡管理相关接口实现- 调整聊天消息和会话管理接口的数据结构定义 -修复用户管理模块中的API调用路径问题 - 添加扫码登录相关工具函数,如设备信息获取等 - 更新邀请绑定接口的数据模型定义 -优化管理员面板组件的样式和功能实现 -修复系统用户管理接口中的参数传递问题 - 添加聊天相关模块的完整API接口实现 - 调整分销商银行卡管理模块的数据结构定义- 修复扫码登录相关接口的URL拼接问题- 更新用户管理模块中的API调用方式 - 添加聊天消息批量发送等相关接口实现- 修复邀请绑定接口中的参数名称问题- 优化管理员面板组件的功能和交互逻辑 - 调整系统用户管理接口的请求参数传递方式 - 添加分销商银行卡管理模块的完整接口实现 -修复聊天相关接口中的数据结构问题 - 更新扫码登录相关接口的数据模型定义 - 优化管理员功能面板的展示效果和用户体验
216 lines
6.8 KiB
TypeScript
216 lines
6.8 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 {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 { useShopInfo } from '@/hooks/useShopInfo';
|
||
import {handleInviteRelation, getStoredInviteParams} from "@/utils/invite";
|
||
import {View,Text} from '@tarojs/components'
|
||
import MySearch from "./MySearch";
|
||
import './Header.scss';
|
||
|
||
const Header = (props: any) => {
|
||
// 使用新的useShopInfo Hook
|
||
const {
|
||
getWebsiteName,
|
||
getWebsiteLogo
|
||
} = useShopInfo();
|
||
|
||
const [IsLogin, setIsLogin] = useState<boolean>(true)
|
||
const [statusBarHeight, setStatusBarHeight] = useState<number>()
|
||
|
||
const reload = async () => {
|
||
Taro.getSystemInfo({
|
||
success: (res) => {
|
||
setStatusBarHeight(res.statusBarHeight)
|
||
},
|
||
})
|
||
// 注意:商店信息现在通过useShopInfo自动管理,不需要手动获取
|
||
// 获取用户信息
|
||
getUserInfo().then((data) => {
|
||
if (data) {
|
||
setIsLogin(true);
|
||
console.log('用户信息>>>', data.phone)
|
||
// 保存userId
|
||
Taro.setStorageSync('UserId', data.userId)
|
||
// 获取openId
|
||
if (!data.openid) {
|
||
Taro.login({
|
||
success: (res) => {
|
||
getWxOpenId({code: res.code}).then(() => {
|
||
})
|
||
}
|
||
})
|
||
}
|
||
// 是否已认证
|
||
if (data.certification) {
|
||
Taro.setStorageSync('Certification', '1')
|
||
}
|
||
// 机构ID
|
||
Taro.setStorageSync('OrganizationId', data.organizationId)
|
||
// 父级机构ID
|
||
if (Number(data.organizationId) > 0) {
|
||
getOrganization(Number(data.organizationId)).then(res => {
|
||
Taro.setStorageSync('OrganizationParentId', res.parentId)
|
||
})
|
||
}
|
||
// 管理员
|
||
const isKdy = data.roles?.findIndex(item => item.roleCode == 'admin')
|
||
if (isKdy != -1) {
|
||
Taro.setStorageSync('RoleName', '管理')
|
||
Taro.setStorageSync('RoleCode', 'admin')
|
||
return false;
|
||
}
|
||
// 注册用户
|
||
const isUser = data.roles?.findIndex(item => item.roleCode == 'user')
|
||
if (isUser != -1) {
|
||
Taro.setStorageSync('RoleName', '注册用户')
|
||
Taro.setStorageSync('RoleCode', 'user')
|
||
return false;
|
||
}
|
||
}
|
||
}).catch(() => {
|
||
setIsLogin(false);
|
||
console.log('未登录')
|
||
});
|
||
// 认证信息
|
||
myUserVerify({status: 1}).then(data => {
|
||
if (data?.realName) {
|
||
Taro.setStorageSync('RealName', data.realName)
|
||
}
|
||
})
|
||
}
|
||
|
||
/* 获取用户手机号 */
|
||
const handleGetPhoneNumber = ({detail}: {detail: {code?: string, encryptedData?: string, iv?: string}}) => {
|
||
const {code, encryptedData, iv} = detail
|
||
|
||
// 防重复登录检查
|
||
const loginKey = 'login_in_progress'
|
||
const loginInProgress = Taro.getStorageSync(loginKey)
|
||
|
||
if (loginInProgress && Date.now() - loginInProgress < 5000) { // 5秒内防重
|
||
return
|
||
}
|
||
|
||
// 标记登录开始
|
||
Taro.setStorageSync(loginKey, Date.now())
|
||
|
||
// 获取存储的邀请参数
|
||
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
|
||
},
|
||
header: {
|
||
'content-type': 'application/json',
|
||
TenantId
|
||
},
|
||
success: async function (res) {
|
||
// 清除登录防重标记
|
||
Taro.removeStorageSync('login_in_progress')
|
||
|
||
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)
|
||
setIsLogin(true)
|
||
|
||
// 处理邀请关系
|
||
if (res.data.data.user?.userId) {
|
||
try {
|
||
await handleInviteRelation(res.data.data.user.userId)
|
||
} catch (error) {
|
||
console.error('处理邀请关系失败:', error)
|
||
}
|
||
}
|
||
|
||
// 重新加载小程序
|
||
Taro.reLaunch({
|
||
url: '/pages/index/index'
|
||
})
|
||
},
|
||
fail: function() {
|
||
// 清除登录防重标记
|
||
Taro.removeStorageSync('login_in_progress')
|
||
}
|
||
})
|
||
} else {
|
||
console.log('登录失败!')
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
useEffect(() => {
|
||
reload().then()
|
||
}, [])
|
||
|
||
return (
|
||
<>
|
||
<View className={'fixed top-0 header-bg'} style={{
|
||
height: !props.stickyStatus ? '180px' : 'auto',
|
||
paddingBottom: '12px'
|
||
}}>
|
||
<MySearch statusBarHeight={statusBarHeight} />
|
||
{/*{!props.stickyStatus && <MySearch done={reload}/>}*/}
|
||
</View>
|
||
<NavBar
|
||
style={{marginTop: `${statusBarHeight}px`, marginBottom: '0px', backgroundColor: 'transparent'}}
|
||
onBackClick={() => {
|
||
}}
|
||
left={
|
||
!IsLogin ? (
|
||
<View style={{display: 'flex', alignItems: 'center'}}>
|
||
<Button style={{color: '#ffffff'}} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
||
<Space>
|
||
<Avatar
|
||
size="22"
|
||
src={getWebsiteLogo()}
|
||
/>
|
||
<Text style={{color: '#ffffff'}}>{getWebsiteName()}</Text>
|
||
<TriangleDown size={9} className={'text-white'}/>
|
||
</Space>
|
||
</Button>
|
||
</View>
|
||
) : (
|
||
<View style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
|
||
<Avatar
|
||
size="22"
|
||
src={getWebsiteLogo()}
|
||
/>
|
||
<Text className={'text-white'}>{getWebsiteName()}</Text>
|
||
<TriangleDown className={'text-white'} size={9}/>
|
||
</View>
|
||
)}>
|
||
{/*<QRLoginButton />*/}
|
||
</NavBar>
|
||
</>
|
||
)
|
||
}
|
||
export default Header
|