1.优化登录页面;

2.新增初次登录强制修改密码;
This commit is contained in:
1638245306
2024-11-06 01:39:20 +08:00
parent 3f58c1cb7a
commit 3ea38a59b7
8 changed files with 384 additions and 55 deletions

View File

@@ -404,7 +404,7 @@ PLUGINS_URL_PATTERNS = []
# ********** 一键导入插件配置开始 ********** # ********** 一键导入插件配置开始 **********
# 例如: # 例如:
# from dvadmin_upgrade_center.settings import * # 升级中心 # from dvadmin_upgrade_center.settings import * # 升级中心
# from dvadmin_celery.settings import * # celery 异步任务 from dvadmin3_celery.settings import * # celery 异步任务
# from dvadmin_third.settings import * # 第三方用户管理 # from dvadmin_third.settings import * # 第三方用户管理
# from dvadmin_ak_sk.settings import * # 秘钥管理管理 # from dvadmin_ak_sk.settings import * # 秘钥管理管理
# from dvadmin_tenants.settings import * # 租户管理 # from dvadmin_tenants.settings import * # 租户管理

View File

@@ -71,6 +71,7 @@ class Users(CoreModel, AbstractUser):
help_text="关联部门", help_text="关联部门",
) )
login_error_count = models.IntegerField(default=0, verbose_name="登录错误次数", help_text="登录错误次数") login_error_count = models.IntegerField(default=0, verbose_name="登录错误次数", help_text="登录错误次数")
pwd_change_count = models.IntegerField(default=0,blank=True, verbose_name="密码修改次数", help_text="密码修改次数")
objects = CustomUserManager() objects = CustomUserManager()
def set_password(self, raw_password): def set_password(self, raw_password):

View File

@@ -4,12 +4,15 @@ from datetime import datetime, timedelta
from captcha.views import CaptchaStore, captcha_image from captcha.views import CaptchaStore, captcha_image
from django.contrib import auth from django.contrib import auth
from django.contrib.auth import login from django.contrib.auth import login
from django.contrib.auth.hashers import check_password, make_password
from django.db.models import Q from django.db.models import Q
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from drf_yasg import openapi from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from rest_framework import serializers from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView from rest_framework_simplejwt.views import TokenObtainPairView
@@ -97,16 +100,17 @@ class LoginSerializer(TokenObtainPairSerializer):
# 必须重置用户名为username,否则使用邮箱手机号登录会提示密码错误 # 必须重置用户名为username,否则使用邮箱手机号登录会提示密码错误
attrs['username'] = user.username attrs['username'] = user.username
data = super().validate(attrs) data = super().validate(attrs)
data["username"] = self.user.username
data["name"] = self.user.name data["name"] = self.user.name
data["userId"] = self.user.id data["userId"] = self.user.id
data["avatar"] = self.user.avatar data["avatar"] = self.user.avatar
data['user_type'] = self.user.user_type data['user_type'] = self.user.user_type
data['pwd_change_count'] = self.user.pwd_change_count
dept = getattr(self.user, 'dept', None) dept = getattr(self.user, 'dept', None)
if dept: if dept:
data['dept_info'] = { data['dept_info'] = {
'dept_id': dept.id, 'dept_id': dept.id,
'dept_name': dept.name, 'dept_name': dept.name,
} }
role = getattr(self.user, 'role', None) role = getattr(self.user, 'role', None)
if role: if role:

View File

