setPhone.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <!-- 更换手机号 -->
  3. <view class="content">
  4. <view class="form-container">
  5. <!-- 标题 -->
  6. <view class="title">请输入你要更换的新手机号,并进行验证</view>
  7. <!-- 手机号输入框 -->
  8. <view class="input-wrapper">
  9. <view class="input-left">
  10. <text class="country-code">+86</text>
  11. <text class="icon-envelope">✉</text>
  12. </view>
  13. <input v-model="phone" type="number" class="input-field" placeholder="手机号"
  14. placeholder-style="color: #999;" maxlength="11" />
  15. </view>
  16. <!-- 验证码输入框 -->
  17. <view class="input-wrapper">
  18. <input v-model="code" type="number" class="input-field code-input" placeholder="输入验证码"
  19. placeholder-style="color: #999;" maxlength="6" />
  20. <view class="code-btn" :class="{ disabled: countdown > 0 || !canGetCode }" @click="handleGetCode">
  21. {{ countdown > 0 ? `${countdown}秒` : '获取验证码' }}
  22. </view>
  23. </view>
  24. </view>
  25. <!-- 修改按钮 - 固定在底部 -->
  26. <view class="submit-btn-wrapper">
  27. <view class="submit-btn" @click="handleSubmit" hover-class="hover-active">
  28. 修改
  29. </view>
  30. </view>
  31. </view>
  32. </template>
  33. <script setup>
  34. import { ref, computed, onUnmounted } from 'vue';
  35. import { useUserStore } from '@/store/user.js';
  36. import { isPhone } from '@/utils/is.js';
  37. import { go } from '@/utils/utils.js';
  38. const userStore = useUserStore();
  39. // 表单数据
  40. const phone = ref('');
  41. const code = ref('');
  42. const countdown = ref(0);
  43. let countdownTimer = null;
  44. // 是否可以获取验证码
  45. const canGetCode = computed(() => {
  46. return isPhone(phone.value);
  47. });
  48. // 是否可以提交
  49. const canSubmit = computed(() => {
  50. return isPhone(phone.value) && code.value.length >= 4;
  51. });
  52. // 获取验证码
  53. const handleGetCode = async () => {
  54. if (countdown.value > 0 || !canGetCode.value) {
  55. return;
  56. }
  57. try {
  58. uni.showToast({
  59. title: '验证码已发送',
  60. icon: 'success'
  61. });
  62. // 开始倒计时
  63. countdown.value = 60;
  64. countdownTimer = setInterval(() => {
  65. countdown.value--;
  66. if (countdown.value <= 0) {
  67. clearInterval(countdownTimer);
  68. countdownTimer = null;
  69. }
  70. }, 1000);
  71. } catch (error) {
  72. console.error('发送验证码失败:', error);
  73. uni.showToast({
  74. title: error?.msg || '发送验证码失败',
  75. icon: 'none'
  76. });
  77. }
  78. };
  79. // 提交修改
  80. const handleSubmit = async () => {
  81. if (!canSubmit.value) {
  82. return;
  83. }
  84. // TODO: 调用修改手机号接口
  85. // 这里需要根据实际API接口来实现
  86. try {
  87. // const res = await UpdatePhone({
  88. // phone: phone.value,
  89. // code: code.value
  90. // });
  91. uni.showToast({
  92. title: '修改成功',
  93. icon: 'success'
  94. });
  95. // 延迟返回上一页
  96. setTimeout(() => {
  97. go(-1);
  98. }, 1500);
  99. } catch (error) {
  100. console.error('修改手机号失败:', error);
  101. uni.showToast({
  102. title: error?.msg || '修改失败,请重试',
  103. icon: 'none'
  104. });
  105. }
  106. };
  107. // 清理定时器
  108. onUnmounted(() => {
  109. if (countdownTimer) {
  110. clearInterval(countdownTimer);
  111. }
  112. });
  113. </script>
  114. <style scoped lang="scss">
  115. .content {
  116. width: 100%;
  117. min-height: 100vh;
  118. background-color: #F5F5F5;
  119. box-sizing: border-box;
  120. padding: 40rpx 30rpx 160rpx;
  121. /* 底部增加空间,避免被固定按钮遮挡 */
  122. position: relative;
  123. }
  124. .form-container {
  125. width: 100%;
  126. }
  127. .title {
  128. font-size: 27rpx;
  129. color: #151515;
  130. font-weight: 400;
  131. margin-bottom: 60rpx;
  132. line-height: 1.5;
  133. }
  134. .input-wrapper {
  135. width: 100%;
  136. height: 88rpx;
  137. background-color: #fff;
  138. border-radius: 16rpx;
  139. display: flex;
  140. align-items: center;
  141. padding: 0 30rpx;
  142. box-sizing: border-box;
  143. margin-bottom: 30rpx;
  144. .input-left {
  145. display: flex;
  146. align-items: center;
  147. gap: 12rpx;
  148. margin-right: 20rpx;
  149. .country-code {
  150. font-size: 28rpx;
  151. color: #333;
  152. font-weight: 400;
  153. }
  154. .icon-envelope {
  155. font-size: 24rpx;
  156. color: #999;
  157. }
  158. }
  159. .input-field {
  160. flex: 1;
  161. font-size: 28rpx;
  162. color: #333;
  163. height: 100%;
  164. }
  165. .code-input {
  166. flex: 1;
  167. }
  168. .code-btn {
  169. font-size: 28rpx;
  170. color: #F47D1F;
  171. padding: 8rpx 20rpx;
  172. margin-left: 20rpx;
  173. cursor: pointer;
  174. white-space: nowrap;
  175. &.disabled {
  176. color: #999;
  177. cursor: not-allowed;
  178. font-size: 27rpx;
  179. color: #151515;
  180. }
  181. }
  182. }
  183. .submit-btn-wrapper {
  184. position: fixed;
  185. bottom: 0;
  186. left: 0;
  187. right: 0;
  188. background-color: #F5F5F5;
  189. padding: 20rpx 30rpx;
  190. padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
  191. /* iOS 11.2+ */
  192. padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
  193. /* iOS 11.2+ */
  194. box-sizing: border-box;
  195. z-index: 100;
  196. }
  197. .submit-btn {
  198. width: 100%;
  199. height: 88rpx;
  200. background: linear-gradient(35deg, #FCB73F 0%, #FC733D 100%);
  201. border-radius: 23rpx;
  202. display: flex;
  203. align-items: center;
  204. justify-content: center;
  205. font-weight: bold;
  206. font-size: 31rpx;
  207. color: #FFFFFF;
  208. box-shadow: 0rpx 4rpx 12rpx 0rpx rgba(255, 107, 53, 0.3);
  209. }
  210. </style>