RegisterForm.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <script setup lang="tsx">
  2. import { Form, FormSchema } from '@/components/Form'
  3. import { reactive, ref, unref } from 'vue'
  4. import { useI18n } from '@/hooks/web/useI18n'
  5. import { useForm } from '@/hooks/web/useForm'
  6. import { ElInput, FormRules } from 'element-plus'
  7. import { useValidator } from '@/hooks/web/useValidator'
  8. import { BaseButton } from '@/components/Button'
  9. import { IAgree } from '@/components/IAgree'
  10. const emit = defineEmits(['to-login'])
  11. const { formRegister, formMethods } = useForm()
  12. const { getElFormExpose } = formMethods
  13. const { t } = useI18n()
  14. const { required, check } = useValidator()
  15. const getCodeTime = ref(60)
  16. const getCodeLoading = ref(false)
  17. const getCode = () => {
  18. getCodeLoading.value = true
  19. const timer = setInterval(() => {
  20. getCodeTime.value--
  21. if (getCodeTime.value <= 0) {
  22. clearInterval(timer)
  23. getCodeTime.value = 60
  24. getCodeLoading.value = false
  25. }
  26. }, 1000)
  27. }
  28. const schema = reactive<FormSchema[]>([
  29. {
  30. field: 'title',
  31. colProps: {
  32. span: 24
  33. },
  34. formItemProps: {
  35. slots: {
  36. default: () => {
  37. return <h2 class="text-2xl font-bold text-center w-[100%]">{t('login.register')}</h2>
  38. }
  39. }
  40. }
  41. },
  42. {
  43. field: 'username',
  44. label: t('login.username'),
  45. value: '',
  46. component: 'Input',
  47. colProps: {
  48. span: 24
  49. },
  50. componentProps: {
  51. placeholder: t('login.usernamePlaceholder')
  52. }
  53. },
  54. {
  55. field: 'password',
  56. label: t('login.password'),
  57. value: '',
  58. component: 'InputPassword',
  59. colProps: {
  60. span: 24
  61. },
  62. componentProps: {
  63. style: {
  64. width: '100%'
  65. },
  66. strength: true,
  67. placeholder: t('login.passwordPlaceholder')
  68. }
  69. },
  70. {
  71. field: 'check_password',
  72. label: t('login.checkPassword'),
  73. value: '',
  74. component: 'InputPassword',
  75. colProps: {
  76. span: 24
  77. },
  78. componentProps: {
  79. style: {
  80. width: '100%'
  81. },
  82. strength: true,
  83. placeholder: t('login.passwordPlaceholder')
  84. }
  85. },
  86. {
  87. field: 'code',
  88. label: t('login.code'),
  89. colProps: {
  90. span: 24
  91. },
  92. formItemProps: {
  93. slots: {
  94. default: (formData) => {
  95. return (
  96. <div class="w-[100%] flex">
  97. <ElInput v-model={formData.code} placeholder={t('login.codePlaceholder')} />
  98. <BaseButton
  99. type="primary"
  100. disabled={unref(getCodeLoading)}
  101. class="ml-10px"
  102. onClick={getCode}
  103. >
  104. {t('login.getCode')}
  105. {unref(getCodeLoading) ? `(${unref(getCodeTime)})` : ''}
  106. </BaseButton>
  107. </div>
  108. )
  109. }
  110. }
  111. }
  112. },
  113. {
  114. field: 'iAgree',
  115. colProps: {
  116. span: 24
  117. },
  118. formItemProps: {
  119. slots: {
  120. default: (formData: any) => {
  121. return (
  122. <>
  123. <IAgree
  124. v-model={formData.iAgree}
  125. text="我同意《用户协议》"
  126. link={[
  127. {
  128. text: '《用户协议》',
  129. url: 'https://element-plus.org/'
  130. }
  131. ]}
  132. />
  133. </>
  134. )
  135. }
  136. }
  137. }
  138. },
  139. {
  140. field: 'register',
  141. colProps: {
  142. span: 24
  143. },
  144. formItemProps: {
  145. slots: {
  146. default: () => {
  147. return (
  148. <>
  149. <div class="w-[100%]">
  150. <BaseButton
  151. type="primary"
  152. class="w-[100%]"
  153. loading={loading.value}
  154. onClick={loginRegister}
  155. >
  156. {t('login.register')}
  157. </BaseButton>
  158. </div>
  159. <div class="w-[100%] mt-15px">
  160. <BaseButton class="w-[100%]" onClick={toLogin}>
  161. {t('login.hasUser')}
  162. </BaseButton>
  163. </div>
  164. </>
  165. )
  166. }
  167. }
  168. }
  169. }
  170. ])
  171. const rules: FormRules = {
  172. username: [required()],
  173. password: [required()],
  174. check_password: [required()],
  175. code: [required()],
  176. iAgree: [required(), check()]
  177. }
  178. const toLogin = () => {
  179. emit('to-login')
  180. }
  181. const loading = ref(false)
  182. const loginRegister = async () => {
  183. const formRef = await getElFormExpose()
  184. formRef?.validate(async (valid) => {
  185. if (valid) {
  186. try {
  187. loading.value = true
  188. toLogin()
  189. } finally {
  190. loading.value = false
  191. }
  192. }
  193. })
  194. }
  195. </script>
  196. <template>
  197. <Form
  198. :schema="schema"
  199. :rules="rules"
  200. label-position="top"
  201. hide-required-asterisk
  202. size="large"
  203. class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
  204. @register="formRegister"
  205. />
  206. </template>