mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-08 09:30:06 +08:00
feat: Update Login Page (#7815)
This commit is contained in:
parent
b2fa0aa2d4
commit
88684c7cf0
@ -2,7 +2,6 @@ package v2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||||
"github.com/1Panel-dev/1Panel/core/app/dto"
|
"github.com/1Panel-dev/1Panel/core/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||||
@ -28,8 +27,8 @@ func (b *BaseApi) Login(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if req.AuthMethod != "jwt" && !req.IgnoreCaptcha {
|
if req.AuthMethod != "jwt" && !req.IgnoreCaptcha {
|
||||||
if err := captcha.VerifyCode(req.CaptchaID, req.Captcha); err != nil {
|
if errMsg := captcha.VerifyCode(req.CaptchaID, req.Captcha); errMsg != "" {
|
||||||
helper.InternalServer(c, err)
|
helper.BadAuth(c, errMsg, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,8 +38,12 @@ func (b *BaseApi) Login(c *gin.Context) {
|
|||||||
entrance, _ = base64.StdEncoding.DecodeString(entranceItem)
|
entrance, _ = base64.StdEncoding.DecodeString(entranceItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := authService.Login(c, req, string(entrance))
|
user, msgKey, err := authService.Login(c, req, string(entrance))
|
||||||
go saveLoginLogs(c, err)
|
go saveLoginLogs(c, err)
|
||||||
|
if msgKey == "ErrAuth" {
|
||||||
|
helper.BadAuth(c, msgKey, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.InternalServer(c, err)
|
helper.InternalServer(c, err)
|
||||||
return
|
return
|
||||||
@ -67,7 +70,11 @@ func (b *BaseApi) MFALogin(c *gin.Context) {
|
|||||||
entrance, _ = base64.StdEncoding.DecodeString(entranceItem)
|
entrance, _ = base64.StdEncoding.DecodeString(entranceItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := authService.MFALogin(c, req, string(entrance))
|
user, msgKey, err := authService.MFALogin(c, req, string(entrance))
|
||||||
|
if msgKey == "ErrAuth" {
|
||||||
|
helper.BadAuth(c, msgKey, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.InternalServer(c, err)
|
helper.InternalServer(c, err)
|
||||||
return
|
return
|
||||||
@ -141,16 +148,7 @@ func saveLoginLogs(c *gin.Context, err error) {
|
|||||||
logs.Status = constant.StatusSuccess
|
logs.Status = constant.StatusSuccess
|
||||||
}
|
}
|
||||||
logs.IP = c.ClientIP()
|
logs.IP = c.ClientIP()
|
||||||
//lang := c.GetHeader("Accept-Language")
|
|
||||||
//if lang == "" {
|
|
||||||
// lang = "zh"
|
|
||||||
//}
|
|
||||||
//address, err := geo.GetIPLocation(logs.IP, lang)
|
|
||||||
//if err != nil {
|
|
||||||
// global.LOG.Errorf("get ip location failed: %s", err)
|
|
||||||
//}
|
|
||||||
logs.Agent = c.GetHeader("User-Agent")
|
logs.Agent = c.GetHeader("User-Agent")
|
||||||
//logs.Address = address
|
|
||||||
_ = logService.CreateLoginLog(logs)
|
_ = logService.CreateLoginLog(logs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ func ErrorWithDetail(ctx *gin.Context, code int, msgKey string, err error) {
|
|||||||
Message: "",
|
Message: "",
|
||||||
}
|
}
|
||||||
if msgKey == "ErrCaptchaCode" || msgKey == "ErrAuth" {
|
if msgKey == "ErrCaptchaCode" || msgKey == "ErrAuth" {
|
||||||
res.Code = 406
|
res.Code = 401
|
||||||
res.Message = msgKey
|
res.Message = msgKey
|
||||||
}
|
}
|
||||||
res.Message = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err})
|
res.Message = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err})
|
||||||
|
@ -13,6 +13,7 @@ type ISettingRepo interface {
|
|||||||
GetValueByKey(key string) (string, error)
|
GetValueByKey(key string) (string, error)
|
||||||
Create(key, value string) error
|
Create(key, value string) error
|
||||||
Update(key, value string) error
|
Update(key, value string) error
|
||||||
|
UpdateOrCreate(key, value string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewISettingRepo() ISettingRepo {
|
func NewISettingRepo() ISettingRepo {
|
||||||
@ -58,3 +59,7 @@ func (u *SettingRepo) GetValueByKey(key string) (string, error) {
|
|||||||
func (u *SettingRepo) Update(key, value string) error {
|
func (u *SettingRepo) Update(key, value string) error {
|
||||||
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
|
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||||
|
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Assign(model.Setting{Key: key, Value: value}).FirstOrCreate(&model.Setting{}).Error
|
||||||
|
}
|
||||||
|
@ -21,9 +21,9 @@ type IAuthService interface {
|
|||||||
CheckIsSafety(code string) (string, error)
|
CheckIsSafety(code string) (string, error)
|
||||||
GetResponsePage() (string, error)
|
GetResponsePage() (string, error)
|
||||||
VerifyCode(code string) (bool, error)
|
VerifyCode(code string) (bool, error)
|
||||||
Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, error)
|
Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, string, error)
|
||||||
LogOut(c *gin.Context) error
|
LogOut(c *gin.Context) error
|
||||||
MFALogin(c *gin.Context, info dto.MFALogin, entrance string) (*dto.UserLoginInfo, error)
|
MFALogin(c *gin.Context, info dto.MFALogin, entrance string) (*dto.UserLoginInfo, string, error)
|
||||||
GetSecurityEntrance() string
|
GetSecurityEntrance() string
|
||||||
IsLogin(c *gin.Context) bool
|
IsLogin(c *gin.Context) bool
|
||||||
}
|
}
|
||||||
@ -32,79 +32,86 @@ func NewIAuthService() IAuthService {
|
|||||||
return &AuthService{}
|
return &AuthService{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *AuthService) Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, error) {
|
func (u *AuthService) Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, string, error) {
|
||||||
nameSetting, err := settingRepo.Get(repo.WithByKey("UserName"))
|
nameSetting, err := settingRepo.Get(repo.WithByKey("UserName"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, buserr.New("ErrRecordNotFound")
|
return nil, "", buserr.New("ErrRecordNotFound")
|
||||||
}
|
}
|
||||||
passwordSetting, err := settingRepo.Get(repo.WithByKey("Password"))
|
passwordSetting, err := settingRepo.Get(repo.WithByKey("Password"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, buserr.New("ErrRecordNotFound")
|
return nil, "", buserr.New("ErrRecordNotFound")
|
||||||
}
|
}
|
||||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, buserr.New("ErrAuth")
|
return nil, "ErrAuth", nil
|
||||||
}
|
}
|
||||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||||
return nil, buserr.New("ErrAuth")
|
return nil, "ErrAuth", nil
|
||||||
}
|
}
|
||||||
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if len(entranceSetting.Value) != 0 && entranceSetting.Value != entrance {
|
if len(entranceSetting.Value) != 0 && entranceSetting.Value != entrance {
|
||||||
return nil, buserr.New("ErrEntrance")
|
return nil, "ErrEntrance", nil
|
||||||
}
|
}
|
||||||
mfa, err := settingRepo.Get(repo.WithByKey("MFAStatus"))
|
mfa, err := settingRepo.Get(repo.WithByKey("MFAStatus"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if err = settingRepo.Update("Language", info.Language); err != nil {
|
if err = settingRepo.Update("Language", info.Language); err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if mfa.Value == constant.StatusEnable {
|
if mfa.Value == constant.StatusEnable {
|
||||||
return &dto.UserLoginInfo{Name: nameSetting.Value, MfaStatus: mfa.Value}, nil
|
return &dto.UserLoginInfo{Name: nameSetting.Value, MfaStatus: mfa.Value}, "", nil
|
||||||
}
|
}
|
||||||
return u.generateSession(c, info.Name, info.AuthMethod)
|
res, err := u.generateSession(c, info.Name, info.AuthMethod)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
return res, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance string) (*dto.UserLoginInfo, error) {
|
func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance string) (*dto.UserLoginInfo, string, error) {
|
||||||
nameSetting, err := settingRepo.Get(repo.WithByKey("UserName"))
|
nameSetting, err := settingRepo.Get(repo.WithByKey("UserName"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, buserr.New("ErrRecordNotFound")
|
return nil, "", buserr.New("ErrRecordNotFound")
|
||||||
}
|
}
|
||||||
passwordSetting, err := settingRepo.Get(repo.WithByKey("Password"))
|
passwordSetting, err := settingRepo.Get(repo.WithByKey("Password"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, buserr.New("ErrRecordNotFound")
|
return nil, "", buserr.New("ErrRecordNotFound")
|
||||||
}
|
}
|
||||||
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||||
return nil, buserr.New("ErrAuth")
|
return nil, "ErrAuth", nil
|
||||||
}
|
}
|
||||||
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
entranceSetting, err := settingRepo.Get(repo.WithByKey("SecurityEntrance"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if len(entranceSetting.Value) != 0 && entranceSetting.Value != entrance {
|
if len(entranceSetting.Value) != 0 && entranceSetting.Value != entrance {
|
||||||
return nil, buserr.New("ErrEntrance")
|
return nil, "", buserr.New("ErrEntrance")
|
||||||
}
|
}
|
||||||
mfaSecret, err := settingRepo.Get(repo.WithByKey("MFASecret"))
|
mfaSecret, err := settingRepo.Get(repo.WithByKey("MFASecret"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
mfaInterval, err := settingRepo.Get(repo.WithByKey("MFAInterval"))
|
mfaInterval, err := settingRepo.Get(repo.WithByKey("MFAInterval"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
success := mfa.ValidCode(info.Code, mfaInterval.Value, mfaSecret.Value)
|
success := mfa.ValidCode(info.Code, mfaInterval.Value, mfaSecret.Value)
|
||||||
if !success {
|
if !success {
|
||||||
return nil, buserr.New("ErrAuth")
|
return nil, "ErrAuth", nil
|
||||||
}
|
}
|
||||||
|
res, err := u.generateSession(c, info.Name, info.AuthMethod)
|
||||||
return u.generateSession(c, info.Name, info.AuthMethod)
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
return res, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *AuthService) generateSession(c *gin.Context, name, authMethod string) (*dto.UserLoginInfo, error) {
|
func (u *AuthService) generateSession(c *gin.Context, name, authMethod string) (*dto.UserLoginInfo, error) {
|
||||||
|
@ -4,24 +4,23 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/core/app/dto"
|
"github.com/1Panel-dev/1Panel/core/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/core/buserr"
|
|
||||||
"github.com/mojocn/base64Captcha"
|
"github.com/mojocn/base64Captcha"
|
||||||
)
|
)
|
||||||
|
|
||||||
var store = base64Captcha.DefaultMemStore
|
var store = base64Captcha.DefaultMemStore
|
||||||
|
|
||||||
func VerifyCode(codeID string, code string) error {
|
func VerifyCode(codeID string, code string) string {
|
||||||
if codeID == "" {
|
if codeID == "" {
|
||||||
return buserr.New("ErrCaptchaCode")
|
return "ErrCaptchaCode"
|
||||||
}
|
}
|
||||||
vv := store.Get(codeID, true)
|
vv := store.Get(codeID, true)
|
||||||
vv = strings.TrimSpace(vv)
|
vv = strings.TrimSpace(vv)
|
||||||
code = strings.TrimSpace(code)
|
code = strings.TrimSpace(code)
|
||||||
|
|
||||||
if strings.EqualFold(vv, code) {
|
if strings.EqualFold(vv, code) {
|
||||||
return nil
|
return ""
|
||||||
}
|
}
|
||||||
return buserr.New("ErrCaptchaCode")
|
return "ErrCaptchaCode"
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateCaptcha() (*dto.CaptchaResponse, error) {
|
func CreateCaptcha() (*dto.CaptchaResponse, error) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-drawer v-model="localOpenPage" :destroy-on-close="true" :size="size">
|
<el-drawer v-model="localOpenPage" :destroy-on-close="true" :size="size" :close-on-press-escape="true">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-page-header @back="handleBack">
|
<el-page-header @back="handleBack">
|
||||||
<template #content>
|
<template #content>
|
||||||
|
@ -177,8 +177,7 @@ const message = {
|
|||||||
mfaTitle: 'MFA Certification',
|
mfaTitle: 'MFA Certification',
|
||||||
mfaCode: 'MFA verification code',
|
mfaCode: 'MFA verification code',
|
||||||
title: 'Linux Server Management Panel',
|
title: 'Linux Server Management Panel',
|
||||||
licenseHelper:
|
licenseHelper: '<Community License Agreement>',
|
||||||
'Agree « <a href="https://www.fit2cloud.com/legal/licenses.html" target="_blank">Community License Agreement</a> »',
|
|
||||||
errorAgree: 'Click to agree to the Community Software License',
|
errorAgree: 'Click to agree to the Community Software License',
|
||||||
logout: 'Logout',
|
logout: 'Logout',
|
||||||
agreeTitle: 'Agreement',
|
agreeTitle: 'Agreement',
|
||||||
|
@ -167,8 +167,7 @@ const message = {
|
|||||||
mfaTitle: 'MFA認定',
|
mfaTitle: 'MFA認定',
|
||||||
mfaCode: 'MFA検証コード',
|
mfaCode: 'MFA検証コード',
|
||||||
title: 'Linuxサーバー管理パネル',
|
title: 'Linuxサーバー管理パネル',
|
||||||
licenseHelper:
|
licenseHelper: '<コミュニティライセンス契約>',
|
||||||
'同意&laquo;<a href = "https://www.fit2cloud.com/legal/licenses.html" target="_blank">コミュニティライセンス契約</a>&raquo;',
|
|
||||||
errorAgree: 'クリックして、コミュニティソフトウェアライセンスに同意します',
|
errorAgree: 'クリックして、コミュニティソフトウェアライセンスに同意します',
|
||||||
logout: 'ログアウト',
|
logout: 'ログアウト',
|
||||||
agreeTitle: '合意',
|
agreeTitle: '合意',
|
||||||
|
@ -166,8 +166,7 @@ const message = {
|
|||||||
mfaTitle: 'MFA 인증',
|
mfaTitle: 'MFA 인증',
|
||||||
mfaCode: 'MFA 인증 코드',
|
mfaCode: 'MFA 인증 코드',
|
||||||
title: 'Linux 서버 관리 패널',
|
title: 'Linux 서버 관리 패널',
|
||||||
licenseHelper:
|
licenseHelper: '<커뮤니티 라이선스 계약>',
|
||||||
'« <a href="https://www.fit2cloud.com/legal/licenses.html" target="_blank">커뮤니티 라이선스 계약</a> »에 동의합니다',
|
|
||||||
errorAgree: '커뮤니티 소프트웨어 라이선스에 동의하려면 클릭하세요',
|
errorAgree: '커뮤니티 소프트웨어 라이선스에 동의하려면 클릭하세요',
|
||||||
logout: '로그아웃',
|
logout: '로그아웃',
|
||||||
agreeTitle: '동의',
|
agreeTitle: '동의',
|
||||||
|
@ -169,8 +169,7 @@ const message = {
|
|||||||
mfaTitle: 'Pengesahan MFA',
|
mfaTitle: 'Pengesahan MFA',
|
||||||
mfaCode: 'Kod pengesahan MFA',
|
mfaCode: 'Kod pengesahan MFA',
|
||||||
title: 'Panel Pengurusan Pelayan Linux',
|
title: 'Panel Pengurusan Pelayan Linux',
|
||||||
licenseHelper:
|
licenseHelper: '<Perjanjian Lesen Komuniti>',
|
||||||
'Setuju « <a href="https://www.fit2cloud.com/legal/licenses.html" target="_blank">Perjanjian Lesen Komuniti</a> »',
|
|
||||||
errorAgree: 'Klik untuk bersetuju dengan Lesen Perisian Komuniti',
|
errorAgree: 'Klik untuk bersetuju dengan Lesen Perisian Komuniti',
|
||||||
logout: 'Log keluar',
|
logout: 'Log keluar',
|
||||||
agreeTitle: 'Agreement',
|
agreeTitle: 'Agreement',
|
||||||
|
@ -168,8 +168,7 @@ const message = {
|
|||||||
mfaTitle: 'Autenticação MFA',
|
mfaTitle: 'Autenticação MFA',
|
||||||
mfaCode: 'Código de verificação MFA',
|
mfaCode: 'Código de verificação MFA',
|
||||||
title: 'Painel de Gerenciamento de Servidores Linux',
|
title: 'Painel de Gerenciamento de Servidores Linux',
|
||||||
licenseHelper:
|
licenseHelper: '<Acordo de Licença Comunitária>',
|
||||||
'Concordar com « <a href="https://www.fit2cloud.com/legal/licenses.html" target="_blank">Acordo de Licença Comunitária</a> »',
|
|
||||||
errorAgree: 'Clique para concordar com o Acordo de Licença de Software Comunitário',
|
errorAgree: 'Clique para concordar com o Acordo de Licença de Software Comunitário',
|
||||||
logout: 'Sair',
|
logout: 'Sair',
|
||||||
agreeTitle: 'Termo de Aceite',
|
agreeTitle: 'Termo de Aceite',
|
||||||
|
@ -167,8 +167,7 @@ const message = {
|
|||||||
mfaTitle: 'MFA Сертификация',
|
mfaTitle: 'MFA Сертификация',
|
||||||
mfaCode: 'MFA код подтверждения',
|
mfaCode: 'MFA код подтверждения',
|
||||||
title: 'Панель управления Linux сервером',
|
title: 'Панель управления Linux сервером',
|
||||||
licenseHelper:
|
licenseHelper: '<Лицензионное соглашение сообщества>',
|
||||||
'Согласен « <a href="https://www.fit2cloud.com/legal/licenses.html" target="_blank">Лицензионное соглашение сообщества</a> »',
|
|
||||||
errorAgree: 'Нажмите, чтобы согласиться с Лицензией программного обеспечения сообщества',
|
errorAgree: 'Нажмите, чтобы согласиться с Лицензией программного обеспечения сообщества',
|
||||||
logout: 'Выход',
|
logout: 'Выход',
|
||||||
agreeTitle: 'Соглашение',
|
agreeTitle: 'Соглашение',
|
||||||
|
@ -175,8 +175,7 @@ const message = {
|
|||||||
mfaTitle: 'MFA 認證',
|
mfaTitle: 'MFA 認證',
|
||||||
mfaCode: 'MFA 驗證碼',
|
mfaCode: 'MFA 驗證碼',
|
||||||
title: 'Linux 服務器運維管理面板',
|
title: 'Linux 服務器運維管理面板',
|
||||||
licenseHelper:
|
licenseHelper: '《飛致雲社區軟件許可協議》',
|
||||||
'同意 « <a href="https://www.fit2cloud.com/legal/licenses.html" target="_blank"> 飛致雲社區軟件許可協議</a> »',
|
|
||||||
errorAgree: '請點擊同意社區軟件許可協議',
|
errorAgree: '請點擊同意社區軟件許可協議',
|
||||||
agreeTitle: '服務協議及隱私保護',
|
agreeTitle: '服務協議及隱私保護',
|
||||||
agreeContent:
|
agreeContent:
|
||||||
|
@ -175,8 +175,7 @@ const message = {
|
|||||||
mfaTitle: 'MFA 认证',
|
mfaTitle: 'MFA 认证',
|
||||||
mfaCode: 'MFA 验证码',
|
mfaCode: 'MFA 验证码',
|
||||||
title: 'Linux 服务器运维管理面板',
|
title: 'Linux 服务器运维管理面板',
|
||||||
licenseHelper:
|
licenseHelper: '《飞致云社区软件许可协议》',
|
||||||
'同意 « <a href="https://www.fit2cloud.com/legal/licenses.html" target="_blank"> 飞致云社区软件许可协议</a> »',
|
|
||||||
errorAgree: '请点击同意社区软件许可协议',
|
errorAgree: '请点击同意社区软件许可协议',
|
||||||
agreeTitle: '服务协议及隐私保护',
|
agreeTitle: '服务协议及隐私保护',
|
||||||
agreeContent:
|
agreeContent:
|
||||||
|
@ -386,7 +386,7 @@ import AppIgnore from './ignore/index.vue';
|
|||||||
import ComposeLogs from '@/components/compose-log/index.vue';
|
import ComposeLogs from '@/components/compose-log/index.vue';
|
||||||
import { App } from '@/api/interface/app';
|
import { App } from '@/api/interface/app';
|
||||||
import Status from '@/components/status/index.vue';
|
import Status from '@/components/status/index.vue';
|
||||||
import { getAge, getLanguage } from '@/utils/util';
|
import { getAge } from '@/utils/util';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { toFolder } from '@/global/business';
|
import { toFolder } from '@/global/business';
|
||||||
@ -432,7 +432,6 @@ const router = useRouter();
|
|||||||
const activeName = ref(i18n.global.t('app.installed'));
|
const activeName = ref(i18n.global.t('app.installed'));
|
||||||
const mode = ref('installed');
|
const mode = ref('installed');
|
||||||
const moreTag = ref('');
|
const moreTag = ref('');
|
||||||
const language = getLanguage();
|
|
||||||
const defaultLink = ref('');
|
const defaultLink = ref('');
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
@ -185,13 +185,11 @@ import { changeLauncherStatus, loadAppLauncher, loadAppLauncherOption } from '@/
|
|||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { GlobalStore } from '@/store';
|
import { GlobalStore } from '@/store';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { getLanguage } from '@/utils/util';
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { toFolder } from '@/global/business';
|
import { toFolder } from '@/global/business';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const language = getLanguage();
|
|
||||||
const globalStore = GlobalStore();
|
const globalStore = GlobalStore();
|
||||||
|
|
||||||
let loading = ref(false);
|
let loading = ref(false);
|
||||||
|
@ -1,50 +1,49 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div class="w-full h-full flex items-center justify-center px-8 py-6">
|
||||||
<div v-if="mfaShow">
|
<div v-loading="loading" class="w-full flex-grow flex flex-col">
|
||||||
<div class="login-form">
|
<div v-if="mfaShow">
|
||||||
<el-form @submit.prevent>
|
<el-form @submit.prevent>
|
||||||
<div class="login-title">{{ $t('commons.login.mfaTitle') }}</div>
|
<div class="flex flex-col justify-center items-center mb-6">
|
||||||
<el-form-item class="no-border">
|
<div class="text-2xl font-medium text-gray-900 text-center">
|
||||||
<el-input
|
{{ $t('commons.login.mfaTitle') }}
|
||||||
size="default"
|
</div>
|
||||||
:placeholder="$t('commons.login.mfaCode')"
|
</div>
|
||||||
v-model.trim="mfaLoginForm.code"
|
|
||||||
@input="mfaLogin(true)"
|
<div class="space-y-6 flex-grow">
|
||||||
>
|
<el-form-item>
|
||||||
<template #prefix>
|
<el-input
|
||||||
<el-icon class="el-input__icon">
|
size="large"
|
||||||
<Finished />
|
:placeholder="$t('commons.login.mfaCode')"
|
||||||
</el-icon>
|
v-model.trim="mfaLoginForm.code"
|
||||||
</template>
|
@input="mfaLogin(true)"
|
||||||
</el-input>
|
></el-input>
|
||||||
<span v-if="errMfaInfo" class="input-error" style="line-height: 14px">
|
<div class="h-1">
|
||||||
{{ $t('commons.login.errorMfaInfo') }}
|
<span v-if="errMfaInfo" class="input-error">
|
||||||
</span>
|
{{ $t('commons.login.errorMfaInfo') }}
|
||||||
</el-form-item>
|
</span>
|
||||||
<el-form-item>
|
</div>
|
||||||
<el-button
|
</el-form-item>
|
||||||
@focus="mfaButtonFocused = true"
|
<el-form-item>
|
||||||
@blur="mfaButtonFocused = false"
|
<el-button
|
||||||
class="login-button"
|
@focus="mfaButtonFocused = true"
|
||||||
type="primary"
|
@blur="mfaButtonFocused = false"
|
||||||
size="default"
|
class="w-full"
|
||||||
round
|
type="primary"
|
||||||
@click="mfaLogin(false)"
|
@click="mfaLogin(false)"
|
||||||
>
|
>
|
||||||
{{ $t('commons.button.verify') }}
|
{{ $t('commons.button.verify') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div v-else>
|
||||||
<div v-else>
|
|
||||||
<div class="login-form">
|
|
||||||
<el-form ref="loginFormRef" :model="loginForm" size="default" :rules="loginRules">
|
<el-form ref="loginFormRef" :model="loginForm" size="default" :rules="loginRules">
|
||||||
<div class="login-form-header">
|
<div class="flex justify-between items-center mb-6">
|
||||||
<div class="title cursor-pointer">{{ $t('commons.button.login') }}</div>
|
<div class="text-2xl font-medium text-gray-900">{{ $t('commons.button.login') }}</div>
|
||||||
<div class="cursor-pointer">
|
<div class="cursor-pointer">
|
||||||
<el-dropdown @command="handleCommand">
|
<el-dropdown @command="handleCommand">
|
||||||
<span>
|
<span class="flex items-center space-x-1">
|
||||||
{{ dropdownText }}
|
{{ dropdownText }}
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<arrow-down />
|
<arrow-down />
|
||||||
@ -70,75 +69,85 @@
|
|||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item prop="name" class="no-border">
|
<div class="space-y-6 flex-grow">
|
||||||
<el-input
|
<el-form-item prop="name" class="w-full">
|
||||||
v-model.trim="loginForm.name"
|
<el-input
|
||||||
:placeholder="$t('commons.login.username')"
|
v-model.trim="loginForm.name"
|
||||||
class="form-input"
|
:placeholder="$t('commons.login.username')"
|
||||||
>
|
class="w-full"
|
||||||
<template #prefix>
|
size="large"
|
||||||
<el-icon class="el-input__icon">
|
></el-input>
|
||||||
<user />
|
|
||||||
</el-icon>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="password" class="no-border">
|
|
||||||
<el-input
|
|
||||||
type="password"
|
|
||||||
clearable
|
|
||||||
v-model.trim="loginForm.password"
|
|
||||||
show-password
|
|
||||||
:placeholder="$t('commons.login.password')"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<el-icon class="el-input__icon">
|
|
||||||
<lock />
|
|
||||||
</el-icon>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<span v-if="errAuthInfo" class="input-error" style="line-height: 14px">
|
|
||||||
{{ $t('commons.login.errorAuthInfo') }}
|
|
||||||
</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="!globalStore.ignoreCaptcha" prop="captcha" class="login-captcha">
|
|
||||||
<el-input v-model.trim="loginForm.captcha" :placeholder="$t('commons.login.captchaHelper')">
|
|
||||||
<template #prefix>
|
|
||||||
<svg-icon style="font-size: 7px" iconName="p-yanzhengma1"></svg-icon>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<img
|
|
||||||
v-if="captcha.imagePath"
|
|
||||||
:src="captcha.imagePath"
|
|
||||||
:alt="$t('commons.login.captchaHelper')"
|
|
||||||
@click="loginVerify()"
|
|
||||||
/>
|
|
||||||
<span v-if="errCaptcha" class="input-error" style="line-height: 14px">
|
|
||||||
{{ $t('commons.login.errorCaptcha') }}
|
|
||||||
</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button
|
|
||||||
@click="login(loginFormRef)"
|
|
||||||
@focus="loginButtonFocused = true"
|
|
||||||
@blur="loginButtonFocused = false"
|
|
||||||
class="login-button"
|
|
||||||
type="primary"
|
|
||||||
size="default"
|
|
||||||
round
|
|
||||||
>
|
|
||||||
{{ $t('commons.button.login') }}
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<template v-if="!isIntl">
|
|
||||||
<el-form-item prop="agreeLicense">
|
|
||||||
<el-checkbox v-model="loginForm.agreeLicense">
|
|
||||||
<template #default>
|
|
||||||
<span class="agree" v-html="$t('commons.login.licenseHelper')"></span>
|
|
||||||
</template>
|
|
||||||
</el-checkbox>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
<el-form-item prop="password" class="w-full">
|
||||||
|
<el-input
|
||||||
|
type="password"
|
||||||
|
v-model.trim="loginForm.password"
|
||||||
|
class="w-full"
|
||||||
|
size="large"
|
||||||
|
:placeholder="$t('commons.login.password')"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="12" v-if="!globalStore.ignoreCaptcha">
|
||||||
|
<el-form-item prop="captcha">
|
||||||
|
<el-input
|
||||||
|
v-model.trim="loginForm.captcha"
|
||||||
|
size="large"
|
||||||
|
:placeholder="$t('commons.login.captchaHelper')"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12" v-if="!globalStore.ignoreCaptcha">
|
||||||
|
<img
|
||||||
|
class="w-full h-10"
|
||||||
|
v-if="captcha.imagePath"
|
||||||
|
:src="captcha.imagePath"
|
||||||
|
:alt="$t('commons.login.captchaHelper')"
|
||||||
|
@click="loginVerify()"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" class="h-1">
|
||||||
|
<span v-show="errCaptcha" class="input-error">
|
||||||
|
{{ $t('commons.login.errorCaptcha') }}
|
||||||
|
</span>
|
||||||
|
<span v-show="errAuthInfo" class="input-error">
|
||||||
|
{{ $t('commons.login.errorAuthInfo') }}
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
@click="login(loginFormRef)"
|
||||||
|
@focus="loginButtonFocused = true"
|
||||||
|
@blur="loginButtonFocused = false"
|
||||||
|
class="w-full"
|
||||||
|
type="primary"
|
||||||
|
size="default"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.login') }}
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<template v-if="!isIntl">
|
||||||
|
<el-form-item prop="agreeLicense">
|
||||||
|
<el-checkbox v-model="loginForm.agreeLicense">
|
||||||
|
<template #default>
|
||||||
|
<span>
|
||||||
|
{{ $t('commons.button.agree') }}
|
||||||
|
<a
|
||||||
|
class="agree"
|
||||||
|
href="https://www.fit2cloud.com/legal/licenses.html"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{{ $t('commons.login.licenseHelper') }}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-checkbox>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="demo">
|
<div class="demo">
|
||||||
<span v-if="isDemo">
|
<span v-if="isDemo">
|
||||||
@ -146,28 +155,28 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<DialogPro v-model="open" center size="w-90">
|
<DialogPro v-model="open" center size="w-90">
|
||||||
<el-row type="flex" justify="center">
|
<el-row type="flex" justify="center">
|
||||||
<span class="text-base mb-4">
|
<span class="text-base mb-4">
|
||||||
{{ $t('commons.login.agreeTitle') }}
|
{{ $t('commons.login.agreeTitle') }}
|
||||||
</span>
|
</span>
|
||||||
</el-row>
|
</el-row>
|
||||||
<div>
|
<div>
|
||||||
<span v-html="$t('commons.login.agreeContent')"></span>
|
<span v-html="$t('commons.login.agreeContent')"></span>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer login-footer-btn">
|
<span class="dialog-footer login-footer-btn">
|
||||||
<el-button @click="open = false">
|
<el-button @click="open = false">
|
||||||
{{ $t('commons.button.notAgree') }}
|
{{ $t('commons.button.notAgree') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" @click="agreeWithLogin()">
|
<el-button type="primary" @click="agreeWithLogin()">
|
||||||
{{ $t('commons.button.agree') }}
|
{{ $t('commons.button.agree') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</DialogPro>
|
</DialogPro>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -319,22 +328,8 @@ const login = (formEl: FormInstance | undefined) => {
|
|||||||
isLoggingIn = true;
|
isLoggingIn = true;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await loginApi(requestLoginForm);
|
const res = await loginApi(requestLoginForm);
|
||||||
if (res.code === 406) {
|
|
||||||
if (res.message === 'ErrCaptchaCode') {
|
|
||||||
loginForm.captcha = '';
|
|
||||||
errCaptcha.value = true;
|
|
||||||
errAuthInfo.value = false;
|
|
||||||
}
|
|
||||||
if (res.message === 'ErrAuth') {
|
|
||||||
globalStore.ignoreCaptcha = false;
|
|
||||||
errCaptcha.value = false;
|
|
||||||
errAuthInfo.value = true;
|
|
||||||
}
|
|
||||||
loginVerify();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
globalStore.ignoreCaptcha = true;
|
globalStore.ignoreCaptcha = true;
|
||||||
if (res.data.mfaStatus === 'enable') {
|
if (res.data.mfaStatus === 'Enable') {
|
||||||
mfaShow.value = true;
|
mfaShow.value = true;
|
||||||
errMfaInfo.value = false;
|
errMfaInfo.value = false;
|
||||||
return;
|
return;
|
||||||
@ -346,7 +341,20 @@ const login = (formEl: FormInstance | undefined) => {
|
|||||||
MsgSuccess(i18n.t('commons.msg.loginSuccess'));
|
MsgSuccess(i18n.t('commons.msg.loginSuccess'));
|
||||||
loadDataFromDB();
|
loadDataFromDB();
|
||||||
router.push({ name: 'home' });
|
router.push({ name: 'home' });
|
||||||
} catch (error) {
|
} catch (res) {
|
||||||
|
if (res.code === 401) {
|
||||||
|
if (res.message === 'ErrCaptchaCode') {
|
||||||
|
loginForm.captcha = '';
|
||||||
|
errCaptcha.value = true;
|
||||||
|
errAuthInfo.value = false;
|
||||||
|
}
|
||||||
|
if (res.message === 'ErrAuth') {
|
||||||
|
globalStore.ignoreCaptcha = false;
|
||||||
|
errCaptcha.value = false;
|
||||||
|
errAuthInfo.value = true;
|
||||||
|
console.log('11111');
|
||||||
|
}
|
||||||
|
}
|
||||||
loginVerify();
|
loginVerify();
|
||||||
} finally {
|
} finally {
|
||||||
isLoggingIn = false;
|
isLoggingIn = false;
|
||||||
@ -361,18 +369,23 @@ const mfaLogin = async (auto: boolean) => {
|
|||||||
isLoggingIn = true;
|
isLoggingIn = true;
|
||||||
mfaLoginForm.name = loginForm.name;
|
mfaLoginForm.name = loginForm.name;
|
||||||
mfaLoginForm.password = loginForm.password;
|
mfaLoginForm.password = loginForm.password;
|
||||||
const res = await mfaLoginApi(mfaLoginForm);
|
try {
|
||||||
if (res.code === 406) {
|
await mfaLoginApi(mfaLoginForm);
|
||||||
errMfaInfo.value = true;
|
globalStore.setLogStatus(true);
|
||||||
|
menuStore.setMenuList([]);
|
||||||
|
tabsStore.removeAllTabs();
|
||||||
|
MsgSuccess(i18n.t('commons.msg.loginSuccess'));
|
||||||
|
loadDataFromDB();
|
||||||
|
router.push({ name: 'home' });
|
||||||
|
} catch (res) {
|
||||||
|
if (res.code === 401) {
|
||||||
|
errMfaInfo.value = true;
|
||||||
|
isLoggingIn = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
isLoggingIn = false;
|
isLoggingIn = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
globalStore.setLogStatus(true);
|
|
||||||
menuStore.setMenuList([]);
|
|
||||||
tabsStore.removeAllTabs();
|
|
||||||
MsgSuccess(i18n.t('commons.msg.loginSuccess'));
|
|
||||||
loadDataFromDB();
|
|
||||||
router.push({ name: 'home' });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const loginVerify = async () => {
|
const loginVerify = async () => {
|
||||||
@ -430,9 +443,28 @@ onMounted(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.login-form {
|
.agree {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.agree:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-button) {
|
||||||
|
height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__inner) {
|
||||||
|
-webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
|
||||||
|
transition: background-color 50000s ease-in-out 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-row) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!-- <style scoped lang='scss' > .login-form {
|
||||||
padding: 0 40px;
|
padding: 0 40px;
|
||||||
.hide {
|
.hide {
|
||||||
width: 0;
|
width: 0;
|
||||||
@ -601,3 +633,4 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
-->
|
||||||
|
@ -1,5 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="flex items-center justify-center min-h-screen relative bg-gray-100">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||||
|
:style="{ backgroundImage: `url(${backgroundImage})` }"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
:style="{ opacity: backgroundOpacity }"
|
||||||
|
class="w-[45%] min-h-[480px] bg-white rounded-lg shadow-lg relative z-10 border border-gray-200 flex overflow-hidden"
|
||||||
|
>
|
||||||
|
<div class="grid md:grid-cols-2 gap-4 items-stretch w-full">
|
||||||
|
<div class="flex flex-col justify-center items-center w-full p-4">
|
||||||
|
<img :src="logoImage" class="max-w-full max-h-full object-contain" />
|
||||||
|
</div>
|
||||||
|
<div class="hidden md:block w-px bg-gray-200 absolute left-1/2 top-4 bottom-4"></div>
|
||||||
|
<div class="hidden md:flex items-center justify-center p-4">
|
||||||
|
<LoginForm ref="loginRef"></LoginForm>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div>
|
||||||
<div class="login-background" v-loading="loading">
|
<div class="login-background" v-loading="loading">
|
||||||
<div class="login-wrapper">
|
<div class="login-wrapper">
|
||||||
<div :class="screenWidth > 1110 ? 'left inline-block' : ''">
|
<div :class="screenWidth > 1110 ? 'left inline-block' : ''">
|
||||||
@ -15,7 +35,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="login">
|
<script setup lang="ts" name="login">
|
||||||
@ -28,6 +48,9 @@ import { getXpackSettingForTheme } from '@/utils/xpack';
|
|||||||
|
|
||||||
const gStore = GlobalStore();
|
const gStore = GlobalStore();
|
||||||
const loading = ref();
|
const loading = ref();
|
||||||
|
const backgroundOpacity = ref(1);
|
||||||
|
const backgroundImage = ref(new URL('', import.meta.url).href);
|
||||||
|
const logoImage = ref(new URL('@/assets/images/1panel-login.png', import.meta.url).href);
|
||||||
|
|
||||||
const mySafetyCode = defineProps({
|
const mySafetyCode = defineProps({
|
||||||
code: {
|
code: {
|
||||||
@ -69,7 +92,7 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<!-- <style scoped lang="scss">
|
||||||
@mixin login-center {
|
@mixin login-center {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -153,4 +176,4 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style> -->
|
||||||
|
@ -88,6 +88,9 @@ interface DialogProps {
|
|||||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||||
const acceptParams = (params: DialogProps): void => {
|
const acceptParams = (params: DialogProps): void => {
|
||||||
form.interval = params.interval;
|
form.interval = params.interval;
|
||||||
|
if (params.interval == 0) {
|
||||||
|
form.interval = 30;
|
||||||
|
}
|
||||||
loadMfaCode();
|
loadMfaCode();
|
||||||
drawerVisible.value = true;
|
drawerVisible.value = true;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user