@@ -286,6 +286,7 @@ class UserViewSet(CustomModelViewSet):
"dept": user.dept_id, "dept": user.dept_id,
"is_superuser": user.is_superuser, "is_superuser": user.is_superuser,
"role": user.role.values_list('id', flat=True), "role": user.role.values_list('id', flat=True),
"pwd_change_count":user.pwd_change_count
} }
if hasattr(connection, 'tenant'): if hasattr(connection, 'tenant'):
result['tenant_id'] = connection.tenant and connection.tenant.id result['tenant_id'] = connection.tenant and connection.tenant.id
@@ -319,7 +320,6 @@ class UserViewSet(CustomModelViewSet):
"""密码修改""" """密码修改"""
data = request.data data = request.data
old_pwd = data.get("oldPassword") old_pwd = data.get("oldPassword")
print(old_pwd)
new_pwd = data.get("newPassword") new_pwd = data.get("newPassword")
new_pwd2 = data.get("newPassword2") new_pwd2 = data.get("newPassword2")
if old_pwd is None or new_pwd is None or new_pwd2 is None: if old_pwd is None or new_pwd is None or new_pwd2 is None:
@@ -336,11 +336,26 @@ class UserViewSet(CustomModelViewSet):
verify_password = check_password(str(old_pwd_md5), request.user.password) verify_password = check_password(str(old_pwd_md5), request.user.password)
if verify_password: if verify_password:
request.user.password = make_password(hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest()) request.user.password = make_password(hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest())
request.user.pwd_change_count += 1
request.user.save() request.user.save()
return DetailResponse(data=None, msg="修改成功") return DetailResponse(data=None, msg="修改成功")
else: else:
return ErrorResponse(msg="旧密码不正确") return ErrorResponse(msg="旧密码不正确")
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated])
def login_change_password(self, request, *args, **kwargs):
"""初次登录进行密码修改"""
data = request.data
new_pwd = data.get("password")
new_pwd2 = data.get("password_regain")
if new_pwd != new_pwd2:
return ErrorResponse(msg="两次密码不匹配")
else:
request.user.password = make_password(hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest())
request.user.pwd_change_count += 1
request.user.save()
return DetailResponse(data=None, msg="修改成功")
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated]) @action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])
def reset_to_default_password(self, request,pk): def reset_to_default_password(self, request,pk):
"""恢复默认密码""" """恢复默认密码"""

BIN
web/src/assets/login-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

View File

