| | |
| | | <template> |
| | | <template> |
| | | <div class="login-container"> |
| | | <el-card class="login-card"> |
| | | <h2>交通统计报表审核系统</h2> |
| | |
| | | <el-form-item prop="password"> |
| | | <el-input v-model="form.password" type="password" placeholder="密码" @keyup.enter.native="login"></el-input> |
| | | </el-form-item> |
| | | <el-form-item v-if="captchaRequired"> |
| | | <captcha3-d ref="captcha" @verified="onCaptchaVerified" @reset="onCaptchaReset"></captcha3-d> |
| | | </el-form-item> |
| | | <el-form-item v-else> |
| | | <div class="captcha-skip-tip">测试模式:行为验证码已跳过,可直接点击登录(正式发布后将启用)</div> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="login" style="width:100%">登 录</el-button> |
| | | <el-button type="primary" :loading="loggingIn" @click="login" style="width:100%">登 录</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import axios from 'axios' |
| | | import Captcha3D from '@/components/Captcha3D.vue' |
| | | |
| | | export default { |
| | | name: 'Login', |
| | | components: { Captcha3D }, |
| | | data() { |
| | | return { |
| | | form: { username: '', password: '' }, |
| | | rules: { |
| | | username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], |
| | | password: [{ required: true, message: '请输入密码', trigger: 'blur' }] |
| | | } |
| | | }, |
| | | captchaVerified: false, |
| | | captchaId: '', |
| | | clickIds: [], |
| | | loggingIn: false, |
| | | captchaRequired: true |
| | | } |
| | | }, |
| | | created() { |
| | | axios.get('/api/auth/captcha-config', { timeout: 10000 }) |
| | | .then(res => { |
| | | const d = res.data |
| | | if (d && d.code === 200) this.captchaRequired = d.data.required !== false |
| | | }) |
| | | .catch(() => {}) |
| | | }, |
| | | methods: { |
| | | onCaptchaVerified(payload) { |
| | | this.captchaVerified = true |
| | | this.captchaId = payload.captchaId |
| | | this.clickIds = payload.clickIds |
| | | }, |
| | | onCaptchaReset() { |
| | | this.captchaVerified = false |
| | | this.captchaId = '' |
| | | this.clickIds = [] |
| | | }, |
| | | login() { |
| | | this.$refs.form.validate(valid => { |
| | | if (valid) { |
| | | this.$router.push('/dashboard') |
| | | if (!valid) return |
| | | if (this.captchaRequired && !this.captchaVerified) { |
| | | this.$message.warning('请先完成行为验证') |
| | | return |
| | | } |
| | | this.loggingIn = true |
| | | axios.post('/api/auth/login', { |
| | | username: this.form.username, |
| | | password: this.form.password, |
| | | captchaId: this.captchaId, |
| | | captchaClickIds: this.clickIds |
| | | }, { timeout: 15000 }).then(res => { |
| | | this.loggingIn = false |
| | | const d = res.data |
| | | if (d.code === 200) { |
| | | localStorage.setItem('token', d.data.token) |
| | | localStorage.setItem('username', d.data.username) |
| | | localStorage.setItem('realName', d.data.realName || '') |
| | | localStorage.setItem('modules', d.data.modules || '') |
| | | this.$message.success('登录成功') |
| | | this.$router.push('/dashboard') |
| | | } else if (d.code === 401) { |
| | | this.$message.error(d.message || '用户名或密码错误') |
| | | if (this.$refs.captcha) this.$refs.captcha.load() |
| | | } else if (d.code === 4001 || d.code === 4002 || d.code === 4003) { |
| | | this.$message.error(d.message || '验证未通过,请重新验证') |
| | | if (this.$refs.captcha) this.$refs.captcha.load() |
| | | } else { |
| | | this.$message.error(d.message || '登录失败,请重试') |
| | | if (this.$refs.captcha) this.$refs.captcha.load() |
| | | } |
| | | }).catch(e => { |
| | | this.loggingIn = false |
| | | if (e && e.code === 'ECONNABORTED') { this.$message.error('登录请求超时,请重试'); return } |
| | | this.$message.error('网络错误,登录失败') |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <style scoped> |
| | | .login-container { display: flex; justify-content: center; align-items: center; height: 100vh; background: #f0f2f5; } |
| | | .login-container { display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px 0; box-sizing: border-box; background: #f0f2f5; } |
| | | .captcha-skip-tip { font-size: 12px; color: #909399; line-height: 1.6; padding: 8px 10px; background: #F5F7FA; border-radius: 4px; } |
| | | .login-card { width: 400px; } |
| | | .login-card h2 { text-align: center; margin-bottom: 30px; } |
| | | .login-card h2 { text-align: center; margin-bottom: 18px; } |
| | | .login-card .el-form-item { margin-bottom: 16px; } |
| | | </style> |