| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- <template>
- <el-dialog
- :model-value="modelValue"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- v-bind="dialogAttrs"
- draggable
- v-on="dialogListeners"
- @update:model-value="handleModelValueChange"
- @close="handleCancel"
- @opened="handleOpened"
- :class="dialogClass"
- >
- <slot name="default"></slot>
- <template v-if="showFooter" #footer>
- <slot name="footer">
- <span class="dialog-footer">
- <el-button @click="handleCancel" v-if="showCancel">{{ cancelText }}</el-button>
- <el-button type="primary" @click="handleConfirm">{{ confirmText }}</el-button>
- </span>
- </slot>
- </template>
- </el-dialog>
- </template>
- <script setup>
- import { defineProps, defineEmits, useAttrs, computed } from 'vue'
- const props = defineProps({
- modelValue: {
- type: Boolean,
- required: true
- },
- showFooter: {
- type: Boolean,
- default: true
- },
- extraData: {
- type: Object,
- default: () => ({})
- },
- cancelText: {
- type: String,
- default: '取消'
- },
- showCancel: {
- type: Boolean,
- default: true
- },
- confirmText: {
- type: String,
- default: '确认'
- },
- position: {
- type: String,
- default: 'top',
- validator: (value) => ['top', 'center', 'custom'].includes(value)
- },
- customTop: {
- type: String,
- default: '10vh'
- }
- })
- const emit = defineEmits([
- 'update:modelValue',
- 'confirm',
- 'cancel'
- ])
- const attrs = useAttrs()
- const dialogClass = computed(() => {
- return {
- 'dialog-top-position': props.position === 'top',
- 'dialog-center-position': props.position === 'center',
- 'dialog-custom-position': props.position === 'custom'
- }
- })
- const dialogAttrs = computed(() => {
- const { onUpdateModelValue, alignCenter, ...restAttrs } = attrs
-
- // 根据 position 设置 top 属性(仅在非 center 时生效)
- const additionalAttrs = {}
- if (props.position !== 'center') {
- if (props.position === 'top') {
- additionalAttrs.top = '10vh'
- } else if (props.position === 'custom') {
- additionalAttrs.top = props.customTop
- }
- }
-
- return {
- ...restAttrs,
- ...additionalAttrs,
- 'onUpdate:modelValue': undefined
- }
- })
- const dialogListeners = computed(() => {
- const listeners = {}
- for (const key in attrs) {
- if (/^on[A-Z]/.test(key) && key !== 'onUpdateModelValue') {
- listeners[key] = attrs[key]
- }
- }
- return listeners
- })
- const handleOpened = () => {
- // 可以在这里添加打开后的逻辑
- }
- const handleModelValueChange = (value) => {
- emit('update:modelValue', value)
- }
- const handleCancel = () => {
- emit('cancel', props.extraData)
- handleModelValueChange(false)
- }
- const handleConfirm = () => {
- emit('confirm', props.extraData)
- handleModelValueChange(false)
- }
- </script>
- <style scoped>
- /* 优化弹窗在顶部位置时的滚动体验 */
- :deep(.dialog-top-position .el-dialog__body) {
- max-height: 70vh;
- overflow-y: auto;
- padding: 20px;
- }
- /* 确保内容区域有合适的最大高度和滚动 */
- :deep(.el-dialog__body) {
- max-height: 65vh;
- overflow-y: auto;
- }
- /* 滚动条样式优化 */
- :deep(.el-dialog__body::-webkit-scrollbar) {
- width: 6px;
- }
- :deep(.el-dialog__body::-webkit-scrollbar-track) {
- background: #f1f1f1;
- border-radius: 3px;
- }
- :deep(.el-dialog__body::-webkit-scrollbar-thumb) {
- background: #c1c1c1;
- border-radius: 3px;
- }
- :deep(.el-dialog__body::-webkit-scrollbar-thumb:hover) {
- background: #a8a8a8;
- }
- </style>
|