login.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <view class="root">
  3. <view class="center">
  4. <image class="logo" src="/static/images/map-logo.png" mode="aspectFit" />
  5. <view class="spacer" />
  6. <button
  7. class="btn"
  8. open-type="getPhoneNumber"
  9. hover-class="btn-press"
  10. :loading="submitting"
  11. :disabled="submitting"
  12. @getphonenumber="handleLogin"
  13. >
  14. 一键登录
  15. </button>
  16. <text v-if="errorMsg" class="err">{{ errorMsg }}</text>
  17. </view>
  18. </view>
  19. </template>
  20. <script setup lang="ts">
  21. import { login } from "@/api/auth";
  22. import { isAuthenticated, isTabBarPage } from "@/utils/auth";
  23. import { onLoad } from "@dcloudio/uni-app";
  24. import { ref } from "vue";
  25. const redirect = ref("");
  26. const submitting = ref(false);
  27. const errorMsg = ref("");
  28. onLoad((query: Record<string, string | undefined>) => {
  29. if (isAuthenticated()) {
  30. performRedirect(query?.redirect || "");
  31. return;
  32. }
  33. if (query?.redirect) {
  34. redirect.value = decodeURIComponent(query.redirect);
  35. }
  36. });
  37. const handleLogin = (e: WechatMiniprogram.ButtonGetPhoneNumber) => {
  38. if (submitting.value) return;
  39. errorMsg.value = "";
  40. submitting.value = true;
  41. login(e)
  42. .then(() => {
  43. uni.showToast({ title: "登录成功", icon: "success", duration: 800 });
  44. setTimeout(() => performRedirect(redirect.value), 800);
  45. })
  46. .catch(() => {
  47. submitting.value = false;
  48. errorMsg.value = "登录失败,请重试";
  49. });
  50. };
  51. const performRedirect = (url: string) => {
  52. if (url && isTabBarPage(url)) return uni.switchTab({ url });
  53. if (url) {
  54. uni.navigateBack({
  55. fail() { uni.switchTab({ url: "/pages/map/map" }); },
  56. });
  57. return;
  58. }
  59. const pages = getCurrentPages();
  60. if (pages.length > 1) {
  61. uni.navigateBack({
  62. fail() { uni.switchTab({ url: "/pages/map/map" }); },
  63. });
  64. } else {
  65. uni.switchTab({ url: "/pages/map/map" });
  66. }
  67. };
  68. </script>
  69. <style lang="scss" scoped>
  70. .root {
  71. min-height: 100vh;
  72. display: flex;
  73. align-items: center;
  74. justify-content: center;
  75. background: var(--color-sec);
  76. padding: 0 56rpx 160rpx;
  77. }
  78. .center {
  79. width: 100%;
  80. display: flex;
  81. flex-direction: column;
  82. align-items: center;
  83. }
  84. .logo {
  85. width: 200rpx;
  86. height: 200rpx;
  87. }
  88. .spacer {
  89. height: 80rpx;
  90. }
  91. .btn {
  92. width: 100%;
  93. height: 100rpx;
  94. display: flex;
  95. align-items: center;
  96. justify-content: center;
  97. background: var(--color-primary);
  98. color: #fff;
  99. font-size: 32rpx;
  100. font-weight: 600;
  101. border-radius: 50rpx;
  102. border: none;
  103. transition: background-color 0.15s cubic-bezier(0.22, 1, 0.36, 1);
  104. }
  105. .btn::after {
  106. border: none;
  107. }
  108. .btn-press {
  109. background: var(--color-primary-deep);
  110. opacity: 0.95;
  111. }
  112. .err {
  113. margin-top: 28rpx;
  114. font-size: 24rpx;
  115. color: var(--color-warning);
  116. }
  117. </style>