LoginForm.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <div class="login-box">
  3. <div class="center">
  4. <!-- <LoginFormTitle v-show="getShow" class="enter-x" /> -->
  5. <Form
  6. class="p-4 enter-x"
  7. :model="formData"
  8. :rules="getFormRules"
  9. ref="formRef"
  10. v-show="getShow"
  11. @keypress.enter="handleLogin"
  12. autocomplete="off"
  13. >
  14. <FormItem name="account" class="enter-x">
  15. <div class="input-box">
  16. <Input size="large" v-model:value="formData.account" :placeholder="t('sys.login.userName')" class="fix-auto-fill" />
  17. </div>
  18. </FormItem>
  19. <FormItem name="password" class="enter-x">
  20. <div class="input-box">
  21. <InputPassword size="large" visibilityToggle v-model:value="formData.password" :placeholder="t('sys.login.password')" />
  22. </div>
  23. </FormItem>
  24. </Form>
  25. <div class="btn-box">
  26. <div class="btn" @click="handleLogin"> {{ t('sys.login.loginButton') }}</div>
  27. </div>
  28. </div>
  29. </div>
  30. </template>
  31. <script lang="ts" setup>
  32. import { reactive, ref, toRaw, unref, computed, onMounted } from 'vue';
  33. import { Checkbox, Form, Input, Row, Col, Button } from 'ant-design-vue';
  34. import { createFromIconfontCN } from '@ant-design/icons-vue';
  35. import { useI18n } from '/@/hooks/web/useI18n';
  36. import { useMessage } from '/@/hooks/web/useMessage';
  37. import { useUserStore } from '/@/store/modules/user';
  38. import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin';
  39. import { useDesign } from '/@/hooks/web/useDesign';
  40. import { getCodeInfo } from '/@/api/sys/user';
  41. //import { onKeyStroke } from '@vueuse/core';
  42. const ACol = Col;
  43. const ARow = Row;
  44. const FormItem = Form.Item;
  45. const InputPassword = Input.Password;
  46. const IconFont = createFromIconfontCN({
  47. scriptUrl: '//at.alicdn.com/t/font_2316098_umqusozousr.js',
  48. });
  49. const { t } = useI18n();
  50. const { notification, createErrorModal } = useMessage();
  51. const { prefixCls } = useDesign('login');
  52. const userStore = useUserStore();
  53. const { setLoginState, getLoginState } = useLoginState();
  54. const { getFormRules } = useFormRules();
  55. const formRef = ref();
  56. const thirdModalRef = ref();
  57. const loading = ref(false);
  58. const rememberMe = ref(false);
  59. const formData = reactive({
  60. account: '',
  61. password: '',
  62. inputCode: '',
  63. });
  64. const randCodeData = reactive({
  65. randCodeImage: '',
  66. requestCodeSuccess: false,
  67. checkKey: null,
  68. });
  69. const { validForm } = useFormValid(formRef);
  70. //onKeyStroke('Enter', handleLogin);
  71. const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
  72. async function handleLogin() {
  73. const data = await validForm();
  74. if (!data) return;
  75. try {
  76. loading.value = true;
  77. const { userInfo } = await userStore.login(
  78. toRaw({
  79. password: data.password,
  80. username: data.account,
  81. captcha: data.inputCode,
  82. checkKey: randCodeData.checkKey,
  83. mode: 'none', //不要默认的错误提示
  84. })
  85. );
  86. if (userInfo) {
  87. notification.success({
  88. message: t('sys.login.loginSuccessTitle'),
  89. description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realname}`,
  90. duration: 3,
  91. });
  92. }
  93. } catch (error) {
  94. notification.error({
  95. message: t('sys.api.errorTip'),
  96. description: error.message || t('sys.api.networkExceptionMsg'),
  97. duration: 3,
  98. });
  99. loading.value = false;
  100. //update-begin-author:taoyan date:2022-5-3 for: issues/41 登录页面,当输入验证码错误时,验证码图片要刷新一下,而不是保持旧的验证码图片不变
  101. handleChangeCheckCode();
  102. //update-end-author:taoyan date:2022-5-3 for: issues/41 登录页面,当输入验证码错误时,验证码图片要刷新一下,而不是保持旧的验证码图片不变
  103. }
  104. }
  105. function handleChangeCheckCode() {
  106. formData.inputCode = '';
  107. //TODO 兼容mock和接口,暂时这样处理
  108. randCodeData.checkKey = 1629428467008; //new Date().getTime();
  109. getCodeInfo(randCodeData.checkKey).then((res) => {
  110. randCodeData.randCodeImage = res;
  111. randCodeData.requestCodeSuccess = true;
  112. });
  113. }
  114. /**
  115. * 第三方登录
  116. * @param type
  117. */
  118. function onThirdLogin(type) {
  119. thirdModalRef.value.onThirdLogin(type);
  120. }
  121. //初始化验证码
  122. onMounted(() => {
  123. handleChangeCheckCode();
  124. });
  125. </script>
  126. <style lang="less" scoped>
  127. @ventSpace: zxm;
  128. .login-box {
  129. position: relative;
  130. margin-top: 10px;
  131. :deep(.@{ventSpace}-form-item) {
  132. .@{ventSpace}-input-affix-wrapper-focused,
  133. .@{ventSpace}-form-item-control-input-content,
  134. .@{ventSpace}-input,
  135. .@{ventSpace}-input-password {
  136. color: #fff !important;
  137. background: #ffffff00 !important;
  138. border: none !important;
  139. box-shadow: none !important;
  140. font-size: 28px !important;
  141. &:focus,
  142. &:active,
  143. &:hover {
  144. color: #fff !important;
  145. border: none !important;
  146. box-shadow: none !important;
  147. }
  148. }
  149. .@{ventSpace}-input-affix-wrapper {
  150. padding: 0 !important;
  151. }
  152. }
  153. :deep(.@{ventSpace}-input-password) {
  154. input {
  155. padding: 4px 11px;
  156. padding-left: 20px !important;
  157. margin-left: 20px !important;
  158. text-align: center;
  159. }
  160. }
  161. :deep(.@{ventSpace}-form-item-control-input-content) {
  162. display: flex;
  163. justify-content: center;
  164. }
  165. .input-box {
  166. width: 983px;
  167. height: 96px;
  168. border: none !important;
  169. text-align: center;
  170. padding-top: 30px !important;
  171. padding-left: 20px !important;
  172. background-color: transparent !important;
  173. background-size: 100% auto;
  174. background: url('/@/assets/images/vent/login/input-normal.png') !important;
  175. &:focus,
  176. &:active {
  177. background: #ffffff00 !important;
  178. color: #fff !important;
  179. border: none !important;
  180. box-shadow: none !important;
  181. }
  182. &:focus {
  183. background: url('/@/assets/images/vent/login/input-down.png') !important;
  184. }
  185. :deep(.@{ventSpace}-input) {
  186. width: 100%;
  187. text-align: center;
  188. &:-webkit-autofill,
  189. &:-webkit-autofill:hover,
  190. &:-webkit-autofill:focus,
  191. &:-webkit-autofill:active {
  192. -webkit-transition-delay: 99999s;
  193. -webkit-transition:
  194. color 99999s ease-out,
  195. background-color 99999s ease-out;
  196. color: #fff;
  197. }
  198. }
  199. }
  200. .btn-box {
  201. width: 100%;
  202. position: relative;
  203. top: 40px;
  204. left: 0px;
  205. display: flex;
  206. justify-content: center;
  207. align-items: center;
  208. cursor: pointer;
  209. .btn {
  210. color: #fff;
  211. display: flex;
  212. justify-content: center;
  213. align-items: center;
  214. font-size: 28px;
  215. padding-top: 20px;
  216. width: 562px;
  217. height: 137px;
  218. background: url('/@/assets/images/vent/login/btn-bg.png');
  219. background: 100% auto;
  220. &:active {
  221. background: url('/@/assets/images/vent/login/btn-bg-hover.png');
  222. }
  223. }
  224. }
  225. }
  226. </style>