index.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <template>
  2. <el-dialog
  3. :model-value="modelValue"
  4. :close-on-click-modal="false"
  5. :close-on-press-escape="false"
  6. v-bind="dialogAttrs"
  7. draggable
  8. v-on="dialogListeners"
  9. @update:model-value="handleModelValueChange"
  10. @close="handleCancel"
  11. @opened="handleOpened"
  12. :class="dialogClass"
  13. >
  14. <slot name="default"></slot>
  15. <template v-if="showFooter" #footer>
  16. <slot name="footer">
  17. <span class="dialog-footer">
  18. <el-button @click="handleCancel" v-if="showCancel">{{ cancelText }}</el-button>
  19. <el-button type="primary" @click="handleConfirm">{{ confirmText }}</el-button>
  20. </span>
  21. </slot>
  22. </template>
  23. </el-dialog>
  24. </template>
  25. <script setup>
  26. import { defineProps, defineEmits, useAttrs, computed } from 'vue'
  27. const props = defineProps({
  28. modelValue: {
  29. type: Boolean,
  30. required: true
  31. },
  32. showFooter: {
  33. type: Boolean,
  34. default: true
  35. },
  36. extraData: {
  37. type: Object,
  38. default: () => ({})
  39. },
  40. cancelText: {
  41. type: String,
  42. default: '取消'
  43. },
  44. showCancel: {
  45. type: Boolean,
  46. default: true
  47. },
  48. confirmText: {
  49. type: String,
  50. default: '确认'
  51. },
  52. position: {
  53. type: String,
  54. default: 'top',
  55. validator: (value) => ['top', 'center', 'custom'].includes(value)
  56. },
  57. customTop: {
  58. type: String,
  59. default: '10vh'
  60. }
  61. })
  62. const emit = defineEmits([
  63. 'update:modelValue',
  64. 'confirm',
  65. 'cancel'
  66. ])
  67. const attrs = useAttrs()
  68. const dialogClass = computed(() => {
  69. return {
  70. 'dialog-top-position': props.position === 'top',
  71. 'dialog-center-position': props.position === 'center',
  72. 'dialog-custom-position': props.position === 'custom'
  73. }
  74. })
  75. const dialogAttrs = computed(() => {
  76. const { onUpdateModelValue, alignCenter, ...restAttrs } = attrs
  77. // 根据 position 设置 top 属性(仅在非 center 时生效)
  78. const additionalAttrs = {}
  79. if (props.position !== 'center') {
  80. if (props.position === 'top') {
  81. additionalAttrs.top = '10vh'
  82. } else if (props.position === 'custom') {
  83. additionalAttrs.top = props.customTop
  84. }
  85. }
  86. return {
  87. ...restAttrs,
  88. ...additionalAttrs,
  89. 'onUpdate:modelValue': undefined
  90. }
  91. })
  92. const dialogListeners = computed(() => {
  93. const listeners = {}
  94. for (const key in attrs) {
  95. if (/^on[A-Z]/.test(key) && key !== 'onUpdateModelValue') {
  96. listeners[key] = attrs[key]
  97. }
  98. }
  99. return listeners
  100. })
  101. const handleOpened = () => {
  102. // 可以在这里添加打开后的逻辑
  103. }
  104. const handleModelValueChange = (value) => {
  105. emit('update:modelValue', value)
  106. }
  107. const handleCancel = () => {
  108. emit('cancel', props.extraData)
  109. handleModelValueChange(false)
  110. }
  111. const handleConfirm = () => {
  112. emit('confirm', props.extraData)
  113. handleModelValueChange(false)
  114. }
  115. </script>
  116. <style scoped>
  117. /* 优化弹窗在顶部位置时的滚动体验 */
  118. :deep(.dialog-top-position .el-dialog__body) {
  119. max-height: 70vh;
  120. overflow-y: auto;
  121. padding: 20px;
  122. }
  123. /* 确保内容区域有合适的最大高度和滚动 */
  124. :deep(.el-dialog__body) {
  125. max-height: 65vh;
  126. overflow-y: auto;
  127. }
  128. /* 滚动条样式优化 */
  129. :deep(.el-dialog__body::-webkit-scrollbar) {
  130. width: 6px;
  131. }
  132. :deep(.el-dialog__body::-webkit-scrollbar-track) {
  133. background: #f1f1f1;
  134. border-radius: 3px;
  135. }
  136. :deep(.el-dialog__body::-webkit-scrollbar-thumb) {
  137. background: #c1c1c1;
  138. border-radius: 3px;
  139. }
  140. :deep(.el-dialog__body::-webkit-scrollbar-thumb:hover) {
  141. background: #a8a8a8;
  142. }
  143. </style>