yb 10 месяцев назад
Родитель
Сommit
080dee107d

+ 2 - 1
src/layout/components/LocaleDropdown/index.ts

@@ -1,3 +1,4 @@
 import LocaleDropdown from './src/LocaleDropdown.vue'
+import LocaleSelect from './src/LocaleSelect.vue'
 
-export { LocaleDropdown }
+export { LocaleDropdown, LocaleSelect }

+ 48 - 0
src/layout/components/LocaleDropdown/src/LocaleSelect.vue

@@ -0,0 +1,48 @@
+<script lang="ts" setup>
+import { useLocaleStore } from '@/store/modules/locale'
+import { useLocale } from '@/hooks/web/useLocale'
+import { propTypes } from '@/utils/propTypes'
+import { useDesign } from '@/hooks/web/useDesign'
+
+defineOptions({ name: 'LocaleSelect' }) // 修改组件名称
+
+const { getPrefixCls } = useDesign()
+
+const prefixCls = getPrefixCls('locale-select') // 修改类名前缀
+
+defineProps({
+  color: propTypes.string.def('')
+})
+
+const localeStore = useLocaleStore()
+
+const langMap = computed(() => localeStore.getLocaleMap)
+
+const currentLang = computed({
+  get: () => localeStore.getCurrentLocale.lang,
+  set: (lang: LocaleType) => {
+    if (lang === unref(currentLang)) return
+    // 需要重新加载页面让整个语言多初始化
+    window.location.reload()
+    localeStore.setCurrentLocale({
+      lang
+    })
+    const { changeLocale } = useLocale()
+    changeLocale(lang)
+  }
+})
+</script>
+
+<template>
+  <ElSelect
+    :class="prefixCls"
+    v-model="currentLang"
+  >
+    <ElOption
+      v-for="item in langMap"
+      :key="item.lang"
+      :label="item.name"
+      :value="item.lang"
+    />
+  </ElSelect>
+</template>

+ 1 - 1
src/layout/components/Menu/src/Menu.vue

@@ -144,7 +144,7 @@ $prefix-cls: #{$namespace}-menu;
 
     // 设置子菜单悬停的高亮和背景色
     .#{$elNamespace}-sub-menu__title,
