login.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <template>
  2. <ie-page bgColor="white">
  3. <ie-navbar title="" :placeholder="false" bgColor="transparent" />
  4. <ie-image :is-oss="true" src="/login-bg.png" custom-class="w-full min-h-350 absolute top-0 left-0 z-1" />
  5. <ie-image :is-oss="true" src="/login-title.png" custom-class="w-auto h-96 mx-auto mt-240" mode="heightFix" />
  6. <view class="relative z-2 mx-46 mt-178">
  7. <view class="ml-18 flex items-center">
  8. <view class="text-32" :class="{ 'is-active': loginType === 'phone' }" @click="changeLoginType('phone')">
  9. 手机号登录
  10. </view>
  11. <view class="w-1 h-30 mx-24 bg-fore-light"></view>
  12. <view class="text-32" :class="{ 'is-active': loginType === 'card' }" @click="changeLoginType('card')">
  13. 会员卡登录
  14. </view>
  15. </view>
  16. <view class="mt-46">
  17. <view v-show="loginType === 'phone'">
  18. <ie-input custom-class="mt-28" type="number" :maxlength="11" v-model="phone" placeholder="请输入手机号" />
  19. <ie-input custom-class="mt-28" type="number" :maxlength="6" v-model="password" placeholder="请输入验证码">
  20. <ie-sms :phone="phone" :sms-api-type="EnumSmsApiType.NO_VALIDATION_NO_TOKEN" @send="handleSendSuccess" />
  21. </ie-input>
  22. </view>
  23. <view v-show="loginType === 'card'">
  24. <ie-input custom-class="mt-28" type="number" :maxlength="8" v-model="cardNo" placeholder="请输入卡号" />
  25. <ie-input custom-class="mt-28" type="number" :password="!showPassword" :maxlength="6" v-model="cardPassword"
  26. placeholder="请输入密码">
  27. <cover-view class="w-60 h-60 flex items-center justify-center" @click="toggleShowPassword">
  28. <cover-image v-show="!showPassword" src="@/pagesSystem/static/image/icon/icon-eye.png" mode="widthFix"
  29. class="w-44 h-44" />
  30. <cover-image v-show="showPassword" src="@/pagesSystem/static/image/icon/icon-eye-off.png" mode="widthFix"
  31. class="w-44 h-44" />
  32. </cover-view>
  33. </ie-input>
  34. </view>
  35. <view class="mt-42 ml-26 h-28">
  36. <uv-checkbox-group v-if="loginType === 'card'" v-model="rememberPassword">
  37. <uv-checkbox :name="true" label="记住密码" :labelSize="15" :iconSize="14" labelColor="#666666"></uv-checkbox>
  38. </uv-checkbox-group>
  39. </view>
  40. </view>
  41. <view class="mt-84">
  42. <ie-button @click="handleLogin">登录</ie-button>
  43. </view>
  44. <view class="mt-42 ml-26">
  45. <uv-checkbox-group v-model="agreePrivacy">
  46. <uv-checkbox name="true" shape="circle" label="记住密码" :labelSize="14" :iconSize="13" labelColor="#666666">
  47. <text class="text-28 text-fore-subcontent">已阅读并同意<text class="text-primary"
  48. @click.stop="handleAgreePrivacy('user')">《用户协议》</text>和<text class="text-primary"
  49. @click.stop="handleAgreePrivacy('privacy')">《隐私政策》</text></text>
  50. </uv-checkbox>
  51. </uv-checkbox-group>
  52. </view>
  53. </view>
  54. <ie-captcha ref="captchaRef" v-model:code="code" v-model:uuid="uuid" @valid="handleValid" />
  55. </ie-page>
  56. </template>
  57. <script lang="ts" setup>
  58. import ieCaptcha from '@/components/ie-sms/ie-captcha.vue';
  59. import { useUserStore } from '@/store/userStore';
  60. import { useTransferPage } from '@/hooks/useTransferPage';
  61. import { validatePhone } from '@/hooks/useValidation';
  62. import { verifyCard } from '@/api/modules/user';
  63. import { EnumBindScene, EnumSmsApiType } from '@/common/enum';
  64. import { login } from '@/api/modules/login';
  65. import { LoginRequestDTO, MobileLoginResponseDTO } from '@/types/user';
  66. const { transferBack, transferTo } = useTransferPage();
  67. const userStore = useUserStore();
  68. const loginType = ref('phone');
  69. const phone = ref('');
  70. const password = ref('');
  71. const cardNo = ref('');
  72. const cardPassword = ref('');
  73. const code = ref('');
  74. const uuid = ref('');
  75. const showPassword = ref(false);
  76. const rememberPassword = ref([false]);
  77. const agreePrivacy = ref([false]);
  78. const changeLoginType = (type: string) => {
  79. loginType.value = type;
  80. }
  81. const handleAgreePrivacy = (type: string) => {
  82. if (type === 'user') {
  83. transferTo('/pagesOther/pages/h5/h5', {
  84. data: {
  85. title: '用户协议',
  86. url: 'https://www.dz1kt.com/admin/protocol/mxjb_user_IE.html'
  87. }
  88. });
  89. } else if (type === 'privacy') {
  90. transferTo('/pagesOther/pages/h5/h5', {
  91. data: {
  92. title: '隐私政策',
  93. url: 'https://www.dz1kt.com/admin/protocol/mxjb_privacy_IE.html'
  94. }
  95. });
  96. }
  97. }
  98. const handleSendSuccess = (_phone: string, _code: string, _uuid: string) => {
  99. console.log('短信发送成功', _phone, _code, _uuid);
  100. code.value = _code;
  101. uuid.value = _uuid;
  102. }
  103. const toggleShowPassword = () => {
  104. showPassword.value = !showPassword.value;
  105. }
  106. const loginValidate = () => {
  107. if (loginType.value === 'phone') {
  108. if (!validatePhone(phone.value)) {
  109. uni.$ie.showToast('请输入正确的手机号');
  110. return false;
  111. }
  112. if (!password.value) {
  113. uni.$ie.showToast('请输入验证码');
  114. return false;
  115. }
  116. } else if (loginType.value === 'card') {
  117. if (!cardNo.value || !cardNo.value.trim()) {
  118. uni.$ie.showToast('请输入卡号');
  119. return false;
  120. }
  121. if (!cardPassword.value || !cardPassword.value.trim()) {
  122. uni.$ie.showToast('请输入密码');
  123. return false;
  124. }
  125. }
  126. if (!agreePrivacy.value[0]) {
  127. uni.$ie.showToast('请先阅读并同意用户协议和隐私政策');
  128. return false;
  129. }
  130. return true;
  131. }
  132. const captchaRef = ref();
  133. const handleLogin = async () => {
  134. if (!loginValidate()) {
  135. return;
  136. }
  137. if (loginType.value === 'phone') {
  138. submitLogin();
  139. } else if (loginType.value === 'card') {
  140. captchaRef.value.open();
  141. userStore.rememberLoginInfo(!!rememberPassword.value[0], cardNo.value, cardPassword.value);
  142. // submitLogin();
  143. }
  144. }
  145. const submitLogin = async () => {
  146. const params: LoginRequestDTO = {
  147. code: code.value,
  148. uuid: uuid.value
  149. };
  150. if (loginType.value === 'phone') {
  151. params.mobile = phone.value;
  152. params.password = password.value;
  153. handleMobileLogin(params);
  154. } else if (loginType.value === 'card') {
  155. params.username = cardNo.value;
  156. params.password = cardPassword.value;
  157. handleCardLogin(params);
  158. }
  159. }
  160. const handleMobileLogin = async (params: LoginRequestDTO) => {
  161. uni.$ie.showLoading();
  162. login(params).then((res) => {
  163. uni.$ie.hideLoading();
  164. if (res.data) {
  165. const { code, message } = res.data;
  166. if (code === 101) {
  167. console.log('registerInfo:', params)
  168. // 账号不存在,需要注册
  169. transferTo('/pagesSystem/pages/bind-profile/bind-profile', {
  170. data: {
  171. scene: EnumBindScene.REGISTER,
  172. userInfo: {},
  173. cardInfo: {},
  174. registerInfo: {
  175. ...params
  176. }
  177. }
  178. });
  179. }
  180. } else {
  181. if (res.token) {
  182. userStore.login(res.token).then((success: boolean) => {
  183. if (success) {
  184. transferBack(true);
  185. } else {
  186. uni.$ie.showToast('登录失败')
  187. }
  188. });
  189. }
  190. }
  191. }).catch(err => {
  192. console.log('登录失败', err)
  193. })
  194. }
  195. const handleCardLogin = (params: LoginRequestDTO) => {
  196. uni.$ie.showLoading();
  197. login(params).then(res => {
  198. if (res.token) {
  199. userStore.login(res.token).then((success: boolean) => {
  200. uni.$ie.hideLoading();
  201. if (success) {
  202. transferBack(true);
  203. } else {
  204. uni.$ie.showToast('登录失败')
  205. }
  206. });
  207. } else if (res.data.code === 101) {
  208. //
  209. verifyCard(cardNo.value, cardPassword.value).then(res => {
  210. console.log('卡信息:', res)
  211. uni.$ie.hideLoading();
  212. if (res.data) {
  213. console.log('registerInfo:', params)
  214. transferTo('/pagesSystem/pages/phone-verify/phone-verify', {
  215. data: {
  216. scene: EnumBindScene.REGISTER,
  217. userInfo: {},
  218. cardInfo: res.data,
  219. registerInfo: params
  220. }
  221. });
  222. }
  223. }).catch(err => {
  224. console.log('验证会员卡失败', err);
  225. })
  226. }
  227. }).catch(err => {
  228. uni.$ie.hideLoading();
  229. console.log('登录失败', err)
  230. });
  231. }
  232. const handleValid = (data: { code: string; uuid: string }) => {
  233. console.log(code.value, uuid.value);
  234. captchaRef.value.close();
  235. submitLogin();
  236. }
  237. onLoad(() => {
  238. rememberPassword.value[0] = userStore.rememberPwd;
  239. if (userStore.rememberPwd) {
  240. cardNo.value = userStore.cardNo;
  241. cardPassword.value = userStore.cardPassword;
  242. }
  243. });
  244. </script>
  245. <style lang="scss" scoped>
  246. .is-active {
  247. @apply text-primary font-[800];
  248. }
  249. </style>