cwg-popup.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <template>
  2. <uni-popup ref="popupRef" type="center" @change="handlePopupChange">
  3. <view class="cwg-dialog">
  4. <!-- 弹窗头部 -->
  5. <view class="dialog-header" v-if="title">
  6. <text class="dialog-title">{{ title || t('Tips.DeleteAccount') }}</text>
  7. <uni-icons type="closeempty" size="20" color="#999" @click="closeDialog" />
  8. </view>
  9. <!-- 弹窗内容 -->
  10. <view class="dialog-content">
  11. <slot />
  12. </view>
  13. <!-- 底部按钮区域 - 支持多种模式 -->
  14. <view class="dialog-footer" v-if="props.showFooters">
  15. <!-- 底部-额外自定义插槽 -->
  16. <template v-if="slotName && slots[slotName]">
  17. <slot :name="slotName" />
  18. </template>
  19. <!-- 自定义底部插槽 -->
  20. <template v-if="slots.footer">
  21. <view class="btn-content">
  22. <slot name="footer" />
  23. </view>
  24. </template>
  25. <!-- 无按钮模式:只显示一条线或不显示任何内容 -->
  26. <template v-else-if="footerType === 'none'">
  27. <!-- 不显示任何按钮,只留一个占位线(可选) -->
  28. <view v-if="showFooterLine" class="footer-line"></view>
  29. </template>
  30. <!-- 单按钮模式 -->
  31. <template v-else-if="footerType === 'single'">
  32. <view class="btn-content">
  33. <button class="single-btn" :class="singleBtnType" @click="handleSingleBtnClick">
  34. {{ singleBtnText || t('Common.Confirm') }}
  35. </button>
  36. </view>
  37. </template>
  38. <!-- 双按钮模式(默认) -->
  39. <template v-else>
  40. <view class="btn-content">
  41. <button class="cancel-btn" @click="closeDialog">
  42. {{ cancelText || t('Common.Cancel') }}
  43. </button>
  44. <button class="confirm-btn" :class="confirmBtnType" @click="handleConfirm">
  45. {{ confirmText || t('Common.Confirm') }}
  46. </button>
  47. </view>
  48. </template>
  49. </view>
  50. </view>
  51. </uni-popup>
  52. </template>
  53. <script setup>
  54. import { ref, watch, computed, useSlots } from 'vue'
  55. import { useI18n } from 'vue-i18n'
  56. const { t } = useI18n()
  57. const props = defineProps({
  58. // 是否显示弹窗
  59. visible: {
  60. type: Boolean,
  61. default: false
  62. },
  63. // 弹窗标题
  64. title: {
  65. type: String,
  66. default: ''
  67. },
  68. // 是否显示底部
  69. showFooters: {
  70. type: Boolean,
  71. default: true
  72. },
  73. // 底部按钮类型:double(双按钮), single(单按钮), none(无按钮)
  74. footerType: {
  75. type: String,
  76. default: 'double',
  77. validator: (value) => ['double', 'single', 'none'].includes(value)
  78. },
  79. // 单按钮文本
  80. singleBtnText: {
  81. type: String,
  82. default: ''
  83. },
  84. // 单按钮类型:primary, danger, default
  85. singleBtnType: {
  86. type: String,
  87. default: 'primary'
  88. },
  89. // 取消按钮文本
  90. cancelText: {
  91. type: String,
  92. default: ''
  93. },
  94. // 确认按钮文本
  95. confirmText: {
  96. type: String,
  97. default: ''
  98. },
  99. // 确认按钮类型:primary, danger
  100. confirmBtnType: {
  101. type: String,
  102. default: 'primary'
  103. },
  104. // 是否显示底部线条(当footerType为none时)
  105. showFooterLine: {
  106. type: Boolean,
  107. default: false
  108. },
  109. // 加载状态
  110. loading: {
  111. type: Boolean,
  112. default: false
  113. },
  114. // 自定义插槽名称
  115. slotName: {
  116. type: String,
  117. default: ''
  118. },
  119. // 分页信息(传递给父组件使用)
  120. pagerInfo: {
  121. type: Object,
  122. default: () => ({
  123. current: 1,
  124. row: 10,
  125. pageTotal: 0,
  126. rowTotal: 0
  127. })
  128. }
  129. })
  130. console.log('props.showFooters:', props.showFooters)
  131. const emit = defineEmits(['update:visible', 'confirm', 'close', 'single-click'])
  132. // 弹窗引用
  133. const popupRef = ref(null)
  134. const slots = useSlots()
  135. // 监听 visible 变化
  136. watch(() => props.visible, (val) => {
  137. console.log(slots)
  138. if (val) {
  139. popupRef.value?.open()
  140. } else {
  141. popupRef.value?.close()
  142. }
  143. }, { immediate: true })
  144. // 弹窗状态变化
  145. const handlePopupChange = (e) => {
  146. if (!e.show) {
  147. emit('update:visible', false)
  148. emit('close')
  149. }
  150. }
  151. // 关闭弹窗
  152. const closeDialog = () => {
  153. popupRef.value?.close()
  154. }
  155. // 确认操作
  156. const handleConfirm = () => {
  157. emit('confirm')
  158. }
  159. // 单按钮点击
  160. const handleSingleBtnClick = () => {
  161. emit('single-click')
  162. }
  163. // 暴露方法给父组件
  164. defineExpose({
  165. close: closeDialog,
  166. open: () => popupRef.value?.open()
  167. })
  168. </script>
  169. <style scoped lang="scss">
  170. @import "@/uni.scss";
  171. .cwg-dialog {
  172. background-color: var(--color-white);
  173. border-radius: px2rpx(8);
  174. overflow: hidden;
  175. width: px2rpx(600);
  176. max-width: 90vw;
  177. }
  178. .dialog-header {
  179. display: flex;
  180. align-items: center;
  181. justify-content: space-between;
  182. padding: px2rpx(30) px2rpx(30) px2rpx(20);
  183. border-bottom: 1px solid #f0f0f0;
  184. .dialog-title {
  185. font-size: px2rpx(20);
  186. font-weight: 600;
  187. color: #333;
  188. }
  189. }
  190. .dialog-content {
  191. padding: px2rpx(20) px2rpx(30);
  192. max-height: 60vh;
  193. overflow-y: auto;
  194. // 自定义滚动条样式
  195. &::-webkit-scrollbar {
  196. width: px2rpx(6);
  197. }
  198. &::-webkit-scrollbar-thumb {
  199. background-color: #ddd;
  200. border-radius: px2rpx(3);
  201. }
  202. }
  203. @media screen and (max-width: 768px) {
  204. :deep(.cwg-dialog) {
  205. width: px2rpx(600) !important;
  206. }
  207. .dialog-content {
  208. padding: px2rpx(20) px2rpx(10);
  209. max-height: 60vh;
  210. overflow-y: auto;
  211. // 自定义滚动条样式
  212. &::-webkit-scrollbar {
  213. width: px2rpx(6);
  214. }
  215. &::-webkit-scrollbar-thumb {
  216. background-color: #ddd;
  217. border-radius: px2rpx(3);
  218. }
  219. }
  220. }
  221. </style>