password.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <template>
  2. <div class="page">
  3. <div class="page-content">
  4. <el-form :model="formData" :rules="rules" label-position="top" ref="form">
  5. <el-form-item label="手机号" prop="mobile">
  6. <el-input
  7. placeholder="请输入手机号"
  8. maxlength="11"
  9. v-model="formData.mobile"
  10. ></el-input>
  11. </el-form-item>
  12. <el-form-item label="验证码" prop="verifyCode">
  13. <div class="verify-code">
  14. <el-input
  15. placeholder="请输入验证码"
  16. maxlength="6"
  17. v-model="formData.verifyCode"
  18. ></el-input>
  19. <div class="send" @click="onSend">{{ sendCodeBtnText }}</div>
  20. </div>
  21. </el-form-item>
  22. <el-form-item label="新密码" prop="password">
  23. <el-input
  24. type="password"
  25. placeholder="请输入新密码"
  26. v-model="formData.password"
  27. ></el-input>
  28. </el-form-item>
  29. <el-form-item label="确认密码" prop="confirmPwd">
  30. <el-input
  31. type="password"
  32. placeholder="请输入确认密码"
  33. v-model="formData.confirmPwd"
  34. ></el-input>
  35. </el-form-item>
  36. </el-form>
  37. <div class="submit-button">
  38. <div class="back btn" @click="onBack">返回</div>
  39. <div class="submit btn" @click="onSubmit">提交</div>
  40. </div>
  41. </div>
  42. </div>
  43. </template>
  44. <script>
  45. import { isMobile, validPassword } from '~/utils/validator'
  46. import { mapGetters } from 'vuex'
  47. export default {
  48. layout: 'app-hyt',
  49. data() {
  50. const passwordValidate = (rule, value, callback) => {
  51. console.log(value)
  52. if (validPassword(value)) {
  53. callback()
  54. } else {
  55. callback(new Error('密码只能包含英文大小写和数字'))
  56. }
  57. }
  58. const confirmPwdValide = (rule, value, callback) => {
  59. if (this.formData.password !== value) {
  60. callback(new Error('两次输入的密码不一致'))
  61. } else {
  62. callback()
  63. }
  64. }
  65. return {
  66. sendStatus: 0,
  67. timer: null,
  68. formData: {
  69. mobile: '',
  70. verifyCode: '',
  71. password: '',
  72. confirmPwd: '',
  73. },
  74. rules: {
  75. mobile: [
  76. { required: true, message: '请输入手机号', trigger: ['blur'] },
  77. ],
  78. verifyCode: [
  79. { required: true, message: '请输入验证码', trigger: ['blur'] },
  80. ],
  81. password: [
  82. { required: true, message: '请输入新密码', trigger: ['blur'] },
  83. { min: 6, message: '密码长度不能小于6位', trigger: ['blur'] },
  84. { validator: passwordValidate, trigger: ['blur'] },
  85. ],
  86. confirmPwd: [
  87. { required: true, message: '请输入确认密码', trigger: ['blur'] },
  88. { validator: confirmPwdValide, trigger: ['blur'] },
  89. ],
  90. },
  91. }
  92. },
  93. computed: {
  94. ...mapGetters(['authUserId', 'routePrefix']),
  95. sendCodeBtnText() {
  96. return this.sendStatus === 0
  97. ? '发送验证码'
  98. : `再次发送${this.sendStatus}s`
  99. },
  100. },
  101. methods: {
  102. // 返回
  103. onBack() {
  104. this.$router.back()
  105. },
  106. // 提交
  107. async onSubmit() {
  108. try {
  109. await this.$refs.form.validate()
  110. this.onResetPassword()
  111. } catch (error) {
  112. console.log(error)
  113. }
  114. },
  115. // 忘记密码
  116. async onResetPassword() {
  117. try {
  118. await this.$http.api.clubUserReset({
  119. mobile: this.formData.mobile,
  120. verifyCode: this.formData.verifyCode,
  121. password: this.formData.password,
  122. authUserId: this.authUserId,
  123. })
  124. this.$toast('密码修改成功,请重新登录')
  125. setTimeout(() => {
  126. this.logout()
  127. }, 2000)
  128. } catch (error) {
  129. console.log(error)
  130. }
  131. },
  132. // 退出登录
  133. logout() {
  134. this.$store.dispatch('user/logout')
  135. this.$removeStorage(this.routePrefix, 'userInfo')
  136. this.backHome()
  137. },
  138. // 回到首页
  139. backHome() {
  140. window.location.href = window.location.origin + this.routePrefix
  141. },
  142. // 发送短信验证码
  143. async onSend() {
  144. if (this.sendStatus > 0) return
  145. // 验证手机号是否合法
  146. if (!isMobile(this.formData.mobile)) {
  147. this.$toast('请输入正确的手机号')
  148. return
  149. }
  150. try {
  151. // 发送验证码
  152. await this.$http.api.clubUserCodeSend({
  153. mobile: this.formData.mobile,
  154. authUserId: this.authUserId,
  155. type: this.formType === 'register' ? 1 : 2,
  156. })
  157. this.$toast('验证码已发送')
  158. // 开启倒计时
  159. this.countdown()
  160. } catch (error) {
  161. console.log(error)
  162. }
  163. },
  164. countdown() {
  165. this.sendStatus = 30
  166. this.timer = setInterval(() => {
  167. if (this.sendStatus === 0) {
  168. clearInterval(this.timer)
  169. return
  170. }
  171. this.sendStatus--
  172. }, 1000)
  173. },
  174. },
  175. }
  176. </script>
  177. <style lang="scss" scoped>
  178. @media screen and (min-width: 768px) {
  179. .page {
  180. position: relative;
  181. min-height: calc(100vh - 80px - 80px);
  182. background-color: #fff;
  183. overflow: hidden;
  184. }
  185. .page-content {
  186. width: 518px;
  187. margin: 0 auto;
  188. margin-top: 100px;
  189. .verify-code {
  190. width: 100%;
  191. display: flex;
  192. align-items: center;
  193. .send {
  194. flex-shrink: 0;
  195. margin-left: 16px;
  196. height: 40px;
  197. text-align: center;
  198. line-height: 40px;
  199. width: 118px;
  200. background: #4093B5;
  201. border-radius: 4px;
  202. font-size: 16px;
  203. color: #fff;
  204. cursor: pointer;
  205. }
  206. }
  207. .submit-button {
  208. display: flex;
  209. align-items: center;
  210. justify-content: center;
  211. margin-top: 32px;
  212. .btn {
  213. text-align: center;
  214. width: 118px;
  215. height: 40px;
  216. border-radius: 4px;
  217. font-size: 16px;
  218. cursor: pointer;
  219. box-sizing: border-box;
  220. margin: 0 16px;
  221. &.back {
  222. border: 1px solid #4093B5;
  223. color: #4093B5;
  224. line-height: 38px;
  225. }
  226. &.submit {
  227. background: #4093B5;
  228. color: #fff;
  229. line-height: 40px;
  230. }
  231. }
  232. }
  233. }
  234. }
  235. @media screen and (max-width: 768px) {
  236. .page-content {
  237. padding: 10vw 4vw 0;
  238. .verify-code {
  239. width: 100%;
  240. display: flex;
  241. align-items: center;
  242. .send {
  243. flex-shrink: 0;
  244. margin-left: 2.4vw;
  245. height: 40px;
  246. text-align: center;
  247. line-height: 40px;
  248. width: 24.2vw;
  249. background: #4093B5;
  250. border-radius: 0.4vw;
  251. font-size: 3.4vw;
  252. color: #fff;
  253. cursor: pointer;
  254. }
  255. }
  256. .submit-button {
  257. margin-top: 20vw;
  258. .btn {
  259. text-align: center;
  260. height: 40px;
  261. border-radius: 0.4vw;
  262. font-size: 3.4vw;
  263. cursor: pointer;
  264. box-sizing: border-box;
  265. margin-bottom: 3.2vw;
  266. &.back {
  267. border: 1px solid #4093B5;
  268. color: #4093B5;
  269. line-height: 38px;
  270. }
  271. &.submit {
  272. background: #4093B5;
  273. color: #fff;
  274. line-height: 40px;
  275. }
  276. }
  277. }
  278. }
  279. }
  280. </style>