@cloudbase/lowcode-builder 1.10.27 → 1.10.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,13 +2,13 @@
2
2
  <view wx:if="{{!initing && !error}}" class="wd-mp-root" data-weui-theme="light">
3
3
  <view style="width:90%;margin:0px auto;display:flex;flex-direction:column;max-width:50rem;" class="login-class">
4
4
  <block wx:if="{{!baseInfoShow}}">
5
- <view style="margin:60px 0px 40px; display: flex; flex-direction: column; align-items: center;">
5
+ <view style="margin:40px 0px 20px; display: flex; flex-direction: column; align-items: center;">
6
6
  <image style="margin:0px auto;display:flex;justify-content:center;width: 80px;height: 80px;" class="weda-ui weda-image" mode="aspectFit" src="{{settingData.logo}}" />
7
7
  <view wx:if="{{ !!settingData.name }}" style="font-size: 16px;">
8
8
  {{ settingData.name }}
9
9
  </view>
10
10
  </view>
11
- <view wx:if="{{currentLoginType === 'password'}}">
11
+ <view wx:if="{{currentLoginType === '__password'}}">
12
12
  <form bindsubmit="loginByPassword">
13
13
  <login-input name="username" placeholder="请输入用户名" type="text" />
14
14
  <view style="margin-bottom:30px;position:relative;">
@@ -21,44 +21,65 @@
21
21
  </button>
22
22
  </form>
23
23
  </view>
24
- <view wx:elif="{{currentLoginType === 'sms'}}">
25
- <form bindsubmit="loginBySms">
26
- <login-input name="phoneNum" defaultValue="{{defaultPhoneNumber}}" placeholder="输入手机号" type="number" auto maxlength="11" bindchange="onPhoneChange">
24
+ <view wx:elif="{{currentLoginType === '__sms'}}">
25
+ <form bindsubmit="handleLogin">
26
+ <login-input name="phoneNum" defaultValue="{{defaultPhoneNumber}}" placeholder="输入手机号" type="number" auto maxlength="11" bindchange="handleInputChange">
27
27
  <view class="input-prefix" style="color:#acacac;padding: 0 10px" slot="prefix">
28
28
  +86
29
29
  </view>
30
30
  </login-input>
31
31
  <view style="margin-bottom:30px;position:relative;">
32
32
  <login-input name="verificationCode" placeholder="输入验证码" style="padding-right:100px" type="text" maxlength="6">
33
- <view class="input-suffix wd-event-tap" style="font-size:14px;width: 150px;text-align:center;padding:0 10px;color:{{phoneValidateMessage || smsDelay>0?'var(--wd-color-brand-disabled)':'var(--wd-color-text-brand)'}};" slot="suffix" bindtap="getCaptcha">
33
+ <view class="input-suffix wd-event-tap" style="font-size:14px;width: 150px;text-align:center;padding:0 10px;color:{{phoneValidateMessage || smsDelay>0?'var(--wd-color-brand-disabled)':'var(--wd-color-text-brand)'}};" slot="suffix" bindtap="handleCaptcha">
34
34
  {{smsDelay > 0 ? '重新获取'+smsDelay : '获取验证码'}}
35
35
  </view>
36
36
  </login-input>
37
37
  </view>
38
38
  <button class="{{loginButtonClass}}" style="width:100%;border-radius:5px;" size="md" form-type="submit">
39
- 登录
39
+ {{isRegister ? '注册' : '登录'}}
40
40
  </button>
41
41
  </form>
42
42
  </view>
