diff --git a/src/layouts/base-layout/base-layout-sider.vue b/src/layouts/base-layout/base-layout-sider.vue index 5aa447f..516a2c8 100644 --- a/src/layouts/base-layout/base-layout-sider.vue +++ b/src/layouts/base-layout/base-layout-sider.vue @@ -44,7 +44,42 @@ function convertRoutesToMenuOptions(routes: Readonly): MenuOpt } return true; }) - .sort((a, b) => a.path.localeCompare(b.path)); + // 排序路由,确保父路由总是在子路由之前,同级路由则根据 `meta.order` 排序 + .sort((a: RouteRecordRaw, b: RouteRecordRaw) => { + const pathA = a.path; + const pathB = b.path; + const segmentsA = pathA.split('/').filter(Boolean); + const segmentsB = pathB.split('/').filter(Boolean); + const parentAPath = `/${segmentsA.slice(0, -1).join('/')}`; + const parentBPath = `/${segmentsB.slice(0, -1).join('/')}`; + + // 如果不是同级路由,则按路径排序,确保父路由在前 + if (parentAPath !== parentBPath) { + return pathA.localeCompare(pathB); + } + + // 同级路由,处理 `meta.order` + const orderA = a.meta?.order; + const orderB = b.meta?.order; + const hasOrderA = orderA !== undefined; + const hasOrderB = orderB !== undefined; + + // 当一个有 order 而另一个没有时,有 order 的排在前面 + if (hasOrderA !== hasOrderB) { + return hasOrderA ? -1 : 1; + } + + // 当两个都有 order 时,按 order 值升序排序 + if (hasOrderA && hasOrderB) { + const orderDiff = orderA - orderB; + if (orderDiff !== 0) { + return orderDiff; + } + } + + // order 相同或都没有 order,按路径字母顺序排序 + return pathA.localeCompare(pathB); + }); // 构建菜单树 for (const route of validRoutes) { diff --git a/src/pages/demos/i18n-demo.page.vue b/src/pages/demos/i18n-demo.page.vue index 77ed5ae..f19b577 100644 --- a/src/pages/demos/i18n-demo.page.vue +++ b/src/pages/demos/i18n-demo.page.vue @@ -1,6 +1,8 @@ diff --git a/src/plugins/00.app-config.ts b/src/plugins/00.app-config.ts index 032717b..85b2b0f 100644 --- a/src/plugins/00.app-config.ts +++ b/src/plugins/00.app-config.ts @@ -1,10 +1,6 @@ -import { autoAnimatePlugin } from '@formkit/auto-animate/vue'; - export function install({ app }: { app: import('vue').App }) { app.config.globalProperties.__DEV__ = __DEV__; - app.use(autoAnimatePlugin); // v-auto-animate="{ duration: 100 }" - app.config.errorHandler = (error, instance, info) => { console.error('Global error:', error); console.error('Component:', instance); diff --git a/src/plugins/00.router-plugin.ts b/src/plugins/00.router-plugin.ts index 9f6c049..9f693a5 100644 --- a/src/plugins/00.router-plugin.ts +++ b/src/plugins/00.router-plugin.ts @@ -43,8 +43,10 @@ declare module 'vue-router' { * @description 是否在菜单中隐藏 */ hideInMenu?: boolean; + /** * @description 菜单标题 + * @deprecated //!⚠️请通过多语言标题方案(搜`PageTitleLocalizations`)维护标题 */ title?: string; @@ -59,6 +61,11 @@ declare module 'vue-router' { * - false: 仅渲染纯文本标签,不可点击(适用于分组标题) */ link?: boolean; + + /** + * @description 菜单排序权重,数值越小越靠前,未设置则按路径字母顺序排序 + */ + order?: number; } }