Login.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <script setup lang="ts">
  2. import { appName, openRegisration } from "@/env";
  3. import { ref, computed, onMounted } from "vue";
  4. import { useMainStore } from "@/stores/main";
  5. import { useDisplay } from "vuetify";
  6. import { storeToRefs } from "pinia";
  7. import { useI18n } from "vue-i18n";
  8. import router from "@/router";
  9. import { saveLocalToken } from "@/utils";
  10. import { googleTokenLogin, decodeCredential } from "vue3-google-login";
  11. import Navbar from "@/components/Navbar.vue";
  12. import type { CallbackTypes } from "vue3-google-login";
  13. const callback: CallbackTypes.CredentialCallback = (response: any) => {
  14. console.log("Handle the response", response);
  15. const userData: any = decodeCredential(response.credential);
  16. console.log("Handle the userData", userData);
  17. mainStore.googleLogin(userData.email);
  18. };
  19. // const data = ref();
  20. // const GOOGLE_CLIENT_ID =
  21. // "136107811725-n71808u8t465f1afhpe2e5j7mn606nd8.apps.googleusercontent.com";
  22. // const handleGoogleAccessTokenLogin = () => {
  23. // googleTokenLogin({
  24. // clientId: GOOGLE_CLIENT_ID,
  25. // }).then((response: any) => {
  26. // console.log("Google response", response);
  27. // console.log("response.access_token", response.access_token);
  28. // data.value = response;
  29. // saveLocalToken(response.access_token);
  30. // mainStore.setToken(response.access_token);
  31. // mainStore.googleLogin(response.access_token);
  32. // });
  33. // };
  34. const mainStore = useMainStore();
  35. const mainStoreRef = storeToRefs(mainStore);
  36. // variable
  37. const email = ref("");
  38. const password = ref("");
  39. const { name } = useDisplay();
  40. const { t } = useI18n();
  41. let showPassword = ref(false);
  42. // getter
  43. const loginError = mainStoreRef.readLoginError;
  44. const width = computed(() => {
  45. // name is reactive and
  46. // must use .value
  47. switch (name.value) {
  48. case "xs":
  49. return 12;
  50. case "sm":
  51. return 12;
  52. // case "md":
  53. // return 6;
  54. }
  55. return 6;
  56. });
  57. // action
  58. function submit() {
  59. mainStore.logIn(email.value, password.value);
  60. }
  61. // lifecycle
  62. onMounted(() => {
  63. console.log("onMounted");
  64. });
  65. </script>
  66. <template>
  67. <Navbar />
  68. <v-container fluid class="pa-0">
  69. <v-row align="center" no-gutters class="overflow-hidden">
  70. <v-col :cols="width">
  71. <section class="overflow-hidden banner-item">
  72. <img src="../assets/img/banner.png" alt="" />
  73. <h2>
  74. {{ t("describe_1") }}
  75. <br />
  76. {{ t("describe_2") }}
  77. </h2>
  78. </section>
  79. </v-col>
  80. <v-col :cols="width" class="px-6 my-8 my-md-0">
  81. <div class="form-title">
  82. <h3>{{ t("login") }}</h3>
  83. <span></span>
  84. </div>
  85. <v-form ref="form" class="login-form" lazy-validation>
  86. <v-text-field
  87. v-model="email"
  88. name="email"
  89. prepend-icon="person"
  90. :rules="[(v) => !!v || '請輸入您的帳號']"
  91. :label="$t('emailAddress')"
  92. required
  93. ></v-text-field>
  94. <v-text-field
  95. v-model="password"
  96. name="password"
  97. id="password"
  98. prepend-icon="key"
  99. :append-icon="showPassword ? 'visibility' : 'visibility_off'"
  100. :rules="[(v) => !!v || '請輸入您的密碼']"
  101. :type="showPassword ? 'text' : 'password'"
  102. :label="$t('password')"
  103. hint="4-12 位數密碼"
  104. @click:append="showPassword = !showPassword"
  105. @keyup.enter="submit"
  106. required
  107. ></v-text-field>
  108. <p class="text-center">
  109. {{ t("haventAccount") }}
  110. <router-link to="/signup">{{ t("register") }}</router-link> /
  111. <router-link to="/recover-password">{{
  112. t("forgotPsd")
  113. }}</router-link>
  114. </p>
  115. <div class="d-flex flex-column">
  116. <v-btn
  117. rounded="pill"
  118. color="primary"
  119. @click.prevent="submit"
  120. class="login-btn"
  121. >
  122. {{ t("loginLink") }}
  123. </v-btn>
  124. <section class="line">
  125. <p>&ensp;快速登入&ensp;</p>
  126. <span></span>
  127. </section>
  128. <div class="w-100 mx-auto mt-5" style="max-width: 235px">
  129. <GoogleLogin
  130. :callback="callback"
  131. prompt
  132. popup-type="TOKEN"
  133. class="w-100"
  134. />
  135. </div>
  136. <!-- <v-btn
  137. class="google-btn"
  138. type="button"
  139. @click="handleGoogleAccessTokenLogin"
  140. rounded="pill"
  141. >
  142. <img src="@/assets/img/google.png" alt="" />
  143. 使用 Google 進行登入
  144. </v-btn> -->
  145. </div>
  146. </v-form>
  147. </v-col>
  148. </v-row>
  149. </v-container>
  150. </template>
  151. <style lang="scss" scoped>
  152. .line {
  153. margin-top: 50px;
  154. display: flex;
  155. justify-content: center;
  156. position: relative;
  157. p {
  158. position: relative;
  159. z-index: 1;
  160. color: #888888;
  161. background-color: #fff;
  162. }
  163. span {
  164. display: block;
  165. border-top: 1px solid #888888;
  166. width: 280px;
  167. position: absolute;
  168. bottom: 12px;
  169. }
  170. }
  171. .google-btn {
  172. margin-top: 20px;
  173. background-color: #fff;
  174. img {
  175. width: 20px;
  176. margin-right: 10px;
  177. }
  178. }
  179. </style>