提交
This commit is contained in:
1 parent
06956b742b
commit
e59b2aa6cb
104 files changed
+653227
-7621
No files matched your search
@@ -264,11 +264,17 @@ function handleClose() {
|
||||
resetForm()
|
||||
}
|
||||
|
||||
function defaultComment(type: typeof actionType.value) {
|
||||
if (type === 'approve') return '审批通过'
|
||||
if (type === 'reject') return '审批驳回'
|
||||
return ''
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
form.value = {
|
||||
approvalType: 'sequential',
|
||||
approverIds: [],
|
||||
comment: '',
|
||||
comment: defaultComment(actionType.value),
|
||||
remark: ''
|
||||
}
|
||||
formRef.value?.clearValidate()
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RouterView v-if="isRefresh" v-slot="{ Component, route }" :style="contentStyle">
|
||||
<!-- 勿强制 minHeight:calc(100vh-…),否则门户布局会叠出多余纵向滚动条 -->
|
||||
<RouterView v-if="isRefresh" v-slot="{ Component, route }">
|
||||
<!-- 缓存路由动画 -->
|
||||
<Transition :name="showTransitionMask ? '' : actualTransition" mode="out-in" appear>
|
||||
<KeepAlive :max="keepAliveMax" :exclude="keepAliveExclude">
|
||||
@@ -58,7 +59,8 @@
|
||||
defineOptions({ name: 'ArtPageContent' })
|
||||
|
||||
const route = useRoute()
|
||||
const { containerMinHeight } = useAutoLayoutHeight()
|
||||
// 仅同步 --art-full-height;不给业务页强制 minHeight
|
||||
useAutoLayoutHeight()
|
||||
const { pageTransition, containerWidth, refresh, showWorkTab } = storeToRefs(useSettingStore())
|
||||
const { keepAliveExclude } = storeToRefs(useWorktabStore())
|
||||
|
||||
@@ -114,12 +116,6 @@
|
||||
}
|
||||
)
|
||||
|
||||
const contentStyle = computed(
|
||||
(): CSSProperties => ({
|
||||
minHeight: containerMinHeight.value
|
||||
})
|
||||
)
|
||||
|
||||
const reload = () => {
|
||||
isRefresh.value = false
|
||||
nextTick(() => {
|
||||
|
||||
@@ -1,71 +1,47 @@
|
||||
<!-- 一体化门户顶栏 -->
|
||||
<!-- 一体化门户顶栏:一级横排 + 大面板菜单(方案 A) -->
|
||||
<template>
|
||||
<header class="portal-header">
|
||||
<div class="portal-header-start">
|
||||
<div class="portal-header-brand" @click="toHome">
|
||||
<ArtLogo class="portal-header-logo" src="/logo-sx.svg" :size="28" />
|
||||
<p class="portal-header-title">{{ AppConfig.systemInfo.name }}</p>
|
||||
</div>
|
||||
<div class="portal-header-brand" @click="toHome">
|
||||
<ArtLogo class="portal-header-logo" src="/logo-sx.svg" :size="28" />
|
||||
<p class="portal-header-title">{{ AppConfig.systemInfo.name }}</p>
|
||||
</div>
|
||||
|
||||
<div class="portal-header-nav">
|
||||
<div class="portal-header-nav">
|
||||
<ArtPortalMegaMenu />
|
||||
</div>
|
||||
|
||||
<div class="portal-header-end">
|
||||
<div class="portal-header-actions">
|
||||
<ArtIconButton
|
||||
icon="fold"
|
||||
class="portal-header-icon-btn portal-header-fold-btn"
|
||||
:class="{ 'is-menu-collapsed': !menuOpen }"
|
||||
@click="toggleSidebar"
|
||||
v-if="shouldShowFullscreen"
|
||||
icon="fullscreen"
|
||||
:class="[
|
||||
'portal-header-icon-btn max-md:!hidden',
|
||||
!isFullscreen ? 'full-screen-btn' : 'exit-full-screen-btn'
|
||||
]"
|
||||
@click="toggleFullScreen"
|
||||
/>
|
||||
<ArtPortalModuleSelect />
|
||||
<ArtUserMenu />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="portal-header-center" aria-hidden="false">
|
||||
<p v-if="pageTitle" class="portal-header-page-title">{{ pageTitle }}</p>
|
||||
</div>
|
||||
|
||||
<div class="portal-header-actions">
|
||||
<ArtIconButton
|
||||
v-if="shouldShowFullscreen"
|
||||
icon="fullscreen"
|
||||
:class="[
|
||||
'portal-header-icon-btn max-md:!hidden',
|
||||
!isFullscreen ? 'full-screen-btn' : 'exit-full-screen-btn'
|
||||
]"
|
||||
@click="toggleFullScreen"
|
||||
/>
|
||||
<ArtUserMenu />
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import AppConfig from '@/config'
|
||||
import { useCommon } from '@/hooks/core/useCommon'
|
||||
import { useHeaderBar } from '@/hooks/core/useHeaderBar'
|
||||
import { useSettingStore } from '@/store/modules/setting'
|
||||
import { formatMenuTitle } from '@/utils/router'
|
||||
import ArtUserMenu from '../art-header-bar/widget/ArtUserMenu.vue'
|
||||
import ArtPortalMegaMenu from '../art-portal-mega-menu/index.vue'
|
||||
|
||||
defineOptions({ name: 'ArtPortalHeader' })
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { homePath } = useCommon()
|
||||
const { shouldShowFullscreen } = useHeaderBar()
|
||||
const { isFullscreen, toggle: toggleFullscreen } = useFullscreen()
|
||||
const settingStore = useSettingStore()
|
||||
const { menuOpen } = storeToRefs(settingStore)
|
||||
|
||||
const pageTitle = computed(() => {
|
||||
const matched = route.matched
|
||||
if (!matched.length) return ''
|
||||
const current = matched[matched.length - 1]
|
||||
const title = current.meta?.title
|
||||
return title ? formatMenuTitle(String(title)) : ''
|
||||
})
|
||||
|
||||
const toHome = (): void => {
|
||||
router.push(homePath.value)
|
||||
@@ -74,10 +50,6 @@
|
||||
const toggleFullScreen = (): void => {
|
||||
toggleFullscreen()
|
||||
}
|
||||
|
||||
const toggleSidebar = (): void => {
|
||||
settingStore.setMenuOpen(!menuOpen.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -85,42 +57,27 @@
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
/* 左侧无 padding:brand 区与侧栏同宽,右边框才能纵向对齐 */
|
||||
padding: 0 var(--mint-content-padding, 24px) 0 0;
|
||||
user-select: none;
|
||||
background: var(--mint-primary, #1ca851);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
.portal-header-start {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.portal-header-brand {
|
||||
box-sizing: border-box;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
/* +1px:与侧栏 #app-sidebar 外边框(内容宽 + 1px border)纵向对齐 */
|
||||
width: calc(var(--app-sidebar-open-width, 270px) + 1px);
|
||||
min-width: calc(var(--app-sidebar-open-width, 270px) + 1px);
|
||||
max-width: calc(var(--app-sidebar-open-width, 270px) + 1px);
|
||||
max-width: none;
|
||||
padding-left: var(--mint-content-padding, 24px);
|
||||
padding-right: 16px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.22);
|
||||
}
|
||||
|
||||
.portal-header-logo {
|
||||
@@ -128,11 +85,8 @@
|
||||
}
|
||||
|
||||
.portal-header-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
flex: 0 0 auto;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
@@ -141,34 +95,27 @@
|
||||
}
|
||||
|
||||
.portal-header-nav {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.portal-header-center {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
z-index: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
max-width: min(520px, calc(100% - 420px));
|
||||
pointer-events: none;
|
||||
width: max-content;
|
||||
max-width: min(720px, calc(100% - 520px));
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.portal-header-page-title {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
.portal-header-end {
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.portal-header-actions {
|
||||
@@ -176,21 +123,6 @@
|
||||
flex-shrink: 0;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
:deep(.portal-module-select-trigger) {
|
||||
background: transparent;
|
||||
|
||||
.portal-module-select-trigger__icon,
|
||||
.portal-module-select-trigger__label,
|
||||
.portal-module-select-trigger__arrow {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover:not(.is-disabled) {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.portal-header-icon-btn) {
|
||||
@@ -201,26 +133,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.portal-header-fold-btn :deep(.art-svg-icon) {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.portal-header-fold-btn.is-menu-collapsed :deep(.art-svg-icon) {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
@media only screen and (width <= 800px) {
|
||||
.portal-header-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.portal-header-center {
|
||||
max-width: min(290px, calc(100% - 290px));
|
||||
}
|
||||
|
||||
.portal-header-page-title {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
<!-- 门户顶栏:一级横排 + 方案 A 大面板(左右分行二级/三级文字链) -->
|
||||
<template>
|
||||
<div class="portal-mega-menu" ref="rootRef">
|
||||
<nav class="portal-mega-l1" aria-label="一级模块">
|
||||
<button
|
||||
v-for="item in moduleList"
|
||||
:key="item.path"
|
||||
type="button"
|
||||
class="portal-mega-l1__item"
|
||||
:class="{
|
||||
'is-selected': isL1Selected(item)
|
||||
}"
|
||||
@click="toggleModule(item)"
|
||||
>
|
||||
<span>{{ item.formattedTitle }}</span>
|
||||
<span class="portal-mega-l1__caret">{{ openModulePath === item.path ? '▴' : '▾' }}</span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<Teleport to="body">
|
||||
<div
|
||||
v-if="openModule"
|
||||
class="portal-mega-overlay"
|
||||
@click="closePanel"
|
||||
/>
|
||||
<div
|
||||
v-if="openModule"
|
||||
class="portal-mega-panel"
|
||||
role="dialog"
|
||||
aria-label="子菜单"
|
||||
:style="panelStyle"
|
||||
>
|
||||
<div class="portal-mega-panel__body">
|
||||
<div class="portal-mega-split" :class="{ 'is-single': isSingleColumn }">
|
||||
<div class="portal-mega-pane">
|
||||
<div
|
||||
v-for="row in columns.left"
|
||||
:key="row.l2.path || row.l2.meta?.title"
|
||||
class="portal-mega-row"
|
||||
>
|
||||
<div class="portal-mega-row__l2">{{ formatMenuTitle(row.l2.meta.title) }}</div>
|
||||
<div class="portal-mega-row__l3">
|
||||
<button
|
||||
v-for="link in row.l3Links"
|
||||
:key="link.path || link.meta?.title"
|
||||
type="button"
|
||||
class="portal-mega-link"
|
||||
:class="{ 'is-active': isLinkActive(link) }"
|
||||
@click="handleLinkClick(link)"
|
||||
>
|
||||
{{ formatMenuTitle(link.meta.title) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!columns.left.length" class="portal-mega-empty">暂无菜单</p>
|
||||
</div>
|
||||
<div v-if="!isSingleColumn" class="portal-mega-pane portal-mega-pane--right">
|
||||
<div
|
||||
v-for="row in columns.right"
|
||||
:key="row.l2.path || row.l2.meta?.title"
|
||||
class="portal-mega-row"
|
||||
>
|
||||
<div class="portal-mega-row__l2">{{ formatMenuTitle(row.l2.meta.title) }}</div>
|
||||
<div class="portal-mega-row__l3">
|
||||
<button
|
||||
v-for="link in row.l3Links"
|
||||
:key="link.path || link.meta?.title"
|
||||
type="button"
|
||||
class="portal-mega-link"
|
||||
:class="{ 'is-active': isLinkActive(link) }"
|
||||
@click="handleLinkClick(link)"
|
||||
>
|
||||
{{ formatMenuTitle(link.meta.title) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import { formatMenuTitle } from '@/utils/router'
|
||||
import { handleMenuJump } from '@/utils/navigation'
|
||||
import { useMenuStore } from '@/store/modules/menu'
|
||||
import {
|
||||
buildMegaPanelColumns,
|
||||
filterPortalTopModules,
|
||||
isMegaPanelLinkActive,
|
||||
isPortalModuleActive,
|
||||
type PortalMegaPanelColumns
|
||||
} from '@/utils/router/portal-menu'
|
||||
import type { AppRouteRecord } from '@/types/router'
|
||||
import type { CSSProperties } from 'vue'
|
||||
|
||||
defineOptions({ name: 'ArtPortalMegaMenu' })
|
||||
|
||||
interface PortalModuleItem extends AppRouteRecord {
|
||||
isRouteActive: boolean
|
||||
formattedTitle: string
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
const menuStore = useMenuStore()
|
||||
const { menuList } = storeToRefs(menuStore)
|
||||
|
||||
const rootRef = ref<HTMLElement | null>(null)
|
||||
const openModulePath = ref<string | null>(null)
|
||||
const panelStyle = ref<CSSProperties>({})
|
||||
|
||||
const currentRoutePath = computed(() => String(route.meta.activePath || route.path))
|
||||
|
||||
const moduleList = computed<PortalModuleItem[]>(() => {
|
||||
return filterPortalTopModules(menuList.value).map((item) => ({
|
||||
...item,
|
||||
isRouteActive: isPortalModuleActive(item, currentRoutePath.value),
|
||||
formattedTitle: formatMenuTitle(item.meta.title)
|
||||
}))
|
||||
})
|
||||
|
||||
const openModule = computed(() => {
|
||||
if (!openModulePath.value) return undefined
|
||||
return moduleList.value.find((item) => item.path === openModulePath.value)
|
||||
})
|
||||
|
||||
const columns = computed<PortalMegaPanelColumns>(() =>
|
||||
buildMegaPanelColumns(openModule.value)
|
||||
)
|
||||
|
||||
const isSingleColumn = computed(() => columns.value.right.length === 0)
|
||||
|
||||
/** 与顶栏中间槽上限一致;一级较少时保证两栏二级可读 */
|
||||
const PANEL_MIN_WIDTH = 720
|
||||
const PANEL_EDGE_PAD = 16
|
||||
|
||||
const syncPanelPosition = (): void => {
|
||||
const el = rootRef.value
|
||||
if (!el) return
|
||||
const rect = el.getBoundingClientRect()
|
||||
const viewportW = window.innerWidth
|
||||
const minWidth = Math.min(PANEL_MIN_WIDTH, Math.max(0, viewportW - PANEL_EDGE_PAD * 2))
|
||||
const width = Math.max(rect.width, minWidth)
|
||||
const centerX = rect.left + rect.width / 2
|
||||
let left = centerX - width / 2
|
||||
left = Math.max(PANEL_EDGE_PAD, Math.min(left, viewportW - width - PANEL_EDGE_PAD))
|
||||
panelStyle.value = {
|
||||
top: `${rect.bottom}px`,
|
||||
left: `${left}px`,
|
||||
width: `${width}px`
|
||||
}
|
||||
}
|
||||
|
||||
const closePanel = (): void => {
|
||||
openModulePath.value = null
|
||||
}
|
||||
|
||||
const toggleModule = async (item: PortalModuleItem): Promise<void> => {
|
||||
const path = String(item.path || '')
|
||||
if (!path) return
|
||||
openModulePath.value = openModulePath.value === path ? null : path
|
||||
if (openModulePath.value) {
|
||||
await nextTick()
|
||||
syncPanelPosition()
|
||||
}
|
||||
}
|
||||
|
||||
/** 顶栏同时只高亮一个一级:面板展开时跟展开项,否则跟当前路由 */
|
||||
const isL1Selected = (item: PortalModuleItem): boolean => {
|
||||
if (openModulePath.value) {
|
||||
return openModulePath.value === item.path
|
||||
}
|
||||
return item.isRouteActive
|
||||
}
|
||||
|
||||
const isLinkActive = (link: AppRouteRecord): boolean => {
|
||||
return isMegaPanelLinkActive(link, currentRoutePath.value)
|
||||
}
|
||||
|
||||
const handleLinkClick = (link: AppRouteRecord): void => {
|
||||
closePanel()
|
||||
handleMenuJump(link)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
() => {
|
||||
closePanel()
|
||||
}
|
||||
)
|
||||
|
||||
watch(openModulePath, async (path) => {
|
||||
if (!path) return
|
||||
await nextTick()
|
||||
syncPanelPosition()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', syncPanelPosition)
|
||||
window.addEventListener('scroll', syncPanelPosition, true)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', syncPanelPosition)
|
||||
window.removeEventListener('scroll', syncPanelPosition, true)
|
||||
})
|
||||
|
||||
onClickOutside(rootRef, (event) => {
|
||||
const target = event.target as HTMLElement | null
|
||||
if (target?.closest?.('.portal-mega-panel')) {
|
||||
return
|
||||
}
|
||||
closePanel()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.portal-mega-menu {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.portal-mega-l1 {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 2px;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
min-width: 0;
|
||||
max-height: 100%;
|
||||
/* 仅允许横向溢出;若只写 overflow-x:auto,overflow-y 会被算成 auto,易出现竖向滚动条 */
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.portal-mega-l1__item {
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
max-height: 56px;
|
||||
padding: 0 14px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.2;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 4px solid transparent;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
color 0.15s ease,
|
||||
border-color 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
background: rgba(255, 255, 255, 0.14);
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.portal-mega-l1__caret {
|
||||
font-size: 10px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.portal-mega-overlay {
|
||||
position: fixed;
|
||||
inset: 56px 0 0 0;
|
||||
z-index: 190;
|
||||
background: rgba(15, 23, 42, 0.25);
|
||||
}
|
||||
|
||||
.portal-mega-panel {
|
||||
position: fixed;
|
||||
z-index: 200;
|
||||
box-sizing: border-box;
|
||||
max-height: min(720px, calc(100vh - 72px));
|
||||
overflow: auto;
|
||||
background: #fff;
|
||||
border: 1px solid var(--mint-border, #e2e8f0);
|
||||
border-top: none;
|
||||
border-radius: 0 0 10px 10px;
|
||||
box-shadow: 0 14px 32px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
|
||||
.portal-mega-panel__body {
|
||||
padding: 12px 16px 18px;
|
||||
}
|
||||
|
||||
.portal-mega-split {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0 16px;
|
||||
align-items: stretch;
|
||||
|
||||
&.is-single {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.portal-mega-pane {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.portal-mega-pane--right {
|
||||
padding-left: 16px;
|
||||
border-left: 1px solid var(--mint-border, #e2e8f0);
|
||||
}
|
||||
|
||||
.portal-mega-row {
|
||||
display: grid;
|
||||
grid-template-columns: 110px 1fr;
|
||||
gap: 8px 14px;
|
||||
align-items: start;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.portal-mega-row__l2 {
|
||||
padding-top: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 1.35;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.portal-mega-row__l3 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
gap: 4px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.portal-mega-link {
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 4px 0;
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 1.45;
|
||||
color: #0f172a;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
transition: color 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-dark, #059669);
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark, #059669);
|
||||
}
|
||||
}
|
||||
|
||||
.portal-mega-empty {
|
||||
margin: 12px 0;
|
||||
font-size: 13px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
@media only screen and (width <= 900px) {
|
||||
.portal-mega-split {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.portal-mega-pane--right {
|
||||
padding-left: 0;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.portal-mega-row {
|
||||
grid-template-columns: 96px 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user