<template>
|
<div class="login-container">
|
<div class="login-box">
|
<div class="login-header">
|
<h2>WIDESEA WMS</h2>
|
<p>仓库管理系统</p>
|
</div>
|
|
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="login-form">
|
<el-form-item prop="username">
|
<el-input
|
v-model="loginForm.username"
|
placeholder="请输入账号"
|
size="large"
|
prefix-icon="User"
|
/>
|
</el-form-item>
|
<el-form-item prop="password">
|
<el-input
|
v-model="loginForm.password"
|
type="password"
|
placeholder="请输入密码"
|
size="large"
|
prefix-icon="Lock"
|
show-password
|
/>
|
</el-form-item>
|
<el-form-item prop="verificationCode">
|
<el-input
|
v-model="loginForm.verificationCode"
|
placeholder="请输入验证码"
|
size="large"
|
prefix-icon="CircleCheck"
|
style="width: 60%"
|
@keyup.enter="handleLogin"
|
/>
|
<div class="captcha-box" @click="loadCaptcha">
|
<img v-if="captchaImg" :src="captchaImg" alt="验证码" />
|
<span v-else class="captcha-placeholder">点击刷新</span>
|
</div>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" size="large" style="width: 100%" :loading="loading" @click="handleLogin">
|
{{ loading ? '登录中...' : '登 录' }}
|
</el-button>
|
</el-form-item>
|
</el-form>
|
|
<div class="login-footer">
|
<span>演示账号:admin666 密码:123456</span>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { reactive, ref, onMounted } from 'vue';
|
import { useRouter } from 'vue-router';
|
import { ElMessage } from 'element-plus';
|
import { User, Lock, CircleCheck } from '@element-plus/icons-vue';
|
import { userApi } from '@/api/modules/user';
|
import { useUserStore } from '@/store';
|
|
const router = useRouter();
|
const userStore = useUserStore();
|
const loginFormRef = ref();
|
const loading = ref(false);
|
const captchaImg = ref('');
|
const uuid = ref('');
|
|
const loginForm = reactive({
|
username: 'admin',
|
password: '123456',
|
verificationCode: '',
|
});
|
|
const loginRules = {
|
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
verificationCode: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
|
};
|
|
async function loadCaptcha() {
|
try {
|
const res = await userApi.getCaptcha();
|
if (res?.img) {
|
captchaImg.value = `data:image/png;base64,${res.img}`;
|
uuid.value = res.uuid;
|
}
|
} catch {
|
ElMessage.error('获取验证码失败');
|
}
|
}
|
|
async function handleLogin() {
|
if (!loginFormRef.value) return;
|
await loginFormRef.value.validate(async (valid) => {
|
if (!valid) return;
|
loading.value = true;
|
try {
|
const res = await userApi.login({
|
userName: loginForm.username,
|
password: loginForm.password,
|
verificationCode: loginForm.verificationCode,
|
UUID: uuid.value,
|
});
|
if (res?.status === false) {
|
ElMessage.error(res.message || '登录失败');
|
loadCaptcha();
|
return;
|
}
|
const userData = res.data || res;
|
userStore.setUserInfo({
|
token: userData.token || userData.access_token || '',
|
userName: userData.userName || loginForm.username,
|
userTrueName: userData.userTrueName || userData.name || '',
|
img: userData.img || '',
|
});
|
ElMessage.success('登录成功');
|
router.push('/');
|
} catch {
|
ElMessage.error('登录异常');
|
loadCaptcha();
|
} finally {
|
loading.value = false;
|
}
|
});
|
}
|
|
onMounted(() => {
|
loadCaptcha();
|
});
|
</script>
|
|
<style scoped>
|
.login-container {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
min-height: 100vh;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
}
|
.login-box {
|
width: 420px;
|
padding: 40px;
|
background: #fff;
|
border-radius: 12px;
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
}
|
.login-header {
|
text-align: center;
|
margin-bottom: 30px;
|
}
|
.login-header h2 {
|
margin: 0 0 8px;
|
font-size: 28px;
|
color: #333;
|
font-weight: 600;
|
}
|
.login-header p {
|
margin: 0;
|
font-size: 14px;
|
color: #999;
|
}
|
.login-form {
|
margin-top: 20px;
|
}
|
.captcha-box {
|
width: 38%;
|
height: 40px;
|
margin-left: 10px;
|
border: 1px solid #dcdfe6;
|
border-radius: 4px;
|
overflow: hidden;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
cursor: pointer;
|
background: #f5f7fa;
|
}
|
.captcha-box img {
|
width: 100%;
|
height: 100%;
|
object-fit: fill;
|
}
|
.captcha-placeholder {
|
font-size: 12px;
|
color: #999;
|
}
|
.login-footer {
|
margin-top: 20px;
|
text-align: center;
|
font-size: 12px;
|
color: #999;
|
}
|
</style>
|