goLogin.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <template>
  2. <uni-popup ref="dlRef" :animation="true" :is-mask-click="false" mask-background-color="rgba(255, 255, 255, 0.6);">
  3. <!-- 返回 -->
  4. <view class="icon-title-navBar-box">
  5. <view @click="handleBack" class="nav-bar-icon"></view>
  6. <text class="nav-bar-title">登录</text>
  7. </view>
  8. <!-- 用户名 -->
  9. <view class="phone-input-box">
  10. <view class="phone-prefix">+86</view>
  11. <input class="phone-input" type="text" v-model="loginData.phoneNumber" placeholder="请输入手机号" maxlength="11"
  12. @input="clearTelInput" />
  13. <view class="close-btn" v-if="loginData.clearTelIcon" @click="clearTel"></view>
  14. </view>
  15. <!-- 隐私协议 -->
  16. <view class="agreement-checkbox-box">
  17. <checkbox-group @change="handleUpdateAgree">
  18. <checkbox class="agreement-checkbox-input" color="#FFFFFF" value="agree" :checked="isAgreed" />
  19. </checkbox-group>
  20. <view class="agreement-text-box">
  21. 我已阅读并同意
  22. <view class="agreement-text" @click="agreeBtn('yhxy')">《用户协议》</view>
  23. <view @click="agreeBtn('ystk')" class="agreement-text">《隐私政策》</view>
  24. </view>
  25. </view>
  26. <!-- 登录按钮 -->
  27. </uni-popup>
  28. <!-- 政策协议 -->
  29. <agree-content-dialog ref="agreeContentDialogRef" :agreeType="agreeType"></agree-content-dialog>
  30. <!-- 图形验证码 -->
  31. <captcha ref="captcha" :config="config" @captchaSuccess="captchaSuccess" @captchaError="captchaError"
  32. @captchaFail="captchaFail" @captchaReady="captchaReady" @captchaClose="captchaClose"></captcha>
  33. <!-- 确认协议 -->
  34. <agree-dialog ref="agreeDialogRef" @confirm-btn="confirmBtn"></agree-dialog>
  35. </template>
  36. <script setup>
  37. import {
  38. ref,
  39. reactive
  40. } from "vue"
  41. import {
  42. toast
  43. } from "@/utils/common";
  44. import {
  45. login,
  46. banbenImpinfo,sendCode
  47. } from "@/api/login";
  48. import cacheManager from "@/utils/cacheManager";
  49. const emits = defineEmits(['success'])
  50. const dlRef = ref(null)
  51. const captcha = ref(null);
  52. const agreeType = ref(null);
  53. const agreeDialogRef = ref(null);
  54. const agreeContentDialogRef = ref(null);
  55. const isAgreed = ref(false);
  56. const config = ref({
  57. captchaId: "9d5837b0807b8de44da0de310a0b2813",
  58. });
  59. const loginData = reactive({
  60. phoneNumber: null,
  61. yzmNumber: null,
  62. clearYzmIcon: false,
  63. yzmStatus: 'login-btn-disabled',
  64. timeLeft: 60, // 初始倒计时时间(秒)
  65. intervalId: null, // 定时器ID
  66. isDisabled: false, // 按钮是否禁用
  67. buttonText: '', // 按钮文本
  68. })
  69. const sliderData = reactive({})
  70. function showDl() {
  71. dlRef.value.open('bottom');
  72. }
  73. function closeDl() {
  74. loginData.phoneNumber = null;
  75. loginData.yzmNumber = null;
  76. loginData.clearYzmIcon = false;
  77. loginData.yzmStatus = 'login-btn-disabled';
  78. loginData.timeLeft = 60;
  79. loginData.intervalId = null;
  80. loginData.isDisabled = false;
  81. loginData.buttonText = '';
  82. config.value = null;
  83. isAgreed.value = false;
  84. dlRef.value.close();
  85. }
  86. // 返回
  87. function handleBack() {
  88. closeDl();
  89. }
  90. // 手机号校验规则
  91. const validatePhoneNumber = (value) => {
  92. const phoneRegex = /^1[3-9]\d{9}$/;
  93. if (phoneRegex.test(value)) {
  94. loginData.telStatus = 'login-btn-normal';
  95. } else {
  96. loginData.telStatus = 'login-btn-disabled';
  97. }
  98. }
  99. function clearTelInput(event) {
  100. if (event.detail.value.length > 0) {
  101. loginData.clearTelIcon = true;
  102. validatePhoneNumber(event.detail.value);
  103. } else {
  104. loginData.clearTelIcon = false;
  105. }
  106. }
  107. function clearTel() {
  108. loginData.phoneNumber = '';
  109. loginData.telStatus = 'login-btn-disabled';
  110. loginData.clearTelIcon = false;
  111. }
  112. // 登录
  113. function handleLogin() {
  114. // 用户名
  115. if (!loginData.phoneNumber) {
  116. toast('请输入手机号')
  117. return;
  118. }
  119. // 协议
  120. if (!isAgreed.value) {
  121. agreeDialogRef.value.handleShow()
  122. return;
  123. }
  124. let req = {
  125. tel: loginData.phoneNumber,
  126. code: loginData.yzmNumber,
  127. }
  128. login(req).then(res => {
  129. if (res.code == 0) {
  130. // 更新用户信息
  131. cacheManager.set('auth', res.data)
  132. setTimeout(() => {
  133. banbenImpinfo({}).then(res => {
  134. if (res.code == 0) {
  135. cacheManager.updateObject("auth", {
  136. banbenId: res.data.banbenId,
  137. chanpinId: res.data.chanpinId,
  138. danyuanId: res.data.danyuanId,
  139. dengjiId: res.data.dengjiId,
  140. })
  141. // 更新学习信息 移除学习记录执通过后台更新记录
  142. if (cacheManager.get('xuexi-shuxue')) {
  143. cacheManager.remove("xuexi-shuxue")
  144. }
  145. // 关闭登录 返回支付
  146. toast('登录成功')
  147. // 返回支付
  148. handleBack();
  149. emits('success')
  150. }
  151. }).catch(() => {
  152. toast('数据异常')
  153. return false
  154. })
  155. })
  156. }
  157. })
  158. }
  159. // 更新协议
  160. function handleUpdateAgree() {
  161. isAgreed.value = !isAgreed.value
  162. }
  163. // 协议跳转
  164. function agreeBtn(data) {
  165. agreeType.value = data;
  166. agreeContentDialogRef.value.handleShow();
  167. }
  168. function confirmBtn() {
  169. isAgreed.value = true;
  170. handleLogin();
  171. }
  172. // 图形验证码
  173. function showCaptcha() {
  174. captcha.value.showCaptcha();
  175. }
  176. function startCountdown() {
  177. if (loginData.buttonText === '重新发送') {
  178. showCaptcha();
  179. }
  180. loginData.isDisabled = true;
  181. loginData.buttonText = `重新发送(${loginData.timeLeft}S)`;
  182. // 清除之前的定时器(如果有)
  183. if (loginData.intervalId) {
  184. clearInterval(loginData.intervalId);
  185. loginData.intervalId = null;
  186. }
  187. // 设置新的定时器
  188. loginData.intervalId = setInterval(() => {
  189. loginData.timeLeft--;
  190. if (loginData.timeLeft <= 0) {
  191. clearInterval(loginData.intervalId);
  192. loginData.intervalId = null;
  193. loginData.timeLeft = 60; // 重置倒计时
  194. loginData.isDisabled = false;
  195. loginData.buttonText = '重新发送';
  196. } else {
  197. loginData.buttonText = `重新发送(${loginData.timeLeft}S)`;
  198. }
  199. }, 1000);
  200. }
  201. function getYzmBtn() {
  202. let req = {
  203. phone: loginData.phoneNumber,
  204. captchaOutput: sliderData.captcha_output,
  205. genTime: sliderData.gen_time,
  206. lotNumber: sliderData.lot_number,
  207. passToken: sliderData.pass_token,
  208. }
  209. sendCode(req).then(res => {})
  210. }
  211. function captchaSuccess(result) {
  212. startCountdown();
  213. Object.assign(sliderData, result)
  214. getYzmBtn();
  215. }
  216. function captchaError(e) {
  217. toast(JSON.stringify(e))
  218. }
  219. function captchaFail() {
  220. toast('验证失败!')
  221. }
  222. function captchaReady() {}
  223. function captchaClose() {}
  224. defineExpose({
  225. showDl
  226. })
  227. </script>
  228. <style>
  229. </style>