LoginForm.vue 8.2 KB

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