-    .#{$elNamespace}-menu-item {
+    .#{$elNamespace}-menu-item {            
       &:hover {
         color: var(--left-menu-text-active-color) !important;
         background-color: var(--left-menu-bg-color) !important;

+ 0 - 1
src/layout/components/Menu/src/components/useRenderMenuTitle.tsx

@@ -6,7 +6,6 @@ export const useRenderMenuTitle = () => {
   const renderMenuTitle = (meta: RouteMeta) => {
     const { t } = useI18n()
     const { title = 'Please set title', icon } = meta
-    console.log("🚀 ~ renderMenuTitle ~ title:", title)
 
     return icon ? (
       <>

+ 2 - 1
src/store/modules/permission.ts

@@ -38,7 +38,8 @@ export const usePermissionStore = defineStore('permission', {
         if (wsCache.get(CACHE_KEY.ROLE_ROUTERS)) {
           res = wsCache.get(CACHE_KEY.ROLE_ROUTERS) as AppCustomRouteRecordRaw[]
         }
-        const routerMap: AppRouteRecordRaw[] = generateRoute(res)
+        const lang = wsCache.get(CACHE_KEY.LANG)
+        const routerMap: AppRouteRecordRaw[] = generateRoute(res,lang)
         // 动态路由,404一定要放到最后面
         this.addRouters = routerMap.concat([
           {

+ 20 - 20
src/utils/routerHelper.ts

@@ -61,20 +61,30 @@ export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormal
 }
 
 // 后端控制路由生成
-export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] => {
+export const generateRoute = (routes: AppCustomRouteRecordRaw[], lang): AppRouteRecordRaw[] => {
   const res: AppRouteRecordRaw[] = []
   const modulesRoutesKeys = Object.keys(modules)
   for (const route of routes) {
     // 1. 生成 meta 菜单元数据
+    let title = route.nameEn
+    switch (lang) {
+      case 'zh-CN':
+        title = route.name
+        break
+      case 'en':
+        title = route.nameEn
+        break
+      case 'ja':
+        title = route.nameJp
+        break
+    }
+
     const meta = {
-      title: route.name,
+      title: title,
       icon: route.icon,
       hidden: !route.visible,
       noCache: !route.keepAlive,
-      alwaysShow:
-        route.children &&
-        route.children.length === 1 &&
-        (route.alwaysShow !== undefined ? route.alwaysShow : true)
+      alwaysShow: route.children && route.children.length === 1 && (route.alwaysShow !== undefined ? route.alwaysShow : true)
     } as any
     // 特殊逻辑:如果后端配置的 MenuDO.component 包含 ?,则表示需要传递参数
     // 此时,我们需要解析参数,并且将参数放到 meta.query 中
@@ -89,10 +99,7 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord
     // 路由地址转首字母大写驼峰,作为路由名称,适配keepAlive
     let data: AppRouteRecordRaw = {
       path: route.path.indexOf('?') > -1 ? route.path.split('?')[0] : route.path,
-      name:
-        route.componentName && route.componentName.length > 0
-          ? route.componentName
-          : toCamelCase(route.path, true),
+      name: route.componentName && route.componentName.length > 0 ? route.componentName : toCamelCase(route.path, true),
       redirect: route.redirect,
       meta: meta
     }
@@ -105,10 +112,7 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord
       meta.alwaysShow = true
       const childrenData: AppRouteRecordRaw = {
         path: '',
-        name:
-          route.componentName && route.componentName.length > 0
-            ? route.componentName
-            : toCamelCase(route.path, true),
+        name: route.componentName && route.componentName.length > 0 ? route.componentName : toCamelCase(route.path, true),
         redirect: route.redirect,
         meta: meta
       }
@@ -141,7 +145,7 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord
         data.component = modules[modulesRoutesKeys[index]]
       }
       if (route.children) {
-        data.children = generateRoute(route.children)
+        data.children = generateRoute(route.children, lang)
       }
     }
     res.push(data as AppRouteRecordRaw)
@@ -218,11 +222,7 @@ const promoteRouteLevel = (route: AppRouteRecordRaw) => {
 }
 
 // 添加所有子菜单
-const addToChildren = (
-  routes: RouteRecordNormalized[],
-  children: AppRouteRecordRaw[],
-  routeModule: AppRouteRecordRaw
-) => {
+const addToChildren = (routes: RouteRecordNormalized[], children: AppRouteRecordRaw[], routeModule: AppRouteRecordRaw) => {
   for (let index = 0; index < children.length; index++) {
     const child = children[index]
     const route = routes.find((item) => item.name === child.name)

+ 17 - 32
src/views/Login/components/LoginForm.vue

@@ -15,8 +15,13 @@
           <LoginFormTitle style="width: 100%" />
         </el-form-item>
       </el-col>
+      <el-col v-if="locale" :span="24" style="padding-left: 10px; padding-right: 10px">
+        <el-form-item>
+          <LocaleSelect />
+        </el-form-item>
+      </el-col>
       <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
-       <el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantName">
+        <el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantName">
           <el-input
             v-model="loginData.loginForm.tenantName"
             :placeholder="t('login.tenantNamePlaceholder')"
@@ -28,11 +33,7 @@
       </el-col>
       <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
         <el-form-item prop="username">
-          <el-input
-            v-model="loginData.loginForm.username"
-            :placeholder="t('login.usernamePlaceholder')"
-            :prefix-icon="iconAvatar"
-          />
+          <el-input v-model="loginData.loginForm.username" :placeholder="t('login.usernamePlaceholder')" :prefix-icon="iconAvatar" />
         </el-form-item>
       </el-col>
       <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
@@ -47,10 +48,7 @@
           />
         </el-form-item>
       </el-col>
-      <el-col
-        :span="24"
-        style="padding-left: 10px; padding-right: 10px; margin-top: -20px; margin-bottom: -20px"
-      >
+      <el-col :span="24" style="padding-left: 10px; padding-right: 10px; margin-top: -20px; margin-bottom: -20px">
         <el-form-item>
           <el-row justify="space-between" style="width: 100%">
             <el-col :span="6">
@@ -63,23 +61,10 @@
       </el-col>
       <el-col :span="24" style="padding-left: 10px; padding-right: 10px">
         <el-form-item>
-          <XButton
-            :loading="loginLoading"
-            :title="t('login.login')"
-            class="w-[100%]"
-            type="primary"
-            @click="getCode()"
-          />
+          <XButton :loading="loginLoading" :title="t('login.login')" class="w-[100%]" type="primary" @click="getCode()" />
         </el-form-item>
       </el-col>
-      <Verify
-        ref="verify"
-        :captchaType="captchaType"
-        :imgSize="{ width: '400px', height: '200px' }"
-        mode="pop"
-        @success="handleLogin"
-      />
-   
+      <Verify ref="verify" :captchaType="captchaType" :imgSize="{ width: '400px', height: '200px' }" mode="pop" @success="handleLogin" />
     </el-row>
   </el-form>
 </template>
@@ -94,7 +79,8 @@ import * as authUtil from '@/utils/auth'
 import { usePermissionStore } from '@/store/modules/permission'
 import * as LoginApi from '@/api/login'
 import { LoginStateEnum, useFormValid, useLoginState } from './useLogin'
-
+import { LocaleSelect } from '@/layout/components/LocaleDropdown'
+import { useAppStore } from '@/store/modules/app'
 const { t } = useI18n()
 //const message = useMessage()
 const iconAvatar = useIcon({ icon: 'ep:avatar' })
@@ -108,7 +94,8 @@ const redirect = ref<string>('')
 const loginLoading = ref(false)
 const verify = ref()
 const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字
-
+const appStore = useAppStore()
+const locale = computed(() => appStore.getLocale)
 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN)
 
 const LoginRules = {
@@ -124,19 +111,17 @@ const loginData = reactive({
     tenantName: 'yshop',
     //username: 'yshop002',
     //password: '123456789',
-    username: 'admin',
-    password: 'admin123',
+    username: '',
+    password: '',
     captchaVerification: '',
     rememberMe: false
   }
 })
 
-
-
 // 获取验证码
 const getCode = async () => {
   // 情况一,未开启:则直接登录
-  console.log('oginData.captchaEnable:',loginData.captchaEnable)
+  console.log('oginData.captchaEnable:', loginData.captchaEnable)
   if (loginData.captchaEnable === 'false') {
     await handleLogin({})
   } else {

+ 3 - 4
types/router.d.ts

@@ -48,10 +48,7 @@ declare module 'vue-router' {
   }
 }
 
-type Component<T = any> =
-  | ReturnType<typeof defineComponent>
-  | (() => Promise<typeof import('*.vue')>)
-  | (() => Promise<T>)
+type Component<T = any> = ReturnType<typeof defineComponent> | (() => Promise<typeof import('*.vue')>) | (() => Promise<T>)
 
 declare global {
   interface AppRouteRecordRaw extends Omit<RouteRecordRaw, 'meta'> {
@@ -67,6 +64,8 @@ declare global {
   interface AppCustomRouteRecordRaw extends Omit<RouteRecordRaw, 'meta'> {
     icon: any
     name: string
+    nameEn: string
+    nameJp: string
     meta: RouteMeta
     component: string
     componentName?: string