修改 ui 包结构.
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import type { RouteRecordNormalized } from 'vue-router';
|
||||
import { UserState } from '@/store/modules/user/types';
|
||||
|
||||
export function getUserInfo() {
|
||||
return axios.post<UserState>('/api/user/info');
|
||||
}
|
||||
|
||||
export function getMenuList() {
|
||||
return axios.post<RouteRecordNormalized[]>('/api/user/menu');
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios';
|
||||
import { UserState } from '@/store/modules/user/types';
|
||||
|
||||
export interface LoginRequest {
|
||||
username: string;
|
||||
@@ -9,10 +10,30 @@ export interface LoginResponse {
|
||||
token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登陆
|
||||
*/
|
||||
export function login(data: LoginRequest) {
|
||||
return axios.post<LoginResponse>('/infra/auth/login', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出
|
||||
*/
|
||||
export function logout() {
|
||||
return axios.get('/infra/auth/logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export function getUserPermission() {
|
||||
return axios.get('/infra/permission/user');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单列表
|
||||
*/
|
||||
export function getMenuList() {
|
||||
return axios.get('/infra/permission/menu');
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ body {
|
||||
background-color: var(--color-bg-1);
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
--color-scrollbar-track: var(--color-neutral-1);
|
||||
--color-scrollbar-thumb: #959FAB;
|
||||
}
|
||||
|
||||
.echarts-tooltip-diy {
|
||||
@@ -25,6 +27,7 @@ body {
|
||||
/* Note: backdrop-filter has minimal browser support */
|
||||
|
||||
border-radius: 6px !important;
|
||||
|
||||
.content-panel {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -37,12 +40,15 @@ body {
|
||||
border-radius: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.tooltip-title {
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tooltip-title,
|
||||
.tooltip-value {
|
||||
font-size: 13px;
|
||||
@@ -53,6 +59,7 @@ body {
|
||||
color: #1d2129;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tooltip-item-icon {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
@@ -65,11 +72,13 @@ body {
|
||||
.general-card {
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
|
||||
& > .arco-card-header {
|
||||
height: auto;
|
||||
padding: 20px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
& > .arco-card-body {
|
||||
padding: 0 20px 20px 20px;
|
||||
}
|
||||
@@ -87,8 +96,32 @@ body {
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: rgb(var(--blue-6));
|
||||
|
||||
&.pass {
|
||||
background-color: rgb(var(--green-6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#app {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: var(--color-scrollbar-track);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
-webkit-appearance: none;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
background-color: var(--color-scrollbar-thumb);
|
||||
transition: color .2s ease;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useAppStore } from '@/store';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
export default function useMenuTree() {
|
||||
const permission = usePermission();
|
||||
const appStore = useAppStore();
|
||||
const appRoute = computed(() => {
|
||||
return appStore.appAsyncMenus;
|
||||
@@ -20,39 +19,40 @@ export default function useMenuTree() {
|
||||
if (!_routes) return null;
|
||||
|
||||
const collector: any = _routes.map((element) => {
|
||||
// no access
|
||||
if (!permission.accessRouter(element)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// leaf node
|
||||
// 隐藏子目录
|
||||
if (element.meta?.hideChildrenInMenu || !element.children) {
|
||||
element.children = [];
|
||||
return element;
|
||||
|
||||
if (element.meta?.hideInMenu) {
|
||||
// 如果隐藏菜单 则不显示
|
||||
return null;
|
||||
} else {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
// route filter hideInMenu true
|
||||
// 过滤不显示的菜单
|
||||
element.children = element.children.filter(
|
||||
(x) => x.meta?.hideInMenu !== true
|
||||
);
|
||||
|
||||
// Associated child node
|
||||
// 关联子节点
|
||||
const subItem = travel(element.children, layer + 1);
|
||||
|
||||
if (subItem.length) {
|
||||
element.children = subItem;
|
||||
return element;
|
||||
}
|
||||
// the else logic
|
||||
// 第二层 (子目录)
|
||||
if (layer > 1) {
|
||||
element.children = subItem;
|
||||
return element;
|
||||
}
|
||||
|
||||
// 是否隐藏目录
|
||||
if (element.meta?.hideInMenu === false) {
|
||||
return element;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
return collector.filter(Boolean);
|
||||
|
||||
@@ -185,9 +185,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, inject } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { useDark, useToggle, useFullscreen } from '@vueuse/core';
|
||||
import { computed, inject, ref } from 'vue';
|
||||
import { useDark, useFullscreen, useToggle } from '@vueuse/core';
|
||||
import { useAppStore, useUserStore } from '@/store';
|
||||
import { LOCALE_OPTIONS } from '@/locale';
|
||||
import useLocale from '@/hooks/locale';
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { DirectiveBinding } from 'vue';
|
||||
import { useUserStore } from '@/store';
|
||||
import usePermission from '@/hooks/permission';
|
||||
|
||||
function checkPermission(el: HTMLElement, binding: DirectiveBinding) {
|
||||
const { value } = binding;
|
||||
const userStore = useUserStore();
|
||||
// TODO TEST
|
||||
const permission = usePermission();
|
||||
if (Array.isArray(value)) {
|
||||
if (value.length > 0) {
|
||||
const hasPermission = userStore.permission?.includes(value as any as string);
|
||||
if (!hasPermission && el.parentNode) {
|
||||
if (!permission.hasAnyPermission(value) && el.parentNode) {
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ export default function useChartOption(sourceOption: optionsFn) {
|
||||
});
|
||||
// echarts support https://echarts.apache.org/zh/theme-builder.html
|
||||
// It's not used here
|
||||
// TODO echarts themes
|
||||
const chartOption = computed<EChartsOption>(() => {
|
||||
return sourceOption(isDark.value);
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
v-if="hideMenu"
|
||||
:visible="drawerVisible"
|
||||
placement="left"
|
||||
:header="false"
|
||||
:footer="false"
|
||||
mask-closable
|
||||
:closable="false"
|
||||
@@ -47,23 +48,20 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, provide, onMounted } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { useAppStore, useUserStore } from '@/store';
|
||||
import { computed, onMounted, provide, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useAppStore } from '@/store';
|
||||
import NavBar from '@/components/navbar/index.vue';
|
||||
import Menu from '@/components/menu/index.vue';
|
||||
import Footer from '@/components/footer/index.vue';
|
||||
import TabBar from '@/components/tab-bar/index.vue';
|
||||
import usePermission from '@/hooks/permission';
|
||||
import useResponsive from '@/hooks/responsive';
|
||||
import PageLayout from './page-layout.vue';
|
||||
|
||||
const isInit = ref(false);
|
||||
const appStore = useAppStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const permission = usePermission();
|
||||
useResponsive(true);
|
||||
const navbarHeight = `60px`;
|
||||
const navbar = computed(() => appStore.navbar);
|
||||
@@ -94,15 +92,6 @@
|
||||
appStore.updateSettings({ menuCollapse: val });
|
||||
};
|
||||
|
||||
// 监听权限变化
|
||||
watch(
|
||||
() => userStore.permission,
|
||||
(permissionValue) => {
|
||||
if (permissionValue && !permission.accessRouter(route))
|
||||
router.push({ name: 'forbidden' });
|
||||
}
|
||||
);
|
||||
|
||||
const drawerVisible = ref(false);
|
||||
const drawerCancel = () => {
|
||||
drawerVisible.value = false;
|
||||
|
||||
@@ -6,20 +6,6 @@ import localeWorkplace from '@/views/dashboard/workplace/locale/zh-CN';
|
||||
import localeSettings from './zh-CN/settings';
|
||||
|
||||
export default {
|
||||
'menu.dashboard': '仪表盘',
|
||||
'menu.server.dashboard': '仪表盘-服务端',
|
||||
'menu.server.workplace': '工作台-服务端',
|
||||
'menu.server.monitor': '实时监控-服务端',
|
||||
'menu.list': '列表页',
|
||||
'menu.result': '结果页',
|
||||
'menu.exception': '异常页',
|
||||
'menu.form': '表单页',
|
||||
'menu.profile': '详情页',
|
||||
'menu.visualization': '数据可视化',
|
||||
'menu.user': '个人中心',
|
||||
'menu.arcoWebsite': 'Arco Design',
|
||||
'menu.faq': '常见问题',
|
||||
'navbar.docs': '文档中心',
|
||||
'navbar.action.locale': '切换为中文',
|
||||
...localeSettings,
|
||||
...localeMessageBox,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import Mock from 'mockjs';
|
||||
|
||||
import './user';
|
||||
import './message-box';
|
||||
// import './user';
|
||||
|
||||
import '@/views/dashboard/workplace/mock';
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import Mock from 'mockjs';
|
||||
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
|
||||
|
||||
const haveReadIds: number[] = [];
|
||||
const getMessageList = () => {
|
||||
return [
|
||||
{
|
||||
id: 1,
|
||||
type: 'message',
|
||||
title: '郑曦月',
|
||||
subTitle: '的私信',
|
||||
avatar:
|
||||
'123123',
|
||||
content: '审批请求已发送,请查收',
|
||||
time: '今天 12:30:01',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
type: 'message',
|
||||
title: '宁波',
|
||||
subTitle: '的回复',
|
||||
avatar:
|
||||
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp',
|
||||
content: '此处 bug 已经修复',
|
||||
time: '今天 12:30:01',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
type: 'message',
|
||||
title: '宁波',
|
||||
subTitle: '的回复',
|
||||
avatar:
|
||||
'//p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp',
|
||||
content: '此处 bug 已经修复',
|
||||
time: '今天 12:20:01',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
type: 'notice',
|
||||
title: '续费通知',
|
||||
subTitle: '',
|
||||
avatar: '',
|
||||
content: '您的产品使用期限即将截止,如需继续使用产品请前往购…',
|
||||
time: '今天 12:20:01',
|
||||
messageType: 3,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
type: 'notice',
|
||||
title: '规则开通成功',
|
||||
subTitle: '',
|
||||
avatar: '',
|
||||
content: '内容屏蔽规则于 2021-12-01 开通成功并生效',
|
||||
time: '今天 12:20:01',
|
||||
messageType: 1,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
type: 'todo',
|
||||
title: '质检队列变更',
|
||||
subTitle: '',
|
||||
avatar: '',
|
||||
content: '内容质检队列于 2021-12-01 19:50:23 进行变更,请重新…',
|
||||
time: '今天 12:20:01',
|
||||
messageType: 0,
|
||||
},
|
||||
].map((item) => ({
|
||||
...item,
|
||||
status: haveReadIds.indexOf(item.id) === -1 ? 0 : 1,
|
||||
}));
|
||||
};
|
||||
|
||||
setupMock({
|
||||
setup: () => {
|
||||
Mock.mock(new RegExp('/api/message/list'), () => {
|
||||
return successResponseWrap(getMessageList());
|
||||
});
|
||||
|
||||
Mock.mock(new RegExp('/api/message/read'), (params: { body: string }) => {
|
||||
const { ids } = JSON.parse(params.body);
|
||||
haveReadIds.push(...(ids || []));
|
||||
return successResponseWrap(true);
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -1,104 +1,16 @@
|
||||
import Mock from 'mockjs';
|
||||
import setupMock, {
|
||||
successResponseWrap,
|
||||
failResponseWrap,
|
||||
} from '@/utils/setup-mock';
|
||||
|
||||
import { MockParams } from '@/types/mock';
|
||||
import { isLogin } from '@/utils/auth';
|
||||
|
||||
setupMock({
|
||||
setup() {
|
||||
// Mock.XHR.prototype.withCredentials = true;
|
||||
|
||||
// 用户信息
|
||||
Mock.mock(new RegExp('/api/user/info'), () => {
|
||||
if (isLogin()) {
|
||||
const role = window.localStorage.getItem('userRole') || 'admin';
|
||||
return successResponseWrap({
|
||||
id: '1',
|
||||
name: '王立群',
|
||||
username:
|
||||
'//lf1-xgcdn-tos.pstatp.com/obj/vcloud/vadmin/start.8e0e4855ee346a46ccff8ff3e24db27b.png',
|
||||
email: 'wangliqun@email.com',
|
||||
job: 'frontend',
|
||||
jobName: '前端艺术家',
|
||||
organization: 'Frontend',
|
||||
organizationName: '前端',
|
||||
location: 'beijing',
|
||||
locationName: '北京',
|
||||
introduction: '人潇洒,性温存',
|
||||
personalWebsite: 'https://www.arco.design',
|
||||
phone: '150****0000',
|
||||
registrationDate: '2013-05-10 12:10:00',
|
||||
accountId: '15012312300',
|
||||
certification: 1,
|
||||
role,
|
||||
});
|
||||
}
|
||||
return failResponseWrap(null, '未登录', 50008);
|
||||
});
|
||||
|
||||
// 用户的服务端菜单
|
||||
Mock.mock(new RegExp('/api/user/menu'), () => {
|
||||
const menuList = [
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'dashboard',
|
||||
meta: {
|
||||
locale: 'menu.server.dashboard',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-dashboard',
|
||||
order: 1,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'workplace',
|
||||
name: 'workplace',
|
||||
meta: {
|
||||
locale: 'menu.server.workplace',
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'https://arco.design',
|
||||
name: 'arcoWebsite',
|
||||
meta: {
|
||||
locale: 'menu.arcoWebsite',
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'User',
|
||||
meta: {
|
||||
locale: '1',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-dashboard',
|
||||
order: 1,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/user/userChild',
|
||||
name: 'userChild',
|
||||
meta: {
|
||||
locale: 'userChild',
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/user/userChild1',
|
||||
name: 'userChild1',
|
||||
meta: {
|
||||
locale: 'userChild1',
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
return successResponseWrap(menuList);
|
||||
});
|
||||
},
|
||||
});
|
||||
// import Mock from 'mockjs';
|
||||
// import setupMock, { successResponseWrap, } from '@/utils/setup-mock';
|
||||
//
|
||||
// setupMock({
|
||||
// setup() {
|
||||
// // Mock.XHR.prototype.withCredentials = true;
|
||||
//
|
||||
// // 用户信息
|
||||
// Mock.mock(new RegExp('/api/user/info'), () => {
|
||||
// return successResponseWrap({
|
||||
// id: '1',
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// },
|
||||
// });
|
||||
|
||||
@@ -7,7 +7,10 @@ import setupRouteEmitterGuard from './router-listener-emitter';
|
||||
* 创建路由守卫
|
||||
*/
|
||||
export default function createRouteGuard(router: Router) {
|
||||
// 路由监听守卫
|
||||
setupRouteEmitterGuard(router);
|
||||
// 登录检查守卫
|
||||
setupUserLoginInfoGuard(router);
|
||||
// 权限检查守卫
|
||||
setupPermissionGuard(router);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,6 @@ export const LOGIN_ROUTER: RouteRecordRaw = {
|
||||
path: '/login',
|
||||
name: LOGIN_ROUTE_NAME,
|
||||
component: () => import('@/views/login/index.vue'),
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -37,7 +34,6 @@ export const REDIRECT_ROUTER: RouteRecordRaw = {
|
||||
name: 'redirectWrapper',
|
||||
component: DEFAULT_LAYOUT,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
hideInMenu: true,
|
||||
},
|
||||
children: [
|
||||
@@ -46,7 +42,6 @@ export const REDIRECT_ROUTER: RouteRecordRaw = {
|
||||
name: REDIRECT_ROUTE_NAME,
|
||||
component: () => import('@/views/redirect/index.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
hideInMenu: true,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,24 +2,13 @@ import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const DASHBOARD: AppRouteRecordRaw = {
|
||||
path: '/dashboard',
|
||||
name: 'dashboard',
|
||||
component: DEFAULT_LAYOUT,
|
||||
meta: {
|
||||
locale: 'menu.dashboard',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-dashboard',
|
||||
order: 0,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'workplace',
|
||||
path: '/dashboard/workplace',
|
||||
name: 'workplace',
|
||||
component: () => import('@/views/dashboard/workplace/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.dashboard.workplace',
|
||||
requiresAuth: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -2,24 +2,18 @@ import { DEFAULT_LAYOUT } from '../base';
|
||||
import { AppRouteRecordRaw } from '../types';
|
||||
|
||||
const USER: AppRouteRecordRaw = {
|
||||
path: '/user',
|
||||
name: 'user',
|
||||
component: DEFAULT_LAYOUT,
|
||||
meta: {
|
||||
locale: 'USER',
|
||||
requiresAuth: true,
|
||||
icon: 'icon-dashboard',
|
||||
order: 0,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'userChild',
|
||||
name: 'userChild',
|
||||
component: () => import('@/views/user/child/index.vue'),
|
||||
meta: {
|
||||
locale: '用户子页面',
|
||||
requiresAuth: true,
|
||||
},
|
||||
path: '/user/userChild1',
|
||||
name: 'userChild1',
|
||||
component: () => import('@/views/user/child1/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/user/userChild2',
|
||||
name: 'userChild2',
|
||||
component: () => import('@/views/user/child2/index.vue'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ export type Component<T = any> =
|
||||
| (() => Promise<T>);
|
||||
|
||||
export interface AppRouteRecordRaw {
|
||||
path: string;
|
||||
path?: string;
|
||||
name?: string | symbol;
|
||||
meta?: RouteMeta;
|
||||
redirect?: string;
|
||||
|
||||
16
orion-ops-ui/src/router/typings.d.ts
vendored
16
orion-ops-ui/src/router/typings.d.ts
vendored
@@ -2,15 +2,21 @@ import 'vue-router';
|
||||
|
||||
declare module 'vue-router' {
|
||||
interface RouteMeta {
|
||||
permission?: string;
|
||||
requiresAuth: boolean;
|
||||
// 后端赋值
|
||||
icon?: string;
|
||||
// 后端赋值
|
||||
locale?: string;
|
||||
hideInMenu?: boolean;
|
||||
hideChildrenInMenu?: boolean;
|
||||
activeMenu?: string;
|
||||
// 后端赋值
|
||||
order?: number;
|
||||
// 后端赋值 是否隐藏菜单
|
||||
hideInMenu?: boolean;
|
||||
// 后端赋值 是否隐藏子菜单
|
||||
hideChildrenInMenu?: boolean;
|
||||
// 后端赋值 是否添加到 tab
|
||||
noAffix?: boolean;
|
||||
// 前端赋值 是否忽略缓存
|
||||
ignoreCache?: boolean;
|
||||
// 不赋值
|
||||
activeMenu?: string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,5 +15,7 @@ export interface AppState {
|
||||
device: string;
|
||||
tabBar: boolean;
|
||||
serverMenu: RouteRecordNormalized[];
|
||||
menuFetched: boolean;
|
||||
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,9 @@
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
import { defineStore } from 'pinia';
|
||||
import { DEFAULT_TAB, DEFAULT_ROUTE_NAME, REDIRECT_ROUTE_NAME, } from '@/router/constants';
|
||||
import { DEFAULT_TAB, DEFAULT_ROUTE_NAME, BAN_TAB_LIST, routerToTag } from '@/router/constants';
|
||||
import { isString } from '@/utils/is';
|
||||
import { TabBarState, TagProps } from './types';
|
||||
|
||||
/**
|
||||
* router 转 tag
|
||||
*/
|
||||
const formatTag = (route: RouteLocationNormalized): TagProps => {
|
||||
const { name, meta, fullPath, query } = route;
|
||||
return {
|
||||
title: meta.locale || '',
|
||||
name: String(name),
|
||||
fullPath,
|
||||
query,
|
||||
ignoreCache: meta.ignoreCache,
|
||||
};
|
||||
};
|
||||
|
||||
// 不添加的 tab 集合
|
||||
const BAN_LIST = [REDIRECT_ROUTE_NAME];
|
||||
|
||||
const useTabBarStore = defineStore('tabBar', {
|
||||
state: (): TabBarState => ({
|
||||
cacheTabList: new Set([DEFAULT_ROUTE_NAME]),
|
||||
@@ -41,8 +24,8 @@ const useTabBarStore = defineStore('tabBar', {
|
||||
* 添加 tab
|
||||
*/
|
||||
updateTabList(route: RouteLocationNormalized) {
|
||||
if (BAN_LIST.includes(route.name as string)) return;
|
||||
this.tagList.push(formatTag(route));
|
||||
if (BAN_TAB_LIST.includes(route.name as string)) return;
|
||||
this.tagList.push(routerToTag(route));
|
||||
if (!route.meta.ignoreCache) {
|
||||
this.cacheTabList.add(route.name as string);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@ export interface UserState {
|
||||
username?: string;
|
||||
nickname?: string;
|
||||
avatar?: string;
|
||||
permission?: string[];
|
||||
roles?: string[];
|
||||
permission?: string[];
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export interface MockParams {
|
||||
url: string;
|
||||
type: string;
|
||||
body: string;
|
||||
}
|
||||
@@ -57,37 +57,6 @@ export function isEmptyStr(val: any) {
|
||||
return typeof (val) === 'undefined' || val == null || val === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制到剪切板
|
||||
*/
|
||||
// export function copyToClipboard(content: any) {
|
||||
// const clipboardData = window.clipboardData;
|
||||
// if (clipboardData) {
|
||||
// clipboardData.clearData();
|
||||
// clipboardData.setData('Text', content);
|
||||
// return true;
|
||||
// } else if (document.execCommand) {
|
||||
// const el = document.createElement('textarea');
|
||||
// el.value = content;
|
||||
// el.setAttribute('readonly', '');
|
||||
// el.style.position = 'absolute';
|
||||
// el.style.left = '-9999px';
|
||||
// document.body.appendChild(el);
|
||||
// el.select();
|
||||
// document.execCommand('copy');
|
||||
// document.body.removeChild(el);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取剪切板内容 返回 promise
|
||||
*/
|
||||
export function getClipboardText() {
|
||||
return navigator.clipboard.readText();
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,6 @@ export default ({ mock, setup }: { mock?: boolean; setup: () => void }) => {
|
||||
export const successResponseWrap = (data: unknown) => {
|
||||
return {
|
||||
data,
|
||||
status: 'ok',
|
||||
msg: '请求成功',
|
||||
code: 200,
|
||||
};
|
||||
@@ -16,7 +15,6 @@ export const successResponseWrap = (data: unknown) => {
|
||||
export const failResponseWrap = (data: unknown, msg: string, code = 5000) => {
|
||||
return {
|
||||
data,
|
||||
status: 'fail',
|
||||
msg,
|
||||
code,
|
||||
};
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'Dashboard', // If you want the include property of keep-alive to take effect, you must name the component
|
||||
name: 'workplace',
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -83,13 +83,16 @@
|
||||
border-radius: 4px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:deep(.panel-border) {
|
||||
margin-bottom: 0;
|
||||
border-bottom: 1px solid rgb(var(--gray-2));
|
||||
}
|
||||
|
||||
.moduler-wrap {
|
||||
border-radius: 4px;
|
||||
background-color: var(--color-bg-2);
|
||||
|
||||
:deep(.text) {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
@@ -106,11 +109,13 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon {
|
||||
color: rgb(var(--arcoblue-6));
|
||||
background-color: #e8f3ff;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: rgb(var(--arcoblue-6));
|
||||
}
|
||||
@@ -138,6 +143,7 @@
|
||||
.container {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.right-side {
|
||||
// display: none;
|
||||
width: 100%;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<p>UserChild</p>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UserChild',
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<p>这是user组件</p>
|
||||
<div>
|
||||
<p>UserChild 1</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'User',
|
||||
name: 'UserChild1',
|
||||
};
|
||||
</script>
|
||||
|
||||
16
orion-ops-ui/src/views/user/child2/index.vue
Normal file
16
orion-ops-ui/src/views/user/child2/index.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>UserChild 2</p>
|
||||
<h1 v-permission="['admin']">123</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UserChild2',
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user