index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. <template>
  2. <div class="login-container">
  3. <el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
  4. <div class="title-container">
  5. <h3 class="title">{{ $t('login.title') }}</h3>
  6. <lang-select class="set-language" />
  7. </div>
  8. <el-form-item prop="username">
  9. <span class="svg-container">
  10. <svg-icon icon-class="user" />
  11. </span>
  12. <el-input
  13. ref="username"
  14. v-model="loginForm.username"
  15. :placeholder="$t('login.username')"
  16. name="username"
  17. type="text"
  18. tabindex="1"
  19. auto-complete="on"
  20. />
  21. </el-form-item>
  22. <el-form-item prop="password">
  23. <span class="svg-container">
  24. <svg-icon icon-class="password" />
  25. </span>
  26. <el-input
  27. ref="passwordRef"
  28. :key="passwordType"
  29. v-model="loginForm.password"
  30. :type="passwordType"
  31. :placeholder="$t('login.password')"
  32. name="password"
  33. tabindex="2"
  34. auto-complete="on"
  35. @keyup.enter="handleLogin"
  36. />
  37. <span class="show-pwd" @click="showPwd">
  38. <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
  39. </span>
  40. </el-form-item>
  41. <el-button size="default" :loading="loading" type="primary" style="width: 100%; margin-bottom: 30px" @click.prevent="handleLogin"
  42. >{{ $t('login.login') }}
  43. </el-button>
  44. </el-form>
  45. </div>
  46. </template>
  47. <script setup lang="ts">
  48. import { reactive, ref, toRefs, watch, nextTick } from 'vue'
  49. // 组件依赖
  50. import LangSelect from '@/components/LangSelect/index.vue'
  51. // 状态管理依赖
  52. import useStore from '@/store'
  53. // API依赖
  54. // import { getGeetConfig } from '@/api/login'
  55. import { useRoute } from 'vue-router'
  56. const { user } = useStore()
  57. const route = useRoute()
  58. const loginFormRef = ref(/*ElForm*/)
  59. const passwordRef = ref(/*ElInput*/)
  60. const state = reactive({
  61. loginForm: {
  62. username: 'admin',
  63. password: '100607'
  64. },
  65. loginRules: {
  66. username: [{ required: true, message: '用户名不能为空', trigger: 'blur' }],
  67. password: [{ required: true, message: '密码不能为空', trigger: 'blur' }]
  68. },
  69. loading: false,
  70. passwordType: 'password'
  71. })
  72. const { loginForm, loginRules, loading, passwordType } = toRefs(state)
  73. function showPwd() {
  74. if (state.passwordType === 'password') {
  75. state.passwordType = ''
  76. } else {
  77. state.passwordType = 'password'
  78. }
  79. nextTick(() => {
  80. passwordRef.value.focus()
  81. })
  82. }
  83. function handleLogin() {
  84. loginFormRef.value.validate((valid: boolean) => {
  85. if (valid) {
  86. state.loading = true
  87. user.login(state.loginForm).finally(() => {
  88. state.loading = false
  89. })
  90. }
  91. })
  92. }
  93. watch(
  94. route,
  95. () => {
  96. const query = route.query
  97. user.$patch({
  98. loginQuery: query
  99. })
  100. },
  101. {
  102. immediate: true
  103. }
  104. )
  105. </script>
  106. <style lang="scss">
  107. /* 修复input 背景不协调 和光标变色 */
  108. /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
  109. $bg: #283443;
  110. $light_gray: #fff;
  111. $cursor: #fff;
  112. /* reset element-plus css */
  113. .login-container {
  114. .title-container {
  115. position: relative;
  116. .title {
  117. font-size: 26px;
  118. color: $light_gray;
  119. margin: 0px auto 40px auto;
  120. text-align: center;
  121. font-weight: bold;
  122. }
  123. .set-language {
  124. color: #fff;
  125. position: absolute;
  126. top: 3px;
  127. font-size: 18px;
  128. right: 0px;
  129. cursor: pointer;
  130. }
  131. }
  132. //.localFormItem {
  133. //}
  134. //.el-form-item.localFormItem {
  135. .el-form-item:nth-child(2),
  136. .el-form-item:nth-child(3) {
  137. border: 1px solid rgba(255, 255, 255, 0.1);
  138. background: rgba(0, 0, 0, 0.1);
  139. border-radius: 5px;
  140. color: #454545;
  141. .el-input {
  142. display: inline-block;
  143. height: 47px;
  144. width: 85%;
  145. .el-input__wrapper {
  146. padding: 0;
  147. background: transparent;
  148. box-shadow: none;
  149. .el-input__inner {
  150. background: transparent;
  151. border: 0px;
  152. -webkit-appearance: none;
  153. border-radius: 0px;
  154. padding: 12px 5px 12px 15px;
  155. color: $light_gray;
  156. height: 47px;
  157. caret-color: $cursor;
  158. &:-webkit-autofill {
  159. box-shadow: 0 0 0px 1000px $bg inset !important;
  160. -webkit-text-fill-color: $cursor !important;
  161. }
  162. }
  163. }
  164. }
  165. .el-input__inner {
  166. &:hover {
  167. border-color: var(--el-input-hover-border, var(--el-border-color-hover));
  168. box-shadow: none;
  169. }
  170. box-shadow: none;
  171. }
  172. }
  173. .gt_float {
  174. padding: 8px 0;
  175. }
  176. .copyright {
  177. width: 100%;
  178. position: absolute;
  179. bottom: 0;
  180. font-size: 12px;
  181. text-align: center;
  182. color: #cccccc;
  183. }
  184. }
  185. //// 极验证样式
  186. //#captcha .gt_holder {
  187. // &.gt_float {
  188. // width: 100%;
  189. // }
  190. // .gt_slider {
  191. // //width: 100%;
  192. // width: calc(100% - 42px);
  193. // }
  194. // .gt_guide_tip {
  195. // width: calc(100% - 42px);
  196. // }
  197. //}
  198. </style>
  199. <style lang="scss" scoped>
  200. $bg: #2d3a4b;
  201. $dark_gray: #889aa4;
  202. $light_gray: #eee;
  203. .login-container {
  204. min-height: 100%;
  205. width: 100%;
  206. background-color: $bg;
  207. overflow: hidden;
  208. .login-form {
  209. position: relative;
  210. //width: 520px;
  211. width: 374px;
  212. max-width: 100%;
  213. padding: 160px 35px 0;
  214. margin: 0 auto;
  215. overflow: hidden;
  216. position: absolute;
  217. top: 40%;
  218. left: 50%;
  219. transform: translate(-50%, -50%);
  220. }
  221. .tips {
  222. font-size: 14px;
  223. color: #fff;
  224. margin-bottom: 10px;
  225. span {
  226. &:first-of-type {
  227. margin-right: 16px;
  228. }
  229. }
  230. }
  231. .svg-container {
  232. padding: 6px 5px 6px 15px;
  233. color: $dark_gray;
  234. vertical-align: middle;
  235. width: 30px;
  236. display: inline-block;
  237. }
  238. .title-container {
  239. position: relative;
  240. .title {
  241. font-size: 26px;
  242. color: $light_gray;
  243. margin: 0px auto 40px auto;
  244. text-align: center;
  245. font-weight: bold;
  246. }
  247. }
  248. .show-pwd {
  249. position: absolute;
  250. right: 10px;
  251. top: 12px;
  252. font-size: 16px;
  253. color: $dark_gray;
  254. cursor: pointer;
  255. user-select: none;
  256. }
  257. }
  258. </style>