LoginForm.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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. @import '/@/design/theme.less';
  128. @ventSpace: zxm;
  129. @{theme-deepblue} {
  130. .login-box {
  131. --image-input-normal: url('/@/assets/images/themify/deepblue/vent/login/input-normal.png');
  132. --image-input-down: url('/@/assets/images/themify/deepblue/vent/login/input-down.png');
  133. --image-btn-bg: url('/@/assets/images/themify/deepblue/vent/login/btn-bg.png');
  134. --image-btn-bg-hover: url('/@/assets/images/themify/deepblue/vent/login/btn-bg-hover.png');
  135. }
  136. }
  137. .login-box {
  138. --image-input-normal: url('/@/assets/images/vent/login/input-normal.png');
  139. --image-input-down: url('/@/assets/images/vent/login/input-down.png');
  140. --image-btn-bg: url('/@/assets/images/vent/login/btn-bg.png');
  141. --image-btn-bg-hover: url('/@/assets/images/vent/login/btn-bg-hover.png');
  142. position: relative;
  143. margin-top: 10px;
  144. :deep(.@{ventSpace}-form-item) {
  145. .@{ventSpace}-input-affix-wrapper-focused,
  146. .@{ventSpace}-form-item-control-input-content,
  147. .@{ventSpace}-input,
  148. .@{ventSpace}-input-password {
  149. color: #fff !important;
  150. background: #ffffff00 !important;
  151. border: none !important;
  152. box-shadow: none !important;
  153. font-size: 28px !important;
  154. &:focus,
  155. &:active,
  156. &:hover {
  157. color: #fff !important;
  158. border: none !important;
  159. box-shadow: none !important;
  160. }
  161. }
  162. .@{ventSpace}-input-affix-wrapper {
  163. padding: 0 !important;
  164. }
  165. }
  166. :deep(.@{ventSpace}-input-password) {
  167. input {
  168. padding: 4px 11px;
  169. padding-left: 20px !important;
  170. margin-left: 20px !important;
  171. text-align: center;
  172. }
  173. }
  174. :deep(.@{ventSpace}-form-item-control-input-content) {
  175. display: flex;
  176. justify-content: center;
  177. }
  178. .input-box {
  179. width: 983px;
  180. height: 96px;
  181. border: none !important;
  182. text-align: center;
  183. padding-top: 30px !important;
  184. padding-left: 20px !important;
  185. background-color: transparent !important;
  186. background-size: 100% auto;
  187. background: var(--image-input-normal) !important;
  188. &:focus,
  189. &:active {
  190. background: #ffffff00 !important;
  191. color: #fff !important;
  192. border: none !important;
  193. box-shadow: none !important;
  194. }
  195. &:focus {
  196. background: var(--image-input-down) !important;
  197. }
  198. :deep(.@{ventSpace}-input) {
  199. width: 100%;
  200. text-align: center;
  201. &:-webkit-autofill,
  202. &:-webkit-autofill:hover,
  203. &:-webkit-autofill:focus,
  204. &:-webkit-autofill:active {
  205. -webkit-transition-delay: 99999s;
  206. -webkit-transition:
  207. color 99999s ease-out,
  208. background-color 99999s ease-out;
  209. color: #fff;
  210. }
  211. }
  212. }
  213. .btn-box {
  214. width: 100%;
  215. position: relative;
  216. top: 40px;
  217. left: 0px;
  218. display: flex;
  219. justify-content: center;
  220. align-items: center;
  221. cursor: pointer;
  222. .btn {
  223. color: #fff;
  224. display: flex;
  225. justify-content: center;
  226. align-items: center;
  227. font-size: 28px;
  228. padding-top: 20px;
  229. width: 562px;
  230. height: 137px;
  231. background: var(--image-btn-bg);
  232. background: 100% auto;
  233. &:active {
  234. background: var(--image-btn-bg-hover);
  235. }
  236. }
  237. }
  238. }
  239. </style>