+
Plusone Admin
@@ -15,8 +22,9 @@ const props = defineProps({
.logo {
padding: 20px 16px;
display: inline-flex;
- background-color: rgb(0, 20, 40);
+ background-color: var(--n-color);
color: #ffffff;
+ height: 32px;
}
.logo > img {
diff --git a/src/views/HomeView/components/MenuVO.ts b/src/views/HomeView/components/MenuVO.ts
new file mode 100644
index 0000000..7eeed30
--- /dev/null
+++ b/src/views/HomeView/components/MenuVO.ts
@@ -0,0 +1,113 @@
+import type { MenuOption } from 'naive-ui'
+import { type RouteRecordRaw, RouterLink } from 'vue-router'
+import { NIcon } from 'naive-ui'
+import * as iconComponents from '@vicons/fluent'
+import { type Component, h } from 'vue'
+
+export interface MenuVO {
+ type: number
+ typeName: string
+ id: number
+ parentId: number
+ name: string
+ // 若 type 为 MENU_ITEM 且 path 以 http:// 或 https:// 开头则被识别为外链
+ path: string
+ title: string
+ icon: string
+ hidden: boolean
+ orderNumber: number
+ status: number
+ remarks: string
+
+ // MENU_ITEM
+ component?: string
+ cache?: boolean
+ resource?: string
+ actions?: ActionVO[]
+
+ // MENU_LIST
+ children?: MenuVO[]
+}
+
+interface ActionVO {
+ id: number
+ identifier: string
+ label: string
+ value: string
+}
+
+export enum MenuType {
+ MENU_LIST,
+ MENU_ITEM,
+}
+
+export function convertToRoutes(menuVOTree: MenuVO[]): RouteRecordRaw[] {
+ const routes: RouteRecordRaw[] = menuVOTree.map((menuVO) => {
+ if (menuVO.type == MenuType.MENU_LIST) {
+ return {
+ path: menuVO.path,
+ name: menuVO.name,
+ component:
+ menuVO.component !== undefined ? () => import('@/views' + menuVO.component) : undefined,
+ children: convertToRoutes(menuVO.children ? menuVO.children : []),
+ meta: {
+ title: menuVO.title,
+ icon: menuVO.icon,
+ hidden: menuVO.hidden,
+ order: menuVO.orderNumber,
+ status: menuVO.status,
+ remarks: menuVO.remarks,
+ },
+ }
+ } else {
+ return {
+ path: menuVO.path,
+ name: menuVO.name,
+ component: import('@/views' + menuVO.component),
+ meta: {
+ title: menuVO.title,
+ icon: menuVO.icon,
+ hidden: menuVO.hidden,
+ order: menuVO.orderNumber,
+ status: menuVO.status,
+ remarks: menuVO.remarks,
+ },
+ }
+ }
+ })
+
+ return routes
+}
+
+export function convertToMenuOptions(menuVOTree: MenuVO[]): MenuOption[] {
+ const menuOptions: MenuOption[] = menuVOTree.map((menuVO) => {
+ if (menuVO.type == MenuType.MENU_ITEM) {
+ return {
+ key: menuVO.name,
+ icon: renderIcon(menuVO.icon),
+ label:
+ menuVO.path.startsWith('http://') || menuVO.path.startsWith('https://')
+ ? () => h('a', { href: menuVO.path, target: '_blank' }, menuVO.title)
+ : () => h(RouterLink, { to: menuVO.path }, menuVO.title),
+ }
+ } else {
+ return {
+ key: menuVO.name,
+ icon: renderIcon(menuVO.icon),
+ label: menuVO.title,
+ children: convertToMenuOptions(menuVO.children ? menuVO.children : []),
+ }
+ }
+ })
+
+ return menuOptions
+}
+
+const icons: Map
= new Map(Object.entries(iconComponents))
+export function renderIcon(icon: string) {
+ const iconComponent = icons.get(icon)
+ return () =>
+ h(NIcon, null, {
+ default: () => h(iconComponent ? iconComponent : iconComponents.QuestionCircle20Regular),
+ })
+}
diff --git a/src/views/HomeView/components/SiderMenu.vue b/src/views/HomeView/components/SiderMenu.vue
new file mode 100644
index 0000000..c2da31f
--- /dev/null
+++ b/src/views/HomeView/components/SiderMenu.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
diff --git a/tsconfig.json b/tsconfig.json
index 8d23599..1e30659 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,8 +2,11 @@
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"compilerOptions": {
+ "lib": ["ES2017"],
+ "target": "ES2015",
"baseUrl": ".",
"paths": {
+ "@": ["src"],
"@/*": ["./src/*"]
}
},
diff --git a/vite.config.ts b/vite.config.ts
index 0404e6b..ed5fc1f 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -11,4 +11,7 @@ export default defineConfig({
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
+ server: {
+ port: 8888,
+ },
})