@cloudbase/lowcode-builder 1.8.105 → 1.8.106

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.
@@ -1,7 +1,10 @@
1
- import { app, $app } from '../../../../app/weapps-api'
2
- import loginByPassword from './methods/loginByPassword'
3
- import loginByWXPhone from './methods/loginByWXPhone'
4
- import { getLoginConfig } from '../../../../common/util'
1
+ import { app, $app } from '../../../../app/weapps-api';
2
+ import loginByPassword from './methods/loginByPassword';
3
+ import loginByWXPhone from './methods/loginByWXPhone';
4
+ import { parseSmsError } from './methods/errorHandler';
5
+ import loginBySms from './methods/loginBySms';
6
+ import { getLoginConfig } from '../../../../common/util';
7
+ import { phoneNumberPattern, phoneVerifyInfoKey, verifyDelay, loginOnly } from './methods/contants';
5
8
 
6
9
  function decodePageQuery(query) {
7
10
  return Object.keys(query).reduce((decoded, key) => {
@@ -10,107 +13,172 @@ function decodePageQuery(query) {
10
13
  }, {});
11
14
  }
12
15
 
16
+ const BUTTON_CLASSNAME = 'weda-ui weda-button weui-btn weui-btn_primary wd-event-tap';
17
+
18
+ function setStorage(data) {
19
+ const current = wx.getStorageSync(phoneVerifyInfoKey);
20
+ wx.setStorageSync(phoneVerifyInfoKey, { ...current, ...data });
21
+ }
22
+
13
23
  Component({
14
24
  data: {
15
25
  params: {},
16
26
  initing: true,
17
27
  error: null,
18
28
  settingData: {
19
- "logo": "",
20
- "agreement": {
21
- "items": [],
22
- "enable": false
29
+ logo: '',
30
+ agreement: {
31
+ items: [],
32
+ enable: false,
23
33
  },
24
- "miniprogram": [],
34
+ miniprogram: [],
25
35
  },
26
36
  pageStyle: '',
27
37
  agreement: false,
28
38
  wxLoginStatus: '',
29
39
  passwordVisible: false,
30
40
  enablePassword: false,
31
- enableMpPhone: false
41
+ enableMpPhone: false,
42
+ enbaleSms: false,
43
+ disableLoginSubmit: false,
44
+ loginButtonClass: BUTTON_CLASSNAME,
45
+ phoneValidateMessage: '手机号为空',
46
+ phoneNum: '',
47
+ defaultPhoneNumber: '',
48
+ smsVerificationInfo: {
49
+ id: '',
50
+ isUser: false,
51
+ },
32
52
  },
33
53
  methods: {
34
54
  async getPhoneCodeNumber(e) {
35
- if (
36
- e?.detail?.errMsg?.includes('fail') ||
37
- e?.detail?.errno ||
38
- !e?.detail?.code
39
- ) {
40
- console.warn(
41
- '获取手机号授权令牌失败:',
42
- !e?.detail.code ? { errMsg: '可能基础库版本过低' } : e.detail
43
- );
55
+ const agree = this.checkAgreement();
56
+ if (!agree) {
57
+ return;
58
+ }
59
+ if (e?.detail?.errMsg?.includes('fail') || e?.detail?.errno || !e?.detail?.code) {
60
+ console.warn('获取手机号授权令牌失败:', !e?.detail.code ? { errMsg: '可能基础库版本过低' } : e.detail);
44
61
 
45
62
  $app.showModal({
46
- "cancelColor": "#000000",
47
- "cancelText": "取消",
48
- "confirmColor": "#576B95",
49
- "confirmText": "确认",
50
- "showCancel": true,
51
- "title": "获取手机号授权令牌失败",
52
- "content": `获取手机号授权令牌失败: ${e.detail.errno || e.detail?.errMsg || '可能基础库版本过低'}`
53
- })
63
+ cancelColor: '#000000',
64
+ cancelText: '取消',
65
+ confirmColor: '#576B95',
66
+ confirmText: '确认',
67
+ showCancel: true,
68
+ title: '获取手机号授权令牌失败',
69
+ content: `获取手机号授权令牌失败: ${e.detail.errno || e.detail?.errMsg || '可能基础库版本过低'}`,
70
+ });
54
71
 
55
72
  return;
56
73
  }
57
74
 
58
- return loginByWXPhone(this, { event: e })
75
+ return loginByWXPhone(this, { event: e });
59
76
  },
60
77
  async onLoad(options) {
61
78
  try {
79
+ const cache = wx.getStorageSync(phoneVerifyInfoKey);
80
+ if (cache.phoneNum) {
81
+ this.setData({ defaultPhoneNumber: cache.phoneNum, phoneNum: cache.phoneNum, phoneValidateMessage: '' });
82
+ }
83
+
62
84
  const config = await getLoginConfig().catch(() => {
63
- return getLoginConfig()
64
- })
85
+ return getLoginConfig();
86
+ });
65
87
  const query = decodePageQuery(options || {});
66
88
  let settingData = {
67
- "logo": app.__internal__.resolveStaticResourceUrl(config.logo) || "https://sso-1303824488.cos.ap-shanghai.myqcloud.com/logo.svg",
68
- "agreement": {
69
- "items": [],
70
- "enable": false,
71
- ...config.agreement
89
+ logo:
90
+ app.__internal__.resolveStaticResourceUrl(config.logo) ||
91
+ 'https://sso-1303824488.cos.ap-shanghai.myqcloud.com/logo.svg',
92
+ agreement: {
93
+ items: [],
94
+ enable: false,
95
+ ...config.agreement,
72
96
  },
73
- "miniprogram": config.miniprogram || [],
74
- }
97
+ miniprogram: config.miniprogram || [],
98
+ };
99
+
100
+ const enableSms = this._getEnableSms(settingData);
101
+ const smsDelay =
102
+ enableSms && !cache.phoneNum ? Math.max(0, Math.ceil(((cache?.smsDelay || 0) - +new Date()) / 1000)) : 0;
103
+
75
104
  this.setData({
76
105
  params: query,
77
106
  settingData,
78
107
  enablePassword: this._getEnablePassword(settingData),
79
108
  enableMpPhone: this._getEnableMpPhone(settingData),
109
+ enableSms,
110
+ smsDelay,
111
+ smsVerificationInfo: cache,
80
112
  pageStyle: `${this.data.pageStyle}; background-color: ${config.backgroundColor || '#fff'};`,
81
- initing: false
82
- })
83
- } catch(e) {
84
- console.error('获取登录配置失败:', e)
113
+ initing: false,
114
+ });
115
+
116
+ if (smsDelay > 0) {
117
+ this._intervalSender(smsDelay);
118
+ }
119
+ } catch (e) {
120
+ console.error('获取登录配置失败:', e);
85
121
  this.setData({
86
122
  initing: false,
87
123
  error: {
88
- message: '获取登录配置失败,' + (e.message || '')
89
- }
90
- })
124
+ message: '获取登录配置失败,' + (e.message || ''),
125
+ },
126
+ });
91
127
  }
