indexYQ.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <!--
  2. 移动端 底部弹出对话框 组件
  3. - pc 端,仅展示【插槽】内容,无弹出对话框,无对话框相关 header footer
  4. - mobile 端,底部弹出对话框,支持 对话框相关 header footer 定制展示,详情请参见参数列表
  5. -->
  6. <template>
  7. <div v-if="props.show">
  8. <div
  9. v-if="!isPC"
  10. :class="[
  11. 'bottom-popup',
  12. isUniFrameWork && 'bottom-popup-uni',
  13. !isPC && 'bottom-popup-h5',
  14. !isPC && props.modal && 'bottom-popup-modal',
  15. ]"
  16. @click="closeBottomPopup"
  17. >
  18. <div
  19. ref="dialogRef"
  20. :class="['bottom-popup-main', !isPC && 'bottom-popup-h5-main']"
  21. :style="{
  22. width: props.width,
  23. height: props.height,
  24. borderRadius: props.borderRadius,
  25. position: props.position,
  26. left: props.left,
  27. top: props.top,
  28. }"
  29. @click.stop
  30. >
  31. <div v-if="title || showHeaderCloseButton" class="header">
  32. <div v-if="title" class="header-title">
  33. {{ title }}
  34. </div>
  35. <div
  36. v-if="showHeaderCloseButton"
  37. class="header-close"
  38. @click="closeBottomPopup"
  39. >
  40. {{ TUITranslateService.t("关闭") }}
  41. </div>
  42. </div>
  43. <slot />
  44. <div v-if="showFooterSubmitButton" class="footer">
  45. <div class="footer-submit" @click="submit">
  46. {{ submitButtonContent }}
  47. </div>
  48. </div>
  49. </div>
  50. </div>
  51. <slot v-else />
  52. </div>
  53. </template>
  54. <script setup lang="ts">
  55. import { ref, watch, nextTick } from "../../../adapter-vue";
  56. import { TUITranslateService } from "@tencentcloud/chat-uikit-engine";
  57. import { outsideClick } from "@tencentcloud/universal-api";
  58. import { isPC, isH5, isUniFrameWork } from "../../../utils/env";
  59. const props = defineProps({
  60. // 是否展示 底部弹出对话框
  61. show: {
  62. type: Boolean,
  63. default: false,
  64. },
  65. // 是否需要遮罩层,默认为true
  66. modal: {
  67. type: Boolean,
  68. default: true,
  69. },
  70. // 弹出框内容区域高度(不包含遮罩), 默认为 fit-content
  71. height: {
  72. type: String,
  73. default: "fit-content",
  74. },
  75. // 是否可以通过点击外部关闭弹出对话框, 默认为true
  76. // uniapp 仅支持点击蒙版关闭弹出对话框
  77. closeByClickOutside: {
  78. type: Boolean,
  79. default: true,
  80. },
  81. // 上边框两角圆角角度,默认为 0px,即默认为直角
  82. borderRadius: {
  83. type: String,
  84. default: "0px",
  85. },
  86. // title 标题文本
  87. title: {
  88. type: String,
  89. default: "",
  90. },
  91. // 是否展示顶部关闭按钮, 默认不展示
  92. showHeaderCloseButton: {
  93. type: Boolean,
  94. default: false,
  95. },
  96. // 是否展示底部提交按钮,默认不展示
  97. showFooterSubmitButton: {
  98. type: Boolean,
  99. default: false,
  100. },
  101. // 底部提交按钮文案,仅 showFooterSubmitButton 为 true 时有效
  102. submitButtonContent: {
  103. type: String,
  104. default: () => TUITranslateService.t("确定"),
  105. },
  106. });
  107. const emits = defineEmits(["onOpen", "onClose", "onSubmit"]);
  108. const dialogRef = ref();
  109. watch(
  110. () => props.show,
  111. (newVal: boolean, oldVal: boolean) => {
  112. if (newVal === oldVal) {
  113. return;
  114. }
  115. switch (newVal) {
  116. case true:
  117. emits("onOpen", dialogRef);
  118. nextTick(() => {
  119. // web h5 下生效
  120. if (isH5 && !isUniFrameWork) {
  121. if (props.closeByClickOutside) {
  122. outsideClick.listen({
  123. domRefs: dialogRef.value,
  124. handler: closeBottomPopup,
  125. });
  126. }
  127. }
  128. });
  129. break;
  130. case false:
  131. emits("onClose", dialogRef);
  132. break;
  133. }
  134. }
  135. );
  136. const closeBottomPopup = () => {
  137. if (isUniFrameWork || isH5) {
  138. emits("onClose", dialogRef);
  139. }
  140. };
  141. const submit = () => {
  142. emits("onSubmit");
  143. closeBottomPopup();
  144. };
  145. </script>
  146. <style scoped lang="scss" src="./style/index.scss"></style>
  147. <style scoped lang="scss">
  148. .bottom-popup-main {
  149. position: absolute;
  150. top: 90px !important;
  151. width: 90% !important;
  152. left: 20px !important;
  153. border-radius: 10px;
  154. }
  155. </style>