register.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <template>
  2. <div>
  3. <div class="bg-white w-full py-[60px] px-[30px]" v-if="active">
  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]': 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 justify-center w-full mt-[20px]" v-if="configStore.login.agreement_show">
  83. {{ t('registerAgreeTips') }}
  84. <NuxtLink to="/auth/agreement?key=service">
  85. <span class="text-primary mx-[4px]">{{ t('userAgreement') }}</span>
  86. </NuxtLink>
  87. {{ t('and') }}
  88. <NuxtLink to="/auth/agreement?key=privacy">
  89. <span class="text-primary mx-[4px]">{{ t('privacyAgreement') }}</span>
  90. </NuxtLink>
  91. </div>
  92. <!-- <div class="mt-[20px] flex justify-center" v-if="show">
  93. <span class="iconfont icon-weixin1 text-[#1AAD19] !text-[24px]" @click="active = !active"></span>
  94. </div> -->
  95. </el-form>
  96. </div>
  97. <div class="flex flex-col items-center w-[380px] py-[100px] h-[556px]" v-else>
  98. <div class="title font-bold text-xl">打开手机微信</div>
  99. <div class="tips text-sm mt-[5px]">点击右上角打开扫一扫</div>
  100. <div class="qrcode mt-[30px] border leading-none">
  101. <el-image :src="img('https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQHU7zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAySlJSbU1Sb0hiMlQxOEcwSGhBY1AAAgTSfStkAwRYAgAA')" class="w-[120px]"></el-image>
  102. </div>
  103. <div class="mt-[60px] text-base cursor-pointer leading-none" @click="active = !active">账号注册</div>
  104. </div>
  105. </div>
  106. </template>
  107. <script lang="ts" setup>
  108. import { ref,reactive,computed } from 'vue'
  109. import { usernameRegister, mobileRegister, wechatCheck } from '@/app/api/auth'
  110. import useMemberStore from '@/stores/member'
  111. import useConfigStore from '@/stores/config'
  112. import { FormInstance } from 'element-plus'
  113. definePageMeta({
  114. layout: "container"
  115. });
  116. const memberStore = useMemberStore()
  117. const configStore = useConfigStore()
  118. configStore.getLoginConfig()
  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. let active = ref(true)
  129. const formData = reactive({
  130. username: '',
  131. password: '',
  132. confirm_password: '',
  133. mobile: '',
  134. mobile_code: '',
  135. mobile_key: '',
  136. captcha_key: '',
  137. captcha_code: ''
  138. })
  139. const formRules = computed(() => {
  140. return {
  141. 'username': {
  142. type: 'string',
  143. required: type.value == 'username',
  144. message: t('usernamePlaceholder'),
  145. trigger: ['blur', 'change'],
  146. },
  147. 'password': {
  148. type: 'string',
  149. required: type.value == 'username',
  150. message: t('passwordPlaceholder'),
  151. trigger: ['blur', 'change']
  152. },
  153. 'confirm_password': [
  154. {
  155. type: 'string',
  156. required: type.value == 'username',
  157. message: t('confirmPasswordPlaceholder'),
  158. trigger: ['blur', 'change']
  159. },
  160. {
  161. validator(rule: any, value: string, callback: any) {
  162. return value == formData.password
  163. },
  164. message: t('confirmPasswordError'),
  165. trigger: ['change', 'blur'],
  166. }
  167. ],
  168. 'mobile': [
  169. {
  170. type: 'string',
  171. required: type.value == 'mobile' || configStore.login.is_bind_mobile,
  172. message: t('mobilePlaceholder'),
  173. trigger: ['blur', 'change'],
  174. },
  175. {
  176. validator(rule: any, value: string, callback: any) {
  177. if (type.value != 'mobile' && !configStore.login.is_bind_mobile) return true
  178. else return test.mobile(value)
  179. },
  180. message: t('mobileError'),
  181. trigger: ['change', 'blur'],
  182. }
  183. ],
  184. 'mobile_code': {
  185. type: 'string',
  186. required: type.value == 'mobile' || configStore.login.is_bind_mobile,
  187. message: t('codePlaceholder'),
  188. trigger: ['blur', 'change']
  189. },
  190. 'captcha_code': {
  191. type: 'string',
  192. required: type.value == 'username',
  193. message: t('captchaPlaceholder'),
  194. trigger: ['blur', 'change'],
  195. }
  196. }
  197. })
  198. const formRef = ref<FormInstance>()
  199. const handleRegister = async () => {
  200. await formRef.value?.validate(async (valid, fields) => {
  201. if (valid) {
  202. if (loading.value) return
  203. loading.value = true
  204. const register = type.value == 'username' ? usernameRegister : mobileRegister
  205. register(formData).then((res: responseResult) => {
  206. memberStore.setToken(res.data.token)
  207. memberStore.logClose()
  208. }).catch(() => {
  209. loading.value = false
  210. captcha.refresh()
  211. })
  212. }
  213. })
  214. }
  215. let show = ref(false)
  216. const wechatCheckFn = () =>{
  217. wechatCheck().then((res:any) =>{
  218. show.value = res.data
  219. })
  220. }
  221. wechatCheckFn()
  222. // 验证码
  223. const captcha = useCaptcha(formData)
  224. captcha.refresh()
  225. // 获取手机验证码
  226. const smsCodeRef = ref<AnyObject | null>(null)
  227. const sendSmsCode = async () => {
  228. await formRef.value?.validateField('mobile', async (valid, fields) => {
  229. if (valid) {
  230. smsCodeRef.value?.send()
  231. }
  232. })
  233. }
  234. //去登录
  235. const emit = defineEmits(['typeChange'])
  236. const typeChange = ()=>{
  237. emit('typeChange','login')
  238. }
  239. const real_name_input = ref(true)
  240. const password_input = ref(true)
  241. const confirm_password_input = ref(true)
  242. </script>
  243. <style lang="scss" scoped>
  244. </style>