ie-page.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <template>
  2. <view class="ie-page theme-ie"
  3. :class="[safeAreaInsetBottom ? 'safe-area-inset-bottom' : '', { 'is-fixed': fixHeight }]"
  4. :style="{ backgroundColor: bgColor }">
  5. <view class="ie-page-content">
  6. <slot></slot>
  7. </view>
  8. <view class="ie-page-popup">
  9. <vip-popup ref="vipPopupRef" />
  10. </view>
  11. <view v-if="$slots.tabbar" class="ie-page-tabbar">
  12. <slot name="tabbar"></slot>
  13. </view>
  14. </view>
  15. </template>
  16. <script lang="ts" setup>
  17. import { CLOSE_VIP_POPUP, OPEN_VIP_POPUP } from '@/types/injectionSymbols';
  18. import VipPopup from './components/vip-popup.vue';
  19. import { EnumEvent } from '@/common/enum';
  20. defineOptions({
  21. name: 'ie-page',
  22. options: {
  23. virtualHost: true
  24. }
  25. });
  26. type PageProps = {
  27. safeAreaInsetBottom?: boolean;
  28. bgColor?: string;
  29. fixHeight?: boolean;
  30. safeAreaInsetBottomColor?: string;
  31. }
  32. const props = withDefaults(defineProps<PageProps>(), {
  33. safeAreaInsetBottom: true,
  34. bgColor: '',
  35. fixHeight: false,
  36. safeAreaInsetBottomColor: ''
  37. });
  38. const safeAreaColor = computed(() => {
  39. return props.safeAreaInsetBottom ? props.safeAreaInsetBottomColor : (props.bgColor ? props.bgColor
  40. : '#FFFFFF');
  41. });
  42. // 为 ref 添加类型定义
  43. const vipPopupRef = ref<InstanceType<typeof VipPopup>>();
  44. // 添加安全检查
  45. const showVipPopup = () => {
  46. console.log('showVipPopup called, vipPopupRef.value:', vipPopupRef.value);
  47. if (vipPopupRef.value) {
  48. vipPopupRef.value.open();
  49. } else {
  50. console.error('vipPopupRef is not initialized');
  51. }
  52. }
  53. const closeVipPopup = () => {
  54. console.log('closeVipPopup called');
  55. if (vipPopupRef.value) {
  56. vipPopupRef.value.close();
  57. } else {
  58. console.error('vipPopupRef is not initialized');
  59. }
  60. }
  61. // provide 给 ie-page 内部的子组件(slot 内容)使用
  62. // console.log('ie-page setup: providing OPEN_VIP_POPUP and CLOSE_VIP_POPUP');
  63. provide(OPEN_VIP_POPUP, showVipPopup);
  64. provide(CLOSE_VIP_POPUP, closeVipPopup);
  65. // console.log('ie-page setup: provided successfully');
  66. // 暴露方法给父组件通过 ref 调用
  67. defineExpose({
  68. showVipPopup,
  69. closeVipPopup
  70. });
  71. const addListener = () => {
  72. uni.$on(EnumEvent.OPEN_VIP_POPUP, showVipPopup);
  73. }
  74. const removeListener = () => {
  75. uni.$off(EnumEvent.OPEN_VIP_POPUP);
  76. }
  77. onMounted(() => {
  78. addListener();
  79. });
  80. onBeforeUnmount(() => {
  81. removeListener();
  82. });
  83. onHide(() => {
  84. removeListener();
  85. });
  86. onUnload(() => {
  87. removeListener();
  88. });
  89. </script>
  90. <style lang="scss" scoped>
  91. .ie-page {
  92. min-height: 100vh;
  93. box-sizing: border-box;
  94. }
  95. .ie-page-content {
  96. @apply min-h-full relative flex flex-col z-99;
  97. }
  98. .ie-page-tabbar {
  99. @apply relative z-100 h-[50px];
  100. }
  101. .is-fixed {
  102. height: 1px;
  103. }
  104. .ie-fixed-bottom {
  105. box-shadow: 0 -2px 8px 0 rgba(0, 0, 0, 0.05);
  106. }
  107. </style>