index.bak.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <el-dialog custom-class="cip-dialog__wrapper"
  3. :title="title"
  4. :model-value="modelValue"
  5. :width="width"
  6. :close-on-click-modal="closeOnClickModal"
  7. :top="top"
  8. append-to-body
  9. :destroyOnClose="destroyOnClose"
  10. @close="$emit('close')"
  11. @update:modelValue="changeVisible"
  12. @opened="handleOpened">
  13. <slot></slot>
  14. <template v-slot:footer v-if="!$slots.footer && !showOnly">
  15. <div style="text-align:right">
  16. <el-button @click="cancel" :size="buttonSize" v-if="!waiting">{{cancelText}}</el-button>
  17. <el-button @click="confirm" type="primary" :size="buttonSize" :loading="waiting">{{confirmText}}</el-button>
  18. </div>
  19. </template>
  20. <template #footer v-else>
  21. <slot name="footer" :confirm="confirm" :loading="waiting"></slot>
  22. </template>
  23. </el-dialog>
  24. </template>
  25. <script>
  26. import { ref, defineComponent, isRef } from 'vue'
  27. import { ElDialog, ElButton } from 'element-plus'
  28. export default defineComponent({
  29. name: 'CipDialog',
  30. components: { ElDialog, ElButton },
  31. props: {
  32. title: String,
  33. modelValue: { default: false }, // 是否显示dialog
  34. onConfirm: { type: Function }, // Function(resolve,reject)
  35. beforeConfirm: { type: Function, default: () => {} }, // 触发表单验证前的值设置
  36. width: { // 设置dialog宽度
  37. default: '870px'
  38. },
  39. top: { default: '15vh' },
  40. closeOnClickModal: { // 点击遮罩层是否关闭dialog
  41. type: Boolean,
  42. default: false
  43. },
  44. showOnly: {
  45. default: false
  46. },
  47. buttonSize: { // 设置footer按钮大小
  48. default: 'default'
  49. },
  50. confirmText: { // 触发on-confirm方法的按钮文字
  51. default: '确认'
  52. },
  53. cancelText: { // 触发关闭dialog方法按钮的文字
  54. default: '取消'
  55. },
  56. destroyOnClose: { // 默认关闭时销毁dialog
  57. type: Boolean,
  58. default: true
  59. }
  60. },
  61. emits: ['update:modelValue', 'cancel', 'close'],
  62. setup (props, context) {
  63. const waiting = ref(false)
  64. const changeVisible = (val) => {
  65. context.emit('update:modelValue', val)
  66. }
  67. const handleOpened = () => {
  68. const vnodeList = context.slots.default?.() || []
  69. vnodeList.forEach(vnode => {
  70. if (isRef(vnode.ref?.r)) {
  71. // ref直接勇士ref的变量
  72. // eslint-disable-next-line no-unused-expressions
  73. vnode.ref?.r.value?.clearValidate()
  74. } else {
  75. // ref使用字符串
  76. // eslint-disable-next-line no-unused-expressions
  77. vnode.ref?.i?.refs[vnode.ref?.r ?? 'form']?.clearValidate?.()
  78. }
  79. })
  80. }
  81. const validElForm = async (vnodeList = [], validList = []) => {
  82. const vnodeListLen = vnodeList.length
  83. for (let i = 0; i < vnodeListLen; i++) {
  84. const vnode = vnodeList[i]
  85. if (isRef(vnode.ref?.r)) {
  86. // eslint-disable-next-line no-unused-expressions
  87. vnode.ref?.r.value?.validate((valid) => {
  88. validList.push(valid)
  89. })
  90. } else {
  91. // eslint-disable-next-line no-unused-expressions
  92. vnode.ref?.i?.refs[vnode.ref?.r ?? 'form']?.validate?.((valid) => {
  93. validList.push(valid)
  94. })
  95. }
  96. }
  97. return validList
  98. }
  99. const confirm = async () => {
  100. waiting.value = true
  101. // 校验方法暂不可用
  102. try {
  103. const validList = await validElForm(context.slots.default?.())
  104. if (!validList.includes(false)) {
  105. await new Promise((resolve, reject) => {
  106. if (typeof props.onConfirm === 'function') {
  107. props.onConfirm(resolve, reject)
  108. } else {
  109. throw new TypeError('onConfirm is not a function')
  110. }
  111. })
  112. changeVisible(false)
  113. } else {
  114. // 存在未通过验证的表单
  115. }
  116. } catch (e) {
  117. // 错误捕捉
  118. console.error(e)
  119. }
  120. waiting.value = false
  121. }
  122. const cancel = () => {
  123. changeVisible(false)
  124. context.emit('cancel')
  125. }
  126. return {
  127. waiting,
  128. changeVisible,
  129. handleOpened,
  130. confirm,
  131. cancel
  132. }
  133. }
  134. })
  135. </script>
  136. <style lang="less">
  137. .cip-dialog__wrapper{
  138. &.@{elNamespace}-dialog{
  139. .@{elNamespace}-dialog__header{
  140. border-bottom: 1px solid #ddd;
  141. }
  142. .@{elNamespace}-dialog__body{
  143. max-height: 60vh;
  144. overflow-y: auto;
  145. overflow-x: hidden;
  146. padding-bottom: 12px;
  147. }
  148. .@{elNamespace}-dialog__footer{
  149. border-top: 1px solid #ddd;
  150. }
  151. }
  152. }
  153. </style>