43
- <view wx:elif="{{currentLoginType === 'miniprogram_phone'}}">
43
+ <view wx:elif="{{currentLoginType === 'email'}}">
44
+ <form bindsubmit="handleLogin">
45
+ <login-input name="email" defaultValue="{{defaultEmail}}" placeholder="输入邮箱" type="text" auto bindchange="handleInputChange"></login-input>
46
+ <view style="margin-bottom:30px;position:relative;">
47
+ <login-input name="verificationCode" placeholder="输入验证码" style="padding-right:100px" type="text" maxlength="6">
48
+ <view class="input-suffix wd-event-tap" style="font-size:14px;width: 150px;text-align:center;padding:0 10px;color:{{emailValidateMessage || emailDelay>0?'var(--wd-color-brand-disabled)':'var(--wd-color-text-brand)'}};" slot="suffix" bindtap="handleCaptcha">
49
+ {{emailDelay > 0 ? '重新获取'+emailDelay : '获取验证码'}}
50
+ </view>
51
+ </login-input>
52
+ </view>
53
+ <button class="{{loginButtonClass}}" style="width:100%;border-radius:5px;" size="md" form-type="submit">
54
+ {{isRegister ? '注册' : '登录'}}
55
+ </button>
56
+ </form>
57
+ </view>
58
+ <view wx:elif="{{currentLoginType === '__miniprogram_phone'}}">
44
59
  <button style="width:100%;border-radius: 5px;" bindgetphonenumber="getPhoneCodeNumber" open-type="getPhoneNumber" role="button" class="{{loginButtonClass}}">
45
- 登录
60
+ {{isRegister ? '注册' : '登录'}}
46
61
  </button>
47
62
  </view>
48
- <view wx:if="{{publicPage && publicPage.length > 0}}" class="weda-ui weda-button weui-btn weui-btn_default wd-event-tap" style="margin-top: 30rpx; width:100%; background: transparent;font-size: 14px;" size="md" bind:tap="loginCancel">
63
+ <view wx:if="{{!isRegister && publicPage && publicPage.length > 0}}" class="weda-ui weda-button weui-btn weui-btn_default wd-event-tap" style="margin-top: 30rpx; width:100%; background: transparent;font-size: 14px;" size="md" bind:tap="loginCancel">
49
64
  暂不登录
50
65
  </view>
51
- <view wx:if="{{currentLoginList.length >= 1}}" class="login-method">
66
+ <view wx:if="{{registerMethods.length}}" class="register">
67
+ <text>{{isRegister ? '已有账号?' : '没有账号?'}}</text>
68
+ <text class="link" bind:tap="toRegister">{{isRegister ? '立即登录' : '立即注册'}}</text>
69
+ </view>
70
+ <view wx:if="{{isRegister ? registerMethods.length > 1 : currentLoginList.length > 1}}" class="login-method">
52
71
  <view class="divider">
53
72
  <view class="divider-line"></view>
54
- <view class="divider-title">可选登录方式</view>
73
+ <view class="divider-title">可选{{isRegister?'注册':'登录'}}方式</view>
55
74
  <view class="divider-line"></view>
56
75
  </view>
57
76
  <view class="login-method__list">
58
- <view class="login-method__list-item" wx:for="{{currentLoginList}}" wx:for-item="item" wx:key="index" bind:tap="methodClick" data-item="{{item}}">
59
- <view class="short-name">{{item.label[0]}}</view>
60
- <view class="name">{{item.label}}</view>
61
- </view>
77
+ <block wx:for="{{isRegister ? registerMethods : currentLoginList}}" wx:for-item="item" wx:key="index">
78
+ <view wx:if="{{item.id !== currentLoginType}}" class="login-method__list-item" bind:tap="methodClick" data-item="{{item}}">
79
+ <view class="short-name">{{item.label[0]}}</view>
80
+ <view class="name">{{isRegister ? item.registerLabel : item.label}}</view>
81
+ </view>
82
+ </block>
62
83
  </view>
63
84
  </view>
64
85
  <view style="display:flex;justify-content:center;flex-direction:row;font-size:0.8rem;position:fixed;left:0px;right:0px;bottom:50px;" class="have-read" wx:if="{{settingData.agreement.enable}}">