92
128
  },
93
129
  togglePasswordVisible() {
94
130
  this.setData({
95
- passwordVisible: !this.data.passwordVisible
96
- })
131
+ passwordVisible: !this.data.passwordVisible,
132
+ });
97
133
  },
98
134
  loginByPassword(e) {
99
- const values = e.detail.value
135
+ if (!this.checkAgreement()) {
136
+ return;
137
+ }
138
+
139
+ const values = e.detail.value;
140
+
141
+ return loginByPassword(this, {
142
+ phone: values?.username?.value,
143
+ sms: values?.password?.value,
144
+ });
145
+ },
146
+ loginBySms(e) {
147
+ if (!this.checkAgreement()) {
148
+ return;
149
+ }
100
150
 
101
- return loginByPassword(this, { username: values?.username?.value, password: values?.password?.value })
151
+ const values = e.detail.value;
152
+
153
+ return loginBySms(this, {
154
+ phoneNum: values?.phoneNum,
155
+ verificationCode: values?.verificationCode,
156
+ verificationInfo: this.data.smsVerificationInfo,
157
+ callback: (err, data) => {
158
+ if (err) {
159
+ const { usedCount = 0 } = wx.getStorageSync(phoneVerifyInfoKey) || {};
160
+ setStorage({ usedCount: usedCount + 1 });
161
+ } else {
162
+ setStorage({ usedCount: 0, smsDelay: 0 });
163
+ }
164
+ },
165
+ });
102
166
  },
