Login.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <div class="login-container">
  3. <div class="login-card">
  4. <div class="login-header">
  5. <h1>实验室安全智能监测与管控中心</h1>
  6. <p>中国安全生产科学研究院</p>
  7. </div>
  8. <el-form
  9. ref="loginForm"
  10. :model="loginForm"
  11. :rules="loginRules"
  12. class="login-form"
  13. >
  14. <el-form-item prop="account">
  15. <el-input
  16. v-model="loginForm.account"
  17. placeholder="请输入用户名/手机号"
  18. prefix-icon="el-icon-user"
  19. />
  20. </el-form-item>
  21. <el-form-item prop="password">
  22. <el-input
  23. v-model="loginForm.password"
  24. type="password"
  25. placeholder="请输入密码"
  26. prefix-icon="el-icon-lock"
  27. show-password
  28. @keyup.enter.native="handleLogin"
  29. />
  30. </el-form-item>
  31. <el-form-item prop="captcha">
  32. <div class="captcha-row">
  33. <el-input
  34. v-model="loginForm.captcha"
  35. placeholder="请输入验证码"
  36. prefix-icon="el-icon-key"
  37. />
  38. <div class="captcha-img" @click="refreshCaptcha">
  39. {{ captchaText }}
  40. </div>
  41. </div>
  42. </el-form-item>
  43. <el-form-item>
  44. <el-button
  45. type="primary"
  46. :loading="loading"
  47. class="login-btn"
  48. @click="handleLogin"
  49. >
  50. 登 录
  51. </el-button>
  52. </el-form-item>
  53. </el-form>
  54. </div>
  55. </div>
  56. </template>
  57. <script>
  58. import md5 from 'js-md5'
  59. import { loginApi } from '@/api/auth'
  60. export default {
  61. name: 'Login',
  62. data() {
  63. return {
  64. loginForm: {
  65. account: '',
  66. password: '',
  67. captcha: ''
  68. },
  69. loginRules: {
  70. account: [
  71. { required: true, message: '请输入用户名', trigger: 'blur' }
  72. ],
  73. password: [
  74. { required: true, message: '请输入密码', trigger: 'blur' }
  75. ],
  76. captcha: [
  77. { required: true, message: '请输入验证码', trigger: 'blur' }
  78. ]
  79. },
  80. loading: false,
  81. captchaText: '0000',
  82. captchaUuid: 'captcha-uuid-default'
  83. }
  84. },
  85. methods: {
  86. refreshCaptcha() {
  87. this.captchaText = '0000'
  88. },
  89. handleLogin() {
  90. this.$refs.loginForm.validate(async (valid) => {
  91. if (!valid) return
  92. this.loading = true
  93. try {
  94. const res = await loginApi({
  95. account: this.loginForm.account,
  96. password: md5(this.loginForm.password),
  97. code: this.loginForm.captcha,
  98. uuid: this.captchaUuid
  99. })
  100. if (res.code === 200) {
  101. this.$store.dispatch('login', res.data.token)
  102. this.$message.success('登录成功')
  103. this.$router.push('/screen')
  104. } else {
  105. this.$message.error(res.message || '登录失败')
  106. }
  107. } catch (err) {
  108. // 错误已由拦截器处理
  109. } finally {
  110. this.loading = false
  111. }
  112. })
  113. }
  114. }
  115. }
  116. </script>
  117. <style lang="scss" scoped>
  118. .login-container {
  119. width: 100%;
  120. height: 100%;
  121. display: flex;
  122. align-items: center;
  123. justify-content: center;
  124. background: linear-gradient(135deg, #0a1a3a 0%, #0d2b5e 50%, #0a1a3a 100%);
  125. position: relative;
  126. &::before {
  127. content: '';
  128. position: absolute;
  129. top: 0;
  130. left: 0;
  131. right: 0;
  132. bottom: 0;
  133. background:
  134. radial-gradient(ellipse at 20% 50%, rgba(0, 100, 200, 0.15) 0%, transparent 50%),
  135. radial-gradient(ellipse at 80% 50%, rgba(0, 150, 255, 0.1) 0%, transparent 50%);
  136. pointer-events: none;
  137. }
  138. }
  139. .login-card {
  140. width: 480px;
  141. padding: 48px 40px;
  142. background: rgba(8, 30, 65, 0.9);
  143. border: 1px solid rgba(46, 120, 210, 0.4);
  144. border-radius: 12px;
  145. backdrop-filter: blur(10px);
  146. z-index: 1;
  147. }
  148. .login-header {
  149. text-align: center;
  150. margin-bottom: 40px;
  151. h1 {
  152. font-size: 24px;
  153. color: $cyan;
  154. margin-bottom: 8px;
  155. letter-spacing: 2px;
  156. }
  157. p {
  158. font-size: 14px;
  159. color: $text-dim;
  160. }
  161. }
  162. .login-form {
  163. ::v-deep .el-input__inner {
  164. background: rgba(6, 40, 90, 0.6);
  165. border: 1px solid rgba(46, 120, 210, 0.3);
  166. color: #fff;
  167. height: 44px;
  168. &::placeholder {
  169. color: rgba(140, 180, 230, 0.5);
  170. }
  171. &:focus {
  172. border-color: $cyan;
  173. }
  174. }
  175. ::v-deep .el-input__prefix {
  176. color: $cyan;
  177. }
  178. }
  179. .captcha-row {
  180. display: flex;
  181. gap: 12px;
  182. .el-input {
  183. flex: 1;
  184. }
  185. .captcha-img {
  186. width: 120px;
  187. height: 44px;
  188. background: rgba(6, 40, 90, 0.8);
  189. border: 1px solid rgba(46, 120, 210, 0.3);
  190. border-radius: 4px;
  191. display: flex;
  192. align-items: center;
  193. justify-content: center;
  194. font-size: 20px;
  195. color: $cyan;
  196. letter-spacing: 8px;
  197. cursor: pointer;
  198. user-select: none;
  199. }
  200. }
  201. .login-btn {
  202. width: 100%;
  203. height: 44px;
  204. font-size: 16px;
  205. background: linear-gradient(90deg, #1890ff, #00e5ff);
  206. border: none;
  207. letter-spacing: 8px;
  208. &:hover {
  209. opacity: 0.9;
  210. }
  211. }
  212. </style>