index.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <el-dialog :id="uuid"
  3. v-model="isShow"
  4. :before-close="beforeClose"
  5. :class="[isTable?'hc-modal-table':'', isSlotExtra?'hc-modal-header-extra':'', padding ? '':'hc-modal-no-padding', ui]"
  6. :close-on-click-modal="false" :destroy-on-close="!isLoading" :show-close="isClose"
  7. :style="isBgColor?'--el-dialog-bg-color:' + isBgColor:''" :title="title" :width="isWidth"
  8. class="hc-modal-border"
  9. close-on-press-escape
  10. draggable
  11. >
  12. <template v-if="isSlotHeader || isSlotExtra" #header>
  13. <slot v-if="isSlotHeader" name='header'/>
  14. <div v-if="!isSlotHeader && isSlotExtra" class="el-dialog__title" role="heading">{{ title }}</div>
  15. <slot v-if="isSlotExtra" name='extra'/>
  16. </template>
  17. <slot></slot>
  18. <template v-if="footer" #footer>
  19. <slot v-if="isSlotFooter" name='footer'/>
  20. <div v-else-if="isRowFooter" class="lr-dialog-footer">
  21. <div class="left">
  22. <slot name='leftRowFooter'/>
  23. </div>
  24. <div class="right flex">
  25. <slot name='rightRowFooter'/>
  26. </div>
  27. </div>
  28. <div v-else :class="isFooterCenter?'text-center':''" class="dialog-footer">
  29. <el-button :disabled="isLoading" size="large" @click="dialogClosed">
  30. <HcIcon name="close"/>
  31. <span>取消</span>
  32. </el-button>
  33. <el-button :loading="isLoading" hc-btn type="primary" @click="buttonSaveClick">
  34. <HcIcon name="check"/>
  35. <span>{{ saveText }}</span>
  36. </el-button>
  37. </div>
  38. </template>
  39. </el-dialog>
  40. </template>
  41. <script setup>
  42. import {ref, watch, useSlots, onMounted} from "vue";
  43. import {getRandom} from "vue-utils-plus"
  44. const props = defineProps({
  45. ui: {
  46. type: String,
  47. default: ''
  48. },
  49. show: {
  50. type: Boolean,
  51. default: false
  52. },
  53. title: {
  54. type: [String, Number],
  55. default: 'dialog'
  56. },
  57. widths: {
  58. type: String,
  59. default: '38rem'
  60. },
  61. loading: {
  62. type: Boolean,
  63. default: false
  64. },
  65. loadingText: {
  66. type: String,
  67. default: '请求中,请耐心等待...'
  68. },
  69. footer: {
  70. type: Boolean,
  71. default: true
  72. },
  73. saveText: {
  74. type: [String, Number],
  75. default: '提交'
  76. },
  77. bgColor: {
  78. type: [String, Number],
  79. default: '#f1f5f8'
  80. },
  81. isTable: {
  82. type: Boolean,
  83. default: false
  84. },
  85. isRowFooter: {
  86. type: Boolean,
  87. default: false
  88. },
  89. isClose: {
  90. type: Boolean,
  91. default: true
  92. },
  93. padding: {
  94. type: Boolean,
  95. default: true
  96. },
  97. isFooterCenter: {
  98. type: Boolean,
  99. default: false
  100. },
  101. })
  102. //变量
  103. const uuid = getRandom()
  104. const isShow = ref(props.show)
  105. const isWidth = ref(props.widths)
  106. const isLoading = ref(props.loading)
  107. const isBgColor = ref(props.bgColor)
  108. const loadingText = ref(props.loadingText)
  109. onMounted(() => {
  110. setLoading(props.loading)
  111. })
  112. //监听
  113. watch(() => [
  114. props.show,
  115. props.widths,
  116. props.loading,
  117. props.bgColor,
  118. props.loadingText,
  119. ], ([show, width, loading, bgColor, loadingText1]) => {
  120. isShow.value = show
  121. isWidth.value = width
  122. isLoading.value = loading
  123. isBgColor.value = bgColor
  124. loadingText.value = loadingText1
  125. setLoading(loading)
  126. })
  127. //判断<slot>是否有传值
  128. const slots = useSlots()
  129. const isSlotHeader = ref(!!slots.header);
  130. const isSlotExtra = ref(!!slots.extra);
  131. const isSlotFooter = ref(!!slots.footer);
  132. const emit = defineEmits(['close', 'save'])
  133. const loadingInstance = ref(null);
  134. const setLoading = (val) => {
  135. if (val) {
  136. const dom = document.getElementById(uuid)
  137. loadingInstance.value = window.$loading.service({
  138. target: dom,
  139. text: loadingText.value,
  140. })
  141. } else {
  142. if (loadingInstance.value) {
  143. loadingInstance.value.close()
  144. }
  145. }
  146. }
  147. //关闭
  148. const dialogClosed = () => {
  149. isShow.value = false
  150. emit('close', false)
  151. }
  152. const beforeClose = (done) => {
  153. if (!isLoading.value) {
  154. isShow.value = false
  155. done()
  156. emit('close', false)
  157. }
  158. }
  159. //按钮保存
  160. const buttonSaveClick = () => {
  161. emit('save')
  162. }
  163. </script>
  164. <style lang="scss">
  165. .el-overlay-dialog {
  166. .el-dialog.hc-modal-border.hc-modal-header-extra,
  167. .el-dialog.hc-modal-header-extra {
  168. .el-dialog__header {
  169. position: relative;
  170. display: flex;
  171. align-items: center;
  172. padding: 8px var(--el-dialog-padding-primary);
  173. .el-dialog__title {
  174. flex: 1;
  175. }
  176. .el-dialog__headerbtn {
  177. position: relative;
  178. top: initial;
  179. right: initial;
  180. width: auto;
  181. height: inherit;
  182. margin-left: 24px;
  183. font-size: 18px;
  184. }
  185. }
  186. }
  187. .el-dialog.hc-modal-no-padding .el-dialog__body {
  188. padding: 0;
  189. }
  190. }
  191. </style>