Sidebar.vue 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. <template>
  2. <div class="sidebar">
  3. <div v-if="title" class="title">
  4. <h2>{{ title }}</h2>
  5. </div>
  6. <ul class="sidebar-menu">
  7. <slot />
  8. <li v-for="(item, key) in items" :key="key">
  9. <a v-if="item.link.startsWith('http')" :href="item.link" target="_blank">
  10. {{ item.text }}
  11. <Icon name="material-symbols-light:chevron-right" />
  12. </a>
  13. <router-link v-else :to="item.link" :class="{ 'active': item.id == activeId }">
  14. {{ item.text }}
  15. <Icon name="material-symbols-light:chevron-right" />
  16. </router-link>
  17. </li>
  18. <li v-if="showBackUpLevel">
  19. <router-link :to="backUpLevelLink">
  20. <div @click="emit('backUpLevel')">
  21. <Icon name="material-symbols:undo" />
  22. 返回上一级
  23. </div>
  24. </router-link>
  25. </li>
  26. <li v-else-if="showEmpty && (!items || items.length === 0)" class="no-content">
  27. 暂无相关子分类
  28. </li>
  29. </ul>
  30. </div>
  31. </template>
  32. <script setup lang="ts">
  33. const props = defineProps({
  34. title: {
  35. type: String,
  36. default: '',
  37. },
  38. activeId: {
  39. type: Number,
  40. default: 0,
  41. },
  42. showBackUpLevel: {
  43. type: Boolean,
  44. default: false,
  45. },
  46. showEmpty: {
  47. type: Boolean,
  48. default: true,
  49. },
  50. backUpLevelLink: {
  51. type: String,
  52. default: '',
  53. },
  54. items: {
  55. type: Object as PropType<Array<{
  56. id: number;
  57. text: string;
  58. link: string;
  59. }>>,
  60. default: () => ([]),
  61. },
  62. });
  63. const emit = defineEmits(['backUpLevel']);
  64. </script>