index.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <template>
  2. <div
  3. ref="toolbarItemRef"
  4. :class="[
  5. 'toolbar-item-container',
  6. !isPC && 'toolbar-item-container-h5',
  7. isUniFrameWork && 'toolbar-item-container-uni',
  8. ]"
  9. >
  10. <div
  11. :class="[
  12. 'toolbar-item-container-icon',
  13. isUniFrameWork && 'toolbar-item-container-uni-icon',
  14. ]"
  15. @click="toggleToolbarItem"
  16. >
  17. <Icon
  18. :file="props.iconFile"
  19. class="icon"
  20. :width="props.iconWidth"
  21. :height="props.iconHeight"
  22. />
  23. </div>
  24. <div
  25. v-if="isUniFrameWork"
  26. :class="['toolbar-item-container-uni-title']"
  27. >
  28. {{ props.title }}
  29. </div>
  30. <div
  31. v-show="showDialog"
  32. ref="dialogRef"
  33. :class="[
  34. 'toolbar-item-container-dialog',
  35. !isPC && 'toolbar-item-container-h5-dialog',
  36. isUniFrameWork && 'toolbar-item-container-uni-dialog',
  37. ]"
  38. >
  39. <BottomPopup
  40. v-if="props.needBottomPopup && !isPC"
  41. class="toolbar-bottom-popup"
  42. :show="showDialog"
  43. @touchmove.stop.prevent
  44. @onClose="onPopupClose"
  45. >
  46. <slot />
  47. </BottomPopup>
  48. <slot v-else />
  49. </div>
  50. </div>
  51. </template>
  52. <script lang="ts" setup>
  53. import { ref } from '../../../../adapter-vue';
  54. import { outsideClick } from '@tencentcloud/universal-api';
  55. import Icon from '../../../common/Icon.vue';
  56. import BottomPopup from '../../../common/BottomPopup/index.vue';
  57. import { isPC, isUniFrameWork } from '../../../../utils/env';
  58. const props = defineProps({
  59. iconFile: {
  60. type: String,
  61. required: true,
  62. },
  63. title: {
  64. type: String,
  65. default: '',
  66. },
  67. needDialog: {
  68. type: Boolean,
  69. default: true,
  70. },
  71. iconWidth: {
  72. type: String,
  73. default: '20px',
  74. },
  75. iconHeight: {
  76. type: String,
  77. default: '20px',
  78. },
  79. // Whether to display the bottom popup dialog on mobile devices
  80. // Invalid on PC
  81. needBottomPopup: {
  82. type: Boolean,
  83. default: false,
  84. },
  85. });
  86. const emits = defineEmits(['onIconClick', 'onDialogClose', 'onDialogShow']);
  87. const showDialog = ref(false);
  88. const toolbarItemRef = ref();
  89. const dialogRef = ref();
  90. const toggleToolbarItem = () => {
  91. emits('onIconClick', dialogRef);
  92. if (isPC) {
  93. outsideClick.listen({
  94. domRefs: toolbarItemRef.value,
  95. handler: closeToolbarItem,
  96. });
  97. }
  98. if (!props.needDialog) {
  99. return;
  100. }
  101. toggleDialogDisplay(!showDialog.value);
  102. };
  103. const closeToolbarItem = () => {
  104. showDialog.value = false;
  105. emits('onDialogClose', dialogRef);
  106. };
  107. const toggleDialogDisplay = (showStatus: boolean) => {
  108. if (showDialog.value === showStatus) {
  109. return;
  110. }
  111. showDialog.value = showStatus;
  112. switch (showStatus) {
  113. case true:
  114. emits('onDialogShow', dialogRef);
  115. break;
  116. case false:
  117. emits('onDialogClose', dialogRef);
  118. }
  119. };
  120. const onPopupClose = () => {
  121. showDialog.value = false;
  122. };
  123. defineExpose({
  124. toggleDialogDisplay,
  125. });
  126. </script>
  127. <style lang="scss" scoped src="./style/index.scss"></style>