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.

403 lines
15 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <template>
  2. <div class="tw-bg-white tw-mt-[30px] md:tw-rounded-[24px] md:tw-pt-[60px] md:tw-pb-[150px] md:tw-px-[30px]">
  3. <h1 class="tw-text-[40px] tw-font-bold tw-mb-[20px] md:tw-text-[24px]">{{ $t('Login') }}</h1>
  4. <p class="tw-body-3 tw-text-neutral-400 tw-mb-[16px] md:tw-mb-[12px]">
  5. {{ $t('Welcome back! Please enter your details') }}
  6. </p>
  7. <p class="tw-body-3 tw-mb-[24px] md:tw-mb-[32px]">{{ $t('Not a member?') }} <nuxt-link
  8. :to="localePath('/user/signup')" class="primary--text text-decoration-none">{{ $t('Sign up') }}</nuxt-link>
  9. </p>
  10. <!-- <div class="tw-grid tw-grid-cols-1 tw-gap-[10px] tw-mb-[30px] md:tw-gap-[12px] md:tw-mb-[12px]">
  11. <button @click="googleLogin"
  12. class="tw-block tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img
  13. width="20px" height="20px" src="~/assets/img/g-normal.png" class="mr-5" />{{ $t('Login with Google')
  14. }}</button>
  15. <button @click="facebookLogin"
  16. class="tw-block tw-w-full tw-py-[8px] tw-rounded-[16px] tw-border tw-border-solid tw-text-black tw-border-neutrals-200"><img
  17. width="20px" height="20px" src="~/assets/img/f_logo_RGB-Blue_72.png" class="mr-5" />
  18. {{ $t("Login with Facebook")
  19. }}</button>
  20. </div>
  21. <div class="tw-grid tw-grid-cols-[auto_16px_auto] tw-gap-[28px] tw-mb-[6px]">
  22. <div class="tw-flex tw-justify-center tw-items-center">
  23. <div class="tw-w-full tw-h-[1px] tw-bg-neutral-200"></div>
  24. </div>
  25. <div class="tw-text-neutral-400 tw-body-3 tw-font-normal">{{ $t("or") }}</div>
  26. <div class="tw-flex tw-justify-center tw-items-center">
  27. <div class="tw-w-full tw-h-[1px] tw-bg-neutral-200"></div>
  28. </div>
  29. </div> -->
  30. <div v-if="wrongMessageActive" class="warning--text text-size-14 ps-1 mb-3">
  31. {{ $t('The username or password entered is incorrect') }}
  32. </div>
  33. <v-form ref="loginFormRef" lazy-validation>
  34. <!-- <div v-if="$auth.$storage.getUniversal('userAccount') && $auth.$storage.getUniversal('userPassword')"></div>
  35. <div v-else></div> -->
  36. <v-text-field
  37. v-model="userData.Account" background-color="neutrals darken-1" :label="this.$t('Email')"
  38. :placeholder="this.$t('Email')" height="40px" filled rounded dense single-line persistent-placeholder
  39. :rules="[rules.email,rules.require]" v-on:input="updateValid"
  40. />
  41. <v-text-field
  42. v-model="userData.Password" background-color="neutrals darken-1" :label="this.$t('Password')"
  43. :type=" showPass ? 'text' : 'password'" :placeholder="this.$t('Password')" filled rounded dense single-line
  44. persistent-placeholder :append-icon=" showPass ? 'mdi-eye' : 'mdi-eye-off'" @click:append="showPass = !showPass"
  45. :rules="[rules.checkPassword,rules.require]" v-on:input="updateValid" @keyup.enter="userLogin"
  46. />
  47. </v-form>
  48. <div class="tw-flex tw-justify-between tw-items-center tw-mb-[28px] md:tw-mb-[32px]">
  49. <div class="tw-flex tw-items-center">
  50. <div class="tw-flex tw-items-center">
  51. <div class="tw-flex tw-flex-col">
  52. <label class="tw-body-4 container-checkbox" for="remember">
  53. {{ $t('Remember me')
  54. }}
  55. <input id="remember" type="checkbox" value="remember" v-model="remember" />
  56. <span class="checkmark"></span>
  57. </label>
  58. </div>
  59. </div>
  60. </div>
  61. <div class="tw-flex tw-items-center">
  62. <nuxt-link class="complementary--text text-decoration-none text-size-14" :to="localePath('/user/forgot')">{{
  63. $t('Forgot Password?') }}</nuxt-link>
  64. </div>
  65. </div>
  66. <div class="md:tw-flex md:tw-justify-center md:tw-items-center"> <button @click="userLogin" :disabled="!valid"
  67. :class="['tw-block tw-w-full tw-py-[10px] tw-rounded-[16px] tw-border tw-border-solid tw-body-3 tw-font-normal tw-transition-all tw-duration-200 tw-ease-in-out',valid?'tw-text-white tw-bg-primary-default tw-border-primary-default':'tw-text-base-disable tw-bg-neutral-100 tw-border-neutral-100']">{{
  68. $t("Login")
  69. }}</button></div>
  70. <v-dialog v-model="dialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294"
  71. @click:outside="colseDialog()">
  72. <v-card class="tw-p-[30px]" :height="$vuetify.breakpoint.smAndUp ? 289 : 290">
  73. <v-spacer class="d-flex align-center tw-justify-between tw-mb-[30px]">
  74. <div class="tw-text-[20px] tw-font-bold tw-text-black">
  75. {{ $t("Verify your email") }}
  76. </div>
  77. <v-btn @click="colseDialog()" icon>
  78. <v-icon> mdi-close </v-icon>
  79. </v-btn>
  80. </v-spacer>
  81. <v-spacer class="tw-mb-[40px]">
  82. <div class="tw-text-[16px] tw-text-neutrals-800">
  83. {{ $t("Oops! Seems like you haven't verified your email,please click the button below to resend a verification email.")}}
  84. </div>
  85. </v-spacer>
  86. <button @click="resendVerifyEmail()" :class="['tw-text-white tw-bg-primary-1 hover:tw-bg-primary-light tw-text-[18px] tw-rounded-[16px] tw-px-[77px] tw-py-[13px]']">
  87. {{ $t("Resend verification email") }}
  88. </button>
  89. <!-- <v-btn @click="resendVerifyEmail" class="tw-bg-primary-1 hover:tw-bg-primary-light tw-text-white tw-text-[18px] tw-rounded-[16px] tw-px-[77px] tw-py-[13px]"
  90. :disabled="countdown > 0">
  91. {{ $t("Resend verification email") }}
  92. <span v-if="countdown > 0">
  93. {{ `(${this.countdown})` }}
  94. </span>
  95. </v-btn> -->
  96. </v-card>
  97. </v-dialog>
  98. <v-dialog v-model="deleteDialog" :width="$vuetify.breakpoint.smAndUp ? 423 : 294"
  99. @click:outside="colseDialog()">
  100. <v-card class="tw-p-[30px]" :height="$vuetify.breakpoint.smAndUp ? 289 : 290">
  101. <v-spacer class="d-flex tw-justify-between align-center tw-mb-[30px]">
  102. <div class="tw-text-[20px] tw-text-black tw-font-bold">
  103. {{ $t("Reactivate your account") }}
  104. </div>
  105. <v-btn @click="colseDialog()" icon>
  106. <v-icon> mdi-close </v-icon>
  107. </v-btn>
  108. </v-spacer>
  109. <v-spacer class="tw-mb-[40px]">
  110. <div class="tw-text-[16px] tw-text-neutrals-800 tw-font-bold">
  111. {{ $t("Welcome back!")}}
  112. </div>
  113. <div class="tw-text-[16px] tw-text-neutrals-800">
  114. {{ $t("Looks like your account has been deactivated.")}}
  115. <br />
  116. {{ $t("Would you like to reactivate this account?")}}
  117. </div>
  118. </v-spacer>
  119. <button @click="ReactivateAccount()" class="tw-bg-primary-1 tw-text-white hover:tw-bg-primary-light tw-text-[18px] tw-rounded-[16px] tw-px-[86px] tw-py-[13px]">
  120. {{ $t("Reactivate my account") }}
  121. </button>
  122. <!-- <v-btn class="primary tw-w-auto" rounded
  123. :disabled="countdown > 0">
  124. <span v-if="countdown > 0">
  125. {{ `(${this.countdown})` }}
  126. </span>
  127. </v-btn> -->
  128. </v-card>
  129. </v-dialog>
  130. </div>
  131. </template>
  132. <script>
  133. import { getCurrentTime } from "~/utils/assist";
  134. export default {
  135. name: "login",
  136. layout: "login",
  137. auth: false,
  138. data() {
  139. return {
  140. timer: null,
  141. showPass: false,
  142. resendDialog: false,
  143. wrongMessageActive: false,
  144. verifyEmailSent: false,
  145. valid: false,
  146. remember: false,
  147. countdown: 60,
  148. userData: {
  149. Account: '',
  150. Password: '',
  151. },
  152. rules: {
  153. require: value => !!value || this.$t('Required.'),
  154. email: v => /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/.test(v) || this.$t('Invalid email'),
  155. // checkPassword: v => (/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])/.test(v) && v.length >= 8 && v.length <= 20) || '請輸入密碼',
  156. checkPassword: v => v.length >= 1 || '請輸入密碼',
  157. },
  158. deleteDialog: false,
  159. dialog: false,
  160. }
  161. },
  162. watch: {
  163. remember: {
  164. handler: function () {
  165. if (this.remember == true) {
  166. this.$auth.$storage.setUniversal("userPassword", this.userData.Password);
  167. this.$auth.$storage.setUniversal("userAccount", this.userData.Account);
  168. }else{
  169. this.$auth.$storage.removeUniversal("userPassword");
  170. this.$auth.$storage.removeUniversal("userAccount", this.userData.Account);
  171. }
  172. },
  173. },
  174. },
  175. mounted(){
  176. var userAccount = this.$auth.$storage.getUniversal('userAccount');
  177. var userPassword = this.$auth.$storage.getUniversal('userPassword');
  178. this.userData.Account = userAccount ? userAccount : '';
  179. this.userData.Password = userPassword ? userPassword : '';
  180. if(this.userData.Account !=='' && this.userData.Password !==''){
  181. this.valid = true;
  182. }else{
  183. this.valid = false;
  184. }
  185. },
  186. methods: {
  187. colseDialog(){
  188. this.dialog = false;
  189. this.deleteDialog = false;
  190. },
  191. async userLogin() {
  192. let that = this;
  193. if (!that.$refs.loginFormRef.validate()) return;
  194. console.log("測試登錄接口請求開始:" + getCurrentTime());
  195. try {
  196. const response =await that.$auth.loginWith('local', { data: that.userData });
  197. that.$auth.$storage.removeUniversal('authtoken');
  198. console.log("測試登錄接口請求結束:" + getCurrentTime());
  199. if(response.data.STATUSCODE==200){
  200. let data = response.data.DATA;
  201. console.log(JSON.stringify(data.authtoken));
  202. if(data.authtoken){
  203. const authtoken = data.authtoken;
  204. that.$auth.$storage.setUniversal('authtoken', authtoken);
  205. that.$auth.loggedIn ? that.$router.push(that.$auth.$storage.getUniversal('userBeforePath')) : that.$auth.redirect('login');
  206. }
  207. }else if(response.data.STATUSCODE==500){
  208. that.$auth.redirect('login');
  209. }else if(response.data.STATUSCODE==401){
  210. if(response.data.MSG == "0"){
  211. this.dialog = true;
  212. }else if(response.data.MSG == "2"){
  213. this.deleteDialog = true;
  214. }else if(response.data.MSG == "帳號或密碼不正確"){
  215. this.wrongMessageActive = true;
  216. }
  217. }else{
  218. // that.resendDialog = !that.resendDialog;
  219. that.wrongMessageActive = true;
  220. }
  221. } catch(err) {
  222. console.log(err);
  223. // if(err && err.response && err.response.status){
  224. // err.response.status === 403 ? that.resendDialog = !that.resendDialog : err.response.status === 401 ? that.wrongMessageActive = true : that.resendDialog;
  225. // }
  226. }
  227. },
  228. resendVerifyEmail() {
  229. this.$axios
  230. .post(
  231. `/trending/api/Signup/ReSendVerifyMail?Email=${this.userData.Account}`
  232. )
  233. .then((response) => {
  234. //console.log(JSON.stringify(response))
  235. if(response && response.data){
  236. this.dialog = false;
  237. }
  238. })
  239. .catch((error) => {
  240. console.log(error);
  241. });
  242. },
  243. ReactivateAccount(){
  244. this.$axios
  245. .post(
  246. `/trending/api/Members/ReactivateAccountByAcc?Account=${this.userData.Account}`
  247. )
  248. .then((response) => {
  249. //console.log(JSON.stringify(response))
  250. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  251. let data = response.data.DATA.rel
  252. if(data){
  253. this.deleteDialog = false;
  254. }
  255. }
  256. })
  257. .catch((error) => {
  258. console.log(error);
  259. });
  260. },
  261. updateValid(){
  262. if(this.userData.Account !=='' && this.userData.Password !==''){
  263. this.valid = true;
  264. }else{
  265. this.valid = false;
  266. }
  267. },
  268. },
  269. beforeUnmount() {
  270. if(this.timer!=null){
  271. clearInterval(this.timer);
  272. }
  273. },
  274. beforeRouteEnter(to, from, next) {
  275. next(vm => {
  276. if (from.name) {
  277. if (!from.path.includes('user')) {
  278. vm.$auth.$storage.setUniversal("userBeforePath", from.fullPath, true)
  279. }
  280. }
  281. if (vm.$auth.loggedIn) {
  282. vm.$router.push(vm.$auth.$storage.getUniversal('userBeforePath') || '/')
  283. }
  284. else {
  285. next()
  286. }
  287. })
  288. },
  289. }
  290. </script>
  291. <style lang="scss" scoped>
  292. $border-style: 1px solid #E5E5E5;
  293. .title {
  294. font-weight: 700;
  295. font-size: 26px;
  296. line-height: 34px;
  297. letter-spacing: 0.02em;
  298. color: #232323;
  299. }
  300. .btn-border {
  301. border: $border-style;
  302. }
  303. .seperator {
  304. border-bottom: $border-style;
  305. text-align: center;
  306. height: 12px;
  307. margin: 20px 0 30px;
  308. }
  309. :deep(.v-text-field.v-text-field--enclosed .v-text-field__details) {
  310. margin-bottom: 0;
  311. padding: 0;
  312. .v-messages {
  313. display: none;
  314. }
  315. .v-messages.error--text {
  316. display: block;
  317. margin-top: 4px;
  318. margin-bottom: 16px;
  319. }
  320. }
  321. /* The container */
  322. .container-checkbox {
  323. display: block;
  324. position: relative;
  325. padding-left: 28px;
  326. cursor: pointer;
  327. -webkit-user-select: none;
  328. -moz-user-select: none;
  329. -ms-user-select: none;
  330. user-select: none;
  331. }
  332. /* Hide the browser's default checkbox */
  333. .container-checkbox input {
  334. position: absolute;
  335. opacity: 0;
  336. cursor: pointer;
  337. }
  338. /* Create a custom checkbox */
  339. .container-checkbox .checkmark {
  340. position: absolute;
  341. top: 0;
  342. left: 0;
  343. height: 18px;
  344. width: 18px;
  345. background-color: transparent;
  346. border: 1px solid #f48800;
  347. border-radius: 4px;
  348. }
  349. /* On mouse-over, add a grey background color */
  350. .container-checkbox:hover input~.checkmark {
  351. border-color: #f48800;
  352. }
  353. /* When the checkbox is checked, add a blue background */
  354. .container-checkbox input:checked~.checkmark {
  355. background-color: #f48800;
  356. border-color: #f48800;
  357. }
  358. /* Create the checkmark/indicator (hidden when not checked) */
  359. .container-checkbox .checkmark:after {
  360. content: "";
  361. position: absolute;
  362. display: none;
  363. }
  364. /* Show the checkmark when checked */
  365. .container-checkbox input:checked~.checkmark:after {
  366. display: block;
  367. }
  368. /* Style the checkmark/indicator */
  369. .container-checkbox .checkmark:after {
  370. left: 5px;
  371. top: 2px;
  372. width: 5px;
  373. height: 10px;
  374. border: solid #ffffff;
  375. border-width: 0 2px 2px 0;
  376. -webkit-transform: rotate(45deg);
  377. -ms-transform: rotate(45deg);
  378. transform: rotate(45deg);
  379. }
  380. </style>