password.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. <template>
  2. <view>
  3. <view class="password-type-2">
  4. <!--顶部返回按钮-->
  5. <text class="back-btn iconfont iconzuo" @tap="navBack"></text>
  6. <view class="login-top" :class="'bg-' + themeColor.name">
  7. <view class="desc">
  8. <view class="title">Hi~</view>
  9. <text>{{ this.$i18n.locale == 'zh' ? '找回密码' : 'RetrievePassword' }}!</text>
  10. </view>
  11. <image class="login-pic" :src="loginPic"></image>
  12. </view>
  13. <view class="login-type-content">
  14. <image class="login-bg" :src="loginBg"></image>
  15. <view class="main">
  16. <view class="login-type-form">
  17. <view class="input-item" style="display: flex;">
  18. <text class="iconfont icondianhua" :class="'text-' + themeColor.name"></text>
  19. <input class="login-type-input" type="number" name="mobile"
  20. v-model="resetPasswordParams.mobile" :placeholder="i18n('EnterMobile')"
  21. maxlength="20" />
  22. <text @click="toGR" style="width:240upx;">
  23. <text
  24. style="max-width:100upx; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;display: inline-block;vertical-align: middle;">
  25. {{selectName}}</text>
  26. <text style="vertical-align: middle;"> ({{'+' + select}})</text>
  27. </text>
  28. </view>
  29. <view class="input-item input-item-sms-code">
  30. <text class="iconfont iconyanzhengma" :class="'text-' + themeColor.name"></text>
  31. <view class="input-wrapper">
  32. <view class="rf-input-wrapper">
  33. <input type="number" class="login-type-input" v-model="resetPasswordParams.code"
  34. :placeholder="i18n('EnterVerification')" maxlength="6" />
  35. </view>
  36. <button class="sms-code-btn" :disabled="smsCodeBtnDisabled" @click="getSmsCode">
  37. <text v-if="!smsCodeBtnDisabled">{{i18n('GetVerification')}}</text>
  38. <text v-else class="sms-code-resend">{{codeSeconds}}s{{i18n('resend')}}</text>
  39. <!-- {{`重新发送 (${codeSeconds})`}}</text> -->
  40. </button>
  41. </view>
  42. </view>
  43. <view class="input-item">
  44. <text class="iconfont iconmimaffffffpx" :class="'text-' + themeColor.name"></text>
  45. <input class="login-type-input" type="password" v-model="resetPasswordParams.password"
  46. :placeholder="this.$i18n.locale == 'zh' ? '请输入密码':'Please input a password'"
  47. maxlength="20" />
  48. </view>
  49. <view class="input-item">
  50. <text class="iconfont iconmimaffffffpx" :class="'text-' + themeColor.name"></text>
  51. <input class="login-type-input" type="password"
  52. v-model="resetPasswordParams.password_repetition"
  53. :placeholder="this.$i18n.locale == 'zh' ? '请输入确认密码':'Please input a password'"
  54. maxlength="20" />
  55. </view>
  56. </view>
  57. <view class="login-type-tips">
  58. <view @tap="navTo('/pages/public/login')" class="forget-section">
  59. {{this.$i18n.locale == 'zh' ? '马上登陆' :'login'}}
  60. </view>
  61. <text @tap="toHome">{{this.$i18n.locale == 'zh' ? '返回主页' :'Home'}}</text>
  62. </view>
  63. <button class="confirm-btn" :class="'bg-' + themeColor.name" :disabled="btnLoading"
  64. :loading="btnLoading" @tap="restPassword">
  65. {{this.$i18n.locale == 'zh' ? '找回密码' : 'RetrievePassword'}}
  66. </button>
  67. </view>
  68. </view>
  69. <view class="login-type-bottom" :class="'text-' + themeColor.name">
  70. {{ appName }}{{this.$i18n.locale == 'zh' ? '版权所有' : 'Copyright'}}
  71. </view>
  72. <u-toast ref="uToast" />
  73. </view>
  74. </view>
  75. </template>
  76. <script>
  77. import {
  78. smsCode,
  79. updatePassword
  80. } from '@/api/login';
  81. import moment from '@/common/moment';
  82. export default {
  83. data() {
  84. return {
  85. resetPasswordParams: {
  86. mobile: '',
  87. password: '',
  88. password_repetition: '',
  89. code: ''
  90. },
  91. btnLoading: false,
  92. type: null,
  93. smsCodeBtnDisabled: true,
  94. loginBg: this.$mAssetsPath.loginBg,
  95. loginPic: this.$mAssetsPath.loginPic,
  96. appName: this.$mSettingConfig.appName,
  97. reqBody: {},
  98. codeSeconds: 0, // 验证码发送时间间隔
  99. second: 60,
  100. service: '',
  101. phoneNum: '',
  102. userInfo: [],
  103. select: '0086',
  104. selectName: this.$i18n.locale == 'zh' ? '中国' : 'China',
  105. selectList: '',
  106. regLogStyle: '4'
  107. };
  108. },
  109. onLoad(options) {
  110. this.selectList = options.data ? JSON.parse(options.data) : {};
  111. this.select = this.selectList.id ? this.selectList.id : this.select;
  112. let countryName = this.$i18n.locale == 'zh' ? this.selectList.cnValue : this.selectList.enValue;
  113. this.selectName = countryName ? countryName : this.selectName;
  114. console.log('select:', this.select)
  115. console.log('selectName:', this.selectName)
  116. const time =
  117. moment().valueOf() / 1000 - uni.getStorageSync('pwdSmsCodeTime');
  118. if (time < 60) {
  119. this.codeSeconds =
  120. this.$mConstDataConfig.sendCodeTime - parseInt(time, 10);
  121. this.handleSmsCodeTime(this.codeSeconds);
  122. } else {
  123. this.codeSeconds = this.$mConstDataConfig.sendCodeTime;
  124. this.smsCodeBtnDisabled = false;
  125. uni.removeStorageSync('pwdSmsCodeTime');
  126. }
  127. this.type = options.type;
  128. },
  129. methods: {
  130. async getSmsCode() {
  131. //获取当前手机号的用户信息
  132. this.getUserInfo();
  133. },
  134. // 获取手机验证码
  135. async userInfoBack() {
  136. this.service = "TX";
  137. //发送验证码 判断当前是手机号还是邮箱号 短信:service:“TX" 邮件:service:“YJ
  138. let language = this.$i18n.locale;
  139. const res = await this.$myRequest({
  140. url: '/ums/umsUsers/Code',
  141. data: {
  142. account: this.phoneNum,
  143. service: this.service,
  144. language
  145. },
  146. });
  147. if (res.status == '200') {
  148. this.handleSmsCodeTime(this.second);
  149. return this.$refs.uToast.show({
  150. title: res.msg,
  151. type: 'success',
  152. }); //手机号不能为空
  153. } else {
  154. return this.$refs.uToast.show({
  155. title: res.msg,
  156. type: 'error',
  157. });
  158. }
  159. },
  160. //验证手机号合法性
  161. verificationTel(name) {
  162. if (!name) {
  163. return this.$refs.uToast.show({
  164. title: this.i18n('Mobilephonenumbercannotbeempty') + "!",
  165. type: 'warning',
  166. }); //手机号不能为空
  167. }
  168. // const regPhone = /^([0-9]*)$/;
  169. const regPhone = /^(0|86|17951)?(13[0-9]|15[123456789]|16[6]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
  170. if (regPhone.test(name)) {
  171. return true;
  172. } else {
  173. this.$refs.uToast.show({
  174. title: this.i18n('Pleaseenteravalidmobilephonenumber') + "!",
  175. type: 'warning',
  176. }); //请输入合法的手机号
  177. return false;
  178. }
  179. },
  180. async getUserInfo() {
  181. var bool = this.verificationTel(this.resetPasswordParams.mobile);
  182. if (!bool) {
  183. return;
  184. }
  185. //校验手机号/邮箱/验证码格式
  186. this.phoneNum = this.select + this.resetPasswordParams.mobile
  187. this.userInfoBack();
  188. //获取当前登录手机号的用户信息
  189. // const result = await this.$myRequest({
  190. // url: '/ums/umsUsers/getByUserName',
  191. // data: {
  192. // userName: this.phoneNum
  193. // }
  194. // });
  195. // if (result.status == 200 && result.data != null && result.data != "") {
  196. // this.userInfo = result.data;
  197. // } else {
  198. // this.$refs.uToast.show({
  199. // title: this.$i18n.locale == 'zh' ? '用户不存在' : 'user does not exist',
  200. // type: 'error',
  201. // })
  202. // };
  203. },
  204. handleSmsCodeTime(time) {
  205. let timer = setInterval(() => {
  206. if (time === 0) {
  207. clearInterval(timer);
  208. this.smsCodeBtnDisabled = false;
  209. } else {
  210. this.codeSeconds = time;
  211. this.smsCodeBtnDisabled = true;
  212. time--;
  213. }
  214. }, 1000);
  215. },
  216. //后台自动登录,获取token值
  217. async codeLogin() {
  218. this.service = "TX";
  219. const res = await this.$myRequest({
  220. url: '/sys/token',
  221. data: {},
  222. });
  223. const that = this;
  224. let token = res.data;
  225. let VCode = this.resetPasswordParams.code;
  226. this.phoneNum = this.select + this.resetPasswordParams.mobile
  227. // let page = JSON.stringify({
  228. // mobile: this.phoneNum,
  229. // code: VCode,
  230. // grant_type: 'password',
  231. // client_id: 'client_2',
  232. // client_secret: '1xapp',
  233. // });
  234. let page = {
  235. mobile: this.phoneNum,
  236. code: VCode,
  237. grant_type: 'password',
  238. client_id: 'client_2',
  239. client_secret: '1xapp',
  240. };
  241. const login = await this.$myRequest({
  242. url: '/ums/mobile/login',
  243. data: page,
  244. method: 'post',
  245. type: 'formData'
  246. });
  247. if (login.msg == 'ok') {
  248. try {
  249. uni.setStorageSync('user', login.data.userInfo);
  250. uni.setStorageSync('Auth-Token', login.data.access_token);
  251. //存储登录账号
  252. uni.setStorageSync('loginAccount', this.resetPasswordParams.mobile);
  253. } catch (e) {
  254. }
  255. this.toUpdatePassword();
  256. } else {
  257. return this.$refs.uToast.show({
  258. title: this.$i18n.locale == 'zh' ? '修改失败请重新再试' :
  259. 'Modification failed. Please try again',
  260. type: 'error',
  261. });
  262. }
  263. },
  264. // 更新密码
  265. async toUpdatePassword() {
  266. let Storage_data;
  267. let token;
  268. try {
  269. Storage_data = JSON.parse(uni.getStorageSync('user'));
  270. token = uni.getStorageSync('Auth-Token');
  271. } catch (e) {
  272. }
  273. let userId = Storage_data.id
  274. // console.log('Storage_data', Storage_data)
  275. console.log('userId', userId)
  276. // this.Storage_data = JSON.parse(uni.getStorageSync('user'));
  277. // this.AuthToken = uni.getStorageSync('Auth-Token');
  278. if (userId == "" || userId == null) {
  279. return this.$refs.uToast.show({
  280. title: this.$i18n.locale == 'zh' ? '系统繁忙,请稍后再试' :
  281. 'The system is busy. Please try again later',
  282. type: 'warning',
  283. });
  284. }
  285. if (this.resetPasswordParams.password == "" || this.resetPasswordParams.password == null) {
  286. return this.$refs.uToast.show({
  287. title: this.$i18n.locale == 'zh' ? '新密码不能为空' : 'New password cannot be empty',
  288. type: 'warning',
  289. });
  290. }
  291. if (this.resetPasswordParams.password_repetition == "" || this.resetPasswordParams
  292. .password_repetition == null) {
  293. return this.$refs.uToast.show({
  294. title: this.$i18n.locale == 'zh' ? '确认密码不能为空' : 'Confirm password cannot be empty',
  295. type: 'warning',
  296. });
  297. }
  298. //判断两次密码是否一致
  299. if (this.resetPasswordParams.password != this.resetPasswordParams.password_repetition) {
  300. return this.$refs.uToast.show({
  301. title: this.$i18n.locale == 'zh' ? '两次输入密码不一致' : 'The two passwords are inconsistent',
  302. type: 'warning',
  303. });
  304. }
  305. //校验密码格式
  306. var msg = /((?=.*\d)(?=.*\D)(?=.*[a-z])(?=.*[A-Z]))(?!^.*[\u4E00-\u9FA5].*$)^\S{8,20}$/.test(
  307. this.resetPasswordParams.password_repetition) ? "" : this.$i18n.locale == 'zh' ? '请输入8~20为密码' :
  308. 'Your password strength is too low, please enter your password';
  309. if (msg != "") {
  310. return this.$refs.uToast.show({
  311. title: msg,
  312. type: 'warning',
  313. });
  314. }
  315. let param = JSON.stringify({
  316. id: userId,
  317. password: this.resetPasswordParams.password_repetition,
  318. Authorization: token
  319. });
  320. const result = await this.$myRequest({
  321. url: '/ums/umsUsers/changePassword',
  322. method: 'post',
  323. data: {
  324. param: param
  325. }
  326. });
  327. if (result.status == '200') {
  328. this.$refs.uToast.show({
  329. title: this.$i18n.locale == 'zh' ? '密码修改成功,请使用新密码重新登录!' :
  330. 'Password modified successfully, please use the new password to login again!',
  331. type: 'success',
  332. });
  333. uni.removeStorageSync('user');
  334. uni.removeStorageSync('Auth-Token');
  335. setTimeout(() => {
  336. uni.navigateTo({
  337. url: `/pages/public/login`
  338. });
  339. }, 2000);
  340. } else {
  341. this.$refs.uToast.show({
  342. title: result.msg,
  343. type: 'error',
  344. });
  345. try {
  346. uni.removeStorageSync('user');
  347. uni.removeStorageSync('Auth-Token');
  348. } catch (e) {
  349. }
  350. }
  351. },
  352. async restPassword() {
  353. if (!this.resetPasswordParams.code) {
  354. this.$refs.uToast.show({
  355. title: this.$i18n.locale == 'zh' ? '验证码不能为空' : 'verificationCode cannot be empty',
  356. type: 'warning',
  357. });
  358. return;
  359. }
  360. this.codeLogin();
  361. },
  362. toGR() {
  363. uni.navigateTo({
  364. url: '/pages/public/GlobalRoaming?regLogStyle=' + this.regLogStyle
  365. })
  366. },
  367. i18n(data) {
  368. return this.$t('common.' + data);
  369. },
  370. navBack() {
  371. this.$mRouter.back();
  372. },
  373. navTo(route) {
  374. this.$mRouter.push({
  375. route
  376. });
  377. },
  378. toHome() {
  379. this.$mRouter.reLaunch({
  380. route: '/pages/index/index'
  381. });
  382. },
  383. }
  384. };
  385. </script>
  386. <style lang="scss">
  387. page {
  388. background: $color-white;
  389. }
  390. /* .container {
  391. padding-top: 60px;
  392. position: relative;
  393. width: 100vw;
  394. overflow: hidden;
  395. .wrapper {
  396. position: relative;
  397. width: 100vw;
  398. z-index: 90;
  399. background: #fff;
  400. padding-bottom: 40upx;
  401. .welcome {
  402. position: relative;
  403. left: 50upx;
  404. top: -90upx;
  405. font-size: 46upx;
  406. color: #555;
  407. text-shadow: 1px 0px 1px rgba(0, 0, 0, 0.3);
  408. }
  409. .input-content {
  410. padding: 0 60upx;
  411. }
  412. .input-item {
  413. display: flex;
  414. flex-direction: column;
  415. align-items: flex-start;
  416. justify-content: center;
  417. padding: 0 30upx;
  418. background: $page-color-light;
  419. height: 120upx;
  420. border-radius: 4px;
  421. margin-bottom: 50upx;
  422. &:last-child {
  423. margin-bottom: 0;
  424. }
  425. .tit {
  426. height: 50upx;
  427. line-height: 56upx;
  428. font-size: $font-sm + 2upx;
  429. color: $font-color-base;
  430. }
  431. input {
  432. height: 60upx;
  433. font-size: $font-base + 2upx;
  434. color: $font-color-dark;
  435. width: 100%;
  436. }
  437. }
  438. .input-item-sms-code {
  439. position: relative;
  440. .sms-code-btn {
  441. position: absolute;
  442. right: 20upx;
  443. color: #111;
  444. bottom: 20upx;
  445. font-size: 28upx;
  446. }
  447. .sms-code-resend {
  448. color: #999;
  449. }
  450. }
  451. .forget-section {
  452. font-size: $font-sm + 2upx;
  453. color: $font-color-spec;
  454. text-align: center;
  455. margin-top: 40upx;
  456. }
  457. }
  458. .back-btn {
  459. position: absolute;
  460. left: 40upx;
  461. z-index: 9999;
  462. padding-top: var(--status-bar-height);
  463. top: 40upx;
  464. font-size: 40upx;
  465. color: $font-color-dark;
  466. }
  467. .left-top-sign {
  468. font-size: 120upx;
  469. color: $page-color-base;
  470. position: relative;
  471. left: -16upx;
  472. }
  473. .right-top-sign {
  474. position: absolute;
  475. top: 80upx;
  476. right: -30upx;
  477. z-index: 95;
  478. &:before,
  479. &:after {
  480. display: block;
  481. content: '';
  482. width: 400upx;
  483. height: 80upx;
  484. background: #b4f3e2;
  485. }
  486. &:before {
  487. transform: rotate(50deg);
  488. border-radius: 0 50px 0 0;
  489. }
  490. &:after {
  491. position: absolute;
  492. right: -198upx;
  493. top: 0;
  494. transform: rotate(-50deg);
  495. border-radius: 50px 0 0 0;
  496. }
  497. }
  498. .register-section {
  499. margin: 50upx 0 50upx 0;
  500. width: 100%;
  501. font-size: $font-sm + 2upx;
  502. color: $font-color-base;
  503. text-align: center;
  504. text {
  505. color: $font-color-spec;
  506. margin-left: 10upx;
  507. margin-right: 10upx;
  508. }
  509. }
  510. }
  511. */
  512. .password-type-2 {
  513. width: 100%;
  514. position: relative;
  515. .back-btn {
  516. position: absolute;
  517. left: 40upx;
  518. z-index: 9999;
  519. padding-top: var(--status-bar-height);
  520. top: 40upx;
  521. font-size: 48upx;
  522. color: $color-white;
  523. }
  524. .login-top {
  525. height: 460upx;
  526. position: relative;
  527. .desc {
  528. position: absolute;
  529. top: 200upx;
  530. left: 40upx;
  531. font-size: 48upx;
  532. z-index: 2;
  533. .title {
  534. font-size: 48upx;
  535. }
  536. }
  537. .login-pic {
  538. position: absolute;
  539. width: 750upx;
  540. height: 270upx;
  541. right: 30upx;
  542. top: 100upx;
  543. z-index: 1;
  544. }
  545. }
  546. .login-type-content {
  547. position: relative;
  548. top: -72upx;
  549. .login-bg {
  550. width: 94vw;
  551. height: 114vw;
  552. margin: 0 3vw;
  553. }
  554. .main {
  555. width: 94vw;
  556. position: absolute;
  557. top: 0;
  558. left: 3vw;
  559. .nav-bar {
  560. display: flex;
  561. height: 100upx;
  562. justify-content: center;
  563. align-items: center;
  564. position: relative;
  565. z-index: 10;
  566. .nav-bar-item {
  567. flex: 1;
  568. display: flex;
  569. height: 100%;
  570. line-height: 96upx;
  571. font-size: $font-lg;
  572. display: flex;
  573. margin: 0 120upx;
  574. justify-content: center;
  575. }
  576. .nav-bar-item-active {
  577. border-bottom: 5upx solid;
  578. }
  579. }
  580. .login-type-form {
  581. width: 80%;
  582. margin: 50upx auto;
  583. .input-item {
  584. position: relative;
  585. height: 90upx;
  586. line-height: 90upx;
  587. margin-bottom: $spacing-lg;
  588. .iconfont {
  589. font-size: 50upx;
  590. position: absolute;
  591. left: 0;
  592. }
  593. .login-type-input {
  594. height: 90upx;
  595. padding-left: 80upx;
  596. border-bottom: 1upx solid rgba(0, 0, 0, .1);
  597. }
  598. .sms-code-btn,
  599. sms-code-resend {
  600. width: 240upx;
  601. font-size: $font-base - 2upx;
  602. }
  603. }
  604. }
  605. .login-type-tips {
  606. padding: 0 50upx;
  607. display: flex;
  608. justify-content: space-between;
  609. }
  610. .confirm-btn {
  611. height: 80upx;
  612. line-height: 80upx;
  613. }
  614. }
  615. }
  616. .login-type-bottom {
  617. width: 100%;
  618. padding-bottom: 30upx;
  619. text-align: center;
  620. font-size: $font-lg;
  621. }
  622. }
  623. </style>