register.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <template>
  2. <div>
  3. <div class="bg-white w-full py-[60px] px-[30px] !rounded-[var(--rounded-big)]">
  4. <div class="flex items-end justify-center mb-[30px]">
  5. <div class="text-[18px] cursor-pointer text-[#999] leading-[24px] oppoSans-R" :class="{ '!text-[#333] font-600': type == item.type,'mr-[70px]': (index+1) != registerType.length }" v-for="(item,index) in registerType" @click="type = item.type">{{item.title }}</div>
  6. </div>
  7. <el-form :model="formData" ref="formRef" :rules="formRules" :validate-on-rule-change="false">
  8. <div v-show="type == 'username'">
  9. <el-form-item prop="username">
  10. <div class="flex-1 h-[50px] border-[1px] border-solid border-[#ccc] rounded-[8px] flex items-center">
  11. <el-input v-model="formData.username" :placeholder="t('usernamePlaceholder')" clearable :inline-message="true" :readonly="real_name_input" @click="real_name_input = false" @blur="real_name_input = true">
  12. <template #prefix>
  13. <span class="iconfont icon-woV6xx1 !mr-[14px]"></span>
  14. </template>
  15. </el-input>
  16. </div>
  17. </el-form-item>
  18. <el-form-item prop="password">
  19. <div class="flex-1 h-[50px] border-[1px] border-solid border-[#ccc] rounded-[8px] flex items-center">
  20. <el-input v-model="formData.password" :placeholder="t('passwordPlaceholder')" type="password" clearable :show-password="true" :readonly="password_input" @click="password_input = false" @blur="password_input = true" >
  21. <template #prefix>
  22. <span class="iconfont icon-mima !mr-[14px]"></span>
  23. </template>
  24. </el-input>
  25. </div>
  26. </el-form-item>
  27. <el-form-item prop="confirm_password">
  28. <div class="flex-1 h-[50px] border-[1px] border-solid border-[#ccc] rounded-[8px] flex items-center">
  29. <el-input v-model="formData.confirm_password" :placeholder="t('confirmPasswordPlaceholder')" type="password" clearable :show-password="true" :readonly="confirm_password_input" @click="confirm_password_input = false" @blur="confirm_password_input = true" >
  30. <template #prefix>
  31. <span class="iconfont icon-mima !mr-[14px]"></span>
  32. </template>
  33. </el-input>
  34. </div>
  35. </el-form-item>
  36. </div>
  37. <div v-show="type == 'mobile' || configStore.login.is_bind_mobile">
  38. <el-form-item prop="mobile">
  39. <div class="flex-1 h-[50px] border-[1px] border-solid border-[#ccc] rounded-[8px] flex items-center">
  40. <el-input v-model="formData.mobile" :placeholder="t('mobilePlaceholder')" clearable>
  41. <template #prefix>
  42. <span class="iconfont icon-shoujiV6xx !mr-[14px]"></span>
  43. </template>
  44. </el-input>
  45. </div>
  46. </el-form-item>
  47. <el-form-item prop="mobile_code">
  48. <div class="flex-1 h-[50px] border-[1px] border-solid border-[#ccc] rounded-[8px] flex items-center">
  49. <el-input v-model="formData.mobile_code" :placeholder="t('codePlaceholder')">
  50. <template #prefix>
  51. <span class="iconfont icon-a-zhibao5 !mr-[14px]"></span>
  52. </template>
  53. <template #suffix>
  54. <sms-code :mobile="formData.mobile" type="login" v-model="formData.mobile_key" @click="sendSmsCode" ref="smsCodeRef"></sms-code>
  55. </template>
  56. </el-input>
  57. </div>
  58. </el-form-item>
  59. </div>
  60. <div v-show="type == 'username'">
  61. <el-form-item prop="captcha_code">
  62. <div class="flex-1 h-[50px] border-[1px] border-solid border-[#ccc] rounded-[8px] flex items-center">
  63. <el-input v-model="formData.captcha_code" :placeholder="t('captchaPlaceholder')">
  64. <template #prefix>
  65. <span class="iconfont icon-a-zhibao5 !mr-[14px]"></span>
  66. </template>
  67. <template #suffix>
  68. <div class="py-0 leading-none">
  69. <el-image :src="captcha.image.value" class="h-[30px] cursor-pointer" @click="captcha.refresh()"></el-image>
  70. </div>
  71. </template>
  72. </el-input>
  73. </div>
  74. </el-form-item>
  75. </div>
  76. <div class="flex justify-end">
  77. <el-button type="primary" link @click="typeChange" class="!text-[12px]">{{ t('haveAccount') }},{{ t('toLogin') }}</el-button>
  78. </div>
  79. <div class="mt-[20px]">
  80. <el-button type="primary" class="w-full !h-[50px] !rounded-[8px] oppoSans-M" size="large" @click="handleRegister" :loading="loading">{{ loading ? t('registering') : t('register') }}</el-button>
  81. </div>
  82. <div class="text-[12px] leading-[24px] flex items-center w-full mt-[20px]" v-if="configStore.login.agreement_show">
  83. <span class="iconfont text-primary mr-[5px]" :class="isAgree ? 'icon-xuanze1' : 'icon-checkbox_nol'" @click="isAgree = !isAgree"></span>
  84. {{ t('registerAgreeTips') }}
  85. <NuxtLink :to="service">
  86. <span class="text-primary mx-[4px]">{{ t('userAgreement') }}</span>
  87. </NuxtLink>
  88. {{ t('and') }}
  89. <NuxtLink :to="privacy">
  90. <span class="text-primary mx-[4px]">{{ t('privacyAgreement') }}</span>
  91. </NuxtLink>
  92. </div>
  93. </el-form>
  94. </div>
  95. </div>
  96. </template>
  97. <script lang="ts" setup>
  98. import { ref,reactive,computed } from 'vue'
  99. import { usernameRegister, mobileRegister, wechatCheck } from '@/app/api/auth'
  100. import useMemberStore from '@/stores/member'
  101. import useConfigStore from '@/stores/config'
  102. import { FormInstance } from 'element-plus'
  103. definePageMeta({
  104. layout: "container"
  105. });
  106. const memberStore = useMemberStore()
  107. const configStore = useConfigStore()
  108. configStore.getLoginConfig()
  109. // 跳转
  110. const service = ref('')
  111. const privacy = ref('')
  112. if(location.pathname.indexOf('web') != -1){
  113. service.value = '/web/auth/agreement?key=service'
  114. privacy.value = '/web/auth/agreement?key=privacy'
  115. }else{
  116. service.value = '/auth/agreement?key=service'
  117. privacy.value = '/auth/agreement?key=privacy'
  118. }
  119. const type = ref('')
  120. const registerType = computed(() => {
  121. const value = []
  122. configStore.login.is_username && (value.push({ type: 'username', title: t('usernameRegister') }))
  123. configStore.login.is_mobile && !configStore.login.is_bind_mobile && (value.push({ type: 'mobile', title: t('mobileRegister') }))
  124. type.value = value[0] ? value[0].type : ''
  125. return value
  126. })
  127. const loading = ref(false)
  128. const formData = reactive({
  129. username: '',
  130. password: '',
  131. confirm_password: '',
  132. mobile: '',
  133. mobile_code: '',
  134. mobile_key: '',
  135. captcha_key: '',
  136. captcha_code: ''
  137. })
  138. const formRules = computed(() => {
  139. return {
  140. 'username': {
  141. type: 'string',
  142. required: type.value == 'username',
  143. message: t('usernamePlaceholder'),
  144. trigger: ['blur', 'change'],
  145. },
  146. 'password': {
  147. type: 'string',
  148. required: type.value == 'username',
  149. message: t('passwordPlaceholder'),
  150. trigger: ['blur', 'change']
  151. },
  152. 'confirm_password': [
  153. {
  154. type: 'string',
  155. required: type.value == 'username',
  156. message: t('confirmPasswordPlaceholder'),
  157. trigger: ['blur', 'change']
  158. },
  159. {
  160. validator(rule: any, value: string, callback: any) {
  161. return value == formData.password
  162. },
  163. message: t('confirmPasswordError'),
  164. trigger: ['change', 'blur'],
  165. }
  166. ],
  167. 'mobile': [
  168. {
  169. type: 'string',
  170. required: type.value == 'mobile' || configStore.login.is_bind_mobile,
  171. message: t('mobilePlaceholder'),
  172. trigger: ['blur', 'change'],
  173. },
  174. {
  175. validator(rule: any, value: string, callback: any) {
  176. if (type.value != 'mobile' && !configStore.login.is_bind_mobile) return true
  177. else return test.mobile(value)
  178. },
  179. message: t('mobileError'),
  180. trigger: ['change', 'blur'],
  181. }
  182. ],
  183. 'mobile_code': {
  184. type: 'string',
  185. required: type.value == 'mobile' || configStore.login.is_bind_mobile,
  186. message: t('codePlaceholder'),
  187. trigger: ['blur', 'change']
  188. },
  189. 'captcha_code': {
  190. type: 'string',
  191. required: type.value == 'username',
  192. message: t('captchaPlaceholder'),
  193. trigger: ['blur', 'change'],
  194. }
  195. }
  196. })
  197. const isAgree = ref(false)
  198. const formRef = ref<FormInstance>()
  199. const handleRegister = async () => {
  200. await formRef.value?.validate(async (valid, fields) => {
  201. if (valid) {
  202. if (configStore.login.agreement_show && !isAgree.value) {
  203. ElMessage.error(t('isAgreeTips'))
  204. return false;
  205. }
  206. if (loading.value) return
  207. loading.value = true
  208. const register = type.value == 'username' ? usernameRegister : mobileRegister
  209. register(formData).then((res: any) => {
  210. memberStore.setToken(res.data.token)
  211. memberStore.logClose()
  212. }).catch(() => {
  213. loading.value = false
  214. captcha.refresh()
  215. })
  216. }
  217. })
  218. }
  219. let show = ref(false)
  220. const wechatCheckFn = () =>{
  221. wechatCheck().then((res:any) =>{
  222. show.value = res.data
  223. })
  224. }
  225. wechatCheckFn()
  226. // 验证码
  227. const captcha = useCaptcha(formData)
  228. captcha.refresh()
  229. // 获取手机验证码
  230. const smsCodeRef = ref<AnyObject | null>(null)
  231. const sendSmsCode = async () => {
  232. await formRef.value?.validateField('mobile', async (valid, fields) => {
  233. if (valid) {
  234. smsCodeRef.value?.send()
  235. }
  236. })
  237. }
  238. //去登录
  239. const emit = defineEmits(['typeChange'])
  240. const typeChange = ()=>{
  241. emit('typeChange','login')
  242. }
  243. const real_name_input = ref(true)
  244. const password_input = ref(true)
  245. const confirm_password_input = ref(true)
  246. </script>
  247. <style lang="scss" scoped>
  248. :deep(.el-checkbox.el-checkbox--large){
  249. height: 0px;
  250. margin-right: 5px;
  251. }
  252. </style>