register.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <script setup lang="ts">
  2. import type { RegisterEmits } from './typings';
  3. import { computed, reactive } from 'vue';
  4. import { useRouter } from 'vue-router';
  5. import { $t } from '@vben/locales';
  6. import {
  7. VbenButton,
  8. VbenCheckbox,
  9. VbenInput,
  10. VbenInputPassword,
  11. } from '@vben-core/shadcn-ui';
  12. import Title from './auth-title.vue';
  13. interface Props {
  14. /**
  15. * @zh_CN 是否处于加载处理状态
  16. */
  17. loading?: boolean;
  18. /**
  19. * @zh_CN 登陆路径
  20. */
  21. loginPath?: string;
  22. }
  23. defineOptions({
  24. name: 'RegisterForm',
  25. });
  26. const props = withDefaults(defineProps<Props>(), {
  27. loading: false,
  28. loginPath: '/auth/login',
  29. });
  30. const emit = defineEmits<{
  31. submit: RegisterEmits['submit'];
  32. }>();
  33. const router = useRouter();
  34. const formState = reactive({
  35. agreePolicy: false,
  36. confirmPassword: '',
  37. password: '',
  38. submitted: false,
  39. username: '',
  40. });
  41. const usernameStatus = computed(() => {
  42. return formState.submitted && !formState.username ? 'error' : 'default';
  43. });
  44. const passwordStatus = computed(() => {
  45. return formState.submitted && !formState.password ? 'error' : 'default';
  46. });
  47. const confirmPasswordStatus = computed(() => {
  48. return formState.submitted && formState.password !== formState.confirmPassword
  49. ? 'error'
  50. : 'default';
  51. });
  52. function handleSubmit() {
  53. formState.submitted = true;
  54. if (
  55. usernameStatus.value !== 'default' ||
  56. passwordStatus.value !== 'default'
  57. ) {
  58. return;
  59. }
  60. emit('submit', {
  61. password: formState.password,
  62. username: formState.username,
  63. });
  64. }
  65. function goToLogin() {
  66. router.push(props.loginPath);
  67. }
  68. </script>
  69. <template>
  70. <div>
  71. <Title>
  72. {{ $t('authentication.createAnAccount') }} 🚀
  73. <template #desc> {{ $t('authentication.signUpSubtitle') }} </template>
  74. </Title>
  75. <VbenInput
  76. v-model="formState.username"
  77. :error-tip="$t('authentication.usernameTip')"
  78. :label="$t('authentication.username')"
  79. :placeholder="$t('authentication.username')"
  80. :status="usernameStatus"
  81. name="username"
  82. type="text"
  83. />
  84. <!-- Use 8 or more characters with a mix of letters, numbers & symbols. -->
  85. <VbenInputPassword
  86. v-model="formState.password"
  87. :error-tip="$t('authentication.passwordTip')"
  88. :label="$t('authentication.password')"
  89. :password-strength="true"
  90. :placeholder="$t('authentication.password')"
  91. :status="passwordStatus"
  92. name="password"
  93. required
  94. type="password"
  95. >
  96. <template #strengthText>
  97. {{ $t('authentication.passwordStrength') }}
  98. </template>
  99. </VbenInputPassword>
  100. <VbenInputPassword
  101. v-model="formState.confirmPassword"
  102. :error-tip="$t('authentication.confirmPasswordTip')"
  103. :label="$t('authentication.confirmPassword')"
  104. :placeholder="$t('authentication.confirmPassword')"
  105. :status="confirmPasswordStatus"
  106. name="confirmPassword"
  107. required
  108. type="password"
  109. />
  110. <div class="relative mt-4 flex pb-6">
  111. <div class="flex-center">
  112. <VbenCheckbox
  113. v-model:checked="formState.agreePolicy"
  114. name="agreePolicy"
  115. >
  116. {{ $t('authentication.agree') }}
  117. <span class="text-primary hover:text-primary-hover">{{
  118. $t('authentication.privacyPolicy')
  119. }}</span>
  120. &
  121. <span class="text-primary hover:text-primary-hover">
  122. {{ $t('authentication.terms') }}
  123. </span>
  124. </VbenCheckbox>
  125. </div>
  126. <Transition name="slide-up">
  127. <p
  128. v-show="formState.submitted && !formState.agreePolicy"
  129. class="text-destructive absolute bottom-1 left-0 text-xs"
  130. >
  131. {{ $t('authentication.agreeTip') }}
  132. </p>
  133. </Transition>
  134. </div>
  135. <div>
  136. <VbenButton :loading="loading" class="w-full" @click="handleSubmit">
  137. {{ $t('authentication.signUp') }}
  138. </VbenButton>
  139. </div>
  140. <div class="mt-4 text-center text-sm">
  141. {{ $t('authentication.alreadyHaveAccount') }}
  142. <span
  143. class="text-primary hover:text-primary-hover cursor-pointer text-sm font-normal"
  144. @click="goToLogin()"
  145. >
  146. {{ $t('authentication.goToLogin') }}
  147. </span>
  148. </div>
  149. </div>
  150. </template>