103
167
  showAgreement(e) {
104
- const index = e.currentTarget?.dataset?.index
105
- const agreementContent = this.data.settingData.agreement.items[index]?.value
168
+ const index = e.currentTarget?.dataset?.index;
169
+ const agreementContent = this.data.settingData.agreement.items[index]?.value;
106
170
  this.setData({
107
171
  agreementContent,
108
- isShowAgreement: !!agreementContent
109
- })
172
+ isShowAgreement: !!agreementContent,
173
+ });
110
174
  },
111
- checkAgreement(e) {
112
- if (this.data.settingData.agreement.enable && !this.data.agreement) {
113
- app.showToast({ title: '请阅读勾选协议', icon: 'error', duartion: 1500 })
175
+ checkAgreement() {
176
+ if (this.data.settingData?.agreement?.enable && !this.data.agreement) {
177
+ app.showToast({
178
+ title: '请阅读勾选协议',
179
+ icon: 'error',
180
+ duartion: 1500,
181
+ });
114
182
 
115
183
  return false;
116
184
  }
@@ -118,17 +186,108 @@ Component({
118
186
  },
119
187
  onAgreementChange(e) {
120
188
  this.setData({
121
- agreement: e.detail.value.length > 0
122
- })
189
+ agreement: e.detail.value.length > 0,
190
+ });
191
+ },
192
+ onPhoneChange(e) {
193
+ const { value } = e.detail;
194
+ if (!phoneNumberPattern.test(value)) {
195
+ this.setData({ phoneValidateMessage: '手机号格式非法', phoneNum: value });
196
+ } else {
197
+ this.setData({ phoneValidateMessage: '', phoneNum: value });
198
+ }
199
+ },
200
+ getCaptcha(e) {
201
+ if (this.data.phoneValidateMessage) {
202
+ wx.showToast({
203
+ icon: 'error',
204
+ title: this.data.phoneValidateMessage,
205
+ });
206
+ return;
207
+ }
208
+ if (this.data.smsDelay > 0) {
209
+ return;
210
+ }
211
+ this._intervalSender(verifyDelay);
212
+ const target = loginOnly ? 'USER' : 'ANY';
213
+ const phoneNum = this.data.phoneNum;
214
+ app.cloud
215
+ .getCloudInstance()
216
+ .then((cloudbase) => {
217
+ return cloudbase.authInstance || cloudbase.auth;
218
+ })
219
+ .then((auth) => {
220
+ setStorage({ phoneNum });
221
+ return auth.getVerification({
222
+ target,
223
+ phone_number: `+86 ${phoneNum}`,
224
+ });
225
+ })
226
+ .then((data) => {
227
+ const verifyInfo = {
228
+ id: data.verification_id,
229
+ isUser: data.is_user,
230
+ };
231
+ this.setData({
232
+ smsVerificationInfo: verifyInfo,
233
+ });
234
+ setStorage({ ...verifyInfo, usedCount: 0 });
235
+ wx.showToast({
236
+ title: '验证码已发送',
237
+ });
238
+ })
239
+ .catch((e) => {
240
+ wx.hideLoading()
241
+ clearInterval(this.timerInterval);
242
+ this.setData({ smsDelay: 0 });
243
+ setStorage({ smsDelay: 0 });
244
+ wx.showModal({
245
+ title: '获取验证码失败',
246
+ content: parseSmsError(e, target, loginOnly),
247
+ showCancel: false,
248
+ });
249
+ });
123
250
  },
124
251
  _getEnablePassword(settingData) {
125
- const config = settingData || this.data.settingData
126
- return config.miniprogram?.find?.(item => item.type === 'password')?.enable ?? false
252
+ const config = settingData || this.data.settingData;
253
+ return config.miniprogram?.find?.((item) => item.type === 'password')?.enable ?? false;
127
254
  },
128
255
  _getEnableMpPhone(settingData) {
129
- const config = settingData || this.data.settingData
130
- return !!config.miniprogram.find(function (item) { return item.type === 'miniprogram_phone' }
131
- )
256
+ const config = settingData || this.data.settingData;
257
+ return !!config.miniprogram.find(function (item) {
258
+ return item.type === 'miniprogram_phone';
259
+ })?.enable;
260
+ },
261
+ _getEnableSms(settingData) {
262
+ const config = settingData || this.data.settingData;
263
+ return !!config.miniprogram.find(function (item) {
264
+ return item.type === 'sms';
265
+ })?.enable;
266
+ },
267
+ _intervalSender(delay) {
268
+ this.setData({ smsDelay: delay });
269
+ const timerInterval = setInterval(() => {
270
+ delay = delay - 1;
271
+ if (delay <= 0) {
272
+ clearInterval(timerInterval);
273
+ }
274
+ this.setData({ smsDelay: delay });
275
+ setStorage({ smsDelay: +new Date() + delay * 1000 });
276
+ }, 1000);
277
+ this.timerInterval = timerInterval;
132
278
  },
133
- }
134
- })
279
+ },
280
+ observers: {
281
+ 'settingData,agreement': function (settingData, agreement) {
282
+ const disabled = settingData?.agreement?.enable && !agreement;
283
+ if (!!this.data.disableLoginSubmit !== disabled) {
284
+ this.setData({ disableLoginSubmit: disabled });
285
+ }
286
+ },
287
+ disableLoginSubmit: function (disableLoginSubmit) {
288
+ this.setData({
289
+ loginButtonClass: `${BUTTON_CLASSNAME} ${disableLoginSubmit ? 'is-disabled' : ''}`,
290
+ });
291
+ },
292
+ },
293
+ });
@@ -4,7 +4,8 @@
4
4
  "gsd-h5-react-Modal": "../../../../materials/gsd-h5-react/components/modal/index",
