|
|
@@ -0,0 +1,352 @@
|
|
|
+import { YTLog } from '../../../../Index';
|
|
|
+import { IBestToast } from '@ibestservices/ibest-ui';
|
|
|
+import { YTToast } from '../utils/YTToast';
|
|
|
+import { AppStorageKeyCollect } from '../constants';
|
|
|
+import { YTUserRequest } from '../apis/YTUserRequest';
|
|
|
+
|
|
|
+export class LoginCollect {
|
|
|
+ phonenumber?: string; // 用户输入的手机号
|
|
|
+ password?: string; // 密码(密码登录/注册/重置时使用)
|
|
|
+ smsCode?: string; // 验证码(验证码登录/注册/重置时使用)
|
|
|
+ confirmPassword?: string; // 确认密码(注册/重置时使用)
|
|
|
+ isAgreePrivacy: boolean = false; // 是否同意隐私政策
|
|
|
+ private code?: string //华为登录code
|
|
|
+ private operation: 'register' | 'reset' | 'login'; // 当前操作类型:注册/重置/登录
|
|
|
+ private uuid?: string //验证码登录防伪标识
|
|
|
+ private isRequesting: boolean = false //是否已经发送一个请求了
|
|
|
+ private loginMethod: 'harmony' | 'common' = 'common'
|
|
|
+ private countDown: number = 0
|
|
|
+
|
|
|
+ constructor(registerOrReset: 'register' | 'reset' | 'login') {
|
|
|
+ this.operation = registerOrReset
|
|
|
+ const storageUUID = AppStorage.get<string>(AppStorageKeyCollect.UUID)
|
|
|
+ if (storageUUID) {
|
|
|
+ this.uuid = storageUUID
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行登录/注册/重置操作,根据当前场景校验必要字段并处理逻辑
|
|
|
+ * @param harmony表示华为登录,common表示其它普通登录
|
|
|
+ */
|
|
|
+ executeLogin(loginMethod: 'harmony' | 'common' = this.loginMethod) {
|
|
|
+ if (loginMethod == undefined) {
|
|
|
+ throw Error("请传入登录方法")
|
|
|
+ }
|
|
|
+ //记录弹出隐私政策时的登录方法
|
|
|
+ this.loginMethod = loginMethod
|
|
|
+ // 基础校验:必须同意隐私政策
|
|
|
+ if (!this.isAgreePrivacy) {
|
|
|
+ YTToast.getInstance().agreePrivacy({ loginType: this })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //已有请求则拦截多于请求
|
|
|
+ if (this.isRequesting) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (loginMethod == 'harmony') {
|
|
|
+ YTUserRequest.harmonyLogin(this)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据当前操作类型分支处理
|
|
|
+ switch (this.operation) {
|
|
|
+ case 'register':
|
|
|
+ this.handleRegister(); // 处理注册逻辑
|
|
|
+ break
|
|
|
+ case 'reset':
|
|
|
+ this.handleResetPassword(); // 处理重置密码逻辑
|
|
|
+ break
|
|
|
+ case 'login':
|
|
|
+ this.handleLogin(); // 默认处理登录逻辑(密码/验证码登录)
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //将所有属性重置为初始态
|
|
|
+ clearAll() {
|
|
|
+ this.code = undefined
|
|
|
+ this.phonenumber = undefined
|
|
|
+ this.password = undefined
|
|
|
+ this.smsCode = undefined
|
|
|
+ this.confirmPassword = undefined
|
|
|
+ this.isAgreePrivacy = false
|
|
|
+ this.uuid = undefined
|
|
|
+ this.isRequesting = false
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //如获取验证码或华为登录后,后端返回的字段使用此方法接收
|
|
|
+ updateUsefulProperty(instance: LoginCollect) {
|
|
|
+ //判断不为空再赋值
|
|
|
+ if (instance.code) {
|
|
|
+ this.code = instance.code
|
|
|
+ }
|
|
|
+ if (instance.phonenumber) {
|
|
|
+ this.phonenumber = instance.phonenumber
|
|
|
+ }
|
|
|
+ if (instance.password) {
|
|
|
+ this.password = instance.password
|
|
|
+ }
|
|
|
+ if (instance.operation) {
|
|
|
+ this.operation = instance.operation
|
|
|
+ }
|
|
|
+ if (instance.smsCode) {
|
|
|
+ this.smsCode = instance.smsCode
|
|
|
+ }
|
|
|
+ if (instance.confirmPassword) {
|
|
|
+ this.confirmPassword = instance.confirmPassword
|
|
|
+ }
|
|
|
+ if (instance.isAgreePrivacy) {
|
|
|
+ this.isAgreePrivacy = instance.isAgreePrivacy
|
|
|
+ }
|
|
|
+ if (instance.uuid) {
|
|
|
+ this.uuid = instance.uuid
|
|
|
+ }
|
|
|
+
|
|
|
+ return this
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //发送验证码
|
|
|
+ requestSmsCode(success: (res: LoginCollect) => void) {
|
|
|
+ if (this.phonenumber?.match(new RegExp('^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\\d{8}$'))) {
|
|
|
+
|
|
|
+ YTUserRequest.getLoginCaptcha(this.phonenumber, (res, err) => {
|
|
|
+ if (!err && !res) {
|
|
|
+ IBestToast.show({ message: '请勿重复发送验证码' })
|
|
|
+ return
|
|
|
+ } else if (res) {
|
|
|
+ //防止退出登录页导致uuid直接失效
|
|
|
+ AppStorage.setOrCreate<string>(AppStorageKeyCollect.UUID, this.uuid)
|
|
|
+ IBestToast.show({ message: '验证码发送成功' })
|
|
|
+ this.updateUsefulProperty(res)
|
|
|
+ success(this)
|
|
|
+ } else {
|
|
|
+ YTLog.error(err)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+ IBestToast.show({ message: '请输入正确的手机号' })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ getCode(): string | undefined {
|
|
|
+ return this.code
|
|
|
+ }
|
|
|
+
|
|
|
+ setCode(code: string) {
|
|
|
+ this.code = code
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ getPhonenumber(): string | undefined {
|
|
|
+ return this.phonenumber
|
|
|
+ }
|
|
|
+
|
|
|
+ setPhonenumber(phonenumber: string) {
|
|
|
+ this.phonenumber = phonenumber
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+ getPassword(): string | undefined {
|
|
|
+ return this.password
|
|
|
+ }
|
|
|
+
|
|
|
+ setPassword(password: string) {
|
|
|
+ this.password = password
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+ getOperation(): 'register' | 'reset' | 'login' {
|
|
|
+ return this.operation
|
|
|
+ }
|
|
|
+
|
|
|
+ setOperation(registerOrReset: 'register' | 'reset' | 'login') {
|
|
|
+ this.operation = registerOrReset
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+ getSmsCode(): string | undefined {
|
|
|
+ return this.smsCode
|
|
|
+ }
|
|
|
+
|
|
|
+ setSmsCode(smsCode: string) {
|
|
|
+ this.smsCode = smsCode
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+ getConfirmPassword(): string | undefined {
|
|
|
+ return this.confirmPassword
|
|
|
+ }
|
|
|
+
|
|
|
+ setConfirmPassword(confirmPassword: string) {
|
|
|
+ this.confirmPassword = confirmPassword
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+ getIsAgreePrivacy(): boolean {
|
|
|
+ return this.isAgreePrivacy
|
|
|
+ }
|
|
|
+
|
|
|
+ setIsAgreePrivacy(isAgreePrivacy: boolean) {
|
|
|
+ this.isAgreePrivacy = isAgreePrivacy
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+ getUuid(): string | undefined {
|
|
|
+ return this.uuid
|
|
|
+ }
|
|
|
+
|
|
|
+ setUuid(uuid: string) {
|
|
|
+ this.uuid = uuid
|
|
|
+ return this
|
|
|
+ }
|
|
|
+
|
|
|
+ getCountDown() {
|
|
|
+ return this.countDown
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理登录逻辑(支持密码登录或验证码登录)
|
|
|
+ */
|
|
|
+ private handleLogin() {
|
|
|
+ // 核心校验:手机号必填
|
|
|
+ if (!this.phonenumber) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '登录失败:请输入手机号码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 场景分支:密码登录 或 验证码登录
|
|
|
+ if (this.password) {
|
|
|
+ // 密码登录:校验密码非空
|
|
|
+ if (!this.password.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '登录失败:请输入密码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 调用密码登录接口
|
|
|
+ YTUserRequest.passwordLogin(this)
|
|
|
+ return
|
|
|
+ } else if (this.smsCode) {
|
|
|
+ // 验证码登录:校验验证码非空
|
|
|
+ if (!this.smsCode.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '登录失败:请输入验证码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 验证码登录逻辑
|
|
|
+ YTUserRequest.phonenumberLogin(this)
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ // 无密码/验证码时提示
|
|
|
+
|
|
|
+ IBestToast.show({ message: '登录失败:请输入密码或验证码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理注册逻辑(手机号+验证码+密码+确认密码)
|
|
|
+ */
|
|
|
+ private handleRegister() {
|
|
|
+ // 核心校验:手机号必填
|
|
|
+ if (!this.phonenumber) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '注册失败:请输入手机号码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 场景分支:注册需要验证码
|
|
|
+ if (!this.smsCode?.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '注册失败:请输入验证码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 密码相关校验
|
|
|
+ if (!this.password?.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '注册失败:请设置密码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.confirmPassword?.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '注册失败:请确认密码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.validatePassword(this.password)) {
|
|
|
+ IBestToast.show({ message: '注册失败:密码必须包含字母、数字和特殊符号,并且长度在8到20位之间', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.password !== this.confirmPassword) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '注册失败:两次输入的密码不一致', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 实际场景可调用注册接口(示例)
|
|
|
+ YTUserRequest.register(this)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理重置密码逻辑(手机号+验证码+新密码+确认密码)
|
|
|
+ */
|
|
|
+ private handleResetPassword() {
|
|
|
+ // 核心校验:手机号必填
|
|
|
+ if (!this.phonenumber) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '重置密码失败:请输入手机号码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 场景分支:重置需要验证码
|
|
|
+ if (!this.smsCode?.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '重置密码失败:请输入验证码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 新密码相关校验
|
|
|
+ if (!this.password?.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '重置密码失败:请设置新密码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.confirmPassword?.trim()) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '重置密码失败:请确认新密码', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.password !== this.confirmPassword) {
|
|
|
+
|
|
|
+ IBestToast.show({ message: '重置密码失败:两次输入的新密码不一致', type: "warning" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 实际场景可调用重置密码接口
|
|
|
+ YTUserRequest.resetPassword(this, () => {
|
|
|
+ this.handleLogin()
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 密码校验函数
|
|
|
+ private validatePassword(password: string): boolean {
|
|
|
+ // 正则表达式说明:
|
|
|
+ // ^ 表示字符串开始
|
|
|
+ // (?=.*[A-Za-z]) 至少包含一个字母(大小写均可)
|
|
|
+ // (?=.*\d) 至少包含一个数字
|
|
|
+ // (?=.*[^A-Za-z0-9]) 至少包含一个非字母数字的特殊符号(如@#$%^&*等)
|
|
|
+ // .{8,20} 长度限制 8-20 位
|
|
|
+ // $ 表示字符串结束
|
|
|
+ const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,20}$/;
|
|
|
+ return passwordRegex.test(password);
|
|
|
+ }
|
|
|
+}
|