SideMenuItem.vue 1.58 KB
<template>
  <template v-if="item.type === 1 && item.children?.length">
    <el-sub-menu :index="String(item.id)">
      <template #title>
        <el-icon class="menu-ico"><component :is="iconComp" /></el-icon>
        <span>{{ item.name }}</span>
      </template>
      <SideMenuItem v-for="ch in item.children" :key="ch.id" :item="ch" />
    </el-sub-menu>
  </template>
  <el-menu-item v-else-if="item.path && item.type === 2" :index="item.path">
    <el-icon class="menu-ico"><component :is="iconComp" /></el-icon>
    <span>{{ item.name }}</span>
  </el-menu-item>
  <el-sub-menu v-else-if="item.children?.length" :index="String(item.id)">
    <template #title>
      <span>{{ item.name }}</span>
    </template>
    <SideMenuItem v-for="ch in item.children" :key="ch.id" :item="ch" />
  </el-sub-menu>
</template>

<script setup lang="ts">
import { computed } from "vue";
import type { MenuNode } from "@/api/admin";
import {
  Menu,
  User,
  Setting,
  Odometer,
  Document,
  Picture,
  UserFilled,
  PictureFilled,
  MapLocation,
  CircleCheck,
  Avatar,
} from "@element-plus/icons-vue";

const props = defineProps<{ item: MenuNode }>();

const iconMap: Record<string, typeof Menu> = {
  setting: Setting,
  user: User,
  team: UserFilled,
  menu: Menu,
  picture: Picture,
  image: PictureFilled,
  audit: CircleCheck,
  map: MapLocation,
  odometer: Odometer,
  document: Document,
  avatar: Avatar,
};

const iconComp = computed(() => {
  const key = (props.item.icon || "").toLowerCase();
  return iconMap[key] || Document;
});
</script>

<style scoped>
.menu-ico {
  margin-right: 8px;
}
</style>