Modal.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <script setup>
  2. import { ref, watchEffect, nextTick } from "vue";
  3. const popup = ref(null);
  4. const props = defineProps({
  5. open: {
  6. type: Boolean,
  7. default: false,
  8. },
  9. backgroundColor: {
  10. type: String,
  11. default: "#fff",
  12. },
  13. width: {
  14. type: String,
  15. default: "600rpx",
  16. },
  17. height: {
  18. type: String,
  19. default: "",
  20. },
  21. title: {
  22. type: String,
  23. default: "",
  24. },
  25. footer: {
  26. type: Boolean,
  27. default: true,
  28. },
  29. });
  30. const emit = defineEmits(["change", "close", "submit"]);
  31. const onChange = (e) => {
  32. emit("change", e);
  33. };
  34. watchEffect(() => {
  35. // 监听这两个函数
  36. popup.value;
  37. props.open;
  38. nextTick(() => {
  39. if (props.open) {
  40. popup.value?.open?.();
  41. } else {
  42. popup.value?.close?.();
  43. }
  44. });
  45. });
  46. defineExpose({
  47. popup,
  48. });
  49. </script>
  50. <template>
  51. <uni-popup
  52. ref="popup"
  53. @change="onChange"
  54. v-bind="$attrs"
  55. background-color="transparent"
  56. >
  57. <view
  58. class="popup-content"
  59. :style="{
  60. backgroundColor,
  61. width,
  62. height,
  63. }"
  64. >
  65. <view class="title">
  66. <slot name="title">{{ title }}</slot>
  67. <uni-icons
  68. type="closeempty"
  69. class="icons"
  70. @click="popup?.close"
  71. ></uni-icons>
  72. </view>
  73. <view class="content">
  74. <slot></slot>
  75. </view>
  76. <view v-if="footer" class="footer">
  77. <slot name="footer">
  78. <button class="plain" @click="emit('close')">取消</button>
  79. <button class="primary" @click="emit('submit')">确认</button>
  80. </slot>
  81. </view>
  82. </view>
  83. </uni-popup>
  84. </template>
  85. <style scoped lang="scss">
  86. @import "@/uni.scss";
  87. .popup-content {
  88. display: flex;
  89. align-items: center;
  90. flex-direction: column;
  91. justify-content: space-between;
  92. gap: 20rpx;
  93. padding: 20rpx;
  94. border-radius: 10rpx;
  95. .title {
  96. font-family: PingFang SC, PingFang SC;
  97. font-weight: bold;
  98. font-size: 36rpx;
  99. color: #000000;
  100. position: relative;
  101. display: flex;
  102. align-items: center;
  103. justify-content: center;
  104. width: 100%;
  105. margin-top: 10rpx;
  106. .icons {
  107. position: absolute;
  108. right: 0;
  109. top: -10rpx;
  110. }
  111. }
  112. .content {
  113. width: 100%;
  114. flex: 1;
  115. }
  116. .footer {
  117. display: flex;
  118. gap: 20rpx;
  119. width: 100%;
  120. padding: 0 30rpx;
  121. box-sizing: border-box;
  122. button {
  123. flex: 1;
  124. font-family: PingFang SC, PingFang SC;
  125. border-radius: 100rpx 100rpx 100rpx 100rpx;
  126. border: 1rpx solid $primary;
  127. background-color: transparent;
  128. font-weight: 500;
  129. font-size: 32rpx;
  130. &::after {
  131. border: 0;
  132. }
  133. }
  134. .plain {
  135. background: $uni-primary-light;
  136. color: $primary;
  137. }
  138. .primary {
  139. background: $primary;
  140. color: #fff;
  141. }
  142. }
  143. }
  144. </style>