123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- <template>
- <ButtonPane class="menus" :size="size" :dire="dire">
- <div
- v-for="menu in menus"
- :key="menu.key"
- class="menu"
- :style="menuStyle"
- :class="{
- active: activeKey === menu.key,
- dire,
- disabled: disabledMap[menu.key],
- border: menu.border,
- }"
- @click="menu.onClick && menu.onClick(menu)"
- v-show="!menu.hide"
- >
- <template v-if="$slots.default">
- <slot :data="menu" />
- </template>
- <ui-icon :type="menu.icon || 'close'" class="icon" v-else />
- <p v-if="menu.text">{{ menu.text }}</p>
- </div>
- </ButtonPane>
- </template>
- <script setup lang="ts">
- import ButtonPane from "@/components/button-pane/index.vue";
- import UiIcon from "@/components/base/components/icon/index.vue";
- import { computed } from "vue";
- type Menu = {
- key: any;
- text?: string;
- hide?: boolean;
- border?: boolean;
- icon?: string;
- disabled?: boolean | (() => boolean);
- onClick?: (menu: Menu) => void;
- };
- const props = withDefaults(
- defineProps<{
- menus: Menu[];
- activeKey?: any;
- dire?: "row" | "column";
- size?: number;
- }>(),
- { dire: "row", size: 64 }
- );
- const disabledMap = computed(() => {
- const map = {};
- for (let menu of props.menus) {
- map[menu.key] = !menu.disabled
- ? false
- : typeof menu.disabled === "boolean"
- ? menu.disabled
- : menu.disabled();
- }
- return map;
- });
- const menuStyle = computed(() => {
- const offset = props.size / 4;
- return props.dire === "row"
- ? {
- padding: `0 10px`,
- marginRight: "8px",
- }
- : {
- padding: `10px 0 `,
- marginBottom: "8px",
- };
- });
- </script>
- <style lang="scss" scoped>
- .menu {
- &:first-child:last-child {
- position: absolute;
- left: 50%;
- top: 50%;
- height: 80%;
- transform: translate(-50%, -50%);
- }
- min-width: 56px;
- display: flex;
- flex-direction: column;
- cursor: pointer;
- height: 100%;
- text-align: center;
- transition: color 0.3s ease;
- color: #fff;
- border-radius: 4px;
- align-items: center;
- justify-content: center;
- &.border {
- position: relative;
- &:after {
- content: "";
- position: absolute;
- border-bottom: 1px solid rgba(255, 255, 255, 0.2);
- left: 10px;
- right: 10px;
- bottom: 0;
- }
- }
- &.active {
- color: var(--colors-primary-base);
- }
- &.active {
- background: rgba(255, 255, 255, 0.1);
- }
- .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 20px;
- }
- p {
- flex: 1;
- flex: none;
- margin-top: 4px;
- line-height: 17px;
- font-size: 14px;
- white-space: nowrap;
- }
- }
- </style>
|