@@ -116,4 +137,4 @@
116
137
  </view>
117
138
  <wd-info type="{{initing? 'loading': 'auth'}}" wx:if="{{initing || error}}" message="{{loading?'加载配置中...':' '}}" error="{{error}}" />
118
139
  <captcha-dialog />
119
- </page-meta>
140
+ </page-meta>
@@ -2,134 +2,147 @@ button,
2
2
  button:hover,
3
3
  button,
4
4
  button:active {
5
- font-size: 14px !important;
6
- color: white;
5
+ font-size: 32rpx !important;
6
+ color: white;
7
7
  }
8
8
 
9
9
  .login-class .weda-ui .wedatea2td-input,
10
10
  .login-class .weda-ui .wedatea2td-button {
11
- border: none;
11
+ border: none;
12
12
  }
13
13
 
14
14
  .login-class .weda-ui .wedatea2td-input,
15
15
  .login-class .weda-ui .weda-input {
16
- width: 100%;
16
+ width: 100%;
17
17
  }
18
18
 
19
19
  .login-class .weda-ui .wedatea2td-btn {
20
- border: none;
21
- line-height: 1;
20
+ border: none;
21
+ line-height: 1;
22
22
  }
23
23
 
24
24
  .login-class .weda-ui .wedatea2td-btn::after {
25
- border: none;
25
+ border: none;
26
26
  }
27
27
 
28
28
  .login-class .weda-ui .weui-cells:before,
29
29
  .login-class .weda-ui .weui-cells::after {
30
- display: none;
30
+ display: none;
31
31
  }
32
32
 
33
33
  .login-class .token-container .weda-button {
34
- width: 11rem;
35
- padding: 0.5rem;
36
- color: #1e6fd8;
34
+ width: 11rem;
35
+ padding: 0.5rem;
36
+ color: #1e6fd8;
37
37
  }
38
38
 
39
39
  .login-class .token-container .weda-button::after {
40
- border: none;
40
+ border: none;
41
41
  }
42
42
 
43
43
  .login-class .token-container .weda-button[disabled] {
44
- color: #d0d0d0;
44
+ color: #d0d0d0;
45
45
  }
46
46
 
47
47
  .login-class .have-read .weui-cells {
48
- font-size: 0.8rem;
48
+ font-size: 0.8rem;
49
49
  }
50
50
 
51
51
  .login-class .have-read .weui-cell {
52
- padding: 0;
52
+ padding: 0;
53
53
  }
54
54
 
55
55
  .login-class .have-read .weui-cells_checkbox .weui-cell__hd {
56
- padding-right: 0.5rem;
56
+ padding-right: 0.5rem;
57
57
  }
58
58
 
59
59
  .login-class .have-read .weui-cells_checkbox .weui-icon-checked {
60
- width: 1.2rem;
60
+ width: 1.2rem;
61
61
  }
62
62
 
63
63
  .login-class .weui-btn_primary.is-disabled {
64
- background-color: var(--wd-color-brand-disabled) !important;
65
- border-color: var(--wd-color-brand-disabled) !important;
66
- color: #fff !important;
64
+ background-color: var(--wd-color-brand-disabled) !important;
65
+ border-color: var(--wd-color-brand-disabled) !important;
66
+ color: #fff !important;
67
67
  }
68
68
 
69
69
  .login-class .input-prefix {
70
- border-right: 1px solid #dbdbdb;
70
+ border-right: 1px solid #dbdbdb;
71
71
  }
72
72
 
73
73
  .login-class .input-suffix {
74
- border-left: 1px solid #dbdbdb;
74
+ border-left: 1px solid #dbdbdb;
75
+ }
76
+
77
+ .login-method {
78
+ text-align: center;
75
79
  }
76
80
 
