2026-05-27 16:38:40 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="login-page">
|
2026-05-27 17:04:48 +08:00
|
|
|
<div class="login-panel">
|
2026-05-27 16:38:40 +08:00
|
|
|
<div class="login-header">
|
2026-05-27 17:04:48 +08:00
|
|
|
<div class="header-mark">S</div>
|
|
|
|
|
<div class="header-right">
|
|
|
|
|
<div class="header-title">SIMATIC L2</div>
|
|
|
|
|
<div class="header-sub">推拉酸洗线 过程控制系统</div>
|
|
|
|
|
</div>
|
2026-05-27 16:38:40 +08:00
|
|
|
</div>
|
|
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
<div class="login-body">
|
|
|
|
|
<div class="field-group">
|
|
|
|
|
<div class="field-label">用户名</div>
|
|
|
|
|
<input v-model="form.username" class="kv-input" autocomplete="username" @keyup.enter="handleLogin" />
|
2026-05-27 16:38:40 +08:00
|
|
|
</div>
|
2026-05-27 17:04:48 +08:00
|
|
|
<div class="field-group">
|
|
|
|
|
<div class="field-label">密码</div>
|
|
|
|
|
<input v-model="form.password" type="password" class="kv-input" autocomplete="current-password" @keyup.enter="handleLogin" />
|
2026-05-27 16:38:40 +08:00
|
|
|
</div>
|
|
|
|
|
<div v-if="error" class="login-error">{{ error }}</div>
|
2026-05-27 17:04:48 +08:00
|
|
|
<button class="btn btn-primary fw" style="margin-top:18px;padding:7px;" :disabled="loading" @click="handleLogin">
|
|
|
|
|
{{ loading ? '验证中...' : '登录' }}
|
|
|
|
|
</button>
|
2026-05-27 16:38:40 +08:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="login-footer">
|
2026-05-27 17:04:48 +08:00
|
|
|
<i class="dot g"></i>系统就绪
|
|
|
|
|
<span style="margin-left:auto;">v1.0.0</span>
|
2026-05-27 16:38:40 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
export default {
|
|
|
|
|
name: 'Login',
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
loading: false,
|
|
|
|
|
error: '',
|
|
|
|
|
form: { username: '', password: '' }
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
async handleLogin() {
|
|
|
|
|
if (!this.form.username || !this.form.password) {
|
2026-05-27 17:04:48 +08:00
|
|
|
this.error = '用户名和密码不能为空'
|
2026-05-27 16:38:40 +08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
this.loading = true
|
|
|
|
|
this.error = ''
|
|
|
|
|
try {
|
|
|
|
|
await this.$store.dispatch('auth/login', this.form)
|
|
|
|
|
this.$router.push('/')
|
|
|
|
|
} catch {
|
|
|
|
|
this.error = '用户名或密码错误'
|
|
|
|
|
} finally {
|
|
|
|
|
this.loading = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
@import '@/assets/styles/variables';
|
|
|
|
|
|
|
|
|
|
.login-page {
|
|
|
|
|
height: 100vh;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
2026-05-27 17:04:48 +08:00
|
|
|
background: $bg-base;
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
.login-panel {
|
|
|
|
|
width: 360px;
|
2026-05-27 16:38:40 +08:00
|
|
|
background: $bg-card;
|
|
|
|
|
border: 1px solid $border;
|
2026-05-27 17:04:48 +08:00
|
|
|
border-top: 3px solid $sms-teal;
|
|
|
|
|
border-radius: 2px;
|
2026-05-27 16:38:40 +08:00
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.login-header {
|
2026-05-27 17:04:48 +08:00
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
padding: 20px 24px;
|
2026-05-27 16:38:40 +08:00
|
|
|
background: $bg-panel;
|
|
|
|
|
border-bottom: 1px solid $border;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
.header-mark {
|
|
|
|
|
width: 36px;
|
|
|
|
|
height: 36px;
|
|
|
|
|
background: $sms-teal;
|
|
|
|
|
color: $bg-base;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
flex-shrink: 0;
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
.header-title {
|
2026-05-27 16:38:40 +08:00
|
|
|
font-size: 14px;
|
2026-05-27 17:04:48 +08:00
|
|
|
font-weight: 700;
|
2026-05-27 16:38:40 +08:00
|
|
|
color: $text-primary;
|
2026-05-27 17:04:48 +08:00
|
|
|
letter-spacing: 2px;
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
.header-sub {
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
color: $text-secondary;
|
|
|
|
|
margin-top: 3px;
|
|
|
|
|
letter-spacing: .3px;
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
.login-body {
|
|
|
|
|
padding: 24px;
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
.field-group {
|
2026-05-27 16:38:40 +08:00
|
|
|
margin-bottom: 14px;
|
2026-05-27 17:04:48 +08:00
|
|
|
|
|
|
|
|
.field-label {
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
color: $text-secondary;
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
letter-spacing: .6px;
|
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.kv-input { padding: 7px 9px; font-size: 13px; }
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.login-error {
|
2026-05-27 17:04:48 +08:00
|
|
|
margin-top: 8px;
|
|
|
|
|
font-size: 11px;
|
2026-05-27 16:38:40 +08:00
|
|
|
color: $accent-red;
|
2026-05-27 17:04:48 +08:00
|
|
|
padding: 5px 8px;
|
|
|
|
|
background: rgba($accent-red, .08);
|
|
|
|
|
border-left: 2px solid $accent-red;
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.login-footer {
|
2026-05-27 17:04:48 +08:00
|
|
|
padding: 8px 24px;
|
2026-05-27 16:38:40 +08:00
|
|
|
background: $bg-panel;
|
|
|
|
|
border-top: 1px solid $border;
|
2026-05-27 17:04:48 +08:00
|
|
|
font-size: 10px;
|
2026-05-27 16:38:40 +08:00
|
|
|
color: $text-muted;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 6px;
|
2026-05-27 17:04:48 +08:00
|
|
|
letter-spacing: .3px;
|
2026-05-27 16:38:40 +08:00
|
|
|
|
2026-05-27 17:04:48 +08:00
|
|
|
.dot {
|
|
|
|
|
width: 5px; height: 5px; border-radius: 50%; display: inline-block;
|
|
|
|
|
&.g { background: $status-run; }
|
|
|
|
|
}
|
2026-05-27 16:38:40 +08:00
|
|
|
}
|
|
|
|
|
</style>
|