diff --git a/package.json b/package.json index 56917e61..3ce66f75 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "intro.js": "^5.1.0", "lodash-es": "^4.17.21", "marked": "^4.0.17", + "mitt": "^3.0.0", "mockjs": "^1.1.0", "path": "^0.12.7", "pinia": "^2.0.14", diff --git a/src/components/Application/AppLocale.vue b/src/components/Application/AppLocale.vue index ff2337ed..a1adb050 100644 --- a/src/components/Application/AppLocale.vue +++ b/src/components/Application/AppLocale.vue @@ -16,11 +16,11 @@ + + diff --git a/src/layouts/pageLayouts/components/Breadcrumb/index.vue b/src/layouts/pageLayouts/components/Breadcrumb/index.vue index 921c5ac5..119bde22 100644 --- a/src/layouts/pageLayouts/components/Breadcrumb/index.vue +++ b/src/layouts/pageLayouts/components/Breadcrumb/index.vue @@ -34,7 +34,7 @@ import { getAppCollapseMenu } from '@/hooks/userAppWindow'; import { useRoute, useRouter } from 'vue-router'; import { useI18n } from '@/hooks/web/useI18n'; - import { useAppStore } from '@/store/modules/app'; + import { useAppStoreHook } from '@/store/modules/app'; import { AppRouteRecordRaw } from '#/route'; import { getParentPaths, findRouteByPath } from '@/router/utils'; @@ -51,7 +51,7 @@ // 解析路由匹配的数组 const getBreadcrumb = () => { const matched: AppRouteRecordRaw[] = []; - const parentRoutes = getParentPaths(router.currentRoute.value.name || '', routes); + const parentRoutes = getParentPaths(router.currentRoute.value.path || '', routes); // 获取每个父级路径对应的路由信息 parentRoutes.forEach((path) => { if (path !== '/') { @@ -91,7 +91,7 @@ // 当前是否折叠导航栏 const { appConfigMode } = getAppCollapseMenu(); const isAppConfigMode = ref(appConfigMode.value); - const appStore = useAppStore(); + const appStore = useAppStoreHook(); // 折叠菜单事件 const handerShowElmenu = () => { isAppConfigMode.value.collapseMenu = !isAppConfigMode.value.collapseMenu; diff --git a/src/layouts/pageLayouts/components/Seting/index.vue b/src/layouts/pageLayouts/components/Seting/index.vue index b80a7665..a9178358 100644 --- a/src/layouts/pageLayouts/components/Seting/index.vue +++ b/src/layouts/pageLayouts/components/Seting/index.vue @@ -27,7 +27,7 @@ diff --git a/src/router/index.ts b/src/router/index.ts index 0adbd2a8..d2bfb753 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,12 +1,14 @@ import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; import { App } from 'vue'; -import routeModuleList from './modules'; +import whiteRouteModulesList from './modules'; import { handleAliveRoute, initAsyncRoute } from './utils'; import { usePermissionStoreHook } from '@/store/modules/permission'; +const routeList = whiteRouteModulesList; + export const router = createRouter({ history: createWebHistory(''), - routes: routeModuleList as unknown as RouteRecordRaw[], + routes: routeList as unknown as RouteRecordRaw[], }); export const configMainRouter = async (app: App) => { @@ -20,7 +22,7 @@ router.beforeEach((to, from, next) => { const newMatched = to.matched; handleAliveRoute(newMatched, 'add'); // 页面整体刷新 - if (from.name === undefined || from.name === 'redirect') { + if (from.name === undefined || from.name === 'Redirect') { handleAliveRoute(newMatched); } } diff --git a/src/router/modules/editor/index.ts b/src/router/modules/editor/index.ts index 53d9118d..33b11e3e 100644 --- a/src/router/modules/editor/index.ts +++ b/src/router/modules/editor/index.ts @@ -4,7 +4,7 @@ import { t } from '@/hooks/web/useI18n'; const editor: AppRouteRecordRaw[] = [ { path: '/editor', - redirect: '/editor/logic-flow', + redirect: '/editor/rich-text', name: 'RtEditor', meta: { title: t('route.pathName.editor'), icon: 'editor', position: 4 }, children: [ diff --git a/src/router/modules/useradmin/index.ts b/src/router/modules/useradmin/index.ts index 7a08717c..ad0aa36d 100644 --- a/src/router/modules/useradmin/index.ts +++ b/src/router/modules/useradmin/index.ts @@ -4,7 +4,7 @@ import { t } from '@/hooks/web/useI18n'; const useradmin: AppRouteRecordRaw[] = [ { path: '/useradmin', - redirect: '/useradmin/userlist', + redirect: '/useradmin/refSyntax', name: 'RtUseradmin', meta: { title: t('route.pathName.userInfo'), icon: 'iEL-avatar', position: 5 }, children: [ diff --git a/src/router/utils.ts b/src/router/utils.ts index 384246b7..d1e19aed 100644 --- a/src/router/utils.ts +++ b/src/router/utils.ts @@ -161,13 +161,13 @@ function handleAliveRoute(matched: RouteRecordNormalized[], mode?: string) { } // 通过path获取父级路径 -function getParentPaths(routeName: RouteRecordName, routes: AppRouteRecordRaw[]) { +function getParentPaths(routePath: string, routes: AppRouteRecordRaw[]) { // 深度遍历查找 - function dfs(routes: AppRouteRecordRaw[], path: RouteRecordName, parents: string[]) { + function dfs(routes: AppRouteRecordRaw[], path: string, parents: string[]) { for (let i = 0; i < routes.length; i++) { const item = routes[i]; // 找到path则返回父级path - if (item.name === path) return [item.name]; + if (item.path === path) return [item.path]; // children不存在或为空则不递归 if (!item.children || !item.children.length) continue; // 往下查找时将当前path入栈 @@ -180,26 +180,23 @@ function getParentPaths(routeName: RouteRecordName, routes: AppRouteRecordRaw[]) // 未找到时返回空数组 return []; } - return dfs(routes, routeName, []); + return dfs(routes, routePath, []); } // 查找对应path的路由信息 -function findRouteByPath( - path: RouteRecordName, - routes: AppRouteRecordRaw[], -): AppRouteRecordRaw | null { - let res = routes.find((item: { path: RouteRecordName }) => item.path == path) || null; +function findRouteByPath(path: string, routes: AppRouteRecordRaw[]): AppRouteRecordRaw | null { + const res = routes.find((item: { path: string }) => item.path == path) || null; if (res) { return res; } else { for (let i = 0; i < routes.length; i++) { if (routes[i].children instanceof Array && routes[i].children?.length) { - res = findRouteByPath(path, routes[i].children as AppRouteRecordRaw[]); - if (res) { - return res; + const miRes = findRouteByPath(path, routes[i].children as AppRouteRecordRaw[]); + if (miRes) { + return miRes; + } else { + if (routes[i].path == path) return routes[i]; } - } else { - return routes[i]; } } return null; diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts index 7a579da5..da743565 100644 --- a/src/store/modules/app.ts +++ b/src/store/modules/app.ts @@ -9,7 +9,7 @@ let localAppConfig: appConfig = { locale: 'zh-ch', }; -export const useAppStore = defineStore({ +const useAppStore = defineStore({ id: 'app', state: (): AppState => ({ appConfigMode: localAppConfig, diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts index 9c77a070..86bb40ed 100644 --- a/src/store/modules/permission.ts +++ b/src/store/modules/permission.ts @@ -1,16 +1,18 @@ import { defineStore } from 'pinia'; import { store } from '@/store'; import { RouteRecordName } from 'vue-router'; -import type { PermissionState } from '../types'; +import type { MultiTabsType, PermissionState } from '../types'; import { AppRouteRecordRaw } from '#/route'; -export const usePermissionStore = defineStore({ +const usePermissionStore = defineStore({ id: 'permission', state: (): PermissionState => ({ // 路由菜单 wholeMenus: [], // 缓存页面keepAlive cachePageList: [], + // 标签页(路由记录) + multiTabs: [], }), actions: { setWholeMenus(routeList: AppRouteRecordRaw[]) { @@ -32,6 +34,23 @@ export const usePermissionStore = defineStore({ clearAllCachePage() { this.cachePageList = []; }, + handleMultiTabs(type: 'add' | 'delete', value: T | MultiTabsType) { + switch (type) { + case 'add': + const route = value as MultiTabsType; + const isAlike = this.multiTabs.find((i) => i.path === route.path); + if (isAlike) return; + this.multiTabs.push(route); + break; + case 'delete': + const index = this.multiTabs.findIndex((i) => i.path === (value as unknown as string)); + if (index === -1) return; + this.multiTabs.splice(index, 1); + break; + default: + break; + } + }, }, }); diff --git a/src/store/types.ts b/src/store/types.ts index 732afa3d..fc3f620a 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -1,5 +1,5 @@ import { AppRouteRecordRaw } from '#/route'; -import { RouteRecordName } from 'vue-router'; +import { RouteRecordName, _RouteLocationBase } from 'vue-router'; export type AppState = { appConfigMode: appConfig; @@ -14,7 +14,12 @@ export interface appConfig { locale: string; } +export type MultiTabsType = Omit< + _RouteLocationBase, + 'fullPath' | 'hash' | 'params' | 'redirectedFrom' +>; export type PermissionState = { wholeMenus: AppRouteRecordRaw[]; cachePageList: RouteRecordName[]; + multiTabs: MultiTabsType[]; }; diff --git a/src/styles/el-theme.scss b/src/styles/el-theme.scss index 4853e053..86c1cf56 100644 --- a/src/styles/el-theme.scss +++ b/src/styles/el-theme.scss @@ -2,7 +2,7 @@ $sideBarWidth: 210px; $sideHideBarWidth: 54px; $navBarHeight: 57px; -$TabsPageHeight: 0; //面包屑高度 38px +$tabsPageHeight: 38px; //面包屑高度 38px $menuBg: var(--main-bg-color); // 侧边栏背景颜色 $menuHover: var(--sub-main-bg-content); // 焦点背景色 diff --git a/src/styles/index.scss b/src/styles/index.scss index 80250f0b..050b5057 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -83,6 +83,10 @@ ul { margin: 0; } +.cursor { + cursor: pointer; +} + @for $i from 1 to 6 { * > .enter-x:nth-child(#{$i}) { transform: translateX(50px); diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss index ad353de3..037e3e39 100644 --- a/src/styles/sidebar.scss +++ b/src/styles/sidebar.scss @@ -34,8 +34,7 @@ .main-container-tabs { width: 100%; - height: #{$TabsPageHeight}; - padding: 0 20px; + height: #{$tabsPageHeight}; background-color: $TabsPageColor; } } diff --git a/src/utils/mitt.ts b/src/utils/mitt.ts new file mode 100644 index 00000000..d7e312f4 --- /dev/null +++ b/src/utils/mitt.ts @@ -0,0 +1,6 @@ +import type { Emitter } from 'mitt'; +import mitt from 'mitt'; + +type Events = {}; + +export const emitter: Emitter = mitt(); diff --git a/src/utils/plugin/element.ts b/src/utils/plugin/element.ts index 735ea193..c65dfba1 100644 --- a/src/utils/plugin/element.ts +++ b/src/utils/plugin/element.ts @@ -34,6 +34,8 @@ import { ElTable, ElTableColumn, ElCalendar, + ElTabs, + ElTabPane, // 指令 ElLoading, ElInfiniteScroll, @@ -77,6 +79,8 @@ const components = [ ElTable, ElTableColumn, ElCalendar, + ElTabs, + ElTabPane, ]; // https://element-plus.org/zh-CN/component/icon.html @@ -87,10 +91,11 @@ import { Grid, Setting, RemoveFilled, + Refresh, } from '@element-plus/icons-vue'; // Icon -export const iconComponents = [HomeFilled, Avatar, Operation, Grid, Setting, RemoveFilled]; +export const iconComponents = [HomeFilled, Avatar, Operation, Grid, Setting, RemoveFilled, Refresh]; export function useElementPlus(app: App) { // 注册组件