| rsf-design/package.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/pnpm-lock.yaml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/components/core/layouts/art-header-bar/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/components/core/layouts/art-settings-panel/composables/useSettingsState.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| rsf-design/src/main.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
rsf-design/package.json
@@ -57,6 +57,7 @@ }, "devDependencies": { "@eslint/js": "^9.9.1", "@playwright/test": "^1.58.2", "@types/node": "^24.0.5", "@vitejs/plugin-vue": "^6.0.1", "@vue/compiler-sfc": "^3.0.5", rsf-design/pnpm-lock.yaml
@@ -117,6 +117,9 @@ '@eslint/js': specifier: ^9.9.1 version: 9.36.0 '@playwright/test': specifier: ^1.58.2 version: 1.58.2 '@types/node': specifier: ^24.0.5 version: 24.8.1 @@ -788,6 +791,11 @@ '@pkgr/core@0.2.9': resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} '@playwright/test@1.58.2': resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==} engines: {node: '>=18'} hasBin: true '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -1829,6 +1837,11 @@ resolution: {integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==} engines: {node: '>=14.14'} fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2437,6 +2450,16 @@ pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} playwright-core@1.58.2: resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==} engines: {node: '>=18'} hasBin: true playwright@1.58.2: resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==} engines: {node: '>=18'} hasBin: true postcss-html@1.8.0: resolution: {integrity: sha512-5mMeb1TgLWoRKxZ0Xh9RZDfwUUIqRrcxO2uXO+Ezl1N5lqpCiSU5Gk6+1kZediBfBHFtPCdopr2UZ2SgUsKcgQ==} @@ -3654,6 +3677,10 @@ '@pkgr/core@0.2.9': {} '@playwright/test@1.58.2': dependencies: playwright: 1.58.2 '@polka/url@1.0.0-next.29': {} '@rolldown/pluginutils@1.0.0-beta.29': {} @@ -4752,6 +4779,9 @@ jsonfile: 6.2.0 universalify: 2.0.1 fsevents@2.3.2: optional: true fsevents@2.3.3: optional: true @@ -5246,6 +5276,14 @@ exsolve: 1.0.7 pathe: 2.0.3 playwright-core@1.58.2: {} playwright@1.58.2: dependencies: playwright-core: 1.58.2 optionalDependencies: fsevents: 2.3.2 postcss-html@1.8.0: dependencies: htmlparser2: 8.0.2 rsf-design/src/components/core/layouts/art-header-bar/index.vue
@@ -54,10 +54,10 @@ /> <!-- 顶部菜单 --> <ArtHorizontalMenu v-if="isTopMenu" :list="menuList" /> <ArtHorizontalMenu v-if="isTopMenu" :key="topMenuRenderKey" :list="menuList" /> <!-- 混合菜单-顶部 --> <ArtMixedMenu v-if="isTopLeftMenu" :list="menuList" /> <ArtMixedMenu v-if="isTopLeftMenu" :key="topMenuRenderKey" :list="menuList" /> </div> <div class="flex-c gap-2.5"> @@ -175,7 +175,7 @@ import { themeAnimation } from '@/utils/ui/animation' import { useI18n } from 'vue-i18n' import { useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router' import { useFullscreen, useWindowSize } from '@vueuse/core' import { MenuTypeEnum } from '@/enums/appEnum' import { useSettingStore } from '@/store/modules/setting' @@ -186,6 +186,7 @@ import { useHeaderBar } from '@/hooks/core/useHeaderBar' defineOptions({ name: 'ArtHeaderBar' }) const isWindows = navigator.userAgent.includes('Windows') const route = useRoute() const router = useRouter() const { locale } = useI18n() const { width } = useWindowSize() @@ -216,6 +217,9 @@ const isDualMenu = computed(() => menuType.value === MenuTypeEnum.DUAL_MENU) const isTopMenu = computed(() => menuType.value === MenuTypeEnum.TOP) const isTopLeftMenu = computed(() => menuType.value === MenuTypeEnum.TOP_LEFT) const topMenuRenderKey = computed(() => { return `${menuType.value}:${String(route.meta.activePath || route.path)}` }) const { isFullscreen, toggle: toggleFullscreen } = useFullscreen() onMounted(() => { initLanguage() rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue
@@ -88,6 +88,7 @@ </div> <ElScrollbar :style="scrollbarStyle"> <ElMenu :key="menuRenderKey" :class="'el-menu-' + getMenuTheme.theme" :collapse="!menuOpen" :default-active="routerPath" @@ -161,8 +162,35 @@ ) const isDualMenu = computed(() => menuType.value === MenuTypeEnum.DUAL_MENU) const isMobileScreen = computed(() => width.value < MOBILE_BREAKPOINT) const firstLevelMenuPath = computed(() => route.matched[0]?.path) const routerPath = computed(() => String(route.meta.activePath || route.path)) const normalizeRoutePath = (path) => { if (!path) { return '' } return `/${String(path).replace(/^\/+/, '').replace(/\/+$/, '')}` } const findTopLevelMenuByPath = (menus, targetPath) => { const normalizedTargetPath = normalizeRoutePath(targetPath) const containsPath = (menu) => { if (!menu) { return false } if (normalizeRoutePath(menu.path) === normalizedTargetPath) { return true } if (!Array.isArray(menu.children) || menu.children.length === 0) { return false } return menu.children.some((child) => containsPath(child)) } return menus.find((menu) => containsPath(menu)) || null } const currentTopLevelMenu = computed(() => { return findTopLevelMenuByPath(useMenuStore().menuList, routerPath.value) }) const firstLevelMenuPath = computed( () => currentTopLevelMenu.value?.path || route.matched[0]?.path ) const firstLevelMenus = computed(() => { return useMenuStore().menuList.filter((menu) => !menu.meta.isHide) }) @@ -178,9 +206,10 @@ if (route.meta.isFirstLevel) { return [] } const currentTopPath = `/${route.path.split('/')[1]}` const currentMenu = allMenus.find((menu) => menu.path === currentTopPath) return currentMenu?.children ?? [] return currentTopLevelMenu.value?.children ?? [] }) const menuRenderKey = computed(() => { return `${menuType.value}:${firstLevelMenuPath.value || 'root'}` }) const scrollbarStyle = computed(() => { const isCollapsed = isDualMenu.value && !menuOpen.value rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss
@@ -49,8 +49,13 @@ border-radius: 5px; .art-svg-icon { display: block; margin: 0 auto; display: flex !important; align-items: center; justify-content: center; width: 100%; margin: 0 auto !important; margin-right: auto !important; margin-left: auto !important; font-size: 20px; } rsf-design/src/components/core/layouts/art-settings-panel/composables/useSettingsState.js
@@ -1,3 +1,4 @@ import { nextTick } from 'vue' import { useSettingStore } from '@/store/modules/setting' import { MenuThemeEnum, MenuTypeEnum } from '@/enums/appEnum' function useSettingsState() { @@ -11,6 +12,9 @@ } } const switchMenuLayouts = (type) => { if (settingStore.menuType === type) { return } if (type === MenuTypeEnum.LEFT || type === MenuTypeEnum.TOP_LEFT) { settingStore.setMenuOpen(true) } @@ -19,6 +23,9 @@ settingStore.switchMenuStyles(MenuThemeEnum.DESIGN) settingStore.setMenuOpen(true) } nextTick(() => { settingStore.reload() }) } return { // 方法 rsf-design/src/main.js
@@ -12,6 +12,22 @@ document.addEventListener('touchstart', function () {}, { passive: false }) registerLocalIconCollections() const app = createApp(App) // 注入错误日志面板用于调试 app.config.errorHandler = (err, vm, info) => { console.error("Vue Error:", err, info); const div = document.createElement("div"); div.style = "position:fixed;top:0;left:0;z-index:99999;background:red;color:white;padding:20px;font-size:16px;white-space:pre-wrap;width:100vw;height:100vh;overflow:auto;"; div.innerText = "Error: " + (err.message || err) + "\n\nStack:\n" + err.stack + "\n\nInfo: " + info; document.body.appendChild(div); }; window.addEventListener("error", (event) => { const div = document.createElement("div"); div.style = "position:fixed;top:0;left:0;z-index:99999;background:red;color:white;padding:20px;font-size:16px;white-space:pre-wrap;width:100vw;height:100vh;overflow:auto;"; div.innerText = "Global Error: " + event.message + "\n\n" + event.error?.stack; document.body.appendChild(div); }); initStore(app) initRouter(app) setupGlobDirectives(app)