功能变化: 新增登录页及登录初始化配置

pull/56/head
李强 2022-05-11 00:03:49 +08:00
parent cf267f0e44
commit 0f73d725d9
19 changed files with 3729 additions and 492 deletions

View File

@ -327,11 +327,11 @@ CAPTCHA_LENGTH = 4 # 字符个数
CAPTCHA_TIMEOUT = 1 # 超时(minutes)
CAPTCHA_OUTPUT_FORMAT = "%(image)s %(text_field)s %(hidden_field)s "
CAPTCHA_FONT_SIZE = 40 # 字体大小
CAPTCHA_FOREGROUND_COLOR = "#0033FF" # 前景色
CAPTCHA_FOREGROUND_COLOR = "#64DAAA" # 前景色
CAPTCHA_BACKGROUND_COLOR = "#F5F7F4" # 背景色
CAPTCHA_NOISE_FUNCTIONS = (
"captcha.helpers.noise_arcs", # 线
"captcha.helpers.noise_dots", # 点
# "captcha.helpers.noise_dots", # 点
)
# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge' #字母验证码
CAPTCHA_CHALLENGE_FUNCT = "captcha.helpers.math_challenge" # 加减乘除验证码

View File

@ -207,11 +207,13 @@ class InitSettingsViewSet(APIView):
def get(self, request):
data = {
"site_name": "DVAdmin", # 网站名称
"site_name": "企业级后台管理系统", # 网站名称
"site_logo": "", # 网站logo地址
"login_background": "", # 登录页背景图
"login_banner": "", # 登录页Banner图
"copyright": "2021-2022 django-vue-admin.com 版权所有", # 版权
"keep_record": "晋ICP备18005113号-3" # 备案
"keep_record": "晋ICP备18005113号-3", # 备案
"help_url": "https://django-vue-admin.com", # 帮助
"privacy_url": "#", # 隐私
"clause_url": "#", # 条款
}
return DetailResponse(data=data)

View File

@ -1,7 +1,7 @@
# 开发环境
NODE_ENV=development
# 页面 title 前缀
VUE_APP_TITLE=DVAdmin
VUE_APP_TITLE=企业级后台管理系统
# 启用权限管理
VUE_APP_PM_ENABLED = true
# 后端接口地址及端口(域名)

View File

@ -6,7 +6,7 @@ NODE_ENV=production
# 标记当前构建方式
VUE_APP_BUILD_MODE=PREVIEW
# 页面 title 前缀
VUE_APP_TITLE=DVAdmin
VUE_APP_TITLE=企业级后台管理系统
# 显示源码按钮
VUE_APP_SCOURCE_LINK=FALSE

View File

@ -1,7 +1,7 @@
# 测试环境
# 页面 title 前缀
VUE_APP_TITLE=DVAdmin
VUE_APP_TITLE=企业级后台管理系统
# 启用权限管理
VUE_APP_PM_ENABLED = true
# 后端接口地址及端口(域名)

View File

