perf: layout style optimization
| | |
| | | VITE_PORT = 3100 |
| | | |
| | | # spa-title |
| | | VITE_GLOB_APP_TITLE = Vben Admin 2.0 |
| | | VITE_GLOB_APP_TITLE = Vben Admin |
| | | |
| | | # spa shortname |
| | | VITE_GLOB_APP_SHORT_NAME = vue_vben_admin_2x |
| | |
| | | ## Wip |
| | | |
| | | ### ⚡ Performance Improvements |
| | | |
| | | - Layout 界面布局样式调整 |
| | | |
| | | ### 🐛 Bug Fixes |
| | | |
| | | - 修复表格类型错误 |
| | | |
| | | ## 2.0.0-rc.7 (2020-10-31) |
| | | |
| | | ### ✨ Features |
| | |
| | | .breadcrumb { |
| | | height: @header-height; |
| | | padding-right: 20px; |
| | | font-size: 12px; |
| | | font-size: 14px; |
| | | line-height: @header-height; |
| | | // line-height: 1; |
| | | |
| | |
| | | offset += 54; |
| | | } |
| | | return { |
| | | height: `calc(100% - ${offset - 30}px)`, |
| | | height: `calc(100% - ${offset - 38}px)`, |
| | | position: 'relative', |
| | | overflow: 'auto', |
| | | }; |
| | |
| | | } |
| | | |
| | | const showTitle = computed(() => { |
| | | if (props.isTop) return true; |
| | | if (!props.isAppMenu) return true; |
| | | if (!props.collapsedShowTitle) { |
| | | return !menuStore.getCollapsedState; |
| | |
| | | return () => { |
| | | const { getCollapsedState } = menuStore; |
| | | const { mode } = props; |
| | | |
| | | return mode === MenuModeEnum.HORIZONTAL ? ( |
| | | renderMenu() |
| | | ) : ( |
| | |
| | | .ant-input { |
| | | color: @text-color-base; |
| | | background: #fff; |
| | | border: 0; |
| | | // border: 0; |
| | | outline: none; |
| | | |
| | | &:hover, |
| | |
| | | color: @white; |
| | | background: linear-gradient( |
| | | 118deg, |
| | | rgba(@primary-color, 0.7), |
| | | rgba(@primary-color, 0.8), |
| | | rgba(@primary-color, 1) |
| | | ) !important; |
| | | border-radius: 2px; |
| | |
| | | font-size: 12px; |
| | | flex-direction: column; |
| | | line-height: 24px; |
| | | align-items: center; |
| | | } |
| | | |
| | | & > li[role='menuitem']:not(.ant-menu-submenu) { |
| | |
| | | } |
| | | |
| | | &-bg__sidebar-hor { |
| | | overflow: hidden; |
| | | |
| | | &.ant-menu-horizontal { |
| | | display: flex; |
| | | border: 0; |
| | |
| | | &.ant-menu-light { |
| | | .ant-menu-item { |
| | | &.basic-menu-item__level1 { |
| | | height: 38px; |
| | | line-height: 38px; |
| | | height: @header-height; |
| | | line-height: @header-height; |
| | | } |
| | | } |
| | | |
| | | .ant-menu-item:hover, |
| | | .ant-menu-submenu:hover, |
| | | .ant-menu-item-active, |
| | | .ant-menu-submenu-active, |
| | | .ant-menu-item-open, |
| | | .ant-menu-submenu-open, |
| | | .ant-menu-item-selected, |
| | | .ant-menu-submenu-selected { |
| | | color: @primary-color !important; |
| | | border-bottom: 3px solid @primary-color; |
| | | } |
| | | |
| | | .ant-menu-submenu-selected, |
| | | .ant-menu-item:hover, |
| | | .ant-menu-item-active, |
| | | .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open, |
| | |
| | | } |
| | | |
| | | &.ant-menu-light { |
| | | overflow-x: hidden; |
| | | border-right: none; |
| | | |
| | | .basic-menu-item__level1 { |
| | | &.top-active-menu { |
| | | color: @primary-color; |
| | | border-bottom: 6px solid @primary-color; |
| | | border-bottom: 3px solid @primary-color; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | &-light { |
| | | border-right: 1px solid rgba(221, 221, 221, 0.6); |
| | | |
| | | .ant-layout-sider-trigger { |
| | | color: @text-color-base; |
| | | background: @trigger-light-bg-color; |
| | | |
| | | &:hover { |
| | | color: @text-color-base; |
| | | background: @trigger-light-hover-bg-color; |
| | | } |
| | | border-top: 1px solid @border-color-light; |
| | | } |
| | | } |
| | | } |
| | |
| | | type: Boolean as PropType<boolean>, |
| | | default: true, |
| | | }, |
| | | isTop: { |
| | | type: Boolean as PropType<boolean>, |
| | | default: false, |
| | | }, |
| | | beforeClickFn: { |
| | | type: Function as PropType<Fn>, |
| | | default: null, |
| | |
| | | @import './input.less'; |
| | | @import './btn.less'; |
| | | |
| | | // TODO beta.11 fix |
| | | .ant-col { |
| | | width: 100%; |
| | | } |
| | | |
| | | // .ant-form-item-label { |
| | | // text-align: unset; |
| | | // } |
| | | |
| | | // ================================= |
| | | // ==============descriptions======= |
| | | // ================================= |
| | |
| | | } |
| | | |
| | | body { |
| | | font-family: 'Microsoft YaHei,微软雅黑,Arial,sans-serif,Helvetica Neue,Helvetica,Pingfang SC,Hiragino Sans GB'; |
| | | // font-family: 'Microsoft YaHei,微软雅黑,Arial,sans-serif,Helvetica Neue,Helvetica,Pingfang SC,Hiragino Sans GB'; |
| | | font-family: '-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji'; |
| | | font-style: normal; |
| | | font-weight: normal; |
| | | line-height: 1.428571429; // 20/14 |
| | |
| | | } |
| | | |
| | | .ant-layout { |
| | | background: #f1f1f6; |
| | | background: #f0f2f5; |
| | | |
| | | &-content { |
| | | position: relative; |
| | |
| | | } |
| | | |
| | | // TODO 滚动条样式-待修改 |
| | | ::-webkit-scrollbar-track { |
| | | // background: rgba(0, 0, 0, 0.06); |
| | | // border-radius: 2px; |
| | | // box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | } |
| | | // ::-webkit-scrollbar-track { |
| | | // // background: rgba(0, 0, 0, 0.06); |
| | | // // border-radius: 2px; |
| | | // // box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | // } |
| | | |
| | | /* 滚动条滑块 */ |
| | | ::-webkit-scrollbar-thumb { |
| | |
| | | @import 'breakpoint'; |
| | | |
| | | // tabs |
| | | @multiple-height: 36px; |
| | | @multiple-height: 30px; |
| | | |
| | | // headers |
| | | @header-height: 36px; |
| | | @header-height: 46px; |
| | | |
| | | // logo width |
| | | @logo-width: 40px; |
| | | @logo-width: 36px; |
| | | |
| | | // |
| | | @sider-drag-z-index: 200; |
| | |
| | | // app menu |
| | | |
| | | // left-menu |
| | | @app-menu-item-height: 44px; |
| | | @app-menu-item-height: 42px; |
| | |
| | | <template> |
| | | <div class="app-logo" @click="handleGoHome"> |
| | | <div class="app-logo" @click="handleGoHome" :style="wrapStyle"> |
| | | <img :src="logo" /> |
| | | <div v-if="show" class="logo-title ml-1 mt-1 ellipsis">{{ globSetting.title }}</div> |
| | | <div v-if="show" class="logo-title ml-2 ellipsis">{{ globSetting.title }}</div> |
| | | </div> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { defineComponent, PropType, ref, watch } from 'vue'; |
| | | import { computed, defineComponent, PropType, ref, watch } from 'vue'; |
| | | // hooks |
| | | import { useSetting } from '/@/hooks/core/useSetting'; |
| | | |
| | | import { PageEnum } from '/@/enums/pageEnum'; |
| | | import logo from '/@/assets/images/logo.png'; |
| | | import { useTimeout } from '/@/hooks/core/useTimeout'; |
| | | import { useGo } from '/@/hooks/web/usePage'; |
| | | |
| | | import { PageEnum } from '/@/enums/pageEnum'; |
| | | import { MenuTypeEnum } from '../enums/menuEnum'; |
| | | |
| | | import logo from '/@/assets/images/logo.png'; |
| | | |
| | | import { menuStore } from '../store/modules/menu'; |
| | | import { appStore } from '../store/modules/app'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'Logo', |
| | |
| | | } |
| | | ); |
| | | |
| | | const wrapStyle = computed(() => { |
| | | const { getCollapsedState } = menuStore; |
| | | const { |
| | | menuSetting: { menuWidth, type }, |
| | | } = appStore.getProjectConfig; |
| | | const miniWidth = { minWidth: `${menuWidth}px` }; |
| | | if (type !== MenuTypeEnum.SIDEBAR) { |
| | | return miniWidth; |
| | | } |
| | | return getCollapsedState ? {} : miniWidth; |
| | | }); |
| | | |
| | | return { |
| | | handleGoHome, |
| | | globSetting, |
| | | show: showRef, |
| | | logo, |
| | | wrapStyle, |
| | | }; |
| | | }, |
| | | }); |
| | |
| | | .app-logo { |
| | | display: flex; |
| | | align-items: center; |
| | | padding-left: 16px; |
| | | cursor: pointer; |
| | | |
| | | .logo-title { |
| | | display: none; |
| | | font-family: Georgia, serif; |
| | | font-size: 16px; |
| | | font-weight: 400; |
| | | .respond-to(medium,{ |
| | | display: block; |
| | | }); |
| | |
| | | |
| | | import { ContentEnum } from '/@/enums/appEnum'; |
| | | import { appStore } from '/@/store/modules/app'; |
| | | // import { RouterView } from 'vue-router'; |
| | | import PageLayout from '/@/layouts/page/index'; |
| | | export default defineComponent({ |
| | | name: 'DefaultLayoutContent', |
| | |
| | | const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed'; |
| | | return ( |
| | | <Layout.Content class={`layout-content ${wrapClass} `}> |
| | | {{ |
| | | default: () => <PageLayout />, |
| | | }} |
| | | {() => <PageLayout />} |
| | | </Layout.Content> |
| | | ); |
| | | }; |
| | |
| | | import { defineComponent, unref, computed, ref } from 'vue'; |
| | | |
| | | import { Layout, Tooltip, Badge } from 'ant-design-vue'; |
| | | import Logo from '/@/layouts/Logo.vue'; |
| | | import UserDropdown from './UserDropdown'; |
| | | import LayoutMenu from './LayoutMenu'; |
| | | import { appStore } from '/@/store/modules/app'; |
| | | import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; |
| | | import LayoutBreadcrumb from './LayoutBreadcrumb'; |
| | | import LockAction from './actions/LockActionItem'; |
| | | import NoticeAction from './actions/notice/NoticeActionItem.vue'; |
| | | import { |
| | | RedoOutlined, |
| | | FullscreenExitOutlined, |
| | |
| | | LockOutlined, |
| | | BugOutlined, |
| | | } from '@ant-design/icons-vue'; |
| | | |
| | | import { useFullscreen } from '/@/hooks/web/useFullScreen'; |
| | | import { useTabs } from '/@/hooks/web/useTabs'; |
| | | import { GITHUB_URL } from '/@/settings/siteSetting'; |
| | | import LockAction from './actions/LockActionItem'; |
| | | import { useModal } from '/@/components/Modal/index'; |
| | | import { errorStore } from '/@/store/modules/error'; |
| | | import { useWindowSizeFn } from '/@/hooks/event/useWindowSize'; |
| | | import NoticeAction from './actions/notice/NoticeActionItem.vue'; |
| | | import { useRouter } from 'vue-router'; |
| | | import { useModal } from '/@/components/Modal/index'; |
| | | |
| | | import { appStore } from '/@/store/modules/app'; |
| | | import { errorStore } from '/@/store/modules/error'; |
| | | |
| | | import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; |
| | | import { GITHUB_URL } from '/@/settings/siteSetting'; |
| | | export default defineComponent({ |
| | | name: 'DefaultLayoutHeader', |
| | | setup() { |
| | | const widthRef = ref(200); |
| | | let logoEl: Element | null; |
| | | |
| | | const { refreshPage } = useTabs(); |
| | | const { push } = useRouter(); |
| | | const [register, { openModal }] = useModal(); |
| | |
| | | const getProjectConfigRef = computed(() => { |
| | | return appStore.getProjectConfig; |
| | | }); |
| | | |
| | | const showTopMenu = computed(() => { |
| | | const getProjectConfig = unref(getProjectConfigRef); |
| | | const { |
| | |
| | | return mode === MenuModeEnum.HORIZONTAL || splitMenu; |
| | | }); |
| | | |
| | | let logoEl: Element | null; |
| | | useWindowSizeFn( |
| | | () => { |
| | | if (!unref(showTopMenu)) return; |
| | |
| | | function handleLockPage() { |
| | | openModal(true); |
| | | } |
| | | |
| | | return () => { |
| | | const getProjectConfig = unref(getProjectConfigRef); |
| | | const { |
| | |
| | | } = getProjectConfig; |
| | | |
| | | const isSidebarType = menuType === MenuTypeEnum.SIDEBAR; |
| | | |
| | | const width = unref(widthRef); |
| | | |
| | | return ( |
| | | <Layout.Header class={['layout-header', 'flex p-0 px-4 ', unref(headerClass)]}> |
| | | {() => ( |
| | |
| | | )} |
| | | {unref(showTopMenu) && ( |
| | | <div |
| | | class={[`layout-header__menu `, `justify-${topMenuAlign}`]} |
| | | class={[`layout-header__menu `]} |
| | | style={{ width: `calc(100% - ${unref(width)}px)` }} |
| | | > |
| | | <LayoutMenu |
| | | isTop={true} |
| | | class={`justify-${topMenuAlign}`} |
| | | theme={headerTheme} |
| | | splitType={splitMenu ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE} |
| | | menuMode={splitMenu ? MenuModeEnum.HORIZONTAL : null} |
| | |
| | | type: Boolean as PropType<boolean>, |
| | | default: true, |
| | | }, |
| | | isTop: { |
| | | type: Boolean as PropType<boolean>, |
| | | default: false, |
| | | }, |
| | | menuMode: { |
| | | type: [String] as PropType<MenuModeEnum | null>, |
| | | default: '', |
| | |
| | | flatItems={unref(flatMenusRef)} |
| | | onClickSearchInput={handleClickSearchInput} |
| | | appendClass={props.splitType === MenuSplitTyeEnum.TOP} |
| | | isTop={props.isTop} |
| | | > |
| | | {{ |
| | | header: () => |
| | |
| | | // import darkMiniIMg from '/@/assets/images/sidebar/dark-mini.png'; |
| | | // import lightMiniImg from '/@/assets/images/sidebar/light-mini.png'; |
| | | import darkImg from '/@/assets/images/sidebar/dark.png'; |
| | | import lightImg from '/@/assets/images/sidebar/light.png'; |
| | | // import lightImg from '/@/assets/images/sidebar/light.png'; |
| | | import { appStore } from '/@/store/modules/app'; |
| | | import { MenuModeEnum, MenuSplitTyeEnum, MenuThemeEnum } from '/@/enums/menuEnum'; |
| | | import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum'; |
| | |
| | | // const collapse = unref(collapseRef); |
| | | |
| | | const theme = unref(getProjectConfigRef).menuSetting.theme; |
| | | if (theme === MenuThemeEnum.LIGHT) { |
| | | // bg = lightImg; |
| | | return {}; |
| | | } |
| | | let bg = ''; |
| | | if (theme === MenuThemeEnum.DARK) { |
| | | // bg = collapse ? darkMiniIMg : darkImg; |
| | | bg = darkImg; |
| | | } |
| | | if (theme === MenuThemeEnum.LIGHT) { |
| | | bg = lightImg; |
| | | // bg = collapse ? lightMiniImg : lightImg; |
| | | } |
| | | |
| | | return { |
| | | 'background-image': `url(${bg})`, |
| | | }; |
| | |
| | | return appStore.getProjectConfig; |
| | | }); |
| | | |
| | | const getUserInfo = computed(() => { |
| | | const { realName = '', desc } = userStore.getUserInfoState || {}; |
| | | return { realName, desc }; |
| | | }); |
| | | |
| | | /** |
| | | * @description: 退出登录 |
| | | */ |
| | |
| | | openDoc(); |
| | | } |
| | | } |
| | | const getUserInfo = computed(() => { |
| | | const { realName = '', desc } = userStore.getUserInfoState || {}; |
| | | return { realName, desc }; |
| | | }); |
| | | |
| | | function renderItem({ icon, text, key }: { icon: string; text: string; key: string }) { |
| | | return ( |
| | | <Menu.Item key={key}> |
| | | {() => ( |
| | | <span class="flex items-center"> |
| | | <Icon icon={icon} class="mr-1" /> |
| | | <span>{text}</span> |
| | | </span> |
| | | )} |
| | | </Menu.Item> |
| | | ); |
| | | } |
| | | |
| | | return () => { |
| | | const { realName } = unref(getUserInfo); |
| | | const { |
| | |
| | | <Menu slot="overlay" onClick={handleMenuClick}> |
| | | {() => ( |
| | | <> |
| | | {showDoc && ( |
| | | <Menu.Item key="doc"> |
| | | {() => ( |
| | | <span class="flex items-center"> |
| | | <Icon icon="gg:loadbar-doc" class="mr-1" /> |
| | | <span>文档</span> |
| | | </span> |
| | | )} |
| | | </Menu.Item> |
| | | )} |
| | | {showDoc && renderItem({ key: 'doc', text: '文档', icon: 'gg:loadbar-doc' })} |
| | | {showDoc && <Divider />} |
| | | |
| | | <Menu.Item key="loginOut"> |
| | | {() => ( |
| | | <> |
| | | <span class="flex items-center"> |
| | | <Icon icon="ant-design:poweroff-outlined" class="mr-1" /> |
| | | <span>退出系统</span> |
| | | </span> |
| | | </> |
| | | )} |
| | | </Menu.Item> |
| | | {renderItem({ |
| | | key: 'loginOut', |
| | | text: '退出系统', |
| | | icon: 'ant-design:poweroff-outlined', |
| | | })} |
| | | </> |
| | | )} |
| | | </Menu> |
| | |
| | | .lock-modal { |
| | | &__entry { |
| | | position: relative; |
| | | width: 500px; |
| | | // width: 500px; |
| | | height: 240px; |
| | | padding: 80px 30px 0 30px; |
| | | padding: 130px 30px 60px 30px; |
| | | background: #fff; |
| | | border-radius: 10px; |
| | | } |
| | |
| | | schemas: [ |
| | | { |
| | | field: 'password', |
| | | label: '锁屏密码', |
| | | label: '', |
| | | component: 'InputPassword', |
| | | componentProps: { |
| | | placeholder: '请输入锁屏密码', |
| | |
| | | @import (reference) '../../design/index.less'; |
| | | |
| | | .default-layout { |
| | | // .ant-menu-submenu .ant-menu-sub { |
| | | // transition: none !important; |
| | | // // transition: background 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) 0s, |
| | | // // padding 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) 0s !important; |
| | | // } |
| | | |
| | | &__content { |
| | | position: relative; |
| | | |
| | |
| | | .layout-sidebar { |
| | | background-size: 100% 100%; |
| | | |
| | | &:not(.ant-layout-sider-dark) { |
| | | border-right: 1px solid @border-color-light; |
| | | } |
| | | |
| | | .ant-layout-sider-zero-width-trigger { |
| | | top: 40%; |
| | | z-index: 10; |
| | |
| | | } |
| | | } |
| | | |
| | | .setting-button { |
| | | top: 45%; |
| | | right: 0; |
| | | padding: 8px; |
| | | border-radius: 6px 0 0 6px; |
| | | |
| | | svg { |
| | | width: 1em; |
| | | height: 1em; |
| | | } |
| | | } |
| | | |
| | | &__tabs { |
| | | z-index: 10; |
| | | height: @multiple-height; |
| | | padding: 0; |
| | | line-height: @multiple-height; |
| | | background: @border-color-shallow-light; |
| | | box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.08); |
| | | box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.12); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | .ant-layout-header { |
| | | .ant-layout-header:not(.default-layout__tabs) { |
| | | height: @header-height; |
| | | line-height: @header-height; |
| | | } |
| | | |
| | | .ant-layout-header.default-layout__tabs { |
| | | height: @multiple-height + 2; |
| | | line-height: @multiple-height + 2; |
| | | background: @white; |
| | | } |
| | | |
| | | .layout-header { |
| | |
| | | } |
| | | |
| | | &__menu { |
| | | // display: flex; |
| | | margin-left: 20px; |
| | | overflow: hidden; |
| | | align-items: center; |
| | | // flex-grow: 1; |
| | | } |
| | | |
| | | &__user-dropdown { |
| | | height: 52px; |
| | | height: @header-height; |
| | | padding: 0 0 0 10px; |
| | | } |
| | | } |
| | | |
| | | .user-dropdown { |
| | | display: flex; |
| | | height: 100%; |
| | | padding-right: 10px; |
| | | font-size: 12px; |
| | | cursor: pointer; |
| | | align-items: center; |
| | |
| | | img { |
| | | width: 26px; |
| | | height: 26px; |
| | | margin-right: 16px; |
| | | margin-right: 12px; |
| | | } |
| | | |
| | | &__header { |
| | | border-radius: 50%; |
| | | } |
| | | |
| | | &__divider { |
| | | width: 1px; |
| | | height: 30px; |
| | | margin-right: 20px; |
| | | background: #c6d9ee; |
| | | } |
| | | |
| | | &__exit { |
| | | margin-top: -40px; |
| | | font-size: 12px; |
| | | color: #c6d9ee; |
| | | text-align: center; |
| | | |
| | | > section { |
| | | height: 20px; |
| | | } |
| | | } |
| | | |
| | | &__info { |
| | | display: flex; |
| | | margin-right: 12px; |
| | | flex-direction: column; |
| | | |
| | | > section { |
| | | line-height: 1.8; |
| | | } |
| | | } |
| | | |
| | | &__name { |
| | | font-size: 12px; |
| | | } |
| | | |
| | | &__desc { |
| | | font-size: 12px; |
| | | .text-truncate(); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | .ant-layout-sider-trigger { |
| | | height: 30px; |
| | | line-height: 30px; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | } |
| | | |
| | | .hide-title { |
| | |
| | | import { defineComponent, unref, onMounted, computed } from 'vue'; |
| | | import { defineComponent, unref, computed } from 'vue'; |
| | | import { Layout, BackTop } from 'ant-design-vue'; |
| | | import LayoutHeader from './LayoutHeader'; |
| | | |
| | |
| | | const getProjectConfigRef = computed(() => { |
| | | return appStore.getProjectConfig; |
| | | }); |
| | | |
| | | const getLockMainScrollStateRef = computed(() => { |
| | | return appStore.getLockMainScrollState; |
| | | }); |
| | |
| | | } = unref(getProjectConfigRef); |
| | | return show; |
| | | }); |
| | | |
| | | const isShowMixHeaderRef = computed(() => { |
| | | const { |
| | | menuSetting: { type }, |
| | |
| | | return show && mode !== MenuModeEnum.HORIZONTAL && !unref(getFullContent); |
| | | }); |
| | | |
| | | // const { currentRoute } = useRouter(); |
| | | onMounted(() => { |
| | | // Each refresh will request the latest user information, if you don’t need it, you can delete it |
| | | // userStore.getUserInfoAction({ userId: userStore.getUserInfoState.userId }); |
| | | }); |
| | | |
| | | // Get project configuration |
| | | // const { getFullContent } = useFullContent(currentRoute); |
| | | function getTarget(): any { |
| | |
| | | } = unref(getProjectConfigRef); |
| | | return document.querySelector(`.default-layout__${fixed ? 'main' : 'content'}`); |
| | | } |
| | | |
| | | return () => { |
| | | const { getPageLoading, getLockInfo } = appStore; |
| | | const { |
| | |
| | | multiTabsSetting: { show: showTabs }, |
| | | headerSetting: { fixed }, |
| | | } = unref(getProjectConfigRef); |
| | | // const fixedHeaderCls = fixed ? ('fixed' + getLockMainScrollState ? ' lock' : '') : ''; |
| | | |
| | | const fixedHeaderCls = fixed |
| | | ? 'fixed' + (unref(getLockMainScrollStateRef) ? ' lock' : '') |
| | | : ''; |
| | | |
| | | const { isLock } = getLockInfo; |
| | | return ( |
| | | <Layout class="default-layout relative"> |
| | |
| | | @import (reference) '../../../design/index.less'; |
| | | |
| | | .multiple-tabs { |
| | | box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); |
| | | |
| | | .ant-tabs-small { |
| | | height: @multiple-height; |
| | | } |
| | |
| | | margin: 0; |
| | | background: @white; |
| | | border: 0; |
| | | box-shadow: 0 4px 26px 1px rgba(0, 0, 0, 0.08); |
| | | box-shadow: none; |
| | | |
| | | .ant-tabs-nav-container { |
| | | height: @multiple-height; |
| | |
| | | |
| | | .ant-tabs-tab { |
| | | height: calc(@multiple-height - 2px); |
| | | font-size: 14px; |
| | | line-height: calc(@multiple-height - 2px); |
| | | color: @text-color-call-out; |
| | | background: @white; |
| | | border: 1px solid darken(@border-color-light, 6%); |
| | | border-radius: 2px 2px 0 0; |
| | | border: 1px solid darken(@border-color-light, 8%); |
| | | border-radius: none !important; |
| | | transition: none; |
| | | |
| | | .ant-tabs-close-x { |
| | | // display: none; |
| | | width: 12px; |
| | | height: 12px; |
| | | font-size: 12px; |
| | | color: inherit; |
| | | transition: none; |
| | | |
| | | &:hover { |
| | | svg { |
| | | width: 0.8em; |
| | | transition: all 0.1s; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &:hover { |
| | |
| | | svg { |
| | | fill: @text-color-base; |
| | | } |
| | | |
| | | &::before { |
| | | position: absolute; |
| | | top: -2px; |
| | | right: 0; |
| | | left: 0; |
| | | height: 4px; |
| | | background-color: @primary-color; |
| | | border-radius: 16px 6px 0 0; |
| | | content: ''; |
| | | transform: scaleX(0); |
| | | transform-origin: bottom right; |
| | | } |
| | | |
| | | &:hover::before { |
| | | transform: scaleX(1); |
| | | transition: transform 0.3s ease; |
| | | transform-origin: bottom left; |
| | | } |
| | | } |
| | | |
| | | .ant-tabs-tab-active { |
| | | height: calc(@multiple-height - 3px); |
| | | color: @white; |
| | | background: linear-gradient( |
| | | 118deg, |
| | | rgba(@primary-color, 0.8), |
| | | rgba(@primary-color, 1) |
| | | ) !important; |
| | | background: fade(@primary-color, 100%); |
| | | border: 0; |
| | | box-shadow: 0 0 6px 1px rgba(@primary-color, 0.7); |
| | | |
| | | &::before { |
| | | display: none; |
| | |
| | | |
| | | svg { |
| | | fill: @white; |
| | | width: 0.7em; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ant-tabs-nav > div:nth-child(1) { |
| | | padding: 0 10px; |
| | | } |
| | | |
| | | .ant-tabs-tab-prev, |
| | | .ant-tabs-tab-next { |
| | | color: @border-color-dark; |
| | | background: @white; |
| | | } |
| | | } |
| | | |
| | |
| | | font-size: 12px; |
| | | |
| | | svg { |
| | | width: 0.8em; |
| | | } |
| | | } |
| | | |
| | | &:hover { |
| | | .anticon-close { |
| | | color: @white; |
| | | width: 0.6em; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ant-tabs-extra-content { |
| | | line-height: @multiple-height; |
| | | margin-top: 2px; |
| | | line-height: @multiple-height !important; |
| | | } |
| | | |
| | | .ant-dropdown-trigger { |
| | | display: inline-flex; |
| | | } |
| | | |
| | | .multiple-tabs-content { |
| | |
| | | color: @primary-color; |
| | | text-align: center; |
| | | cursor: pointer; |
| | | box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); |
| | | // box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); |
| | | |
| | | span[role='img'] { |
| | | transform: rotate(90deg); |
| | |
| | | &__content { |
| | | display: inline-block; |
| | | width: 100%; |
| | | padding-left: 10px; |
| | | height: @multiple-height - 2; |
| | | padding-left: 0; |
| | | margin-left: -10px; |
| | | font-size: 12px; |
| | | cursor: pointer; |
| | | user-select: none; |
| | | } |
| | |
| | | size="small" |
| | | animated={false} |
| | | hideAdd={true} |
| | | tabBarGutter={2} |
| | | tabBarGutter={4} |
| | | activeKey={unref(activeKeyRef)} |
| | | onChange={handleChange} |
| | | onEdit={handleEdit} |
| | |
| | | |
| | | .setting-button { |
| | | position: absolute; |
| | | top: 45%; |
| | | right: 0; |
| | | z-index: 10; |
| | | display: flex; |
| | | // padding: 10px; |
| | | padding: 10px; |
| | | color: @white; |
| | | cursor: pointer; |
| | | background: @primary-color; |
| | | border-radius: 6px 0 0 6px; |
| | | justify-content: center; |
| | | align-items: center; |
| | | |
| | | svg { |
| | | width: 1em; |
| | | height: 1em; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | </template> |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | import { useFrameKeepAlive } from './useFrameKeepAlive'; |
| | | import FramePage from '/@/views/sys/iframe/index.vue'; |
| | | |
| | | import { useFrameKeepAlive } from './useFrameKeepAlive'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'FrameLayout', |
| | | components: { FramePage }, |
| | | setup() { |
| | | const { hasRenderFrame, showIframe, getFramePages } = useFrameKeepAlive(); |
| | | return { hasRenderFrame, showIframe, getFramePages }; |
| | | return { ...useFrameKeepAlive() }; |
| | | }, |
| | | }); |
| | | </script> |
| | |
| | | // 是否显示搜索框 |
| | | showSearch: true, |
| | | // 菜单宽度 |
| | | menuWidth: 180, |
| | | menuWidth: 200, |
| | | // 菜单模式 |
| | | mode: MenuModeEnum.INLINE, |
| | | // 菜单类型 |
| | |
| | | // 分割菜单 |
| | | split: false, |
| | | // 顶部菜单布局 |
| | | topMenuAlign: 'start', |
| | | topMenuAlign: 'center', |
| | | }, |
| | | // 消息配置 |
| | | messageSetting: { |
| | |
| | | // 开启快速操作 |
| | | showQuick: true, |
| | | // 显示icon |
| | | showIcon: true, |
| | | showIcon: false, |
| | | // 标签页缓存最大数量 |
| | | max: 12, |
| | | }, |