index.vue 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <template>
  2. <ButtonPane class="menus" :size="size" :dire="dire">
  3. <div
  4. v-for="menu in menus"
  5. :key="menu.key"
  6. class="menu"
  7. :style="menuStyle"
  8. :class="{ active: activeKey === menu.key, dire, disabled: disabledMap[menu.key] }"
  9. @click="menu.onClick && menu.onClick(menu)"
  10. >
  11. <template v-if="$slots.default">
  12. <slot :data="menu" />
  13. </template>
  14. <ui-icon :type="menu.icon || 'close'" class="icon" v-else/>
  15. <p v-if="menu.text">{{ menu.text }}</p>
  16. </div>
  17. </ButtonPane>
  18. </template>
  19. <script setup lang="ts">
  20. import ButtonPane from '@/components/button-pane/index.vue'
  21. import UiIcon from "@/components/base/components/icon/index.vue";
  22. import {computed} from "vue";
  23. type Menu = {
  24. key: any,
  25. text?: string,
  26. icon?: string,
  27. disabled?: boolean | (() => boolean)
  28. onClick?: (menu: Menu) => void
  29. }
  30. const props = withDefaults(
  31. defineProps<{ menus: Menu[], activeKey?: any, dire?: 'row' | 'column', size?: number }>(),
  32. {dire: 'row', size: 64}
  33. )
  34. const disabledMap = computed(() => {
  35. const map = {}
  36. for (let menu of props.menus) {
  37. map[menu.key] = !menu.disabled ? false :
  38. typeof menu.disabled === "boolean" ? menu.disabled : menu.disabled()
  39. }
  40. return map
  41. })
  42. const menuStyle = computed(() => {
  43. const offset = props.size / 4;
  44. return props.dire === 'row'
  45. ? {
  46. padding: `0 10px`,
  47. marginRight: '8px'
  48. }
  49. :
  50. {
  51. padding: `10px 0 `,
  52. marginBottom: '8px'
  53. }
  54. })
  55. </script>
  56. <style lang="scss" scoped>
  57. .menu {
  58. min-width: 56px;
  59. display: flex;
  60. flex-direction: column;
  61. cursor: pointer;
  62. height: 100%;
  63. text-align: center;
  64. transition: color .3s ease;
  65. color: #fff;
  66. border-radius: 4px;
  67. &.active {
  68. color: var(--colors-primary-base);
  69. }
  70. &.active {
  71. background: rgba(255, 255, 255, 0.1);;
  72. }
  73. .icon {
  74. display: flex;
  75. align-items: center;
  76. justify-content: center;
  77. font-size: 20px;
  78. flex: 1;
  79. }
  80. p {
  81. line-height: 17px;
  82. font-size: 14px;
  83. white-space:nowrap;
  84. }
  85. }
  86. </style>