| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- <template>
- <div class="login-container">
- <div class="login-card">
- <!-- 页头 Logo -->
- <div class="login-header">
- <i class="el-icon-cpu logo-icon"></i>
- <h2>设备管理系统</h2>
- <p>后台管理平台</p>
- </div>
- <!-- 登录表单 -->
- <el-form
- ref="loginForm"
- :model="loginForm"
- :rules="loginRules"
- class="login-form"
- @keyup.enter.native="handleLogin"
- >
- <el-form-item prop="username">
- <el-input
- v-model="loginForm.username"
- prefix-icon="el-icon-user"
- placeholder="用户名"
- clearable
- />
- </el-form-item>
- <el-form-item prop="password">
- <el-input
- v-model="loginForm.password"
- prefix-icon="el-icon-lock"
- placeholder="密码"
- type="password"
- show-password
- clearable
- />
- </el-form-item>
- <el-form-item prop="captcha">
- <el-row :gutter="10">
- <el-col :span="16">
- <el-input
- v-model="loginForm.captcha"
- prefix-icon="el-icon-key"
- placeholder="请输入验证码"
- />
- </el-col>
- <el-col :span="8">
- <div class="captcha-wrap" @click="loadCaptcha" title="点击刷新验证码">
- <img
- v-if="captchaImage"
- :src="captchaImage"
- class="captcha-img"
- alt="验证码"
- />
- <span v-else class="captcha-placeholder">加载中...</span>
- </div>
- </el-col>
- </el-row>
- </el-form-item>
- <el-form-item>
- <el-button
- type="primary"
- class="login-btn"
- :loading="loading"
- @click="handleLogin"
- >
- {{ loading ? '登录中...' : '登 录' }}
- </el-button>
- </el-form-item>
- </el-form>
- </div>
- </div>
- </template>
- <script>
- import md5 from 'js-md5'
- import { getCaptcha } from '@/api/auth'
- export default {
- name: 'Login',
- data() {
- return {
- loginForm: {
- username: '',
- password: '',
- captcha: ''
- },
- captchaKey: '', // 后端返回的验证码 key
- captchaImage: '', // Base64 验证码图片
- loading: false,
- loginRules: {
- username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
- password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
- captcha: [{ required: true, message: '请输入验证码', trigger: 'blur' }]
- }
- }
- },
- created() {
- this.loadCaptcha()
- },
- methods: {
- async loadCaptcha() {
- try {
- const res = await getCaptcha()
- this.captchaKey = res.data.captchaKey
- this.captchaImage = res.data.captchaImage
- this.loginForm.captcha = ''
- } catch {
- // 加载失败时保持旧图片
- }
- },
- handleLogin() {
- this.$refs.loginForm.validate(async valid => {
- if (!valid) return
- this.loading = true
- try {
- await this.$store.dispatch('user/login', {
- username: this.loginForm.username,
- password: md5(this.loginForm.password),
- captchaKey: this.captchaKey,
- captchaCode: this.loginForm.captcha
- })
- const redirect = this.$route.query.redirect || '/role'
- this.$router.push(redirect)
- this.$message.success('登录成功,欢迎回来!')
- } catch (err) {
- // 登录失败后刷新验证码
- this.loadCaptcha()
- this.$message.error(err.message || '登录失败,请重试')
- } finally {
- this.loading = false
- }
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .login-container {
- width: 100%;
- height: 100vh;
- display: flex;
- align-items: center;
- justify-content: center;
- background: linear-gradient(135deg, #1a2a3a 0%, #304156 50%, #409eff 100%);
- .login-card {
- width: 420px;
- background: #fff;
- border-radius: 12px;
- padding: 40px;
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
- .login-header {
- text-align: center;
- margin-bottom: 32px;
- .logo-icon {
- font-size: 52px;
- color: #409eff;
- }
- h2 {
- margin: 12px 0 6px;
- font-size: 22px;
- color: #303133;
- font-weight: 600;
- }
- p {
- color: #909399;
- font-size: 13px;
- }
- }
- .login-form {
- .captcha-wrap {
- height: 40px;
- border: 1px solid #dcdfe6;
- border-radius: 4px;
- overflow: hidden;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- background: #f5f7fa;
- transition: border-color 0.2s;
- &:hover { border-color: #409eff; }
- .captcha-img {
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
- .captcha-placeholder {
- font-size: 12px;
- color: #909399;
- }
- }
- .login-btn {
- width: 100%;
- height: 44px;
- font-size: 16px;
- letter-spacing: 4px;
- margin-top: 8px;
- }
- }
- }
- }
- </style>
|