UserPhoneModal.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <BasicModal v-bind="$attrs" @register="registerModal" width="500px" :title="title" :showCancelBtn="false" :showOkBtn="false">
  3. <a-form v-if="type === 'updatePhone'" class="antd-modal-form" ref="updateFormRef" :model="updateFormState" :rules="updateValidatorRules">
  4. <div v-if="current === 0">
  5. <a-form-item name="phoneText">
  6. <span class="black font-size-13">原手机号</span>
  7. <div class="phone-padding">
  8. <span>{{ updateFormState.phoneText }}</span>
  9. </div>
  10. </a-form-item>
  11. <a-form-item name="smscode">
  12. <span class="black font-size-13">验证码</span>
  13. <CountdownInput
  14. class="phone-padding"
  15. size="large"
  16. v-model:value="updateFormState.smscode"
  17. placeholder="输入6位验证码"
  18. :sendCodeApi="() => updateSendCodeApi('verifyOriginalPhone')"
  19. />
  20. </a-form-item>
  21. <a-form-item>
  22. <a-button size="large" type="primary" block @click="nextStepClick"> 下一步 </a-button>
  23. </a-form-item>
  24. </div>
  25. <div v-else-if="current === 1">
  26. <a-form-item name="newPhone">
  27. <span class="black font-size-13">新手机号</span>
  28. <div class="phone-padding">
  29. <a-input v-model:value="updateFormState.newPhone" placeholder="请输入新手机号" />
  30. </div>
  31. </a-form-item>
  32. <a-form-item name="smscode">
  33. <span class="black font-size-13">验证码</span>
  34. <CountdownInput
  35. class="phone-padding"
  36. size="large"
  37. v-model:value="updateFormState.smscode"
  38. placeholder="输入6位验证码"
  39. :sendCodeApi="() => updateSendCodeApi('updatePhone')"
  40. />
  41. </a-form-item>
  42. <a-form-item>
  43. <a-button size="large" type="primary" block @click="finishedClick"> 完成 </a-button>
  44. </a-form-item>
  45. </div>
  46. </a-form>
  47. <a-form v-else-if="type === 'bindPhone'" class="antd-modal-form" ref="formRef" :model="formState" :rules="validatorRules">
  48. <a-form-item name="phone">
  49. <a-input size="large" v-model:value="formState.phone" placeholder="请输入手机号" />
  50. </a-form-item>
  51. <a-form-item name="smscode">
  52. <CountdownInput size="large" v-model:value="formState.smscode" placeholder="输入6位验证码" :sendCodeApi="sendCodeApi" />
  53. </a-form-item>
  54. <a-form-item>
  55. <a-button size="large" type="primary" block @click="updatePhone"> 确认 </a-button>
  56. </a-form-item>
  57. </a-form>
  58. </BasicModal>
  59. </template>
  60. <script lang="ts" setup name="user-replace-phone-modal">
  61. import BasicModal from '/@/components/Modal/src/BasicModal.vue';
  62. import { CountdownInput } from '/@/components/CountDown';
  63. import { useUserStore } from '/@/store/modules/user';
  64. import { useMessage } from '/@/hooks/web/useMessage';
  65. import { defineEmits, ref, reactive, toRaw } from 'vue';
  66. import { useModalInner } from '/@/components/Modal';
  67. import { getCaptcha } from '/@/api/sys/user';
  68. import { SmsEnum } from '/@/views/sys/login/useLogin';
  69. import { Rule } from '/@/components/Form';
  70. import { rules } from '/@/utils/helper/validator';
  71. import { Form } from 'ant-design-vue';
  72. import { updateMobile, changePhone } from '../UserSetting.api';
  73. import { duplicateCheck } from '/@/views/system/user/user.api';
  74. import { defHttp } from '@/utils/http/axios';
  75. import { ExceptionEnum } from '@/enums/exceptionEnum';
  76. const userStore = useUserStore();
  77. const { createMessage } = useMessage();
  78. const formState = reactive<Record<string, any>>({
  79. phone: '',
  80. smscode: '',
  81. });
  82. //修改手机号
  83. const updateFormState = reactive<Record<string, any>>({
  84. phone: '',
  85. smscode: '',
  86. newPhone: '',
  87. phoneText: '',
  88. newSmsCode: '',
  89. });
  90. const formRef = ref();
  91. const userData = ref<any>({});
  92. const validatorRules: Record<string, Rule[]> = {
  93. phone: [
  94. { ...rules.duplicateCheckRule('sys_user', 'phone', formState, { label: '手机号' })[0] },
  95. { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误' },
  96. ],
  97. smscode: [{ required: true, message: '请输入验证码' }],
  98. };
  99. //修改手机号验证规则
  100. const updateValidatorRules: Record<string, Rule[]> = {
  101. newPhone: [
  102. { ...rules.duplicateCheckRule('sys_user', 'phone', formState, { label: '手机号' })[0] },
  103. { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误' },
  104. ],
  105. smscode: [{ required: true, message: '请输入验证码' }],
  106. newSmsCode: [{ required: true, message: '请输入验证码' }],
  107. };
  108. const useForm = Form.useForm;
  109. const title = ref<string>('');
  110. const emit = defineEmits(['register', 'success']);
  111. //修改手机号还是绑定手机号
  112. const type = ref<string>('updatePhone');
  113. const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
  114. setModalProps({ confirmLoading: false });
  115. if (data.record.phone) {
  116. updateFormState.phone = '';
  117. updateFormState.smscode = '';
  118. current.value = 0;
  119. title.value = '修改手机号';
  120. type.value = 'updatePhone';
  121. Object.assign(updateFormState, data.record);
  122. } else {
  123. title.value = '绑定手机号';
  124. type.value = 'bindPhone';
  125. //赋值
  126. data.record.smscode = '';
  127. Object.assign(formState, data.record);
  128. setTimeout(() => {
  129. formRef.value.resetFields();
  130. formRef.value.clearValidate();
  131. }, 300);
  132. }
  133. userData.value = data.record;
  134. });
  135. /**
  136. * 倒计时执行前的函数
  137. */
  138. function sendCodeApi() {
  139. return getCaptcha({ mobile: formState.phone, smsmode: SmsEnum.REGISTER });
  140. }
  141. /**
  142. * 倒计时执行前的函数
  143. *
  144. * @param type 类型 verifyOriginalPhone 验证员手机号 updatePhone 修改手机号
  145. */
  146. function updateSendCodeApi(type) {
  147. let phone = '';
  148. if (current.value === 0) {
  149. phone = updateFormState.phone;
  150. } else {
  151. phone = updateFormState.newPhone;
  152. }
  153. let params = { phone: phone, type: type };
  154. return new Promise((resolve, reject) => {
  155. defHttp
  156. .post({ url: '/sys/user/sendChangePhoneSms', params }, { isTransformResponse: false })
  157. .then((res) => {
  158. console.log(res);
  159. if (res.success) {
  160. resolve(true);
  161. } else {
  162. //update-begin---author:wangshuai---date:2024-04-18---for:【QQYUN-9005】同一个IP,1分钟超过5次短信,则提示需要验证码---
  163. if (res.code != ExceptionEnum.PHONE_SMS_FAIL_CODE) {
  164. createMessage.error(res.message || '未知问题');
  165. reject();
  166. }
  167. reject(res);
  168. //update-end---author:wangshuai---date:2024-04-18---for:【QQYUN-9005】同一个IP,1分钟超过5次短信,则提示需要验证码---
  169. }
  170. })
  171. .catch((res) => {
  172. createMessage.error(res.message || '未知问题');
  173. reject();
  174. });
  175. });
  176. }
  177. /**
  178. * 更新手机号
  179. */
  180. async function updatePhone() {
  181. await formRef.value.validateFields();
  182. updateMobile(formState).then((res) => {
  183. if (res.success) {
  184. createMessage.success(type.value === 'updatePhone' ? '修改手机号成功' : '绑定手机号成功');
  185. emit('success');
  186. closeModal();
  187. } else {
  188. createMessage.warning(res.message);
  189. }
  190. });
  191. }
  192. //走到第几步
  193. const current = ref<number>(0);
  194. const updateFormRef = ref();
  195. /**
  196. * 下一步点击事件
  197. */
  198. async function nextStepClick() {
  199. let params = { phone: updateFormState.phone, smscode: updateFormState.smscode, type: 'verifyOriginalPhone' };
  200. changeAndVerifyPhone(params, 1);
  201. }
  202. /**
  203. * 完成
  204. */
  205. function finishedClick() {
  206. changeAndVerifyPhone(
  207. { phone: updateFormState.phone, newPhone: updateFormState.newPhone, smscode: updateFormState.smscode, type: 'updatePhone' },
  208. 0
  209. );
  210. }
  211. /**
  212. * 修改并验证手机号
  213. * @param params
  214. * @param index
  215. */
  216. async function changeAndVerifyPhone(params, index) {
  217. await updateFormRef.value.validateFields();
  218. changePhone(params)
  219. .then((res) => {
  220. if (res.success) {
  221. current.value = index;
  222. if (index == 0) {
  223. createMessage.success(res.message);
  224. emit('success');
  225. closeModal();
  226. }
  227. updateFormState.smscode = '';
  228. } else {
  229. createMessage.warn(res.message);
  230. }
  231. })
  232. .catch((res) => {
  233. createMessage.warn(res.message);
  234. });
  235. }
  236. </script>
  237. <style lang="less" scoped>
  238. .antd-modal-form {
  239. padding: 10px 24px 10px 24px;
  240. }
  241. .black {
  242. color: #000000;
  243. }
  244. .font-size-13 {
  245. font-size: 13px;
  246. line-height: 15px;
  247. }
  248. .phone-padding {
  249. padding-top: 10px;
  250. padding-bottom: 10px;
  251. }
  252. :deep(.ant-form-item) {
  253. margin-bottom: 10px;
  254. }
  255. </style>