@@ -1,7 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NModal } from 'naive-ui'
|
||||
import { computed } from 'vue'
|
||||
|
||||
defineProps<{
|
||||
import { useIsMobile } from '@/composables/useIsMobile'
|
||||
|
||||
const props = defineProps<{
|
||||
show: boolean
|
||||
title: string
|
||||
submitting?: boolean
|
||||
@@ -12,6 +15,15 @@ defineProps<{
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{ 'update:show': [boolean]; submit: [] }>()
|
||||
|
||||
const isMobile = useIsMobile()
|
||||
|
||||
/** 移动端全屏(100dvh 覆盖底栏与手势区),桌面维持定宽居中 */
|
||||
const modalStyle = computed(() =>
|
||||
isMobile.value
|
||||
? { width: '100vw', height: '100dvh', maxWidth: '100vw', margin: '0', borderRadius: '0' }
|
||||
: { width: `${props.width ?? 480}px`, maxWidth: 'calc(100vw - 24px)' },
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -19,7 +31,8 @@ const emit = defineEmits<{ 'update:show': [boolean]; submit: [] }>()
|
||||
:show="show"
|
||||
preset="card"
|
||||
:title="title"
|
||||
:style="{ width: `${width ?? 480}px`, maxWidth: 'calc(100vw - 24px)' }"
|
||||
:style="modalStyle"
|
||||
:class="isMobile ? 'form-modal-mobile' : ''"
|
||||
:mask-closable="!submitting"
|
||||
:close-on-esc="!submitting"
|
||||
@update:show="emit('update:show', $event)"
|
||||
@@ -33,11 +46,17 @@ const emit = defineEmits<{ 'update:show': [boolean]; submit: [] }>()
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-2.5">
|
||||
<NButton size="small" :disabled="submitting" @click="emit('update:show', false)">
|
||||
<NButton
|
||||
:size="isMobile ? 'medium' : 'small'"
|
||||
:class="isMobile ? 'flex-1' : ''"
|
||||
:disabled="submitting"
|
||||
@click="emit('update:show', false)"
|
||||
>
|
||||
取消
|
||||
</NButton>
|
||||
<NButton
|
||||
size="small"
|
||||
:size="isMobile ? 'medium' : 'small'"
|
||||
:class="isMobile ? 'flex-1' : ''"
|
||||
:type="danger ? 'error' : 'primary'"
|
||||
:loading="submitting"
|
||||
:disabled="submitDisabled"
|
||||
@@ -54,9 +73,19 @@ const emit = defineEmits<{ 'update:show': [boolean]; submit: [] }>()
|
||||
/* 长表单不撑破视口:内容区限高滚动,页脚按钮常驻;
|
||||
负 margin + 等量 padding 让滚动条贴弹窗边缘(变量继承自 .n-card) */
|
||||
.form-modal-body {
|
||||
max-height: min(62vh, calc(100vh - 220px));
|
||||
overflow-y: auto;
|
||||
margin-inline: calc(-1 * var(--n-padding-left, 24px));
|
||||
padding-inline: var(--n-padding-left, 24px);
|
||||
}
|
||||
/* 限高只在桌面定宽形态生效:移动全屏由全局 .form-modal-mobile 的 flex:1
|
||||
接管高度。不能靠全局规则 max-height:none 覆盖——main.css 先于组件
|
||||
scoped 样式加载,同特异性下这里会反超,故直接用断点隔离 */
|
||||
@media (min-width: 768px) {
|
||||
.form-modal-body {
|
||||
max-height: min(62vh, calc(100vh - 220px));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 移动端全屏形态 .form-modal-mobile 的规则在 main.css(全局):
|
||||
NModal teleport 到 body,scoped 够不到;且该类被各弹窗跨 chunk 复用 -->
|
||||
|
||||
Reference in New Issue
Block a user