77
81
  .login-method .divider {
78
- margin: 32px auto 8px;
79
- color: #9e9e9e;
80
- display: flex;
81
- align-items: center;
82
- justify-content: center;
83
- font-size: 13px;
84
- width: 100%;
82
+ margin: 30rpx auto 16rpx;
83
+ color: #9e9e9e;
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ font-size: 28rpx;
88
+ width: 100%;
85
89
  }
86
90
 
87
91
  .login-method .divider-line {
88
- flex: 1;
89
- display: inline-block;
90
- background-color: #ddd;
91
- height: 1rpx;
92
- width: 100%;
92
+ flex: 1;
93
+ display: inline-block;
94
+ background-color: #ddd;
95
+ height: 1rpx;
96
+ width: 100%;
93
97
  }
94
98
 
95
99
  .login-method .divider-title {
96
- margin: 0 32rpx;
100
+ margin: 0 32rpx;
97
101
  }
98
102
 
99
103
  .login-method .login-method__list {
100
- display: flex;
101
- flex-wrap: wrap;
102
- padding: 10rpx 0;
103
- justify-content: center;
104
+ display: inline-flex;
105
+ flex-wrap: wrap;
106
+ padding: 10rpx 0;
104
107
  }
105
108
 
106
109
  .login-method .login-method__list .login-method__list-item {
107
- cursor: pointer;
108
- margin: 16rpx;
109
- border-radius: 50%;
110
- display: flex;
111
- align-items: center;
112
- justify-content: center;
113
- flex-direction: column;
114
- width: 28.7%;
110
+ cursor: pointer;
111
+ margin: 16rpx;
112
+ border-radius: 50%;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ flex-direction: column;
117
+ width: auto;
115
118
  }
116
119
 
117
120
  .login-method .login-method__list .login-method__list-item .short-name {
118
- width: 84rpx;
119
- height: 84rpx;
120
- line-height: 84rpx;
121
- border-radius: 100%;
122
- text-align: center;
123
- background-color: #7fb5f1;
124
- color: #fff;
121
+ width: 84rpx;
122
+ height: 84rpx;
123
+ line-height: 84rpx;
124
+ border-radius: 100%;
125
+ text-align: center;
126
+ background-color: #7fb5f1;
127
+ color: #fff;
125
128
  }
126
129
 
127
130
  .login-method .login-method__list .login-method__list-item .name {
128
- font-size: 24rpx;
129
- margin-top: 12rpx;
130
- text-overflow: ellipsis;
131
- overflow: hidden;
132
- white-space: nowrap;
133
- width: 100%;
134
- text-align: center;
131
+ font-size: 24rpx;
132
+ margin-top: 12rpx;
133
+ text-overflow: ellipsis;
134
+ overflow: hidden;
135
+ white-space: nowrap;
136
+ width: 100%;
137
+ text-align: center;
135
138
  }
139
+
140
+ .register {
141
+ font-size: 28rpx;
142
+ margin-top: 30rpx;
143
+ text-align: center;
144
+ }
145
+
146
+ .register .link {
147
+ color: #006eff;
148
+ }
@@ -1,5 +1,7 @@
1
1
  export const phoneNumberPattern = /^1[0-9]{10}$/;
2
2
  export const phoneVerifyInfoKey = 'sso_phone_verifyInfo'; // 获取短信信息缓存key
3
- export const verifyCodeFailedLimit = 8; // 同一个短信验证码使用8次即提示错误
3
+ export const emailVerifyInfoKey = 'sso_email_verifyInfo'; // 获取邮箱信息缓存key
4
+ export const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
5
+ export const verifyCodeFailedLimit = 8; // 同一个验证码使用8次即提示错误
4
6
  export const verifyDelay = 60; // 获取验证码倒计时,单位s
5
7
  export const loginOnly = false;