@ -58,10 +58,201 @@
text-decoration: none;
}
.d2-home__loading {
height: 32px;
width: 32px;
margin-bottom: 20px;
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999999;
}
#loader {
display: block;
position: relative;
left: 50%;
top: 50%;
width: 120px;
height: 120px;
margin: -75px 0 0 -75px;
border-radius: 50%;
border: 3px solid transparent;
/* COLOR 1 */
border-top-color: #FFF;
-webkit-animation: spin 2s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-ms-animation: spin 2s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-moz-animation: spin 2s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-o-animation: spin 2s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
animation: spin 2s linear infinite;
/* Chrome, Firefox 16+, IE 10+, Opera */
z-index: 1001;
}
#loader:before {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
/* COLOR 2 */
border-top-color: #FFF;
-webkit-animation: spin 3s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-moz-animation: spin 3s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-o-animation: spin 3s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-ms-animation: spin 3s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
animation: spin 3s linear infinite;
/* Chrome, Firefox 16+, IE 10+, Opera */
}
#loader:after {
content: "";
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #FFF;
/* COLOR 3 */
-moz-animation: spin 1.5s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-o-animation: spin 1.5s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-ms-animation: spin 1.5s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
-webkit-animation: spin 1.5s linear infinite;
/* Chrome, Opera 15+, Safari 5+ */
animation: spin 1.5s linear infinite;
/* Chrome, Firefox 16+, IE 10+, Opera */
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(0deg);
/* IE 9 */
transform: rotate(0deg);
/* Firefox 16+, IE 10+, Opera */
}
100% {
-webkit-transform: rotate(360deg);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg);
/* IE 9 */
transform: rotate(360deg);
/* Firefox 16+, IE 10+, Opera */
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(0deg);
/* IE 9 */
transform: rotate(0deg);
/* Firefox 16+, IE 10+, Opera */
}
100% {
-webkit-transform: rotate(360deg);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(360deg);
/* IE 9 */
transform: rotate(360deg);
/* Firefox 16+, IE 10+, Opera */
}
}
#loader-wrapper .loader-section {
position: fixed;
top: 0;
width: 51%;
height: 100%;
background: #49a9ee;
/* Old browsers */
z-index: 1000;
-webkit-transform: translateX(0);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: translateX(0);
/* IE 9 */
transform: translateX(0);
/* Firefox 16+, IE 10+, Opera */
}
#loader-wrapper .loader-section.section-left {
left: 0;
}
#loader-wrapper .loader-section.section-right {
right: 0;
}
/* Loaded */
.loaded #loader-wrapper .loader-section.section-left {
-webkit-transform: translateX(-100%);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: translateX(-100%);
/* IE 9 */
transform: translateX(-100%);
/* Firefox 16+, IE 10+, Opera */
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
}
.loaded #loader-wrapper .loader-section.section-right {
-webkit-transform: translateX(100%);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: translateX(100%);
/* IE 9 */
transform: translateX(100%);
/* Firefox 16+, IE 10+, Opera */
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
}
.loaded #loader {
opacity: 0;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.loaded #loader-wrapper {
visibility: hidden;
-webkit-transform: translateY(-100%);
/* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: translateY(-100%);
/* IE 9 */
transform: translateY(-100%);
/* Firefox 16+, IE 10+, Opera */
-webkit-transition: all 0.3s 1s ease-out;
transition: all 0.3s 1s ease-out;
}
/* JavaScript Turned Off */
.no-js #loader-wrapper {
display: none;
}
.no-js h1 {
color: #222222;
}
#loader-wrapper .load_title {
font-family: 'Open Sans';
color: #FFF;
font-size: 14px;
width: 100%;
text-align: center;
z-index: 9999999999999;
position: absolute;
top: 60%;
opacity: 1;
line-height: 30px;
}
#loader-wrapper .load_title span {
font-weight: normal;
font-style: italic;
font-size: 14px;
color: #FFF;
opacity: 0.5;
}
</style>
<script>
@ -78,15 +269,11 @@
</strong>
</noscript>
<div id="app">
<div class="d2-home">
<div class="d2-home__main">
<img class="d2-home__loading" src="./image/loading/loading-spin.svg" alt="loading">
</div>
<div class="d2-home__footer">
<a href="https://gitee.com/liqianglog/django-vue-admin" target="_blank">
https://gitee.com/liqianglog/django-vue-admin
</a>
</div>
<div id="loader-wrapper">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
<div class="load_title">正在加载中,请耐心等待...</div>
</div>
</div>
<!-- 使用 CDN 加速的 JS 文件配置在 vue.config.js -->

View File

