RegisterForm.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <script setup lang="ts">
  2. import { Form } 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 { ElButton, ElInput, FormRules, ElMessage } from 'element-plus'
  7. import { getCodeApi, registerApi } from '@/api/register'
  8. import { useValidator } from '@/hooks/web/useValidator'
  9. import { IUserModel } from '@/api-types/user'
  10. const emit = defineEmits(['to-login'])
  11. const { register, methods, elFormRef } = useForm()
  12. const { getFormData } = methods
  13. const { t } = useI18n()
  14. const { required, lengthRange, notSpace, notSpecialCharacters, isEqual } = useValidator()
  15. const schema = reactive<FormSchema[]>([
  16. {
  17. field: 'title',
  18. colProps: {
  19. span: 24
  20. }
  21. },
  22. {
  23. field: 'user_name',
  24. label: t('login.username'),
  25. value: '',
  26. component: 'Input',
  27. colProps: {
  28. span: 24
  29. },
  30. componentProps: {
  31. placeholder: t('login.usernamePlaceholder')
  32. }
  33. },
  34. {
  35. field: 'password',
  36. label: t('login.password'),
  37. value: '',
  38. component: 'InputPassword',
  39. colProps: {
  40. span: 24
  41. },
  42. componentProps: {
  43. style: {
  44. width: '100%'
  45. },
  46. strength: true,
  47. placeholder: t('login.passwordPlaceholder')
  48. }
  49. },
  50. {
  51. field: 'check_password',
  52. label: t('login.checkPassword'),
  53. value: '',
  54. component: 'InputPassword',
  55. colProps: {
  56. span: 24
  57. },
  58. componentProps: {
  59. style: {
  60. width: '100%'
  61. },
  62. strength: true,
  63. placeholder: t('login.passwordPlaceholder')
  64. }
  65. },
  66. {
  67. field: 'code',
  68. label: t('login.code'),
  69. colProps: {
  70. span: 24
  71. }
  72. },
  73. {
  74. field: 'register',
  75. colProps: {
  76. span: 24
  77. }
  78. }
  79. ])
  80. const rules: FormRules = {
  81. user_name: [
  82. required('用户名不能为空'),
  83. {
  84. validator: (_, value, callback) =>
  85. lengthRange(value, callback, { min: 2, max: 10, message: '用户名长度必须在2-10之间' })
  86. },
  87. {
  88. validator: (_, value, callback) => notSpace(value, callback, '用户名不能有空格')
  89. }
  90. ],
  91. password: [
  92. required('密码不能为空'),
  93. {
  94. validator: (_, value, callback) =>
  95. lengthRange(value, callback, { min: 6, max: 20, message: '密码长度必须在6-20之间' })
  96. },
  97. {
  98. validator: (_, value, callback) => notSpecialCharacters(value, callback, '密码不能是特殊字符')
  99. }
  100. ],
  101. check_password: [
  102. required('确认密码不能为空'),
  103. {
  104. validator: (_, value, callback) =>
  105. lengthRange(value, callback, { min: 6, max: 20, message: '确认密码长度必须在6-20之间' })
  106. },
  107. {
  108. validator: (_, value, callback) =>
  109. notSpecialCharacters(value, callback, '确认密码不能是特殊字符')
  110. },
  111. {
  112. validator: async (_, value, callback) => {
  113. const formData = await getFormData<Omit<IUserModel, 'is_admin'>>()
  114. return isEqual(value, formData.password, callback, '两次密码不一致')
  115. }
  116. }
  117. ],
  118. code: [required('验证码不能为空')]
  119. }
  120. const toLogin = () => {
  121. emit('to-login')
  122. }
  123. const codeUrl = ref('')
  124. const getCode = async () => {
  125. const { data } = await getCodeApi()
  126. codeUrl.value = data.result
  127. }
  128. getCode()
  129. const loading = ref(false)
  130. const loginRegister = async () => {
  131. const formRef = unref(elFormRef)
  132. formRef?.validate(async (valid) => {
  133. if (valid) {
  134. try {
  135. loading.value = true
  136. const formData = await getFormData<Omit<IUserModel, 'is_admin'>>()
  137. const { data } = await registerApi(formData)
  138. if (data) {
  139. ElMessage.success('注册成功')
  140. toLogin()
  141. }
  142. } finally {
  143. loading.value = false
  144. }
  145. }
  146. })
  147. }
  148. </script>
  149. <template>
  150. <Form
  151. :schema="schema"
  152. :rules="rules"
  153. label-position="top"
  154. hide-required-asterisk
  155. size="large"
  156. class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
  157. @register="register"
  158. >
  159. <template #title>
  160. <h2 class="text-2xl font-bold text-center w-[100%]">{{ t('login.register') }}</h2>
  161. </template>
  162. <template #code="form">
  163. <div class="w-[100%] flex">
  164. <ElInput v-model="form['code']" :placeholder="t('login.codePlaceholder')" class="flex-2" />
  165. <div v-html="codeUrl" class="h-38px flex-1 cursor-pointer" @click="getCode"></div>
  166. </div>
  167. </template>
  168. <template #register>
  169. <div class="w-[100%]">
  170. <ElButton type="primary" class="w-[100%]" :loading="loading" @click="loginRegister">
  171. {{ t('login.register') }}
  172. </ElButton>
  173. </div>
  174. <div class="w-[100%] mt-15px">
  175. <ElButton class="w-[100%]" @click="toLogin">
  176. {{ t('login.hasUser') }}
  177. </ElButton>
  178. </div>
  179. </template>
  180. </Form>
  181. </template>