- 在用户注册时支持从邀请参数中获取推荐人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调用方式 - 添加聊天消息批量发送等相关接口实现- 修复邀请绑定接口中的参数名称问题- 优化管理员面板组件的功能和交互逻辑 - 调整系统用户管理接口的请求参数传递方式 - 添加分销商银行卡管理模块的完整接口实现 -修复聊天相关接口中的数据结构问题 - 更新扫码登录相关接口的数据模型定义 - 优化管理员功能面板的展示效果和用户体验
157 lines
5.4 KiB
TypeScript
157 lines
5.4 KiB
TypeScript
import {useEffect, useState} from "react";
|
||
import Taro from '@tarojs/taro'
|
||
import {Input, Radio, Button} from '@nutui/nutui-react-taro'
|
||
import {TenantId} from "@/config/app";
|
||
import './login.scss';
|
||
import {saveStorageByLoginUser} from "@/utils/server";
|
||
import {handleInviteRelation, getStoredInviteParams} from "@/utils/invite";
|
||
|
||
// 微信获取手机号回调参数类型
|
||
interface GetPhoneNumberDetail {
|
||
code?: string;
|
||
encryptedData?: string;
|
||
iv?: string;
|
||
errMsg: string;
|
||
}
|
||
|
||
interface GetPhoneNumberEvent {
|
||
detail: GetPhoneNumberDetail;
|
||
}
|
||
|
||
interface LoginProps {
|
||
done?: (user: any) => void;
|
||
[key: string]: any;
|
||
}
|
||
|
||
// 登录接口返回数据类型
|
||
interface LoginResponse {
|
||
data: {
|
||
data: {
|
||
access_token: string;
|
||
user: any;
|
||
};
|
||
};
|
||
}
|
||
|
||
const Login = (props: LoginProps) => {
|
||
const [isAgree, setIsAgree] = useState(false)
|
||
const [env, setEnv] = useState<string>()
|
||
|
||
/* 获取用户手机号 */
|
||
const handleGetPhoneNumber = ({detail}: GetPhoneNumberEvent) => {
|
||
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
|
||
},
|
||
header: {
|
||
'content-type': 'application/json',
|
||
TenantId
|
||
},
|
||
success: async function (res: LoginResponse) {
|
||
saveStorageByLoginUser(res.data.data.access_token, res.data.data.user)
|
||
|
||
// 处理邀请关系
|
||
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)
|
||
}
|
||
}
|
||
|
||
props.done?.(res.data.data.user);
|
||
}
|
||
})
|
||
} else {
|
||
console.log('登录失败!')
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const reload = () => {
|
||
Taro.hideTabBar()
|
||
setEnv(Taro.getEnv())
|
||
}
|
||
|
||
useEffect(() => {
|
||
reload()
|
||
}, [])
|
||
|
||
return (
|
||
<>
|
||
<div style={{height: '80vh'}} className={'flex flex-col justify-center px-5'}>
|
||
<div className={'text-3xl text-center py-5 font-normal mb-10 '}>登录</div>
|
||
{
|
||
env === 'WEAPP' && (
|
||
<>
|
||
<div className={'flex flex-col w-full text-white rounded-full justify-between items-center my-2'} style={{ background: 'linear-gradient(to right, #7e22ce, #9333ea)'}}>
|
||
<Button open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
||
授权手机号登录
|
||
</Button>
|
||
</div>
|
||
</>
|
||
)
|
||
}
|
||
{
|
||
env === 'WEB' && (
|
||
<>
|
||
<div className={'flex flex-col justify-between items-center my-2'}>
|
||
<Input type="text" placeholder="手机号" maxLength={11}
|
||
style={{backgroundColor: '#ffffff', borderRadius: '8px'}}/>
|
||
</div>
|
||
<div className={'flex flex-col justify-between items-center my-2'}>
|
||
<Input type="password" placeholder="密码" style={{backgroundColor: '#ffffff', borderRadius: '8px'}}/>
|
||
</div>
|
||
<div className={'flex justify-between my-2 text-left px-1'}>
|
||
<a href={'#'} className={'text-blue-600 text-sm'}
|
||
onClick={() => Taro.navigateTo({url: '/passport/forget'})}>忘记密码</a>
|
||
<a href={'#'} className={'text-blue-600 text-sm'}
|
||
onClick={() => Taro.navigateTo({url: '/passport/setting'})}>服务配置</a>
|
||
</div>
|
||
<div className={'flex justify-center my-5'}>
|
||
<Button type="info" size={'large'} className={'w-full rounded-lg p-2'} disabled={!isAgree}>登录</Button>
|
||
</div>
|
||
<div className={'w-full bottom-20 my-2 flex justify-center text-sm items-center text-center'}>
|
||
没有账号?<a href={''} onClick={() => Taro.navigateTo({url: '/passport/register'})}
|
||
className={'text-blue-600'}>立即注册</a>
|
||
</div>
|
||
<div className={'my-2 flex fixed bottom-20 text-sm items-center px-1'}>
|
||
<Radio style={{color: '#333333'}} checked={isAgree} onClick={() => setIsAgree(!isAgree)}></Radio>
|
||
<span className={'text-gray-400'} onClick={() => setIsAgree(!isAgree)}>登录表示您已阅读并同意</span><a
|
||
onClick={() => Taro.navigateTo({url: '/passport/agreement'})}
|
||
className={'text-blue-600'}>《服务协议及隐私政策》</a>
|
||
</div>
|
||
</>
|
||
)
|
||
}
|
||
</div>
|
||
</>
|
||
)
|
||
}
|
||
export default Login
|