mirror of
https://github.com/pure-admin/pure-admin-thin.git
synced 2025-04-25 07:57:18 +08:00
174 lines
4.3 KiB
Vue
174 lines
4.3 KiB
Vue
<template>
|
|
<el-dialog
|
|
v-model="visible"
|
|
:fullscreen="fullScreen"
|
|
class="v-dialog"
|
|
:class="dialogClazz"
|
|
:draggable="props.draggable"
|
|
:show-close="false"
|
|
v-bind="$attrs"
|
|
>
|
|
<template #header>
|
|
<slot name="header">
|
|
<div
|
|
style="
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 24px;
|
|
font-weight: bold;
|
|
color: rgb(118 131 164);
|
|
"
|
|
>
|
|
<div v-text="props.title" />
|
|
<div
|
|
style="
|
|
position: absolute;
|
|
right: 0;
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: center;
|
|
"
|
|
>
|
|
<el-button
|
|
v-if="props.showFullScreen"
|
|
:icon="fullScreen ? FullScreenMinimize : FullScreenMaximize"
|
|
link
|
|
@click="requestFullScreen"
|
|
class="header-btn"
|
|
/>
|
|
<el-button
|
|
:icon="Close"
|
|
link
|
|
@click="handleCloseClick"
|
|
class="header-btn"
|
|
style="margin-left: 0"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</slot>
|
|
</template>
|
|
<template v-if="useBodyScrolling">
|
|
<el-scrollbar :max-height="bodyHeight" always>
|
|
<slot name="default" />
|
|
</el-scrollbar>
|
|
</template>
|
|
<template v-else>
|
|
<slot name="default" />
|
|
</template>
|
|
|
|
<template #footer>
|
|
<slot name="footer" v-if="!props.hiddenFooter">
|
|
<div style="display: flex; justify-content: center">
|
|
<el-button
|
|
:loading="props.loading"
|
|
type="primary"
|
|
@click="handleConfirm"
|
|
>{{ props.confirmText }}</el-button
|
|
>
|
|
<el-button :loading="props.loading" @click="handleCancel">{{
|
|
cancelText
|
|
}}</el-button>
|
|
</div>
|
|
</slot>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, ref } from "vue";
|
|
import { ElDialog, ElButton, ElScrollbar } from "element-plus";
|
|
import { DialogEmits, DialogProps } from "./dialog";
|
|
import { Close } from "@element-plus/icons-vue";
|
|
import FullScreenMaximize from "@/assets/svg/FullScreenMaximize.svg?component";
|
|
import FullScreenMinimize from "@/assets/svg/FullScreenMinimize.svg?component";
|
|
|
|
const props = withDefaults(defineProps<DialogProps>(), {
|
|
fullScreen: undefined,
|
|
confirmText: "确定",
|
|
cancelText: "取消",
|
|
disableFooter: false,
|
|
useBodyScrolling: false,
|
|
fixedBodyHeight: true,
|
|
draggable: true,
|
|
loading: false
|
|
});
|
|
const emits = defineEmits<DialogEmits>();
|
|
|
|
const visible = computed<boolean>({
|
|
get: () => {
|
|
return props.modelValue;
|
|
},
|
|
set: v => emits("update:modelValue", v)
|
|
});
|
|
|
|
const fullScreenState = ref(!!props.initFullScreen);
|
|
const fullScreen = computed<boolean>({
|
|
get: () => {
|
|
console.log("fullScreen getter", props.fullScreen, fullScreenState.value);
|
|
// 非受控模式,状态完全由组件内部控制
|
|
if (props.fullScreen === undefined) {
|
|
return fullScreenState.value;
|
|
} else {
|
|
return props.fullScreen;
|
|
}
|
|
},
|
|
set: v => {
|
|
fullScreenState.value = v;
|
|
console.log("fullScreen setter", v, props.fullScreen);
|
|
// 受控模式,将状态更新到父组件
|
|
if (props.fullScreen !== undefined) {
|
|
emits("update:fullScreen", v);
|
|
}
|
|
}
|
|
});
|
|
|
|
// const fullScreen = ref<boolean>(false)
|
|
function requestFullScreen() {
|
|
fullScreen.value = !fullScreen.value;
|
|
}
|
|
|
|
const bodyHeight = computed(() => {
|
|
const footerHeight = props.hiddenFooter ? "0" : "52px";
|
|
if (props.fullScreen) {
|
|
// footerHeight=52,headerHeight=44,padding=12
|
|
return `calc(100dvh - ${footerHeight} - 44px)`;
|
|
} else {
|
|
return `calc(70dvh - ${footerHeight} - 44px)`;
|
|
}
|
|
});
|
|
|
|
const dialogClazz = computed(() => {
|
|
const classList: string[] = ["v-dialog"];
|
|
if (!props.fixedBodyHeight) {
|
|
classList.push("flex-body");
|
|
}
|
|
if (props.hiddenFooter) {
|
|
classList.push("hidden-footer");
|
|
}
|
|
return classList;
|
|
});
|
|
|
|
function handleConfirm() {
|
|
emits("confirm");
|
|
}
|
|
|
|
function handleCancel() {
|
|
emits("cancel");
|
|
}
|
|
|
|
function handleCloseClick() {
|
|
visible.value = false;
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.header-btn :deep(.el-icon),
|
|
.header-btn :deep(.el-icon svg) {
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
</style>
|