|
|
@@ -1,51 +1,66 @@
|
|
|
<template>
|
|
|
- <div class="login" v-loading="pageLoading" element-loading-background="rgba(0,0,0,0.6)">
|
|
|
+ <div class="login" v-loading="pageLoading" element-loading-background="rgba(255,255,255,0.9)">
|
|
|
<template v-if="!pageLoading">
|
|
|
- <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
|
|
|
- <div class="title-box">
|
|
|
- <h3 class="title">{{ title }}</h3>
|
|
|
- <lang-select />
|
|
|
+ <div class="login-container">
|
|
|
+ <div class="login-left">
|
|
|
+ <div class="brand-area">
|
|
|
+ <div class="brand-logo">
|
|
|
+ <svg-icon icon-class="system" class="logo-icon" />
|
|
|
+ </div>
|
|
|
+ <h1 class="brand-title">{{ title }}</h1>
|
|
|
+ <p class="brand-desc">华晟ERP订单管理系统</p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <el-form-item v-if="tenantEnabled" prop="tenantId">
|
|
|
- <el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')"
|
|
|
- style="width: 100%">
|
|
|
- <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName"
|
|
|
- :value="item.tenantId"></el-option>
|
|
|
- <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item prop="username">
|
|
|
- <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off"
|
|
|
- :placeholder="proxy.$t('login.username')">
|
|
|
- <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item prop="password">
|
|
|
- <el-input v-model="loginForm.password" type="password" size="large" auto-complete="off"
|
|
|
- :placeholder="proxy.$t('login.password')" @keyup.enter="handleLogin">
|
|
|
- <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item v-if="captchaEnabled" prop="code">
|
|
|
- <el-input v-model="loginForm.code" size="large" auto-complete="off" :placeholder="proxy.$t('login.code')"
|
|
|
- style="width: 63%" @keyup.enter="handleLogin">
|
|
|
- <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
|
|
|
- </el-input>
|
|
|
- <div class="login-code">
|
|
|
- <img :src="codeUrl" class="login-code-img" @click="getCode" />
|
|
|
+ <div class="login-right">
|
|
|
+ <div class="login-card">
|
|
|
+ <h2 class="card-title">欢迎登录</h2>
|
|
|
+ <p class="card-sub">请输入您的账号信息</p>
|
|
|
+ <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
|
|
|
+ <el-form-item v-if="tenantEnabled" prop="tenantId">
|
|
|
+ <el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')"
|
|
|
+ style="width: 100%" size="large">
|
|
|
+ <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName"
|
|
|
+ :value="item.tenantId"></el-option>
|
|
|
+ <template #prefix><svg-icon icon-class="company" class="input-icon" /></template>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item prop="username">
|
|
|
+ <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off"
|
|
|
+ :placeholder="proxy.$t('login.username')">
|
|
|
+ <template #prefix><svg-icon icon-class="user" class="input-icon" /></template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item prop="password">
|
|
|
+ <el-input v-model="loginForm.password" type="password" size="large" auto-complete="off"
|
|
|
+ :placeholder="proxy.$t('login.password')" @keyup.enter="handleLogin">
|
|
|
+ <template #prefix><svg-icon icon-class="password" class="input-icon" /></template>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="captchaEnabled" prop="code">
|
|
|
+ <el-input v-model="loginForm.code" size="large" auto-complete="off"
|
|
|
+ :placeholder="proxy.$t('login.code')" style="width: 63%" @keyup.enter="handleLogin">
|
|
|
+ <template #prefix><svg-icon icon-class="validCode" class="input-icon" /></template>
|
|
|
+ </el-input>
|
|
|
+ <div class="login-code">
|
|
|
+ <img :src="codeUrl" class="login-code-img" @click="getCode" />
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ <div class="form-options">
|
|
|
+ <el-checkbox v-model="loginForm.rememberMe">{{ proxy.$t('login.rememberPassword') }}</el-checkbox>
|
|
|
+ </div>
|
|
|
+ <el-form-item style="width: 100%; margin-bottom: 0">
|
|
|
+ <el-button :loading="loading" size="large" type="primary" class="login-btn"
|
|
|
+ @click.prevent="handleLogin">
|
|
|
+ <span v-if="!loading">{{ proxy.$t('login.login') }}</span>
|
|
|
+ <span v-else>{{ proxy.$t('login.logging') }}</span>
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
</div>
|
|
|
- </el-form-item>
|
|
|
- <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">{{ proxy.$t('login.rememberPassword')
|
|
|
- }}</el-checkbox>
|
|
|
- <el-form-item style="width: 100%">
|
|
|
- <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
|
|
|
- <span v-if="!loading">{{ proxy.$t('login.login') }}</span>
|
|
|
- <span v-else>{{ proxy.$t('login.logging') }}</span>
|
|
|
- </el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <div class="el-login-footer">
|
|
|
- <span>Copyright © 2018-2026 疯狂的狮子Li All Rights Reserved.</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="login-footer">
|
|
|
+ <span>Copyright © 2026 华晟ERP订单管理系统</span>
|
|
|
</div>
|
|
|
</template>
|
|
|
</div>
|
|
|
@@ -213,87 +228,207 @@ onMounted(async () => {
|
|
|
<style lang="scss" scoped>
|
|
|
.login {
|
|
|
display: flex;
|
|
|
+ flex-direction: column;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
height: 100%;
|
|
|
- background-image: url('../assets/images/login-background.jpg');
|
|
|
- background-size: cover;
|
|
|
- background-position: center;
|
|
|
-}
|
|
|
+ min-height: 100vh;
|
|
|
+ background: linear-gradient(135deg, #f5f7fa 0%, #e4e9f0 50%, #dce3eb 100%);
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
|
|
|
-.title-box {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 8px;
|
|
|
-
|
|
|
- .title {
|
|
|
- margin: 0px auto 26px auto;
|
|
|
- text-align: center;
|
|
|
- color: var(--el-text-color-primary);
|
|
|
- font-weight: 600;
|
|
|
- letter-spacing: 0.5px;
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: -50%;
|
|
|
+ right: -20%;
|
|
|
+ width: 600px;
|
|
|
+ height: 600px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: linear-gradient(135deg, rgba(26, 115, 232, 0.06) 0%, rgba(26, 115, 232, 0.02) 100%);
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
|
|
|
- :deep(.lang-select--style) {
|
|
|
- line-height: 0;
|
|
|
- color: var(--el-text-color-secondary);
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ bottom: -30%;
|
|
|
+ left: -10%;
|
|
|
+ width: 400px;
|
|
|
+ height: 400px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: linear-gradient(135deg, rgba(66, 133, 244, 0.05) 0%, rgba(66, 133, 244, 0.02) 100%);
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.login-form {
|
|
|
- border-radius: var(--app-radius-lg);
|
|
|
- background: rgba(255, 255, 255, 0.94);
|
|
|
- border: 1px solid rgba(255, 255, 255, 0.5);
|
|
|
- width: min(420px, 90vw);
|
|
|
- padding: 32px 30px 12px 30px;
|
|
|
+.login-container {
|
|
|
+ display: flex;
|
|
|
+ width: 960px;
|
|
|
+ min-height: 520px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 16px;
|
|
|
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04);
|
|
|
+ overflow: hidden;
|
|
|
z-index: 1;
|
|
|
- box-shadow: var(--app-shadow-lg);
|
|
|
- backdrop-filter: blur(6px);
|
|
|
- -webkit-backdrop-filter: blur(6px);
|
|
|
+}
|
|
|
|
|
|
- .el-input {
|
|
|
- height: 40px;
|
|
|
+.login-left {
|
|
|
+ flex: 0 0 420px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background: linear-gradient(135deg, #1a73e8 0%, #4285f4 50%, #5b9cf6 100%);
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
|
|
|
- input {
|
|
|
- height: 40px;
|
|
|
- }
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: -60px;
|
|
|
+ right: -60px;
|
|
|
+ width: 200px;
|
|
|
+ height: 200px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: rgba(255, 255, 255, 0.06);
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
|
|
|
- .input-icon {
|
|
|
- height: 39px;
|
|
|
- width: 14px;
|
|
|
- margin-left: 0px;
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ bottom: -40px;
|
|
|
+ left: -40px;
|
|
|
+ width: 160px;
|
|
|
+ height: 160px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: rgba(255, 255, 255, 0.04);
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.login-tip {
|
|
|
- font-size: 13px;
|
|
|
+.brand-area {
|
|
|
text-align: center;
|
|
|
- color: #bfbfbf;
|
|
|
+ color: #fff;
|
|
|
+ z-index: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.brand-logo {
|
|
|
+ width: 72px;
|
|
|
+ height: 72px;
|
|
|
+ margin: 0 auto 24px;
|
|
|
+ background: rgba(255, 255, 255, 0.15);
|
|
|
+ border-radius: 18px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ backdrop-filter: blur(10px);
|
|
|
+}
|
|
|
+
|
|
|
+.logo-icon {
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.brand-title {
|
|
|
+ font-size: 28px;
|
|
|
+ font-weight: 700;
|
|
|
+ margin: 0 0 12px;
|
|
|
+ letter-spacing: 2px;
|
|
|
+}
|
|
|
+
|
|
|
+.brand-desc {
|
|
|
+ font-size: 14px;
|
|
|
+ opacity: 0.85;
|
|
|
+ margin: 0;
|
|
|
+ letter-spacing: 1px;
|
|
|
+}
|
|
|
+
|
|
|
+.login-right {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 48px 40px;
|
|
|
}
|
|
|
|
|
|
-.login-form :deep(.el-input__wrapper) {
|
|
|
- background-color: rgba(255, 255, 255, 0.9);
|
|
|
+.login-card {
|
|
|
+ width: 100%;
|
|
|
+ max-width: 360px;
|
|
|
+}
|
|
|
+
|
|
|
+.card-title {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #1a1a2e;
|
|
|
+ margin: 0 0 8px;
|
|
|
}
|
|
|
|
|
|
-.login-form :deep(.el-input__wrapper.is-focus) {
|
|
|
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
|
+.card-sub {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #909399;
|
|
|
+ margin: 0 0 32px;
|
|
|
}
|
|
|
|
|
|
-.login-form :deep(.el-button--primary) {
|
|
|
- border-radius: var(--app-radius-md);
|
|
|
- box-shadow: 0 8px 20px rgba(59, 130, 246, 0.25);
|
|
|
+.login-form {
|
|
|
+ .input-icon {
|
|
|
+ height: 16px;
|
|
|
+ width: 16px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 0 0 1px #e4e7ed inset;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 0 0 1px #c0c4cc inset;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-input__wrapper.is-focus) {
|
|
|
+ box-shadow: 0 0 0 1px #1a73e8 inset;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-select .el-input__wrapper) {
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.login-form :deep(.el-button.is-circle) {
|
|
|
- background: rgba(15, 23, 42, 0.04);
|
|
|
- border: 1px solid rgba(15, 23, 42, 0.08);
|
|
|
- color: var(--el-text-color-regular);
|
|
|
+.form-options {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 24px;
|
|
|
+
|
|
|
+ :deep(.el-checkbox__label) {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.login-form :deep(.el-button.is-circle:hover) {
|
|
|
- background: rgba(59, 130, 246, 0.1);
|
|
|
- border-color: rgba(59, 130, 246, 0.2);
|
|
|
+.login-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ letter-spacing: 2px;
|
|
|
+ background: linear-gradient(135deg, #1a73e8 0%, #4285f4 100%);
|
|
|
+ border: none;
|
|
|
+ box-shadow: 0 4px 15px rgba(26, 115, 232, 0.3);
|
|
|
+ transition: all 0.3s ease;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 6px 20px rgba(26, 115, 232, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.login-code {
|
|
|
@@ -301,58 +436,54 @@ onMounted(async () => {
|
|
|
height: 40px;
|
|
|
float: right;
|
|
|
margin-left: 10px;
|
|
|
- box-sizing: border-box;
|
|
|
- border-radius: var(--app-radius-sm);
|
|
|
+ border-radius: 8px;
|
|
|
overflow: hidden;
|
|
|
- background: rgba(255, 255, 255, 0.9);
|
|
|
- border: 1px solid var(--el-border-color-light);
|
|
|
+ cursor: pointer;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
|
|
|
img {
|
|
|
- cursor: pointer;
|
|
|
- vertical-align: middle;
|
|
|
display: block;
|
|
|
width: 100%;
|
|
|
- height: 40px;
|
|
|
+ height: 100%;
|
|
|
object-fit: cover;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.el-login-footer {
|
|
|
- height: 40px;
|
|
|
- line-height: 40px;
|
|
|
+.login-footer {
|
|
|
position: fixed;
|
|
|
- bottom: 0;
|
|
|
+ bottom: 24px;
|
|
|
width: 100%;
|
|
|
text-align: center;
|
|
|
- color: rgba(255, 255, 255, 0.75);
|
|
|
- font-family: Arial, serif;
|
|
|
+ color: #909399;
|
|
|
font-size: 12px;
|
|
|
- letter-spacing: 1px;
|
|
|
+ letter-spacing: 0.5px;
|
|
|
+ z-index: 1;
|
|
|
}
|
|
|
|
|
|
-.login-code-img {
|
|
|
- height: 40px;
|
|
|
- padding-left: 0;
|
|
|
-}
|
|
|
+@media (max-width: 1000px) {
|
|
|
+ .login-container {
|
|
|
+ width: 90vw;
|
|
|
+ flex-direction: column;
|
|
|
+ min-height: auto;
|
|
|
+ }
|
|
|
|
|
|
-:global(html.dark) {
|
|
|
- .login-form {
|
|
|
- background: rgba(17, 24, 39, 0.9);
|
|
|
- border-color: rgba(148, 163, 184, 0.2);
|
|
|
+ .login-left {
|
|
|
+ flex: 0 0 auto;
|
|
|
+ padding: 40px 20px;
|
|
|
}
|
|
|
|
|
|
- .login-form :deep(.el-input__wrapper) {
|
|
|
- background-color: rgba(17, 24, 39, 0.7);
|
|
|
+ .login-right {
|
|
|
+ padding: 32px 24px;
|
|
|
}
|
|
|
|
|
|
- .login-form :deep(.el-button.is-circle) {
|
|
|
- background: rgba(148, 163, 184, 0.12);
|
|
|
- border-color: rgba(148, 163, 184, 0.25);
|
|
|
- color: #e5e7eb;
|
|
|
+ .brand-logo {
|
|
|
+ width: 56px;
|
|
|
+ height: 56px;
|
|
|
+ margin-bottom: 16px;
|
|
|
}
|
|
|
|
|
|
- .el-login-footer {
|
|
|
- color: rgba(226, 232, 240, 0.65);
|
|
|
+ .brand-title {
|
|
|
+ font-size: 22px;
|
|
|
}
|
|
|
}
|
|
|
</style>
|