LoginFormInputCode.vue 8.9 KB

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