5
5
  "gsd-h5-react-RichTextView": "../../../../materials/gsd-h5-react/components/richText/index",
6
6
  "wd-ph": "../../../../common/placeholder/index",
7
- "wd-info": "../../../../common/info/index"
7
+ "wd-info": "../../../../common/info/index",
8
+ "captcha-dialog": "./components/captchaDialog/index"
8
9
  },
9
10
  "componentPlaceholder": {
10
11
  "gsd-h5-react-Modal": "wd-ph",
@@ -1,29 +1,48 @@
1
1
  <page-meta page-style="{{pageStyle}}">
2
- <view wx:if="{{!initing && !error}}" id="wd-page-root" class="wd-mp-root" data-weui-theme="light">
3
- <view id="id33" style="width:90%;margin:0px auto;display:flex;flex-direction:column;max-width:50rem;" class="login-class">
4
- <view id="id44" style="margin:80px 0px;">
5
- <image id="id15" style="margin:0px auto;display:flex;justify-content:center;width: 120px;height: 120px;" class="weda-ui weda-image" mode="aspectFit" src="{{settingData.logo}}" />
2
+ <view wx:if="{{!initing && !error}}" class="wd-mp-root" data-weui-theme="light">
3
+ <view style="width:90%;margin:0px auto;display:flex;flex-direction:column;max-width:50rem;" class="login-class">
4
+ <view style="margin:80px 0px 60px;">
5
+ <image style="margin:0px auto;display:flex;justify-content:center;width: 80px;height: 80px;" class="weda-ui weda-image" mode="aspectFit" src="{{settingData.logo}}" />
6
6
  </view>
7
- <view id="container1" wx:if="{{enablePassword}}">
7
+ <view wx:if="{{enablePassword}}">
8
8
  <form bindsubmit="loginByPassword">
9
- <login-input id="input1" name="username" placeholder="请输入用户名" type="text" />
10
- <view id="container2" style="margin-bottom:30px;position:relative;">
11
- <login-input id="input2" name="password" placeholder="请输入密码" type="{{passwordVisible?'text':'password'}}" />
12
- <image id="image1" style="width:20PX;height:20PX;position:absolute;right:17px;top:20px;z-index: 9999;" class="weda-ui weda-image wd-event-tap" mode="widthFix" src="{{passwordVisible?'https://qcloudimg.tencent-cloud.cn/raw/487eba32ccfc23ebc68f8fac005d6919.svg':'https://qcloudimg.tencent-cloud.cn/raw/0b6cef53d62a3356e3bcc5bd83341482.svg'}}" bind:tap="togglePasswordVisible" />
9
+ <login-input name="username" placeholder="请输入用户名" type="text" />
10
+ <view style="margin-bottom:30px;position:relative;">
11
+ <login-input name="password" placeholder="输入验证码" style="padding-right:100px" type="{{passwordVisible?'text':'password'}}">
12
+ <image style="width:20px;height:20px;padding:0 10px;box-sizing: content-box;" class="weda-ui weda-image wd-event-tap input-suffix" mode="widthFix" src="{{passwordVisible?'https://qcloudimg.tencent-cloud.cn/raw/487eba32ccfc23ebc68f8fac005d6919.svg':'https://qcloudimg.tencent-cloud.cn/raw/0b6cef53d62a3356e3bcc5bd83341482.svg'}}" bind:tap="togglePasswordVisible" slot="suffix" />
13
+ </login-input>
13
14
  </view>
14
- <button id="button1" class="weda-ui weda-button weui-btn weui-btn_primary wd-event-tap" style="width:100%;border-radius:5px;" size="md" form-type="submit">
15
+ <button class="{{loginButtonClass}}" style="width:100%;border-radius:5px;" size="md" form-type="submit">
15
16
  账号密码登录
16
17
  </button>
17
18
  </form>
18
19
  </view>
19
- <view id="id37" style="display:flex;flex-direction:column;">
20
- <view id="id48" style="width:100%;margin-top:20px;position:relative;" wx:if="{{enableMpPhone}}">
21
- <button style="width:100%;margin-top:0px;z-index:1;font-weight:normal;border-radius:0.5713rem;background:rgb(7, 193, 96);position:absolute;left:0px;top:0px;" bindgetphonenumber="getPhoneCodeNumber" aria-disabled="false" open-type="getPhoneNumber" role="button" class="weda-ui weda-button weui-btn weui-btn_primary weui-btn_wechat">登录</button>
22
- <button id="id47" style="width:100%;margin-top:0px;z-index:1;font-weight:normal;border-radius:0.5713rem;background:rgb(7, 193, 96);position:absolute;left:0px;top:0px;" role="button" class="weda-ui weda-button weui-btn weui-btn_primary wd-event-tap wd-event-tap" bind:tap="checkAgreement" wx:if="{{settingData.agreement.enable && !agreement}}">登录</button>
23
- </view>
20
+ <view wx:if="{{enableSms}}">
21
+ <form bindsubmit="loginBySms">
22
+ <login-input name="phoneNum" defaultValue="{{defaultPhoneNumber}}" placeholder="输入手机号" type="number" auto maxlength="11" bindchange="onPhoneChange">
23
+ <view class="input-prefix" style="color:#acacac;padding: 0 10px" slot="prefix">
24
+ +86
25
+ </view>
26
+ </login-input>
27
+ <view style="margin-bottom:30px;position:relative;">
28
+ <login-input name="verificationCode" placeholder="输入验证码" style="padding-right:100px" type="text" maxlength="6">
29
+ <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">
30
+ {{smsDelay > 0 ? '重新获取'+smsDelay : '获取验证码'}}
31
+ </view>
32
+ </login-input>
33
+ </view>
34
+ <button class="{{loginButtonClass}}" style="width:100%;border-radius:5px;" size="md" form-type="submit">
35
+ 登录
36
+ </button>
37
+ </form>
38
+ </view>
39
+ <view wx:if="{{enableMpPhone}}">
40
+ <button style="width:100%;border-radius: 5px;" bindgetphonenumber="getPhoneCodeNumber" open-type="getPhoneNumber" role="button" class="{{loginButtonClass}}">
41
+ 登录
42
+ </button>
24
43
  </view>
25
- <view id="id11" 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}}">
26
- <view id="id19" class="weda-ui weda-ui-to-wd">
44
+ <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}}">
45
+ <view class="weda-ui weda-ui-to-wd">
27
46
  <view class="weda-ui weda-checkbox wd-event-change">
