mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 登录页增加语言选项 (#1752)
Refs https://github.com/1Panel-dev/1Panel/issues/1728
This commit is contained in:
parent
b05e5736a6
commit
4d368a4de8
@ -120,6 +120,20 @@ func (b *BaseApi) CheckIsDemo(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, global.CONF.System.IsDemo)
|
helper.SuccessWithData(c, global.CONF.System.IsDemo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Tags Auth
|
||||||
|
// @Summary Load System Language
|
||||||
|
// @Description 获取系统语言设置
|
||||||
|
// @Success 200
|
||||||
|
// @Router /auth/language [get]
|
||||||
|
func (b *BaseApi) GetLanguage(c *gin.Context) {
|
||||||
|
settingInfo, err := settingService.GetSettingInfo()
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, settingInfo.Language)
|
||||||
|
}
|
||||||
|
|
||||||
func saveLoginLogs(c *gin.Context, err error) {
|
func saveLoginLogs(c *gin.Context, err error) {
|
||||||
var logs model.LoginLog
|
var logs model.LoginLog
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -24,6 +24,7 @@ type Login struct {
|
|||||||
Captcha string `json:"captcha"`
|
Captcha string `json:"captcha"`
|
||||||
CaptchaID string `json:"captchaID"`
|
CaptchaID string `json:"captchaID"`
|
||||||
AuthMethod string `json:"authMethod"`
|
AuthMethod string `json:"authMethod"`
|
||||||
|
Language string `json:"language"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MFALogin struct {
|
type MFALogin struct {
|
||||||
|
@ -48,10 +48,12 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err = settingRepo.Update("Language", info.Language); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if mfa.Value == "enable" {
|
if mfa.Value == "enable" {
|
||||||
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)
|
return u.generateSession(c, info.Name, info.AuthMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,5 +17,6 @@ func (s *BaseRouter) InitBaseRouter(Router *gin.RouterGroup) {
|
|||||||
baseRouter.GET("/issafety", baseApi.CheckIsSafety)
|
baseRouter.GET("/issafety", baseApi.CheckIsSafety)
|
||||||
baseRouter.POST("/logout", baseApi.LogOut)
|
baseRouter.POST("/logout", baseApi.LogOut)
|
||||||
baseRouter.GET("/demo", baseApi.CheckIsDemo)
|
baseRouter.GET("/demo", baseApi.CheckIsDemo)
|
||||||
|
baseRouter.GET("/language", baseApi.GetLanguage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -882,6 +882,20 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/auth/language": {
|
||||||
|
"get": {
|
||||||
|
"description": "获取系统语言设置",
|
||||||
|
"tags": [
|
||||||
|
"Auth"
|
||||||
|
],
|
||||||
|
"summary": "Load System Language",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/auth/login": {
|
"/auth/login": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "用户登录",
|
"description": "用户登录",
|
||||||
@ -12541,6 +12555,9 @@ const docTemplate = `{
|
|||||||
"ignoreCaptcha": {
|
"ignoreCaptcha": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"language": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -875,6 +875,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/auth/language": {
|
||||||
|
"get": {
|
||||||
|
"description": "获取系统语言设置",
|
||||||
|
"tags": [
|
||||||
|
"Auth"
|
||||||
|
],
|
||||||
|
"summary": "Load System Language",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/auth/login": {
|
"/auth/login": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "用户登录",
|
"description": "用户登录",
|
||||||
@ -12534,6 +12548,9 @@
|
|||||||
"ignoreCaptcha": {
|
"ignoreCaptcha": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"language": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -1062,6 +1062,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
ignoreCaptcha:
|
ignoreCaptcha:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
language:
|
||||||
|
type: string
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
password:
|
password:
|
||||||
@ -4285,6 +4287,15 @@ paths:
|
|||||||
summary: Load safety status
|
summary: Load safety status
|
||||||
tags:
|
tags:
|
||||||
- Auth
|
- Auth
|
||||||
|
/auth/language:
|
||||||
|
get:
|
||||||
|
description: 获取系统语言设置
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
summary: Load System Language
|
||||||
|
tags:
|
||||||
|
- Auth
|
||||||
/auth/login:
|
/auth/login:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -24,3 +24,7 @@ export const checkIsSafety = (code: string) => {
|
|||||||
export const checkIsDemo = () => {
|
export const checkIsDemo = () => {
|
||||||
return http.get<boolean>('/auth/demo');
|
return http.get<boolean>('/auth/demo');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getLanguage = () => {
|
||||||
|
return http.get<string>(`/auth/language`);
|
||||||
|
};
|
||||||
|
@ -39,8 +39,26 @@
|
|||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="login-form">
|
<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-title">{{ $t('commons.button.login') }}</div>
|
<div class="login-form-header">
|
||||||
|
<div class="title">{{ $t('commons.button.login') }}</div>
|
||||||
|
<div>
|
||||||
|
<el-dropdown @command="handleCommand">
|
||||||
|
<span>
|
||||||
|
{{ dropdownText }}
|
||||||
|
<el-icon>
|
||||||
|
<arrow-down />
|
||||||
|
</el-icon>
|
||||||
|
</span>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item command="zh">中文(简体)</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="tw">中文(繁體)</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="en">English</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<el-form-item prop="name" class="no-border">
|
<el-form-item prop="name" class="no-border">
|
||||||
<el-input
|
<el-input
|
||||||
v-model.trim="loginForm.name"
|
v-model.trim="loginForm.name"
|
||||||
@ -133,14 +151,16 @@
|
|||||||
import { ref, reactive, onMounted } from 'vue';
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import type { ElForm } from 'element-plus';
|
import type { ElForm } from 'element-plus';
|
||||||
import { loginApi, getCaptcha, mfaLoginApi, checkIsDemo } from '@/api/modules/auth';
|
import { loginApi, getCaptcha, mfaLoginApi, checkIsDemo, getLanguage } from '@/api/modules/auth';
|
||||||
import { GlobalStore } from '@/store';
|
import { GlobalStore } from '@/store';
|
||||||
import { MenuStore } from '@/store/modules/menu';
|
import { MenuStore } from '@/store/modules/menu';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const globalStore = GlobalStore();
|
const globalStore = GlobalStore();
|
||||||
const menuStore = MenuStore();
|
const menuStore = MenuStore();
|
||||||
|
const usei18n = useI18n();
|
||||||
|
|
||||||
const errAuthInfo = ref(false);
|
const errAuthInfo = ref(false);
|
||||||
const errCaptcha = ref(false);
|
const errCaptcha = ref(false);
|
||||||
@ -160,6 +180,7 @@ const loginForm = reactive({
|
|||||||
captchaID: '',
|
captchaID: '',
|
||||||
authMethod: '',
|
authMethod: '',
|
||||||
agreeLicense: false,
|
agreeLicense: false,
|
||||||
|
language: 'zh',
|
||||||
});
|
});
|
||||||
const loginRules = reactive({
|
const loginRules = reactive({
|
||||||
name: [{ required: true, message: i18n.global.t('commons.rule.username'), trigger: 'blur' }],
|
name: [{ required: true, message: i18n.global.t('commons.rule.username'), trigger: 'blur' }],
|
||||||
@ -183,8 +204,21 @@ const captcha = reactive({
|
|||||||
|
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
const mfaShow = ref<boolean>(false);
|
const mfaShow = ref<boolean>(false);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const dropdownText = ref('中文(简体)');
|
||||||
|
|
||||||
|
function handleCommand(command: string) {
|
||||||
|
loginForm.language = command;
|
||||||
|
usei18n.locale.value = command;
|
||||||
|
globalStore.updateLanguage(command);
|
||||||
|
if (command === 'zh') {
|
||||||
|
dropdownText.value = '中文(简体)';
|
||||||
|
} else if (command === 'en') {
|
||||||
|
dropdownText.value = 'English';
|
||||||
|
} else if (command === 'tw') {
|
||||||
|
dropdownText.value = '中文(繁體)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const login = (formEl: FormInstance | undefined) => {
|
const login = (formEl: FormInstance | undefined) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
@ -197,6 +231,7 @@ const login = (formEl: FormInstance | undefined) => {
|
|||||||
captcha: loginForm.captcha,
|
captcha: loginForm.captcha,
|
||||||
captchaID: captcha.captchaID,
|
captchaID: captcha.captchaID,
|
||||||
authMethod: '',
|
authMethod: '',
|
||||||
|
language: loginForm.language,
|
||||||
};
|
};
|
||||||
if (!globalStore.ignoreCaptcha && requestLoginForm.captcha == '') {
|
if (!globalStore.ignoreCaptcha && requestLoginForm.captcha == '') {
|
||||||
errCaptcha.value = true;
|
errCaptcha.value = true;
|
||||||
@ -269,8 +304,17 @@ const checkIsSystemDemo = async () => {
|
|||||||
isDemo.value = res.data;
|
isDemo.value = res.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadLanguage = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getLanguage();
|
||||||
|
loginForm.language = res.data;
|
||||||
|
handleCommand(res.data);
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loginVerify();
|
loginVerify();
|
||||||
|
loadLanguage();
|
||||||
document.title = globalStore.themeConfig.panelName;
|
document.title = globalStore.themeConfig.panelName;
|
||||||
loginForm.agreeLicense = globalStore.agreeLicense;
|
loginForm.agreeLicense = globalStore.agreeLicense;
|
||||||
checkIsSystemDemo();
|
checkIsSystemDemo();
|
||||||
@ -380,5 +424,23 @@ onMounted(() => {
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-form-header {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
.title {
|
||||||
|
color: #646a73;
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-select {
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
background: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user