@@ -58,8 +58,6 @@ export const parseSignUpError = (e) => {
58
58
  // 验证码验证token
59
59
  export const parseVerifyError = (e) => {
60
60
  switch (e.error) {
61
- case 'invalid_argument':
62
- return `您输入的验证码不正确或已过期 ${e.message || ''}`;
63
61
  case 'get_verify_code':
64
62
  return '请重新获取验证码';
65
63
  case 'aborted':
@@ -130,6 +128,31 @@ export function parseSmsError(e, verificationTarget, loginOnly) {
130
128
  }
131
129
  }
132
130
 
131
+ export function parseEmailError(e, verificationTarget, loginOnly) {
132
+ switch (e.error) {
133
+ case 'failed_precondition':
134
+ switch (verificationTarget) {
135
+ case 'USER':
136
+ if (loginOnly) {
137
+ return '用户不存在,请输入在平台注册过的邮箱';
138
+ }
139
+ return '你输入的手机号已被注册,请使用其他号码';
140
+ case 'NOT_USER':
141
+ return '该用户已被注册,请使用其他邮箱';
142
+ default:
143
+ return '邮箱功能未开启,请联系管理员开启';
144
+ }
145
+ case 'payment_required':
146
+ return '邮箱获取验证码资源不足,请联系管理员充值';
147
+ case 'aborted':
148
+ return '你尝试的次数过多,稍后重试';
149
+ case 'unavailable':
150
+ return `发件服务不可用,请稍后重试${prefixMsg(e.error_description)}`;
151
+ default:
152
+ return parseCommonError(e);
153
+ }
154
+ }
155
+
133
156
  export const parseCommonError = (e) => {
134
157
  let msg;
135
158
  switch (e.error) {
@@ -0,0 +1,87 @@
1
+ import {
2
+ parseEmailError
3
+ } from './errorHandler';
4
+ import {
5
+ app
6
+ } from '../../../../../app/weapps-api';
7
+ import loginSuccessCallBack from './loginSuccessCallBack';
8
+ import {
9
+ emailVerifyInfoKey,
10
+ verifyCodeFailedLimit,
11
+ } from './contants';
12
+
13
+ export default async function loginByEmail(
14
+ instance, {
15
+ callback,
16
+ verificationInfo,
17
+ verificationCode,
18
+ email,
19
+ loginOnly,
20
+ isRegister,
21
+ bindInfo,
22
+ hasRegisterConfig
23
+ },
24
+ ) {
25
+ wx.showLoading({
26
+ mask: true
27
+ });
28
+ const {
29
+ usedCount = 0
30
+ } = wx.getStorageSync(emailVerifyInfoKey) || {};
31
+ try {
32
+ const cloud = await app.cloud.getCloudInstance();
33
+ const auth = cloud.auth;
34
+
35
+ // 验证码使用次数超过限制,直接提示错误
36
+ if (usedCount >= verifyCodeFailedLimit) {
37
+ throw {
38
+ error: 'get_verify_code'
39
+ };
40
+ }
41
+
42
+ if (isRegister && verificationInfo.isUser && verificationInfo.email === email) {
43
+ throw { error: 'user has already registered, please log in directly' };
44
+ }
45
+
46
+ // 校验
47
+ if (!email || !verificationCode) {
48
+ throw new Error('输入内容不合法');
49
+ }
50
+
51
+ // 1. 验证验证码
52
+ const { verification_token } = await auth.verify({
53
+ verification_id: verificationInfo.id,
54
+ verification_code: verificationCode,
55
+ });
56
+
57
+ // 2. 根据是否已经是用户,分别走登录或注册逻辑
58
+ if ((verificationInfo.isUser || loginOnly) && !isRegister) {
59
+ await auth.signIn({ verification_token, username: email });
60
+
61
+ if (bindInfo) {
62
+ await auth.bindWithProvider({
63
+ provider_token: bindInfo.providerToken,
64
+ });
65
+ }
66
+ } else if (!hasRegisterConfig || isRegister) {
67
+ // 3. 注册
68
+ await auth.signUp({
69
+ email,
70
+ verification_token,
71
+ provider_token: bindInfo?.providerToken,
72
+ });
73
+ }
74
+
75
+ await app.cloud.signIn({ userType: 'externalUser', force: true });
76
+ callback?.(null, 'success');
77
+ wx.hideLoading();
78
+ loginSuccessCallBack(instance);
79
+ } catch (e) {
80
+ wx.hideLoading();
81
+ wx.showModal({
82
+ title: '邮箱登录失败',
83
+ content: parseEmailError(e),
84
+ });
85
+ callback?.(new Error(parseEmailError(e)));
86
+ }
87
+ }
@@ -1,55 +1,34 @@
1
1
  import { app } from '../../../../../app/weapps-api';
2
2
  import loginSuccessCallBack from './loginSuccessCallBack'
3
+ import { parseLoginError } from './errorHandler';
3
4
  /**
4
5
  * 账号密码登录
5
6
  */
6
- export default async function (instance, {username, password}) {
7
- const cloudbase = await app.cloud.getCloudInstance();
8
- const auth = cloudbase.authInstance || cloudbase.auth;
9
-
10
- // 校验
11
- if (typeof username !== 'string' || typeof password !== 'string') {
12
- throw new Error('账号密码填写不合法');
13
- }
14
- username = username.trim();
15
- password = password.trim();
16
- // 发起校验
17
- // const validateResult = await Promise.all([$w.input1.custom.handleValidate(), $w.input2.handleValidate()]);
18
- // if (validateResult.some((item) => item.length !== 0) || !username || !password) {
19
- // app.showModal({
20
- // title: '无法提交',
21
- // content: '账号或密码填写不合法',
22
- // showCancel: false,
23
- // });
24
- // return;
25
- // }
7
+ export default async function (instance, { username, password }) {
26
8
  // 登录
27
9
  try {
28
- const res = await auth.signIn({ username, password });
10
+ const cloudbase = await app.cloud.getCloudInstance();
11
+ const auth = cloudbase.authInstance || cloudbase.auth;
12
+
13
+ // 校验
14
+ if (typeof username !== 'string' || typeof password !== 'string') {
15
+ throw new Error('账号密码填写不合法');
16
+ }
17
+ username = username.trim();
18
+ password = password.trim();
19
+ wx.showLoading({
20
+ title: '请稍后'
21
+ })
22
+ await auth.signIn({ username, password });
23
+ await app.cloud.signIn({ userType: 'externalUser', force: true });
24
+ wx.hideLoading()
29
25
  // 登录完成
30
26
  loginSuccessCallBack(instance);
31
27
  } catch (e) {
32
- console.error(e)
33
- // 错误处理
34
- if (e?.error === 'invalid_password') {
35
- app.showModal({
36
- title: '登录失败',
37
- content: '密码错误',
38
- showCancel: false,
39
- });
40
- } else if (e?.error === 'not_found') {
41
- app.showModal({
42
- title: '登录失败',
43
- content: '用户不存在',
44
- showCancel: false,
45
- });
46
- } else {
47
- app.showModal({
48
- title: '登录失败',
49
- content: JSON.stringify(e),
50
- showCancel: false,
51
- });
52
- }
53
-
28
+ wx.hideLoading()
29
+ wx.showModal({
30
+ title: '登录失败',
31
+ content: parseLoginError(e),
32
+ });
54
33
  }
55
34
  }
@@ -5,41 +5,46 @@ import { phoneVerifyInfoKey, verifyCodeFailedLimit, loginOnly } from './contants
5
5
 
6
6
  export default async function loginBySms(
7
7
  instance,
8
- { callback, verificationInfo, verificationCode, phoneNum, bindInfo },
8
+ { callback, verificationInfo, verificationCode, phoneNum, bindInfo, isRegister, hasRegisterConfig },
9
9
  ) {
10
10
  wx.showLoading({ mask: true });
11
11
  const { usedCount = 0 } = wx.getStorageSync(phoneVerifyInfoKey) || {};
12
12
  try {
13
13
  const cloud = await app.cloud.getCloudInstance();
14
14
  const auth = cloud.auth;
15
- const isV2 = false;
16
15
 
17
16
  // 验证码使用次数超过限制,直接提示错误
18
17
  if (usedCount >= verifyCodeFailedLimit) {
19
18
  throw { error: 'get_verify_code' };
20
19
  }
20
+
21
+ if (isRegister && verificationInfo.isUser && verificationInfo.phoneNum === phoneNum) {
22
+ throw { error: 'user has already registered, please log in directly' };
23
+ }
24
+
25
+ // 校验
26
+ if (!phoneNum || !verificationCode) {
27
+ throw new Error('输入内容不合法');
28
+ }
29
+
21
30
  // 1. 验证验证码
22
31
  const { verification_token } = await auth.verify({
23
- verification_id: isV2 ? undefined : verificationInfo.id,
24
- verification_token: isV2 ? verificationInfo.id : undefined,
32
+ verification_id: verificationInfo.id,
25
33
  verification_code: verificationCode,
26
- version: isV2 ? 'v2' : undefined,
27
34
  });
28
35
  // 2. 根据是否已经是用户,分别走登录或注册逻辑
29
- if (verificationInfo.isUser || loginOnly) {
30
- // 私有化环境或者自定义应用走v1版本的老逻辑
31
- if (!isV2) {
32
- await auth.signIn({
33
- username: `+86 ${phoneNum}`,
34
- verification_token,
35
- });
36
- }
36
+ if ((verificationInfo.isUser || loginOnly) && !isRegister) {
37
+ await auth.signIn({
38
+ username: `+86 ${phoneNum}`,
39
+ verification_token,
40
+ });
41
+
37
42
  if (bindInfo) {
38
43
  await auth.bindWithProvider({
39
44
  provider_token: bindInfo.providerToken,
40
45
  });
41
46
  }
42
- } else if (!isV2) {
47
+ } else if (!hasRegisterConfig || isRegister) {
43
48
  // 自定义应用走signUp逻辑
44
49
  await auth.signUp({
45
50
  phone_number: `+86 ${phoneNum}`,
@@ -0,0 +1,41 @@
1
+ export const randomStr = (len = 32) => {
2
+ const s = [];
3
+ const hexDigits = '0123456789abcdef';
4
+ const dictLen = hexDigits.length;
5
+ for (var i = 0; i < len; i++) {
6
+ const index = Math.floor(Math.random() * dictLen);
7
+ s[i] = hexDigits[index];
8
+ }
9
+ const result = s.join('');
10
+ return result;
11
+ }
12
+
13
+ export const compareVersion = (version1, version2) => {
14
+ // 将版本号字符串分割成数组
15
+ const v1 = version1.split('.');
16
+ const v2 = version2.split('.');
17
+
18
+ // 获取两个版本号数组的最大长度
19
+ const maxLength = Math.max(v1.length, v2.length);
20
+
21
+ // 遍历版本号数组并比较每个部分
22
+ for (let i = 0; i < maxLength; i++) {
23
+ // 如果某个版本号的长度较短,则将其补0
24
+ const num1 = parseInt(v1[i] || 0, 10);
25
+ const num2 = parseInt(v2[i] || 0, 10);
26
+
27
+ // 比较当前位置的数字大小
28
+ if (num1 > num2) {
29
+ return 1;
30
+ } else if (num1 < num2) {
31
+ return -1;
32
+ }
33
+ }
34
+
35
+ // 如果所有位置的数字都相同,则两个版本号相等
36
+ return 0;
37
+ }
38
+
39
+ export const calDelay = (enable, delay) => {
40
+ return enable ? Math.max(0, Math.ceil(((delay || 0) - +new Date()) / 1000)) : 0;
41
+ }