28
47
  <view class="weda-ui weda-formcells weui-cells weui-cells_checkbox weui-flex">
29
48
  <view class="weui-flex__item">
@@ -44,17 +63,23 @@
44
63
  </view>
45
64
  </view>
46
65
  </view>
47
- <text class="weda-text weda-ui wd-event-tap" style="white-space: pre-line; margin:0px 5px;display:flex;align-items:center;color:rgb(68, 144, 238);text-align:center;white-space:pre-line;" wx:if="{{settingData.agreement.items[0].enable}}" data-index="0" bind:tap="showAgreement">《{{settingData.agreement.items[0].label}}》</text>
48
- <text id="id14" style="white-space: pre-warp; display:flex;align-items:center;white-space:pre-line;" class="weda-text weda-ui" wx:if="{{settingData.agreement.items[0].enable && settingData.agreement.items[1].enable}}">和</text>
49
- <text class="weda-text weda-ui wd-event-tap" id="id12" style="white-space: pre-line; margin:0px 5px;display:flex;align-items:center;color:rgb(68, 144, 238);white-space:pre-line;" data-index="1" wx:if="{{settingData.agreement.items[1].enable}}" bind:tap="showAgreement">《{{settingData.agreement.items[1].label}}》</text>
66
+ <text class="weda-text weda-ui wd-event-tap" style="white-space: pre-line; margin:0px 5px;display:flex;align-items:center;color:rgb(68, 144, 238);text-align:center;white-space:pre-line;" wx:if="{{settingData.agreement.items[0].enable}}" data-index="0" bind:tap="showAgreement">
67
+ {{settingData.agreement.items[0].label}}
68
+ </text>
69
+ <text style="white-space: pre-warp; display:flex;align-items:center;white-space:pre-line;" class="weda-text weda-ui" wx:if="{{settingData.agreement.items[0].enable && settingData.agreement.items[1].enable}}">
70
+
71
+ </text>
72
+ <text class="weda-text weda-ui wd-event-tap" style="white-space: pre-line; margin:0px 5px;display:flex;align-items:center;color:rgb(68, 144, 238);white-space:pre-line;" data-index="1" wx:if="{{settingData.agreement.items[1].enable}}" bind:tap="showAgreement">
73
+ 《{{settingData.agreement.items[1].label}}》
74
+ </text>
50
75
  </view>
