Merge pull request #346 from tongque0/main

feat:完成layout部分国际化
This commit is contained in:
wangdan-fit2cloud 2024-05-06 10:27:19 +08:00 committed by GitHub
commit 71fc0e5603
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 113 additions and 38 deletions

View File

@ -16,23 +16,23 @@
> >
<div class="flex align-center cursor"> <div class="flex align-center cursor">
<AppIcon iconName="app-reading" class="mr-16 ml-8" style="font-size: 24px"></AppIcon> <AppIcon iconName="app-reading" class="mr-16 ml-8" style="font-size: 24px"></AppIcon>
<span>用户手册</span> <span>{{ $t("layout.topbar.wiki") }}</span>
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" class="mb-16" @click="toUrl('https://github.com/1Panel-dev/MaxKB')"> <el-card shadow="hover" class="mb-16" @click="toUrl('https://github.com/1Panel-dev/MaxKB')">
<div class="flex align-center cursor"> <div class="flex align-center cursor">
<AppIcon iconName="app-github" class="mr-16 ml-8" style="font-size: 24px"></AppIcon> <AppIcon iconName="app-github" class="mr-16 ml-8" style="font-size: 24px"></AppIcon>
<span>项目地址</span> <span>{{ $t("layout.topbar.github") }}</span>
</div> </div>
</el-card> </el-card>
<el-card shadow="hover" class="mb-16" @click="toUrl('https://bbs.fit2cloud.com/c/mk/11')"> <el-card shadow="hover" class="mb-16" @click="toUrl('https://bbs.fit2cloud.com/c/mk/11')">
<div class="flex align-center cursor"> <div class="flex align-center cursor">
<AppIcon iconName="app-help" class="mr-16 ml-8" style="font-size: 24px"></AppIcon> <AppIcon iconName="app-help" class="mr-16 ml-8" style="font-size: 24px"></AppIcon>
<span>论坛求助</span> <span>{{ $t("layout.topbar.forum") }}</span>
</div> </div>
</el-card> </el-card>
</div> </div>
<div class="text-center">版本号{{ version }}</div> <div class="text-center">{{ $t("layout.topbar.version") }}:{{ version }}</div>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">

View File

