mirror of
				https://github.com/soybeanjs/soybean-admin.git
				synced 2025-11-04 15:53:43 +08:00 
			
		
		
		
	@@ -11,6 +11,7 @@
 | 
			
		||||
    :sider-collapsed-width="siderCollapsedWidth"
 | 
			
		||||
    :sider-collapse="app.siderCollapse"
 | 
			
		||||
    :fixed-footer="theme.footer.fixed"
 | 
			
		||||
    :footer-visible="theme.footer.visible"
 | 
			
		||||
    @update:sider-collapse="app.setSiderCollapse"
 | 
			
		||||
  >
 | 
			
		||||
    <template #header>
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,8 @@ interface Props {
 | 
			
		||||
  visible?: boolean;
 | 
			
		||||
  /** 当前路由路径 */
 | 
			
		||||
  currentPath?: string;
 | 
			
		||||
  /** 是否固定在tab卡不可关闭  */
 | 
			
		||||
  affix?: boolean;
 | 
			
		||||
  /** 鼠标x坐标 */
 | 
			
		||||
  x: number;
 | 
			
		||||
  /** 鼠标y坐标 */
 | 
			
		||||
@@ -72,7 +74,7 @@ const options = computed<Option[]>(() => [
 | 
			
		||||
  {
 | 
			
		||||
    label: '关闭',
 | 
			
		||||
    key: 'close-current',
 | 
			
		||||
    disabled: props.currentPath === tab.homeTab.fullPath,
 | 
			
		||||
    disabled: props.currentPath === tab.homeTab.fullPath || Boolean(props.affix),
 | 
			
		||||
    icon: iconRender({ icon: 'ant-design:close-outlined' })
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,12 @@
 | 
			
		||||
      :key="item.fullPath"
 | 
			
		||||
      :is-active="tab.activeTab === item.fullPath"
 | 
			
		||||
      :primary-color="theme.themeColor"
 | 
			
		||||
      :closable="item.name !== tab.homeTab.name"
 | 
			
		||||
      :closable="!(item.name === tab.homeTab.name || item.meta.affix)"
 | 
			
		||||
      :dark-mode="theme.darkMode"
 | 
			
		||||
      :class="{ '!mr-0': isChromeMode && index === tab.tabs.length - 1, 'mr-10px': !isChromeMode }"
 | 
			
		||||
      @click="tab.handleClickTab(item.fullPath)"
 | 
			
		||||
      @close="tab.removeTab(item.fullPath)"
 | 
			
		||||
      @contextmenu="handleContextMenu($event, item.fullPath)"
 | 
			
		||||
      @contextmenu="handleContextMenu($event, item.fullPath, item.meta.affix)"
 | 
			
		||||
    >
 | 
			
		||||
      <svg-icon
 | 
			
		||||
        :icon="item.meta.icon"
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
  <context-menu
 | 
			
		||||
    :visible="dropdown.visible"
 | 
			
		||||
    :current-path="dropdown.currentPath"
 | 
			
		||||
    :affix="dropdown.affix"
 | 
			
		||||
    :x="dropdown.x"
 | 
			
		||||
    :y="dropdown.y"
 | 
			
		||||
    @update:visible="handleDropdownVisible"
 | 
			
		||||
@@ -66,6 +67,7 @@ async function getActiveTabClientX() {
 | 
			
		||||
 | 
			
		||||
const dropdown = reactive({
 | 
			
		||||
  visible: false,
 | 
			
		||||
  affix: false,
 | 
			
		||||
  x: 0,
 | 
			
		||||
  y: 0,
 | 
			
		||||
  currentPath: ''
 | 
			
		||||
@@ -76,8 +78,8 @@ function showDropdown() {
 | 
			
		||||
function hideDropdown() {
 | 
			
		||||
  dropdown.visible = false;
 | 
			
		||||
}
 | 
			
		||||
function setDropdown(x: number, y: number, currentPath: string) {
 | 
			
		||||
  Object.assign(dropdown, { x, y, currentPath });
 | 
			
		||||
function setDropdown(x: number, y: number, currentPath: string, affix?: boolean) {
 | 
			
		||||
  Object.assign(dropdown, { x, y, currentPath, affix });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let isClickContextMenu = false;
 | 
			
		||||
@@ -89,7 +91,7 @@ function handleDropdownVisible(visible: boolean) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 点击右键菜单 */
 | 
			
		||||
async function handleContextMenu(e: MouseEvent, fullPath: string) {
 | 
			
		||||
async function handleContextMenu(e: MouseEvent, fullPath: string, affix?: boolean) {
 | 
			
		||||
  e.preventDefault();
 | 
			
		||||
 | 
			
		||||
  const { clientX, clientY } = e;
 | 
			
		||||
@@ -101,7 +103,7 @@ async function handleContextMenu(e: MouseEvent, fullPath: string) {
 | 
			
		||||
  hideDropdown();
 | 
			
		||||
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    setDropdown(clientX, clientY, fullPath);
 | 
			
		||||
    setDropdown(clientX, clientY, fullPath, affix);
 | 
			
		||||
    showDropdown();
 | 
			
		||||
    isClickContextMenu = false;
 | 
			
		||||
  }, DURATION);
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,9 @@
 | 
			
		||||
    <setting-menu label="固定底部">
 | 
			
		||||
      <n-switch :value="theme.footer.fixed" @update:value="theme.setFooterIsFixed" />
 | 
			
		||||
    </setting-menu>
 | 
			
		||||
    <setting-menu label="显示底部">
 | 
			
		||||
      <n-switch :value="theme.footer.visible" @update:value="theme.setFooterVisible" />
 | 
			
		||||
    </setting-menu>
 | 
			
		||||
  </n-space>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -110,7 +110,8 @@
 | 
			
		||||
  },
 | 
			
		||||
  "footer": {
 | 
			
		||||
    "fixed": false,
 | 
			
		||||
    "height": 48
 | 
			
		||||
    "height": 48,
 | 
			
		||||
    "visible": true
 | 
			
		||||
  },
 | 
			
		||||
  "page": {
 | 
			
		||||
    "animate": true,
 | 
			
		||||
 
 | 
			
		||||
@@ -88,7 +88,8 @@ const defaultThemeSetting: Theme.Setting = {
 | 
			
		||||
  },
 | 
			
		||||
  footer: {
 | 
			
		||||
    fixed: false,
 | 
			
		||||
    height: 48
 | 
			
		||||
    height: 48,
 | 
			
		||||
    visible: true
 | 
			
		||||
  },
 | 
			
		||||
  page: {
 | 
			
		||||
    animate: true,
 | 
			
		||||
 
 | 
			
		||||
@@ -149,6 +149,10 @@ export const useThemeStore = defineStore('theme-store', {
 | 
			
		||||
    setFooterHeight(height: number) {
 | 
			
		||||
      this.footer.height = height;
 | 
			
		||||
    },
 | 
			
		||||
    /** 设置底部是否显示 */
 | 
			
		||||
    setFooterVisible(isVisible: boolean) {
 | 
			
		||||
      this.footer.visible = isVisible;
 | 
			
		||||
    },
 | 
			
		||||
    /** 设置切换页面时是否过渡动画 */
 | 
			
		||||
    setPageIsAnimate(animate: boolean) {
 | 
			
		||||
      this.page.animate = animate;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								src/typings/route.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/typings/route.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -60,6 +60,8 @@ declare namespace AuthRoute {
 | 
			
		||||
    activeMenu?: RouteKey;
 | 
			
		||||
    /** 表示是否是多级路由的中间级路由(用于转换路由数据时筛选多级路由的标识,定义路由时不用填写) */
 | 
			
		||||
    multi?: boolean;
 | 
			
		||||
    /** 是否固定在tab卡不可关闭  */
 | 
			
		||||
    affix?: boolean;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  type Route<K extends AllRouteKey = AllRouteKey> = K extends AllRouteKey
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								src/typings/system.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/typings/system.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -236,6 +236,8 @@ declare namespace Theme {
 | 
			
		||||
    fixed: boolean;
 | 
			
		||||
    /** 底部高度 */
 | 
			
		||||
    height: number;
 | 
			
		||||
    /* 底部是否可见 */
 | 
			
		||||
    visible: boolean;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** 页面样式 */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user