51
76
  </view>
52
- <gsd-h5-react-Modal id="id4" style="position: absolute;" isDefaultButton="{{false}}" visible="{{isShowAgreement}}" bind:close="showAgreement">
53
- <scroll-view id="id6" style="height:500px;margin-top:20px;" class="weda-ui" scroll-y="true" slot="customContent">
54
- <gsd-h5-react-RichTextView id="id5" style="height: 60%" value="{{agreementContent}}" />
77
+ <gsd-h5-react-Modal style="position: absolute;" isDefaultButton="{{false}}" visible="{{isShowAgreement}}" bind:close="showAgreement">
78
+ <scroll-view style="height:500px;margin-top:20px;" class="weda-ui" scroll-y="true" slot="customContent">
79
+ <gsd-h5-react-RichTextView style="height: 60%" value="{{agreementContent}}" />
55
80
  </scroll-view>
56
81
  </gsd-h5-react-Modal>
57
82
  </view>
58
83
  <wd-info type="{{initing? 'loading': 'auth'}}" wx:if="{{initing || error}}" message="{{loading?'加载配置中...':' '}}" error="{{error}}" />
59
- </page-meta>
60
-
84
+ <captcha-dialog />
85
+ </page-meta>
@@ -1,7 +1,8 @@
1
1
  button,
