feat: 面包屑组件&国际化配置调整

This commit is contained in:
baiqi 2023-06-28 10:34:15 +08:00 committed by 刘瑞斌
parent 07e5deb6d6
commit e491170747
22 changed files with 234 additions and 180 deletions

View File

@ -26,8 +26,14 @@
*/
listenerRouteChange((newRoute) => {
const { name } = newRoute;
//
if (name === appStore.currentTopMenu.name) {
appStore.setBreadcrumbList(appStore.currentTopMenu?.meta?.breadcrumbs);
} else if ((name as string).includes(appStore.currentTopMenu.name as string)) {
//
const currentRoute = router.currentRoute.value.matched[1].children.find((e) => e.name === name);
appStore.setBreadcrumbList(currentRoute?.meta?.breadcrumbs);
} else {
appStore.setBreadcrumbList([]);
}
@ -51,7 +57,7 @@
color: var(--color-text-brand);
}
&:last-child {
@apply cursor-auto;
@apply cursor-auto font-normal;
color: var(--color-text-2);
}

View File

@ -0,0 +1,6 @@
import type { RouteRecordName } from 'vue-router';
export interface BreadcrumbItem {
name: RouteRecordName;
locale: string;
}

View File

@ -37,12 +37,20 @@
);
function setCurrentTopMenu(key: string) {
const secParent = appStore.topMenus.find((el: RouteRecordRaw) => {
return (el?.name as string).includes(key);
//
const secParentFullSame = appStore.topMenus.find((el: RouteRecordRaw) => {
return key === el?.name;
});
if (secParent) {
appStore.setCurrentTopMenu(secParent);
//
const secParentLike = appStore.topMenus.find((el: RouteRecordRaw) => {
return key.includes(el?.name as string);
});
if (secParentFullSame) {
appStore.setCurrentTopMenu(secParentFullSame);
} else if (secParentLike) {
appStore.setCurrentTopMenu(secParentLike);
}
}

View File

@ -1,35 +0,0 @@
<template>
<a-breadcrumb class="container-breadcrumb">
<a-breadcrumb-item>
<icon-apps />
</a-breadcrumb-item>
<a-breadcrumb-item v-for="item in items" :key="item">
{{ $t(item) }}
</a-breadcrumb-item>
</a-breadcrumb>
</template>
<script lang="ts" setup>
import { PropType } from 'vue';
defineProps({
items: {
type: Array as PropType<string[]>,
default() {
return [];
},
},
});
</script>
<style scoped lang="less">
.container-breadcrumb {
margin: 16px 0;
:deep(.arco-breadcrumb-item) {
color: rgb(var(--gray-6));
&:last-child {
color: rgb(var(--gray-8));
}
}
}
</style>

View File

@ -23,9 +23,10 @@
<style lang="less" scoped>
.page-content {
overflow: hidden;
border-radius: 12px;
background: #ffffff;
@apply overflow-hidden bg-white;
padding: 24px;
border-radius: var(--border-radius-large);
box-shadow: 0 0 10px rgb(120 56 135 / 5%);
}
</style>

View File

@ -1,33 +1,34 @@
import dayjsLocale from 'dayjs/locale/en';
import localeSettings from './settings';
import sys from './sys';
import localeMessageBox from '@/components/pure/message-box/locale/en-US';
import minder from '@/components/pure/minder-editor/locale/en-US';
import localeLogin from '@/views/login/locale/en-US';
import localeTable from '@/components/pure/ms-table/locale/en-US';
import localeApiTest from '@/views/api-test/locale/en-US';
import localeSystem from '@/views/system/locale/en-US';
import baseLocale from '@/views/base/locale/en-US';
const _Cmodules: any = import.meta.glob('../../components/**/locale/en-US.ts', { eager: true });
const _Vmodules: any = import.meta.glob('../../views/**/locale/en-US.ts', { eager: true });
let result = {};
Object.keys(_Cmodules).forEach((key) => {
const defaultModule = _Cmodules[key as any].default;
if (!defaultModule) return;
result = { ...result, ...defaultModule };
});
Object.keys(_Vmodules).forEach((key) => {
const defaultModule = _Vmodules[key as any].default;
if (!defaultModule) return;
result = { ...result, ...defaultModule };
});
export default {
message: {
'menu.apiTest': 'Api Test',
'menu.settings': 'System Settings',
'menu.settings.system': 'System',
'menu.settings.organization': 'Organization',
'menu.settings.usergroup': 'User Group',
'menu.settings.user': 'User',
'menu.settings.organizationAndProject': 'Org & Project',
'menu.settings.system.usergroup': 'User Group',
'menu.settings.system.user': 'User',
'menu.settings.system.organizationAndProject': 'Org & Project',
'menu.settings.system.resourcePool': 'Resource Pool',
'navbar.action.locale': 'Switch to English',
...sys,
...localeSettings,
...localeMessageBox,
...localeLogin,
...minder,
...localeTable,
...localeApiTest,
...localeSystem,
...baseLocale,
...result,
},
dayjsLocale,
dayjsLocaleName: 'en-US',

View File

@ -1 +0,0 @@
export default {};

View File

@ -1,34 +1,37 @@
import dayjsLocale from 'dayjs/locale/zh-cn';
import localeSettings from './settings';
import sys from './sys';
import localeMessageBox from '@/components/pure/message-box/locale/zh-CN';
import minder from '@/components/pure/minder-editor/locale/zh-CN';
import localeLogin from '@/views/login/locale/zh-CN';
import localeTable from '@/components/pure/ms-table/locale/zh-CN';
import localeApiTest from '@/views/api-test/locale/zh-CN';
import localeSystem from '@/views/system/locale/zh-CN';
import baseLocale from '@/views/base/locale/zh-CN';
const _Cmodules: any = import.meta.glob('../../components/**/locale/zh-CN.ts', { eager: true });
const _Vmodules: any = import.meta.glob('../../views/**/locale/zh-CN.ts', { eager: true });
let result = {};
Object.keys(_Cmodules).forEach((key) => {
const defaultModule = _Cmodules[key as any].default;
if (!defaultModule) return;
result = { ...result, ...defaultModule };
});
Object.keys(_Vmodules).forEach((key) => {
const defaultModule = _Vmodules[key as any].default;
if (!defaultModule) return;
result = { ...result, ...defaultModule };
});
export default {
message: {
'menu.apiTest': '接口测试',
'menu.settings': '系统设置',
'menu.settings.system': '系统',
'menu.settings.organization': '组织',
'menu.settings.user': '用户',
'menu.settings.usergroup': '用户组',
'menu.settings.organizationAndProject': '组织与项目',
'menu.settings.system.user': '用户',
'menu.settings.system.usergroup': '用户组',
'menu.settings.system.organizationAndProject': '组织与项目',
'menu.settings.system.resourcePool': '资源池',
'menu.settings.system.resourcePoolDetail': '添加资源池',
'menu.settings.system.resourcePoolEdit': '编辑资源池',
'menu.user': '个人中心',
'navbar.action.locale': '切换为中文',
...sys,
...localeSettings,
...localeMessageBox,
...localeLogin,
...minder,
...localeTable,
...localeApiTest,
...localeSystem,
...baseLocale,
...result,
},
dayjsLocale,
dayjsLocaleName: 'zh-CN',

View File

@ -1 +0,0 @@
export default {};

View File

@ -2,7 +2,6 @@ import { createApp } from 'vue';
import FormCreate from '@form-create/arco-design';
import ArcoVueIcon from '@arco-design/web-vue/es/icon';
import SvgIcon from '@/components/pure/svg-icon/index.vue';
import Breadcrumb from '@/components/pure/breadcrumb/index.vue';
import router from './router';
import store from './store';
import { setupI18n } from './locale';
@ -25,7 +24,6 @@ async function bootstrap() {
app.use(ArcoVueIcon);
app.component('SvgIcon', SvgIcon);
app.component('Breadcrumb', Breadcrumb);
app.use(router);
app.use(directive);

View File

@ -88,7 +88,7 @@ setupMock({
path: 'user',
name: 'settingSystemUser',
meta: {
locale: 'menu.settings.user',
locale: 'menu.settings.system.user',
roles: ['*'],
isTopMenu: true,
},
@ -97,11 +97,28 @@ setupMock({
path: 'usergroup',
name: 'settingSystemUsergroup',
meta: {
locale: 'menu.settings.usergroup',
locale: 'menu.settings.system.usergroup',
roles: ['*'],
isTopMenu: true,
},
},
{
path: 'resourcePool',
name: 'settingSystemResourcePool',
meta: {
locale: 'menu.settings.system.resourcePool',
roles: ['*'],
isTopMenu: true,
},
},
{
path: 'resourcePoolDetail',
name: 'settingSystemResourcePoolDetail',
meta: {
locale: 'menu.settings.system.resourcePoolDetail',
roles: ['*'],
},
},
],
},
],

View File

@ -27,7 +27,7 @@ const System: AppRouteRecordRaw = {
name: 'settingSystemUser',
component: () => import('@/views/system/user/index.vue'),
meta: {
locale: 'menu.settings.user',
locale: 'menu.settings.system.user',
roles: ['*'],
isTopMenu: true,
},
@ -37,11 +37,46 @@ const System: AppRouteRecordRaw = {
name: 'settingSystemUsergroup',
component: () => import('@/views/system/usergroup/index.vue'),
meta: {
locale: 'menu.settings.usergroup',
locale: 'menu.settings.system.usergroup',
roles: ['*'],
isTopMenu: true,
},
},
{
path: 'resourcePool',
name: 'settingSystemResourcePool',
component: () => import('@/views/system/resourcePool/index.vue'),
meta: {
locale: 'menu.settings.system.resourcePool',
roles: ['*'],
isTopMenu: true,
breadcrumbs: [
{
name: 'settingSystemResourcePool',
locale: 'menu.settings.system.resourcePool',
},
],
},
},
{
path: 'resourcePoolDetail',
name: 'settingSystemResourcePoolDetail',
component: () => import('@/views/system/resourcePool/detail.vue'),
meta: {
locale: 'menu.settings.system.resourcePoolDetail',
roles: ['*'],
breadcrumbs: [
{
name: 'settingSystemResourcePool',
locale: 'menu.settings.system.resourcePool',
},
{
name: 'settingSystemResourcePoolDetail',
locale: 'menu.settings.system.resourcePoolDetail',
},
],
},
},
],
},
],

View File

@ -1,11 +1,26 @@
import { defineComponent } from 'vue';
import type { RouteMeta, NavigationGuard } from 'vue-router';
import type { NavigationGuard } from 'vue-router';
import type { BreadcrumbItem } from '@/components/bussiness/ms-breadcrumb/types';
export type Component<T = any> =
| ReturnType<typeof defineComponent>
| (() => Promise<typeof import('*.vue')>)
| (() => Promise<T>);
export interface RouteMeta {
roles?: string[]; // 角色数组
requiresAuth?: boolean; // 是否需要权限,默认需要
icon?: string; // 菜单icon
locale?: string; // 国际化语言单词
hideInMenu?: boolean; // 此路由不在菜单展示
hideChildrenInMenu?: boolean; // 子路由不展示在菜单
activeMenu?: string; // 激活状态
order?: number; // 排序权重
noAffix?: boolean; // tab展示设置设置为true则不在tab列表展示激活页面的tab
ignoreCache?: boolean; // 缓存设置true则不缓存
isTopMenu?: boolean; // 是否为顶部菜单
breadcrumbs?: BreadcrumbItem[]; // 面包屑
}
export interface AppRouteRecordRaw {
path: string;
name?: string | symbol;

View File

@ -5,9 +5,10 @@ import { getMenuList } from '@/api/modules/user';
import { useI18n } from '@/hooks/useI18n';
import { cloneDeep } from 'lodash-es';
import type { AppState, BreadcrumbItem } from './types';
import type { NotificationReturn } from '@arco-design/web-vue/es/notification/interface';
import type { RouteRecordNormalized, RouteRecordRaw } from 'vue-router';
import type { AppState } from './types';
import type { BreadcrumbItem } from '@/components/bussiness/ms-breadcrumb/types';
const useAppStore = defineStore('app', {
state: (): AppState => ({
@ -134,7 +135,7 @@ const useAppStore = defineStore('app', {
this.topMenus = menus ? [...menus] : [];
},
/**
*
*
*/
setCurrentTopMenu(menu: RouteRecordRaw) {
this.currentTopMenu = cloneDeep(menu);

View File

@ -1,9 +1,5 @@
import type { RouteRecordNormalized, RouteRecordRaw, RouteRecordName } from 'vue-router';
export interface BreadcrumbItem {
name: RouteRecordName;
locale: string;
}
import type { RouteRecordNormalized, RouteRecordRaw } from 'vue-router';
import type { BreadcrumbItem } from '@/components/bussiness/ms-breadcrumb/types';
export interface AppState {
theme: string;

View File

@ -1,5 +1,5 @@
<template>
<div class="p-6">
<div>
<div class="mb-4 flex items-center justify-between">
<div>
<a-button class="mr-3" type="primary" @click="showUserModal('create')">{{

View File

@ -1,47 +1,4 @@
export default {
'system': {
userGroup: {
searchHolder: 'Please input user group name',
inSystem: 'In system',
customUserGroup: 'Custom user group',
addSystemUserGroup: 'Add system user group',
addSystemUser: 'Add system user',
addUser: 'Add user',
emptyUserGroup:
'There are currently no custom user groups available. Please click "Create" or "+" above to create a user group',
rename: 'Rename',
changeAuthScope: 'Change auth scope',
delete: 'Delete',
user: 'user',
add: 'Add',
cancel: 'Cancel',
create: 'Create',
createUserGroup: 'create user group',
userGroupName: 'User group name',
authScope: 'Auth scope',
auth: 'Auth',
deleteSuccess: 'Delete success',
revokeSuccess: 'Revoke success',
revoke: 'revoke',
pleaseSelectUser: 'Please select user',
pleaseInputUserGroupName: 'Please input user group name,and not equal to system user group name',
userGroupNameIsExist: `Usergroup {name} is exist`,
pleaseSelectAuthScope: 'Please select auth scope',
userGroupNameIsNotNone: 'User group name is not none',
authScopeIsNotNone: 'Auth scope is not none',
userIsNotNone: 'User is not none',
confirm: 'Confirm',
global: 'Global',
searchPlacehoder: 'Search by ID/Name',
SYSTEM: '系统',
PROJECT: '项目',
ORGANIZATION: '组织',
isDeleteUserGroup: 'Delete or not: {name}?',
beforeDeleteUserGroup:
'After deletion, the project data under the organization will be deleted together. Please operate with caution!',
confirmDelete: 'Confirm delete',
},
},
'system.user.createUser': 'Create User',
'system.user.emailInvite': 'Email Invite',
'system.user.importUser': 'Import User',

View File

@ -1,46 +1,4 @@
export default {
'system': {
userGroup: {
global: '全局用户组',
searchHolder: '请输入用户组名称',
inSystem: '系统内置',
customUserGroup: '自定义用户组',
addSystemUserGroup: '添加系统用户组',
addSystemUser: '添加系统用户',
addUser: '添加成员',
emptyUserGroup: '暂无自定义用户组,请点击上方创建或 “+” 创建用户组',
rename: '重命名',
changeAuthScope: '修改权限范围',
delete: '删除',
user: '成员',
add: '添加',
confirm: '确认',
create: '创建',
cancel: '取消',
createUserGroup: '创建用户组',
userGroupName: '用户组名称',
authScope: '权限范围',
auth: '权限',
deleteSuccess: '删除成功',
revokeSuccess: '撤销成功',
revoke: '撤销',
pleaseSelectUserGroup: '请选择用户组',
pleaseSelectUser: '请选择成员',
userGroupNameIsNotNone: '用户组名称不能为空',
authScopeIsNotNone: '权限范围不能为空',
userIsNotNone: '成员不能为空',
pleaseInputUserGroupName: '请输入用户组名称,且不与其他用户组名称重复',
userGroupNameIsExist: `用户组{name}已存在`,
pleaseSelectAuthScope: '请选择用户组所属的权限范围',
searchPlacehoder: '通过ID/名称搜索',
SYSTEM: '系统',
PROJECT: '项目',
ORGANIZATION: '组织',
isDeleteUserGroup: '是否删除: {name}?',
beforeDeleteUserGroup: '删除后,该组织下的项目数据将一起删除,请谨慎操作!',
confirmDelete: '确认删除',
},
},
'system.user.createUser': '创建用户',
'system.user.emailInvite': '邮箱邀请',
'system.user.importUser': '导入用户',

View File

@ -0,0 +1,45 @@
export default {
system: {
userGroup: {
searchHolder: 'Please input user group name',
inSystem: 'In system',
customUserGroup: 'Custom user group',
addSystemUserGroup: 'Add system user group',
addSystemUser: 'Add system user',
addUser: 'Add user',
emptyUserGroup:
'There are currently no custom user groups available. Please click "Create" or "+" above to create a user group',
rename: 'Rename',
changeAuthScope: 'Change auth scope',
delete: 'Delete',
user: 'user',
add: 'Add',
cancel: 'Cancel',
create: 'Create',
createUserGroup: 'create user group',
userGroupName: 'User group name',
authScope: 'Auth scope',
auth: 'Auth',
deleteSuccess: 'Delete success',
revokeSuccess: 'Revoke success',
revoke: 'revoke',
pleaseSelectUser: 'Please select user',
pleaseInputUserGroupName: 'Please input user group name,and not equal to system user group name',
userGroupNameIsExist: `Usergroup {name} is exist`,
pleaseSelectAuthScope: 'Please select auth scope',
userGroupNameIsNotNone: 'User group name is not none',
authScopeIsNotNone: 'Auth scope is not none',
userIsNotNone: 'User is not none',
confirm: 'Confirm',
global: 'Global',
searchPlacehoder: 'Search by ID/Name',
SYSTEM: '系统',
PROJECT: '项目',
ORGANIZATION: '组织',
isDeleteUserGroup: 'Delete or not: {name}?',
beforeDeleteUserGroup:
'After deletion, the project data under the organization will be deleted together. Please operate with caution!',
confirmDelete: 'Confirm delete',
},
},
};

View File

@ -0,0 +1,44 @@
export default {
system: {
userGroup: {
global: '全局用户组',
searchHolder: '请输入用户组名称',
inSystem: '系统内置',
customUserGroup: '自定义用户组',
addSystemUserGroup: '添加系统用户组',
addSystemUser: '添加系统用户',
addUser: '添加成员',
emptyUserGroup: '暂无自定义用户组,请点击上方创建或 “+” 创建用户组',
rename: '重命名',
changeAuthScope: '修改权限范围',
delete: '删除',
user: '成员',
add: '添加',
confirm: '确认',
create: '创建',
cancel: '取消',
createUserGroup: '创建用户组',
userGroupName: '用户组名称',
authScope: '权限范围',
auth: '权限',
deleteSuccess: '删除成功',
revokeSuccess: '撤销成功',
revoke: '撤销',
pleaseSelectUserGroup: '请选择用户组',
pleaseSelectUser: '请选择成员',
userGroupNameIsNotNone: '用户组名称不能为空',
authScopeIsNotNone: '权限范围不能为空',
userIsNotNone: '成员不能为空',
pleaseInputUserGroupName: '请输入用户组名称,且不与其他用户组名称重复',
userGroupNameIsExist: `用户组{name}已存在`,
pleaseSelectAuthScope: '请选择用户组所属的权限范围',
searchPlacehoder: '通过ID/名称搜索',
SYSTEM: '系统',
PROJECT: '项目',
ORGANIZATION: '组织',
isDeleteUserGroup: '是否删除: {name}?',
beforeDeleteUserGroup: '删除后,该组织下的项目数据将一起删除,请谨慎操作!',
confirmDelete: '确认删除',
},
},
};