LoginForm.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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
  13. size="large"
  14. v-model:value="formData.account"
  15. :placeholder="t('sys.login.userName')"
  16. class="fix-auto-fill"
  17. />
  18. </FormItem>
  19. <FormItem name="password" class="enter-x">
  20. <InputPassword
  21. size="large"
  22. visibilityToggle
  23. v-model:value="formData.password"
  24. :placeholder="t('sys.login.password')"
  25. />
  26. </FormItem>
  27. <ARow class="enter-x">
  28. <ACol :span="12">
  29. <FormItem name="captcha">
  30. <Input
  31. size="large"
  32. v-model:value="formData.captcha"
  33. :placeholder="t('sys.login.captcha')"
  34. class="captcha"
  35. />
  36. </FormItem>
  37. </ACol>
  38. <ACol :span="12" :style="{ 'text-align': 'right' }">
  39. <img class="captcha-img" :src="`http://192.168.0.47:8190/captcha.jpg?t=${Date.now()}`" />
  40. </ACol>
  41. </ARow>
  42. <!-- <FormItem name="drag" class="enter-x" :style="{ 'text-align': 'right' }">
  43. <BasicDragVerify
  44. ref="el3"
  45. @success="handleSuccess"
  46. text="拖动以进行校验"
  47. successText="校验成功"
  48. />
  49. </FormItem> -->
  50. <ARow class="enter-x">
  51. <ACol :span="12">
  52. <FormItem>
  53. <!-- No logic, you need to deal with it yourself -->
  54. <Checkbox v-model:checked="rememberMe" size="small">
  55. {{ t('sys.login.rememberMe') }}
  56. </Checkbox>
  57. </FormItem>
  58. </ACol>
  59. <ACol :span="12">
  60. <FormItem :style="{ 'text-align': 'right' }">
  61. <!-- No logic, you need to deal with it yourself -->
  62. <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
  63. {{ t('sys.login.forgetPassword') }}
  64. </Button>
  65. </FormItem>
  66. </ACol>
  67. </ARow>
  68. <FormItem class="enter-x">
  69. <Button type="primary" size="large" block @click="handleLogin" :loading="loading">
  70. {{ t('sys.login.loginButton') }}
  71. </Button>
  72. <!-- <Button size="large" class="mt-4 enter-x" block @click="handleRegister">
  73. {{ t('sys.login.registerButton') }}
  74. </Button> -->
  75. </FormItem>
  76. <!-- <ARow class="enter-x">
  77. <ACol :md="8" :xs="24">
  78. <Button block @click="setLoginState(LoginStateEnum.MOBILE)">
  79. {{ t('sys.login.mobileSignInFormTitle') }}
  80. </Button>
  81. </ACol>
  82. <ACol :md="8" :xs="24" class="!my-2 !md:my-0 xs:mx-0 md:mx-2">
  83. <Button block @click="setLoginState(LoginStateEnum.QR_CODE)">
  84. {{ t('sys.login.qrSignInFormTitle') }}
  85. </Button>
  86. </ACol>
  87. <ACol :md="7" :xs="24">
  88. <Button block @click="setLoginState(LoginStateEnum.REGISTER)">
  89. {{ t('sys.login.registerButton') }}
  90. </Button>
  91. </ACol>
  92. </ARow> -->
  93. <!-- <Divider class="enter-x">{{ t('sys.login.otherSignIn') }}</Divider> -->
  94. <!-- <div class="flex justify-evenly enter-x" :class="`${prefixCls}-sign-in-way`">
  95. <GithubFilled />
  96. <WechatFilled />
  97. <AlipayCircleFilled />
  98. <GoogleCircleFilled />
  99. <TwitterCircleFilled />
  100. </div> -->
  101. </Form>
  102. </template>
  103. <script lang="ts" setup>
  104. import { reactive, ref, unref, computed } from 'vue';
  105. // Divider
  106. import { Checkbox, Form, Input, Row, Col, Button } from 'ant-design-vue';
  107. // import {
  108. // GithubFilled,
  109. // WechatFilled,
  110. // AlipayCircleFilled,
  111. // GoogleCircleFilled,
  112. // TwitterCircleFilled,
  113. // } from '@ant-design/icons-vue';
  114. import LoginFormTitle from './LoginFormTitle.vue';
  115. // import { BasicDragVerify } from '/@/components/Verify/index';
  116. import { useI18n } from '/@/hooks/web/useI18n';
  117. import { useMessage } from '/@/hooks/web/useMessage';
  118. import { useUserStore } from '/@/store/modules/user';
  119. import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
  120. import { useDesign } from '/@/hooks/web/useDesign';
  121. //import { onKeyStroke } from '@vueuse/core';
  122. const ACol = Col;
  123. const ARow = Row;
  124. const FormItem = Form.Item;
  125. const InputPassword = Input.Password;
  126. const { t } = useI18n();
  127. const { notification, createErrorModal } = useMessage();
  128. const { prefixCls } = useDesign('login');
  129. const userStore = useUserStore();
  130. const { setLoginState, getLoginState } = useLoginState();
  131. const { getFormRules } = useFormRules();
  132. const formRef = ref();
  133. const loading = ref(false);
  134. const rememberMe = ref(false);
  135. // const isDragValidate = ref(false);
  136. const formData = reactive({
  137. account: '17324327132',
  138. password: 'zfb123456',
  139. // password: encodeStr(window.btoa('zfb123456')),
  140. captcha: '',
  141. });
  142. const { validForm } = useFormValid(formRef);
  143. //onKeyStroke('Enter', handleLogin);
  144. const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
  145. // function handleSuccess() {
  146. // // console.log('11');
  147. // isDragValidate.value = true;
  148. // }
  149. async function handleLogin() {
  150. const data = await validForm();
  151. if (!data) return;
  152. // if (!isDragValidate.value) {
  153. // notification.info({
  154. // message: t('sys.login.loginDragValidate'),
  155. // description: `${t('sys.login.loginAgain')}`,
  156. // duration: 3,
  157. // });
  158. // return;
  159. // }
  160. try {
  161. loading.value = true;
  162. const userInfo = await userStore.login({
  163. password: data.password,
  164. username: data.account,
  165. captcha: data.captcha,
  166. mode: 'none', //不要默认的错误提示
  167. });
  168. if (userInfo) {
  169. notification.success({
  170. message: t('sys.login.loginSuccessTitle'),
  171. description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`,
  172. duration: 3,
  173. });
  174. }
  175. } catch (error) {
  176. createErrorModal({
  177. title: t('sys.api.errorTip'),
  178. content: (error as unknown as Error).message || t('sys.api.networkExceptionMsg'),
  179. getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body,
  180. });
  181. } finally {
  182. loading.value = false;
  183. }
  184. }
  185. </script>
  186. <style>
  187. .captcha {
  188. min-width: 80px !important;
  189. }
  190. .captcha-img {
  191. height: 40px;
  192. display: inline-block;
  193. }
  194. </style>