From cd95f8f1b8a4c3e00eae763714c9542319885cca Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期三, 01 四月 2026 08:10:59 +0800
Subject: [PATCH] #前端
---
rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue | 37 ++++++++++++++++--
rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss | 9 +++-
rsf-design/pnpm-lock.yaml | 38 +++++++++++++++++++
rsf-design/src/components/core/layouts/art-settings-panel/composables/useSettingsState.js | 7 +++
rsf-design/package.json | 1
rsf-design/src/components/core/layouts/art-header-bar/index.vue | 10 +++-
rsf-design/src/main.js | 16 ++++++++
7 files changed, 109 insertions(+), 9 deletions(-)
diff --git a/rsf-design/package.json b/rsf-design/package.json
index 82a0385..50c1f4f 100644
--- a/rsf-design/package.json
+++ b/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",
diff --git a/rsf-design/pnpm-lock.yaml b/rsf-design/pnpm-lock.yaml
index b62433e..f72aaef 100644
--- a/rsf-design/pnpm-lock.yaml
+++ b/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
diff --git a/rsf-design/src/components/core/layouts/art-header-bar/index.vue b/rsf-design/src/components/core/layouts/art-header-bar/index.vue
index ccebde0..d43b54a 100644
--- a/rsf-design/src/components/core/layouts/art-header-bar/index.vue
+++ b/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()
diff --git a/rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue b/rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue
index 9832685..3cc1fd4 100644
--- a/rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue
+++ b/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
diff --git a/rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss b/rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss
index 8cccdd9..1641584 100644
--- a/rsf-design/src/components/core/layouts/art-menus/art-sidebar-menu/style.scss
+++ b/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;
}
diff --git a/rsf-design/src/components/core/layouts/art-settings-panel/composables/useSettingsState.js b/rsf-design/src/components/core/layouts/art-settings-panel/composables/useSettingsState.js
index ee95813..ed9a46b 100644
--- a/rsf-design/src/components/core/layouts/art-settings-panel/composables/useSettingsState.js
+++ b/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 {
// 鏂规硶
diff --git a/rsf-design/src/main.js b/rsf-design/src/main.js
index 65788a6..8f704c3 100644
--- a/rsf-design/src/main.js
+++ b/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)
--
Gitblit v1.9.1