UpdatePassword.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <template>
  2. <div>
  3. <n-modal
  4. v-model:show="visiablePassword"
  5. style="width: 500px"
  6. preset="dialog"
  7. :showIcon="false"
  8. title="修改密码"
  9. >
  10. <!-- model={forms} ref={formsRef} label-placement="left" label-width="100" -->
  11. <n-form
  12. :model="forms"
  13. ref="formsRef"
  14. label-placement="left"
  15. label-width="auto"
  16. style="padding-top: 12px"
  17. >
  18. <n-form-item label="手机号" path="phone">
  19. <n-input v-model:value="forms.phone" placeholder="请输入手机号" disabled />
  20. </n-form-item>
  21. <n-form-item
  22. label="新密码"
  23. path="newPasswordFirst"
  24. :rule="[
  25. {
  26. required: true,
  27. message: '请选择输入新密码'
  28. },
  29. {
  30. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  31. message: '密码为6-20位数字和字母组合',
  32. trigger: 'blur'
  33. }
  34. ]"
  35. >
  36. <n-input
  37. v-model:value="forms.newPasswordFirst"
  38. type="password"
  39. show-password-on="click"
  40. placeholder="请选择输入新密码"
  41. autocomplete="off"
  42. />
  43. </n-form-item>
  44. <n-form-item
  45. label="再次输入"
  46. path="newPasswordSecond"
  47. :rule="[
  48. {
  49. validator: validatePass2,
  50. trigger: 'blur',
  51. required: true
  52. }
  53. ]"
  54. >
  55. <n-input
  56. v-model:value="forms.newPasswordSecond"
  57. type="password"
  58. show-password-on="click"
  59. placeholder="请再次输入密码"
  60. autocomplete="off"
  61. />
  62. </n-form-item>
  63. <n-form-item
  64. label="验证码"
  65. path="authCode"
  66. :rule="[
  67. {
  68. required: true,
  69. message: '请选择输入验证码'
  70. }
  71. ]"
  72. >
  73. <n-input-group>
  74. <n-input v-model:value="forms.authCode" placeholder="请选择输入验证码" />
  75. <n-button type="primary" v-if="!active" @click="onSendCode" :loading="codeLoading">
  76. 获取验证码
  77. </n-button>
  78. <n-button type="default" v-else disabled>
  79. <n-countdown
  80. :render="renderCountdown"
  81. :duration="50 * 1000"
  82. :active="active"
  83. @finish="() => (active = false)"
  84. />
  85. </n-button>
  86. </n-input-group>
  87. </n-form-item>
  88. <n-space justify="end">
  89. <n-button type="default" @click="visiablePassword = false">取消</n-button>
  90. <n-button type="primary" :loading="btnLoading" @click="onSubmit">保存</n-button>
  91. </n-space>
  92. </n-form>
  93. </n-modal>
  94. <n-modal v-model:show="showSmsClass" style="">
  95. <SmsLogin
  96. :phone="forms.phone"
  97. type="PASSWORD"
  98. @close="() => (showSmsClass = false)"
  99. @sendCode="() => (active = true)"
  100. />
  101. </n-modal>
  102. </div>
  103. </template>
  104. <script lang="ts">
  105. import { defineComponent, reactive, toRefs, ref } from 'vue'
  106. import { CountdownProps, useMessage } from 'naive-ui'
  107. import { useUserStore } from '@/store/modules/user'
  108. import { userUpdateInfo, sendSms, updatePassword } from '@/api/system/user'
  109. import { TABS_ROUTES } from '@/store/mutation-types'
  110. import { useRoute, useRouter } from 'vue-router'
  111. import SmsLogin from '../smsLogin'
  112. export default defineComponent({
  113. emits: ['updateInfo'],
  114. components: {
  115. SmsLogin
  116. },
  117. setup(props, { emit }) {
  118. const userStore = useUserStore()
  119. const message = useMessage()
  120. const formsRef = ref()
  121. const router = useRouter()
  122. const route = useRoute()
  123. const state = reactive({
  124. visiablePassword: false,
  125. btnLoading: false,
  126. showSmsClass: false,
  127. codeLoading: false,
  128. forms: {
  129. phone: null,
  130. newPasswordFirst: '',
  131. newPasswordSecond: '',
  132. authCode: ''
  133. } as any,
  134. active: false
  135. })
  136. const renderCountdown: CountdownProps['render'] = ({ hours, minutes, seconds }) => {
  137. return `${String(seconds).padStart(2, '00')}s后重试`
  138. }
  139. const openModal = () => {
  140. state.visiablePassword = true
  141. const userInfo: any = userStore.getUserInfo || {}
  142. state.forms.phone = userInfo.account.phone || null
  143. }
  144. const validatePass2 = (rule: any, value: any, callback: Function) => {
  145. const reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/
  146. if (value === '') {
  147. callback(new Error('请再次输入密码'))
  148. } else if (value !== state.forms.newPasswordFirst) {
  149. callback(new Error('两次输入密码不一致!'))
  150. } else if (!reg.test(value)) {
  151. callback(new Error('密码为6-20位数字和字母组合'))
  152. } else {
  153. callback()
  154. }
  155. }
  156. const onSendCode = async () => {
  157. try {
  158. // state.codeLoading = true
  159. // await sendSms({
  160. // mobile: state.forms.phone,
  161. // type: 'PASSWORD',
  162. // clientId: 'jmedu-backend'
  163. // })
  164. // state.codeLoading = false
  165. // state.active = true
  166. // message.success('发送成功')
  167. state.showSmsClass = true
  168. } catch (e) {
  169. state.codeLoading = false
  170. }
  171. }
  172. const onSubmit = async () => {
  173. if (state.forms.newPasswordFirst !== state.forms.newPasswordSecond) {
  174. message.error('两次密码必须相同')
  175. return
  176. }
  177. formsRef.value.validate(async (error: any) => {
  178. if (error) return false
  179. try {
  180. state.btnLoading = true
  181. await updatePassword({
  182. code: state.forms.authCode,
  183. password: state.forms.newPasswordFirst
  184. })
  185. userStore.logout().then(() => {
  186. message.success('密码修改成功')
  187. // 移除标签页
  188. localStorage.removeItem(TABS_ROUTES)
  189. router
  190. .replace({
  191. name: 'Login',
  192. query: {
  193. redirect: route.fullPath
  194. }
  195. })
  196. .finally(() => location.reload())
  197. })
  198. } catch {}
  199. state.btnLoading = false
  200. })
  201. }
  202. return {
  203. message,
  204. ...toRefs(state),
  205. openModal,
  206. onSubmit,
  207. formsRef,
  208. renderCountdown,
  209. validatePass2,
  210. onSendCode
  211. }
  212. }
  213. })
  214. </script>