@ -1,18 +1,18 @@
<template> <template>
<el-dialog v-model="resetPasswordDialog" title="修改密码"> <el-dialog v-model="resetPasswordDialog" :title="$t('layout.topbar.avatar.resetPassword')">
<el-form <el-form
class="reset-password-form mb-24" class="reset-password-form mb-24"
ref="resetPasswordFormRef" ref="resetPasswordFormRef"
:model="resetPasswordForm" :model="resetPasswordForm"
:rules="rules" :rules="rules"
> >
<p class="mb-8 lighter">新密码</p> <p class="mb-8 lighter">{{ $t("layout.topbar.avatar.dialog.newPassword") }}</p>
<el-form-item prop="password" style="margin-bottom: 8px"> <el-form-item prop="password" style="margin-bottom: 8px">
<el-input <el-input
type="password" type="password"
class="input-item" class="input-item"
v-model="resetPasswordForm.password" v-model="resetPasswordForm.password"
placeholder="请输入密码" :placeholder="$t('layout.topbar.avatar.dialog.enterPassword')"
show-password show-password
> >
</el-input> </el-input>
@ -22,24 +22,24 @@
type="password" type="password"
class="input-item" class="input-item"
v-model="resetPasswordForm.re_password" v-model="resetPasswordForm.re_password"
placeholder="请输入确认密码" :placeholder="$t('layout.topbar.avatar.dialog.confirmPassword')"
show-password show-password
> >
</el-input> </el-input>
</el-form-item> </el-form-item>
<p class="mb-8 lighter">使用邮箱</p> <p class="mb-8 lighter">{{ $t("layout.topbar.avatar.dialog.useEmail") }}</p>
<el-form-item style="margin-bottom: 8px"> <el-form-item style="margin-bottom: 8px">
<el-input <el-input
class="input-item" class="input-item"
:disabled="true" :disabled="true"
v-bind:modelValue="user.userInfo?.email" v-bind:modelValue="user.userInfo?.email"
placeholder="请输入邮箱" :placeholder="$t('layout.topbar.avatar.dialog.enterEmail')"
> >
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code"> <el-form-item prop="code">
<div class="flex-between w-full"> <div class="flex-between w-full">
<el-input class="code-input" v-model="resetPasswordForm.code" placeholder="请输入验证码"> <el-input class="code-input" v-model="resetPasswordForm.code" :placeholder="$t('layout.topbar.avatar.dialog.enterVerificationCode')">
</el-input> </el-input>
<el-button <el-button
:disabled="isDisabled" :disabled="isDisabled"
@ -47,15 +47,15 @@
@click="sendEmail" @click="sendEmail"
:loading="loading" :loading="loading"
> >
{{ isDisabled ? `重新发送(${time}s` : '获取验证码' }}</el-button {{ isDisabled ? $t('layout.topbar.avatar.dialog.resend', { time }) : $t('layout.topbar.avatar.dialog.getVerificationCode') }}
> </el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="resetPasswordDialog = false"> 取消 </el-button> <el-button @click="resetPasswordDialog = false">{{ $t('layout.topbar.avatar.dialog.cancel') }}</el-button>
<el-button type="primary" @click="resetPassword"> 保存 </el-button> <el-button type="primary" @click="resetPassword"> {{ $t('layout.topbar.avatar.dialog.save') }} </el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -68,6 +68,7 @@ import { MsgSuccess } from '@/utils/message'
import UserApi from '@/api/user' import UserApi from '@/api/user'
import useStore from '@/stores' import useStore from '@/stores'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { t } from '@/locales'
const router = useRouter() const router = useRouter()
const { user } = useStore() const { user } = useStore()
@ -86,36 +87,37 @@ const isDisabled = ref<boolean>(false)
const time = ref<number>(60) const time = ref<number>(60)
const rules = ref<FormRules<ResetCurrentUserPasswordRequest>>({ const rules = ref<FormRules<ResetCurrentUserPasswordRequest>>({
code: [{ required: true, message: '请输入验证码' }], // @ts-ignore
code: [{ required: true, message: t('layout.topbar.avatar.dialog.enterVerificationCode'), trigger: 'blur' }],
password: [ password: [
{ {
required: true, required: true,
message: '请输入密码', message: t('layout.topbar.avatar.dialog.enterPassword'),
trigger: 'blur' trigger: 'blur'
}, },
{ {
min: 6, min: 6,
max: 20, max: 20,
message: '长度在 6 到 20 个字符', message: t('layout.topbar.avatar.dialog.passwordLength'),
trigger: 'blur' trigger: 'blur'
} }
], ],
re_password: [ re_password: [
{ {
required: true, required: true,
message: '请输入确认密码', message: t('layout.topbar.avatar.dialog.confirmPassword'),
trigger: 'blur' trigger: 'blur'
}, },
{ {
min: 6, min: 6,
max: 20, max: 20,
message: '长度在 6 到 20 个字符', message: t('layout.topbar.avatar.dialog.passwordLength'),
trigger: 'blur' trigger: 'blur'
}, },
{ {
validator: (rule, value, callback) => { validator: (rule, value, callback) => {
if (resetPasswordForm.value.password != resetPasswordForm.value.re_password) { if (resetPasswordForm.value.password != resetPasswordForm.value.re_password) {
callback(new Error('密码不一致')) callback(new Error(t('layout.topbar.avatar.dialog.passwordMismatch')))
} else { } else {
callback() callback()
} }
@ -129,7 +131,7 @@ const rules = ref<FormRules<ResetCurrentUserPasswordRequest>>({
*/ */
const sendEmail = () => { const sendEmail = () => {
UserApi.sendEmailToCurrent(loading).then(() => { UserApi.sendEmailToCurrent(loading).then(() => {
MsgSuccess('发送验证码成功') MsgSuccess(t('verificationCodeSentSuccess'))
isDisabled.value = true isDisabled.value = true
handleTimeChange() handleTimeChange()
}) })
@ -174,5 +176,7 @@ const close = () => {
} }
defineExpose({ open, close }) defineExpose({ open, close })
</script> </script>
<style lang="scss" scope></style> <style lang="scss" scope></style>

View File

@ -21,10 +21,10 @@
</p> </p>
</div> </div>
<el-dropdown-item class="border-t p-8" @click="openResetPassword"> <el-dropdown-item class="border-t p-8" @click="openResetPassword">
修改密码 {{ $t("layout.topbar.avatar.resetPassword") }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item class="border-t" @click="openAbout"> 关于 </el-dropdown-item> <el-dropdown-item class="border-t" @click="openAbout"> {{ $t("layout.topbar.avatar.about") }} </el-dropdown-item>
<el-dropdown-item class="border-t" @click="logout"> 退出 </el-dropdown-item> <el-dropdown-item class="border-t" @click="logout"> {{ $t("layout.topbar.avatar.logout") }} </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>

View File

@ -19,7 +19,7 @@
@click="toUrl('https://github.com/1Panel-dev/MaxKB')" @click="toUrl('https://github.com/1Panel-dev/MaxKB')"
></AppIcon> ></AppIcon>
</el-tooltip> </el-tooltip>
<el-tooltip effect="dark" :content="$t('layout.topbar.handbook')" placement="top"> <el-tooltip effect="dark" :content="$t('layout.topbar.wiki')" placement="top">
<AppIcon <AppIcon
iconName="app-reading" iconName="app-reading"
class="cursor color-secondary mr-8 ml-8" class="cursor color-secondary mr-8 ml-8"

View File

@ -1,13 +1,17 @@
<template> <template>
<div <div class="menu-item-container flex-center h-full" :class="isActive ? 'active' : ''"
class="menu-item-container flex-center h-full" @click="router.push({ name: menu.name })">
:class="isActive ? 'active' : ''"
@click="router.push({ name: menu.name })"
>
<!-- <div class="icon"> <!-- <div class="icon">
<AppIcon :iconName="menu.meta ? (menu.meta.icon as string) : '404'" /> <AppIcon :iconName="menu.meta ? (menu.meta.icon as string) : '404'" />
</div> --> </div> -->
<div class="title">{{ menu.meta?.title }}</div> <div class="title">
{{
$te(`layout.topbar.MenuItem.${String(props.menu.name)}`)
? $t(`layout.topbar.MenuItem.${String(props.menu.name)}`)
: menu.meta?.title
}}
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -31,11 +35,13 @@ const isActive = computed(() => {
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
position: relative; position: relative;
.icon { .icon {
font-size: 15px; font-size: 15px;
margin-right: 5px; margin-right: 5px;
margin-top: 2px; margin-top: 2px;
} }
&:hover { &:hover {
color: var(--el-color-primary); color: var(--el-color-primary);
} }
@ -43,6 +49,7 @@ const isActive = computed(() => {
.active { .active {
color: var(--el-color-primary); color: var(--el-color-primary);
&::after { &::after {
position: absolute; position: absolute;
bottom: 0; bottom: 0;

View File

@ -1,7 +1,39 @@
export default { export default {
breadcrumb: {
},
sidebar: {
},
topbar: { topbar: {
github:"Github", github: "Project address",
handbook:"Handbook", wiki: "User manual",
forum:"Forum" forum: "Forum for help",
MenuItem: {
application: "Application",
dataset: "Knowledge base",
setting: "System settings"
},
avatar: {
resetPassword: "Change password",
about: "About",
logout: "Logout",
version:"Version",
dialog:{
newPassword:"New password",
enterPassword: "Please enter new password",
confirmPassword: "Confirm password",
passwordLength:"Password length should be between 6 and 20 characters",
passwordMismatch:"Passwords do not match",
useEmail:"Use email",
enterEmail: "Please enter email",
enterVerificationCode: "Please enter verification code",
getVerificationCode: "Get verification code",
verificationCodeSentSuccess:"Verification code sent successfully",
resend:"Resend",
cancel:"Cancel",
save:"Save",
}
}
}, },
}; };

View File

@ -1,7 +1,39 @@
export default { export default {
breadcrumb: {
},
sidebar: {
},
topbar: { topbar: {
github: "项目地址", github: "项目地址",
handbook:"用户手册", wiki: "用户手册",
forum:"论坛求助" forum: "论坛求助",
MenuItem: {
application: "应用",
dataset: "知识库",
setting: "系统设置"
},
avatar: {
resetPassword: "修改密码",
about: "关于",
logout: "退出",
version:"版本号",
dialog:{
newPassword:"新密码",
enterPassword: "请输入修改密码",
confirmPassword: "确认密码",
passwordLength:"密码长度在 6 到 20 个字符",
passwordMismatch:"两次密码输入不一致",
useEmail:"使用邮箱",
enterEmail: "请输入邮箱",
enterVerificationCode: "请输入验证码",
getVerificationCode: "获取验证码",
verificationCodeSentSuccess:"验证码发送成功",
resend:"重新发送",
cancel:"取消",
save:"保存",
}
}
}, },
}; };