2
2
  button:hover,
3
3
  button,
4
- button:active {
4
+ button:active {
5
+ font-size: 14px !important;
5
6
  color: white;
6
7
  }
7
8
 
@@ -58,3 +59,17 @@ button:active {
58
59
  .login-class .have-read .weui-cells_checkbox .weui-icon-checked {
59
60
  width: 1.2rem;
60
61
  }
62
+
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;
67
+ }
68
+
69
+ .login-class .input-prefix {
70
+ border-right: 1px solid #dbdbdb;
71
+ }
72
+
73
+ .login-class .input-suffix {
74
+ border-left: 1px solid #dbdbdb;
75
+ }
@@ -0,0 +1,5 @@
1
+ export const phoneNumberPattern = /^1[0-9]{10}$/;
2
+ export const phoneVerifyInfoKey = 'sso_phone_verifyInfo'; // 获取短信信息缓存key
3
+ export const verifyCodeFailedLimit = 8; // 同一个短信验证码使用8次即提示错误
4
+ export const verifyDelay = 60; // 获取验证码倒计时,单位s
5
+ export const loginOnly = false;
@@ -0,0 +1,152 @@
1
+ export function prefixMsg(msg, prefix = ' - ') {
2
+ return `${msg ? prefix + msg : ''}`;
3
+ }
4
+
5
+ // 登录错误处理
6
+ export const parseLoginError = (e) => {
7
+ switch (e.error) {
8
+ case 'not_found':
9
+ return '用户不存在';
10
+ case 'password_not_set':
11
+ return '当前用户未设置密码,请使用验证码登录或第三方登录方式';
12
+ case 'invalid_password':
13
+ if (e.details && e.details.length > 0) {
14
+ return `密码验证失败, 您还有 ${e.details[0].remaining} 次重试机会`;
15
+ }
16
+ return '密码不正确';
17
+ case 'user_pending':
18
+ return '该用户未激活';
19
+ case 'user_blocked':
20
+ return '该用户被停用';
21
+ case 'invalid_status':
22
+ if (e.details && e.details.length > 0) {
23
+ const retryInSeconds = e.details[0].retry_in;
24
+ const retryInTime = retryInSeconds < 3600 ? `${retryInSeconds / 60}分钟` : `${retryInSeconds / 3600}小时`;
25
+ return `您已经超过了密码最大重试次数,请于 ${retryInTime} 后重试`;
26
+ }
27
+ return '您已经超过了密码最大重试次数,请稍后重试';
28
+ case '__invalid_redirect_uri':
29
+ return 'redirect_uri参数无效';
30
+ case 'license_required':
31
+ return '该用户没有产品许可证,请授权后重试';
32
+ case 'unimplemented':
33
+ return '请在控制台上“身份源管理”页面,开启用户名密码登录';
34
+ default:
35
+ return '您输入的帐号或密码不正确,请重新输入';
36
+ }
37
+ };
38
+
39
+ export const parseSmsLoginError = (e) => {
40
+ switch (e.error) {
41
+ case 'not_found':
42
+ return '用户不存在';
43
+ default:
44
+ return parseSignUpError(e);
45
+ }
46
+ };
47
+
48
+ // 注册错误处理
49
+ export const parseSignUpError = (e) => {
50
+ switch (e.error) {
51
+ case 'failed_precondition':
52
+ return '您输入的手机号已被注册,请使用其他号码';
53
+ default:
54
+ return parseVerifyError(e);
55
+ }
56
+ };
57
+
58
+ // 验证码验证token
59
+ export const parseVerifyError = (e) => {
60
+ switch (e.error) {
61
+ case 'invalid_argument':
62
+ return `您输入的验证码不正确或已过期 ${e.message || ''}`;
63
+ case 'get_verify_code':
64
+ return '请重新获取验证码';
65
+ case 'aborted':
66
+ return '您尝试的次数过多,稍后重试';
67
+ default:
68
+ return parseCommonError(e);
69
+ }
70
+ };
71
+
72
+ // 三方登录表单错误
73
+ export const parseProviderSignError = (e) => {
74
+ switch (e.error) {
75
+ case 'permission_denied':
76
+ return '您当前的会话已过期,请返回重试';
77
+ case 'invalid_argument':
78
+ return '您输入的验证码不正确或已过期';
79
+ case 'aborted':
80
+ return '您尝试的次数过多,稍后重试';
81
+ default:
82
+ return parseCommonError(e);
83
+ }
84
+ };
85
+
86
+ // 重置密码错误
87
+ export const parseResetPasswordError = (e) => {
88
+ switch (e.error) {
89
+ case 'invalid_argument':
90
+ return '您输入的密码不符合要求, 请重新输入';
91
+ default:
92
+ return parseCommonError(e);
93
+ }
94
+ };
95
+
96
+ // 验证码验证token
97
+ export const parseProviderTokenError = (e) => {
98
+ switch (e.error) {
99
+ case 'failed_precondition':
100
+ return `从第三方获取用户信息失败${prefixMsg(e.error_description)}`;
101
+ case 'not_found':
102
+ return `没有找到匹配的用户\n请联系管理员确认您的配置`;
103
+ default:
104
+ return parseCommonError(e);
105
+ }
106
+ };
107
+
108
+ export function parseSmsError(e, verificationTarget, loginOnly) {
109
+ switch (e.error) {
110
+ case 'failed_precondition':
111
+ switch (verificationTarget) {
112
+ case 'USER':
113
+ if (loginOnly) {
114
+ return '用户不存在,请输入在平台注册过的手机号码';
115
+ }
116
+ return '你输入的手机号已被注册,请使用其他号码';
117
+ case 'NOT_USER':
118
+ return '该用户已被注册,请使用其他号码';
119
+ default:
120
+ return '短信功能未开启,请联系管理员开启';
121
+ }
122
+ case 'payment_required':
123
+ return '短信包剩余条数不足,请联系管理员充值';
124
+ case 'aborted':
125
+ return '你尝试的次数过多,稍后重试';
126
+ case 'unavailable':
127
+ return `发件服务不可用,请稍后重试${prefixMsg(e.error_description)}`;
128
+ default:
129
+ return parseCommonError(e);
130
+ }
131
+ }
132
+
133
+ export const parseCommonError = (e) => {
134
+ let msg;
135
+ switch (e.error) {
136
+ // __开头为前端异常
137
+ case '__invalid_redirect_uri':
138
+ msg = 'redirect_uri参数无效';
139
+ break;
140
+ case 'unreachable':
141
+ msg = `网络错误,请检查您的网络连接,稍后重试${prefixMsg(e.error_description)}`;
142
+ break;
143
+ case 'resource_exhausted':
144
+ return '验证码已被使用,或者尝试过于频繁,请稍后重试';
145
+ case 'license_required':
146
+ return '该用户没有产品许可证,请授权后重试';
147
+ default:
148
+ msg = `请刷新后重试${prefixMsg(e.error || e.message)}${prefixMsg(e.error_description)}`;
149
+ break;
150
+ }
151
+ return msg;
152
+ };