438e8c46 by joe

登录、验证接口

1 parent 69f5d420
...@@ -12,10 +12,15 @@ module.exports = { ...@@ -12,10 +12,15 @@ module.exports = {
12 gsRegCheck : "/pingan_hklife_webapi/auth/gsRegCheck", 12 gsRegCheck : "/pingan_hklife_webapi/auth/gsRegCheck",
13 // 账户整合登录接口 13 // 账户整合登录接口
14 gsLogin : "/pingan_hklife_webapi/auth/gsLogin", 14 gsLogin : "/pingan_hklife_webapi/auth/gsLogin",
15 // 注册接口
16 stdRegister : "/pingan_hklife_webapi/auth/stdRegister",
15 // 找回密码定位用户信息 17 // 找回密码定位用户信息
16 gsLocateUserV2 : "/pingan_hklife_webapi/auth/gsLocateUserV2", 18 gsLocateUserV2 : "/pingan_hklife_webapi/auth/gsLocateUserV2",
17 // 账户整合忘记密码重置用户密码 19 // 账户整合忘记密码重置用户密码
18 gsResetPwd : "/pingan_hklife_webapi/auth/gsResetPwd", 20 gsResetPwd : "/pingan_hklife_webapi/auth/gsResetPwd",
19 // 账户整合修改密码接口 21 // 账户整合修改密码接口
20 gsModifyPwd : "/pingan_hklife_webapi/auth/gsModifyPwd", 22 gsModifyPwd : "/pingan_hklife_webapi/auth/gsModifyPwd",
23 // 短信验证码登录
24 otpLogin : "/pingan_hklife_webapi/otpLogin",
25
21 } 26 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -137,6 +137,18 @@ module.exports = { ...@@ -137,6 +137,18 @@ module.exports = {
137 verifyCodeGet: "獲取驗證碼", 137 verifyCodeGet: "獲取驗證碼",
138 }, 138 },
139 register: { 139 register: {
140 mobileOptions: [{
141 type: "hk",
142 name: "香港手機號",
143 placeHolder: "請輸入8位手機號碼",
144 areaCode: "+852"
145 }, {
146 type: "zh",
147 name: "大陸手機號",
148 placeHolder: "請輸入11位手機號碼",
149 areaCode: "+86"
150 }],
151 coutTips : "{second}秒後重新獲取",
140 title: "歡迎註冊一賬通", 152 title: "歡迎註冊一賬通",
141 title2: "請設置新的密碼", 153 title2: "請設置新的密碼",
142 mobilePlaceholder: "请输入8位手机号码", 154 mobilePlaceholder: "请输入8位手机号码",
......
...@@ -15,24 +15,24 @@ module.exports = { ...@@ -15,24 +15,24 @@ module.exports = {
15 list: [{ 15 list: [{
16 name: "註冊", 16 name: "註冊",
17 path: "/register", 17 path: "/register",
18 type : "noAuth", 18 type: "noAuth",
19 value: "" 19 value: ""
20 },{ 20 }, {
21 name: "登入", 21 name: "登入",
22 path: "/login", 22 path: "/login",
23 type : "noAuth", 23 type: "noAuth",
24 value: "" 24 value: ""
25 }, 25 },
26 { 26 {
27 name: "修改密碼", 27 name: "修改密碼",
28 path: "", 28 path: "",
29 type : "auth", 29 type: "auth",
30 value: "" 30 value: ""
31 }, 31 },
32 { 32 {
33 name: "登出", 33 name: "登出",
34 path: "", 34 path: "",
35 type : "auth", 35 type: "auth",
36 value: "logout" 36 value: "logout"
37 }, 37 },
38 ] 38 ]
...@@ -137,6 +137,18 @@ module.exports = { ...@@ -137,6 +137,18 @@ module.exports = {
137 verifyCodeGet: "獲取驗證碼", 137 verifyCodeGet: "獲取驗證碼",
138 }, 138 },
139 register: { 139 register: {
140 mobileOptions: [{
141 type: "hk",
142 name: "香港手機號",
143 placeHolder: "請輸入8位手機號碼",
144 areaCode: "+852"
145 }, {
146 type: "zh",
147 name: "大陸手機號",
148 placeHolder: "請輸入11位手機號碼",
149 areaCode: "+86"
150 }],
151 coutTips : "{second}秒後重新獲取",
140 title: "歡迎註冊一賬通", 152 title: "歡迎註冊一賬通",
141 title2: "請設置新的密碼", 153 title2: "請設置新的密碼",
142 mobilePlaceholder: "請輸入8位手機號碼", 154 mobilePlaceholder: "請輸入8位手機號碼",
...@@ -250,7 +262,7 @@ module.exports = { ...@@ -250,7 +262,7 @@ module.exports = {
250 t4Title: "受益人資料", // t4BeneficiaryInformation 262 t4Title: "受益人資料", // t4BeneficiaryInformation
251 t4NameCn: "姓名(中文)", 263 t4NameCn: "姓名(中文)",
252 t4NameEn: "姓名(英文)", 264 t4NameEn: "姓名(英文)",
253 t4Relation : "與受保人關係", 265 t4Relation: "與受保人關係",
254 t4Allocation: "分配比例", 266 t4Allocation: "分配比例",
255 267
256 t5Title: "繳費資料", 268 t5Title: "繳費資料",
...@@ -267,8 +279,8 @@ module.exports = { ...@@ -267,8 +279,8 @@ module.exports = {
267 t6ClosingDate: "實收日期", 279 t6ClosingDate: "實收日期",
268 t6PaymentAmount: "繳費金額", 280 t6PaymentAmount: "繳費金額",
269 }, 281 },
270 reservation :{ 282 reservation: {
271 submitBtn : '確認' 283 submitBtn: '確認'
272 } 284 }
273 } 285 }
274 } 286 }
......
...@@ -15,24 +15,24 @@ module.exports = { ...@@ -15,24 +15,24 @@ module.exports = {
15 list: [{ 15 list: [{
16 name: "注册", 16 name: "注册",
17 path: "/register", 17 path: "/register",
18 type : "noAuth", 18 type: "noAuth",
19 value: "" 19 value: ""
20 },{ 20 }, {
21 name: "登陆", 21 name: "登陆",
22 path: "/login", 22 path: "/login",
23 type : "noAuth", 23 type: "noAuth",
24 value: "" 24 value: ""
25 }, 25 },
26 { 26 {
27 name: "修改密码", 27 name: "修改密码",
28 path: "", 28 path: "",
29 type : "auth", 29 type: "auth",
30 value: "" 30 value: ""
31 }, 31 },
32 { 32 {
33 name: "登出", 33 name: "登出",
34 path: "", 34 path: "",
35 type : "auth", 35 type: "auth",
36 value: "logout" 36 value: "logout"
37 }, 37 },
38 ] 38 ]
...@@ -137,6 +137,18 @@ module.exports = { ...@@ -137,6 +137,18 @@ module.exports = {
137 verifyCodeGet: "获取验证码", 137 verifyCodeGet: "获取验证码",
138 }, 138 },
139 register: { 139 register: {
140 mobileOptions: [{
141 type: "hk",
142 name: "香港手机号",
143 placeHolder: "请输入8位手机号码",
144 areaCode: "+852"
145 }, {
146 type: "zh",
147 name: "大陆手机号",
148 placeHolder: "请输入11位手机号码",
149 areaCode: "+86"
150 }],
151 coutTips : "{second}秒后重新获取",
140 title: "欢迎注册一账通", 152 title: "欢迎注册一账通",
141 title2: "请设置新的密码", 153 title2: "请设置新的密码",
142 mobilePlaceholder: "请输入8位手机号码", 154 mobilePlaceholder: "请输入8位手机号码",
...@@ -250,7 +262,7 @@ module.exports = { ...@@ -250,7 +262,7 @@ module.exports = {
250 t4Title: "受益人资料", // t4BeneficiaryInformation 262 t4Title: "受益人资料", // t4BeneficiaryInformation
251 t4NameCn: "姓名(中文)", 263 t4NameCn: "姓名(中文)",
252 t4NameEn: "姓名(英文)", 264 t4NameEn: "姓名(英文)",
253 t4Relation : "与受保人关系", 265 t4Relation: "与受保人关系",
254 t4Allocation: "分配比例", 266 t4Allocation: "分配比例",
255 267
256 t5Title: "缴费资料", 268 t5Title: "缴费资料",
...@@ -267,8 +279,8 @@ module.exports = { ...@@ -267,8 +279,8 @@ module.exports = {
267 t6ClosingDate: "实收日期", 279 t6ClosingDate: "实收日期",
268 t6PaymentAmount: "缴费金额", 280 t6PaymentAmount: "缴费金额",
269 }, 281 },
270 reservation :{ 282 reservation: {
271 submitBtn : '确认' 283 submitBtn: '确认'
272 } 284 }
273 } 285 }
274 } 286 }
......
...@@ -84,7 +84,7 @@ export default { ...@@ -84,7 +84,7 @@ export default {
84 this.sTitle = curData.name; 84 this.sTitle = curData.name;
85 window.location.reload(); 85 window.location.reload();
86 } else { 86 } else {
87 console.log("curData.value == =", curData.value) 87 // console.log("curData.value == =", curData.value)
88 if (curData.value == "logout") { 88 if (curData.value == "logout") {
89 // this.$store.commit("SET_USER_INFO", null); 89 // this.$store.commit("SET_USER_INFO", null);
90 this._loginHandler(); 90 this._loginHandler();
......
...@@ -6,9 +6,6 @@ import { ...@@ -6,9 +6,6 @@ import {
6 httpGet, 6 httpGet,
7 httpPost 7 httpPost
8 } from '@/api/fetch-api.js' 8 } from '@/api/fetch-api.js'
9 import { reject } from '_any-promise@1.3.0@any-promise';
10
11 let urls
12 9
13 let PK = 'B5FE03847F02046C47292AF0FF2DE88977241483DD40C123046EB39CBE4C48167B120096CFF12CD16559322884A3C56FA92B07B89AB51FC8C91A75127622151DDD730DFF1F993D5A290CEAC0BBA7FC88285D8994ACBAFF50101EDE9A0925AD5DFFAFE96D53C370E9C5B37DF2F871F81C4D7CA6B7EC37FF459C07975AD9A74A95'; 10 let PK = 'B5FE03847F02046C47292AF0FF2DE88977241483DD40C123046EB39CBE4C48167B120096CFF12CD16559322884A3C56FA92B07B89AB51FC8C91A75127622151DDD730DFF1F993D5A290CEAC0BBA7FC88285D8994ACBAFF50101EDE9A0925AD5DFFAFE96D53C370E9C5B37DF2F871F81C4D7CA6B7EC37FF459C07975AD9A74A95';
14 let E = '10001'; 11 let E = '10001';
...@@ -22,10 +19,27 @@ export default { ...@@ -22,10 +19,27 @@ export default {
22 // 返回的token,串连整个流程,后台安全校验使用 19 // 返回的token,串连整个流程,后台安全校验使用
23 token: "", 20 token: "",
24 deviceId: "", 21 deviceId: "",
22 vcodeuuid: "",
23 token: "",
24 deviceId: "",
25 imageBase64: "",
26 password: "",
27 passwordRepeat: ""
28 },
29 times: {
30 interval: 0, // 索引
31 remain: 0, // 剩余时间
32 tip: "" // 显示的文字
25 }, 33 },
26 loginForm: { 34 loginForm: {
27 userId: "18334783910", 35 // userId: "18334783910",
28 password: "qweqwe123" 36 // password: "qweqwe123"
37 userId: "",
38 password: "",
39
40 imageValue: "",
41 mobileNo: "",
42 otp: ""
29 }, 43 },
30 loginCheck: { 44 loginCheck: {
31 showImageCode: false, 45 showImageCode: false,
...@@ -99,11 +113,17 @@ export default { ...@@ -99,11 +113,17 @@ export default {
99 }, 113 },
100 handlerLogin() { 114 handlerLogin() {
101 this.refreshDeviceId(); 115 this.refreshDeviceId();
102 // console.log("this.loginCheck.agreeProtocol == ", this.loginCheck.agreeProtocol);
103 if (!this.loginCheck.agreeProtocol) { 116 if (!this.loginCheck.agreeProtocol) {
104 this._showAgreeProtocalTips(); 117 this._showAgreeProtocalTips();
105 return; 118 return;
106 } 119 }
120 if (this.type == 1) {
121 this._passwordLogin();
122 } else {
123 this._otpLogin();
124 }
125 },
126 _passwordLogin() {
107 // 刷新图形二维码 127 // 刷新图形二维码
108 this.handlerIsShowImageVcode().then(() => { 128 this.handlerIsShowImageVcode().then(() => {
109 httpPost({ 129 httpPost({
...@@ -121,7 +141,7 @@ export default { ...@@ -121,7 +141,7 @@ export default {
121 // 处理登录结果 141 // 处理登录结果
122 _handlerLoginResponse(response) { 142 _handlerLoginResponse(response) {
123 // let res = response.content; 143 // let res = response.content;
124 if (response.returnCode == 0) { 144 if (response.returnCode == 0 || response.resultCode == "0") {
125 this.$store.commit("SET_USER_INFO", response.data); 145 this.$store.commit("SET_USER_INFO", response.data);
126 this._redirectTo(); 146 this._redirectTo();
127 } else { 147 } else {
...@@ -141,14 +161,160 @@ export default { ...@@ -141,14 +161,160 @@ export default {
141 path: path 161 path: path
142 }); 162 });
143 }, 163 },
144 handlerSendOTP() { 164 _otpLogin() {
145 // 发送短信 165 this._checkOptParams().then(() => {
166 let data = {
167 mobileNo: this.loginForm.mobileNo,
168 token: this.values.token,
169 otp: this.loginForm.otp,
170 deviceId: this.refreshDeviceId()
171 };
172 httpPost({
173 url: api.otpLogin,
174 data: data
175 }).then(response => {
176 this._handlerLoginResponse(response);
177 });
178 });
179 },
180 _checkOptParams() {
181 return new Promise((resolve, reject) => {
182 this._checkMobileLegal().then(() => {
183 if (!this.loginForm.otp) {
184 this._showOtpEmptyTips();
185 return;
186 }
187 if (!this.values.token) {
188 this._showGetOptTips();
189 return;
190 }
191 resolve();
192 });
193 })
194 },
195 _showGetOptTips() {
196 alert('请先获取短信验证码');
197 },
198 _showImageValueTip() {
199 alert("请输入图片验证码")
200 },
201 _showOtpEmptyTips() {
202 alert('请输入短信验证码');
203 },
204 handlerStdSendOTP() {
205 // 发送短信验证码
206 this._checkMobileLegal().then(() => {
207 if (this.times.remain > 0) {
208 return;
209 }
210 if (this.values.vcodeuuid && !this.loginForm.imageValue) {
211 this._showImageValueTip();
212 return;
213 }
214 this._handlerIsShowImageVcode().then(() => {
215 this._startStdSendOTP();
216 this._startTimeClick();
217 });
218 });
219 },
220 handlerRefreshImageValue() {
221 httpPost({
222 url: api.stdRefreshVcode,
223 data: {
224 vcodeuuid: this.values.vcodeuuid
225 }
226 }).then(response => {
227 this.values.imageBase64 = response.data.image;
228 })
229 },
230 _checkMobileLegal() {
231 // 检测手机号是否正确
232 return new Promise((resolve, reject) => {
233 let mobile = this.loginForm.mobileNo;
234 if (mobile.length != 8 && mobile.length != 11) {
235 this._showMobileNoIllegalTip()
236 return;
237 }
238 resolve(true);
239 });
240 },
241 _handlerIsShowImageVcode() {
242 return new Promise((resolve, reject) => {
243 // 如果这个值不为空,标识出现了图片验证码,不需要重新询问是否需要图像验证码了
244 if (this.values.vcodeuuid) {
245 resolve();
246 return;
247 }
248 httpPost({
249 url: api.stdIsShowImageVcode,
250 data: {
251 deviceId: this.values.deviceId,
252 userId: this.loginForm.mobileNo
253 }
254 }).then(response => {
255 // 判断是否显示图形验证码
256 if (response.returnCode == "0") {
257 this.values.token = response.data.token;
258 if (response.data.isShowVcode == "N") {
259 // if (!this.values.vcodeuuid) {
260 // this.loginCheck.showImageCode = true;
261 // this.values.vcodeuuid = "123456";
262 // return;
263 // }
264 this.values.vcodeuuid = null;
265 resolve(response);
266 } else {
267 // image 值:
268 this.loginCheck.showImageCode = true;
269 this.values.vcodeuuid = response.data.vcodeuuid;
270 this.values.imageBase64 = response.data.image;
271 }
272 }
273 return false;
274 })
275 });
146 }, 276 },
147 handlerValidateOTPandRepeat() { 277 _showMobileNoIllegalTip() {
148 // 验证短信验证码 278 alert("手机号不正确");
279 },
280 _startStdSendOTP() {
281 // 正式发送OTP信号
282 let data = {
283 mobileNo: this.loginForm.mobileNo,
284 token: this.values.token,
285 signFactor: new Date().getTime(),
286 scene: "otpLogin",
287 deviceId: this.refreshDeviceId()
288 }
289 if (this.values.vcodeuuid) {
290 data["vcodeuuid"] = this.values.vcodeuuid;
291 data["imageValue"] = this.loginForm.imageValue;
292 }
293 httpPost({ url: api.stdSendOTP, data: data });
294 },
295 _startTimeClick() {
296 this.times.remain = 120;
297 let _this = this;
298 let i18n = this.$i18n.messages[this.$i18n.locale] || {};
299 let msg = i18n.register.coutTips;
300 _this.times.tip = msg.replace("{second}", _this.times.remain);
301 this.times.interval = setInterval(function () {
302 if (_this.times.remain <= 0) {
303 clearInterval(_this.times.interval);
304 _this.times.interval = 0;
305 _this.times.remain = 0;
306 return;
307 }
308 _this.times.remain--;
309 _this.times.tip = msg.replace("{second}", _this.times.remain);
310 _this.$set(_this, 'times', _this.times);
311 }, 1000);
149 }, 312 },
150 refreshDeviceId() { 313 refreshDeviceId() {
151 this.values.deviceId = this.values.deviceId || (Math.random() + "").substring(2) 314 if (!this.values.deviceId) {
315 this.values.deviceId = (Math.random() + "").substring(2)
316 }
317 return this.values.deviceId
152 }, 318 },
153 _passwordEncrypt(rawPwd) { 319 _passwordEncrypt(rawPwd) {
154 let rsa = new RSAKey(); 320 let rsa = new RSAKey();
...@@ -158,6 +324,11 @@ export default { ...@@ -158,6 +324,11 @@ export default {
158 return res; 324 return res;
159 } 325 }
160 }, 326 },
327 watch: {
328 type() {
329 this.loginCheck.showImageCode = false;
330 }
331 },
161 mounted() { 332 mounted() {
162 // console.log("PK === ", this.PK) 333 // console.log("PK === ", this.PK)
163 // console.log("E === ", this.E) 334 // console.log("E === ", this.E)
......
...@@ -124,6 +124,15 @@ ...@@ -124,6 +124,15 @@
124 justify-content: space-between; 124 justify-content: space-between;
125 flex-wrap: wrap; 125 flex-wrap: wrap;
126 126
127 .vcode {
128 background-color: transparent !important;
129 padding: 0 !important;
130 overflow: hidden;
131 img {
132 width: 100%;
133 height: 100%;
134 }
135 }
127 136
128 &-item { 137 &-item {
129 position: relative; 138 position: relative;
...@@ -189,6 +198,7 @@ ...@@ -189,6 +198,7 @@
189 color: #4c4948; 198 color: #4c4948;
190 } 199 }
191 200
201
192 // 框内按钮 202 // 框内按钮
193 .ipt2 { 203 .ipt2 {
194 display: flex; 204 display: flex;
...@@ -204,13 +214,12 @@ ...@@ -204,13 +214,12 @@
204 color: #f05a23; 214 color: #f05a23;
205 text-decoration: underline; 215 text-decoration: underline;
206 } 216 }
207 }
208
209
210
211 217
218 .veri-btn-default {
219 color: #aaaaaa;
220 }
221 }
212 } 222 }
213
214 } 223 }
215 } 224 }
216 225
......
...@@ -35,10 +35,12 @@ ...@@ -35,10 +35,12 @@
35 <input v-model="loginForm.password" :placeholder="$t('login.passwordPlaceholder')" class="ipt" type="password"> 35 <input v-model="loginForm.password" :placeholder="$t('login.passwordPlaceholder')" class="ipt" type="password">
36 </div> 36 </div>
37 </div> 37 </div>
38 <div class="pure-u-1 form-item" v-if="loginCheck.showImageCode"> 38 <div class="pure-u-1 form-item" v-if="type == 1 && loginCheck.showImageCode">
39 <div class="ipt-wrap"> 39 <div class="ipt-wrap">
40 <input :placeholder="$t('login.verifyPlaceholder')" class="ipt ipt-verify" type="text"> 40 <input :placeholder="$t('login.verifyPlaceholder')" class="ipt ipt-verify" type="text" v-model="loginForm.imageValue">
41 <div class="ipt verify-btn pointer">5136</div> 41 <div class="ipt verify-btn pointer vcode" @click="handlerRefreshImageValue">
42 <img :src="values.imageBase64">
43 </div>
42 </div> 44 </div>
43 </div> 45 </div>
44 </div> 46 </div>
...@@ -73,7 +75,15 @@ ...@@ -73,7 +75,15 @@
73 <img src="@/assets/images/login/icon-login-phone.png"> {{$t('login.mobile')}} 75 <img src="@/assets/images/login/icon-login-phone.png"> {{$t('login.mobile')}}
74 </div> 76 </div>
75 <div class="ipt-wrap"> 77 <div class="ipt-wrap">
76 <input :placeholder="$t('login.mobilePlaceholder')" class="ipt" type="text"> 78 <input :placeholder="$t('login.mobilePlaceholder')" class="ipt" type="text" v-model="loginForm.mobileNo">
79 </div>
80 </div>
81 <div class="pure-u-1 form-item" v-if="type == 2 && loginCheck.showImageCode">
82 <div class="ipt-wrap">
83 <input :placeholder="$t('login.verifyPlaceholder')" class="ipt ipt-verify" type="text" v-model="loginForm.imageValue">
84 <div class="ipt verify-btn pointer vcode" @click="handlerRefreshImageValue">
85 <img :src="values.imageBase64">
86 </div>
77 </div> 87 </div>
78 </div> 88 </div>
79 <div class="pure-u-1 form-item"> 89 <div class="pure-u-1 form-item">
...@@ -82,17 +92,20 @@ ...@@ -82,17 +92,20 @@
82 </div> 92 </div>
83 <div class="ipt-wrap"> 93 <div class="ipt-wrap">
84 <div class="ipt ipt2"> 94 <div class="ipt ipt2">
85 <input :placeholder="$t('login.verifyCodePlaceholder')" class="ipt-code" type="text"> 95 <input :placeholder="$t('login.verifyCodePlaceholder')" class="ipt-code" type="text" v-model="loginForm.otp">
86 <div class="veri-btn pointer"> {{$t('login.verifyCodeGet')}}</div> 96 <div v-if="times.remain == 0" class="veri-btn pointer" @click="handlerStdSendOTP" >{{$t('register.verifyCodeGet')}}</div>
97 <div v-else class="veri-btn-default">{{times.tip}}</div>
87 </div> 98 </div>
88 </div> 99 </div>
89 </div> 100 </div>
90 </div> 101 </div>
91 <div class="login-protocol"> 102 <div class="login-protocol pointer" @click="loginCheck.agreeProtocol = !loginCheck.agreeProtocol" >
92 <img @click="onCheckHandler()" class="check pointer" src="@/assets/images/login/login-check.png"> {{$t('login.agree')}} 103 <img v-if="!loginCheck.agreeProtocol" class="check" src="@/assets/images/login/un-check.png">
104 <img v-if="loginCheck.agreeProtocol" class="check" src="@/assets/images/login/check.png">
105 {{$t('login.agree')}}
93 <span @click="onProtocolHandler()" class="protocol pointer">{{$t('login.protocol')}}</span> 106 <span @click="onProtocolHandler()" class="protocol pointer">{{$t('login.protocol')}}</span>
94 </div> 107 </div>
95 <div @click="onSubmitHandler()" class="login-submit pointer">{{$t('login.login')}}</div> 108 <div @click="handlerLogin()" class="login-submit pointer">{{$t('login.login')}}</div>
96 <div class="login-func"> 109 <div class="login-func">
97 <div @click="onRegisterHandler()" class="login-func-btn pointer">{{$t('login.register')}}</div> 110 <div @click="onRegisterHandler()" class="login-func-btn pointer">{{$t('login.register')}}</div>
98 <div @click="onForgetHandler()" class="login-func-btn pointer">{{$t('login.forget')}}</div> 111 <div @click="onForgetHandler()" class="login-func-btn pointer">{{$t('login.forget')}}</div>
......
...@@ -4,11 +4,43 @@ import { ...@@ -4,11 +4,43 @@ import {
4 httpPost 4 httpPost
5 } from '@/api/fetch-api.js' 5 } from '@/api/fetch-api.js'
6 6
7 let PK = 'B5FE03847F02046C47292AF0FF2DE88977241483DD40C123046EB39CBE4C48167B120096CFF12CD16559322884A3C56FA92B07B89AB51FC8C91A75127622151DDD730DFF1F993D5A290CEAC0BBA7FC88285D8994ACBAFF50101EDE9A0925AD5DFFAFE96D53C370E9C5B37DF2F871F81C4D7CA6B7EC37FF459C07975AD9A74A95';
8 let E = '10001';
9
7 export default { 10 export default {
8 data() { 11 data() {
9 return { 12 return {
10 key: 'value', 13 key: 'value',
11 type: 1, // 1:手机验证 2:输入密码 14 type: 1, // 1:手机验证 2:输入密码
15 mobileNoType: "hk",// 选择的手机好类型
16 mobileTip: {},
17 mobileOptions: [],
18
19 registerCheck: {
20 showImageCode: false,
21 agreeProtocol: false
22 },
23 values: {
24 // 返回的token,串连整个流程,后台安全校验使用
25 vcodeuuid: "",
26 token: "",
27 deviceId: "",
28 imageBase64: "",
29 password: "",
30 passwordRepeat: ""
31 },
32 registerForm: {
33 imageValue: "",
34 mobileNo: "",
35 otp: ""
36 },
37 times: {
38 interval: 0, // 索引
39 remain: 0, // 剩余时间
40 tip: "" // 显示的文字
41 },
42 PK: process.env.RSA_PUBLIC_KEY || PK,
43 E: process.env.RSA_KEY_INDEX || E,
12 } 44 }
13 }, 45 },
14 components: {}, 46 components: {},
...@@ -21,19 +53,324 @@ export default { ...@@ -21,19 +53,324 @@ export default {
21 } 53 }
22 }, 54 },
23 methods: { 55 methods: {
24 onCheckHandler() {
25
26 },
27 onProtocolHandler() { 56 onProtocolHandler() {
28 this.$router.push({ 57 this.$router.push({
29 path: "/protocol" 58 path: "/protocol"
30 }) 59 })
31 }, 60 },
61 handlerStdSendOTP() {
62 // 发送短信验证码
63 this._checkMobileLegal().then(() => {
64 if (this.times.remain > 0) {
65 return;
66 }
67 if (this.values.vcodeuuid && !this.registerForm.imageValue) {
68 this._showImageValueTip();
69 return;
70 }
71 this._handlerIsShowImageVcode().then(() => {
72 this._startStdSendOTP();
73 this._startTimeClick();
74 });
75 });
76 },
77 _checkMobileLegal() {
78 // 检测手机号是否正确
79 return new Promise((resolve, reject) => {
80 let mobile = this.registerForm.mobileNo;
81 if (this.mobileNoType == "hk") {
82 if (mobile.length != 8) {
83 this._showMobileNoIllegalTip()
84 return;
85 }
86 } else {
87 if (mobile.length != 11) {
88 this._showMobileNoIllegalTip()
89 return;
90 }
91 }
92 resolve(true);
93 });
94 },
95 _handlerIsShowImageVcode() {
96 return new Promise((resolve, reject) => {
97
98 // 如果这个值不为空,标识出现了图片验证码,不需要重新询问是否需要图像验证码了
99 if (this.values.vcodeuuid) {
100 resolve();
101 return;
102 }
103
104 httpPost({
105 url: api.stdIsShowImageVcode,
106 data: {
107 deviceId: this.values.deviceId,
108 userId: this.registerForm.mobileNo
109 }
110 }).then(response => {
111 // 判断是否显示图形验证码
112 if (response.returnCode == "0") {
113 this.values.token = response.data.token;
114 if (response.data.isShowVcode == "N") {
115 // 测试代码
116 // if (!this.values.vcodeuuid) {
117 // this.registerCheck.showImageCode = true;
118 // this.values.vcodeuuid = "123456";
119 // return;
120 // }
121 this.values.vcodeuuid = null;
122 resolve(response);
123 } else {
124 // image 值:
125 this.registerCheck.showImageCode = true;
126 this.values.vcodeuuid = response.data.vcodeuuid;
127 this.values.imageBase64 = response.data.image;
128 }
129 }
130 return false;
131 })
132 });
133 },
134 _showMobileNoIllegalTip() {
135 alert("手机号不正确");
136 },
137 _startStdSendOTP() {
138 // 正式发送OTP信号
139 let data = {
140 mobileNo: this.registerForm.mobileNo,
141 token: this.values.token,
142 signFactor: new Date().getTime(),
143 scene: "register",
144 }
145 if (this.values.vcodeuuid) {
146 data["vcodeuuid"] = this.values.vcodeuuid;
147 data["imageValue"] = this.registerForm.imageValue;
148 }
149 httpPost({ url: api.stdSendOTP, data: data });
150 },
151 _startTimeClick() {
152 this.times.remain = 120;
153 let _this = this;
154 let i18n = this.$i18n.messages[this.$i18n.locale] || {};
155 let msg = i18n.register.coutTips;
156 _this.times.tip = msg.replace("{second}", _this.times.remain);
157 this.times.interval = setInterval(function () {
158 if (_this.times.remain <= 0) {
159 clearInterval(_this.times.interval);
160 _this.times.interval = 0;
161 _this.times.remain = 0;
162 return;
163 }
164 _this.times.remain--;
165 _this.times.tip = msg.replace("{second}", _this.times.remain);
166 _this.$set(_this, 'times', _this.times);
167 }, 1000);
168 },
32 onSubmitHandler() { 169 onSubmitHandler() {
170 // this.type = 2;
171 this._checkParams().then(() => {
172 this._regCheck().then(() => {
173 // 验证短信验证码
174 this._validateOTPandRepeat().then(() => {
33 this.type = 2; 175 this.type = 2;
176 });
177 });
178 });
179 },
180 _validateOTPandRepeat() {
181 return new Promise((resolve, reject) => {
182 let data = {
183 mobileNo: this.registerForm.mobileNo,
184 token: this.values.token,
185 signFactor: new Date().getTime(),
186 otp: this.registerForm.opt
187 };
188 httpPost({
189 url: api.stdValidateOTPandRepeat,
190 data: data
191 }).then(response => {
192 if (response.returnCode != "0") {
193 this._showCheckOTPErrTip(response.returnMsg);
194 // TODO 测试代码
195 // resolve();
196 } else {
197 // this.type = 2;
198 resolve();
199 }
200 })
201 });
202 },
203 _regCheck() {
204 // 检测手机号注册情况
205 return new Promise((resolve, reject) => {
206 let data = {
207 mobileNo: this.registerForm.mobileNo,
208 };
209 httpPost({
210 url: api.gsRegCheck,
211 data: data
212 }).then(response => {
213 if (response.returnCode == "0") {
214 if (response.data.mobileStatus == "N") {
215 resolve();
216 } else {
217 // 重复注册
218 this._showDuplicateRegistrationTip();
219 }
220 } else {
221 // 错误提示
222 this._showCheckOTPErrTip(response.returnMsg);
223 }
224 })
225 });
226 },
227 _checkParams() {
228 return new Promise((resolve, reject) => {
229 if (!this.registerCheck.agreeProtocol) {
230 this._showAgreeProtocolTip();
231 return;
232 }
233 if (!this.values.token) {
234 this._showTokenTip();
235 return;
236 }
237 if (this.values.vcodeuuid && !this.registerForm.imageValue) {
238 this._showImageValueTip();
239 return;
240 }
241 if (!this.registerForm.opt) {
242 this._showOTPTip();
243 return;
244 }
245 this._checkMobileLegal().then(() => {
246 resolve();
247 })
248 });
249 },
250
251 _showAgreeProtocolTip() {
252 alert("请同意协议")
253 },
254 _showOTPTip() {
255 alert("请填写短信验证码")
256 },
257 _showTokenTip() {
258 alert("请先请求短信验证码")
259 },
260 _showDuplicateRegistrationTip() {
261 alert("手机号已经被注册,请使用其他手机号重新注册")
262 },
263 _showImageValueTip() {
264 alert("请输入图片验证码")
265 },
266 _showCheckOTPErrTip(msg) {
267 alert(msg);
34 }, 268 },
35 onRegisterHandler() { 269 onRegisterHandler() {
270 this._checkPassword().then(() => {
271 let data = {
272 token: this.values.token,
273 mobileNo: this.registerForm.mobileNo,
274 loginPwd: this._passwordEncrypt(this.values.password)
275 };
276 httpPost({
277 url: api.stdRegister,
278 data: data
279 }).then(response => {
280 if (response.returnCode != 0) {
281 this._showRegisterFailure(response);
282 this.type = 1;
283 } else {
284 this._showSuccessMessage();
285 this.$router.push({
286 path: "/login"
287 });
288 }
289 })
290 });
291 },
292 _checkPassword() {
293 return new Promise((resolve, reject) => {
294 let password = this.values.password;
295 if (password.length < 8) {
296 this._showPasswordLenthNotEnouth();
297 return;
298 }
299 // 匹配字母
300 let m1 = /([a-z])+/.test(password);
301 let m2 = /([A-Z])+/.test(password);
302 // 匹配数字
303 let m3 = /([0-9])+/.test(password);
304 // 匹配特殊字符
305 let m4 = /[^a-zA-Z0-9]+/.test(password);
306 console.log(m1, m2, m3, m4)
307 if ((m1 | m2) & m3 & m4) {
308 if (password != this.values.passwordRepeat) {
309 this._showPasswordNotTheSameTips();
310 } else {
311 resolve();
312 }
313 } else {
314 this._showPasswordComplexityTips();
315 }
316 });
317 },
318 _showPasswordLenthNotEnouth() {
319 alert("密码长度不能少于8位")
320 },
321 _showPasswordComplexityTips() {
322 alert("密码必须同时包含数字、字母、特殊字符")
323 },
324 _showPasswordNotTheSameTips() {
325 alert("两次输入的密码不一致")
326 },
327 _showRegisterFailure(response) {
328 if ("COMMON_ERROR_052" == response.returnCode) {
329 this._resetRegisterParam();
330 this.handlerRefreshImageVcode();
331 alert("验证码过期,请重新申请验证码");
332 } else {
333 this._resetAllParams();
334 alert("注册失败,请联系工作人员");
335 }
336 },
337 _resetAllParams() {
338 this.values.vcodeuuid = "";
339 this.values.token = "";
340 this.values.imageBase64 = "";
341 this.values.password = "";
342 this.values.passwordRepeat = "";
36 343
344 this.registerForm.imageValue = "";
345 this.registerForm.mobileNo = "";
346 this.registerForm.otp = "";
347
348 this.times.interval = "";
349 this.times.remain = "";
350 this.times.tip = "";
351 },
352 _resetRegisterParam() {
353 this.values.token = "";
354 this.registerForm.otp = "";
355 this.times.interval = "";
356 this.times.remain = "";
357 this.times.tip = "";
358 },
359 handlerRefreshImageVcode() {
360 if (this.values.vcodeuuid) {
361 let data = {
362 vcodeuuid: this.values.vcodeuuid
363 }
364 httpPost({
365 url: api.stdRefreshVcode,
366 data: data
367 }).then(response => {
368 this.$set(this.values, 'imageBase64', response.data.image);
369 })
370 }
371 },
372 _showSuccessMessage() {
373 alert("注册成功")
37 }, 374 },
38 onForgetHandler() { 375 onForgetHandler() {
39 376
...@@ -41,8 +378,31 @@ export default { ...@@ -41,8 +378,31 @@ export default {
41 onLoginTypeHandler(val) { 378 onLoginTypeHandler(val) {
42 379
43 }, 380 },
44 initData() {} 381 _passwordEncrypt(rawPwd) {
382 let rsa = new RSAKey();
383 rsa.setPublic(this.PK, this.E);
384 let res = rsa.encrypt(rawPwd);
385 if (res == null) return rawPwd;
386 return res;
45 }, 387 },
46 mounted() {}, 388 initData() {
47 created() {} 389 let i18n = this.$i18n.messages[this.$i18n.locale] || {};
390 let mobileOptions = JSON.parse(JSON.stringify(i18n.register.mobileOptions));
391 this.mobileOptions = mobileOptions;
392 this.mobileTip = this.mobileOptions[0];
393 }
394 },
395 mounted() { },
396 watch: {
397 mobileNoType() {
398 this.mobileOptions.forEach(element => {
399 if (element.type == this.mobileNoType) {
400 this.$set(this, 'mobileTip', element);
401 }
402 })
403 }
404 },
405 created() {
406 this.initData();
407 }
48 } 408 }
......
...@@ -120,6 +120,20 @@ ...@@ -120,6 +120,20 @@
120 justify-content: space-between; 120 justify-content: space-between;
121 flex-wrap: wrap; 121 flex-wrap: wrap;
122 122
123 .vcode {
124 background-color: transparent !important;
125 padding: 0 !important;
126 overflow: hidden;
127 img {
128 width: 100%;
129 height: 100%;
130 }
131 }
132
133 input {
134 font-size: 1.166667rem; /* 14/12 */
135 letter-spacing: .1rem;/* 1.2/12 */
136 }
123 137
124 &-item { 138 &-item {
125 position: relative; 139 position: relative;
...@@ -206,6 +220,9 @@ ...@@ -206,6 +220,9 @@
206 color: #f05a23; 220 color: #f05a23;
207 text-decoration: underline; 221 text-decoration: underline;
208 } 222 }
223 .veri-btn-default {
224 color: #aaaaaa;
225 }
209 } 226 }
210 227
211 } 228 }
......
...@@ -16,36 +16,44 @@ ...@@ -16,36 +16,44 @@
16 <div class="pure-u-1 form-item"> 16 <div class="pure-u-1 form-item">
17 <div class="ipt-wrap"> 17 <div class="ipt-wrap">
18 <img class="down-arrow" src="@/assets/images/reservation/re-down-arrow.png" alt=""> 18 <img class="down-arrow" src="@/assets/images/reservation/re-down-arrow.png" alt="">
19 <select class="ipt"> 19 <select class="ipt" v-model="mobileNoType">
20 <template v-if="locale == 'zh'"> 20 <option v-for="(item,index) in mobileOptions" :key="index" :value="item.type">{{item.name}}</option>
21 <option>香港手机号</option>
22 </template>
23 <template v-else>
24 <option>香港手機號</option>
25 </template>
26 </select> 21 </select>
27 </div> 22 </div>
28 </div> 23 </div>
29 <div class="pure-u-1 form-item"> 24 <div class="pure-u-1 form-item">
30 <div class="ipt-wrap"> 25 <div class="ipt-wrap">
31 <div class="ipt ipt2"> 26 <div class="ipt ipt2">
32 <div class="region-tel">+852</div> 27 <div class="region-tel">{{mobileTip.areaCode}}</div>
33 <input :placeholder="$t('register.mobilePlaceholder')" class="ipt-tel" type="text"> 28 <input :placeholder="mobileTip.placeHolder" class="ipt-tel" type="text" v-model="registerForm.mobileNo">
29 </div>
30 </div>
31 </div>
32
33 <div class="pure-u-1 form-item" v-if="registerCheck.showImageCode">
34 <div class="ipt-wrap">
35 <input :placeholder="$t('login.verifyPlaceholder')" class="ipt ipt-verify" type="text" v-model="registerForm.imageValue">
36 <div class="ipt verify-btn pointer vcode" @click="handlerRefreshImageVcode">
37 <img :src="values.imageBase64">
34 </div> 38 </div>
35 </div> 39 </div>
36 </div> 40 </div>
37 <div class="pure-u-1 form-item"> 41 <div class="pure-u-1 form-item">
38 <div class="ipt-wrap"> 42 <div class="ipt-wrap">
39 <div class="ipt ipt2"> 43 <div class="ipt ipt2">
40 <input :placeholder="$t('register.verifyCodePlaceholder')" class="ipt-code" type="text"> 44 <input :placeholder="$t('register.verifyCodePlaceholder')" class="ipt-code" type="text" v-model="registerForm.opt">
41 <div class="veri-btn pointer">{{$t('register.verifyCodeGet')}}</div> 45 <div v-if="times.remain == 0" class="veri-btn pointer" @click="handlerStdSendOTP" >{{$t('register.verifyCodeGet')}}</div>
46 <div v-else class="veri-btn-default">{{times.tip}}</div>
42 </div> 47 </div>
43 </div> 48 </div>
44 </div> 49 </div>
45 </div> 50 </div>
46 <div class="login-protocol"> 51
47 <img @click="onCheckHandler()" class="check pointer" src="@/assets/images/login/login-check.png">{{$t('register.agree')}} 52 <div class="login-protocol pointer" @click="registerCheck.agreeProtocol = !registerCheck.agreeProtocol" >
48 <span @click="onProtocolHandler()" class="protocol pointer">{{$t('register.protocol')}}</span> 53 <img v-if="!registerCheck.agreeProtocol" class="check" src="@/assets/images/login/un-check.png">
54 <img v-if="registerCheck.agreeProtocol" class="check" src="@/assets/images/login/check.png">
55 {{$t('login.agree')}}
56 <span @click="onProtocolHandler()" class="protocol pointer">{{$t('login.protocol')}}</span>
49 </div> 57 </div>
50 <div @click="onSubmitHandler()" class="login-submit pointer">{{$t('register.register')}}</div> 58 <div @click="onSubmitHandler()" class="login-submit pointer">{{$t('register.register')}}</div>
51 </div> 59 </div>
...@@ -57,7 +65,7 @@ ...@@ -57,7 +65,7 @@
57 <img src="@/assets/images/register/icon-register-lock.png"> {{$t('register.newPassword')}} 65 <img src="@/assets/images/register/icon-register-lock.png"> {{$t('register.newPassword')}}
58 </div> 66 </div>
59 <div class="ipt-wrap"> 67 <div class="ipt-wrap">
60 <input :placeholder="$t('register.newPasswordPlaceholder')" class="ipt" type="text"> 68 <input :placeholder="$t('register.newPasswordPlaceholder')" class="ipt" type="password" v-model="values.password">
61 </div> 69 </div>
62 </div> 70 </div>
63 <div class="pure-u-1 form-item"> 71 <div class="pure-u-1 form-item">
...@@ -65,11 +73,11 @@ ...@@ -65,11 +73,11 @@
65 <img src="@/assets/images/register/icon-register-lock.png"> {{$t('register.newPasswordSure')}} 73 <img src="@/assets/images/register/icon-register-lock.png"> {{$t('register.newPasswordSure')}}
66 </div> 74 </div>
67 <div class="ipt-wrap"> 75 <div class="ipt-wrap">
68 <input :placeholder="$t('register.newPasswordSurePlaceholder')" class="ipt" type="text"> 76 <input :placeholder="$t('register.newPasswordSurePlaceholder')" class="ipt" type="password" v-model="values.passwordRepeat">
69 </div> 77 </div>
70 </div> 78 </div>
71 </div> 79 </div>
72 <div @click="onSubmitHandler()" class="login-submit pointer">{{$t('register.sure')}}</div> 80 <div @click="onRegisterHandler()" class="login-submit pointer">{{$t('register.sure')}}</div>
73 </div> 81 </div>
74 </div> 82 </div>
75 </div> 83 </div>
......