LoginForm.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template>
  2. <LoginFormTitle v-show="getShow" class="enter-x" />
  3. <Form
  4. class="p-4 enter-x"
  5. :model="formData"
  6. :rules="getFormRules"
  7. ref="formRef"
  8. v-show="getShow"
  9. @keypress.enter="handleLogin"
  10. >
  11. <FormItem name="account" class="enter-x">
  12. <Input size="large" v-model:value="formData.account" :placeholder="t('sys.login.userName')" />
  13. </FormItem>
  14. <FormItem name="password" class="enter-x">
  15. <InputPassword
  16. size="large"
  17. visibilityToggle
  18. v-model:value="formData.password"
  19. :placeholder="t('sys.login.password')"
  20. />
  21. </FormItem>
  22. <ARow class="enter-x">
  23. <ACol :span="12">
  24. <FormItem>
  25. <!-- No logic, you need to deal with it yourself -->
  26. <Checkbox v-model:checked="rememberMe" size="small">
  27. {{ t('sys.login.rememberMe') }}
  28. </Checkbox>
  29. </FormItem>
  30. </ACol>
  31. <ACol :span="12">
  32. <FormItem :style="{ 'text-align': 'right' }">
  33. <!-- No logic, you need to deal with it yourself -->
  34. <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
  35. {{ t('sys.login.forgetPassword') }}
  36. </Button>
  37. </FormItem>
  38. </ACol>
  39. </ARow>
  40. <FormItem class="enter-x">
  41. <Button type="primary" size="large" block @click="handleLogin" :loading="loading">
  42. {{ t('sys.login.loginButton') }}
  43. </Button>
  44. <!-- <Button size="large" class="mt-4 enter-x" block @click="handleRegister">
  45. {{ t('sys.login.registerButton') }}
  46. </Button> -->
  47. </FormItem>
  48. <ARow class="enter-x">
  49. <ACol :xs="24" :md="8">
  50. <Button block @click="setLoginState(LoginStateEnum.MOBILE)">
  51. {{ t('sys.login.mobileSignInFormTitle') }}
  52. </Button>
  53. </ACol>
  54. <ACol :md="8" :xs="24" class="!my-2 !md:my-0 xs:mx-0 md:mx-2">
  55. <Button block @click="setLoginState(LoginStateEnum.QR_CODE)">
  56. {{ t('sys.login.qrSignInFormTitle') }}
  57. </Button>
  58. </ACol>
  59. <ACol :md="7" :xs="24">
  60. <Button block @click="setLoginState(LoginStateEnum.REGISTER)">
  61. {{ t('sys.login.registerButton') }}
  62. </Button>
  63. </ACol>
  64. </ARow>
  65. <Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider>
  66. <div class="flex justify-evenly enter-x" :class="`${prefixCls}-sign-in-way`">
  67. <GithubFilled />
  68. <WechatFilled />
  69. <AlipayCircleFilled />
  70. <GoogleCircleFilled />
  71. <TwitterCircleFilled />
  72. </div>
  73. </Form>
  74. </template>
  75. <script lang="ts">
  76. import { defineComponent, reactive, ref, toRaw, unref, computed } from 'vue';
  77. import { Checkbox, Form, Input, Row, Col, Button, Divider } from 'ant-design-vue';
  78. import {
  79. GithubFilled,
  80. WechatFilled,
  81. AlipayCircleFilled,
  82. GoogleCircleFilled,
  83. TwitterCircleFilled,
  84. } from '@ant-design/icons-vue';
  85. import LoginFormTitle from './LoginFormTitle.vue';
  86. import { useI18n } from '/@/hooks/web/useI18n';
  87. import { useMessage } from '/@/hooks/web/useMessage';
  88. import { useUserStore } from '/@/store/modules/user';
  89. import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
  90. import { useDesign } from '/@/hooks/web/useDesign';
  91. //import { onKeyStroke } from '@vueuse/core';
  92. export default defineComponent({
  93. name: 'LoginForm',
  94. components: {
  95. [Col.name]: Col,
  96. [Row.name]: Row,
  97. Checkbox,
  98. Button,
  99. Form,
  100. FormItem: Form.Item,
  101. Input,
  102. Divider,
  103. LoginFormTitle,
  104. InputPassword: Input.Password,
  105. GithubFilled,
  106. WechatFilled,
  107. AlipayCircleFilled,
  108. GoogleCircleFilled,
  109. TwitterCircleFilled,
  110. },
  111. setup() {
  112. const { t } = useI18n();
  113. const { notification, createErrorModal } = useMessage();
  114. const { prefixCls } = useDesign('login');
  115. const userStore = useUserStore();
  116. const { setLoginState, getLoginState } = useLoginState();
  117. const { getFormRules } = useFormRules();
  118. const formRef = ref();
  119. const loading = ref(false);
  120. const rememberMe = ref(false);
  121. const formData = reactive({
  122. account: 'vben',
  123. password: '123456',
  124. });
  125. const { validForm } = useFormValid(formRef);
  126. //onKeyStroke('Enter', handleLogin);
  127. const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
  128. async function handleLogin() {
  129. const data = await validForm();
  130. if (!data) return;
  131. try {
  132. loading.value = true;
  133. const userInfo = await userStore.login(
  134. toRaw({
  135. password: data.password,
  136. username: data.account,
  137. mode: 'none', //不要默认的错误提示
  138. })
  139. );
  140. if (userInfo) {
  141. notification.success({
  142. message: t('sys.login.loginSuccessTitle'),
  143. description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`,
  144. duration: 3,
  145. });
  146. }
  147. } catch (error) {
  148. createErrorModal({
  149. title: t('sys.api.errorTip'),
  150. content: error.message || t('sys.api.networkExceptionMsg'),
  151. getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body,
  152. });
  153. } finally {
  154. loading.value = false;
  155. }
  156. }
  157. return {
  158. t,
  159. prefixCls,
  160. formRef,
  161. formData,
  162. getFormRules,
  163. rememberMe,
  164. handleLogin,
  165. loading,
  166. setLoginState,
  167. LoginStateEnum,
  168. getShow,
  169. };
  170. },
  171. });
  172. </script>