feat: 左侧菜单样式&个人菜单
This commit is contained in:
parent
8920a12690
commit
6378e1ea30
|
@ -243,22 +243,39 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 下拉菜单 **/
|
/** 下拉菜单 **/
|
||||||
.arco-dropdown {
|
.arco-dropdown,
|
||||||
|
.arco-trigger-menu {
|
||||||
border: 0.5px solid var(--color-text-n8);
|
border: 0.5px solid var(--color-text-n8);
|
||||||
box-shadow: 0 3px 14px 2px rgb(0 0 0 / 5%), 0 8px 10px 1px rgb(0 0 0 / 6%), 0 5px 5px -3px rgb(0 0 0 / 10%);
|
box-shadow: 0 3px 14px 2px rgb(0 0 0 / 5%), 0 8px 10px 1px rgb(0 0 0 / 6%), 0 5px 5px -3px rgb(0 0 0 / 10%);
|
||||||
.arco-dropdown-list {
|
.arco-dropdown-list,
|
||||||
|
.arco-trigger-menu-inner {
|
||||||
@apply relative flex w-full flex-col overflow-hidden;
|
@apply relative flex w-full flex-col overflow-hidden;
|
||||||
.arco-dropdown-option {
|
.arco-dropdown-option,
|
||||||
@apply w-auto;
|
.arco-trigger-menu-item {
|
||||||
|
@apply flex w-auto items-center;
|
||||||
|
|
||||||
margin: 0 6px;
|
margin: 0 6px;
|
||||||
padding: 3px 8px;
|
padding: 3px 8px;
|
||||||
|
height: 30px;
|
||||||
border-radius: var(--border-radius-small);
|
border-radius: var(--border-radius-small);
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgb(var(--primary-1));
|
background-color: rgb(var(--primary-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ms-dropdown-divider {
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
.arco-trigger-menu-item {
|
||||||
|
width: 108px;
|
||||||
|
.arco-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-trigger-menu-selected {
|
||||||
|
color: rgb(var(--primary-7));
|
||||||
|
background-color: rgb(var(--primary-1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent, ref, h, compile, computed } from 'vue';
|
import { defineComponent, ref, h, compile, computed } from 'vue';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
import { useRoute, useRouter, RouteRecordRaw } from 'vue-router';
|
import { useRoute, useRouter, RouteRecordRaw } from 'vue-router';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useUser from '@/hooks/useUser';
|
||||||
import type { RouteMeta } from 'vue-router';
|
import type { RouteMeta } from 'vue-router';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore, useUserStore } from '@/store';
|
||||||
import { listenerRouteChange } from '@/utils/route-listener';
|
import { listenerRouteChange } from '@/utils/route-listener';
|
||||||
import { openWindow, regexUrl } from '@/utils';
|
import { openWindow, regexUrl } from '@/utils';
|
||||||
import useMenuTree from './use-menu-tree';
|
import useMenuTree from './use-menu-tree';
|
||||||
|
import { PERSONAL_ROUTE } from '@/router/routes/base';
|
||||||
|
import { BOTTOM_MENU_LIST } from '@/router/constants';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
emit: ['collapse'],
|
emit: ['collapse'],
|
||||||
setup() {
|
setup() {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const { logout } = useUser();
|
||||||
const { menuTree } = useMenuTree();
|
const { menuTree } = useMenuTree();
|
||||||
const collapsed = computed({
|
const collapsed = computed({
|
||||||
get() {
|
get() {
|
||||||
|
@ -53,6 +58,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const personalActiveMenus = ref(['']);
|
||||||
/**
|
/**
|
||||||
* 查找激活的菜单项
|
* 查找激活的菜单项
|
||||||
* @param target 目标菜单名
|
* @param target 目标菜单名
|
||||||
|
@ -73,9 +79,14 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
menuTree.value?.forEach((el: RouteRecordRaw | null) => {
|
menuTree.value?.forEach((el: RouteRecordRaw | null) => {
|
||||||
if (isFind) return; // Performance optimization
|
if (isFind) return; // 节省性能
|
||||||
backtrack(el, [el?.name as string]);
|
backtrack(el, [el?.name as string]);
|
||||||
});
|
});
|
||||||
|
personalActiveMenus.value = [''];
|
||||||
|
if (result.length === 0) {
|
||||||
|
backtrack(PERSONAL_ROUTE, [PERSONAL_ROUTE.name as string]);
|
||||||
|
personalActiveMenus.value = [...result];
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -96,11 +107,84 @@
|
||||||
if (appStore.device === 'desktop') appStore.updateSettings({ menuCollapse: val });
|
if (appStore.device === 'desktop') appStore.updateSettings({ menuCollapse: val });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const personalMenusVisble = ref(false);
|
||||||
|
|
||||||
|
const personalMenus = [
|
||||||
|
{
|
||||||
|
label: t('personal.info'),
|
||||||
|
icon: <icon-user />,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
route: PERSONAL_ROUTE.children![0],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('personal.switchOrg'),
|
||||||
|
icon: <icon-swap />,
|
||||||
|
event: () => {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
divider: <a-divider class="ms-dropdown-divider" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('personal.exit'),
|
||||||
|
icon: <icon-export />,
|
||||||
|
event: logout,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const personalInfoMenu = () => {
|
||||||
|
return (
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible={personalMenusVisble.value}
|
||||||
|
trigger="click"
|
||||||
|
unmount-on-close={false}
|
||||||
|
popup-offset={4}
|
||||||
|
position="right"
|
||||||
|
class="arco-trigger-menu absolute"
|
||||||
|
v-slots={{
|
||||||
|
content: () => (
|
||||||
|
<div class="arco-trigger-menu-inner">
|
||||||
|
{personalMenus.map((e) => {
|
||||||
|
if (e.divider) {
|
||||||
|
return e.divider;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={[
|
||||||
|
'arco-trigger-menu-item',
|
||||||
|
personalActiveMenus.value.includes(e.route?.name as string)
|
||||||
|
? 'arco-trigger-menu-selected'
|
||||||
|
: '',
|
||||||
|
]}
|
||||||
|
onClick={() => {
|
||||||
|
if (typeof e.event === 'function') {
|
||||||
|
e.event();
|
||||||
|
} else if (e.route) {
|
||||||
|
goto(e.route);
|
||||||
|
}
|
||||||
|
personalMenusVisble.value = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{e.icon}
|
||||||
|
{e.label}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<a-menu-item key="personalInfo">
|
||||||
|
<a-icon type="user" />
|
||||||
|
{userStore.name}
|
||||||
|
</a-menu-item>
|
||||||
|
</a-trigger>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const renderSubMenu = () => {
|
const renderSubMenu = () => {
|
||||||
function travel(_route: (RouteRecordRaw | null)[] | null, nodes = []) {
|
function travel(_route: (RouteRecordRaw | null)[] | null, nodes = []) {
|
||||||
if (_route) {
|
if (_route) {
|
||||||
_route.forEach((element) => {
|
_route.forEach((element) => {
|
||||||
// This is demo, modify nodes as needed
|
|
||||||
const icon = element?.meta?.icon ? () => h(compile(`<${element?.meta?.icon}/>`)) : null;
|
const icon = element?.meta?.icon ? () => h(compile(`<${element?.meta?.icon}/>`)) : null;
|
||||||
const node =
|
const node =
|
||||||
element?.children && element?.children.length !== 0 ? (
|
element?.children && element?.children.length !== 0 ? (
|
||||||
|
@ -110,6 +194,7 @@
|
||||||
icon,
|
icon,
|
||||||
title: () => h(compile(t(element?.meta?.locale || ''))),
|
title: () => h(compile(t(element?.meta?.locale || ''))),
|
||||||
}}
|
}}
|
||||||
|
class={BOTTOM_MENU_LIST.includes(element?.name as string) ? 'arco-menu-inline--bottom' : ''}
|
||||||
>
|
>
|
||||||
{travel(element?.children)}
|
{travel(element?.children)}
|
||||||
</a-sub-menu>
|
</a-sub-menu>
|
||||||
|
@ -138,24 +223,108 @@
|
||||||
level-indent={34}
|
level-indent={34}
|
||||||
style="height: 100%;width:100%;"
|
style="height: 100%;width:100%;"
|
||||||
onCollapse={setCollapse}
|
onCollapse={setCollapse}
|
||||||
|
trigger-props={{
|
||||||
|
'show-arrow': false,
|
||||||
|
'popup-offset': -4,
|
||||||
|
}}
|
||||||
|
v-slots={{
|
||||||
|
'collapse-icon': () => (appStore.menuCollapse ? <icon-right /> : <icon-left />),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{renderSubMenu()}
|
{renderSubMenu()}
|
||||||
|
{personalInfoMenu()}
|
||||||
</a-menu>
|
</a-menu>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less">
|
||||||
:deep(.arco-menu-inner) {
|
.menu-wrapper {
|
||||||
padding: 16px 16px 0;
|
background-color: var(--color-bg-3);
|
||||||
.arco-menu-inline-header {
|
}
|
||||||
@apply flex items-center;
|
.arco-menu {
|
||||||
|
&:hover {
|
||||||
|
.arco-menu-collapse-button {
|
||||||
|
@apply flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.arco-icon {
|
.arco-menu-collapse-button {
|
||||||
&:not(.arco-icon-down) {
|
@apply hidden rounded-full;
|
||||||
font-size: 18px;
|
|
||||||
|
top: 22px;
|
||||||
|
right: 4px;
|
||||||
|
border: 1px solid #ffffff;
|
||||||
|
background: linear-gradient(90deg, rgb(var(--primary-9)) 3.36%, #ffffff 100%);
|
||||||
|
box-shadow: 0 0 7px rgb(15 0 78 / 9%);
|
||||||
|
.arco-icon {
|
||||||
|
color: rgb(var(--primary-5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.arco-menu-inner {
|
||||||
|
@apply flex flex-col;
|
||||||
|
|
||||||
|
padding: 16px 32px 16px 16px !important;
|
||||||
|
.arco-menu-inline {
|
||||||
|
&--bottom {
|
||||||
|
@apply mt-auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-menu-pop-header {
|
||||||
|
@apply leading-none;
|
||||||
|
|
||||||
|
padding: 11px;
|
||||||
|
}
|
||||||
|
.arco-menu-inline-header {
|
||||||
|
@apply flex items-center;
|
||||||
|
}
|
||||||
|
.arco-menu-inline-header,
|
||||||
|
.arco-menu-item {
|
||||||
|
@apply mb-0 !bg-transparent;
|
||||||
|
|
||||||
|
color: var(--color-text-1) !important;
|
||||||
|
&:hover,
|
||||||
|
.arco-menu-indent-list:hover,
|
||||||
|
.arco-icon:hover {
|
||||||
|
background-color: rgb(var(--primary-1)) !important;
|
||||||
|
}
|
||||||
|
.arco-menu-item-inner,
|
||||||
|
.arco-menu-item-inner:hover {
|
||||||
|
@apply !bg-transparent;
|
||||||
|
}
|
||||||
|
.arco-menu-icon {
|
||||||
|
.arco-icon {
|
||||||
|
&:not(.arco-icon-down) {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
color: var(--color-text-4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-menu-title {
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-menu-selected {
|
||||||
|
color: rgb(var(--primary-5)) !important;
|
||||||
|
&:not(.arco-menu-inline-header) {
|
||||||
|
background-color: rgb(var(--primary-9)) !important;
|
||||||
|
}
|
||||||
|
.arco-menu-icon {
|
||||||
|
.arco-icon {
|
||||||
|
color: rgb(var(--primary-5)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-menu-title {
|
||||||
|
color: rgb(var(--primary-5)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-menu-pop {
|
||||||
|
@apply bg-transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.arco-menu-collapsed {
|
||||||
|
width: 86px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<MsButton><icon-more /></MsButton>
|
<MsButton><icon-more /></MsButton>
|
||||||
<template #content>
|
<template #content>
|
||||||
<template v-for="item of props.list">
|
<template v-for="item of props.list">
|
||||||
<a-divider v-if="item.isDivider" :key="`${item.label}-divider`" class="mx-0 my-[6px]" />
|
<a-divider v-if="item.isDivider" :key="`${item.label}-divider`" class="ms-dropdown-divider" />
|
||||||
<a-doption v-else :key="item.label" :class="item.danger ? 'error-6' : ''">{{ t(item.label || '') }}</a-doption>
|
<a-doption v-else :key="item.label" :class="item.danger ? 'error-6' : ''">{{ t(item.label || '') }}</a-doption>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -2,13 +2,7 @@
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<div class="left-side">
|
<div class="left-side">
|
||||||
<a-space>
|
<a-space>
|
||||||
<svg-icon :width="'43px'" :height="'33px'" :name="'logo'" />
|
<svg-icon width="145px" height="32px" name="MS-full-logo" />
|
||||||
<a-divider direction="vertical" />
|
|
||||||
<icon-menu-fold
|
|
||||||
v-if="!topMenu && appStore.device === 'mobile'"
|
|
||||||
style="font-size: 22px; cursor: pointer"
|
|
||||||
@click="toggleDrawerMenu"
|
|
||||||
/>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<div class="center-side">
|
<div class="center-side">
|
||||||
|
@ -122,7 +116,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, inject } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { useFullscreen } from '@vueuse/core';
|
import { useFullscreen } from '@vueuse/core';
|
||||||
import { useAppStore, useUserStore } from '@/store';
|
import { useAppStore, useUserStore } from '@/store';
|
||||||
|
@ -170,7 +164,6 @@
|
||||||
const res = await userStore.switchRoles();
|
const res = await userStore.switchRoles();
|
||||||
Message.success(res as string);
|
Message.success(res as string);
|
||||||
};
|
};
|
||||||
const toggleDrawerMenu = inject('toggleDrawerMenu') as () => void;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
@ -182,7 +175,7 @@
|
||||||
.left-side {
|
.left-side {
|
||||||
@apply flex items-center;
|
@apply flex items-center;
|
||||||
|
|
||||||
padding-left: 20px;
|
padding-left: 24px;
|
||||||
}
|
}
|
||||||
.center-side {
|
.center-side {
|
||||||
@apply flex-1;
|
@apply flex-1;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
"menuCollapse": false,
|
"menuCollapse": false,
|
||||||
"footer": false,
|
"footer": false,
|
||||||
"themeColor": "#5736E9",
|
"themeColor": "#5736E9",
|
||||||
"menuWidth": 200,
|
"menuWidth": 212,
|
||||||
"globalSettings": false,
|
"globalSettings": false,
|
||||||
"device": "desktop",
|
"device": "desktop",
|
||||||
"tabBar": false,
|
"tabBar": false,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import Mock from 'mockjs';
|
import Mock from 'mockjs';
|
||||||
import setupMock, { successResponseWrap, failResponseWrap } from '@/utils/setup-mock';
|
import setupMock, { successResponseWrap, failResponseWrap } from '@/utils/setup-mock';
|
||||||
|
|
||||||
import { MockParams } from '#/mock';
|
import { GetMenuListUrl, LogoutUrl, GetUserInfoUrl } from '@/api/requrls/user';
|
||||||
import { isLogin } from '@/utils/auth';
|
import { isLogin } from '@/utils/auth';
|
||||||
|
|
||||||
setupMock({
|
setupMock({
|
||||||
setup() {
|
setup() {
|
||||||
// 用户信息
|
// 用户信息
|
||||||
Mock.mock(new RegExp('/api/user/info'), () => {
|
Mock.mock(new RegExp(GetUserInfoUrl), () => {
|
||||||
if (isLogin()) {
|
if (isLogin()) {
|
||||||
const role = window.localStorage.getItem('userRole') || 'admin';
|
const role = window.localStorage.getItem('userRole') || 'admin';
|
||||||
return successResponseWrap({
|
return successResponseWrap({
|
||||||
|
@ -32,37 +32,13 @@ setupMock({
|
||||||
return failResponseWrap(null, '未登录', 50008);
|
return failResponseWrap(null, '未登录', 50008);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 登录
|
|
||||||
Mock.mock(new RegExp('/api/user/login'), (params: MockParams) => {
|
|
||||||
const { username, password } = JSON.parse(params.body);
|
|
||||||
if (!username) {
|
|
||||||
return failResponseWrap(null, '用户名不能为空', 50000);
|
|
||||||
}
|
|
||||||
if (!password) {
|
|
||||||
return failResponseWrap(null, '密码不能为空', 50000);
|
|
||||||
}
|
|
||||||
if (username === 'admin' && password === 'admin') {
|
|
||||||
window.localStorage.setItem('userRole', 'admin');
|
|
||||||
return successResponseWrap({
|
|
||||||
token: '12345',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (username === 'user' && password === 'user') {
|
|
||||||
window.localStorage.setItem('userRole', 'user');
|
|
||||||
return successResponseWrap({
|
|
||||||
token: '54321',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return failResponseWrap(null, '账号或者密码错误', 50000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 登出
|
// 登出
|
||||||
Mock.mock(new RegExp('/api/user/logout'), () => {
|
Mock.mock(new RegExp(LogoutUrl), () => {
|
||||||
return successResponseWrap(null);
|
return successResponseWrap(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 用户的服务端菜单
|
// 用户的服务端菜单
|
||||||
Mock.mock(new RegExp('/api/user/menu'), () => {
|
Mock.mock(new RegExp(GetMenuListUrl), () => {
|
||||||
const menuList = [
|
const menuList = [
|
||||||
{
|
{
|
||||||
path: '/api-test',
|
path: '/api-test',
|
||||||
|
@ -114,6 +90,18 @@ setupMock({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/personal',
|
||||||
|
name: 'personal',
|
||||||
|
meta: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/personal/info',
|
||||||
|
name: 'personalInfo',
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
return successResponseWrap(menuList);
|
return successResponseWrap(menuList);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,8 @@ export const WHITE_LIST = [
|
||||||
{ name: 'invite', children: [] },
|
{ name: 'invite', children: [] },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const BOTTOM_MENU_LIST = ['system'];
|
||||||
|
|
||||||
export const NOT_FOUND = {
|
export const NOT_FOUND = {
|
||||||
name: 'notFound',
|
name: 'notFound',
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ import NProgress from 'nprogress'; // progress bar
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
|
|
||||||
import appRoutes from './routes';
|
import appRoutes from './routes';
|
||||||
import { REDIRECT_MAIN, NOT_FOUND_ROUTE, INVITE_ROUTE } from './routes/base';
|
import { REDIRECT_MAIN, NOT_FOUND_ROUTE, INVITE_ROUTE, PERSONAL_ROUTE } from './routes/base';
|
||||||
import createRouteGuard from './guard';
|
import createRouteGuard from './guard';
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false }); // NProgress Configuration
|
NProgress.configure({ showSpinner: false }); // NProgress Configuration
|
||||||
|
@ -27,6 +27,7 @@ const router = createRouter({
|
||||||
REDIRECT_MAIN,
|
REDIRECT_MAIN,
|
||||||
NOT_FOUND_ROUTE,
|
NOT_FOUND_ROUTE,
|
||||||
INVITE_ROUTE,
|
INVITE_ROUTE,
|
||||||
|
PERSONAL_ROUTE,
|
||||||
],
|
],
|
||||||
scrollBehavior() {
|
scrollBehavior() {
|
||||||
return { top: 0 };
|
return { top: 0 };
|
||||||
|
|
|
@ -37,3 +37,18 @@ export const INVITE_ROUTE: RouteRecordRaw = {
|
||||||
hideInMenu: true,
|
hideInMenu: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PERSONAL_ROUTE: RouteRecordRaw = {
|
||||||
|
path: '/personal',
|
||||||
|
name: 'personal',
|
||||||
|
component: DEFAULT_LAYOUT,
|
||||||
|
meta: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/personal/info',
|
||||||
|
name: 'personalInfo',
|
||||||
|
component: () => import('@/views/base/personal/index.vue'),
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
|
@ -18,7 +18,6 @@ const ApiTest: AppRouteRecordRaw = {
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.user',
|
locale: 'menu.settings.user',
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
icon: 'icon-computer',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -28,7 +27,6 @@ const ApiTest: AppRouteRecordRaw = {
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.usergroup',
|
locale: 'menu.settings.usergroup',
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
icon: 'icon-computer',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -14,4 +14,7 @@ export default {
|
||||||
'invite.passwordTipTitle': 'The passwords must match both, only the following rules are supported',
|
'invite.passwordTipTitle': 'The passwords must match both, only the following rules are supported',
|
||||||
'invite.passwordLengthRule': 'The length is 8-32 digits',
|
'invite.passwordLengthRule': 'The length is 8-32 digits',
|
||||||
'invite.passwordWordRule': 'Must contain numbers and letters, Chinese or spaces are not allowed',
|
'invite.passwordWordRule': 'Must contain numbers and letters, Chinese or spaces are not allowed',
|
||||||
|
'personal.info': 'Personal Info',
|
||||||
|
'personal.switchOrg': 'Switch Org',
|
||||||
|
'personal.exit': 'Log out',
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,4 +14,7 @@ export default {
|
||||||
'invite.passwordTipTitle': '密码须同时符合,仅支持以下规则',
|
'invite.passwordTipTitle': '密码须同时符合,仅支持以下规则',
|
||||||
'invite.passwordLengthRule': '长度为8-32位',
|
'invite.passwordLengthRule': '长度为8-32位',
|
||||||
'invite.passwordWordRule': '必须包含数字和字母,不允许输入中文或空格',
|
'invite.passwordWordRule': '必须包含数字和字母,不允许输入中文或空格',
|
||||||
|
'personal.info': '个人信息',
|
||||||
|
'personal.switchOrg': '切换组织',
|
||||||
|
'personal.exit': '退出系统',
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<template>
|
||||||
|
<div> </div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
|
@ -102,6 +102,7 @@ export default {
|
||||||
'system.user.inviteCancel': 'Cancel',
|
'system.user.inviteCancel': 'Cancel',
|
||||||
'system.user.inviteEmailPlaceholder': 'Enter multiple email addresses, separated by spaces or carriage returns',
|
'system.user.inviteEmailPlaceholder': 'Enter multiple email addresses, separated by spaces or carriage returns',
|
||||||
'system.user.inviteSendEmail': 'SendEmail',
|
'system.user.inviteSendEmail': 'SendEmail',
|
||||||
|
'system.user.inviteSuccess': 'Invitation successful',
|
||||||
'system.user.importModalTitle': 'Import user',
|
'system.user.importModalTitle': 'Import user',
|
||||||
'system.user.importDownload': 'Download the template',
|
'system.user.importDownload': 'Download the template',
|
||||||
'system.user.importModalTip': 'User groups only support adding user groups that exist in the system',
|
'system.user.importModalTip': 'User groups only support adding user groups that exist in the system',
|
||||||
|
|
|
@ -100,6 +100,7 @@ export default {
|
||||||
'system.user.inviteCancel': '取消',
|
'system.user.inviteCancel': '取消',
|
||||||
'system.user.inviteEmailPlaceholder': '可输入多个邮箱地址,空格或回车分隔',
|
'system.user.inviteEmailPlaceholder': '可输入多个邮箱地址,空格或回车分隔',
|
||||||
'system.user.inviteSendEmail': '发送邮件',
|
'system.user.inviteSendEmail': '发送邮件',
|
||||||
|
'system.user.inviteSuccess': '邀请成功',
|
||||||
'system.user.importModalTitle': '导入用户',
|
'system.user.importModalTitle': '导入用户',
|
||||||
'system.user.importModalTip': '用户组仅支持添加系统存在的用户组',
|
'system.user.importModalTip': '用户组仅支持添加系统存在的用户组',
|
||||||
'system.user.importDownload': '下载模板',
|
'system.user.importDownload': '下载模板',
|
||||||
|
|
Loading…
Reference in New Issue