@ -9,9 +9,11 @@ export default {
siteName: '', // 网站名称
siteLogo: '', // 网站logo地址
loginBackground: '', // 登录页背景图
loginBanner: '', // 登录页Banner图
copyright: '', // 版权
keepRecord: '' // 备案
keepRecord: '', // 备案
helpUrl: '', // 帮助地址
privacyUrl: '', // 隐私
clauseUrl: '' // 条款
},
actions: {
/**
@ -49,9 +51,11 @@ export default {
state.siteName = res.site_name
state.siteLogo = res.site_logo
state.loginBackground = res.login_background
state.loginBanner = res.login_banner
state.copyright = res.copyright
state.keepRecord = res.keep_record
state.helpUrl = res.help_url
state.privacyUrl = res.privacy_url
state.clauseUrl = res.clause_url
}
},
mutations: {

View File

@ -0,0 +1,226 @@
<template>
<div class="page-login">
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex'
import localeMixin from '@/locales/mixin.js'
import * as api from '@/views/system/login/api'
export default {
mixins: [localeMixin],
computed: {
...mapState('d2admin', {
siteName: (state) => state.settings.siteName, //
siteLogo: (state) => state.settings.siteLogo || require('./image/dvadmin.png'), // logo
loginBackground: (state) => state.settings.loginBackground || require('./image/bg.jpg'), //
copyright: (state) => state.settings.copyright, //
keepRecord: (state) => state.settings.keepRecord, //
helpUrl: (state) => state.settings.helpUrl, //
privacyUrl: (state) => state.settings.privacyUrl, //
clauseUrl: (state) => state.settings.clauseUrl //
})
},
beforeCreate () {
//
this.$store.dispatch('d2admin/settings/init')
},
data () {
return {
processTitle: process.env.VUE_APP_TITLE || 'D2Admin',
backgroundImage: 'url(' + this.loginBackground + ')',
//
formLogin: {
username: '',
password: '',
captcha: ''
},
//
rules: {
username: [
{
required: true,
message: '请输入用户名',
trigger: 'blur'
}
],
password: [
{
required: true,
message: '请输入密码',
trigger: 'blur'
}
],
captcha: [
{
required: true,
message: '请输入验证码',
trigger: 'blur'
}
]
},
captchaKey: null,
image_base: null
}
},
mounted () {
},
beforeDestroy () {
},
methods: {
...mapActions('d2admin/account', ['login']),
/**
* 获取验证码
*/
getCaptcha () {
api.getCaptcha().then((ret) => {
this.formLogin.captcha = null
this.captchaKey = ret.data.key
this.image_base = ret.data.image_base
})
},
/**
* @description 提交表单
*/
//
submit () {
const that = this
this.$refs.loginForm.validate((valid) => {
if (valid) {
//
//
//
this.login({
username: that.formLogin.username,
password: that.$md5(that.formLogin.password),
captcha: that.formLogin.captcha,
captchaKey: that.captchaKey
})
.then(() => {
//
this.$router.replace(this.$route.query.redirect || '/')
})
.catch(() => {
this.getCaptcha()
})
} else {
//
this.$message.error('表单校验失败,请检查')
}
})
}
},
created () {
this.$store.dispatch('d2admin/db/databaseClear')
this.getCaptcha()
}
}
</script>
<style lang="scss" scoped>
// ----
.page-login {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-image: url(./image/bg.jpg);
background-position: center 0;
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
-webkit-background-size: cover; /* 兼容Webkit内核浏览器如Chrome和Safari */
-o-background-size: cover; /* 兼容Opera */
zoom: 1;
}
::v-deep .el-card__body {
height: 100%;
padding: 0;
}
.card {
height: 100%;
width: 100%;
border-radius: 30px;
padding: 0;
margin-top: 12%;
}
.right-card {
float: right;
text-align: center;
width: 50%;
height: 100%;
}
.right-card h1 {
color: #098dee;
margin-bottom: 40px;
margin-top: 40px;
}
.button-login {
width: 100%;
margin-top: 30px;
}
::v-deep .el-input-group__append {
padding: 0;
}
// footer
.page-login--content-footer {
margin-top: 10%;
padding: 1em 0;
.page-login--content-footer-locales {
padding: 0px;
margin: 0px;
margin-bottom: 15px;
font-size: 12px;
line-height: 12px;
text-align: center;
color: $color-text-normal;
a {
color: $color-text-normal;
margin: 0 0.5em;
&:hover {
color: $color-text-main;
}
}
}
.page-login--content-footer-copyright {
padding: 0px;
margin: 0px;
margin-bottom: 10px;
font-size: 12px;
line-height: 12px;
text-align: center;
color: $color-text-normal;
a {
color: $color-text-normal;
}
}
.page-login--content-footer-options {
padding: 0px;
margin: 0px;
font-size: 12px;
line-height: 12px;
text-align: center;
a {
color: $color-text-normal;
margin: 0 1em;
}
}
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,520 @@
/*--
Author: W3layouts
Author URL: http://w3layouts.com
--*/
/* reset code */
html {
scroll-behavior: smooth;
}
body,
html {
margin: 0;
padding: 0;
color: #585858;
}
* {
box-sizing: border-box;
font-family: 'Kumbh Sans', sans-serif;
}
/* wrapper */
.wrapper {
width: 100%;
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto;
}
@media (min-width: 576px) {
.wrapper {
max-width: 540px;
}
}
@media (min-width: 768px) {
.wrapper {
max-width: 720px;
}
}
@media (min-width: 992px) {
.wrapper {
max-width: 960px;
}
}
@media (min-width: 1200px) {
.wrapper {
max-width: 1280px;
}
}
/* /wrapper */
.d-grid {
display: grid;
}
button,
input,
select {
-webkit-appearance: none;
outline: none;
}
button,
.btn,
select {
cursor: pointer;
}
a {
text-decoration: none;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol {
margin: 0;
padding: 0;
}
body {
background: #f1f1f1;
margin: 0;
padding: 0;
}
form,
fieldset {
border: 0;
padding: 0;
margin: 0;
}
img {
max-width: 100%;
}
.login-code{
max-width: 400px;
}
.el-input-group__append, .el-input-group__prepend{
padding: 0;
}
.page-login--logo{
margin: 0 auto;
top: 10px;
left: 52em;
position: absolute;
}
/*-- //Reset-Code --*/
/*-- form styling --*/
.w3l-form-info {
padding-top: 6em;
}
.w3l-signinform{
padding: 40px 40px;
min-height: 100vh;
background-size: cover;
-webkit-background-size: cover;
-o-background-size: cover;
-moz-background-size: cover;
-ms-background-size: cover;
position: relative;
z-index: 1;
align-items:center;
}
.w3l-signinform::before{
content: "";
position: absolute;
top: 0;
min-height: 100%;
left: 0;
right: 0;
z-index: -1;
}
.btn-block {
display: block;
width: 50%;
margin: 0 auto;
}
.btn:active {
outline: none;
}
.btn-primary {
color: #232005;
background-color: #ffd900;
margin-top: 30px;
outline: none;
width: 100%;
padding: 15px 15px;
cursor: pointer;
font-size: 18px;
font-weight: 600;
border-radius:6px;
-webkit-border-radius:6px;
-moz-border-radius:6px;
-ms-border-radius:6px;
-o-border-radius:6px;
border: none;
text-transform: capitalize;
}
.btn-primary:hover {
background-color:#eac803;
}
.form-row.bottom {
display: flex;
justify-content: space-between;
}
.form-row .form-check input[type="checkbox"] {
display: none;
}
.form-row .form-check input[type="checkbox"]+label:before {
border-radius: 3px;
border: 1px solid #e2e2e2;
color: transparent;
content: "\2714";
display: inline-block;
height: 18px;
margin-right: 5px;
transition: 0.2s;
vertical-align: inherit;
width: 18px;
text-align: center;
line-height: 20px;
}
.form-row .form-check input[type="checkbox"]:checked+label:before {
background-color: #ffd900;
border-color: #ffd900;
color: #232005;
}
.form-row .form-check input[type="checkbox"]+label {
cursor: pointer;
color: #000;
}
.w3_info h2 {
display: inline-block;
font-size: 24px;
line-height: 35px;
margin-bottom: 20px;
font-weight: 600;
color: #fff;
}
.w3_info h4 {
display: inline-block;
font-size: 15px;
padding: 8px 0px;
color: #444;
text-transform: capitalize;
}
h1 {
font-size: 36px;
font-weight: 600;
color: #fff;
margin-bottom: 0.4em;
line-height: 40px;
}
.w3_info {
padding: 1em 1em;
background: transparent;
max-width: 450px;
display: grid;
margin-left: auto;
}
.left_grid_info {
padding: 6em 0;
}
.w3l_form {
padding: 0px;
flex-basis: 50%;
-webkit-flex-basis: 50%;
background: #dad1f8;
}
/*.w3_info p {*/
/* padding-bottom: 30px;*/
/* text-align: center;*/
/*}*/
/*.w3_info p.sub-para {*/
/* padding-bottom: 40px;*/
/* text-align:left;*/
/* color:#fff;*/
/* opacity:0.9;*/
/* line-height:28px;*/
/*}*/
p.account,
p.account a {
text-align: center;
padding-top: 20px;
padding-bottom: 0px;
font-size: 16px;
color: #fff;
opacity: 0.9;
}
p.account a {
color: #ffd900;
}
p.account a:hover {
text-decoration: underline;
}
a.forgot {
color: #ffeb3b;
margin-top: 2px;
opacity: 0.8;
}
a.forgot:hover {
text-decoration: underline;
}
h3.w3ls {
margin: 10px 0px;
padding-left: 60px;
}
h3.agileits {
padding-left: 10px;
}
.container {
max-width: 890px;
margin: 0 auto;
}
h5 {
text-align: center;
margin: 10px 0px;
font-size: 15px;
font-weight: 600;
color: #000;
}
.footer {
padding-top: 3em;
}
.footer p {
text-align: center;
font-size: 14px;
line-height: 28px;
color: #fff;
opacity:0.9;
}
.footer p a {
color: #ffd900;
}
.footer p a:hover {
text-decoration: underline;
}
p.continue {
margin-top: 25px;
padding: 0;
margin-bottom: 20px;
color: #fff;
}
p.continue span {
position: relative;
}
p.continue span:before {
position: absolute;
content: '';
height: 1px;
background: #fff;
width: 89%;
left: -100%;
top: 5px;
}
p.continue span:after {
position: absolute;
content: '';
height: 1px;
background: #fff;
width: 89%;
right: -100%;
top: 5px;
}
::-webkit-input-placeholder {
/* Edge */
color: #fff;
}
:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: #fff;
}
::placeholder {
color:#fff;
}
/** Responsive **/
@media screen and (max-width: 1024px) {
.left_grid_info h3 {
font-size: 2em;
}
}
@media screen and (max-width: 991px) {
/*.w3_info h2 {*/
/* font-size: 24px;*/
/*}*/
h1 {
font-size: 35px;
}
}
@media screen and (max-width: 900px) {
.left_grid_info h4 {
font-size: 1em;
}
}
@media screen and (max-width: 800px) {
/*.w3_info h2 {*/
/* font-size: 23px;*/
/*}*/
}
@media screen and (max-width: 767px) {
/*.w3_info {*/
/* margin-right: auto;*/
/*}*/
}
@media screen and (max-width: 736px) {
/*.w3_info h2 {*/
/* font-size: 22px;*/
/*}*/
}
@media screen and (max-width: 667px) {
.w3l-form-info {
margin: 20px 0 30px;
}
}
@media screen and (max-width: 640px) {
h1 {
font-size: 37px;
}
}
@media screen and (max-width:568px) {
.w3l_form {
padding: 0em;
}
h1 {
font-size: 34px;
}
/*.w3_info {*/
/* padding:0;*/
/*}*/
}
@media screen and (max-width: 415px) {
h1 {
font-size: 32px;
}
.left_grid_info p {
font-size: 13px;
}
.w3l-signinform{
padding: 40px 20px;
}
}
@media screen and (max-width: 384px) {
.w3l-signinform{
padding: 30px 15px;
}
.social-login {
grid-auto-flow: row;
}
}
@media screen and (max-width: 375px) {
.left_grid_info h3 {
font-size: 1.5em;
}
.form-row.bottom {
flex-direction: column;
}
a.forgot {
margin-top: 17px;
}
}
@media screen and (max-width: 320px) {
h1 {
font-size: 25px;
}
/*.w3_info h2 {*/
/* font-size: 18px;*/
/*}*/
.btn-primary {
padding: 13px 12px;
font-size: 13px;
}
input[type="text"],
input[type="email"],
input[type="password"] {
font-size: 13px;
}
.footer p {
font-size: 13px;
}
.footer p a {
font-size: 13px;
}
}
/** /Responsive **/
/*-- //form styling --*/

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -1,491 +1,114 @@
<template>
<div class="page-login">
<div class="page-login--layer page-login--layer-area">
<ul class="circles">
<li v-for="n in 10" :key="n"></li>
</ul>
</div>
<div class="page-login--layer page-login--layer-time" flex="main:center cross:center">{{ time }}</div>
<div class="page-login--layer">
<div class="page-login--content" flex="dir:top main:justify cross:stretch box:justify">
<div class="page-login--content-header">
<p class="page-login--content-header-motto">时间是一切财富中最宝贵的财富</p>
</div>
<div class="page-login--content-main" flex="dir:top main:center cross:center">
<!-- logo -->
<img class="page-login--logo" src="./image/dvadmin.png" />
<!-- form -->
<div class="page-login--form">
<el-card shadow="never">
<el-form
ref="loginForm"
label-position="top"
:rules="rules"
:model="formLogin"
size="default"
>
<el-form-item prop="username">
<el-input type="text" v-model="formLogin.username" placeholder="用户名">
<i slot="prepend" class="fa fa-user-circle-o"></i>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
v-model="formLogin.password"
show-password
placeholder="密码"
>
<i slot="prepend" class="fa fa-keyboard-o"></i>
</el-input>
</el-form-item>
<el-form-item prop="captcha" v-if="captchaVisible">
<el-input type="text" v-model="formLogin.captcha" placeholder="验证码">
<template slot="append">
<img class="login-code" :src="image_base" @click="getCaptcha" />
</template>
</el-input>
</el-form-item>
<el-button size="default" @click="submit" type="primary" class="button-login">登录</el-button>
</el-form>
</el-card>
<!-- <p class="page-login--options" flex="main:justify cross:center">
<span><d2-icon name="question-circle" /> 忘记密码</span>
<span>注册用户</span>
</p>-->
<!-- quick login -->
<el-button
class="page-login--quick"
size="default"
type="info"
v-if="$env === 'development'"
@click="dialogVisible = true"
>
快速选择用户限dev环境
</el-button>
<div class="w3l-signinform" :style="{background: 'url('+ (loginBackground || require('./image/bg.jpg')) + ') no-repeat center'}">
<!-- container -->
<div class="wrapper">
<!-- main content -->
<div class="w3l-form-info">
<!-- logo -->
<img class="page-login--logo" :src="siteLogo" width="300"/>
<div class="w3_info">
<h2>{{siteName || processTitle}}</h2>
<el-card shadow="always" class="card">
<el-tabs v-model="activeName">
<el-tab-pane label="账号密码登录" name="first" stretch>
<span slot="label"><span style="margin: 30px;">账号密码登录</span></span>
<br>
<el-form
ref="loginForm"
label-position="top"
:rules="rules"
:model="formLogin"
size="default"
>
<el-form-item prop="username">
<el-input
type="text"
v-model="formLogin.username"
prefix-icon="el-icon-user-solid"
placeholder="用户名"
>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
v-model="formLogin.password"
prefix-icon="el-icon-s-promotion"
show-password
placeholder="密码"
>
</el-input>
</el-form-item>
<el-form-item prop="captcha">
<el-input
type="text"
v-model="formLogin.captcha"
placeholder="验证码"
@keyup.enter.native="submit"
>
<template slot="append">
<img
class="login-code"
height="33px"
width="145px"
slot="suffix"
:src="image_base"
@click="getCaptcha"
/>
</template>
</el-input>
</el-form-item>
<button class="btn btn-primary btn-block" @click="submit"></button>
</el-form>
</el-tab-pane>
</el-tabs>
</el-card>
<!-- footer -->
<div class="footer">
<p>Copyright &copy; {{copyright}}</p>
<p>
<a href="https://beian.miit.gov.cn" target="_blank">{{keepRecord}}</a> |
<a :href="helpUrl || '#'" target="_blank">帮助</a> |
<a :href="privacyUrl || '#'" target="_blank">隐私</a> |
<a :href="clauseUrl || '#'" target="_blank">条款</a>
</p>
</div>
</div>
<div class="page-login--content-footer">
<p class="page-login--content-footer-locales">
<a
v-for="language in $languages"
:key="language.value"
@click="onChangeLocale(language.value)"
>
{{ language.label }}
</a>
</p>
<p class="page-login--content-footer-copyright">
Copyright
<d2-icon name="copyright" />Copyright © 2018-2021 pro.django-vue-admin.com All Rights Reserved.
|
<a href="https://beian.miit.gov.cn" target="_blank">晋ICP备18005113号-3</a>
</p>
<p class="page-login--content-footer-options">
<a href="#">帮助</a>
<a href="#">隐私</a>
<a href="#">条款</a>
</p>
<!-- footer -->
</div>
</div>
<!-- //main content -->
</div>
<el-dialog title="快速选择用户" :visible.sync="dialogVisible" width="400px">
<el-row :gutter="10" style="margin: -20px 0px -10px 0px">
<el-col v-for="(user, index) in users" :key="index" :span="8">
<div class="page-login--quick-user" @click="handleUserBtnClick(user)">
<d2-icon name="user-circle-o" />
<span>{{ user.name }}</span>
</div>
</el-col>
</el-row>
</el-dialog>
<!-- //container -->
</div>
</template>
<script>
import dayjs from 'dayjs'
import { mapActions } from 'vuex'
import localeMixin from '@/locales/mixin.js'
import * as api from './api'
import base from './base.vue'
export default {
mixins: [localeMixin],
extends: base,
name: 'page',
data () {
return {
timeInterval: null,
time: dayjs().format('HH:mm:ss'),
//
dialogVisible: false,
captchaVisible: false,
users: [
{
name: '超管',
username: 'superadmin',
password: 'admin123456'
},
{
name: '管理员',
username: 'admin',
password: 'admin123456'
}
],
//
formLogin: {
username: '',
password: '',
captcha: ''
},
//
rules: {
username: [
{
required: true,
message: '请输入用户名',
trigger: 'blur'
}
],
password: [
{
required: true,
message: '请输入密码',
trigger: 'blur'
}
],
captcha: [
{
required: true,
message: '请输入验证码',
trigger: 'blur'
}
]
},
captchaKey: null,
image_base: null
activeName: 'first'
}
},
created () {
this.$store.dispatch('d2admin/db/databaseClear')
this.getCaptcha()
},
mounted () {
this.timeInterval = setInterval(() => {
this.refreshTime()
}, 1000)
},
beforeDestroy () {
clearInterval(this.timeInterval)
},
methods: {
...mapActions('d2admin/account', ['login']),
refreshTime () {
this.time = dayjs().format('HH:mm:ss')
},
/**
* @description 接收选择一个用户快速登录的事件
* @param {Object} user 用户信息
*/
handleUserBtnClick (user) {
this.formLogin.username = user.username
this.formLogin.password = user.password
this.dialogVisible = !this.dialogVisible
if (!this.captchaVisible) {
this.submit()
}
},
/**
* @description 提交表单
*/
//
submit () {
const that = this
this.$refs.loginForm.validate((valid) => {
if (valid) {
//
//
//
this.login({
username: that.formLogin.username,
password: that.$md5(that.formLogin.password),
captcha: that.formLogin.captcha,
captchaKey: that.captchaKey
})
.then(() => {
//
this.$router.replace(this.$route.query.redirect || '/')
})
.catch(() => {
this.getCaptcha()
})
} else {
//
this.$message.error('表单校验失败,请检查')
}
})
},
/**
* 获取验证码
*/
getCaptcha () {
api.getCaptchaStatus().then((ret) => {
this.captchaVisible = ret.data.status
if (this.captchaVisible) {
api.getCaptcha().then((ret) => {
this.formLogin.captcha = null
if (ret.data) {
this.captchaKey = ret.data.key
this.image_base = ret.data.image_base
}
})
}
})
}
}
methods: {}
}
</script>
<style lang="scss">
.page-login {
@extend %unable-select;
$backgroundColor: #f0f2f5;
// ---
background-color: $backgroundColor;
height: 100%;
position: relative;
//
.page-login--layer {
@extend %full;
overflow: auto;
}
.page-login--layer-area {
<style lang="scss" scoped>
@import './css/style.css';
.copyrights {
text-indent: -9999px;
height: 0;
line-height: 0;
font-size: 0;
overflow: hidden;
}
//
.page-login--layer-time {
font-size: 24em;
font-weight: bold;
color: rgba(0, 0, 0, 0.03);
overflow: hidden;
}
//
.page-login--content {
height: 100%;
min-height: 500px;
}
// header
.page-login--content-header {
padding: 1em 0;
.page-login--content-header-motto {
margin: 0px;
padding: 0px;
color: $color-text-normal;
text-align: center;
font-size: 12px;
}
}
// main
.page-login--logo {
width: 240px;
margin-bottom: 2em;
margin-top: -2em;
}
//
.page-login--form {
width: 280px;
//
.el-card {
margin-bottom: 15px;
}
//
.button-login {
width: 100%;
}
//
.el-input-group__prepend {
padding: 0px 14px;
}
.login-code {
height: 40px - 2px;
display: block;
margin: 0px -20px;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
//
.page-login--options {
margin: 0px;
padding: 0px;
font-size: 14px;
color: $color-primary;
margin-bottom: 15px;
font-weight: bold;
}
.page-login--quick {
width: 100%;
}
}
//
.page-login--quick-user {
@extend %flex-center-col;
padding: 10px 0px;
border-radius: 4px;
&:hover {
background-color: $color-bg;
i {
color: $color-text-normal;
}
span {
color: $color-text-normal;
}
}
i {
font-size: 36px;
color: $color-text-sub;
}
span {
font-size: 12px;
margin-top: 10px;
color: $color-text-sub;
}
}
// footer
.page-login--content-footer {
padding: 1em 0;
.page-login--content-footer-locales {
padding: 0px;
margin: 0px;
margin-bottom: 15px;
font-size: 12px;
line-height: 12px;
text-align: center;
color: $color-text-normal;
a {
color: $color-text-normal;
margin: 0 0.5em;
&:hover {
color: $color-text-main;
}
}
}
.page-login--content-footer-copyright {
padding: 0px;
margin: 0px;
font-size: 12px;
line-height: 12px;
text-align: center;
color: $color-text-normal;
a {
color: $color-text-normal;
}
}
.page-login--content-footer-options {
padding: 0px;
margin: 0px;
margin-bottom: 10px;
font-size: 12px;
line-height: 12px;
text-align: center;
a {
color: $color-text-normal;
margin: 0 1em;
}
}
}
//
.circles {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
margin: 0px;
padding: 0px;
li {
position: absolute;
display: block;
list-style: none;
width: 20px;
height: 20px;
background: #fff;
animation: animate 25s linear infinite;
bottom: -200px;
@keyframes animate {
0% {
transform: translateY(0) rotate(0deg);
opacity: 1;
border-radius: 0;
}
100% {
transform: translateY(-1000px) rotate(720deg);
opacity: 0;
border-radius: 50%;
}
}
&:nth-child(1) {
left: 15%;
width: 80px;
height: 80px;
animation-delay: 0s;
}
&:nth-child(2) {
left: 5%;
width: 20px;
height: 20px;
animation-delay: 2s;
animation-duration: 12s;
}
&:nth-child(3) {
left: 70%;
width: 20px;
height: 20px;
animation-delay: 4s;
}
&:nth-child(4) {
left: 40%;
width: 60px;
height: 60px;
animation-delay: 0s;
animation-duration: 18s;
}
&:nth-child(5) {
left: 65%;
width: 20px;
height: 20px;
animation-delay: 0s;
}
&:nth-child(6) {
left: 75%;
width: 150px;
height: 150px;
animation-delay: 3s;
}
&:nth-child(7) {
left: 35%;
width: 200px;
height: 200px;
animation-delay: 7s;
}
&:nth-child(8) {
left: 50%;
width: 25px;
height: 25px;
animation-delay: 15s;
animation-duration: 45s;
}
&:nth-child(9) {
left: 20%;
width: 15px;
height: 15px;
animation-delay: 2s;
animation-duration: 35s;
}
&:nth-child(10) {
left: 85%;
width: 150px;
height: 150px;
animation-delay: 0s;
animation-duration: 11s;
}
}
}
}
</style>