mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-12-25 14:20:21 +08:00
154 lines
3.2 KiB
Vue
154 lines
3.2 KiB
Vue
<template>
|
|
<n-dropdown
|
|
:show="dropdownVisible"
|
|
:options="options"
|
|
placement="bottom-start"
|
|
:x="x"
|
|
:y="y"
|
|
@clickoutside="hide"
|
|
@select="handleDropdown"
|
|
/>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, watch } from 'vue';
|
|
import { NDropdown } from 'naive-ui';
|
|
import type { DropdownOption } from 'naive-ui';
|
|
import { useAppStore } from '@/store';
|
|
import { useReloadInject } from '@/context';
|
|
import { useBoolean } from '@/hooks';
|
|
import { ROUTE_HOME } from '@/router';
|
|
import { iconifyRender } from '@/utils';
|
|
|
|
interface Props {
|
|
/** 右键菜单可见性 */
|
|
visible?: boolean;
|
|
/** 当前是否是路由首页 */
|
|
isRouteHome?: boolean;
|
|
/** 当前路由路径 */
|
|
currentPath?: string;
|
|
/** 鼠标x坐标 */
|
|
x: number;
|
|
/** 鼠标y坐标 */
|
|
y: number;
|
|
}
|
|
|
|
type DropdownKey = 'reload-current' | 'close-current' | 'close-other' | 'close-left' | 'close-right' | 'close-all';
|
|
type Option = DropdownOption & {
|
|
key: DropdownKey;
|
|
};
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
visible: false,
|
|
isRouteHome: false,
|
|
currentPath: ''
|
|
});
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:visible', visible: boolean): void;
|
|
}>();
|
|
|
|
const app = useAppStore();
|
|
const { removeMultiTab, clearMultiTab, clearLeftMultiTab, clearRightMultiTab } = useAppStore();
|
|
const { handleReload } = useReloadInject();
|
|
const { bool: dropdownVisible, setTrue: show, setFalse: hide } = useBoolean(props.visible);
|
|
|
|
const options = computed<Option[]>(() => [
|
|
{
|
|
label: '重新加载',
|
|
key: 'reload-current',
|
|
disabled: props.currentPath !== app.multiTab.activeRoute,
|
|
icon: iconifyRender('ant-design:reload-outlined')
|
|
},
|
|
{
|
|
label: '关闭标签页',
|
|
key: 'close-current',
|
|
disabled: props.currentPath === ROUTE_HOME.path,
|
|
icon: iconifyRender('ant-design:close-outlined')
|
|
},
|
|
{
|
|
label: '关闭其他标签页',
|
|
key: 'close-other',
|
|
icon: iconifyRender('ant-design:column-width-outlined')
|
|
},
|
|
{
|
|
label: '关闭左边标签页',
|
|
key: 'close-left',
|
|
icon: iconifyRender('mdi:format-horizontal-align-left')
|
|
},
|
|
{
|
|
label: '关闭右边标签页',
|
|
key: 'close-right',
|
|
icon: iconifyRender('mdi:format-horizontal-align-right')
|
|
},
|
|
{
|
|
label: '关闭全部标签页',
|
|
key: 'close-all',
|
|
icon: iconifyRender('ant-design:minus-outlined')
|
|
}
|
|
]);
|
|
|
|
const actionMap = new Map<DropdownKey, () => void>([
|
|
[
|
|
'reload-current',
|
|
() => {
|
|
handleReload();
|
|
}
|
|
],
|
|
[
|
|
'close-current',
|
|
() => {
|
|
removeMultiTab(props.currentPath);
|
|
}
|
|
],
|
|
[
|
|
'close-other',
|
|
() => {
|
|
clearMultiTab([props.currentPath]);
|
|
}
|
|
],
|
|
[
|
|
'close-left',
|
|
() => {
|
|
clearLeftMultiTab(props.currentPath);
|
|
}
|
|
],
|
|
[
|
|
'close-right',
|
|
() => {
|
|
clearRightMultiTab(props.currentPath);
|
|
}
|
|
],
|
|
[
|
|
'close-all',
|
|
() => {
|
|
clearMultiTab();
|
|
}
|
|
]
|
|
]);
|
|
|
|
function handleDropdown(optionKey: string) {
|
|
const key = optionKey as DropdownKey;
|
|
const actionFunc = actionMap.get(key);
|
|
if (actionFunc) {
|
|
actionFunc();
|
|
}
|
|
hide();
|
|
}
|
|
|
|
watch(
|
|
() => props.visible,
|
|
newValue => {
|
|
if (newValue) {
|
|
show();
|
|
} else {
|
|
hide();
|
|
}
|
|
}
|
|
);
|
|
watch(dropdownVisible, newValue => {
|
|
emit('update:visible', newValue);
|
|
});
|
|
</script>
|
|
<style scoped></style>
|