You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
4.4 KiB

  1. <template>
  2. <view class="main">
  3. <view :style="{height:iSMT+'px'}"></view>
  4. <view class="tab">
  5. <view class="tab-item" :class="{active: activeTab === 'email'}" @click="activeTab = 'email'">邮箱</view>
  6. <view class="tab-item" :class="{active: activeTab === 'phone'}" @click="activeTab = 'phone'">手机号</view>
  7. </view>
  8. <view class="switch-tab">
  9. <view class="input-list" v-if="activeTab === 'email'">
  10. <image src="/static/my/changeEmail.png" mode="aspectFit"></image>
  11. <input type="text" placeholder="请输入邮箱" class="input" v-model="userEmail"/>
  12. <button class="code-btn" :class="{disabled: gettingCode}" @click="getCode" :disabled="gettingCode">
  13. {{ gettingCode ? `重新发送 ${time}s` : '获取验证码' }}
  14. </button>
  15. </view>
  16. <view class="input-list" v-else>
  17. <image src="/static/my/changeBindPhone.png" mode="aspectFit"></image>
  18. <input type="number" placeholder="请输入手机号" class="input" v-model="userPhone"/>
  19. <button class="code-btn" :class="{disabled: gettingCode}" @click="getCode" :disabled="gettingCode">
  20. {{ gettingCode ? `重新发送 ${time}s` : '获取验证码' }}
  21. </button>
  22. </view>
  23. <view class="input-list">
  24. <image src="/static/my/verification.png" mode="aspectFit"></image>
  25. <input type="text" placeholder="请输入验证码" class="input" v-model="verifyCode"/>
  26. </view>
  27. </view>
  28. <view class="btn-area">
  29. <button class="next-btn" @click="goToPwdNext">下一步</button>
  30. </view>
  31. </view>
  32. </template>
  33. <script setup>
  34. import {
  35. ref,
  36. onMounted
  37. } from 'vue'
  38. import {sendEmail, validateCode} from "@/api/setting/password";
  39. const iSMT = ref(0)
  40. const activeTab = ref('email')
  41. const gettingCode = ref(false)
  42. const time = ref(60)
  43. const userEmail = ref('')
  44. const userPhone = ref('')
  45. const verifyCode = ref('')
  46. const getCode = () => {
  47. if (gettingCode.value) return
  48. gettingCode.value = true
  49. time.value = 2
  50. const timer = setInterval(() => {
  51. time.value--
  52. if (time.value <= 0) {
  53. clearInterval(timer)
  54. gettingCode.value = false
  55. time.value = 2
  56. }
  57. }, 1000)
  58. sendEmail({email: userEmail.value})
  59. }
  60. const goToPwdNext = () => {
  61. if (!userEmail.value) {
  62. uni.showToast({title: '请输入邮箱', icon: 'none'})
  63. return
  64. }
  65. if (!verifyCode.value) {
  66. uni.showToast({title: '请输入验证码', icon: 'none'})
  67. return
  68. }
  69. try {
  70. const res = validateCode({
  71. loginType:'EMAIL',
  72. account: userEmail.value,
  73. verifyCode: verifyCode.value
  74. })
  75. console.log('validateCode 返回:', res)
  76. // 如果返回成功
  77. if (res.code === 200) {
  78. uni.showToast({title: '验证成功', icon: 'success'})
  79. uni.navigateTo({
  80. url: '../setting/nextPwd'
  81. })
  82. } else {
  83. uni.showToast({title: res.msg || '验证失败', icon: 'none'})
  84. }
  85. } catch (err) {
  86. console.error(err)
  87. uni.showToast({title: '请求出错', icon: 'none'})
  88. }
  89. }
  90. onMounted(() => {
  91. // 获取状态栏高度
  92. iSMT.value = uni.getSystemInfoSync().statusBarHeight;
  93. })
  94. </script>
  95. <style>
  96. .tab {
  97. display: flex;
  98. height: 8vh;
  99. background-color: #fff;
  100. border-bottom: 1rpx solid #eee;
  101. }
  102. .tab-item {
  103. flex: 1;
  104. display: flex;
  105. justify-content: center;
  106. align-items: center;
  107. font-size: 32rpx;
  108. position: relative;
  109. }
  110. .tab-item.active {
  111. color: #000;
  112. font-weight: bold;
  113. }
  114. .tab-item.active::after {
  115. content: '';
  116. position: absolute;
  117. bottom: 0;
  118. left: 50%;
  119. transform: translateX(-50%);
  120. width: 40rpx;
  121. height: 6rpx;
  122. background-color: #000; /* ????? */
  123. }
  124. .switch-tab {
  125. background-color: #fff;
  126. padding: 0 60rpx;
  127. }
  128. .input-list {
  129. display: flex;
  130. align-items: center;
  131. justify-content: center;
  132. height: 7vh;
  133. border-bottom: 1rpx solid #eee;
  134. }
  135. .input-list image {
  136. width: 40rpx;
  137. height: 40rpx;
  138. margin-right: 20rpx;
  139. }
  140. .input {
  141. flex: 1;
  142. height: 14vh;
  143. font-size: 28rpx;
  144. }
  145. .code-btn {
  146. width: 200rpx;
  147. height: 60rpx;
  148. font-size: 24rpx;
  149. border-radius: 10rpx;
  150. background-color: #eee;
  151. color: #666;
  152. display: flex;
  153. align-items: center;
  154. justify-content: center;
  155. }
  156. .code-btn.disabled {
  157. background-color: #ccc;
  158. color: #999;
  159. }
  160. .btn-area {
  161. height: 8vh;
  162. background-color: white;
  163. padding-top: 120rpx;
  164. }
  165. .next-btn {
  166. width: 610rpx;
  167. height: 85rpx;
  168. background-color: #000;
  169. color: #fff;
  170. font-size: 30rpx;
  171. border-radius: 40rpx;
  172. display: flex;
  173. align-items: center;
  174. justify-content: center;
  175. }
  176. </style>