@@ -45,6 +45,12 @@
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 申请试用-->
<div style="text-align: center" v-if="showApply()">
<el-button class="login-content-apply" link type="primary" plain round @click="applyBtnClick">
<span>申请试用</span>
</el-button>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@@ -67,6 +73,7 @@ import { SystemConfigStore } from '/@/stores/systemConfig';
import { BtnPermissionStore } from '/@/plugin/permission/store.permission'; import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
import { Md5 } from 'ts-md5'; import { Md5 } from 'ts-md5';
import { errorMessage } from '/@/utils/message'; import { errorMessage } from '/@/utils/message';
import {getBaseURL} from "/@/utils/baseUrl";
export default defineComponent({ export default defineComponent({
name: 'loginAccount', name: 'loginAccount',
@@ -125,7 +132,10 @@ export default defineComponent({
state.ruleForm.captchaKey = ret.data.key; state.ruleForm.captchaKey = ret.data.key;
}); });
}; };
const refreshCaptcha = async () => { const applyBtnClick = async () => {
window.open(getBaseURL('/api/system/apply_for_trial/'));
};
const refreshCaptcha = async () => {
state.ruleForm.captcha='' state.ruleForm.captcha=''
loginApi.getCaptcha().then((ret: any) => { loginApi.getCaptcha().then((ret: any) => {
state.ruleForm.captchaImgBase = ret.data.image_base; state.ruleForm.captchaImgBase = ret.data.image_base;
@@ -138,8 +148,13 @@ export default defineComponent({
if (valid) { if (valid) {
loginApi.login({ ...state.ruleForm, password: Md5.hashStr(state.ruleForm.password) }).then((res: any) => { loginApi.login({ ...state.ruleForm, password: Md5.hashStr(state.ruleForm.password) }).then((res: any) => {
if (res.code === 2000) { if (res.code === 2000) {
Session.set('token', res.data.access); const {data} = res
Cookies.set('username', res.data.name); Cookies.set('username', res.data.username);
Session.set('token', res.data.access);
useUserInfo().setPwdChangeCount(data.pwd_change_count)
if(data.pwd_change_count==0){
return router.push('/login');
}
if (!themeConfig.value.isRequestRoutes) { if (!themeConfig.value.isRequestRoutes) {
// 前端控制路由2、请注意执行顺序 // 前端控制路由2、请注意执行顺序
initFrontEndControlRoutes(); initFrontEndControlRoutes();
@@ -162,35 +177,33 @@ export default defineComponent({
}) })
}; };
const getUserInfo = () => {
useUserInfo().setUserInfos();
};
// 登录成功后的跳转 // 登录成功后的跳转
const loginSuccess = () => { const loginSuccess = () => {
//登录成功获取用户信息,获取系统字典数据
getUserInfo();
//获取所有字典 //获取所有字典
DictionaryStore().getSystemDictionarys(); DictionaryStore().getSystemDictionarys();
// 初始化登录成功时间问候语 // 初始化登录成功时间问候语
let currentTimeInfo = currentTime.value; let currentTimeInfo = currentTime.value;
// 登录成功,跳到转首页 // 登录成功,跳到转首页
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中 const pwd_change_count = userInfos.value.pwd_change_count
if (route.query?.redirect) { if(pwd_change_count>0){
router.push({ // 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
path: <string>route.query?.redirect, if (route.query?.redirect) {
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '', router.push({
}); path: <string>route.query?.redirect,
} else { query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
router.push('/'); });
} } else {
// 登录成功提示 router.push('/');
// 关闭 loading }
state.loading.signIn = true; // 登录成功提示
const signInText = t('message.signInText'); // 关闭 loading
ElMessage.success(`${currentTimeInfo}${signInText}`); state.loading.signIn = true;
const signInText = t('message.signInText');
ElMessage.success(`${currentTimeInfo}${signInText}`);
}
// 添加 loading防止第一次进入界面时出现短暂空白 // 添加 loading防止第一次进入界面时出现短暂空白
NextLoading.start(); NextLoading.start();
}; };
@@ -199,7 +212,10 @@ export default defineComponent({
//获取系统配置 //获取系统配置
SystemConfigStore().getSystemConfigs(); SystemConfigStore().getSystemConfigs();
}); });
// 是否显示申请试用按钮
const showApply = () => {
return window.location.href.indexOf('public') != -1
}
return { return {
refreshCaptcha, refreshCaptcha,
@@ -209,6 +225,8 @@ export default defineComponent({
state, state,
formRef, formRef,
rules, rules,
applyBtnClick,
showApply,
...toRefs(state), ...toRefs(state),
}; };
}, },
@@ -249,7 +267,7 @@ export default defineComponent({
.login-content-submit { .login-content-submit {
width: 100%; width: 100%;
letter-spacing: 2px; letter-spacing: 2px;
font-weight: 300; font-weight: 800;
margin-top: 15px; margin-top: 15px;
} }
} }

View File

@@ -0,0 +1,276 @@
<template>
<el-form ref="formRef" size="large" class="login-content-form" :model="state.ruleForm" :rules="rules" @keyup.enter="loginClick">
<el-form-item class="login-animation1" prop="username">
<el-input type="text" :placeholder="$t('message.account.accountPlaceholder1')" readonly v-model="ruleForm.username"
clearable autocomplete="off">
<template #prefix>
<el-icon class="el-input__icon"><ele-User /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item class="login-animation2" prop="password">
<el-input :type="isShowPassword ? 'text' : 'password'" :placeholder="$t('message.account.accountPlaceholder4')"
v-model="ruleForm.password">
<template #prefix>
<el-icon class="el-input__icon"><ele-Unlock /></el-icon>
</template>
<template #suffix>
<i class="iconfont el-input__icon login-content-password"
:class="isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'"
@click="isShowPassword = !isShowPassword">
</i>
</template>
</el-input>
</el-form-item>
<el-form-item class="login-animation3" prop="password_regain">
<el-input :type="isShowPassword ? 'text' : 'password'" :placeholder="$t('message.account.accountPlaceholder5')"
v-model="ruleForm.password_regain">
<template #prefix>
<el-icon class="el-input__icon"><ele-Unlock /></el-icon>
</template>
<template #suffix>
<i class="iconfont el-input__icon login-content-password"
:class="isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'"
@click="isShowPassword = !isShowPassword">
</i>
</template>
</el-input>
</el-form-item>
<el-form-item class="login-animation4">
<el-button type="primary" class="login-content-submit" round @click="loginClick"
:loading="loading.signIn">
<span>{{ $t('message.account.accountBtnText') }}</span>
</el-button>
</el-form-item>
</el-form>
<!-- 申请试用-->
<div style="text-align: center" v-if="showApply()">
<el-button class="login-content-apply" link type="primary" plain round @click="applyBtnClick">
<span>申请试用</span>
</el-button>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, defineComponent, computed, onMounted, onUnmounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ElMessage, FormInstance, FormRules } from 'element-plus';
import { useI18n } from 'vue-i18n';
import Cookies from 'js-cookie';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
import { initFrontEndControlRoutes } from '/@/router/frontEnd';
import { initBackEndControlRoutes } from '/@/router/backEnd';
import { Session } from '/@/utils/storage';
import { formatAxis } from '/@/utils/formatTime';
import { NextLoading } from '/@/utils/loading';
import * as loginApi from '/@/views/system/login/api';
import { useUserInfo } from '/@/stores/userInfo';
import { DictionaryStore } from '/@/stores/dictionary';
import { SystemConfigStore } from '/@/stores/systemConfig';
import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
import { Md5 } from 'ts-md5';
import { errorMessage } from '/@/utils/message';
import {getBaseURL} from "/@/utils/baseUrl";
import {loginChangePwd} from "/@/views/system/login/api";
export default defineComponent({
name: 'changePwd',
setup() {
const { t } = useI18n();
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);
const { userInfos } = storeToRefs(useUserInfo());
const route = useRoute();
const router = useRouter();
const state = reactive({
isShowPassword: false,
ruleForm: {
username: '',
password: '',
password_regain:''
},
loading: {
signIn: false,
},
});
const validatePass = (rule, value, callback) => {
const pwdRegex = new RegExp('(?=.*[0-9])(?=.*[a-zA-Z]).{8,30}');
if (value === '') {
callback(new Error('请输入密码'));
} else if (!pwdRegex.test(value)) {
callback(new Error('您的密码复杂度太低(密码中必须包含字母、数字)'));
} else {
if (state.ruleForm.password !== '') {
formRef.value.validateField('password');
}
callback();
}
};
const validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !==state.ruleForm.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
const rules = reactive<FormRules>({
username: [
{ required: true, message: '请填写账号', trigger: 'blur' },
],
password: [
{
required: true,
message: '请填写密码',
trigger: 'blur',
},
{
validator: validatePass,
trigger: 'blur',
},
],
password_regain: [
{
required: true,
message: '请填写密码',
trigger: 'blur',
},
{
validator: validatePass2,
trigger: 'blur',
},
],
})
const formRef = ref();
// 时间获取
const currentTime = computed(() => {
return formatAxis(new Date());
});
const applyBtnClick = async () => {
window.open(getBaseURL('/api/system/apply_for_trial/'));
};
const loginClick = async () => {
if (!formRef.value) return
await formRef.value.validate((valid: any) => {
if (valid) {
loginApi.loginChangePwd({ ...state.ruleForm, password: state.ruleForm.password,password_regain: state.ruleForm.password_regain }).then((res: any) => {
if (res.code === 2000) {
if (!themeConfig.value.isRequestRoutes) {
// 前端控制路由2、请注意执行顺序
initFrontEndControlRoutes();
loginSuccess();
} else {
// 模拟后端控制路由isRequestRoutes 为 true则开启后端控制路由
// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
initBackEndControlRoutes();
// 执行完 initBackEndControlRoutes再执行 signInSuccess
loginSuccess();
}
}
}).catch((err: any) => {
// 登录错误之后,刷新验证码
errorMessage("登录失败")
});
} else {
errorMessage("请填写登录信息")
}
})
};
// 登录成功后的跳转
const loginSuccess = () => {
//获取所有字典
DictionaryStore().getSystemDictionarys();
// 初始化登录成功时间问候语
let currentTimeInfo = currentTime.value;
// 登录成功,跳到转首页
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
if (route.query?.redirect) {
router.push({
path: <string>route.query?.redirect,
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
});
} else {
router.push('/');
}
// 登录成功提示
// 关闭 loading
state.loading.signIn = true;
const signInText = t('message.signInText');
ElMessage.success(`${currentTimeInfo}${signInText}`);
// 添加 loading防止第一次进入界面时出现短暂空白
NextLoading.start();
};
onMounted(() => {
state.ruleForm.username = Cookies.get('username')
//获取系统配置
SystemConfigStore().getSystemConfigs();
});
// 是否显示申请试用按钮
const showApply = () => {
return window.location.href.indexOf('public') != -1
}
return {
loginClick,
loginSuccess,
state,
formRef,
rules,
applyBtnClick,
showApply,
...toRefs(state),
};
},
});
</script>
<style scoped lang="scss">
.login-content-form {
margin-top: 20px;
@for $i from 1 through 5 {
.login-animation#{$i} {
opacity: 0;
animation-name: error-num;
animation-duration: 0.5s;
animation-fill-mode: forwards;
animation-delay: calc($i/10) + s;
}
}
.login-content-password {
display: inline-block;
width: 20px;
cursor: pointer;
&:hover {
color: #909399;
}
}
.login-content-captcha {
width: 100%;
padding: 0;
font-weight: bold;
letter-spacing: 5px;
}
.login-content-submit {
width: 100%;
letter-spacing: 2px;
font-weight: 800;
margin-top: 15px;
}
}
</style>

View File

@@ -5,51 +5,52 @@
<img :src="siteLogo" /> <img :src="siteLogo" />
<div class="login-left-logo-text"> <div class="login-left-logo-text">
<span>{{ getSystemConfig['login.site_title'] || getThemeConfig.globalViceTitle }}</span> <span>{{ getSystemConfig['login.site_title'] || getThemeConfig.globalViceTitle }}</span>
<span class="login-left-logo-text-msg">{{ <span class="login-left-logo-text-msg" style="margin-top: 5px;">{{
getSystemConfig['login.site_name'] || getThemeConfig.globalViceTitleMsg }}</span> getSystemConfig['login.site_name'] || getThemeConfig.globalViceTitleMsg }}</span>
</div> </div>
</div> </div>
<div class="login-left-img">
<img :src="loginMain" />
</div>
<img :src="loginBg" class="login-left-waves" />
</div> </div>
<div class="login-right flex z-10"> <div class="login-right flex z-10">
<div class="login-right-warp flex-margin"> <div class="login-right-warp flex-margin">
<span class="login-right-warp-one"></span> <!-- <span class="login-right-warp-one"></span>-->
<span class="login-right-warp-two"></span> <!-- <span class="login-right-warp-two"></span>-->
<div class="login-right-warp-mian"> <div class="login-right-warp-mian">
<div class="login-right-warp-main-title">{{ getSystemConfig['login.site_title'] || <div class="login-right-warp-main-title">
getThemeConfig.globalTitle }} 欢迎您</div> {{userInfos.pwd_change_count===0?'初次登录修改密码':'欢迎登录'}}
</div>
<div class="login-right-warp-main-form"> <div class="login-right-warp-main-form">
<div v-if="!state.isScan"> <div v-if="!state.isScan">
<el-tabs v-model="state.tabsActiveName"> <el-tabs v-model="state.tabsActiveName">
<el-tab-pane :label="$t('message.label.one1')" name="account"> <el-tab-pane :label="$t('message.label.changePwd')" name="changePwd" v-if="userInfos.pwd_change_count===0">
<ChangePwd />
</el-tab-pane>
<el-tab-pane :label="$t('message.label.one1')" name="account" v-else>
<Account /> <Account />
</el-tab-pane> </el-tab-pane>
<!-- TODO 手机号码登录未接入展示隐藏 --> <!-- TODO 手机号码登录未接入展示隐藏 -->
<!-- <el-tab-pane :label="$t('message.label.two2')" name="mobile"> <!-- <el-tab-pane :label="$t('message.label.two2')" name="mobile">
<Mobile /> <Mobile />
</el-tab-pane> --> </el-tab-pane> -->
</el-tabs> </el-tabs>
</div> </div>
<Scan v-if="state.isScan" /> <!-- <Scan v-if="state.isScan" />-->
<div class="login-content-main-sacn" @click="state.isScan = !state.isScan"> <!-- <div class="login-content-main-sacn" @click="state.isScan = !state.isScan">-->
<i class="iconfont" :class="state.isScan ? 'icon-diannao1' : 'icon-barcode-qr'"></i> <!-- <i class="iconfont" :class="state.isScan ? 'icon-diannao1' : 'icon-barcode-qr'"></i>-->
<div class="login-content-main-sacn-delta"></div> <!-- <div class="login-content-main-sacn-delta"></div>-->
</div> <!-- </div>-->
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="login-authorization z-10"> <div class="login-authorization z-10">
<p>Copyright © {{ getSystemConfig['login.copyright'] || '2021-2024 django-vue-admin.com' }} 版权所有</p> <p>Copyright © {{ getSystemConfig['login.copyright'] || '2021-2024 北京信码新创科技有限公司' }} 版权所有</p>
<p class="la-other"> <p class="la-other" style="margin-top: 5px;">
<a href="https://beian.miit.gov.cn" target="_blank">{{ getSystemConfig['login.keep_record'] || <a href="https://beian.miit.gov.cn" target="_blank">{{ getSystemConfig['login.keep_record'] ||
'ICP备18005113号-3' }}</a> 'ICP备2021031018号' }}</a>
| |
<a :href="getSystemConfig['login.help_url'] ? getSystemConfig['login.help_url'] : 'https://django-vue-admin.com'" <a :href="getSystemConfig['login.help_url'] ? getSystemConfig['login.help_url'] : '#'"
target="_blank">帮助</a> target="_blank">帮助</a>
| |
<a <a
@@ -60,26 +61,29 @@
</p> </p>
</div> </div>
</div> </div>
<div v-if="siteBg"> <div v-if="loginBg">
<img :src="siteBg" class="fixed inset-0 z-1 w-full h-full" /> <img :src="loginBg" class="loginBg fixed inset-0 z-1 w-full h-full" />
</div> </div>
</template> </template>
<script setup lang="ts" name="loginIndex"> <script setup lang="ts" name="loginIndex">
import { defineAsyncComponent, onMounted, reactive, computed } from 'vue'; import {defineAsyncComponent, onMounted, reactive, computed, watch} from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig'; import { useThemeConfig } from '/@/stores/themeConfig';
import { NextLoading } from '/@/utils/loading'; import { NextLoading } from '/@/utils/loading';
import logoMini from '/@/assets/logo-mini.svg'; import logoMini from '/@/assets/logo-mini.svg';
import loginMain from '/@/assets/login-main.svg'; import loginMain from '/@/assets/login-main.svg';
import loginBg from '/@/assets/login-bg.svg'; import loginBg from '/@/assets/login-bg.png';
import { SystemConfigStore } from '/@/stores/systemConfig' import { SystemConfigStore } from '/@/stores/systemConfig'
import { getBaseURL } from "/@/utils/baseUrl"; import { getBaseURL } from "/@/utils/baseUrl";
// 引入组件 // 引入组件
const Account = defineAsyncComponent(() => import('/@/views/system/login/component/account.vue')); const Account = defineAsyncComponent(() => import('/@/views/system/login/component/account.vue'));
const Mobile = defineAsyncComponent(() => import('/@/views/system/login/component/mobile.vue')); const Mobile = defineAsyncComponent(() => import('/@/views/system/login/component/mobile.vue'));
const Scan = defineAsyncComponent(() => import('/@/views/system/login/component/scan.vue')); const Scan = defineAsyncComponent(() => import('/@/views/system/login/component/scan.vue'));
const ChangePwd = defineAsyncComponent(() => import('/@/views/system/login/component/changePwd.vue'));
import _ from "lodash-es"; import _ from "lodash-es";
import {useUserInfo} from "/@/stores/userInfo";
const { userInfos } = storeToRefs(useUserInfo());
// 定义变量内容 // 定义变量内容
const storesThemeConfig = useThemeConfig(); const storesThemeConfig = useThemeConfig();
@@ -89,6 +93,16 @@ const state = reactive({
isScan: false, isScan: false,
}); });
watch(()=>userInfos.value.pwd_change_count,(val)=>{
if(val===0){
state.tabsActiveName ='changePwd'
}else{
state.tabsActiveName ='account'
}
},{deep:true,immediate:true})
// 获取布局配置信息 // 获取布局配置信息
const getThemeConfig = computed(() => { const getThemeConfig = computed(() => {
return themeConfig.value; return themeConfig.value;
@@ -187,13 +201,13 @@ onMounted(() => {
width: 700px; width: 700px;
.login-right-warp { .login-right-warp {
border: 1px solid var(--el-color-primary-light-3); //border: 1px solid var(--el-color-primary-light-3);
border-radius: 3px; border-radius: 3px;
width: 500px; width: 500px;
height: 500px; height: 500px;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
background-color: var(--el-color-white); //background-color: var(--el-color-white);
.login-right-warp-one, .login-right-warp-one,
.login-right-warp-two { .login-right-warp-two {
@@ -265,7 +279,8 @@ onMounted(() => {
.login-right-warp-main-title { .login-right-warp-main-title {
height: 130px; height: 130px;
line-height: 130px; line-height: 130px;
font-size: 27px; font-size: 32px;
font-weight: 600;
text-align: center; text-align: center;
letter-spacing: 3px; letter-spacing: 3px;
animation: logoAnimation 0.3s ease; animation: logoAnimation 0.3s ease;
@@ -321,7 +336,7 @@ onMounted(() => {
} }
.login-authorization { .login-authorization {
position: fixed; position: absolute;
bottom: 30px; bottom: 30px;
left: 0; left: 0;
right: 0; right: 0;