This commit is contained in:
2026-09-04 14:43:34 +08:00
parent e4ba4cbb2c
commit 2fc84d249c
4 changed files with 37 additions and 9 deletions
+14 -1
View File
@@ -8,12 +8,13 @@ import AppDialog from './AppDialog.vue'
const ElDialogStub = defineComponent({
props: {
modelValue: Boolean,
title: String,
showClose: Boolean,
closeOnClickModal: Boolean,
closeOnPressEscape: Boolean,
fullscreen: Boolean,
},
template: '<section data-testid="dialog"><slot name="header" /><slot /><slot name="footer" /></section>',
template: '<section data-testid="dialog"><h2 v-if="!$slots.header" data-testid="native-title">{{ title }}</h2><slot name="header" /><slot /><slot name="footer" /></section>',
})
const ElButtonStub = defineComponent({
@@ -73,6 +74,9 @@ describe('AppDialog', () => {
const wrapper = mountDialog({ fullscreenable: true, defaultFullscreen: true })
expect(wrapper.getComponent(ElDialogStub).props('fullscreen')).toBe(true)
expect(wrapper.get('[data-testid="native-title"]').text()).toBe('编辑资料')
expect(wrapper.find('.app-dialog__header').exists()).toBe(false)
expect(wrapper.find('.app-dialog__native-fullscreen-control').exists()).toBe(true)
expect(wrapper.find('button[aria-label="退出全屏"]').exists()).toBe(true)
await wrapper.get('button[aria-label="退出全屏"]').trigger('click')
@@ -88,4 +92,13 @@ describe('AppDialog', () => {
expect(source).toContain(':global(.app-dialog .el-dialog__body) { min-height: 0; overflow-y: auto;')
expect(source).toContain('max-height: calc(100svh - 20px)')
})
it('keeps the native title bar when fullscreen is enabled without a custom header', () => {
const source = readFileSync(resolve(process.cwd(), 'src/shared/components/AppDialog.vue'), 'utf8')
expect(source).toContain('<template v-if="$slots.header" #header>')
expect(source).not.toContain('<template v-if="$slots.header || fullscreenable" #header>')
expect(source).toContain("fullscreenable && !$slots.header")
expect(source).toContain('app-dialog__native-fullscreen-control')
})
})
+21 -7
View File
@@ -80,22 +80,33 @@ function closeDialog() {
:close-on-press-escape="closeOnPressEscape && !submittingLocked"
:destroy-on-close="destroyOnClose"
:fullscreen="fullscreenable && fullscreen"
:class="{ 'has-native-fullscreen-control': fullscreenable && !$slots.header }"
>
<template v-if="$slots.header || fullscreenable" #header>
<div v-if="fullscreenable" class="app-dialog__header">
<template v-if="$slots.header" #header>
<div class="app-dialog__header">
<div class="app-dialog__header-content">
<slot v-if="$slots.header" name="header" :fullscreen="fullscreen" :toggle-fullscreen="toggleFullscreen" />
<span v-else>{{ title }}</span>
<slot name="header" :fullscreen="fullscreen" :toggle-fullscreen="toggleFullscreen" />
</div>
<el-tooltip :content="fullscreen ? '退出全屏' : '展开全屏'" placement="bottom">
<el-tooltip v-if="fullscreenable" :content="fullscreen ? '退出全屏' : '展开全屏'" placement="bottom">
<el-button text :aria-label="fullscreen ? '退出全屏' : '展开全屏'" @click="toggleFullscreen">
<Minimize2 v-if="fullscreen" :size="18" />
<Maximize2 v-else :size="18" />
</el-button>
</el-tooltip>
</div>
<slot v-else name="header" />
</template>
<el-tooltip v-if="fullscreenable && !$slots.header" :content="fullscreen ? '退出全屏' : '展开全屏'" placement="bottom">
<el-button
class="app-dialog__native-fullscreen-control"
:class="{ 'is-without-close': !showClose || submittingLocked }"
text
:aria-label="fullscreen ? '退出全屏' : '展开全屏'"
@click="toggleFullscreen"
>
<Minimize2 v-if="fullscreen" :size="18" />
<Maximize2 v-else :size="18" />
</el-button>
</el-tooltip>
<div v-loading="loading" class="app-dialog__body" :aria-busy="loading || confirmLoading">
<slot />
</div>
@@ -117,13 +128,16 @@ function closeDialog() {
</template>
<style scoped>
:global(.app-dialog.el-dialog) { display: flex; max-height: min(90vh, 900px); flex-direction: column; overflow: hidden; }
:global(.app-dialog.el-dialog) { position: relative; display: flex; max-height: min(90vh, 900px); flex-direction: column; overflow: hidden; }
:global(.app-dialog.el-dialog.is-fullscreen) { width: 100%; max-width: 100%; height: 100vh; max-height: 100vh; margin: 0 !important; border-radius: 0; }
:global(.app-dialog .el-dialog__header), :global(.app-dialog .el-dialog__footer) { flex: 0 0 auto; }
:global(.app-dialog .el-dialog__body) { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
:global(.app-dialog.has-native-fullscreen-control .el-dialog__title) { display: block; padding-right: 44px; }
.app-dialog__header { display: flex; width: 100%; min-width: 0; align-items: center; justify-content: space-between; gap: 12px; color: var(--cc-text); font-size: 18px; font-weight: 600; line-height: 24px; }
.app-dialog__header-content { min-width: 0; flex: 1; }
.app-dialog__header > :deep(.el-button) { flex: 0 0 auto; margin-right: 24px; color: var(--cc-muted); }
.app-dialog__native-fullscreen-control { position: absolute; z-index: 2; top: 10px; right: 48px; color: var(--cc-muted); }
.app-dialog__native-fullscreen-control.is-without-close { right: 12px; }
.app-dialog__body { min-height: 0; }
.app-dialog__footer { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }
.app-dialog__footer :deep(.el-button) { margin-left: 0; }